summaryrefslogtreecommitdiff
path: root/public/js/fullcalendar
diff options
context:
space:
mode:
Diffstat (limited to 'public/js/fullcalendar')
-rw-r--r--public/js/fullcalendar/LICENSE.md22
-rw-r--r--public/js/fullcalendar/README.md73
-rw-r--r--public/js/fullcalendar/dist/index.global.js14775
-rw-r--r--public/js/fullcalendar/dist/index.global.min.js6
-rw-r--r--public/js/fullcalendar/examples/background-events.html101
-rw-r--r--public/js/fullcalendar/examples/daygrid-views.html104
-rw-r--r--public/js/fullcalendar/examples/external-dragging-2cals.html69
-rw-r--r--public/js/fullcalendar/examples/external-dragging-builtin.html149
-rw-r--r--public/js/fullcalendar/examples/full-height.html125
-rw-r--r--public/js/fullcalendar/examples/list-sticky-header.html76
-rw-r--r--public/js/fullcalendar/examples/list-views.html114
-rw-r--r--public/js/fullcalendar/examples/month-view.html100
-rw-r--r--public/js/fullcalendar/examples/multimonth-view.html110
-rw-r--r--public/js/fullcalendar/examples/multiweek-view.html107
-rw-r--r--public/js/fullcalendar/examples/natural-height.html108
-rw-r--r--public/js/fullcalendar/examples/selectable.html123
-rw-r--r--public/js/fullcalendar/examples/timegrid-views-modal.html180
-rw-r--r--public/js/fullcalendar/examples/timegrid-views.html108
-rw-r--r--public/js/fullcalendar/packages/bootstrap4/index.global.js64
-rw-r--r--public/js/fullcalendar/packages/bootstrap4/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/bootstrap5/index.global.js64
-rw-r--r--public/js/fullcalendar/packages/bootstrap5/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/index.global.js9929
-rw-r--r--public/js/fullcalendar/packages/core/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales-all.global.js1933
-rw-r--r--public/js/fullcalendar/packages/core/locales-all.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/af.global.js32
-rw-r--r--public/js/fullcalendar/packages/core/locales/af.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-dz.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-dz.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-kw.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-kw.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-ly.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-ly.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-ma.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-ma.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-sa.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-sa.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-tn.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar-tn.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ar.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/az.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/az.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/bg.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/bg.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/bn.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/bn.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/bs.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/bs.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ca.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/ca.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/cs.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/cs.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/cy.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/cy.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/da.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/da.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/de-at.global.js69
-rw-r--r--public/js/fullcalendar/packages/core/locales/de-at.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/de.global.js69
-rw-r--r--public/js/fullcalendar/packages/core/locales/de.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/el.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/el.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-au.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-au.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-gb.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-gb.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-nz.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/en-nz.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/eo.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/eo.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/es-us.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/es-us.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/es.global.js52
-rw-r--r--public/js/fullcalendar/packages/core/locales/es.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/et.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/et.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/eu.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/eu.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/fa.global.js36
-rw-r--r--public/js/fullcalendar/packages/core/locales/fa.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/fi.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/fi.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr-ca.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr-ca.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr-ch.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr-ch.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/fr.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/gl.global.js52
-rw-r--r--public/js/fullcalendar/packages/core/locales/gl.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/he.global.js30
-rw-r--r--public/js/fullcalendar/packages/core/locales/he.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/hi.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/hi.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/hr.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/hr.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/hu.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/hu.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/hy-am.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/hy-am.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/id.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/id.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/is.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/is.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/it.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/it.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ja.global.js31
-rw-r--r--public/js/fullcalendar/packages/core/locales/ja.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ka.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/ka.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/kk.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/kk.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/km.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/km.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ko.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/ko.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ku.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/ku.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/lb.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/lb.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/lt.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/lt.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/lv.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/lv.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/mk.global.js31
-rw-r--r--public/js/fullcalendar/packages/core/locales/mk.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ms.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/ms.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/nb.global.js44
-rw-r--r--public/js/fullcalendar/packages/core/locales/nb.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ne.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/ne.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/nl.global.js32
-rw-r--r--public/js/fullcalendar/packages/core/locales/nl.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/nn.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/nn.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/pl.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/pl.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/pt-br.global.js52
-rw-r--r--public/js/fullcalendar/packages/core/locales/pt-br.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/pt.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/pt.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ro.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/ro.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ru.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/ru.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/si-lk.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/si-lk.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sk.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/sk.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sl.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/sl.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sm.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/sm.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sq.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/sq.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sr-cyrl.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/sr-cyrl.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sr.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/sr.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/sv.global.js53
-rw-r--r--public/js/fullcalendar/packages/core/locales/sv.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ta-in.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/ta-in.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/th.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/th.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/tr.global.js33
-rw-r--r--public/js/fullcalendar/packages/core/locales/tr.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/ug.global.js26
-rw-r--r--public/js/fullcalendar/packages/core/locales/ug.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/uk.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/uk.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/uz-cy.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/uz-cy.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/uz.global.js34
-rw-r--r--public/js/fullcalendar/packages/core/locales/uz.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/vi.global.js35
-rw-r--r--public/js/fullcalendar/packages/core/locales/vi.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/zh-cn.global.js36
-rw-r--r--public/js/fullcalendar/packages/core/locales/zh-cn.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/core/locales/zh-tw.global.js29
-rw-r--r--public/js/fullcalendar/packages/core/locales/zh-tw.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/daygrid/index.global.js1040
-rw-r--r--public/js/fullcalendar/packages/daygrid/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/google-calendar/index.global.js150
-rw-r--r--public/js/fullcalendar/packages/google-calendar/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/icalendar/index.global.js225
-rw-r--r--public/js/fullcalendar/packages/icalendar/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/interaction/index.global.js2141
-rw-r--r--public/js/fullcalendar/packages/interaction/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/list/index.global.js332
-rw-r--r--public/js/fullcalendar/packages/list/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/luxon1/index.global.js128
-rw-r--r--public/js/fullcalendar/packages/luxon1/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/luxon2/index.global.js131
-rw-r--r--public/js/fullcalendar/packages/luxon2/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/luxon3/index.global.js131
-rw-r--r--public/js/fullcalendar/packages/luxon3/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/moment-timezone/index.global.js35
-rw-r--r--public/js/fullcalendar/packages/moment-timezone/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/moment/index.global.js113
-rw-r--r--public/js/fullcalendar/packages/moment/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/multimonth/index.global.js252
-rw-r--r--public/js/fullcalendar/packages/multimonth/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/rrule/index.global.js169
-rw-r--r--public/js/fullcalendar/packages/rrule/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/timegrid/index.global.js1198
-rw-r--r--public/js/fullcalendar/packages/timegrid/index.global.min.js6
-rw-r--r--public/js/fullcalendar/packages/web-component/index.global.js79
-rw-r--r--public/js/fullcalendar/packages/web-component/index.global.min.js6
212 files changed, 37933 insertions, 0 deletions
diff --git a/public/js/fullcalendar/LICENSE.md b/public/js/fullcalendar/LICENSE.md
new file mode 100644
index 0000000..18ac667
--- /dev/null
+++ b/public/js/fullcalendar/LICENSE.md
@@ -0,0 +1,22 @@
1MIT License
2
3Copyright (c) 2021 Adam Shaw
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/public/js/fullcalendar/README.md b/public/js/fullcalendar/README.md
new file mode 100644
index 0000000..379e2c3
--- /dev/null
+++ b/public/js/fullcalendar/README.md
@@ -0,0 +1,73 @@
1# FullCalendar
2
3Full-sized drag & drop calendar in JavaScript
4
5- [Project Website](https://fullcalendar.io/)
6- [Documentation](https://fullcalendar.io/docs)
7- [Changelog](CHANGELOG.md)
8- [Support](https://fullcalendar.io/support)
9- [License](LICENSE.md)
10- [Roadmap](https://fullcalendar.io/roadmap)
11
12Connectors:
13
14- [React](https://github.com/fullcalendar/fullcalendar-react)
15- [Angular](https://github.com/fullcalendar/fullcalendar-angular)
16- [Vue 3](https://github.com/fullcalendar/fullcalendar-vue) |
17 [2](https://github.com/fullcalendar/fullcalendar-vue2)
18
19## Bundle
20
21The [FullCalendar Standard Bundle](bundle) is easier to install than individual plugins, though filesize will be larger. It works well with a CDN.
22
23## Installation
24
25Install the FullCalendar core package and any plugins you plan to use:
26
27```sh
28npm install @fullcalendar/core @fullcalendar/interaction @fullcalendar/daygrid
29```
30
31## Usage
32
33Instantiate a Calendar with plugins and options:
34
35```js
36import { Calendar } from '@fullcalendar/core'
37import interactionPlugin from '@fullcalendar/interaction'
38import dayGridPlugin from '@fullcalendar/daygrid'
39
40const calendarEl = document.getElementById('calendar')
41const calendar = new Calendar(calendarEl, {
42 plugins: [
43 interactionPlugin,
44 dayGridPlugin
45 ],
46 initialView: 'timeGridWeek',
47 editable: true,
48 events: [
49 { title: 'Meeting', start: new Date() }
50 ]
51})
52
53calendar.render()
54```
55
56## Development
57
58You must install this repo with [PNPM](https://pnpm.io/):
59
60```
61pnpm install
62```
63
64Available scripts (via `pnpm run <script>`):
65
66- `build` - build production-ready dist files
67- `dev` - build & watch development dist files
68- `test` - test headlessly
69- `test:dev` - test interactively
70- `lint`
71- `clean`
72
73[Info about contributing code &raquo;](CONTRIBUTING.md)
diff --git a/public/js/fullcalendar/dist/index.global.js b/public/js/fullcalendar/dist/index.global.js
new file mode 100644
index 0000000..9a97af4
--- /dev/null
+++ b/public/js/fullcalendar/dist/index.global.js
@@ -0,0 +1,14775 @@
1/*!
2FullCalendar Standard Bundle v6.1.17
3Docs & License: https://fullcalendar.io/docs/initialize-globals
4(c) 2024 Adam Shaw
5*/
6var FullCalendar = (function (exports) {
7 'use strict';
8
9 var n,l$1,u$1,i$1,t,r$1,o,f$1,e$1,c$1={},s=[],a$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function h(n,l){for(var u in l)n[u]=l[u];return n}function v$1(n){var l=n.parentNode;l&&l.removeChild(n);}function y(l,u,i){var t,r,o,f={};for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps)void 0===f[o]&&(f[o]=l.defaultProps[o]);return p(l,f,t,r,null)}function p(n,i,t,r,o){var f={type:n,props:i,key:t,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++u$1:o};return null==o&&null!=l$1.vnode&&l$1.vnode(f),f}function d(){return {current:null}}function _(n){return n.children}function k$1(n,l,u,i,t){var r;for(r in u)"children"===r||"key"===r||r in l||g$2(n,r,null,u[r],i);for(r in l)t&&"function"!=typeof l[r]||"children"===r||"key"===r||"value"===r||"checked"===r||u[r]===l[r]||g$2(n,r,l[r],u[r],i);}function b$1(n,l,u){"-"===l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||a$1.test(l)?u:u+"px";}function g$2(n,l,u,i,t){var r;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof i&&(n.style.cssText=i=""),i)for(l in i)u&&l in u||b$1(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||b$1(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])r=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?i||n.addEventListener(l,r?w$2:m$1,r):n.removeEventListener(l,r?w$2:m$1,r);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==l&&"height"!==l&&"href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||!1===u&&-1==l.indexOf("-")?n.removeAttribute(l):n.setAttribute(l,u));}}function m$1(n){t=!0;try{return this.l[n.type+!1](l$1.event?l$1.event(n):n)}finally{t=!1;}}function w$2(n){t=!0;try{return this.l[n.type+!0](l$1.event?l$1.event(n):n)}finally{t=!1;}}function x$1(n,l){this.props=n,this.context=l;}function A(n,l){if(null==l)return n.__?A(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?A(n):null}function P$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return P$1(n)}}function C$1(n){t?setTimeout(n):f$1(n);}function T$1(n){(!n.__d&&(n.__d=!0)&&r$1.push(n)&&!$$1.__r++||o!==l$1.debounceRendering)&&((o=l$1.debounceRendering)||C$1)($$1);}function $$1(){var n,l,u,i,t,o,f,e;for(r$1.sort(function(n,l){return n.__v.__b-l.__v.__b});n=r$1.shift();)n.__d&&(l=r$1.length,i=void 0,t=void 0,f=(o=(u=n).__v).__e,(e=u.__P)&&(i=[],(t=h({},o)).__v=o.__v+1,M(e,o,t,u.__n,void 0!==e.ownerSVGElement,null!=o.__h?[f]:null,i,null==f?A(o):f,o.__h),N(i,o),o.__e!=f&&P$1(o)),r$1.length>l&&r$1.sort(function(n,l){return n.__v.__b-l.__v.__b}));$$1.__r=0;}function H$1(n,l,u,i,t,r,o,f,e,a){var h,v,y,d,k,b,g,m=i&&i.__k||s,w=m.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(d=u.__k[h]=null==(d=l[h])||"boolean"==typeof d?null:"string"==typeof d||"number"==typeof d||"bigint"==typeof d?p(null,d,null,null,d):Array.isArray(d)?p(_,{children:d},null,null,null):d.__b>0?p(d.type,d.props,d.key,d.ref?d.ref:null,d.__v):d)){if(d.__=u,d.__b=u.__b+1,null===(y=m[h])||y&&d.key==y.key&&d.type===y.type)m[h]=void 0;else for(v=0;v<w;v++){if((y=m[v])&&d.key==y.key&&d.type===y.type){m[v]=void 0;break}y=null;}M(n,d,y=y||c$1,t,r,o,f,e,a),k=d.__e,(v=d.ref)&&y.ref!=v&&(g||(g=[]),y.ref&&g.push(y.ref,null,d),g.push(v,d.__c||k,d)),null!=k?(null==b&&(b=k),"function"==typeof d.type&&d.__k===y.__k?d.__d=e=I$1(d,e,n):e=z$1(n,d,y,m,k,e),"function"==typeof u.type&&(u.__d=e)):e&&y.__e==e&&e.parentNode!=n&&(e=A(y));}for(u.__e=b,h=w;h--;)null!=m[h]&&("function"==typeof u.type&&null!=m[h].__e&&m[h].__e==u.__d&&(u.__d=L$1(i).nextSibling),q(m[h],m[h]));if(g)for(h=0;h<g.length;h++)S(g[h],g[++h],g[++h]);}function I$1(n,l,u){for(var i,t=n.__k,r=0;t&&r<t.length;r++)(i=t[r])&&(i.__=n,l="function"==typeof i.type?I$1(i,l,u):z$1(u,i,i,t,i.__e,l));return l}function j$2(n,l){return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some(function(n){j$2(n,l);}):l.push(n)),l}function z$1(n,l,u,i,t,r){var o,f,e;if(void 0!==l.__d)o=l.__d,l.__d=void 0;else if(null==u||t!=r||null==t.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(t),o=null;else {for(f=r,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,r),o=r;}return void 0!==o?o:t.nextSibling}function L$1(n){var l,u,i;if(null==n.type||"string"==typeof n.type)return n.__e;if(n.__k)for(l=n.__k.length-1;l>=0;l--)if((u=n.__k[l])&&(i=L$1(u)))return i;return null}function M(n,u,i,t,r,o,f,e,c){var s,a,v,y,p,d,k,b,g,m,w,A,P,C,T,$=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,o=[e]),(s=l$1.__b)&&s(u);try{n:if("function"==typeof $){if(b=u.props,g=(s=$.contextType)&&t[s.__c],m=s?g?g.props.value:s.__:t,i.__c?k=(a=u.__c=i.__c).__=a.__E:("prototype"in $&&$.prototype.render?u.__c=a=new $(b,m):(u.__c=a=new x$1(b,m),a.constructor=$,a.render=B$1),g&&g.sub(a),a.props=b,a.state||(a.state={}),a.context=m,a.__n=t,v=a.__d=!0,a.__h=[],a._sb=[]),null==a.__s&&(a.__s=a.state),null!=$.getDerivedStateFromProps&&(a.__s==a.state&&(a.__s=h({},a.__s)),h(a.__s,$.getDerivedStateFromProps(b,a.__s))),y=a.props,p=a.state,a.__v=u,v)null==$.getDerivedStateFromProps&&null!=a.componentWillMount&&a.componentWillMount(),null!=a.componentDidMount&&a.__h.push(a.componentDidMount);else {if(null==$.getDerivedStateFromProps&&b!==y&&null!=a.componentWillReceiveProps&&a.componentWillReceiveProps(b,m),!a.__e&&null!=a.shouldComponentUpdate&&!1===a.shouldComponentUpdate(b,a.__s,m)||u.__v===i.__v){for(u.__v!==i.__v&&(a.props=b,a.state=a.__s,a.__d=!1),u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),w=0;w<a._sb.length;w++)a.__h.push(a._sb[w]);a._sb=[],a.__h.length&&f.push(a);break n}null!=a.componentWillUpdate&&a.componentWillUpdate(b,a.__s,m),null!=a.componentDidUpdate&&a.__h.push(function(){a.componentDidUpdate(y,p,d);});}if(a.context=m,a.props=b,a.__P=n,A=l$1.__r,P=0,"prototype"in $&&$.prototype.render){for(a.state=a.__s,a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),C=0;C<a._sb.length;C++)a.__h.push(a._sb[C]);a._sb=[];}else do{a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),a.state=a.__s;}while(a.__d&&++P<25);a.state=a.__s,null!=a.getChildContext&&(t=h(h({},t),a.getChildContext())),v||null==a.getSnapshotBeforeUpdate||(d=a.getSnapshotBeforeUpdate(y,p)),T=null!=s&&s.type===_&&null==s.key?s.props.children:s,H$1(n,Array.isArray(T)?T:[T],u,i,t,r,o,f,e,c),a.base=u.__e,u.__h=null,a.__h.length&&f.push(a),k&&(a.__E=a.__=null),a.__e=!1;}else null==o&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=O(i.__e,u,i,t,r,o,f,c);(s=l$1.diffed)&&s(u);}catch(n){u.__v=null,(c||null!=o)&&(u.__e=e,u.__h=!!c,o[o.indexOf(e)]=null),l$1.__e(n,u,i);}}function N(n,u){l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function O(l,u,i,t,r,o,f,e){var s,a,h,y=i.props,p=u.props,d=u.type,_=0;if("svg"===d&&(r=!0),null!=o)for(;_<o.length;_++)if((s=o[_])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,o[_]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=r?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),o=null,e=!1;}if(null===d)y===p||e&&l.data===p||(l.data=p);else {if(o=o&&n.call(l.childNodes),a=(y=i.props||c$1).dangerouslySetInnerHTML,h=p.dangerouslySetInnerHTML,!e){if(null!=o)for(y={},_=0;_<l.attributes.length;_++)y[l.attributes[_].name]=l.attributes[_].value;(h||a)&&(h&&(a&&h.__html==a.__html||h.__html===l.innerHTML)||(l.innerHTML=h&&h.__html||""));}if(k$1(l,p,y,r,e),h)u.__k=[];else if(_=u.props.children,H$1(l,Array.isArray(_)?_:[_],u,i,t,r&&"foreignObject"!==d,o,f,o?o[0]:i.__k&&A(i,0),e),null!=o)for(_=o.length;_--;)null!=o[_]&&v$1(o[_]);e||("value"in p&&void 0!==(_=p.value)&&(_!==l.value||"progress"===d&&!_||"option"===d&&_!==y.value)&&g$2(l,"value",_,y.value,!1),"checked"in p&&void 0!==(_=p.checked)&&_!==l.checked&&g$2(l,"checked",_,y.checked,!1));}return l}function S(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function q(n,u,i){var t,r;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||S(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(n){l$1.__e(n,u);}t.base=t.__P=null,n.__c=void 0;}if(t=n.__k)for(r=0;r<t.length;r++)t[r]&&q(t[r],u,i||"function"!=typeof n.type);i||null==n.__e||v$1(n.__e),n.__=n.__e=n.__d=void 0;}function B$1(n,l,u){return this.constructor(n,u)}function D$1(u,i,t){var r,o,f;l$1.__&&l$1.__(u,i),o=(r="function"==typeof t)?null:t&&t.__k||i.__k,f=[],M(i,u=(!r&&t||i).__k=y(_,null,[u]),o||c$1,c$1,void 0!==i.ownerSVGElement,!r&&t?[t]:o?null:i.firstChild?n.call(i.childNodes):null,f,!r&&t?t:o?o.__e:i.firstChild,r),N(f,u);}function E(n,l){D$1(n,l,E);}function F$1(l,u,i){var t,r,o,f=h({},l.props);for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),p(l.type,f,t||l.key,r||l.ref,null)}function G$1(n,l){var u={__c:l="__cC"+e$1++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(function(n){n.__e=!0,T$1(n);});},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n);};}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=s.slice,l$1={__e:function(n,l,u,i){for(var t,r,o;l=l.__;)if((t=l.__c)&&!t.__)try{if((r=t.constructor)&&null!=r.getDerivedStateFromError&&(t.setState(r.getDerivedStateFromError(n)),o=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),o=t.__d),o)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,i$1=function(n){return null!=n&&void 0===n.constructor},t=!1,x$1.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=h({},this.state),"function"==typeof n&&(n=n(h({},u),this.props)),n&&h(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),T$1(this));},x$1.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),T$1(this));},x$1.prototype.render=_,r$1=[],f$1="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,$$1.__r=0,e$1=0;
10
11 var r,u,i,f=[],c=[],e=l$1.__b,a=l$1.__r,v=l$1.diffed,l=l$1.__c,m=l$1.unmount;function b(){for(var t;t=f.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(k),t.__H.__h.forEach(w$1),t.__H.__h=[];}catch(r){t.__H.__h=[],l$1.__e(r,t.__v);}}l$1.__b=function(n){r=null,e&&e(n);},l$1.__r=function(n){a&&a(n);var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=c,n.__N=n.i=void 0;})):(i.__h.forEach(k),i.__h.forEach(w$1),i.__h=[])),u=r;},l$1.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==f.push(o)&&i===l$1.requestAnimationFrame||((i=l$1.requestAnimationFrame)||j$1)(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==c&&(n.__=n.__V),n.i=void 0,n.__V=c;})),u=r=null;},l$1.__c=function(t,r){r.some(function(t){try{t.__h.forEach(k),t.__h=t.__h.filter(function(n){return !n.__||w$1(n)});}catch(u){r.some(function(n){n.__h&&(n.__h=[]);}),r=[],l$1.__e(u,t.__v);}}),l&&l(t,r);},l$1.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{k(n);}catch(n){r=n;}}),u.__H=void 0,r&&l$1.__e(r,u.__v));};var g$1="function"==typeof requestAnimationFrame;function j$1(n){var t,r=function(){clearTimeout(u),g$1&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,100);g$1&&(t=requestAnimationFrame(r));}function k(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function w$1(n){var t=r;n.__c=n.__(),r=t;}
12
13 function g(n,t){for(var e in t)n[e]=t[e];return n}function C(n,t){for(var e in n)if("__source"!==e&&!(e in t))return !0;for(var r in t)if("__source"!==r&&n[r]!==t[r])return !0;return !1}function w(n){this.props=n;}(w.prototype=new x$1).isPureReactComponent=!0,w.prototype.shouldComponentUpdate=function(n,t){return C(this.props,n)||C(this.state,t)};var x=l$1.__b;l$1.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),x&&x(n);};var T=l$1.__e;l$1.__e=function(n,t,e,r){if(n.then)for(var u,o=t;o=o.__;)if((u=o.__c)&&u.__c)return null==t.__e&&(t.__e=e.__e,t.__k=e.__k),u.__c(n,t);T(n,t,e,r);};var I=l$1.unmount;function L(n,t,e){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(n){"function"==typeof n.__c&&n.__c();}),n.__c.__H=null),null!=(n=g({},n)).__c&&(n.__c.__P===e&&(n.__c.__P=t),n.__c=null),n.__k=n.__k&&n.__k.map(function(n){return L(n,t,e)})),n}function U(n,t,e){return n&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(n){return U(n,t,e)}),n.__c&&n.__c.__P===t&&(n.__e&&e.insertBefore(n.__e,n.__d),n.__c.__e=!0,n.__c.__P=e)),n}function D(){this.__u=0,this.t=null,this.__b=null;}function F(n){var t=n.__.__c;return t&&t.__a&&t.__a(n)}function V(){this.u=null,this.o=null;}l$1.unmount=function(n){var t=n.__c;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),I&&I(n);},(D.prototype=new x$1).__c=function(n,t){var e=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(e);var u=F(r.__v),o=!1,i=function(){o||(o=!0,e.__R=null,u?u(l):l());};e.__R=i;var l=function(){if(!--r.__u){if(r.state.__a){var n=r.state.__a;r.__v.__k[0]=U(n,n.__c.__P,n.__c.__O);}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate();}},c=!0===t.__h;r.__u++||c||r.setState({__a:r.__b=r.__v.__k[0]}),n.then(i,i);},D.prototype.componentWillUnmount=function(){this.t=[];},D.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),o=this.__v.__k[0].__c;this.__v.__k[0]=L(this.__b,r,o.__O=o.__P);}this.__b=null;}var i=e.__a&&y(_,null,n.fallback);return i&&(i.__h=null),[y(_,null,e.__a?null:n.children),i]};var W=function(n,t,e){if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&("t"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2];}};function P(n){return this.getChildContext=function(){return n.context},n.children}function $(n){var e=this,r=n.i;e.componentWillUnmount=function(){D$1(null,e.l),e.l=null,e.i=null;},e.i&&e.i!==r&&e.componentWillUnmount(),n.__v?(e.l||(e.i=r,e.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),e.i.appendChild(n);},insertBefore:function(n,t){this.childNodes.push(n),e.i.appendChild(n);},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),e.i.removeChild(n);}}),D$1(y(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount();}function j(n,e){var r=y($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new x$1).__a=function(n){var t=this,e=F(t.__v),r=t.o.get(n);return r[0]++,function(u){var o=function(){t.props.revealOrder?(r.push(u),W(t,n,r)):u();};e?e(o):o();}},V.prototype.render=function(n){this.u=null,this.o=new Map;var t=j$2(n.children);n.revealOrder&&"b"===n.revealOrder[0]&&t.reverse();for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children},V.prototype.componentDidUpdate=V.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(t,e){W(n,e,t);});};var z="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,B=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,H="undefined"!=typeof document,Z=function(n){return ("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n)};x$1.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(x$1.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(n){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:n});}});});var G=l$1.event;function J(){}function K(){return this.cancelBubble}function Q(){return this.defaultPrevented}l$1.event=function(n){return G&&(n=G(n)),n.persist=J,n.isPropagationStopped=K,n.isDefaultPrevented=Q,n.nativeEvent=n};var nn={configurable:!0,get:function(){return this.class}},tn=l$1.vnode;l$1.vnode=function(n){var t=n.type,e=n.props,u=e;if("string"==typeof t){var o=-1===t.indexOf("-");for(var i in u={},e){var l=e[i];H&&"children"===i&&"noscript"===t||"value"===i&&"defaultValue"in e&&null==l||("defaultValue"===i&&"value"in e&&null==e.value?i="value":"download"===i&&!0===l?l="":/ondoubleclick/i.test(i)?i="ondblclick":/^onchange(textarea|input)/i.test(i+t)&&!Z(e.type)?i="oninput":/^onfocus$/i.test(i)?i="onfocusin":/^onblur$/i.test(i)?i="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)?i=i.toLowerCase():o&&B.test(i)?i=i.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===l&&(l=void 0),/^oninput$/i.test(i)&&(i=i.toLowerCase(),u[i]&&(i="oninputCapture")),u[i]=l);}"select"==t&&u.multiple&&Array.isArray(u.value)&&(u.value=j$2(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value);})),"select"==t&&null!=u.defaultValue&&(u.value=j$2(e.children).forEach(function(n){n.props.selected=u.multiple?-1!=u.defaultValue.indexOf(n.props.value):u.defaultValue==n.props.value;})),n.props=u,e.class!=e.className&&(nn.enumerable="className"in e,null!=e.className&&(u.class=e.className),Object.defineProperty(u,"className",nn));}n.$$typeof=z,tn&&tn(n);};var en=l$1.__r;l$1.__r=function(n){en&&en(n),n.__c;};
14
15 const styleTexts = [];
16 const styleEls = new Map();
17 function injectStyles(styleText) {
18 styleTexts.push(styleText);
19 styleEls.forEach((styleEl) => {
20 appendStylesTo(styleEl, styleText);
21 });
22 }
23 function ensureElHasStyles(el) {
24 if (el.isConnected && // sometimes true if SSR system simulates DOM
25 el.getRootNode // sometimes undefined if SSR system simulates DOM
26 ) {
27 registerStylesRoot(el.getRootNode());
28 }
29 }
30 function registerStylesRoot(rootNode) {
31 let styleEl = styleEls.get(rootNode);
32 if (!styleEl || !styleEl.isConnected) {
33 styleEl = rootNode.querySelector('style[data-fullcalendar]');
34 if (!styleEl) {
35 styleEl = document.createElement('style');
36 styleEl.setAttribute('data-fullcalendar', '');
37 const nonce = getNonceValue();
38 if (nonce) {
39 styleEl.nonce = nonce;
40 }
41 const parentEl = rootNode === document ? document.head : rootNode;
42 const insertBefore = rootNode === document
43 ? parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style')
44 : parentEl.firstChild;
45 parentEl.insertBefore(styleEl, insertBefore);
46 }
47 styleEls.set(rootNode, styleEl);
48 hydrateStylesRoot(styleEl);
49 }
50 }
51 function hydrateStylesRoot(styleEl) {
52 for (const styleText of styleTexts) {
53 appendStylesTo(styleEl, styleText);
54 }
55 }
56 function appendStylesTo(styleEl, styleText) {
57 const { sheet } = styleEl;
58 const ruleCnt = sheet.cssRules.length;
59 styleText.split('}').forEach((styleStr, i) => {
60 styleStr = styleStr.trim();
61 if (styleStr) {
62 sheet.insertRule(styleStr + '}', ruleCnt + i);
63 }
64 });
65 }
66 // nonce
67 // -------------------------------------------------------------------------------------------------
68 let queriedNonceValue;
69 function getNonceValue() {
70 if (queriedNonceValue === undefined) {
71 queriedNonceValue = queryNonceValue();
72 }
73 return queriedNonceValue;
74 }
75 /*
76 TODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag
77 */
78 function queryNonceValue() {
79 const metaWithNonce = document.querySelector('meta[name="csp-nonce"]');
80 if (metaWithNonce && metaWithNonce.hasAttribute('content')) {
81 return metaWithNonce.getAttribute('content');
82 }
83 const elWithNonce = document.querySelector('script[nonce]');
84 if (elWithNonce) {
85 return elWithNonce.nonce || '';
86 }
87 return '';
88 }
89 // main
90 // -------------------------------------------------------------------------------------------------
91 if (typeof document !== 'undefined') {
92 registerStylesRoot(document);
93 }
94
95 var css_248z$4 = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}";
96 injectStyles(css_248z$4);
97
98 class DelayedRunner {
99 constructor(drainedOption) {
100 this.drainedOption = drainedOption;
101 this.isRunning = false;
102 this.isDirty = false;
103 this.pauseDepths = {};
104 this.timeoutId = 0;
105 }
106 request(delay) {
107 this.isDirty = true;
108 if (!this.isPaused()) {
109 this.clearTimeout();
110 if (delay == null) {
111 this.tryDrain();
112 }
113 else {
114 this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
115 this.tryDrain.bind(this), delay);
116 }
117 }
118 }
119 pause(scope = '') {
120 let { pauseDepths } = this;
121 pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
122 this.clearTimeout();
123 }
124 resume(scope = '', force) {
125 let { pauseDepths } = this;
126 if (scope in pauseDepths) {
127 if (force) {
128 delete pauseDepths[scope];
129 }
130 else {
131 pauseDepths[scope] -= 1;
132 let depth = pauseDepths[scope];
133 if (depth <= 0) {
134 delete pauseDepths[scope];
135 }
136 }
137 this.tryDrain();
138 }
139 }
140 isPaused() {
141 return Object.keys(this.pauseDepths).length;
142 }
143 tryDrain() {
144 if (!this.isRunning && !this.isPaused()) {
145 this.isRunning = true;
146 while (this.isDirty) {
147 this.isDirty = false;
148 this.drained(); // might set isDirty to true again
149 }
150 this.isRunning = false;
151 }
152 }
153 clear() {
154 this.clearTimeout();
155 this.isDirty = false;
156 this.pauseDepths = {};
157 }
158 clearTimeout() {
159 if (this.timeoutId) {
160 clearTimeout(this.timeoutId);
161 this.timeoutId = 0;
162 }
163 }
164 drained() {
165 if (this.drainedOption) {
166 this.drainedOption();
167 }
168 }
169 }
170
171 function removeElement(el) {
172 if (el.parentNode) {
173 el.parentNode.removeChild(el);
174 }
175 }
176 // Querying
177 // ----------------------------------------------------------------------------------------------------------------
178 function elementClosest(el, selector) {
179 if (el.closest) {
180 return el.closest(selector);
181 // really bad fallback for IE
182 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
183 }
184 if (!document.documentElement.contains(el)) {
185 return null;
186 }
187 do {
188 if (elementMatches(el, selector)) {
189 return el;
190 }
191 el = (el.parentElement || el.parentNode);
192 } while (el !== null && el.nodeType === 1);
193 return null;
194 }
195 function elementMatches(el, selector) {
196 let method = el.matches || el.matchesSelector || el.msMatchesSelector;
197 return method.call(el, selector);
198 }
199 // accepts multiple subject els
200 // returns a real array. good for methods like forEach
201 // TODO: accept the document
202 function findElements(container, selector) {
203 let containers = container instanceof HTMLElement ? [container] : container;
204 let allMatches = [];
205 for (let i = 0; i < containers.length; i += 1) {
206 let matches = containers[i].querySelectorAll(selector);
207 for (let j = 0; j < matches.length; j += 1) {
208 allMatches.push(matches[j]);
209 }
210 }
211 return allMatches;
212 }
213 // accepts multiple subject els
214 // only queries direct child elements // TODO: rename to findDirectChildren!
215 function findDirectChildren(parent, selector) {
216 let parents = parent instanceof HTMLElement ? [parent] : parent;
217 let allMatches = [];
218 for (let i = 0; i < parents.length; i += 1) {
219 let childNodes = parents[i].children; // only ever elements
220 for (let j = 0; j < childNodes.length; j += 1) {
221 let childNode = childNodes[j];
222 if (!selector || elementMatches(childNode, selector)) {
223 allMatches.push(childNode);
224 }
225 }
226 }
227 return allMatches;
228 }
229 // Style
230 // ----------------------------------------------------------------------------------------------------------------
231 const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
232 function applyStyle(el, props) {
233 for (let propName in props) {
234 applyStyleProp(el, propName, props[propName]);
235 }
236 }
237 function applyStyleProp(el, name, val) {
238 if (val == null) {
239 el.style[name] = '';
240 }
241 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
242 el.style[name] = `${val}px`;
243 }
244 else {
245 el.style[name] = val;
246 }
247 }
248 // Event Handling
249 // ----------------------------------------------------------------------------------------------------------------
250 // if intercepting bubbled events at the document/window/body level,
251 // and want to see originating element (the 'target'), use this util instead
252 // of `ev.target` because it goes within web-component boundaries.
253 function getEventTargetViaRoot(ev) {
254 var _a, _b;
255 return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
256 }
257 // Unique ID for DOM attribute
258 let guid$1 = 0;
259 function getUniqueDomId() {
260 guid$1 += 1;
261 return 'fc-dom-' + guid$1;
262 }
263
264 // Stops a mouse/touch event from doing it's native browser action
265 function preventDefault(ev) {
266 ev.preventDefault();
267 }
268 // Event Delegation
269 // ----------------------------------------------------------------------------------------------------------------
270 function buildDelegationHandler(selector, handler) {
271 return (ev) => {
272 let matchedChild = elementClosest(ev.target, selector);
273 if (matchedChild) {
274 handler.call(matchedChild, ev, matchedChild);
275 }
276 };
277 }
278 function listenBySelector(container, eventType, selector, handler) {
279 let attachedHandler = buildDelegationHandler(selector, handler);
280 container.addEventListener(eventType, attachedHandler);
281 return () => {
282 container.removeEventListener(eventType, attachedHandler);
283 };
284 }
285 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
286 let currentMatchedChild;
287 return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
288 if (matchedChild !== currentMatchedChild) {
289 currentMatchedChild = matchedChild;
290 onMouseEnter(mouseOverEv, matchedChild);
291 let realOnMouseLeave = (mouseLeaveEv) => {
292 currentMatchedChild = null;
293 onMouseLeave(mouseLeaveEv, matchedChild);
294 matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
295 };
296 // listen to the next mouseleave, and then unattach
297 matchedChild.addEventListener('mouseleave', realOnMouseLeave);
298 }
299 });
300 }
301 // Animation
302 // ----------------------------------------------------------------------------------------------------------------
303 const transitionEventNames = [
304 'webkitTransitionEnd',
305 'otransitionend',
306 'oTransitionEnd',
307 'msTransitionEnd',
308 'transitionend',
309 ];
310 // triggered only when the next single subsequent transition finishes
311 function whenTransitionDone(el, callback) {
312 let realCallback = (ev) => {
313 callback(ev);
314 transitionEventNames.forEach((eventName) => {
315 el.removeEventListener(eventName, realCallback);
316 });
317 };
318 transitionEventNames.forEach((eventName) => {
319 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
320 });
321 }
322 // ARIA workarounds
323 // ----------------------------------------------------------------------------------------------------------------
324 function createAriaClickAttrs(handler) {
325 return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));
326 }
327 function createAriaKeyboardAttrs(handler) {
328 return {
329 tabIndex: 0,
330 onKeyDown(ev) {
331 if (ev.key === 'Enter' || ev.key === ' ') {
332 handler(ev);
333 ev.preventDefault(); // if space, don't scroll down page
334 }
335 },
336 };
337 }
338
339 let guidNumber = 0;
340 function guid() {
341 guidNumber += 1;
342 return String(guidNumber);
343 }
344 /* FullCalendar-specific DOM Utilities
345 ----------------------------------------------------------------------------------------------------------------------*/
346 // Make the mouse cursor express that an event is not allowed in the current area
347 function disableCursor() {
348 document.body.classList.add('fc-not-allowed');
349 }
350 // Returns the mouse cursor to its original look
351 function enableCursor() {
352 document.body.classList.remove('fc-not-allowed');
353 }
354 /* Selection
355 ----------------------------------------------------------------------------------------------------------------------*/
356 function preventSelection(el) {
357 el.style.userSelect = 'none';
358 el.style.webkitUserSelect = 'none';
359 el.addEventListener('selectstart', preventDefault);
360 }
361 function allowSelection(el) {
362 el.style.userSelect = '';
363 el.style.webkitUserSelect = '';
364 el.removeEventListener('selectstart', preventDefault);
365 }
366 /* Context Menu
367 ----------------------------------------------------------------------------------------------------------------------*/
368 function preventContextMenu(el) {
369 el.addEventListener('contextmenu', preventDefault);
370 }
371 function allowContextMenu(el) {
372 el.removeEventListener('contextmenu', preventDefault);
373 }
374 function parseFieldSpecs(input) {
375 let specs = [];
376 let tokens = [];
377 let i;
378 let token;
379 if (typeof input === 'string') {
380 tokens = input.split(/\s*,\s*/);
381 }
382 else if (typeof input === 'function') {
383 tokens = [input];
384 }
385 else if (Array.isArray(input)) {
386 tokens = input;
387 }
388 for (i = 0; i < tokens.length; i += 1) {
389 token = tokens[i];
390 if (typeof token === 'string') {
391 specs.push(token.charAt(0) === '-' ?
392 { field: token.substring(1), order: -1 } :
393 { field: token, order: 1 });
394 }
395 else if (typeof token === 'function') {
396 specs.push({ func: token });
397 }
398 }
399 return specs;
400 }
401 function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
402 let i;
403 let cmp;
404 for (i = 0; i < fieldSpecs.length; i += 1) {
405 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
406 if (cmp) {
407 return cmp;
408 }
409 }
410 return 0;
411 }
412 function compareByFieldSpec(obj0, obj1, fieldSpec) {
413 if (fieldSpec.func) {
414 return fieldSpec.func(obj0, obj1);
415 }
416 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
417 * (fieldSpec.order || 1);
418 }
419 function flexibleCompare(a, b) {
420 if (!a && !b) {
421 return 0;
422 }
423 if (b == null) {
424 return -1;
425 }
426 if (a == null) {
427 return 1;
428 }
429 if (typeof a === 'string' || typeof b === 'string') {
430 return String(a).localeCompare(String(b));
431 }
432 return a - b;
433 }
434 /* String Utilities
435 ----------------------------------------------------------------------------------------------------------------------*/
436 function padStart(val, len) {
437 let s = String(val);
438 return '000'.substr(0, len - s.length) + s;
439 }
440 function formatWithOrdinals(formatter, args, fallbackText) {
441 if (typeof formatter === 'function') {
442 return formatter(...args);
443 }
444 if (typeof formatter === 'string') { // non-blank string
445 return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
446 }
447 return fallbackText;
448 }
449 /* Number Utilities
450 ----------------------------------------------------------------------------------------------------------------------*/
451 function compareNumbers(a, b) {
452 return a - b;
453 }
454 function isInt(n) {
455 return n % 1 === 0;
456 }
457 /* FC-specific DOM dimension stuff
458 ----------------------------------------------------------------------------------------------------------------------*/
459 function computeSmallestCellWidth(cellEl) {
460 let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
461 let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
462 if (!allWidthEl) {
463 throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
464 }
465 if (!contentWidthEl) {
466 throw new Error('needs fc-scrollgrid-shrink-cushion className');
467 }
468 return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
469 contentWidthEl.getBoundingClientRect().width;
470 }
471
472 const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
473 const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
474 // Parsing and Creation
475 function createDuration(input, unit) {
476 if (typeof input === 'string') {
477 return parseString(input);
478 }
479 if (typeof input === 'object' && input) { // non-null object
480 return parseObject(input);
481 }
482 if (typeof input === 'number') {
483 return parseObject({ [unit || 'milliseconds']: input });
484 }
485 return null;
486 }
487 function parseString(s) {
488 let m = PARSE_RE.exec(s);
489 if (m) {
490 let sign = m[1] ? -1 : 1;
491 return {
492 years: 0,
493 months: 0,
494 days: sign * (m[2] ? parseInt(m[2], 10) : 0),
495 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
496 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
497 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
498 (m[6] ? parseInt(m[6], 10) : 0) // ms
499 ),
500 };
501 }
502 return null;
503 }
504 function parseObject(obj) {
505 let duration = {
506 years: obj.years || obj.year || 0,
507 months: obj.months || obj.month || 0,
508 days: obj.days || obj.day || 0,
509 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
510 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
511 (obj.seconds || obj.second || 0) * 1000 + // seconds
512 (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
513 };
514 let weeks = obj.weeks || obj.week;
515 if (weeks) {
516 duration.days += weeks * 7;
517 duration.specifiedWeeks = true;
518 }
519 return duration;
520 }
521 // Equality
522 function durationsEqual(d0, d1) {
523 return d0.years === d1.years &&
524 d0.months === d1.months &&
525 d0.days === d1.days &&
526 d0.milliseconds === d1.milliseconds;
527 }
528 function asCleanDays(dur) {
529 if (!dur.years && !dur.months && !dur.milliseconds) {
530 return dur.days;
531 }
532 return 0;
533 }
534 // Simple Math
535 function addDurations(d0, d1) {
536 return {
537 years: d0.years + d1.years,
538 months: d0.months + d1.months,
539 days: d0.days + d1.days,
540 milliseconds: d0.milliseconds + d1.milliseconds,
541 };
542 }
543 function subtractDurations(d1, d0) {
544 return {
545 years: d1.years - d0.years,
546 months: d1.months - d0.months,
547 days: d1.days - d0.days,
548 milliseconds: d1.milliseconds - d0.milliseconds,
549 };
550 }
551 function multiplyDuration(d, n) {
552 return {
553 years: d.years * n,
554 months: d.months * n,
555 days: d.days * n,
556 milliseconds: d.milliseconds * n,
557 };
558 }
559 // Conversions
560 // "Rough" because they are based on average-case Gregorian months/years
561 function asRoughYears(dur) {
562 return asRoughDays(dur) / 365;
563 }
564 function asRoughMonths(dur) {
565 return asRoughDays(dur) / 30;
566 }
567 function asRoughDays(dur) {
568 return asRoughMs(dur) / 864e5;
569 }
570 function asRoughMinutes(dur) {
571 return asRoughMs(dur) / (1000 * 60);
572 }
573 function asRoughSeconds(dur) {
574 return asRoughMs(dur) / 1000;
575 }
576 function asRoughMs(dur) {
577 return dur.years * (365 * 864e5) +
578 dur.months * (30 * 864e5) +
579 dur.days * 864e5 +
580 dur.milliseconds;
581 }
582 // Advanced Math
583 function wholeDivideDurations(numerator, denominator) {
584 let res = null;
585 for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
586 let unit = INTERNAL_UNITS[i];
587 if (denominator[unit]) {
588 let localRes = numerator[unit] / denominator[unit];
589 if (!isInt(localRes) || (res !== null && res !== localRes)) {
590 return null;
591 }
592 res = localRes;
593 }
594 else if (numerator[unit]) {
595 // needs to divide by something but can't!
596 return null;
597 }
598 }
599 return res;
600 }
601 function greatestDurationDenominator(dur) {
602 let ms = dur.milliseconds;
603 if (ms) {
604 if (ms % 1000 !== 0) {
605 return { unit: 'millisecond', value: ms };
606 }
607 if (ms % (1000 * 60) !== 0) {
608 return { unit: 'second', value: ms / 1000 };
609 }
610 if (ms % (1000 * 60 * 60) !== 0) {
611 return { unit: 'minute', value: ms / (1000 * 60) };
612 }
613 if (ms) {
614 return { unit: 'hour', value: ms / (1000 * 60 * 60) };
615 }
616 }
617 if (dur.days) {
618 if (dur.specifiedWeeks && dur.days % 7 === 0) {
619 return { unit: 'week', value: dur.days / 7 };
620 }
621 return { unit: 'day', value: dur.days };
622 }
623 if (dur.months) {
624 return { unit: 'month', value: dur.months };
625 }
626 if (dur.years) {
627 return { unit: 'year', value: dur.years };
628 }
629 return { unit: 'millisecond', value: 0 };
630 }
631
632 // TODO: new util arrayify?
633 function removeExact(array, exactVal) {
634 let removeCnt = 0;
635 let i = 0;
636 while (i < array.length) {
637 if (array[i] === exactVal) {
638 array.splice(i, 1);
639 removeCnt += 1;
640 }
641 else {
642 i += 1;
643 }
644 }
645 return removeCnt;
646 }
647 function isArraysEqual(a0, a1, equalityFunc) {
648 if (a0 === a1) {
649 return true;
650 }
651 let len = a0.length;
652 let i;
653 if (len !== a1.length) { // not array? or not same length?
654 return false;
655 }
656 for (i = 0; i < len; i += 1) {
657 if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
658 return false;
659 }
660 }
661 return true;
662 }
663
664 const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
665 // Adding
666 function addWeeks(m, n) {
667 let a = dateToUtcArray(m);
668 a[2] += n * 7;
669 return arrayToUtcDate(a);
670 }
671 function addDays(m, n) {
672 let a = dateToUtcArray(m);
673 a[2] += n;
674 return arrayToUtcDate(a);
675 }
676 function addMs(m, n) {
677 let a = dateToUtcArray(m);
678 a[6] += n;
679 return arrayToUtcDate(a);
680 }
681 // Diffing (all return floats)
682 // TODO: why not use ranges?
683 function diffWeeks(m0, m1) {
684 return diffDays(m0, m1) / 7;
685 }
686 function diffDays(m0, m1) {
687 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
688 }
689 function diffHours(m0, m1) {
690 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
691 }
692 function diffMinutes(m0, m1) {
693 return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
694 }
695 function diffSeconds(m0, m1) {
696 return (m1.valueOf() - m0.valueOf()) / 1000;
697 }
698 function diffDayAndTime(m0, m1) {
699 let m0day = startOfDay(m0);
700 let m1day = startOfDay(m1);
701 return {
702 years: 0,
703 months: 0,
704 days: Math.round(diffDays(m0day, m1day)),
705 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
706 };
707 }
708 // Diffing Whole Units
709 function diffWholeWeeks(m0, m1) {
710 let d = diffWholeDays(m0, m1);
711 if (d !== null && d % 7 === 0) {
712 return d / 7;
713 }
714 return null;
715 }
716 function diffWholeDays(m0, m1) {
717 if (timeAsMs(m0) === timeAsMs(m1)) {
718 return Math.round(diffDays(m0, m1));
719 }
720 return null;
721 }
722 // Start-Of
723 function startOfDay(m) {
724 return arrayToUtcDate([
725 m.getUTCFullYear(),
726 m.getUTCMonth(),
727 m.getUTCDate(),
728 ]);
729 }
730 function startOfHour(m) {
731 return arrayToUtcDate([
732 m.getUTCFullYear(),
733 m.getUTCMonth(),
734 m.getUTCDate(),
735 m.getUTCHours(),
736 ]);
737 }
738 function startOfMinute(m) {
739 return arrayToUtcDate([
740 m.getUTCFullYear(),
741 m.getUTCMonth(),
742 m.getUTCDate(),
743 m.getUTCHours(),
744 m.getUTCMinutes(),
745 ]);
746 }
747 function startOfSecond(m) {
748 return arrayToUtcDate([
749 m.getUTCFullYear(),
750 m.getUTCMonth(),
751 m.getUTCDate(),
752 m.getUTCHours(),
753 m.getUTCMinutes(),
754 m.getUTCSeconds(),
755 ]);
756 }
757 // Week Computation
758 function weekOfYear(marker, dow, doy) {
759 let y = marker.getUTCFullYear();
760 let w = weekOfGivenYear(marker, y, dow, doy);
761 if (w < 1) {
762 return weekOfGivenYear(marker, y - 1, dow, doy);
763 }
764 let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
765 if (nextW >= 1) {
766 return Math.min(w, nextW);
767 }
768 return w;
769 }
770 function weekOfGivenYear(marker, year, dow, doy) {
771 let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
772 let dayStart = startOfDay(marker);
773 let days = Math.round(diffDays(firstWeekStart, dayStart));
774 return Math.floor(days / 7) + 1; // zero-indexed
775 }
776 // start-of-first-week - start-of-year
777 function firstWeekOffset(year, dow, doy) {
778 // first-week day -- which january is always in the first week (4 for iso, 1 for other)
779 let fwd = 7 + dow - doy;
780 // first-week day local weekday -- which local weekday is fwd
781 let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
782 return -fwdlw + fwd - 1;
783 }
784 // Array Conversion
785 function dateToLocalArray(date) {
786 return [
787 date.getFullYear(),
788 date.getMonth(),
789 date.getDate(),
790 date.getHours(),
791 date.getMinutes(),
792 date.getSeconds(),
793 date.getMilliseconds(),
794 ];
795 }
796 function arrayToLocalDate(a) {
797 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
798 a[3] || 0, a[4] || 0, a[5] || 0);
799 }
800 function dateToUtcArray(date) {
801 return [
802 date.getUTCFullYear(),
803 date.getUTCMonth(),
804 date.getUTCDate(),
805 date.getUTCHours(),
806 date.getUTCMinutes(),
807 date.getUTCSeconds(),
808 date.getUTCMilliseconds(),
809 ];
810 }
811 function arrayToUtcDate(a) {
812 // according to web standards (and Safari), a month index is required.
813 // massage if only given a year.
814 if (a.length === 1) {
815 a = a.concat([0]);
816 }
817 return new Date(Date.UTC(...a));
818 }
819 // Other Utils
820 function isValidDate(m) {
821 return !isNaN(m.valueOf());
822 }
823 function timeAsMs(m) {
824 return m.getUTCHours() * 1000 * 60 * 60 +
825 m.getUTCMinutes() * 1000 * 60 +
826 m.getUTCSeconds() * 1000 +
827 m.getUTCMilliseconds();
828 }
829
830 // timeZoneOffset is in minutes
831 function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
832 let s = marker.toISOString();
833 s = s.replace('.000', '');
834 if (stripZeroTime) {
835 s = s.replace('T00:00:00Z', '');
836 }
837 if (s.length > 10) { // time part wasn't stripped, can add timezone info
838 if (timeZoneOffset == null) {
839 s = s.replace('Z', '');
840 }
841 else if (timeZoneOffset !== 0) {
842 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
843 }
844 // otherwise, its UTC-0 and we want to keep the Z
845 }
846 return s;
847 }
848 // formats the date, but with no time part
849 // TODO: somehow merge with buildIsoString and stripZeroTime
850 // TODO: rename. omit "string"
851 function formatDayString(marker) {
852 return marker.toISOString().replace(/T.*$/, '');
853 }
854 function formatIsoMonthStr(marker) {
855 return marker.toISOString().match(/^\d{4}-\d{2}/)[0];
856 }
857 // TODO: use Date::toISOString and use everything after the T?
858 function formatIsoTimeString(marker) {
859 return padStart(marker.getUTCHours(), 2) + ':' +
860 padStart(marker.getUTCMinutes(), 2) + ':' +
861 padStart(marker.getUTCSeconds(), 2);
862 }
863 function formatTimeZoneOffset(minutes, doIso = false) {
864 let sign = minutes < 0 ? '-' : '+';
865 let abs = Math.abs(minutes);
866 let hours = Math.floor(abs / 60);
867 let mins = Math.round(abs % 60);
868 if (doIso) {
869 return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
870 }
871 return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
872 }
873
874 function memoize(workerFunc, resEquality, teardownFunc) {
875 let currentArgs;
876 let currentRes;
877 return function (...newArgs) {
878 if (!currentArgs) {
879 currentRes = workerFunc.apply(this, newArgs);
880 }
881 else if (!isArraysEqual(currentArgs, newArgs)) {
882 if (teardownFunc) {
883 teardownFunc(currentRes);
884 }
885 let res = workerFunc.apply(this, newArgs);
886 if (!resEquality || !resEquality(res, currentRes)) {
887 currentRes = res;
888 }
889 }
890 currentArgs = newArgs;
891 return currentRes;
892 };
893 }
894 function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
895 let currentArg;
896 let currentRes;
897 return (newArg) => {
898 if (!currentArg) {
899 currentRes = workerFunc.call(this, newArg);
900 }
901 else if (!isPropsEqual(currentArg, newArg)) {
902 if (teardownFunc) {
903 teardownFunc(currentRes);
904 }
905 let res = workerFunc.call(this, newArg);
906 if (!resEquality || !resEquality(res, currentRes)) {
907 currentRes = res;
908 }
909 }
910 currentArg = newArg;
911 return currentRes;
912 };
913 }
914 function memoizeArraylike(// used at all?
915 workerFunc, resEquality, teardownFunc) {
916 let currentArgSets = [];
917 let currentResults = [];
918 return (newArgSets) => {
919 let currentLen = currentArgSets.length;
920 let newLen = newArgSets.length;
921 let i = 0;
922 for (; i < currentLen; i += 1) {
923 if (!newArgSets[i]) { // one of the old sets no longer exists
924 if (teardownFunc) {
925 teardownFunc(currentResults[i]);
926 }
927 }
928 else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
929 if (teardownFunc) {
930 teardownFunc(currentResults[i]);
931 }
932 let res = workerFunc.apply(this, newArgSets[i]);
933 if (!resEquality || !resEquality(res, currentResults[i])) {
934 currentResults[i] = res;
935 }
936 }
937 }
938 for (; i < newLen; i += 1) {
939 currentResults[i] = workerFunc.apply(this, newArgSets[i]);
940 }
941 currentArgSets = newArgSets;
942 currentResults.splice(newLen); // remove excess
943 return currentResults;
944 };
945 }
946 function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
947 let currentArgHash = {};
948 let currentResHash = {};
949 return (newArgHash) => {
950 let newResHash = {};
951 for (let key in newArgHash) {
952 if (!currentResHash[key]) {
953 newResHash[key] = workerFunc.apply(this, newArgHash[key]);
954 }
955 else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
956 if (teardownFunc) {
957 teardownFunc(currentResHash[key]);
958 }
959 let res = workerFunc.apply(this, newArgHash[key]);
960 newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))
961 ? currentResHash[key]
962 : res;
963 }
964 else {
965 newResHash[key] = currentResHash[key];
966 }
967 }
968 currentArgHash = newArgHash;
969 currentResHash = newResHash;
970 return newResHash;
971 };
972 }
973
974 const EXTENDED_SETTINGS_AND_SEVERITIES = {
975 week: 3,
976 separator: 9,
977 omitZeroMinute: 9,
978 meridiem: 9,
979 omitCommas: 9,
980 };
981 const STANDARD_DATE_PROP_SEVERITIES = {
982 timeZoneName: 7,
983 era: 6,
984 year: 5,
985 month: 4,
986 day: 2,
987 weekday: 2,
988 hour: 1,
989 minute: 1,
990 second: 1,
991 };
992 const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
993 const COMMA_RE = /,/g; // we need re for globalness
994 const MULTI_SPACE_RE = /\s+/g;
995 const LTR_RE = /\u200e/g; // control character
996 const UTC_RE = /UTC|GMT/;
997 class NativeFormatter {
998 constructor(formatSettings) {
999 let standardDateProps = {};
1000 let extendedSettings = {};
1001 let smallestUnitNum = 9; // the smallest unit in the formatter (9 is a sentinel, beyond max)
1002 for (let name in formatSettings) {
1003 if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
1004 extendedSettings[name] = formatSettings[name];
1005 const severity = EXTENDED_SETTINGS_AND_SEVERITIES[name];
1006 if (severity < 9) {
1007 smallestUnitNum = Math.min(EXTENDED_SETTINGS_AND_SEVERITIES[name], smallestUnitNum);
1008 }
1009 }
1010 else {
1011 standardDateProps[name] = formatSettings[name];
1012 if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
1013 smallestUnitNum = Math.min(STANDARD_DATE_PROP_SEVERITIES[name], smallestUnitNum);
1014 }
1015 }
1016 }
1017 this.standardDateProps = standardDateProps;
1018 this.extendedSettings = extendedSettings;
1019 this.smallestUnitNum = smallestUnitNum;
1020 this.buildFormattingFunc = memoize(buildFormattingFunc);
1021 }
1022 format(date, context) {
1023 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
1024 }
1025 formatRange(start, end, context, betterDefaultSeparator) {
1026 let { standardDateProps, extendedSettings } = this;
1027 let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
1028 if (!diffSeverity) {
1029 return this.format(start, context);
1030 }
1031 let biggestUnitForPartial = diffSeverity;
1032 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
1033 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
1034 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
1035 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
1036 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
1037 }
1038 let full0 = this.format(start, context);
1039 let full1 = this.format(end, context);
1040 if (full0 === full1) {
1041 return full0;
1042 }
1043 let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
1044 let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
1045 let partial0 = partialFormattingFunc(start);
1046 let partial1 = partialFormattingFunc(end);
1047 let insertion = findCommonInsertion(full0, partial0, full1, partial1);
1048 let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
1049 if (insertion) {
1050 return insertion.before + partial0 + separator + partial1 + insertion.after;
1051 }
1052 return full0 + separator + full1;
1053 }
1054 getSmallestUnit() {
1055 switch (this.smallestUnitNum) {
1056 case 7:
1057 case 6:
1058 case 5:
1059 return 'year';
1060 case 4:
1061 return 'month';
1062 case 3:
1063 return 'week';
1064 case 2:
1065 return 'day';
1066 default:
1067 return 'time'; // really?
1068 }
1069 }
1070 }
1071 function buildFormattingFunc(standardDateProps, extendedSettings, context) {
1072 let standardDatePropCnt = Object.keys(standardDateProps).length;
1073 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
1074 return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
1075 }
1076 if (standardDatePropCnt === 0 && extendedSettings.week) {
1077 return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
1078 }
1079 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
1080 }
1081 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
1082 standardDateProps = Object.assign({}, standardDateProps); // copy
1083 extendedSettings = Object.assign({}, extendedSettings); // copy
1084 sanitizeSettings(standardDateProps, extendedSettings);
1085 standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
1086 let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
1087 let zeroFormat; // needed?
1088 if (extendedSettings.omitZeroMinute) {
1089 let zeroProps = Object.assign({}, standardDateProps);
1090 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
1091 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
1092 }
1093 return (date) => {
1094 let { marker } = date;
1095 let format;
1096 if (zeroFormat && !marker.getUTCMinutes()) {
1097 format = zeroFormat;
1098 }
1099 else {
1100 format = normalFormat;
1101 }
1102 let s = format.format(marker);
1103 return postProcess(s, date, standardDateProps, extendedSettings, context);
1104 };
1105 }
1106 function sanitizeSettings(standardDateProps, extendedSettings) {
1107 // deal with a browser inconsistency where formatting the timezone
1108 // requires that the hour/minute be present.
1109 if (standardDateProps.timeZoneName) {
1110 if (!standardDateProps.hour) {
1111 standardDateProps.hour = '2-digit';
1112 }
1113 if (!standardDateProps.minute) {
1114 standardDateProps.minute = '2-digit';
1115 }
1116 }
1117 // only support short timezone names
1118 if (standardDateProps.timeZoneName === 'long') {
1119 standardDateProps.timeZoneName = 'short';
1120 }
1121 // if requesting to display seconds, MUST display minutes
1122 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
1123 delete extendedSettings.omitZeroMinute;
1124 }
1125 }
1126 function postProcess(s, date, standardDateProps, extendedSettings, context) {
1127 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
1128 if (standardDateProps.timeZoneName === 'short') {
1129 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
1130 'UTC' : // important to normalize for IE, which does "GMT"
1131 formatTimeZoneOffset(date.timeZoneOffset));
1132 }
1133 if (extendedSettings.omitCommas) {
1134 s = s.replace(COMMA_RE, '').trim();
1135 }
1136 if (extendedSettings.omitZeroMinute) {
1137 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
1138 }
1139 // ^ do anything that might create adjacent spaces before this point,
1140 // because MERIDIEM_RE likes to eat up loading spaces
1141 if (extendedSettings.meridiem === false) {
1142 s = s.replace(MERIDIEM_RE, '').trim();
1143 }
1144 else if (extendedSettings.meridiem === 'narrow') { // a/p
1145 s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
1146 }
1147 else if (extendedSettings.meridiem === 'short') { // am/pm
1148 s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
1149 }
1150 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
1151 s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
1152 }
1153 s = s.replace(MULTI_SPACE_RE, ' ');
1154 s = s.trim();
1155 return s;
1156 }
1157 function injectTzoStr(s, tzoStr) {
1158 let replaced = false;
1159 s = s.replace(UTC_RE, () => {
1160 replaced = true;
1161 return tzoStr;
1162 });
1163 // IE11 doesn't include UTC/GMT in the original string, so append to end
1164 if (!replaced) {
1165 s += ` ${tzoStr}`;
1166 }
1167 return s;
1168 }
1169 function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
1170 let parts = [];
1171 if (display === 'long') {
1172 parts.push(weekTextLong);
1173 }
1174 else if (display === 'short' || display === 'narrow') {
1175 parts.push(weekText);
1176 }
1177 if (display === 'long' || display === 'short') {
1178 parts.push(' ');
1179 }
1180 parts.push(locale.simpleNumberFormat.format(num));
1181 if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
1182 parts.reverse();
1183 }
1184 return parts.join('');
1185 }
1186 // Range Formatting Utils
1187 // 0 = exactly the same
1188 // 1 = different by time
1189 // and bigger
1190 function computeMarkerDiffSeverity(d0, d1, ca) {
1191 if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
1192 return 5;
1193 }
1194 if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
1195 return 4;
1196 }
1197 if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
1198 return 2;
1199 }
1200 if (timeAsMs(d0) !== timeAsMs(d1)) {
1201 return 1;
1202 }
1203 return 0;
1204 }
1205 function computePartialFormattingOptions(options, biggestUnit) {
1206 let partialOptions = {};
1207 for (let name in options) {
1208 if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
1209 STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
1210 partialOptions[name] = options[name];
1211 }
1212 }
1213 return partialOptions;
1214 }
1215 function findCommonInsertion(full0, partial0, full1, partial1) {
1216 let i0 = 0;
1217 while (i0 < full0.length) {
1218 let found0 = full0.indexOf(partial0, i0);
1219 if (found0 === -1) {
1220 break;
1221 }
1222 let before0 = full0.substr(0, found0);
1223 i0 = found0 + partial0.length;
1224 let after0 = full0.substr(i0);
1225 let i1 = 0;
1226 while (i1 < full1.length) {
1227 let found1 = full1.indexOf(partial1, i1);
1228 if (found1 === -1) {
1229 break;
1230 }
1231 let before1 = full1.substr(0, found1);
1232 i1 = found1 + partial1.length;
1233 let after1 = full1.substr(i1);
1234 if (before0 === before1 && after0 === after1) {
1235 return {
1236 before: before0,
1237 after: after0,
1238 };
1239 }
1240 }
1241 }
1242 return null;
1243 }
1244
1245 function expandZonedMarker(dateInfo, calendarSystem) {
1246 let a = calendarSystem.markerToArray(dateInfo.marker);
1247 return {
1248 marker: dateInfo.marker,
1249 timeZoneOffset: dateInfo.timeZoneOffset,
1250 array: a,
1251 year: a[0],
1252 month: a[1],
1253 day: a[2],
1254 hour: a[3],
1255 minute: a[4],
1256 second: a[5],
1257 millisecond: a[6],
1258 };
1259 }
1260
1261 function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
1262 let startInfo = expandZonedMarker(start, context.calendarSystem);
1263 let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
1264 return {
1265 date: startInfo,
1266 start: startInfo,
1267 end: endInfo,
1268 timeZone: context.timeZone,
1269 localeCodes: context.locale.codes,
1270 defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
1271 };
1272 }
1273
1274 /*
1275 TODO: fix the terminology of "formatter" vs "formatting func"
1276 */
1277 /*
1278 At the time of instantiation, this object does not know which cmd-formatting system it will use.
1279 It receives this at the time of formatting, as a setting.
1280 */
1281 class CmdFormatter {
1282 constructor(cmdStr) {
1283 this.cmdStr = cmdStr;
1284 }
1285 format(date, context, betterDefaultSeparator) {
1286 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1287 }
1288 formatRange(start, end, context, betterDefaultSeparator) {
1289 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1290 }
1291 }
1292
1293 class FuncFormatter {
1294 constructor(func) {
1295 this.func = func;
1296 }
1297 format(date, context, betterDefaultSeparator) {
1298 return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1299 }
1300 formatRange(start, end, context, betterDefaultSeparator) {
1301 return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1302 }
1303 }
1304
1305 function createFormatter(input) {
1306 if (typeof input === 'object' && input) { // non-null object
1307 return new NativeFormatter(input);
1308 }
1309 if (typeof input === 'string') {
1310 return new CmdFormatter(input);
1311 }
1312 if (typeof input === 'function') {
1313 return new FuncFormatter(input);
1314 }
1315 return null;
1316 }
1317
1318 // base options
1319 // ------------
1320 const BASE_OPTION_REFINERS = {
1321 navLinkDayClick: identity,
1322 navLinkWeekClick: identity,
1323 duration: createDuration,
1324 bootstrapFontAwesome: identity,
1325 buttonIcons: identity,
1326 customButtons: identity,
1327 defaultAllDayEventDuration: createDuration,
1328 defaultTimedEventDuration: createDuration,
1329 nextDayThreshold: createDuration,
1330 scrollTime: createDuration,
1331 scrollTimeReset: Boolean,
1332 slotMinTime: createDuration,
1333 slotMaxTime: createDuration,
1334 dayPopoverFormat: createFormatter,
1335 slotDuration: createDuration,
1336 snapDuration: createDuration,
1337 headerToolbar: identity,
1338 footerToolbar: identity,
1339 defaultRangeSeparator: String,
1340 titleRangeSeparator: String,
1341 forceEventDuration: Boolean,
1342 dayHeaders: Boolean,
1343 dayHeaderFormat: createFormatter,
1344 dayHeaderClassNames: identity,
1345 dayHeaderContent: identity,
1346 dayHeaderDidMount: identity,
1347 dayHeaderWillUnmount: identity,
1348 dayCellClassNames: identity,
1349 dayCellContent: identity,
1350 dayCellDidMount: identity,
1351 dayCellWillUnmount: identity,
1352 initialView: String,
1353 aspectRatio: Number,
1354 weekends: Boolean,
1355 weekNumberCalculation: identity,
1356 weekNumbers: Boolean,
1357 weekNumberClassNames: identity,
1358 weekNumberContent: identity,
1359 weekNumberDidMount: identity,
1360 weekNumberWillUnmount: identity,
1361 editable: Boolean,
1362 viewClassNames: identity,
1363 viewDidMount: identity,
1364 viewWillUnmount: identity,
1365 nowIndicator: Boolean,
1366 nowIndicatorClassNames: identity,
1367 nowIndicatorContent: identity,
1368 nowIndicatorDidMount: identity,
1369 nowIndicatorWillUnmount: identity,
1370 showNonCurrentDates: Boolean,
1371 lazyFetching: Boolean,
1372 startParam: String,
1373 endParam: String,
1374 timeZoneParam: String,
1375 timeZone: String,
1376 locales: identity,
1377 locale: identity,
1378 themeSystem: String,
1379 dragRevertDuration: Number,
1380 dragScroll: Boolean,
1381 allDayMaintainDuration: Boolean,
1382 unselectAuto: Boolean,
1383 dropAccept: identity,
1384 eventOrder: parseFieldSpecs,
1385 eventOrderStrict: Boolean,
1386 handleWindowResize: Boolean,
1387 windowResizeDelay: Number,
1388 longPressDelay: Number,
1389 eventDragMinDistance: Number,
1390 expandRows: Boolean,
1391 height: identity,
1392 contentHeight: identity,
1393 direction: String,
1394 weekNumberFormat: createFormatter,
1395 eventResizableFromStart: Boolean,
1396 displayEventTime: Boolean,
1397 displayEventEnd: Boolean,
1398 weekText: String,
1399 weekTextLong: String,
1400 progressiveEventRendering: Boolean,
1401 businessHours: identity,
1402 initialDate: identity,
1403 now: identity,
1404 eventDataTransform: identity,
1405 stickyHeaderDates: identity,
1406 stickyFooterScrollbar: identity,
1407 viewHeight: identity,
1408 defaultAllDay: Boolean,
1409 eventSourceFailure: identity,
1410 eventSourceSuccess: identity,
1411 eventDisplay: String,
1412 eventStartEditable: Boolean,
1413 eventDurationEditable: Boolean,
1414 eventOverlap: identity,
1415 eventConstraint: identity,
1416 eventAllow: identity,
1417 eventBackgroundColor: String,
1418 eventBorderColor: String,
1419 eventTextColor: String,
1420 eventColor: String,
1421 eventClassNames: identity,
1422 eventContent: identity,
1423 eventDidMount: identity,
1424 eventWillUnmount: identity,
1425 selectConstraint: identity,
1426 selectOverlap: identity,
1427 selectAllow: identity,
1428 droppable: Boolean,
1429 unselectCancel: String,
1430 slotLabelFormat: identity,
1431 slotLaneClassNames: identity,
1432 slotLaneContent: identity,
1433 slotLaneDidMount: identity,
1434 slotLaneWillUnmount: identity,
1435 slotLabelClassNames: identity,
1436 slotLabelContent: identity,
1437 slotLabelDidMount: identity,
1438 slotLabelWillUnmount: identity,
1439 dayMaxEvents: identity,
1440 dayMaxEventRows: identity,
1441 dayMinWidth: Number,
1442 slotLabelInterval: createDuration,
1443 allDayText: String,
1444 allDayClassNames: identity,
1445 allDayContent: identity,
1446 allDayDidMount: identity,
1447 allDayWillUnmount: identity,
1448 slotMinWidth: Number,
1449 navLinks: Boolean,
1450 eventTimeFormat: createFormatter,
1451 rerenderDelay: Number,
1452 moreLinkText: identity,
1453 moreLinkHint: identity,
1454 selectMinDistance: Number,
1455 selectable: Boolean,
1456 selectLongPressDelay: Number,
1457 eventLongPressDelay: Number,
1458 selectMirror: Boolean,
1459 eventMaxStack: Number,
1460 eventMinHeight: Number,
1461 eventMinWidth: Number,
1462 eventShortHeight: Number,
1463 slotEventOverlap: Boolean,
1464 plugins: identity,
1465 firstDay: Number,
1466 dayCount: Number,
1467 dateAlignment: String,
1468 dateIncrement: createDuration,
1469 hiddenDays: identity,
1470 fixedWeekCount: Boolean,
1471 validRange: identity,
1472 visibleRange: identity,
1473 titleFormat: identity,
1474 eventInteractive: Boolean,
1475 // only used by list-view, but languages define the value, so we need it in base options
1476 noEventsText: String,
1477 viewHint: identity,
1478 navLinkHint: identity,
1479 closeHint: String,
1480 timeHint: String,
1481 eventHint: String,
1482 moreLinkClick: identity,
1483 moreLinkClassNames: identity,
1484 moreLinkContent: identity,
1485 moreLinkDidMount: identity,
1486 moreLinkWillUnmount: identity,
1487 monthStartFormat: createFormatter,
1488 // for connectors
1489 // (can't be part of plugin system b/c must be provided at runtime)
1490 handleCustomRendering: identity,
1491 customRenderingMetaMap: identity,
1492 customRenderingReplaces: Boolean,
1493 };
1494 // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
1495 // raw values.
1496 const BASE_OPTION_DEFAULTS = {
1497 eventDisplay: 'auto',
1498 defaultRangeSeparator: ' - ',
1499 titleRangeSeparator: ' \u2013 ',
1500 defaultTimedEventDuration: '01:00:00',
1501 defaultAllDayEventDuration: { day: 1 },
1502 forceEventDuration: false,
1503 nextDayThreshold: '00:00:00',
1504 dayHeaders: true,
1505 initialView: '',
1506 aspectRatio: 1.35,
1507 headerToolbar: {
1508 start: 'title',
1509 center: '',
1510 end: 'today prev,next',
1511 },
1512 weekends: true,
1513 weekNumbers: false,
1514 weekNumberCalculation: 'local',
1515 editable: false,
1516 nowIndicator: false,
1517 scrollTime: '06:00:00',
1518 scrollTimeReset: true,
1519 slotMinTime: '00:00:00',
1520 slotMaxTime: '24:00:00',
1521 showNonCurrentDates: true,
1522 lazyFetching: true,
1523 startParam: 'start',
1524 endParam: 'end',
1525 timeZoneParam: 'timeZone',
1526 timeZone: 'local',
1527 locales: [],
1528 locale: '',
1529 themeSystem: 'standard',
1530 dragRevertDuration: 500,
1531 dragScroll: true,
1532 allDayMaintainDuration: false,
1533 unselectAuto: true,
1534 dropAccept: '*',
1535 eventOrder: 'start,-duration,allDay,title',
1536 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
1537 handleWindowResize: true,
1538 windowResizeDelay: 100,
1539 longPressDelay: 1000,
1540 eventDragMinDistance: 5,
1541 expandRows: false,
1542 navLinks: false,
1543 selectable: false,
1544 eventMinHeight: 15,
1545 eventMinWidth: 30,
1546 eventShortHeight: 30,
1547 monthStartFormat: { month: 'long', day: 'numeric' },
1548 };
1549 // calendar listeners
1550 // ------------------
1551 const CALENDAR_LISTENER_REFINERS = {
1552 datesSet: identity,
1553 eventsSet: identity,
1554 eventAdd: identity,
1555 eventChange: identity,
1556 eventRemove: identity,
1557 windowResize: identity,
1558 eventClick: identity,
1559 eventMouseEnter: identity,
1560 eventMouseLeave: identity,
1561 select: identity,
1562 unselect: identity,
1563 loading: identity,
1564 // internal
1565 _unmount: identity,
1566 _beforeprint: identity,
1567 _afterprint: identity,
1568 _noEventDrop: identity,
1569 _noEventResize: identity,
1570 _resize: identity,
1571 _scrollRequest: identity,
1572 };
1573 // calendar-specific options
1574 // -------------------------
1575 const CALENDAR_OPTION_REFINERS = {
1576 buttonText: identity,
1577 buttonHints: identity,
1578 views: identity,
1579 plugins: identity,
1580 initialEvents: identity,
1581 events: identity,
1582 eventSources: identity,
1583 };
1584 const COMPLEX_OPTION_COMPARATORS = {
1585 headerToolbar: isMaybeObjectsEqual,
1586 footerToolbar: isMaybeObjectsEqual,
1587 buttonText: isMaybeObjectsEqual,
1588 buttonHints: isMaybeObjectsEqual,
1589 buttonIcons: isMaybeObjectsEqual,
1590 dateIncrement: isMaybeObjectsEqual,
1591 plugins: isMaybeArraysEqual,
1592 events: isMaybeArraysEqual,
1593 eventSources: isMaybeArraysEqual,
1594 ['resources']: isMaybeArraysEqual,
1595 };
1596 function isMaybeObjectsEqual(a, b) {
1597 if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
1598 return isPropsEqual(a, b);
1599 }
1600 return a === b;
1601 }
1602 function isMaybeArraysEqual(a, b) {
1603 if (Array.isArray(a) && Array.isArray(b)) {
1604 return isArraysEqual(a, b);
1605 }
1606 return a === b;
1607 }
1608 // view-specific options
1609 // ---------------------
1610 const VIEW_OPTION_REFINERS = {
1611 type: String,
1612 component: identity,
1613 buttonText: String,
1614 buttonTextKey: String,
1615 dateProfileGeneratorClass: identity,
1616 usesMinMaxTime: Boolean,
1617 classNames: identity,
1618 content: identity,
1619 didMount: identity,
1620 willUnmount: identity,
1621 };
1622 // util funcs
1623 // ----------------------------------------------------------------------------------------------------
1624 function mergeRawOptions(optionSets) {
1625 return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
1626 }
1627 function refineProps(input, refiners) {
1628 let refined = {};
1629 let extra = {};
1630 for (let propName in refiners) {
1631 if (propName in input) {
1632 refined[propName] = refiners[propName](input[propName]);
1633 }
1634 }
1635 for (let propName in input) {
1636 if (!(propName in refiners)) {
1637 extra[propName] = input[propName];
1638 }
1639 }
1640 return { refined, extra };
1641 }
1642 function identity(raw) {
1643 return raw;
1644 }
1645
1646 const { hasOwnProperty } = Object.prototype;
1647 // Merges an array of objects into a single object.
1648 // The second argument allows for an array of property names who's object values will be merged together.
1649 function mergeProps(propObjs, complexPropsMap) {
1650 let dest = {};
1651 if (complexPropsMap) {
1652 for (let name in complexPropsMap) {
1653 if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable
1654 let complexObjs = [];
1655 // collect the trailing object values, stopping when a non-object is discovered
1656 for (let i = propObjs.length - 1; i >= 0; i -= 1) {
1657 let val = propObjs[i][name];
1658 if (typeof val === 'object' && val) { // non-null object
1659 complexObjs.unshift(val);
1660 }
1661 else if (val !== undefined) {
1662 dest[name] = val; // if there were no objects, this value will be used
1663 break;
1664 }
1665 }
1666 // if the trailing values were objects, use the merged value
1667 if (complexObjs.length) {
1668 dest[name] = mergeProps(complexObjs);
1669 }
1670 }
1671 }
1672 }
1673 // copy values into the destination, going from last to first
1674 for (let i = propObjs.length - 1; i >= 0; i -= 1) {
1675 let props = propObjs[i];
1676 for (let name in props) {
1677 if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
1678 dest[name] = props[name];
1679 }
1680 }
1681 }
1682 return dest;
1683 }
1684 function filterHash(hash, func) {
1685 let filtered = {};
1686 for (let key in hash) {
1687 if (func(hash[key], key)) {
1688 filtered[key] = hash[key];
1689 }
1690 }
1691 return filtered;
1692 }
1693 function mapHash(hash, func) {
1694 let newHash = {};
1695 for (let key in hash) {
1696 newHash[key] = func(hash[key], key);
1697 }
1698 return newHash;
1699 }
1700 function arrayToHash(a) {
1701 let hash = {};
1702 for (let item of a) {
1703 hash[item] = true;
1704 }
1705 return hash;
1706 }
1707 // TODO: reassess browser support
1708 // https://caniuse.com/?search=object.values
1709 function hashValuesToArray(obj) {
1710 let a = [];
1711 for (let key in obj) {
1712 a.push(obj[key]);
1713 }
1714 return a;
1715 }
1716 function isPropsEqual(obj0, obj1) {
1717 if (obj0 === obj1) {
1718 return true;
1719 }
1720 for (let key in obj0) {
1721 if (hasOwnProperty.call(obj0, key)) {
1722 if (!(key in obj1)) {
1723 return false;
1724 }
1725 }
1726 }
1727 for (let key in obj1) {
1728 if (hasOwnProperty.call(obj1, key)) {
1729 if (obj0[key] !== obj1[key]) {
1730 return false;
1731 }
1732 }
1733 }
1734 return true;
1735 }
1736 const HANDLER_RE = /^on[A-Z]/;
1737 function isNonHandlerPropsEqual(obj0, obj1) {
1738 const keys = getUnequalProps(obj0, obj1);
1739 for (let key of keys) {
1740 if (!HANDLER_RE.test(key)) {
1741 return false;
1742 }
1743 }
1744 return true;
1745 }
1746 function getUnequalProps(obj0, obj1) {
1747 let keys = [];
1748 for (let key in obj0) {
1749 if (hasOwnProperty.call(obj0, key)) {
1750 if (!(key in obj1)) {
1751 keys.push(key);
1752 }
1753 }
1754 }
1755 for (let key in obj1) {
1756 if (hasOwnProperty.call(obj1, key)) {
1757 if (obj0[key] !== obj1[key]) {
1758 keys.push(key);
1759 }
1760 }
1761 }
1762 return keys;
1763 }
1764 function compareObjs(oldProps, newProps, equalityFuncs = {}) {
1765 if (oldProps === newProps) {
1766 return true;
1767 }
1768 for (let key in newProps) {
1769 if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;
1770 else {
1771 return false;
1772 }
1773 }
1774 // check for props that were omitted in the new
1775 for (let key in oldProps) {
1776 if (!(key in newProps)) {
1777 return false;
1778 }
1779 }
1780 return true;
1781 }
1782 /*
1783 assumed "true" equality for handler names like "onReceiveSomething"
1784 */
1785 function isObjValsEqual(val0, val1, comparator) {
1786 if (val0 === val1 || comparator === true) {
1787 return true;
1788 }
1789 if (comparator) {
1790 return comparator(val0, val1);
1791 }
1792 return false;
1793 }
1794 function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
1795 let res = [];
1796 if (endIndex == null) {
1797 endIndex = Object.keys(hash).length;
1798 }
1799 for (let i = startIndex; i < endIndex; i += step) {
1800 let val = hash[i];
1801 if (val !== undefined) { // will disregard undefined for sparse arrays
1802 res.push(val);
1803 }
1804 }
1805 return res;
1806 }
1807
1808 let calendarSystemClassMap = {};
1809 function registerCalendarSystem(name, theClass) {
1810 calendarSystemClassMap[name] = theClass;
1811 }
1812 function createCalendarSystem(name) {
1813 return new calendarSystemClassMap[name]();
1814 }
1815 class GregorianCalendarSystem {
1816 getMarkerYear(d) {
1817 return d.getUTCFullYear();
1818 }
1819 getMarkerMonth(d) {
1820 return d.getUTCMonth();
1821 }
1822 getMarkerDay(d) {
1823 return d.getUTCDate();
1824 }
1825 arrayToMarker(arr) {
1826 return arrayToUtcDate(arr);
1827 }
1828 markerToArray(marker) {
1829 return dateToUtcArray(marker);
1830 }
1831 }
1832 registerCalendarSystem('gregory', GregorianCalendarSystem);
1833
1834 const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
1835 function parse(str) {
1836 let m = ISO_RE.exec(str);
1837 if (m) {
1838 let marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number(`0.${m[12]}`) * 1000 : 0));
1839 if (isValidDate(marker)) {
1840 let timeZoneOffset = null;
1841 if (m[13]) {
1842 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
1843 Number(m[18] || 0));
1844 }
1845 return {
1846 marker,
1847 isTimeUnspecified: !m[6],
1848 timeZoneOffset,
1849 };
1850 }
1851 }
1852 return null;
1853 }
1854
1855 class DateEnv {
1856 constructor(settings) {
1857 let timeZone = this.timeZone = settings.timeZone;
1858 let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
1859 if (settings.namedTimeZoneImpl && isNamedTimeZone) {
1860 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
1861 }
1862 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
1863 this.calendarSystem = createCalendarSystem(settings.calendarSystem);
1864 this.locale = settings.locale;
1865 this.weekDow = settings.locale.week.dow;
1866 this.weekDoy = settings.locale.week.doy;
1867 if (settings.weekNumberCalculation === 'ISO') {
1868 this.weekDow = 1;
1869 this.weekDoy = 4;
1870 }
1871 if (typeof settings.firstDay === 'number') {
1872 this.weekDow = settings.firstDay;
1873 }
1874 if (typeof settings.weekNumberCalculation === 'function') {
1875 this.weekNumberFunc = settings.weekNumberCalculation;
1876 }
1877 this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
1878 this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
1879 this.cmdFormatter = settings.cmdFormatter;
1880 this.defaultSeparator = settings.defaultSeparator;
1881 }
1882 // Creating / Parsing
1883 createMarker(input) {
1884 let meta = this.createMarkerMeta(input);
1885 if (meta === null) {
1886 return null;
1887 }
1888 return meta.marker;
1889 }
1890 createNowMarker() {
1891 if (this.canComputeOffset) {
1892 return this.timestampToMarker(new Date().valueOf());
1893 }
1894 // if we can't compute the current date val for a timezone,
1895 // better to give the current local date vals than UTC
1896 return arrayToUtcDate(dateToLocalArray(new Date()));
1897 }
1898 createMarkerMeta(input) {
1899 if (typeof input === 'string') {
1900 return this.parse(input);
1901 }
1902 let marker = null;
1903 if (typeof input === 'number') {
1904 marker = this.timestampToMarker(input);
1905 }
1906 else if (input instanceof Date) {
1907 input = input.valueOf();
1908 if (!isNaN(input)) {
1909 marker = this.timestampToMarker(input);
1910 }
1911 }
1912 else if (Array.isArray(input)) {
1913 marker = arrayToUtcDate(input);
1914 }
1915 if (marker === null || !isValidDate(marker)) {
1916 return null;
1917 }
1918 return { marker, isTimeUnspecified: false, forcedTzo: null };
1919 }
1920 parse(s) {
1921 let parts = parse(s);
1922 if (parts === null) {
1923 return null;
1924 }
1925 let { marker } = parts;
1926 let forcedTzo = null;
1927 if (parts.timeZoneOffset !== null) {
1928 if (this.canComputeOffset) {
1929 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
1930 }
1931 else {
1932 forcedTzo = parts.timeZoneOffset;
1933 }
1934 }
1935 return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
1936 }
1937 // Accessors
1938 getYear(marker) {
1939 return this.calendarSystem.getMarkerYear(marker);
1940 }
1941 getMonth(marker) {
1942 return this.calendarSystem.getMarkerMonth(marker);
1943 }
1944 getDay(marker) {
1945 return this.calendarSystem.getMarkerDay(marker);
1946 }
1947 // Adding / Subtracting
1948 add(marker, dur) {
1949 let a = this.calendarSystem.markerToArray(marker);
1950 a[0] += dur.years;
1951 a[1] += dur.months;
1952 a[2] += dur.days;
1953 a[6] += dur.milliseconds;
1954 return this.calendarSystem.arrayToMarker(a);
1955 }
1956 subtract(marker, dur) {
1957 let a = this.calendarSystem.markerToArray(marker);
1958 a[0] -= dur.years;
1959 a[1] -= dur.months;
1960 a[2] -= dur.days;
1961 a[6] -= dur.milliseconds;
1962 return this.calendarSystem.arrayToMarker(a);
1963 }
1964 addYears(marker, n) {
1965 let a = this.calendarSystem.markerToArray(marker);
1966 a[0] += n;
1967 return this.calendarSystem.arrayToMarker(a);
1968 }
1969 addMonths(marker, n) {
1970 let a = this.calendarSystem.markerToArray(marker);
1971 a[1] += n;
1972 return this.calendarSystem.arrayToMarker(a);
1973 }
1974 // Diffing Whole Units
1975 diffWholeYears(m0, m1) {
1976 let { calendarSystem } = this;
1977 if (timeAsMs(m0) === timeAsMs(m1) &&
1978 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
1979 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
1980 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
1981 }
1982 return null;
1983 }
1984 diffWholeMonths(m0, m1) {
1985 let { calendarSystem } = this;
1986 if (timeAsMs(m0) === timeAsMs(m1) &&
1987 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
1988 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
1989 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
1990 }
1991 return null;
1992 }
1993 // Range / Duration
1994 greatestWholeUnit(m0, m1) {
1995 let n = this.diffWholeYears(m0, m1);
1996 if (n !== null) {
1997 return { unit: 'year', value: n };
1998 }
1999 n = this.diffWholeMonths(m0, m1);
2000 if (n !== null) {
2001 return { unit: 'month', value: n };
2002 }
2003 n = diffWholeWeeks(m0, m1);
2004 if (n !== null) {
2005 return { unit: 'week', value: n };
2006 }
2007 n = diffWholeDays(m0, m1);
2008 if (n !== null) {
2009 return { unit: 'day', value: n };
2010 }
2011 n = diffHours(m0, m1);
2012 if (isInt(n)) {
2013 return { unit: 'hour', value: n };
2014 }
2015 n = diffMinutes(m0, m1);
2016 if (isInt(n)) {
2017 return { unit: 'minute', value: n };
2018 }
2019 n = diffSeconds(m0, m1);
2020 if (isInt(n)) {
2021 return { unit: 'second', value: n };
2022 }
2023 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
2024 }
2025 countDurationsBetween(m0, m1, d) {
2026 // TODO: can use greatestWholeUnit
2027 let diff;
2028 if (d.years) {
2029 diff = this.diffWholeYears(m0, m1);
2030 if (diff !== null) {
2031 return diff / asRoughYears(d);
2032 }
2033 }
2034 if (d.months) {
2035 diff = this.diffWholeMonths(m0, m1);
2036 if (diff !== null) {
2037 return diff / asRoughMonths(d);
2038 }
2039 }
2040 if (d.days) {
2041 diff = diffWholeDays(m0, m1);
2042 if (diff !== null) {
2043 return diff / asRoughDays(d);
2044 }
2045 }
2046 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
2047 }
2048 // Start-Of
2049 // these DON'T return zoned-dates. only UTC start-of dates
2050 startOf(m, unit) {
2051 if (unit === 'year') {
2052 return this.startOfYear(m);
2053 }
2054 if (unit === 'month') {
2055 return this.startOfMonth(m);
2056 }
2057 if (unit === 'week') {
2058 return this.startOfWeek(m);
2059 }
2060 if (unit === 'day') {
2061 return startOfDay(m);
2062 }
2063 if (unit === 'hour') {
2064 return startOfHour(m);
2065 }
2066 if (unit === 'minute') {
2067 return startOfMinute(m);
2068 }
2069 if (unit === 'second') {
2070 return startOfSecond(m);
2071 }
2072 return null;
2073 }
2074 startOfYear(m) {
2075 return this.calendarSystem.arrayToMarker([
2076 this.calendarSystem.getMarkerYear(m),
2077 ]);
2078 }
2079 startOfMonth(m) {
2080 return this.calendarSystem.arrayToMarker([
2081 this.calendarSystem.getMarkerYear(m),
2082 this.calendarSystem.getMarkerMonth(m),
2083 ]);
2084 }
2085 startOfWeek(m) {
2086 return this.calendarSystem.arrayToMarker([
2087 this.calendarSystem.getMarkerYear(m),
2088 this.calendarSystem.getMarkerMonth(m),
2089 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
2090 ]);
2091 }
2092 // Week Number
2093 computeWeekNumber(marker) {
2094 if (this.weekNumberFunc) {
2095 return this.weekNumberFunc(this.toDate(marker));
2096 }
2097 return weekOfYear(marker, this.weekDow, this.weekDoy);
2098 }
2099 // TODO: choke on timeZoneName: long
2100 format(marker, formatter, dateOptions = {}) {
2101 return formatter.format({
2102 marker,
2103 timeZoneOffset: dateOptions.forcedTzo != null ?
2104 dateOptions.forcedTzo :
2105 this.offsetForMarker(marker),
2106 }, this);
2107 }
2108 formatRange(start, end, formatter, dateOptions = {}) {
2109 if (dateOptions.isEndExclusive) {
2110 end = addMs(end, -1);
2111 }
2112 return formatter.formatRange({
2113 marker: start,
2114 timeZoneOffset: dateOptions.forcedStartTzo != null ?
2115 dateOptions.forcedStartTzo :
2116 this.offsetForMarker(start),
2117 }, {
2118 marker: end,
2119 timeZoneOffset: dateOptions.forcedEndTzo != null ?
2120 dateOptions.forcedEndTzo :
2121 this.offsetForMarker(end),
2122 }, this, dateOptions.defaultSeparator);
2123 }
2124 /*
2125 DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
2126 might as well use buildIsoString or some other util directly
2127 */
2128 formatIso(marker, extraOptions = {}) {
2129 let timeZoneOffset = null;
2130 if (!extraOptions.omitTimeZoneOffset) {
2131 if (extraOptions.forcedTzo != null) {
2132 timeZoneOffset = extraOptions.forcedTzo;
2133 }
2134 else {
2135 timeZoneOffset = this.offsetForMarker(marker);
2136 }
2137 }
2138 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
2139 }
2140 // TimeZone
2141 timestampToMarker(ms) {
2142 if (this.timeZone === 'local') {
2143 return arrayToUtcDate(dateToLocalArray(new Date(ms)));
2144 }
2145 if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
2146 return new Date(ms);
2147 }
2148 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
2149 }
2150 offsetForMarker(m) {
2151 if (this.timeZone === 'local') {
2152 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
2153 }
2154 if (this.timeZone === 'UTC') {
2155 return 0;
2156 }
2157 if (this.namedTimeZoneImpl) {
2158 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
2159 }
2160 return null;
2161 }
2162 // Conversion
2163 toDate(m, forcedTzo) {
2164 if (this.timeZone === 'local') {
2165 return arrayToLocalDate(dateToUtcArray(m));
2166 }
2167 if (this.timeZone === 'UTC') {
2168 return new Date(m.valueOf()); // make sure it's a copy
2169 }
2170 if (!this.namedTimeZoneImpl) {
2171 return new Date(m.valueOf() - (forcedTzo || 0));
2172 }
2173 return new Date(m.valueOf() -
2174 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
2175 }
2176 }
2177
2178 class Theme {
2179 constructor(calendarOptions) {
2180 if (this.iconOverrideOption) {
2181 this.setIconOverride(calendarOptions[this.iconOverrideOption]);
2182 }
2183 }
2184 setIconOverride(iconOverrideHash) {
2185 let iconClassesCopy;
2186 let buttonName;
2187 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
2188 iconClassesCopy = Object.assign({}, this.iconClasses);
2189 for (buttonName in iconOverrideHash) {
2190 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
2191 }
2192 this.iconClasses = iconClassesCopy;
2193 }
2194 else if (iconOverrideHash === false) {
2195 this.iconClasses = {};
2196 }
2197 }
2198 applyIconOverridePrefix(className) {
2199 let prefix = this.iconOverridePrefix;
2200 if (prefix && className.indexOf(prefix) !== 0) { // if not already present
2201 className = prefix + className;
2202 }
2203 return className;
2204 }
2205 getClass(key) {
2206 return this.classes[key] || '';
2207 }
2208 getIconClass(buttonName, isRtl) {
2209 let className;
2210 if (isRtl && this.rtlIconClasses) {
2211 className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
2212 }
2213 else {
2214 className = this.iconClasses[buttonName];
2215 }
2216 if (className) {
2217 return `${this.baseIconClass} ${className}`;
2218 }
2219 return '';
2220 }
2221 getCustomButtonIconClass(customButtonProps) {
2222 let className;
2223 if (this.iconOverrideCustomButtonOption) {
2224 className = customButtonProps[this.iconOverrideCustomButtonOption];
2225 if (className) {
2226 return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
2227 }
2228 }
2229 return '';
2230 }
2231 }
2232 Theme.prototype.classes = {};
2233 Theme.prototype.iconClasses = {};
2234 Theme.prototype.baseIconClass = '';
2235 Theme.prototype.iconOverridePrefix = '';
2236
2237 /*
2238 NOTE: this can be a public API, especially createElement for hooks.
2239 See examples/typescript-scheduler/src/index.ts
2240 */
2241 function flushSync(runBeforeFlush) {
2242 runBeforeFlush();
2243 let oldDebounceRendering = l$1.debounceRendering; // orig
2244 let callbackQ = [];
2245 function execCallbackSync(callback) {
2246 callbackQ.push(callback);
2247 }
2248 l$1.debounceRendering = execCallbackSync;
2249 D$1(y(FakeComponent, {}), document.createElement('div'));
2250 while (callbackQ.length) {
2251 callbackQ.shift()();
2252 }
2253 l$1.debounceRendering = oldDebounceRendering;
2254 }
2255 class FakeComponent extends x$1 {
2256 render() { return y('div', {}); }
2257 componentDidMount() { this.setState({}); }
2258 }
2259 // TODO: use preact/compat instead?
2260 function createContext(defaultValue) {
2261 let ContextType = G$1(defaultValue);
2262 let origProvider = ContextType.Provider;
2263 ContextType.Provider = function () {
2264 let isNew = !this.getChildContext;
2265 let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
2266 if (isNew) {
2267 let subs = [];
2268 this.shouldComponentUpdate = (_props) => {
2269 if (this.props.value !== _props.value) {
2270 subs.forEach((c) => {
2271 c.context = _props.value;
2272 c.forceUpdate();
2273 });
2274 }
2275 };
2276 this.sub = (c) => {
2277 subs.push(c);
2278 let old = c.componentWillUnmount;
2279 c.componentWillUnmount = () => {
2280 subs.splice(subs.indexOf(c), 1);
2281 old && old.call(c);
2282 };
2283 };
2284 }
2285 return children;
2286 };
2287 return ContextType;
2288 }
2289
2290 class ScrollResponder {
2291 constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
2292 this.execFunc = execFunc;
2293 this.emitter = emitter;
2294 this.scrollTime = scrollTime;
2295 this.scrollTimeReset = scrollTimeReset;
2296 this.handleScrollRequest = (request) => {
2297 this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
2298 this.drain();
2299 };
2300 emitter.on('_scrollRequest', this.handleScrollRequest);
2301 this.fireInitialScroll();
2302 }
2303 detach() {
2304 this.emitter.off('_scrollRequest', this.handleScrollRequest);
2305 }
2306 update(isDatesNew) {
2307 if (isDatesNew && this.scrollTimeReset) {
2308 this.fireInitialScroll(); // will drain
2309 }
2310 else {
2311 this.drain();
2312 }
2313 }
2314 fireInitialScroll() {
2315 this.handleScrollRequest({
2316 time: this.scrollTime,
2317 });
2318 }
2319 drain() {
2320 if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
2321 this.queuedRequest = null;
2322 }
2323 }
2324 }
2325
2326 const ViewContextType = createContext({}); // for Components
2327 function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, nowManager, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
2328 return {
2329 dateEnv,
2330 nowManager,
2331 options: viewOptions,
2332 pluginHooks,
2333 emitter,
2334 dispatch,
2335 getCurrentData,
2336 calendarApi,
2337 viewSpec,
2338 viewApi,
2339 dateProfileGenerator,
2340 theme,
2341 isRtl: viewOptions.direction === 'rtl',
2342 addResizeHandler(handler) {
2343 emitter.on('_resize', handler);
2344 },
2345 removeResizeHandler(handler) {
2346 emitter.off('_resize', handler);
2347 },
2348 createScrollResponder(execFunc) {
2349 return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
2350 },
2351 registerInteractiveComponent,
2352 unregisterInteractiveComponent,
2353 };
2354 }
2355
2356 /* eslint max-classes-per-file: off */
2357 class PureComponent extends x$1 {
2358 shouldComponentUpdate(nextProps, nextState) {
2359 if (this.debug) {
2360 // eslint-disable-next-line no-console
2361 console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
2362 }
2363 return !compareObjs(this.props, nextProps, this.propEquality) ||
2364 !compareObjs(this.state, nextState, this.stateEquality);
2365 }
2366 // HACK for freakin' React StrictMode
2367 safeSetState(newState) {
2368 if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
2369 this.setState(newState);
2370 }
2371 }
2372 }
2373 PureComponent.addPropsEquality = addPropsEquality;
2374 PureComponent.addStateEquality = addStateEquality;
2375 PureComponent.contextType = ViewContextType;
2376 PureComponent.prototype.propEquality = {};
2377 PureComponent.prototype.stateEquality = {};
2378 class BaseComponent extends PureComponent {
2379 }
2380 BaseComponent.contextType = ViewContextType;
2381 function addPropsEquality(propEquality) {
2382 let hash = Object.create(this.prototype.propEquality);
2383 Object.assign(hash, propEquality);
2384 this.prototype.propEquality = hash;
2385 }
2386 function addStateEquality(stateEquality) {
2387 let hash = Object.create(this.prototype.stateEquality);
2388 Object.assign(hash, stateEquality);
2389 this.prototype.stateEquality = hash;
2390 }
2391 // use other one
2392 function setRef(ref, current) {
2393 if (typeof ref === 'function') {
2394 ref(current);
2395 }
2396 else if (ref) {
2397 // see https://github.com/facebook/react/issues/13029
2398 ref.current = current;
2399 }
2400 }
2401
2402 class ContentInjector extends BaseComponent {
2403 constructor() {
2404 super(...arguments);
2405 this.id = guid();
2406 this.queuedDomNodes = [];
2407 this.currentDomNodes = [];
2408 this.handleEl = (el) => {
2409 const { options } = this.context;
2410 const { generatorName } = this.props;
2411 if (!options.customRenderingReplaces || !hasCustomRenderingHandler(generatorName, options)) {
2412 this.updateElRef(el);
2413 }
2414 };
2415 this.updateElRef = (el) => {
2416 if (this.props.elRef) {
2417 setRef(this.props.elRef, el);
2418 }
2419 };
2420 }
2421 render() {
2422 const { props, context } = this;
2423 const { options } = context;
2424 const { customGenerator, defaultGenerator, renderProps } = props;
2425 const attrs = buildElAttrs(props, [], this.handleEl);
2426 let useDefault = false;
2427 let innerContent;
2428 let queuedDomNodes = [];
2429 let currentGeneratorMeta;
2430 if (customGenerator != null) {
2431 const customGeneratorRes = typeof customGenerator === 'function' ?
2432 customGenerator(renderProps, y) :
2433 customGenerator;
2434 if (customGeneratorRes === true) {
2435 useDefault = true;
2436 }
2437 else {
2438 const isObject = customGeneratorRes && typeof customGeneratorRes === 'object'; // non-null
2439 if (isObject && ('html' in customGeneratorRes)) {
2440 attrs.dangerouslySetInnerHTML = { __html: customGeneratorRes.html };
2441 }
2442 else if (isObject && ('domNodes' in customGeneratorRes)) {
2443 queuedDomNodes = Array.prototype.slice.call(customGeneratorRes.domNodes);
2444 }
2445 else if (isObject
2446 ? i$1(customGeneratorRes) // vdom node
2447 : typeof customGeneratorRes !== 'function' // primitive value (like string or number)
2448 ) {
2449 // use in vdom
2450 innerContent = customGeneratorRes;
2451 }
2452 else {
2453 // an exotic object for handleCustomRendering
2454 currentGeneratorMeta = customGeneratorRes;
2455 }
2456 }
2457 }
2458 else {
2459 useDefault = !hasCustomRenderingHandler(props.generatorName, options);
2460 }
2461 if (useDefault && defaultGenerator) {
2462 innerContent = defaultGenerator(renderProps);
2463 }
2464 this.queuedDomNodes = queuedDomNodes;
2465 this.currentGeneratorMeta = currentGeneratorMeta;
2466 return y(props.elTag, attrs, innerContent);
2467 }
2468 componentDidMount() {
2469 this.applyQueueudDomNodes();
2470 this.triggerCustomRendering(true);
2471 }
2472 componentDidUpdate() {
2473 this.applyQueueudDomNodes();
2474 this.triggerCustomRendering(true);
2475 }
2476 componentWillUnmount() {
2477 this.triggerCustomRendering(false); // TODO: different API for removal?
2478 }
2479 triggerCustomRendering(isActive) {
2480 var _a;
2481 const { props, context } = this;
2482 const { handleCustomRendering, customRenderingMetaMap } = context.options;
2483 if (handleCustomRendering) {
2484 const generatorMeta = (_a = this.currentGeneratorMeta) !== null && _a !== void 0 ? _a : customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
2485 if (generatorMeta) {
2486 handleCustomRendering(Object.assign(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.updateElRef, // front-end framework tells us about new container els
2487 generatorMeta }, props), { elClasses: (props.elClasses || []).filter(isTruthy) }));
2488 }
2489 }
2490 }
2491 applyQueueudDomNodes() {
2492 const { queuedDomNodes, currentDomNodes } = this;
2493 const el = this.base;
2494 if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
2495 currentDomNodes.forEach(removeElement);
2496 for (let newNode of queuedDomNodes) {
2497 el.appendChild(newNode);
2498 }
2499 this.currentDomNodes = queuedDomNodes;
2500 }
2501 }
2502 }
2503 ContentInjector.addPropsEquality({
2504 elClasses: isArraysEqual,
2505 elStyle: isPropsEqual,
2506 elAttrs: isNonHandlerPropsEqual,
2507 renderProps: isPropsEqual,
2508 });
2509 // Util
2510 /*
2511 Does UI-framework provide custom way of rendering that does not use Preact VDOM
2512 AND does the calendar's options define custom rendering?
2513 AKA. Should we NOT render the default content?
2514 */
2515 function hasCustomRenderingHandler(generatorName, options) {
2516 var _a;
2517 return Boolean(options.handleCustomRendering &&
2518 generatorName &&
2519 ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
2520 }
2521 function buildElAttrs(props, extraClassNames, elRef) {
2522 const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: elRef });
2523 if (props.elClasses || extraClassNames) {
2524 attrs.className = (props.elClasses || [])
2525 .concat(extraClassNames || [])
2526 .concat(attrs.className || [])
2527 .filter(Boolean)
2528 .join(' ');
2529 }
2530 if (props.elStyle) {
2531 attrs.style = props.elStyle;
2532 }
2533 return attrs;
2534 }
2535 function isTruthy(val) {
2536 return Boolean(val);
2537 }
2538
2539 const RenderId = createContext(0);
2540
2541 class ContentContainer extends x$1 {
2542 constructor() {
2543 super(...arguments);
2544 this.InnerContent = InnerContentInjector.bind(undefined, this);
2545 this.handleEl = (el) => {
2546 this.el = el;
2547 if (this.props.elRef) {
2548 setRef(this.props.elRef, el);
2549 if (el && this.didMountMisfire) {
2550 this.componentDidMount();
2551 }
2552 }
2553 };
2554 }
2555 render() {
2556 const { props } = this;
2557 const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
2558 if (props.children) {
2559 const elAttrs = buildElAttrs(props, generatedClassNames, this.handleEl);
2560 const children = props.children(this.InnerContent, props.renderProps, elAttrs);
2561 if (props.elTag) {
2562 return y(props.elTag, elAttrs, children);
2563 }
2564 else {
2565 return children;
2566 }
2567 }
2568 else {
2569 return y((ContentInjector), Object.assign(Object.assign({}, props), { elRef: this.handleEl, elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));
2570 }
2571 }
2572 componentDidMount() {
2573 var _a, _b;
2574 if (this.el) {
2575 (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
2576 }
2577 else {
2578 this.didMountMisfire = true;
2579 }
2580 }
2581 componentWillUnmount() {
2582 var _a, _b;
2583 (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
2584 }
2585 }
2586 ContentContainer.contextType = RenderId;
2587 function InnerContentInjector(containerComponent, props) {
2588 const parentProps = containerComponent.props;
2589 return y((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, customGenerator: parentProps.customGenerator, defaultGenerator: parentProps.defaultGenerator, renderId: containerComponent.context }, props));
2590 }
2591 // Utils
2592 function generateClassNames(classNameGenerator, renderProps) {
2593 const classNames = typeof classNameGenerator === 'function' ?
2594 classNameGenerator(renderProps) :
2595 classNameGenerator || [];
2596 return typeof classNames === 'string' ? [classNames] : classNames;
2597 }
2598
2599 class ViewContainer extends BaseComponent {
2600 render() {
2601 let { props, context } = this;
2602 let { options } = context;
2603 let renderProps = { view: context.viewApi };
2604 return (y(ContentContainer, Object.assign({}, props, { elTag: props.elTag || 'div', elClasses: [
2605 ...buildViewClassNames(props.viewSpec),
2606 ...(props.elClasses || []),
2607 ], renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }), () => props.children));
2608 }
2609 }
2610 function buildViewClassNames(viewSpec) {
2611 return [
2612 `fc-${viewSpec.type}-view`,
2613 'fc-view',
2614 ];
2615 }
2616
2617 function parseRange(input, dateEnv) {
2618 let start = null;
2619 let end = null;
2620 if (input.start) {
2621 start = dateEnv.createMarker(input.start);
2622 }
2623 if (input.end) {
2624 end = dateEnv.createMarker(input.end);
2625 }
2626 if (!start && !end) {
2627 return null;
2628 }
2629 if (start && end && end < start) {
2630 return null;
2631 }
2632 return { start, end };
2633 }
2634 // SIDE-EFFECT: will mutate ranges.
2635 // Will return a new array result.
2636 function invertRanges(ranges, constraintRange) {
2637 let invertedRanges = [];
2638 let { start } = constraintRange; // the end of the previous range. the start of the new range
2639 let i;
2640 let dateRange;
2641 // ranges need to be in order. required for our date-walking algorithm
2642 ranges.sort(compareRanges);
2643 for (i = 0; i < ranges.length; i += 1) {
2644 dateRange = ranges[i];
2645 // add the span of time before the event (if there is any)
2646 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
2647 invertedRanges.push({ start, end: dateRange.start });
2648 }
2649 if (dateRange.end > start) {
2650 start = dateRange.end;
2651 }
2652 }
2653 // add the span of time after the last event (if there is any)
2654 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
2655 invertedRanges.push({ start, end: constraintRange.end });
2656 }
2657 return invertedRanges;
2658 }
2659 function compareRanges(range0, range1) {
2660 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
2661 }
2662 function intersectRanges(range0, range1) {
2663 let { start, end } = range0;
2664 let newRange = null;
2665 if (range1.start !== null) {
2666 if (start === null) {
2667 start = range1.start;
2668 }
2669 else {
2670 start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
2671 }
2672 }
2673 if (range1.end != null) {
2674 if (end === null) {
2675 end = range1.end;
2676 }
2677 else {
2678 end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
2679 }
2680 }
2681 if (start === null || end === null || start < end) {
2682 newRange = { start, end };
2683 }
2684 return newRange;
2685 }
2686 function rangesEqual(range0, range1) {
2687 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
2688 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
2689 }
2690 function rangesIntersect(range0, range1) {
2691 return (range0.end === null || range1.start === null || range0.end > range1.start) &&
2692 (range0.start === null || range1.end === null || range0.start < range1.end);
2693 }
2694 function rangeContainsRange(outerRange, innerRange) {
2695 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
2696 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
2697 }
2698 function rangeContainsMarker(range, date) {
2699 return (range.start === null || date >= range.start) &&
2700 (range.end === null || date < range.end);
2701 }
2702 // If the given date is not within the given range, move it inside.
2703 // (If it's past the end, make it one millisecond before the end).
2704 function constrainMarkerToRange(date, range) {
2705 if (range.start != null && date < range.start) {
2706 return range.start;
2707 }
2708 if (range.end != null && date >= range.end) {
2709 return new Date(range.end.valueOf() - 1);
2710 }
2711 return date;
2712 }
2713
2714 /* Date stuff that doesn't belong in datelib core
2715 ----------------------------------------------------------------------------------------------------------------------*/
2716 // given a timed range, computes an all-day range that has the same exact duration,
2717 // but whose start time is aligned with the start of the day.
2718 function computeAlignedDayRange(timedRange) {
2719 let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
2720 let start = startOfDay(timedRange.start);
2721 let end = addDays(start, dayCnt);
2722 return { start, end };
2723 }
2724 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
2725 // TODO: give nextDayThreshold a default arg
2726 function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
2727 let startDay = null;
2728 let endDay = null;
2729 if (timedRange.end) {
2730 endDay = startOfDay(timedRange.end);
2731 let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
2732 // If the end time is actually inclusively part of the next day and is equal to or
2733 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
2734 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
2735 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
2736 endDay = addDays(endDay, 1);
2737 }
2738 }
2739 if (timedRange.start) {
2740 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
2741 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
2742 if (endDay && endDay <= startDay) {
2743 endDay = addDays(startDay, 1);
2744 }
2745 }
2746 return { start: startDay, end: endDay };
2747 }
2748 // spans from one day into another?
2749 function isMultiDayRange(range) {
2750 let visibleRange = computeVisibleDayRange(range);
2751 return diffDays(visibleRange.start, visibleRange.end) > 1;
2752 }
2753 function diffDates(date0, date1, dateEnv, largeUnit) {
2754 if (largeUnit === 'year') {
2755 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
2756 }
2757 if (largeUnit === 'month') {
2758 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
2759 }
2760 return diffDayAndTime(date0, date1); // returns a duration
2761 }
2762
2763 class DateProfileGenerator {
2764 constructor(props) {
2765 this.props = props;
2766 this.initHiddenDays();
2767 }
2768 /* Date Range Computation
2769 ------------------------------------------------------------------------------------------------------------------*/
2770 // Builds a structure with info about what the dates/ranges will be for the "prev" view.
2771 buildPrev(currentDateProfile, currentDate, forceToValid) {
2772 let { dateEnv } = this.props;
2773 let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2774 currentDateProfile.dateIncrement);
2775 return this.build(prevDate, -1, forceToValid);
2776 }
2777 // Builds a structure with info about what the dates/ranges will be for the "next" view.
2778 buildNext(currentDateProfile, currentDate, forceToValid) {
2779 let { dateEnv } = this.props;
2780 let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
2781 currentDateProfile.dateIncrement);
2782 return this.build(nextDate, 1, forceToValid);
2783 }
2784 // Builds a structure holding dates/ranges for rendering around the given date.
2785 // Optional direction param indicates whether the date is being incremented/decremented
2786 // from its previous value. decremented = -1, incremented = 1 (default).
2787 build(currentDate, direction, forceToValid = true) {
2788 let { props } = this;
2789 let validRange;
2790 let currentInfo;
2791 let isRangeAllDay;
2792 let renderRange;
2793 let activeRange;
2794 let isValid;
2795 validRange = this.buildValidRange();
2796 validRange = this.trimHiddenDays(validRange);
2797 if (forceToValid) {
2798 currentDate = constrainMarkerToRange(currentDate, validRange);
2799 }
2800 currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
2801 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
2802 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
2803 renderRange = this.trimHiddenDays(renderRange);
2804 activeRange = renderRange;
2805 if (!props.showNonCurrentDates) {
2806 activeRange = intersectRanges(activeRange, currentInfo.range);
2807 }
2808 activeRange = this.adjustActiveRange(activeRange);
2809 activeRange = intersectRanges(activeRange, validRange); // might return null
2810 // it's invalid if the originally requested date is not contained,
2811 // or if the range is completely outside of the valid range.
2812 isValid = rangesIntersect(currentInfo.range, validRange);
2813 // HACK: constrain to render-range so `currentDate` is more useful to view rendering
2814 if (!rangeContainsMarker(renderRange, currentDate)) {
2815 currentDate = renderRange.start;
2816 }
2817 return {
2818 currentDate,
2819 // constraint for where prev/next operations can go and where events can be dragged/resized to.
2820 // an object with optional start and end properties.
2821 validRange,
2822 // range the view is formally responsible for.
2823 // for example, a month view might have 1st-31st, excluding padded dates
2824 currentRange: currentInfo.range,
2825 // name of largest unit being displayed, like "month" or "week"
2826 currentRangeUnit: currentInfo.unit,
2827 isRangeAllDay,
2828 // dates that display events and accept drag-n-drop
2829 // will be `null` if no dates accept events
2830 activeRange,
2831 // date range with a rendered skeleton
2832 // includes not-active days that need some sort of DOM
2833 renderRange,
2834 // Duration object that denotes the first visible time of any given day
2835 slotMinTime: props.slotMinTime,
2836 // Duration object that denotes the exclusive visible end time of any given day
2837 slotMaxTime: props.slotMaxTime,
2838 isValid,
2839 // how far the current date will move for a prev/next operation
2840 dateIncrement: this.buildDateIncrement(currentInfo.duration),
2841 // pass a fallback (might be null) ^
2842 };
2843 }
2844 // Builds an object with optional start/end properties.
2845 // Indicates the minimum/maximum dates to display.
2846 // not responsible for trimming hidden days.
2847 buildValidRange() {
2848 let input = this.props.validRangeInput;
2849 let simpleInput = typeof input === 'function'
2850 ? input.call(this.props.calendarApi, this.props.dateEnv.toDate(this.props.nowManager.getDateMarker()))
2851 : input;
2852 return this.refineRange(simpleInput) ||
2853 { start: null, end: null }; // completely open-ended
2854 }
2855 // Builds a structure with info about the "current" range, the range that is
2856 // highlighted as being the current month for example.
2857 // See build() for a description of `direction`.
2858 // Guaranteed to have `range` and `unit` properties. `duration` is optional.
2859 buildCurrentRangeInfo(date, direction) {
2860 let { props } = this;
2861 let duration = null;
2862 let unit = null;
2863 let range = null;
2864 let dayCount;
2865 if (props.duration) {
2866 duration = props.duration;
2867 unit = props.durationUnit;
2868 range = this.buildRangeFromDuration(date, direction, duration, unit);
2869 }
2870 else if ((dayCount = this.props.dayCount)) {
2871 unit = 'day';
2872 range = this.buildRangeFromDayCount(date, direction, dayCount);
2873 }
2874 else if ((range = this.buildCustomVisibleRange(date))) {
2875 unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
2876 }
2877 else {
2878 duration = this.getFallbackDuration();
2879 unit = greatestDurationDenominator(duration).unit;
2880 range = this.buildRangeFromDuration(date, direction, duration, unit);
2881 }
2882 return { duration, unit, range };
2883 }
2884 getFallbackDuration() {
2885 return createDuration({ day: 1 });
2886 }
2887 // Returns a new activeRange to have time values (un-ambiguate)
2888 // slotMinTime or slotMaxTime causes the range to expand.
2889 adjustActiveRange(range) {
2890 let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;
2891 let { start, end } = range;
2892 if (usesMinMaxTime) {
2893 // expand active range if slotMinTime is negative (why not when positive?)
2894 if (asRoughDays(slotMinTime) < 0) {
2895 start = startOfDay(start); // necessary?
2896 start = dateEnv.add(start, slotMinTime);
2897 }
2898 // expand active range if slotMaxTime is beyond one day (why not when negative?)
2899 if (asRoughDays(slotMaxTime) > 1) {
2900 end = startOfDay(end); // necessary?
2901 end = addDays(end, -1);
2902 end = dateEnv.add(end, slotMaxTime);
2903 }
2904 }
2905 return { start, end };
2906 }
2907 // Builds the "current" range when it is specified as an explicit duration.
2908 // `unit` is the already-computed greatestDurationDenominator unit of duration.
2909 buildRangeFromDuration(date, direction, duration, unit) {
2910 let { dateEnv, dateAlignment } = this.props;
2911 let start;
2912 let end;
2913 let res;
2914 // compute what the alignment should be
2915 if (!dateAlignment) {
2916 let { dateIncrement } = this.props;
2917 if (dateIncrement) {
2918 // use the smaller of the two units
2919 if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
2920 dateAlignment = greatestDurationDenominator(dateIncrement).unit;
2921 }
2922 else {
2923 dateAlignment = unit;
2924 }
2925 }
2926 else {
2927 dateAlignment = unit;
2928 }
2929 }
2930 // if the view displays a single day or smaller
2931 if (asRoughDays(duration) <= 1) {
2932 if (this.isHiddenDay(start)) {
2933 start = this.skipHiddenDays(start, direction);
2934 start = startOfDay(start);
2935 }
2936 }
2937 function computeRes() {
2938 start = dateEnv.startOf(date, dateAlignment);
2939 end = dateEnv.add(start, duration);
2940 res = { start, end };
2941 }
2942 computeRes();
2943 // if range is completely enveloped by hidden days, go past the hidden days
2944 if (!this.trimHiddenDays(res)) {
2945 date = this.skipHiddenDays(date, direction);
2946 computeRes();
2947 }
2948 return res;
2949 }
2950 // Builds the "current" range when a dayCount is specified.
2951 buildRangeFromDayCount(date, direction, dayCount) {
2952 let { dateEnv, dateAlignment } = this.props;
2953 let runningCount = 0;
2954 let start = date;
2955 let end;
2956 if (dateAlignment) {
2957 start = dateEnv.startOf(start, dateAlignment);
2958 }
2959 start = startOfDay(start);
2960 start = this.skipHiddenDays(start, direction);
2961 end = start;
2962 do {
2963 end = addDays(end, 1);
2964 if (!this.isHiddenDay(end)) {
2965 runningCount += 1;
2966 }
2967 } while (runningCount < dayCount);
2968 return { start, end };
2969 }
2970 // Builds a normalized range object for the "visible" range,
2971 // which is a way to define the currentRange and activeRange at the same time.
2972 buildCustomVisibleRange(date) {
2973 let { props } = this;
2974 let input = props.visibleRangeInput;
2975 let simpleInput = typeof input === 'function'
2976 ? input.call(props.calendarApi, props.dateEnv.toDate(date))
2977 : input;
2978 let range = this.refineRange(simpleInput);
2979 if (range && (range.start == null || range.end == null)) {
2980 return null;
2981 }
2982 return range;
2983 }
2984 // Computes the range that will represent the element/cells for *rendering*,
2985 // but which may have voided days/times.
2986 // not responsible for trimming hidden days.
2987 buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
2988 return currentRange;
2989 }
2990 // Compute the duration value that should be added/substracted to the current date
2991 // when a prev/next operation happens.
2992 buildDateIncrement(fallback) {
2993 let { dateIncrement } = this.props;
2994 let customAlignment;
2995 if (dateIncrement) {
2996 return dateIncrement;
2997 }
2998 if ((customAlignment = this.props.dateAlignment)) {
2999 return createDuration(1, customAlignment);
3000 }
3001 if (fallback) {
3002 return fallback;
3003 }
3004 return createDuration({ days: 1 });
3005 }
3006 refineRange(rangeInput) {
3007 if (rangeInput) {
3008 let range = parseRange(rangeInput, this.props.dateEnv);
3009 if (range) {
3010 range = computeVisibleDayRange(range);
3011 }
3012 return range;
3013 }
3014 return null;
3015 }
3016 /* Hidden Days
3017 ------------------------------------------------------------------------------------------------------------------*/
3018 // Initializes internal variables related to calculating hidden days-of-week
3019 initHiddenDays() {
3020 let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
3021 let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
3022 let dayCnt = 0;
3023 let i;
3024 if (this.props.weekends === false) {
3025 hiddenDays.push(0, 6); // 0=sunday, 6=saturday
3026 }
3027 for (i = 0; i < 7; i += 1) {
3028 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
3029 dayCnt += 1;
3030 }
3031 }
3032 if (!dayCnt) {
3033 throw new Error('invalid hiddenDays'); // all days were hidden? bad.
3034 }
3035 this.isHiddenDayHash = isHiddenDayHash;
3036 }
3037 // Remove days from the beginning and end of the range that are computed as hidden.
3038 // If the whole range is trimmed off, returns null
3039 trimHiddenDays(range) {
3040 let { start, end } = range;
3041 if (start) {
3042 start = this.skipHiddenDays(start);
3043 }
3044 if (end) {
3045 end = this.skipHiddenDays(end, -1, true);
3046 }
3047 if (start == null || end == null || start < end) {
3048 return { start, end };
3049 }
3050 return null;
3051 }
3052 // Is the current day hidden?
3053 // `day` is a day-of-week index (0-6), or a Date (used for UTC)
3054 isHiddenDay(day) {
3055 if (day instanceof Date) {
3056 day = day.getUTCDay();
3057 }
3058 return this.isHiddenDayHash[day];
3059 }
3060 // Incrementing the current day until it is no longer a hidden day, returning a copy.
3061 // DOES NOT CONSIDER validRange!
3062 // If the initial value of `date` is not a hidden day, don't do anything.
3063 // Pass `isExclusive` as `true` if you are dealing with an end date.
3064 // `inc` defaults to `1` (increment one day forward each time)
3065 skipHiddenDays(date, inc = 1, isExclusive = false) {
3066 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
3067 date = addDays(date, inc);
3068 }
3069 return date;
3070 }
3071 }
3072
3073 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
3074 return {
3075 instanceId: guid(),
3076 defId,
3077 range,
3078 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
3079 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
3080 };
3081 }
3082
3083 function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
3084 for (let i = 0; i < recurringTypes.length; i += 1) {
3085 let parsed = recurringTypes[i].parse(refined, dateEnv);
3086 if (parsed) {
3087 let { allDay } = refined;
3088 if (allDay == null) {
3089 allDay = defaultAllDay;
3090 if (allDay == null) {
3091 allDay = parsed.allDayGuess;
3092 if (allDay == null) {
3093 allDay = false;
3094 }
3095 }
3096 }
3097 return {
3098 allDay,
3099 duration: parsed.duration,
3100 typeData: parsed.typeData,
3101 typeId: i,
3102 };
3103 }
3104 }
3105 return null;
3106 }
3107 function expandRecurring(eventStore, framingRange, context) {
3108 let { dateEnv, pluginHooks, options } = context;
3109 let { defs, instances } = eventStore;
3110 // remove existing recurring instances
3111 // TODO: bad. always expand events as a second step
3112 instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
3113 for (let defId in defs) {
3114 let def = defs[defId];
3115 if (def.recurringDef) {
3116 let { duration } = def.recurringDef;
3117 if (!duration) {
3118 duration = def.allDay ?
3119 options.defaultAllDayEventDuration :
3120 options.defaultTimedEventDuration;
3121 }
3122 let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
3123 for (let start of starts) {
3124 let instance = createEventInstance(defId, {
3125 start,
3126 end: dateEnv.add(start, duration),
3127 });
3128 instances[instance.instanceId] = instance;
3129 }
3130 }
3131 }
3132 return { defs, instances };
3133 }
3134 /*
3135 Event MUST have a recurringDef
3136 */
3137 function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
3138 let typeDef = recurringTypes[eventDef.recurringDef.typeId];
3139 let markers = typeDef.expand(eventDef.recurringDef.typeData, {
3140 start: dateEnv.subtract(framingRange.start, duration),
3141 end: framingRange.end,
3142 }, dateEnv);
3143 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
3144 if (eventDef.allDay) {
3145 markers = markers.map(startOfDay);
3146 }
3147 return markers;
3148 }
3149
3150 const EVENT_NON_DATE_REFINERS = {
3151 id: String,
3152 groupId: String,
3153 title: String,
3154 url: String,
3155 interactive: Boolean,
3156 };
3157 const EVENT_DATE_REFINERS = {
3158 start: identity,
3159 end: identity,
3160 date: identity,
3161 allDay: Boolean,
3162 };
3163 const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });
3164 function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context), defIdMap, instanceIdMap) {
3165 let { refined, extra } = refineEventDef(raw, context, refiners);
3166 let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
3167 let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
3168 if (recurringRes) {
3169 let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context, defIdMap);
3170 def.recurringDef = {
3171 typeId: recurringRes.typeId,
3172 typeData: recurringRes.typeData,
3173 duration: recurringRes.duration,
3174 };
3175 return { def, instance: null };
3176 }
3177 let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
3178 if (singleRes) {
3179 let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context, defIdMap);
3180 let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
3181 if (instanceIdMap && def.publicId && instanceIdMap[def.publicId]) {
3182 instance.instanceId = instanceIdMap[def.publicId];
3183 }
3184 return { def, instance };
3185 }
3186 return null;
3187 }
3188 function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
3189 return refineProps(raw, refiners);
3190 }
3191 function buildEventRefiners(context) {
3192 return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
3193 }
3194 /*
3195 Will NOT populate extendedProps with the leftover properties.
3196 Will NOT populate date-related props.
3197 */
3198 function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context, defIdMap) {
3199 let def = {
3200 title: refined.title || '',
3201 groupId: refined.groupId || '',
3202 publicId: refined.id || '',
3203 url: refined.url || '',
3204 recurringDef: null,
3205 defId: ((defIdMap && refined.id) ? defIdMap[refined.id] : '') || guid(),
3206 sourceId,
3207 allDay,
3208 hasEnd,
3209 interactive: refined.interactive,
3210 ui: createEventUi(refined, context),
3211 extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
3212 };
3213 for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
3214 Object.assign(def, memberAdder(refined));
3215 }
3216 // help out EventImpl from having user modify props
3217 Object.freeze(def.ui.classNames);
3218 Object.freeze(def.extendedProps);
3219 return def;
3220 }
3221 function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
3222 let { allDay } = refined;
3223 let startMeta;
3224 let startMarker = null;
3225 let hasEnd = false;
3226 let endMeta;
3227 let endMarker = null;
3228 let startInput = refined.start != null ? refined.start : refined.date;
3229 startMeta = context.dateEnv.createMarkerMeta(startInput);
3230 if (startMeta) {
3231 startMarker = startMeta.marker;
3232 }
3233 else if (!allowOpenRange) {
3234 return null;
3235 }
3236 if (refined.end != null) {
3237 endMeta = context.dateEnv.createMarkerMeta(refined.end);
3238 }
3239 if (allDay == null) {
3240 if (defaultAllDay != null) {
3241 allDay = defaultAllDay;
3242 }
3243 else {
3244 // fall back to the date props LAST
3245 allDay = (!startMeta || startMeta.isTimeUnspecified) &&
3246 (!endMeta || endMeta.isTimeUnspecified);
3247 }
3248 }
3249 if (allDay && startMarker) {
3250 startMarker = startOfDay(startMarker);
3251 }
3252 if (endMeta) {
3253 endMarker = endMeta.marker;
3254 if (allDay) {
3255 endMarker = startOfDay(endMarker);
3256 }
3257 if (startMarker && endMarker <= startMarker) {
3258 endMarker = null;
3259 }
3260 }
3261 if (endMarker) {
3262 hasEnd = true;
3263 }
3264 else if (!allowOpenRange) {
3265 hasEnd = context.options.forceEventDuration || false;
3266 endMarker = context.dateEnv.add(startMarker, allDay ?
3267 context.options.defaultAllDayEventDuration :
3268 context.options.defaultTimedEventDuration);
3269 }
3270 return {
3271 allDay,
3272 hasEnd,
3273 range: { start: startMarker, end: endMarker },
3274 forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
3275 forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
3276 };
3277 }
3278 function computeIsDefaultAllDay(eventSource, context) {
3279 let res = null;
3280 if (eventSource) {
3281 res = eventSource.defaultAllDay;
3282 }
3283 if (res == null) {
3284 res = context.options.defaultAllDay;
3285 }
3286 return res;
3287 }
3288
3289 function parseEvents(rawEvents, eventSource, context, allowOpenRange, defIdMap, instanceIdMap) {
3290 let eventStore = createEmptyEventStore();
3291 let eventRefiners = buildEventRefiners(context);
3292 for (let rawEvent of rawEvents) {
3293 let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners, defIdMap, instanceIdMap);
3294 if (tuple) {
3295 eventTupleToStore(tuple, eventStore);
3296 }
3297 }
3298 return eventStore;
3299 }
3300 function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
3301 eventStore.defs[tuple.def.defId] = tuple.def;
3302 if (tuple.instance) {
3303 eventStore.instances[tuple.instance.instanceId] = tuple.instance;
3304 }
3305 return eventStore;
3306 }
3307 // retrieves events that have the same groupId as the instance specified by `instanceId`
3308 // or they are the same as the instance.
3309 // why might instanceId not be in the store? an event from another calendar?
3310 function getRelevantEvents(eventStore, instanceId) {
3311 let instance = eventStore.instances[instanceId];
3312 if (instance) {
3313 let def = eventStore.defs[instance.defId];
3314 // get events/instances with same group
3315 let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
3316 // add the original
3317 // TODO: wish we could use eventTupleToStore or something like it
3318 newStore.defs[def.defId] = def;
3319 newStore.instances[instance.instanceId] = instance;
3320 return newStore;
3321 }
3322 return createEmptyEventStore();
3323 }
3324 function isEventDefsGrouped(def0, def1) {
3325 return Boolean(def0.groupId && def0.groupId === def1.groupId);
3326 }
3327 function createEmptyEventStore() {
3328 return { defs: {}, instances: {} };
3329 }
3330 function mergeEventStores(store0, store1) {
3331 return {
3332 defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
3333 instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
3334 };
3335 }
3336 function filterEventStoreDefs(eventStore, filterFunc) {
3337 let defs = filterHash(eventStore.defs, filterFunc);
3338 let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
3339 ));
3340 return { defs, instances };
3341 }
3342 function excludeSubEventStore(master, sub) {
3343 let { defs, instances } = master;
3344 let filteredDefs = {};
3345 let filteredInstances = {};
3346 for (let defId in defs) {
3347 if (!sub.defs[defId]) { // not explicitly excluded
3348 filteredDefs[defId] = defs[defId];
3349 }
3350 }
3351 for (let instanceId in instances) {
3352 if (!sub.instances[instanceId] && // not explicitly excluded
3353 filteredDefs[instances[instanceId].defId] // def wasn't filtered away
3354 ) {
3355 filteredInstances[instanceId] = instances[instanceId];
3356 }
3357 }
3358 return {
3359 defs: filteredDefs,
3360 instances: filteredInstances,
3361 };
3362 }
3363
3364 function normalizeConstraint(input, context) {
3365 if (Array.isArray(input)) {
3366 return parseEvents(input, null, context, true); // allowOpenRange=true
3367 }
3368 if (typeof input === 'object' && input) { // non-null object
3369 return parseEvents([input], null, context, true); // allowOpenRange=true
3370 }
3371 if (input != null) {
3372 return String(input);
3373 }
3374 return null;
3375 }
3376
3377 function parseClassNames(raw) {
3378 if (Array.isArray(raw)) {
3379 return raw;
3380 }
3381 if (typeof raw === 'string') {
3382 return raw.split(/\s+/);
3383 }
3384 return [];
3385 }
3386
3387 // TODO: better called "EventSettings" or "EventConfig"
3388 // TODO: move this file into structs
3389 // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
3390 const EVENT_UI_REFINERS = {
3391 display: String,
3392 editable: Boolean,
3393 startEditable: Boolean,
3394 durationEditable: Boolean,
3395 constraint: identity,
3396 overlap: identity,
3397 allow: identity,
3398 className: parseClassNames,
3399 classNames: parseClassNames,
3400 color: String,
3401 backgroundColor: String,
3402 borderColor: String,
3403 textColor: String,
3404 };
3405 const EMPTY_EVENT_UI = {
3406 display: null,
3407 startEditable: null,
3408 durationEditable: null,
3409 constraints: [],
3410 overlap: null,
3411 allows: [],
3412 backgroundColor: '',
3413 borderColor: '',
3414 textColor: '',
3415 classNames: [],
3416 };
3417 function createEventUi(refined, context) {
3418 let constraint = normalizeConstraint(refined.constraint, context);
3419 return {
3420 display: refined.display || null,
3421 startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
3422 durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
3423 constraints: constraint != null ? [constraint] : [],
3424 overlap: refined.overlap != null ? refined.overlap : null,
3425 allows: refined.allow != null ? [refined.allow] : [],
3426 backgroundColor: refined.backgroundColor || refined.color || '',
3427 borderColor: refined.borderColor || refined.color || '',
3428 textColor: refined.textColor || '',
3429 classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
3430 };
3431 }
3432 // TODO: prevent against problems with <2 args!
3433 function combineEventUis(uis) {
3434 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
3435 }
3436 function combineTwoEventUis(item0, item1) {
3437 return {
3438 display: item1.display != null ? item1.display : item0.display,
3439 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
3440 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
3441 constraints: item0.constraints.concat(item1.constraints),
3442 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
3443 allows: item0.allows.concat(item1.allows),
3444 backgroundColor: item1.backgroundColor || item0.backgroundColor,
3445 borderColor: item1.borderColor || item0.borderColor,
3446 textColor: item1.textColor || item0.textColor,
3447 classNames: item0.classNames.concat(item1.classNames),
3448 };
3449 }
3450
3451 const EVENT_SOURCE_REFINERS = {
3452 id: String,
3453 defaultAllDay: Boolean,
3454 url: String,
3455 format: String,
3456 events: identity,
3457 eventDataTransform: identity,
3458 // for any network-related sources
3459 success: identity,
3460 failure: identity,
3461 };
3462 function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
3463 let rawObj;
3464 if (typeof raw === 'string') {
3465 rawObj = { url: raw };
3466 }
3467 else if (typeof raw === 'function' || Array.isArray(raw)) {
3468 rawObj = { events: raw };
3469 }
3470 else if (typeof raw === 'object' && raw) { // not null
3471 rawObj = raw;
3472 }
3473 if (rawObj) {
3474 let { refined, extra } = refineProps(rawObj, refiners);
3475 let metaRes = buildEventSourceMeta(refined, context);
3476 if (metaRes) {
3477 return {
3478 _raw: raw,
3479 isFetching: false,
3480 latestFetchId: '',
3481 fetchRange: null,
3482 defaultAllDay: refined.defaultAllDay,
3483 eventDataTransform: refined.eventDataTransform,
3484 success: refined.success,
3485 failure: refined.failure,
3486 publicId: refined.id || '',
3487 sourceId: guid(),
3488 sourceDefId: metaRes.sourceDefId,
3489 meta: metaRes.meta,
3490 ui: createEventUi(refined, context),
3491 extendedProps: extra,
3492 };
3493 }
3494 }
3495 return null;
3496 }
3497 function buildEventSourceRefiners(context) {
3498 return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
3499 }
3500 function buildEventSourceMeta(raw, context) {
3501 let defs = context.pluginHooks.eventSourceDefs;
3502 for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
3503 let def = defs[i];
3504 let meta = def.parseMeta(raw);
3505 if (meta) {
3506 return { sourceDefId: i, meta };
3507 }
3508 }
3509 return null;
3510 }
3511
3512 function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
3513 switch (action.type) {
3514 case 'RECEIVE_EVENTS': // raw
3515 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
3516 case 'RESET_RAW_EVENTS':
3517 return resetRawEvents(eventStore, eventSources[action.sourceId], action.rawEvents, dateProfile.activeRange, context);
3518 case 'ADD_EVENTS': // already parsed, but not expanded
3519 return addEvent(eventStore, action.eventStore, // new ones
3520 dateProfile ? dateProfile.activeRange : null, context);
3521 case 'RESET_EVENTS':
3522 return action.eventStore;
3523 case 'MERGE_EVENTS': // already parsed and expanded
3524 return mergeEventStores(eventStore, action.eventStore);
3525 case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
3526 case 'NEXT':
3527 case 'CHANGE_DATE':
3528 case 'CHANGE_VIEW_TYPE':
3529 if (dateProfile) {
3530 return expandRecurring(eventStore, dateProfile.activeRange, context);
3531 }
3532 return eventStore;
3533 case 'REMOVE_EVENTS':
3534 return excludeSubEventStore(eventStore, action.eventStore);
3535 case 'REMOVE_EVENT_SOURCE':
3536 return excludeEventsBySourceId(eventStore, action.sourceId);
3537 case 'REMOVE_ALL_EVENT_SOURCES':
3538 return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
3539 ));
3540 case 'REMOVE_ALL_EVENTS':
3541 return createEmptyEventStore();
3542 default:
3543 return eventStore;
3544 }
3545 }
3546 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
3547 if (eventSource && // not already removed
3548 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
3549 ) {
3550 let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
3551 if (fetchRange) {
3552 subset = expandRecurring(subset, fetchRange, context);
3553 }
3554 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
3555 }
3556 return eventStore;
3557 }
3558 function resetRawEvents(existingEventStore, eventSource, rawEvents, activeRange, context) {
3559 const { defIdMap, instanceIdMap } = buildPublicIdMaps(existingEventStore);
3560 let newEventStore = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context, false, defIdMap, instanceIdMap);
3561 return expandRecurring(newEventStore, activeRange, context);
3562 }
3563 function transformRawEvents(rawEvents, eventSource, context) {
3564 let calEachTransform = context.options.eventDataTransform;
3565 let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
3566 if (sourceEachTransform) {
3567 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
3568 }
3569 if (calEachTransform) {
3570 rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
3571 }
3572 return rawEvents;
3573 }
3574 function transformEachRawEvent(rawEvents, func) {
3575 let refinedEvents;
3576 if (!func) {
3577 refinedEvents = rawEvents;
3578 }
3579 else {
3580 refinedEvents = [];
3581 for (let rawEvent of rawEvents) {
3582 let refinedEvent = func(rawEvent);
3583 if (refinedEvent) {
3584 refinedEvents.push(refinedEvent);
3585 }
3586 else if (refinedEvent == null) {
3587 refinedEvents.push(rawEvent);
3588 } // if a different falsy value, do nothing
3589 }
3590 }
3591 return refinedEvents;
3592 }
3593 function addEvent(eventStore, subset, expandRange, context) {
3594 if (expandRange) {
3595 subset = expandRecurring(subset, expandRange, context);
3596 }
3597 return mergeEventStores(eventStore, subset);
3598 }
3599 function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
3600 let { defs } = eventStore;
3601 let instances = mapHash(eventStore.instances, (instance) => {
3602 let def = defs[instance.defId];
3603 if (def.allDay) {
3604 return instance; // isn't dependent on timezone
3605 }
3606 return Object.assign(Object.assign({}, instance), { range: {
3607 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
3608 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
3609 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
3610 });
3611 return { defs, instances };
3612 }
3613 function excludeEventsBySourceId(eventStore, sourceId) {
3614 return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
3615 }
3616 // QUESTION: why not just return instances? do a general object-property-exclusion util
3617 function excludeInstances(eventStore, removals) {
3618 return {
3619 defs: eventStore.defs,
3620 instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
3621 };
3622 }
3623 function buildPublicIdMaps(eventStore) {
3624 const { defs, instances } = eventStore;
3625 const defIdMap = {};
3626 const instanceIdMap = {};
3627 for (let defId in defs) {
3628 const def = defs[defId];
3629 const { publicId } = def;
3630 if (publicId) {
3631 defIdMap[publicId] = defId;
3632 }
3633 }
3634 for (let instanceId in instances) {
3635 const instance = instances[instanceId];
3636 const def = defs[instance.defId];
3637 const { publicId } = def;
3638 if (publicId) {
3639 instanceIdMap[publicId] = instanceId;
3640 }
3641 }
3642 return { defIdMap, instanceIdMap };
3643 }
3644
3645 class Emitter {
3646 constructor() {
3647 this.handlers = {};
3648 this.thisContext = null;
3649 }
3650 setThisContext(thisContext) {
3651 this.thisContext = thisContext;
3652 }
3653 setOptions(options) {
3654 this.options = options;
3655 }
3656 on(type, handler) {
3657 addToHash(this.handlers, type, handler);
3658 }
3659 off(type, handler) {
3660 removeFromHash(this.handlers, type, handler);
3661 }
3662 trigger(type, ...args) {
3663 let attachedHandlers = this.handlers[type] || [];
3664 let optionHandler = this.options && this.options[type];
3665 let handlers = [].concat(optionHandler || [], attachedHandlers);
3666 for (let handler of handlers) {
3667 handler.apply(this.thisContext, args);
3668 }
3669 }
3670 hasHandlers(type) {
3671 return Boolean((this.handlers[type] && this.handlers[type].length) ||
3672 (this.options && this.options[type]));
3673 }
3674 }
3675 function addToHash(hash, type, handler) {
3676 (hash[type] || (hash[type] = []))
3677 .push(handler);
3678 }
3679 function removeFromHash(hash, type, handler) {
3680 if (handler) {
3681 if (hash[type]) {
3682 hash[type] = hash[type].filter((func) => func !== handler);
3683 }
3684 }
3685 else {
3686 delete hash[type]; // remove all handler funcs for this type
3687 }
3688 }
3689
3690 const DEF_DEFAULTS = {
3691 startTime: '09:00',
3692 endTime: '17:00',
3693 daysOfWeek: [1, 2, 3, 4, 5],
3694 display: 'inverse-background',
3695 classNames: 'fc-non-business',
3696 groupId: '_businessHours', // so multiple defs get grouped
3697 };
3698 /*
3699 TODO: pass around as EventDefHash!!!
3700 */
3701 function parseBusinessHours(input, context) {
3702 return parseEvents(refineInputs(input), null, context);
3703 }
3704 function refineInputs(input) {
3705 let rawDefs;
3706 if (input === true) {
3707 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
3708 }
3709 else if (Array.isArray(input)) {
3710 // if specifying an array, every sub-definition NEEDS a day-of-week
3711 rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
3712 }
3713 else if (typeof input === 'object' && input) { // non-null object
3714 rawDefs = [input];
3715 }
3716 else { // is probably false
3717 rawDefs = [];
3718 }
3719 rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
3720 return rawDefs;
3721 }
3722
3723 function triggerDateSelect(selection, pev, context) {
3724 context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));
3725 }
3726 function triggerDateUnselect(pev, context) {
3727 context.emitter.trigger('unselect', {
3728 jsEvent: pev ? pev.origEvent : null,
3729 view: context.viewApi || context.calendarApi.view,
3730 });
3731 }
3732 function buildDateSpanApiWithContext(dateSpan, context) {
3733 let props = {};
3734 for (let transform of context.pluginHooks.dateSpanTransforms) {
3735 Object.assign(props, transform(dateSpan, context));
3736 }
3737 Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
3738 return props;
3739 }
3740 // Given an event's allDay status and start date, return what its fallback end date should be.
3741 // TODO: rename to computeDefaultEventEnd
3742 function getDefaultEventEnd(allDay, marker, context) {
3743 let { dateEnv, options } = context;
3744 let end = marker;
3745 if (allDay) {
3746 end = startOfDay(end);
3747 end = dateEnv.add(end, options.defaultAllDayEventDuration);
3748 }
3749 else {
3750 end = dateEnv.add(end, options.defaultTimedEventDuration);
3751 }
3752 return end;
3753 }
3754
3755 // applies the mutation to ALL defs/instances within the event store
3756 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
3757 let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
3758 let dest = createEmptyEventStore();
3759 for (let defId in eventStore.defs) {
3760 let def = eventStore.defs[defId];
3761 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
3762 }
3763 for (let instanceId in eventStore.instances) {
3764 let instance = eventStore.instances[instanceId];
3765 let def = dest.defs[instance.defId]; // important to grab the newly modified def
3766 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
3767 }
3768 return dest;
3769 }
3770 function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
3771 let standardProps = mutation.standardProps || {};
3772 // if hasEnd has not been specified, guess a good value based on deltas.
3773 // if duration will change, there's no way the default duration will persist,
3774 // and thus, we need to mark the event as having a real end
3775 if (standardProps.hasEnd == null &&
3776 eventConfig.durationEditable &&
3777 (mutation.startDelta || mutation.endDelta)) {
3778 standardProps.hasEnd = true; // TODO: is this mutation okay?
3779 }
3780 let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });
3781 if (mutation.extendedProps) {
3782 copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
3783 }
3784 for (let applier of context.pluginHooks.eventDefMutationAppliers) {
3785 applier(copy, mutation, context);
3786 }
3787 if (!copy.hasEnd && context.options.forceEventDuration) {
3788 copy.hasEnd = true;
3789 }
3790 return copy;
3791 }
3792 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
3793 eventConfig, mutation, context) {
3794 let { dateEnv } = context;
3795 let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
3796 let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
3797 let copy = Object.assign({}, eventInstance);
3798 if (forceAllDay) {
3799 copy.range = computeAlignedDayRange(copy.range);
3800 }
3801 if (mutation.datesDelta && eventConfig.startEditable) {
3802 copy.range = {
3803 start: dateEnv.add(copy.range.start, mutation.datesDelta),
3804 end: dateEnv.add(copy.range.end, mutation.datesDelta),
3805 };
3806 }
3807 if (mutation.startDelta && eventConfig.durationEditable) {
3808 copy.range = {
3809 start: dateEnv.add(copy.range.start, mutation.startDelta),
3810 end: copy.range.end,
3811 };
3812 }
3813 if (mutation.endDelta && eventConfig.durationEditable) {
3814 copy.range = {
3815 start: copy.range.start,
3816 end: dateEnv.add(copy.range.end, mutation.endDelta),
3817 };
3818 }
3819 if (clearEnd) {
3820 copy.range = {
3821 start: copy.range.start,
3822 end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
3823 };
3824 }
3825 // in case event was all-day but the supplied deltas were not
3826 // better util for this?
3827 if (eventDef.allDay) {
3828 copy.range = {
3829 start: startOfDay(copy.range.start),
3830 end: startOfDay(copy.range.end),
3831 };
3832 }
3833 // handle invalid durations
3834 if (copy.range.end < copy.range.start) {
3835 copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
3836 }
3837 return copy;
3838 }
3839
3840 class EventSourceImpl {
3841 constructor(context, internalEventSource) {
3842 this.context = context;
3843 this.internalEventSource = internalEventSource;
3844 }
3845 remove() {
3846 this.context.dispatch({
3847 type: 'REMOVE_EVENT_SOURCE',
3848 sourceId: this.internalEventSource.sourceId,
3849 });
3850 }
3851 refetch() {
3852 this.context.dispatch({
3853 type: 'FETCH_EVENT_SOURCES',
3854 sourceIds: [this.internalEventSource.sourceId],
3855 isRefetch: true,
3856 });
3857 }
3858 get id() {
3859 return this.internalEventSource.publicId;
3860 }
3861 get url() {
3862 return this.internalEventSource.meta.url;
3863 }
3864 get format() {
3865 return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
3866 }
3867 }
3868
3869 class EventImpl {
3870 // instance will be null if expressing a recurring event that has no current instances,
3871 // OR if trying to validate an incoming external event that has no dates assigned
3872 constructor(context, def, instance) {
3873 this._context = context;
3874 this._def = def;
3875 this._instance = instance || null;
3876 }
3877 /*
3878 TODO: make event struct more responsible for this
3879 */
3880 setProp(name, val) {
3881 if (name in EVENT_DATE_REFINERS) {
3882 console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
3883 // TODO: make proper aliasing system?
3884 }
3885 else if (name === 'id') {
3886 val = EVENT_NON_DATE_REFINERS[name](val);
3887 this.mutate({
3888 standardProps: { publicId: val }, // hardcoded internal name
3889 });
3890 }
3891 else if (name in EVENT_NON_DATE_REFINERS) {
3892 val = EVENT_NON_DATE_REFINERS[name](val);
3893 this.mutate({
3894 standardProps: { [name]: val },
3895 });
3896 }
3897 else if (name in EVENT_UI_REFINERS) {
3898 let ui = EVENT_UI_REFINERS[name](val);
3899 if (name === 'color') {
3900 ui = { backgroundColor: val, borderColor: val };
3901 }
3902 else if (name === 'editable') {
3903 ui = { startEditable: val, durationEditable: val };
3904 }
3905 else {
3906 ui = { [name]: val };
3907 }
3908 this.mutate({
3909 standardProps: { ui },
3910 });
3911 }
3912 else {
3913 console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
3914 }
3915 }
3916 setExtendedProp(name, val) {
3917 this.mutate({
3918 extendedProps: { [name]: val },
3919 });
3920 }
3921 setStart(startInput, options = {}) {
3922 let { dateEnv } = this._context;
3923 let start = dateEnv.createMarker(startInput);
3924 if (start && this._instance) { // TODO: warning if parsed bad
3925 let instanceRange = this._instance.range;
3926 let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
3927 if (options.maintainDuration) {
3928 this.mutate({ datesDelta: startDelta });
3929 }
3930 else {
3931 this.mutate({ startDelta });
3932 }
3933 }
3934 }
3935 setEnd(endInput, options = {}) {
3936 let { dateEnv } = this._context;
3937 let end;
3938 if (endInput != null) {
3939 end = dateEnv.createMarker(endInput);
3940 if (!end) {
3941 return; // TODO: warning if parsed bad
3942 }
3943 }
3944 if (this._instance) {
3945 if (end) {
3946 let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
3947 this.mutate({ endDelta });
3948 }
3949 else {
3950 this.mutate({ standardProps: { hasEnd: false } });
3951 }
3952 }
3953 }
3954 setDates(startInput, endInput, options = {}) {
3955 let { dateEnv } = this._context;
3956 let standardProps = { allDay: options.allDay };
3957 let start = dateEnv.createMarker(startInput);
3958 let end;
3959 if (!start) {
3960 return; // TODO: warning if parsed bad
3961 }
3962 if (endInput != null) {
3963 end = dateEnv.createMarker(endInput);
3964 if (!end) { // TODO: warning if parsed bad
3965 return;
3966 }
3967 }
3968 if (this._instance) {
3969 let instanceRange = this._instance.range;
3970 // when computing the diff for an event being converted to all-day,
3971 // compute diff off of the all-day values the way event-mutation does.
3972 if (options.allDay === true) {
3973 instanceRange = computeAlignedDayRange(instanceRange);
3974 }
3975 let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
3976 if (end) {
3977 let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
3978 if (durationsEqual(startDelta, endDelta)) {
3979 this.mutate({ datesDelta: startDelta, standardProps });
3980 }
3981 else {
3982 this.mutate({ startDelta, endDelta, standardProps });
3983 }
3984 }
3985 else { // means "clear the end"
3986 standardProps.hasEnd = false;
3987 this.mutate({ datesDelta: startDelta, standardProps });
3988 }
3989 }
3990 }
3991 moveStart(deltaInput) {
3992 let delta = createDuration(deltaInput);
3993 if (delta) { // TODO: warning if parsed bad
3994 this.mutate({ startDelta: delta });
3995 }
3996 }
3997 moveEnd(deltaInput) {
3998 let delta = createDuration(deltaInput);
3999 if (delta) { // TODO: warning if parsed bad
4000 this.mutate({ endDelta: delta });
4001 }
4002 }
4003 moveDates(deltaInput) {
4004 let delta = createDuration(deltaInput);
4005 if (delta) { // TODO: warning if parsed bad
4006 this.mutate({ datesDelta: delta });
4007 }
4008 }
4009 setAllDay(allDay, options = {}) {
4010 let standardProps = { allDay };
4011 let { maintainDuration } = options;
4012 if (maintainDuration == null) {
4013 maintainDuration = this._context.options.allDayMaintainDuration;
4014 }
4015 if (this._def.allDay !== allDay) {
4016 standardProps.hasEnd = maintainDuration;
4017 }
4018 this.mutate({ standardProps });
4019 }
4020 formatRange(formatInput) {
4021 let { dateEnv } = this._context;
4022 let instance = this._instance;
4023 let formatter = createFormatter(formatInput);
4024 if (this._def.hasEnd) {
4025 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
4026 forcedStartTzo: instance.forcedStartTzo,
4027 forcedEndTzo: instance.forcedEndTzo,
4028 });
4029 }
4030 return dateEnv.format(instance.range.start, formatter, {
4031 forcedTzo: instance.forcedStartTzo,
4032 });
4033 }
4034 mutate(mutation) {
4035 let instance = this._instance;
4036 if (instance) {
4037 let def = this._def;
4038 let context = this._context;
4039 let { eventStore } = context.getCurrentData();
4040 let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
4041 let eventConfigBase = {
4042 '': {
4043 display: '',
4044 startEditable: true,
4045 durationEditable: true,
4046 constraints: [],
4047 overlap: null,
4048 allows: [],
4049 backgroundColor: '',
4050 borderColor: '',
4051 textColor: '',
4052 classNames: [],
4053 },
4054 };
4055 relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
4056 let oldEvent = new EventImpl(context, def, instance); // snapshot
4057 this._def = relevantEvents.defs[def.defId];
4058 this._instance = relevantEvents.instances[instance.instanceId];
4059 context.dispatch({
4060 type: 'MERGE_EVENTS',
4061 eventStore: relevantEvents,
4062 });
4063 context.emitter.trigger('eventChange', {
4064 oldEvent,
4065 event: this,
4066 relatedEvents: buildEventApis(relevantEvents, context, instance),
4067 revert() {
4068 context.dispatch({
4069 type: 'RESET_EVENTS',
4070 eventStore, // the ORIGINAL store
4071 });
4072 },
4073 });
4074 }
4075 }
4076 remove() {
4077 let context = this._context;
4078 let asStore = eventApiToStore(this);
4079 context.dispatch({
4080 type: 'REMOVE_EVENTS',
4081 eventStore: asStore,
4082 });
4083 context.emitter.trigger('eventRemove', {
4084 event: this,
4085 relatedEvents: [],
4086 revert() {
4087 context.dispatch({
4088 type: 'MERGE_EVENTS',
4089 eventStore: asStore,
4090 });
4091 },
4092 });
4093 }
4094 get source() {
4095 let { sourceId } = this._def;
4096 if (sourceId) {
4097 return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
4098 }
4099 return null;
4100 }
4101 get start() {
4102 return this._instance ?
4103 this._context.dateEnv.toDate(this._instance.range.start) :
4104 null;
4105 }
4106 get end() {
4107 return (this._instance && this._def.hasEnd) ?
4108 this._context.dateEnv.toDate(this._instance.range.end) :
4109 null;
4110 }
4111 get startStr() {
4112 let instance = this._instance;
4113 if (instance) {
4114 return this._context.dateEnv.formatIso(instance.range.start, {
4115 omitTime: this._def.allDay,
4116 forcedTzo: instance.forcedStartTzo,
4117 });
4118 }
4119 return '';
4120 }
4121 get endStr() {
4122 let instance = this._instance;
4123 if (instance && this._def.hasEnd) {
4124 return this._context.dateEnv.formatIso(instance.range.end, {
4125 omitTime: this._def.allDay,
4126 forcedTzo: instance.forcedEndTzo,
4127 });
4128 }
4129 return '';
4130 }
4131 // computable props that all access the def
4132 // TODO: find a TypeScript-compatible way to do this at scale
4133 get id() { return this._def.publicId; }
4134 get groupId() { return this._def.groupId; }
4135 get allDay() { return this._def.allDay; }
4136 get title() { return this._def.title; }
4137 get url() { return this._def.url; }
4138 get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier
4139 get startEditable() { return this._def.ui.startEditable; }
4140 get durationEditable() { return this._def.ui.durationEditable; }
4141 get constraint() { return this._def.ui.constraints[0] || null; }
4142 get overlap() { return this._def.ui.overlap; }
4143 get allow() { return this._def.ui.allows[0] || null; }
4144 get backgroundColor() { return this._def.ui.backgroundColor; }
4145 get borderColor() { return this._def.ui.borderColor; }
4146 get textColor() { return this._def.ui.textColor; }
4147 // NOTE: user can't modify these because Object.freeze was called in event-def parsing
4148 get classNames() { return this._def.ui.classNames; }
4149 get extendedProps() { return this._def.extendedProps; }
4150 toPlainObject(settings = {}) {
4151 let def = this._def;
4152 let { ui } = def;
4153 let { startStr, endStr } = this;
4154 let res = {
4155 allDay: def.allDay,
4156 };
4157 if (def.title) {
4158 res.title = def.title;
4159 }
4160 if (startStr) {
4161 res.start = startStr;
4162 }
4163 if (endStr) {
4164 res.end = endStr;
4165 }
4166 if (def.publicId) {
4167 res.id = def.publicId;
4168 }
4169 if (def.groupId) {
4170 res.groupId = def.groupId;
4171 }
4172 if (def.url) {
4173 res.url = def.url;
4174 }
4175 if (ui.display && ui.display !== 'auto') {
4176 res.display = ui.display;
4177 }
4178 // TODO: what about recurring-event properties???
4179 // TODO: include startEditable/durationEditable/constraint/overlap/allow
4180 if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
4181 res.color = ui.backgroundColor;
4182 }
4183 else {
4184 if (ui.backgroundColor) {
4185 res.backgroundColor = ui.backgroundColor;
4186 }
4187 if (ui.borderColor) {
4188 res.borderColor = ui.borderColor;
4189 }
4190 }
4191 if (ui.textColor) {
4192 res.textColor = ui.textColor;
4193 }
4194 if (ui.classNames.length) {
4195 res.classNames = ui.classNames;
4196 }
4197 if (Object.keys(def.extendedProps).length) {
4198 if (settings.collapseExtendedProps) {
4199 Object.assign(res, def.extendedProps);
4200 }
4201 else {
4202 res.extendedProps = def.extendedProps;
4203 }
4204 }
4205 return res;
4206 }
4207 toJSON() {
4208 return this.toPlainObject();
4209 }
4210 }
4211 function eventApiToStore(eventApi) {
4212 let def = eventApi._def;
4213 let instance = eventApi._instance;
4214 return {
4215 defs: { [def.defId]: def },
4216 instances: instance
4217 ? { [instance.instanceId]: instance }
4218 : {},
4219 };
4220 }
4221 function buildEventApis(eventStore, context, excludeInstance) {
4222 let { defs, instances } = eventStore;
4223 let eventApis = [];
4224 let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
4225 for (let id in instances) {
4226 let instance = instances[id];
4227 let def = defs[instance.defId];
4228 if (instance.instanceId !== excludeInstanceId) {
4229 eventApis.push(new EventImpl(context, def, instance));
4230 }
4231 }
4232 return eventApis;
4233 }
4234
4235 /*
4236 Specifying nextDayThreshold signals that all-day ranges should be sliced.
4237 */
4238 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
4239 let inverseBgByGroupId = {};
4240 let inverseBgByDefId = {};
4241 let defByGroupId = {};
4242 let bgRanges = [];
4243 let fgRanges = [];
4244 let eventUis = compileEventUis(eventStore.defs, eventUiBases);
4245 for (let defId in eventStore.defs) {
4246 let def = eventStore.defs[defId];
4247 let ui = eventUis[def.defId];
4248 if (ui.display === 'inverse-background') {
4249 if (def.groupId) {
4250 inverseBgByGroupId[def.groupId] = [];
4251 if (!defByGroupId[def.groupId]) {
4252 defByGroupId[def.groupId] = def;
4253 }
4254 }
4255 else {
4256 inverseBgByDefId[defId] = [];
4257 }
4258 }
4259 }
4260 for (let instanceId in eventStore.instances) {
4261 let instance = eventStore.instances[instanceId];
4262 let def = eventStore.defs[instance.defId];
4263 let ui = eventUis[def.defId];
4264 let origRange = instance.range;
4265 let normalRange = (!def.allDay && nextDayThreshold) ?
4266 computeVisibleDayRange(origRange, nextDayThreshold) :
4267 origRange;
4268 let slicedRange = intersectRanges(normalRange, framingRange);
4269 if (slicedRange) {
4270 if (ui.display === 'inverse-background') {
4271 if (def.groupId) {
4272 inverseBgByGroupId[def.groupId].push(slicedRange);
4273 }
4274 else {
4275 inverseBgByDefId[instance.defId].push(slicedRange);
4276 }
4277 }
4278 else if (ui.display !== 'none') {
4279 (ui.display === 'background' ? bgRanges : fgRanges).push({
4280 def,
4281 ui,
4282 instance,
4283 range: slicedRange,
4284 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
4285 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
4286 });
4287 }
4288 }
4289 }
4290 for (let groupId in inverseBgByGroupId) { // BY GROUP
4291 let ranges = inverseBgByGroupId[groupId];
4292 let invertedRanges = invertRanges(ranges, framingRange);
4293 for (let invertedRange of invertedRanges) {
4294 let def = defByGroupId[groupId];
4295 let ui = eventUis[def.defId];
4296 bgRanges.push({
4297 def,
4298 ui,
4299 instance: null,
4300 range: invertedRange,
4301 isStart: false,
4302 isEnd: false,
4303 });
4304 }
4305 }
4306 for (let defId in inverseBgByDefId) {
4307 let ranges = inverseBgByDefId[defId];
4308 let invertedRanges = invertRanges(ranges, framingRange);
4309 for (let invertedRange of invertedRanges) {
4310 bgRanges.push({
4311 def: eventStore.defs[defId],
4312 ui: eventUis[defId],
4313 instance: null,
4314 range: invertedRange,
4315 isStart: false,
4316 isEnd: false,
4317 });
4318 }
4319 }
4320 return { bg: bgRanges, fg: fgRanges };
4321 }
4322 function hasBgRendering(def) {
4323 return def.ui.display === 'background' || def.ui.display === 'inverse-background';
4324 }
4325 function setElSeg(el, seg) {
4326 el.fcSeg = seg;
4327 }
4328 function getElSeg(el) {
4329 return el.fcSeg ||
4330 el.parentNode.fcSeg || // for the harness
4331 null;
4332 }
4333 // event ui computation
4334 function compileEventUis(eventDefs, eventUiBases) {
4335 return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
4336 }
4337 function compileEventUi(eventDef, eventUiBases) {
4338 let uis = [];
4339 if (eventUiBases['']) {
4340 uis.push(eventUiBases['']);
4341 }
4342 if (eventUiBases[eventDef.defId]) {
4343 uis.push(eventUiBases[eventDef.defId]);
4344 }
4345 uis.push(eventDef.ui);
4346 return combineEventUis(uis);
4347 }
4348 function sortEventSegs(segs, eventOrderSpecs) {
4349 let objs = segs.map(buildSegCompareObj);
4350 objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
4351 return objs.map((c) => c._seg);
4352 }
4353 // returns a object with all primitive props that can be compared
4354 function buildSegCompareObj(seg) {
4355 let { eventRange } = seg;
4356 let eventDef = eventRange.def;
4357 let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
4358 let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
4359 let end = range.end ? range.end.valueOf() : 0; // "
4360 return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
4361 end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
4362 }
4363 function computeSegDraggable(seg, context) {
4364 let { pluginHooks } = context;
4365 let transformers = pluginHooks.isDraggableTransformers;
4366 let { def, ui } = seg.eventRange;
4367 let val = ui.startEditable;
4368 for (let transformer of transformers) {
4369 val = transformer(val, def, ui, context);
4370 }
4371 return val;
4372 }
4373 function computeSegStartResizable(seg, context) {
4374 return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
4375 }
4376 function computeSegEndResizable(seg, context) {
4377 return seg.isEnd && seg.eventRange.ui.durationEditable;
4378 }
4379 function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
4380 defaultDisplayEventEnd, // defaults to true
4381 startOverride, endOverride) {
4382 let { dateEnv, options } = context;
4383 let { displayEventTime, displayEventEnd } = options;
4384 let eventDef = seg.eventRange.def;
4385 let eventInstance = seg.eventRange.instance;
4386 if (displayEventTime == null) {
4387 displayEventTime = defaultDisplayEventTime !== false;
4388 }
4389 if (displayEventEnd == null) {
4390 displayEventEnd = defaultDisplayEventEnd !== false;
4391 }
4392 let wholeEventStart = eventInstance.range.start;
4393 let wholeEventEnd = eventInstance.range.end;
4394 let segStart = startOverride || seg.start || seg.eventRange.range.start;
4395 let segEnd = endOverride || seg.end || seg.eventRange.range.end;
4396 let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
4397 let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
4398 if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
4399 segStart = isStartDay ? wholeEventStart : segStart;
4400 segEnd = isEndDay ? wholeEventEnd : segEnd;
4401 if (displayEventEnd && eventDef.hasEnd) {
4402 return dateEnv.formatRange(segStart, segEnd, timeFormat, {
4403 forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
4404 forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
4405 });
4406 }
4407 return dateEnv.format(segStart, timeFormat, {
4408 forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
4409 });
4410 }
4411 return '';
4412 }
4413 function getSegMeta(seg, todayRange, nowDate) {
4414 let segRange = seg.eventRange.range;
4415 return {
4416 isPast: segRange.end <= (nowDate || todayRange.start),
4417 isFuture: segRange.start >= (nowDate || todayRange.end),
4418 isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
4419 };
4420 }
4421 function getEventClassNames(props) {
4422 let classNames = ['fc-event'];
4423 if (props.isMirror) {
4424 classNames.push('fc-event-mirror');
4425 }
4426 if (props.isDraggable) {
4427 classNames.push('fc-event-draggable');
4428 }
4429 if (props.isStartResizable || props.isEndResizable) {
4430 classNames.push('fc-event-resizable');
4431 }
4432 if (props.isDragging) {
4433 classNames.push('fc-event-dragging');
4434 }
4435 if (props.isResizing) {
4436 classNames.push('fc-event-resizing');
4437 }
4438 if (props.isSelected) {
4439 classNames.push('fc-event-selected');
4440 }
4441 if (props.isStart) {
4442 classNames.push('fc-event-start');
4443 }
4444 if (props.isEnd) {
4445 classNames.push('fc-event-end');
4446 }
4447 if (props.isPast) {
4448 classNames.push('fc-event-past');
4449 }
4450 if (props.isToday) {
4451 classNames.push('fc-event-today');
4452 }
4453 if (props.isFuture) {
4454 classNames.push('fc-event-future');
4455 }
4456 return classNames;
4457 }
4458 function buildEventRangeKey(eventRange) {
4459 return eventRange.instance
4460 ? eventRange.instance.instanceId
4461 : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
4462 // inverse-background events don't have specific instances. TODO: better solution
4463 }
4464 function getSegAnchorAttrs(seg, context) {
4465 let { def, instance } = seg.eventRange;
4466 let { url } = def;
4467 if (url) {
4468 return { href: url };
4469 }
4470 let { emitter, options } = context;
4471 let { eventInteractive } = options;
4472 if (eventInteractive == null) {
4473 eventInteractive = def.interactive;
4474 if (eventInteractive == null) {
4475 eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
4476 }
4477 }
4478 // mock what happens in EventClicking
4479 if (eventInteractive) {
4480 // only attach keyboard-related handlers because click handler is already done in EventClicking
4481 return createAriaKeyboardAttrs((ev) => {
4482 emitter.trigger('eventClick', {
4483 el: ev.target,
4484 event: new EventImpl(context, def, instance),
4485 jsEvent: ev,
4486 view: context.viewApi,
4487 });
4488 });
4489 }
4490 return {};
4491 }
4492
4493 const STANDARD_PROPS = {
4494 start: identity,
4495 end: identity,
4496 allDay: Boolean,
4497 };
4498 function parseDateSpan(raw, dateEnv, defaultDuration) {
4499 let span = parseOpenDateSpan(raw, dateEnv);
4500 let { range } = span;
4501 if (!range.start) {
4502 return null;
4503 }
4504 if (!range.end) {
4505 if (defaultDuration == null) {
4506 return null;
4507 }
4508 range.end = dateEnv.add(range.start, defaultDuration);
4509 }
4510 return span;
4511 }
4512 /*
4513 TODO: somehow combine with parseRange?
4514 Will return null if the start/end props were present but parsed invalidly.
4515 */
4516 function parseOpenDateSpan(raw, dateEnv) {
4517 let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);
4518 let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
4519 let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
4520 let { allDay } = standardProps;
4521 if (allDay == null) {
4522 allDay = (startMeta && startMeta.isTimeUnspecified) &&
4523 (!endMeta || endMeta.isTimeUnspecified);
4524 }
4525 return Object.assign({ range: {
4526 start: startMeta ? startMeta.marker : null,
4527 end: endMeta ? endMeta.marker : null,
4528 }, allDay }, extra);
4529 }
4530 function isDateSpansEqual(span0, span1) {
4531 return rangesEqual(span0.range, span1.range) &&
4532 span0.allDay === span1.allDay &&
4533 isSpanPropsEqual(span0, span1);
4534 }
4535 // the NON-DATE-RELATED props
4536 function isSpanPropsEqual(span0, span1) {
4537 for (let propName in span1) {
4538 if (propName !== 'range' && propName !== 'allDay') {
4539 if (span0[propName] !== span1[propName]) {
4540 return false;
4541 }
4542 }
4543 }
4544 // are there any props that span0 has that span1 DOESN'T have?
4545 // both have range/allDay, so no need to special-case.
4546 for (let propName in span0) {
4547 if (!(propName in span1)) {
4548 return false;
4549 }
4550 }
4551 return true;
4552 }
4553 function buildDateSpanApi(span, dateEnv) {
4554 return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });
4555 }
4556 function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
4557 return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });
4558 }
4559 function buildRangeApi(range, dateEnv, omitTime) {
4560 return {
4561 start: dateEnv.toDate(range.start),
4562 end: dateEnv.toDate(range.end),
4563 startStr: dateEnv.formatIso(range.start, { omitTime }),
4564 endStr: dateEnv.formatIso(range.end, { omitTime }),
4565 };
4566 }
4567 function fabricateEventRange(dateSpan, eventUiBases, context) {
4568 let res = refineEventDef({ editable: false }, context);
4569 let def = parseEventDef(res.refined, res.extra, '', // sourceId
4570 dateSpan.allDay, true, // hasEnd
4571 context);
4572 return {
4573 def,
4574 ui: compileEventUi(def, eventUiBases),
4575 instance: createEventInstance(def.defId, dateSpan.range),
4576 range: dateSpan.range,
4577 isStart: true,
4578 isEnd: true,
4579 };
4580 }
4581
4582 /*
4583 given a function that resolves a result asynchronously.
4584 the function can either call passed-in success and failure callbacks,
4585 or it can return a promise.
4586 if you need to pass additional params to func, bind them first.
4587 */
4588 function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
4589 // guard against success/failure callbacks being called more than once
4590 // and guard against a promise AND callback being used together.
4591 let isResolved = false;
4592 let wrappedSuccess = function (res) {
4593 if (!isResolved) {
4594 isResolved = true;
4595 normalizedSuccessCallback(res);
4596 }
4597 };
4598 let wrappedFailure = function (error) {
4599 if (!isResolved) {
4600 isResolved = true;
4601 normalizedFailureCallback(error);
4602 }
4603 };
4604 let res = func(wrappedSuccess, wrappedFailure);
4605 if (res && typeof res.then === 'function') {
4606 res.then(wrappedSuccess, wrappedFailure);
4607 }
4608 }
4609
4610 class JsonRequestError extends Error {
4611 constructor(message, response) {
4612 super(message);
4613 this.response = response;
4614 }
4615 }
4616 function requestJson(method, url, params) {
4617 method = method.toUpperCase();
4618 const fetchOptions = {
4619 method,
4620 };
4621 if (method === 'GET') {
4622 url += (url.indexOf('?') === -1 ? '?' : '&') +
4623 new URLSearchParams(params);
4624 }
4625 else {
4626 fetchOptions.body = new URLSearchParams(params);
4627 fetchOptions.headers = {
4628 'Content-Type': 'application/x-www-form-urlencoded',
4629 };
4630 }
4631 return fetch(url, fetchOptions).then((fetchRes) => {
4632 if (fetchRes.ok) {
4633 return fetchRes.json().then((parsedResponse) => {
4634 return [parsedResponse, fetchRes];
4635 }, () => {
4636 throw new JsonRequestError('Failure parsing JSON', fetchRes);
4637 });
4638 }
4639 else {
4640 throw new JsonRequestError('Request failed', fetchRes);
4641 }
4642 });
4643 }
4644
4645 let canVGrowWithinCell;
4646 function getCanVGrowWithinCell() {
4647 if (canVGrowWithinCell == null) {
4648 canVGrowWithinCell = computeCanVGrowWithinCell();
4649 }
4650 return canVGrowWithinCell;
4651 }
4652 function computeCanVGrowWithinCell() {
4653 // for SSR, because this function is call immediately at top-level
4654 // TODO: just make this logic execute top-level, immediately, instead of doing lazily
4655 if (typeof document === 'undefined') {
4656 return true;
4657 }
4658 let el = document.createElement('div');
4659 el.style.position = 'absolute';
4660 el.style.top = '0px';
4661 el.style.left = '0px';
4662 el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
4663 el.querySelector('table').style.height = '100px';
4664 el.querySelector('div').style.height = '100%';
4665 document.body.appendChild(el);
4666 let div = el.querySelector('div');
4667 let possible = div.offsetHeight > 0;
4668 document.body.removeChild(el);
4669 return possible;
4670 }
4671
4672 class CalendarRoot extends BaseComponent {
4673 constructor() {
4674 super(...arguments);
4675 this.state = {
4676 forPrint: false,
4677 };
4678 this.handleBeforePrint = () => {
4679 flushSync(() => {
4680 this.setState({ forPrint: true });
4681 });
4682 };
4683 this.handleAfterPrint = () => {
4684 flushSync(() => {
4685 this.setState({ forPrint: false });
4686 });
4687 };
4688 }
4689 render() {
4690 let { props } = this;
4691 let { options } = props;
4692 let { forPrint } = this.state;
4693 let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
4694 let height = (!isHeightAuto && options.height != null) ? options.height : '';
4695 let classNames = [
4696 'fc',
4697 forPrint ? 'fc-media-print' : 'fc-media-screen',
4698 `fc-direction-${options.direction}`,
4699 props.theme.getClass('root'),
4700 ];
4701 if (!getCanVGrowWithinCell()) {
4702 classNames.push('fc-liquid-hack');
4703 }
4704 return props.children(classNames, height, isHeightAuto, forPrint);
4705 }
4706 componentDidMount() {
4707 let { emitter } = this.props;
4708 emitter.on('_beforeprint', this.handleBeforePrint);
4709 emitter.on('_afterprint', this.handleAfterPrint);
4710 }
4711 componentWillUnmount() {
4712 let { emitter } = this.props;
4713 emitter.off('_beforeprint', this.handleBeforePrint);
4714 emitter.off('_afterprint', this.handleAfterPrint);
4715 }
4716 }
4717
4718 class Interaction {
4719 constructor(settings) {
4720 this.component = settings.component;
4721 this.isHitComboAllowed = settings.isHitComboAllowed || null;
4722 }
4723 destroy() {
4724 }
4725 }
4726 function parseInteractionSettings(component, input) {
4727 return {
4728 component,
4729 el: input.el,
4730 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
4731 isHitComboAllowed: input.isHitComboAllowed || null,
4732 };
4733 }
4734 function interactionSettingsToStore(settings) {
4735 return {
4736 [settings.component.uid]: settings,
4737 };
4738 }
4739 // global state
4740 const interactionSettingsStore = {};
4741
4742 class NowTimer extends x$1 {
4743 constructor(props, context) {
4744 super(props, context);
4745 this.handleRefresh = () => {
4746 let timing = this.computeTiming();
4747 if (timing.state.nowDate.valueOf() !== this.state.nowDate.valueOf()) {
4748 this.setState(timing.state);
4749 }
4750 this.clearTimeout();
4751 this.setTimeout(timing.waitMs);
4752 };
4753 this.handleVisibilityChange = () => {
4754 if (!document.hidden) {
4755 this.handleRefresh();
4756 }
4757 };
4758 this.state = this.computeTiming().state;
4759 }
4760 render() {
4761 let { props, state } = this;
4762 return props.children(state.nowDate, state.todayRange);
4763 }
4764 componentDidMount() {
4765 this.setTimeout();
4766 this.context.nowManager.addResetListener(this.handleRefresh);
4767 // fired tab becomes visible after being hidden
4768 document.addEventListener('visibilitychange', this.handleVisibilityChange);
4769 }
4770 componentDidUpdate(prevProps) {
4771 if (prevProps.unit !== this.props.unit) {
4772 this.clearTimeout();
4773 this.setTimeout();
4774 }
4775 }
4776 componentWillUnmount() {
4777 this.clearTimeout();
4778 this.context.nowManager.removeResetListener(this.handleRefresh);
4779 document.removeEventListener('visibilitychange', this.handleVisibilityChange);
4780 }
4781 computeTiming() {
4782 let { props, context } = this;
4783 let unroundedNow = context.nowManager.getDateMarker();
4784 let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
4785 let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
4786 let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
4787 // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
4788 // ensure no longer than a day
4789 waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
4790 return {
4791 state: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
4792 waitMs,
4793 };
4794 }
4795 setTimeout(waitMs = this.computeTiming().waitMs) {
4796 // NOTE: timeout could take longer than expected if tab sleeps,
4797 // which is why we listen to 'visibilitychange'
4798 this.timeoutId = setTimeout(() => {
4799 // NOTE: timeout could also return *earlier* than expected, and we need to wait 2 ms more
4800 // This is why use use same waitMs from computeTiming, so we don't skip an interval while
4801 // .setState() is executing
4802 const timing = this.computeTiming();
4803 this.setState(timing.state, () => {
4804 this.setTimeout(timing.waitMs);
4805 });
4806 }, waitMs);
4807 }
4808 clearTimeout() {
4809 if (this.timeoutId) {
4810 clearTimeout(this.timeoutId);
4811 }
4812 }
4813 }
4814 NowTimer.contextType = ViewContextType;
4815 function buildDayRange(date) {
4816 let start = startOfDay(date);
4817 let end = addDays(start, 1);
4818 return { start, end };
4819 }
4820
4821 class CalendarImpl {
4822 getCurrentData() {
4823 return this.currentDataManager.getCurrentData();
4824 }
4825 dispatch(action) {
4826 this.currentDataManager.dispatch(action);
4827 }
4828 get view() { return this.getCurrentData().viewApi; }
4829 batchRendering(callback) {
4830 callback();
4831 }
4832 updateSize() {
4833 this.trigger('_resize', true);
4834 }
4835 // Options
4836 // -----------------------------------------------------------------------------------------------------------------
4837 setOption(name, val) {
4838 this.dispatch({
4839 type: 'SET_OPTION',
4840 optionName: name,
4841 rawOptionValue: val,
4842 });
4843 }
4844 getOption(name) {
4845 return this.currentDataManager.currentCalendarOptionsInput[name];
4846 }
4847 getAvailableLocaleCodes() {
4848 return Object.keys(this.getCurrentData().availableRawLocales);
4849 }
4850 // Trigger
4851 // -----------------------------------------------------------------------------------------------------------------
4852 on(handlerName, handler) {
4853 let { currentDataManager } = this;
4854 if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
4855 currentDataManager.emitter.on(handlerName, handler);
4856 }
4857 else {
4858 console.warn(`Unknown listener name '${handlerName}'`);
4859 }
4860 }
4861 off(handlerName, handler) {
4862 this.currentDataManager.emitter.off(handlerName, handler);
4863 }
4864 // not meant for public use
4865 trigger(handlerName, ...args) {
4866 this.currentDataManager.emitter.trigger(handlerName, ...args);
4867 }
4868 // View
4869 // -----------------------------------------------------------------------------------------------------------------
4870 changeView(viewType, dateOrRange) {
4871 this.batchRendering(() => {
4872 this.unselect();
4873 if (dateOrRange) {
4874 if (dateOrRange.start && dateOrRange.end) { // a range
4875 this.dispatch({
4876 type: 'CHANGE_VIEW_TYPE',
4877 viewType,
4878 });
4879 this.dispatch({
4880 type: 'SET_OPTION',
4881 optionName: 'visibleRange',
4882 rawOptionValue: dateOrRange,
4883 });
4884 }
4885 else {
4886 let { dateEnv } = this.getCurrentData();
4887 this.dispatch({
4888 type: 'CHANGE_VIEW_TYPE',
4889 viewType,
4890 dateMarker: dateEnv.createMarker(dateOrRange),
4891 });
4892 }
4893 }
4894 else {
4895 this.dispatch({
4896 type: 'CHANGE_VIEW_TYPE',
4897 viewType,
4898 });
4899 }
4900 });
4901 }
4902 // Forces navigation to a view for the given date.
4903 // `viewType` can be a specific view name or a generic one like "week" or "day".
4904 // needs to change
4905 zoomTo(dateMarker, viewType) {
4906 let state = this.getCurrentData();
4907 let spec;
4908 viewType = viewType || 'day'; // day is default zoom
4909 spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
4910 this.unselect();
4911 if (spec) {
4912 this.dispatch({
4913 type: 'CHANGE_VIEW_TYPE',
4914 viewType: spec.type,
4915 dateMarker,
4916 });
4917 }
4918 else {
4919 this.dispatch({
4920 type: 'CHANGE_DATE',
4921 dateMarker,
4922 });
4923 }
4924 }
4925 // Given a duration singular unit, like "week" or "day", finds a matching view spec.
4926 // Preference is given to views that have corresponding buttons.
4927 getUnitViewSpec(unit) {
4928 let { viewSpecs, toolbarConfig } = this.getCurrentData();
4929 let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
4930 let i;
4931 let spec;
4932 for (let viewType in viewSpecs) {
4933 viewTypes.push(viewType);
4934 }
4935 for (i = 0; i < viewTypes.length; i += 1) {
4936 spec = viewSpecs[viewTypes[i]];
4937 if (spec) {
4938 if (spec.singleUnit === unit) {
4939 return spec;
4940 }
4941 }
4942 }
4943 return null;
4944 }
4945 // Current Date
4946 // -----------------------------------------------------------------------------------------------------------------
4947 prev() {
4948 this.unselect();
4949 this.dispatch({ type: 'PREV' });
4950 }
4951 next() {
4952 this.unselect();
4953 this.dispatch({ type: 'NEXT' });
4954 }
4955 prevYear() {
4956 let state = this.getCurrentData();
4957 this.unselect();
4958 this.dispatch({
4959 type: 'CHANGE_DATE',
4960 dateMarker: state.dateEnv.addYears(state.currentDate, -1),
4961 });
4962 }
4963 nextYear() {
4964 let state = this.getCurrentData();
4965 this.unselect();
4966 this.dispatch({
4967 type: 'CHANGE_DATE',
4968 dateMarker: state.dateEnv.addYears(state.currentDate, 1),
4969 });
4970 }
4971 today() {
4972 let state = this.getCurrentData();
4973 this.unselect();
4974 this.dispatch({
4975 type: 'CHANGE_DATE',
4976 dateMarker: state.nowManager.getDateMarker(),
4977 });
4978 }
4979 gotoDate(zonedDateInput) {
4980 let state = this.getCurrentData();
4981 this.unselect();
4982 this.dispatch({
4983 type: 'CHANGE_DATE',
4984 dateMarker: state.dateEnv.createMarker(zonedDateInput),
4985 });
4986 }
4987 incrementDate(deltaInput) {
4988 let state = this.getCurrentData();
4989 let delta = createDuration(deltaInput);
4990 if (delta) { // else, warn about invalid input?
4991 this.unselect();
4992 this.dispatch({
4993 type: 'CHANGE_DATE',
4994 dateMarker: state.dateEnv.add(state.currentDate, delta),
4995 });
4996 }
4997 }
4998 getDate() {
4999 let state = this.getCurrentData();
5000 return state.dateEnv.toDate(state.currentDate);
5001 }
5002 // Date Formatting Utils
5003 // -----------------------------------------------------------------------------------------------------------------
5004 formatDate(d, formatter) {
5005 let { dateEnv } = this.getCurrentData();
5006 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
5007 }
5008 // `settings` is for formatter AND isEndExclusive
5009 formatRange(d0, d1, settings) {
5010 let { dateEnv } = this.getCurrentData();
5011 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
5012 }
5013 formatIso(d, omitTime) {
5014 let { dateEnv } = this.getCurrentData();
5015 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
5016 }
5017 // Date Selection / Event Selection / DayClick
5018 // -----------------------------------------------------------------------------------------------------------------
5019 select(dateOrObj, endDate) {
5020 let selectionInput;
5021 if (endDate == null) {
5022 if (dateOrObj.start != null) {
5023 selectionInput = dateOrObj;
5024 }
5025 else {
5026 selectionInput = {
5027 start: dateOrObj,
5028 end: null,
5029 };
5030 }
5031 }
5032 else {
5033 selectionInput = {
5034 start: dateOrObj,
5035 end: endDate,
5036 };
5037 }
5038 let state = this.getCurrentData();
5039 let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
5040 if (selection) { // throw parse error otherwise?
5041 this.dispatch({ type: 'SELECT_DATES', selection });
5042 triggerDateSelect(selection, null, state);
5043 }
5044 }
5045 unselect(pev) {
5046 let state = this.getCurrentData();
5047 if (state.dateSelection) {
5048 this.dispatch({ type: 'UNSELECT_DATES' });
5049 triggerDateUnselect(pev, state);
5050 }
5051 }
5052 // Public Events API
5053 // -----------------------------------------------------------------------------------------------------------------
5054 addEvent(eventInput, sourceInput) {
5055 if (eventInput instanceof EventImpl) {
5056 let def = eventInput._def;
5057 let instance = eventInput._instance;
5058 let currentData = this.getCurrentData();
5059 // not already present? don't want to add an old snapshot
5060 if (!currentData.eventStore.defs[def.defId]) {
5061 this.dispatch({
5062 type: 'ADD_EVENTS',
5063 eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
5064 });
5065 this.triggerEventAdd(eventInput);
5066 }
5067 return eventInput;
5068 }
5069 let state = this.getCurrentData();
5070 let eventSource;
5071 if (sourceInput instanceof EventSourceImpl) {
5072 eventSource = sourceInput.internalEventSource;
5073 }
5074 else if (typeof sourceInput === 'boolean') {
5075 if (sourceInput) { // true. part of the first event source
5076 [eventSource] = hashValuesToArray(state.eventSources);
5077 }
5078 }
5079 else if (sourceInput != null) { // an ID. accepts a number too
5080 let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
5081 if (!sourceApi) {
5082 console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
5083 return null;
5084 }
5085 eventSource = sourceApi.internalEventSource;
5086 }
5087 let tuple = parseEvent(eventInput, eventSource, state, false);
5088 if (tuple) {
5089 let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
5090 this.dispatch({
5091 type: 'ADD_EVENTS',
5092 eventStore: eventTupleToStore(tuple),
5093 });
5094 this.triggerEventAdd(newEventApi);
5095 return newEventApi;
5096 }
5097 return null;
5098 }
5099 triggerEventAdd(eventApi) {
5100 let { emitter } = this.getCurrentData();
5101 emitter.trigger('eventAdd', {
5102 event: eventApi,
5103 relatedEvents: [],
5104 revert: () => {
5105 this.dispatch({
5106 type: 'REMOVE_EVENTS',
5107 eventStore: eventApiToStore(eventApi),
5108 });
5109 },
5110 });
5111 }
5112 // TODO: optimize
5113 getEventById(id) {
5114 let state = this.getCurrentData();
5115 let { defs, instances } = state.eventStore;
5116 id = String(id);
5117 for (let defId in defs) {
5118 let def = defs[defId];
5119 if (def.publicId === id) {
5120 if (def.recurringDef) {
5121 return new EventImpl(state, def, null);
5122 }
5123 for (let instanceId in instances) {
5124 let instance = instances[instanceId];
5125 if (instance.defId === def.defId) {
5126 return new EventImpl(state, def, instance);
5127 }
5128 }
5129 }
5130 }
5131 return null;
5132 }
5133 getEvents() {
5134 let currentData = this.getCurrentData();
5135 return buildEventApis(currentData.eventStore, currentData);
5136 }
5137 removeAllEvents() {
5138 this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
5139 }
5140 // Public Event Sources API
5141 // -----------------------------------------------------------------------------------------------------------------
5142 getEventSources() {
5143 let state = this.getCurrentData();
5144 let sourceHash = state.eventSources;
5145 let sourceApis = [];
5146 for (let internalId in sourceHash) {
5147 sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
5148 }
5149 return sourceApis;
5150 }
5151 getEventSourceById(id) {
5152 let state = this.getCurrentData();
5153 let sourceHash = state.eventSources;
5154 id = String(id);
5155 for (let sourceId in sourceHash) {
5156 if (sourceHash[sourceId].publicId === id) {
5157 return new EventSourceImpl(state, sourceHash[sourceId]);
5158 }
5159 }
5160 return null;
5161 }
5162 addEventSource(sourceInput) {
5163 let state = this.getCurrentData();
5164 if (sourceInput instanceof EventSourceImpl) {
5165 // not already present? don't want to add an old snapshot
5166 if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
5167 this.dispatch({
5168 type: 'ADD_EVENT_SOURCES',
5169 sources: [sourceInput.internalEventSource],
5170 });
5171 }
5172 return sourceInput;
5173 }
5174 let eventSource = parseEventSource(sourceInput, state);
5175 if (eventSource) { // TODO: error otherwise?
5176 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
5177 return new EventSourceImpl(state, eventSource);
5178 }
5179 return null;
5180 }
5181 removeAllEventSources() {
5182 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
5183 }
5184 refetchEvents() {
5185 this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
5186 }
5187 // Scroll
5188 // -----------------------------------------------------------------------------------------------------------------
5189 scrollToTime(timeInput) {
5190 let time = createDuration(timeInput);
5191 if (time) {
5192 this.trigger('_scrollRequest', { time });
5193 }
5194 }
5195 }
5196
5197 function pointInsideRect(point, rect) {
5198 return point.left >= rect.left &&
5199 point.left < rect.right &&
5200 point.top >= rect.top &&
5201 point.top < rect.bottom;
5202 }
5203 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
5204 function intersectRects(rect1, rect2) {
5205 let res = {
5206 left: Math.max(rect1.left, rect2.left),
5207 right: Math.min(rect1.right, rect2.right),
5208 top: Math.max(rect1.top, rect2.top),
5209 bottom: Math.min(rect1.bottom, rect2.bottom),
5210 };
5211 if (res.left < res.right && res.top < res.bottom) {
5212 return res;
5213 }
5214 return false;
5215 }
5216 function translateRect(rect, deltaX, deltaY) {
5217 return {
5218 left: rect.left + deltaX,
5219 right: rect.right + deltaX,
5220 top: rect.top + deltaY,
5221 bottom: rect.bottom + deltaY,
5222 };
5223 }
5224 // Returns a new point that will have been moved to reside within the given rectangle
5225 function constrainPoint(point, rect) {
5226 return {
5227 left: Math.min(Math.max(point.left, rect.left), rect.right),
5228 top: Math.min(Math.max(point.top, rect.top), rect.bottom),
5229 };
5230 }
5231 // Returns a point that is the center of the given rectangle
5232 function getRectCenter(rect) {
5233 return {
5234 left: (rect.left + rect.right) / 2,
5235 top: (rect.top + rect.bottom) / 2,
5236 };
5237 }
5238 // Subtracts point2's coordinates from point1's coordinates, returning a delta
5239 function diffPoints(point1, point2) {
5240 return {
5241 left: point1.left - point2.left,
5242 top: point1.top - point2.top,
5243 };
5244 }
5245
5246 const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
5247 class Splitter {
5248 constructor() {
5249 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
5250 this.splitDateSelection = memoize(this._splitDateSpan);
5251 this.splitEventStore = memoize(this._splitEventStore);
5252 this.splitIndividualUi = memoize(this._splitIndividualUi);
5253 this.splitEventDrag = memoize(this._splitInteraction);
5254 this.splitEventResize = memoize(this._splitInteraction);
5255 this.eventUiBuilders = {}; // TODO: typescript protection
5256 }
5257 splitProps(props) {
5258 let keyInfos = this.getKeyInfo(props);
5259 let defKeys = this.getKeysForEventDefs(props.eventStore);
5260 let dateSelections = this.splitDateSelection(props.dateSelection);
5261 let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
5262 let eventStores = this.splitEventStore(props.eventStore, defKeys);
5263 let eventDrags = this.splitEventDrag(props.eventDrag);
5264 let eventResizes = this.splitEventResize(props.eventResize);
5265 let splitProps = {};
5266 this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
5267 for (let key in keyInfos) {
5268 let keyInfo = keyInfos[key];
5269 let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
5270 let buildEventUi = this.eventUiBuilders[key];
5271 splitProps[key] = {
5272 businessHours: keyInfo.businessHours || props.businessHours,
5273 dateSelection: dateSelections[key] || null,
5274 eventStore,
5275 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
5276 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
5277 eventDrag: eventDrags[key] || null,
5278 eventResize: eventResizes[key] || null,
5279 };
5280 }
5281 return splitProps;
5282 }
5283 _splitDateSpan(dateSpan) {
5284 let dateSpans = {};
5285 if (dateSpan) {
5286 let keys = this.getKeysForDateSpan(dateSpan);
5287 for (let key of keys) {
5288 dateSpans[key] = dateSpan;
5289 }
5290 }
5291 return dateSpans;
5292 }
5293 _getKeysForEventDefs(eventStore) {
5294 return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
5295 }
5296 _splitEventStore(eventStore, defKeys) {
5297 let { defs, instances } = eventStore;
5298 let splitStores = {};
5299 for (let defId in defs) {
5300 for (let key of defKeys[defId]) {
5301 if (!splitStores[key]) {
5302 splitStores[key] = createEmptyEventStore();
5303 }
5304 splitStores[key].defs[defId] = defs[defId];
5305 }
5306 }
5307 for (let instanceId in instances) {
5308 let instance = instances[instanceId];
5309 for (let key of defKeys[instance.defId]) {
5310 if (splitStores[key]) { // must have already been created
5311 splitStores[key].instances[instanceId] = instance;
5312 }
5313 }
5314 }
5315 return splitStores;
5316 }
5317 _splitIndividualUi(eventUiBases, defKeys) {
5318 let splitHashes = {};
5319 for (let defId in eventUiBases) {
5320 if (defId) { // not the '' key
5321 for (let key of defKeys[defId]) {
5322 if (!splitHashes[key]) {
5323 splitHashes[key] = {};
5324 }
5325 splitHashes[key][defId] = eventUiBases[defId];
5326 }
5327 }
5328 }
5329 return splitHashes;
5330 }
5331 _splitInteraction(interaction) {
5332 let splitStates = {};
5333 if (interaction) {
5334 let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
5335 // can't rely on defKeys because event data is mutated
5336 let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
5337 let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
5338 let populate = (key) => {
5339 if (!splitStates[key]) {
5340 splitStates[key] = {
5341 affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
5342 mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
5343 isEvent: interaction.isEvent,
5344 };
5345 }
5346 };
5347 for (let key in affectedStores) {
5348 populate(key);
5349 }
5350 for (let key in mutatedStores) {
5351 populate(key);
5352 }
5353 }
5354 return splitStates;
5355 }
5356 }
5357 function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
5358 let baseParts = [];
5359 if (allUi) {
5360 baseParts.push(allUi);
5361 }
5362 if (eventUiForKey) {
5363 baseParts.push(eventUiForKey);
5364 }
5365 let stuff = {
5366 '': combineEventUis(baseParts),
5367 };
5368 if (individualUi) {
5369 Object.assign(stuff, individualUi);
5370 }
5371 return stuff;
5372 }
5373
5374 function getDateMeta(date, todayRange, nowDate, dateProfile) {
5375 return {
5376 dow: date.getUTCDay(),
5377 isDisabled: Boolean(dateProfile && (!dateProfile.activeRange || !rangeContainsMarker(dateProfile.activeRange, date))),
5378 isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
5379 isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
5380 isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
5381 isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
5382 };
5383 }
5384 function getDayClassNames(meta, theme) {
5385 let classNames = [
5386 'fc-day',
5387 `fc-day-${DAY_IDS[meta.dow]}`,
5388 ];
5389 if (meta.isDisabled) {
5390 classNames.push('fc-day-disabled');
5391 }
5392 else {
5393 if (meta.isToday) {
5394 classNames.push('fc-day-today');
5395 classNames.push(theme.getClass('today'));
5396 }
5397 if (meta.isPast) {
5398 classNames.push('fc-day-past');
5399 }
5400 if (meta.isFuture) {
5401 classNames.push('fc-day-future');
5402 }
5403 if (meta.isOther) {
5404 classNames.push('fc-day-other');
5405 }
5406 }
5407 return classNames;
5408 }
5409 function getSlotClassNames(meta, theme) {
5410 let classNames = [
5411 'fc-slot',
5412 `fc-slot-${DAY_IDS[meta.dow]}`,
5413 ];
5414 if (meta.isDisabled) {
5415 classNames.push('fc-slot-disabled');
5416 }
5417 else {
5418 if (meta.isToday) {
5419 classNames.push('fc-slot-today');
5420 classNames.push(theme.getClass('today'));
5421 }
5422 if (meta.isPast) {
5423 classNames.push('fc-slot-past');
5424 }
5425 if (meta.isFuture) {
5426 classNames.push('fc-slot-future');
5427 }
5428 }
5429 return classNames;
5430 }
5431
5432 const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
5433 const WEEK_FORMAT = createFormatter({ week: 'long' });
5434 function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
5435 const { dateEnv, options, calendarApi } = context;
5436 let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
5437 if (options.navLinks) {
5438 let zonedDate = dateEnv.toDate(dateMarker);
5439 const handleInteraction = (ev) => {
5440 let customAction = viewType === 'day' ? options.navLinkDayClick :
5441 viewType === 'week' ? options.navLinkWeekClick : null;
5442 if (typeof customAction === 'function') {
5443 customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
5444 }
5445 else {
5446 if (typeof customAction === 'string') {
5447 viewType = customAction;
5448 }
5449 calendarApi.zoomTo(dateMarker, viewType);
5450 }
5451 };
5452 return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
5453 ? createAriaClickAttrs(handleInteraction)
5454 : { onClick: handleInteraction }));
5455 }
5456 return { 'aria-label': dateStr };
5457 }
5458
5459 let _isRtlScrollbarOnLeft = null;
5460 function getIsRtlScrollbarOnLeft() {
5461 if (_isRtlScrollbarOnLeft === null) {
5462 _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
5463 }
5464 return _isRtlScrollbarOnLeft;
5465 }
5466 function computeIsRtlScrollbarOnLeft() {
5467 let outerEl = document.createElement('div');
5468 applyStyle(outerEl, {
5469 position: 'absolute',
5470 top: -1000,
5471 left: 0,
5472 border: 0,
5473 padding: 0,
5474 overflow: 'scroll',
5475 direction: 'rtl',
5476 });
5477 outerEl.innerHTML = '<div></div>';
5478 document.body.appendChild(outerEl);
5479 let innerEl = outerEl.firstChild;
5480 let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
5481 removeElement(outerEl);
5482 return res;
5483 }
5484
5485 let _scrollbarWidths;
5486 function getScrollbarWidths() {
5487 if (!_scrollbarWidths) {
5488 _scrollbarWidths = computeScrollbarWidths();
5489 }
5490 return _scrollbarWidths;
5491 }
5492 function computeScrollbarWidths() {
5493 let el = document.createElement('div');
5494 el.style.overflow = 'scroll';
5495 el.style.position = 'absolute';
5496 el.style.top = '-9999px';
5497 el.style.left = '-9999px';
5498 document.body.appendChild(el);
5499 let res = computeScrollbarWidthsForEl(el);
5500 document.body.removeChild(el);
5501 return res;
5502 }
5503 // WARNING: will include border
5504 function computeScrollbarWidthsForEl(el) {
5505 return {
5506 x: el.offsetHeight - el.clientHeight,
5507 y: el.offsetWidth - el.clientWidth,
5508 };
5509 }
5510
5511 function computeEdges(el, getPadding = false) {
5512 let computedStyle = window.getComputedStyle(el);
5513 let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
5514 let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
5515 let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
5516 let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
5517 let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
5518 let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
5519 let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
5520 let res = {
5521 borderLeft,
5522 borderRight,
5523 borderTop,
5524 borderBottom,
5525 scrollbarBottom,
5526 scrollbarLeft: 0,
5527 scrollbarRight: 0,
5528 };
5529 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
5530 res.scrollbarLeft = scrollbarLeftRight;
5531 }
5532 else {
5533 res.scrollbarRight = scrollbarLeftRight;
5534 }
5535 if (getPadding) {
5536 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
5537 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
5538 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
5539 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
5540 }
5541 return res;
5542 }
5543 function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
5544 let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
5545 let edges = computeEdges(el, goWithinPadding);
5546 let res = {
5547 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
5548 right: outerRect.right - edges.borderRight - edges.scrollbarRight,
5549 top: outerRect.top + edges.borderTop,
5550 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
5551 };
5552 if (goWithinPadding) {
5553 res.left += edges.paddingLeft;
5554 res.right -= edges.paddingRight;
5555 res.top += edges.paddingTop;
5556 res.bottom -= edges.paddingBottom;
5557 }
5558 return res;
5559 }
5560 function computeRect(el) {
5561 let rect = el.getBoundingClientRect();
5562 return {
5563 left: rect.left + window.scrollX,
5564 top: rect.top + window.scrollY,
5565 right: rect.right + window.scrollX,
5566 bottom: rect.bottom + window.scrollY,
5567 };
5568 }
5569 function computeClippedClientRect(el) {
5570 let clippingParents = getClippingParents(el);
5571 let rect = el.getBoundingClientRect();
5572 for (let clippingParent of clippingParents) {
5573 let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
5574 if (intersection) {
5575 rect = intersection;
5576 }
5577 else {
5578 return null;
5579 }
5580 }
5581 return rect;
5582 }
5583 // does not return window
5584 function getClippingParents(el) {
5585 let parents = [];
5586 while (el instanceof HTMLElement) { // will stop when gets to document or null
5587 let computedStyle = window.getComputedStyle(el);
5588 if (computedStyle.position === 'fixed') {
5589 break;
5590 }
5591 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
5592 parents.push(el);
5593 }
5594 el = el.parentNode;
5595 }
5596 return parents;
5597 }
5598
5599 /*
5600 Records offset information for a set of elements, relative to an origin element.
5601 Can record the left/right OR the top/bottom OR both.
5602 Provides methods for querying the cache by position.
5603 */
5604 class PositionCache {
5605 constructor(originEl, els, isHorizontal, isVertical) {
5606 this.els = els;
5607 let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
5608 if (isHorizontal) {
5609 this.buildElHorizontals(originClientRect.left);
5610 }
5611 if (isVertical) {
5612 this.buildElVerticals(originClientRect.top);
5613 }
5614 }
5615 // Populates the left/right internal coordinate arrays
5616 buildElHorizontals(originClientLeft) {
5617 let lefts = [];
5618 let rights = [];
5619 for (let el of this.els) {
5620 let rect = el.getBoundingClientRect();
5621 lefts.push(rect.left - originClientLeft);
5622 rights.push(rect.right - originClientLeft);
5623 }
5624 this.lefts = lefts;
5625 this.rights = rights;
5626 }
5627 // Populates the top/bottom internal coordinate arrays
5628 buildElVerticals(originClientTop) {
5629 let tops = [];
5630 let bottoms = [];
5631 for (let el of this.els) {
5632 let rect = el.getBoundingClientRect();
5633 tops.push(rect.top - originClientTop);
5634 bottoms.push(rect.bottom - originClientTop);
5635 }
5636 this.tops = tops;
5637 this.bottoms = bottoms;
5638 }
5639 // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
5640 // If no intersection is made, returns undefined.
5641 leftToIndex(leftPosition) {
5642 let { lefts, rights } = this;
5643 let len = lefts.length;
5644 let i;
5645 for (i = 0; i < len; i += 1) {
5646 if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
5647 return i;
5648 }
5649 }
5650 return undefined; // TODO: better
5651 }
5652 // Given a top offset (from document top), returns the index of the el that it vertically intersects.
5653 // If no intersection is made, returns undefined.
5654 topToIndex(topPosition) {
5655 let { tops, bottoms } = this;
5656 let len = tops.length;
5657 let i;
5658 for (i = 0; i < len; i += 1) {
5659 if (topPosition >= tops[i] && topPosition < bottoms[i]) {
5660 return i;
5661 }
5662 }
5663 return undefined; // TODO: better
5664 }
5665 // Gets the width of the element at the given index
5666 getWidth(leftIndex) {
5667 return this.rights[leftIndex] - this.lefts[leftIndex];
5668 }
5669 // Gets the height of the element at the given index
5670 getHeight(topIndex) {
5671 return this.bottoms[topIndex] - this.tops[topIndex];
5672 }
5673 similarTo(otherCache) {
5674 return similarNumArrays(this.tops || [], otherCache.tops || []) &&
5675 similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
5676 similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
5677 similarNumArrays(this.rights || [], otherCache.rights || []);
5678 }
5679 }
5680 function similarNumArrays(a, b) {
5681 const len = a.length;
5682 if (len !== b.length) {
5683 return false;
5684 }
5685 for (let i = 0; i < len; i++) {
5686 if (Math.round(a[i]) !== Math.round(b[i])) {
5687 return false;
5688 }
5689 }
5690 return true;
5691 }
5692
5693 /* eslint max-classes-per-file: "off" */
5694 /*
5695 An object for getting/setting scroll-related information for an element.
5696 Internally, this is done very differently for window versus DOM element,
5697 so this object serves as a common interface.
5698 */
5699 class ScrollController {
5700 getMaxScrollTop() {
5701 return this.getScrollHeight() - this.getClientHeight();
5702 }
5703 getMaxScrollLeft() {
5704 return this.getScrollWidth() - this.getClientWidth();
5705 }
5706 canScrollVertically() {
5707 return this.getMaxScrollTop() > 0;
5708 }
5709 canScrollHorizontally() {
5710 return this.getMaxScrollLeft() > 0;
5711 }
5712 canScrollUp() {
5713 return this.getScrollTop() > 0;
5714 }
5715 canScrollDown() {
5716 return this.getScrollTop() < this.getMaxScrollTop();
5717 }
5718 canScrollLeft() {
5719 return this.getScrollLeft() > 0;
5720 }
5721 canScrollRight() {
5722 return this.getScrollLeft() < this.getMaxScrollLeft();
5723 }
5724 }
5725 class ElementScrollController extends ScrollController {
5726 constructor(el) {
5727 super();
5728 this.el = el;
5729 }
5730 getScrollTop() {
5731 return this.el.scrollTop;
5732 }
5733 getScrollLeft() {
5734 return this.el.scrollLeft;
5735 }
5736 setScrollTop(top) {
5737 this.el.scrollTop = top;
5738 }
5739 setScrollLeft(left) {
5740 this.el.scrollLeft = left;
5741 }
5742 getScrollWidth() {
5743 return this.el.scrollWidth;
5744 }
5745 getScrollHeight() {
5746 return this.el.scrollHeight;
5747 }
5748 getClientHeight() {
5749 return this.el.clientHeight;
5750 }
5751 getClientWidth() {
5752 return this.el.clientWidth;
5753 }
5754 }
5755 class WindowScrollController extends ScrollController {
5756 getScrollTop() {
5757 return window.scrollY;
5758 }
5759 getScrollLeft() {
5760 return window.scrollX;
5761 }
5762 setScrollTop(n) {
5763 window.scroll(window.scrollX, n);
5764 }
5765 setScrollLeft(n) {
5766 window.scroll(n, window.scrollY);
5767 }
5768 getScrollWidth() {
5769 return document.documentElement.scrollWidth;
5770 }
5771 getScrollHeight() {
5772 return document.documentElement.scrollHeight;
5773 }
5774 getClientHeight() {
5775 return document.documentElement.clientHeight;
5776 }
5777 getClientWidth() {
5778 return document.documentElement.clientWidth;
5779 }
5780 }
5781
5782 /*
5783 an INTERACTABLE date component
5784
5785 PURPOSES:
5786 - hook up to fg, fill, and mirror renderers
5787 - interface for dragging and hits
5788 */
5789 class DateComponent extends BaseComponent {
5790 constructor() {
5791 super(...arguments);
5792 this.uid = guid();
5793 }
5794 // Hit System
5795 // -----------------------------------------------------------------------------------------------------------------
5796 prepareHits() {
5797 }
5798 queryHit(positionLeft, positionTop, elWidth, elHeight) {
5799 return null; // this should be abstract
5800 }
5801 // Pointer Interaction Utils
5802 // -----------------------------------------------------------------------------------------------------------------
5803 isValidSegDownEl(el) {
5804 return !this.props.eventDrag && // HACK
5805 !this.props.eventResize && // HACK
5806 !elementClosest(el, '.fc-event-mirror');
5807 }
5808 isValidDateDownEl(el) {
5809 return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
5810 !elementClosest(el, '.fc-more-link') && // a "more.." link
5811 !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
5812 !elementClosest(el, '.fc-popover'); // hack
5813 }
5814 }
5815
5816 class NamedTimeZoneImpl {
5817 constructor(timeZoneName) {
5818 this.timeZoneName = timeZoneName;
5819 }
5820 }
5821
5822 class SegHierarchy {
5823 constructor(getEntryThickness = (entry) => {
5824 // if no thickness known, assume 1 (if 0, so small it always fits)
5825 return entry.thickness || 1;
5826 }) {
5827 this.getEntryThickness = getEntryThickness;
5828 // settings
5829 this.strictOrder = false;
5830 this.allowReslicing = false;
5831 this.maxCoord = -1; // -1 means no max
5832 this.maxStackCnt = -1; // -1 means no max
5833 this.levelCoords = []; // ordered
5834 this.entriesByLevel = []; // parallel with levelCoords
5835 this.stackCnts = {}; // TODO: use better technique!?
5836 }
5837 addSegs(inputs) {
5838 let hiddenEntries = [];
5839 for (let input of inputs) {
5840 this.insertEntry(input, hiddenEntries);
5841 }
5842 return hiddenEntries;
5843 }
5844 insertEntry(entry, hiddenEntries) {
5845 let insertion = this.findInsertion(entry);
5846 if (this.isInsertionValid(insertion, entry)) {
5847 this.insertEntryAt(entry, insertion);
5848 }
5849 else {
5850 this.handleInvalidInsertion(insertion, entry, hiddenEntries);
5851 }
5852 }
5853 isInsertionValid(insertion, entry) {
5854 return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&
5855 (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
5856 }
5857 handleInvalidInsertion(insertion, entry, hiddenEntries) {
5858 if (this.allowReslicing && insertion.touchingEntry) {
5859 const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });
5860 hiddenEntries.push(hiddenEntry);
5861 this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
5862 }
5863 else {
5864 hiddenEntries.push(entry);
5865 }
5866 }
5867 /*
5868 Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.
5869 */
5870 splitEntry(entry, barrier, hiddenEntries) {
5871 let entrySpan = entry.span;
5872 let barrierSpan = barrier.span;
5873 if (entrySpan.start < barrierSpan.start) {
5874 this.insertEntry({
5875 index: entry.index,
5876 thickness: entry.thickness,
5877 span: { start: entrySpan.start, end: barrierSpan.start },
5878 }, hiddenEntries);
5879 }
5880 if (entrySpan.end > barrierSpan.end) {
5881 this.insertEntry({
5882 index: entry.index,
5883 thickness: entry.thickness,
5884 span: { start: barrierSpan.end, end: entrySpan.end },
5885 }, hiddenEntries);
5886 }
5887 }
5888 insertEntryAt(entry, insertion) {
5889 let { entriesByLevel, levelCoords } = this;
5890 if (insertion.lateral === -1) {
5891 // create a new level
5892 insertAt(levelCoords, insertion.level, insertion.levelCoord);
5893 insertAt(entriesByLevel, insertion.level, [entry]);
5894 }
5895 else {
5896 // insert into existing level
5897 insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
5898 }
5899 this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
5900 }
5901 /*
5902 does not care about limits
5903 */
5904 findInsertion(newEntry) {
5905 let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
5906 let levelCnt = levelCoords.length;
5907 let candidateCoord = 0;
5908 let touchingLevel = -1;
5909 let touchingLateral = -1;
5910 let touchingEntry = null;
5911 let stackCnt = 0;
5912 for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
5913 const trackingCoord = levelCoords[trackingLevel];
5914 // if the current level is past the placed entry, we have found a good empty space and can stop.
5915 // if strictOrder, keep finding more lateral intersections.
5916 if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {
5917 break;
5918 }
5919 let trackingEntries = entriesByLevel[trackingLevel];
5920 let trackingEntry;
5921 let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
5922 let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
5923 while ( // loop through entries that horizontally intersect
5924 (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
5925 trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
5926 ) {
5927 let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
5928 // intersects into the top of the candidate?
5929 if (trackingEntryBottom > candidateCoord) {
5930 candidateCoord = trackingEntryBottom;
5931 touchingEntry = trackingEntry;
5932 touchingLevel = trackingLevel;
5933 touchingLateral = lateralIndex;
5934 }
5935 // butts up against top of candidate? (will happen if just intersected as well)
5936 if (trackingEntryBottom === candidateCoord) {
5937 // accumulate the highest possible stackCnt of the trackingEntries that butt up
5938 stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
5939 }
5940 lateralIndex += 1;
5941 }
5942 }
5943 // the destination level will be after touchingEntry's level. find it
5944 let destLevel = 0;
5945 if (touchingEntry) {
5946 destLevel = touchingLevel + 1;
5947 while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
5948 destLevel += 1;
5949 }
5950 }
5951 // if adding to an existing level, find where to insert
5952 let destLateral = -1;
5953 if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
5954 destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
5955 }
5956 return {
5957 touchingLevel,
5958 touchingLateral,
5959 touchingEntry,
5960 stackCnt,
5961 levelCoord: candidateCoord,
5962 level: destLevel,
5963 lateral: destLateral,
5964 };
5965 }
5966 // sorted by levelCoord (lowest to highest)
5967 toRects() {
5968 let { entriesByLevel, levelCoords } = this;
5969 let levelCnt = entriesByLevel.length;
5970 let rects = [];
5971 for (let level = 0; level < levelCnt; level += 1) {
5972 let entries = entriesByLevel[level];
5973 let levelCoord = levelCoords[level];
5974 for (let entry of entries) {
5975 rects.push(Object.assign(Object.assign({}, entry), { thickness: this.getEntryThickness(entry), levelCoord }));
5976 }
5977 }
5978 return rects;
5979 }
5980 }
5981 function getEntrySpanEnd(entry) {
5982 return entry.span.end;
5983 }
5984 function buildEntryKey(entry) {
5985 return entry.index + ':' + entry.span.start;
5986 }
5987 // returns groups with entries sorted by input order
5988 function groupIntersectingEntries(entries) {
5989 let merges = [];
5990 for (let entry of entries) {
5991 let filteredMerges = [];
5992 let hungryMerge = {
5993 span: entry.span,
5994 entries: [entry],
5995 };
5996 for (let merge of merges) {
5997 if (intersectSpans(merge.span, hungryMerge.span)) {
5998 hungryMerge = {
5999 entries: merge.entries.concat(hungryMerge.entries),
6000 span: joinSpans(merge.span, hungryMerge.span),
6001 };
6002 }
6003 else {
6004 filteredMerges.push(merge);
6005 }
6006 }
6007 filteredMerges.push(hungryMerge);
6008 merges = filteredMerges;
6009 }
6010 return merges;
6011 }
6012 function joinSpans(span0, span1) {
6013 return {
6014 start: Math.min(span0.start, span1.start),
6015 end: Math.max(span0.end, span1.end),
6016 };
6017 }
6018 function intersectSpans(span0, span1) {
6019 let start = Math.max(span0.start, span1.start);
6020 let end = Math.min(span0.end, span1.end);
6021 if (start < end) {
6022 return { start, end };
6023 }
6024 return null;
6025 }
6026 // general util
6027 // ---------------------------------------------------------------------------------------------------------------------
6028 function insertAt(arr, index, item) {
6029 arr.splice(index, 0, item);
6030 }
6031 function binarySearch(a, searchVal, getItemVal) {
6032 let startIndex = 0;
6033 let endIndex = a.length; // exclusive
6034 if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
6035 return [0, 0];
6036 }
6037 if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
6038 return [endIndex, 0];
6039 }
6040 while (startIndex < endIndex) {
6041 let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
6042 let middleVal = getItemVal(a[middleIndex]);
6043 if (searchVal < middleVal) {
6044 endIndex = middleIndex;
6045 }
6046 else if (searchVal > middleVal) {
6047 startIndex = middleIndex + 1;
6048 }
6049 else { // equal!
6050 return [middleIndex, 1];
6051 }
6052 }
6053 return [startIndex, 0];
6054 }
6055
6056 /*
6057 An abstraction for a dragging interaction originating on an event.
6058 Does higher-level things than PointerDragger, such as possibly:
6059 - a "mirror" that moves with the pointer
6060 - a minimum number of pixels or other criteria for a true drag to begin
6061
6062 subclasses must emit:
6063 - pointerdown
6064 - dragstart
6065 - dragmove
6066 - pointerup
6067 - dragend
6068 */
6069 class ElementDragging {
6070 constructor(el, selector) {
6071 this.emitter = new Emitter();
6072 }
6073 destroy() {
6074 }
6075 setMirrorIsVisible(bool) {
6076 // optional if subclass doesn't want to support a mirror
6077 }
6078 setMirrorNeedsRevert(bool) {
6079 // optional if subclass doesn't want to support a mirror
6080 }
6081 setAutoScrollEnabled(bool) {
6082 // optional
6083 }
6084 }
6085
6086 // TODO: get rid of this in favor of options system,
6087 // tho it's really easy to access this globally rather than pass thru options.
6088 const config = {};
6089
6090 /*
6091 Information about what will happen when an external element is dragged-and-dropped
6092 onto a calendar. Contains information for creating an event.
6093 */
6094 const DRAG_META_REFINERS = {
6095 startTime: createDuration,
6096 duration: createDuration,
6097 create: Boolean,
6098 sourceId: String,
6099 };
6100 function parseDragMeta(raw) {
6101 let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
6102 return {
6103 startTime: refined.startTime || null,
6104 duration: refined.duration || null,
6105 create: refined.create != null ? refined.create : true,
6106 sourceId: refined.sourceId,
6107 leftoverProps: extra,
6108 };
6109 }
6110
6111 // Computes a default column header formatting string if `colFormat` is not explicitly defined
6112 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
6113 // if more than one week row, or if there are a lot of columns with not much space,
6114 // put just the day numbers will be in each cell
6115 if (!datesRepDistinctDays || dayCnt > 10) {
6116 return createFormatter({ weekday: 'short' }); // "Sat"
6117 }
6118 if (dayCnt > 1) {
6119 return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
6120 }
6121 return createFormatter({ weekday: 'long' }); // "Saturday"
6122 }
6123
6124 const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
6125 function renderInner$1(renderProps) {
6126 return renderProps.text;
6127 }
6128
6129 // BAD name for this class now. used in the Header
6130 class TableDateCell extends BaseComponent {
6131 render() {
6132 let { dateEnv, options, theme, viewApi } = this.context;
6133 let { props } = this;
6134 let { date, dateProfile } = props;
6135 let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
6136 let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
6137 let text = dateEnv.format(date, props.dayHeaderFormat);
6138 // if colCnt is 1, we are already in a day-view and don't need a navlink
6139 let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
6140 ? buildNavLinkAttrs(this.context, date)
6141 : {};
6142 let publicDate = dateEnv.toDate(date);
6143 // workaround for Luxon (and maybe moment) returning prior-days when start-of-day
6144 // in DST gap: https://github.com/fullcalendar/fullcalendar/issues/7633
6145 if (dateEnv.namedTimeZoneImpl) {
6146 publicDate = addMs(publicDate, 3600000); // add an hour
6147 }
6148 let renderProps = Object.assign(Object.assign(Object.assign({ date: publicDate, view: viewApi }, props.extraRenderProps), { text }), dayMeta);
6149 return (y(ContentContainer, { elTag: "th", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (y("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (y(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
6150 'fc-col-header-cell-cushion',
6151 props.isSticky && 'fc-sticky',
6152 ] }))))));
6153 }
6154 }
6155
6156 const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
6157 class TableDowCell extends BaseComponent {
6158 render() {
6159 let { props } = this;
6160 let { dateEnv, theme, viewApi, options } = this.context;
6161 let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
6162 let dateMeta = {
6163 dow: props.dow,
6164 isDisabled: false,
6165 isFuture: false,
6166 isPast: false,
6167 isToday: false,
6168 isOther: false,
6169 };
6170 let text = dateEnv.format(date, props.dayHeaderFormat);
6171 let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
6172 date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
6173 return (y(ContentContainer, { elTag: "th", elClasses: [
6174 CLASS_NAME,
6175 ...getDayClassNames(dateMeta, theme),
6176 ...(props.extraClassNames || []),
6177 ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (y("div", { className: "fc-scrollgrid-sync-inner" },
6178 y(InnerContent, { elTag: "a", elClasses: [
6179 'fc-col-header-cell-cushion',
6180 props.isSticky && 'fc-sticky',
6181 ], elAttrs: {
6182 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
6183 } })))));
6184 }
6185 }
6186
6187 class DayHeader extends BaseComponent {
6188 constructor() {
6189 super(...arguments);
6190 this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
6191 }
6192 render() {
6193 let { context } = this;
6194 let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;
6195 let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
6196 return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => (y("tr", { role: "row" },
6197 renderIntro && renderIntro('day'),
6198 dates.map((date) => (datesRepDistinctDays ? (y(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (y(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));
6199 }
6200 }
6201 function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
6202 return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
6203 }
6204
6205 class DaySeriesModel {
6206 constructor(range, dateProfileGenerator) {
6207 let date = range.start;
6208 let { end } = range;
6209 let indices = [];
6210 let dates = [];
6211 let dayIndex = -1;
6212 while (date < end) { // loop each day from start to end
6213 if (dateProfileGenerator.isHiddenDay(date)) {
6214 indices.push(dayIndex + 0.5); // mark that it's between indices
6215 }
6216 else {
6217 dayIndex += 1;
6218 indices.push(dayIndex);
6219 dates.push(date);
6220 }
6221 date = addDays(date, 1);
6222 }
6223 this.dates = dates;
6224 this.indices = indices;
6225 this.cnt = dates.length;
6226 }
6227 sliceRange(range) {
6228 let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
6229 let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
6230 let clippedFirstIndex = Math.max(0, firstIndex);
6231 let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
6232 // deal with in-between indices
6233 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
6234 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
6235 if (clippedFirstIndex <= clippedLastIndex) {
6236 return {
6237 firstIndex: clippedFirstIndex,
6238 lastIndex: clippedLastIndex,
6239 isStart: firstIndex === clippedFirstIndex,
6240 isEnd: lastIndex === clippedLastIndex,
6241 };
6242 }
6243 return null;
6244 }
6245 // Given a date, returns its chronolocial cell-index from the first cell of the grid.
6246 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
6247 // If before the first offset, returns a negative number.
6248 // If after the last offset, returns an offset past the last cell offset.
6249 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
6250 getDateDayIndex(date) {
6251 let { indices } = this;
6252 let dayOffset = Math.floor(diffDays(this.dates[0], date));
6253 if (dayOffset < 0) {
6254 return indices[0] - 1;
6255 }
6256 if (dayOffset >= indices.length) {
6257 return indices[indices.length - 1] + 1;
6258 }
6259 return indices[dayOffset];
6260 }
6261 }
6262
6263 class DayTableModel {
6264 constructor(daySeries, breakOnWeeks) {
6265 let { dates } = daySeries;
6266 let daysPerRow;
6267 let firstDay;
6268 let rowCnt;
6269 if (breakOnWeeks) {
6270 // count columns until the day-of-week repeats
6271 firstDay = dates[0].getUTCDay();
6272 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
6273 if (dates[daysPerRow].getUTCDay() === firstDay) {
6274 break;
6275 }
6276 }
6277 rowCnt = Math.ceil(dates.length / daysPerRow);
6278 }
6279 else {
6280 rowCnt = 1;
6281 daysPerRow = dates.length;
6282 }
6283 this.rowCnt = rowCnt;
6284 this.colCnt = daysPerRow;
6285 this.daySeries = daySeries;
6286 this.cells = this.buildCells();
6287 this.headerDates = this.buildHeaderDates();
6288 }
6289 buildCells() {
6290 let rows = [];
6291 for (let row = 0; row < this.rowCnt; row += 1) {
6292 let cells = [];
6293 for (let col = 0; col < this.colCnt; col += 1) {
6294 cells.push(this.buildCell(row, col));
6295 }
6296 rows.push(cells);
6297 }
6298 return rows;
6299 }
6300 buildCell(row, col) {
6301 let date = this.daySeries.dates[row * this.colCnt + col];
6302 return {
6303 key: date.toISOString(),
6304 date,
6305 };
6306 }
6307 buildHeaderDates() {
6308 let dates = [];
6309 for (let col = 0; col < this.colCnt; col += 1) {
6310 dates.push(this.cells[0][col].date);
6311 }
6312 return dates;
6313 }
6314 sliceRange(range) {
6315 let { colCnt } = this;
6316 let seriesSeg = this.daySeries.sliceRange(range);
6317 let segs = [];
6318 if (seriesSeg) {
6319 let { firstIndex, lastIndex } = seriesSeg;
6320 let index = firstIndex;
6321 while (index <= lastIndex) {
6322 let row = Math.floor(index / colCnt);
6323 let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
6324 segs.push({
6325 row,
6326 firstCol: index % colCnt,
6327 lastCol: (nextIndex - 1) % colCnt,
6328 isStart: seriesSeg.isStart && index === firstIndex,
6329 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
6330 });
6331 index = nextIndex;
6332 }
6333 }
6334 return segs;
6335 }
6336 }
6337
6338 class Slicer {
6339 constructor() {
6340 this.sliceBusinessHours = memoize(this._sliceBusinessHours);
6341 this.sliceDateSelection = memoize(this._sliceDateSpan);
6342 this.sliceEventStore = memoize(this._sliceEventStore);
6343 this.sliceEventDrag = memoize(this._sliceInteraction);
6344 this.sliceEventResize = memoize(this._sliceInteraction);
6345 this.forceDayIfListItem = false; // hack
6346 }
6347 sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
6348 let { eventUiBases } = props;
6349 let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
6350 return {
6351 dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),
6352 businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
6353 fgEventSegs: eventSegs.fg,
6354 bgEventSegs: eventSegs.bg,
6355 eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6356 eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
6357 eventSelection: props.eventSelection,
6358 }; // TODO: give interactionSegs?
6359 }
6360 sliceNowDate(// does not memoize
6361 date, dateProfile, nextDayThreshold, context, ...extraArgs) {
6362 return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range
6363 dateProfile, nextDayThreshold, {}, context, ...extraArgs);
6364 }
6365 _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
6366 if (!businessHours) {
6367 return [];
6368 }
6369 return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
6370 }
6371 _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6372 if (eventStore) {
6373 let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6374 return {
6375 bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
6376 fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
6377 };
6378 }
6379 return { bg: [], fg: [] };
6380 }
6381 _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
6382 if (!interaction) {
6383 return null;
6384 }
6385 let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
6386 return {
6387 segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
6388 affectedInstances: interaction.affectedEvents.instances,
6389 isEvent: interaction.isEvent,
6390 };
6391 }
6392 _sliceDateSpan(dateSpan, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs) {
6393 if (!dateSpan) {
6394 return [];
6395 }
6396 let activeRange = computeActiveRange(dateProfile, Boolean(nextDayThreshold));
6397 let activeDateSpanRange = intersectRanges(dateSpan.range, activeRange);
6398 if (activeDateSpanRange) {
6399 dateSpan = Object.assign(Object.assign({}, dateSpan), { range: activeDateSpanRange });
6400 let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
6401 let segs = this.sliceRange(dateSpan.range, ...extraArgs);
6402 for (let seg of segs) {
6403 seg.eventRange = eventRange;
6404 }
6405 return segs;
6406 }
6407 return [];
6408 }
6409 /*
6410 "complete" seg means it has component and eventRange
6411 */
6412 sliceEventRanges(eventRanges, extraArgs) {
6413 let segs = [];
6414 for (let eventRange of eventRanges) {
6415 segs.push(...this.sliceEventRange(eventRange, extraArgs));
6416 }
6417 return segs;
6418 }
6419 /*
6420 "complete" seg means it has component and eventRange
6421 */
6422 sliceEventRange(eventRange, extraArgs) {
6423 let dateRange = eventRange.range;
6424 // hack to make multi-day events that are being force-displayed as list-items to take up only one day
6425 if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
6426 dateRange = {
6427 start: dateRange.start,
6428 end: addDays(dateRange.start, 1),
6429 };
6430 }
6431 let segs = this.sliceRange(dateRange, ...extraArgs);
6432 for (let seg of segs) {
6433 seg.eventRange = eventRange;
6434 seg.isStart = eventRange.isStart && seg.isStart;
6435 seg.isEnd = eventRange.isEnd && seg.isEnd;
6436 }
6437 return segs;
6438 }
6439 }
6440 /*
6441 for incorporating slotMinTime/slotMaxTime if appropriate
6442 TODO: should be part of DateProfile!
6443 TimelineDateProfile already does this btw
6444 */
6445 function computeActiveRange(dateProfile, isComponentAllDay) {
6446 let range = dateProfile.activeRange;
6447 if (isComponentAllDay) {
6448 return range;
6449 }
6450 return {
6451 start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
6452 end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
6453 };
6454 }
6455
6456 // high-level segmenting-aware tester functions
6457 // ------------------------------------------------------------------------------------------------------------------------
6458 function isInteractionValid(interaction, dateProfile, context) {
6459 let { instances } = interaction.mutatedEvents;
6460 for (let instanceId in instances) {
6461 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
6462 return false;
6463 }
6464 }
6465 return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
6466 }
6467 function isDateSelectionValid(dateSelection, dateProfile, context) {
6468 if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
6469 return false;
6470 }
6471 return isNewPropsValid({ dateSelection }, context);
6472 }
6473 function isNewPropsValid(newProps, context) {
6474 let calendarState = context.getCurrentData();
6475 let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
6476 return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
6477 }
6478 function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
6479 if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6480 return false;
6481 }
6482 if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
6483 return false;
6484 }
6485 return true;
6486 }
6487 // Moving Event Validation
6488 // ------------------------------------------------------------------------------------------------------------------------
6489 function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
6490 let currentState = context.getCurrentData();
6491 let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
6492 let subjectEventStore = interaction.mutatedEvents;
6493 let subjectDefs = subjectEventStore.defs;
6494 let subjectInstances = subjectEventStore.instances;
6495 let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
6496 state.eventUiBases :
6497 { '': currentState.selectionConfig });
6498 if (filterConfig) {
6499 subjectConfigs = mapHash(subjectConfigs, filterConfig);
6500 }
6501 // exclude the subject events. TODO: exclude defs too?
6502 let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
6503 let otherDefs = otherEventStore.defs;
6504 let otherInstances = otherEventStore.instances;
6505 let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
6506 for (let subjectInstanceId in subjectInstances) {
6507 let subjectInstance = subjectInstances[subjectInstanceId];
6508 let subjectRange = subjectInstance.range;
6509 let subjectConfig = subjectConfigs[subjectInstance.defId];
6510 let subjectDef = subjectDefs[subjectInstance.defId];
6511 // constraint
6512 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
6513 return false;
6514 }
6515 // overlap
6516 let { eventOverlap } = context.options;
6517 let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
6518 for (let otherInstanceId in otherInstances) {
6519 let otherInstance = otherInstances[otherInstanceId];
6520 // intersect! evaluate
6521 if (rangesIntersect(subjectRange, otherInstance.range)) {
6522 let otherOverlap = otherConfigs[otherInstance.defId].overlap;
6523 // consider the other event's overlap. only do this if the subject event is a "real" event
6524 if (otherOverlap === false && interaction.isEvent) {
6525 return false;
6526 }
6527 if (subjectConfig.overlap === false) {
6528 return false;
6529 }
6530 if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
6531 new EventImpl(context, subjectDef, subjectInstance))) {
6532 return false;
6533 }
6534 }
6535 }
6536 // allow (a function)
6537 let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
6538 for (let subjectAllow of subjectConfig.allows) {
6539 let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
6540 let origDef = calendarEventStore.defs[subjectDef.defId];
6541 let origInstance = calendarEventStore.instances[subjectInstanceId];
6542 let eventApi;
6543 if (origDef) { // was previously in the calendar
6544 eventApi = new EventImpl(context, origDef, origInstance);
6545 }
6546 else { // was an external event
6547 eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
6548 }
6549 if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
6550 return false;
6551 }
6552 }
6553 }
6554 return true;
6555 }
6556 // Date Selection Validation
6557 // ------------------------------------------------------------------------------------------------------------------------
6558 function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
6559 let relevantEventStore = state.eventStore;
6560 let relevantDefs = relevantEventStore.defs;
6561 let relevantInstances = relevantEventStore.instances;
6562 let selection = state.dateSelection;
6563 let selectionRange = selection.range;
6564 let { selectionConfig } = context.getCurrentData();
6565 if (filterConfig) {
6566 selectionConfig = filterConfig(selectionConfig);
6567 }
6568 // constraint
6569 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
6570 return false;
6571 }
6572 // overlap
6573 let { selectOverlap } = context.options;
6574 let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
6575 for (let relevantInstanceId in relevantInstances) {
6576 let relevantInstance = relevantInstances[relevantInstanceId];
6577 // intersect! evaluate
6578 if (rangesIntersect(selectionRange, relevantInstance.range)) {
6579 if (selectionConfig.overlap === false) {
6580 return false;
6581 }
6582 if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
6583 return false;
6584 }
6585 }
6586 }
6587 // allow (a function)
6588 for (let selectionAllow of selectionConfig.allows) {
6589 let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
6590 if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
6591 return false;
6592 }
6593 }
6594 return true;
6595 }
6596 // Constraint Utils
6597 // ------------------------------------------------------------------------------------------------------------------------
6598 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
6599 for (let constraint of constraints) {
6600 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
6601 return false;
6602 }
6603 }
6604 return true;
6605 }
6606 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
6607 otherEventStore, // for if constraint is an even group ID
6608 businessHoursUnexpanded, // for if constraint is 'businessHours'
6609 context) {
6610 if (constraint === 'businessHours') {
6611 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
6612 }
6613 if (typeof constraint === 'string') { // an group ID
6614 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
6615 }
6616 if (typeof constraint === 'object' && constraint) { // non-null object
6617 return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
6618 }
6619 return []; // if it's false
6620 }
6621 // TODO: move to event-store file?
6622 function eventStoreToRanges(eventStore) {
6623 let { instances } = eventStore;
6624 let ranges = [];
6625 for (let instanceId in instances) {
6626 ranges.push(instances[instanceId].range);
6627 }
6628 return ranges;
6629 }
6630 // TODO: move to geom file?
6631 function anyRangesContainRange(outerRanges, innerRange) {
6632 for (let outerRange of outerRanges) {
6633 if (rangeContainsRange(outerRange, innerRange)) {
6634 return true;
6635 }
6636 }
6637 return false;
6638 }
6639
6640 const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
6641 class Scroller extends BaseComponent {
6642 constructor() {
6643 super(...arguments);
6644 this.handleEl = (el) => {
6645 this.el = el;
6646 setRef(this.props.elRef, el);
6647 };
6648 }
6649 render() {
6650 let { props } = this;
6651 let { liquid, liquidIsAbsolute } = props;
6652 let isAbsolute = liquid && liquidIsAbsolute;
6653 let className = ['fc-scroller'];
6654 if (liquid) {
6655 if (liquidIsAbsolute) {
6656 className.push('fc-scroller-liquid-absolute');
6657 }
6658 else {
6659 className.push('fc-scroller-liquid');
6660 }
6661 }
6662 return (y("div", { ref: this.handleEl, className: className.join(' '), style: {
6663 overflowX: props.overflowX,
6664 overflowY: props.overflowY,
6665 left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
6666 right: (isAbsolute && -(props.overcomeRight || 0)) || '',
6667 bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
6668 marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
6669 marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
6670 marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
6671 maxHeight: props.maxHeight || '',
6672 } }, props.children));
6673 }
6674 needsXScrolling() {
6675 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6676 return false;
6677 }
6678 // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
6679 // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6680 // inner-child margins and absolute positioning
6681 let { el } = this;
6682 let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
6683 let { children } = el;
6684 for (let i = 0; i < children.length; i += 1) {
6685 let childEl = children[i];
6686 if (childEl.getBoundingClientRect().width > realClientWidth) {
6687 return true;
6688 }
6689 }
6690 return false;
6691 }
6692 needsYScrolling() {
6693 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6694 return false;
6695 }
6696 // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
6697 // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6698 // inner-child margins and absolute positioning
6699 let { el } = this;
6700 let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
6701 let { children } = el;
6702 for (let i = 0; i < children.length; i += 1) {
6703 let childEl = children[i];
6704 if (childEl.getBoundingClientRect().height > realClientHeight) {
6705 return true;
6706 }
6707 }
6708 return false;
6709 }
6710 getXScrollbarWidth() {
6711 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6712 return 0;
6713 }
6714 return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
6715 }
6716 getYScrollbarWidth() {
6717 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6718 return 0;
6719 }
6720 return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
6721 }
6722 }
6723
6724 /*
6725 TODO: somehow infer OtherArgs from masterCallback?
6726 TODO: infer RefType from masterCallback if provided
6727 */
6728 class RefMap {
6729 constructor(masterCallback) {
6730 this.masterCallback = masterCallback;
6731 this.currentMap = {};
6732 this.depths = {};
6733 this.callbackMap = {};
6734 this.handleValue = (val, key) => {
6735 let { depths, currentMap } = this;
6736 let removed = false;
6737 let added = false;
6738 if (val !== null) {
6739 // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
6740 removed = (key in currentMap);
6741 currentMap[key] = val;
6742 depths[key] = (depths[key] || 0) + 1;
6743 added = true;
6744 }
6745 else {
6746 depths[key] -= 1;
6747 if (!depths[key]) {
6748 delete currentMap[key];
6749 delete this.callbackMap[key];
6750 removed = true;
6751 }
6752 }
6753 if (this.masterCallback) {
6754 if (removed) {
6755 this.masterCallback(null, String(key));
6756 }
6757 if (added) {
6758 this.masterCallback(val, String(key));
6759 }
6760 }
6761 };
6762 }
6763 createRef(key) {
6764 let refCallback = this.callbackMap[key];
6765 if (!refCallback) {
6766 refCallback = this.callbackMap[key] = (val) => {
6767 this.handleValue(val, String(key));
6768 };
6769 }
6770 return refCallback;
6771 }
6772 // TODO: check callers that don't care about order. should use getAll instead
6773 // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
6774 // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
6775 collect(startIndex, endIndex, step) {
6776 return collectFromHash(this.currentMap, startIndex, endIndex, step);
6777 }
6778 getAll() {
6779 return hashValuesToArray(this.currentMap);
6780 }
6781 }
6782
6783 function computeShrinkWidth(chunkEls) {
6784 let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
6785 let largestWidth = 0;
6786 for (let shrinkCell of shrinkCells) {
6787 largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
6788 }
6789 return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
6790 }
6791 function getSectionHasLiquidHeight(props, sectionConfig) {
6792 return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
6793 }
6794 function getAllowYScrolling(props, sectionConfig) {
6795 return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
6796 getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
6797 }
6798 // TODO: ONLY use `arg`. force out internal function to use same API
6799 function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
6800 let { expandRows } = arg;
6801 let content = typeof chunkConfig.content === 'function' ?
6802 chunkConfig.content(arg) :
6803 y('table', {
6804 role: 'presentation',
6805 className: [
6806 chunkConfig.tableClassName,
6807 sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
6808 ].join(' '),
6809 style: {
6810 minWidth: arg.tableMinWidth,
6811 width: arg.clientWidth,
6812 height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
6813 },
6814 }, arg.tableColGroupNode, y(isHeader ? 'thead' : 'tbody', {
6815 role: 'presentation',
6816 }, typeof chunkConfig.rowContent === 'function'
6817 ? chunkConfig.rowContent(arg)
6818 : chunkConfig.rowContent));
6819 return content;
6820 }
6821 function isColPropsEqual(cols0, cols1) {
6822 return isArraysEqual(cols0, cols1, isPropsEqual);
6823 }
6824 function renderMicroColGroup(cols, shrinkWidth) {
6825 let colNodes = [];
6826 /*
6827 for ColProps with spans, it would have been great to make a single <col span="">
6828 HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
6829 SOLUTION: making individual <col> elements makes Chrome behave.
6830 */
6831 for (let colProps of cols) {
6832 let span = colProps.span || 1;
6833 for (let i = 0; i < span; i += 1) {
6834 colNodes.push(y("col", { style: {
6835 width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
6836 minWidth: colProps.minWidth || '',
6837 } }));
6838 }
6839 }
6840 return y('colgroup', {}, ...colNodes);
6841 }
6842 function sanitizeShrinkWidth(shrinkWidth) {
6843 /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
6844 4 accounts for 2 2-pixel borders. TODO: better solution? */
6845 return shrinkWidth == null ? 4 : shrinkWidth;
6846 }
6847 function hasShrinkWidth(cols) {
6848 for (let col of cols) {
6849 if (col.width === 'shrink') {
6850 return true;
6851 }
6852 }
6853 return false;
6854 }
6855 function getScrollGridClassNames(liquid, context) {
6856 let classNames = [
6857 'fc-scrollgrid',
6858 context.theme.getClass('table'),
6859 ];
6860 if (liquid) {
6861 classNames.push('fc-scrollgrid-liquid');
6862 }
6863 return classNames;
6864 }
6865 function getSectionClassNames(sectionConfig, wholeTableVGrow) {
6866 let classNames = [
6867 'fc-scrollgrid-section',
6868 `fc-scrollgrid-section-${sectionConfig.type}`,
6869 sectionConfig.className, // used?
6870 ];
6871 if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
6872 classNames.push('fc-scrollgrid-section-liquid');
6873 }
6874 if (sectionConfig.isSticky) {
6875 classNames.push('fc-scrollgrid-section-sticky');
6876 }
6877 return classNames;
6878 }
6879 function renderScrollShim(arg) {
6880 return (y("div", { className: "fc-scrollgrid-sticky-shim", style: {
6881 width: arg.clientWidth,
6882 minWidth: arg.tableMinWidth,
6883 } }));
6884 }
6885 function getStickyHeaderDates(options) {
6886 let { stickyHeaderDates } = options;
6887 if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
6888 stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
6889 }
6890 return stickyHeaderDates;
6891 }
6892 function getStickyFooterScrollbar(options) {
6893 let { stickyFooterScrollbar } = options;
6894 if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
6895 stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
6896 }
6897 return stickyFooterScrollbar;
6898 }
6899
6900 class SimpleScrollGrid extends BaseComponent {
6901 constructor() {
6902 super(...arguments);
6903 this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
6904 // yucky to memoize VNodes, but much more efficient for consumers
6905 this.renderMicroColGroup = memoize(renderMicroColGroup);
6906 this.scrollerRefs = new RefMap();
6907 this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
6908 this.state = {
6909 shrinkWidth: null,
6910 forceYScrollbars: false,
6911 scrollerClientWidths: {},
6912 scrollerClientHeights: {},
6913 };
6914 // TODO: can do a really simple print-view. dont need to join rows
6915 this.handleSizing = () => {
6916 this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
6917 };
6918 }
6919 render() {
6920 let { props, state, context } = this;
6921 let sectionConfigs = props.sections || [];
6922 let cols = this.processCols(props.cols);
6923 let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
6924 let classNames = getScrollGridClassNames(props.liquid, context);
6925 if (props.collapsibleWidth) {
6926 classNames.push('fc-scrollgrid-collapsible');
6927 }
6928 // TODO: make DRY
6929 let configCnt = sectionConfigs.length;
6930 let configI = 0;
6931 let currentConfig;
6932 let headSectionNodes = [];
6933 let bodySectionNodes = [];
6934 let footSectionNodes = [];
6935 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
6936 headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6937 configI += 1;
6938 }
6939 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
6940 bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
6941 configI += 1;
6942 }
6943 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
6944 footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6945 configI += 1;
6946 }
6947 // firefox bug: when setting height on table and there is a thead or tfoot,
6948 // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
6949 // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
6950 // if so, use a simpler dom structure, jam everything into a lone tbody.
6951 let isBuggy = !getCanVGrowWithinCell();
6952 const roleAttrs = { role: 'rowgroup' };
6953 return y('table', {
6954 role: 'grid',
6955 className: classNames.join(' '),
6956 style: { height: props.height },
6957 }, Boolean(!isBuggy && headSectionNodes.length) && y('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && y('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && y('tfoot', roleAttrs, ...footSectionNodes), isBuggy && y('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
6958 }
6959 renderSection(sectionConfig, microColGroupNode, isHeader) {
6960 if ('outerContent' in sectionConfig) {
6961 return (y(_, { key: sectionConfig.key }, sectionConfig.outerContent));
6962 }
6963 return (y("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
6964 }
6965 renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
6966 if ('outerContent' in chunkConfig) {
6967 return chunkConfig.outerContent;
6968 }
6969 let { props } = this;
6970 let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
6971 let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
6972 let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
6973 // for `!props.liquid` - is WHOLE scrollgrid natural height?
6974 // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
6975 let overflowY = !props.liquid ? 'visible' :
6976 forceYScrollbars ? 'scroll' :
6977 !needsYScrolling ? 'hidden' :
6978 'auto';
6979 let sectionKey = sectionConfig.key;
6980 let content = renderChunkContent(sectionConfig, chunkConfig, {
6981 tableColGroupNode: microColGroupNode,
6982 tableMinWidth: '',
6983 clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
6984 clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
6985 expandRows: sectionConfig.expandRows,
6986 syncRowHeights: false,
6987 rowSyncHeights: [],
6988 reportRowHeightChange: () => { },
6989 }, isHeader);
6990 return y(isHeader ? 'th' : 'td', {
6991 ref: chunkConfig.elRef,
6992 role: 'presentation',
6993 }, y("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
6994 y(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness
6995 : true }, content)));
6996 }
6997 _handleScrollerEl(scrollerEl, key) {
6998 let section = getSectionByKey(this.props.sections, key);
6999 if (section) {
7000 setRef(section.chunk.scrollerElRef, scrollerEl);
7001 }
7002 }
7003 componentDidMount() {
7004 this.handleSizing();
7005 this.context.addResizeHandler(this.handleSizing);
7006 }
7007 componentDidUpdate() {
7008 // TODO: need better solution when state contains non-sizing things
7009 this.handleSizing();
7010 }
7011 componentWillUnmount() {
7012 this.context.removeResizeHandler(this.handleSizing);
7013 }
7014 computeShrinkWidth() {
7015 return hasShrinkWidth(this.props.cols)
7016 ? computeShrinkWidth(this.scrollerElRefs.getAll())
7017 : 0;
7018 }
7019 computeScrollerDims() {
7020 let scrollbarWidth = getScrollbarWidths();
7021 let { scrollerRefs, scrollerElRefs } = this;
7022 let forceYScrollbars = false;
7023 let scrollerClientWidths = {};
7024 let scrollerClientHeights = {};
7025 for (let sectionKey in scrollerRefs.currentMap) {
7026 let scroller = scrollerRefs.currentMap[sectionKey];
7027 if (scroller && scroller.needsYScrolling()) {
7028 forceYScrollbars = true;
7029 break;
7030 }
7031 }
7032 for (let section of this.props.sections) {
7033 let sectionKey = section.key;
7034 let scrollerEl = scrollerElRefs.currentMap[sectionKey];
7035 if (scrollerEl) {
7036 let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
7037 scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
7038 ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
7039 : 0));
7040 scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
7041 }
7042 }
7043 return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
7044 }
7045 }
7046 SimpleScrollGrid.addStateEquality({
7047 scrollerClientWidths: isPropsEqual,
7048 scrollerClientHeights: isPropsEqual,
7049 });
7050 function getSectionByKey(sections, key) {
7051 for (let section of sections) {
7052 if (section.key === key) {
7053 return section;
7054 }
7055 }
7056 return null;
7057 }
7058
7059 class EventContainer extends BaseComponent {
7060 constructor() {
7061 super(...arguments);
7062 this.handleEl = (el) => {
7063 this.el = el;
7064 if (el) {
7065 setElSeg(el, this.props.seg);
7066 }
7067 };
7068 }
7069 render() {
7070 const { props, context } = this;
7071 const { options } = context;
7072 const { seg } = props;
7073 const { eventRange } = seg;
7074 const { ui } = eventRange;
7075 const renderProps = {
7076 event: new EventImpl(context, eventRange.def, eventRange.instance),
7077 view: context.viewApi,
7078 timeText: props.timeText,
7079 textColor: ui.textColor,
7080 backgroundColor: ui.backgroundColor,
7081 borderColor: ui.borderColor,
7082 isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
7083 isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
7084 isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
7085 isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
7086 isStart: Boolean(seg.isStart),
7087 isEnd: Boolean(seg.isEnd),
7088 isPast: Boolean(props.isPast),
7089 isFuture: Boolean(props.isFuture),
7090 isToday: Boolean(props.isToday),
7091 isSelected: Boolean(props.isSelected),
7092 isDragging: Boolean(props.isDragging),
7093 isResizing: Boolean(props.isResizing),
7094 };
7095 return (y(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
7096 ...getEventClassNames(renderProps),
7097 ...seg.eventRange.ui.classNames,
7098 ...(props.elClasses || []),
7099 ], renderProps: renderProps, generatorName: "eventContent", customGenerator: options.eventContent, defaultGenerator: props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
7100 }
7101 componentDidUpdate(prevProps) {
7102 if (this.el && this.props.seg !== prevProps.seg) {
7103 setElSeg(this.el, this.props.seg);
7104 }
7105 }
7106 }
7107
7108 // should not be a purecomponent
7109 class StandardEvent extends BaseComponent {
7110 render() {
7111 let { props, context } = this;
7112 let { options } = context;
7113 let { seg } = props;
7114 let { ui } = seg.eventRange;
7115 let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
7116 let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
7117 return (y(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
7118 borderColor: ui.borderColor,
7119 backgroundColor: ui.backgroundColor,
7120 }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1$1, timeText: timeText }), (InnerContent, eventContentArg) => (y(_, null,
7121 y(InnerContent, { elTag: "div", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),
7122 Boolean(eventContentArg.isStartResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-start" })),
7123 Boolean(eventContentArg.isEndResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
7124 }
7125 }
7126 function renderInnerContent$1$1(innerProps) {
7127 return (y("div", { className: "fc-event-main-frame" },
7128 innerProps.timeText && (y("div", { className: "fc-event-time" }, innerProps.timeText)),
7129 y("div", { className: "fc-event-title-container" },
7130 y("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || y(_, null, "\u00A0")))));
7131 }
7132
7133 const NowIndicatorContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
7134 let { options } = context;
7135 let renderProps = {
7136 isAxis: props.isAxis,
7137 date: context.dateEnv.toDate(props.date),
7138 view: context.viewApi,
7139 };
7140 return (y(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", customGenerator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
7141 }));
7142
7143 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
7144 class DayCellContainer extends BaseComponent {
7145 constructor() {
7146 super(...arguments);
7147 this.refineRenderProps = memoizeObjArg(refineRenderProps);
7148 }
7149 render() {
7150 let { props, context } = this;
7151 let { options } = context;
7152 let renderProps = this.refineRenderProps({
7153 date: props.date,
7154 dateProfile: props.dateProfile,
7155 todayRange: props.todayRange,
7156 isMonthStart: props.isMonthStart || false,
7157 showDayNumber: props.showDayNumber,
7158 extraRenderProps: props.extraRenderProps,
7159 viewApi: context.viewApi,
7160 dateEnv: context.dateEnv,
7161 monthStartFormat: options.monthStartFormat,
7162 });
7163 return (y(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
7164 ...getDayClassNames(renderProps, context.theme),
7165 ...(props.elClasses || []),
7166 ], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator:
7167 // don't use custom classNames if disabled
7168 renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
7169 }
7170 }
7171 function hasCustomDayCellContent(options) {
7172 return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
7173 }
7174 function refineRenderProps(raw) {
7175 let { date, dateEnv, dateProfile, isMonthStart } = raw;
7176 let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
7177 let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
7178 return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,
7179 dayNumberText }), raw.extraRenderProps);
7180 }
7181
7182 class BgEvent extends BaseComponent {
7183 render() {
7184 let { props } = this;
7185 let { seg } = props;
7186 return (y(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: seg.eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent$3, seg: seg, timeText: "", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));
7187 }
7188 }
7189 function renderInnerContent$3(props) {
7190 let { title } = props.event;
7191 return title && (y("div", { className: "fc-event-title" }, props.event.title));
7192 }
7193 function renderFill(fillType) {
7194 return (y("div", { className: `fc-${fillType}` }));
7195 }
7196
7197 const WeekNumberContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
7198 let { dateEnv, options } = context;
7199 let { date } = props;
7200 let format = options.weekNumberFormat || props.defaultFormat;
7201 let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
7202 let text = dateEnv.format(date, format);
7203 let renderProps = { num, text, date };
7204 return (y(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
7205 , Object.assign({}, props /* includes children */, { renderProps: renderProps, generatorName: "weekNumberContent", customGenerator: options.weekNumberContent, defaultGenerator: renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount })));
7206 }));
7207 function renderInner(innerProps) {
7208 return innerProps.text;
7209 }
7210
7211 const PADDING_FROM_VIEWPORT = 10;
7212 class Popover extends BaseComponent {
7213 constructor() {
7214 super(...arguments);
7215 this.state = {
7216 titleId: getUniqueDomId(),
7217 };
7218 this.handleRootEl = (el) => {
7219 this.rootEl = el;
7220 if (this.props.elRef) {
7221 setRef(this.props.elRef, el);
7222 }
7223 };
7224 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
7225 this.handleDocumentMouseDown = (ev) => {
7226 // only hide the popover if the click happened outside the popover
7227 const target = getEventTargetViaRoot(ev);
7228 if (!this.rootEl.contains(target)) {
7229 this.handleCloseClick();
7230 }
7231 };
7232 this.handleDocumentKeyDown = (ev) => {
7233 if (ev.key === 'Escape') {
7234 this.handleCloseClick();
7235 }
7236 };
7237 this.handleCloseClick = () => {
7238 let { onClose } = this.props;
7239 if (onClose) {
7240 onClose();
7241 }
7242 };
7243 }
7244 render() {
7245 let { theme, options } = this.context;
7246 let { props, state } = this;
7247 let classNames = [
7248 'fc-popover',
7249 theme.getClass('popover'),
7250 ].concat(props.extraClassNames || []);
7251 return j(y("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
7252 y("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
7253 y("span", { className: "fc-popover-title", id: state.titleId }, props.title),
7254 y("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
7255 y("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
7256 }
7257 componentDidMount() {
7258 document.addEventListener('mousedown', this.handleDocumentMouseDown);
7259 document.addEventListener('keydown', this.handleDocumentKeyDown);
7260 this.updateSize();
7261 }
7262 componentWillUnmount() {
7263 document.removeEventListener('mousedown', this.handleDocumentMouseDown);
7264 document.removeEventListener('keydown', this.handleDocumentKeyDown);
7265 }
7266 updateSize() {
7267 let { isRtl } = this.context;
7268 let { alignmentEl, alignGridTop } = this.props;
7269 let { rootEl } = this;
7270 let alignmentRect = computeClippedClientRect(alignmentEl);
7271 if (alignmentRect) {
7272 let popoverDims = rootEl.getBoundingClientRect();
7273 // position relative to viewport
7274 let popoverTop = alignGridTop
7275 ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top
7276 : alignmentRect.top;
7277 let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
7278 // constrain
7279 popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
7280 popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
7281 popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
7282 let origin = rootEl.offsetParent.getBoundingClientRect();
7283 applyStyle(rootEl, {
7284 top: popoverTop - origin.top,
7285 left: popoverLeft - origin.left,
7286 });
7287 }
7288 }
7289 }
7290
7291 class MorePopover extends DateComponent {
7292 constructor() {
7293 super(...arguments);
7294 this.handleRootEl = (rootEl) => {
7295 this.rootEl = rootEl;
7296 if (rootEl) {
7297 this.context.registerInteractiveComponent(this, {
7298 el: rootEl,
7299 useEventCenter: false,
7300 });
7301 }
7302 else {
7303 this.context.unregisterInteractiveComponent(this);
7304 }
7305 };
7306 }
7307 render() {
7308 let { options, dateEnv } = this.context;
7309 let { props } = this;
7310 let { startDate, todayRange, dateProfile } = props;
7311 let title = dateEnv.format(startDate, options.dayPopoverFormat);
7312 return (y(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (y(Popover, { elRef: elAttrs.ref, id: props.id, title: title, extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []), extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */, parentEl: props.parentEl, alignmentEl: props.alignmentEl, alignGridTop: props.alignGridTop, onClose: props.onClose },
7313 hasCustomDayCellContent(options) && (y(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
7314 props.children))));
7315 }
7316 queryHit(positionLeft, positionTop, elWidth, elHeight) {
7317 let { rootEl, props } = this;
7318 if (positionLeft >= 0 && positionLeft < elWidth &&
7319 positionTop >= 0 && positionTop < elHeight) {
7320 return {
7321 dateProfile: props.dateProfile,
7322 dateSpan: Object.assign({ allDay: !props.forceTimed, range: {
7323 start: props.startDate,
7324 end: props.endDate,
7325 } }, props.extraDateSpan),
7326 dayEl: rootEl,
7327 rect: {
7328 left: 0,
7329 top: 0,
7330 right: elWidth,
7331 bottom: elHeight,
7332 },
7333 layer: 1, // important when comparing with hits from other components
7334 };
7335 }
7336 return null;
7337 }
7338 }
7339
7340 class MoreLinkContainer extends BaseComponent {
7341 constructor() {
7342 super(...arguments);
7343 this.state = {
7344 isPopoverOpen: false,
7345 popoverId: getUniqueDomId(),
7346 };
7347 this.handleLinkEl = (linkEl) => {
7348 this.linkEl = linkEl;
7349 if (this.props.elRef) {
7350 setRef(this.props.elRef, linkEl);
7351 }
7352 };
7353 this.handleClick = (ev) => {
7354 let { props, context } = this;
7355 let { moreLinkClick } = context.options;
7356 let date = computeRange(props).start;
7357 function buildPublicSeg(seg) {
7358 let { def, instance, range } = seg.eventRange;
7359 return {
7360 event: new EventImpl(context, def, instance),
7361 start: context.dateEnv.toDate(range.start),
7362 end: context.dateEnv.toDate(range.end),
7363 isStart: seg.isStart,
7364 isEnd: seg.isEnd,
7365 };
7366 }
7367 if (typeof moreLinkClick === 'function') {
7368 moreLinkClick = moreLinkClick({
7369 date,
7370 allDay: Boolean(props.allDayDate),
7371 allSegs: props.allSegs.map(buildPublicSeg),
7372 hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
7373 jsEvent: ev,
7374 view: context.viewApi,
7375 });
7376 }
7377 if (!moreLinkClick || moreLinkClick === 'popover') {
7378 this.setState({ isPopoverOpen: true });
7379 }
7380 else if (typeof moreLinkClick === 'string') { // a view name
7381 context.calendarApi.zoomTo(date, moreLinkClick);
7382 }
7383 };
7384 this.handlePopoverClose = () => {
7385 this.setState({ isPopoverOpen: false });
7386 };
7387 }
7388 render() {
7389 let { props, state } = this;
7390 return (y(ViewContextType.Consumer, null, (context) => {
7391 let { viewApi, options, calendarApi } = context;
7392 let { moreLinkText } = options;
7393 let { moreCnt } = props;
7394 let range = computeRange(props);
7395 let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
7396 ? moreLinkText.call(calendarApi, moreCnt)
7397 : `+${moreCnt} ${moreLinkText}`;
7398 let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
7399 let renderProps = {
7400 num: moreCnt,
7401 shortText: `+${moreCnt}`,
7402 text,
7403 view: viewApi,
7404 };
7405 return (y(_, null,
7406 Boolean(props.moreCnt) && (y(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
7407 ...(props.elClasses || []),
7408 'fc-more-link',
7409 ], elStyle: props.elStyle, elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: "moreLinkContent", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner$1, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
7410 state.isPopoverOpen && (y(MorePopover, { id: state.popoverId, startDate: range.start, endDate: range.end, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: props.extraDateSpan, parentEl: this.parentEl, alignmentEl: props.alignmentElRef ?
7411 props.alignmentElRef.current :
7412 this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));
7413 }));
7414 }
7415 componentDidMount() {
7416 this.updateParentEl();
7417 }
7418 componentDidUpdate() {
7419 this.updateParentEl();
7420 }
7421 updateParentEl() {
7422 if (this.linkEl) {
7423 this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');
7424 }
7425 }
7426 }
7427 function renderMoreLinkInner$1(props) {
7428 return props.text;
7429 }
7430 function computeRange(props) {
7431 if (props.allDayDate) {
7432 return {
7433 start: props.allDayDate,
7434 end: addDays(props.allDayDate, 1),
7435 };
7436 }
7437 let { hiddenSegs } = props;
7438 return {
7439 start: computeEarliestSegStart(hiddenSegs),
7440 end: computeLatestSegEnd(hiddenSegs),
7441 };
7442 }
7443 function computeEarliestSegStart(segs) {
7444 return segs.reduce(pickEarliestStart).eventRange.range.start;
7445 }
7446 function pickEarliestStart(seg0, seg1) {
7447 return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
7448 }
7449 function computeLatestSegEnd(segs) {
7450 return segs.reduce(pickLatestEnd).eventRange.range.end;
7451 }
7452 function pickLatestEnd(seg0, seg1) {
7453 return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
7454 }
7455
7456 class Store {
7457 constructor() {
7458 this.handlers = [];
7459 }
7460 set(value) {
7461 this.currentValue = value;
7462 for (let handler of this.handlers) {
7463 handler(value);
7464 }
7465 }
7466 subscribe(handler) {
7467 this.handlers.push(handler);
7468 if (this.currentValue !== undefined) {
7469 handler(this.currentValue);
7470 }
7471 }
7472 }
7473
7474 /*
7475 Subscribers will get a LIST of CustomRenderings
7476 */
7477 class CustomRenderingStore extends Store {
7478 constructor() {
7479 super(...arguments);
7480 this.map = new Map();
7481 }
7482 // for consistent order
7483 handle(customRendering) {
7484 const { map } = this;
7485 let updated = false;
7486 if (customRendering.isActive) {
7487 map.set(customRendering.id, customRendering);
7488 updated = true;
7489 }
7490 else if (map.has(customRendering.id)) {
7491 map.delete(customRendering.id);
7492 updated = true;
7493 }
7494 if (updated) {
7495 this.set(map);
7496 }
7497 }
7498 }
7499
7500 var internal = {
7501 __proto__: null,
7502 BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
7503 BaseComponent: BaseComponent,
7504 BgEvent: BgEvent,
7505 CalendarImpl: CalendarImpl,
7506 CalendarRoot: CalendarRoot,
7507 ContentContainer: ContentContainer,
7508 CustomRenderingStore: CustomRenderingStore,
7509 DateComponent: DateComponent,
7510 DateEnv: DateEnv,
7511 DateProfileGenerator: DateProfileGenerator,
7512 DayCellContainer: DayCellContainer,
7513 DayHeader: DayHeader,
7514 DaySeriesModel: DaySeriesModel,
7515 DayTableModel: DayTableModel,
7516 DelayedRunner: DelayedRunner,
7517 ElementDragging: ElementDragging,
7518 ElementScrollController: ElementScrollController,
7519 Emitter: Emitter,
7520 EventContainer: EventContainer,
7521 EventImpl: EventImpl,
7522 Interaction: Interaction,
7523 MoreLinkContainer: MoreLinkContainer,
7524 NamedTimeZoneImpl: NamedTimeZoneImpl,
7525 NowIndicatorContainer: NowIndicatorContainer,
7526 NowTimer: NowTimer,
7527 PositionCache: PositionCache,
7528 RefMap: RefMap,
7529 ScrollController: ScrollController,
7530 ScrollResponder: ScrollResponder,
7531 Scroller: Scroller,
7532 SegHierarchy: SegHierarchy,
7533 SimpleScrollGrid: SimpleScrollGrid,
7534 Slicer: Slicer,
7535 Splitter: Splitter,
7536 StandardEvent: StandardEvent,
7537 TableDateCell: TableDateCell,
7538 TableDowCell: TableDowCell,
7539 Theme: Theme,
7540 ViewContainer: ViewContainer,
7541 ViewContextType: ViewContextType,
7542 WeekNumberContainer: WeekNumberContainer,
7543 WindowScrollController: WindowScrollController,
7544 addDays: addDays,
7545 addDurations: addDurations,
7546 addMs: addMs,
7547 addWeeks: addWeeks,
7548 allowContextMenu: allowContextMenu,
7549 allowSelection: allowSelection,
7550 applyMutationToEventStore: applyMutationToEventStore,
7551 applyStyle: applyStyle,
7552 asCleanDays: asCleanDays,
7553 asRoughMinutes: asRoughMinutes,
7554 asRoughMs: asRoughMs,
7555 asRoughSeconds: asRoughSeconds,
7556 binarySearch: binarySearch,
7557 buildElAttrs: buildElAttrs,
7558 buildEntryKey: buildEntryKey,
7559 buildEventApis: buildEventApis,
7560 buildEventRangeKey: buildEventRangeKey,
7561 buildIsoString: buildIsoString,
7562 buildNavLinkAttrs: buildNavLinkAttrs,
7563 buildSegTimeText: buildSegTimeText,
7564 collectFromHash: collectFromHash,
7565 combineEventUis: combineEventUis,
7566 compareByFieldSpecs: compareByFieldSpecs,
7567 compareNumbers: compareNumbers,
7568 compareObjs: compareObjs,
7569 computeEarliestSegStart: computeEarliestSegStart,
7570 computeEdges: computeEdges,
7571 computeFallbackHeaderFormat: computeFallbackHeaderFormat,
7572 computeInnerRect: computeInnerRect,
7573 computeRect: computeRect,
7574 computeShrinkWidth: computeShrinkWidth,
7575 computeVisibleDayRange: computeVisibleDayRange,
7576 config: config,
7577 constrainPoint: constrainPoint,
7578 createDuration: createDuration,
7579 createEmptyEventStore: createEmptyEventStore,
7580 createEventInstance: createEventInstance,
7581 createEventUi: createEventUi,
7582 createFormatter: createFormatter,
7583 diffDates: diffDates,
7584 diffDayAndTime: diffDayAndTime,
7585 diffDays: diffDays,
7586 diffPoints: diffPoints,
7587 diffWeeks: diffWeeks,
7588 diffWholeDays: diffWholeDays,
7589 diffWholeWeeks: diffWholeWeeks,
7590 disableCursor: disableCursor,
7591 elementClosest: elementClosest,
7592 elementMatches: elementMatches,
7593 enableCursor: enableCursor,
7594 eventTupleToStore: eventTupleToStore,
7595 filterHash: filterHash,
7596 findDirectChildren: findDirectChildren,
7597 findElements: findElements,
7598 flexibleCompare: flexibleCompare,
7599 formatDayString: formatDayString,
7600 formatIsoMonthStr: formatIsoMonthStr,
7601 formatIsoTimeString: formatIsoTimeString,
7602 getAllowYScrolling: getAllowYScrolling,
7603 getCanVGrowWithinCell: getCanVGrowWithinCell,
7604 getClippingParents: getClippingParents,
7605 getDateMeta: getDateMeta,
7606 getDayClassNames: getDayClassNames,
7607 getDefaultEventEnd: getDefaultEventEnd,
7608 getElSeg: getElSeg,
7609 getEntrySpanEnd: getEntrySpanEnd,
7610 getEventTargetViaRoot: getEventTargetViaRoot,
7611 getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
7612 getRectCenter: getRectCenter,
7613 getRelevantEvents: getRelevantEvents,
7614 getScrollGridClassNames: getScrollGridClassNames,
7615 getScrollbarWidths: getScrollbarWidths,
7616 getSectionClassNames: getSectionClassNames,
7617 getSectionHasLiquidHeight: getSectionHasLiquidHeight,
7618 getSegAnchorAttrs: getSegAnchorAttrs,
7619 getSegMeta: getSegMeta,
7620 getSlotClassNames: getSlotClassNames,
7621 getStickyFooterScrollbar: getStickyFooterScrollbar,
7622 getStickyHeaderDates: getStickyHeaderDates,
7623 getUniqueDomId: getUniqueDomId,
7624 greatestDurationDenominator: greatestDurationDenominator,
7625 groupIntersectingEntries: groupIntersectingEntries,
7626 guid: guid,
7627 hasBgRendering: hasBgRendering,
7628 hasCustomDayCellContent: hasCustomDayCellContent,
7629 hasShrinkWidth: hasShrinkWidth,
7630 identity: identity,
7631 injectStyles: injectStyles,
7632 interactionSettingsStore: interactionSettingsStore,
7633 interactionSettingsToStore: interactionSettingsToStore,
7634 intersectRanges: intersectRanges,
7635 intersectRects: intersectRects,
7636 intersectSpans: intersectSpans,
7637 isArraysEqual: isArraysEqual,
7638 isColPropsEqual: isColPropsEqual,
7639 isDateSelectionValid: isDateSelectionValid,
7640 isDateSpansEqual: isDateSpansEqual,
7641 isInt: isInt,
7642 isInteractionValid: isInteractionValid,
7643 isMultiDayRange: isMultiDayRange,
7644 isPropsEqual: isPropsEqual,
7645 isPropsValid: isPropsValid,
7646 isValidDate: isValidDate,
7647 mapHash: mapHash,
7648 memoize: memoize,
7649 memoizeArraylike: memoizeArraylike,
7650 memoizeHashlike: memoizeHashlike,
7651 memoizeObjArg: memoizeObjArg,
7652 mergeEventStores: mergeEventStores,
7653 multiplyDuration: multiplyDuration,
7654 padStart: padStart,
7655 parseBusinessHours: parseBusinessHours,
7656 parseClassNames: parseClassNames,
7657 parseDragMeta: parseDragMeta,
7658 parseEventDef: parseEventDef,
7659 parseFieldSpecs: parseFieldSpecs,
7660 parseMarker: parse,
7661 pointInsideRect: pointInsideRect,
7662 preventContextMenu: preventContextMenu,
7663 preventDefault: preventDefault,
7664 preventSelection: preventSelection,
7665 rangeContainsMarker: rangeContainsMarker,
7666 rangeContainsRange: rangeContainsRange,
7667 rangesEqual: rangesEqual,
7668 rangesIntersect: rangesIntersect,
7669 refineEventDef: refineEventDef,
7670 refineProps: refineProps,
7671 removeElement: removeElement,
7672 removeExact: removeExact,
7673 renderChunkContent: renderChunkContent,
7674 renderFill: renderFill,
7675 renderMicroColGroup: renderMicroColGroup,
7676 renderScrollShim: renderScrollShim,
7677 requestJson: requestJson,
7678 sanitizeShrinkWidth: sanitizeShrinkWidth,
7679 setRef: setRef,
7680 sliceEventStore: sliceEventStore,
7681 sortEventSegs: sortEventSegs,
7682 startOfDay: startOfDay,
7683 translateRect: translateRect,
7684 triggerDateSelect: triggerDateSelect,
7685 unpromisify: unpromisify,
7686 whenTransitionDone: whenTransitionDone,
7687 wholeDivideDurations: wholeDivideDurations
7688 };
7689
7690 var preact = {
7691 __proto__: null,
7692 createPortal: j,
7693 createContext: createContext,
7694 flushSync: flushSync,
7695 Component: x$1,
7696 Fragment: _,
7697 cloneElement: F$1,
7698 createElement: y,
7699 createRef: d,
7700 h: y,
7701 hydrate: E,
7702 get isValidElement () { return i$1; },
7703 get options () { return l$1; },
7704 render: D$1,
7705 toChildArray: j$2
7706 };
7707
7708 const globalLocales = [];
7709
7710 const MINIMAL_RAW_EN_LOCALE = {
7711 code: 'en',
7712 week: {
7713 dow: 0,
7714 doy: 4, // 4 days need to be within the year to be considered the first week
7715 },
7716 direction: 'ltr',
7717 buttonText: {
7718 prev: 'prev',
7719 next: 'next',
7720 prevYear: 'prev year',
7721 nextYear: 'next year',
7722 year: 'year',
7723 today: 'today',
7724 month: 'month',
7725 week: 'week',
7726 day: 'day',
7727 list: 'list',
7728 },
7729 weekText: 'W',
7730 weekTextLong: 'Week',
7731 closeHint: 'Close',
7732 timeHint: 'Time',
7733 eventHint: 'Event',
7734 allDayText: 'all-day',
7735 moreLinkText: 'more',
7736 noEventsText: 'No events to display',
7737 };
7738 const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
7739 // Includes things we don't want other locales to inherit,
7740 // things that derive from other translatable strings.
7741 buttonHints: {
7742 prev: 'Previous $0',
7743 next: 'Next $0',
7744 today(buttonText, unit) {
7745 return (unit === 'day')
7746 ? 'Today'
7747 : `This ${buttonText}`;
7748 },
7749 }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
7750 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
7751 } });
7752 function organizeRawLocales(explicitRawLocales) {
7753 let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
7754 let allRawLocales = globalLocales.concat(explicitRawLocales);
7755 let rawLocaleMap = {
7756 en: RAW_EN_LOCALE,
7757 };
7758 for (let rawLocale of allRawLocales) {
7759 rawLocaleMap[rawLocale.code] = rawLocale;
7760 }
7761 return {
7762 map: rawLocaleMap,
7763 defaultCode,
7764 };
7765 }
7766 function buildLocale(inputSingular, available) {
7767 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
7768 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
7769 }
7770 return queryLocale(inputSingular, available);
7771 }
7772 function queryLocale(codeArg, available) {
7773 let codes = [].concat(codeArg || []); // will convert to array
7774 let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
7775 return parseLocale(codeArg, codes, raw);
7776 }
7777 function queryRawLocale(codes, available) {
7778 for (let i = 0; i < codes.length; i += 1) {
7779 let parts = codes[i].toLocaleLowerCase().split('-');
7780 for (let j = parts.length; j > 0; j -= 1) {
7781 let simpleId = parts.slice(0, j).join('-');
7782 if (available[simpleId]) {
7783 return available[simpleId];
7784 }
7785 }
7786 }
7787 return null;
7788 }
7789 function parseLocale(codeArg, codes, raw) {
7790 let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
7791 delete merged.code; // don't want this part of the options
7792 let { week } = merged;
7793 delete merged.week;
7794 return {
7795 codeArg,
7796 codes,
7797 week,
7798 simpleNumberFormat: new Intl.NumberFormat(codeArg),
7799 options: merged,
7800 };
7801 }
7802
7803 // TODO: easier way to add new hooks? need to update a million things
7804 function createPlugin(input) {
7805 return {
7806 id: guid(),
7807 name: input.name,
7808 premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
7809 deps: input.deps || [],
7810 reducers: input.reducers || [],
7811 isLoadingFuncs: input.isLoadingFuncs || [],
7812 contextInit: [].concat(input.contextInit || []),
7813 eventRefiners: input.eventRefiners || {},
7814 eventDefMemberAdders: input.eventDefMemberAdders || [],
7815 eventSourceRefiners: input.eventSourceRefiners || {},
7816 isDraggableTransformers: input.isDraggableTransformers || [],
7817 eventDragMutationMassagers: input.eventDragMutationMassagers || [],
7818 eventDefMutationAppliers: input.eventDefMutationAppliers || [],
7819 dateSelectionTransformers: input.dateSelectionTransformers || [],
7820 datePointTransforms: input.datePointTransforms || [],
7821 dateSpanTransforms: input.dateSpanTransforms || [],
7822 views: input.views || {},
7823 viewPropsTransformers: input.viewPropsTransformers || [],
7824 isPropsValid: input.isPropsValid || null,
7825 externalDefTransforms: input.externalDefTransforms || [],
7826 viewContainerAppends: input.viewContainerAppends || [],
7827 eventDropTransformers: input.eventDropTransformers || [],
7828 componentInteractions: input.componentInteractions || [],
7829 calendarInteractions: input.calendarInteractions || [],
7830 themeClasses: input.themeClasses || {},
7831 eventSourceDefs: input.eventSourceDefs || [],
7832 cmdFormatter: input.cmdFormatter,
7833 recurringTypes: input.recurringTypes || [],
7834 namedTimeZonedImpl: input.namedTimeZonedImpl,
7835 initialView: input.initialView || '',
7836 elementDraggingImpl: input.elementDraggingImpl,
7837 optionChangeHandlers: input.optionChangeHandlers || {},
7838 scrollGridImpl: input.scrollGridImpl || null,
7839 listenerRefiners: input.listenerRefiners || {},
7840 optionRefiners: input.optionRefiners || {},
7841 propSetHandlers: input.propSetHandlers || {},
7842 };
7843 }
7844 function buildPluginHooks(pluginDefs, globalDefs) {
7845 let currentPluginIds = {};
7846 let hooks = {
7847 premiumReleaseDate: undefined,
7848 reducers: [],
7849 isLoadingFuncs: [],
7850 contextInit: [],
7851 eventRefiners: {},
7852 eventDefMemberAdders: [],
7853 eventSourceRefiners: {},
7854 isDraggableTransformers: [],
7855 eventDragMutationMassagers: [],
7856 eventDefMutationAppliers: [],
7857 dateSelectionTransformers: [],
7858 datePointTransforms: [],
7859 dateSpanTransforms: [],
7860 views: {},
7861 viewPropsTransformers: [],
7862 isPropsValid: null,
7863 externalDefTransforms: [],
7864 viewContainerAppends: [],
7865 eventDropTransformers: [],
7866 componentInteractions: [],
7867 calendarInteractions: [],
7868 themeClasses: {},
7869 eventSourceDefs: [],
7870 cmdFormatter: null,
7871 recurringTypes: [],
7872 namedTimeZonedImpl: null,
7873 initialView: '',
7874 elementDraggingImpl: null,
7875 optionChangeHandlers: {},
7876 scrollGridImpl: null,
7877 listenerRefiners: {},
7878 optionRefiners: {},
7879 propSetHandlers: {},
7880 };
7881 function addDefs(defs) {
7882 for (let def of defs) {
7883 const pluginName = def.name;
7884 const currentId = currentPluginIds[pluginName];
7885 if (currentId === undefined) {
7886 currentPluginIds[pluginName] = def.id;
7887 addDefs(def.deps);
7888 hooks = combineHooks(hooks, def);
7889 }
7890 else if (currentId !== def.id) {
7891 // different ID than the one already added
7892 console.warn(`Duplicate plugin '${pluginName}'`);
7893 }
7894 }
7895 }
7896 if (pluginDefs) {
7897 addDefs(pluginDefs);
7898 }
7899 addDefs(globalDefs);
7900 return hooks;
7901 }
7902 function buildBuildPluginHooks() {
7903 let currentOverrideDefs = [];
7904 let currentGlobalDefs = [];
7905 let currentHooks;
7906 return (overrideDefs, globalDefs) => {
7907 if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
7908 currentHooks = buildPluginHooks(overrideDefs, globalDefs);
7909 }
7910 currentOverrideDefs = overrideDefs;
7911 currentGlobalDefs = globalDefs;
7912 return currentHooks;
7913 };
7914 }
7915 function combineHooks(hooks0, hooks1) {
7916 return {
7917 premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
7918 reducers: hooks0.reducers.concat(hooks1.reducers),
7919 isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
7920 contextInit: hooks0.contextInit.concat(hooks1.contextInit),
7921 eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
7922 eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
7923 eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
7924 isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
7925 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
7926 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
7927 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
7928 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
7929 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
7930 views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
7931 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
7932 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
7933 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
7934 viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
7935 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
7936 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
7937 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
7938 themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
7939 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
7940 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
7941 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
7942 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
7943 initialView: hooks0.initialView || hooks1.initialView,
7944 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
7945 optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
7946 scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
7947 listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
7948 optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
7949 propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
7950 };
7951 }
7952 function compareOptionalDates(date0, date1) {
7953 if (date0 === undefined) {
7954 return date1;
7955 }
7956 if (date1 === undefined) {
7957 return date0;
7958 }
7959 return new Date(Math.max(date0.valueOf(), date1.valueOf()));
7960 }
7961
7962 class StandardTheme extends Theme {
7963 }
7964 StandardTheme.prototype.classes = {
7965 root: 'fc-theme-standard',
7966 tableCellShaded: 'fc-cell-shaded',
7967 buttonGroup: 'fc-button-group',
7968 button: 'fc-button fc-button-primary',
7969 buttonActive: 'fc-button-active',
7970 };
7971 StandardTheme.prototype.baseIconClass = 'fc-icon';
7972 StandardTheme.prototype.iconClasses = {
7973 close: 'fc-icon-x',
7974 prev: 'fc-icon-chevron-left',
7975 next: 'fc-icon-chevron-right',
7976 prevYear: 'fc-icon-chevrons-left',
7977 nextYear: 'fc-icon-chevrons-right',
7978 };
7979 StandardTheme.prototype.rtlIconClasses = {
7980 prev: 'fc-icon-chevron-right',
7981 next: 'fc-icon-chevron-left',
7982 prevYear: 'fc-icon-chevrons-right',
7983 nextYear: 'fc-icon-chevrons-left',
7984 };
7985 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
7986 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
7987 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
7988
7989 function compileViewDefs(defaultConfigs, overrideConfigs) {
7990 let hash = {};
7991 let viewType;
7992 for (viewType in defaultConfigs) {
7993 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7994 }
7995 for (viewType in overrideConfigs) {
7996 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7997 }
7998 return hash;
7999 }
8000 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8001 if (hash[viewType]) {
8002 return hash[viewType];
8003 }
8004 let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8005 if (viewDef) {
8006 hash[viewType] = viewDef;
8007 }
8008 return viewDef;
8009 }
8010 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8011 let defaultConfig = defaultConfigs[viewType];
8012 let overrideConfig = overrideConfigs[viewType];
8013 let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
8014 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
8015 let theComponent = queryProp('component');
8016 let superType = queryProp('superType');
8017 let superDef = null;
8018 if (superType) {
8019 if (superType === viewType) {
8020 throw new Error('Can\'t have a custom view type that references itself');
8021 }
8022 superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
8023 }
8024 if (!theComponent && superDef) {
8025 theComponent = superDef.component;
8026 }
8027 if (!theComponent) {
8028 return null; // don't throw a warning, might be settings for a single-unit view
8029 }
8030 return {
8031 type: viewType,
8032 component: theComponent,
8033 defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
8034 overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
8035 };
8036 }
8037
8038 function parseViewConfigs(inputs) {
8039 return mapHash(inputs, parseViewConfig);
8040 }
8041 function parseViewConfig(input) {
8042 let rawOptions = typeof input === 'function' ?
8043 { component: input } :
8044 input;
8045 let { component } = rawOptions;
8046 if (rawOptions.content) {
8047 // TODO: remove content/classNames/didMount/etc from options?
8048 component = createViewHookComponent(rawOptions);
8049 }
8050 else if (component && !(component.prototype instanceof BaseComponent)) {
8051 // WHY?: people were using `component` property for `content`
8052 // TODO: converge on one setting name
8053 component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), { content: component }));
8054 }
8055 return {
8056 superType: rawOptions.type,
8057 component: component,
8058 rawOptions, // includes type and component too :(
8059 };
8060 }
8061 function createViewHookComponent(options) {
8062 return (viewProps) => (y(ViewContextType.Consumer, null, (context) => (y(ContentContainer, { elTag: "div", elClasses: buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, customGenerator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
8063 }
8064
8065 function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8066 let defaultConfigs = parseViewConfigs(defaultInputs);
8067 let overrideConfigs = parseViewConfigs(optionOverrides.views);
8068 let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
8069 return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
8070 }
8071 function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8072 let durationInput = viewDef.overrides.duration ||
8073 viewDef.defaults.duration ||
8074 dynamicOptionOverrides.duration ||
8075 optionOverrides.duration;
8076 let duration = null;
8077 let durationUnit = '';
8078 let singleUnit = '';
8079 let singleUnitOverrides = {};
8080 if (durationInput) {
8081 duration = createDurationCached(durationInput);
8082 if (duration) { // valid?
8083 let denom = greatestDurationDenominator(duration);
8084 durationUnit = denom.unit;
8085 if (denom.value === 1) {
8086 singleUnit = durationUnit;
8087 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
8088 }
8089 }
8090 }
8091 let queryButtonText = (optionsSubset) => {
8092 let buttonTextMap = optionsSubset.buttonText || {};
8093 let buttonTextKey = viewDef.defaults.buttonTextKey;
8094 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
8095 return buttonTextMap[buttonTextKey];
8096 }
8097 if (buttonTextMap[viewDef.type] != null) {
8098 return buttonTextMap[viewDef.type];
8099 }
8100 if (buttonTextMap[singleUnit] != null) {
8101 return buttonTextMap[singleUnit];
8102 }
8103 return null;
8104 };
8105 let queryButtonTitle = (optionsSubset) => {
8106 let buttonHints = optionsSubset.buttonHints || {};
8107 let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
8108 if (buttonKey != null && buttonHints[buttonKey] != null) {
8109 return buttonHints[buttonKey];
8110 }
8111 if (buttonHints[viewDef.type] != null) {
8112 return buttonHints[viewDef.type];
8113 }
8114 if (buttonHints[singleUnit] != null) {
8115 return buttonHints[singleUnit];
8116 }
8117 return null;
8118 };
8119 return {
8120 type: viewDef.type,
8121 component: viewDef.component,
8122 duration,
8123 durationUnit,
8124 singleUnit,
8125 optionDefaults: viewDef.defaults,
8126 optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
8127 buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
8128 queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
8129 viewDef.overrides.buttonText,
8130 buttonTextDefault: queryButtonText(localeDefaults) ||
8131 viewDef.defaults.buttonText ||
8132 queryButtonText(BASE_OPTION_DEFAULTS) ||
8133 viewDef.type,
8134 // not DRY
8135 buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
8136 queryButtonTitle(optionOverrides) ||
8137 viewDef.overrides.buttonHint,
8138 buttonTitleDefault: queryButtonTitle(localeDefaults) ||
8139 viewDef.defaults.buttonHint ||
8140 queryButtonTitle(BASE_OPTION_DEFAULTS),
8141 // will eventually fall back to buttonText
8142 };
8143 }
8144 // hack to get memoization working
8145 let durationInputMap = {};
8146 function createDurationCached(durationInput) {
8147 let json = JSON.stringify(durationInput);
8148 let res = durationInputMap[json];
8149 if (res === undefined) {
8150 res = createDuration(durationInput);
8151 durationInputMap[json] = res;
8152 }
8153 return res;
8154 }
8155
8156 function reduceViewType(viewType, action) {
8157 switch (action.type) {
8158 case 'CHANGE_VIEW_TYPE':
8159 viewType = action.viewType;
8160 }
8161 return viewType;
8162 }
8163
8164 function reduceCurrentDate(currentDate, action) {
8165 switch (action.type) {
8166 case 'CHANGE_DATE':
8167 return action.dateMarker;
8168 default:
8169 return currentDate;
8170 }
8171 }
8172 // should be initialized once and stay constant
8173 // this will change too
8174 function getInitialDate(options, dateEnv, nowManager) {
8175 let initialDateInput = options.initialDate;
8176 // compute the initial ambig-timezone date
8177 if (initialDateInput != null) {
8178 return dateEnv.createMarker(initialDateInput);
8179 }
8180 return nowManager.getDateMarker();
8181 }
8182
8183 function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
8184 switch (action.type) {
8185 case 'SET_OPTION':
8186 return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
8187 default:
8188 return dynamicOptionOverrides;
8189 }
8190 }
8191
8192 function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
8193 let dp;
8194 switch (action.type) {
8195 case 'CHANGE_VIEW_TYPE':
8196 return dateProfileGenerator.build(action.dateMarker || currentDate);
8197 case 'CHANGE_DATE':
8198 return dateProfileGenerator.build(action.dateMarker);
8199 case 'PREV':
8200 dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
8201 if (dp.isValid) {
8202 return dp;
8203 }
8204 break;
8205 case 'NEXT':
8206 dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
8207 if (dp.isValid) {
8208 return dp;
8209 }
8210 break;
8211 }
8212 return currentDateProfile;
8213 }
8214
8215 function initEventSources(calendarOptions, dateProfile, context) {
8216 let activeRange = dateProfile ? dateProfile.activeRange : null;
8217 return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
8218 }
8219 function reduceEventSources(eventSources, action, dateProfile, context) {
8220 let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8221 switch (action.type) {
8222 case 'ADD_EVENT_SOURCES': // already parsed
8223 return addSources(eventSources, action.sources, activeRange, context);
8224 case 'REMOVE_EVENT_SOURCE':
8225 return removeSource(eventSources, action.sourceId);
8226 case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
8227 case 'NEXT':
8228 case 'CHANGE_DATE':
8229 case 'CHANGE_VIEW_TYPE':
8230 if (dateProfile) {
8231 return fetchDirtySources(eventSources, activeRange, context);
8232 }
8233 return eventSources;
8234 case 'FETCH_EVENT_SOURCES':
8235 return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
8236 arrayToHash(action.sourceIds) :
8237 excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
8238 case 'RECEIVE_EVENTS':
8239 case 'RECEIVE_EVENT_ERROR':
8240 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
8241 case 'REMOVE_ALL_EVENT_SOURCES':
8242 return {};
8243 default:
8244 return eventSources;
8245 }
8246 }
8247 function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
8248 let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8249 return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
8250 }
8251 function computeEventSourcesLoading(eventSources) {
8252 for (let sourceId in eventSources) {
8253 if (eventSources[sourceId].isFetching) {
8254 return true;
8255 }
8256 }
8257 return false;
8258 }
8259 function addSources(eventSourceHash, sources, fetchRange, context) {
8260 let hash = {};
8261 for (let source of sources) {
8262 hash[source.sourceId] = source;
8263 }
8264 if (fetchRange) {
8265 hash = fetchDirtySources(hash, fetchRange, context);
8266 }
8267 return Object.assign(Object.assign({}, eventSourceHash), hash);
8268 }
8269 function removeSource(eventSourceHash, sourceId) {
8270 return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
8271 }
8272 function fetchDirtySources(sourceHash, fetchRange, context) {
8273 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
8274 }
8275 function isSourceDirty(eventSource, fetchRange, context) {
8276 if (!doesSourceNeedRange(eventSource, context)) {
8277 return !eventSource.latestFetchId;
8278 }
8279 return !context.options.lazyFetching ||
8280 !eventSource.fetchRange ||
8281 eventSource.isFetching || // always cancel outdated in-progress fetches
8282 fetchRange.start < eventSource.fetchRange.start ||
8283 fetchRange.end > eventSource.fetchRange.end;
8284 }
8285 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
8286 let nextSources = {};
8287 for (let sourceId in prevSources) {
8288 let source = prevSources[sourceId];
8289 if (sourceIdHash[sourceId]) {
8290 nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
8291 }
8292 else {
8293 nextSources[sourceId] = source;
8294 }
8295 }
8296 return nextSources;
8297 }
8298 function fetchSource(eventSource, fetchRange, isRefetch, context) {
8299 let { options, calendarApi } = context;
8300 let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
8301 let fetchId = guid();
8302 sourceDef.fetch({
8303 eventSource,
8304 range: fetchRange,
8305 isRefetch,
8306 context,
8307 }, (res) => {
8308 let { rawEvents } = res;
8309 if (options.eventSourceSuccess) {
8310 rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
8311 }
8312 if (eventSource.success) {
8313 rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
8314 }
8315 context.dispatch({
8316 type: 'RECEIVE_EVENTS',
8317 sourceId: eventSource.sourceId,
8318 fetchId,
8319 fetchRange,
8320 rawEvents,
8321 });
8322 }, (error) => {
8323 let errorHandled = false;
8324 if (options.eventSourceFailure) {
8325 options.eventSourceFailure.call(calendarApi, error);
8326 errorHandled = true;
8327 }
8328 if (eventSource.failure) {
8329 eventSource.failure(error);
8330 errorHandled = true;
8331 }
8332 if (!errorHandled) {
8333 console.warn(error.message, error);
8334 }
8335 context.dispatch({
8336 type: 'RECEIVE_EVENT_ERROR',
8337 sourceId: eventSource.sourceId,
8338 fetchId,
8339 fetchRange,
8340 error,
8341 });
8342 });
8343 return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
8344 }
8345 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
8346 let eventSource = sourceHash[sourceId];
8347 if (eventSource && // not already removed
8348 fetchId === eventSource.latestFetchId) {
8349 return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
8350 }
8351 return sourceHash;
8352 }
8353 function excludeStaticSources(eventSources, context) {
8354 return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
8355 }
8356 function parseInitialSources(rawOptions, context) {
8357 let refiners = buildEventSourceRefiners(context);
8358 let rawSources = [].concat(rawOptions.eventSources || []);
8359 let sources = []; // parsed
8360 if (rawOptions.initialEvents) {
8361 rawSources.unshift(rawOptions.initialEvents);
8362 }
8363 if (rawOptions.events) {
8364 rawSources.unshift(rawOptions.events);
8365 }
8366 for (let rawSource of rawSources) {
8367 let source = parseEventSource(rawSource, context, refiners);
8368 if (source) {
8369 sources.push(source);
8370 }
8371 }
8372 return sources;
8373 }
8374 function doesSourceNeedRange(eventSource, context) {
8375 let defs = context.pluginHooks.eventSourceDefs;
8376 return !defs[eventSource.sourceDefId].ignoreRange;
8377 }
8378
8379 function reduceDateSelection(currentSelection, action) {
8380 switch (action.type) {
8381 case 'UNSELECT_DATES':
8382 return null;
8383 case 'SELECT_DATES':
8384 return action.selection;
8385 default:
8386 return currentSelection;
8387 }
8388 }
8389
8390 function reduceSelectedEvent(currentInstanceId, action) {
8391 switch (action.type) {
8392 case 'UNSELECT_EVENT':
8393 return '';
8394 case 'SELECT_EVENT':
8395 return action.eventInstanceId;
8396 default:
8397 return currentInstanceId;
8398 }
8399 }
8400
8401 function reduceEventDrag(currentDrag, action) {
8402 let newDrag;
8403 switch (action.type) {
8404 case 'UNSET_EVENT_DRAG':
8405 return null;
8406 case 'SET_EVENT_DRAG':
8407 newDrag = action.state;
8408 return {
8409 affectedEvents: newDrag.affectedEvents,
8410 mutatedEvents: newDrag.mutatedEvents,
8411 isEvent: newDrag.isEvent,
8412 };
8413 default:
8414 return currentDrag;
8415 }
8416 }
8417
8418 function reduceEventResize(currentResize, action) {
8419 let newResize;
8420 switch (action.type) {
8421 case 'UNSET_EVENT_RESIZE':
8422 return null;
8423 case 'SET_EVENT_RESIZE':
8424 newResize = action.state;
8425 return {
8426 affectedEvents: newResize.affectedEvents,
8427 mutatedEvents: newResize.mutatedEvents,
8428 isEvent: newResize.isEvent,
8429 };
8430 default:
8431 return currentResize;
8432 }
8433 }
8434
8435 function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8436 let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8437 let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8438 return { header, footer };
8439 }
8440 function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8441 let sectionWidgets = {};
8442 let viewsWithButtons = [];
8443 let hasTitle = false;
8444 for (let sectionName in sectionStrHash) {
8445 let sectionStr = sectionStrHash[sectionName];
8446 let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
8447 sectionWidgets[sectionName] = sectionRes.widgets;
8448 viewsWithButtons.push(...sectionRes.viewsWithButtons);
8449 hasTitle = hasTitle || sectionRes.hasTitle;
8450 }
8451 return { sectionWidgets, viewsWithButtons, hasTitle };
8452 }
8453 /*
8454 BAD: querying icons and text here. should be done at render time
8455 */
8456 function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
8457 calendarOptionOverrides, // overrides only!, unrefined :(
8458 theme, viewSpecs, calendarApi) {
8459 let isRtl = calendarOptions.direction === 'rtl';
8460 let calendarCustomButtons = calendarOptions.customButtons || {};
8461 let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
8462 let calendarButtonText = calendarOptions.buttonText || {};
8463 let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
8464 let calendarButtonHints = calendarOptions.buttonHints || {};
8465 let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
8466 let viewsWithButtons = [];
8467 let hasTitle = false;
8468 let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
8469 if (buttonName === 'title') {
8470 hasTitle = true;
8471 return { buttonName };
8472 }
8473 let customButtonProps;
8474 let viewSpec;
8475 let buttonClick;
8476 let buttonIcon; // only one of these will be set
8477 let buttonText; // "
8478 let buttonHint;
8479 // ^ for the title="" attribute, for accessibility
8480 if ((customButtonProps = calendarCustomButtons[buttonName])) {
8481 buttonClick = (ev) => {
8482 if (customButtonProps.click) {
8483 customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
8484 }
8485 };
8486 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
8487 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8488 (buttonText = customButtonProps.text);
8489 buttonHint = customButtonProps.hint || customButtonProps.text;
8490 }
8491 else if ((viewSpec = viewSpecs[buttonName])) {
8492 viewsWithButtons.push(buttonName);
8493 buttonClick = () => {
8494 calendarApi.changeView(buttonName);
8495 };
8496 (buttonText = viewSpec.buttonTextOverride) ||
8497 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8498 (buttonText = viewSpec.buttonTextDefault);
8499 let textFallback = viewSpec.buttonTextOverride ||
8500 viewSpec.buttonTextDefault;
8501 buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
8502 viewSpec.buttonTitleDefault ||
8503 calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
8504 textFallback);
8505 }
8506 else if (calendarApi[buttonName]) { // a calendarApi method
8507 buttonClick = () => {
8508 calendarApi[buttonName]();
8509 };
8510 (buttonText = calendarButtonTextOverrides[buttonName]) ||
8511 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8512 (buttonText = calendarButtonText[buttonName]); // everything else is considered default
8513 if (buttonName === 'prevYear' || buttonName === 'nextYear') {
8514 let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
8515 buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
8516 calendarButtonHints[prevOrNext], [
8517 calendarButtonText.year || 'year',
8518 'year',
8519 ], calendarButtonText[buttonName]);
8520 }
8521 else {
8522 buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
8523 calendarButtonHints[buttonName], [
8524 calendarButtonText[navUnit] || navUnit,
8525 navUnit,
8526 ], calendarButtonText[buttonName]);
8527 }
8528 }
8529 return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
8530 })));
8531 return { widgets, viewsWithButtons, hasTitle };
8532 }
8533
8534 // always represents the current view. otherwise, it'd need to change value every time date changes
8535 class ViewImpl {
8536 constructor(type, getCurrentData, dateEnv) {
8537 this.type = type;
8538 this.getCurrentData = getCurrentData;
8539 this.dateEnv = dateEnv;
8540 }
8541 get calendar() {
8542 return this.getCurrentData().calendarApi;
8543 }
8544 get title() {
8545 return this.getCurrentData().viewTitle;
8546 }
8547 get activeStart() {
8548 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
8549 }
8550 get activeEnd() {
8551 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
8552 }
8553 get currentStart() {
8554 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
8555 }
8556 get currentEnd() {
8557 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
8558 }
8559 getOption(name) {
8560 return this.getCurrentData().options[name]; // are the view-specific options
8561 }
8562 }
8563
8564 let eventSourceDef$2 = {
8565 ignoreRange: true,
8566 parseMeta(refined) {
8567 if (Array.isArray(refined.events)) {
8568 return refined.events;
8569 }
8570 return null;
8571 },
8572 fetch(arg, successCallback) {
8573 successCallback({
8574 rawEvents: arg.eventSource.meta,
8575 });
8576 },
8577 };
8578 const arrayEventSourcePlugin = createPlugin({
8579 name: 'array-event-source',
8580 eventSourceDefs: [eventSourceDef$2],
8581 });
8582
8583 let eventSourceDef$1 = {
8584 parseMeta(refined) {
8585 if (typeof refined.events === 'function') {
8586 return refined.events;
8587 }
8588 return null;
8589 },
8590 fetch(arg, successCallback, errorCallback) {
8591 const { dateEnv } = arg.context;
8592 const func = arg.eventSource.meta;
8593 unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
8594 },
8595 };
8596 const funcEventSourcePlugin = createPlugin({
8597 name: 'func-event-source',
8598 eventSourceDefs: [eventSourceDef$1],
8599 });
8600
8601 const JSON_FEED_EVENT_SOURCE_REFINERS = {
8602 method: String,
8603 extraParams: identity,
8604 startParam: String,
8605 endParam: String,
8606 timeZoneParam: String,
8607 };
8608
8609 let eventSourceDef = {
8610 parseMeta(refined) {
8611 if (refined.url && (refined.format === 'json' || !refined.format)) {
8612 return {
8613 url: refined.url,
8614 format: 'json',
8615 method: (refined.method || 'GET').toUpperCase(),
8616 extraParams: refined.extraParams,
8617 startParam: refined.startParam,
8618 endParam: refined.endParam,
8619 timeZoneParam: refined.timeZoneParam,
8620 };
8621 }
8622 return null;
8623 },
8624 fetch(arg, successCallback, errorCallback) {
8625 const { meta } = arg.eventSource;
8626 const requestParams = buildRequestParams(meta, arg.range, arg.context);
8627 requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
8628 successCallback({ rawEvents, response });
8629 }, errorCallback);
8630 },
8631 };
8632 const jsonFeedEventSourcePlugin = createPlugin({
8633 name: 'json-event-source',
8634 eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
8635 eventSourceDefs: [eventSourceDef],
8636 });
8637 function buildRequestParams(meta, range, context) {
8638 let { dateEnv, options } = context;
8639 let startParam;
8640 let endParam;
8641 let timeZoneParam;
8642 let customRequestParams;
8643 let params = {};
8644 startParam = meta.startParam;
8645 if (startParam == null) {
8646 startParam = options.startParam;
8647 }
8648 endParam = meta.endParam;
8649 if (endParam == null) {
8650 endParam = options.endParam;
8651 }
8652 timeZoneParam = meta.timeZoneParam;
8653 if (timeZoneParam == null) {
8654 timeZoneParam = options.timeZoneParam;
8655 }
8656 // retrieve any outbound GET/POST data from the options
8657 if (typeof meta.extraParams === 'function') {
8658 // supplied as a function that returns a key/value object
8659 customRequestParams = meta.extraParams();
8660 }
8661 else {
8662 // probably supplied as a straight key/value object
8663 customRequestParams = meta.extraParams || {};
8664 }
8665 Object.assign(params, customRequestParams);
8666 params[startParam] = dateEnv.formatIso(range.start);
8667 params[endParam] = dateEnv.formatIso(range.end);
8668 if (dateEnv.timeZone !== 'local') {
8669 params[timeZoneParam] = dateEnv.timeZone;
8670 }
8671 return params;
8672 }
8673
8674 const SIMPLE_RECURRING_REFINERS = {
8675 daysOfWeek: identity,
8676 startTime: createDuration,
8677 endTime: createDuration,
8678 duration: createDuration,
8679 startRecur: identity,
8680 endRecur: identity,
8681 };
8682
8683 let recurring = {
8684 parse(refined, dateEnv) {
8685 if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
8686 let recurringData = {
8687 daysOfWeek: refined.daysOfWeek || null,
8688 startTime: refined.startTime || null,
8689 endTime: refined.endTime || null,
8690 startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
8691 endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
8692 dateEnv,
8693 };
8694 let duration;
8695 if (refined.duration) {
8696 duration = refined.duration;
8697 }
8698 if (!duration && refined.startTime && refined.endTime) {
8699 duration = subtractDurations(refined.endTime, refined.startTime);
8700 }
8701 return {
8702 allDayGuess: Boolean(!refined.startTime && !refined.endTime),
8703 duration,
8704 typeData: recurringData, // doesn't need endTime anymore but oh well
8705 };
8706 }
8707 return null;
8708 },
8709 expand(typeData, framingRange, dateEnv) {
8710 let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
8711 if (clippedFramingRange) {
8712 return expandRanges(typeData.daysOfWeek, typeData.startTime, typeData.dateEnv, dateEnv, clippedFramingRange);
8713 }
8714 return [];
8715 },
8716 };
8717 const simpleRecurringEventsPlugin = createPlugin({
8718 name: 'simple-recurring-event',
8719 recurringTypes: [recurring],
8720 eventRefiners: SIMPLE_RECURRING_REFINERS,
8721 });
8722 function expandRanges(daysOfWeek, startTime, eventDateEnv, calendarDateEnv, framingRange) {
8723 let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
8724 let dayMarker = startOfDay(framingRange.start);
8725 let endMarker = framingRange.end;
8726 let instanceStarts = [];
8727 while (dayMarker < endMarker) {
8728 let instanceStart;
8729 // if everyday, or this particular day-of-week
8730 if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
8731 if (startTime) {
8732 instanceStart = calendarDateEnv.add(dayMarker, startTime);
8733 }
8734 else {
8735 instanceStart = dayMarker;
8736 }
8737 instanceStarts.push(calendarDateEnv.createMarker(eventDateEnv.toDate(instanceStart)));
8738 }
8739 dayMarker = addDays(dayMarker, 1);
8740 }
8741 return instanceStarts;
8742 }
8743
8744 const changeHandlerPlugin = createPlugin({
8745 name: 'change-handler',
8746 optionChangeHandlers: {
8747 events(events, context) {
8748 handleEventSources([events], context);
8749 },
8750 eventSources: handleEventSources,
8751 },
8752 });
8753 /*
8754 BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
8755 */
8756 function handleEventSources(inputs, context) {
8757 let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
8758 if (unfoundSources.length === 1 &&
8759 inputs.length === 1 &&
8760 Array.isArray(unfoundSources[0]._raw) &&
8761 Array.isArray(inputs[0])) {
8762 context.dispatch({
8763 type: 'RESET_RAW_EVENTS',
8764 sourceId: unfoundSources[0].sourceId,
8765 rawEvents: inputs[0],
8766 });
8767 return;
8768 }
8769 let newInputs = [];
8770 for (let input of inputs) {
8771 let inputFound = false;
8772 for (let i = 0; i < unfoundSources.length; i += 1) {
8773 if (unfoundSources[i]._raw === input) {
8774 unfoundSources.splice(i, 1); // delete
8775 inputFound = true;
8776 break;
8777 }
8778 }
8779 if (!inputFound) {
8780 newInputs.push(input);
8781 }
8782 }
8783 for (let unfoundSource of unfoundSources) {
8784 context.dispatch({
8785 type: 'REMOVE_EVENT_SOURCE',
8786 sourceId: unfoundSource.sourceId,
8787 });
8788 }
8789 for (let newInput of newInputs) {
8790 context.calendarApi.addEventSource(newInput);
8791 }
8792 }
8793
8794 function handleDateProfile(dateProfile, context) {
8795 context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
8796 }
8797
8798 function handleEventStore(eventStore, context) {
8799 let { emitter } = context;
8800 if (emitter.hasHandlers('eventsSet')) {
8801 emitter.trigger('eventsSet', buildEventApis(eventStore, context));
8802 }
8803 }
8804
8805 /*
8806 this array is exposed on the root namespace so that UMD plugins can add to it.
8807 see the rollup-bundles script.
8808 */
8809 const globalPlugins = [
8810 arrayEventSourcePlugin,
8811 funcEventSourcePlugin,
8812 jsonFeedEventSourcePlugin,
8813 simpleRecurringEventsPlugin,
8814 changeHandlerPlugin,
8815 createPlugin({
8816 name: 'misc',
8817 isLoadingFuncs: [
8818 (state) => computeEventSourcesLoading(state.eventSources),
8819 ],
8820 propSetHandlers: {
8821 dateProfile: handleDateProfile,
8822 eventStore: handleEventStore,
8823 },
8824 }),
8825 ];
8826
8827 class TaskRunner {
8828 constructor(runTaskOption, drainedOption) {
8829 this.runTaskOption = runTaskOption;
8830 this.drainedOption = drainedOption;
8831 this.queue = [];
8832 this.delayedRunner = new DelayedRunner(this.drain.bind(this));
8833 }
8834 request(task, delay) {
8835 this.queue.push(task);
8836 this.delayedRunner.request(delay);
8837 }
8838 pause(scope) {
8839 this.delayedRunner.pause(scope);
8840 }
8841 resume(scope, force) {
8842 this.delayedRunner.resume(scope, force);
8843 }
8844 drain() {
8845 let { queue } = this;
8846 while (queue.length) {
8847 let completedTasks = [];
8848 let task;
8849 while ((task = queue.shift())) {
8850 this.runTask(task);
8851 completedTasks.push(task);
8852 }
8853 this.drained(completedTasks);
8854 } // keep going, in case new tasks were added in the drained handler
8855 }
8856 runTask(task) {
8857 if (this.runTaskOption) {
8858 this.runTaskOption(task);
8859 }
8860 }
8861 drained(completedTasks) {
8862 if (this.drainedOption) {
8863 this.drainedOption(completedTasks);
8864 }
8865 }
8866 }
8867
8868 // Computes what the title at the top of the calendarApi should be for this view
8869 function buildTitle(dateProfile, viewOptions, dateEnv) {
8870 let range;
8871 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
8872 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
8873 range = dateProfile.currentRange;
8874 }
8875 else { // for day units or smaller, use the actual day range
8876 range = dateProfile.activeRange;
8877 }
8878 return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
8879 isEndExclusive: dateProfile.isRangeAllDay,
8880 defaultSeparator: viewOptions.titleRangeSeparator,
8881 });
8882 }
8883 // Generates the format string that should be used to generate the title for the current date range.
8884 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
8885 function buildTitleFormat(dateProfile) {
8886 let { currentRangeUnit } = dateProfile;
8887 if (currentRangeUnit === 'year') {
8888 return { year: 'numeric' };
8889 }
8890 if (currentRangeUnit === 'month') {
8891 return { year: 'numeric', month: 'long' }; // like "September 2014"
8892 }
8893 let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
8894 if (days !== null && days > 1) {
8895 // multi-day range. shorter, like "Sep 9 - 10 2014"
8896 return { year: 'numeric', month: 'short', day: 'numeric' };
8897 }
8898 // one day. longer, like "September 9 2014"
8899 return { year: 'numeric', month: 'long', day: 'numeric' };
8900 }
8901
8902 /*
8903 TODO: test switching timezones when NO timezone plugin
8904 */
8905 class CalendarNowManager {
8906 constructor() {
8907 this.resetListeners = new Set();
8908 }
8909 handleInput(dateEnv, // will change if timezone setup changed
8910 nowInput) {
8911 const oldDateEnv = this.dateEnv;
8912 if (dateEnv !== oldDateEnv) {
8913 if (typeof nowInput === 'function') {
8914 this.nowFn = nowInput;
8915 }
8916 else if (!oldDateEnv) { // first time?
8917 this.nowAnchorDate = dateEnv.toDate(nowInput
8918 ? dateEnv.createMarker(nowInput)
8919 : dateEnv.createNowMarker());
8920 this.nowAnchorQueried = Date.now();
8921 }
8922 this.dateEnv = dateEnv;
8923 // not first time? fire reset handlers
8924 if (oldDateEnv) {
8925 for (const resetListener of this.resetListeners.values()) {
8926 resetListener();
8927 }
8928 }
8929 }
8930 }
8931 getDateMarker() {
8932 return this.nowAnchorDate
8933 ? this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf() +
8934 (Date.now() - this.nowAnchorQueried))
8935 : this.dateEnv.createMarker(this.nowFn());
8936 }
8937 addResetListener(handler) {
8938 this.resetListeners.add(handler);
8939 }
8940 removeResetListener(handler) {
8941 this.resetListeners.delete(handler);
8942 }
8943 }
8944
8945 // in future refactor, do the redux-style function(state=initial) for initial-state
8946 // also, whatever is happening in constructor, have it happen in action queue too
8947 class CalendarDataManager {
8948 constructor(props) {
8949 this.computeCurrentViewData = memoize(this._computeCurrentViewData);
8950 this.organizeRawLocales = memoize(organizeRawLocales);
8951 this.buildLocale = memoize(buildLocale);
8952 this.buildPluginHooks = buildBuildPluginHooks();
8953 this.buildDateEnv = memoize(buildDateEnv$1);
8954 this.buildTheme = memoize(buildTheme);
8955 this.parseToolbars = memoize(parseToolbars);
8956 this.buildViewSpecs = memoize(buildViewSpecs);
8957 this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
8958 this.buildViewApi = memoize(buildViewApi);
8959 this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
8960 this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
8961 this.buildEventUiBases = memoize(buildEventUiBases);
8962 this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
8963 this.buildTitle = memoize(buildTitle);
8964 this.nowManager = new CalendarNowManager();
8965 this.emitter = new Emitter();
8966 this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
8967 this.currentCalendarOptionsInput = {};
8968 this.currentCalendarOptionsRefined = {};
8969 this.currentViewOptionsInput = {};
8970 this.currentViewOptionsRefined = {};
8971 this.currentCalendarOptionsRefiners = {};
8972 this.optionsForRefining = [];
8973 this.optionsForHandling = [];
8974 this.getCurrentData = () => this.data;
8975 this.dispatch = (action) => {
8976 this.actionRunner.request(action); // protects against recursive calls to _handleAction
8977 };
8978 this.props = props;
8979 this.actionRunner.pause();
8980 this.nowManager = new CalendarNowManager();
8981 let dynamicOptionOverrides = {};
8982 let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
8983 let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
8984 let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
8985 // wire things up
8986 // TODO: not DRY
8987 props.calendarApi.currentDataManager = this;
8988 this.emitter.setThisContext(props.calendarApi);
8989 this.emitter.setOptions(currentViewData.options);
8990 let calendarContext = {
8991 nowManager: this.nowManager,
8992 dateEnv: optionsData.dateEnv,
8993 options: optionsData.calendarOptions,
8994 pluginHooks: optionsData.pluginHooks,
8995 calendarApi: props.calendarApi,
8996 dispatch: this.dispatch,
8997 emitter: this.emitter,
8998 getCurrentData: this.getCurrentData,
8999 };
9000 let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv, this.nowManager);
9001 let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9002 if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
9003 currentDate = dateProfile.currentRange.start;
9004 }
9005 // needs to be after setThisContext
9006 for (let callback of optionsData.pluginHooks.contextInit) {
9007 callback(calendarContext);
9008 }
9009 // NOT DRY
9010 let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
9011 let initialState = {
9012 dynamicOptionOverrides,
9013 currentViewType,
9014 currentDate,
9015 dateProfile,
9016 businessHours: this.parseContextBusinessHours(calendarContext),
9017 eventSources,
9018 eventUiBases: {},
9019 eventStore: createEmptyEventStore(),
9020 renderableEventStore: createEmptyEventStore(),
9021 dateSelection: null,
9022 eventSelection: '',
9023 eventDrag: null,
9024 eventResize: null,
9025 selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
9026 };
9027 let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
9028 for (let reducer of optionsData.pluginHooks.reducers) {
9029 Object.assign(initialState, reducer(null, null, contextAndState));
9030 }
9031 if (computeIsLoading(initialState, calendarContext)) {
9032 this.emitter.trigger('loading', true); // NOT DRY
9033 }
9034 this.state = initialState;
9035 this.updateData();
9036 this.actionRunner.resume();
9037 }
9038 resetOptions(optionOverrides, changedOptionNames) {
9039 let { props } = this;
9040 if (changedOptionNames === undefined) {
9041 props.optionOverrides = optionOverrides;
9042 }
9043 else {
9044 props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);
9045 this.optionsForRefining.push(...changedOptionNames);
9046 }
9047 if (changedOptionNames === undefined || changedOptionNames.length) {
9048 this.actionRunner.request({
9049 type: 'NOTHING',
9050 });
9051 }
9052 }
9053 _handleAction(action) {
9054 let { props, state, emitter } = this;
9055 let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
9056 let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
9057 let currentViewType = reduceViewType(state.currentViewType, action);
9058 let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
9059 // wire things up
9060 // TODO: not DRY
9061 props.calendarApi.currentDataManager = this;
9062 emitter.setThisContext(props.calendarApi);
9063 emitter.setOptions(currentViewData.options);
9064 let calendarContext = {
9065 nowManager: this.nowManager,
9066 dateEnv: optionsData.dateEnv,
9067 options: optionsData.calendarOptions,
9068 pluginHooks: optionsData.pluginHooks,
9069 calendarApi: props.calendarApi,
9070 dispatch: this.dispatch,
9071 emitter,
9072 getCurrentData: this.getCurrentData,
9073 };
9074 let { currentDate, dateProfile } = state;
9075 if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
9076 dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9077 }
9078 currentDate = reduceCurrentDate(currentDate, action);
9079 dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
9080 if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
9081 action.type === 'NEXT' || // "
9082 !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
9083 currentDate = dateProfile.currentRange.start;
9084 }
9085 let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
9086 let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
9087 let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
9088 let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
9089 (state.renderableEventStore || eventStore) : // try from previous state
9090 eventStore;
9091 let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
9092 let eventUiBySource = this.buildEventUiBySource(eventSources);
9093 let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
9094 let newState = {
9095 dynamicOptionOverrides,
9096 currentViewType,
9097 currentDate,
9098 dateProfile,
9099 eventSources,
9100 eventStore,
9101 renderableEventStore,
9102 selectionConfig,
9103 eventUiBases,
9104 businessHours: this.parseContextBusinessHours(calendarContext),
9105 dateSelection: reduceDateSelection(state.dateSelection, action),
9106 eventSelection: reduceSelectedEvent(state.eventSelection, action),
9107 eventDrag: reduceEventDrag(state.eventDrag, action),
9108 eventResize: reduceEventResize(state.eventResize, action),
9109 };
9110 let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
9111 for (let reducer of optionsData.pluginHooks.reducers) {
9112 Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
9113 }
9114 let wasLoading = computeIsLoading(state, calendarContext);
9115 let isLoading = computeIsLoading(newState, calendarContext);
9116 // TODO: use propSetHandlers in plugin system
9117 if (!wasLoading && isLoading) {
9118 emitter.trigger('loading', true);
9119 }
9120 else if (wasLoading && !isLoading) {
9121 emitter.trigger('loading', false);
9122 }
9123 this.state = newState;
9124 if (props.onAction) {
9125 props.onAction(action);
9126 }
9127 }
9128 updateData() {
9129 let { props, state } = this;
9130 let oldData = this.data;
9131 let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
9132 let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
9133 let data = this.data = Object.assign(Object.assign(Object.assign({ nowManager: this.nowManager, viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
9134 let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
9135 let oldCalendarOptions = oldData && oldData.calendarOptions;
9136 let newCalendarOptions = optionsData.calendarOptions;
9137 if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
9138 if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
9139 // hack
9140 state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
9141 state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
9142 state.renderableEventStore = data.renderableEventStore = rezoneEventStoreDates(data.renderableEventStore, oldData.dateEnv, data.dateEnv);
9143 }
9144 for (let optionName in changeHandlers) {
9145 if (this.optionsForHandling.indexOf(optionName) !== -1 ||
9146 oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
9147 changeHandlers[optionName](newCalendarOptions[optionName], data);
9148 }
9149 }
9150 }
9151 this.optionsForHandling = [];
9152 if (props.onData) {
9153 props.onData(data);
9154 }
9155 }
9156 computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
9157 // TODO: blacklist options that are handled by optionChangeHandlers
9158 if (!this.optionsForRefining.length &&
9159 optionOverrides === this.stableOptionOverrides &&
9160 dynamicOptionOverrides === this.stableDynamicOptionOverrides) {
9161 return this.stableCalendarOptionsData;
9162 }
9163 let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
9164 warnUnknownOptions(extra);
9165 let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
9166 let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);
9167 let theme = this.buildTheme(refinedOptions, pluginHooks);
9168 let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);
9169 return this.stableCalendarOptionsData = {
9170 calendarOptions: refinedOptions,
9171 pluginHooks,
9172 dateEnv,
9173 viewSpecs,
9174 theme,
9175 toolbarConfig,
9176 localeDefaults,
9177 availableRawLocales: availableLocaleData.map,
9178 };
9179 }
9180 // always called from behind a memoizer
9181 processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
9182 let { locales, locale } = mergeRawOptions([
9183 BASE_OPTION_DEFAULTS,
9184 optionOverrides,
9185 dynamicOptionOverrides,
9186 ]);
9187 let availableLocaleData = this.organizeRawLocales(locales);
9188 let availableRawLocales = availableLocaleData.map;
9189 let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
9190 let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
9191 let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
9192 let extra = {};
9193 let raw = mergeRawOptions([
9194 BASE_OPTION_DEFAULTS,
9195 localeDefaults,
9196 optionOverrides,
9197 dynamicOptionOverrides,
9198 ]);
9199 let refined = {};
9200 let currentRaw = this.currentCalendarOptionsInput;
9201 let currentRefined = this.currentCalendarOptionsRefined;
9202 let anyChanges = false;
9203 for (let optionName in raw) {
9204 if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (COMPLEX_OPTION_COMPARATORS[optionName] &&
9205 (optionName in currentRaw) &&
9206 COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName])))) {
9207 refined[optionName] = currentRefined[optionName];
9208 }
9209 else if (refiners[optionName]) {
9210 refined[optionName] = refiners[optionName](raw[optionName]);
9211 anyChanges = true;
9212 }
9213 else {
9214 extra[optionName] = currentRaw[optionName];
9215 }
9216 }
9217 if (anyChanges) {
9218 this.currentCalendarOptionsInput = raw;
9219 this.currentCalendarOptionsRefined = refined;
9220 this.stableOptionOverrides = optionOverrides;
9221 this.stableDynamicOptionOverrides = dynamicOptionOverrides;
9222 }
9223 this.optionsForHandling.push(...this.optionsForRefining);
9224 this.optionsForRefining = [];
9225 return {
9226 rawOptions: this.currentCalendarOptionsInput,
9227 refinedOptions: this.currentCalendarOptionsRefined,
9228 pluginHooks,
9229 availableLocaleData,
9230 localeDefaults,
9231 extra,
9232 };
9233 }
9234 _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
9235 let viewSpec = optionsData.viewSpecs[viewType];
9236 if (!viewSpec) {
9237 throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
9238 }
9239 let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
9240 warnUnknownOptions(extra);
9241 this.nowManager.handleInput(optionsData.dateEnv, refinedOptions.now);
9242 let dateProfileGenerator = this.buildDateProfileGenerator({
9243 dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
9244 nowManager: this.nowManager,
9245 duration: viewSpec.duration,
9246 durationUnit: viewSpec.durationUnit,
9247 usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
9248 dateEnv: optionsData.dateEnv,
9249 calendarApi: this.props.calendarApi,
9250 slotMinTime: refinedOptions.slotMinTime,
9251 slotMaxTime: refinedOptions.slotMaxTime,
9252 showNonCurrentDates: refinedOptions.showNonCurrentDates,
9253 dayCount: refinedOptions.dayCount,
9254 dateAlignment: refinedOptions.dateAlignment,
9255 dateIncrement: refinedOptions.dateIncrement,
9256 hiddenDays: refinedOptions.hiddenDays,
9257 weekends: refinedOptions.weekends,
9258 validRangeInput: refinedOptions.validRange,
9259 visibleRangeInput: refinedOptions.visibleRange,
9260 fixedWeekCount: refinedOptions.fixedWeekCount,
9261 });
9262 let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
9263 return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
9264 }
9265 processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
9266 let raw = mergeRawOptions([
9267 BASE_OPTION_DEFAULTS,
9268 viewSpec.optionDefaults,
9269 localeDefaults,
9270 optionOverrides,
9271 viewSpec.optionOverrides,
9272 dynamicOptionOverrides,
9273 ]);
9274 let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
9275 let refined = {};
9276 let currentRaw = this.currentViewOptionsInput;
9277 let currentRefined = this.currentViewOptionsRefined;
9278 let anyChanges = false;
9279 let extra = {};
9280 for (let optionName in raw) {
9281 if (raw[optionName] === currentRaw[optionName] ||
9282 (COMPLEX_OPTION_COMPARATORS[optionName] &&
9283 COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
9284 refined[optionName] = currentRefined[optionName];
9285 }
9286 else {
9287 if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
9288 (COMPLEX_OPTION_COMPARATORS[optionName] &&
9289 COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
9290 if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
9291 refined[optionName] = this.currentCalendarOptionsRefined[optionName];
9292 }
9293 }
9294 else if (refiners[optionName]) {
9295 refined[optionName] = refiners[optionName](raw[optionName]);
9296 }
9297 else {
9298 extra[optionName] = raw[optionName];
9299 }
9300 anyChanges = true;
9301 }
9302 }
9303 if (anyChanges) {
9304 this.currentViewOptionsInput = raw;
9305 this.currentViewOptionsRefined = refined;
9306 }
9307 return {
9308 rawOptions: this.currentViewOptionsInput,
9309 refinedOptions: this.currentViewOptionsRefined,
9310 extra,
9311 };
9312 }
9313 }
9314 function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
9315 let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
9316 return new DateEnv({
9317 calendarSystem: 'gregory',
9318 timeZone,
9319 namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
9320 locale,
9321 weekNumberCalculation,
9322 firstDay,
9323 weekText,
9324 cmdFormatter: pluginHooks.cmdFormatter,
9325 defaultSeparator,
9326 });
9327 }
9328 function buildTheme(options, pluginHooks) {
9329 let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
9330 return new ThemeClass(options);
9331 }
9332 function buildDateProfileGenerator(props) {
9333 let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
9334 return new DateProfileGeneratorClass(props);
9335 }
9336 function buildViewApi(type, getCurrentData, dateEnv) {
9337 return new ViewImpl(type, getCurrentData, dateEnv);
9338 }
9339 function buildEventUiBySource(eventSources) {
9340 return mapHash(eventSources, (eventSource) => eventSource.ui);
9341 }
9342 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
9343 let eventUiBases = { '': eventUiSingleBase };
9344 for (let defId in eventDefs) {
9345 let def = eventDefs[defId];
9346 if (def.sourceId && eventUiBySource[def.sourceId]) {
9347 eventUiBases[defId] = eventUiBySource[def.sourceId];
9348 }
9349 }
9350 return eventUiBases;
9351 }
9352 function buildViewUiProps(calendarContext) {
9353 let { options } = calendarContext;
9354 return {
9355 eventUiSingleBase: createEventUi({
9356 display: options.eventDisplay,
9357 editable: options.editable,
9358 startEditable: options.eventStartEditable,
9359 durationEditable: options.eventDurationEditable,
9360 constraint: options.eventConstraint,
9361 overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
9362 allow: options.eventAllow,
9363 backgroundColor: options.eventBackgroundColor,
9364 borderColor: options.eventBorderColor,
9365 textColor: options.eventTextColor,
9366 color: options.eventColor,
9367 // classNames: options.eventClassNames // render hook will handle this
9368 }, calendarContext),
9369 selectionConfig: createEventUi({
9370 constraint: options.selectConstraint,
9371 overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
9372 allow: options.selectAllow,
9373 }, calendarContext),
9374 };
9375 }
9376 function computeIsLoading(state, context) {
9377 for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
9378 if (isLoadingFunc(state)) {
9379 return true;
9380 }
9381 }
9382 return false;
9383 }
9384 function parseContextBusinessHours(calendarContext) {
9385 return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
9386 }
9387 function warnUnknownOptions(options, viewName) {
9388 for (let optionName in options) {
9389 console.warn(`Unknown option '${optionName}'` +
9390 (viewName ? ` for view '${viewName}'` : ''));
9391 }
9392 }
9393
9394 class ToolbarSection extends BaseComponent {
9395 render() {
9396 let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
9397 return y('div', { className: 'fc-toolbar-chunk' }, ...children);
9398 }
9399 renderWidgetGroup(widgetGroup) {
9400 let { props } = this;
9401 let { theme } = this.context;
9402 let children = [];
9403 let isOnlyButtons = true;
9404 for (let widget of widgetGroup) {
9405 let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
9406 if (buttonName === 'title') {
9407 isOnlyButtons = false;
9408 children.push(y("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
9409 }
9410 else {
9411 let isPressed = buttonName === props.activeButton;
9412 let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
9413 (!props.isPrevEnabled && buttonName === 'prev') ||
9414 (!props.isNextEnabled && buttonName === 'next');
9415 let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
9416 if (isPressed) {
9417 buttonClasses.push(theme.getClass('buttonActive'));
9418 }
9419 children.push(y("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? y("span", { className: buttonIcon, role: "img" }) : '')));
9420 }
9421 }
9422 if (children.length > 1) {
9423 let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
9424 return y('div', { className: groupClassName }, ...children);
9425 }
9426 return children[0];
9427 }
9428 }
9429
9430 class Toolbar extends BaseComponent {
9431 render() {
9432 let { model, extraClassName } = this.props;
9433 let forceLtr = false;
9434 let startContent;
9435 let endContent;
9436 let sectionWidgets = model.sectionWidgets;
9437 let centerContent = sectionWidgets.center;
9438 if (sectionWidgets.left) {
9439 forceLtr = true;
9440 startContent = sectionWidgets.left;
9441 }
9442 else {
9443 startContent = sectionWidgets.start;
9444 }
9445 if (sectionWidgets.right) {
9446 forceLtr = true;
9447 endContent = sectionWidgets.right;
9448 }
9449 else {
9450 endContent = sectionWidgets.end;
9451 }
9452 let classNames = [
9453 extraClassName || '',
9454 'fc-toolbar',
9455 forceLtr ? 'fc-toolbar-ltr' : '',
9456 ];
9457 return (y("div", { className: classNames.join(' ') },
9458 this.renderSection('start', startContent || []),
9459 this.renderSection('center', centerContent || []),
9460 this.renderSection('end', endContent || [])));
9461 }
9462 renderSection(key, widgetGroups) {
9463 let { props } = this;
9464 return (y(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));
9465 }
9466 }
9467
9468 class ViewHarness extends BaseComponent {
9469 constructor() {
9470 super(...arguments);
9471 this.state = {
9472 availableWidth: null,
9473 };
9474 this.handleEl = (el) => {
9475 this.el = el;
9476 setRef(this.props.elRef, el);
9477 this.updateAvailableWidth();
9478 };
9479 this.handleResize = () => {
9480 this.updateAvailableWidth();
9481 };
9482 }
9483 render() {
9484 let { props, state } = this;
9485 let { aspectRatio } = props;
9486 let classNames = [
9487 'fc-view-harness',
9488 (aspectRatio || props.liquid || props.height)
9489 ? 'fc-view-harness-active' // harness controls the height
9490 : 'fc-view-harness-passive', // let the view do the height
9491 ];
9492 let height = '';
9493 let paddingBottom = '';
9494 if (aspectRatio) {
9495 if (state.availableWidth !== null) {
9496 height = state.availableWidth / aspectRatio;
9497 }
9498 else {
9499 // while waiting to know availableWidth, we can't set height to *zero*
9500 // because will cause lots of unnecessary scrollbars within scrollgrid.
9501 // BETTER: don't start rendering ANYTHING yet until we know container width
9502 // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
9503 paddingBottom = `${(1 / aspectRatio) * 100}%`;
9504 }
9505 }
9506 else {
9507 height = props.height || '';
9508 }
9509 return (y("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
9510 }
9511 componentDidMount() {
9512 this.context.addResizeHandler(this.handleResize);
9513 }
9514 componentWillUnmount() {
9515 this.context.removeResizeHandler(this.handleResize);
9516 }
9517 updateAvailableWidth() {
9518 if (this.el && // needed. but why?
9519 this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
9520 ) {
9521 this.setState({ availableWidth: this.el.offsetWidth });
9522 }
9523 }
9524 }
9525
9526 /*
9527 Detects when the user clicks on an event within a DateComponent
9528 */
9529 class EventClicking extends Interaction {
9530 constructor(settings) {
9531 super(settings);
9532 this.handleSegClick = (ev, segEl) => {
9533 let { component } = this;
9534 let { context } = component;
9535 let seg = getElSeg(segEl);
9536 if (seg && // might be the <div> surrounding the more link
9537 component.isValidSegDownEl(ev.target)) {
9538 // our way to simulate a link click for elements that can't be <a> tags
9539 // grab before trigger fired in case trigger trashes DOM thru rerendering
9540 let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
9541 let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
9542 context.emitter.trigger('eventClick', {
9543 el: segEl,
9544 event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
9545 jsEvent: ev,
9546 view: context.viewApi,
9547 });
9548 if (url && !ev.defaultPrevented) {
9549 window.location.href = url;
9550 }
9551 }
9552 };
9553 this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
9554 this.handleSegClick);
9555 }
9556 }
9557
9558 /*
9559 Triggers events and adds/removes core classNames when the user's pointer
9560 enters/leaves event-elements of a component.
9561 */
9562 class EventHovering extends Interaction {
9563 constructor(settings) {
9564 super(settings);
9565 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
9566 this.handleEventElRemove = (el) => {
9567 if (el === this.currentSegEl) {
9568 this.handleSegLeave(null, this.currentSegEl);
9569 }
9570 };
9571 this.handleSegEnter = (ev, segEl) => {
9572 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
9573 this.currentSegEl = segEl;
9574 this.triggerEvent('eventMouseEnter', ev, segEl);
9575 }
9576 };
9577 this.handleSegLeave = (ev, segEl) => {
9578 if (this.currentSegEl) {
9579 this.currentSegEl = null;
9580 this.triggerEvent('eventMouseLeave', ev, segEl);
9581 }
9582 };
9583 this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
9584 this.handleSegEnter, this.handleSegLeave);
9585 }
9586 destroy() {
9587 this.removeHoverListeners();
9588 }
9589 triggerEvent(publicEvName, ev, segEl) {
9590 let { component } = this;
9591 let { context } = component;
9592 let seg = getElSeg(segEl);
9593 if (!ev || component.isValidSegDownEl(ev.target)) {
9594 context.emitter.trigger(publicEvName, {
9595 el: segEl,
9596 event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
9597 jsEvent: ev,
9598 view: context.viewApi,
9599 });
9600 }
9601 }
9602 }
9603
9604 class CalendarContent extends PureComponent {
9605 constructor() {
9606 super(...arguments);
9607 this.buildViewContext = memoize(buildViewContext);
9608 this.buildViewPropTransformers = memoize(buildViewPropTransformers);
9609 this.buildToolbarProps = memoize(buildToolbarProps);
9610 this.headerRef = d();
9611 this.footerRef = d();
9612 this.interactionsStore = {};
9613 // eslint-disable-next-line
9614 this.state = {
9615 viewLabelId: getUniqueDomId(),
9616 };
9617 // Component Registration
9618 // -----------------------------------------------------------------------------------------------------------------
9619 this.registerInteractiveComponent = (component, settingsInput) => {
9620 let settings = parseInteractionSettings(component, settingsInput);
9621 let DEFAULT_INTERACTIONS = [
9622 EventClicking,
9623 EventHovering,
9624 ];
9625 let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
9626 let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
9627 this.interactionsStore[component.uid] = interactions;
9628 interactionSettingsStore[component.uid] = settings;
9629 };
9630 this.unregisterInteractiveComponent = (component) => {
9631 let listeners = this.interactionsStore[component.uid];
9632 if (listeners) {
9633 for (let listener of listeners) {
9634 listener.destroy();
9635 }
9636 delete this.interactionsStore[component.uid];
9637 }
9638 delete interactionSettingsStore[component.uid];
9639 };
9640 // Resizing
9641 // -----------------------------------------------------------------------------------------------------------------
9642 this.resizeRunner = new DelayedRunner(() => {
9643 this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
9644 this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
9645 });
9646 this.handleWindowResize = (ev) => {
9647 let { options } = this.props;
9648 if (options.handleWindowResize &&
9649 ev.target === window // avoid jqui events
9650 ) {
9651 this.resizeRunner.request(options.windowResizeDelay);
9652 }
9653 };
9654 }
9655 /*
9656 renders INSIDE of an outer div
9657 */
9658 render() {
9659 let { props } = this;
9660 let { toolbarConfig, options } = props;
9661 let viewVGrow = false;
9662 let viewHeight = '';
9663 let viewAspectRatio;
9664 if (props.isHeightAuto || props.forPrint) {
9665 viewHeight = '';
9666 }
9667 else if (options.height != null) {
9668 viewVGrow = true;
9669 }
9670 else if (options.contentHeight != null) {
9671 viewHeight = options.contentHeight;
9672 }
9673 else {
9674 viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
9675 }
9676 let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.nowManager, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
9677 let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
9678 ? this.state.viewLabelId
9679 : undefined;
9680 return (y(ViewContextType.Provider, { value: viewContext },
9681 y(NowTimer, { unit: "day" }, (nowDate) => {
9682 let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, nowDate, props.viewTitle);
9683 return (y(_, null,
9684 toolbarConfig.header && (y(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
9685 y(ViewHarness, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
9686 this.renderView(props),
9687 this.buildAppendContent()),
9688 toolbarConfig.footer && (y(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
9689 })));
9690 }
9691 componentDidMount() {
9692 let { props } = this;
9693 this.calendarInteractions = props.pluginHooks.calendarInteractions
9694 .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
9695 window.addEventListener('resize', this.handleWindowResize);
9696 let { propSetHandlers } = props.pluginHooks;
9697 for (let propName in propSetHandlers) {
9698 propSetHandlers[propName](props[propName], props);
9699 }
9700 }
9701 componentDidUpdate(prevProps) {
9702 let { props } = this;
9703 let { propSetHandlers } = props.pluginHooks;
9704 for (let propName in propSetHandlers) {
9705 if (props[propName] !== prevProps[propName]) {
9706 propSetHandlers[propName](props[propName], props);
9707 }
9708 }
9709 }
9710 componentWillUnmount() {
9711 window.removeEventListener('resize', this.handleWindowResize);
9712 this.resizeRunner.clear();
9713 for (let interaction of this.calendarInteractions) {
9714 interaction.destroy();
9715 }
9716 this.props.emitter.trigger('_unmount');
9717 }
9718 buildAppendContent() {
9719 let { props } = this;
9720 let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
9721 return y(_, {}, ...children);
9722 }
9723 renderView(props) {
9724 let { pluginHooks } = props;
9725 let { viewSpec } = props;
9726 let viewProps = {
9727 dateProfile: props.dateProfile,
9728 businessHours: props.businessHours,
9729 eventStore: props.renderableEventStore,
9730 eventUiBases: props.eventUiBases,
9731 dateSelection: props.dateSelection,
9732 eventSelection: props.eventSelection,
9733 eventDrag: props.eventDrag,
9734 eventResize: props.eventResize,
9735 isHeightAuto: props.isHeightAuto,
9736 forPrint: props.forPrint,
9737 };
9738 let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
9739 for (let transformer of transformers) {
9740 Object.assign(viewProps, transformer.transform(viewProps, props));
9741 }
9742 let ViewComponent = viewSpec.component;
9743 return (y(ViewComponent, Object.assign({}, viewProps)));
9744 }
9745 }
9746 function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
9747 // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
9748 let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
9749 let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
9750 let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
9751 return {
9752 title,
9753 activeButton: viewSpec.type,
9754 navUnit: viewSpec.singleUnit,
9755 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
9756 isPrevEnabled: prevInfo.isValid,
9757 isNextEnabled: nextInfo.isValid,
9758 };
9759 }
9760 // Plugin
9761 // -----------------------------------------------------------------------------------------------------------------
9762 function buildViewPropTransformers(theClasses) {
9763 return theClasses.map((TheClass) => new TheClass());
9764 }
9765
9766 class Calendar extends CalendarImpl {
9767 constructor(el, optionOverrides = {}) {
9768 super();
9769 this.isRendering = false;
9770 this.isRendered = false;
9771 this.currentClassNames = [];
9772 this.customContentRenderId = 0;
9773 this.handleAction = (action) => {
9774 // actions we know we want to render immediately
9775 switch (action.type) {
9776 case 'SET_EVENT_DRAG':
9777 case 'SET_EVENT_RESIZE':
9778 this.renderRunner.tryDrain();
9779 }
9780 };
9781 this.handleData = (data) => {
9782 this.currentData = data;
9783 this.renderRunner.request(data.calendarOptions.rerenderDelay);
9784 };
9785 this.handleRenderRequest = () => {
9786 if (this.isRendering) {
9787 this.isRendered = true;
9788 let { currentData } = this;
9789 flushSync(() => {
9790 D$1(y(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
9791 this.setClassNames(classNames);
9792 this.setHeight(height);
9793 return (y(RenderId.Provider, { value: this.customContentRenderId },
9794 y(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
9795 }), this.el);
9796 });
9797 }
9798 else if (this.isRendered) {
9799 this.isRendered = false;
9800 D$1(null, this.el);
9801 this.setClassNames([]);
9802 this.setHeight('');
9803 }
9804 };
9805 ensureElHasStyles(el);
9806 this.el = el;
9807 this.renderRunner = new DelayedRunner(this.handleRenderRequest);
9808 new CalendarDataManager({
9809 optionOverrides,
9810 calendarApi: this,
9811 onAction: this.handleAction,
9812 onData: this.handleData,
9813 });
9814 }
9815 render() {
9816 let wasRendering = this.isRendering;
9817 if (!wasRendering) {
9818 this.isRendering = true;
9819 }
9820 else {
9821 this.customContentRenderId += 1;
9822 }
9823 this.renderRunner.request();
9824 if (wasRendering) {
9825 this.updateSize();
9826 }
9827 }
9828 destroy() {
9829 if (this.isRendering) {
9830 this.isRendering = false;
9831 this.renderRunner.request();
9832 }
9833 }
9834 updateSize() {
9835 flushSync(() => {
9836 super.updateSize();
9837 });
9838 }
9839 batchRendering(func) {
9840 this.renderRunner.pause('batchRendering');
9841 func();
9842 this.renderRunner.resume('batchRendering');
9843 }
9844 pauseRendering() {
9845 this.renderRunner.pause('pauseRendering');
9846 }
9847 resumeRendering() {
9848 this.renderRunner.resume('pauseRendering', true);
9849 }
9850 resetOptions(optionOverrides, changedOptionNames) {
9851 this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);
9852 }
9853 setClassNames(classNames) {
9854 if (!isArraysEqual(classNames, this.currentClassNames)) {
9855 let { classList } = this.el;
9856 for (let className of this.currentClassNames) {
9857 classList.remove(className);
9858 }
9859 for (let className of classNames) {
9860 classList.add(className);
9861 }
9862 this.currentClassNames = classNames;
9863 }
9864 }
9865 setHeight(height) {
9866 applyStyleProp(this.el, 'height', height);
9867 }
9868 }
9869
9870 function formatDate(dateInput, options = {}) {
9871 let dateEnv = buildDateEnv(options);
9872 let formatter = createFormatter(options);
9873 let dateMeta = dateEnv.createMarkerMeta(dateInput);
9874 if (!dateMeta) { // TODO: warning?
9875 return '';
9876 }
9877 return dateEnv.format(dateMeta.marker, formatter, {
9878 forcedTzo: dateMeta.forcedTzo,
9879 });
9880 }
9881 function formatRange(startInput, endInput, options) {
9882 let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
9883 let formatter = createFormatter(options);
9884 let startMeta = dateEnv.createMarkerMeta(startInput);
9885 let endMeta = dateEnv.createMarkerMeta(endInput);
9886 if (!startMeta || !endMeta) { // TODO: warning?
9887 return '';
9888 }
9889 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
9890 forcedStartTzo: startMeta.forcedTzo,
9891 forcedEndTzo: endMeta.forcedTzo,
9892 isEndExclusive: options.isEndExclusive,
9893 defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
9894 });
9895 }
9896 // TODO: more DRY and optimized
9897 function buildDateEnv(settings) {
9898 let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
9899 return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
9900 }
9901
9902 // HELPERS
9903 /*
9904 if nextDayThreshold is specified, slicing is done in an all-day fashion.
9905 you can get nextDayThreshold from context.nextDayThreshold
9906 */
9907 function sliceEvents(props, allDay) {
9908 return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
9909 }
9910
9911 const version = '6.1.17';
9912
9913 config.touchMouseIgnoreWait = 500;
9914 let ignoreMouseDepth = 0;
9915 let listenerCnt = 0;
9916 let isWindowTouchMoveCancelled = false;
9917 /*
9918 Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
9919 Tracks when the pointer "drags" on a certain element, meaning down+move+up.
9920
9921 Also, tracks if there was touch-scrolling.
9922 Also, can prevent touch-scrolling from happening.
9923 Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
9924
9925 emits:
9926 - pointerdown
9927 - pointermove
9928 - pointerup
9929 */
9930 class PointerDragging {
9931 constructor(containerEl) {
9932 this.subjectEl = null;
9933 // options that can be directly assigned by caller
9934 this.selector = ''; // will cause subjectEl in all emitted events to be this element
9935 this.handleSelector = '';
9936 this.shouldIgnoreMove = false;
9937 this.shouldWatchScroll = true; // for simulating pointermove on scroll
9938 // internal states
9939 this.isDragging = false;
9940 this.isTouchDragging = false;
9941 this.wasTouchScroll = false;
9942 // Mouse
9943 // ----------------------------------------------------------------------------------------------------
9944 this.handleMouseDown = (ev) => {
9945 if (!this.shouldIgnoreMouse() &&
9946 isPrimaryMouseButton(ev) &&
9947 this.tryStart(ev)) {
9948 let pev = this.createEventFromMouse(ev, true);
9949 this.emitter.trigger('pointerdown', pev);
9950 this.initScrollWatch(pev);
9951 if (!this.shouldIgnoreMove) {
9952 document.addEventListener('mousemove', this.handleMouseMove);
9953 }
9954 document.addEventListener('mouseup', this.handleMouseUp);
9955 }
9956 };
9957 this.handleMouseMove = (ev) => {
9958 let pev = this.createEventFromMouse(ev);
9959 this.recordCoords(pev);
9960 this.emitter.trigger('pointermove', pev);
9961 };
9962 this.handleMouseUp = (ev) => {
9963 document.removeEventListener('mousemove', this.handleMouseMove);
9964 document.removeEventListener('mouseup', this.handleMouseUp);
9965 this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
9966 this.cleanup(); // call last so that pointerup has access to props
9967 };
9968 // Touch
9969 // ----------------------------------------------------------------------------------------------------
9970 this.handleTouchStart = (ev) => {
9971 if (this.tryStart(ev)) {
9972 this.isTouchDragging = true;
9973 let pev = this.createEventFromTouch(ev, true);
9974 this.emitter.trigger('pointerdown', pev);
9975 this.initScrollWatch(pev);
9976 // unlike mouse, need to attach to target, not document
9977 // https://stackoverflow.com/a/45760014
9978 let targetEl = ev.target;
9979 if (!this.shouldIgnoreMove) {
9980 targetEl.addEventListener('touchmove', this.handleTouchMove);
9981 }
9982 targetEl.addEventListener('touchend', this.handleTouchEnd);
9983 targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
9984 // attach a handler to get called when ANY scroll action happens on the page.
9985 // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
9986 // http://stackoverflow.com/a/32954565/96342
9987 window.addEventListener('scroll', this.handleTouchScroll, true);
9988 }
9989 };
9990 this.handleTouchMove = (ev) => {
9991 let pev = this.createEventFromTouch(ev);
9992 this.recordCoords(pev);
9993 this.emitter.trigger('pointermove', pev);
9994 };
9995 this.handleTouchEnd = (ev) => {
9996 if (this.isDragging) { // done to guard against touchend followed by touchcancel
9997 let targetEl = ev.target;
9998 targetEl.removeEventListener('touchmove', this.handleTouchMove);
9999 targetEl.removeEventListener('touchend', this.handleTouchEnd);
10000 targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
10001 window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
10002 this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
10003 this.cleanup(); // call last so that pointerup has access to props
10004 this.isTouchDragging = false;
10005 startIgnoringMouse();
10006 }
10007 };
10008 this.handleTouchScroll = () => {
10009 this.wasTouchScroll = true;
10010 };
10011 this.handleScroll = (ev) => {
10012 if (!this.shouldIgnoreMove) {
10013 let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX;
10014 let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY;
10015 this.emitter.trigger('pointermove', {
10016 origEvent: ev,
10017 isTouch: this.isTouchDragging,
10018 subjectEl: this.subjectEl,
10019 pageX,
10020 pageY,
10021 deltaX: pageX - this.origPageX,
10022 deltaY: pageY - this.origPageY,
10023 });
10024 }
10025 };
10026 this.containerEl = containerEl;
10027 this.emitter = new Emitter();
10028 containerEl.addEventListener('mousedown', this.handleMouseDown);
10029 containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
10030 listenerCreated();
10031 }
10032 destroy() {
10033 this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
10034 this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
10035 listenerDestroyed();
10036 }
10037 tryStart(ev) {
10038 let subjectEl = this.querySubjectEl(ev);
10039 let downEl = ev.target;
10040 if (subjectEl &&
10041 (!this.handleSelector || elementClosest(downEl, this.handleSelector))) {
10042 this.subjectEl = subjectEl;
10043 this.isDragging = true; // do this first so cancelTouchScroll will work
10044 this.wasTouchScroll = false;
10045 return true;
10046 }
10047 return false;
10048 }
10049 cleanup() {
10050 isWindowTouchMoveCancelled = false;
10051 this.isDragging = false;
10052 this.subjectEl = null;
10053 // keep wasTouchScroll around for later access
10054 this.destroyScrollWatch();
10055 }
10056 querySubjectEl(ev) {
10057 if (this.selector) {
10058 return elementClosest(ev.target, this.selector);
10059 }
10060 return this.containerEl;
10061 }
10062 shouldIgnoreMouse() {
10063 return ignoreMouseDepth || this.isTouchDragging;
10064 }
10065 // can be called by user of this class, to cancel touch-based scrolling for the current drag
10066 cancelTouchScroll() {
10067 if (this.isDragging) {
10068 isWindowTouchMoveCancelled = true;
10069 }
10070 }
10071 // Scrolling that simulates pointermoves
10072 // ----------------------------------------------------------------------------------------------------
10073 initScrollWatch(ev) {
10074 if (this.shouldWatchScroll) {
10075 this.recordCoords(ev);
10076 window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
10077 }
10078 }
10079 recordCoords(ev) {
10080 if (this.shouldWatchScroll) {
10081 this.prevPageX = ev.pageX;
10082 this.prevPageY = ev.pageY;
10083 this.prevScrollX = window.scrollX;
10084 this.prevScrollY = window.scrollY;
10085 }
10086 }
10087 destroyScrollWatch() {
10088 if (this.shouldWatchScroll) {
10089 window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
10090 }
10091 }
10092 // Event Normalization
10093 // ----------------------------------------------------------------------------------------------------
10094 createEventFromMouse(ev, isFirst) {
10095 let deltaX = 0;
10096 let deltaY = 0;
10097 // TODO: repeat code
10098 if (isFirst) {
10099 this.origPageX = ev.pageX;
10100 this.origPageY = ev.pageY;
10101 }
10102 else {
10103 deltaX = ev.pageX - this.origPageX;
10104 deltaY = ev.pageY - this.origPageY;
10105 }
10106 return {
10107 origEvent: ev,
10108 isTouch: false,
10109 subjectEl: this.subjectEl,
10110 pageX: ev.pageX,
10111 pageY: ev.pageY,
10112 deltaX,
10113 deltaY,
10114 };
10115 }
10116 createEventFromTouch(ev, isFirst) {
10117 let touches = ev.touches;
10118 let pageX;
10119 let pageY;
10120 let deltaX = 0;
10121 let deltaY = 0;
10122 // if touch coords available, prefer,
10123 // because FF would give bad ev.pageX ev.pageY
10124 if (touches && touches.length) {
10125 pageX = touches[0].pageX;
10126 pageY = touches[0].pageY;
10127 }
10128 else {
10129 pageX = ev.pageX;
10130 pageY = ev.pageY;
10131 }
10132 // TODO: repeat code
10133 if (isFirst) {
10134 this.origPageX = pageX;
10135 this.origPageY = pageY;
10136 }
10137 else {
10138 deltaX = pageX - this.origPageX;
10139 deltaY = pageY - this.origPageY;
10140 }
10141 return {
10142 origEvent: ev,
10143 isTouch: true,
10144 subjectEl: this.subjectEl,
10145 pageX,
10146 pageY,
10147 deltaX,
10148 deltaY,
10149 };
10150 }
10151 }
10152 // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
10153 function isPrimaryMouseButton(ev) {
10154 return ev.button === 0 && !ev.ctrlKey;
10155 }
10156 // Ignoring fake mouse events generated by touch
10157 // ----------------------------------------------------------------------------------------------------
10158 function startIgnoringMouse() {
10159 ignoreMouseDepth += 1;
10160 setTimeout(() => {
10161 ignoreMouseDepth -= 1;
10162 }, config.touchMouseIgnoreWait);
10163 }
10164 // We want to attach touchmove as early as possible for Safari
10165 // ----------------------------------------------------------------------------------------------------
10166 function listenerCreated() {
10167 listenerCnt += 1;
10168 if (listenerCnt === 1) {
10169 window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
10170 }
10171 }
10172 function listenerDestroyed() {
10173 listenerCnt -= 1;
10174 if (!listenerCnt) {
10175 window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
10176 }
10177 }
10178 function onWindowTouchMove(ev) {
10179 if (isWindowTouchMoveCancelled) {
10180 ev.preventDefault();
10181 }
10182 }
10183
10184 /*
10185 An effect in which an element follows the movement of a pointer across the screen.
10186 The moving element is a clone of some other element.
10187 Must call start + handleMove + stop.
10188 */
10189 class ElementMirror {
10190 constructor() {
10191 this.isVisible = false; // must be explicitly enabled
10192 this.sourceEl = null;
10193 this.mirrorEl = null;
10194 this.sourceElRect = null; // screen coords relative to viewport
10195 // options that can be set directly by caller
10196 this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
10197 this.zIndex = 9999;
10198 this.revertDuration = 0;
10199 }
10200 start(sourceEl, pageX, pageY) {
10201 this.sourceEl = sourceEl;
10202 this.sourceElRect = this.sourceEl.getBoundingClientRect();
10203 this.origScreenX = pageX - window.scrollX;
10204 this.origScreenY = pageY - window.scrollY;
10205 this.deltaX = 0;
10206 this.deltaY = 0;
10207 this.updateElPosition();
10208 }
10209 handleMove(pageX, pageY) {
10210 this.deltaX = (pageX - window.scrollX) - this.origScreenX;
10211 this.deltaY = (pageY - window.scrollY) - this.origScreenY;
10212 this.updateElPosition();
10213 }
10214 // can be called before start
10215 setIsVisible(bool) {
10216 if (bool) {
10217 if (!this.isVisible) {
10218 if (this.mirrorEl) {
10219 this.mirrorEl.style.display = '';
10220 }
10221 this.isVisible = bool; // needs to happen before updateElPosition
10222 this.updateElPosition(); // because was not updating the position while invisible
10223 }
10224 }
10225 else if (this.isVisible) {
10226 if (this.mirrorEl) {
10227 this.mirrorEl.style.display = 'none';
10228 }
10229 this.isVisible = bool;
10230 }
10231 }
10232 // always async
10233 stop(needsRevertAnimation, callback) {
10234 let done = () => {
10235 this.cleanup();
10236 callback();
10237 };
10238 if (needsRevertAnimation &&
10239 this.mirrorEl &&
10240 this.isVisible &&
10241 this.revertDuration && // if 0, transition won't work
10242 (this.deltaX || this.deltaY) // if same coords, transition won't work
10243 ) {
10244 this.doRevertAnimation(done, this.revertDuration);
10245 }
10246 else {
10247 setTimeout(done, 0);
10248 }
10249 }
10250 doRevertAnimation(callback, revertDuration) {
10251 let mirrorEl = this.mirrorEl;
10252 let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
10253 mirrorEl.style.transition =
10254 'top ' + revertDuration + 'ms,' +
10255 'left ' + revertDuration + 'ms';
10256 applyStyle(mirrorEl, {
10257 left: finalSourceElRect.left,
10258 top: finalSourceElRect.top,
10259 });
10260 whenTransitionDone(mirrorEl, () => {
10261 mirrorEl.style.transition = '';
10262 callback();
10263 });
10264 }
10265 cleanup() {
10266 if (this.mirrorEl) {
10267 removeElement(this.mirrorEl);
10268 this.mirrorEl = null;
10269 }
10270 this.sourceEl = null;
10271 }
10272 updateElPosition() {
10273 if (this.sourceEl && this.isVisible) {
10274 applyStyle(this.getMirrorEl(), {
10275 left: this.sourceElRect.left + this.deltaX,
10276 top: this.sourceElRect.top + this.deltaY,
10277 });
10278 }
10279 }
10280 getMirrorEl() {
10281 let sourceElRect = this.sourceElRect;
10282 let mirrorEl = this.mirrorEl;
10283 if (!mirrorEl) {
10284 mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
10285 // we don't want long taps or any mouse interaction causing selection/menus.
10286 // would use preventSelection(), but that prevents selectstart, causing problems.
10287 mirrorEl.style.userSelect = 'none';
10288 mirrorEl.style.webkitUserSelect = 'none';
10289 mirrorEl.style.pointerEvents = 'none';
10290 mirrorEl.classList.add('fc-event-dragging');
10291 applyStyle(mirrorEl, {
10292 position: 'fixed',
10293 zIndex: this.zIndex,
10294 visibility: '',
10295 boxSizing: 'border-box',
10296 width: sourceElRect.right - sourceElRect.left,
10297 height: sourceElRect.bottom - sourceElRect.top,
10298 right: 'auto',
10299 bottom: 'auto',
10300 margin: 0,
10301 });
10302 this.parentNode.appendChild(mirrorEl);
10303 }
10304 return mirrorEl;
10305 }
10306 }
10307
10308 /*
10309 Is a cache for a given element's scroll information (all the info that ScrollController stores)
10310 in addition the "client rectangle" of the element.. the area within the scrollbars.
10311
10312 The cache can be in one of two modes:
10313 - doesListening:false - ignores when the container is scrolled by someone else
10314 - doesListening:true - watch for scrolling and update the cache
10315 */
10316 class ScrollGeomCache extends ScrollController {
10317 constructor(scrollController, doesListening) {
10318 super();
10319 this.handleScroll = () => {
10320 this.scrollTop = this.scrollController.getScrollTop();
10321 this.scrollLeft = this.scrollController.getScrollLeft();
10322 this.handleScrollChange();
10323 };
10324 this.scrollController = scrollController;
10325 this.doesListening = doesListening;
10326 this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
10327 this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
10328 this.scrollWidth = scrollController.getScrollWidth();
10329 this.scrollHeight = scrollController.getScrollHeight();
10330 this.clientWidth = scrollController.getClientWidth();
10331 this.clientHeight = scrollController.getClientHeight();
10332 this.clientRect = this.computeClientRect(); // do last in case it needs cached values
10333 if (this.doesListening) {
10334 this.getEventTarget().addEventListener('scroll', this.handleScroll);
10335 }
10336 }
10337 destroy() {
10338 if (this.doesListening) {
10339 this.getEventTarget().removeEventListener('scroll', this.handleScroll);
10340 }
10341 }
10342 getScrollTop() {
10343 return this.scrollTop;
10344 }
10345 getScrollLeft() {
10346 return this.scrollLeft;
10347 }
10348 setScrollTop(top) {
10349 this.scrollController.setScrollTop(top);
10350 if (!this.doesListening) {
10351 // we are not relying on the element to normalize out-of-bounds scroll values
10352 // so we need to sanitize ourselves
10353 this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
10354 this.handleScrollChange();
10355 }
10356 }
10357 setScrollLeft(top) {
10358 this.scrollController.setScrollLeft(top);
10359 if (!this.doesListening) {
10360 // we are not relying on the element to normalize out-of-bounds scroll values
10361 // so we need to sanitize ourselves
10362 this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
10363 this.handleScrollChange();
10364 }
10365 }
10366 getClientWidth() {
10367 return this.clientWidth;
10368 }
10369 getClientHeight() {
10370 return this.clientHeight;
10371 }
10372 getScrollWidth() {
10373 return this.scrollWidth;
10374 }
10375 getScrollHeight() {
10376 return this.scrollHeight;
10377 }
10378 handleScrollChange() {
10379 }
10380 }
10381
10382 class ElementScrollGeomCache extends ScrollGeomCache {
10383 constructor(el, doesListening) {
10384 super(new ElementScrollController(el), doesListening);
10385 }
10386 getEventTarget() {
10387 return this.scrollController.el;
10388 }
10389 computeClientRect() {
10390 return computeInnerRect(this.scrollController.el);
10391 }
10392 }
10393
10394 class WindowScrollGeomCache extends ScrollGeomCache {
10395 constructor(doesListening) {
10396 super(new WindowScrollController(), doesListening);
10397 }
10398 getEventTarget() {
10399 return window;
10400 }
10401 computeClientRect() {
10402 return {
10403 left: this.scrollLeft,
10404 right: this.scrollLeft + this.clientWidth,
10405 top: this.scrollTop,
10406 bottom: this.scrollTop + this.clientHeight,
10407 };
10408 }
10409 // the window is the only scroll object that changes it's rectangle relative
10410 // to the document's topleft as it scrolls
10411 handleScrollChange() {
10412 this.clientRect = this.computeClientRect();
10413 }
10414 }
10415
10416 // If available we are using native "performance" API instead of "Date"
10417 // Read more about it on MDN:
10418 // https://developer.mozilla.org/en-US/docs/Web/API/Performance
10419 const getTime = typeof performance === 'function' ? performance.now : Date.now;
10420 /*
10421 For a pointer interaction, automatically scrolls certain scroll containers when the pointer
10422 approaches the edge.
10423
10424 The caller must call start + handleMove + stop.
10425 */
10426 class AutoScroller {
10427 constructor() {
10428 // options that can be set by caller
10429 this.isEnabled = true;
10430 this.scrollQuery = [window, '.fc-scroller'];
10431 this.edgeThreshold = 50; // pixels
10432 this.maxVelocity = 300; // pixels per second
10433 // internal state
10434 this.pointerScreenX = null;
10435 this.pointerScreenY = null;
10436 this.isAnimating = false;
10437 this.scrollCaches = null;
10438 // protect against the initial pointerdown being too close to an edge and starting the scroll
10439 this.everMovedUp = false;
10440 this.everMovedDown = false;
10441 this.everMovedLeft = false;
10442 this.everMovedRight = false;
10443 this.animate = () => {
10444 if (this.isAnimating) { // wasn't cancelled between animation calls
10445 let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY);
10446 if (edge) {
10447 let now = getTime();
10448 this.handleSide(edge, (now - this.msSinceRequest) / 1000);
10449 this.requestAnimation(now);
10450 }
10451 else {
10452 this.isAnimating = false; // will stop animation
10453 }
10454 }
10455 };
10456 }
10457 start(pageX, pageY, scrollStartEl) {
10458 if (this.isEnabled) {
10459 this.scrollCaches = this.buildCaches(scrollStartEl);
10460 this.pointerScreenX = null;
10461 this.pointerScreenY = null;
10462 this.everMovedUp = false;
10463 this.everMovedDown = false;
10464 this.everMovedLeft = false;
10465 this.everMovedRight = false;
10466 this.handleMove(pageX, pageY);
10467 }
10468 }
10469 handleMove(pageX, pageY) {
10470 if (this.isEnabled) {
10471 let pointerScreenX = pageX - window.scrollX;
10472 let pointerScreenY = pageY - window.scrollY;
10473 let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
10474 let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
10475 if (yDelta < 0) {
10476 this.everMovedUp = true;
10477 }
10478 else if (yDelta > 0) {
10479 this.everMovedDown = true;
10480 }
10481 if (xDelta < 0) {
10482 this.everMovedLeft = true;
10483 }
10484 else if (xDelta > 0) {
10485 this.everMovedRight = true;
10486 }
10487 this.pointerScreenX = pointerScreenX;
10488 this.pointerScreenY = pointerScreenY;
10489 if (!this.isAnimating) {
10490 this.isAnimating = true;
10491 this.requestAnimation(getTime());
10492 }
10493 }
10494 }
10495 stop() {
10496 if (this.isEnabled) {
10497 this.isAnimating = false; // will stop animation
10498 for (let scrollCache of this.scrollCaches) {
10499 scrollCache.destroy();
10500 }
10501 this.scrollCaches = null;
10502 }
10503 }
10504 requestAnimation(now) {
10505 this.msSinceRequest = now;
10506 requestAnimationFrame(this.animate);
10507 }
10508 handleSide(edge, seconds) {
10509 let { scrollCache } = edge;
10510 let { edgeThreshold } = this;
10511 let invDistance = edgeThreshold - edge.distance;
10512 let velocity = // the closer to the edge, the faster we scroll
10513 ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
10514 this.maxVelocity * seconds;
10515 let sign = 1;
10516 switch (edge.name) {
10517 case 'left':
10518 sign = -1;
10519 // falls through
10520 case 'right':
10521 scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
10522 break;
10523 case 'top':
10524 sign = -1;
10525 // falls through
10526 case 'bottom':
10527 scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
10528 break;
10529 }
10530 }
10531 // left/top are relative to document topleft
10532 computeBestEdge(left, top) {
10533 let { edgeThreshold } = this;
10534 let bestSide = null;
10535 let scrollCaches = this.scrollCaches || [];
10536 for (let scrollCache of scrollCaches) {
10537 let rect = scrollCache.clientRect;
10538 let leftDist = left - rect.left;
10539 let rightDist = rect.right - left;
10540 let topDist = top - rect.top;
10541 let bottomDist = rect.bottom - top;
10542 // completely within the rect?
10543 if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
10544 if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
10545 (!bestSide || bestSide.distance > topDist)) {
10546 bestSide = { scrollCache, name: 'top', distance: topDist };
10547 }
10548 if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
10549 (!bestSide || bestSide.distance > bottomDist)) {
10550 bestSide = { scrollCache, name: 'bottom', distance: bottomDist };
10551 }
10552 /*
10553 TODO: fix broken RTL scrolling. canScrollLeft always returning false
10554 https://github.com/fullcalendar/fullcalendar/issues/4837
10555 */
10556 if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
10557 (!bestSide || bestSide.distance > leftDist)) {
10558 bestSide = { scrollCache, name: 'left', distance: leftDist };
10559 }
10560 if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
10561 (!bestSide || bestSide.distance > rightDist)) {
10562 bestSide = { scrollCache, name: 'right', distance: rightDist };
10563 }
10564 }
10565 }
10566 return bestSide;
10567 }
10568 buildCaches(scrollStartEl) {
10569 return this.queryScrollEls(scrollStartEl).map((el) => {
10570 if (el === window) {
10571 return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
10572 }
10573 return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
10574 });
10575 }
10576 queryScrollEls(scrollStartEl) {
10577 let els = [];
10578 for (let query of this.scrollQuery) {
10579 if (typeof query === 'object') {
10580 els.push(query);
10581 }
10582 else {
10583 /*
10584 TODO: in the future, always have auto-scroll happen on element where current Hit came from
10585 Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593
10586 */
10587 els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query)));
10588 }
10589 }
10590 return els;
10591 }
10592 }
10593
10594 /*
10595 Monitors dragging on an element. Has a number of high-level features:
10596 - minimum distance required before dragging
10597 - minimum wait time ("delay") before dragging
10598 - a mirror element that follows the pointer
10599 */
10600 class FeaturefulElementDragging extends ElementDragging {
10601 constructor(containerEl, selector) {
10602 super(containerEl);
10603 this.containerEl = containerEl;
10604 // options that can be directly set by caller
10605 // the caller can also set the PointerDragging's options as well
10606 this.delay = null;
10607 this.minDistance = 0;
10608 this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
10609 this.mirrorNeedsRevert = false;
10610 this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
10611 this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
10612 this.isDelayEnded = false;
10613 this.isDistanceSurpassed = false;
10614 this.delayTimeoutId = null;
10615 this.onPointerDown = (ev) => {
10616 if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
10617 this.isInteracting = true;
10618 this.isDelayEnded = false;
10619 this.isDistanceSurpassed = false;
10620 preventSelection(document.body);
10621 preventContextMenu(document.body);
10622 // prevent links from being visited if there's an eventual drag.
10623 // also prevents selection in older browsers (maybe?).
10624 // not necessary for touch, besides, browser would complain about passiveness.
10625 if (!ev.isTouch) {
10626 ev.origEvent.preventDefault();
10627 }
10628 this.emitter.trigger('pointerdown', ev);
10629 if (this.isInteracting && // not destroyed via pointerdown handler
10630 !this.pointer.shouldIgnoreMove) {
10631 // actions related to initiating dragstart+dragmove+dragend...
10632 this.mirror.setIsVisible(false); // reset. caller must set-visible
10633 this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
10634 this.startDelay(ev);
10635 if (!this.minDistance) {
10636 this.handleDistanceSurpassed(ev);
10637 }
10638 }
10639 }
10640 };
10641 this.onPointerMove = (ev) => {
10642 if (this.isInteracting) {
10643 this.emitter.trigger('pointermove', ev);
10644 if (!this.isDistanceSurpassed) {
10645 let minDistance = this.minDistance;
10646 let distanceSq; // current distance from the origin, squared
10647 let { deltaX, deltaY } = ev;
10648 distanceSq = deltaX * deltaX + deltaY * deltaY;
10649 if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
10650 this.handleDistanceSurpassed(ev);
10651 }
10652 }
10653 if (this.isDragging) {
10654 // a real pointer move? (not one simulated by scrolling)
10655 if (ev.origEvent.type !== 'scroll') {
10656 this.mirror.handleMove(ev.pageX, ev.pageY);
10657 this.autoScroller.handleMove(ev.pageX, ev.pageY);
10658 }
10659 this.emitter.trigger('dragmove', ev);
10660 }
10661 }
10662 };
10663 this.onPointerUp = (ev) => {
10664 if (this.isInteracting) {
10665 this.isInteracting = false;
10666 allowSelection(document.body);
10667 allowContextMenu(document.body);
10668 this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
10669 if (this.isDragging) {
10670 this.autoScroller.stop();
10671 this.tryStopDrag(ev); // which will stop the mirror
10672 }
10673 if (this.delayTimeoutId) {
10674 clearTimeout(this.delayTimeoutId);
10675 this.delayTimeoutId = null;
10676 }
10677 }
10678 };
10679 let pointer = this.pointer = new PointerDragging(containerEl);
10680 pointer.emitter.on('pointerdown', this.onPointerDown);
10681 pointer.emitter.on('pointermove', this.onPointerMove);
10682 pointer.emitter.on('pointerup', this.onPointerUp);
10683 if (selector) {
10684 pointer.selector = selector;
10685 }
10686 this.mirror = new ElementMirror();
10687 this.autoScroller = new AutoScroller();
10688 }
10689 destroy() {
10690 this.pointer.destroy();
10691 // HACK: simulate a pointer-up to end the current drag
10692 // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
10693 this.onPointerUp({});
10694 }
10695 startDelay(ev) {
10696 if (typeof this.delay === 'number') {
10697 this.delayTimeoutId = setTimeout(() => {
10698 this.delayTimeoutId = null;
10699 this.handleDelayEnd(ev);
10700 }, this.delay); // not assignable to number!
10701 }
10702 else {
10703 this.handleDelayEnd(ev);
10704 }
10705 }
10706 handleDelayEnd(ev) {
10707 this.isDelayEnded = true;
10708 this.tryStartDrag(ev);
10709 }
10710 handleDistanceSurpassed(ev) {
10711 this.isDistanceSurpassed = true;
10712 this.tryStartDrag(ev);
10713 }
10714 tryStartDrag(ev) {
10715 if (this.isDelayEnded && this.isDistanceSurpassed) {
10716 if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
10717 this.isDragging = true;
10718 this.mirrorNeedsRevert = false;
10719 this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
10720 this.emitter.trigger('dragstart', ev);
10721 if (this.touchScrollAllowed === false) {
10722 this.pointer.cancelTouchScroll();
10723 }
10724 }
10725 }
10726 }
10727 tryStopDrag(ev) {
10728 // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
10729 // that come from the document to fire beforehand. much more convenient this way.
10730 this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
10731 }
10732 stopDrag(ev) {
10733 this.isDragging = false;
10734 this.emitter.trigger('dragend', ev);
10735 }
10736 // fill in the implementations...
10737 setIgnoreMove(bool) {
10738 this.pointer.shouldIgnoreMove = bool;
10739 }
10740 setMirrorIsVisible(bool) {
10741 this.mirror.setIsVisible(bool);
10742 }
10743 setMirrorNeedsRevert(bool) {
10744 this.mirrorNeedsRevert = bool;
10745 }
10746 setAutoScrollEnabled(bool) {
10747 this.autoScroller.isEnabled = bool;
10748 }
10749 }
10750
10751 /*
10752 When this class is instantiated, it records the offset of an element (relative to the document topleft),
10753 and continues to monitor scrolling, updating the cached coordinates if it needs to.
10754 Does not access the DOM after instantiation, so highly performant.
10755
10756 Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
10757 and an determine if a given point is inside the combined clipping rectangle.
10758 */
10759 class OffsetTracker {
10760 constructor(el) {
10761 this.el = el;
10762 this.origRect = computeRect(el);
10763 // will work fine for divs that have overflow:hidden
10764 this.scrollCaches = getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
10765 }
10766 destroy() {
10767 for (let scrollCache of this.scrollCaches) {
10768 scrollCache.destroy();
10769 }
10770 }
10771 computeLeft() {
10772 let left = this.origRect.left;
10773 for (let scrollCache of this.scrollCaches) {
10774 left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
10775 }
10776 return left;
10777 }
10778 computeTop() {
10779 let top = this.origRect.top;
10780 for (let scrollCache of this.scrollCaches) {
10781 top += scrollCache.origScrollTop - scrollCache.getScrollTop();
10782 }
10783 return top;
10784 }
10785 isWithinClipping(pageX, pageY) {
10786 let point = { left: pageX, top: pageY };
10787 for (let scrollCache of this.scrollCaches) {
10788 if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
10789 !pointInsideRect(point, scrollCache.clientRect)) {
10790 return false;
10791 }
10792 }
10793 return true;
10794 }
10795 }
10796 // certain clipping containers should never constrain interactions, like <html> and <body>
10797 // https://github.com/fullcalendar/fullcalendar/issues/3615
10798 function isIgnoredClipping(node) {
10799 let tagName = node.tagName;
10800 return tagName === 'HTML' || tagName === 'BODY';
10801 }
10802
10803 /*
10804 Tracks movement over multiple droppable areas (aka "hits")
10805 that exist in one or more DateComponents.
10806 Relies on an existing draggable.
10807
10808 emits:
10809 - pointerdown
10810 - dragstart
10811 - hitchange - fires initially, even if not over a hit
10812 - pointerup
10813 - (hitchange - again, to null, if ended over a hit)
10814 - dragend
10815 */
10816 class HitDragging {
10817 constructor(dragging, droppableStore) {
10818 // options that can be set by caller
10819 this.useSubjectCenter = false;
10820 this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
10821 this.disablePointCheck = false;
10822 this.initialHit = null;
10823 this.movingHit = null;
10824 this.finalHit = null; // won't ever be populated if shouldIgnoreMove
10825 this.handlePointerDown = (ev) => {
10826 let { dragging } = this;
10827 this.initialHit = null;
10828 this.movingHit = null;
10829 this.finalHit = null;
10830 this.prepareHits();
10831 this.processFirstCoord(ev);
10832 if (this.initialHit || !this.requireInitial) {
10833 dragging.setIgnoreMove(false);
10834 // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
10835 this.emitter.trigger('pointerdown', ev);
10836 }
10837 else {
10838 dragging.setIgnoreMove(true);
10839 }
10840 };
10841 this.handleDragStart = (ev) => {
10842 this.emitter.trigger('dragstart', ev);
10843 this.handleMove(ev, true); // force = fire even if initially null
10844 };
10845 this.handleDragMove = (ev) => {
10846 this.emitter.trigger('dragmove', ev);
10847 this.handleMove(ev);
10848 };
10849 this.handlePointerUp = (ev) => {
10850 this.releaseHits();
10851 this.emitter.trigger('pointerup', ev);
10852 };
10853 this.handleDragEnd = (ev) => {
10854 if (this.movingHit) {
10855 this.emitter.trigger('hitupdate', null, true, ev);
10856 }
10857 this.finalHit = this.movingHit;
10858 this.movingHit = null;
10859 this.emitter.trigger('dragend', ev);
10860 };
10861 this.droppableStore = droppableStore;
10862 dragging.emitter.on('pointerdown', this.handlePointerDown);
10863 dragging.emitter.on('dragstart', this.handleDragStart);
10864 dragging.emitter.on('dragmove', this.handleDragMove);
10865 dragging.emitter.on('pointerup', this.handlePointerUp);
10866 dragging.emitter.on('dragend', this.handleDragEnd);
10867 this.dragging = dragging;
10868 this.emitter = new Emitter();
10869 }
10870 // sets initialHit
10871 // sets coordAdjust
10872 processFirstCoord(ev) {
10873 let origPoint = { left: ev.pageX, top: ev.pageY };
10874 let adjustedPoint = origPoint;
10875 let subjectEl = ev.subjectEl;
10876 let subjectRect;
10877 if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
10878 subjectRect = computeRect(subjectEl);
10879 adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
10880 }
10881 let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
10882 if (initialHit) {
10883 if (this.useSubjectCenter && subjectRect) {
10884 let slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
10885 if (slicedSubjectRect) {
10886 adjustedPoint = getRectCenter(slicedSubjectRect);
10887 }
10888 }
10889 this.coordAdjust = diffPoints(adjustedPoint, origPoint);
10890 }
10891 else {
10892 this.coordAdjust = { left: 0, top: 0 };
10893 }
10894 }
10895 handleMove(ev, forceHandle) {
10896 let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
10897 if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
10898 this.movingHit = hit;
10899 this.emitter.trigger('hitupdate', hit, false, ev);
10900 }
10901 }
10902 prepareHits() {
10903 this.offsetTrackers = mapHash(this.droppableStore, (interactionSettings) => {
10904 interactionSettings.component.prepareHits();
10905 return new OffsetTracker(interactionSettings.el);
10906 });
10907 }
10908 releaseHits() {
10909 let { offsetTrackers } = this;
10910 for (let id in offsetTrackers) {
10911 offsetTrackers[id].destroy();
10912 }
10913 this.offsetTrackers = {};
10914 }
10915 queryHitForOffset(offsetLeft, offsetTop) {
10916 let { droppableStore, offsetTrackers } = this;
10917 let bestHit = null;
10918 for (let id in droppableStore) {
10919 let component = droppableStore[id].component;
10920 let offsetTracker = offsetTrackers[id];
10921 if (offsetTracker && // wasn't destroyed mid-drag
10922 offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
10923 let originLeft = offsetTracker.computeLeft();
10924 let originTop = offsetTracker.computeTop();
10925 let positionLeft = offsetLeft - originLeft;
10926 let positionTop = offsetTop - originTop;
10927 let { origRect } = offsetTracker;
10928 let width = origRect.right - origRect.left;
10929 let height = origRect.bottom - origRect.top;
10930 if (
10931 // must be within the element's bounds
10932 positionLeft >= 0 && positionLeft < width &&
10933 positionTop >= 0 && positionTop < height) {
10934 let hit = component.queryHit(positionLeft, positionTop, width, height);
10935 if (hit && (
10936 // make sure the hit is within activeRange, meaning it's not a dead cell
10937 rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
10938 // Ensure the component we are querying for the hit is accessibly my the pointer
10939 // Prevents obscured calendars (ex: under a modal dialog) from accepting hit
10940 // https://github.com/fullcalendar/fullcalendar/issues/5026
10941 (this.disablePointCheck ||
10942 offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint(
10943 // add-back origins to get coordinate relative to top-left of window viewport
10944 positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) &&
10945 (!bestHit || hit.layer > bestHit.layer)) {
10946 hit.componentId = id;
10947 hit.context = component.context;
10948 // TODO: better way to re-orient rectangle
10949 hit.rect.left += originLeft;
10950 hit.rect.right += originLeft;
10951 hit.rect.top += originTop;
10952 hit.rect.bottom += originTop;
10953 bestHit = hit;
10954 }
10955 }
10956 }
10957 }
10958 return bestHit;
10959 }
10960 }
10961 function isHitsEqual(hit0, hit1) {
10962 if (!hit0 && !hit1) {
10963 return true;
10964 }
10965 if (Boolean(hit0) !== Boolean(hit1)) {
10966 return false;
10967 }
10968 return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
10969 }
10970
10971 function buildDatePointApiWithContext(dateSpan, context) {
10972 let props = {};
10973 for (let transform of context.pluginHooks.datePointTransforms) {
10974 Object.assign(props, transform(dateSpan, context));
10975 }
10976 Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
10977 return props;
10978 }
10979 function buildDatePointApi(span, dateEnv) {
10980 return {
10981 date: dateEnv.toDate(span.range.start),
10982 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
10983 allDay: span.allDay,
10984 };
10985 }
10986
10987 /*
10988 Monitors when the user clicks on a specific date/time of a component.
10989 A pointerdown+pointerup on the same "hit" constitutes a click.
10990 */
10991 class DateClicking extends Interaction {
10992 constructor(settings) {
10993 super(settings);
10994 this.handlePointerDown = (pev) => {
10995 let { dragging } = this;
10996 let downEl = pev.origEvent.target;
10997 // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
10998 dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
10999 };
11000 // won't even fire if moving was ignored
11001 this.handleDragEnd = (ev) => {
11002 let { component } = this;
11003 let { pointer } = this.dragging;
11004 if (!pointer.wasTouchScroll) {
11005 let { initialHit, finalHit } = this.hitDragging;
11006 if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
11007 let { context } = component;
11008 let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });
11009 context.emitter.trigger('dateClick', arg);
11010 }
11011 }
11012 };
11013 // we DO want to watch pointer moves because otherwise finalHit won't get populated
11014 this.dragging = new FeaturefulElementDragging(settings.el);
11015 this.dragging.autoScroller.isEnabled = false;
11016 let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11017 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11018 hitDragging.emitter.on('dragend', this.handleDragEnd);
11019 }
11020 destroy() {
11021 this.dragging.destroy();
11022 }
11023 }
11024
11025 /*
11026 Tracks when the user selects a portion of time of a component,
11027 constituted by a drag over date cells, with a possible delay at the beginning of the drag.
11028 */
11029 class DateSelecting extends Interaction {
11030 constructor(settings) {
11031 super(settings);
11032 this.dragSelection = null;
11033 this.handlePointerDown = (ev) => {
11034 let { component, dragging } = this;
11035 let { options } = component.context;
11036 let canSelect = options.selectable &&
11037 component.isValidDateDownEl(ev.origEvent.target);
11038 // don't bother to watch expensive moves if component won't do selection
11039 dragging.setIgnoreMove(!canSelect);
11040 // if touch, require user to hold down
11041 dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
11042 };
11043 this.handleDragStart = (ev) => {
11044 this.component.context.calendarApi.unselect(ev); // unselect previous selections
11045 };
11046 this.handleHitUpdate = (hit, isFinal) => {
11047 let { context } = this.component;
11048 let dragSelection = null;
11049 let isInvalid = false;
11050 if (hit) {
11051 let initialHit = this.hitDragging.initialHit;
11052 let disallowed = hit.componentId === initialHit.componentId
11053 && this.isHitComboAllowed
11054 && !this.isHitComboAllowed(initialHit, hit);
11055 if (!disallowed) {
11056 dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
11057 }
11058 if (!dragSelection || !isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
11059 isInvalid = true;
11060 dragSelection = null;
11061 }
11062 }
11063 if (dragSelection) {
11064 context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
11065 }
11066 else if (!isFinal) { // only unselect if moved away while dragging
11067 context.dispatch({ type: 'UNSELECT_DATES' });
11068 }
11069 if (!isInvalid) {
11070 enableCursor();
11071 }
11072 else {
11073 disableCursor();
11074 }
11075 if (!isFinal) {
11076 this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
11077 }
11078 };
11079 this.handlePointerUp = (pev) => {
11080 if (this.dragSelection) {
11081 // selection is already rendered, so just need to report selection
11082 triggerDateSelect(this.dragSelection, pev, this.component.context);
11083 this.dragSelection = null;
11084 }
11085 };
11086 let { component } = settings;
11087 let { options } = component.context;
11088 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11089 dragging.touchScrollAllowed = false;
11090 dragging.minDistance = options.selectMinDistance || 0;
11091 dragging.autoScroller.isEnabled = options.dragScroll;
11092 let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11093 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11094 hitDragging.emitter.on('dragstart', this.handleDragStart);
11095 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11096 hitDragging.emitter.on('pointerup', this.handlePointerUp);
11097 }
11098 destroy() {
11099 this.dragging.destroy();
11100 }
11101 }
11102 function getComponentTouchDelay$1(component) {
11103 let { options } = component.context;
11104 let delay = options.selectLongPressDelay;
11105 if (delay == null) {
11106 delay = options.longPressDelay;
11107 }
11108 return delay;
11109 }
11110 function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
11111 let dateSpan0 = hit0.dateSpan;
11112 let dateSpan1 = hit1.dateSpan;
11113 let ms = [
11114 dateSpan0.range.start,
11115 dateSpan0.range.end,
11116 dateSpan1.range.start,
11117 dateSpan1.range.end,
11118 ];
11119 ms.sort(compareNumbers);
11120 let props = {};
11121 for (let transformer of dateSelectionTransformers) {
11122 let res = transformer(hit0, hit1);
11123 if (res === false) {
11124 return null;
11125 }
11126 if (res) {
11127 Object.assign(props, res);
11128 }
11129 }
11130 props.range = { start: ms[0], end: ms[3] };
11131 props.allDay = dateSpan0.allDay;
11132 return props;
11133 }
11134
11135 class EventDragging extends Interaction {
11136 constructor(settings) {
11137 super(settings);
11138 // internal state
11139 this.subjectEl = null;
11140 this.subjectSeg = null; // the seg being selected/dragged
11141 this.isDragging = false;
11142 this.eventRange = null;
11143 this.relevantEvents = null; // the events being dragged
11144 this.receivingContext = null;
11145 this.validMutation = null;
11146 this.mutatedRelevantEvents = null;
11147 this.handlePointerDown = (ev) => {
11148 let origTarget = ev.origEvent.target;
11149 let { component, dragging } = this;
11150 let { mirror } = dragging;
11151 let { options } = component.context;
11152 let initialContext = component.context;
11153 this.subjectEl = ev.subjectEl;
11154 let subjectSeg = this.subjectSeg = getElSeg(ev.subjectEl);
11155 let eventRange = this.eventRange = subjectSeg.eventRange;
11156 let eventInstanceId = eventRange.instance.instanceId;
11157 this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
11158 dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
11159 dragging.delay =
11160 // only do a touch delay if touch and this event hasn't been selected yet
11161 (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
11162 getComponentTouchDelay(component) :
11163 null;
11164 if (options.fixedMirrorParent) {
11165 mirror.parentNode = options.fixedMirrorParent;
11166 }
11167 else {
11168 mirror.parentNode = elementClosest(origTarget, '.fc');
11169 }
11170 mirror.revertDuration = options.dragRevertDuration;
11171 let isValid = component.isValidSegDownEl(origTarget) &&
11172 !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
11173 dragging.setIgnoreMove(!isValid);
11174 // disable dragging for elements that are resizable (ie, selectable)
11175 // but are not draggable
11176 this.isDragging = isValid &&
11177 ev.subjectEl.classList.contains('fc-event-draggable');
11178 };
11179 this.handleDragStart = (ev) => {
11180 let initialContext = this.component.context;
11181 let eventRange = this.eventRange;
11182 let eventInstanceId = eventRange.instance.instanceId;
11183 if (ev.isTouch) {
11184 // need to select a different event?
11185 if (eventInstanceId !== this.component.props.eventSelection) {
11186 initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });
11187 }
11188 }
11189 else {
11190 // if now using mouse, but was previous touch interaction, clear selected event
11191 initialContext.dispatch({ type: 'UNSELECT_EVENT' });
11192 }
11193 if (this.isDragging) {
11194 initialContext.calendarApi.unselect(ev); // unselect *date* selection
11195 initialContext.emitter.trigger('eventDragStart', {
11196 el: this.subjectEl,
11197 event: new EventImpl(initialContext, eventRange.def, eventRange.instance),
11198 jsEvent: ev.origEvent,
11199 view: initialContext.viewApi,
11200 });
11201 }
11202 };
11203 this.handleHitUpdate = (hit, isFinal) => {
11204 if (!this.isDragging) {
11205 return;
11206 }
11207 let relevantEvents = this.relevantEvents;
11208 let initialHit = this.hitDragging.initialHit;
11209 let initialContext = this.component.context;
11210 // states based on new hit
11211 let receivingContext = null;
11212 let mutation = null;
11213 let mutatedRelevantEvents = null;
11214 let isInvalid = false;
11215 let interaction = {
11216 affectedEvents: relevantEvents,
11217 mutatedEvents: createEmptyEventStore(),
11218 isEvent: true,
11219 };
11220 if (hit) {
11221 receivingContext = hit.context;
11222 let receivingOptions = receivingContext.options;
11223 if (initialContext === receivingContext ||
11224 (receivingOptions.editable && receivingOptions.droppable)) {
11225 mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
11226 if (mutation) {
11227 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
11228 interaction.mutatedEvents = mutatedRelevantEvents;
11229 if (!isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
11230 isInvalid = true;
11231 mutation = null;
11232 mutatedRelevantEvents = null;
11233 interaction.mutatedEvents = createEmptyEventStore();
11234 }
11235 }
11236 }
11237 else {
11238 receivingContext = null;
11239 }
11240 }
11241 this.displayDrag(receivingContext, interaction);
11242 if (!isInvalid) {
11243 enableCursor();
11244 }
11245 else {
11246 disableCursor();
11247 }
11248 if (!isFinal) {
11249 if (initialContext === receivingContext && // TODO: write test for this
11250 isHitsEqual(initialHit, hit)) {
11251 mutation = null;
11252 }
11253 this.dragging.setMirrorNeedsRevert(!mutation);
11254 // render the mirror if no already-rendered mirror
11255 // TODO: wish we could somehow wait for dispatch to guarantee render
11256 this.dragging.setMirrorIsVisible(!hit || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror'));
11257 // assign states based on new hit
11258 this.receivingContext = receivingContext;
11259 this.validMutation = mutation;
11260 this.mutatedRelevantEvents = mutatedRelevantEvents;
11261 }
11262 };
11263 this.handlePointerUp = () => {
11264 if (!this.isDragging) {
11265 this.cleanup(); // because handleDragEnd won't fire
11266 }
11267 };
11268 this.handleDragEnd = (ev) => {
11269 if (this.isDragging) {
11270 let initialContext = this.component.context;
11271 let initialView = initialContext.viewApi;
11272 let { receivingContext, validMutation } = this;
11273 let eventDef = this.eventRange.def;
11274 let eventInstance = this.eventRange.instance;
11275 let eventApi = new EventImpl(initialContext, eventDef, eventInstance);
11276 let relevantEvents = this.relevantEvents;
11277 let mutatedRelevantEvents = this.mutatedRelevantEvents;
11278 let { finalHit } = this.hitDragging;
11279 this.clearDrag(); // must happen after revert animation
11280 initialContext.emitter.trigger('eventDragStop', {
11281 el: this.subjectEl,
11282 event: eventApi,
11283 jsEvent: ev.origEvent,
11284 view: initialView,
11285 });
11286 if (validMutation) {
11287 // dropped within same calendar
11288 if (receivingContext === initialContext) {
11289 let updatedEventApi = new EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
11290 initialContext.dispatch({
11291 type: 'MERGE_EVENTS',
11292 eventStore: mutatedRelevantEvents,
11293 });
11294 let eventChangeArg = {
11295 oldEvent: eventApi,
11296 event: updatedEventApi,
11297 relatedEvents: buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
11298 revert() {
11299 initialContext.dispatch({
11300 type: 'MERGE_EVENTS',
11301 eventStore: relevantEvents, // the pre-change data
11302 });
11303 },
11304 };
11305 let transformed = {};
11306 for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
11307 Object.assign(transformed, transformer(validMutation, initialContext));
11308 }
11309 initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));
11310 initialContext.emitter.trigger('eventChange', eventChangeArg);
11311 // dropped in different calendar
11312 }
11313 else if (receivingContext) {
11314 let eventRemoveArg = {
11315 event: eventApi,
11316 relatedEvents: buildEventApis(relevantEvents, initialContext, eventInstance),
11317 revert() {
11318 initialContext.dispatch({
11319 type: 'MERGE_EVENTS',
11320 eventStore: relevantEvents,
11321 });
11322 },
11323 };
11324 initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));
11325 initialContext.dispatch({
11326 type: 'REMOVE_EVENTS',
11327 eventStore: relevantEvents,
11328 });
11329 initialContext.emitter.trigger('eventRemove', eventRemoveArg);
11330 let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
11331 let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
11332 let addedEventApi = new EventImpl(receivingContext, addedEventDef, addedEventInstance);
11333 receivingContext.dispatch({
11334 type: 'MERGE_EVENTS',
11335 eventStore: mutatedRelevantEvents,
11336 });
11337 let eventAddArg = {
11338 event: addedEventApi,
11339 relatedEvents: buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
11340 revert() {
11341 receivingContext.dispatch({
11342 type: 'REMOVE_EVENTS',
11343 eventStore: mutatedRelevantEvents,
11344 });
11345 },
11346 };
11347 receivingContext.emitter.trigger('eventAdd', eventAddArg);
11348 if (ev.isTouch) {
11349 receivingContext.dispatch({
11350 type: 'SELECT_EVENT',
11351 eventInstanceId: eventInstance.instanceId,
11352 });
11353 }
11354 receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));
11355 receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));
11356 }
11357 }
11358 else {
11359 initialContext.emitter.trigger('_noEventDrop');
11360 }
11361 }
11362 this.cleanup();
11363 };
11364 let { component } = this;
11365 let { options } = component.context;
11366 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11367 dragging.pointer.selector = EventDragging.SELECTOR;
11368 dragging.touchScrollAllowed = false;
11369 dragging.autoScroller.isEnabled = options.dragScroll;
11370 let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsStore);
11371 hitDragging.useSubjectCenter = settings.useEventCenter;
11372 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11373 hitDragging.emitter.on('dragstart', this.handleDragStart);
11374 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11375 hitDragging.emitter.on('pointerup', this.handlePointerUp);
11376 hitDragging.emitter.on('dragend', this.handleDragEnd);
11377 }
11378 destroy() {
11379 this.dragging.destroy();
11380 }
11381 // render a drag state on the next receivingCalendar
11382 displayDrag(nextContext, state) {
11383 let initialContext = this.component.context;
11384 let prevContext = this.receivingContext;
11385 // does the previous calendar need to be cleared?
11386 if (prevContext && prevContext !== nextContext) {
11387 // does the initial calendar need to be cleared?
11388 // if so, don't clear all the way. we still need to to hide the affectedEvents
11389 if (prevContext === initialContext) {
11390 prevContext.dispatch({
11391 type: 'SET_EVENT_DRAG',
11392 state: {
11393 affectedEvents: state.affectedEvents,
11394 mutatedEvents: createEmptyEventStore(),
11395 isEvent: true,
11396 },
11397 });
11398 // completely clear the old calendar if it wasn't the initial
11399 }
11400 else {
11401 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11402 }
11403 }
11404 if (nextContext) {
11405 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11406 }
11407 }
11408 clearDrag() {
11409 let initialCalendar = this.component.context;
11410 let { receivingContext } = this;
11411 if (receivingContext) {
11412 receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11413 }
11414 // the initial calendar might have an dummy drag state from displayDrag
11415 if (initialCalendar !== receivingContext) {
11416 initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
11417 }
11418 }
11419 cleanup() {
11420 this.subjectSeg = null;
11421 this.isDragging = false;
11422 this.eventRange = null;
11423 this.relevantEvents = null;
11424 this.receivingContext = null;
11425 this.validMutation = null;
11426 this.mutatedRelevantEvents = null;
11427 }
11428 }
11429 // TODO: test this in IE11
11430 // QUESTION: why do we need it on the resizable???
11431 EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';
11432 function computeEventMutation(hit0, hit1, eventInstanceStart, massagers) {
11433 let dateSpan0 = hit0.dateSpan;
11434 let dateSpan1 = hit1.dateSpan;
11435 let date0 = dateSpan0.range.start;
11436 let date1 = dateSpan1.range.start;
11437 let standardProps = {};
11438 if (dateSpan0.allDay !== dateSpan1.allDay) {
11439 standardProps.allDay = dateSpan1.allDay;
11440 standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
11441 if (dateSpan1.allDay) {
11442 // means date1 is already start-of-day,
11443 // but date0 needs to be converted
11444 date0 = startOfDay(eventInstanceStart);
11445 }
11446 else {
11447 // Moving from allDate->timed
11448 // Doesn't matter where on the event the drag began, mutate the event's start-date to date1
11449 date0 = eventInstanceStart;
11450 }
11451 }
11452 let delta = diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
11453 hit0.largeUnit :
11454 null);
11455 if (delta.milliseconds) { // has hours/minutes/seconds
11456 standardProps.allDay = false;
11457 }
11458 let mutation = {
11459 datesDelta: delta,
11460 standardProps,
11461 };
11462 for (let massager of massagers) {
11463 massager(mutation, hit0, hit1);
11464 }
11465 return mutation;
11466 }
11467 function getComponentTouchDelay(component) {
11468 let { options } = component.context;
11469 let delay = options.eventLongPressDelay;
11470 if (delay == null) {
11471 delay = options.longPressDelay;
11472 }
11473 return delay;
11474 }
11475
11476 class EventResizing extends Interaction {
11477 constructor(settings) {
11478 super(settings);
11479 // internal state
11480 this.draggingSegEl = null;
11481 this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
11482 this.eventRange = null;
11483 this.relevantEvents = null;
11484 this.validMutation = null;
11485 this.mutatedRelevantEvents = null;
11486 this.handlePointerDown = (ev) => {
11487 let { component } = this;
11488 let segEl = this.querySegEl(ev);
11489 let seg = getElSeg(segEl);
11490 let eventRange = this.eventRange = seg.eventRange;
11491 this.dragging.minDistance = component.context.options.eventDragMinDistance;
11492 // if touch, need to be working with a selected event
11493 this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
11494 (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
11495 };
11496 this.handleDragStart = (ev) => {
11497 let { context } = this.component;
11498 let eventRange = this.eventRange;
11499 this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
11500 let segEl = this.querySegEl(ev);
11501 this.draggingSegEl = segEl;
11502 this.draggingSeg = getElSeg(segEl);
11503 context.calendarApi.unselect();
11504 context.emitter.trigger('eventResizeStart', {
11505 el: segEl,
11506 event: new EventImpl(context, eventRange.def, eventRange.instance),
11507 jsEvent: ev.origEvent,
11508 view: context.viewApi,
11509 });
11510 };
11511 this.handleHitUpdate = (hit, isFinal, ev) => {
11512 let { context } = this.component;
11513 let relevantEvents = this.relevantEvents;
11514 let initialHit = this.hitDragging.initialHit;
11515 let eventInstance = this.eventRange.instance;
11516 let mutation = null;
11517 let mutatedRelevantEvents = null;
11518 let isInvalid = false;
11519 let interaction = {
11520 affectedEvents: relevantEvents,
11521 mutatedEvents: createEmptyEventStore(),
11522 isEvent: true,
11523 };
11524 if (hit) {
11525 let disallowed = hit.componentId === initialHit.componentId
11526 && this.isHitComboAllowed
11527 && !this.isHitComboAllowed(initialHit, hit);
11528 if (!disallowed) {
11529 mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
11530 }
11531 }
11532 if (mutation) {
11533 mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
11534 interaction.mutatedEvents = mutatedRelevantEvents;
11535 if (!isInteractionValid(interaction, hit.dateProfile, context)) {
11536 isInvalid = true;
11537 mutation = null;
11538 mutatedRelevantEvents = null;
11539 interaction.mutatedEvents = null;
11540 }
11541 }
11542 if (mutatedRelevantEvents) {
11543 context.dispatch({
11544 type: 'SET_EVENT_RESIZE',
11545 state: interaction,
11546 });
11547 }
11548 else {
11549 context.dispatch({ type: 'UNSET_EVENT_RESIZE' });
11550 }
11551 if (!isInvalid) {
11552 enableCursor();
11553 }
11554 else {
11555 disableCursor();
11556 }
11557 if (!isFinal) {
11558 if (mutation && isHitsEqual(initialHit, hit)) {
11559 mutation = null;
11560 }
11561 this.validMutation = mutation;
11562 this.mutatedRelevantEvents = mutatedRelevantEvents;
11563 }
11564 };
11565 this.handleDragEnd = (ev) => {
11566 let { context } = this.component;
11567 let eventDef = this.eventRange.def;
11568 let eventInstance = this.eventRange.instance;
11569 let eventApi = new EventImpl(context, eventDef, eventInstance);
11570 let relevantEvents = this.relevantEvents;
11571 let mutatedRelevantEvents = this.mutatedRelevantEvents;
11572 context.emitter.trigger('eventResizeStop', {
11573 el: this.draggingSegEl,
11574 event: eventApi,
11575 jsEvent: ev.origEvent,
11576 view: context.viewApi,
11577 });
11578 if (this.validMutation) {
11579 let updatedEventApi = new EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
11580 context.dispatch({
11581 type: 'MERGE_EVENTS',
11582 eventStore: mutatedRelevantEvents,
11583 });
11584 let eventChangeArg = {
11585 oldEvent: eventApi,
11586 event: updatedEventApi,
11587 relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance),
11588 revert() {
11589 context.dispatch({
11590 type: 'MERGE_EVENTS',
11591 eventStore: relevantEvents, // the pre-change events
11592 });
11593 },
11594 };
11595 context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), { el: this.draggingSegEl, startDelta: this.validMutation.startDelta || createDuration(0), endDelta: this.validMutation.endDelta || createDuration(0), jsEvent: ev.origEvent, view: context.viewApi }));
11596 context.emitter.trigger('eventChange', eventChangeArg);
11597 }
11598 else {
11599 context.emitter.trigger('_noEventResize');
11600 }
11601 // reset all internal state
11602 this.draggingSeg = null;
11603 this.relevantEvents = null;
11604 this.validMutation = null;
11605 // okay to keep eventInstance around. useful to set it in handlePointerDown
11606 };
11607 let { component } = settings;
11608 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
11609 dragging.pointer.selector = '.fc-event-resizer';
11610 dragging.touchScrollAllowed = false;
11611 dragging.autoScroller.isEnabled = component.context.options.dragScroll;
11612 let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
11613 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
11614 hitDragging.emitter.on('dragstart', this.handleDragStart);
11615 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11616 hitDragging.emitter.on('dragend', this.handleDragEnd);
11617 }
11618 destroy() {
11619 this.dragging.destroy();
11620 }
11621 querySegEl(ev) {
11622 return elementClosest(ev.subjectEl, '.fc-event');
11623 }
11624 }
11625 function computeMutation(hit0, hit1, isFromStart, instanceRange) {
11626 let dateEnv = hit0.context.dateEnv;
11627 let date0 = hit0.dateSpan.range.start;
11628 let date1 = hit1.dateSpan.range.start;
11629 let delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
11630 if (isFromStart) {
11631 if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
11632 return { startDelta: delta };
11633 }
11634 }
11635 else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
11636 return { endDelta: delta };
11637 }
11638 return null;
11639 }
11640
11641 class UnselectAuto {
11642 constructor(context) {
11643 this.context = context;
11644 this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
11645 this.matchesCancel = false;
11646 this.matchesEvent = false;
11647 this.onSelect = (selectInfo) => {
11648 if (selectInfo.jsEvent) {
11649 this.isRecentPointerDateSelect = true;
11650 }
11651 };
11652 this.onDocumentPointerDown = (pev) => {
11653 let unselectCancel = this.context.options.unselectCancel;
11654 let downEl = getEventTargetViaRoot(pev.origEvent);
11655 this.matchesCancel = !!elementClosest(downEl, unselectCancel);
11656 this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
11657 };
11658 this.onDocumentPointerUp = (pev) => {
11659 let { context } = this;
11660 let { documentPointer } = this;
11661 let calendarState = context.getCurrentData();
11662 // touch-scrolling should never unfocus any type of selection
11663 if (!documentPointer.wasTouchScroll) {
11664 if (calendarState.dateSelection && // an existing date selection?
11665 !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
11666 ) {
11667 let unselectAuto = context.options.unselectAuto;
11668 if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
11669 context.calendarApi.unselect(pev);
11670 }
11671 }
11672 if (calendarState.eventSelection && // an existing event selected?
11673 !this.matchesEvent // interaction DIDN'T start on an event
11674 ) {
11675 context.dispatch({ type: 'UNSELECT_EVENT' });
11676 }
11677 }
11678 this.isRecentPointerDateSelect = false;
11679 };
11680 let documentPointer = this.documentPointer = new PointerDragging(document);
11681 documentPointer.shouldIgnoreMove = true;
11682 documentPointer.shouldWatchScroll = false;
11683 documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
11684 documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
11685 /*
11686 TODO: better way to know about whether there was a selection with the pointer
11687 */
11688 context.emitter.on('select', this.onSelect);
11689 }
11690 destroy() {
11691 this.context.emitter.off('select', this.onSelect);
11692 this.documentPointer.destroy();
11693 }
11694 }
11695
11696 const OPTION_REFINERS$3 = {
11697 fixedMirrorParent: identity,
11698 };
11699 const LISTENER_REFINERS = {
11700 dateClick: identity,
11701 eventDragStart: identity,
11702 eventDragStop: identity,
11703 eventDrop: identity,
11704 eventResizeStart: identity,
11705 eventResizeStop: identity,
11706 eventResize: identity,
11707 drop: identity,
11708 eventReceive: identity,
11709 eventLeave: identity,
11710 };
11711
11712 /*
11713 Given an already instantiated draggable object for one-or-more elements,
11714 Interprets any dragging as an attempt to drag an events that lives outside
11715 of a calendar onto a calendar.
11716 */
11717 class ExternalElementDragging {
11718 constructor(dragging, suppliedDragMeta) {
11719 this.receivingContext = null;
11720 this.droppableEvent = null; // will exist for all drags, even if create:false
11721 this.suppliedDragMeta = null;
11722 this.dragMeta = null;
11723 this.handleDragStart = (ev) => {
11724 this.dragMeta = this.buildDragMeta(ev.subjectEl);
11725 };
11726 this.handleHitUpdate = (hit, isFinal, ev) => {
11727 let { dragging } = this.hitDragging;
11728 let receivingContext = null;
11729 let droppableEvent = null;
11730 let isInvalid = false;
11731 let interaction = {
11732 affectedEvents: createEmptyEventStore(),
11733 mutatedEvents: createEmptyEventStore(),
11734 isEvent: this.dragMeta.create,
11735 };
11736 if (hit) {
11737 receivingContext = hit.context;
11738 if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
11739 droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
11740 interaction.mutatedEvents = eventTupleToStore(droppableEvent);
11741 isInvalid = !isInteractionValid(interaction, hit.dateProfile, receivingContext);
11742 if (isInvalid) {
11743 interaction.mutatedEvents = createEmptyEventStore();
11744 droppableEvent = null;
11745 }
11746 }
11747 }
11748 this.displayDrag(receivingContext, interaction);
11749 // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
11750 // TODO: wish we could somehow wait for dispatch to guarantee render
11751 dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
11752 if (!isInvalid) {
11753 enableCursor();
11754 }
11755 else {
11756 disableCursor();
11757 }
11758 if (!isFinal) {
11759 dragging.setMirrorNeedsRevert(!droppableEvent);
11760 this.receivingContext = receivingContext;
11761 this.droppableEvent = droppableEvent;
11762 }
11763 };
11764 this.handleDragEnd = (pev) => {
11765 let { receivingContext, droppableEvent } = this;
11766 this.clearDrag();
11767 if (receivingContext && droppableEvent) {
11768 let finalHit = this.hitDragging.finalHit;
11769 let finalView = finalHit.context.viewApi;
11770 let dragMeta = this.dragMeta;
11771 receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));
11772 if (dragMeta.create) {
11773 let addingEvents = eventTupleToStore(droppableEvent);
11774 receivingContext.dispatch({
11775 type: 'MERGE_EVENTS',
11776 eventStore: addingEvents,
11777 });
11778 if (pev.isTouch) {
11779 receivingContext.dispatch({
11780 type: 'SELECT_EVENT',
11781 eventInstanceId: droppableEvent.instance.instanceId,
11782 });
11783 }
11784 // signal that an external event landed
11785 receivingContext.emitter.trigger('eventReceive', {
11786 event: new EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
11787 relatedEvents: [],
11788 revert() {
11789 receivingContext.dispatch({
11790 type: 'REMOVE_EVENTS',
11791 eventStore: addingEvents,
11792 });
11793 },
11794 draggedEl: pev.subjectEl,
11795 view: finalView,
11796 });
11797 }
11798 }
11799 this.receivingContext = null;
11800 this.droppableEvent = null;
11801 };
11802 let hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore);
11803 hitDragging.requireInitial = false; // will start outside of a component
11804 hitDragging.emitter.on('dragstart', this.handleDragStart);
11805 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
11806 hitDragging.emitter.on('dragend', this.handleDragEnd);
11807 this.suppliedDragMeta = suppliedDragMeta;
11808 }
11809 buildDragMeta(subjectEl) {
11810 if (typeof this.suppliedDragMeta === 'object') {
11811 return parseDragMeta(this.suppliedDragMeta);
11812 }
11813 if (typeof this.suppliedDragMeta === 'function') {
11814 return parseDragMeta(this.suppliedDragMeta(subjectEl));
11815 }
11816 return getDragMetaFromEl(subjectEl);
11817 }
11818 displayDrag(nextContext, state) {
11819 let prevContext = this.receivingContext;
11820 if (prevContext && prevContext !== nextContext) {
11821 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11822 }
11823 if (nextContext) {
11824 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
11825 }
11826 }
11827 clearDrag() {
11828 if (this.receivingContext) {
11829 this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
11830 }
11831 }
11832 canDropElOnCalendar(el, receivingContext) {
11833 let dropAccept = receivingContext.options.dropAccept;
11834 if (typeof dropAccept === 'function') {
11835 return dropAccept.call(receivingContext.calendarApi, el);
11836 }
11837 if (typeof dropAccept === 'string' && dropAccept) {
11838 return Boolean(elementMatches(el, dropAccept));
11839 }
11840 return true;
11841 }
11842 }
11843 // Utils for computing event store from the DragMeta
11844 // ----------------------------------------------------------------------------------------------------
11845 function computeEventForDateSpan(dateSpan, dragMeta, context) {
11846 let defProps = Object.assign({}, dragMeta.leftoverProps);
11847 for (let transform of context.pluginHooks.externalDefTransforms) {
11848 Object.assign(defProps, transform(dateSpan, dragMeta));
11849 }
11850 let { refined, extra } = refineEventDef(defProps, context);
11851 let def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
11852 context);
11853 let start = dateSpan.range.start;
11854 // only rely on time info if drop zone is all-day,
11855 // otherwise, we already know the time
11856 if (dateSpan.allDay && dragMeta.startTime) {
11857 start = context.dateEnv.add(start, dragMeta.startTime);
11858 }
11859 let end = dragMeta.duration ?
11860 context.dateEnv.add(start, dragMeta.duration) :
11861 getDefaultEventEnd(dateSpan.allDay, start, context);
11862 let instance = createEventInstance(def.defId, { start, end });
11863 return { def, instance };
11864 }
11865 // Utils for extracting data from element
11866 // ----------------------------------------------------------------------------------------------------
11867 function getDragMetaFromEl(el) {
11868 let str = getEmbeddedElData(el, 'event');
11869 let obj = str ?
11870 JSON.parse(str) :
11871 { create: false }; // if no embedded data, assume no event creation
11872 return parseDragMeta(obj);
11873 }
11874 config.dataAttrPrefix = '';
11875 function getEmbeddedElData(el, name) {
11876 let prefix = config.dataAttrPrefix;
11877 let prefixedName = (prefix ? prefix + '-' : '') + name;
11878 return el.getAttribute('data-' + prefixedName) || '';
11879 }
11880
11881 /*
11882 Makes an element (that is *external* to any calendar) draggable.
11883 Can pass in data that determines how an event will be created when dropped onto a calendar.
11884 Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
11885 */
11886 class ExternalDraggable {
11887 constructor(el, settings = {}) {
11888 this.handlePointerDown = (ev) => {
11889 let { dragging } = this;
11890 let { minDistance, longPressDelay } = this.settings;
11891 dragging.minDistance =
11892 minDistance != null ?
11893 minDistance :
11894 (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance);
11895 dragging.delay =
11896 ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
11897 (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) :
11898 0;
11899 };
11900 this.handleDragStart = (ev) => {
11901 if (ev.isTouch &&
11902 this.dragging.delay &&
11903 ev.subjectEl.classList.contains('fc-event')) {
11904 this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
11905 }
11906 };
11907 this.settings = settings;
11908 let dragging = this.dragging = new FeaturefulElementDragging(el);
11909 dragging.touchScrollAllowed = false;
11910 if (settings.itemSelector != null) {
11911 dragging.pointer.selector = settings.itemSelector;
11912 }
11913 if (settings.appendTo != null) {
11914 dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
11915 }
11916 dragging.emitter.on('pointerdown', this.handlePointerDown);
11917 dragging.emitter.on('dragstart', this.handleDragStart);
11918 new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
11919 }
11920 destroy() {
11921 this.dragging.destroy();
11922 }
11923 }
11924
11925 /*
11926 Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
11927 The third-party system is responsible for drawing the visuals effects of the drag.
11928 This class simply monitors for pointer movements and fires events.
11929 It also has the ability to hide the moving element (the "mirror") during the drag.
11930 */
11931 class InferredElementDragging extends ElementDragging {
11932 constructor(containerEl) {
11933 super(containerEl);
11934 this.shouldIgnoreMove = false;
11935 this.mirrorSelector = '';
11936 this.currentMirrorEl = null;
11937 this.handlePointerDown = (ev) => {
11938 this.emitter.trigger('pointerdown', ev);
11939 if (!this.shouldIgnoreMove) {
11940 // fire dragstart right away. does not support delay or min-distance
11941 this.emitter.trigger('dragstart', ev);
11942 }
11943 };
11944 this.handlePointerMove = (ev) => {
11945 if (!this.shouldIgnoreMove) {
11946 this.emitter.trigger('dragmove', ev);
11947 }
11948 };
11949 this.handlePointerUp = (ev) => {
11950 this.emitter.trigger('pointerup', ev);
11951 if (!this.shouldIgnoreMove) {
11952 // fire dragend right away. does not support a revert animation
11953 this.emitter.trigger('dragend', ev);
11954 }
11955 };
11956 let pointer = this.pointer = new PointerDragging(containerEl);
11957 pointer.emitter.on('pointerdown', this.handlePointerDown);
11958 pointer.emitter.on('pointermove', this.handlePointerMove);
11959 pointer.emitter.on('pointerup', this.handlePointerUp);
11960 }
11961 destroy() {
11962 this.pointer.destroy();
11963 }
11964 setIgnoreMove(bool) {
11965 this.shouldIgnoreMove = bool;
11966 }
11967 setMirrorIsVisible(bool) {
11968 if (bool) {
11969 // restore a previously hidden element.
11970 // use the reference in case the selector class has already been removed.
11971 if (this.currentMirrorEl) {
11972 this.currentMirrorEl.style.visibility = '';
11973 this.currentMirrorEl = null;
11974 }
11975 }
11976 else {
11977 let mirrorEl = this.mirrorSelector
11978 // TODO: somehow query FullCalendars WITHIN shadow-roots
11979 ? document.querySelector(this.mirrorSelector)
11980 : null;
11981 if (mirrorEl) {
11982 this.currentMirrorEl = mirrorEl;
11983 mirrorEl.style.visibility = 'hidden';
11984 }
11985 }
11986 }
11987 }
11988
11989 /*
11990 Bridges third-party drag-n-drop systems with FullCalendar.
11991 Must be instantiated and destroyed by caller.
11992 */
11993 class ThirdPartyDraggable {
11994 constructor(containerOrSettings, settings) {
11995 let containerEl = document;
11996 if (
11997 // wish we could just test instanceof EventTarget, but doesn't work in IE11
11998 containerOrSettings === document ||
11999 containerOrSettings instanceof Element) {
12000 containerEl = containerOrSettings;
12001 settings = settings || {};
12002 }
12003 else {
12004 settings = (containerOrSettings || {});
12005 }
12006 let dragging = this.dragging = new InferredElementDragging(containerEl);
12007 if (typeof settings.itemSelector === 'string') {
12008 dragging.pointer.selector = settings.itemSelector;
12009 }
12010 else if (containerEl === document) {
12011 dragging.pointer.selector = '[data-event]';
12012 }
12013 if (typeof settings.mirrorSelector === 'string') {
12014 dragging.mirrorSelector = settings.mirrorSelector;
12015 }
12016 let externalDragging = new ExternalElementDragging(dragging, settings.eventData);
12017 // The hit-detection system requires that the dnd-mirror-element be pointer-events:none,
12018 // but this can't be guaranteed for third-party draggables, so disable
12019 externalDragging.hitDragging.disablePointCheck = true;
12020 }
12021 destroy() {
12022 this.dragging.destroy();
12023 }
12024 }
12025
12026 var index$4 = createPlugin({
12027 name: '@fullcalendar/interaction',
12028 componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
12029 calendarInteractions: [UnselectAuto],
12030 elementDraggingImpl: FeaturefulElementDragging,
12031 optionRefiners: OPTION_REFINERS$3,
12032 listenerRefiners: LISTENER_REFINERS,
12033 });
12034
12035 /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
12036 ----------------------------------------------------------------------------------------------------------------------*/
12037 // It is a manager for a Table subcomponent, which does most of the heavy lifting.
12038 // It is responsible for managing width/height.
12039 class TableView extends DateComponent {
12040 constructor() {
12041 super(...arguments);
12042 this.headerElRef = d();
12043 }
12044 renderSimpleLayout(headerRowContent, bodyContent) {
12045 let { props, context } = this;
12046 let sections = [];
12047 let stickyHeaderDates = getStickyHeaderDates(context.options);
12048 if (headerRowContent) {
12049 sections.push({
12050 type: 'header',
12051 key: 'header',
12052 isSticky: stickyHeaderDates,
12053 chunk: {
12054 elRef: this.headerElRef,
12055 tableClassName: 'fc-col-header',
12056 rowContent: headerRowContent,
12057 },
12058 });
12059 }
12060 sections.push({
12061 type: 'body',
12062 key: 'body',
12063 liquid: true,
12064 chunk: { content: bodyContent },
12065 });
12066 return (y(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
12067 y(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
12068 }
12069 renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
12070 let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
12071 if (!ScrollGrid) {
12072 throw new Error('No ScrollGrid implementation');
12073 }
12074 let { props, context } = this;
12075 let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
12076 let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
12077 let sections = [];
12078 if (headerRowContent) {
12079 sections.push({
12080 type: 'header',
12081 key: 'header',
12082 isSticky: stickyHeaderDates,
12083 chunks: [{
12084 key: 'main',
12085 elRef: this.headerElRef,
12086 tableClassName: 'fc-col-header',
12087 rowContent: headerRowContent,
12088 }],
12089 });
12090 }
12091 sections.push({
12092 type: 'body',
12093 key: 'body',
12094 liquid: true,
12095 chunks: [{
12096 key: 'main',
12097 content: bodyContent,
12098 }],
12099 });
12100 if (stickyFooterScrollbar) {
12101 sections.push({
12102 type: 'footer',
12103 key: 'footer',
12104 isSticky: true,
12105 chunks: [{
12106 key: 'main',
12107 content: renderScrollShim,
12108 }],
12109 });
12110 }
12111 return (y(ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
12112 y(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
12113 }
12114 }
12115
12116 function splitSegsByRow(segs, rowCnt) {
12117 let byRow = [];
12118 for (let i = 0; i < rowCnt; i += 1) {
12119 byRow[i] = [];
12120 }
12121 for (let seg of segs) {
12122 byRow[seg.row].push(seg);
12123 }
12124 return byRow;
12125 }
12126 function splitSegsByFirstCol(segs, colCnt) {
12127 let byCol = [];
12128 for (let i = 0; i < colCnt; i += 1) {
12129 byCol[i] = [];
12130 }
12131 for (let seg of segs) {
12132 byCol[seg.firstCol].push(seg);
12133 }
12134 return byCol;
12135 }
12136 function splitInteractionByRow(ui, rowCnt) {
12137 let byRow = [];
12138 if (!ui) {
12139 for (let i = 0; i < rowCnt; i += 1) {
12140 byRow[i] = null;
12141 }
12142 }
12143 else {
12144 for (let i = 0; i < rowCnt; i += 1) {
12145 byRow[i] = {
12146 affectedInstances: ui.affectedInstances,
12147 isEvent: ui.isEvent,
12148 segs: [],
12149 };
12150 }
12151 for (let seg of ui.segs) {
12152 byRow[seg.row].segs.push(seg);
12153 }
12154 }
12155 return byRow;
12156 }
12157
12158 const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
12159 hour: 'numeric',
12160 minute: '2-digit',
12161 omitZeroMinute: true,
12162 meridiem: 'narrow',
12163 });
12164 function hasListItemDisplay(seg) {
12165 let { display } = seg.eventRange.ui;
12166 return display === 'list-item' || (display === 'auto' &&
12167 !seg.eventRange.def.allDay &&
12168 seg.firstCol === seg.lastCol && // can't be multi-day
12169 seg.isStart && // "
12170 seg.isEnd // "
12171 );
12172 }
12173
12174 class TableBlockEvent extends BaseComponent {
12175 render() {
12176 let { props } = this;
12177 return (y(StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
12178 }
12179 }
12180
12181 class TableListItemEvent extends BaseComponent {
12182 render() {
12183 let { props, context } = this;
12184 let { options } = context;
12185 let { seg } = props;
12186 let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
12187 let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
12188 return (y(EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent$2, timeText: timeText, isResizing: false, isDateSelecting: false })));
12189 }
12190 }
12191 function renderInnerContent$2(renderProps) {
12192 return (y(_, null,
12193 y("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
12194 renderProps.timeText && (y("div", { className: "fc-event-time" }, renderProps.timeText)),
12195 y("div", { className: "fc-event-title" }, renderProps.event.title || y(_, null, "\u00A0"))));
12196 }
12197
12198 class TableCellMoreLink extends BaseComponent {
12199 constructor() {
12200 super(...arguments);
12201 this.compileSegs = memoize(compileSegs);
12202 }
12203 render() {
12204 let { props } = this;
12205 let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
12206 return (y(MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
12207 let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
12208 (props.eventResize ? props.eventResize.affectedInstances : null) ||
12209 {};
12210 return (y(_, null, allSegs.map((seg) => {
12211 let instanceId = seg.eventRange.instance.instanceId;
12212 return (y("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
12213 visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
12214 } }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange)))) : (y(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, getSegMeta(seg, props.todayRange))))));
12215 })));
12216 } }));
12217 }
12218 }
12219 function compileSegs(singlePlacements) {
12220 let allSegs = [];
12221 let invisibleSegs = [];
12222 for (let placement of singlePlacements) {
12223 allSegs.push(placement.seg);
12224 if (!placement.isVisible) {
12225 invisibleSegs.push(placement.seg);
12226 }
12227 }
12228 return { allSegs, invisibleSegs };
12229 }
12230
12231 const DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({ week: 'narrow' });
12232 class TableCell extends DateComponent {
12233 constructor() {
12234 super(...arguments);
12235 this.rootElRef = d();
12236 this.state = {
12237 dayNumberId: getUniqueDomId(),
12238 };
12239 this.handleRootEl = (el) => {
12240 setRef(this.rootElRef, el);
12241 setRef(this.props.elRef, el);
12242 };
12243 }
12244 render() {
12245 let { context, props, state, rootElRef } = this;
12246 let { options, dateEnv } = context;
12247 let { date, dateProfile } = props;
12248 // TODO: memoize this?
12249 const isMonthStart = props.showDayNumber &&
12250 shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
12251 return (y(DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
12252 'fc-daygrid-day',
12253 ...(props.extraClassNames || []),
12254 ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (y("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
12255 props.showWeekNumber && (y(WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1 })),
12256 !renderProps.isDisabled &&
12257 (props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop) ? (y("div", { className: "fc-daygrid-day-top" },
12258 y(InnerContent, { elTag: "a", elClasses: [
12259 'fc-daygrid-day-number',
12260 isMonthStart && 'fc-daygrid-month-start',
12261 ], elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
12262 // for creating correct amount of space (see issue #7162)
12263 y("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
12264 y("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
12265 y("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
12266 props.fgContent,
12267 y("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
12268 y(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
12269 y("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
12270 }
12271 }
12272 function renderTopInner(props) {
12273 return props.dayNumberText || y(_, null, "\u00A0");
12274 }
12275 function shouldDisplayMonthStart(date, currentRange, dateEnv) {
12276 const { start: currentStart, end: currentEnd } = currentRange;
12277 const currentEndIncl = addMs(currentEnd, -1);
12278 const currentFirstYear = dateEnv.getYear(currentStart);
12279 const currentFirstMonth = dateEnv.getMonth(currentStart);
12280 const currentLastYear = dateEnv.getYear(currentEndIncl);
12281 const currentLastMonth = dateEnv.getMonth(currentEndIncl);
12282 // spans more than one month?
12283 return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
12284 Boolean(
12285 // first date in current view?
12286 date.valueOf() === currentStart.valueOf() ||
12287 // a month-start that's within the current range?
12288 (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
12289 }
12290
12291 function generateSegKey(seg) {
12292 return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
12293 }
12294 function generateSegUid(seg) {
12295 return generateSegKey(seg) + ':' + seg.lastCol;
12296 }
12297 function computeFgSegPlacement(segs, // assumed already sorted
12298 dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
12299 let hierarchy = new DayGridSegHierarchy((segEntry) => {
12300 // TODO: more DRY with generateSegUid
12301 let segUid = segs[segEntry.index].eventRange.instance.instanceId +
12302 ':' + segEntry.span.start +
12303 ':' + (segEntry.span.end - 1);
12304 // if no thickness known, assume 1 (if 0, so small it always fits)
12305 return segHeights[segUid] || 1;
12306 });
12307 hierarchy.allowReslicing = true;
12308 hierarchy.strictOrder = strictOrder;
12309 if (dayMaxEvents === true || dayMaxEventRows === true) {
12310 hierarchy.maxCoord = maxContentHeight;
12311 hierarchy.hiddenConsumes = true;
12312 }
12313 else if (typeof dayMaxEvents === 'number') {
12314 hierarchy.maxStackCnt = dayMaxEvents;
12315 }
12316 else if (typeof dayMaxEventRows === 'number') {
12317 hierarchy.maxStackCnt = dayMaxEventRows;
12318 hierarchy.hiddenConsumes = true;
12319 }
12320 // create segInputs only for segs with known heights
12321 let segInputs = [];
12322 let unknownHeightSegs = [];
12323 for (let i = 0; i < segs.length; i += 1) {
12324 let seg = segs[i];
12325 let segUid = generateSegUid(seg);
12326 let eventHeight = segHeights[segUid];
12327 if (eventHeight != null) {
12328 segInputs.push({
12329 index: i,
12330 span: {
12331 start: seg.firstCol,
12332 end: seg.lastCol + 1,
12333 },
12334 });
12335 }
12336 else {
12337 unknownHeightSegs.push(seg);
12338 }
12339 }
12340 let hiddenEntries = hierarchy.addSegs(segInputs);
12341 let segRects = hierarchy.toRects();
12342 let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
12343 let moreCnts = [];
12344 let moreMarginTops = [];
12345 // add segs with unknown heights
12346 for (let seg of unknownHeightSegs) {
12347 multiColPlacements[seg.firstCol].push({
12348 seg,
12349 isVisible: false,
12350 isAbsolute: true,
12351 absoluteTop: 0,
12352 marginTop: 0,
12353 });
12354 for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
12355 singleColPlacements[col].push({
12356 seg: resliceSeg(seg, col, col + 1, cells),
12357 isVisible: false,
12358 isAbsolute: false,
12359 absoluteTop: 0,
12360 marginTop: 0,
12361 });
12362 }
12363 }
12364 // add the hidden entries
12365 for (let col = 0; col < cells.length; col += 1) {
12366 moreCnts.push(0);
12367 }
12368 for (let hiddenEntry of hiddenEntries) {
12369 let seg = segs[hiddenEntry.index];
12370 let hiddenSpan = hiddenEntry.span;
12371 multiColPlacements[hiddenSpan.start].push({
12372 seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
12373 isVisible: false,
12374 isAbsolute: true,
12375 absoluteTop: 0,
12376 marginTop: 0,
12377 });
12378 for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
12379 moreCnts[col] += 1;
12380 singleColPlacements[col].push({
12381 seg: resliceSeg(seg, col, col + 1, cells),
12382 isVisible: false,
12383 isAbsolute: false,
12384 absoluteTop: 0,
12385 marginTop: 0,
12386 });
12387 }
12388 }
12389 // deal with leftover margins
12390 for (let col = 0; col < cells.length; col += 1) {
12391 moreMarginTops.push(leftoverMargins[col]);
12392 }
12393 return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
12394 }
12395 // rects ordered by top coord, then left
12396 function placeRects(allRects, segs, cells) {
12397 let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
12398 let singleColPlacements = [];
12399 let multiColPlacements = [];
12400 let leftoverMargins = [];
12401 for (let col = 0; col < cells.length; col += 1) {
12402 let rects = rectsByEachCol[col];
12403 // compute all static segs in singlePlacements
12404 let singlePlacements = [];
12405 let currentHeight = 0;
12406 let currentMarginTop = 0;
12407 for (let rect of rects) {
12408 let seg = segs[rect.index];
12409 singlePlacements.push({
12410 seg: resliceSeg(seg, col, col + 1, cells),
12411 isVisible: true,
12412 isAbsolute: false,
12413 absoluteTop: rect.levelCoord,
12414 marginTop: rect.levelCoord - currentHeight,
12415 });
12416 currentHeight = rect.levelCoord + rect.thickness;
12417 }
12418 // compute mixed static/absolute segs in multiPlacements
12419 let multiPlacements = [];
12420 currentHeight = 0;
12421 currentMarginTop = 0;
12422 for (let rect of rects) {
12423 let seg = segs[rect.index];
12424 let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
12425 let isFirstCol = rect.span.start === col;
12426 currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
12427 currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
12428 if (isAbsolute) {
12429 currentMarginTop += rect.thickness;
12430 if (isFirstCol) {
12431 multiPlacements.push({
12432 seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12433 isVisible: true,
12434 isAbsolute: true,
12435 absoluteTop: rect.levelCoord,
12436 marginTop: 0,
12437 });
12438 }
12439 }
12440 else if (isFirstCol) {
12441 multiPlacements.push({
12442 seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
12443 isVisible: true,
12444 isAbsolute: false,
12445 absoluteTop: rect.levelCoord,
12446 marginTop: currentMarginTop, // claim the margin
12447 });
12448 currentMarginTop = 0;
12449 }
12450 }
12451 singleColPlacements.push(singlePlacements);
12452 multiColPlacements.push(multiPlacements);
12453 leftoverMargins.push(currentMarginTop);
12454 }
12455 return { singleColPlacements, multiColPlacements, leftoverMargins };
12456 }
12457 function groupRectsByEachCol(rects, colCnt) {
12458 let rectsByEachCol = [];
12459 for (let col = 0; col < colCnt; col += 1) {
12460 rectsByEachCol.push([]);
12461 }
12462 for (let rect of rects) {
12463 for (let col = rect.span.start; col < rect.span.end; col += 1) {
12464 rectsByEachCol[col].push(rect);
12465 }
12466 }
12467 return rectsByEachCol;
12468 }
12469 function resliceSeg(seg, spanStart, spanEnd, cells) {
12470 if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
12471 return seg;
12472 }
12473 let eventRange = seg.eventRange;
12474 let origRange = eventRange.range;
12475 let slicedRange = intersectRanges(origRange, {
12476 start: cells[spanStart].date,
12477 end: addDays(cells[spanEnd - 1].date, 1),
12478 });
12479 return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
12480 def: eventRange.def,
12481 ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
12482 instance: eventRange.instance,
12483 range: slicedRange,
12484 }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
12485 }
12486 class DayGridSegHierarchy extends SegHierarchy {
12487 constructor() {
12488 super(...arguments);
12489 // config
12490 this.hiddenConsumes = false;
12491 // allows us to keep hidden entries in the hierarchy so they take up space
12492 this.forceHidden = {};
12493 }
12494 addSegs(segInputs) {
12495 const hiddenSegs = super.addSegs(segInputs);
12496 const { entriesByLevel } = this;
12497 const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
12498 // remove the forced-hidden segs
12499 for (let level = 0; level < entriesByLevel.length; level += 1) {
12500 entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
12501 }
12502 return hiddenSegs;
12503 }
12504 handleInvalidInsertion(insertion, entry, hiddenEntries) {
12505 const { entriesByLevel, forceHidden } = this;
12506 const { touchingEntry, touchingLevel, touchingLateral } = insertion;
12507 // the entry that the new insertion is touching must be hidden
12508 if (this.hiddenConsumes && touchingEntry) {
12509 const touchingEntryId = buildEntryKey(touchingEntry);
12510 if (!forceHidden[touchingEntryId]) {
12511 if (this.allowReslicing) {
12512 // split up the touchingEntry, reinsert it
12513 const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: intersectSpans(touchingEntry.span, entry.span) });
12514 // reinsert the area that turned into a "more" link (so no other entries try to
12515 // occupy the space) but mark it forced-hidden
12516 const hiddenEntryId = buildEntryKey(hiddenEntry);
12517 forceHidden[hiddenEntryId] = true;
12518 entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
12519 hiddenEntries.push(hiddenEntry);
12520 this.splitEntry(touchingEntry, entry, hiddenEntries);
12521 }
12522 else {
12523 forceHidden[touchingEntryId] = true;
12524 hiddenEntries.push(touchingEntry);
12525 }
12526 }
12527 }
12528 // will try to reslice...
12529 super.handleInvalidInsertion(insertion, entry, hiddenEntries);
12530 }
12531 }
12532
12533 class TableRow extends DateComponent {
12534 constructor() {
12535 super(...arguments);
12536 this.cellElRefs = new RefMap(); // the <td>
12537 this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
12538 this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
12539 this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
12540 this.rootElRef = d();
12541 this.state = {
12542 framePositions: null,
12543 maxContentHeight: null,
12544 segHeights: {},
12545 };
12546 this.handleResize = (isForced) => {
12547 if (isForced) {
12548 this.updateSizing(true); // isExternal=true
12549 }
12550 };
12551 }
12552 render() {
12553 let { props, state, context } = this;
12554 let { options } = context;
12555 let colCnt = props.cells.length;
12556 let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
12557 let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
12558 let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
12559 let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
12560 let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
12561 let isForcedInvisible = // TODO: messy way to compute this
12562 (props.eventDrag && props.eventDrag.affectedInstances) ||
12563 (props.eventResize && props.eventResize.affectedInstances) ||
12564 {};
12565 return (y("tr", { ref: this.rootElRef, role: "row" },
12566 props.renderIntro && props.renderIntro(),
12567 props.cells.map((cell, col) => {
12568 let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
12569 let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
12570 return (y(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
12571 y(_, null,
12572 y(_, null, normalFgNodes),
12573 y(_, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
12574 y(_, null,
12575 this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
12576 this.renderFillSegs(businessHoursByCol[col], 'non-business'),
12577 this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
12578 })));
12579 }
12580 componentDidMount() {
12581 this.updateSizing(true);
12582 this.context.addResizeHandler(this.handleResize);
12583 }
12584 componentDidUpdate(prevProps, prevState) {
12585 let currentProps = this.props;
12586 this.updateSizing(!isPropsEqual(prevProps, currentProps));
12587 }
12588 componentWillUnmount() {
12589 this.context.removeResizeHandler(this.handleResize);
12590 }
12591 getHighlightSegs() {
12592 let { props } = this;
12593 if (props.eventDrag && props.eventDrag.segs.length) { // messy check
12594 return props.eventDrag.segs;
12595 }
12596 if (props.eventResize && props.eventResize.segs.length) { // messy check
12597 return props.eventResize.segs;
12598 }
12599 return props.dateSelectionSegs;
12600 }
12601 getMirrorSegs() {
12602 let { props } = this;
12603 if (props.eventResize && props.eventResize.segs.length) { // messy check
12604 return props.eventResize.segs;
12605 }
12606 return [];
12607 }
12608 renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
12609 let { context } = this;
12610 let { eventSelection } = this.props;
12611 let { framePositions } = this.state;
12612 let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
12613 let isMirror = isDragging || isResizing || isDateSelecting;
12614 let nodes = [];
12615 if (framePositions) {
12616 for (let placement of segPlacements) {
12617 let { seg } = placement;
12618 let { instanceId } = seg.eventRange.instance;
12619 let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
12620 let isAbsolute = placement.isAbsolute;
12621 let left = '';
12622 let right = '';
12623 if (isAbsolute) {
12624 if (context.isRtl) {
12625 right = 0;
12626 left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
12627 }
12628 else {
12629 left = 0;
12630 right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
12631 }
12632 }
12633 /*
12634 known bug: events that are force to be list-item but span multiple days still take up space in later columns
12635 todo: in print view, for multi-day events, don't display title within non-start/end segs
12636 */
12637 nodes.push(y("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
12638 visibility: isVisible ? '' : 'hidden',
12639 marginTop: isAbsolute ? '' : placement.marginTop,
12640 top: isAbsolute ? placement.absoluteTop : '',
12641 left,
12642 right,
12643 } }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange)))) : (y(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, getSegMeta(seg, todayRange))))));
12644 }
12645 }
12646 return nodes;
12647 }
12648 renderFillSegs(segs, fillType) {
12649 let { isRtl } = this.context;
12650 let { todayRange } = this.props;
12651 let { framePositions } = this.state;
12652 let nodes = [];
12653 if (framePositions) {
12654 for (let seg of segs) {
12655 let leftRightCss = isRtl ? {
12656 right: 0,
12657 left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
12658 } : {
12659 left: 0,
12660 right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
12661 };
12662 nodes.push(y("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
12663 y(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange))) :
12664 renderFill(fillType)));
12665 }
12666 }
12667 return y(_, {}, ...nodes);
12668 }
12669 updateSizing(isExternalSizingChange) {
12670 let { props, state, frameElRefs } = this;
12671 if (!props.forPrint &&
12672 props.clientWidth !== null // positioning ready?
12673 ) {
12674 if (isExternalSizingChange) {
12675 let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
12676 if (frameEls.length) {
12677 let originEl = this.rootElRef.current;
12678 let newPositionCache = new PositionCache(originEl, frameEls, true, // isHorizontal
12679 false);
12680 if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
12681 this.setState({
12682 framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
12683 false),
12684 });
12685 }
12686 }
12687 }
12688 const oldSegHeights = this.state.segHeights;
12689 const newSegHeights = this.querySegHeights();
12690 const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
12691 this.safeSetState({
12692 // HACK to prevent oscillations of events being shown/hidden from max-event-rows
12693 // Essentially, once you compute an element's height, never null-out.
12694 // TODO: always display all events, as visibility:hidden?
12695 segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
12696 maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
12697 });
12698 }
12699 }
12700 querySegHeights() {
12701 let segElMap = this.segHarnessRefs.currentMap;
12702 let segHeights = {};
12703 // get the max height amongst instance segs
12704 for (let segUid in segElMap) {
12705 let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
12706 segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
12707 }
12708 return segHeights;
12709 }
12710 computeMaxContentHeight() {
12711 let firstKey = this.props.cells[0].key;
12712 let cellEl = this.cellElRefs.currentMap[firstKey];
12713 let fcContainerEl = this.fgElRefs.currentMap[firstKey];
12714 return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
12715 }
12716 getCellEls() {
12717 let elMap = this.cellElRefs.currentMap;
12718 return this.props.cells.map((cell) => elMap[cell.key]);
12719 }
12720 }
12721 TableRow.addStateEquality({
12722 segHeights: isPropsEqual,
12723 });
12724 function buildMirrorPlacements(mirrorSegs, colPlacements) {
12725 if (!mirrorSegs.length) {
12726 return [];
12727 }
12728 let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
12729 return mirrorSegs.map((seg) => ({
12730 seg,
12731 isVisible: true,
12732 isAbsolute: true,
12733 absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
12734 marginTop: 0,
12735 }));
12736 }
12737 function buildAbsoluteTopHash(colPlacements) {
12738 let topsByInstanceId = {};
12739 for (let placements of colPlacements) {
12740 for (let placement of placements) {
12741 topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
12742 }
12743 }
12744 return topsByInstanceId;
12745 }
12746
12747 class TableRows extends DateComponent {
12748 constructor() {
12749 super(...arguments);
12750 this.splitBusinessHourSegs = memoize(splitSegsByRow);
12751 this.splitBgEventSegs = memoize(splitSegsByRow);
12752 this.splitFgEventSegs = memoize(splitSegsByRow);
12753 this.splitDateSelectionSegs = memoize(splitSegsByRow);
12754 this.splitEventDrag = memoize(splitInteractionByRow);
12755 this.splitEventResize = memoize(splitInteractionByRow);
12756 this.rowRefs = new RefMap();
12757 }
12758 render() {
12759 let { props, context } = this;
12760 let rowCnt = props.cells.length;
12761 let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
12762 let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
12763 let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
12764 let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
12765 let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
12766 let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
12767 // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
12768 // choose 7 because a month view will have max 6 rows
12769 let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
12770 props.clientWidth / context.options.aspectRatio / 6 :
12771 null;
12772 return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => (y(_, null, props.cells.map((cells, row) => (y(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
12773 ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
12774 : row // in case there are no cells (like when resource view is loading)
12775 , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
12776 }
12777 componentDidMount() {
12778 this.registerInteractiveComponent();
12779 }
12780 componentDidUpdate() {
12781 // for if started with zero cells
12782 this.registerInteractiveComponent();
12783 }
12784 registerInteractiveComponent() {
12785 if (!this.rootEl) {
12786 // HACK: need a daygrid wrapper parent to do positioning
12787 // NOTE: a daygrid resource view w/o resources can have zero cells
12788 const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
12789 const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
12790 if (rootEl) {
12791 this.rootEl = rootEl;
12792 this.context.registerInteractiveComponent(this, {
12793 el: rootEl,
12794 isHitComboAllowed: this.props.isHitComboAllowed,
12795 });
12796 }
12797 }
12798 }
12799 componentWillUnmount() {
12800 if (this.rootEl) {
12801 this.context.unregisterInteractiveComponent(this);
12802 this.rootEl = null;
12803 }
12804 }
12805 // Hit System
12806 // ----------------------------------------------------------------------------------------------------
12807 prepareHits() {
12808 this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
12809 false, true);
12810 this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
12811 true, // horizontal
12812 false);
12813 }
12814 queryHit(positionLeft, positionTop) {
12815 let { colPositions, rowPositions } = this;
12816 let col = colPositions.leftToIndex(positionLeft);
12817 let row = rowPositions.topToIndex(positionTop);
12818 if (row != null && col != null) {
12819 let cell = this.props.cells[row][col];
12820 return {
12821 dateProfile: this.props.dateProfile,
12822 dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
12823 dayEl: this.getCellEl(row, col),
12824 rect: {
12825 left: colPositions.lefts[col],
12826 right: colPositions.rights[col],
12827 top: rowPositions.tops[row],
12828 bottom: rowPositions.bottoms[row],
12829 },
12830 layer: 0,
12831 };
12832 }
12833 return null;
12834 }
12835 getCellEl(row, col) {
12836 return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
12837 }
12838 getCellRange(row, col) {
12839 let start = this.props.cells[row][col].date;
12840 let end = addDays(start, 1);
12841 return { start, end };
12842 }
12843 }
12844 function isSegAllDay(seg) {
12845 return seg.eventRange.def.allDay;
12846 }
12847
12848 class Table extends DateComponent {
12849 constructor() {
12850 super(...arguments);
12851 this.elRef = d();
12852 this.needsScrollReset = false;
12853 }
12854 render() {
12855 let { props } = this;
12856 let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
12857 let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
12858 // if rows can't expand to fill fixed height, can't do balanced-height event limit
12859 // TODO: best place to normalize these options?
12860 if (limitViaBalanced && !expandRows) {
12861 limitViaBalanced = false;
12862 dayMaxEventRows = null;
12863 dayMaxEvents = null;
12864 }
12865 let classNames = [
12866 'fc-daygrid-body',
12867 limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
12868 expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
12869 ];
12870 return (y("div", { ref: this.elRef, className: classNames.join(' '), style: {
12871 // these props are important to give this wrapper correct dimensions for interactions
12872 // TODO: if we set it here, can we avoid giving to inner tables?
12873 width: props.clientWidth,
12874 minWidth: props.tableMinWidth,
12875 } },
12876 y("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
12877 width: props.clientWidth,
12878 minWidth: props.tableMinWidth,
12879 height: expandRows ? props.clientHeight : '',
12880 } },
12881 props.colGroupNode,
12882 y("tbody", { role: "presentation" },
12883 y(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
12884 }
12885 componentDidMount() {
12886 this.requestScrollReset();
12887 }
12888 componentDidUpdate(prevProps) {
12889 if (prevProps.dateProfile !== this.props.dateProfile) {
12890 this.requestScrollReset();
12891 }
12892 else {
12893 this.flushScrollReset();
12894 }
12895 }
12896 requestScrollReset() {
12897 this.needsScrollReset = true;
12898 this.flushScrollReset();
12899 }
12900 flushScrollReset() {
12901 if (this.needsScrollReset &&
12902 this.props.clientWidth // sizes computed?
12903 ) {
12904 const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
12905 if (subjectEl) {
12906 const originEl = subjectEl.closest('.fc-daygrid-body');
12907 const scrollEl = originEl.closest('.fc-scroller');
12908 const scrollTop = subjectEl.getBoundingClientRect().top -
12909 originEl.getBoundingClientRect().top;
12910 scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
12911 }
12912 this.needsScrollReset = false;
12913 }
12914 }
12915 }
12916 function getScrollSubjectEl(containerEl, dateProfile) {
12917 let el;
12918 if (dateProfile.currentRangeUnit.match(/year|month/)) {
12919 el = containerEl.querySelector(`[data-date="${formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
12920 // even if view is month-based, first-of-month might be hidden...
12921 }
12922 if (!el) {
12923 el = containerEl.querySelector(`[data-date="${formatDayString(dateProfile.currentDate)}"]`);
12924 // could still be hidden if an interior-view hidden day
12925 }
12926 return el;
12927 }
12928
12929 class DayTableSlicer extends Slicer {
12930 constructor() {
12931 super(...arguments);
12932 this.forceDayIfListItem = true;
12933 }
12934 sliceRange(dateRange, dayTableModel) {
12935 return dayTableModel.sliceRange(dateRange);
12936 }
12937 }
12938
12939 class DayTable extends DateComponent {
12940 constructor() {
12941 super(...arguments);
12942 this.slicer = new DayTableSlicer();
12943 this.tableRef = d();
12944 }
12945 render() {
12946 let { props, context } = this;
12947 return (y(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
12948 }
12949 }
12950
12951 class DayTableView extends TableView {
12952 constructor() {
12953 super(...arguments);
12954 this.buildDayTableModel = memoize(buildDayTableModel);
12955 this.headerRef = d();
12956 this.tableRef = d();
12957 // can't override any lifecycle methods from parent
12958 }
12959 render() {
12960 let { options, dateProfileGenerator } = this.context;
12961 let { props } = this;
12962 let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
12963 let headerContent = options.dayHeaders && (y(DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
12964 let bodyContent = (contentArg) => (y(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
12965 return options.dayMinWidth
12966 ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
12967 : this.renderSimpleLayout(headerContent, bodyContent);
12968 }
12969 }
12970 function buildDayTableModel(dateProfile, dateProfileGenerator) {
12971 let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
12972 return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
12973 }
12974
12975 class TableDateProfileGenerator extends DateProfileGenerator {
12976 // Computes the date range that will be rendered
12977 buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
12978 let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
12979 let { props } = this;
12980 return buildDayTableRenderRange({
12981 currentRange: renderRange,
12982 snapToWeek: /^(year|month)$/.test(currentRangeUnit),
12983 fixedWeekCount: props.fixedWeekCount,
12984 dateEnv: props.dateEnv,
12985 });
12986 }
12987 }
12988 function buildDayTableRenderRange(props) {
12989 let { dateEnv, currentRange } = props;
12990 let { start, end } = currentRange;
12991 let endOfWeek;
12992 // year and month views should be aligned with weeks. this is already done for week
12993 if (props.snapToWeek) {
12994 start = dateEnv.startOfWeek(start);
12995 // make end-of-week if not already
12996 endOfWeek = dateEnv.startOfWeek(end);
12997 if (endOfWeek.valueOf() !== end.valueOf()) {
12998 end = addWeeks(endOfWeek, 1);
12999 }
13000 }
13001 // ensure 6 weeks
13002 if (props.fixedWeekCount) {
13003 // TODO: instead of these date-math gymnastics (for multimonth view),
13004 // compute dateprofiles of all months, then use start of first and end of last.
13005 let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
13006 let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
13007 diffWeeks(lastMonthRenderStart, end));
13008 end = addWeeks(end, 6 - rowCnt);
13009 }
13010 return { start, end };
13011 }
13012
13013 var css_248z$3 = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
13014 injectStyles(css_248z$3);
13015
13016 var index$3 = createPlugin({
13017 name: '@fullcalendar/daygrid',
13018 initialView: 'dayGridMonth',
13019 views: {
13020 dayGrid: {
13021 component: DayTableView,
13022 dateProfileGeneratorClass: TableDateProfileGenerator,
13023 },
13024 dayGridDay: {
13025 type: 'dayGrid',
13026 duration: { days: 1 },
13027 },
13028 dayGridWeek: {
13029 type: 'dayGrid',
13030 duration: { weeks: 1 },
13031 },
13032 dayGridMonth: {
13033 type: 'dayGrid',
13034 duration: { months: 1 },
13035 fixedWeekCount: true,
13036 },
13037 dayGridYear: {
13038 type: 'dayGrid',
13039 duration: { years: 1 },
13040 },
13041 },
13042 });
13043
13044 class AllDaySplitter extends Splitter {
13045 getKeyInfo() {
13046 return {
13047 allDay: {},
13048 timed: {},
13049 };
13050 }
13051 getKeysForDateSpan(dateSpan) {
13052 if (dateSpan.allDay) {
13053 return ['allDay'];
13054 }
13055 return ['timed'];
13056 }
13057 getKeysForEventDef(eventDef) {
13058 if (!eventDef.allDay) {
13059 return ['timed'];
13060 }
13061 if (hasBgRendering(eventDef)) {
13062 return ['timed', 'allDay'];
13063 }
13064 return ['allDay'];
13065 }
13066 }
13067
13068 const DEFAULT_SLAT_LABEL_FORMAT = createFormatter({
13069 hour: 'numeric',
13070 minute: '2-digit',
13071 omitZeroMinute: true,
13072 meridiem: 'short',
13073 });
13074 function TimeColsAxisCell(props) {
13075 let classNames = [
13076 'fc-timegrid-slot',
13077 'fc-timegrid-slot-label',
13078 props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
13079 ];
13080 return (y(ViewContextType.Consumer, null, (context) => {
13081 if (!props.isLabeled) {
13082 return (y("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
13083 }
13084 let { dateEnv, options, viewApi } = context;
13085 let labelFormat = // TODO: fully pre-parse
13086 options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
13087 Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) :
13088 createFormatter(options.slotLabelFormat);
13089 let renderProps = {
13090 level: 0,
13091 time: props.time,
13092 date: dateEnv.toDate(props.date),
13093 view: viewApi,
13094 text: dateEnv.format(props.date, labelFormat),
13095 };
13096 return (y(ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
13097 'data-time': props.isoTimeStr,
13098 }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent$1, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (y("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
13099 y(InnerContent, { elTag: "div", elClasses: [
13100 'fc-timegrid-slot-label-cushion',
13101 'fc-scrollgrid-shrink-cushion',
13102 ] })))));
13103 }));
13104 }
13105 function renderInnerContent$1(props) {
13106 return props.text;
13107 }
13108
13109 class TimeBodyAxis extends BaseComponent {
13110 render() {
13111 return this.props.slatMetas.map((slatMeta) => (y("tr", { key: slatMeta.key },
13112 y(TimeColsAxisCell, Object.assign({}, slatMeta)))));
13113 }
13114 }
13115
13116 const DEFAULT_WEEK_NUM_FORMAT = createFormatter({ week: 'short' });
13117 const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
13118 class TimeColsView extends DateComponent {
13119 constructor() {
13120 super(...arguments);
13121 this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
13122 this.headerElRef = d();
13123 this.rootElRef = d();
13124 this.scrollerElRef = d();
13125 this.state = {
13126 slatCoords: null,
13127 };
13128 this.handleScrollTopRequest = (scrollTop) => {
13129 let scrollerEl = this.scrollerElRef.current;
13130 if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
13131 scrollerEl.scrollTop = scrollTop;
13132 }
13133 };
13134 /* Header Render Methods
13135 ------------------------------------------------------------------------------------------------------------------*/
13136 this.renderHeadAxis = (rowKey, frameHeight = '') => {
13137 let { options } = this.context;
13138 let { dateProfile } = this.props;
13139 let range = dateProfile.renderRange;
13140 let dayCnt = diffDays(range.start, range.end);
13141 // only do in day views (to avoid doing in week views that dont need it)
13142 let navLinkAttrs = (dayCnt === 1)
13143 ? buildNavLinkAttrs(this.context, range.start, 'week')
13144 : {};
13145 if (options.weekNumbers && rowKey === 'day') {
13146 return (y(WeekNumberContainer, { elTag: "th", elClasses: [
13147 'fc-timegrid-axis',
13148 'fc-scrollgrid-shrink',
13149 ], elAttrs: {
13150 'aria-hidden': true,
13151 }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (y("div", { className: [
13152 'fc-timegrid-axis-frame',
13153 'fc-scrollgrid-shrink-frame',
13154 'fc-timegrid-axis-frame-liquid',
13155 ].join(' '), style: { height: frameHeight } },
13156 y(InnerContent, { elTag: "a", elClasses: [
13157 'fc-timegrid-axis-cushion',
13158 'fc-scrollgrid-shrink-cushion',
13159 'fc-scrollgrid-sync-inner',
13160 ], elAttrs: navLinkAttrs })))));
13161 }
13162 return (y("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
13163 y("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
13164 };
13165 /* Table Component Render Methods
13166 ------------------------------------------------------------------------------------------------------------------*/
13167 // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
13168 // but DayGrid still needs to have classNames on inner elements in order to measure.
13169 this.renderTableRowAxis = (rowHeight) => {
13170 let { options, viewApi } = this.context;
13171 let renderProps = {
13172 text: options.allDayText,
13173 view: viewApi,
13174 };
13175 return (
13176 // TODO: make reusable hook. used in list view too
13177 y(ContentContainer, { elTag: "td", elClasses: [
13178 'fc-timegrid-axis',
13179 'fc-scrollgrid-shrink',
13180 ], elAttrs: {
13181 'aria-hidden': true,
13182 }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner$1, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (y("div", { className: [
13183 'fc-timegrid-axis-frame',
13184 'fc-scrollgrid-shrink-frame',
13185 rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
13186 ].join(' '), style: { height: rowHeight } },
13187 y(InnerContent, { elTag: "span", elClasses: [
13188 'fc-timegrid-axis-cushion',
13189 'fc-scrollgrid-shrink-cushion',
13190 'fc-scrollgrid-sync-inner',
13191 ] })))));
13192 };
13193 this.handleSlatCoords = (slatCoords) => {
13194 this.setState({ slatCoords });
13195 };
13196 }
13197 // rendering
13198 // ----------------------------------------------------------------------------------------------------
13199 renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
13200 let { context, props } = this;
13201 let sections = [];
13202 let stickyHeaderDates = getStickyHeaderDates(context.options);
13203 if (headerRowContent) {
13204 sections.push({
13205 type: 'header',
13206 key: 'header',
13207 isSticky: stickyHeaderDates,
13208 chunk: {
13209 elRef: this.headerElRef,
13210 tableClassName: 'fc-col-header',
13211 rowContent: headerRowContent,
13212 },
13213 });
13214 }
13215 if (allDayContent) {
13216 sections.push({
13217 type: 'body',
13218 key: 'all-day',
13219 chunk: { content: allDayContent },
13220 });
13221 sections.push({
13222 type: 'body',
13223 key: 'all-day-divider',
13224 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
13225 y("tr", { role: "presentation", className: "fc-scrollgrid-section" },
13226 y("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
13227 });
13228 }
13229 sections.push({
13230 type: 'body',
13231 key: 'body',
13232 liquid: true,
13233 expandRows: Boolean(context.options.expandRows),
13234 chunk: {
13235 scrollerElRef: this.scrollerElRef,
13236 content: timeContent,
13237 },
13238 });
13239 return (y(ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
13240 y(SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
13241 }
13242 renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
13243 let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
13244 if (!ScrollGrid) {
13245 throw new Error('No ScrollGrid implementation');
13246 }
13247 let { context, props } = this;
13248 let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
13249 let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
13250 let sections = [];
13251 if (headerRowContent) {
13252 sections.push({
13253 type: 'header',
13254 key: 'header',
13255 isSticky: stickyHeaderDates,
13256 syncRowHeights: true,
13257 chunks: [
13258 {
13259 key: 'axis',
13260 rowContent: (arg) => (y("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
13261 },
13262 {
13263 key: 'cols',
13264 elRef: this.headerElRef,
13265 tableClassName: 'fc-col-header',
13266 rowContent: headerRowContent,
13267 },
13268 ],
13269 });
13270 }
13271 if (allDayContent) {
13272 sections.push({
13273 type: 'body',
13274 key: 'all-day',
13275 syncRowHeights: true,
13276 chunks: [
13277 {
13278 key: 'axis',
13279 rowContent: (contentArg) => (y("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
13280 },
13281 {
13282 key: 'cols',
13283 content: allDayContent,
13284 },
13285 ],
13286 });
13287 sections.push({
13288 key: 'all-day-divider',
13289 type: 'body',
13290 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
13291 y("tr", { role: "presentation", className: "fc-scrollgrid-section" },
13292 y("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
13293 });
13294 }
13295 let isNowIndicator = context.options.nowIndicator;
13296 sections.push({
13297 type: 'body',
13298 key: 'body',
13299 liquid: true,
13300 expandRows: Boolean(context.options.expandRows),
13301 chunks: [
13302 {
13303 key: 'axis',
13304 content: (arg) => (
13305 // TODO: make this now-indicator arrow more DRY with TimeColsContent
13306 y("div", { className: "fc-timegrid-axis-chunk" },
13307 y("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
13308 arg.tableColGroupNode,
13309 y("tbody", null,
13310 y(TimeBodyAxis, { slatMetas: slatMetas }))),
13311 y("div", { className: "fc-timegrid-now-indicator-container" },
13312 y(NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
13313 let nowIndicatorTop = isNowIndicator &&
13314 slatCoords &&
13315 slatCoords.safeComputeTop(nowDate); // might return void
13316 if (typeof nowIndicatorTop === 'number') {
13317 return (y(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
13318 }
13319 return null;
13320 })))),
13321 },
13322 {
13323 key: 'cols',
13324 scrollerElRef: this.scrollerElRef,
13325 content: timeContent,
13326 },
13327 ],
13328 });
13329 if (stickyFooterScrollbar) {
13330 sections.push({
13331 key: 'footer',
13332 type: 'footer',
13333 isSticky: true,
13334 chunks: [
13335 {
13336 key: 'axis',
13337 content: renderScrollShim,
13338 },
13339 {
13340 key: 'cols',
13341 content: renderScrollShim,
13342 },
13343 ],
13344 });
13345 }
13346 return (y(ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
13347 y(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [
13348 { width: 'shrink', cols: [{ width: 'shrink' }] },
13349 { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
13350 ], sections: sections })));
13351 }
13352 /* Dimensions
13353 ------------------------------------------------------------------------------------------------------------------*/
13354 getAllDayMaxEventProps() {
13355 let { dayMaxEvents, dayMaxEventRows } = this.context.options;
13356 if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
13357 dayMaxEvents = undefined;
13358 dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
13359 }
13360 return { dayMaxEvents, dayMaxEventRows };
13361 }
13362 }
13363 function renderAllDayInner$1(renderProps) {
13364 return renderProps.text;
13365 }
13366
13367 class TimeColsSlatsCoords {
13368 constructor(positions, dateProfile, slotDuration) {
13369 this.positions = positions;
13370 this.dateProfile = dateProfile;
13371 this.slotDuration = slotDuration;
13372 }
13373 safeComputeTop(date) {
13374 let { dateProfile } = this;
13375 if (rangeContainsMarker(dateProfile.currentRange, date)) {
13376 let startOfDayDate = startOfDay(date);
13377 let timeMs = date.valueOf() - startOfDayDate.valueOf();
13378 if (timeMs >= asRoughMs(dateProfile.slotMinTime) &&
13379 timeMs < asRoughMs(dateProfile.slotMaxTime)) {
13380 return this.computeTimeTop(createDuration(timeMs));
13381 }
13382 }
13383 return null;
13384 }
13385 // Computes the top coordinate, relative to the bounds of the grid, of the given date.
13386 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
13387 computeDateTop(when, startOfDayDate) {
13388 if (!startOfDayDate) {
13389 startOfDayDate = startOfDay(when);
13390 }
13391 return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
13392 }
13393 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
13394 // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
13395 // Eventually allow computation with arbirary slat dates.
13396 computeTimeTop(duration) {
13397 let { positions, dateProfile } = this;
13398 let len = positions.els.length;
13399 // floating-point value of # of slots covered
13400 let slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration);
13401 let slatIndex;
13402 let slatRemainder;
13403 // compute a floating-point number for how many slats should be progressed through.
13404 // from 0 to number of slats (inclusive)
13405 // constrained because slotMinTime/slotMaxTime might be customized.
13406 slatCoverage = Math.max(0, slatCoverage);
13407 slatCoverage = Math.min(len, slatCoverage);
13408 // an integer index of the furthest whole slat
13409 // from 0 to number slats (*exclusive*, so len-1)
13410 slatIndex = Math.floor(slatCoverage);
13411 slatIndex = Math.min(slatIndex, len - 1);
13412 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
13413 // could be 1.0 if slatCoverage is covering *all* the slots
13414 slatRemainder = slatCoverage - slatIndex;
13415 return positions.tops[slatIndex] +
13416 positions.getHeight(slatIndex) * slatRemainder;
13417 }
13418 }
13419
13420 class TimeColsSlatsBody extends BaseComponent {
13421 render() {
13422 let { props, context } = this;
13423 let { options } = context;
13424 let { slatElRefs } = props;
13425 return (y("tbody", null, props.slatMetas.map((slatMeta, i) => {
13426 let renderProps = {
13427 time: slatMeta.time,
13428 date: context.dateEnv.toDate(slatMeta.date),
13429 view: context.viewApi,
13430 };
13431 return (y("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
13432 props.axis && (y(TimeColsAxisCell, Object.assign({}, slatMeta))),
13433 y(ContentContainer, { elTag: "td", elClasses: [
13434 'fc-timegrid-slot',
13435 'fc-timegrid-slot-lane',
13436 !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
13437 ], elAttrs: {
13438 'data-time': slatMeta.isoTimeStr,
13439 }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
13440 })));
13441 }
13442 }
13443
13444 /*
13445 for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
13446 */
13447 class TimeColsSlats extends BaseComponent {
13448 constructor() {
13449 super(...arguments);
13450 this.rootElRef = d();
13451 this.slatElRefs = new RefMap();
13452 }
13453 render() {
13454 let { props, context } = this;
13455 return (y("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
13456 y("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
13457 minWidth: props.tableMinWidth,
13458 width: props.clientWidth,
13459 height: props.minHeight,
13460 } },
13461 props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
13462 y(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
13463 }
13464 componentDidMount() {
13465 this.updateSizing();
13466 }
13467 componentDidUpdate() {
13468 this.updateSizing();
13469 }
13470 componentWillUnmount() {
13471 if (this.props.onCoords) {
13472 this.props.onCoords(null);
13473 }
13474 }
13475 updateSizing() {
13476 let { context, props } = this;
13477 if (props.onCoords &&
13478 props.clientWidth !== null // means sizing has stabilized
13479 ) {
13480 let rootEl = this.rootElRef.current;
13481 if (rootEl.offsetHeight) { // not hidden by css
13482 props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
13483 }
13484 }
13485 }
13486 }
13487 function collectSlatEls(elMap, slatMetas) {
13488 return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
13489 }
13490
13491 function splitSegsByCol(segs, colCnt) {
13492 let segsByCol = [];
13493 let i;
13494 for (i = 0; i < colCnt; i += 1) {
13495 segsByCol.push([]);
13496 }
13497 if (segs) {
13498 for (i = 0; i < segs.length; i += 1) {
13499 segsByCol[segs[i].col].push(segs[i]);
13500 }
13501 }
13502 return segsByCol;
13503 }
13504 function splitInteractionByCol(ui, colCnt) {
13505 let byRow = [];
13506 if (!ui) {
13507 for (let i = 0; i < colCnt; i += 1) {
13508 byRow[i] = null;
13509 }
13510 }
13511 else {
13512 for (let i = 0; i < colCnt; i += 1) {
13513 byRow[i] = {
13514 affectedInstances: ui.affectedInstances,
13515 isEvent: ui.isEvent,
13516 segs: [],
13517 };
13518 }
13519 for (let seg of ui.segs) {
13520 byRow[seg.col].segs.push(seg);
13521 }
13522 }
13523 return byRow;
13524 }
13525
13526 class TimeColMoreLink extends BaseComponent {
13527 render() {
13528 let { props } = this;
13529 return (y(MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
13530 top: props.top,
13531 bottom: props.bottom,
13532 }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner, forceTimed: true }, (InnerContent) => (y(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
13533 }
13534 }
13535 function renderMoreLinkInner(props) {
13536 return props.shortText;
13537 }
13538
13539 // segInputs assumed sorted
13540 function buildPositioning(segInputs, strictOrder, maxStackCnt) {
13541 let hierarchy = new SegHierarchy();
13542 if (strictOrder != null) {
13543 hierarchy.strictOrder = strictOrder;
13544 }
13545 if (maxStackCnt != null) {
13546 hierarchy.maxStackCnt = maxStackCnt;
13547 }
13548 let hiddenEntries = hierarchy.addSegs(segInputs);
13549 let hiddenGroups = groupIntersectingEntries(hiddenEntries);
13550 let web = buildWeb(hierarchy);
13551 web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
13552 let segRects = webToRects(web);
13553 return { segRects, hiddenGroups };
13554 }
13555 function buildWeb(hierarchy) {
13556 const { entriesByLevel } = hierarchy;
13557 const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
13558 let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
13559 let nextLevelRes = buildNodes(siblingRange, buildNode);
13560 let entry = entriesByLevel[level][lateral];
13561 return [
13562 Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
13563 entry.thickness + nextLevelRes[1], // the pressure builds
13564 ];
13565 });
13566 return buildNodes(entriesByLevel.length
13567 ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
13568 : null, buildNode)[0];
13569 }
13570 function buildNodes(siblingRange, buildNode) {
13571 if (!siblingRange) {
13572 return [[], 0];
13573 }
13574 let { level, lateralStart, lateralEnd } = siblingRange;
13575 let lateral = lateralStart;
13576 let pairs = [];
13577 while (lateral < lateralEnd) {
13578 pairs.push(buildNode(level, lateral));
13579 lateral += 1;
13580 }
13581 pairs.sort(cmpDescPressures);
13582 return [
13583 pairs.map(extractNode),
13584 pairs[0][1], // first item's pressure
13585 ];
13586 }
13587 function cmpDescPressures(a, b) {
13588 return b[1] - a[1];
13589 }
13590 function extractNode(a) {
13591 return a[0];
13592 }
13593 function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
13594 let { levelCoords, entriesByLevel } = hierarchy;
13595 let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
13596 let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
13597 let levelCnt = levelCoords.length;
13598 let level = subjectLevel;
13599 // skip past levels that are too high up
13600 for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
13601 ; // do nothing
13602 for (; level < levelCnt; level += 1) {
13603 let entries = entriesByLevel[level];
13604 let entry;
13605 let searchIndex = binarySearch(entries, subjectEntry.span.start, getEntrySpanEnd);
13606 let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
13607 let lateralEnd = lateralStart;
13608 while ( // loop through entries that horizontally intersect
13609 (entry = entries[lateralEnd]) && // but not past the whole seg list
13610 entry.span.start < subjectEntry.span.end) {
13611 lateralEnd += 1;
13612 }
13613 if (lateralStart < lateralEnd) {
13614 return { level, lateralStart, lateralEnd };
13615 }
13616 }
13617 return null;
13618 }
13619 function stretchWeb(topLevelNodes, totalThickness) {
13620 const stretchNode = cacheable((node, startCoord, prevThickness) => buildEntryKey(node), (node, startCoord, prevThickness) => {
13621 let { nextLevelNodes, thickness } = node;
13622 let allThickness = thickness + prevThickness;
13623 let thicknessFraction = thickness / allThickness;
13624 let endCoord;
13625 let newChildren = [];
13626 if (!nextLevelNodes.length) {
13627 endCoord = totalThickness;
13628 }
13629 else {
13630 for (let childNode of nextLevelNodes) {
13631 if (endCoord === undefined) {
13632 let res = stretchNode(childNode, startCoord, allThickness);
13633 endCoord = res[0];
13634 newChildren.push(res[1]);
13635 }
13636 else {
13637 let res = stretchNode(childNode, endCoord, 0);
13638 newChildren.push(res[1]);
13639 }
13640 }
13641 }
13642 let newThickness = (endCoord - startCoord) * thicknessFraction;
13643 return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
13644 });
13645 return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
13646 }
13647 // not sorted in any particular order
13648 function webToRects(topLevelNodes) {
13649 let rects = [];
13650 const processNode = cacheable((node, levelCoord, stackDepth) => buildEntryKey(node), (node, levelCoord, stackDepth) => {
13651 let rect = Object.assign(Object.assign({}, node), { levelCoord,
13652 stackDepth, stackForward: 0 });
13653 rects.push(rect);
13654 return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
13655 });
13656 function processNodes(nodes, levelCoord, stackDepth) {
13657 let stackForward = 0;
13658 for (let node of nodes) {
13659 stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
13660 }
13661 return stackForward;
13662 }
13663 processNodes(topLevelNodes, 0, 0);
13664 return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
13665 }
13666 // TODO: move to general util
13667 function cacheable(keyFunc, workFunc) {
13668 const cache = {};
13669 return (...args) => {
13670 let key = keyFunc(...args);
13671 return (key in cache)
13672 ? cache[key]
13673 : (cache[key] = workFunc(...args));
13674 };
13675 }
13676
13677 function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
13678 let vcoords = [];
13679 if (slatCoords) {
13680 for (let i = 0; i < segs.length; i += 1) {
13681 let seg = segs[i];
13682 let spanStart = slatCoords.computeDateTop(seg.start, colDate);
13683 let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
13684 slatCoords.computeDateTop(seg.end, colDate));
13685 vcoords.push({
13686 start: Math.round(spanStart),
13687 end: Math.round(spanEnd), //
13688 });
13689 }
13690 }
13691 return vcoords;
13692 }
13693 function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
13694 eventOrderStrict, eventMaxStack) {
13695 let segInputs = [];
13696 let dumbSegs = []; // segs without coords
13697 for (let i = 0; i < segs.length; i += 1) {
13698 let vcoords = segVCoords[i];
13699 if (vcoords) {
13700 segInputs.push({
13701 index: i,
13702 thickness: 1,
13703 span: vcoords,
13704 });
13705 }
13706 else {
13707 dumbSegs.push(segs[i]);
13708 }
13709 }
13710 let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
13711 let segPlacements = [];
13712 for (let segRect of segRects) {
13713 segPlacements.push({
13714 seg: segs[segRect.index],
13715 rect: segRect,
13716 });
13717 }
13718 for (let dumbSeg of dumbSegs) {
13719 segPlacements.push({ seg: dumbSeg, rect: null });
13720 }
13721 return { segPlacements, hiddenGroups };
13722 }
13723
13724 const DEFAULT_TIME_FORMAT$1 = createFormatter({
13725 hour: 'numeric',
13726 minute: '2-digit',
13727 meridiem: false,
13728 });
13729 class TimeColEvent extends BaseComponent {
13730 render() {
13731 return (y(StandardEvent, Object.assign({}, this.props, { elClasses: [
13732 'fc-timegrid-event',
13733 'fc-v-event',
13734 this.props.isShort && 'fc-timegrid-event-short',
13735 ], defaultTimeFormat: DEFAULT_TIME_FORMAT$1 })));
13736 }
13737 }
13738
13739 class TimeCol extends BaseComponent {
13740 constructor() {
13741 super(...arguments);
13742 this.sortEventSegs = memoize(sortEventSegs);
13743 }
13744 // TODO: memoize event-placement?
13745 render() {
13746 let { props, context } = this;
13747 let { options } = context;
13748 let isSelectMirror = options.selectMirror;
13749 let mirrorSegs = // yuck
13750 (props.eventDrag && props.eventDrag.segs) ||
13751 (props.eventResize && props.eventResize.segs) ||
13752 (isSelectMirror && props.dateSelectionSegs) ||
13753 [];
13754 let interactionAffectedInstances = // TODO: messy way to compute this
13755 (props.eventDrag && props.eventDrag.affectedInstances) ||
13756 (props.eventResize && props.eventResize.affectedInstances) ||
13757 {};
13758 let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
13759 return (y(DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
13760 'fc-timegrid-col',
13761 ...(props.extraClassNames || []),
13762 ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (y("div", { className: "fc-timegrid-col-frame" },
13763 y("div", { className: "fc-timegrid-col-bg" },
13764 this.renderFillSegs(props.businessHourSegs, 'non-business'),
13765 this.renderFillSegs(props.bgEventSegs, 'bg-event'),
13766 this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
13767 y("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
13768 y("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),
13769 y("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
13770 hasCustomDayCellContent(options) && (y(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
13771 }
13772 renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
13773 let { props } = this;
13774 if (props.forPrint) {
13775 return renderPlainFgSegs(sortedFgSegs, props);
13776 }
13777 return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);
13778 }
13779 renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
13780 segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
13781 let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
13782 let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
13783 let isMirror = isDragging || isResizing || isDateSelecting;
13784 let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
13785 let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
13786 return (y(_, null,
13787 this.renderHiddenGroups(hiddenGroups, segs),
13788 segPlacements.map((segPlacement) => {
13789 let { seg, rect } = segPlacement;
13790 let instanceId = seg.eventRange.instance.instanceId;
13791 let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
13792 let vStyle = computeSegVStyle(rect && rect.span);
13793 let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
13794 let isInset = Boolean(rect) && rect.stackForward > 0;
13795 let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
13796 return (y("div", { className: 'fc-timegrid-event-harness' +
13797 (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: forcedKey || instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
13798 y(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, getSegMeta(seg, todayRange, nowDate)))));
13799 })));
13800 }
13801 // will already have eventMinHeight applied because segInputs already had it
13802 renderHiddenGroups(hiddenGroups, segs) {
13803 let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
13804 return (y(_, null, hiddenGroups.map((hiddenGroup) => {
13805 let positionCss = computeSegVStyle(hiddenGroup.span);
13806 let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
13807 return (y(TimeColMoreLink, { key: buildIsoString(computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
13808 })));
13809 }
13810 renderFillSegs(segs, fillType) {
13811 let { props, context } = this;
13812 let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
13813 let children = segVCoords.map((vcoords, i) => {
13814 let seg = segs[i];
13815 return (y("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
13816 y(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, props.todayRange, props.nowDate))) :
13817 renderFill(fillType)));
13818 });
13819 return y(_, null, children);
13820 }
13821 renderNowIndicator(segs) {
13822 let { slatCoords, date } = this.props;
13823 if (!slatCoords) {
13824 return null;
13825 }
13826 return segs.map((seg, i) => (y(NowIndicatorContainer
13827 // key doesn't matter. will only ever be one
13828 , {
13829 // key doesn't matter. will only ever be one
13830 key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
13831 top: slatCoords.computeDateTop(seg.start, date),
13832 }, isAxis: false, date: date })));
13833 }
13834 computeSegHStyle(segHCoords) {
13835 let { isRtl, options } = this.context;
13836 let shouldOverlap = options.slotEventOverlap;
13837 let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
13838 let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
13839 let left; // amount of space from left edge, a fraction of the total width
13840 let right; // amount of space from right edge, a fraction of the total width
13841 if (shouldOverlap) {
13842 // double the width, but don't go beyond the maximum forward coordinate (1.0)
13843 farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
13844 }
13845 if (isRtl) {
13846 left = 1 - farCoord;
13847 right = nearCoord;
13848 }
13849 else {
13850 left = nearCoord;
13851 right = 1 - farCoord;
13852 }
13853 let props = {
13854 zIndex: segHCoords.stackDepth + 1,
13855 left: left * 100 + '%',
13856 right: right * 100 + '%',
13857 };
13858 if (shouldOverlap && !segHCoords.stackForward) {
13859 // add padding to the edge so that forward stacked events don't cover the resizer's icon
13860 props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
13861 }
13862 return props;
13863 }
13864 }
13865 function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
13866 let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
13867 (eventResize ? eventResize.affectedInstances : null) ||
13868 {};
13869 return (y(_, null, sortedFgSegs.map((seg) => {
13870 let instanceId = seg.eventRange.instance.instanceId;
13871 return (y("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
13872 y(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, getSegMeta(seg, todayRange, nowDate)))));
13873 })));
13874 }
13875 function computeSegVStyle(segVCoords) {
13876 if (!segVCoords) {
13877 return { top: '', bottom: '' };
13878 }
13879 return {
13880 top: segVCoords.start,
13881 bottom: -segVCoords.end,
13882 };
13883 }
13884 function compileSegsFromEntries(segEntries, allSegs) {
13885 return segEntries.map((segEntry) => allSegs[segEntry.index]);
13886 }
13887
13888 class TimeColsContent extends BaseComponent {
13889 constructor() {
13890 super(...arguments);
13891 this.splitFgEventSegs = memoize(splitSegsByCol);
13892 this.splitBgEventSegs = memoize(splitSegsByCol);
13893 this.splitBusinessHourSegs = memoize(splitSegsByCol);
13894 this.splitNowIndicatorSegs = memoize(splitSegsByCol);
13895 this.splitDateSelectionSegs = memoize(splitSegsByCol);
13896 this.splitEventDrag = memoize(splitInteractionByCol);
13897 this.splitEventResize = memoize(splitInteractionByCol);
13898 this.rootElRef = d();
13899 this.cellElRefs = new RefMap();
13900 }
13901 render() {
13902 let { props, context } = this;
13903 let nowIndicatorTop = context.options.nowIndicator &&
13904 props.slatCoords &&
13905 props.slatCoords.safeComputeTop(props.nowDate); // might return void
13906 let colCnt = props.cells.length;
13907 let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
13908 let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
13909 let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
13910 let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
13911 let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
13912 let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
13913 let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
13914 return (y("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
13915 y("table", { role: "presentation", style: {
13916 minWidth: props.tableMinWidth,
13917 width: props.clientWidth,
13918 } },
13919 props.tableColGroupNode,
13920 y("tbody", { role: "presentation" },
13921 y("tr", { role: "row" },
13922 props.axis && (y("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
13923 y("div", { className: "fc-timegrid-col-frame" },
13924 y("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (y(NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
13925 props.cells.map((cell, i) => (y(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
13926 }
13927 componentDidMount() {
13928 this.updateCoords();
13929 }
13930 componentDidUpdate() {
13931 this.updateCoords();
13932 }
13933 updateCoords() {
13934 let { props } = this;
13935 if (props.onColCoords &&
13936 props.clientWidth !== null // means sizing has stabilized
13937 ) {
13938 props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
13939 false));
13940 }
13941 }
13942 }
13943 function collectCellEls(elMap, cells) {
13944 return cells.map((cell) => elMap[cell.key]);
13945 }
13946
13947 /* A component that renders one or more columns of vertical time slots
13948 ----------------------------------------------------------------------------------------------------------------------*/
13949 class TimeCols extends DateComponent {
13950 constructor() {
13951 super(...arguments);
13952 this.processSlotOptions = memoize(processSlotOptions);
13953 this.state = {
13954 slatCoords: null,
13955 };
13956 this.handleRootEl = (el) => {
13957 if (el) {
13958 this.context.registerInteractiveComponent(this, {
13959 el,
13960 isHitComboAllowed: this.props.isHitComboAllowed,
13961 });
13962 }
13963 else {
13964 this.context.unregisterInteractiveComponent(this);
13965 }
13966 };
13967 this.handleScrollRequest = (request) => {
13968 let { onScrollTopRequest } = this.props;
13969 let { slatCoords } = this.state;
13970 if (onScrollTopRequest && slatCoords) {
13971 if (request.time) {
13972 let top = slatCoords.computeTimeTop(request.time);
13973 top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
13974 if (top) {
13975 top += 1; // to overcome top border that slots beyond the first have. looks better
13976 }
13977 onScrollTopRequest(top);
13978 }
13979 return true;
13980 }
13981 return false;
13982 };
13983 this.handleColCoords = (colCoords) => {
13984 this.colCoords = colCoords;
13985 };
13986 this.handleSlatCoords = (slatCoords) => {
13987 this.setState({ slatCoords });
13988 if (this.props.onSlatCoords) {
13989 this.props.onSlatCoords(slatCoords);
13990 }
13991 };
13992 }
13993 render() {
13994 let { props, state } = this;
13995 return (y("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
13996 // these props are important to give this wrapper correct dimensions for interactions
13997 // TODO: if we set it here, can we avoid giving to inner tables?
13998 width: props.clientWidth,
13999 minWidth: props.tableMinWidth,
14000 } },
14001 y(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),
14002 y(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
14003 }
14004 componentDidMount() {
14005 this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
14006 }
14007 componentDidUpdate(prevProps) {
14008 this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
14009 }
14010 componentWillUnmount() {
14011 this.scrollResponder.detach();
14012 }
14013 queryHit(positionLeft, positionTop) {
14014 let { dateEnv, options } = this.context;
14015 let { colCoords } = this;
14016 let { dateProfile } = this.props;
14017 let { slatCoords } = this.state;
14018 let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
14019 let colIndex = colCoords.leftToIndex(positionLeft);
14020 let slatIndex = slatCoords.positions.topToIndex(positionTop);
14021 if (colIndex != null && slatIndex != null) {
14022 let cell = this.props.cells[colIndex];
14023 let slatTop = slatCoords.positions.tops[slatIndex];
14024 let slatHeight = slatCoords.positions.getHeight(slatIndex);
14025 let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
14026 let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
14027 let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
14028 let dayDate = this.props.cells[colIndex].date;
14029 let time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex));
14030 let start = dateEnv.add(dayDate, time);
14031 let end = dateEnv.add(start, snapDuration);
14032 return {
14033 dateProfile,
14034 dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
14035 dayEl: colCoords.els[colIndex],
14036 rect: {
14037 left: colCoords.lefts[colIndex],
14038 right: colCoords.rights[colIndex],
14039 top: slatTop,
14040 bottom: slatTop + slatHeight,
14041 },
14042 layer: 0,
14043 };
14044 }
14045 return null;
14046 }
14047 }
14048 function processSlotOptions(slotDuration, snapDurationOverride) {
14049 let snapDuration = snapDurationOverride || slotDuration;
14050 let snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
14051 if (snapsPerSlot === null) {
14052 snapDuration = slotDuration;
14053 snapsPerSlot = 1;
14054 // TODO: say warning?
14055 }
14056 return { snapDuration, snapsPerSlot };
14057 }
14058
14059 class DayTimeColsSlicer extends Slicer {
14060 sliceRange(range, dayRanges) {
14061 let segs = [];
14062 for (let col = 0; col < dayRanges.length; col += 1) {
14063 let segRange = intersectRanges(range, dayRanges[col]);
14064 if (segRange) {
14065 segs.push({
14066 start: segRange.start,
14067 end: segRange.end,
14068 isStart: segRange.start.valueOf() === range.start.valueOf(),
14069 isEnd: segRange.end.valueOf() === range.end.valueOf(),
14070 col,
14071 });
14072 }
14073 }
14074 return segs;
14075 }
14076 }
14077
14078 class DayTimeCols extends DateComponent {
14079 constructor() {
14080 super(...arguments);
14081 this.buildDayRanges = memoize(buildDayRanges);
14082 this.slicer = new DayTimeColsSlicer();
14083 this.timeColsRef = d();
14084 }
14085 render() {
14086 let { props, context } = this;
14087 let { dateProfile, dayTableModel } = props;
14088 let { nowIndicator, nextDayThreshold } = context.options;
14089 let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
14090 // give it the first row of cells
14091 // TODO: would move this further down hierarchy, but sliceNowDate needs it
14092 return (y(NowTimer, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (y(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
14093 }
14094 }
14095 function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
14096 let ranges = [];
14097 for (let date of dayTableModel.headerDates) {
14098 ranges.push({
14099 start: dateEnv.add(date, dateProfile.slotMinTime),
14100 end: dateEnv.add(date, dateProfile.slotMaxTime),
14101 });
14102 }
14103 return ranges;
14104 }
14105
14106 // potential nice values for the slot-duration and interval-duration
14107 // from largest to smallest
14108 const STOCK_SUB_DURATIONS = [
14109 { hours: 1 },
14110 { minutes: 30 },
14111 { minutes: 15 },
14112 { seconds: 30 },
14113 { seconds: 15 },
14114 ];
14115 function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
14116 let dayStart = new Date(0);
14117 let slatTime = slotMinTime;
14118 let slatIterator = createDuration(0);
14119 let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
14120 let metas = [];
14121 while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) {
14122 let date = dateEnv.add(dayStart, slatTime);
14123 let isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null;
14124 metas.push({
14125 date,
14126 time: slatTime,
14127 key: date.toISOString(),
14128 isoTimeStr: formatIsoTimeString(date),
14129 isLabeled,
14130 });
14131 slatTime = addDurations(slatTime, slotDuration);
14132 slatIterator = addDurations(slatIterator, slotDuration);
14133 }
14134 return metas;
14135 }
14136 // Computes an automatic value for slotLabelInterval
14137 function computeLabelInterval(slotDuration) {
14138 let i;
14139 let labelInterval;
14140 let slotsPerLabel;
14141 // find the smallest stock label interval that results in more than one slots-per-label
14142 for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
14143 labelInterval = createDuration(STOCK_SUB_DURATIONS[i]);
14144 slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
14145 if (slotsPerLabel !== null && slotsPerLabel > 1) {
14146 return labelInterval;
14147 }
14148 }
14149 return slotDuration; // fall back
14150 }
14151
14152 class DayTimeColsView extends TimeColsView {
14153 constructor() {
14154 super(...arguments);
14155 this.buildTimeColsModel = memoize(buildTimeColsModel);
14156 this.buildSlatMetas = memoize(buildSlatMetas);
14157 }
14158 render() {
14159 let { options, dateEnv, dateProfileGenerator } = this.context;
14160 let { props } = this;
14161 let { dateProfile } = props;
14162 let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
14163 let splitProps = this.allDaySplitter.splitProps(props);
14164 let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
14165 let { dayMinWidth } = options;
14166 let hasAttachedAxis = !dayMinWidth;
14167 let hasDetachedAxis = dayMinWidth;
14168 let headerContent = options.dayHeaders && (y(DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
14169 let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (y(DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
14170 let timeGridContent = (contentArg) => (y(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
14171 return hasDetachedAxis
14172 ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
14173 : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
14174 }
14175 }
14176 function buildTimeColsModel(dateProfile, dateProfileGenerator) {
14177 let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
14178 return new DayTableModel(daySeries, false);
14179 }
14180
14181 var css_248z$2 = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
14182 injectStyles(css_248z$2);
14183
14184 const OPTION_REFINERS$2 = {
14185 allDaySlot: Boolean,
14186 };
14187
14188 var index$2 = createPlugin({
14189 name: '@fullcalendar/timegrid',
14190 initialView: 'timeGridWeek',
14191 optionRefiners: OPTION_REFINERS$2,
14192 views: {
14193 timeGrid: {
14194 component: DayTimeColsView,
14195 usesMinMaxTime: true,
14196 allDaySlot: true,
14197 slotDuration: '00:30:00',
14198 slotEventOverlap: true, // a bad name. confused with overlap/constraint system
14199 },
14200 timeGridDay: {
14201 type: 'timeGrid',
14202 duration: { days: 1 },
14203 },
14204 timeGridWeek: {
14205 type: 'timeGrid',
14206 duration: { weeks: 1 },
14207 },
14208 },
14209 });
14210
14211 class ListViewHeaderRow extends BaseComponent {
14212 constructor() {
14213 super(...arguments);
14214 this.state = {
14215 textId: getUniqueDomId(),
14216 };
14217 }
14218 render() {
14219 let { theme, dateEnv, options, viewApi } = this.context;
14220 let { cellId, dayDate, todayRange } = this.props;
14221 let { textId } = this.state;
14222 let dayMeta = getDateMeta(dayDate, todayRange);
14223 // will ever be falsy?
14224 let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
14225 // will ever be falsy? also, BAD NAME "alt"
14226 let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
14227 let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,
14228 text,
14229 sideText, navLinkAttrs: buildNavLinkAttrs(this.context, dayDate), sideNavLinkAttrs: buildNavLinkAttrs(this.context, dayDate, 'day', false) }, dayMeta);
14230 // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
14231 return (y(ContentContainer, { elTag: "tr", elClasses: [
14232 'fc-list-day',
14233 ...getDayClassNames(dayMeta, theme),
14234 ], elAttrs: {
14235 'data-date': formatDayString(dayDate),
14236 }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
14237 y("th", { scope: "colgroup", colSpan: 3, id: cellId, "aria-labelledby": textId },
14238 y(InnerContent, { elTag: "div", elClasses: [
14239 'fc-list-day-cushion',
14240 theme.getClass('tableCellShaded'),
14241 ] })))));
14242 }
14243 }
14244 function renderInnerContent(props) {
14245 return (y(_, null,
14246 props.text && (y("a", Object.assign({ id: props.textId, className: "fc-list-day-text" }, props.navLinkAttrs), props.text)),
14247 props.sideText && ( /* not keyboard tabbable */y("a", Object.assign({ "aria-hidden": true, className: "fc-list-day-side-text" }, props.sideNavLinkAttrs), props.sideText))));
14248 }
14249
14250 const DEFAULT_TIME_FORMAT = createFormatter({
14251 hour: 'numeric',
14252 minute: '2-digit',
14253 meridiem: 'short',
14254 });
14255 class ListViewEventRow extends BaseComponent {
14256 render() {
14257 let { props, context } = this;
14258 let { options } = context;
14259 let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;
14260 let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
14261 return (y(EventContainer, Object.assign({}, props, { elTag: "tr", elClasses: [
14262 'fc-list-event',
14263 seg.eventRange.def.url && 'fc-event-forced-url',
14264 ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: "", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => (y(_, null,
14265 buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
14266 y("td", { "aria-hidden": true, className: "fc-list-event-graphic" },
14267 y("span", { className: "fc-list-event-dot", style: {
14268 borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
14269 } })),
14270 y(InnerContent, { elTag: "td", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));
14271 }
14272 }
14273 function renderEventInnerContent(seg, context) {
14274 let interactiveAttrs = getSegAnchorAttrs(seg, context);
14275 return (y("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
14276 }
14277 function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
14278 let { options } = context;
14279 if (options.displayEventTime !== false) {
14280 let eventDef = seg.eventRange.def;
14281 let eventInstance = seg.eventRange.instance;
14282 let doAllDay = false;
14283 let timeText;
14284 if (eventDef.allDay) {
14285 doAllDay = true;
14286 }
14287 else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
14288 if (seg.isStart) {
14289 timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
14290 }
14291 else if (seg.isEnd) {
14292 timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
14293 }
14294 else {
14295 doAllDay = true;
14296 }
14297 }
14298 else {
14299 timeText = buildSegTimeText(seg, timeFormat, context);
14300 }
14301 if (doAllDay) {
14302 let renderProps = {
14303 text: context.options.allDayText,
14304 view: context.viewApi,
14305 };
14306 return (y(ContentContainer, { elTag: "td", elClasses: ['fc-list-event-time'], elAttrs: {
14307 headers: `${timeHeaderId} ${dateHeaderId}`,
14308 }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));
14309 }
14310 return (y("td", { className: "fc-list-event-time" }, timeText));
14311 }
14312 return null;
14313 }
14314 function renderAllDayInner(renderProps) {
14315 return renderProps.text;
14316 }
14317
14318 /*
14319 Responsible for the scroller, and forwarding event-related actions into the "grid".
14320 */
14321 class ListView extends DateComponent {
14322 constructor() {
14323 super(...arguments);
14324 this.computeDateVars = memoize(computeDateVars);
14325 this.eventStoreToSegs = memoize(this._eventStoreToSegs);
14326 this.state = {
14327 timeHeaderId: getUniqueDomId(),
14328 eventHeaderId: getUniqueDomId(),
14329 dateHeaderIdRoot: getUniqueDomId(),
14330 };
14331 this.setRootEl = (rootEl) => {
14332 if (rootEl) {
14333 this.context.registerInteractiveComponent(this, {
14334 el: rootEl,
14335 });
14336 }
14337 else {
14338 this.context.unregisterInteractiveComponent(this);
14339 }
14340 };
14341 }
14342 render() {
14343 let { props, context } = this;
14344 let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);
14345 let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
14346 return (y(ViewContainer, { elRef: this.setRootEl, elClasses: [
14347 'fc-list',
14348 context.theme.getClass('table'),
14349 context.options.stickyHeaderDates !== false ?
14350 'fc-list-sticky' :
14351 '',
14352 ], viewSpec: context.viewSpec },
14353 y(Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?
14354 this.renderSegList(eventSegs, dayDates) :
14355 this.renderEmptyMessage())));
14356 }
14357 renderEmptyMessage() {
14358 let { options, viewApi } = this.context;
14359 let renderProps = {
14360 text: options.noEventsText,
14361 view: viewApi,
14362 };
14363 return (y(ContentContainer, { elTag: "div", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: "noEventsContent", customGenerator: options.noEventsContent, defaultGenerator: renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => (y(InnerContent, { elTag: "div", elClasses: ['fc-list-empty-cushion'] }))));
14364 }
14365 renderSegList(allSegs, dayDates) {
14366 let { theme, options } = this.context;
14367 let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;
14368 let segsByDay = groupSegsByDay(allSegs); // sparse array
14369 return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => {
14370 let innerNodes = [];
14371 for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
14372 let daySegs = segsByDay[dayIndex];
14373 if (daySegs) { // sparse array, so might be undefined
14374 let dayStr = formatDayString(dayDates[dayIndex]);
14375 let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
14376 // append a day header
14377 innerNodes.push(y(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));
14378 daySegs = sortEventSegs(daySegs, options.eventOrder);
14379 for (let seg of daySegs) {
14380 innerNodes.push(y(ListViewEventRow, Object.assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, timeHeaderId: timeHeaderId, eventHeaderId: eventHeaderId, dateHeaderId: dateHeaderId }, getSegMeta(seg, todayRange, nowDate))));
14381 }
14382 }
14383 }
14384 return (y("table", { className: 'fc-list-table ' + theme.getClass('table') },
14385 y("thead", null,
14386 y("tr", null,
14387 y("th", { scope: "col", id: timeHeaderId }, options.timeHint),
14388 y("th", { scope: "col", "aria-hidden": true }),
14389 y("th", { scope: "col", id: eventHeaderId }, options.eventHint))),
14390 y("tbody", null, innerNodes)));
14391 }));
14392 }
14393 _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
14394 return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
14395 }
14396 eventRangesToSegs(eventRanges, dayRanges) {
14397 let segs = [];
14398 for (let eventRange of eventRanges) {
14399 segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
14400 }
14401 return segs;
14402 }
14403 eventRangeToSegs(eventRange, dayRanges) {
14404 let { dateEnv } = this.context;
14405 let { nextDayThreshold } = this.context.options;
14406 let range = eventRange.range;
14407 let allDay = eventRange.def.allDay;
14408 let dayIndex;
14409 let segRange;
14410 let seg;
14411 let segs = [];
14412 for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
14413 segRange = intersectRanges(range, dayRanges[dayIndex]);
14414 if (segRange) {
14415 seg = {
14416 component: this,
14417 eventRange,
14418 start: segRange.start,
14419 end: segRange.end,
14420 isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
14421 isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
14422 dayIndex,
14423 };
14424 segs.push(seg);
14425 // detect when range won't go fully into the next day,
14426 // and mutate the latest seg to the be the end.
14427 if (!seg.isEnd && !allDay &&
14428 dayIndex + 1 < dayRanges.length &&
14429 range.end <
14430 dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
14431 seg.end = range.end;
14432 seg.isEnd = true;
14433 break;
14434 }
14435 }
14436 }
14437 return segs;
14438 }
14439 }
14440 function renderNoEventsInner(renderProps) {
14441 return renderProps.text;
14442 }
14443 function computeDateVars(dateProfile) {
14444 let dayStart = startOfDay(dateProfile.renderRange.start);
14445 let viewEnd = dateProfile.renderRange.end;
14446 let dayDates = [];
14447 let dayRanges = [];
14448 while (dayStart < viewEnd) {
14449 dayDates.push(dayStart);
14450 dayRanges.push({
14451 start: dayStart,
14452 end: addDays(dayStart, 1),
14453 });
14454 dayStart = addDays(dayStart, 1);
14455 }
14456 return { dayDates, dayRanges };
14457 }
14458 // Returns a sparse array of arrays, segs grouped by their dayIndex
14459 function groupSegsByDay(segs) {
14460 let segsByDay = []; // sparse array
14461 let i;
14462 let seg;
14463 for (i = 0; i < segs.length; i += 1) {
14464 seg = segs[i];
14465 (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
14466 .push(seg);
14467 }
14468 return segsByDay;
14469 }
14470
14471 var css_248z$1 = ":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\"\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}";
14472 injectStyles(css_248z$1);
14473
14474 const OPTION_REFINERS$1 = {
14475 listDayFormat: createFalsableFormatter,
14476 listDaySideFormat: createFalsableFormatter,
14477 noEventsClassNames: identity,
14478 noEventsContent: identity,
14479 noEventsDidMount: identity,
14480 noEventsWillUnmount: identity,
14481 // noEventsText is defined in base options
14482 };
14483 function createFalsableFormatter(input) {
14484 return input === false ? null : createFormatter(input);
14485 }
14486
14487 var index$1 = createPlugin({
14488 name: '@fullcalendar/list',
14489 optionRefiners: OPTION_REFINERS$1,
14490 views: {
14491 list: {
14492 component: ListView,
14493 buttonTextKey: 'list',
14494 listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
14495 },
14496 listDay: {
14497 type: 'list',
14498 duration: { days: 1 },
14499 listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar
14500 },
14501 listWeek: {
14502 type: 'list',
14503 duration: { weeks: 1 },
14504 listDayFormat: { weekday: 'long' },
14505 listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },
14506 },
14507 listMonth: {
14508 type: 'list',
14509 duration: { month: 1 },
14510 listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14511 },
14512 listYear: {
14513 type: 'list',
14514 duration: { year: 1 },
14515 listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
14516 },
14517 },
14518 });
14519
14520 class SingleMonth extends DateComponent {
14521 constructor() {
14522 super(...arguments);
14523 this.buildDayTableModel = memoize(buildDayTableModel);
14524 this.slicer = new DayTableSlicer();
14525 this.state = {
14526 labelId: getUniqueDomId(),
14527 };
14528 }
14529 render() {
14530 const { props, state, context } = this;
14531 const { dateProfile, forPrint } = props;
14532 const { options } = context;
14533 const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
14534 const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
14535 // ensure single-month has aspect ratio
14536 const tableHeight = props.tableWidth != null ? props.tableWidth / options.aspectRatio : null;
14537 const rowCnt = dayTableModel.cells.length;
14538 const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
14539 return (y("div", { ref: props.elRef, "data-date": props.isoDateStr, className: "fc-multimonth-month", style: { width: props.width }, role: "grid", "aria-labelledby": state.labelId },
14540 y("div", { className: "fc-multimonth-header", style: { marginBottom: rowHeight }, role: "presentation" },
14541 y("div", { className: "fc-multimonth-title", id: state.labelId }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
14542 y("table", { className: [
14543 'fc-multimonth-header-table',
14544 context.theme.getClass('table'),
14545 ].join(' '), role: "presentation" },
14546 y("thead", { role: "rowgroup" },
14547 y(DayHeader, { dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: false })))),
14548 y("div", { className: [
14549 'fc-multimonth-daygrid',
14550 'fc-daygrid',
14551 'fc-daygrid-body',
14552 !forPrint && 'fc-daygrid-body-balanced',
14553 forPrint && 'fc-daygrid-body-unbalanced',
14554 forPrint && 'fc-daygrid-body-natural',
14555 ].join(' '), style: { marginTop: -rowHeight } },
14556 y("table", { className: [
14557 'fc-multimonth-daygrid-table',
14558 context.theme.getClass('table'),
14559 ].join(' '), style: { height: forPrint ? '' : tableHeight }, role: "presentation" },
14560 y("tbody", { role: "rowgroup" },
14561 y(TableRows, Object.assign({}, slicedProps, { dateProfile: dateProfile, cells: dayTableModel.cells, eventSelection: props.eventSelection, dayMaxEvents: !forPrint, dayMaxEventRows: !forPrint, showWeekNumbers: options.weekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: forPrint })))))));
14562 }
14563 }
14564
14565 class MultiMonthView extends DateComponent {
14566 constructor() {
14567 super(...arguments);
14568 this.splitDateProfileByMonth = memoize(splitDateProfileByMonth);
14569 this.buildMonthFormat = memoize(buildMonthFormat);
14570 this.scrollElRef = d();
14571 this.firstMonthElRef = d();
14572 this.needsScrollReset = false;
14573 this.handleSizing = (isForced) => {
14574 if (isForced) {
14575 this.updateSize();
14576 }
14577 };
14578 }
14579 render() {
14580 const { context, props, state } = this;
14581 const { options } = context;
14582 const { clientWidth, clientHeight } = state;
14583 const monthHPadding = state.monthHPadding || 0;
14584 const colCount = Math.min(clientWidth != null ?
14585 Math.floor(clientWidth / (options.multiMonthMinWidth + monthHPadding)) :
14586 1, options.multiMonthMaxColumns) || 1;
14587 const monthWidthPct = (100 / colCount) + '%';
14588 const monthTableWidth = clientWidth == null ? null :
14589 (clientWidth / colCount) - monthHPadding;
14590 const isLegitSingleCol = clientWidth != null && colCount === 1;
14591 const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, isLegitSingleCol ? false : options.fixedWeekCount, options.showNonCurrentDates);
14592 const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
14593 const rootClassNames = [
14594 'fc-multimonth',
14595 isLegitSingleCol ?
14596 'fc-multimonth-singlecol' :
14597 'fc-multimonth-multicol',
14598 (monthTableWidth != null && monthTableWidth < 400) ?
14599 'fc-multimonth-compact' :
14600 '',
14601 props.isHeightAuto ?
14602 '' :
14603 'fc-scroller', // for AutoScroller
14604 ];
14605 return (y(ViewContainer, { elRef: this.scrollElRef, elClasses: rootClassNames, viewSpec: context.viewSpec }, monthDateProfiles.map((monthDateProfile, i) => {
14606 const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
14607 return (y(SingleMonth, Object.assign({}, props, { key: monthStr, isoDateStr: monthStr, elRef: i === 0 ? this.firstMonthElRef : undefined, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: monthWidthPct, tableWidth: monthTableWidth, clientWidth: clientWidth, clientHeight: clientHeight })));
14608 })));
14609 }
14610 componentDidMount() {
14611 this.updateSize();
14612 this.context.addResizeHandler(this.handleSizing);
14613 this.requestScrollReset();
14614 }
14615 componentDidUpdate(prevProps) {
14616 if (!isPropsEqual(prevProps, this.props)) { // an external change?
14617 this.handleSizing(false);
14618 }
14619 if (prevProps.dateProfile !== this.props.dateProfile) {
14620 this.requestScrollReset();
14621 }
14622 else {
14623 this.flushScrollReset();
14624 }
14625 }
14626 componentWillUnmount() {
14627 this.context.removeResizeHandler(this.handleSizing);
14628 }
14629 updateSize() {
14630 const scrollEl = this.scrollElRef.current;
14631 const firstMonthEl = this.firstMonthElRef.current;
14632 if (scrollEl) {
14633 this.setState({
14634 clientWidth: scrollEl.clientWidth,
14635 clientHeight: scrollEl.clientHeight,
14636 });
14637 }
14638 if (firstMonthEl && scrollEl) {
14639 if (this.state.monthHPadding == null) { // always remember initial non-zero value
14640 this.setState({
14641 monthHPadding: scrollEl.clientWidth - // go within padding
14642 firstMonthEl.firstChild.offsetWidth,
14643 });
14644 }
14645 }
14646 }
14647 requestScrollReset() {
14648 this.needsScrollReset = true;
14649 this.flushScrollReset();
14650 }
14651 flushScrollReset() {
14652 if (this.needsScrollReset &&
14653 this.state.monthHPadding != null // indicates sizing already happened
14654 ) {
14655 const { currentDate } = this.props.dateProfile;
14656 const scrollEl = this.scrollElRef.current;
14657 const monthEl = scrollEl.querySelector(`[data-date="${formatIsoMonthStr(currentDate)}"]`);
14658 scrollEl.scrollTop = monthEl.getBoundingClientRect().top -
14659 this.firstMonthElRef.current.getBoundingClientRect().top;
14660 this.needsScrollReset = false;
14661 }
14662 }
14663 // workaround for when queued setState render (w/ clientWidth) gets cancelled because
14664 // subsequent update and shouldComponentUpdate says not to render :(
14665 shouldComponentUpdate() {
14666 return true;
14667 }
14668 }
14669 // date profile
14670 // -------------------------------------------------------------------------------------------------
14671 const oneMonthDuration = createDuration(1, 'month');
14672 function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
14673 const { start, end } = dateProfile.currentRange;
14674 let monthStart = start;
14675 const monthDateProfiles = [];
14676 while (monthStart.valueOf() < end.valueOf()) {
14677 const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
14678 const currentRange = {
14679 // yuck
14680 start: dateProfileGenerator.skipHiddenDays(monthStart),
14681 end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
14682 };
14683 let renderRange = buildDayTableRenderRange({
14684 currentRange,
14685 snapToWeek: true,
14686 fixedWeekCount,
14687 dateEnv,
14688 });
14689 renderRange = {
14690 // yuck
14691 start: dateProfileGenerator.skipHiddenDays(renderRange.start),
14692 end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
14693 };
14694 const activeRange = dateProfile.activeRange ?
14695 intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
14696 null;
14697 monthDateProfiles.push({
14698 currentDate: dateProfile.currentDate,
14699 isValid: dateProfile.isValid,
14700 validRange: dateProfile.validRange,
14701 renderRange,
14702 activeRange,
14703 currentRange,
14704 currentRangeUnit: 'month',
14705 isRangeAllDay: true,
14706 dateIncrement: dateProfile.dateIncrement,
14707 slotMinTime: dateProfile.slotMaxTime,
14708 slotMaxTime: dateProfile.slotMinTime,
14709 });
14710 monthStart = monthEnd;
14711 }
14712 return monthDateProfiles;
14713 }
14714 // date formatting
14715 // -------------------------------------------------------------------------------------------------
14716 const YEAR_MONTH_FORMATTER = createFormatter({ year: 'numeric', month: 'long' });
14717 const YEAR_FORMATTER = createFormatter({ month: 'long' });
14718 function buildMonthFormat(formatOverride, monthDateProfiles) {
14719 return formatOverride ||
14720 ((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
14721 monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear())
14722 ? YEAR_MONTH_FORMATTER
14723 : YEAR_FORMATTER);
14724 }
14725
14726 const OPTION_REFINERS = {
14727 multiMonthTitleFormat: createFormatter,
14728 multiMonthMaxColumns: Number,
14729 multiMonthMinWidth: Number,
14730 };
14731
14732 var css_248z = ".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}";
14733 injectStyles(css_248z);
14734
14735 var index = createPlugin({
14736 name: '@fullcalendar/multimonth',
14737 initialView: 'multiMonthYear',
14738 optionRefiners: OPTION_REFINERS,
14739 views: {
14740 multiMonth: {
14741 component: MultiMonthView,
14742 dateProfileGeneratorClass: TableDateProfileGenerator,
14743 multiMonthMinWidth: 350,
14744 multiMonthMaxColumns: 3,
14745 },
14746 multiMonthYear: {
14747 type: 'multiMonth',
14748 duration: { years: 1 },
14749 fixedWeekCount: true,
14750 showNonCurrentDates: false,
14751 },
14752 },
14753 });
14754
14755 globalPlugins.push(index$4, index$3, index$2, index$1, index);
14756
14757 exports.Calendar = Calendar;
14758 exports.Draggable = ExternalDraggable;
14759 exports.Internal = internal;
14760 exports.JsonRequestError = JsonRequestError;
14761 exports.Preact = preact;
14762 exports.ThirdPartyDraggable = ThirdPartyDraggable;
14763 exports.createPlugin = createPlugin;
14764 exports.formatDate = formatDate;
14765 exports.formatRange = formatRange;
14766 exports.globalLocales = globalLocales;
14767 exports.globalPlugins = globalPlugins;
14768 exports.sliceEvents = sliceEvents;
14769 exports.version = version;
14770
14771 Object.defineProperty(exports, '__esModule', { value: true });
14772
14773 return exports;
14774
14775})({});
diff --git a/public/js/fullcalendar/dist/index.global.min.js b/public/js/fullcalendar/dist/index.global.min.js
new file mode 100644
index 0000000..d907d04
--- /dev/null
+++ b/public/js/fullcalendar/dist/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Standard Bundle v6.1.17
3Docs & License: https://fullcalendar.io/docs/initialize-globals
4(c) 2024 Adam Shaw
5*/
6var FullCalendar=function(e){"use strict";var t,n,r,i,s,o,a,l,c,d={},u=[],h=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function f(e,t){for(var n in t)e[n]=t[n];return e}function g(e){var t=e.parentNode;t&&t.removeChild(e)}function p(e,n,r){var i,s,o,a={};for(o in n)"key"==o?i=n[o]:"ref"==o?s=n[o]:a[o]=n[o];if(arguments.length>2&&(a.children=arguments.length>3?t.call(arguments,2):r),"function"==typeof e&&null!=e.defaultProps)for(o in e.defaultProps)void 0===a[o]&&(a[o]=e.defaultProps[o]);return m(e,a,i,s,null)}function m(e,t,i,s,o){var a={type:e,props:t,key:i,ref:s,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++r:o};return null==o&&null!=n.vnode&&n.vnode(a),a}function v(){return{current:null}}function y(e){return e.children}function b(e,t,n){"-"===t[0]?e.setProperty(t,null==n?"":n):e[t]=null==n?"":"number"!=typeof n||h.test(t)?n:n+"px"}function E(e,t,n,r,i){var s;e:if("style"===t)if("string"==typeof n)e.style.cssText=n;else{if("string"==typeof r&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||b(e.style,t,"");if(n)for(t in n)r&&n[t]===r[t]||b(e.style,t,n[t])}else if("o"===t[0]&&"n"===t[1])s=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in e?t.toLowerCase().slice(2):t.slice(2),e.l||(e.l={}),e.l[t+s]=n,n?r||e.addEventListener(t,s?D:S,s):e.removeEventListener(t,s?D:S,s);else if("dangerouslySetInnerHTML"!==t){if(i)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==t&&"height"!==t&&"href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in e)try{e[t]=null==n?"":n;break e}catch(e){}"function"==typeof n||(null==n||!1===n&&-1==t.indexOf("-")?e.removeAttribute(t):e.setAttribute(t,n))}}function S(e){s=!0;try{return this.l[e.type+!1](n.event?n.event(e):e)}finally{s=!1}}function D(e){s=!0;try{return this.l[e.type+!0](n.event?n.event(e):e)}finally{s=!1}}function A(e,t){this.props=e,this.context=t}function w(e,t){if(null==t)return e.__?w(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e)return n.__e;return"function"==typeof e.type?w(e):null}function C(e){var t,n;if(null!=(e=e.__)&&null!=e.__c){for(e.__e=e.__c.base=null,t=0;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e){e.__e=e.__c.base=n.__e;break}return C(e)}}function R(e){s?setTimeout(e):l(e)}function x(e){(!e.__d&&(e.__d=!0)&&o.push(e)&&!_.__r++||a!==n.debounceRendering)&&((a=n.debounceRendering)||R)(_)}function _(){var e,t,n,r,i,s,a,l;for(o.sort((function(e,t){return e.__v.__b-t.__v.__b}));e=o.shift();)e.__d&&(t=o.length,r=void 0,i=void 0,a=(s=(n=e).__v).__e,(l=n.__P)&&(r=[],(i=f({},s)).__v=s.__v+1,N(l,s,i,n.__n,void 0!==l.ownerSVGElement,null!=s.__h?[a]:null,r,null==a?w(s):a,s.__h),P(r,s),s.__e!=a&&C(s)),o.length>t&&o.sort((function(e,t){return e.__v.__b-t.__v.__b})));_.__r=0}function T(e,t,n,r,i,s,o,a,l,c){var h,f,g,p,v,b,E,S=r&&r.__k||u,D=S.length;for(n.__k=[],h=0;h<t.length;h++)if(null!=(p=n.__k[h]=null==(p=t[h])||"boolean"==typeof p?null:"string"==typeof p||"number"==typeof p||"bigint"==typeof p?m(null,p,null,null,p):Array.isArray(p)?m(y,{children:p},null,null,null):p.__b>0?m(p.type,p.props,p.key,p.ref?p.ref:null,p.__v):p)){if(p.__=n,p.__b=n.__b+1,null===(g=S[h])||g&&p.key==g.key&&p.type===g.type)S[h]=void 0;else for(f=0;f<D;f++){if((g=S[f])&&p.key==g.key&&p.type===g.type){S[f]=void 0;break}g=null}N(e,p,g=g||d,i,s,o,a,l,c),v=p.__e,(f=p.ref)&&g.ref!=f&&(E||(E=[]),g.ref&&E.push(g.ref,null,p),E.push(f,p.__c||v,p)),null!=v?(null==b&&(b=v),"function"==typeof p.type&&p.__k===g.__k?p.__d=l=k(p,l,e):l=I(e,p,g,S,v,l),"function"==typeof n.type&&(n.__d=l)):l&&g.__e==l&&l.parentNode!=e&&(l=w(g))}for(n.__e=b,h=D;h--;)null!=S[h]&&("function"==typeof n.type&&null!=S[h].__e&&S[h].__e==n.__d&&(n.__d=O(r).nextSibling),j(S[h],S[h]));if(E)for(h=0;h<E.length;h++)B(E[h],E[++h],E[++h])}function k(e,t,n){for(var r,i=e.__k,s=0;i&&s<i.length;s++)(r=i[s])&&(r.__=e,t="function"==typeof r.type?k(r,t,n):I(n,r,r,i,r.__e,t));return t}function M(e,t){return t=t||[],null==e||"boolean"==typeof e||(Array.isArray(e)?e.some((function(e){M(e,t)})):t.push(e)),t}function I(e,t,n,r,i,s){var o,a,l;if(void 0!==t.__d)o=t.__d,t.__d=void 0;else if(null==n||i!=s||null==i.parentNode)e:if(null==s||s.parentNode!==e)e.appendChild(i),o=null;else{for(a=s,l=0;(a=a.nextSibling)&&l<r.length;l+=1)if(a==i)break e;e.insertBefore(i,s),o=s}return void 0!==o?o:i.nextSibling}function O(e){var t,n,r;if(null==e.type||"string"==typeof e.type)return e.__e;if(e.__k)for(t=e.__k.length-1;t>=0;t--)if((n=e.__k[t])&&(r=O(n)))return r;return null}function N(e,t,r,i,s,o,a,l,c){var d,u,h,g,p,m,v,b,E,S,D,w,C,R,x,_=t.type;if(void 0!==t.constructor)return null;null!=r.__h&&(c=r.__h,l=t.__e=r.__e,t.__h=null,o=[l]),(d=n.__b)&&d(t);try{e:if("function"==typeof _){if(b=t.props,E=(d=_.contextType)&&i[d.__c],S=d?E?E.props.value:d.__:i,r.__c?v=(u=t.__c=r.__c).__=u.__E:("prototype"in _&&_.prototype.render?t.__c=u=new _(b,S):(t.__c=u=new A(b,S),u.constructor=_,u.render=z),E&&E.sub(u),u.props=b,u.state||(u.state={}),u.context=S,u.__n=i,h=u.__d=!0,u.__h=[],u._sb=[]),null==u.__s&&(u.__s=u.state),null!=_.getDerivedStateFromProps&&(u.__s==u.state&&(u.__s=f({},u.__s)),f(u.__s,_.getDerivedStateFromProps(b,u.__s))),g=u.props,p=u.state,u.__v=t,h)null==_.getDerivedStateFromProps&&null!=u.componentWillMount&&u.componentWillMount(),null!=u.componentDidMount&&u.__h.push(u.componentDidMount);else{if(null==_.getDerivedStateFromProps&&b!==g&&null!=u.componentWillReceiveProps&&u.componentWillReceiveProps(b,S),!u.__e&&null!=u.shouldComponentUpdate&&!1===u.shouldComponentUpdate(b,u.__s,S)||t.__v===r.__v){for(t.__v!==r.__v&&(u.props=b,u.state=u.__s,u.__d=!1),t.__e=r.__e,t.__k=r.__k,t.__k.forEach((function(e){e&&(e.__=t)})),D=0;D<u._sb.length;D++)u.__h.push(u._sb[D]);u._sb=[],u.__h.length&&a.push(u);break e}null!=u.componentWillUpdate&&u.componentWillUpdate(b,u.__s,S),null!=u.componentDidUpdate&&u.__h.push((function(){u.componentDidUpdate(g,p,m)}))}if(u.context=S,u.props=b,u.__P=e,w=n.__r,C=0,"prototype"in _&&_.prototype.render){for(u.state=u.__s,u.__d=!1,w&&w(t),d=u.render(u.props,u.state,u.context),R=0;R<u._sb.length;R++)u.__h.push(u._sb[R]);u._sb=[]}else do{u.__d=!1,w&&w(t),d=u.render(u.props,u.state,u.context),u.state=u.__s}while(u.__d&&++C<25);u.state=u.__s,null!=u.getChildContext&&(i=f(f({},i),u.getChildContext())),h||null==u.getSnapshotBeforeUpdate||(m=u.getSnapshotBeforeUpdate(g,p)),x=null!=d&&d.type===y&&null==d.key?d.props.children:d,T(e,Array.isArray(x)?x:[x],t,r,i,s,o,a,l,c),u.base=t.__e,t.__h=null,u.__h.length&&a.push(u),v&&(u.__E=u.__=null),u.__e=!1}else null==o&&t.__v===r.__v?(t.__k=r.__k,t.__e=r.__e):t.__e=H(r.__e,t,r,i,s,o,a,c);(d=n.diffed)&&d(t)}catch(e){t.__v=null,(c||null!=o)&&(t.__e=l,t.__h=!!c,o[o.indexOf(l)]=null),n.__e(e,t,r)}}function P(e,t){n.__c&&n.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){n.__e(e,t.__v)}}))}function H(e,n,r,i,s,o,a,l){var c,u,h,f=r.props,p=n.props,m=n.type,v=0;if("svg"===m&&(s=!0),null!=o)for(;v<o.length;v++)if((c=o[v])&&"setAttribute"in c==!!m&&(m?c.localName===m:3===c.nodeType)){e=c,o[v]=null;break}if(null==e){if(null===m)return document.createTextNode(p);e=s?document.createElementNS("http://www.w3.org/2000/svg",m):document.createElement(m,p.is&&p),o=null,l=!1}if(null===m)f===p||l&&e.data===p||(e.data=p);else{if(o=o&&t.call(e.childNodes),u=(f=r.props||d).dangerouslySetInnerHTML,h=p.dangerouslySetInnerHTML,!l){if(null!=o)for(f={},v=0;v<e.attributes.length;v++)f[e.attributes[v].name]=e.attributes[v].value;(h||u)&&(h&&(u&&h.__html==u.__html||h.__html===e.innerHTML)||(e.innerHTML=h&&h.__html||""))}if(function(e,t,n,r,i){var s;for(s in n)"children"===s||"key"===s||s in t||E(e,s,null,n[s],r);for(s in t)i&&"function"!=typeof t[s]||"children"===s||"key"===s||"value"===s||"checked"===s||n[s]===t[s]||E(e,s,t[s],n[s],r)}(e,p,f,s,l),h)n.__k=[];else if(v=n.props.children,T(e,Array.isArray(v)?v:[v],n,r,i,s&&"foreignObject"!==m,o,a,o?o[0]:r.__k&&w(r,0),l),null!=o)for(v=o.length;v--;)null!=o[v]&&g(o[v]);l||("value"in p&&void 0!==(v=p.value)&&(v!==e.value||"progress"===m&&!v||"option"===m&&v!==f.value)&&E(e,"value",v,f.value,!1),"checked"in p&&void 0!==(v=p.checked)&&v!==e.checked&&E(e,"checked",v,f.checked,!1))}return e}function B(e,t,r){try{"function"==typeof e?e(t):e.current=t}catch(e){n.__e(e,r)}}function j(e,t,r){var i,s;if(n.unmount&&n.unmount(e),(i=e.ref)&&(i.current&&i.current!==e.__e||B(i,null,t)),null!=(i=e.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(e){n.__e(e,t)}i.base=i.__P=null,e.__c=void 0}if(i=e.__k)for(s=0;s<i.length;s++)i[s]&&j(i[s],t,r||"function"!=typeof e.type);r||null==e.__e||g(e.__e),e.__=e.__e=e.__d=void 0}function z(e,t,n){return this.constructor(e,n)}function U(e,r,i){var s,o,a;n.__&&n.__(e,r),o=(s="function"==typeof i)?null:i&&i.__k||r.__k,a=[],N(r,e=(!s&&i||r).__k=p(y,null,[e]),o||d,d,void 0!==r.ownerSVGElement,!s&&i?[i]:o?null:r.firstChild?t.call(r.childNodes):null,a,!s&&i?i:o?o.__e:r.firstChild,s),P(a,e)}t=u.slice,n={__e:function(e,t,n,r){for(var i,s,o;t=t.__;)if((i=t.__c)&&!i.__)try{if((s=i.constructor)&&null!=s.getDerivedStateFromError&&(i.setState(s.getDerivedStateFromError(e)),o=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(e,r||{}),o=i.__d),o)return i.__E=i}catch(t){e=t}throw e}},r=0,i=function(e){return null!=e&&void 0===e.constructor},s=!1,A.prototype.setState=function(e,t){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=f({},this.state),"function"==typeof e&&(e=e(f({},n),this.props)),e&&f(n,e),null!=e&&this.__v&&(t&&this._sb.push(t),x(this))},A.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),x(this))},A.prototype.render=y,o=[],l="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,_.__r=0,c=0;var L,W,F,V=[],G=[],Q=n.__b,q=n.__r,Y=n.diffed,Z=n.__c,X=n.unmount;function $(){for(var e;e=V.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(ee),e.__H.__h.forEach(te),e.__H.__h=[]}catch(t){e.__H.__h=[],n.__e(t,e.__v)}}n.__b=function(e){L=null,Q&&Q(e)},n.__r=function(e){q&&q(e);var t=(L=e.__c).__H;t&&(W===L?(t.__h=[],L.__h=[],t.__.forEach((function(e){e.__N&&(e.__=e.__N),e.__V=G,e.__N=e.i=void 0}))):(t.__h.forEach(ee),t.__h.forEach(te),t.__h=[])),W=L},n.diffed=function(e){Y&&Y(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(1!==V.push(t)&&F===n.requestAnimationFrame||((F=n.requestAnimationFrame)||K)($)),t.__H.__.forEach((function(e){e.i&&(e.__H=e.i),e.__V!==G&&(e.__=e.__V),e.i=void 0,e.__V=G}))),W=L=null},n.__c=function(e,t){t.some((function(e){try{e.__h.forEach(ee),e.__h=e.__h.filter((function(e){return!e.__||te(e)}))}catch(r){t.some((function(e){e.__h&&(e.__h=[])})),t=[],n.__e(r,e.__v)}})),Z&&Z(e,t)},n.unmount=function(e){X&&X(e);var t,r=e.__c;r&&r.__H&&(r.__H.__.forEach((function(e){try{ee(e)}catch(e){t=e}})),r.__H=void 0,t&&n.__e(t,r.__v))};var J="function"==typeof requestAnimationFrame;function K(e){var t,n=function(){clearTimeout(r),J&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,100);J&&(t=requestAnimationFrame(n))}function ee(e){var t=L,n=e.__c;"function"==typeof n&&(e.__c=void 0,n()),L=t}function te(e){var t=L;e.__c=e.__(),L=t}function ne(e,t){for(var n in e)if("__source"!==n&&!(n in t))return!0;for(var r in t)if("__source"!==r&&e[r]!==t[r])return!0;return!1}function re(e){this.props=e}(re.prototype=new A).isPureReactComponent=!0,re.prototype.shouldComponentUpdate=function(e,t){return ne(this.props,e)||ne(this.state,t)};var ie=n.__b;n.__b=function(e){e.type&&e.type.__f&&e.ref&&(e.props.ref=e.ref,e.ref=null),ie&&ie(e)};var se=n.__e;n.__e=function(e,t,n,r){if(e.then)for(var i,s=t;s=s.__;)if((i=s.__c)&&i.__c)return null==t.__e&&(t.__e=n.__e,t.__k=n.__k),i.__c(e,t);se(e,t,n,r)};var oe=n.unmount;function ae(){this.__u=0,this.t=null,this.__b=null}function le(e){var t=e.__.__c;return t&&t.__a&&t.__a(e)}function ce(){this.u=null,this.o=null}n.unmount=function(e){var t=e.__c;t&&t.__R&&t.__R(),t&&!0===e.__h&&(e.type=null),oe&&oe(e)},(ae.prototype=new A).__c=function(e,t){var n=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(n);var i=le(r.__v),s=!1,o=function(){s||(s=!0,n.__R=null,i?i(a):a())};n.__R=o;var a=function(){if(!--r.__u){if(r.state.__a){var e=r.state.__a;r.__v.__k[0]=function e(t,n,r){return t&&(t.__v=null,t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)})),t.__c&&t.__c.__P===n&&(t.__e&&r.insertBefore(t.__e,t.__d),t.__c.__e=!0,t.__c.__P=r)),t}(e,e.__c.__P,e.__c.__O)}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate()}},l=!0===t.__h;r.__u++||l||r.setState({__a:r.__b=r.__v.__k[0]}),e.then(o,o)},ae.prototype.componentWillUnmount=function(){this.t=[]},ae.prototype.render=function(e,t){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),r=this.__v.__k[0].__c;this.__v.__k[0]=function e(t,n,r){return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach((function(e){"function"==typeof e.__c&&e.__c()})),t.__c.__H=null),null!=(t=function(e,t){for(var n in t)e[n]=t[n];return e}({},t)).__c&&(t.__c.__P===r&&(t.__c.__P=n),t.__c=null),t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)}))),t}(this.__b,n,r.__O=r.__P)}this.__b=null}var i=t.__a&&p(y,null,e.fallback);return i&&(i.__h=null),[p(y,null,t.__a?null:e.children),i]};var de=function(e,t,n){if(++n[1]===n[0]&&e.o.delete(t),e.props.revealOrder&&("t"!==e.props.revealOrder[0]||!e.o.size))for(n=e.u;n;){for(;n.length>3;)n.pop()();if(n[1]<n[0])break;e.u=n=n[2]}};function ue(e){return this.getChildContext=function(){return e.context},e.children}function he(e){var t=this,n=e.i;t.componentWillUnmount=function(){U(null,t.l),t.l=null,t.i=null},t.i&&t.i!==n&&t.componentWillUnmount(),e.__v?(t.l||(t.i=n,t.l={nodeType:1,parentNode:n,childNodes:[],appendChild:function(e){this.childNodes.push(e),t.i.appendChild(e)},insertBefore:function(e,n){this.childNodes.push(e),t.i.appendChild(e)},removeChild:function(e){this.childNodes.splice(this.childNodes.indexOf(e)>>>1,1),t.i.removeChild(e)}}),U(p(ue,{context:t.context},e.__v),t.l)):t.l&&t.componentWillUnmount()}function fe(e,t){var n=p(he,{__v:e,i:t});return n.containerInfo=t,n}(ce.prototype=new A).__a=function(e){var t=this,n=le(t.__v),r=t.o.get(e);return r[0]++,function(i){var s=function(){t.props.revealOrder?(r.push(i),de(t,e,r)):i()};n?n(s):s()}},ce.prototype.render=function(e){this.u=null,this.o=new Map;var t=M(e.children);e.revealOrder&&"b"===e.revealOrder[0]&&t.reverse();for(var n=t.length;n--;)this.o.set(t[n],this.u=[1,0,this.u]);return e.children},ce.prototype.componentDidUpdate=ce.prototype.componentDidMount=function(){var e=this;this.o.forEach((function(t,n){de(e,n,t)}))};var ge="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,pe=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,me="undefined"!=typeof document,ve=function(e){return("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(e)};A.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach((function(e){Object.defineProperty(A.prototype,e,{configurable:!0,get:function(){return this["UNSAFE_"+e]},set:function(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,value:t})}})}));var ye=n.event;function be(){}function Ee(){return this.cancelBubble}function Se(){return this.defaultPrevented}n.event=function(e){return ye&&(e=ye(e)),e.persist=be,e.isPropagationStopped=Ee,e.isDefaultPrevented=Se,e.nativeEvent=e};var De={configurable:!0,get:function(){return this.class}},Ae=n.vnode;n.vnode=function(e){var t=e.type,n=e.props,r=n;if("string"==typeof t){var i=-1===t.indexOf("-");for(var s in r={},n){var o=n[s];me&&"children"===s&&"noscript"===t||"value"===s&&"defaultValue"in n&&null==o||("defaultValue"===s&&"value"in n&&null==n.value?s="value":"download"===s&&!0===o?o="":/ondoubleclick/i.test(s)?s="ondblclick":/^onchange(textarea|input)/i.test(s+t)&&!ve(n.type)?s="oninput":/^onfocus$/i.test(s)?s="onfocusin":/^onblur$/i.test(s)?s="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(s)?s=s.toLowerCase():i&&pe.test(s)?s=s.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===o&&(o=void 0),/^oninput$/i.test(s)&&(s=s.toLowerCase(),r[s]&&(s="oninputCapture")),r[s]=o)}"select"==t&&r.multiple&&Array.isArray(r.value)&&(r.value=M(n.children).forEach((function(e){e.props.selected=-1!=r.value.indexOf(e.props.value)}))),"select"==t&&null!=r.defaultValue&&(r.value=M(n.children).forEach((function(e){e.props.selected=r.multiple?-1!=r.defaultValue.indexOf(e.props.value):r.defaultValue==e.props.value}))),e.props=r,n.class!=n.className&&(De.enumerable="className"in n,null!=n.className&&(r.class=n.className),Object.defineProperty(r,"className",De))}e.$$typeof=ge,Ae&&Ae(e)};var we=n.__r;n.__r=function(e){we&&we(e),e.__c};const Ce=[],Re=new Map;function xe(e){Ce.push(e),Re.forEach(t=>{Te(t,e)})}function _e(e){let t=Re.get(e);if(!t||!t.isConnected){if(t=e.querySelector("style[data-fullcalendar]"),!t){t=document.createElement("style"),t.setAttribute("data-fullcalendar","");const n=function(){void 0===ke&&(ke=function(){const e=document.querySelector('meta[name="csp-nonce"]');if(e&&e.hasAttribute("content"))return e.getAttribute("content");const t=document.querySelector("script[nonce]");if(t)return t.nonce||"";return""}());return ke}();n&&(t.nonce=n);const r=e===document?document.head:e,i=e===document?r.querySelector("script,link[rel=stylesheet],link[as=style],style"):r.firstChild;r.insertBefore(t,i)}Re.set(e,t),function(e){for(const t of Ce)Te(e,t)}(t)}}function Te(e,t){const{sheet:n}=e,r=n.cssRules.length;t.split("}").forEach((e,t)=>{(e=e.trim())&&n.insertRule(e+"}",r+t)})}let ke;"undefined"!=typeof document&&_e(document);xe(':root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") format("truetype")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:"\\e900"}.fc-icon-chevron-right:before{content:"\\e901"}.fc-icon-chevrons-left:before{content:"\\e902"}.fc-icon-chevrons-right:before{content:"\\e903"}.fc-icon-minus-square:before{content:"\\e904"}.fc-icon-plus-square:before{content:"\\e905"}.fc-icon-x:before{content:"\\e906"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:"";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:"";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}');class Me{constructor(e){this.drainedOption=e,this.isRunning=!1,this.isDirty=!1,this.pauseDepths={},this.timeoutId=0}request(e){this.isDirty=!0,this.isPaused()||(this.clearTimeout(),null==e?this.tryDrain():this.timeoutId=setTimeout(this.tryDrain.bind(this),e))}pause(e=""){let{pauseDepths:t}=this;t[e]=(t[e]||0)+1,this.clearTimeout()}resume(e="",t){let{pauseDepths:n}=this;if(e in n){if(t)delete n[e];else{n[e]-=1,n[e]<=0&&delete n[e]}this.tryDrain()}}isPaused(){return Object.keys(this.pauseDepths).length}tryDrain(){if(!this.isRunning&&!this.isPaused()){for(this.isRunning=!0;this.isDirty;)this.isDirty=!1,this.drained();this.isRunning=!1}}clear(){this.clearTimeout(),this.isDirty=!1,this.pauseDepths={}}clearTimeout(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=0)}drained(){this.drainedOption&&this.drainedOption()}}function Ie(e){e.parentNode&&e.parentNode.removeChild(e)}function Oe(e,t){if(e.closest)return e.closest(t);if(!document.documentElement.contains(e))return null;do{if(Ne(e,t))return e;e=e.parentElement||e.parentNode}while(null!==e&&1===e.nodeType);return null}function Ne(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector).call(e,t)}function Pe(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].querySelectorAll(t);for(let e=0;e<i.length;e+=1)r.push(i[e])}return r}const He=/(top|left|right|bottom|width|height)$/i;function Be(e,t){for(let n in t)je(e,n,t[n])}function je(e,t,n){null==n?e.style[t]="":"number"==typeof n&&He.test(t)?e.style[t]=n+"px":e.style[t]=n}function ze(e){var t,n;return null!==(n=null===(t=e.composedPath)||void 0===t?void 0:t.call(e)[0])&&void 0!==n?n:e.target}let Ue=0;function Le(){return Ue+=1,"fc-dom-"+Ue}function We(e){e.preventDefault()}function Fe(e,t,n,r){let i=function(e,t){return n=>{let r=Oe(n.target,e);r&&t.call(r,n,r)}}(n,r);return e.addEventListener(t,i),()=>{e.removeEventListener(t,i)}}const Ve=["webkitTransitionEnd","otransitionend","oTransitionEnd","msTransitionEnd","transitionend"];function Ge(e,t){let n=r=>{t(r),Ve.forEach(t=>{e.removeEventListener(t,n)})};Ve.forEach(t=>{e.addEventListener(t,n)})}function Qe(e){return Object.assign({onClick:e},qe(e))}function qe(e){return{tabIndex:0,onKeyDown(t){"Enter"!==t.key&&" "!==t.key||(e(t),t.preventDefault())}}}let Ye=0;function Ze(){return Ye+=1,String(Ye)}function Xe(){document.body.classList.add("fc-not-allowed")}function $e(){document.body.classList.remove("fc-not-allowed")}function Je(e){e.style.userSelect="none",e.style.webkitUserSelect="none",e.addEventListener("selectstart",We)}function Ke(e){e.style.userSelect="",e.style.webkitUserSelect="",e.removeEventListener("selectstart",We)}function et(e){e.addEventListener("contextmenu",We)}function tt(e){e.removeEventListener("contextmenu",We)}function nt(e){let t,n,r=[],i=[];for("string"==typeof e?i=e.split(/\s*,\s*/):"function"==typeof e?i=[e]:Array.isArray(e)&&(i=e),t=0;t<i.length;t+=1)n=i[t],"string"==typeof n?r.push("-"===n.charAt(0)?{field:n.substring(1),order:-1}:{field:n,order:1}):"function"==typeof n&&r.push({func:n});return r}function rt(e,t,n){let r,i;for(r=0;r<n.length;r+=1)if(i=it(e,t,n[r]),i)return i;return 0}function it(e,t,n){return n.func?n.func(e,t):st(e[n.field],t[n.field])*(n.order||1)}function st(e,t){return e||t?null==t?-1:null==e?1:"string"==typeof e||"string"==typeof t?String(e).localeCompare(String(t)):e-t:0}function ot(e,t){let n=String(e);return"000".substr(0,t-n.length)+n}function at(e,t,n){return"function"==typeof e?e(...t):"string"==typeof e?t.reduce((e,t,n)=>e.replace("$"+n,t||""),e):n}function lt(e,t){return e-t}function ct(e){return e%1==0}function dt(e){let t=e.querySelector(".fc-scrollgrid-shrink-frame"),n=e.querySelector(".fc-scrollgrid-shrink-cushion");if(!t)throw new Error("needs fc-scrollgrid-shrink-frame className");if(!n)throw new Error("needs fc-scrollgrid-shrink-cushion className");return e.getBoundingClientRect().width-t.getBoundingClientRect().width+n.getBoundingClientRect().width}const ut=["years","months","days","milliseconds"],ht=/^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;function ft(e,t){return"string"==typeof e?function(e){let t=ht.exec(e);if(t){let e=t[1]?-1:1;return{years:0,months:0,days:e*(t[2]?parseInt(t[2],10):0),milliseconds:e*(60*(t[3]?parseInt(t[3],10):0)*60*1e3+60*(t[4]?parseInt(t[4],10):0)*1e3+1e3*(t[5]?parseInt(t[5],10):0)+(t[6]?parseInt(t[6],10):0))}}return null}(e):"object"==typeof e&&e?gt(e):"number"==typeof e?gt({[t||"milliseconds"]:e}):null}function gt(e){let t={years:e.years||e.year||0,months:e.months||e.month||0,days:e.days||e.day||0,milliseconds:60*(e.hours||e.hour||0)*60*1e3+60*(e.minutes||e.minute||0)*1e3+1e3*(e.seconds||e.second||0)+(e.milliseconds||e.millisecond||e.ms||0)},n=e.weeks||e.week;return n&&(t.days+=7*n,t.specifiedWeeks=!0),t}function pt(e,t){return{years:e.years+t.years,months:e.months+t.months,days:e.days+t.days,milliseconds:e.milliseconds+t.milliseconds}}function mt(e,t){return{years:e.years*t,months:e.months*t,days:e.days*t,milliseconds:e.milliseconds*t}}function vt(e){return yt(e)/864e5}function yt(e){return 31536e6*e.years+2592e6*e.months+864e5*e.days+e.milliseconds}function bt(e,t){let n=null;for(let r=0;r<ut.length;r+=1){let i=ut[r];if(t[i]){let r=e[i]/t[i];if(!ct(r)||null!==n&&n!==r)return null;n=r}else if(e[i])return null}return n}function Et(e){let t=e.milliseconds;if(t){if(t%1e3!=0)return{unit:"millisecond",value:t};if(t%6e4!=0)return{unit:"second",value:t/1e3};if(t%36e5!=0)return{unit:"minute",value:t/6e4};if(t)return{unit:"hour",value:t/36e5}}return e.days?e.specifiedWeeks&&e.days%7==0?{unit:"week",value:e.days/7}:{unit:"day",value:e.days}:e.months?{unit:"month",value:e.months}:e.years?{unit:"year",value:e.years}:{unit:"millisecond",value:0}}function St(e,t,n){if(e===t)return!0;let r,i=e.length;if(i!==t.length)return!1;for(r=0;r<i;r+=1)if(!(n?n(e[r],t[r]):e[r]===t[r]))return!1;return!0}const Dt=["sun","mon","tue","wed","thu","fri","sat"];function At(e,t){let n=Ht(e);return n[2]+=7*t,Bt(n)}function wt(e,t){let n=Ht(e);return n[2]+=t,Bt(n)}function Ct(e,t){let n=Ht(e);return n[6]+=t,Bt(n)}function Rt(e,t){return xt(e,t)/7}function xt(e,t){return(t.valueOf()-e.valueOf())/864e5}function _t(e,t){let n=Mt(e),r=Mt(t);return{years:0,months:0,days:Math.round(xt(n,r)),milliseconds:t.valueOf()-r.valueOf()-(e.valueOf()-n.valueOf())}}function Tt(e,t){let n=kt(e,t);return null!==n&&n%7==0?n/7:null}function kt(e,t){return zt(e)===zt(t)?Math.round(xt(e,t)):null}function Mt(e){return Bt([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()])}function It(e,t,n,r){let i=Bt([t,0,1+Ot(t,n,r)]),s=Mt(e),o=Math.round(xt(i,s));return Math.floor(o/7)+1}function Ot(e,t,n){let r=7+t-n;return-((7+Bt([e,0,r]).getUTCDay()-t)%7)+r-1}function Nt(e){return[e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()]}function Pt(e){return new Date(e[0],e[1]||0,null==e[2]?1:e[2],e[3]||0,e[4]||0,e[5]||0)}function Ht(e){return[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds()]}function Bt(e){return 1===e.length&&(e=e.concat([0])),new Date(Date.UTC(...e))}function jt(e){return!isNaN(e.valueOf())}function zt(e){return 1e3*e.getUTCHours()*60*60+1e3*e.getUTCMinutes()*60+1e3*e.getUTCSeconds()+e.getUTCMilliseconds()}function Ut(e,t,n=!1){let r=e.toISOString();return r=r.replace(".000",""),n&&(r=r.replace("T00:00:00Z","")),r.length>10&&(null==t?r=r.replace("Z",""):0!==t&&(r=r.replace("Z",Vt(t,!0)))),r}function Lt(e){return e.toISOString().replace(/T.*$/,"")}function Wt(e){return e.toISOString().match(/^\d{4}-\d{2}/)[0]}function Ft(e){return ot(e.getUTCHours(),2)+":"+ot(e.getUTCMinutes(),2)+":"+ot(e.getUTCSeconds(),2)}function Vt(e,t=!1){let n=e<0?"-":"+",r=Math.abs(e),i=Math.floor(r/60),s=Math.round(r%60);return t?`${n+ot(i,2)}:${ot(s,2)}`:`GMT${n}${i}${s?":"+ot(s,2):""}`}function Gt(e,t,n){let r,i;return function(...s){if(r){if(!St(r,s)){n&&n(i);let r=e.apply(this,s);t&&t(r,i)||(i=r)}}else i=e.apply(this,s);return r=s,i}}function Qt(e,t,n){let r,i;return s=>{if(r){if(!Cn(r,s)){n&&n(i);let r=e.call(this,s);t&&t(r,i)||(i=r)}}else i=e.call(this,s);return r=s,i}}const qt={week:3,separator:9,omitZeroMinute:9,meridiem:9,omitCommas:9},Yt={timeZoneName:7,era:6,year:5,month:4,day:2,weekday:2,hour:1,minute:1,second:1},Zt=/\s*([ap])\.?m\.?/i,Xt=/,/g,$t=/\s+/g,Jt=/\u200e/g,Kt=/UTC|GMT/;class en{constructor(e){let t={},n={},r=9;for(let i in e)if(i in qt){n[i]=e[i];qt[i]<9&&(r=Math.min(qt[i],r))}else t[i]=e[i],i in Yt&&(r=Math.min(Yt[i],r));this.standardDateProps=t,this.extendedSettings=n,this.smallestUnitNum=r,this.buildFormattingFunc=Gt(tn)}format(e,t){return this.buildFormattingFunc(this.standardDateProps,this.extendedSettings,t)(e)}formatRange(e,t,n,r){let{standardDateProps:i,extendedSettings:s}=this,o=function(e,t,n){if(n.getMarkerYear(e)!==n.getMarkerYear(t))return 5;if(n.getMarkerMonth(e)!==n.getMarkerMonth(t))return 4;if(n.getMarkerDay(e)!==n.getMarkerDay(t))return 2;if(zt(e)!==zt(t))return 1;return 0}(e.marker,t.marker,n.calendarSystem);if(!o)return this.format(e,n);let a=o;!(a>1)||"numeric"!==i.year&&"2-digit"!==i.year||"numeric"!==i.month&&"2-digit"!==i.month||"numeric"!==i.day&&"2-digit"!==i.day||(a=1);let l=this.format(e,n),c=this.format(t,n);if(l===c)return l;let d=tn(function(e,t){let n={};for(let r in e)(!(r in Yt)||Yt[r]<=t)&&(n[r]=e[r]);return n}(i,a),s,n),u=d(e),h=d(t),f=function(e,t,n,r){let i=0;for(;i<e.length;){let s=e.indexOf(t,i);if(-1===s)break;let o=e.substr(0,s);i=s+t.length;let a=e.substr(i),l=0;for(;l<n.length;){let e=n.indexOf(r,l);if(-1===e)break;let t=n.substr(0,e);l=e+r.length;let i=n.substr(l);if(o===t&&a===i)return{before:o,after:a}}}return null}(l,u,c,h),g=s.separator||r||n.defaultSeparator||"";return f?f.before+u+g+h+f.after:l+g+c}getSmallestUnit(){switch(this.smallestUnitNum){case 7:case 6:case 5:return"year";case 4:return"month";case 3:return"week";case 2:return"day";default:return"time"}}}function tn(e,t,n){let r=Object.keys(e).length;return 1===r&&"short"===e.timeZoneName?e=>Vt(e.timeZoneOffset):0===r&&t.week?e=>function(e,t,n,r,i){let s=[];"long"===i?s.push(n):"short"!==i&&"narrow"!==i||s.push(t);"long"!==i&&"short"!==i||s.push(" ");s.push(r.simpleNumberFormat.format(e)),"rtl"===r.options.direction&&s.reverse();return s.join("")}(n.computeWeekNumber(e.marker),n.weekText,n.weekTextLong,n.locale,t.week):function(e,t,n){e=Object.assign({},e),t=Object.assign({},t),function(e,t){e.timeZoneName&&(e.hour||(e.hour="2-digit"),e.minute||(e.minute="2-digit"));"long"===e.timeZoneName&&(e.timeZoneName="short");t.omitZeroMinute&&(e.second||e.millisecond)&&delete t.omitZeroMinute}(e,t),e.timeZone="UTC";let r,i=new Intl.DateTimeFormat(n.locale.codes,e);if(t.omitZeroMinute){let t=Object.assign({},e);delete t.minute,r=new Intl.DateTimeFormat(n.locale.codes,t)}return s=>{let o,{marker:a}=s;return o=r&&!a.getUTCMinutes()?r:i,function(e,t,n,r,i){e=e.replace(Jt,""),"short"===n.timeZoneName&&(e=function(e,t){let n=!1;e=e.replace(Kt,()=>(n=!0,t)),n||(e+=" "+t);return e}(e,"UTC"===i.timeZone||null==t.timeZoneOffset?"UTC":Vt(t.timeZoneOffset)));r.omitCommas&&(e=e.replace(Xt,"").trim());r.omitZeroMinute&&(e=e.replace(":00",""));!1===r.meridiem?e=e.replace(Zt,"").trim():"narrow"===r.meridiem?e=e.replace(Zt,(e,t)=>t.toLocaleLowerCase()):"short"===r.meridiem?e=e.replace(Zt,(e,t)=>t.toLocaleLowerCase()+"m"):"lowercase"===r.meridiem&&(e=e.replace(Zt,e=>e.toLocaleLowerCase()));return e=(e=e.replace($t," ")).trim()}(o.format(a),s,e,t,n)}}(e,t,n)}function nn(e,t){let n=t.markerToArray(e.marker);return{marker:e.marker,timeZoneOffset:e.timeZoneOffset,array:n,year:n[0],month:n[1],day:n[2],hour:n[3],minute:n[4],second:n[5],millisecond:n[6]}}function rn(e,t,n,r){let i=nn(e,n.calendarSystem);return{date:i,start:i,end:t?nn(t,n.calendarSystem):null,timeZone:n.timeZone,localeCodes:n.locale.codes,defaultSeparator:r||n.defaultSeparator}}class sn{constructor(e){this.cmdStr=e}format(e,t,n){return t.cmdFormatter(this.cmdStr,rn(e,null,t,n))}formatRange(e,t,n,r){return n.cmdFormatter(this.cmdStr,rn(e,t,n,r))}}class on{constructor(e){this.func=e}format(e,t,n){return this.func(rn(e,null,t,n))}formatRange(e,t,n,r){return this.func(rn(e,t,n,r))}}function an(e){return"object"==typeof e&&e?new en(e):"string"==typeof e?new sn(e):"function"==typeof e?new on(e):null}const ln={navLinkDayClick:yn,navLinkWeekClick:yn,duration:ft,bootstrapFontAwesome:yn,buttonIcons:yn,customButtons:yn,defaultAllDayEventDuration:ft,defaultTimedEventDuration:ft,nextDayThreshold:ft,scrollTime:ft,scrollTimeReset:Boolean,slotMinTime:ft,slotMaxTime:ft,dayPopoverFormat:an,slotDuration:ft,snapDuration:ft,headerToolbar:yn,footerToolbar:yn,defaultRangeSeparator:String,titleRangeSeparator:String,forceEventDuration:Boolean,dayHeaders:Boolean,dayHeaderFormat:an,dayHeaderClassNames:yn,dayHeaderContent:yn,dayHeaderDidMount:yn,dayHeaderWillUnmount:yn,dayCellClassNames:yn,dayCellContent:yn,dayCellDidMount:yn,dayCellWillUnmount:yn,initialView:String,aspectRatio:Number,weekends:Boolean,weekNumberCalculation:yn,weekNumbers:Boolean,weekNumberClassNames:yn,weekNumberContent:yn,weekNumberDidMount:yn,weekNumberWillUnmount:yn,editable:Boolean,viewClassNames:yn,viewDidMount:yn,viewWillUnmount:yn,nowIndicator:Boolean,nowIndicatorClassNames:yn,nowIndicatorContent:yn,nowIndicatorDidMount:yn,nowIndicatorWillUnmount:yn,showNonCurrentDates:Boolean,lazyFetching:Boolean,startParam:String,endParam:String,timeZoneParam:String,timeZone:String,locales:yn,locale:yn,themeSystem:String,dragRevertDuration:Number,dragScroll:Boolean,allDayMaintainDuration:Boolean,unselectAuto:Boolean,dropAccept:yn,eventOrder:nt,eventOrderStrict:Boolean,handleWindowResize:Boolean,windowResizeDelay:Number,longPressDelay:Number,eventDragMinDistance:Number,expandRows:Boolean,height:yn,contentHeight:yn,direction:String,weekNumberFormat:an,eventResizableFromStart:Boolean,displayEventTime:Boolean,displayEventEnd:Boolean,weekText:String,weekTextLong:String,progressiveEventRendering:Boolean,businessHours:yn,initialDate:yn,now:yn,eventDataTransform:yn,stickyHeaderDates:yn,stickyFooterScrollbar:yn,viewHeight:yn,defaultAllDay:Boolean,eventSourceFailure:yn,eventSourceSuccess:yn,eventDisplay:String,eventStartEditable:Boolean,eventDurationEditable:Boolean,eventOverlap:yn,eventConstraint:yn,eventAllow:yn,eventBackgroundColor:String,eventBorderColor:String,eventTextColor:String,eventColor:String,eventClassNames:yn,eventContent:yn,eventDidMount:yn,eventWillUnmount:yn,selectConstraint:yn,selectOverlap:yn,selectAllow:yn,droppable:Boolean,unselectCancel:String,slotLabelFormat:yn,slotLaneClassNames:yn,slotLaneContent:yn,slotLaneDidMount:yn,slotLaneWillUnmount:yn,slotLabelClassNames:yn,slotLabelContent:yn,slotLabelDidMount:yn,slotLabelWillUnmount:yn,dayMaxEvents:yn,dayMaxEventRows:yn,dayMinWidth:Number,slotLabelInterval:ft,allDayText:String,allDayClassNames:yn,allDayContent:yn,allDayDidMount:yn,allDayWillUnmount:yn,slotMinWidth:Number,navLinks:Boolean,eventTimeFormat:an,rerenderDelay:Number,moreLinkText:yn,moreLinkHint:yn,selectMinDistance:Number,selectable:Boolean,selectLongPressDelay:Number,eventLongPressDelay:Number,selectMirror:Boolean,eventMaxStack:Number,eventMinHeight:Number,eventMinWidth:Number,eventShortHeight:Number,slotEventOverlap:Boolean,plugins:yn,firstDay:Number,dayCount:Number,dateAlignment:String,dateIncrement:ft,hiddenDays:yn,fixedWeekCount:Boolean,validRange:yn,visibleRange:yn,titleFormat:yn,eventInteractive:Boolean,noEventsText:String,viewHint:yn,navLinkHint:yn,closeHint:String,timeHint:String,eventHint:String,moreLinkClick:yn,moreLinkClassNames:yn,moreLinkContent:yn,moreLinkDidMount:yn,moreLinkWillUnmount:yn,monthStartFormat:an,handleCustomRendering:yn,customRenderingMetaMap:yn,customRenderingReplaces:Boolean},cn={eventDisplay:"auto",defaultRangeSeparator:" - ",titleRangeSeparator:" – ",defaultTimedEventDuration:"01:00:00",defaultAllDayEventDuration:{day:1},forceEventDuration:!1,nextDayThreshold:"00:00:00",dayHeaders:!0,initialView:"",aspectRatio:1.35,headerToolbar:{start:"title",center:"",end:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberCalculation:"local",editable:!1,nowIndicator:!1,scrollTime:"06:00:00",scrollTimeReset:!0,slotMinTime:"00:00:00",slotMaxTime:"24:00:00",showNonCurrentDates:!0,lazyFetching:!0,startParam:"start",endParam:"end",timeZoneParam:"timeZone",timeZone:"local",locales:[],locale:"",themeSystem:"standard",dragRevertDuration:500,dragScroll:!0,allDayMaintainDuration:!1,unselectAuto:!0,dropAccept:"*",eventOrder:"start,-duration,allDay,title",dayPopoverFormat:{month:"long",day:"numeric",year:"numeric"},handleWindowResize:!0,windowResizeDelay:100,longPressDelay:1e3,eventDragMinDistance:5,expandRows:!1,navLinks:!1,selectable:!1,eventMinHeight:15,eventMinWidth:30,eventShortHeight:30,monthStartFormat:{month:"long",day:"numeric"}},dn={datesSet:yn,eventsSet:yn,eventAdd:yn,eventChange:yn,eventRemove:yn,windowResize:yn,eventClick:yn,eventMouseEnter:yn,eventMouseLeave:yn,select:yn,unselect:yn,loading:yn,_unmount:yn,_beforeprint:yn,_afterprint:yn,_noEventDrop:yn,_noEventResize:yn,_resize:yn,_scrollRequest:yn},un={buttonText:yn,buttonHints:yn,views:yn,plugins:yn,initialEvents:yn,events:yn,eventSources:yn},hn={headerToolbar:fn,footerToolbar:fn,buttonText:fn,buttonHints:fn,buttonIcons:fn,dateIncrement:fn,plugins:gn,events:gn,eventSources:gn,resources:gn};function fn(e,t){return"object"==typeof e&&"object"==typeof t&&e&&t?Cn(e,t):e===t}function gn(e,t){return Array.isArray(e)&&Array.isArray(t)?St(e,t):e===t}const pn={type:String,component:yn,buttonText:String,buttonTextKey:String,dateProfileGeneratorClass:yn,usesMinMaxTime:Boolean,classNames:yn,content:yn,didMount:yn,willUnmount:yn};function mn(e){return En(e,hn)}function vn(e,t){let n={},r={};for(let r in t)r in e&&(n[r]=t[r](e[r]));for(let n in e)n in t||(r[n]=e[n]);return{refined:n,extra:r}}function yn(e){return e}const{hasOwnProperty:bn}=Object.prototype;function En(e,t){let n={};if(t)for(let r in t)if(t[r]===fn){let t=[];for(let i=e.length-1;i>=0;i-=1){let s=e[i][r];if("object"==typeof s&&s)t.unshift(s);else if(void 0!==s){n[r]=s;break}}t.length&&(n[r]=En(t))}for(let t=e.length-1;t>=0;t-=1){let r=e[t];for(let e in r)e in n||(n[e]=r[e])}return n}function Sn(e,t){let n={};for(let r in e)t(e[r],r)&&(n[r]=e[r]);return n}function Dn(e,t){let n={};for(let r in e)n[r]=t(e[r],r);return n}function An(e){let t={};for(let n of e)t[n]=!0;return t}function wn(e){let t=[];for(let n in e)t.push(e[n]);return t}function Cn(e,t){if(e===t)return!0;for(let n in e)if(bn.call(e,n)&&!(n in t))return!1;for(let n in t)if(bn.call(t,n)&&e[n]!==t[n])return!1;return!0}const Rn=/^on[A-Z]/;function xn(e,t){let n=[];for(let r in e)bn.call(e,r)&&(r in t||n.push(r));for(let r in t)bn.call(t,r)&&e[r]!==t[r]&&n.push(r);return n}function _n(e,t,n={}){if(e===t)return!0;for(let r in t)if(!(r in e)||!Tn(e[r],t[r],n[r]))return!1;for(let n in e)if(!(n in t))return!1;return!0}function Tn(e,t,n){return e===t||!0===n||!!n&&n(e,t)}function kn(e,t=0,n,r=1){let i=[];null==n&&(n=Object.keys(e).length);for(let s=t;s<n;s+=r){let t=e[s];void 0!==t&&i.push(t)}return i}let Mn={};var In,On;In="gregory",On=class{getMarkerYear(e){return e.getUTCFullYear()}getMarkerMonth(e){return e.getUTCMonth()}getMarkerDay(e){return e.getUTCDate()}arrayToMarker(e){return Bt(e)}markerToArray(e){return Ht(e)}},Mn[In]=On;const Nn=/^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;function Pn(e){let t=Nn.exec(e);if(t){let e=new Date(Date.UTC(Number(t[1]),t[3]?Number(t[3])-1:0,Number(t[5]||1),Number(t[7]||0),Number(t[8]||0),Number(t[10]||0),t[12]?1e3*Number("0."+t[12]):0));if(jt(e)){let n=null;return t[13]&&(n=("-"===t[15]?-1:1)*(60*Number(t[16]||0)+Number(t[18]||0))),{marker:e,isTimeUnspecified:!t[6],timeZoneOffset:n}}}return null}class Hn{constructor(e){let t=this.timeZone=e.timeZone,n="local"!==t&&"UTC"!==t;e.namedTimeZoneImpl&&n&&(this.namedTimeZoneImpl=new e.namedTimeZoneImpl(t)),this.canComputeOffset=Boolean(!n||this.namedTimeZoneImpl),this.calendarSystem=function(e){return new Mn[e]}(e.calendarSystem),this.locale=e.locale,this.weekDow=e.locale.week.dow,this.weekDoy=e.locale.week.doy,"ISO"===e.weekNumberCalculation&&(this.weekDow=1,this.weekDoy=4),"number"==typeof e.firstDay&&(this.weekDow=e.firstDay),"function"==typeof e.weekNumberCalculation&&(this.weekNumberFunc=e.weekNumberCalculation),this.weekText=null!=e.weekText?e.weekText:e.locale.options.weekText,this.weekTextLong=(null!=e.weekTextLong?e.weekTextLong:e.locale.options.weekTextLong)||this.weekText,this.cmdFormatter=e.cmdFormatter,this.defaultSeparator=e.defaultSeparator}createMarker(e){let t=this.createMarkerMeta(e);return null===t?null:t.marker}createNowMarker(){return this.canComputeOffset?this.timestampToMarker((new Date).valueOf()):Bt(Nt(new Date))}createMarkerMeta(e){if("string"==typeof e)return this.parse(e);let t=null;return"number"==typeof e?t=this.timestampToMarker(e):e instanceof Date?(e=e.valueOf(),isNaN(e)||(t=this.timestampToMarker(e))):Array.isArray(e)&&(t=Bt(e)),null!==t&&jt(t)?{marker:t,isTimeUnspecified:!1,forcedTzo:null}:null}parse(e){let t=Pn(e);if(null===t)return null;let{marker:n}=t,r=null;return null!==t.timeZoneOffset&&(this.canComputeOffset?n=this.timestampToMarker(n.valueOf()-60*t.timeZoneOffset*1e3):r=t.timeZoneOffset),{marker:n,isTimeUnspecified:t.isTimeUnspecified,forcedTzo:r}}getYear(e){return this.calendarSystem.getMarkerYear(e)}getMonth(e){return this.calendarSystem.getMarkerMonth(e)}getDay(e){return this.calendarSystem.getMarkerDay(e)}add(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t.years,n[1]+=t.months,n[2]+=t.days,n[6]+=t.milliseconds,this.calendarSystem.arrayToMarker(n)}subtract(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]-=t.years,n[1]-=t.months,n[2]-=t.days,n[6]-=t.milliseconds,this.calendarSystem.arrayToMarker(n)}addYears(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t,this.calendarSystem.arrayToMarker(n)}addMonths(e,t){let n=this.calendarSystem.markerToArray(e);return n[1]+=t,this.calendarSystem.arrayToMarker(n)}diffWholeYears(e,t){let{calendarSystem:n}=this;return zt(e)===zt(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)&&n.getMarkerMonth(e)===n.getMarkerMonth(t)?n.getMarkerYear(t)-n.getMarkerYear(e):null}diffWholeMonths(e,t){let{calendarSystem:n}=this;return zt(e)===zt(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)?n.getMarkerMonth(t)-n.getMarkerMonth(e)+12*(n.getMarkerYear(t)-n.getMarkerYear(e)):null}greatestWholeUnit(e,t){let n=this.diffWholeYears(e,t);return null!==n?{unit:"year",value:n}:(n=this.diffWholeMonths(e,t),null!==n?{unit:"month",value:n}:(n=Tt(e,t),null!==n?{unit:"week",value:n}:(n=kt(e,t),null!==n?{unit:"day",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/36e5}(e,t),ct(n)?{unit:"hour",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/6e4}(e,t),ct(n)?{unit:"minute",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/1e3}(e,t),ct(n)?{unit:"second",value:n}:{unit:"millisecond",value:t.valueOf()-e.valueOf()}))))))}countDurationsBetween(e,t,n){let r;return n.years&&(r=this.diffWholeYears(e,t),null!==r)?r/(vt(n)/365):n.months&&(r=this.diffWholeMonths(e,t),null!==r)?r/function(e){return vt(e)/30}(n):n.days&&(r=kt(e,t),null!==r)?r/vt(n):(t.valueOf()-e.valueOf())/yt(n)}startOf(e,t){return"year"===t?this.startOfYear(e):"month"===t?this.startOfMonth(e):"week"===t?this.startOfWeek(e):"day"===t?Mt(e):"hour"===t?function(e){return Bt([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()])}(e):"minute"===t?function(e){return Bt([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()])}(e):"second"===t?function(e){return Bt([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()])}(e):null}startOfYear(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e)])}startOfMonth(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e)])}startOfWeek(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e),e.getUTCDate()-(e.getUTCDay()-this.weekDow+7)%7])}computeWeekNumber(e){return this.weekNumberFunc?this.weekNumberFunc(this.toDate(e)):function(e,t,n){let r=e.getUTCFullYear(),i=It(e,r,t,n);if(i<1)return It(e,r-1,t,n);let s=It(e,r+1,t,n);return s>=1?Math.min(i,s):i}(e,this.weekDow,this.weekDoy)}format(e,t,n={}){return t.format({marker:e,timeZoneOffset:null!=n.forcedTzo?n.forcedTzo:this.offsetForMarker(e)},this)}formatRange(e,t,n,r={}){return r.isEndExclusive&&(t=Ct(t,-1)),n.formatRange({marker:e,timeZoneOffset:null!=r.forcedStartTzo?r.forcedStartTzo:this.offsetForMarker(e)},{marker:t,timeZoneOffset:null!=r.forcedEndTzo?r.forcedEndTzo:this.offsetForMarker(t)},this,r.defaultSeparator)}formatIso(e,t={}){let n=null;return t.omitTimeZoneOffset||(n=null!=t.forcedTzo?t.forcedTzo:this.offsetForMarker(e)),Ut(e,n,t.omitTime)}timestampToMarker(e){return"local"===this.timeZone?Bt(Nt(new Date(e))):"UTC"!==this.timeZone&&this.namedTimeZoneImpl?Bt(this.namedTimeZoneImpl.timestampToArray(e)):new Date(e)}offsetForMarker(e){return"local"===this.timeZone?-Pt(Ht(e)).getTimezoneOffset():"UTC"===this.timeZone?0:this.namedTimeZoneImpl?this.namedTimeZoneImpl.offsetForArray(Ht(e)):null}toDate(e,t){return"local"===this.timeZone?Pt(Ht(e)):"UTC"===this.timeZone?new Date(e.valueOf()):this.namedTimeZoneImpl?new Date(e.valueOf()-1e3*this.namedTimeZoneImpl.offsetForArray(Ht(e))*60):new Date(e.valueOf()-(t||0))}}class Bn{constructor(e){this.iconOverrideOption&&this.setIconOverride(e[this.iconOverrideOption])}setIconOverride(e){let t,n;if("object"==typeof e&&e){for(n in t=Object.assign({},this.iconClasses),e)t[n]=this.applyIconOverridePrefix(e[n]);this.iconClasses=t}else!1===e&&(this.iconClasses={})}applyIconOverridePrefix(e){let t=this.iconOverridePrefix;return t&&0!==e.indexOf(t)&&(e=t+e),e}getClass(e){return this.classes[e]||""}getIconClass(e,t){let n;return n=t&&this.rtlIconClasses&&this.rtlIconClasses[e]||this.iconClasses[e],n?`${this.baseIconClass} ${n}`:""}getCustomButtonIconClass(e){let t;return this.iconOverrideCustomButtonOption&&(t=e[this.iconOverrideCustomButtonOption],t)?`${this.baseIconClass} ${this.applyIconOverridePrefix(t)}`:""}}function jn(e){e();let t=n.debounceRendering,r=[];for(n.debounceRendering=function(e){r.push(e)},U(p(zn,{}),document.createElement("div"));r.length;)r.shift()();n.debounceRendering=t}Bn.prototype.classes={},Bn.prototype.iconClasses={},Bn.prototype.baseIconClass="",Bn.prototype.iconOverridePrefix="";class zn extends A{render(){return p("div",{})}componentDidMount(){this.setState({})}}function Un(e){let t=function(e,t){var n={__c:t="__cC"+c++,__:e,Consumer:function(e,t){return e.children(t)},Provider:function(e){var n,r;return this.getChildContext||(n=[],(r={})[t]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(e){this.props.value!==e.value&&n.some((function(e){e.__e=!0,x(e)}))},this.sub=function(e){n.push(e);var t=e.componentWillUnmount;e.componentWillUnmount=function(){n.splice(n.indexOf(e),1),t&&t.call(e)}}),e.children}};return n.Provider.__=n.Consumer.contextType=n}(e),n=t.Provider;return t.Provider=function(){let e=!this.getChildContext,t=n.apply(this,arguments);if(e){let e=[];this.shouldComponentUpdate=t=>{this.props.value!==t.value&&e.forEach(e=>{e.context=t.value,e.forceUpdate()})},this.sub=t=>{e.push(t);let n=t.componentWillUnmount;t.componentWillUnmount=()=>{e.splice(e.indexOf(t),1),n&&n.call(t)}}}return t},t}class Ln{constructor(e,t,n,r){this.execFunc=e,this.emitter=t,this.scrollTime=n,this.scrollTimeReset=r,this.handleScrollRequest=e=>{this.queuedRequest=Object.assign({},this.queuedRequest||{},e),this.drain()},t.on("_scrollRequest",this.handleScrollRequest),this.fireInitialScroll()}detach(){this.emitter.off("_scrollRequest",this.handleScrollRequest)}update(e){e&&this.scrollTimeReset?this.fireInitialScroll():this.drain()}fireInitialScroll(){this.handleScrollRequest({time:this.scrollTime})}drain(){this.queuedRequest&&this.execFunc(this.queuedRequest)&&(this.queuedRequest=null)}}const Wn=Un({});function Fn(e,t,n,r,i,s,o,a,l,c,d,u,h,f){return{dateEnv:i,nowManager:s,options:n,pluginHooks:a,emitter:d,dispatch:l,getCurrentData:c,calendarApi:u,viewSpec:e,viewApi:t,dateProfileGenerator:r,theme:o,isRtl:"rtl"===n.direction,addResizeHandler(e){d.on("_resize",e)},removeResizeHandler(e){d.off("_resize",e)},createScrollResponder:e=>new Ln(e,d,ft(n.scrollTime),n.scrollTimeReset),registerInteractiveComponent:h,unregisterInteractiveComponent:f}}class Vn extends A{shouldComponentUpdate(e,t){return this.debug&&console.log(xn(e,this.props),xn(t,this.state)),!_n(this.props,e,this.propEquality)||!_n(this.state,t,this.stateEquality)}safeSetState(e){_n(this.state,Object.assign(Object.assign({},this.state),e),this.stateEquality)||this.setState(e)}}Vn.addPropsEquality=function(e){let t=Object.create(this.prototype.propEquality);Object.assign(t,e),this.prototype.propEquality=t},Vn.addStateEquality=function(e){let t=Object.create(this.prototype.stateEquality);Object.assign(t,e),this.prototype.stateEquality=t},Vn.contextType=Wn,Vn.prototype.propEquality={},Vn.prototype.stateEquality={};class Gn extends Vn{}function Qn(e,t){"function"==typeof e?e(t):e&&(e.current=t)}Gn.contextType=Wn;class qn extends Gn{constructor(){super(...arguments),this.id=Ze(),this.queuedDomNodes=[],this.currentDomNodes=[],this.handleEl=e=>{const{options:t}=this.context,{generatorName:n}=this.props;t.customRenderingReplaces&&Yn(n,t)||this.updateElRef(e)},this.updateElRef=e=>{this.props.elRef&&Qn(this.props.elRef,e)}}render(){const{props:e,context:t}=this,{options:n}=t,{customGenerator:r,defaultGenerator:s,renderProps:o}=e,a=Zn(e,[],this.handleEl);let l,c,d=!1,u=[];if(null!=r){const e="function"==typeof r?r(o,p):r;if(!0===e)d=!0;else{const t=e&&"object"==typeof e;t&&"html"in e?a.dangerouslySetInnerHTML={__html:e.html}:t&&"domNodes"in e?u=Array.prototype.slice.call(e.domNodes):(t?i(e):"function"!=typeof e)?l=e:c=e}}else d=!Yn(e.generatorName,n);return d&&s&&(l=s(o)),this.queuedDomNodes=u,this.currentGeneratorMeta=c,p(e.elTag,a,l)}componentDidMount(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentDidUpdate(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentWillUnmount(){this.triggerCustomRendering(!1)}triggerCustomRendering(e){var t;const{props:n,context:r}=this,{handleCustomRendering:i,customRenderingMetaMap:s}=r.options;if(i){const r=null!==(t=this.currentGeneratorMeta)&&void 0!==t?t:null==s?void 0:s[n.generatorName];r&&i(Object.assign(Object.assign({id:this.id,isActive:e,containerEl:this.base,reportNewContainerEl:this.updateElRef,generatorMeta:r},n),{elClasses:(n.elClasses||[]).filter(Xn)}))}}applyQueueudDomNodes(){const{queuedDomNodes:e,currentDomNodes:t}=this,n=this.base;if(!St(e,t)){t.forEach(Ie);for(let t of e)n.appendChild(t);this.currentDomNodes=e}}}function Yn(e,t){var n;return Boolean(t.handleCustomRendering&&e&&(null===(n=t.customRenderingMetaMap)||void 0===n?void 0:n[e]))}function Zn(e,t,n){const r=Object.assign(Object.assign({},e.elAttrs),{ref:n});return(e.elClasses||t)&&(r.className=(e.elClasses||[]).concat(t||[]).concat(r.className||[]).filter(Boolean).join(" ")),e.elStyle&&(r.style=e.elStyle),r}function Xn(e){return Boolean(e)}qn.addPropsEquality({elClasses:St,elStyle:Cn,elAttrs:function(e,t){const n=xn(e,t);for(let e of n)if(!Rn.test(e))return!1;return!0},renderProps:Cn});const $n=Un(0);class Jn extends A{constructor(){super(...arguments),this.InnerContent=Kn.bind(void 0,this),this.handleEl=e=>{this.el=e,this.props.elRef&&(Qn(this.props.elRef,e),e&&this.didMountMisfire&&this.componentDidMount())}}render(){const{props:e}=this,t=function(e,t){const n="function"==typeof e?e(t):e||[];return"string"==typeof n?[n]:n}(e.classNameGenerator,e.renderProps);if(e.children){const n=Zn(e,t,this.handleEl),r=e.children(this.InnerContent,e.renderProps,n);return e.elTag?p(e.elTag,n,r):r}return p(qn,Object.assign(Object.assign({},e),{elRef:this.handleEl,elTag:e.elTag||"div",elClasses:(e.elClasses||[]).concat(t),renderId:this.context}))}componentDidMount(){var e,t;this.el?null===(t=(e=this.props).didMount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.el})):this.didMountMisfire=!0}componentWillUnmount(){var e,t;null===(t=(e=this.props).willUnmount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.el}))}}function Kn(e,t){const n=e.props;return p(qn,Object.assign({renderProps:n.renderProps,generatorName:n.generatorName,customGenerator:n.customGenerator,defaultGenerator:n.defaultGenerator,renderId:e.context},t))}Jn.contextType=$n;class er extends Gn{render(){let{props:e,context:t}=this,{options:n}=t,r={view:t.viewApi};return p(Jn,Object.assign({},e,{elTag:e.elTag||"div",elClasses:[...tr(e.viewSpec),...e.elClasses||[]],renderProps:r,classNameGenerator:n.viewClassNames,generatorName:void 0,didMount:n.viewDidMount,willUnmount:n.viewWillUnmount}),()=>e.children)}}function tr(e){return[`fc-${e.type}-view`,"fc-view"]}function nr(e,t){let n,r,i=[],{start:s}=t;for(e.sort(rr),n=0;n<e.length;n+=1)r=e[n],r.start>s&&i.push({start:s,end:r.start}),r.end>s&&(s=r.end);return s<t.end&&i.push({start:s,end:t.end}),i}function rr(e,t){return e.start.valueOf()-t.start.valueOf()}function ir(e,t){let{start:n,end:r}=e,i=null;return null!==t.start&&(n=null===n?t.start:new Date(Math.max(n.valueOf(),t.start.valueOf()))),null!=t.end&&(r=null===r?t.end:new Date(Math.min(r.valueOf(),t.end.valueOf()))),(null===n||null===r||n<r)&&(i={start:n,end:r}),i}function sr(e,t){return(null===e.start?null:e.start.valueOf())===(null===t.start?null:t.start.valueOf())&&(null===e.end?null:e.end.valueOf())===(null===t.end?null:t.end.valueOf())}function or(e,t){return(null===e.end||null===t.start||e.end>t.start)&&(null===e.start||null===t.end||e.start<t.end)}function ar(e,t){return(null===e.start||null!==t.start&&t.start>=e.start)&&(null===e.end||null!==t.end&&t.end<=e.end)}function lr(e,t){return(null===e.start||t>=e.start)&&(null===e.end||t<e.end)}function cr(e){let t=Math.floor(xt(e.start,e.end))||1,n=Mt(e.start);return{start:n,end:wt(n,t)}}function dr(e,t=ft(0)){let n=null,r=null;if(e.end){r=Mt(e.end);let n=e.end.valueOf()-r.valueOf();n&&n>=yt(t)&&(r=wt(r,1))}return e.start&&(n=Mt(e.start),r&&r<=n&&(r=wt(n,1))),{start:n,end:r}}function ur(e){let t=dr(e);return xt(t.start,t.end)>1}function hr(e,t,n,r){return"year"===r?ft(n.diffWholeYears(e,t),"year"):"month"===r?ft(n.diffWholeMonths(e,t),"month"):_t(e,t)}class fr{constructor(e){this.props=e,this.initHiddenDays()}buildPrev(e,t,n){let{dateEnv:r}=this.props,i=r.subtract(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,-1,n)}buildNext(e,t,n){let{dateEnv:r}=this.props,i=r.add(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,1,n)}build(e,t,n=!0){let r,i,s,o,a,l,{props:c}=this;var d,u;return r=this.buildValidRange(),r=this.trimHiddenDays(r),n&&(d=e,e=null!=(u=r).start&&d<u.start?u.start:null!=u.end&&d>=u.end?new Date(u.end.valueOf()-1):d),i=this.buildCurrentRangeInfo(e,t),s=/^(year|month|week|day)$/.test(i.unit),o=this.buildRenderRange(this.trimHiddenDays(i.range),i.unit,s),o=this.trimHiddenDays(o),a=o,c.showNonCurrentDates||(a=ir(a,i.range)),a=this.adjustActiveRange(a),a=ir(a,r),l=or(i.range,r),lr(o,e)||(e=o.start),{currentDate:e,validRange:r,currentRange:i.range,currentRangeUnit:i.unit,isRangeAllDay:s,activeRange:a,renderRange:o,slotMinTime:c.slotMinTime,slotMaxTime:c.slotMaxTime,isValid:l,dateIncrement:this.buildDateIncrement(i.duration)}}buildValidRange(){let e=this.props.validRangeInput,t="function"==typeof e?e.call(this.props.calendarApi,this.props.dateEnv.toDate(this.props.nowManager.getDateMarker())):e;return this.refineRange(t)||{start:null,end:null}}buildCurrentRangeInfo(e,t){let n,{props:r}=this,i=null,s=null,o=null;return r.duration?(i=r.duration,s=r.durationUnit,o=this.buildRangeFromDuration(e,t,i,s)):(n=this.props.dayCount)?(s="day",o=this.buildRangeFromDayCount(e,t,n)):(o=this.buildCustomVisibleRange(e))?s=r.dateEnv.greatestWholeUnit(o.start,o.end).unit:(i=this.getFallbackDuration(),s=Et(i).unit,o=this.buildRangeFromDuration(e,t,i,s)),{duration:i,unit:s,range:o}}getFallbackDuration(){return ft({day:1})}adjustActiveRange(e){let{dateEnv:t,usesMinMaxTime:n,slotMinTime:r,slotMaxTime:i}=this.props,{start:s,end:o}=e;return n&&(vt(r)<0&&(s=Mt(s),s=t.add(s,r)),vt(i)>1&&(o=Mt(o),o=wt(o,-1),o=t.add(o,i))),{start:s,end:o}}buildRangeFromDuration(e,t,n,r){let i,s,o,{dateEnv:a,dateAlignment:l}=this.props;if(!l){let{dateIncrement:e}=this.props;l=e&&yt(e)<yt(n)?Et(e).unit:r}function c(){i=a.startOf(e,l),s=a.add(i,n),o={start:i,end:s}}return vt(n)<=1&&this.isHiddenDay(i)&&(i=this.skipHiddenDays(i,t),i=Mt(i)),c(),this.trimHiddenDays(o)||(e=this.skipHiddenDays(e,t),c()),o}buildRangeFromDayCount(e,t,n){let r,{dateEnv:i,dateAlignment:s}=this.props,o=0,a=e;s&&(a=i.startOf(a,s)),a=Mt(a),a=this.skipHiddenDays(a,t),r=a;do{r=wt(r,1),this.isHiddenDay(r)||(o+=1)}while(o<n);return{start:a,end:r}}buildCustomVisibleRange(e){let{props:t}=this,n=t.visibleRangeInput,r="function"==typeof n?n.call(t.calendarApi,t.dateEnv.toDate(e)):n,i=this.refineRange(r);return!i||null!=i.start&&null!=i.end?i:null}buildRenderRange(e,t,n){return e}buildDateIncrement(e){let t,{dateIncrement:n}=this.props;return n||((t=this.props.dateAlignment)?ft(1,t):e||ft({days:1}))}refineRange(e){if(e){let t=function(e,t){let n=null,r=null;return e.start&&(n=t.createMarker(e.start)),e.end&&(r=t.createMarker(e.end)),n||r?n&&r&&r<n?null:{start:n,end:r}:null}(e,this.props.dateEnv);return t&&(t=dr(t)),t}return null}initHiddenDays(){let e,t=this.props.hiddenDays||[],n=[],r=0;for(!1===this.props.weekends&&t.push(0,6),e=0;e<7;e+=1)(n[e]=-1!==t.indexOf(e))||(r+=1);if(!r)throw new Error("invalid hiddenDays");this.isHiddenDayHash=n}trimHiddenDays(e){let{start:t,end:n}=e;return t&&(t=this.skipHiddenDays(t)),n&&(n=this.skipHiddenDays(n,-1,!0)),null==t||null==n||t<n?{start:t,end:n}:null}isHiddenDay(e){return e instanceof Date&&(e=e.getUTCDay()),this.isHiddenDayHash[e]}skipHiddenDays(e,t=1,n=!1){for(;this.isHiddenDayHash[(e.getUTCDay()+(n?t:0)+7)%7];)e=wt(e,t);return e}}function gr(e,t,n,r){return{instanceId:Ze(),defId:e,range:t,forcedStartTzo:null==n?null:n,forcedEndTzo:null==r?null:r}}function pr(e,t,n){let{dateEnv:r,pluginHooks:i,options:s}=n,{defs:o,instances:a}=e;a=Sn(a,e=>!o[e.defId].recurringDef);for(let e in o){let n=o[e];if(n.recurringDef){let{duration:o}=n.recurringDef;o||(o=n.allDay?s.defaultAllDayEventDuration:s.defaultTimedEventDuration);let l=mr(n,o,t,r,i.recurringTypes);for(let t of l){let n=gr(e,{start:t,end:r.add(t,o)});a[n.instanceId]=n}}}return{defs:o,instances:a}}function mr(e,t,n,r,i){let s=i[e.recurringDef.typeId].expand(e.recurringDef.typeData,{start:r.subtract(n.start,t),end:n.end},r);return e.allDay&&(s=s.map(Mt)),s}const vr={id:String,groupId:String,title:String,url:String,interactive:Boolean},yr={start:yn,end:yn,date:yn,allDay:Boolean},br=Object.assign(Object.assign(Object.assign({},vr),yr),{extendedProps:yn});function Er(e,t,n,r,i=Dr(n),s,o){let{refined:a,extra:l}=Sr(e,n,i),c=function(e,t){let n=null;e&&(n=e.defaultAllDay);null==n&&(n=t.options.defaultAllDay);return n}(t,n),d=function(e,t,n,r){for(let i=0;i<r.length;i+=1){let s=r[i].parse(e,n);if(s){let{allDay:n}=e;return null==n&&(n=t,null==n&&(n=s.allDayGuess,null==n&&(n=!1))),{allDay:n,duration:s.duration,typeData:s.typeData,typeId:i}}}return null}(a,c,n.dateEnv,n.pluginHooks.recurringTypes);if(d){let e=Ar(a,l,t?t.sourceId:"",d.allDay,Boolean(d.duration),n,s);return e.recurringDef={typeId:d.typeId,typeData:d.typeData,duration:d.duration},{def:e,instance:null}}let u=function(e,t,n,r){let i,s,{allDay:o}=e,a=null,l=!1,c=null,d=null!=e.start?e.start:e.date;if(i=n.dateEnv.createMarkerMeta(d),i)a=i.marker;else if(!r)return null;null!=e.end&&(s=n.dateEnv.createMarkerMeta(e.end));null==o&&(o=null!=t?t:(!i||i.isTimeUnspecified)&&(!s||s.isTimeUnspecified));o&&a&&(a=Mt(a));s&&(c=s.marker,o&&(c=Mt(c)),a&&c<=a&&(c=null));c?l=!0:r||(l=n.options.forceEventDuration||!1,c=n.dateEnv.add(a,o?n.options.defaultAllDayEventDuration:n.options.defaultTimedEventDuration));return{allDay:o,hasEnd:l,range:{start:a,end:c},forcedStartTzo:i?i.forcedTzo:null,forcedEndTzo:s?s.forcedTzo:null}}(a,c,n,r);if(u){let e=Ar(a,l,t?t.sourceId:"",u.allDay,u.hasEnd,n,s),r=gr(e.defId,u.range,u.forcedStartTzo,u.forcedEndTzo);return o&&e.publicId&&o[e.publicId]&&(r.instanceId=o[e.publicId]),{def:e,instance:r}}return null}function Sr(e,t,n=Dr(t)){return vn(e,n)}function Dr(e){return Object.assign(Object.assign(Object.assign({},Mr),br),e.pluginHooks.eventRefiners)}function Ar(e,t,n,r,i,s,o){let a={title:e.title||"",groupId:e.groupId||"",publicId:e.id||"",url:e.url||"",recurringDef:null,defId:(o&&e.id?o[e.id]:"")||Ze(),sourceId:n,allDay:r,hasEnd:i,interactive:e.interactive,ui:Or(e,s),extendedProps:Object.assign(Object.assign({},e.extendedProps||{}),t)};for(let t of s.pluginHooks.eventDefMemberAdders)Object.assign(a,t(e));return Object.freeze(a.ui.classNames),Object.freeze(a.extendedProps),a}function wr(e,t,n,r,i,s){let o={defs:{},instances:{}},a=Dr(n);for(let l of e){let e=Er(l,t,n,r,a,i,s);e&&Cr(e,o)}return o}function Cr(e,t={defs:{},instances:{}}){return t.defs[e.def.defId]=e.def,e.instance&&(t.instances[e.instance.instanceId]=e.instance),t}function Rr(e,t){let n=e.instances[t];if(n){let t=e.defs[n.defId],r=Tr(e,e=>{return n=t,r=e,Boolean(n.groupId&&n.groupId===r.groupId);var n,r});return r.defs[t.defId]=t,r.instances[n.instanceId]=n,r}return{defs:{},instances:{}}}function xr(){return{defs:{},instances:{}}}function _r(e,t){return{defs:Object.assign(Object.assign({},e.defs),t.defs),instances:Object.assign(Object.assign({},e.instances),t.instances)}}function Tr(e,t){let n=Sn(e.defs,t),r=Sn(e.instances,e=>n[e.defId]);return{defs:n,instances:r}}function kr(e){return Array.isArray(e)?e:"string"==typeof e?e.split(/\s+/):[]}const Mr={display:String,editable:Boolean,startEditable:Boolean,durationEditable:Boolean,constraint:yn,overlap:yn,allow:yn,className:kr,classNames:kr,color:String,backgroundColor:String,borderColor:String,textColor:String},Ir={display:null,startEditable:null,durationEditable:null,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]};function Or(e,t){let n=function(e,t){return Array.isArray(e)?wr(e,null,t,!0):"object"==typeof e&&e?wr([e],null,t,!0):null!=e?String(e):null}(e.constraint,t);return{display:e.display||null,startEditable:null!=e.startEditable?e.startEditable:e.editable,durationEditable:null!=e.durationEditable?e.durationEditable:e.editable,constraints:null!=n?[n]:[],overlap:null!=e.overlap?e.overlap:null,allows:null!=e.allow?[e.allow]:[],backgroundColor:e.backgroundColor||e.color||"",borderColor:e.borderColor||e.color||"",textColor:e.textColor||"",classNames:(e.className||[]).concat(e.classNames||[])}}function Nr(e){return e.reduce(Pr,Ir)}function Pr(e,t){return{display:null!=t.display?t.display:e.display,startEditable:null!=t.startEditable?t.startEditable:e.startEditable,durationEditable:null!=t.durationEditable?t.durationEditable:e.durationEditable,constraints:e.constraints.concat(t.constraints),overlap:"boolean"==typeof t.overlap?t.overlap:e.overlap,allows:e.allows.concat(t.allows),backgroundColor:t.backgroundColor||e.backgroundColor,borderColor:t.borderColor||e.borderColor,textColor:t.textColor||e.textColor,classNames:e.classNames.concat(t.classNames)}}const Hr={id:String,defaultAllDay:Boolean,url:String,format:String,events:yn,eventDataTransform:yn,success:yn,failure:yn};function Br(e,t,n=jr(t)){let r;if("string"==typeof e?r={url:e}:"function"==typeof e||Array.isArray(e)?r={events:e}:"object"==typeof e&&e&&(r=e),r){let{refined:i,extra:s}=vn(r,n),o=function(e,t){let n=t.pluginHooks.eventSourceDefs;for(let t=n.length-1;t>=0;t-=1){let r=n[t].parseMeta(e);if(r)return{sourceDefId:t,meta:r}}return null}(i,t);if(o)return{_raw:e,isFetching:!1,latestFetchId:"",fetchRange:null,defaultAllDay:i.defaultAllDay,eventDataTransform:i.eventDataTransform,success:i.success,failure:i.failure,publicId:i.id||"",sourceId:Ze(),sourceDefId:o.sourceDefId,meta:o.meta,ui:Or(i,t),extendedProps:s}}return null}function jr(e){return Object.assign(Object.assign(Object.assign({},Mr),Hr),e.pluginHooks.eventSourceRefiners)}function zr(e,t,n,r,i){switch(t.type){case"RECEIVE_EVENTS":return function(e,t,n,r,i,s){if(t&&n===t.latestFetchId){let n=wr(Ur(i,t,s),t,s);return r&&(n=pr(n,r,s)),_r(Fr(e,t.sourceId),n)}return e}(e,n[t.sourceId],t.fetchId,t.fetchRange,t.rawEvents,i);case"RESET_RAW_EVENTS":return function(e,t,n,r,i){const{defIdMap:s,instanceIdMap:o}=function(e){const{defs:t,instances:n}=e,r={},i={};for(let e in t){const n=t[e],{publicId:i}=n;i&&(r[i]=e)}for(let e in n){const r=n[e],s=t[r.defId],{publicId:o}=s;o&&(i[o]=e)}return{defIdMap:r,instanceIdMap:i}}(e);return pr(wr(Ur(n,t,i),t,i,!1,s,o),r,i)}(e,n[t.sourceId],t.rawEvents,r.activeRange,i);case"ADD_EVENTS":return function(e,t,n,r){n&&(t=pr(t,n,r));return _r(e,t)}(e,t.eventStore,r?r.activeRange:null,i);case"RESET_EVENTS":return t.eventStore;case"MERGE_EVENTS":return _r(e,t.eventStore);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return r?pr(e,r.activeRange,i):e;case"REMOVE_EVENTS":return function(e,t){let{defs:n,instances:r}=e,i={},s={};for(let e in n)t.defs[e]||(i[e]=n[e]);for(let e in r)!t.instances[e]&&i[r[e].defId]&&(s[e]=r[e]);return{defs:i,instances:s}}(e,t.eventStore);case"REMOVE_EVENT_SOURCE":return Fr(e,t.sourceId);case"REMOVE_ALL_EVENT_SOURCES":return Tr(e,e=>!e.sourceId);case"REMOVE_ALL_EVENTS":return{defs:{},instances:{}};default:return e}}function Ur(e,t,n){let r=n.options.eventDataTransform,i=t?t.eventDataTransform:null;return i&&(e=Lr(e,i)),r&&(e=Lr(e,r)),e}function Lr(e,t){let n;if(t){n=[];for(let r of e){let e=t(r);e?n.push(e):null==e&&n.push(r)}}else n=e;return n}function Wr(e,t,n){let{defs:r}=e,i=Dn(e.instances,e=>r[e.defId].allDay?e:Object.assign(Object.assign({},e),{range:{start:n.createMarker(t.toDate(e.range.start,e.forcedStartTzo)),end:n.createMarker(t.toDate(e.range.end,e.forcedEndTzo))},forcedStartTzo:n.canComputeOffset?null:e.forcedStartTzo,forcedEndTzo:n.canComputeOffset?null:e.forcedEndTzo}));return{defs:r,instances:i}}function Fr(e,t){return Tr(e,e=>e.sourceId!==t)}class Vr{constructor(){this.handlers={},this.thisContext=null}setThisContext(e){this.thisContext=e}setOptions(e){this.options=e}on(e,t){!function(e,t,n){(e[t]||(e[t]=[])).push(n)}(this.handlers,e,t)}off(e,t){!function(e,t,n){n?e[t]&&(e[t]=e[t].filter(e=>e!==n)):delete e[t]}(this.handlers,e,t)}trigger(e,...t){let n=this.handlers[e]||[],r=this.options&&this.options[e],i=[].concat(r||[],n);for(let e of i)e.apply(this.thisContext,t)}hasHandlers(e){return Boolean(this.handlers[e]&&this.handlers[e].length||this.options&&this.options[e])}}const Gr={startTime:"09:00",endTime:"17:00",daysOfWeek:[1,2,3,4,5],display:"inverse-background",classNames:"fc-non-business",groupId:"_businessHours"};function Qr(e,t){return wr(function(e){let t;t=!0===e?[{}]:Array.isArray(e)?e.filter(e=>e.daysOfWeek):"object"==typeof e&&e?[e]:[];return t=t.map(e=>Object.assign(Object.assign({},Gr),e)),t}(e),null,t)}function qr(e,t,n){n.emitter.trigger("select",Object.assign(Object.assign({},Yr(e,n)),{jsEvent:t?t.origEvent:null,view:n.viewApi||n.calendarApi.view}))}function Yr(e,t){let n={};for(let r of t.pluginHooks.dateSpanTransforms)Object.assign(n,r(e,t));var r,i;return Object.assign(n,(r=e,i=t.dateEnv,Object.assign(Object.assign({},Ai(r.range,i,r.allDay)),{allDay:r.allDay}))),n}function Zr(e,t,n){let{dateEnv:r,options:i}=n,s=t;return e?(s=Mt(s),s=r.add(s,i.defaultAllDayEventDuration)):s=r.add(s,i.defaultTimedEventDuration),s}function Xr(e,t,n,r){let i=ai(e.defs,t),s={defs:{},instances:{}};for(let t in e.defs){let o=e.defs[t];s.defs[t]=$r(o,i[t],n,r)}for(let t in e.instances){let o=e.instances[t],a=s.defs[o.defId];s.instances[t]=Jr(o,a,i[o.defId],n,r)}return s}function $r(e,t,n,r){let i=n.standardProps||{};null==i.hasEnd&&t.durationEditable&&(n.startDelta||n.endDelta)&&(i.hasEnd=!0);let s=Object.assign(Object.assign(Object.assign({},e),i),{ui:Object.assign(Object.assign({},e.ui),i.ui)});n.extendedProps&&(s.extendedProps=Object.assign(Object.assign({},s.extendedProps),n.extendedProps));for(let e of r.pluginHooks.eventDefMutationAppliers)e(s,n,r);return!s.hasEnd&&r.options.forceEventDuration&&(s.hasEnd=!0),s}function Jr(e,t,n,r,i){let{dateEnv:s}=i,o=r.standardProps&&!0===r.standardProps.allDay,a=r.standardProps&&!1===r.standardProps.hasEnd,l=Object.assign({},e);return o&&(l.range=cr(l.range)),r.datesDelta&&n.startEditable&&(l.range={start:s.add(l.range.start,r.datesDelta),end:s.add(l.range.end,r.datesDelta)}),r.startDelta&&n.durationEditable&&(l.range={start:s.add(l.range.start,r.startDelta),end:l.range.end}),r.endDelta&&n.durationEditable&&(l.range={start:l.range.start,end:s.add(l.range.end,r.endDelta)}),a&&(l.range={start:l.range.start,end:Zr(t.allDay,l.range.start,i)}),t.allDay&&(l.range={start:Mt(l.range.start),end:Mt(l.range.end)}),l.range.end<l.range.start&&(l.range.end=Zr(t.allDay,l.range.start,i)),l}class Kr{constructor(e,t){this.context=e,this.internalEventSource=t}remove(){this.context.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:this.internalEventSource.sourceId})}refetch(){this.context.dispatch({type:"FETCH_EVENT_SOURCES",sourceIds:[this.internalEventSource.sourceId],isRefetch:!0})}get id(){return this.internalEventSource.publicId}get url(){return this.internalEventSource.meta.url}get format(){return this.internalEventSource.meta.format}}class ei{constructor(e,t,n){this._context=e,this._def=t,this._instance=n||null}setProp(e,t){if(e in yr)console.warn("Could not set date-related prop 'name'. Use one of the date-related methods instead.");else if("id"===e)t=vr[e](t),this.mutate({standardProps:{publicId:t}});else if(e in vr)t=vr[e](t),this.mutate({standardProps:{[e]:t}});else if(e in Mr){let n=Mr[e](t);n="color"===e?{backgroundColor:t,borderColor:t}:"editable"===e?{startEditable:t,durationEditable:t}:{[e]:t},this.mutate({standardProps:{ui:n}})}else console.warn(`Could not set prop '${e}'. Use setExtendedProp instead.`)}setExtendedProp(e,t){this.mutate({extendedProps:{[e]:t}})}setStart(e,t={}){let{dateEnv:n}=this._context,r=n.createMarker(e);if(r&&this._instance){let e=hr(this._instance.range.start,r,n,t.granularity);t.maintainDuration?this.mutate({datesDelta:e}):this.mutate({startDelta:e})}}setEnd(e,t={}){let n,{dateEnv:r}=this._context;if((null==e||(n=r.createMarker(e),n))&&this._instance)if(n){let e=hr(this._instance.range.end,n,r,t.granularity);this.mutate({endDelta:e})}else this.mutate({standardProps:{hasEnd:!1}})}setDates(e,t,n={}){let r,{dateEnv:i}=this._context,s={allDay:n.allDay},o=i.createMarker(e);var a,l;if(o&&((null==t||(r=i.createMarker(t),r))&&this._instance)){let e=this._instance.range;!0===n.allDay&&(e=cr(e));let t=hr(e.start,o,i,n.granularity);if(r){let o=hr(e.end,r,i,n.granularity);l=o,(a=t).years===l.years&&a.months===l.months&&a.days===l.days&&a.milliseconds===l.milliseconds?this.mutate({datesDelta:t,standardProps:s}):this.mutate({startDelta:t,endDelta:o,standardProps:s})}else s.hasEnd=!1,this.mutate({datesDelta:t,standardProps:s})}}moveStart(e){let t=ft(e);t&&this.mutate({startDelta:t})}moveEnd(e){let t=ft(e);t&&this.mutate({endDelta:t})}moveDates(e){let t=ft(e);t&&this.mutate({datesDelta:t})}setAllDay(e,t={}){let n={allDay:e},{maintainDuration:r}=t;null==r&&(r=this._context.options.allDayMaintainDuration),this._def.allDay!==e&&(n.hasEnd=r),this.mutate({standardProps:n})}formatRange(e){let{dateEnv:t}=this._context,n=this._instance,r=an(e);return this._def.hasEnd?t.formatRange(n.range.start,n.range.end,r,{forcedStartTzo:n.forcedStartTzo,forcedEndTzo:n.forcedEndTzo}):t.format(n.range.start,r,{forcedTzo:n.forcedStartTzo})}mutate(e){let t=this._instance;if(t){let n=this._def,r=this._context,{eventStore:i}=r.getCurrentData(),s=Rr(i,t.instanceId);s=Xr(s,{"":{display:"",startEditable:!0,durationEditable:!0,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]}},e,r);let o=new ei(r,n,t);this._def=s.defs[n.defId],this._instance=s.instances[t.instanceId],r.dispatch({type:"MERGE_EVENTS",eventStore:s}),r.emitter.trigger("eventChange",{oldEvent:o,event:this,relatedEvents:ni(s,r,t),revert(){r.dispatch({type:"RESET_EVENTS",eventStore:i})}})}}remove(){let e=this._context,t=ti(this);e.dispatch({type:"REMOVE_EVENTS",eventStore:t}),e.emitter.trigger("eventRemove",{event:this,relatedEvents:[],revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:t})}})}get source(){let{sourceId:e}=this._def;return e?new Kr(this._context,this._context.getCurrentData().eventSources[e]):null}get start(){return this._instance?this._context.dateEnv.toDate(this._instance.range.start):null}get end(){return this._instance&&this._def.hasEnd?this._context.dateEnv.toDate(this._instance.range.end):null}get startStr(){let e=this._instance;return e?this._context.dateEnv.formatIso(e.range.start,{omitTime:this._def.allDay,forcedTzo:e.forcedStartTzo}):""}get endStr(){let e=this._instance;return e&&this._def.hasEnd?this._context.dateEnv.formatIso(e.range.end,{omitTime:this._def.allDay,forcedTzo:e.forcedEndTzo}):""}get id(){return this._def.publicId}get groupId(){return this._def.groupId}get allDay(){return this._def.allDay}get title(){return this._def.title}get url(){return this._def.url}get display(){return this._def.ui.display||"auto"}get startEditable(){return this._def.ui.startEditable}get durationEditable(){return this._def.ui.durationEditable}get constraint(){return this._def.ui.constraints[0]||null}get overlap(){return this._def.ui.overlap}get allow(){return this._def.ui.allows[0]||null}get backgroundColor(){return this._def.ui.backgroundColor}get borderColor(){return this._def.ui.borderColor}get textColor(){return this._def.ui.textColor}get classNames(){return this._def.ui.classNames}get extendedProps(){return this._def.extendedProps}toPlainObject(e={}){let t=this._def,{ui:n}=t,{startStr:r,endStr:i}=this,s={allDay:t.allDay};return t.title&&(s.title=t.title),r&&(s.start=r),i&&(s.end=i),t.publicId&&(s.id=t.publicId),t.groupId&&(s.groupId=t.groupId),t.url&&(s.url=t.url),n.display&&"auto"!==n.display&&(s.display=n.display),e.collapseColor&&n.backgroundColor&&n.backgroundColor===n.borderColor?s.color=n.backgroundColor:(n.backgroundColor&&(s.backgroundColor=n.backgroundColor),n.borderColor&&(s.borderColor=n.borderColor)),n.textColor&&(s.textColor=n.textColor),n.classNames.length&&(s.classNames=n.classNames),Object.keys(t.extendedProps).length&&(e.collapseExtendedProps?Object.assign(s,t.extendedProps):s.extendedProps=t.extendedProps),s}toJSON(){return this.toPlainObject()}}function ti(e){let t=e._def,n=e._instance;return{defs:{[t.defId]:t},instances:n?{[n.instanceId]:n}:{}}}function ni(e,t,n){let{defs:r,instances:i}=e,s=[],o=n?n.instanceId:"";for(let e in i){let n=i[e],a=r[n.defId];n.instanceId!==o&&s.push(new ei(t,a,n))}return s}function ri(e,t,n,r){let i={},s={},o={},a=[],l=[],c=ai(e.defs,t);for(let t in e.defs){let n=e.defs[t];"inverse-background"===c[n.defId].display&&(n.groupId?(i[n.groupId]=[],o[n.groupId]||(o[n.groupId]=n)):s[t]=[])}for(let t in e.instances){let o=e.instances[t],d=e.defs[o.defId],u=c[d.defId],h=o.range,f=!d.allDay&&r?dr(h,r):h,g=ir(f,n);g&&("inverse-background"===u.display?d.groupId?i[d.groupId].push(g):s[o.defId].push(g):"none"!==u.display&&("background"===u.display?a:l).push({def:d,ui:u,instance:o,range:g,isStart:f.start&&f.start.valueOf()===g.start.valueOf(),isEnd:f.end&&f.end.valueOf()===g.end.valueOf()}))}for(let e in i){let t=nr(i[e],n);for(let n of t){let t=o[e],r=c[t.defId];a.push({def:t,ui:r,instance:null,range:n,isStart:!1,isEnd:!1})}}for(let t in s){let r=nr(s[t],n);for(let n of r)a.push({def:e.defs[t],ui:c[t],instance:null,range:n,isStart:!1,isEnd:!1})}return{bg:a,fg:l}}function ii(e){return"background"===e.ui.display||"inverse-background"===e.ui.display}function si(e,t){e.fcSeg=t}function oi(e){return e.fcSeg||e.parentNode.fcSeg||null}function ai(e,t){return Dn(e,e=>li(e,t))}function li(e,t){let n=[];return t[""]&&n.push(t[""]),t[e.defId]&&n.push(t[e.defId]),n.push(e.ui),Nr(n)}function ci(e,t){let n=e.map(di);return n.sort((e,n)=>rt(e,n,t)),n.map(e=>e._seg)}function di(e){let{eventRange:t}=e,n=t.def,r=t.instance?t.instance.range:t.range,i=r.start?r.start.valueOf():0,s=r.end?r.end.valueOf():0;return Object.assign(Object.assign(Object.assign({},n.extendedProps),n),{id:n.publicId,start:i,end:s,duration:s-i,allDay:Number(n.allDay),_seg:e})}function ui(e,t){let{pluginHooks:n}=t,r=n.isDraggableTransformers,{def:i,ui:s}=e.eventRange,o=s.startEditable;for(let e of r)o=e(o,i,s,t);return o}function hi(e,t){return e.isStart&&e.eventRange.ui.durationEditable&&t.options.eventResizableFromStart}function fi(e,t){return e.isEnd&&e.eventRange.ui.durationEditable}function gi(e,t,n,r,i,s,o){let{dateEnv:a,options:l}=n,{displayEventTime:c,displayEventEnd:d}=l,u=e.eventRange.def,h=e.eventRange.instance;null==c&&(c=!1!==r),null==d&&(d=!1!==i);let f=h.range.start,g=h.range.end,p=s||e.start||e.eventRange.range.start,m=o||e.end||e.eventRange.range.end,v=Mt(f).valueOf()===Mt(p).valueOf(),y=Mt(Ct(g,-1)).valueOf()===Mt(Ct(m,-1)).valueOf();return c&&!u.allDay&&(v||y)?(p=v?f:p,m=y?g:m,d&&u.hasEnd?a.formatRange(p,m,t,{forcedStartTzo:s?null:h.forcedStartTzo,forcedEndTzo:o?null:h.forcedEndTzo}):a.format(p,t,{forcedTzo:s?null:h.forcedStartTzo})):""}function pi(e,t,n){let r=e.eventRange.range;return{isPast:r.end<=(n||t.start),isFuture:r.start>=(n||t.end),isToday:t&&lr(t,r.start)}}function mi(e){let t=["fc-event"];return e.isMirror&&t.push("fc-event-mirror"),e.isDraggable&&t.push("fc-event-draggable"),(e.isStartResizable||e.isEndResizable)&&t.push("fc-event-resizable"),e.isDragging&&t.push("fc-event-dragging"),e.isResizing&&t.push("fc-event-resizing"),e.isSelected&&t.push("fc-event-selected"),e.isStart&&t.push("fc-event-start"),e.isEnd&&t.push("fc-event-end"),e.isPast&&t.push("fc-event-past"),e.isToday&&t.push("fc-event-today"),e.isFuture&&t.push("fc-event-future"),t}function vi(e){return e.instance?e.instance.instanceId:`${e.def.defId}:${e.range.start.toISOString()}`}function yi(e,t){let{def:n,instance:r}=e.eventRange,{url:i}=n;if(i)return{href:i};let{emitter:s,options:o}=t,{eventInteractive:a}=o;return null==a&&(a=n.interactive,null==a&&(a=Boolean(s.hasHandlers("eventClick")))),a?qe(e=>{s.trigger("eventClick",{el:e.target,event:new ei(t,n,r),jsEvent:e,view:t.viewApi})}):{}}const bi={start:yn,end:yn,allDay:Boolean};function Ei(e,t,n){let r=function(e,t){let{refined:n,extra:r}=vn(e,bi),i=n.start?t.createMarkerMeta(n.start):null,s=n.end?t.createMarkerMeta(n.end):null,{allDay:o}=n;null==o&&(o=i&&i.isTimeUnspecified&&(!s||s.isTimeUnspecified));return Object.assign({range:{start:i?i.marker:null,end:s?s.marker:null},allDay:o},r)}(e,t),{range:i}=r;if(!i.start)return null;if(!i.end){if(null==n)return null;i.end=t.add(i.start,n)}return r}function Si(e,t){return sr(e.range,t.range)&&e.allDay===t.allDay&&function(e,t){for(let n in t)if("range"!==n&&"allDay"!==n&&e[n]!==t[n])return!1;for(let n in e)if(!(n in t))return!1;return!0}(e,t)}function Di(e,t,n){return Object.assign(Object.assign({},Ai(e,t,n)),{timeZone:t.timeZone})}function Ai(e,t,n){return{start:t.toDate(e.start),end:t.toDate(e.end),startStr:t.formatIso(e.start,{omitTime:n}),endStr:t.formatIso(e.end,{omitTime:n})}}function wi(e,t,n){let r=!1,i=function(e){r||(r=!0,t(e))},s=function(e){r||(r=!0,n(e))},o=e(i,s);o&&"function"==typeof o.then&&o.then(i,s)}class Ci extends Error{constructor(e,t){super(e),this.response=t}}function Ri(e,t,n){const r={method:e=e.toUpperCase()};return"GET"===e?t+=(-1===t.indexOf("?")?"?":"&")+new URLSearchParams(n):(r.body=new URLSearchParams(n),r.headers={"Content-Type":"application/x-www-form-urlencoded"}),fetch(t,r).then(e=>{if(e.ok)return e.json().then(t=>[t,e],()=>{throw new Ci("Failure parsing JSON",e)});throw new Ci("Request failed",e)})}let xi;function _i(){return null==xi&&(xi=function(){if("undefined"==typeof document)return!0;let e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.innerHTML="<table><tr><td><div></div></td></tr></table>",e.querySelector("table").style.height="100px",e.querySelector("div").style.height="100%",document.body.appendChild(e);let t=e.querySelector("div").offsetHeight>0;return document.body.removeChild(e),t}()),xi}class Ti extends Gn{constructor(){super(...arguments),this.state={forPrint:!1},this.handleBeforePrint=()=>{jn(()=>{this.setState({forPrint:!0})})},this.handleAfterPrint=()=>{jn(()=>{this.setState({forPrint:!1})})}}render(){let{props:e}=this,{options:t}=e,{forPrint:n}=this.state,r=n||"auto"===t.height||"auto"===t.contentHeight,i=r||null==t.height?"":t.height,s=["fc",n?"fc-media-print":"fc-media-screen","fc-direction-"+t.direction,e.theme.getClass("root")];return _i()||s.push("fc-liquid-hack"),e.children(s,i,r,n)}componentDidMount(){let{emitter:e}=this.props;e.on("_beforeprint",this.handleBeforePrint),e.on("_afterprint",this.handleAfterPrint)}componentWillUnmount(){let{emitter:e}=this.props;e.off("_beforeprint",this.handleBeforePrint),e.off("_afterprint",this.handleAfterPrint)}}class ki{constructor(e){this.component=e.component,this.isHitComboAllowed=e.isHitComboAllowed||null}destroy(){}}function Mi(e){return{[e.component.uid]:e}}const Ii={};class Oi extends A{constructor(e,t){super(e,t),this.handleRefresh=()=>{let e=this.computeTiming();e.state.nowDate.valueOf()!==this.state.nowDate.valueOf()&&this.setState(e.state),this.clearTimeout(),this.setTimeout(e.waitMs)},this.handleVisibilityChange=()=>{document.hidden||this.handleRefresh()},this.state=this.computeTiming().state}render(){let{props:e,state:t}=this;return e.children(t.nowDate,t.todayRange)}componentDidMount(){this.setTimeout(),this.context.nowManager.addResetListener(this.handleRefresh),document.addEventListener("visibilitychange",this.handleVisibilityChange)}componentDidUpdate(e){e.unit!==this.props.unit&&(this.clearTimeout(),this.setTimeout())}componentWillUnmount(){this.clearTimeout(),this.context.nowManager.removeResetListener(this.handleRefresh),document.removeEventListener("visibilitychange",this.handleVisibilityChange)}computeTiming(){let{props:e,context:t}=this,n=t.nowManager.getDateMarker(),r=t.dateEnv.startOf(n,e.unit),i=t.dateEnv.add(r,ft(1,e.unit)).valueOf()-n.valueOf();return i=Math.min(864e5,i),{state:{nowDate:r,todayRange:Ni(r)},waitMs:i}}setTimeout(e=this.computeTiming().waitMs){this.timeoutId=setTimeout(()=>{const e=this.computeTiming();this.setState(e.state,()=>{this.setTimeout(e.waitMs)})},e)}clearTimeout(){this.timeoutId&&clearTimeout(this.timeoutId)}}function Ni(e){let t=Mt(e);return{start:t,end:wt(t,1)}}Oi.contextType=Wn;class Pi{getCurrentData(){return this.currentDataManager.getCurrentData()}dispatch(e){this.currentDataManager.dispatch(e)}get view(){return this.getCurrentData().viewApi}batchRendering(e){e()}updateSize(){this.trigger("_resize",!0)}setOption(e,t){this.dispatch({type:"SET_OPTION",optionName:e,rawOptionValue:t})}getOption(e){return this.currentDataManager.currentCalendarOptionsInput[e]}getAvailableLocaleCodes(){return Object.keys(this.getCurrentData().availableRawLocales)}on(e,t){let{currentDataManager:n}=this;n.currentCalendarOptionsRefiners[e]?n.emitter.on(e,t):console.warn(`Unknown listener name '${e}'`)}off(e,t){this.currentDataManager.emitter.off(e,t)}trigger(e,...t){this.currentDataManager.emitter.trigger(e,...t)}changeView(e,t){this.batchRendering(()=>{if(this.unselect(),t)if(t.start&&t.end)this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e}),this.dispatch({type:"SET_OPTION",optionName:"visibleRange",rawOptionValue:t});else{let{dateEnv:n}=this.getCurrentData();this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e,dateMarker:n.createMarker(t)})}else this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e})})}zoomTo(e,t){let n;t=t||"day",n=this.getCurrentData().viewSpecs[t]||this.getUnitViewSpec(t),this.unselect(),n?this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:n.type,dateMarker:e}):this.dispatch({type:"CHANGE_DATE",dateMarker:e})}getUnitViewSpec(e){let t,n,{viewSpecs:r,toolbarConfig:i}=this.getCurrentData(),s=[].concat(i.header?i.header.viewsWithButtons:[],i.footer?i.footer.viewsWithButtons:[]);for(let e in r)s.push(e);for(t=0;t<s.length;t+=1)if(n=r[s[t]],n&&n.singleUnit===e)return n;return null}prev(){this.unselect(),this.dispatch({type:"PREV"})}next(){this.unselect(),this.dispatch({type:"NEXT"})}prevYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,-1)})}nextYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,1)})}today(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.nowManager.getDateMarker()})}gotoDate(e){let t=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.createMarker(e)})}incrementDate(e){let t=this.getCurrentData(),n=ft(e);n&&(this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.add(t.currentDate,n)}))}getDate(){let e=this.getCurrentData();return e.dateEnv.toDate(e.currentDate)}formatDate(e,t){let{dateEnv:n}=this.getCurrentData();return n.format(n.createMarker(e),an(t))}formatRange(e,t,n){let{dateEnv:r}=this.getCurrentData();return r.formatRange(r.createMarker(e),r.createMarker(t),an(n),n)}formatIso(e,t){let{dateEnv:n}=this.getCurrentData();return n.formatIso(n.createMarker(e),{omitTime:t})}select(e,t){let n;n=null==t?null!=e.start?e:{start:e,end:null}:{start:e,end:t};let r=this.getCurrentData(),i=Ei(n,r.dateEnv,ft({days:1}));i&&(this.dispatch({type:"SELECT_DATES",selection:i}),qr(i,null,r))}unselect(e){let t=this.getCurrentData();t.dateSelection&&(this.dispatch({type:"UNSELECT_DATES"}),function(e,t){t.emitter.trigger("unselect",{jsEvent:e?e.origEvent:null,view:t.viewApi||t.calendarApi.view})}(e,t))}addEvent(e,t){if(e instanceof ei){let t=e._def,n=e._instance;return this.getCurrentData().eventStore.defs[t.defId]||(this.dispatch({type:"ADD_EVENTS",eventStore:Cr({def:t,instance:n})}),this.triggerEventAdd(e)),e}let n,r=this.getCurrentData();if(t instanceof Kr)n=t.internalEventSource;else if("boolean"==typeof t)t&&([n]=wn(r.eventSources));else if(null!=t){let e=this.getEventSourceById(t);if(!e)return console.warn(`Could not find an event source with ID "${t}"`),null;n=e.internalEventSource}let i=Er(e,n,r,!1);if(i){let e=new ei(r,i.def,i.def.recurringDef?null:i.instance);return this.dispatch({type:"ADD_EVENTS",eventStore:Cr(i)}),this.triggerEventAdd(e),e}return null}triggerEventAdd(e){let{emitter:t}=this.getCurrentData();t.trigger("eventAdd",{event:e,relatedEvents:[],revert:()=>{this.dispatch({type:"REMOVE_EVENTS",eventStore:ti(e)})}})}getEventById(e){let t=this.getCurrentData(),{defs:n,instances:r}=t.eventStore;e=String(e);for(let i in n){let s=n[i];if(s.publicId===e){if(s.recurringDef)return new ei(t,s,null);for(let e in r){let n=r[e];if(n.defId===s.defId)return new ei(t,s,n)}}}return null}getEvents(){let e=this.getCurrentData();return ni(e.eventStore,e)}removeAllEvents(){this.dispatch({type:"REMOVE_ALL_EVENTS"})}getEventSources(){let e=this.getCurrentData(),t=e.eventSources,n=[];for(let r in t)n.push(new Kr(e,t[r]));return n}getEventSourceById(e){let t=this.getCurrentData(),n=t.eventSources;e=String(e);for(let r in n)if(n[r].publicId===e)return new Kr(t,n[r]);return null}addEventSource(e){let t=this.getCurrentData();if(e instanceof Kr)return t.eventSources[e.internalEventSource.sourceId]||this.dispatch({type:"ADD_EVENT_SOURCES",sources:[e.internalEventSource]}),e;let n=Br(e,t);return n?(this.dispatch({type:"ADD_EVENT_SOURCES",sources:[n]}),new Kr(t,n)):null}removeAllEventSources(){this.dispatch({type:"REMOVE_ALL_EVENT_SOURCES"})}refetchEvents(){this.dispatch({type:"FETCH_EVENT_SOURCES",isRefetch:!0})}scrollToTime(e){let t=ft(e);t&&this.trigger("_scrollRequest",{time:t})}}function Hi(e,t){return e.left>=t.left&&e.left<t.right&&e.top>=t.top&&e.top<t.bottom}function Bi(e,t){let n={left:Math.max(e.left,t.left),right:Math.min(e.right,t.right),top:Math.max(e.top,t.top),bottom:Math.min(e.bottom,t.bottom)};return n.left<n.right&&n.top<n.bottom&&n}function ji(e,t){return{left:Math.min(Math.max(e.left,t.left),t.right),top:Math.min(Math.max(e.top,t.top),t.bottom)}}function zi(e){return{left:(e.left+e.right)/2,top:(e.top+e.bottom)/2}}function Ui(e,t){return{left:e.left-t.left,top:e.top-t.top}}const Li={defs:{},instances:{}};class Wi{constructor(){this.getKeysForEventDefs=Gt(this._getKeysForEventDefs),this.splitDateSelection=Gt(this._splitDateSpan),this.splitEventStore=Gt(this._splitEventStore),this.splitIndividualUi=Gt(this._splitIndividualUi),this.splitEventDrag=Gt(this._splitInteraction),this.splitEventResize=Gt(this._splitInteraction),this.eventUiBuilders={}}splitProps(e){let t=this.getKeyInfo(e),n=this.getKeysForEventDefs(e.eventStore),r=this.splitDateSelection(e.dateSelection),i=this.splitIndividualUi(e.eventUiBases,n),s=this.splitEventStore(e.eventStore,n),o=this.splitEventDrag(e.eventDrag),a=this.splitEventResize(e.eventResize),l={};this.eventUiBuilders=Dn(t,(e,t)=>this.eventUiBuilders[t]||Gt(Fi));for(let n in t){let c=t[n],d=s[n]||Li,u=this.eventUiBuilders[n];l[n]={businessHours:c.businessHours||e.businessHours,dateSelection:r[n]||null,eventStore:d,eventUiBases:u(e.eventUiBases[""],c.ui,i[n]),eventSelection:d.instances[e.eventSelection]?e.eventSelection:"",eventDrag:o[n]||null,eventResize:a[n]||null}}return l}_splitDateSpan(e){let t={};if(e){let n=this.getKeysForDateSpan(e);for(let r of n)t[r]=e}return t}_getKeysForEventDefs(e){return Dn(e.defs,e=>this.getKeysForEventDef(e))}_splitEventStore(e,t){let{defs:n,instances:r}=e,i={};for(let e in n)for(let r of t[e])i[r]||(i[r]={defs:{},instances:{}}),i[r].defs[e]=n[e];for(let e in r){let n=r[e];for(let r of t[n.defId])i[r]&&(i[r].instances[e]=n)}return i}_splitIndividualUi(e,t){let n={};for(let r in e)if(r)for(let i of t[r])n[i]||(n[i]={}),n[i][r]=e[r];return n}_splitInteraction(e){let t={};if(e){let n=this._splitEventStore(e.affectedEvents,this._getKeysForEventDefs(e.affectedEvents)),r=this._getKeysForEventDefs(e.mutatedEvents),i=this._splitEventStore(e.mutatedEvents,r),s=r=>{t[r]||(t[r]={affectedEvents:n[r]||Li,mutatedEvents:i[r]||Li,isEvent:e.isEvent})};for(let e in n)s(e);for(let e in i)s(e)}return t}}function Fi(e,t,n){let r=[];e&&r.push(e),t&&r.push(t);let i={"":Nr(r)};return n&&Object.assign(i,n),i}function Vi(e,t,n,r){return{dow:e.getUTCDay(),isDisabled:Boolean(r&&(!r.activeRange||!lr(r.activeRange,e))),isOther:Boolean(r&&!lr(r.currentRange,e)),isToday:Boolean(t&&lr(t,e)),isPast:Boolean(n?e<n:!!t&&e<t.start),isFuture:Boolean(n?e>n:!!t&&e>=t.end)}}function Gi(e,t){let n=["fc-day","fc-day-"+Dt[e.dow]];return e.isDisabled?n.push("fc-day-disabled"):(e.isToday&&(n.push("fc-day-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-day-past"),e.isFuture&&n.push("fc-day-future"),e.isOther&&n.push("fc-day-other")),n}const Qi=an({year:"numeric",month:"long",day:"numeric"}),qi=an({week:"long"});function Yi(e,t,n="day",r=!0){const{dateEnv:i,options:s,calendarApi:o}=e;let a=i.format(t,"week"===n?qi:Qi);if(s.navLinks){let e=i.toDate(t);const l=e=>{let r="day"===n?s.navLinkDayClick:"week"===n?s.navLinkWeekClick:null;"function"==typeof r?r.call(o,i.toDate(t),e):("string"==typeof r&&(n=r),o.zoomTo(t,n))};return Object.assign({title:at(s.navLinkHint,[a,e],a),"data-navlink":""},r?Qe(l):{onClick:l})}return{"aria-label":a}}let Zi,Xi=null;function $i(){return null===Xi&&(Xi=function(){let e=document.createElement("div");Be(e,{position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}),e.innerHTML="<div></div>",document.body.appendChild(e);let t=e.firstChild.getBoundingClientRect().left>e.getBoundingClientRect().left;return Ie(e),t}()),Xi}function Ji(){return Zi||(Zi=function(){let e=document.createElement("div");e.style.overflow="scroll",e.style.position="absolute",e.style.top="-9999px",e.style.left="-9999px",document.body.appendChild(e);let t=Ki(e);return document.body.removeChild(e),t}()),Zi}function Ki(e){return{x:e.offsetHeight-e.clientHeight,y:e.offsetWidth-e.clientWidth}}function es(e,t=!1){let n=window.getComputedStyle(e),r=parseInt(n.borderLeftWidth,10)||0,i=parseInt(n.borderRightWidth,10)||0,s=parseInt(n.borderTopWidth,10)||0,o=parseInt(n.borderBottomWidth,10)||0,a=Ki(e),l=a.y-r-i,c={borderLeft:r,borderRight:i,borderTop:s,borderBottom:o,scrollbarBottom:a.x-s-o,scrollbarLeft:0,scrollbarRight:0};return $i()&&"rtl"===n.direction?c.scrollbarLeft=l:c.scrollbarRight=l,t&&(c.paddingLeft=parseInt(n.paddingLeft,10)||0,c.paddingRight=parseInt(n.paddingRight,10)||0,c.paddingTop=parseInt(n.paddingTop,10)||0,c.paddingBottom=parseInt(n.paddingBottom,10)||0),c}function ts(e,t=!1,n){let r=n?e.getBoundingClientRect():ns(e),i=es(e,t),s={left:r.left+i.borderLeft+i.scrollbarLeft,right:r.right-i.borderRight-i.scrollbarRight,top:r.top+i.borderTop,bottom:r.bottom-i.borderBottom-i.scrollbarBottom};return t&&(s.left+=i.paddingLeft,s.right-=i.paddingRight,s.top+=i.paddingTop,s.bottom-=i.paddingBottom),s}function ns(e){let t=e.getBoundingClientRect();return{left:t.left+window.scrollX,top:t.top+window.scrollY,right:t.right+window.scrollX,bottom:t.bottom+window.scrollY}}function rs(e){let t=[];for(;e instanceof HTMLElement;){let n=window.getComputedStyle(e);if("fixed"===n.position)break;/(auto|scroll)/.test(n.overflow+n.overflowY+n.overflowX)&&t.push(e),e=e.parentNode}return t}class is{constructor(e,t,n,r){this.els=t;let i=this.originClientRect=e.getBoundingClientRect();n&&this.buildElHorizontals(i.left),r&&this.buildElVerticals(i.top)}buildElHorizontals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.left-e),n.push(i.right-e)}this.lefts=t,this.rights=n}buildElVerticals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.top-e),n.push(i.bottom-e)}this.tops=t,this.bottoms=n}leftToIndex(e){let t,{lefts:n,rights:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}topToIndex(e){let t,{tops:n,bottoms:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}getWidth(e){return this.rights[e]-this.lefts[e]}getHeight(e){return this.bottoms[e]-this.tops[e]}similarTo(e){return ss(this.tops||[],e.tops||[])&&ss(this.bottoms||[],e.bottoms||[])&&ss(this.lefts||[],e.lefts||[])&&ss(this.rights||[],e.rights||[])}}function ss(e,t){const n=e.length;if(n!==t.length)return!1;for(let r=0;r<n;r++)if(Math.round(e[r])!==Math.round(t[r]))return!1;return!0}class os{getMaxScrollTop(){return this.getScrollHeight()-this.getClientHeight()}getMaxScrollLeft(){return this.getScrollWidth()-this.getClientWidth()}canScrollVertically(){return this.getMaxScrollTop()>0}canScrollHorizontally(){return this.getMaxScrollLeft()>0}canScrollUp(){return this.getScrollTop()>0}canScrollDown(){return this.getScrollTop()<this.getMaxScrollTop()}canScrollLeft(){return this.getScrollLeft()>0}canScrollRight(){return this.getScrollLeft()<this.getMaxScrollLeft()}}class as extends os{constructor(e){super(),this.el=e}getScrollTop(){return this.el.scrollTop}getScrollLeft(){return this.el.scrollLeft}setScrollTop(e){this.el.scrollTop=e}setScrollLeft(e){this.el.scrollLeft=e}getScrollWidth(){return this.el.scrollWidth}getScrollHeight(){return this.el.scrollHeight}getClientHeight(){return this.el.clientHeight}getClientWidth(){return this.el.clientWidth}}class ls extends os{getScrollTop(){return window.scrollY}getScrollLeft(){return window.scrollX}setScrollTop(e){window.scroll(window.scrollX,e)}setScrollLeft(e){window.scroll(e,window.scrollY)}getScrollWidth(){return document.documentElement.scrollWidth}getScrollHeight(){return document.documentElement.scrollHeight}getClientHeight(){return document.documentElement.clientHeight}getClientWidth(){return document.documentElement.clientWidth}}class cs extends Gn{constructor(){super(...arguments),this.uid=Ze()}prepareHits(){}queryHit(e,t,n,r){return null}isValidSegDownEl(e){return!this.props.eventDrag&&!this.props.eventResize&&!Oe(e,".fc-event-mirror")}isValidDateDownEl(e){return!(Oe(e,".fc-event:not(.fc-bg-event)")||Oe(e,".fc-more-link")||Oe(e,"a[data-navlink]")||Oe(e,".fc-popover"))}}class ds{constructor(e=(e=>e.thickness||1)){this.getEntryThickness=e,this.strictOrder=!1,this.allowReslicing=!1,this.maxCoord=-1,this.maxStackCnt=-1,this.levelCoords=[],this.entriesByLevel=[],this.stackCnts={}}addSegs(e){let t=[];for(let n of e)this.insertEntry(n,t);return t}insertEntry(e,t){let n=this.findInsertion(e);this.isInsertionValid(n,e)?this.insertEntryAt(e,n):this.handleInvalidInsertion(n,e,t)}isInsertionValid(e,t){return(-1===this.maxCoord||e.levelCoord+this.getEntryThickness(t)<=this.maxCoord)&&(-1===this.maxStackCnt||e.stackCnt<this.maxStackCnt)}handleInvalidInsertion(e,t,n){if(this.allowReslicing&&e.touchingEntry){const r=Object.assign(Object.assign({},t),{span:gs(t.span,e.touchingEntry.span)});n.push(r),this.splitEntry(t,e.touchingEntry,n)}else n.push(t)}splitEntry(e,t,n){let r=e.span,i=t.span;r.start<i.start&&this.insertEntry({index:e.index,thickness:e.thickness,span:{start:r.start,end:i.start}},n),r.end>i.end&&this.insertEntry({index:e.index,thickness:e.thickness,span:{start:i.end,end:r.end}},n)}insertEntryAt(e,t){let{entriesByLevel:n,levelCoords:r}=this;-1===t.lateral?(ps(r,t.level,t.levelCoord),ps(n,t.level,[e])):ps(n[t.level],t.lateral,e),this.stackCnts[hs(e)]=t.stackCnt}findInsertion(e){let{levelCoords:t,entriesByLevel:n,strictOrder:r,stackCnts:i}=this,s=t.length,o=0,a=-1,l=-1,c=null,d=0;for(let u=0;u<s;u+=1){const s=t[u];if(!r&&s>=o+this.getEntryThickness(e))break;let h,f=n[u],g=ms(f,e.span.start,us),p=g[0]+g[1];for(;(h=f[p])&&h.span.start<e.span.end;){let e=s+this.getEntryThickness(h);e>o&&(o=e,c=h,a=u,l=p),e===o&&(d=Math.max(d,i[hs(h)]+1)),p+=1}}let u=0;if(c)for(u=a+1;u<s&&t[u]<o;)u+=1;let h=-1;return u<s&&t[u]===o&&(h=ms(n[u],e.span.end,us)[0]),{touchingLevel:a,touchingLateral:l,touchingEntry:c,stackCnt:d,levelCoord:o,level:u,lateral:h}}toRects(){let{entriesByLevel:e,levelCoords:t}=this,n=e.length,r=[];for(let i=0;i<n;i+=1){let n=e[i],s=t[i];for(let e of n)r.push(Object.assign(Object.assign({},e),{thickness:this.getEntryThickness(e),levelCoord:s}))}return r}}function us(e){return e.span.end}function hs(e){return e.index+":"+e.span.start}function fs(e){let t=[];for(let i of e){let e=[],s={span:i.span,entries:[i]};for(let i of t)gs(i.span,s.span)?s={entries:i.entries.concat(s.entries),span:(n=i.span,r=s.span,{start:Math.min(n.start,r.start),end:Math.max(n.end,r.end)})}:e.push(i);e.push(s),t=e}var n,r;return t}function gs(e,t){let n=Math.max(e.start,t.start),r=Math.min(e.end,t.end);return n<r?{start:n,end:r}:null}function ps(e,t,n){e.splice(t,0,n)}function ms(e,t,n){let r=0,i=e.length;if(!i||t<n(e[r]))return[0,0];if(t>n(e[i-1]))return[i,0];for(;r<i;){let s=Math.floor(r+(i-r)/2),o=n(e[s]);if(t<o)i=s;else{if(!(t>o))return[s,1];r=s+1}}return[r,0]}class vs{constructor(e,t){this.emitter=new Vr}destroy(){}setMirrorIsVisible(e){}setMirrorNeedsRevert(e){}setAutoScrollEnabled(e){}}const ys={},bs={startTime:ft,duration:ft,create:Boolean,sourceId:String};function Es(e){let{refined:t,extra:n}=vn(e,bs);return{startTime:t.startTime||null,duration:t.duration||null,create:null==t.create||t.create,sourceId:t.sourceId,leftoverProps:n}}function Ss(e,t){return an(!e||t>10?{weekday:"short"}:t>1?{weekday:"short",month:"numeric",day:"numeric",omitCommas:!0}:{weekday:"long"})}const Ds="fc-col-header-cell";function As(e){return e.text}class ws extends Gn{render(){let{dateEnv:e,options:t,theme:n,viewApi:r}=this.context,{props:i}=this,{date:s,dateProfile:o}=i,a=Vi(s,i.todayRange,null,o),l=[Ds].concat(Gi(a,n)),c=e.format(s,i.dayHeaderFormat),d=!a.isDisabled&&i.colCnt>1?Yi(this.context,s):{},u=e.toDate(s);e.namedTimeZoneImpl&&(u=Ct(u,36e5));let h=Object.assign(Object.assign(Object.assign({date:u,view:r},i.extraRenderProps),{text:c}),a);return p(Jn,{elTag:"th",elClasses:l,elAttrs:Object.assign({role:"columnheader",colSpan:i.colSpan,"data-date":a.isDisabled?void 0:Lt(s)},i.extraDataAttrs),renderProps:h,generatorName:"dayHeaderContent",customGenerator:t.dayHeaderContent,defaultGenerator:As,classNameGenerator:t.dayHeaderClassNames,didMount:t.dayHeaderDidMount,willUnmount:t.dayHeaderWillUnmount},e=>p("div",{className:"fc-scrollgrid-sync-inner"},!a.isDisabled&&p(e,{elTag:"a",elAttrs:d,elClasses:["fc-col-header-cell-cushion",i.isSticky&&"fc-sticky"]})))}}const Cs=an({weekday:"long"});class Rs extends Gn{render(){let{props:e}=this,{dateEnv:t,theme:n,viewApi:r,options:i}=this.context,s=wt(new Date(2592e5),e.dow),o={dow:e.dow,isDisabled:!1,isFuture:!1,isPast:!1,isToday:!1,isOther:!1},a=t.format(s,e.dayHeaderFormat),l=Object.assign(Object.assign(Object.assign(Object.assign({date:s},o),{view:r}),e.extraRenderProps),{text:a});return p(Jn,{elTag:"th",elClasses:[Ds,...Gi(o,n),...e.extraClassNames||[]],elAttrs:Object.assign({role:"columnheader",colSpan:e.colSpan},e.extraDataAttrs),renderProps:l,generatorName:"dayHeaderContent",customGenerator:i.dayHeaderContent,defaultGenerator:As,classNameGenerator:i.dayHeaderClassNames,didMount:i.dayHeaderDidMount,willUnmount:i.dayHeaderWillUnmount},n=>p("div",{className:"fc-scrollgrid-sync-inner"},p(n,{elTag:"a",elClasses:["fc-col-header-cell-cushion",e.isSticky&&"fc-sticky"],elAttrs:{"aria-label":t.format(s,Cs)}})))}}class xs extends Gn{constructor(){super(...arguments),this.createDayHeaderFormatter=Gt(_s)}render(){let{context:e}=this,{dates:t,dateProfile:n,datesRepDistinctDays:r,renderIntro:i}=this.props,s=this.createDayHeaderFormatter(e.options.dayHeaderFormat,r,t.length);return p(Oi,{unit:"day"},(e,o)=>p("tr",{role:"row"},i&&i("day"),t.map(e=>r?p(ws,{key:e.toISOString(),date:e,dateProfile:n,todayRange:o,colCnt:t.length,dayHeaderFormat:s}):p(Rs,{key:e.getUTCDay(),dow:e.getUTCDay(),dayHeaderFormat:s}))))}}function _s(e,t,n){return e||Ss(t,n)}class Ts{constructor(e,t){let n=e.start,{end:r}=e,i=[],s=[],o=-1;for(;n<r;)t.isHiddenDay(n)?i.push(o+.5):(o+=1,i.push(o),s.push(n)),n=wt(n,1);this.dates=s,this.indices=i,this.cnt=s.length}sliceRange(e){let t=this.getDateDayIndex(e.start),n=this.getDateDayIndex(wt(e.end,-1)),r=Math.max(0,t),i=Math.min(this.cnt-1,n);return r=Math.ceil(r),i=Math.floor(i),r<=i?{firstIndex:r,lastIndex:i,isStart:t===r,isEnd:n===i}:null}getDateDayIndex(e){let{indices:t}=this,n=Math.floor(xt(this.dates[0],e));return n<0?t[0]-1:n>=t.length?t[t.length-1]+1:t[n]}}class ks{constructor(e,t){let n,r,i,{dates:s}=e;if(t){for(r=s[0].getUTCDay(),n=1;n<s.length&&s[n].getUTCDay()!==r;n+=1);i=Math.ceil(s.length/n)}else i=1,n=s.length;this.rowCnt=i,this.colCnt=n,this.daySeries=e,this.cells=this.buildCells(),this.headerDates=this.buildHeaderDates()}buildCells(){let e=[];for(let t=0;t<this.rowCnt;t+=1){let n=[];for(let e=0;e<this.colCnt;e+=1)n.push(this.buildCell(t,e));e.push(n)}return e}buildCell(e,t){let n=this.daySeries.dates[e*this.colCnt+t];return{key:n.toISOString(),date:n}}buildHeaderDates(){let e=[];for(let t=0;t<this.colCnt;t+=1)e.push(this.cells[0][t].date);return e}sliceRange(e){let{colCnt:t}=this,n=this.daySeries.sliceRange(e),r=[];if(n){let{firstIndex:e,lastIndex:i}=n,s=e;for(;s<=i;){let o=Math.floor(s/t),a=Math.min((o+1)*t,i+1);r.push({row:o,firstCol:s%t,lastCol:(a-1)%t,isStart:n.isStart&&s===e,isEnd:n.isEnd&&a-1===i}),s=a}}return r}}class Ms{constructor(){this.sliceBusinessHours=Gt(this._sliceBusinessHours),this.sliceDateSelection=Gt(this._sliceDateSpan),this.sliceEventStore=Gt(this._sliceEventStore),this.sliceEventDrag=Gt(this._sliceInteraction),this.sliceEventResize=Gt(this._sliceInteraction),this.forceDayIfListItem=!1}sliceProps(e,t,n,r,...i){let{eventUiBases:s}=e,o=this.sliceEventStore(e.eventStore,s,t,n,...i);return{dateSelectionSegs:this.sliceDateSelection(e.dateSelection,t,n,s,r,...i),businessHourSegs:this.sliceBusinessHours(e.businessHours,t,n,r,...i),fgEventSegs:o.fg,bgEventSegs:o.bg,eventDrag:this.sliceEventDrag(e.eventDrag,s,t,n,...i),eventResize:this.sliceEventResize(e.eventResize,s,t,n,...i),eventSelection:e.eventSelection}}sliceNowDate(e,t,n,r,...i){return this._sliceDateSpan({range:{start:e,end:Ct(e,1)},allDay:!1},t,n,{},r,...i)}_sliceBusinessHours(e,t,n,r,...i){return e?this._sliceEventStore(pr(e,Is(t,Boolean(n)),r),{},t,n,...i).bg:[]}_sliceEventStore(e,t,n,r,...i){if(e){let s=ri(e,t,Is(n,Boolean(r)),r);return{bg:this.sliceEventRanges(s.bg,i),fg:this.sliceEventRanges(s.fg,i)}}return{bg:[],fg:[]}}_sliceInteraction(e,t,n,r,...i){if(!e)return null;let s=ri(e.mutatedEvents,t,Is(n,Boolean(r)),r);return{segs:this.sliceEventRanges(s.fg,i),affectedInstances:e.affectedEvents.instances,isEvent:e.isEvent}}_sliceDateSpan(e,t,n,r,i,...s){if(!e)return[];let o=Is(t,Boolean(n)),a=ir(e.range,o);if(a){let t=function(e,t,n){let r=Sr({editable:!1},n),i=Ar(r.refined,r.extra,"",e.allDay,!0,n);return{def:i,ui:li(i,t),instance:gr(i.defId,e.range),range:e.range,isStart:!0,isEnd:!0}}(e=Object.assign(Object.assign({},e),{range:a}),r,i),n=this.sliceRange(e.range,...s);for(let e of n)e.eventRange=t;return n}return[]}sliceEventRanges(e,t){let n=[];for(let r of e)n.push(...this.sliceEventRange(r,t));return n}sliceEventRange(e,t){let n=e.range;this.forceDayIfListItem&&"list-item"===e.ui.display&&(n={start:n.start,end:wt(n.start,1)});let r=this.sliceRange(n,...t);for(let t of r)t.eventRange=e,t.isStart=e.isStart&&t.isStart,t.isEnd=e.isEnd&&t.isEnd;return r}}function Is(e,t){let n=e.activeRange;return t?n:{start:Ct(n.start,e.slotMinTime.milliseconds),end:Ct(n.end,e.slotMaxTime.milliseconds-864e5)}}function Os(e,t,n){let{instances:r}=e.mutatedEvents;for(let e in r)if(!ar(t.validRange,r[e].range))return!1;return Ps({eventDrag:e},n)}function Ns(e,t,n){return!!ar(t.validRange,e.range)&&Ps({dateSelection:e},n)}function Ps(e,t){let n=t.getCurrentData(),r=Object.assign({businessHours:n.businessHours,dateSelection:"",eventStore:n.eventStore,eventUiBases:n.eventUiBases,eventSelection:"",eventDrag:null,eventResize:null},e);return(t.pluginHooks.isPropsValid||Hs)(r,t)}function Hs(e,t,n={},r){return!(e.eventDrag&&!function(e,t,n,r){let i=t.getCurrentData(),s=e.eventDrag,o=s.mutatedEvents,a=o.defs,l=o.instances,c=ai(a,s.isEvent?e.eventUiBases:{"":i.selectionConfig});r&&(c=Dn(c,r));let d=(g=e.eventStore,p=s.affectedEvents.instances,{defs:g.defs,instances:Sn(g.instances,e=>!p[e.instanceId])}),u=d.defs,h=d.instances,f=ai(u,e.eventUiBases);var g,p;for(let r in l){let o=l[r],g=o.range,p=c[o.defId],m=a[o.defId];if(!Bs(p.constraints,g,d,e.businessHours,t))return!1;let{eventOverlap:v}=t.options,y="function"==typeof v?v:null;for(let e in h){let n=h[e];if(or(g,n.range)){if(!1===f[n.defId].overlap&&s.isEvent)return!1;if(!1===p.overlap)return!1;if(y&&!y(new ei(t,u[n.defId],n),new ei(t,m,o)))return!1}}let b=i.eventStore;for(let e of p.allows){let i,s=Object.assign(Object.assign({},n),{range:o.range,allDay:m.allDay}),a=b.defs[m.defId],l=b.instances[r];if(i=a?new ei(t,a,l):new ei(t,m),!e(Yr(s,t),i))return!1}}return!0}(e,t,n,r))&&!(e.dateSelection&&!function(e,t,n,r){let i=e.eventStore,s=i.defs,o=i.instances,a=e.dateSelection,l=a.range,{selectionConfig:c}=t.getCurrentData();r&&(c=r(c));if(!Bs(c.constraints,l,i,e.businessHours,t))return!1;let{selectOverlap:d}=t.options,u="function"==typeof d?d:null;for(let e in o){let n=o[e];if(or(l,n.range)){if(!1===c.overlap)return!1;if(u&&!u(new ei(t,s[n.defId],n),null))return!1}}for(let e of c.allows){let r=Object.assign(Object.assign({},n),a);if(!e(Yr(r,t),null))return!1}return!0}(e,t,n,r))}function Bs(e,t,n,r,i){for(let s of e)if(!Us(js(s,t,n,r,i),t))return!1;return!0}function js(e,t,n,r,i){return"businessHours"===e?zs(pr(r,t,i)):"string"==typeof e?zs(Tr(n,t=>t.groupId===e)):"object"==typeof e&&e?zs(pr(e,t,i)):[]}function zs(e){let{instances:t}=e,n=[];for(let e in t)n.push(t[e].range);return n}function Us(e,t){for(let n of e)if(ar(n,t))return!0;return!1}const Ls=/^(visible|hidden)$/;class Ws extends Gn{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,Qn(this.props.elRef,e)}}render(){let{props:e}=this,{liquid:t,liquidIsAbsolute:n}=e,r=t&&n,i=["fc-scroller"];return t&&(n?i.push("fc-scroller-liquid-absolute"):i.push("fc-scroller-liquid")),p("div",{ref:this.handleEl,className:i.join(" "),style:{overflowX:e.overflowX,overflowY:e.overflowY,left:r&&-(e.overcomeLeft||0)||"",right:r&&-(e.overcomeRight||0)||"",bottom:r&&-(e.overcomeBottom||0)||"",marginLeft:!r&&-(e.overcomeLeft||0)||"",marginRight:!r&&-(e.overcomeRight||0)||"",marginBottom:!r&&-(e.overcomeBottom||0)||"",maxHeight:e.maxHeight||""}},e.children)}needsXScrolling(){if(Ls.test(this.props.overflowX))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().width-this.getYScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().width>t)return!0}return!1}needsYScrolling(){if(Ls.test(this.props.overflowY))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().height-this.getXScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().height>t)return!0}return!1}getXScrollbarWidth(){return Ls.test(this.props.overflowX)?0:this.el.offsetHeight-this.el.clientHeight}getYScrollbarWidth(){return Ls.test(this.props.overflowY)?0:this.el.offsetWidth-this.el.clientWidth}}class Fs{constructor(e){this.masterCallback=e,this.currentMap={},this.depths={},this.callbackMap={},this.handleValue=(e,t)=>{let{depths:n,currentMap:r}=this,i=!1,s=!1;null!==e?(i=t in r,r[t]=e,n[t]=(n[t]||0)+1,s=!0):(n[t]-=1,n[t]||(delete r[t],delete this.callbackMap[t],i=!0)),this.masterCallback&&(i&&this.masterCallback(null,String(t)),s&&this.masterCallback(e,String(t)))}}createRef(e){let t=this.callbackMap[e];return t||(t=this.callbackMap[e]=t=>{this.handleValue(t,String(e))}),t}collect(e,t,n){return kn(this.currentMap,e,t,n)}getAll(){return wn(this.currentMap)}}function Vs(e){let t=Pe(e,".fc-scrollgrid-shrink"),n=0;for(let e of t)n=Math.max(n,dt(e));return Math.ceil(n)}function Gs(e,t){return e.liquid&&t.liquid}function Qs(e,t){return null!=t.maxHeight||Gs(e,t)}function qs(e,t,n,r){let{expandRows:i}=n;return"function"==typeof t.content?t.content(n):p("table",{role:"presentation",className:[t.tableClassName,e.syncRowHeights?"fc-scrollgrid-sync-table":""].join(" "),style:{minWidth:n.tableMinWidth,width:n.clientWidth,height:i?n.clientHeight:""}},n.tableColGroupNode,p(r?"thead":"tbody",{role:"presentation"},"function"==typeof t.rowContent?t.rowContent(n):t.rowContent))}function Ys(e,t){return St(e,t,Cn)}function Zs(e,t){let n=[];for(let r of e){let e=r.span||1;for(let i=0;i<e;i+=1)n.push(p("col",{style:{width:"shrink"===r.width?Xs(t):r.width||"",minWidth:r.minWidth||""}}))}return p("colgroup",{},...n)}function Xs(e){return null==e?4:e}function $s(e){for(let t of e)if("shrink"===t.width)return!0;return!1}function Js(e,t){let n=["fc-scrollgrid",t.theme.getClass("table")];return e&&n.push("fc-scrollgrid-liquid"),n}function Ks(e,t){let n=["fc-scrollgrid-section","fc-scrollgrid-section-"+e.type,e.className];return t&&e.liquid&&null==e.maxHeight&&n.push("fc-scrollgrid-section-liquid"),e.isSticky&&n.push("fc-scrollgrid-section-sticky"),n}function eo(e){return p("div",{className:"fc-scrollgrid-sticky-shim",style:{width:e.clientWidth,minWidth:e.tableMinWidth}})}function to(e){let{stickyHeaderDates:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t}function no(e){let{stickyFooterScrollbar:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t}class ro extends Gn{constructor(){super(...arguments),this.processCols=Gt(e=>e,Ys),this.renderMicroColGroup=Gt(Zs),this.scrollerRefs=new Fs,this.scrollerElRefs=new Fs(this._handleScrollerEl.bind(this)),this.state={shrinkWidth:null,forceYScrollbars:!1,scrollerClientWidths:{},scrollerClientHeights:{}},this.handleSizing=()=>{this.safeSetState(Object.assign({shrinkWidth:this.computeShrinkWidth()},this.computeScrollerDims()))}}render(){let{props:e,state:t,context:n}=this,r=e.sections||[],i=this.processCols(e.cols),s=this.renderMicroColGroup(i,t.shrinkWidth),o=Js(e.liquid,n);e.collapsibleWidth&&o.push("fc-scrollgrid-collapsible");let a,l=r.length,c=0,d=[],u=[],h=[];for(;c<l&&"header"===(a=r[c]).type;)d.push(this.renderSection(a,s,!0)),c+=1;for(;c<l&&"body"===(a=r[c]).type;)u.push(this.renderSection(a,s,!1)),c+=1;for(;c<l&&"footer"===(a=r[c]).type;)h.push(this.renderSection(a,s,!0)),c+=1;let f=!_i();const g={role:"rowgroup"};return p("table",{role:"grid",className:o.join(" "),style:{height:e.height}},Boolean(!f&&d.length)&&p("thead",g,...d),Boolean(!f&&u.length)&&p("tbody",g,...u),Boolean(!f&&h.length)&&p("tfoot",g,...h),f&&p("tbody",g,...d,...u,...h))}renderSection(e,t,n){return"outerContent"in e?p(y,{key:e.key},e.outerContent):p("tr",{key:e.key,role:"presentation",className:Ks(e,this.props.liquid).join(" ")},this.renderChunkTd(e,t,e.chunk,n))}renderChunkTd(e,t,n,r){if("outerContent"in n)return n.outerContent;let{props:i}=this,{forceYScrollbars:s,scrollerClientWidths:o,scrollerClientHeights:a}=this.state,l=Qs(i,e),c=Gs(i,e),d=i.liquid?s?"scroll":l?"auto":"hidden":"visible",u=e.key,h=qs(e,n,{tableColGroupNode:t,tableMinWidth:"",clientWidth:i.collapsibleWidth||void 0===o[u]?null:o[u],clientHeight:void 0!==a[u]?a[u]:null,expandRows:e.expandRows,syncRowHeights:!1,rowSyncHeights:[],reportRowHeightChange:()=>{}},r);return p(r?"th":"td",{ref:n.elRef,role:"presentation"},p("div",{className:"fc-scroller-harness"+(c?" fc-scroller-harness-liquid":"")},p(Ws,{ref:this.scrollerRefs.createRef(u),elRef:this.scrollerElRefs.createRef(u),overflowY:d,overflowX:i.liquid?"hidden":"visible",maxHeight:e.maxHeight,liquid:c,liquidIsAbsolute:!0},h)))}_handleScrollerEl(e,t){let n=function(e,t){for(let n of e)if(n.key===t)return n;return null}(this.props.sections,t);n&&Qn(n.chunk.scrollerElRef,e)}componentDidMount(){this.handleSizing(),this.context.addResizeHandler(this.handleSizing)}componentDidUpdate(){this.handleSizing()}componentWillUnmount(){this.context.removeResizeHandler(this.handleSizing)}computeShrinkWidth(){return $s(this.props.cols)?Vs(this.scrollerElRefs.getAll()):0}computeScrollerDims(){let e=Ji(),{scrollerRefs:t,scrollerElRefs:n}=this,r=!1,i={},s={};for(let e in t.currentMap){let n=t.currentMap[e];if(n&&n.needsYScrolling()){r=!0;break}}for(let t of this.props.sections){let o=t.key,a=n.currentMap[o];if(a){let t=a.parentNode;i[o]=Math.floor(t.getBoundingClientRect().width-(r?e.y:0)),s[o]=Math.floor(t.getBoundingClientRect().height)}}return{forceYScrollbars:r,scrollerClientWidths:i,scrollerClientHeights:s}}}ro.addStateEquality({scrollerClientWidths:Cn,scrollerClientHeights:Cn});class io extends Gn{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,e&&si(e,this.props.seg)}}render(){const{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{eventRange:i}=r,{ui:s}=i,o={event:new ei(t,i.def,i.instance),view:t.viewApi,timeText:e.timeText,textColor:s.textColor,backgroundColor:s.backgroundColor,borderColor:s.borderColor,isDraggable:!e.disableDragging&&ui(r,t),isStartResizable:!e.disableResizing&&hi(r,t),isEndResizable:!e.disableResizing&&fi(r),isMirror:Boolean(e.isDragging||e.isResizing||e.isDateSelecting),isStart:Boolean(r.isStart),isEnd:Boolean(r.isEnd),isPast:Boolean(e.isPast),isFuture:Boolean(e.isFuture),isToday:Boolean(e.isToday),isSelected:Boolean(e.isSelected),isDragging:Boolean(e.isDragging),isResizing:Boolean(e.isResizing)};return p(Jn,Object.assign({},e,{elRef:this.handleEl,elClasses:[...mi(o),...r.eventRange.ui.classNames,...e.elClasses||[]],renderProps:o,generatorName:"eventContent",customGenerator:n.eventContent,defaultGenerator:e.defaultGenerator,classNameGenerator:n.eventClassNames,didMount:n.eventDidMount,willUnmount:n.eventWillUnmount}))}componentDidUpdate(e){this.el&&this.props.seg!==e.seg&&si(this.el,this.props.seg)}}class so extends Gn{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{ui:i}=r.eventRange,s=gi(r,n.eventTimeFormat||e.defaultTimeFormat,t,e.defaultDisplayEventTime,e.defaultDisplayEventEnd);return p(io,Object.assign({},e,{elTag:"a",elStyle:{borderColor:i.borderColor,backgroundColor:i.backgroundColor},elAttrs:yi(r,t),defaultGenerator:oo,timeText:s}),(e,t)=>p(y,null,p(e,{elTag:"div",elClasses:["fc-event-main"],elStyle:{color:t.textColor}}),Boolean(t.isStartResizable)&&p("div",{className:"fc-event-resizer fc-event-resizer-start"}),Boolean(t.isEndResizable)&&p("div",{className:"fc-event-resizer fc-event-resizer-end"})))}}function oo(e){return p("div",{className:"fc-event-main-frame"},e.timeText&&p("div",{className:"fc-event-time"},e.timeText),p("div",{className:"fc-event-title-container"},p("div",{className:"fc-event-title fc-sticky"},e.event.title||p(y,null," "))))}const ao=e=>p(Wn.Consumer,null,t=>{let{options:n}=t,r={isAxis:e.isAxis,date:t.dateEnv.toDate(e.date),view:t.viewApi};return p(Jn,Object.assign({},e,{elTag:e.elTag||"div",renderProps:r,generatorName:"nowIndicatorContent",customGenerator:n.nowIndicatorContent,classNameGenerator:n.nowIndicatorClassNames,didMount:n.nowIndicatorDidMount,willUnmount:n.nowIndicatorWillUnmount}))}),lo=an({day:"numeric"});class co extends Gn{constructor(){super(...arguments),this.refineRenderProps=Qt(ho)}render(){let{props:e,context:t}=this,{options:n}=t,r=this.refineRenderProps({date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,isMonthStart:e.isMonthStart||!1,showDayNumber:e.showDayNumber,extraRenderProps:e.extraRenderProps,viewApi:t.viewApi,dateEnv:t.dateEnv,monthStartFormat:n.monthStartFormat});return p(Jn,Object.assign({},e,{elClasses:[...Gi(r,t.theme),...e.elClasses||[]],elAttrs:Object.assign(Object.assign({},e.elAttrs),r.isDisabled?{}:{"data-date":Lt(e.date)}),renderProps:r,generatorName:"dayCellContent",customGenerator:n.dayCellContent,defaultGenerator:e.defaultGenerator,classNameGenerator:r.isDisabled?void 0:n.dayCellClassNames,didMount:n.dayCellDidMount,willUnmount:n.dayCellWillUnmount}))}}function uo(e){return Boolean(e.dayCellContent||Yn("dayCellContent",e))}function ho(e){let{date:t,dateEnv:n,dateProfile:r,isMonthStart:i}=e,s=Vi(t,e.todayRange,null,r),o=e.showDayNumber?n.format(t,i?e.monthStartFormat:lo):"";return Object.assign(Object.assign(Object.assign({date:n.toDate(t),view:e.viewApi},s),{isMonthStart:i,dayNumberText:o}),e.extraRenderProps)}class fo extends Gn{render(){let{props:e}=this,{seg:t}=e;return p(io,{elTag:"div",elClasses:["fc-bg-event"],elStyle:{backgroundColor:t.eventRange.ui.backgroundColor},defaultGenerator:go,seg:t,timeText:"",isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,isPast:e.isPast,isFuture:e.isFuture,isToday:e.isToday,disableDragging:!0,disableResizing:!0})}}function go(e){let{title:t}=e.event;return t&&p("div",{className:"fc-event-title"},e.event.title)}function po(e){return p("div",{className:"fc-"+e})}const mo=e=>p(Wn.Consumer,null,t=>{let{dateEnv:n,options:r}=t,{date:i}=e,s=r.weekNumberFormat||e.defaultFormat,o={num:n.computeWeekNumber(i),text:n.format(i,s),date:i};return p(Jn,Object.assign({},e,{renderProps:o,generatorName:"weekNumberContent",customGenerator:r.weekNumberContent,defaultGenerator:vo,classNameGenerator:r.weekNumberClassNames,didMount:r.weekNumberDidMount,willUnmount:r.weekNumberWillUnmount}))});function vo(e){return e.text}class yo extends Gn{constructor(){super(...arguments),this.state={titleId:Le()},this.handleRootEl=e=>{this.rootEl=e,this.props.elRef&&Qn(this.props.elRef,e)},this.handleDocumentMouseDown=e=>{const t=ze(e);this.rootEl.contains(t)||this.handleCloseClick()},this.handleDocumentKeyDown=e=>{"Escape"===e.key&&this.handleCloseClick()},this.handleCloseClick=()=>{let{onClose:e}=this.props;e&&e()}}render(){let{theme:e,options:t}=this.context,{props:n,state:r}=this,i=["fc-popover",e.getClass("popover")].concat(n.extraClassNames||[]);return fe(p("div",Object.assign({},n.extraAttrs,{id:n.id,className:i.join(" "),"aria-labelledby":r.titleId,ref:this.handleRootEl}),p("div",{className:"fc-popover-header "+e.getClass("popoverHeader")},p("span",{className:"fc-popover-title",id:r.titleId},n.title),p("span",{className:"fc-popover-close "+e.getIconClass("close"),title:t.closeHint,onClick:this.handleCloseClick})),p("div",{className:"fc-popover-body "+e.getClass("popoverContent")},n.children)),n.parentEl)}componentDidMount(){document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown),this.updateSize()}componentWillUnmount(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown)}updateSize(){let{isRtl:e}=this.context,{alignmentEl:t,alignGridTop:n}=this.props,{rootEl:r}=this,i=function(e){let t=rs(e),n=e.getBoundingClientRect();for(let e of t){let t=Bi(n,e.getBoundingClientRect());if(!t)return null;n=t}return n}(t);if(i){let s=r.getBoundingClientRect(),o=n?Oe(t,".fc-scrollgrid").getBoundingClientRect().top:i.top,a=e?i.right-s.width:i.left;o=Math.max(o,10),a=Math.min(a,document.documentElement.clientWidth-10-s.width),a=Math.max(a,10);let l=r.offsetParent.getBoundingClientRect();Be(r,{top:o-l.top,left:a-l.left})}}}class bo extends cs{constructor(){super(...arguments),this.handleRootEl=e=>{this.rootEl=e,e?this.context.registerInteractiveComponent(this,{el:e,useEventCenter:!1}):this.context.unregisterInteractiveComponent(this)}}render(){let{options:e,dateEnv:t}=this.context,{props:n}=this,{startDate:r,todayRange:i,dateProfile:s}=n,o=t.format(r,e.dayPopoverFormat);return p(co,{elRef:this.handleRootEl,date:r,dateProfile:s,todayRange:i},(t,r,i)=>p(yo,{elRef:i.ref,id:n.id,title:o,extraClassNames:["fc-more-popover"].concat(i.className||[]),extraAttrs:i,parentEl:n.parentEl,alignmentEl:n.alignmentEl,alignGridTop:n.alignGridTop,onClose:n.onClose},uo(e)&&p(t,{elTag:"div",elClasses:["fc-more-popover-misc"]}),n.children))}queryHit(e,t,n,r){let{rootEl:i,props:s}=this;return e>=0&&e<n&&t>=0&&t<r?{dateProfile:s.dateProfile,dateSpan:Object.assign({allDay:!s.forceTimed,range:{start:s.startDate,end:s.endDate}},s.extraDateSpan),dayEl:i,rect:{left:0,top:0,right:n,bottom:r},layer:1}:null}}class Eo extends Gn{constructor(){super(...arguments),this.state={isPopoverOpen:!1,popoverId:Le()},this.handleLinkEl=e=>{this.linkEl=e,this.props.elRef&&Qn(this.props.elRef,e)},this.handleClick=e=>{let{props:t,context:n}=this,{moreLinkClick:r}=n.options,i=Do(t).start;function s(e){let{def:t,instance:r,range:i}=e.eventRange;return{event:new ei(n,t,r),start:n.dateEnv.toDate(i.start),end:n.dateEnv.toDate(i.end),isStart:e.isStart,isEnd:e.isEnd}}"function"==typeof r&&(r=r({date:i,allDay:Boolean(t.allDayDate),allSegs:t.allSegs.map(s),hiddenSegs:t.hiddenSegs.map(s),jsEvent:e,view:n.viewApi})),r&&"popover"!==r?"string"==typeof r&&n.calendarApi.zoomTo(i,r):this.setState({isPopoverOpen:!0})},this.handlePopoverClose=()=>{this.setState({isPopoverOpen:!1})}}render(){let{props:e,state:t}=this;return p(Wn.Consumer,null,n=>{let{viewApi:r,options:i,calendarApi:s}=n,{moreLinkText:o}=i,{moreCnt:a}=e,l=Do(e),c="function"==typeof o?o.call(s,a):`+${a} ${o}`,d=at(i.moreLinkHint,[a],c),u={num:a,shortText:"+"+a,text:c,view:r};return p(y,null,Boolean(e.moreCnt)&&p(Jn,{elTag:e.elTag||"a",elRef:this.handleLinkEl,elClasses:[...e.elClasses||[],"fc-more-link"],elStyle:e.elStyle,elAttrs:Object.assign(Object.assign(Object.assign({},e.elAttrs),Qe(this.handleClick)),{title:d,"aria-expanded":t.isPopoverOpen,"aria-controls":t.isPopoverOpen?t.popoverId:""}),renderProps:u,generatorName:"moreLinkContent",customGenerator:i.moreLinkContent,defaultGenerator:e.defaultGenerator||So,classNameGenerator:i.moreLinkClassNames,didMount:i.moreLinkDidMount,willUnmount:i.moreLinkWillUnmount},e.children),t.isPopoverOpen&&p(bo,{id:t.popoverId,startDate:l.start,endDate:l.end,dateProfile:e.dateProfile,todayRange:e.todayRange,extraDateSpan:e.extraDateSpan,parentEl:this.parentEl,alignmentEl:e.alignmentElRef?e.alignmentElRef.current:this.linkEl,alignGridTop:e.alignGridTop,forceTimed:e.forceTimed,onClose:this.handlePopoverClose},e.popoverContent()))})}componentDidMount(){this.updateParentEl()}componentDidUpdate(){this.updateParentEl()}updateParentEl(){this.linkEl&&(this.parentEl=Oe(this.linkEl,".fc-view-harness"))}}function So(e){return e.text}function Do(e){if(e.allDayDate)return{start:e.allDayDate,end:wt(e.allDayDate,1)};let{hiddenSegs:t}=e;return{start:Ao(t),end:(n=t,n.reduce(Co).eventRange.range.end)};var n}function Ao(e){return e.reduce(wo).eventRange.range.start}function wo(e,t){return e.eventRange.range.start<t.eventRange.range.start?e:t}function Co(e,t){return e.eventRange.range.end>t.eventRange.range.end?e:t}var Ro={__proto__:null,BASE_OPTION_DEFAULTS:cn,BaseComponent:Gn,BgEvent:fo,CalendarImpl:Pi,CalendarRoot:Ti,ContentContainer:Jn,CustomRenderingStore:class extends class{constructor(){this.handlers=[]}set(e){this.currentValue=e;for(let t of this.handlers)t(e)}subscribe(e){this.handlers.push(e),void 0!==this.currentValue&&e(this.currentValue)}}{constructor(){super(...arguments),this.map=new Map}handle(e){const{map:t}=this;let n=!1;e.isActive?(t.set(e.id,e),n=!0):t.has(e.id)&&(t.delete(e.id),n=!0),n&&this.set(t)}},DateComponent:cs,DateEnv:Hn,DateProfileGenerator:fr,DayCellContainer:co,DayHeader:xs,DaySeriesModel:Ts,DayTableModel:ks,DelayedRunner:Me,ElementDragging:vs,ElementScrollController:as,Emitter:Vr,EventContainer:io,EventImpl:ei,Interaction:ki,MoreLinkContainer:Eo,NamedTimeZoneImpl:class{constructor(e){this.timeZoneName=e}},NowIndicatorContainer:ao,NowTimer:Oi,PositionCache:is,RefMap:Fs,ScrollController:os,ScrollResponder:Ln,Scroller:Ws,SegHierarchy:ds,SimpleScrollGrid:ro,Slicer:Ms,Splitter:Wi,StandardEvent:so,TableDateCell:ws,TableDowCell:Rs,Theme:Bn,ViewContainer:er,ViewContextType:Wn,WeekNumberContainer:mo,WindowScrollController:ls,addDays:wt,addDurations:pt,addMs:Ct,addWeeks:At,allowContextMenu:tt,allowSelection:Ke,applyMutationToEventStore:Xr,applyStyle:Be,asCleanDays:function(e){return e.years||e.months||e.milliseconds?0:e.days},asRoughMinutes:function(e){return yt(e)/6e4},asRoughMs:yt,asRoughSeconds:function(e){return yt(e)/1e3},binarySearch:ms,buildElAttrs:Zn,buildEntryKey:hs,buildEventApis:ni,buildEventRangeKey:vi,buildIsoString:Ut,buildNavLinkAttrs:Yi,buildSegTimeText:gi,collectFromHash:kn,combineEventUis:Nr,compareByFieldSpecs:rt,compareNumbers:lt,compareObjs:_n,computeEarliestSegStart:Ao,computeEdges:es,computeFallbackHeaderFormat:Ss,computeInnerRect:ts,computeRect:ns,computeShrinkWidth:Vs,computeVisibleDayRange:dr,config:ys,constrainPoint:ji,createDuration:ft,createEmptyEventStore:xr,createEventInstance:gr,createEventUi:Or,createFormatter:an,diffDates:hr,diffDayAndTime:_t,diffDays:xt,diffPoints:Ui,diffWeeks:Rt,diffWholeDays:kt,diffWholeWeeks:Tt,disableCursor:Xe,elementClosest:Oe,elementMatches:Ne,enableCursor:$e,eventTupleToStore:Cr,filterHash:Sn,findDirectChildren:function(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].children;for(let e=0;e<i.length;e+=1){let n=i[e];t&&!Ne(n,t)||r.push(n)}}return r},findElements:Pe,flexibleCompare:st,formatDayString:Lt,formatIsoMonthStr:Wt,formatIsoTimeString:Ft,getAllowYScrolling:Qs,getCanVGrowWithinCell:_i,getClippingParents:rs,getDateMeta:Vi,getDayClassNames:Gi,getDefaultEventEnd:Zr,getElSeg:oi,getEntrySpanEnd:us,getEventTargetViaRoot:ze,getIsRtlScrollbarOnLeft:$i,getRectCenter:zi,getRelevantEvents:Rr,getScrollGridClassNames:Js,getScrollbarWidths:Ji,getSectionClassNames:Ks,getSectionHasLiquidHeight:Gs,getSegAnchorAttrs:yi,getSegMeta:pi,getSlotClassNames:function(e,t){let n=["fc-slot","fc-slot-"+Dt[e.dow]];return e.isDisabled?n.push("fc-slot-disabled"):(e.isToday&&(n.push("fc-slot-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-slot-past"),e.isFuture&&n.push("fc-slot-future")),n},getStickyFooterScrollbar:no,getStickyHeaderDates:to,getUniqueDomId:Le,greatestDurationDenominator:Et,groupIntersectingEntries:fs,guid:Ze,hasBgRendering:ii,hasCustomDayCellContent:uo,hasShrinkWidth:$s,identity:yn,injectStyles:xe,interactionSettingsStore:Ii,interactionSettingsToStore:Mi,intersectRanges:ir,intersectRects:Bi,intersectSpans:gs,isArraysEqual:St,isColPropsEqual:Ys,isDateSelectionValid:Ns,isDateSpansEqual:Si,isInt:ct,isInteractionValid:Os,isMultiDayRange:ur,isPropsEqual:Cn,isPropsValid:Hs,isValidDate:jt,mapHash:Dn,memoize:Gt,memoizeArraylike:function(e,t,n){let r=[],i=[];return s=>{let o=r.length,a=s.length,l=0;for(;l<o;l+=1)if(s[l]){if(!St(r[l],s[l])){n&&n(i[l]);let r=e.apply(this,s[l]);t&&t(r,i[l])||(i[l]=r)}}else n&&n(i[l]);for(;l<a;l+=1)i[l]=e.apply(this,s[l]);return r=s,i.splice(a),i}},memoizeHashlike:function(e,t,n){let r={},i={};return s=>{let o={};for(let a in s)if(i[a])if(St(r[a],s[a]))o[a]=i[a];else{n&&n(i[a]);let r=e.apply(this,s[a]);o[a]=t&&t(r,i[a])?i[a]:r}else o[a]=e.apply(this,s[a]);return r=s,i=o,o}},memoizeObjArg:Qt,mergeEventStores:_r,multiplyDuration:mt,padStart:ot,parseBusinessHours:Qr,parseClassNames:kr,parseDragMeta:Es,parseEventDef:Ar,parseFieldSpecs:nt,parseMarker:Pn,pointInsideRect:Hi,preventContextMenu:et,preventDefault:We,preventSelection:Je,rangeContainsMarker:lr,rangeContainsRange:ar,rangesEqual:sr,rangesIntersect:or,refineEventDef:Sr,refineProps:vn,removeElement:Ie,removeExact:function(e,t){let n=0,r=0;for(;r<e.length;)e[r]===t?(e.splice(r,1),n+=1):r+=1;return n},renderChunkContent:qs,renderFill:po,renderMicroColGroup:Zs,renderScrollShim:eo,requestJson:Ri,sanitizeShrinkWidth:Xs,setRef:Qn,sliceEventStore:ri,sortEventSegs:ci,startOfDay:Mt,translateRect:function(e,t,n){return{left:e.left+t,right:e.right+t,top:e.top+n,bottom:e.bottom+n}},triggerDateSelect:qr,unpromisify:wi,whenTransitionDone:Ge,wholeDivideDurations:bt},xo={__proto__:null,createPortal:fe,createContext:Un,flushSync:jn,Component:A,Fragment:y,cloneElement:function(e,n,r){var i,s,o,a=f({},e.props);for(o in n)"key"==o?i=n[o]:"ref"==o?s=n[o]:a[o]=n[o];return arguments.length>2&&(a.children=arguments.length>3?t.call(arguments,2):r),m(e.type,a,i||e.key,s||e.ref,null)},createElement:p,createRef:v,h:p,hydrate:function e(t,n){U(t,n,e)},get isValidElement(){return i},get options(){return n},render:U,toChildArray:M};const _o=[],To={code:"en",week:{dow:0,doy:4},direction:"ltr",buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day",list:"list"},weekText:"W",weekTextLong:"Week",closeHint:"Close",timeHint:"Time",eventHint:"Event",allDayText:"all-day",moreLinkText:"more",noEventsText:"No events to display"},ko=Object.assign(Object.assign({},To),{buttonHints:{prev:"Previous $0",next:"Next $0",today:(e,t)=>"day"===t?"Today":"This "+e},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`});function Mo(e){let t=e.length>0?e[0].code:"en",n=_o.concat(e),r={en:ko};for(let e of n)r[e.code]=e;return{map:r,defaultCode:t}}function Io(e,t){return"object"!=typeof e||Array.isArray(e)?function(e,t){let n=[].concat(e||[]),r=function(e,t){for(let n=0;n<e.length;n+=1){let r=e[n].toLocaleLowerCase().split("-");for(let e=r.length;e>0;e-=1){let n=r.slice(0,e).join("-");if(t[n])return t[n]}}return null}(n,t)||ko;return Oo(e,n,r)}(e,t):Oo(e.code,[e.code],e)}function Oo(e,t,n){let r=En([To,n],["buttonText"]);delete r.code;let{week:i}=r;return delete r.week,{codeArg:e,codes:t,week:i,simpleNumberFormat:new Intl.NumberFormat(e),options:r}}function No(e){return{id:Ze(),name:e.name,premiumReleaseDate:e.premiumReleaseDate?new Date(e.premiumReleaseDate):void 0,deps:e.deps||[],reducers:e.reducers||[],isLoadingFuncs:e.isLoadingFuncs||[],contextInit:[].concat(e.contextInit||[]),eventRefiners:e.eventRefiners||{},eventDefMemberAdders:e.eventDefMemberAdders||[],eventSourceRefiners:e.eventSourceRefiners||{},isDraggableTransformers:e.isDraggableTransformers||[],eventDragMutationMassagers:e.eventDragMutationMassagers||[],eventDefMutationAppliers:e.eventDefMutationAppliers||[],dateSelectionTransformers:e.dateSelectionTransformers||[],datePointTransforms:e.datePointTransforms||[],dateSpanTransforms:e.dateSpanTransforms||[],views:e.views||{},viewPropsTransformers:e.viewPropsTransformers||[],isPropsValid:e.isPropsValid||null,externalDefTransforms:e.externalDefTransforms||[],viewContainerAppends:e.viewContainerAppends||[],eventDropTransformers:e.eventDropTransformers||[],componentInteractions:e.componentInteractions||[],calendarInteractions:e.calendarInteractions||[],themeClasses:e.themeClasses||{},eventSourceDefs:e.eventSourceDefs||[],cmdFormatter:e.cmdFormatter,recurringTypes:e.recurringTypes||[],namedTimeZonedImpl:e.namedTimeZonedImpl,initialView:e.initialView||"",elementDraggingImpl:e.elementDraggingImpl,optionChangeHandlers:e.optionChangeHandlers||{},scrollGridImpl:e.scrollGridImpl||null,listenerRefiners:e.listenerRefiners||{},optionRefiners:e.optionRefiners||{},propSetHandlers:e.propSetHandlers||{}}}function Po(){let e,t=[],n=[];return(r,i)=>(e&&St(r,t)&&St(i,n)||(e=function(e,t){let n={},r={premiumReleaseDate:void 0,reducers:[],isLoadingFuncs:[],contextInit:[],eventRefiners:{},eventDefMemberAdders:[],eventSourceRefiners:{},isDraggableTransformers:[],eventDragMutationMassagers:[],eventDefMutationAppliers:[],dateSelectionTransformers:[],datePointTransforms:[],dateSpanTransforms:[],views:{},viewPropsTransformers:[],isPropsValid:null,externalDefTransforms:[],viewContainerAppends:[],eventDropTransformers:[],componentInteractions:[],calendarInteractions:[],themeClasses:{},eventSourceDefs:[],cmdFormatter:null,recurringTypes:[],namedTimeZonedImpl:null,initialView:"",elementDraggingImpl:null,optionChangeHandlers:{},scrollGridImpl:null,listenerRefiners:{},optionRefiners:{},propSetHandlers:{}};function i(e){for(let o of e){const e=o.name,a=n[e];void 0===a?(n[e]=o.id,i(o.deps),s=o,r={premiumReleaseDate:Ho((t=r).premiumReleaseDate,s.premiumReleaseDate),reducers:t.reducers.concat(s.reducers),isLoadingFuncs:t.isLoadingFuncs.concat(s.isLoadingFuncs),contextInit:t.contextInit.concat(s.contextInit),eventRefiners:Object.assign(Object.assign({},t.eventRefiners),s.eventRefiners),eventDefMemberAdders:t.eventDefMemberAdders.concat(s.eventDefMemberAdders),eventSourceRefiners:Object.assign(Object.assign({},t.eventSourceRefiners),s.eventSourceRefiners),isDraggableTransformers:t.isDraggableTransformers.concat(s.isDraggableTransformers),eventDragMutationMassagers:t.eventDragMutationMassagers.concat(s.eventDragMutationMassagers),eventDefMutationAppliers:t.eventDefMutationAppliers.concat(s.eventDefMutationAppliers),dateSelectionTransformers:t.dateSelectionTransformers.concat(s.dateSelectionTransformers),datePointTransforms:t.datePointTransforms.concat(s.datePointTransforms),dateSpanTransforms:t.dateSpanTransforms.concat(s.dateSpanTransforms),views:Object.assign(Object.assign({},t.views),s.views),viewPropsTransformers:t.viewPropsTransformers.concat(s.viewPropsTransformers),isPropsValid:s.isPropsValid||t.isPropsValid,externalDefTransforms:t.externalDefTransforms.concat(s.externalDefTransforms),viewContainerAppends:t.viewContainerAppends.concat(s.viewContainerAppends),eventDropTransformers:t.eventDropTransformers.concat(s.eventDropTransformers),calendarInteractions:t.calendarInteractions.concat(s.calendarInteractions),componentInteractions:t.componentInteractions.concat(s.componentInteractions),themeClasses:Object.assign(Object.assign({},t.themeClasses),s.themeClasses),eventSourceDefs:t.eventSourceDefs.concat(s.eventSourceDefs),cmdFormatter:s.cmdFormatter||t.cmdFormatter,recurringTypes:t.recurringTypes.concat(s.recurringTypes),namedTimeZonedImpl:s.namedTimeZonedImpl||t.namedTimeZonedImpl,initialView:t.initialView||s.initialView,elementDraggingImpl:t.elementDraggingImpl||s.elementDraggingImpl,optionChangeHandlers:Object.assign(Object.assign({},t.optionChangeHandlers),s.optionChangeHandlers),scrollGridImpl:s.scrollGridImpl||t.scrollGridImpl,listenerRefiners:Object.assign(Object.assign({},t.listenerRefiners),s.listenerRefiners),optionRefiners:Object.assign(Object.assign({},t.optionRefiners),s.optionRefiners),propSetHandlers:Object.assign(Object.assign({},t.propSetHandlers),s.propSetHandlers)}):a!==o.id&&console.warn(`Duplicate plugin '${e}'`)}var t,s}return e&&i(e),i(t),r}(r,i)),t=r,n=i,e)}function Ho(e,t){return void 0===e?t:void 0===t?e:new Date(Math.max(e.valueOf(),t.valueOf()))}class Bo extends Bn{}function jo(e,t,n,r){if(t[e])return t[e];let i=function(e,t,n,r){let i=n[e],s=r[e],o=e=>i&&null!==i[e]?i[e]:s&&null!==s[e]?s[e]:null,a=o("component"),l=o("superType"),c=null;if(l){if(l===e)throw new Error("Can't have a custom view type that references itself");c=jo(l,t,n,r)}!a&&c&&(a=c.component);if(!a)return null;return{type:e,component:a,defaults:Object.assign(Object.assign({},c?c.defaults:{}),i?i.rawOptions:{}),overrides:Object.assign(Object.assign({},c?c.overrides:{}),s?s.rawOptions:{})}}(e,t,n,r);return i&&(t[e]=i),i}function zo(e){return Dn(e,Uo)}function Uo(e){let t="function"==typeof e?{component:e}:e,{component:n}=t;return t.content?n=Lo(t):!n||n.prototype instanceof Gn||(n=Lo(Object.assign(Object.assign({},t),{content:n}))),{superType:t.type,component:n,rawOptions:t}}function Lo(e){return t=>p(Wn.Consumer,null,n=>p(Jn,{elTag:"div",elClasses:tr(n.viewSpec),renderProps:Object.assign(Object.assign({},t),{nextDayThreshold:n.options.nextDayThreshold}),generatorName:void 0,customGenerator:e.content,classNameGenerator:e.classNames,didMount:e.didMount,willUnmount:e.willUnmount}))}function Wo(e,t,n,r){let i=zo(e),s=zo(t.views);return Dn(function(e,t){let n,r={};for(n in e)jo(n,r,e,t);for(n in t)jo(n,r,e,t);return r}(i,s),e=>function(e,t,n,r,i){let s=e.overrides.duration||e.defaults.duration||r.duration||n.duration,o=null,a="",l="",c={};if(s&&(o=function(e){let t=JSON.stringify(e),n=Fo[t];void 0===n&&(n=ft(e),Fo[t]=n);return n}(s),o)){let e=Et(o);a=e.unit,1===e.value&&(l=a,c=t[a]?t[a].rawOptions:{})}let d=t=>{let n=t.buttonText||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null},u=t=>{let n=t.buttonHints||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null};return{type:e.type,component:e.component,duration:o,durationUnit:a,singleUnit:l,optionDefaults:e.defaults,optionOverrides:Object.assign(Object.assign({},c),e.overrides),buttonTextOverride:d(r)||d(n)||e.overrides.buttonText,buttonTextDefault:d(i)||e.defaults.buttonText||d(cn)||e.type,buttonTitleOverride:u(r)||u(n)||e.overrides.buttonHint,buttonTitleDefault:u(i)||e.defaults.buttonHint||u(cn)}}(e,s,t,n,r))}Bo.prototype.classes={root:"fc-theme-standard",tableCellShaded:"fc-cell-shaded",buttonGroup:"fc-button-group",button:"fc-button fc-button-primary",buttonActive:"fc-button-active"},Bo.prototype.baseIconClass="fc-icon",Bo.prototype.iconClasses={close:"fc-icon-x",prev:"fc-icon-chevron-left",next:"fc-icon-chevron-right",prevYear:"fc-icon-chevrons-left",nextYear:"fc-icon-chevrons-right"},Bo.prototype.rtlIconClasses={prev:"fc-icon-chevron-right",next:"fc-icon-chevron-left",prevYear:"fc-icon-chevrons-right",nextYear:"fc-icon-chevrons-left"},Bo.prototype.iconOverrideOption="buttonIcons",Bo.prototype.iconOverrideCustomButtonOption="icon",Bo.prototype.iconOverridePrefix="fc-icon-";let Fo={};function Vo(e,t,n){let r=t?t.activeRange:null;return qo({},function(e,t){let n=jr(t),r=[].concat(e.eventSources||[]),i=[];e.initialEvents&&r.unshift(e.initialEvents);e.events&&r.unshift(e.events);for(let e of r){let r=Br(e,t,n);r&&i.push(r)}return i}(e,n),r,n)}function Go(e,t,n,r){let i=n?n.activeRange:null;switch(t.type){case"ADD_EVENT_SOURCES":return qo(e,t.sources,i,r);case"REMOVE_EVENT_SOURCE":return s=e,o=t.sourceId,Sn(s,e=>e.sourceId!==o);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return n?Yo(e,i,r):e;case"FETCH_EVENT_SOURCES":return Zo(e,t.sourceIds?An(t.sourceIds):$o(e,r),i,t.isRefetch||!1,r);case"RECEIVE_EVENTS":case"RECEIVE_EVENT_ERROR":return function(e,t,n,r){let i=e[t];if(i&&n===i.latestFetchId)return Object.assign(Object.assign({},e),{[t]:Object.assign(Object.assign({},i),{isFetching:!1,fetchRange:r})});return e}(e,t.sourceId,t.fetchId,t.fetchRange);case"REMOVE_ALL_EVENT_SOURCES":return{};default:return e}var s,o}function Qo(e){for(let t in e)if(e[t].isFetching)return!0;return!1}function qo(e,t,n,r){let i={};for(let e of t)i[e.sourceId]=e;return n&&(i=Yo(i,n,r)),Object.assign(Object.assign({},e),i)}function Yo(e,t,n){return Zo(e,Sn(e,e=>function(e,t,n){if(!Jo(e,n))return!e.latestFetchId;return!n.options.lazyFetching||!e.fetchRange||e.isFetching||t.start<e.fetchRange.start||t.end>e.fetchRange.end}(e,t,n)),t,!1,n)}function Zo(e,t,n,r,i){let s={};for(let o in e){let a=e[o];t[o]?s[o]=Xo(a,n,r,i):s[o]=a}return s}function Xo(e,t,n,r){let{options:i,calendarApi:s}=r,o=r.pluginHooks.eventSourceDefs[e.sourceDefId],a=Ze();return o.fetch({eventSource:e,range:t,isRefetch:n,context:r},n=>{let{rawEvents:o}=n;i.eventSourceSuccess&&(o=i.eventSourceSuccess.call(s,o,n.response)||o),e.success&&(o=e.success.call(s,o,n.response)||o),r.dispatch({type:"RECEIVE_EVENTS",sourceId:e.sourceId,fetchId:a,fetchRange:t,rawEvents:o})},n=>{let o=!1;i.eventSourceFailure&&(i.eventSourceFailure.call(s,n),o=!0),e.failure&&(e.failure(n),o=!0),o||console.warn(n.message,n),r.dispatch({type:"RECEIVE_EVENT_ERROR",sourceId:e.sourceId,fetchId:a,fetchRange:t,error:n})}),Object.assign(Object.assign({},e),{isFetching:!0,latestFetchId:a})}function $o(e,t){return Sn(e,e=>Jo(e,t))}function Jo(e,t){return!t.pluginHooks.eventSourceDefs[e.sourceDefId].ignoreRange}function Ko(e,t){switch(t.type){case"UNSELECT_DATES":return null;case"SELECT_DATES":return t.selection;default:return e}}function ea(e,t){switch(t.type){case"UNSELECT_EVENT":return"";case"SELECT_EVENT":return t.eventInstanceId;default:return e}}function ta(e,t){let n;switch(t.type){case"UNSET_EVENT_DRAG":return null;case"SET_EVENT_DRAG":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function na(e,t){let n;switch(t.type){case"UNSET_EVENT_RESIZE":return null;case"SET_EVENT_RESIZE":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function ra(e,t,n,r,i){return{header:e.headerToolbar?ia(e.headerToolbar,e,t,n,r,i):null,footer:e.footerToolbar?ia(e.footerToolbar,e,t,n,r,i):null}}function ia(e,t,n,r,i,s){let o={},a=[],l=!1;for(let c in e){let d=sa(e[c],t,n,r,i,s);o[c]=d.widgets,a.push(...d.viewsWithButtons),l=l||d.hasTitle}return{sectionWidgets:o,viewsWithButtons:a,hasTitle:l}}function sa(e,t,n,r,i,s){let o="rtl"===t.direction,a=t.customButtons||{},l=n.buttonText||{},c=t.buttonText||{},d=n.buttonHints||{},u=t.buttonHints||{},h=e?e.split(" "):[],f=[],g=!1;return{widgets:h.map(e=>e.split(",").map(e=>{if("title"===e)return g=!0,{buttonName:e};let n,h,p,m,v,y;if(n=a[e])p=e=>{n.click&&n.click.call(e.target,e,e.target)},(m=r.getCustomButtonIconClass(n))||(m=r.getIconClass(e,o))||(v=n.text),y=n.hint||n.text;else if(h=i[e]){f.push(e),p=()=>{s.changeView(e)},(v=h.buttonTextOverride)||(m=r.getIconClass(e,o))||(v=h.buttonTextDefault);let n=h.buttonTextOverride||h.buttonTextDefault;y=at(h.buttonTitleOverride||h.buttonTitleDefault||t.viewHint,[n,e],n)}else if(s[e])if(p=()=>{s[e]()},(v=l[e])||(m=r.getIconClass(e,o))||(v=c[e]),"prevYear"===e||"nextYear"===e){let t="prevYear"===e?"prev":"next";y=at(d[t]||u[t],[c.year||"year","year"],c[e])}else y=t=>at(d[e]||u[e],[c[t]||t,t],c[e]);return{buttonName:e,buttonClick:p,buttonIcon:m,buttonText:v,buttonHint:y}})),viewsWithButtons:f,hasTitle:g}}class oa{constructor(e,t,n){this.type=e,this.getCurrentData=t,this.dateEnv=n}get calendar(){return this.getCurrentData().calendarApi}get title(){return this.getCurrentData().viewTitle}get activeStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start)}get activeEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end)}get currentStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start)}get currentEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end)}getOption(e){return this.getCurrentData().options[e]}}function aa(e,t){let n=wn(t.getCurrentData().eventSources);if(1===n.length&&1===e.length&&Array.isArray(n[0]._raw)&&Array.isArray(e[0]))return void t.dispatch({type:"RESET_RAW_EVENTS",sourceId:n[0].sourceId,rawEvents:e[0]});let r=[];for(let t of e){let e=!1;for(let r=0;r<n.length;r+=1)if(n[r]._raw===t){n.splice(r,1),e=!0;break}e||r.push(t)}for(let e of n)t.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:e.sourceId});for(let e of r)t.calendarApi.addEventSource(e)}const la=[No({name:"array-event-source",eventSourceDefs:[{ignoreRange:!0,parseMeta:e=>Array.isArray(e.events)?e.events:null,fetch(e,t){t({rawEvents:e.eventSource.meta})}}]}),No({name:"func-event-source",eventSourceDefs:[{parseMeta:e=>"function"==typeof e.events?e.events:null,fetch(e,t,n){const{dateEnv:r}=e.context;wi(e.eventSource.meta.bind(null,Di(e.range,r)),e=>t({rawEvents:e}),n)}}]}),No({name:"json-event-source",eventSourceRefiners:{method:String,extraParams:yn,startParam:String,endParam:String,timeZoneParam:String},eventSourceDefs:[{parseMeta:e=>!e.url||"json"!==e.format&&e.format?null:{url:e.url,format:"json",method:(e.method||"GET").toUpperCase(),extraParams:e.extraParams,startParam:e.startParam,endParam:e.endParam,timeZoneParam:e.timeZoneParam},fetch(e,t,n){const{meta:r}=e.eventSource,i=function(e,t,n){let r,i,s,o,{dateEnv:a,options:l}=n,c={};r=e.startParam,null==r&&(r=l.startParam);i=e.endParam,null==i&&(i=l.endParam);s=e.timeZoneParam,null==s&&(s=l.timeZoneParam);o="function"==typeof e.extraParams?e.extraParams():e.extraParams||{};Object.assign(c,o),c[r]=a.formatIso(t.start),c[i]=a.formatIso(t.end),"local"!==a.timeZone&&(c[s]=a.timeZone);return c}(r,e.range,e.context);Ri(r.method,r.url,i).then(([e,n])=>{t({rawEvents:e,response:n})},n)}}]}),No({name:"simple-recurring-event",recurringTypes:[{parse(e,t){if(e.daysOfWeek||e.startTime||e.endTime||e.startRecur||e.endRecur){let i,s={daysOfWeek:e.daysOfWeek||null,startTime:e.startTime||null,endTime:e.endTime||null,startRecur:e.startRecur?t.createMarker(e.startRecur):null,endRecur:e.endRecur?t.createMarker(e.endRecur):null,dateEnv:t};return e.duration&&(i=e.duration),!i&&e.startTime&&e.endTime&&(n=e.endTime,r=e.startTime,i={years:n.years-r.years,months:n.months-r.months,days:n.days-r.days,milliseconds:n.milliseconds-r.milliseconds}),{allDayGuess:Boolean(!e.startTime&&!e.endTime),duration:i,typeData:s}}var n,r;return null},expand(e,t,n){let r=ir(t,{start:e.startRecur,end:e.endRecur});return r?function(e,t,n,r,i){let s=e?An(e):null,o=Mt(i.start),a=i.end,l=[];for(;o<a;){let e;s&&!s[o.getUTCDay()]||(e=t?r.add(o,t):o,l.push(r.createMarker(n.toDate(e)))),o=wt(o,1)}return l}(e.daysOfWeek,e.startTime,e.dateEnv,n,r):[]}}],eventRefiners:{daysOfWeek:yn,startTime:ft,endTime:ft,duration:ft,startRecur:yn,endRecur:yn}}),No({name:"change-handler",optionChangeHandlers:{events(e,t){aa([e],t)},eventSources:aa}}),No({name:"misc",isLoadingFuncs:[e=>Qo(e.eventSources)],propSetHandlers:{dateProfile:function(e,t){t.emitter.trigger("datesSet",Object.assign(Object.assign({},Di(e.activeRange,t.dateEnv)),{view:t.viewApi}))},eventStore:function(e,t){let{emitter:n}=t;n.hasHandlers("eventsSet")&&n.trigger("eventsSet",ni(e,t))}}})];class ca{constructor(e,t){this.runTaskOption=e,this.drainedOption=t,this.queue=[],this.delayedRunner=new Me(this.drain.bind(this))}request(e,t){this.queue.push(e),this.delayedRunner.request(t)}pause(e){this.delayedRunner.pause(e)}resume(e,t){this.delayedRunner.resume(e,t)}drain(){let{queue:e}=this;for(;e.length;){let t,n=[];for(;t=e.shift();)this.runTask(t),n.push(t);this.drained(n)}}runTask(e){this.runTaskOption&&this.runTaskOption(e)}drained(e){this.drainedOption&&this.drainedOption(e)}}function da(e,t,n){let r;return r=/^(year|month)$/.test(e.currentRangeUnit)?e.currentRange:e.activeRange,n.formatRange(r.start,r.end,an(t.titleFormat||function(e){let{currentRangeUnit:t}=e;if("year"===t)return{year:"numeric"};if("month"===t)return{year:"numeric",month:"long"};let n=kt(e.currentRange.start,e.currentRange.end);if(null!==n&&n>1)return{year:"numeric",month:"short",day:"numeric"};return{year:"numeric",month:"long",day:"numeric"}}(e)),{isEndExclusive:e.isRangeAllDay,defaultSeparator:t.titleRangeSeparator})}class ua{constructor(){this.resetListeners=new Set}handleInput(e,t){const n=this.dateEnv;if(e!==n&&("function"==typeof t?this.nowFn=t:n||(this.nowAnchorDate=e.toDate(t?e.createMarker(t):e.createNowMarker()),this.nowAnchorQueried=Date.now()),this.dateEnv=e,n))for(const e of this.resetListeners.values())e()}getDateMarker(){return this.nowAnchorDate?this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf()+(Date.now()-this.nowAnchorQueried)):this.dateEnv.createMarker(this.nowFn())}addResetListener(e){this.resetListeners.add(e)}removeResetListener(e){this.resetListeners.delete(e)}}class ha{constructor(e){this.computeCurrentViewData=Gt(this._computeCurrentViewData),this.organizeRawLocales=Gt(Mo),this.buildLocale=Gt(Io),this.buildPluginHooks=Po(),this.buildDateEnv=Gt(fa),this.buildTheme=Gt(ga),this.parseToolbars=Gt(ra),this.buildViewSpecs=Gt(Wo),this.buildDateProfileGenerator=Qt(pa),this.buildViewApi=Gt(ma),this.buildViewUiProps=Qt(ba),this.buildEventUiBySource=Gt(va,Cn),this.buildEventUiBases=Gt(ya),this.parseContextBusinessHours=Qt(Sa),this.buildTitle=Gt(da),this.nowManager=new ua,this.emitter=new Vr,this.actionRunner=new ca(this._handleAction.bind(this),this.updateData.bind(this)),this.currentCalendarOptionsInput={},this.currentCalendarOptionsRefined={},this.currentViewOptionsInput={},this.currentViewOptionsRefined={},this.currentCalendarOptionsRefiners={},this.optionsForRefining=[],this.optionsForHandling=[],this.getCurrentData=()=>this.data,this.dispatch=e=>{this.actionRunner.request(e)},this.props=e,this.actionRunner.pause(),this.nowManager=new ua;let t={},n=this.computeOptionsData(e.optionOverrides,t,e.calendarApi),r=n.calendarOptions.initialView||n.pluginHooks.initialView,i=this.computeCurrentViewData(r,n,e.optionOverrides,t);e.calendarApi.currentDataManager=this,this.emitter.setThisContext(e.calendarApi),this.emitter.setOptions(i.options);let s={nowManager:this.nowManager,dateEnv:n.dateEnv,options:n.calendarOptions,pluginHooks:n.pluginHooks,calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData},o=function(e,t,n){let r=e.initialDate;return null!=r?t.createMarker(r):n.getDateMarker()}(n.calendarOptions,n.dateEnv,this.nowManager),a=i.dateProfileGenerator.build(o);lr(a.activeRange,o)||(o=a.currentRange.start);for(let e of n.pluginHooks.contextInit)e(s);let l=Vo(n.calendarOptions,a,s),c={dynamicOptionOverrides:t,currentViewType:r,currentDate:o,dateProfile:a,businessHours:this.parseContextBusinessHours(s),eventSources:l,eventUiBases:{},eventStore:{defs:{},instances:{}},renderableEventStore:{defs:{},instances:{}},dateSelection:null,eventSelection:"",eventDrag:null,eventResize:null,selectionConfig:this.buildViewUiProps(s).selectionConfig},d=Object.assign(Object.assign({},s),c);for(let e of n.pluginHooks.reducers)Object.assign(c,e(null,null,d));Ea(c,s)&&this.emitter.trigger("loading",!0),this.state=c,this.updateData(),this.actionRunner.resume()}resetOptions(e,t){let{props:n}=this;void 0===t?n.optionOverrides=e:(n.optionOverrides=Object.assign(Object.assign({},n.optionOverrides||{}),e),this.optionsForRefining.push(...t)),(void 0===t||t.length)&&this.actionRunner.request({type:"NOTHING"})}_handleAction(e){let{props:t,state:n,emitter:r}=this,i=function(e,t){switch(t.type){case"SET_OPTION":return Object.assign(Object.assign({},e),{[t.optionName]:t.rawOptionValue});default:return e}}(n.dynamicOptionOverrides,e),s=this.computeOptionsData(t.optionOverrides,i,t.calendarApi),o=function(e,t){switch(t.type){case"CHANGE_VIEW_TYPE":e=t.viewType}return e}(n.currentViewType,e),a=this.computeCurrentViewData(o,s,t.optionOverrides,i);t.calendarApi.currentDataManager=this,r.setThisContext(t.calendarApi),r.setOptions(a.options);let l={nowManager:this.nowManager,dateEnv:s.dateEnv,options:s.calendarOptions,pluginHooks:s.pluginHooks,calendarApi:t.calendarApi,dispatch:this.dispatch,emitter:r,getCurrentData:this.getCurrentData},{currentDate:c,dateProfile:d}=n;this.data&&this.data.dateProfileGenerator!==a.dateProfileGenerator&&(d=a.dateProfileGenerator.build(c)),c=function(e,t){switch(t.type){case"CHANGE_DATE":return t.dateMarker;default:return e}}(c,e),d=function(e,t,n,r){let i;switch(t.type){case"CHANGE_VIEW_TYPE":return r.build(t.dateMarker||n);case"CHANGE_DATE":return r.build(t.dateMarker);case"PREV":if(i=r.buildPrev(e,n),i.isValid)return i;break;case"NEXT":if(i=r.buildNext(e,n),i.isValid)return i}return e}(d,e,c,a.dateProfileGenerator),"PREV"!==e.type&&"NEXT"!==e.type&&lr(d.currentRange,c)||(c=d.currentRange.start);let u=Go(n.eventSources,e,d,l),h=zr(n.eventStore,e,u,d,l),f=Qo(u)&&!a.options.progressiveEventRendering&&n.renderableEventStore||h,{eventUiSingleBase:g,selectionConfig:p}=this.buildViewUiProps(l),m=this.buildEventUiBySource(u),v={dynamicOptionOverrides:i,currentViewType:o,currentDate:c,dateProfile:d,eventSources:u,eventStore:h,renderableEventStore:f,selectionConfig:p,eventUiBases:this.buildEventUiBases(f.defs,g,m),businessHours:this.parseContextBusinessHours(l),dateSelection:Ko(n.dateSelection,e),eventSelection:ea(n.eventSelection,e),eventDrag:ta(n.eventDrag,e),eventResize:na(n.eventResize,e)},y=Object.assign(Object.assign({},l),v);for(let t of s.pluginHooks.reducers)Object.assign(v,t(n,e,y));let b=Ea(n,l),E=Ea(v,l);!b&&E?r.trigger("loading",!0):b&&!E&&r.trigger("loading",!1),this.state=v,t.onAction&&t.onAction(e)}updateData(){let{props:e,state:t}=this,n=this.data,r=this.computeOptionsData(e.optionOverrides,t.dynamicOptionOverrides,e.calendarApi),i=this.computeCurrentViewData(t.currentViewType,r,e.optionOverrides,t.dynamicOptionOverrides),s=this.data=Object.assign(Object.assign(Object.assign({nowManager:this.nowManager,viewTitle:this.buildTitle(t.dateProfile,i.options,r.dateEnv),calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData},r),i),t),o=r.pluginHooks.optionChangeHandlers,a=n&&n.calendarOptions,l=r.calendarOptions;if(a&&a!==l){a.timeZone!==l.timeZone&&(t.eventSources=s.eventSources=function(e,t,n){let r=t?t.activeRange:null;return Zo(e,$o(e,n),r,!0,n)}(s.eventSources,t.dateProfile,s),t.eventStore=s.eventStore=Wr(s.eventStore,n.dateEnv,s.dateEnv),t.renderableEventStore=s.renderableEventStore=Wr(s.renderableEventStore,n.dateEnv,s.dateEnv));for(let e in o)-1===this.optionsForHandling.indexOf(e)&&a[e]===l[e]||o[e](l[e],s)}this.optionsForHandling=[],e.onData&&e.onData(s)}computeOptionsData(e,t,n){if(!this.optionsForRefining.length&&e===this.stableOptionOverrides&&t===this.stableDynamicOptionOverrides)return this.stableCalendarOptionsData;let{refinedOptions:r,pluginHooks:i,localeDefaults:s,availableLocaleData:o,extra:a}=this.processRawCalendarOptions(e,t);Da(a);let l=this.buildDateEnv(r.timeZone,r.locale,r.weekNumberCalculation,r.firstDay,r.weekText,i,o,r.defaultRangeSeparator),c=this.buildViewSpecs(i.views,this.stableOptionOverrides,this.stableDynamicOptionOverrides,s),d=this.buildTheme(r,i),u=this.parseToolbars(r,this.stableOptionOverrides,d,c,n);return this.stableCalendarOptionsData={calendarOptions:r,pluginHooks:i,dateEnv:l,viewSpecs:c,theme:d,toolbarConfig:u,localeDefaults:s,availableRawLocales:o.map}}processRawCalendarOptions(e,t){let{locales:n,locale:r}=mn([cn,e,t]),i=this.organizeRawLocales(n),s=i.map,o=this.buildLocale(r||i.defaultCode,s).options,a=this.buildPluginHooks(e.plugins||[],la),l=this.currentCalendarOptionsRefiners=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},ln),dn),un),a.listenerRefiners),a.optionRefiners),c={},d=mn([cn,o,e,t]),u={},h=this.currentCalendarOptionsInput,f=this.currentCalendarOptionsRefined,g=!1;for(let e in d)-1===this.optionsForRefining.indexOf(e)&&(d[e]===h[e]||hn[e]&&e in h&&hn[e](h[e],d[e]))?u[e]=f[e]:l[e]?(u[e]=l[e](d[e]),g=!0):c[e]=h[e];return g&&(this.currentCalendarOptionsInput=d,this.currentCalendarOptionsRefined=u,this.stableOptionOverrides=e,this.stableDynamicOptionOverrides=t),this.optionsForHandling.push(...this.optionsForRefining),this.optionsForRefining=[],{rawOptions:this.currentCalendarOptionsInput,refinedOptions:this.currentCalendarOptionsRefined,pluginHooks:a,availableLocaleData:i,localeDefaults:o,extra:c}}_computeCurrentViewData(e,t,n,r){let i=t.viewSpecs[e];if(!i)throw new Error(`viewType "${e}" is not available. Please make sure you've loaded all neccessary plugins`);let{refinedOptions:s,extra:o}=this.processRawViewOptions(i,t.pluginHooks,t.localeDefaults,n,r);return Da(o),this.nowManager.handleInput(t.dateEnv,s.now),{viewSpec:i,options:s,dateProfileGenerator:this.buildDateProfileGenerator({dateProfileGeneratorClass:i.optionDefaults.dateProfileGeneratorClass,nowManager:this.nowManager,duration:i.duration,durationUnit:i.durationUnit,usesMinMaxTime:i.optionDefaults.usesMinMaxTime,dateEnv:t.dateEnv,calendarApi:this.props.calendarApi,slotMinTime:s.slotMinTime,slotMaxTime:s.slotMaxTime,showNonCurrentDates:s.showNonCurrentDates,dayCount:s.dayCount,dateAlignment:s.dateAlignment,dateIncrement:s.dateIncrement,hiddenDays:s.hiddenDays,weekends:s.weekends,validRangeInput:s.validRange,visibleRangeInput:s.visibleRange,fixedWeekCount:s.fixedWeekCount}),viewApi:this.buildViewApi(e,this.getCurrentData,t.dateEnv)}}processRawViewOptions(e,t,n,r,i){let s=mn([cn,e.optionDefaults,n,r,e.optionOverrides,i]),o=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},ln),dn),un),pn),t.listenerRefiners),t.optionRefiners),a={},l=this.currentViewOptionsInput,c=this.currentViewOptionsRefined,d=!1,u={};for(let e in s)s[e]===l[e]||hn[e]&&hn[e](s[e],l[e])?a[e]=c[e]:(s[e]===this.currentCalendarOptionsInput[e]||hn[e]&&hn[e](s[e],this.currentCalendarOptionsInput[e])?e in this.currentCalendarOptionsRefined&&(a[e]=this.currentCalendarOptionsRefined[e]):o[e]?a[e]=o[e](s[e]):u[e]=s[e],d=!0);return d&&(this.currentViewOptionsInput=s,this.currentViewOptionsRefined=a),{rawOptions:this.currentViewOptionsInput,refinedOptions:this.currentViewOptionsRefined,extra:u}}}function fa(e,t,n,r,i,s,o,a){let l=Io(t||o.defaultCode,o.map);return new Hn({calendarSystem:"gregory",timeZone:e,namedTimeZoneImpl:s.namedTimeZonedImpl,locale:l,weekNumberCalculation:n,firstDay:r,weekText:i,cmdFormatter:s.cmdFormatter,defaultSeparator:a})}function ga(e,t){return new(t.themeClasses[e.themeSystem]||Bo)(e)}function pa(e){return new(e.dateProfileGeneratorClass||fr)(e)}function ma(e,t,n){return new oa(e,t,n)}function va(e){return Dn(e,e=>e.ui)}function ya(e,t,n){let r={"":t};for(let t in e){let i=e[t];i.sourceId&&n[i.sourceId]&&(r[t]=n[i.sourceId])}return r}function ba(e){let{options:t}=e;return{eventUiSingleBase:Or({display:t.eventDisplay,editable:t.editable,startEditable:t.eventStartEditable,durationEditable:t.eventDurationEditable,constraint:t.eventConstraint,overlap:"boolean"==typeof t.eventOverlap?t.eventOverlap:void 0,allow:t.eventAllow,backgroundColor:t.eventBackgroundColor,borderColor:t.eventBorderColor,textColor:t.eventTextColor,color:t.eventColor},e),selectionConfig:Or({constraint:t.selectConstraint,overlap:"boolean"==typeof t.selectOverlap?t.selectOverlap:void 0,allow:t.selectAllow},e)}}function Ea(e,t){for(let n of t.pluginHooks.isLoadingFuncs)if(n(e))return!0;return!1}function Sa(e){return Qr(e.options.businessHours,e)}function Da(e,t){for(let n in e)console.warn(`Unknown option '${n}'`+(t?` for view '${t}'`:""))}class Aa extends Gn{render(){return p("div",{className:"fc-toolbar-chunk"},...this.props.widgetGroups.map(e=>this.renderWidgetGroup(e)))}renderWidgetGroup(e){let{props:t}=this,{theme:n}=this.context,r=[],i=!0;for(let s of e){let{buttonName:e,buttonClick:o,buttonText:a,buttonIcon:l,buttonHint:c}=s;if("title"===e)i=!1,r.push(p("h2",{className:"fc-toolbar-title",id:t.titleId},t.title));else{let i=e===t.activeButton,s=!t.isTodayEnabled&&"today"===e||!t.isPrevEnabled&&"prev"===e||!t.isNextEnabled&&"next"===e,d=[`fc-${e}-button`,n.getClass("button")];i&&d.push(n.getClass("buttonActive")),r.push(p("button",{type:"button",title:"function"==typeof c?c(t.navUnit):c,disabled:s,"aria-pressed":i,className:d.join(" "),onClick:o},a||(l?p("span",{className:l,role:"img"}):"")))}}if(r.length>1){return p("div",{className:i&&n.getClass("buttonGroup")||""},...r)}return r[0]}}class wa extends Gn{render(){let e,t,{model:n,extraClassName:r}=this.props,i=!1,s=n.sectionWidgets,o=s.center;return s.left?(i=!0,e=s.left):e=s.start,s.right?(i=!0,t=s.right):t=s.end,p("div",{className:[r||"","fc-toolbar",i?"fc-toolbar-ltr":""].join(" ")},this.renderSection("start",e||[]),this.renderSection("center",o||[]),this.renderSection("end",t||[]))}renderSection(e,t){let{props:n}=this;return p(Aa,{key:e,widgetGroups:t,title:n.title,navUnit:n.navUnit,activeButton:n.activeButton,isTodayEnabled:n.isTodayEnabled,isPrevEnabled:n.isPrevEnabled,isNextEnabled:n.isNextEnabled,titleId:n.titleId})}}class Ca extends Gn{constructor(){super(...arguments),this.state={availableWidth:null},this.handleEl=e=>{this.el=e,Qn(this.props.elRef,e),this.updateAvailableWidth()},this.handleResize=()=>{this.updateAvailableWidth()}}render(){let{props:e,state:t}=this,{aspectRatio:n}=e,r=["fc-view-harness",n||e.liquid||e.height?"fc-view-harness-active":"fc-view-harness-passive"],i="",s="";return n?null!==t.availableWidth?i=t.availableWidth/n:s=1/n*100+"%":i=e.height||"",p("div",{"aria-labelledby":e.labeledById,ref:this.handleEl,className:r.join(" "),style:{height:i,paddingBottom:s}},e.children)}componentDidMount(){this.context.addResizeHandler(this.handleResize)}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}updateAvailableWidth(){this.el&&this.props.aspectRatio&&this.setState({availableWidth:this.el.offsetWidth})}}class Ra extends ki{constructor(e){super(e),this.handleSegClick=(e,t)=>{let{component:n}=this,{context:r}=n,i=oi(t);if(i&&n.isValidSegDownEl(e.target)){let s=Oe(e.target,".fc-event-forced-url"),o=s?s.querySelector("a[href]").href:"";r.emitter.trigger("eventClick",{el:t,event:new ei(n.context,i.eventRange.def,i.eventRange.instance),jsEvent:e,view:r.viewApi}),o&&!e.defaultPrevented&&(window.location.href=o)}},this.destroy=Fe(e.el,"click",".fc-event",this.handleSegClick)}}class xa extends ki{constructor(e){super(e),this.handleEventElRemove=e=>{e===this.currentSegEl&&this.handleSegLeave(null,this.currentSegEl)},this.handleSegEnter=(e,t)=>{oi(t)&&(this.currentSegEl=t,this.triggerEvent("eventMouseEnter",e,t))},this.handleSegLeave=(e,t)=>{this.currentSegEl&&(this.currentSegEl=null,this.triggerEvent("eventMouseLeave",e,t))},this.removeHoverListeners=function(e,t,n,r){let i;return Fe(e,"mouseover",t,(e,t)=>{if(t!==i){i=t,n(e,t);let s=e=>{i=null,r(e,t),t.removeEventListener("mouseleave",s)};t.addEventListener("mouseleave",s)}})}(e.el,".fc-event",this.handleSegEnter,this.handleSegLeave)}destroy(){this.removeHoverListeners()}triggerEvent(e,t,n){let{component:r}=this,{context:i}=r,s=oi(n);t&&!r.isValidSegDownEl(t.target)||i.emitter.trigger(e,{el:n,event:new ei(i,s.eventRange.def,s.eventRange.instance),jsEvent:t,view:i.viewApi})}}class _a extends Vn{constructor(){super(...arguments),this.buildViewContext=Gt(Fn),this.buildViewPropTransformers=Gt(ka),this.buildToolbarProps=Gt(Ta),this.headerRef={current:null},this.footerRef={current:null},this.interactionsStore={},this.state={viewLabelId:Le()},this.registerInteractiveComponent=(e,t)=>{let n=function(e,t){return{component:e,el:t.el,useEventCenter:null==t.useEventCenter||t.useEventCenter,isHitComboAllowed:t.isHitComboAllowed||null}}(e,t),r=[Ra,xa].concat(this.props.pluginHooks.componentInteractions).map(e=>new e(n));this.interactionsStore[e.uid]=r,Ii[e.uid]=n},this.unregisterInteractiveComponent=e=>{let t=this.interactionsStore[e.uid];if(t){for(let e of t)e.destroy();delete this.interactionsStore[e.uid]}delete Ii[e.uid]},this.resizeRunner=new Me(()=>{this.props.emitter.trigger("_resize",!0),this.props.emitter.trigger("windowResize",{view:this.props.viewApi})}),this.handleWindowResize=e=>{let{options:t}=this.props;t.handleWindowResize&&e.target===window&&this.resizeRunner.request(t.windowResizeDelay)}}render(){let e,{props:t}=this,{toolbarConfig:n,options:r}=t,i=!1,s="";t.isHeightAuto||t.forPrint?s="":null!=r.height?i=!0:null!=r.contentHeight?s=r.contentHeight:e=Math.max(r.aspectRatio,.5);let o=this.buildViewContext(t.viewSpec,t.viewApi,t.options,t.dateProfileGenerator,t.dateEnv,t.nowManager,t.theme,t.pluginHooks,t.dispatch,t.getCurrentData,t.emitter,t.calendarApi,this.registerInteractiveComponent,this.unregisterInteractiveComponent),a=n.header&&n.header.hasTitle?this.state.viewLabelId:void 0;return p(Wn.Provider,{value:o},p(Oi,{unit:"day"},r=>{let o=this.buildToolbarProps(t.viewSpec,t.dateProfile,t.dateProfileGenerator,t.currentDate,r,t.viewTitle);return p(y,null,n.header&&p(wa,Object.assign({ref:this.headerRef,extraClassName:"fc-header-toolbar",model:n.header,titleId:a},o)),p(Ca,{liquid:i,height:s,aspectRatio:e,labeledById:a},this.renderView(t),this.buildAppendContent()),n.footer&&p(wa,Object.assign({ref:this.footerRef,extraClassName:"fc-footer-toolbar",model:n.footer,titleId:""},o)))}))}componentDidMount(){let{props:e}=this;this.calendarInteractions=e.pluginHooks.calendarInteractions.map(t=>new t(e)),window.addEventListener("resize",this.handleWindowResize);let{propSetHandlers:t}=e.pluginHooks;for(let n in t)t[n](e[n],e)}componentDidUpdate(e){let{props:t}=this,{propSetHandlers:n}=t.pluginHooks;for(let r in n)t[r]!==e[r]&&n[r](t[r],t)}componentWillUnmount(){window.removeEventListener("resize",this.handleWindowResize),this.resizeRunner.clear();for(let e of this.calendarInteractions)e.destroy();this.props.emitter.trigger("_unmount")}buildAppendContent(){let{props:e}=this;return p(y,{},...e.pluginHooks.viewContainerAppends.map(t=>t(e)))}renderView(e){let{pluginHooks:t}=e,{viewSpec:n}=e,r={dateProfile:e.dateProfile,businessHours:e.businessHours,eventStore:e.renderableEventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,isHeightAuto:e.isHeightAuto,forPrint:e.forPrint},i=this.buildViewPropTransformers(t.viewPropsTransformers);for(let t of i)Object.assign(r,t.transform(r,e));return p(n.component,Object.assign({},r))}}function Ta(e,t,n,r,i,s){let o=n.build(i,void 0,!1),a=n.buildPrev(t,r,!1),l=n.buildNext(t,r,!1);return{title:s,activeButton:e.type,navUnit:e.singleUnit,isTodayEnabled:o.isValid&&!lr(t.currentRange,i),isPrevEnabled:a.isValid,isNextEnabled:l.isValid}}function ka(e){return e.map(e=>new e)}function Ma(e){let t=Io(e.locale||"en",Mo([]).map);return new Hn(Object.assign(Object.assign({timeZone:cn.timeZone,calendarSystem:"gregory"},e),{locale:t}))}ys.touchMouseIgnoreWait=500;let Ia=0,Oa=0,Na=!1;class Pa{constructor(e){this.subjectEl=null,this.selector="",this.handleSelector="",this.shouldIgnoreMove=!1,this.shouldWatchScroll=!0,this.isDragging=!1,this.isTouchDragging=!1,this.wasTouchScroll=!1,this.handleMouseDown=e=>{if(!this.shouldIgnoreMouse()&&function(e){return 0===e.button&&!e.ctrlKey}(e)&&this.tryStart(e)){let t=this.createEventFromMouse(e,!0);this.emitter.trigger("pointerdown",t),this.initScrollWatch(t),this.shouldIgnoreMove||document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}},this.handleMouseMove=e=>{let t=this.createEventFromMouse(e);this.recordCoords(t),this.emitter.trigger("pointermove",t)},this.handleMouseUp=e=>{document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),this.emitter.trigger("pointerup",this.createEventFromMouse(e)),this.cleanup()},this.handleTouchStart=e=>{if(this.tryStart(e)){this.isTouchDragging=!0;let t=this.createEventFromTouch(e,!0);this.emitter.trigger("pointerdown",t),this.initScrollWatch(t);let n=e.target;this.shouldIgnoreMove||n.addEventListener("touchmove",this.handleTouchMove),n.addEventListener("touchend",this.handleTouchEnd),n.addEventListener("touchcancel",this.handleTouchEnd),window.addEventListener("scroll",this.handleTouchScroll,!0)}},this.handleTouchMove=e=>{let t=this.createEventFromTouch(e);this.recordCoords(t),this.emitter.trigger("pointermove",t)},this.handleTouchEnd=e=>{if(this.isDragging){let t=e.target;t.removeEventListener("touchmove",this.handleTouchMove),t.removeEventListener("touchend",this.handleTouchEnd),t.removeEventListener("touchcancel",this.handleTouchEnd),window.removeEventListener("scroll",this.handleTouchScroll,!0),this.emitter.trigger("pointerup",this.createEventFromTouch(e)),this.cleanup(),this.isTouchDragging=!1,Ia+=1,setTimeout(()=>{Ia-=1},ys.touchMouseIgnoreWait)}},this.handleTouchScroll=()=>{this.wasTouchScroll=!0},this.handleScroll=e=>{if(!this.shouldIgnoreMove){let t=window.scrollX-this.prevScrollX+this.prevPageX,n=window.scrollY-this.prevScrollY+this.prevPageY;this.emitter.trigger("pointermove",{origEvent:e,isTouch:this.isTouchDragging,subjectEl:this.subjectEl,pageX:t,pageY:n,deltaX:t-this.origPageX,deltaY:n-this.origPageY})}},this.containerEl=e,this.emitter=new Vr,e.addEventListener("mousedown",this.handleMouseDown),e.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),Oa+=1,1===Oa&&window.addEventListener("touchmove",Ha,{passive:!1})}destroy(){this.containerEl.removeEventListener("mousedown",this.handleMouseDown),this.containerEl.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),Oa-=1,Oa||window.removeEventListener("touchmove",Ha,{passive:!1})}tryStart(e){let t=this.querySubjectEl(e),n=e.target;return!(!t||this.handleSelector&&!Oe(n,this.handleSelector))&&(this.subjectEl=t,this.isDragging=!0,this.wasTouchScroll=!1,!0)}cleanup(){Na=!1,this.isDragging=!1,this.subjectEl=null,this.destroyScrollWatch()}querySubjectEl(e){return this.selector?Oe(e.target,this.selector):this.containerEl}shouldIgnoreMouse(){return Ia||this.isTouchDragging}cancelTouchScroll(){this.isDragging&&(Na=!0)}initScrollWatch(e){this.shouldWatchScroll&&(this.recordCoords(e),window.addEventListener("scroll",this.handleScroll,!0))}recordCoords(e){this.shouldWatchScroll&&(this.prevPageX=e.pageX,this.prevPageY=e.pageY,this.prevScrollX=window.scrollX,this.prevScrollY=window.scrollY)}destroyScrollWatch(){this.shouldWatchScroll&&window.removeEventListener("scroll",this.handleScroll,!0)}createEventFromMouse(e,t){let n=0,r=0;return t?(this.origPageX=e.pageX,this.origPageY=e.pageY):(n=e.pageX-this.origPageX,r=e.pageY-this.origPageY),{origEvent:e,isTouch:!1,subjectEl:this.subjectEl,pageX:e.pageX,pageY:e.pageY,deltaX:n,deltaY:r}}createEventFromTouch(e,t){let n,r,i=e.touches,s=0,o=0;return i&&i.length?(n=i[0].pageX,r=i[0].pageY):(n=e.pageX,r=e.pageY),t?(this.origPageX=n,this.origPageY=r):(s=n-this.origPageX,o=r-this.origPageY),{origEvent:e,isTouch:!0,subjectEl:this.subjectEl,pageX:n,pageY:r,deltaX:s,deltaY:o}}}function Ha(e){Na&&e.preventDefault()}class Ba{constructor(){this.isVisible=!1,this.sourceEl=null,this.mirrorEl=null,this.sourceElRect=null,this.parentNode=document.body,this.zIndex=9999,this.revertDuration=0}start(e,t,n){this.sourceEl=e,this.sourceElRect=this.sourceEl.getBoundingClientRect(),this.origScreenX=t-window.scrollX,this.origScreenY=n-window.scrollY,this.deltaX=0,this.deltaY=0,this.updateElPosition()}handleMove(e,t){this.deltaX=e-window.scrollX-this.origScreenX,this.deltaY=t-window.scrollY-this.origScreenY,this.updateElPosition()}setIsVisible(e){e?this.isVisible||(this.mirrorEl&&(this.mirrorEl.style.display=""),this.isVisible=e,this.updateElPosition()):this.isVisible&&(this.mirrorEl&&(this.mirrorEl.style.display="none"),this.isVisible=e)}stop(e,t){let n=()=>{this.cleanup(),t()};e&&this.mirrorEl&&this.isVisible&&this.revertDuration&&(this.deltaX||this.deltaY)?this.doRevertAnimation(n,this.revertDuration):setTimeout(n,0)}doRevertAnimation(e,t){let n=this.mirrorEl,r=this.sourceEl.getBoundingClientRect();n.style.transition="top "+t+"ms,left "+t+"ms",Be(n,{left:r.left,top:r.top}),Ge(n,()=>{n.style.transition="",e()})}cleanup(){this.mirrorEl&&(Ie(this.mirrorEl),this.mirrorEl=null),this.sourceEl=null}updateElPosition(){this.sourceEl&&this.isVisible&&Be(this.getMirrorEl(),{left:this.sourceElRect.left+this.deltaX,top:this.sourceElRect.top+this.deltaY})}getMirrorEl(){let e=this.sourceElRect,t=this.mirrorEl;return t||(t=this.mirrorEl=this.sourceEl.cloneNode(!0),t.style.userSelect="none",t.style.webkitUserSelect="none",t.style.pointerEvents="none",t.classList.add("fc-event-dragging"),Be(t,{position:"fixed",zIndex:this.zIndex,visibility:"",boxSizing:"border-box",width:e.right-e.left,height:e.bottom-e.top,right:"auto",bottom:"auto",margin:0}),this.parentNode.appendChild(t)),t}}class ja extends os{constructor(e,t){super(),this.handleScroll=()=>{this.scrollTop=this.scrollController.getScrollTop(),this.scrollLeft=this.scrollController.getScrollLeft(),this.handleScrollChange()},this.scrollController=e,this.doesListening=t,this.scrollTop=this.origScrollTop=e.getScrollTop(),this.scrollLeft=this.origScrollLeft=e.getScrollLeft(),this.scrollWidth=e.getScrollWidth(),this.scrollHeight=e.getScrollHeight(),this.clientWidth=e.getClientWidth(),this.clientHeight=e.getClientHeight(),this.clientRect=this.computeClientRect(),this.doesListening&&this.getEventTarget().addEventListener("scroll",this.handleScroll)}destroy(){this.doesListening&&this.getEventTarget().removeEventListener("scroll",this.handleScroll)}getScrollTop(){return this.scrollTop}getScrollLeft(){return this.scrollLeft}setScrollTop(e){this.scrollController.setScrollTop(e),this.doesListening||(this.scrollTop=Math.max(Math.min(e,this.getMaxScrollTop()),0),this.handleScrollChange())}setScrollLeft(e){this.scrollController.setScrollLeft(e),this.doesListening||(this.scrollLeft=Math.max(Math.min(e,this.getMaxScrollLeft()),0),this.handleScrollChange())}getClientWidth(){return this.clientWidth}getClientHeight(){return this.clientHeight}getScrollWidth(){return this.scrollWidth}getScrollHeight(){return this.scrollHeight}handleScrollChange(){}}class za extends ja{constructor(e,t){super(new as(e),t)}getEventTarget(){return this.scrollController.el}computeClientRect(){return ts(this.scrollController.el)}}class Ua extends ja{constructor(e){super(new ls,e)}getEventTarget(){return window}computeClientRect(){return{left:this.scrollLeft,right:this.scrollLeft+this.clientWidth,top:this.scrollTop,bottom:this.scrollTop+this.clientHeight}}handleScrollChange(){this.clientRect=this.computeClientRect()}}const La="function"==typeof performance?performance.now:Date.now;class Wa{constructor(){this.isEnabled=!0,this.scrollQuery=[window,".fc-scroller"],this.edgeThreshold=50,this.maxVelocity=300,this.pointerScreenX=null,this.pointerScreenY=null,this.isAnimating=!1,this.scrollCaches=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.animate=()=>{if(this.isAnimating){let e=this.computeBestEdge(this.pointerScreenX+window.scrollX,this.pointerScreenY+window.scrollY);if(e){let t=La();this.handleSide(e,(t-this.msSinceRequest)/1e3),this.requestAnimation(t)}else this.isAnimating=!1}}}start(e,t,n){this.isEnabled&&(this.scrollCaches=this.buildCaches(n),this.pointerScreenX=null,this.pointerScreenY=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.handleMove(e,t))}handleMove(e,t){if(this.isEnabled){let n=e-window.scrollX,r=t-window.scrollY,i=null===this.pointerScreenY?0:r-this.pointerScreenY,s=null===this.pointerScreenX?0:n-this.pointerScreenX;i<0?this.everMovedUp=!0:i>0&&(this.everMovedDown=!0),s<0?this.everMovedLeft=!0:s>0&&(this.everMovedRight=!0),this.pointerScreenX=n,this.pointerScreenY=r,this.isAnimating||(this.isAnimating=!0,this.requestAnimation(La()))}}stop(){if(this.isEnabled){this.isAnimating=!1;for(let e of this.scrollCaches)e.destroy();this.scrollCaches=null}}requestAnimation(e){this.msSinceRequest=e,requestAnimationFrame(this.animate)}handleSide(e,t){let{scrollCache:n}=e,{edgeThreshold:r}=this,i=r-e.distance,s=i*i/(r*r)*this.maxVelocity*t,o=1;switch(e.name){case"left":o=-1;case"right":n.setScrollLeft(n.getScrollLeft()+s*o);break;case"top":o=-1;case"bottom":n.setScrollTop(n.getScrollTop()+s*o)}}computeBestEdge(e,t){let{edgeThreshold:n}=this,r=null,i=this.scrollCaches||[];for(let s of i){let i=s.clientRect,o=e-i.left,a=i.right-e,l=t-i.top,c=i.bottom-t;o>=0&&a>=0&&l>=0&&c>=0&&(l<=n&&this.everMovedUp&&s.canScrollUp()&&(!r||r.distance>l)&&(r={scrollCache:s,name:"top",distance:l}),c<=n&&this.everMovedDown&&s.canScrollDown()&&(!r||r.distance>c)&&(r={scrollCache:s,name:"bottom",distance:c}),o<=n&&this.everMovedLeft&&s.canScrollLeft()&&(!r||r.distance>o)&&(r={scrollCache:s,name:"left",distance:o}),a<=n&&this.everMovedRight&&s.canScrollRight()&&(!r||r.distance>a)&&(r={scrollCache:s,name:"right",distance:a}))}return r}buildCaches(e){return this.queryScrollEls(e).map(e=>e===window?new Ua(!1):new za(e,!1))}queryScrollEls(e){let t=[];for(let n of this.scrollQuery)"object"==typeof n?t.push(n):t.push(...Array.prototype.slice.call(e.getRootNode().querySelectorAll(n)));return t}}class Fa extends vs{constructor(e,t){super(e),this.containerEl=e,this.delay=null,this.minDistance=0,this.touchScrollAllowed=!0,this.mirrorNeedsRevert=!1,this.isInteracting=!1,this.isDragging=!1,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.delayTimeoutId=null,this.onPointerDown=e=>{this.isDragging||(this.isInteracting=!0,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,Je(document.body),et(document.body),e.isTouch||e.origEvent.preventDefault(),this.emitter.trigger("pointerdown",e),this.isInteracting&&!this.pointer.shouldIgnoreMove&&(this.mirror.setIsVisible(!1),this.mirror.start(e.subjectEl,e.pageX,e.pageY),this.startDelay(e),this.minDistance||this.handleDistanceSurpassed(e)))},this.onPointerMove=e=>{if(this.isInteracting){if(this.emitter.trigger("pointermove",e),!this.isDistanceSurpassed){let t,n=this.minDistance,{deltaX:r,deltaY:i}=e;t=r*r+i*i,t>=n*n&&this.handleDistanceSurpassed(e)}this.isDragging&&("scroll"!==e.origEvent.type&&(this.mirror.handleMove(e.pageX,e.pageY),this.autoScroller.handleMove(e.pageX,e.pageY)),this.emitter.trigger("dragmove",e))}},this.onPointerUp=e=>{this.isInteracting&&(this.isInteracting=!1,Ke(document.body),tt(document.body),this.emitter.trigger("pointerup",e),this.isDragging&&(this.autoScroller.stop(),this.tryStopDrag(e)),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null))};let n=this.pointer=new Pa(e);n.emitter.on("pointerdown",this.onPointerDown),n.emitter.on("pointermove",this.onPointerMove),n.emitter.on("pointerup",this.onPointerUp),t&&(n.selector=t),this.mirror=new Ba,this.autoScroller=new Wa}destroy(){this.pointer.destroy(),this.onPointerUp({})}startDelay(e){"number"==typeof this.delay?this.delayTimeoutId=setTimeout(()=>{this.delayTimeoutId=null,this.handleDelayEnd(e)},this.delay):this.handleDelayEnd(e)}handleDelayEnd(e){this.isDelayEnded=!0,this.tryStartDrag(e)}handleDistanceSurpassed(e){this.isDistanceSurpassed=!0,this.tryStartDrag(e)}tryStartDrag(e){this.isDelayEnded&&this.isDistanceSurpassed&&(this.pointer.wasTouchScroll&&!this.touchScrollAllowed||(this.isDragging=!0,this.mirrorNeedsRevert=!1,this.autoScroller.start(e.pageX,e.pageY,this.containerEl),this.emitter.trigger("dragstart",e),!1===this.touchScrollAllowed&&this.pointer.cancelTouchScroll()))}tryStopDrag(e){this.mirror.stop(this.mirrorNeedsRevert,this.stopDrag.bind(this,e))}stopDrag(e){this.isDragging=!1,this.emitter.trigger("dragend",e)}setIgnoreMove(e){this.pointer.shouldIgnoreMove=e}setMirrorIsVisible(e){this.mirror.setIsVisible(e)}setMirrorNeedsRevert(e){this.mirrorNeedsRevert=e}setAutoScrollEnabled(e){this.autoScroller.isEnabled=e}}class Va{constructor(e){this.el=e,this.origRect=ns(e),this.scrollCaches=rs(e).map(e=>new za(e,!0))}destroy(){for(let e of this.scrollCaches)e.destroy()}computeLeft(){let e=this.origRect.left;for(let t of this.scrollCaches)e+=t.origScrollLeft-t.getScrollLeft();return e}computeTop(){let e=this.origRect.top;for(let t of this.scrollCaches)e+=t.origScrollTop-t.getScrollTop();return e}isWithinClipping(e,t){let n={left:e,top:t};for(let e of this.scrollCaches)if(!Ga(e.getEventTarget())&&!Hi(n,e.clientRect))return!1;return!0}}function Ga(e){let t=e.tagName;return"HTML"===t||"BODY"===t}class Qa{constructor(e,t){this.useSubjectCenter=!1,this.requireInitial=!0,this.disablePointCheck=!1,this.initialHit=null,this.movingHit=null,this.finalHit=null,this.handlePointerDown=e=>{let{dragging:t}=this;this.initialHit=null,this.movingHit=null,this.finalHit=null,this.prepareHits(),this.processFirstCoord(e),this.initialHit||!this.requireInitial?(t.setIgnoreMove(!1),this.emitter.trigger("pointerdown",e)):t.setIgnoreMove(!0)},this.handleDragStart=e=>{this.emitter.trigger("dragstart",e),this.handleMove(e,!0)},this.handleDragMove=e=>{this.emitter.trigger("dragmove",e),this.handleMove(e)},this.handlePointerUp=e=>{this.releaseHits(),this.emitter.trigger("pointerup",e)},this.handleDragEnd=e=>{this.movingHit&&this.emitter.trigger("hitupdate",null,!0,e),this.finalHit=this.movingHit,this.movingHit=null,this.emitter.trigger("dragend",e)},this.droppableStore=t,e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("dragstart",this.handleDragStart),e.emitter.on("dragmove",this.handleDragMove),e.emitter.on("pointerup",this.handlePointerUp),e.emitter.on("dragend",this.handleDragEnd),this.dragging=e,this.emitter=new Vr}processFirstCoord(e){let t,n={left:e.pageX,top:e.pageY},r=n,i=e.subjectEl;i instanceof HTMLElement&&(t=ns(i),r=ji(r,t));let s=this.initialHit=this.queryHitForOffset(r.left,r.top);if(s){if(this.useSubjectCenter&&t){let e=Bi(t,s.rect);e&&(r=zi(e))}this.coordAdjust=Ui(r,n)}else this.coordAdjust={left:0,top:0}}handleMove(e,t){let n=this.queryHitForOffset(e.pageX+this.coordAdjust.left,e.pageY+this.coordAdjust.top);!t&&qa(this.movingHit,n)||(this.movingHit=n,this.emitter.trigger("hitupdate",n,!1,e))}prepareHits(){this.offsetTrackers=Dn(this.droppableStore,e=>(e.component.prepareHits(),new Va(e.el)))}releaseHits(){let{offsetTrackers:e}=this;for(let t in e)e[t].destroy();this.offsetTrackers={}}queryHitForOffset(e,t){let{droppableStore:n,offsetTrackers:r}=this,i=null;for(let s in n){let o=n[s].component,a=r[s];if(a&&a.isWithinClipping(e,t)){let n=a.computeLeft(),r=a.computeTop(),l=e-n,c=t-r,{origRect:d}=a,u=d.right-d.left,h=d.bottom-d.top;if(l>=0&&l<u&&c>=0&&c<h){let e=o.queryHit(l,c,u,h);e&&ar(e.dateProfile.activeRange,e.dateSpan.range)&&(this.disablePointCheck||a.el.contains(a.el.getRootNode().elementFromPoint(l+n-window.scrollX,c+r-window.scrollY)))&&(!i||e.layer>i.layer)&&(e.componentId=s,e.context=o.context,e.rect.left+=n,e.rect.right+=n,e.rect.top+=r,e.rect.bottom+=r,i=e)}}}return i}}function qa(e,t){return!e&&!t||Boolean(e)===Boolean(t)&&Si(e.dateSpan,t.dateSpan)}function Ya(e,t){let n={};for(let r of t.pluginHooks.datePointTransforms)Object.assign(n,r(e,t));var r,i;return Object.assign(n,(r=e,{date:(i=t.dateEnv).toDate(r.range.start),dateStr:i.formatIso(r.range.start,{omitTime:r.allDay}),allDay:r.allDay})),n}class Za extends ki{constructor(e){super(e),this.subjectEl=null,this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=e=>{let t=e.origEvent.target,{component:n,dragging:r}=this,{mirror:i}=r,{options:s}=n.context,o=n.context;this.subjectEl=e.subjectEl;let a=this.subjectSeg=oi(e.subjectEl),l=(this.eventRange=a.eventRange).instance.instanceId;this.relevantEvents=Rr(o.getCurrentData().eventStore,l),r.minDistance=e.isTouch?0:s.eventDragMinDistance,r.delay=e.isTouch&&l!==n.props.eventSelection?function(e){let{options:t}=e.context,n=t.eventLongPressDelay;null==n&&(n=t.longPressDelay);return n}(n):null,s.fixedMirrorParent?i.parentNode=s.fixedMirrorParent:i.parentNode=Oe(t,".fc"),i.revertDuration=s.dragRevertDuration;let c=n.isValidSegDownEl(t)&&!Oe(t,".fc-event-resizer");r.setIgnoreMove(!c),this.isDragging=c&&e.subjectEl.classList.contains("fc-event-draggable")},this.handleDragStart=e=>{let t=this.component.context,n=this.eventRange,r=n.instance.instanceId;e.isTouch?r!==this.component.props.eventSelection&&t.dispatch({type:"SELECT_EVENT",eventInstanceId:r}):t.dispatch({type:"UNSELECT_EVENT"}),this.isDragging&&(t.calendarApi.unselect(e),t.emitter.trigger("eventDragStart",{el:this.subjectEl,event:new ei(t,n.def,n.instance),jsEvent:e.origEvent,view:t.viewApi}))},this.handleHitUpdate=(e,t)=>{if(!this.isDragging)return;let n=this.relevantEvents,r=this.hitDragging.initialHit,i=this.component.context,s=null,o=null,a=null,l=!1,c={affectedEvents:n,mutatedEvents:{defs:{},instances:{}},isEvent:!0};if(e){s=e.context;let t=s.options;i===s||t.editable&&t.droppable?(o=function(e,t,n,r){let i=e.dateSpan,s=t.dateSpan,o=i.range.start,a=s.range.start,l={};i.allDay!==s.allDay&&(l.allDay=s.allDay,l.hasEnd=t.context.options.allDayMaintainDuration,o=s.allDay?Mt(n):n);let c=hr(o,a,e.context.dateEnv,e.componentId===t.componentId?e.largeUnit:null);c.milliseconds&&(l.allDay=!1);let d={datesDelta:c,standardProps:l};for(let n of r)n(d,e,t);return d}(r,e,this.eventRange.instance.range.start,s.getCurrentData().pluginHooks.eventDragMutationMassagers),o&&(a=Xr(n,s.getCurrentData().eventUiBases,o,s),c.mutatedEvents=a,Os(c,e.dateProfile,s)||(l=!0,o=null,a=null,c.mutatedEvents={defs:{},instances:{}}))):s=null}this.displayDrag(s,c),l?Xe():$e(),t||(i===s&&qa(r,e)&&(o=null),this.dragging.setMirrorNeedsRevert(!o),this.dragging.setMirrorIsVisible(!e||!this.subjectEl.getRootNode().querySelector(".fc-event-mirror")),this.receivingContext=s,this.validMutation=o,this.mutatedRelevantEvents=a)},this.handlePointerUp=()=>{this.isDragging||this.cleanup()},this.handleDragEnd=e=>{if(this.isDragging){let t=this.component.context,n=t.viewApi,{receivingContext:r,validMutation:i}=this,s=this.eventRange.def,o=this.eventRange.instance,a=new ei(t,s,o),l=this.relevantEvents,c=this.mutatedRelevantEvents,{finalHit:d}=this.hitDragging;if(this.clearDrag(),t.emitter.trigger("eventDragStop",{el:this.subjectEl,event:a,jsEvent:e.origEvent,view:n}),i){if(r===t){let r=new ei(t,c.defs[s.defId],o?c.instances[o.instanceId]:null);t.dispatch({type:"MERGE_EVENTS",eventStore:c});let d={oldEvent:a,event:r,relatedEvents:ni(c,t,o),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:l})}},u={};for(let e of t.getCurrentData().pluginHooks.eventDropTransformers)Object.assign(u,e(i,t));t.emitter.trigger("eventDrop",Object.assign(Object.assign(Object.assign({},d),u),{el:e.subjectEl,delta:i.datesDelta,jsEvent:e.origEvent,view:n})),t.emitter.trigger("eventChange",d)}else if(r){let i={event:a,relatedEvents:ni(l,t,o),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:l})}};t.emitter.trigger("eventLeave",Object.assign(Object.assign({},i),{draggedEl:e.subjectEl,view:n})),t.dispatch({type:"REMOVE_EVENTS",eventStore:l}),t.emitter.trigger("eventRemove",i);let u=c.defs[s.defId],h=c.instances[o.instanceId],f=new ei(r,u,h);r.dispatch({type:"MERGE_EVENTS",eventStore:c});let g={event:f,relatedEvents:ni(c,r,h),revert(){r.dispatch({type:"REMOVE_EVENTS",eventStore:c})}};r.emitter.trigger("eventAdd",g),e.isTouch&&r.dispatch({type:"SELECT_EVENT",eventInstanceId:o.instanceId}),r.emitter.trigger("drop",Object.assign(Object.assign({},Ya(d.dateSpan,r)),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:d.context.viewApi})),r.emitter.trigger("eventReceive",Object.assign(Object.assign({},g),{draggedEl:e.subjectEl,view:d.context.viewApi}))}}else t.emitter.trigger("_noEventDrop")}this.cleanup()};let{component:t}=this,{options:n}=t.context,r=this.dragging=new Fa(e.el);r.pointer.selector=Za.SELECTOR,r.touchScrollAllowed=!1,r.autoScroller.isEnabled=n.dragScroll;let i=this.hitDragging=new Qa(this.dragging,Ii);i.useSubjectCenter=e.useEventCenter,i.emitter.on("pointerdown",this.handlePointerDown),i.emitter.on("dragstart",this.handleDragStart),i.emitter.on("hitupdate",this.handleHitUpdate),i.emitter.on("pointerup",this.handlePointerUp),i.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}displayDrag(e,t){let n=this.component.context,r=this.receivingContext;r&&r!==e&&(r===n?r.dispatch({type:"SET_EVENT_DRAG",state:{affectedEvents:t.affectedEvents,mutatedEvents:{defs:{},instances:{}},isEvent:!0}}):r.dispatch({type:"UNSET_EVENT_DRAG"})),e&&e.dispatch({type:"SET_EVENT_DRAG",state:t})}clearDrag(){let e=this.component.context,{receivingContext:t}=this;t&&t.dispatch({type:"UNSET_EVENT_DRAG"}),e!==t&&e.dispatch({type:"UNSET_EVENT_DRAG"})}cleanup(){this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null}}Za.SELECTOR=".fc-event-draggable, .fc-event-resizable";const Xa={fixedMirrorParent:yn},$a={dateClick:yn,eventDragStart:yn,eventDragStop:yn,eventDrop:yn,eventResizeStart:yn,eventResizeStop:yn,eventResize:yn,drop:yn,eventReceive:yn,eventLeave:yn};class Ja{constructor(e,t){this.receivingContext=null,this.droppableEvent=null,this.suppliedDragMeta=null,this.dragMeta=null,this.handleDragStart=e=>{this.dragMeta=this.buildDragMeta(e.subjectEl)},this.handleHitUpdate=(e,t,n)=>{let{dragging:r}=this.hitDragging,i=null,s=null,o=!1,a={affectedEvents:{defs:{},instances:{}},mutatedEvents:{defs:{},instances:{}},isEvent:this.dragMeta.create};e&&(i=e.context,this.canDropElOnCalendar(n.subjectEl,i)&&(s=function(e,t,n){let r=Object.assign({},t.leftoverProps);for(let i of n.pluginHooks.externalDefTransforms)Object.assign(r,i(e,t));let{refined:i,extra:s}=Sr(r,n),o=Ar(i,s,t.sourceId,e.allDay,n.options.forceEventDuration||Boolean(t.duration),n),a=e.range.start;e.allDay&&t.startTime&&(a=n.dateEnv.add(a,t.startTime));let l=t.duration?n.dateEnv.add(a,t.duration):Zr(e.allDay,a,n),c=gr(o.defId,{start:a,end:l});return{def:o,instance:c}}(e.dateSpan,this.dragMeta,i),a.mutatedEvents=Cr(s),o=!Os(a,e.dateProfile,i),o&&(a.mutatedEvents={defs:{},instances:{}},s=null))),this.displayDrag(i,a),r.setMirrorIsVisible(t||!s||!document.querySelector(".fc-event-mirror")),o?Xe():$e(),t||(r.setMirrorNeedsRevert(!s),this.receivingContext=i,this.droppableEvent=s)},this.handleDragEnd=e=>{let{receivingContext:t,droppableEvent:n}=this;if(this.clearDrag(),t&&n){let r=this.hitDragging.finalHit,i=r.context.viewApi,s=this.dragMeta;if(t.emitter.trigger("drop",Object.assign(Object.assign({},Ya(r.dateSpan,t)),{draggedEl:e.subjectEl,jsEvent:e.origEvent,view:i})),s.create){let r=Cr(n);t.dispatch({type:"MERGE_EVENTS",eventStore:r}),e.isTouch&&t.dispatch({type:"SELECT_EVENT",eventInstanceId:n.instance.instanceId}),t.emitter.trigger("eventReceive",{event:new ei(t,n.def,n.instance),relatedEvents:[],revert(){t.dispatch({type:"REMOVE_EVENTS",eventStore:r})},draggedEl:e.subjectEl,view:i})}}this.receivingContext=null,this.droppableEvent=null};let n=this.hitDragging=new Qa(e,Ii);n.requireInitial=!1,n.emitter.on("dragstart",this.handleDragStart),n.emitter.on("hitupdate",this.handleHitUpdate),n.emitter.on("dragend",this.handleDragEnd),this.suppliedDragMeta=t}buildDragMeta(e){return"object"==typeof this.suppliedDragMeta?Es(this.suppliedDragMeta):"function"==typeof this.suppliedDragMeta?Es(this.suppliedDragMeta(e)):function(e){let t=function(e,t){let n=ys.dataAttrPrefix,r=(n?n+"-":"")+t;return e.getAttribute("data-"+r)||""}(e,"event");return Es(t?JSON.parse(t):{create:!1})}(e)}displayDrag(e,t){let n=this.receivingContext;n&&n!==e&&n.dispatch({type:"UNSET_EVENT_DRAG"}),e&&e.dispatch({type:"SET_EVENT_DRAG",state:t})}clearDrag(){this.receivingContext&&this.receivingContext.dispatch({type:"UNSET_EVENT_DRAG"})}canDropElOnCalendar(e,t){let n=t.options.dropAccept;return"function"==typeof n?n.call(t.calendarApi,e):"string"!=typeof n||!n||Boolean(Ne(e,n))}}ys.dataAttrPrefix="";class Ka extends vs{constructor(e){super(e),this.shouldIgnoreMove=!1,this.mirrorSelector="",this.currentMirrorEl=null,this.handlePointerDown=e=>{this.emitter.trigger("pointerdown",e),this.shouldIgnoreMove||this.emitter.trigger("dragstart",e)},this.handlePointerMove=e=>{this.shouldIgnoreMove||this.emitter.trigger("dragmove",e)},this.handlePointerUp=e=>{this.emitter.trigger("pointerup",e),this.shouldIgnoreMove||this.emitter.trigger("dragend",e)};let t=this.pointer=new Pa(e);t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("pointermove",this.handlePointerMove),t.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.pointer.destroy()}setIgnoreMove(e){this.shouldIgnoreMove=e}setMirrorIsVisible(e){if(e)this.currentMirrorEl&&(this.currentMirrorEl.style.visibility="",this.currentMirrorEl=null);else{let e=this.mirrorSelector?document.querySelector(this.mirrorSelector):null;e&&(this.currentMirrorEl=e,e.style.visibility="hidden")}}}var el=No({name:"@fullcalendar/interaction",componentInteractions:[class extends ki{constructor(e){super(e),this.handlePointerDown=e=>{let{dragging:t}=this,n=e.origEvent.target;t.setIgnoreMove(!this.component.isValidDateDownEl(n))},this.handleDragEnd=e=>{let{component:t}=this,{pointer:n}=this.dragging;if(!n.wasTouchScroll){let{initialHit:n,finalHit:r}=this.hitDragging;if(n&&r&&qa(n,r)){let{context:r}=t,i=Object.assign(Object.assign({},Ya(n.dateSpan,r)),{dayEl:n.dayEl,jsEvent:e.origEvent,view:r.viewApi||r.calendarApi.view});r.emitter.trigger("dateClick",i)}}},this.dragging=new Fa(e.el),this.dragging.autoScroller.isEnabled=!1;let t=this.hitDragging=new Qa(this.dragging,Mi(e));t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}},class extends ki{constructor(e){super(e),this.dragSelection=null,this.handlePointerDown=e=>{let{component:t,dragging:n}=this,{options:r}=t.context,i=r.selectable&&t.isValidDateDownEl(e.origEvent.target);n.setIgnoreMove(!i),n.delay=e.isTouch?function(e){let{options:t}=e.context,n=t.selectLongPressDelay;null==n&&(n=t.longPressDelay);return n}(t):null},this.handleDragStart=e=>{this.component.context.calendarApi.unselect(e)},this.handleHitUpdate=(e,t)=>{let{context:n}=this.component,r=null,i=!1;if(e){let t=this.hitDragging.initialHit;e.componentId===t.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(t,e)||(r=function(e,t,n){let r=e.dateSpan,i=t.dateSpan,s=[r.range.start,r.range.end,i.range.start,i.range.end];s.sort(lt);let o={};for(let r of n){let n=r(e,t);if(!1===n)return null;n&&Object.assign(o,n)}return o.range={start:s[0],end:s[3]},o.allDay=r.allDay,o}(t,e,n.pluginHooks.dateSelectionTransformers)),r&&Ns(r,e.dateProfile,n)||(i=!0,r=null)}r?n.dispatch({type:"SELECT_DATES",selection:r}):t||n.dispatch({type:"UNSELECT_DATES"}),i?Xe():$e(),t||(this.dragSelection=r)},this.handlePointerUp=e=>{this.dragSelection&&(qr(this.dragSelection,e,this.component.context),this.dragSelection=null)};let{component:t}=e,{options:n}=t.context,r=this.dragging=new Fa(e.el);r.touchScrollAllowed=!1,r.minDistance=n.selectMinDistance||0,r.autoScroller.isEnabled=n.dragScroll;let i=this.hitDragging=new Qa(this.dragging,Mi(e));i.emitter.on("pointerdown",this.handlePointerDown),i.emitter.on("dragstart",this.handleDragStart),i.emitter.on("hitupdate",this.handleHitUpdate),i.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.dragging.destroy()}},Za,class extends ki{constructor(e){super(e),this.draggingSegEl=null,this.draggingSeg=null,this.eventRange=null,this.relevantEvents=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=e=>{let{component:t}=this,n=oi(this.querySegEl(e)),r=this.eventRange=n.eventRange;this.dragging.minDistance=t.context.options.eventDragMinDistance,this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(e.origEvent.target)||e.isTouch&&this.component.props.eventSelection!==r.instance.instanceId)},this.handleDragStart=e=>{let{context:t}=this.component,n=this.eventRange;this.relevantEvents=Rr(t.getCurrentData().eventStore,this.eventRange.instance.instanceId);let r=this.querySegEl(e);this.draggingSegEl=r,this.draggingSeg=oi(r),t.calendarApi.unselect(),t.emitter.trigger("eventResizeStart",{el:r,event:new ei(t,n.def,n.instance),jsEvent:e.origEvent,view:t.viewApi})},this.handleHitUpdate=(e,t,n)=>{let{context:r}=this.component,i=this.relevantEvents,s=this.hitDragging.initialHit,o=this.eventRange.instance,a=null,l=null,c=!1,d={affectedEvents:i,mutatedEvents:{defs:{},instances:{}},isEvent:!0};if(e){e.componentId===s.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(s,e)||(a=function(e,t,n,r){let i=e.context.dateEnv,s=e.dateSpan.range.start,o=t.dateSpan.range.start,a=hr(s,o,i,e.largeUnit);if(n){if(i.add(r.start,a)<r.end)return{startDelta:a}}else if(i.add(r.end,a)>r.start)return{endDelta:a};return null}(s,e,n.subjectEl.classList.contains("fc-event-resizer-start"),o.range))}a&&(l=Xr(i,r.getCurrentData().eventUiBases,a,r),d.mutatedEvents=l,Os(d,e.dateProfile,r)||(c=!0,a=null,l=null,d.mutatedEvents=null)),l?r.dispatch({type:"SET_EVENT_RESIZE",state:d}):r.dispatch({type:"UNSET_EVENT_RESIZE"}),c?Xe():$e(),t||(a&&qa(s,e)&&(a=null),this.validMutation=a,this.mutatedRelevantEvents=l)},this.handleDragEnd=e=>{let{context:t}=this.component,n=this.eventRange.def,r=this.eventRange.instance,i=new ei(t,n,r),s=this.relevantEvents,o=this.mutatedRelevantEvents;if(t.emitter.trigger("eventResizeStop",{el:this.draggingSegEl,event:i,jsEvent:e.origEvent,view:t.viewApi}),this.validMutation){let a=new ei(t,o.defs[n.defId],r?o.instances[r.instanceId]:null);t.dispatch({type:"MERGE_EVENTS",eventStore:o});let l={oldEvent:i,event:a,relatedEvents:ni(o,t,r),revert(){t.dispatch({type:"MERGE_EVENTS",eventStore:s})}};t.emitter.trigger("eventResize",Object.assign(Object.assign({},l),{el:this.draggingSegEl,startDelta:this.validMutation.startDelta||ft(0),endDelta:this.validMutation.endDelta||ft(0),jsEvent:e.origEvent,view:t.viewApi})),t.emitter.trigger("eventChange",l)}else t.emitter.trigger("_noEventResize");this.draggingSeg=null,this.relevantEvents=null,this.validMutation=null};let{component:t}=e,n=this.dragging=new Fa(e.el);n.pointer.selector=".fc-event-resizer",n.touchScrollAllowed=!1,n.autoScroller.isEnabled=t.context.options.dragScroll;let r=this.hitDragging=new Qa(this.dragging,Mi(e));r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}querySegEl(e){return Oe(e.subjectEl,".fc-event")}}],calendarInteractions:[class{constructor(e){this.context=e,this.isRecentPointerDateSelect=!1,this.matchesCancel=!1,this.matchesEvent=!1,this.onSelect=e=>{e.jsEvent&&(this.isRecentPointerDateSelect=!0)},this.onDocumentPointerDown=e=>{let t=this.context.options.unselectCancel,n=ze(e.origEvent);this.matchesCancel=!!Oe(n,t),this.matchesEvent=!!Oe(n,Za.SELECTOR)},this.onDocumentPointerUp=e=>{let{context:t}=this,{documentPointer:n}=this,r=t.getCurrentData();if(!n.wasTouchScroll){if(r.dateSelection&&!this.isRecentPointerDateSelect){let n=t.options.unselectAuto;!n||n&&this.matchesCancel||t.calendarApi.unselect(e)}r.eventSelection&&!this.matchesEvent&&t.dispatch({type:"UNSELECT_EVENT"})}this.isRecentPointerDateSelect=!1};let t=this.documentPointer=new Pa(document);t.shouldIgnoreMove=!0,t.shouldWatchScroll=!1,t.emitter.on("pointerdown",this.onDocumentPointerDown),t.emitter.on("pointerup",this.onDocumentPointerUp),e.emitter.on("select",this.onSelect)}destroy(){this.context.emitter.off("select",this.onSelect),this.documentPointer.destroy()}}],elementDraggingImpl:Fa,optionRefiners:Xa,listenerRefiners:$a});class tl extends cs{constructor(){super(...arguments),this.headerElRef={current:null}}renderSimpleLayout(e,t){let{props:n,context:r}=this,i=[],s=to(r.options);return e&&i.push({type:"header",key:"header",isSticky:s,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),i.push({type:"body",key:"body",liquid:!0,chunk:{content:t}}),p(er,{elClasses:["fc-daygrid"],viewSpec:r.viewSpec},p(ro,{liquid:!n.isHeightAuto&&!n.forPrint,collapsibleWidth:n.forPrint,cols:[],sections:i}))}renderHScrollLayout(e,t,n,r){let i=this.context.pluginHooks.scrollGridImpl;if(!i)throw new Error("No ScrollGrid implementation");let{props:s,context:o}=this,a=!s.forPrint&&to(o.options),l=!s.forPrint&&no(o.options),c=[];return e&&c.push({type:"header",key:"header",isSticky:a,chunks:[{key:"main",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),c.push({type:"body",key:"body",liquid:!0,chunks:[{key:"main",content:t}]}),l&&c.push({type:"footer",key:"footer",isSticky:!0,chunks:[{key:"main",content:eo}]}),p(er,{elClasses:["fc-daygrid"],viewSpec:o.viewSpec},p(i,{liquid:!s.isHeightAuto&&!s.forPrint,forPrint:s.forPrint,collapsibleWidth:s.forPrint,colGroups:[{cols:[{span:n,minWidth:r}]}],sections:c}))}}function nl(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.row].push(t);return n}function rl(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.firstCol].push(t);return n}function il(e,t){let n=[];if(e){for(let r=0;r<t;r+=1)n[r]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)n[t.row].segs.push(t)}else for(let e=0;e<t;e+=1)n[e]=null;return n}const sl=an({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"});function ol(e){let{display:t}=e.eventRange.ui;return"list-item"===t||"auto"===t&&!e.eventRange.def.allDay&&e.firstCol===e.lastCol&&e.isStart&&e.isEnd}class al extends Gn{render(){let{props:e}=this;return p(so,Object.assign({},e,{elClasses:["fc-daygrid-event","fc-daygrid-block-event","fc-h-event"],defaultTimeFormat:sl,defaultDisplayEventEnd:e.defaultDisplayEventEnd,disableResizing:!e.seg.eventRange.def.allDay}))}}class ll extends Gn{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r}=e,i=gi(r,n.eventTimeFormat||sl,t,!0,e.defaultDisplayEventEnd);return p(io,Object.assign({},e,{elTag:"a",elClasses:["fc-daygrid-event","fc-daygrid-dot-event"],elAttrs:yi(e.seg,t),defaultGenerator:cl,timeText:i,isResizing:!1,isDateSelecting:!1}))}}function cl(e){return p(y,null,p("div",{className:"fc-daygrid-event-dot",style:{borderColor:e.borderColor||e.backgroundColor}}),e.timeText&&p("div",{className:"fc-event-time"},e.timeText),p("div",{className:"fc-event-title"},e.event.title||p(y,null," ")))}class dl extends Gn{constructor(){super(...arguments),this.compileSegs=Gt(ul)}render(){let{props:e}=this,{allSegs:t,invisibleSegs:n}=this.compileSegs(e.singlePlacements);return p(Eo,{elClasses:["fc-daygrid-more-link"],dateProfile:e.dateProfile,todayRange:e.todayRange,allDayDate:e.allDayDate,moreCnt:e.moreCnt,allSegs:t,hiddenSegs:n,alignmentElRef:e.alignmentElRef,alignGridTop:e.alignGridTop,extraDateSpan:e.extraDateSpan,popoverContent:()=>{let n=(e.eventDrag?e.eventDrag.affectedInstances:null)||(e.eventResize?e.eventResize.affectedInstances:null)||{};return p(y,null,t.map(t=>{let r=t.eventRange.instance.instanceId;return p("div",{className:"fc-daygrid-event-harness",key:r,style:{visibility:n[r]?"hidden":""}},ol(t)?p(ll,Object.assign({seg:t,isDragging:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},pi(t,e.todayRange))):p(al,Object.assign({seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},pi(t,e.todayRange))))}))}})}}function ul(e){let t=[],n=[];for(let r of e)t.push(r.seg),r.isVisible||n.push(r.seg);return{allSegs:t,invisibleSegs:n}}const hl=an({week:"narrow"});class fl extends cs{constructor(){super(...arguments),this.rootElRef={current:null},this.state={dayNumberId:Le()},this.handleRootEl=e=>{Qn(this.rootElRef,e),Qn(this.props.elRef,e)}}render(){let{context:e,props:t,state:n,rootElRef:r}=this,{options:i,dateEnv:s}=e,{date:o,dateProfile:a}=t;const l=t.showDayNumber&&function(e,t,n){const{start:r,end:i}=t,s=Ct(i,-1),o=n.getYear(r),a=n.getMonth(r),l=n.getYear(s),c=n.getMonth(s);return!(o===l&&a===c)&&Boolean(e.valueOf()===r.valueOf()||1===n.getDay(e)&&e.valueOf()<i.valueOf())}(o,a.currentRange,s);return p(co,{elTag:"td",elRef:this.handleRootEl,elClasses:["fc-daygrid-day",...t.extraClassNames||[]],elAttrs:Object.assign(Object.assign(Object.assign({},t.extraDataAttrs),t.showDayNumber?{"aria-labelledby":n.dayNumberId}:{}),{role:"gridcell"}),defaultGenerator:gl,date:o,dateProfile:a,todayRange:t.todayRange,showDayNumber:t.showDayNumber,isMonthStart:l,extraRenderProps:t.extraRenderProps},(s,a)=>p("div",{ref:t.innerElRef,className:"fc-daygrid-day-frame fc-scrollgrid-sync-inner",style:{minHeight:t.minHeight}},t.showWeekNumber&&p(mo,{elTag:"a",elClasses:["fc-daygrid-week-number"],elAttrs:Yi(e,o,"week"),date:o,defaultFormat:hl}),!a.isDisabled&&(t.showDayNumber||uo(i)||t.forceDayTop)?p("div",{className:"fc-daygrid-day-top"},p(s,{elTag:"a",elClasses:["fc-daygrid-day-number",l&&"fc-daygrid-month-start"],elAttrs:Object.assign(Object.assign({},Yi(e,o)),{id:n.dayNumberId})})):t.showDayNumber?p("div",{className:"fc-daygrid-day-top",style:{visibility:"hidden"}},p("a",{className:"fc-daygrid-day-number"}," ")):void 0,p("div",{className:"fc-daygrid-day-events",ref:t.fgContentElRef},t.fgContent,p("div",{className:"fc-daygrid-day-bottom",style:{marginTop:t.moreMarginTop}},p(dl,{allDayDate:o,singlePlacements:t.singlePlacements,moreCnt:t.moreCnt,alignmentElRef:r,alignGridTop:!t.showDayNumber,extraDateSpan:t.extraDateSpan,dateProfile:t.dateProfile,eventSelection:t.eventSelection,eventDrag:t.eventDrag,eventResize:t.eventResize,todayRange:t.todayRange}))),p("div",{className:"fc-daygrid-day-bg"},t.bgContent)))}}function gl(e){return e.dayNumberText||p(y,null," ")}function pl(e){return e.eventRange.instance.instanceId+":"+e.firstCol}function ml(e){return pl(e)+":"+e.lastCol}function vl(e,t,n,r,i,s,o){let a=new bl(t=>{let n=e[t.index].eventRange.instance.instanceId+":"+t.span.start+":"+(t.span.end-1);return i[n]||1});a.allowReslicing=!0,a.strictOrder=r,!0===t||!0===n?(a.maxCoord=s,a.hiddenConsumes=!0):"number"==typeof t?a.maxStackCnt=t:"number"==typeof n&&(a.maxStackCnt=n,a.hiddenConsumes=!0);let l=[],c=[];for(let t=0;t<e.length;t+=1){let n=e[t],r=ml(n);null!=i[r]?l.push({index:t,span:{start:n.firstCol,end:n.lastCol+1}}):c.push(n)}let d=a.addSegs(l),u=a.toRects(),{singleColPlacements:h,multiColPlacements:f,leftoverMargins:g}=function(e,t,n){let r=function(e,t){let n=[];for(let e=0;e<t;e+=1)n.push([]);for(let t of e)for(let e=t.span.start;e<t.span.end;e+=1)n[e].push(t);return n}(e,n.length),i=[],s=[],o=[];for(let e=0;e<n.length;e+=1){let a=r[e],l=[],c=0,d=0;for(let r of a){let i=t[r.index];l.push({seg:yl(i,e,e+1,n),isVisible:!0,isAbsolute:!1,absoluteTop:r.levelCoord,marginTop:r.levelCoord-c}),c=r.levelCoord+r.thickness}let u=[];c=0,d=0;for(let r of a){let i=t[r.index],s=r.span.end-r.span.start>1,o=r.span.start===e;d+=r.levelCoord-c,c=r.levelCoord+r.thickness,s?(d+=r.thickness,o&&u.push({seg:yl(i,r.span.start,r.span.end,n),isVisible:!0,isAbsolute:!0,absoluteTop:r.levelCoord,marginTop:0})):o&&(u.push({seg:yl(i,r.span.start,r.span.end,n),isVisible:!0,isAbsolute:!1,absoluteTop:r.levelCoord,marginTop:d}),d=0)}i.push(l),s.push(u),o.push(d)}return{singleColPlacements:i,multiColPlacements:s,leftoverMargins:o}}(u,e,o),p=[],m=[];for(let e of c){f[e.firstCol].push({seg:e,isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let t=e.firstCol;t<=e.lastCol;t+=1)h[t].push({seg:yl(e,t,t+1,o),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<o.length;e+=1)p.push(0);for(let t of d){let n=e[t.index],r=t.span;f[r.start].push({seg:yl(n,r.start,r.end,o),isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let e=r.start;e<r.end;e+=1)p[e]+=1,h[e].push({seg:yl(n,e,e+1,o),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<o.length;e+=1)m.push(g[e]);return{singleColPlacements:h,multiColPlacements:f,moreCnts:p,moreMarginTops:m}}function yl(e,t,n,r){if(e.firstCol===t&&e.lastCol===n-1)return e;let i=e.eventRange,s=i.range,o=ir(s,{start:r[t].date,end:wt(r[n-1].date,1)});return Object.assign(Object.assign({},e),{firstCol:t,lastCol:n-1,eventRange:{def:i.def,ui:Object.assign(Object.assign({},i.ui),{durationEditable:!1}),instance:i.instance,range:o},isStart:e.isStart&&o.start.valueOf()===s.start.valueOf(),isEnd:e.isEnd&&o.end.valueOf()===s.end.valueOf()})}class bl extends ds{constructor(){super(...arguments),this.hiddenConsumes=!1,this.forceHidden={}}addSegs(e){const t=super.addSegs(e),{entriesByLevel:n}=this,r=e=>!this.forceHidden[hs(e)];for(let e=0;e<n.length;e+=1)n[e]=n[e].filter(r);return t}handleInvalidInsertion(e,t,n){const{entriesByLevel:r,forceHidden:i}=this,{touchingEntry:s,touchingLevel:o,touchingLateral:a}=e;if(this.hiddenConsumes&&s){const e=hs(s);if(!i[e])if(this.allowReslicing){const e=Object.assign(Object.assign({},s),{span:gs(s.span,t.span)});i[hs(e)]=!0,r[o][a]=e,n.push(e),this.splitEntry(s,t,n)}else i[e]=!0,n.push(s)}super.handleInvalidInsertion(e,t,n)}}class El extends cs{constructor(){super(...arguments),this.cellElRefs=new Fs,this.frameElRefs=new Fs,this.fgElRefs=new Fs,this.segHarnessRefs=new Fs,this.rootElRef={current:null},this.state={framePositions:null,maxContentHeight:null,segHeights:{}},this.handleResize=e=>{e&&this.updateSizing(!0)}}render(){let{props:e,state:t,context:n}=this,{options:r}=n,i=e.cells.length,s=rl(e.businessHourSegs,i),o=rl(e.bgEventSegs,i),a=rl(this.getHighlightSegs(),i),l=rl(this.getMirrorSegs(),i),{singleColPlacements:c,multiColPlacements:d,moreCnts:u,moreMarginTops:h}=vl(ci(e.fgEventSegs,r.eventOrder),e.dayMaxEvents,e.dayMaxEventRows,r.eventOrderStrict,t.segHeights,t.maxContentHeight,e.cells),f=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{};return p("tr",{ref:this.rootElRef,role:"row"},e.renderIntro&&e.renderIntro(),e.cells.map((t,n)=>{let r=this.renderFgSegs(n,e.forPrint?c[n]:d[n],e.todayRange,f),i=this.renderFgSegs(n,function(e,t){if(!e.length)return[];let n=function(e){let t={};for(let n of e)for(let e of n)t[e.seg.eventRange.instance.instanceId]=e.absoluteTop;return t}(t);return e.map(e=>({seg:e,isVisible:!0,isAbsolute:!0,absoluteTop:n[e.eventRange.instance.instanceId],marginTop:0}))}(l[n],d),e.todayRange,{},Boolean(e.eventDrag),Boolean(e.eventResize),!1);return p(fl,{key:t.key,elRef:this.cellElRefs.createRef(t.key),innerElRef:this.frameElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,showDayNumber:e.showDayNumbers,showWeekNumber:e.showWeekNumbers&&0===n,forceDayTop:e.showWeekNumbers,todayRange:e.todayRange,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,moreCnt:u[n],moreMarginTop:h[n],singlePlacements:c[n],fgContentElRef:this.fgElRefs.createRef(t.key),fgContent:p(y,null,p(y,null,r),p(y,null,i)),bgContent:p(y,null,this.renderFillSegs(a[n],"highlight"),this.renderFillSegs(s[n],"non-business"),this.renderFillSegs(o[n],"bg-event")),minHeight:e.cellMinHeight})}))}componentDidMount(){this.updateSizing(!0),this.context.addResizeHandler(this.handleResize)}componentDidUpdate(e,t){let n=this.props;this.updateSizing(!Cn(e,n))}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}getHighlightSegs(){let{props:e}=this;return e.eventDrag&&e.eventDrag.segs.length?e.eventDrag.segs:e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:e.dateSelectionSegs}getMirrorSegs(){let{props:e}=this;return e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:[]}renderFgSegs(e,t,n,r,i,s,o){let{context:a}=this,{eventSelection:l}=this.props,{framePositions:c}=this.state,d=1===this.props.cells.length,u=i||s||o,h=[];if(c)for(let e of t){let{seg:t}=e,{instanceId:f}=t.eventRange.instance,g=e.isVisible&&!r[f],m=e.isAbsolute,v="",y="";m&&(a.isRtl?(y=0,v=c.lefts[t.lastCol]-c.lefts[t.firstCol]):(v=0,y=c.rights[t.firstCol]-c.rights[t.lastCol])),h.push(p("div",{className:"fc-daygrid-event-harness"+(m?" fc-daygrid-event-harness-abs":""),key:pl(t),ref:u?null:this.segHarnessRefs.createRef(ml(t)),style:{visibility:g?"":"hidden",marginTop:m?"":e.marginTop,top:m?e.absoluteTop:"",left:v,right:y}},ol(t)?p(ll,Object.assign({seg:t,isDragging:i,isSelected:f===l,defaultDisplayEventEnd:d},pi(t,n))):p(al,Object.assign({seg:t,isDragging:i,isResizing:s,isDateSelecting:o,isSelected:f===l,defaultDisplayEventEnd:d},pi(t,n)))))}return h}renderFillSegs(e,t){let{isRtl:n}=this.context,{todayRange:r}=this.props,{framePositions:i}=this.state,s=[];if(i)for(let o of e){let e=n?{right:0,left:i.lefts[o.lastCol]-i.lefts[o.firstCol]}:{left:0,right:i.rights[o.firstCol]-i.rights[o.lastCol]};s.push(p("div",{key:vi(o.eventRange),className:"fc-daygrid-bg-harness",style:e},"bg-event"===t?p(fo,Object.assign({seg:o},pi(o,r))):po(t)))}return p(y,{},...s)}updateSizing(e){let{props:t,state:n,frameElRefs:r}=this;if(!t.forPrint&&null!==t.clientWidth){if(e){let e=t.cells.map(e=>r.currentMap[e.key]);if(e.length){let t=this.rootElRef.current,r=new is(t,e,!0,!1);n.framePositions&&n.framePositions.similarTo(r)||this.setState({framePositions:new is(t,e,!0,!1)})}}const i=this.state.segHeights,s=this.querySegHeights(),o=!0===t.dayMaxEvents||!0===t.dayMaxEventRows;this.safeSetState({segHeights:Object.assign(Object.assign({},i),s),maxContentHeight:o?this.computeMaxContentHeight():null})}}querySegHeights(){let e=this.segHarnessRefs.currentMap,t={};for(let n in e){let r=Math.round(e[n].getBoundingClientRect().height);t[n]=Math.max(t[n]||0,r)}return t}computeMaxContentHeight(){let e=this.props.cells[0].key,t=this.cellElRefs.currentMap[e],n=this.fgElRefs.currentMap[e];return t.getBoundingClientRect().bottom-n.getBoundingClientRect().top}getCellEls(){let e=this.cellElRefs.currentMap;return this.props.cells.map(t=>e[t.key])}}El.addStateEquality({segHeights:Cn});class Sl extends cs{constructor(){super(...arguments),this.splitBusinessHourSegs=Gt(nl),this.splitBgEventSegs=Gt(nl),this.splitFgEventSegs=Gt(nl),this.splitDateSelectionSegs=Gt(nl),this.splitEventDrag=Gt(il),this.splitEventResize=Gt(il),this.rowRefs=new Fs}render(){let{props:e,context:t}=this,n=e.cells.length,r=this.splitBusinessHourSegs(e.businessHourSegs,n),i=this.splitBgEventSegs(e.bgEventSegs,n),s=this.splitFgEventSegs(e.fgEventSegs,n),o=this.splitDateSelectionSegs(e.dateSelectionSegs,n),a=this.splitEventDrag(e.eventDrag,n),l=this.splitEventResize(e.eventResize,n),c=n>=7&&e.clientWidth?e.clientWidth/t.options.aspectRatio/6:null;return p(Oi,{unit:"day"},(t,d)=>p(y,null,e.cells.map((t,u)=>p(El,{ref:this.rowRefs.createRef(u),key:t.length?t[0].date.toISOString():u,showDayNumbers:n>1,showWeekNumbers:e.showWeekNumbers,todayRange:d,dateProfile:e.dateProfile,cells:t,renderIntro:e.renderRowIntro,businessHourSegs:r[u],eventSelection:e.eventSelection,bgEventSegs:i[u].filter(Dl),fgEventSegs:s[u],dateSelectionSegs:o[u],eventDrag:a[u],eventResize:l[u],dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,clientWidth:e.clientWidth,clientHeight:e.clientHeight,cellMinHeight:c,forPrint:e.forPrint}))))}componentDidMount(){this.registerInteractiveComponent()}componentDidUpdate(){this.registerInteractiveComponent()}registerInteractiveComponent(){if(!this.rootEl){const e=this.rowRefs.currentMap[0].getCellEls()[0],t=e?e.closest(".fc-daygrid-body"):null;t&&(this.rootEl=t,this.context.registerInteractiveComponent(this,{el:t,isHitComboAllowed:this.props.isHitComboAllowed}))}}componentWillUnmount(){this.rootEl&&(this.context.unregisterInteractiveComponent(this),this.rootEl=null)}prepareHits(){this.rowPositions=new is(this.rootEl,this.rowRefs.collect().map(e=>e.getCellEls()[0]),!1,!0),this.colPositions=new is(this.rootEl,this.rowRefs.currentMap[0].getCellEls(),!0,!1)}queryHit(e,t){let{colPositions:n,rowPositions:r}=this,i=n.leftToIndex(e),s=r.topToIndex(t);if(null!=s&&null!=i){let e=this.props.cells[s][i];return{dateProfile:this.props.dateProfile,dateSpan:Object.assign({range:this.getCellRange(s,i),allDay:!0},e.extraDateSpan),dayEl:this.getCellEl(s,i),rect:{left:n.lefts[i],right:n.rights[i],top:r.tops[s],bottom:r.bottoms[s]},layer:0}}return null}getCellEl(e,t){return this.rowRefs.currentMap[e].getCellEls()[t]}getCellRange(e,t){let n=this.props.cells[e][t].date;return{start:n,end:wt(n,1)}}}function Dl(e){return e.eventRange.def.allDay}class Al extends cs{constructor(){super(...arguments),this.elRef={current:null},this.needsScrollReset=!1}render(){let{props:e}=this,{dayMaxEventRows:t,dayMaxEvents:n,expandRows:r}=e,i=!0===n||!0===t;i&&!r&&(i=!1,t=null,n=null);let s=["fc-daygrid-body",i?"fc-daygrid-body-balanced":"fc-daygrid-body-unbalanced",r?"":"fc-daygrid-body-natural"];return p("div",{ref:this.elRef,className:s.join(" "),style:{width:e.clientWidth,minWidth:e.tableMinWidth}},p("table",{role:"presentation",className:"fc-scrollgrid-sync-table",style:{width:e.clientWidth,minWidth:e.tableMinWidth,height:r?e.clientHeight:""}},e.colGroupNode,p("tbody",{role:"presentation"},p(Sl,{dateProfile:e.dateProfile,cells:e.cells,renderRowIntro:e.renderRowIntro,showWeekNumbers:e.showWeekNumbers,clientWidth:e.clientWidth,clientHeight:e.clientHeight,businessHourSegs:e.businessHourSegs,bgEventSegs:e.bgEventSegs,fgEventSegs:e.fgEventSegs,dateSelectionSegs:e.dateSelectionSegs,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,dayMaxEvents:n,dayMaxEventRows:t,forPrint:e.forPrint,isHitComboAllowed:e.isHitComboAllowed}))))}componentDidMount(){this.requestScrollReset()}componentDidUpdate(e){e.dateProfile!==this.props.dateProfile?this.requestScrollReset():this.flushScrollReset()}requestScrollReset(){this.needsScrollReset=!0,this.flushScrollReset()}flushScrollReset(){if(this.needsScrollReset&&this.props.clientWidth){const e=function(e,t){let n;t.currentRangeUnit.match(/year|month/)&&(n=e.querySelector(`[data-date="${Wt(t.currentDate)}-01"]`));n||(n=e.querySelector(`[data-date="${Lt(t.currentDate)}"]`));return n}(this.elRef.current,this.props.dateProfile);if(e){const t=e.closest(".fc-daygrid-body"),n=t.closest(".fc-scroller"),r=e.getBoundingClientRect().top-t.getBoundingClientRect().top;n.scrollTop=r?r+1:0}this.needsScrollReset=!1}}}class wl extends Ms{constructor(){super(...arguments),this.forceDayIfListItem=!0}sliceRange(e,t){return t.sliceRange(e)}}class Cl extends cs{constructor(){super(...arguments),this.slicer=new wl,this.tableRef={current:null}}render(){let{props:e,context:t}=this;return p(Al,Object.assign({ref:this.tableRef},this.slicer.sliceProps(e,e.dateProfile,e.nextDayThreshold,t,e.dayTableModel),{dateProfile:e.dateProfile,cells:e.dayTableModel.cells,colGroupNode:e.colGroupNode,tableMinWidth:e.tableMinWidth,renderRowIntro:e.renderRowIntro,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.showWeekNumbers,expandRows:e.expandRows,headerAlignElRef:e.headerAlignElRef,clientWidth:e.clientWidth,clientHeight:e.clientHeight,forPrint:e.forPrint}))}}function Rl(e,t){let n=new Ts(e.renderRange,t);return new ks(n,/year|month|week/.test(e.currentRangeUnit))}class xl extends fr{buildRenderRange(e,t,n){let r=super.buildRenderRange(e,t,n),{props:i}=this;return _l({currentRange:r,snapToWeek:/^(year|month)$/.test(t),fixedWeekCount:i.fixedWeekCount,dateEnv:i.dateEnv})}}function _l(e){let t,{dateEnv:n,currentRange:r}=e,{start:i,end:s}=r;if(e.snapToWeek&&(i=n.startOfWeek(i),t=n.startOfWeek(s),t.valueOf()!==s.valueOf()&&(s=At(t,1))),e.fixedWeekCount){let e=n.startOfWeek(n.startOfMonth(wt(r.end,-1)));s=At(s,6-Math.ceil(Rt(e,s)))}return{start:i,end:s}}xe(':root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:"";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:"";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}');var Tl=No({name:"@fullcalendar/daygrid",initialView:"dayGridMonth",views:{dayGrid:{component:class extends tl{constructor(){super(...arguments),this.buildDayTableModel=Gt(Rl),this.headerRef={current:null},this.tableRef={current:null}}render(){let{options:e,dateProfileGenerator:t}=this.context,{props:n}=this,r=this.buildDayTableModel(n.dateProfile,t),i=e.dayHeaders&&p(xs,{ref:this.headerRef,dateProfile:n.dateProfile,dates:r.headerDates,datesRepDistinctDays:1===r.rowCnt}),s=t=>p(Cl,{ref:this.tableRef,dateProfile:n.dateProfile,dayTableModel:r,businessHours:n.businessHours,dateSelection:n.dateSelection,eventStore:n.eventStore,eventUiBases:n.eventUiBases,eventSelection:n.eventSelection,eventDrag:n.eventDrag,eventResize:n.eventResize,nextDayThreshold:e.nextDayThreshold,colGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.weekNumbers,expandRows:!n.isHeightAuto,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:n.forPrint});return e.dayMinWidth?this.renderHScrollLayout(i,s,r.colCnt,e.dayMinWidth):this.renderSimpleLayout(i,s)}},dateProfileGeneratorClass:xl},dayGridDay:{type:"dayGrid",duration:{days:1}},dayGridWeek:{type:"dayGrid",duration:{weeks:1}},dayGridMonth:{type:"dayGrid",duration:{months:1},fixedWeekCount:!0},dayGridYear:{type:"dayGrid",duration:{years:1}}}});class kl extends Wi{getKeyInfo(){return{allDay:{},timed:{}}}getKeysForDateSpan(e){return e.allDay?["allDay"]:["timed"]}getKeysForEventDef(e){return e.allDay?ii(e)?["timed","allDay"]:["allDay"]:["timed"]}}const Ml=an({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"});function Il(e){let t=["fc-timegrid-slot","fc-timegrid-slot-label",e.isLabeled?"fc-scrollgrid-shrink":"fc-timegrid-slot-minor"];return p(Wn.Consumer,null,n=>{if(!e.isLabeled)return p("td",{className:t.join(" "),"data-time":e.isoTimeStr});let{dateEnv:r,options:i,viewApi:s}=n,o=null==i.slotLabelFormat?Ml:Array.isArray(i.slotLabelFormat)?an(i.slotLabelFormat[0]):an(i.slotLabelFormat),a={level:0,time:e.time,date:r.toDate(e.date),view:s,text:r.format(e.date,o)};return p(Jn,{elTag:"td",elClasses:t,elAttrs:{"data-time":e.isoTimeStr},renderProps:a,generatorName:"slotLabelContent",customGenerator:i.slotLabelContent,defaultGenerator:Ol,classNameGenerator:i.slotLabelClassNames,didMount:i.slotLabelDidMount,willUnmount:i.slotLabelWillUnmount},e=>p("div",{className:"fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame"},p(e,{elTag:"div",elClasses:["fc-timegrid-slot-label-cushion","fc-scrollgrid-shrink-cushion"]})))})}function Ol(e){return e.text}class Nl extends Gn{render(){return this.props.slatMetas.map(e=>p("tr",{key:e.key},p(Il,Object.assign({},e))))}}const Pl=an({week:"short"});class Hl extends cs{constructor(){super(...arguments),this.allDaySplitter=new kl,this.headerElRef={current:null},this.rootElRef={current:null},this.scrollerElRef={current:null},this.state={slatCoords:null},this.handleScrollTopRequest=e=>{let t=this.scrollerElRef.current;t&&(t.scrollTop=e)},this.renderHeadAxis=(e,t="")=>{let{options:n}=this.context,{dateProfile:r}=this.props,i=r.renderRange,s=1===xt(i.start,i.end)?Yi(this.context,i.start,"week"):{};return n.weekNumbers&&"day"===e?p(mo,{elTag:"th",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},date:i.start,defaultFormat:Pl},e=>p("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame","fc-timegrid-axis-frame-liquid"].join(" "),style:{height:t}},p(e,{elTag:"a",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"],elAttrs:s}))):p("th",{"aria-hidden":!0,className:"fc-timegrid-axis"},p("div",{className:"fc-timegrid-axis-frame",style:{height:t}}))},this.renderTableRowAxis=e=>{let{options:t,viewApi:n}=this.context,r={text:t.allDayText,view:n};return p(Jn,{elTag:"td",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},renderProps:r,generatorName:"allDayContent",customGenerator:t.allDayContent,defaultGenerator:Bl,classNameGenerator:t.allDayClassNames,didMount:t.allDayDidMount,willUnmount:t.allDayWillUnmount},t=>p("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame",null==e?" fc-timegrid-axis-frame-liquid":""].join(" "),style:{height:e}},p(t,{elTag:"span",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"]})))},this.handleSlatCoords=e=>{this.setState({slatCoords:e})}}renderSimpleLayout(e,t,n){let{context:r,props:i}=this,s=[],o=to(r.options);return e&&s.push({type:"header",key:"header",isSticky:o,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),t&&(s.push({type:"body",key:"all-day",chunk:{content:t}}),s.push({type:"body",key:"all-day-divider",outerContent:p("tr",{role:"presentation",className:"fc-scrollgrid-section"},p("td",{className:"fc-timegrid-divider "+r.theme.getClass("tableCellShaded")}))})),s.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(r.options.expandRows),chunk:{scrollerElRef:this.scrollerElRef,content:n}}),p(er,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:r.viewSpec},p(ro,{liquid:!i.isHeightAuto&&!i.forPrint,collapsibleWidth:i.forPrint,cols:[{width:"shrink"}],sections:s}))}renderHScrollLayout(e,t,n,r,i,s,o){let a=this.context.pluginHooks.scrollGridImpl;if(!a)throw new Error("No ScrollGrid implementation");let{context:l,props:c}=this,d=!c.forPrint&&to(l.options),u=!c.forPrint&&no(l.options),h=[];e&&h.push({type:"header",key:"header",isSticky:d,syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>p("tr",{role:"presentation"},this.renderHeadAxis("day",e.rowSyncHeights[0]))},{key:"cols",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),t&&(h.push({type:"body",key:"all-day",syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>p("tr",{role:"presentation"},this.renderTableRowAxis(e.rowSyncHeights[0]))},{key:"cols",content:t}]}),h.push({key:"all-day-divider",type:"body",outerContent:p("tr",{role:"presentation",className:"fc-scrollgrid-section"},p("td",{colSpan:2,className:"fc-timegrid-divider "+l.theme.getClass("tableCellShaded")}))}));let f=l.options.nowIndicator;return h.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(l.options.expandRows),chunks:[{key:"axis",content:e=>p("div",{className:"fc-timegrid-axis-chunk"},p("table",{"aria-hidden":!0,style:{height:e.expandRows?e.clientHeight:""}},e.tableColGroupNode,p("tbody",null,p(Nl,{slatMetas:s}))),p("div",{className:"fc-timegrid-now-indicator-container"},p(Oi,{unit:f?"minute":"day"},e=>{let t=f&&o&&o.safeComputeTop(e);return"number"==typeof t?p(ao,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:t},isAxis:!0,date:e}):null})))},{key:"cols",scrollerElRef:this.scrollerElRef,content:n}]}),u&&h.push({key:"footer",type:"footer",isSticky:!0,chunks:[{key:"axis",content:eo},{key:"cols",content:eo}]}),p(er,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:l.viewSpec},p(a,{liquid:!c.isHeightAuto&&!c.forPrint,forPrint:c.forPrint,collapsibleWidth:!1,colGroups:[{width:"shrink",cols:[{width:"shrink"}]},{cols:[{span:r,minWidth:i}]}],sections:h}))}getAllDayMaxEventProps(){let{dayMaxEvents:e,dayMaxEventRows:t}=this.context.options;return!0!==e&&!0!==t||(e=void 0,t=5),{dayMaxEvents:e,dayMaxEventRows:t}}}function Bl(e){return e.text}class jl{constructor(e,t,n){this.positions=e,this.dateProfile=t,this.slotDuration=n}safeComputeTop(e){let{dateProfile:t}=this;if(lr(t.currentRange,e)){let n=Mt(e),r=e.valueOf()-n.valueOf();if(r>=yt(t.slotMinTime)&&r<yt(t.slotMaxTime))return this.computeTimeTop(ft(r))}return null}computeDateTop(e,t){return t||(t=Mt(e)),this.computeTimeTop(ft(e.valueOf()-t.valueOf()))}computeTimeTop(e){let t,n,{positions:r,dateProfile:i}=this,s=r.els.length,o=(e.milliseconds-yt(i.slotMinTime))/yt(this.slotDuration);return o=Math.max(0,o),o=Math.min(s,o),t=Math.floor(o),t=Math.min(t,s-1),n=o-t,r.tops[t]+r.getHeight(t)*n}}class zl extends Gn{render(){let{props:e,context:t}=this,{options:n}=t,{slatElRefs:r}=e;return p("tbody",null,e.slatMetas.map((i,s)=>{let o={time:i.time,date:t.dateEnv.toDate(i.date),view:t.viewApi};return p("tr",{key:i.key,ref:r.createRef(i.key)},e.axis&&p(Il,Object.assign({},i)),p(Jn,{elTag:"td",elClasses:["fc-timegrid-slot","fc-timegrid-slot-lane",!i.isLabeled&&"fc-timegrid-slot-minor"],elAttrs:{"data-time":i.isoTimeStr},renderProps:o,generatorName:"slotLaneContent",customGenerator:n.slotLaneContent,classNameGenerator:n.slotLaneClassNames,didMount:n.slotLaneDidMount,willUnmount:n.slotLaneWillUnmount}))}))}}class Ul extends Gn{constructor(){super(...arguments),this.rootElRef={current:null},this.slatElRefs=new Fs}render(){let{props:e,context:t}=this;return p("div",{ref:this.rootElRef,className:"fc-timegrid-slots"},p("table",{"aria-hidden":!0,className:t.theme.getClass("table"),style:{minWidth:e.tableMinWidth,width:e.clientWidth,height:e.minHeight}},e.tableColGroupNode,p(zl,{slatElRefs:this.slatElRefs,axis:e.axis,slatMetas:e.slatMetas})))}componentDidMount(){this.updateSizing()}componentDidUpdate(){this.updateSizing()}componentWillUnmount(){this.props.onCoords&&this.props.onCoords(null)}updateSizing(){let{context:e,props:t}=this;if(t.onCoords&&null!==t.clientWidth){this.rootElRef.current.offsetHeight&&t.onCoords(new jl(new is(this.rootElRef.current,(n=this.slatElRefs.currentMap,t.slatMetas.map(e=>n[e.key])),!1,!0),this.props.dateProfile,e.options.slotDuration))}var n}}function Ll(e,t){let n,r=[];for(n=0;n<t;n+=1)r.push([]);if(e)for(n=0;n<e.length;n+=1)r[e[n].col].push(e[n]);return r}function Wl(e,t){let n=[];if(e){for(let r=0;r<t;r+=1)n[r]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)n[t.col].segs.push(t)}else for(let e=0;e<t;e+=1)n[e]=null;return n}class Fl extends Gn{render(){let{props:e}=this;return p(Eo,{elClasses:["fc-timegrid-more-link"],elStyle:{top:e.top,bottom:e.bottom},allDayDate:null,moreCnt:e.hiddenSegs.length,allSegs:e.hiddenSegs,hiddenSegs:e.hiddenSegs,extraDateSpan:e.extraDateSpan,dateProfile:e.dateProfile,todayRange:e.todayRange,popoverContent:()=>ec(e.hiddenSegs,e),defaultGenerator:Vl,forceTimed:!0},e=>p(e,{elTag:"div",elClasses:["fc-timegrid-more-link-inner","fc-sticky"]}))}}function Vl(e){return e.shortText}function Gl(e,t,n){let r=new ds;null!=t&&(r.strictOrder=t),null!=n&&(r.maxStackCnt=n);let i=fs(r.addSegs(e)),s=function(e){const{entriesByLevel:t}=e,n=Zl((e,t)=>e+":"+t,(r,i)=>{let s=Ql(function(e,t,n){let{levelCoords:r,entriesByLevel:i}=e,s=i[t][n],o=r[t]+s.thickness,a=r.length,l=t;for(;l<a&&r[l]<o;l+=1);for(;l<a;l+=1){let e,t=i[l],n=ms(t,s.span.start,us),r=n[0]+n[1],o=r;for(;(e=t[o])&&e.span.start<s.span.end;)o+=1;if(r<o)return{level:l,lateralStart:r,lateralEnd:o}}return null}(e,r,i),n),o=t[r][i];return[Object.assign(Object.assign({},o),{nextLevelNodes:s[0]}),o.thickness+s[1]]});return Ql(t.length?{level:0,lateralStart:0,lateralEnd:t[0].length}:null,n)[0]}(r);return s=function(e,t){const n=Zl((e,t,n)=>hs(e),(e,r,i)=>{let s,{nextLevelNodes:o,thickness:a}=e,l=a+i,c=a/l,d=[];if(o.length)for(let e of o)if(void 0===s){let t=n(e,r,l);s=t[0],d.push(t[1])}else{let t=n(e,s,0);d.push(t[1])}else s=t;let u=(s-r)*c;return[s-u,Object.assign(Object.assign({},e),{thickness:u,nextLevelNodes:d})]});return e.map(e=>n(e,0,0)[1])}(s,1),{segRects:function(e){let t=[];const n=Zl((e,t,n)=>hs(e),(e,n,i)=>{let s=Object.assign(Object.assign({},e),{levelCoord:n,stackDepth:i,stackForward:0});return t.push(s),s.stackForward=r(e.nextLevelNodes,n+e.thickness,i+1)+1});function r(e,t,r){let i=0;for(let s of e)i=Math.max(n(s,t,r),i);return i}return r(e,0,0),t}(s),hiddenGroups:i}}function Ql(e,t){if(!e)return[[],0];let{level:n,lateralStart:r,lateralEnd:i}=e,s=r,o=[];for(;s<i;)o.push(t(n,s)),s+=1;return o.sort(ql),[o.map(Yl),o[0][1]]}function ql(e,t){return t[1]-e[1]}function Yl(e){return e[0]}function Zl(e,t){const n={};return(...r)=>{let i=e(...r);return i in n?n[i]:n[i]=t(...r)}}function Xl(e,t,n=null,r=0){let i=[];if(n)for(let s=0;s<e.length;s+=1){let o=e[s],a=n.computeDateTop(o.start,t),l=Math.max(a+(r||0),n.computeDateTop(o.end,t));i.push({start:Math.round(a),end:Math.round(l)})}return i}const $l=an({hour:"numeric",minute:"2-digit",meridiem:!1});class Jl extends Gn{render(){return p(so,Object.assign({},this.props,{elClasses:["fc-timegrid-event","fc-v-event",this.props.isShort&&"fc-timegrid-event-short"],defaultTimeFormat:$l}))}}class Kl extends Gn{constructor(){super(...arguments),this.sortEventSegs=Gt(ci)}render(){let{props:e,context:t}=this,{options:n}=t,r=n.selectMirror,i=e.eventDrag&&e.eventDrag.segs||e.eventResize&&e.eventResize.segs||r&&e.dateSelectionSegs||[],s=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{},o=this.sortEventSegs(e.fgEventSegs,n.eventOrder);return p(co,{elTag:"td",elRef:e.elRef,elClasses:["fc-timegrid-col",...e.extraClassNames||[]],elAttrs:Object.assign({role:"gridcell"},e.extraDataAttrs),date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,extraRenderProps:e.extraRenderProps},t=>p("div",{className:"fc-timegrid-col-frame"},p("div",{className:"fc-timegrid-col-bg"},this.renderFillSegs(e.businessHourSegs,"non-business"),this.renderFillSegs(e.bgEventSegs,"bg-event"),this.renderFillSegs(e.dateSelectionSegs,"highlight")),p("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(o,s,!1,!1,!1)),p("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(i,{},Boolean(e.eventDrag),Boolean(e.eventResize),Boolean(r),"mirror")),p("div",{className:"fc-timegrid-now-indicator-container"},this.renderNowIndicator(e.nowIndicatorSegs)),uo(n)&&p(t,{elTag:"div",elClasses:["fc-timegrid-col-misc"]})))}renderFgSegs(e,t,n,r,i,s){let{props:o}=this;return o.forPrint?ec(e,o):this.renderPositionedFgSegs(e,t,n,r,i,s)}renderPositionedFgSegs(e,t,n,r,i,s){let{eventMaxStack:o,eventShortHeight:a,eventOrderStrict:l,eventMinHeight:c}=this.context.options,{date:d,slatCoords:u,eventSelection:h,todayRange:f,nowDate:g}=this.props,m=n||r||i,v=Xl(e,d,u,c),{segPlacements:b,hiddenGroups:E}=function(e,t,n,r){let i=[],s=[];for(let n=0;n<e.length;n+=1){let r=t[n];r?i.push({index:n,thickness:1,span:r}):s.push(e[n])}let{segRects:o,hiddenGroups:a}=Gl(i,n,r),l=[];for(let t of o)l.push({seg:e[t.index],rect:t});for(let e of s)l.push({seg:e,rect:null});return{segPlacements:l,hiddenGroups:a}}(e,v,l,o);return p(y,null,this.renderHiddenGroups(E,e),b.map(e=>{let{seg:o,rect:l}=e,c=o.eventRange.instance.instanceId,d=m||Boolean(!t[c]&&l),u=tc(l&&l.span),v=!m&&l?this.computeSegHStyle(l):{left:0,right:0},y=Boolean(l)&&l.stackForward>0,b=Boolean(l)&&l.span.end-l.span.start<a;return p("div",{className:"fc-timegrid-event-harness"+(y?" fc-timegrid-event-harness-inset":""),key:s||c,style:Object.assign(Object.assign({visibility:d?"":"hidden"},u),v)},p(Jl,Object.assign({seg:o,isDragging:n,isResizing:r,isDateSelecting:i,isSelected:c===h,isShort:b},pi(o,f,g))))}))}renderHiddenGroups(e,t){let{extraDateSpan:n,dateProfile:r,todayRange:i,nowDate:s,eventSelection:o,eventDrag:a,eventResize:l}=this.props;return p(y,null,e.map(e=>{let c=tc(e.span),d=(u=e.entries,h=t,u.map(e=>h[e.index]));var u,h;return p(Fl,{key:Ut(Ao(d)),hiddenSegs:d,top:c.top,bottom:c.bottom,extraDateSpan:n,dateProfile:r,todayRange:i,nowDate:s,eventSelection:o,eventDrag:a,eventResize:l})}))}renderFillSegs(e,t){let{props:n,context:r}=this,i=Xl(e,n.date,n.slatCoords,r.options.eventMinHeight).map((r,i)=>{let s=e[i];return p("div",{key:vi(s.eventRange),className:"fc-timegrid-bg-harness",style:tc(r)},"bg-event"===t?p(fo,Object.assign({seg:s},pi(s,n.todayRange,n.nowDate))):po(t))});return p(y,null,i)}renderNowIndicator(e){let{slatCoords:t,date:n}=this.props;return t?e.map((e,r)=>p(ao,{key:r,elClasses:["fc-timegrid-now-indicator-line"],elStyle:{top:t.computeDateTop(e.start,n)},isAxis:!1,date:n})):null}computeSegHStyle(e){let t,n,{isRtl:r,options:i}=this.context,s=i.slotEventOverlap,o=e.levelCoord,a=e.levelCoord+e.thickness;s&&(a=Math.min(1,o+2*(a-o))),r?(t=1-a,n=o):(t=o,n=1-a);let l={zIndex:e.stackDepth+1,left:100*t+"%",right:100*n+"%"};return s&&!e.stackForward&&(l[r?"marginLeft":"marginRight"]=20),l}}function ec(e,{todayRange:t,nowDate:n,eventSelection:r,eventDrag:i,eventResize:s}){let o=(i?i.affectedInstances:null)||(s?s.affectedInstances:null)||{};return p(y,null,e.map(e=>{let i=e.eventRange.instance.instanceId;return p("div",{key:i,style:{visibility:o[i]?"hidden":""}},p(Jl,Object.assign({seg:e,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:i===r,isShort:!1},pi(e,t,n))))}))}function tc(e){return e?{top:e.start,bottom:-e.end}:{top:"",bottom:""}}class nc extends Gn{constructor(){super(...arguments),this.splitFgEventSegs=Gt(Ll),this.splitBgEventSegs=Gt(Ll),this.splitBusinessHourSegs=Gt(Ll),this.splitNowIndicatorSegs=Gt(Ll),this.splitDateSelectionSegs=Gt(Ll),this.splitEventDrag=Gt(Wl),this.splitEventResize=Gt(Wl),this.rootElRef={current:null},this.cellElRefs=new Fs}render(){let{props:e,context:t}=this,n=t.options.nowIndicator&&e.slatCoords&&e.slatCoords.safeComputeTop(e.nowDate),r=e.cells.length,i=this.splitFgEventSegs(e.fgEventSegs,r),s=this.splitBgEventSegs(e.bgEventSegs,r),o=this.splitBusinessHourSegs(e.businessHourSegs,r),a=this.splitNowIndicatorSegs(e.nowIndicatorSegs,r),l=this.splitDateSelectionSegs(e.dateSelectionSegs,r),c=this.splitEventDrag(e.eventDrag,r),d=this.splitEventResize(e.eventResize,r);return p("div",{className:"fc-timegrid-cols",ref:this.rootElRef},p("table",{role:"presentation",style:{minWidth:e.tableMinWidth,width:e.clientWidth}},e.tableColGroupNode,p("tbody",{role:"presentation"},p("tr",{role:"row"},e.axis&&p("td",{"aria-hidden":!0,className:"fc-timegrid-col fc-timegrid-axis"},p("div",{className:"fc-timegrid-col-frame"},p("div",{className:"fc-timegrid-now-indicator-container"},"number"==typeof n&&p(ao,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:n},isAxis:!0,date:e.nowDate})))),e.cells.map((t,n)=>p(Kl,{key:t.key,elRef:this.cellElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,nowDate:e.nowDate,todayRange:e.todayRange,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,fgEventSegs:i[n],bgEventSegs:s[n],businessHourSegs:o[n],nowIndicatorSegs:a[n],dateSelectionSegs:l[n],eventDrag:c[n],eventResize:d[n],slatCoords:e.slatCoords,eventSelection:e.eventSelection,forPrint:e.forPrint}))))))}componentDidMount(){this.updateCoords()}componentDidUpdate(){this.updateCoords()}updateCoords(){let{props:e}=this;var t;e.onColCoords&&null!==e.clientWidth&&e.onColCoords(new is(this.rootElRef.current,(t=this.cellElRefs.currentMap,e.cells.map(e=>t[e.key])),!0,!1))}}class rc extends cs{constructor(){super(...arguments),this.processSlotOptions=Gt(ic),this.state={slatCoords:null},this.handleRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e,isHitComboAllowed:this.props.isHitComboAllowed}):this.context.unregisterInteractiveComponent(this)},this.handleScrollRequest=e=>{let{onScrollTopRequest:t}=this.props,{slatCoords:n}=this.state;if(t&&n){if(e.time){let r=n.computeTimeTop(e.time);r=Math.ceil(r),r&&(r+=1),t(r)}return!0}return!1},this.handleColCoords=e=>{this.colCoords=e},this.handleSlatCoords=e=>{this.setState({slatCoords:e}),this.props.onSlatCoords&&this.props.onSlatCoords(e)}}render(){let{props:e,state:t}=this;return p("div",{className:"fc-timegrid-body",ref:this.handleRootEl,style:{width:e.clientWidth,minWidth:e.tableMinWidth}},p(Ul,{axis:e.axis,dateProfile:e.dateProfile,slatMetas:e.slatMetas,clientWidth:e.clientWidth,minHeight:e.expandRows?e.clientHeight:"",tableMinWidth:e.tableMinWidth,tableColGroupNode:e.axis?e.tableColGroupNode:null,onCoords:this.handleSlatCoords}),p(nc,{cells:e.cells,axis:e.axis,dateProfile:e.dateProfile,businessHourSegs:e.businessHourSegs,bgEventSegs:e.bgEventSegs,fgEventSegs:e.fgEventSegs,dateSelectionSegs:e.dateSelectionSegs,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,todayRange:e.todayRange,nowDate:e.nowDate,nowIndicatorSegs:e.nowIndicatorSegs,clientWidth:e.clientWidth,tableMinWidth:e.tableMinWidth,tableColGroupNode:e.tableColGroupNode,slatCoords:t.slatCoords,onColCoords:this.handleColCoords,forPrint:e.forPrint}))}componentDidMount(){this.scrollResponder=this.context.createScrollResponder(this.handleScrollRequest)}componentDidUpdate(e){this.scrollResponder.update(e.dateProfile!==this.props.dateProfile)}componentWillUnmount(){this.scrollResponder.detach()}queryHit(e,t){let{dateEnv:n,options:r}=this.context,{colCoords:i}=this,{dateProfile:s}=this.props,{slatCoords:o}=this.state,{snapDuration:a,snapsPerSlot:l}=this.processSlotOptions(this.props.slotDuration,r.snapDuration),c=i.leftToIndex(e),d=o.positions.topToIndex(t);if(null!=c&&null!=d){let e=this.props.cells[c],r=o.positions.tops[d],u=o.positions.getHeight(d),h=(t-r)/u,f=d*l+Math.floor(h*l),g=this.props.cells[c].date,p=pt(s.slotMinTime,mt(a,f)),m=n.add(g,p),v=n.add(m,a);return{dateProfile:s,dateSpan:Object.assign({range:{start:m,end:v},allDay:!1},e.extraDateSpan),dayEl:i.els[c],rect:{left:i.lefts[c],right:i.rights[c],top:r,bottom:r+u},layer:0}}return null}}function ic(e,t){let n=t||e,r=bt(e,n);return null===r&&(n=e,r=1),{snapDuration:n,snapsPerSlot:r}}class sc extends Ms{sliceRange(e,t){let n=[];for(let r=0;r<t.length;r+=1){let i=ir(e,t[r]);i&&n.push({start:i.start,end:i.end,isStart:i.start.valueOf()===e.start.valueOf(),isEnd:i.end.valueOf()===e.end.valueOf(),col:r})}return n}}class oc extends cs{constructor(){super(...arguments),this.buildDayRanges=Gt(ac),this.slicer=new sc,this.timeColsRef={current:null}}render(){let{props:e,context:t}=this,{dateProfile:n,dayTableModel:r}=e,{nowIndicator:i,nextDayThreshold:s}=t.options,o=this.buildDayRanges(r,n,t.dateEnv);return p(Oi,{unit:i?"minute":"day"},(a,l)=>p(rc,Object.assign({ref:this.timeColsRef},this.slicer.sliceProps(e,n,null,t,o),{forPrint:e.forPrint,axis:e.axis,dateProfile:n,slatMetas:e.slatMetas,slotDuration:e.slotDuration,cells:r.cells[0],tableColGroupNode:e.tableColGroupNode,tableMinWidth:e.tableMinWidth,clientWidth:e.clientWidth,clientHeight:e.clientHeight,expandRows:e.expandRows,nowDate:a,nowIndicatorSegs:i&&this.slicer.sliceNowDate(a,n,s,t,o),todayRange:l,onScrollTopRequest:e.onScrollTopRequest,onSlatCoords:e.onSlatCoords})))}}function ac(e,t,n){let r=[];for(let i of e.headerDates)r.push({start:n.add(i,t.slotMinTime),end:n.add(i,t.slotMaxTime)});return r}const lc=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];function cc(e,t,n,r,i){let s=new Date(0),o=e,a=ft(0),l=n||function(e){let t,n,r;for(t=lc.length-1;t>=0;t-=1)if(n=ft(lc[t]),r=bt(n,e),null!==r&&r>1)return n;return e}(r),c=[];for(;yt(o)<yt(t);){let e=i.add(s,o),t=null!==bt(a,l);c.push({date:e,time:o,key:e.toISOString(),isoTimeStr:Ft(e),isLabeled:t}),o=pt(o,r),a=pt(a,r)}return c}function dc(e,t){let n=new Ts(e.renderRange,t);return new ks(n,!1)}xe('.fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:"\\00a0"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:"\\00a0-\\00a0"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}');var uc=No({name:"@fullcalendar/timegrid",initialView:"timeGridWeek",optionRefiners:{allDaySlot:Boolean},views:{timeGrid:{component:class extends Hl{constructor(){super(...arguments),this.buildTimeColsModel=Gt(dc),this.buildSlatMetas=Gt(cc)}render(){let{options:e,dateEnv:t,dateProfileGenerator:n}=this.context,{props:r}=this,{dateProfile:i}=r,s=this.buildTimeColsModel(i,n),o=this.allDaySplitter.splitProps(r),a=this.buildSlatMetas(i.slotMinTime,i.slotMaxTime,e.slotLabelInterval,e.slotDuration,t),{dayMinWidth:l}=e,c=!l,d=l,u=e.dayHeaders&&p(xs,{dates:s.headerDates,dateProfile:i,datesRepDistinctDays:!0,renderIntro:c?this.renderHeadAxis:null}),h=!1!==e.allDaySlot&&(t=>p(Cl,Object.assign({},o.allDay,{dateProfile:i,dayTableModel:s,nextDayThreshold:e.nextDayThreshold,tableMinWidth:t.tableMinWidth,colGroupNode:t.tableColGroupNode,renderRowIntro:c?this.renderTableRowAxis:null,showWeekNumbers:!1,expandRows:!1,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:r.forPrint},this.getAllDayMaxEventProps()))),f=t=>p(oc,Object.assign({},o.timed,{dayTableModel:s,dateProfile:i,axis:c,slotDuration:e.slotDuration,slatMetas:a,forPrint:r.forPrint,tableColGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,clientWidth:t.clientWidth,clientHeight:t.clientHeight,onSlatCoords:this.handleSlatCoords,expandRows:t.expandRows,onScrollTopRequest:this.handleScrollTopRequest}));return d?this.renderHScrollLayout(u,h,f,s.colCnt,l,a,this.state.slatCoords):this.renderSimpleLayout(u,h,f)}},usesMinMaxTime:!0,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},timeGridDay:{type:"timeGrid",duration:{days:1}},timeGridWeek:{type:"timeGrid",duration:{weeks:1}}}});class hc extends Gn{constructor(){super(...arguments),this.state={textId:Le()}}render(){let{theme:e,dateEnv:t,options:n,viewApi:r}=this.context,{cellId:i,dayDate:s,todayRange:o}=this.props,{textId:a}=this.state,l=Vi(s,o),c=n.listDayFormat?t.format(s,n.listDayFormat):"",d=n.listDaySideFormat?t.format(s,n.listDaySideFormat):"",u=Object.assign({date:t.toDate(s),view:r,textId:a,text:c,sideText:d,navLinkAttrs:Yi(this.context,s),sideNavLinkAttrs:Yi(this.context,s,"day",!1)},l);return p(Jn,{elTag:"tr",elClasses:["fc-list-day",...Gi(l,e)],elAttrs:{"data-date":Lt(s)},renderProps:u,generatorName:"dayHeaderContent",customGenerator:n.dayHeaderContent,defaultGenerator:fc,classNameGenerator:n.dayHeaderClassNames,didMount:n.dayHeaderDidMount,willUnmount:n.dayHeaderWillUnmount},t=>p("th",{scope:"colgroup",colSpan:3,id:i,"aria-labelledby":a},p(t,{elTag:"div",elClasses:["fc-list-day-cushion",e.getClass("tableCellShaded")]})))}}function fc(e){return p(y,null,e.text&&p("a",Object.assign({id:e.textId,className:"fc-list-day-text"},e.navLinkAttrs),e.text),e.sideText&&p("a",Object.assign({"aria-hidden":!0,className:"fc-list-day-side-text"},e.sideNavLinkAttrs),e.sideText))}const gc=an({hour:"numeric",minute:"2-digit",meridiem:"short"});class pc extends Gn{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r,timeHeaderId:i,eventHeaderId:s,dateHeaderId:o}=e,a=n.eventTimeFormat||gc;return p(io,Object.assign({},e,{elTag:"tr",elClasses:["fc-list-event",r.eventRange.def.url&&"fc-event-forced-url"],defaultGenerator:()=>function(e,t){let n=yi(e,t);return p("a",Object.assign({},n),e.eventRange.def.title)}(r,t),seg:r,timeText:"",disableDragging:!0,disableResizing:!0}),(e,n)=>p(y,null,function(e,t,n,r,i){let{options:s}=n;if(!1!==s.displayEventTime){let o,a=e.eventRange.def,l=e.eventRange.instance,c=!1;if(a.allDay?c=!0:ur(e.eventRange.range)?e.isStart?o=gi(e,t,n,null,null,l.range.start,e.end):e.isEnd?o=gi(e,t,n,null,null,e.start,l.range.end):c=!0:o=gi(e,t,n),c){let e={text:n.options.allDayText,view:n.viewApi};return p(Jn,{elTag:"td",elClasses:["fc-list-event-time"],elAttrs:{headers:`${r} ${i}`},renderProps:e,generatorName:"allDayContent",customGenerator:s.allDayContent,defaultGenerator:mc,classNameGenerator:s.allDayClassNames,didMount:s.allDayDidMount,willUnmount:s.allDayWillUnmount})}return p("td",{className:"fc-list-event-time"},o)}return null}(r,a,t,i,o),p("td",{"aria-hidden":!0,className:"fc-list-event-graphic"},p("span",{className:"fc-list-event-dot",style:{borderColor:n.borderColor||n.backgroundColor}})),p(e,{elTag:"td",elClasses:["fc-list-event-title"],elAttrs:{headers:`${s} ${o}`}})))}}function mc(e){return e.text}function vc(e){return e.text}function yc(e){let t=Mt(e.renderRange.start),n=e.renderRange.end,r=[],i=[];for(;t<n;)r.push(t),i.push({start:t,end:wt(t,1)}),t=wt(t,1);return{dayDates:r,dayRanges:i}}xe(':root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:"";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}');function bc(e){return!1===e?null:an(e)}var Ec=No({name:"@fullcalendar/list",optionRefiners:{listDayFormat:bc,listDaySideFormat:bc,noEventsClassNames:yn,noEventsContent:yn,noEventsDidMount:yn,noEventsWillUnmount:yn},views:{list:{component:class extends cs{constructor(){super(...arguments),this.computeDateVars=Gt(yc),this.eventStoreToSegs=Gt(this._eventStoreToSegs),this.state={timeHeaderId:Le(),eventHeaderId:Le(),dateHeaderIdRoot:Le()},this.setRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e}):this.context.unregisterInteractiveComponent(this)}}render(){let{props:e,context:t}=this,{dayDates:n,dayRanges:r}=this.computeDateVars(e.dateProfile),i=this.eventStoreToSegs(e.eventStore,e.eventUiBases,r);return p(er,{elRef:this.setRootEl,elClasses:["fc-list",t.theme.getClass("table"),!1!==t.options.stickyHeaderDates?"fc-list-sticky":""],viewSpec:t.viewSpec},p(Ws,{liquid:!e.isHeightAuto,overflowX:e.isHeightAuto?"visible":"hidden",overflowY:e.isHeightAuto?"visible":"auto"},i.length>0?this.renderSegList(i,n):this.renderEmptyMessage()))}renderEmptyMessage(){let{options:e,viewApi:t}=this.context,n={text:e.noEventsText,view:t};return p(Jn,{elTag:"div",elClasses:["fc-list-empty"],renderProps:n,generatorName:"noEventsContent",customGenerator:e.noEventsContent,defaultGenerator:vc,classNameGenerator:e.noEventsClassNames,didMount:e.noEventsDidMount,willUnmount:e.noEventsWillUnmount},e=>p(e,{elTag:"div",elClasses:["fc-list-empty-cushion"]}))}renderSegList(e,t){let{theme:n,options:r}=this.context,{timeHeaderId:i,eventHeaderId:s,dateHeaderIdRoot:o}=this.state,a=function(e){let t,n,r=[];for(t=0;t<e.length;t+=1)n=e[t],(r[n.dayIndex]||(r[n.dayIndex]=[])).push(n);return r}(e);return p(Oi,{unit:"day"},(e,l)=>{let c=[];for(let n=0;n<a.length;n+=1){let d=a[n];if(d){let a=Lt(t[n]),u=o+"-"+a;c.push(p(hc,{key:a,cellId:u,dayDate:t[n],todayRange:l})),d=ci(d,r.eventOrder);for(let t of d)c.push(p(pc,Object.assign({key:a+":"+t.eventRange.instance.instanceId,seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,timeHeaderId:i,eventHeaderId:s,dateHeaderId:u},pi(t,l,e))))}}return p("table",{className:"fc-list-table "+n.getClass("table")},p("thead",null,p("tr",null,p("th",{scope:"col",id:i},r.timeHint),p("th",{scope:"col","aria-hidden":!0}),p("th",{scope:"col",id:s},r.eventHint))),p("tbody",null,c))})}_eventStoreToSegs(e,t,n){return this.eventRangesToSegs(ri(e,t,this.props.dateProfile.activeRange,this.context.options.nextDayThreshold).fg,n)}eventRangesToSegs(e,t){let n=[];for(let r of e)n.push(...this.eventRangeToSegs(r,t));return n}eventRangeToSegs(e,t){let n,r,i,{dateEnv:s}=this.context,{nextDayThreshold:o}=this.context.options,a=e.range,l=e.def.allDay,c=[];for(n=0;n<t.length;n+=1)if(r=ir(a,t[n]),r&&(i={component:this,eventRange:e,start:r.start,end:r.end,isStart:e.isStart&&r.start.valueOf()===a.start.valueOf(),isEnd:e.isEnd&&r.end.valueOf()===a.end.valueOf(),dayIndex:n},c.push(i),!i.isEnd&&!l&&n+1<t.length&&a.end<s.add(t[n+1].start,o))){i.end=a.end,i.isEnd=!0;break}return c}},buttonTextKey:"list",listDayFormat:{month:"long",day:"numeric",year:"numeric"}},listDay:{type:"list",duration:{days:1},listDayFormat:{weekday:"long"}},listWeek:{type:"list",duration:{weeks:1},listDayFormat:{weekday:"long"},listDaySideFormat:{month:"long",day:"numeric",year:"numeric"}},listMonth:{type:"list",duration:{month:1},listDaySideFormat:{weekday:"long"}},listYear:{type:"list",duration:{year:1},listDaySideFormat:{weekday:"long"}}}});class Sc extends cs{constructor(){super(...arguments),this.buildDayTableModel=Gt(Rl),this.slicer=new wl,this.state={labelId:Le()}}render(){const{props:e,state:t,context:n}=this,{dateProfile:r,forPrint:i}=e,{options:s}=n,o=this.buildDayTableModel(r,n.dateProfileGenerator),a=this.slicer.sliceProps(e,r,s.nextDayThreshold,n,o),l=null!=e.tableWidth?e.tableWidth/s.aspectRatio:null,c=o.cells.length,d=null!=l?l/c:null;return p("div",{ref:e.elRef,"data-date":e.isoDateStr,className:"fc-multimonth-month",style:{width:e.width},role:"grid","aria-labelledby":t.labelId},p("div",{className:"fc-multimonth-header",style:{marginBottom:d},role:"presentation"},p("div",{className:"fc-multimonth-title",id:t.labelId},n.dateEnv.format(e.dateProfile.currentRange.start,e.titleFormat)),p("table",{className:["fc-multimonth-header-table",n.theme.getClass("table")].join(" "),role:"presentation"},p("thead",{role:"rowgroup"},p(xs,{dateProfile:e.dateProfile,dates:o.headerDates,datesRepDistinctDays:!1})))),p("div",{className:["fc-multimonth-daygrid","fc-daygrid","fc-daygrid-body",!i&&"fc-daygrid-body-balanced",i&&"fc-daygrid-body-unbalanced",i&&"fc-daygrid-body-natural"].join(" "),style:{marginTop:-d}},p("table",{className:["fc-multimonth-daygrid-table",n.theme.getClass("table")].join(" "),style:{height:i?"":l},role:"presentation"},p("tbody",{role:"rowgroup"},p(Sl,Object.assign({},a,{dateProfile:r,cells:o.cells,eventSelection:e.eventSelection,dayMaxEvents:!i,dayMaxEventRows:!i,showWeekNumbers:s.weekNumbers,clientWidth:e.clientWidth,clientHeight:e.clientHeight,forPrint:i}))))))}}const Dc=ft(1,"month");function Ac(e,t,n,r,i){const{start:s,end:o}=t.currentRange;let a=s;const l=[];for(;a.valueOf()<o.valueOf();){const s=n.add(a,Dc),o={start:e.skipHiddenDays(a),end:e.skipHiddenDays(s,-1,!0)};let c=_l({currentRange:o,snapToWeek:!0,fixedWeekCount:r,dateEnv:n});c={start:e.skipHiddenDays(c.start),end:e.skipHiddenDays(c.end,-1,!0)};const d=t.activeRange?ir(t.activeRange,i?c:o):null;l.push({currentDate:t.currentDate,isValid:t.isValid,validRange:t.validRange,renderRange:c,activeRange:d,currentRange:o,currentRangeUnit:"month",isRangeAllDay:!0,dateIncrement:t.dateIncrement,slotMinTime:t.slotMaxTime,slotMaxTime:t.slotMinTime}),a=s}return l}const wc=an({year:"numeric",month:"long"}),Cc=an({month:"long"});function Rc(e,t){return e||(t[0].currentRange.start.getUTCFullYear()!==t[t.length-1].currentRange.start.getUTCFullYear()?wc:Cc)}const xc={multiMonthTitleFormat:an,multiMonthMaxColumns:Number,multiMonthMinWidth:Number};xe(".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}");var _c=No({name:"@fullcalendar/multimonth",initialView:"multiMonthYear",optionRefiners:xc,views:{multiMonth:{component:class extends cs{constructor(){super(...arguments),this.splitDateProfileByMonth=Gt(Ac),this.buildMonthFormat=Gt(Rc),this.scrollElRef={current:null},this.firstMonthElRef={current:null},this.needsScrollReset=!1,this.handleSizing=e=>{e&&this.updateSize()}}render(){const{context:e,props:t,state:n}=this,{options:r}=e,{clientWidth:i,clientHeight:s}=n,o=n.monthHPadding||0,a=Math.min(null!=i?Math.floor(i/(r.multiMonthMinWidth+o)):1,r.multiMonthMaxColumns)||1,l=100/a+"%",c=null==i?null:i/a-o,d=null!=i&&1===a,u=this.splitDateProfileByMonth(e.dateProfileGenerator,t.dateProfile,e.dateEnv,!d&&r.fixedWeekCount,r.showNonCurrentDates),h=this.buildMonthFormat(r.multiMonthTitleFormat,u),f=["fc-multimonth",d?"fc-multimonth-singlecol":"fc-multimonth-multicol",null!=c&&c<400?"fc-multimonth-compact":"",t.isHeightAuto?"":"fc-scroller"];return p(er,{elRef:this.scrollElRef,elClasses:f,viewSpec:e.viewSpec},u.map((e,n)=>{const r=Wt(e.currentRange.start);return p(Sc,Object.assign({},t,{key:r,isoDateStr:r,elRef:0===n?this.firstMonthElRef:void 0,titleFormat:h,dateProfile:e,width:l,tableWidth:c,clientWidth:i,clientHeight:s}))}))}componentDidMount(){this.updateSize(),this.context.addResizeHandler(this.handleSizing),this.requestScrollReset()}componentDidUpdate(e){Cn(e,this.props)||this.handleSizing(!1),e.dateProfile!==this.props.dateProfile?this.requestScrollReset():this.flushScrollReset()}componentWillUnmount(){this.context.removeResizeHandler(this.handleSizing)}updateSize(){const e=this.scrollElRef.current,t=this.firstMonthElRef.current;e&&this.setState({clientWidth:e.clientWidth,clientHeight:e.clientHeight}),t&&e&&null==this.state.monthHPadding&&this.setState({monthHPadding:e.clientWidth-t.firstChild.offsetWidth})}requestScrollReset(){this.needsScrollReset=!0,this.flushScrollReset()}flushScrollReset(){if(this.needsScrollReset&&null!=this.state.monthHPadding){const{currentDate:e}=this.props.dateProfile,t=this.scrollElRef.current,n=t.querySelector(`[data-date="${Wt(e)}"]`);t.scrollTop=n.getBoundingClientRect().top-this.firstMonthElRef.current.getBoundingClientRect().top,this.needsScrollReset=!1}}shouldComponentUpdate(){return!0}},dateProfileGeneratorClass:xl,multiMonthMinWidth:350,multiMonthMaxColumns:3},multiMonthYear:{type:"multiMonth",duration:{years:1},fixedWeekCount:!0,showNonCurrentDates:!1}}});return la.push(el,Tl,uc,Ec,_c),e.Calendar=class extends Pi{constructor(e,t={}){super(),this.isRendering=!1,this.isRendered=!1,this.currentClassNames=[],this.customContentRenderId=0,this.handleAction=e=>{switch(e.type){case"SET_EVENT_DRAG":case"SET_EVENT_RESIZE":this.renderRunner.tryDrain()}},this.handleData=e=>{this.currentData=e,this.renderRunner.request(e.calendarOptions.rerenderDelay)},this.handleRenderRequest=()=>{if(this.isRendering){this.isRendered=!0;let{currentData:e}=this;jn(()=>{U(p(Ti,{options:e.calendarOptions,theme:e.theme,emitter:e.emitter},(t,n,r,i)=>(this.setClassNames(t),this.setHeight(n),p($n.Provider,{value:this.customContentRenderId},p(_a,Object.assign({isHeightAuto:r,forPrint:i},e))))),this.el)})}else this.isRendered&&(this.isRendered=!1,U(null,this.el),this.setClassNames([]),this.setHeight(""))},function(e){e.isConnected&&e.getRootNode&&_e(e.getRootNode())}(e),this.el=e,this.renderRunner=new Me(this.handleRenderRequest),new ha({optionOverrides:t,calendarApi:this,onAction:this.handleAction,onData:this.handleData})}render(){let e=this.isRendering;e?this.customContentRenderId+=1:this.isRendering=!0,this.renderRunner.request(),e&&this.updateSize()}destroy(){this.isRendering&&(this.isRendering=!1,this.renderRunner.request())}updateSize(){jn(()=>{super.updateSize()})}batchRendering(e){this.renderRunner.pause("batchRendering"),e(),this.renderRunner.resume("batchRendering")}pauseRendering(){this.renderRunner.pause("pauseRendering")}resumeRendering(){this.renderRunner.resume("pauseRendering",!0)}resetOptions(e,t){this.currentDataManager.resetOptions(e,t)}setClassNames(e){if(!St(e,this.currentClassNames)){let{classList:t}=this.el;for(let e of this.currentClassNames)t.remove(e);for(let n of e)t.add(n);this.currentClassNames=e}}setHeight(e){je(this.el,"height",e)}},e.Draggable=class{constructor(e,t={}){this.handlePointerDown=e=>{let{dragging:t}=this,{minDistance:n,longPressDelay:r}=this.settings;t.minDistance=null!=n?n:e.isTouch?0:cn.eventDragMinDistance,t.delay=e.isTouch?null!=r?r:cn.longPressDelay:0},this.handleDragStart=e=>{e.isTouch&&this.dragging.delay&&e.subjectEl.classList.contains("fc-event")&&this.dragging.mirror.getMirrorEl().classList.add("fc-event-selected")},this.settings=t;let n=this.dragging=new Fa(e);n.touchScrollAllowed=!1,null!=t.itemSelector&&(n.pointer.selector=t.itemSelector),null!=t.appendTo&&(n.mirror.parentNode=t.appendTo),n.emitter.on("pointerdown",this.handlePointerDown),n.emitter.on("dragstart",this.handleDragStart),new Ja(n,t.eventData)}destroy(){this.dragging.destroy()}},e.Internal=Ro,e.JsonRequestError=Ci,e.Preact=xo,e.ThirdPartyDraggable=class{constructor(e,t){let n=document;e===document||e instanceof Element?(n=e,t=t||{}):t=e||{};let r=this.dragging=new Ka(n);"string"==typeof t.itemSelector?r.pointer.selector=t.itemSelector:n===document&&(r.pointer.selector="[data-event]"),"string"==typeof t.mirrorSelector&&(r.mirrorSelector=t.mirrorSelector),new Ja(r,t.eventData).hitDragging.disablePointCheck=!0}destroy(){this.dragging.destroy()}},e.createPlugin=No,e.formatDate=function(e,t={}){let n=Ma(t),r=an(t),i=n.createMarkerMeta(e);return i?n.format(i.marker,r,{forcedTzo:i.forcedTzo}):""},e.formatRange=function(e,t,n){let r=Ma("object"==typeof n&&n?n:{}),i=an(n),s=r.createMarkerMeta(e),o=r.createMarkerMeta(t);return s&&o?r.formatRange(s.marker,o.marker,i,{forcedStartTzo:s.forcedTzo,forcedEndTzo:o.forcedTzo,isEndExclusive:n.isEndExclusive,defaultSeparator:cn.defaultRangeSeparator}):""},e.globalLocales=_o,e.globalPlugins=la,e.sliceEvents=function(e,t){return ri(e.eventStore,e.eventUiBases,e.dateProfile.activeRange,t?e.nextDayThreshold:null).fg},e.version="6.1.17",Object.defineProperty(e,"__esModule",{value:!0}),e}({}); \ No newline at end of file
diff --git a/public/js/fullcalendar/examples/background-events.html b/public/js/fullcalendar/examples/background-events.html
new file mode 100644
index 0000000..911e0b3
--- /dev/null
+++ b/public/js/fullcalendar/examples/background-events.html
@@ -0,0 +1,101 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 headerToolbar: {
13 left: 'prev,next today',
14 center: 'title',
15 right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
16 },
17 initialDate: '2023-01-12',
18 navLinks: true, // can click day/week names to navigate views
19 businessHours: true, // display business hours
20 editable: true,
21 selectable: true,
22 events: [
23 {
24 title: 'Business Lunch',
25 start: '2023-01-03T13:00:00',
26 constraint: 'businessHours'
27 },
28 {
29 title: 'Meeting',
30 start: '2023-01-13T11:00:00',
31 constraint: 'availableForMeeting', // defined below
32 color: '#257e4a'
33 },
34 {
35 title: 'Conference',
36 start: '2023-01-18',
37 end: '2023-01-20'
38 },
39 {
40 title: 'Party',
41 start: '2023-01-29T20:00:00'
42 },
43
44 // areas where "Meeting" must be dropped
45 {
46 groupId: 'availableForMeeting',
47 start: '2023-01-11T10:00:00',
48 end: '2023-01-11T16:00:00',
49 display: 'background'
50 },
51 {
52 groupId: 'availableForMeeting',
53 start: '2023-01-13T10:00:00',
54 end: '2023-01-13T16:00:00',
55 display: 'background'
56 },
57
58 // red areas where no events can be dropped
59 {
60 start: '2023-01-24',
61 end: '2023-01-28',
62 overlap: false,
63 display: 'background',
64 color: '#ff9f89'
65 },
66 {
67 start: '2023-01-06',
68 end: '2023-01-08',
69 overlap: false,
70 display: 'background',
71 color: '#ff9f89'
72 }
73 ]
74 });
75
76 calendar.render();
77 });
78
79</script>
80<style>
81
82 body {
83 margin: 40px 10px;
84 padding: 0;
85 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
86 font-size: 14px;
87 }
88
89 #calendar {
90 max-width: 1100px;
91 margin: 0 auto;
92 }
93
94</style>
95</head>
96<body>
97
98 <div id='calendar'></div>
99
100</body>
101</html>
diff --git a/public/js/fullcalendar/examples/daygrid-views.html b/public/js/fullcalendar/examples/daygrid-views.html
new file mode 100644
index 0000000..9dafe43
--- /dev/null
+++ b/public/js/fullcalendar/examples/daygrid-views.html
@@ -0,0 +1,104 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 headerToolbar: {
13 left: 'prevYear,prev,next,nextYear today',
14 center: 'title',
15 right: 'dayGridMonth,dayGridWeek,dayGridDay'
16 },
17 initialDate: '2023-01-12',
18 navLinks: true, // can click day/week names to navigate views
19 editable: true,
20 dayMaxEvents: true, // allow "more" link when too many events
21 events: [
22 {
23 title: 'All Day Event',
24 start: '2023-01-01'
25 },
26 {
27 title: 'Long Event',
28 start: '2023-01-07',
29 end: '2023-01-10'
30 },
31 {
32 groupId: 999,
33 title: 'Repeating Event',
34 start: '2023-01-09T16:00:00'
35 },
36 {
37 groupId: 999,
38 title: 'Repeating Event',
39 start: '2023-01-16T16:00:00'
40 },
41 {
42 title: 'Conference',
43 start: '2023-01-11',
44 end: '2023-01-13'
45 },
46 {
47 title: 'Meeting',
48 start: '2023-01-12T10:30:00',
49 end: '2023-01-12T12:30:00'
50 },
51 {
52 title: 'Lunch',
53 start: '2023-01-12T12:00:00'
54 },
55 {
56 title: 'Meeting',
57 start: '2023-01-12T14:30:00'
58 },
59 {
60 title: 'Happy Hour',
61 start: '2023-01-12T17:30:00'
62 },
63 {
64 title: 'Dinner',
65 start: '2023-01-12T20:00:00'
66 },
67 {
68 title: 'Birthday Party',
69 start: '2023-01-13T07:00:00'
70 },
71 {
72 title: 'Click for Google',
73 url: 'http://google.com/',
74 start: '2023-01-28'
75 }
76 ]
77 });
78
79 calendar.render();
80 });
81
82</script>
83<style>
84
85 body {
86 margin: 40px 10px;
87 padding: 0;
88 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
89 font-size: 14px;
90 }
91
92 #calendar {
93 max-width: 1100px;
94 margin: 0 auto;
95 }
96
97</style>
98</head>
99<body>
100
101 <div id='calendar'></div>
102
103</body>
104</html>
diff --git a/public/js/fullcalendar/examples/external-dragging-2cals.html b/public/js/fullcalendar/examples/external-dragging-2cals.html
new file mode 100644
index 0000000..066685d
--- /dev/null
+++ b/public/js/fullcalendar/examples/external-dragging-2cals.html
@@ -0,0 +1,69 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var srcCalendarEl = document.getElementById('source-calendar');
10 var destCalendarEl = document.getElementById('destination-calendar');
11
12 var srcCalendar = new FullCalendar.Calendar(srcCalendarEl, {
13 editable: true,
14 initialDate: '2023-01-12',
15 events: [
16 {
17 title: 'event1',
18 start: '2023-01-11T10:00:00',
19 end: '2023-01-11T16:00:00'
20 },
21 {
22 title: 'event2',
23 start: '2023-01-13T10:00:00',
24 end: '2023-01-13T16:00:00'
25 }
26 ],
27 eventLeave: function(info) {
28 console.log('event left!', info.event);
29 }
30 });
31
32 var destCalendar = new FullCalendar.Calendar(destCalendarEl, {
33 initialDate: '2023-01-12',
34 editable: true,
35 droppable: true, // will let it receive events!
36 eventReceive: function(info) {
37 console.log('event received!', info.event);
38 }
39 });
40
41 srcCalendar.render();
42 destCalendar.render();
43 });
44
45</script>
46<style>
47
48 body {
49 margin: 20px 0 0 20px;
50 font-size: 14px;
51 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
52 }
53
54 #source-calendar,
55 #destination-calendar {
56 float: left;
57 width: 600px;
58 margin: 0 20px 20px 0;
59 }
60
61</style>
62</head>
63<body>
64
65 <div id='source-calendar'></div>
66 <div id='destination-calendar'></div>
67
68</body>
69</html>
diff --git a/public/js/fullcalendar/examples/external-dragging-builtin.html b/public/js/fullcalendar/examples/external-dragging-builtin.html
new file mode 100644
index 0000000..78fcd89
--- /dev/null
+++ b/public/js/fullcalendar/examples/external-dragging-builtin.html
@@ -0,0 +1,149 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9
10 /* initialize the external events
11 -----------------------------------------------------------------*/
12
13 var containerEl = document.getElementById('external-events-list');
14 new FullCalendar.Draggable(containerEl, {
15 itemSelector: '.fc-event',
16 eventData: function(eventEl) {
17 return {
18 title: eventEl.innerText.trim()
19 }
20 }
21 });
22
23 //// the individual way to do it
24 // var containerEl = document.getElementById('external-events-list');
25 // var eventEls = Array.prototype.slice.call(
26 // containerEl.querySelectorAll('.fc-event')
27 // );
28 // eventEls.forEach(function(eventEl) {
29 // new FullCalendar.Draggable(eventEl, {
30 // eventData: {
31 // title: eventEl.innerText.trim(),
32 // }
33 // });
34 // });
35
36 /* initialize the calendar
37 -----------------------------------------------------------------*/
38
39 var calendarEl = document.getElementById('calendar');
40 var calendar = new FullCalendar.Calendar(calendarEl, {
41 headerToolbar: {
42 left: 'prev,next today',
43 center: 'title',
44 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
45 },
46 editable: true,
47 droppable: true, // this allows things to be dropped onto the calendar
48 drop: function(arg) {
49 // is the "remove after drop" checkbox checked?
50 if (document.getElementById('drop-remove').checked) {
51 // if so, remove the element from the "Draggable Events" list
52 arg.draggedEl.parentNode.removeChild(arg.draggedEl);
53 }
54 }
55 });
56 calendar.render();
57
58 });
59
60</script>
61<style>
62
63 body {
64 margin-top: 40px;
65 font-size: 14px;
66 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
67 }
68
69 #external-events {
70 position: fixed;
71 left: 20px;
72 top: 20px;
73 width: 150px;
74 padding: 0 10px;
75 border: 1px solid #ccc;
76 background: #eee;
77 text-align: left;
78 }
79
80 #external-events h4 {
81 font-size: 16px;
82 margin-top: 0;
83 padding-top: 1em;
84 }
85
86 #external-events .fc-event {
87 margin: 3px 0;
88 cursor: move;
89 }
90
91 #external-events p {
92 margin: 1.5em 0;
93 font-size: 11px;
94 color: #666;
95 }
96
97 #external-events p input {
98 margin: 0;
99 vertical-align: middle;
100 }
101
102 #calendar-wrap {
103 margin-left: 200px;
104 }
105
106 #calendar {
107 max-width: 1100px;
108 margin: 0 auto;
109 }
110
111</style>
112</head>
113<body>
114 <div id='wrap'>
115
116 <div id='external-events'>
117 <h4>Draggable Events</h4>
118
119 <div id='external-events-list'>
120 <div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
121 <div class='fc-event-main'>My Event 1</div>
122 </div>
123 <div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
124 <div class='fc-event-main'>My Event 2</div>
125 </div>
126 <div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
127 <div class='fc-event-main'>My Event 3</div>
128 </div>
129 <div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
130 <div class='fc-event-main'>My Event 4</div>
131 </div>
132 <div class='fc-event fc-h-event fc-daygrid-event fc-daygrid-block-event'>
133 <div class='fc-event-main'>My Event 5</div>
134 </div>
135 </div>
136
137 <p>
138 <input type='checkbox' id='drop-remove' />
139 <label for='drop-remove'>remove after drop</label>
140 </p>
141 </div>
142
143 <div id='calendar-wrap'>
144 <div id='calendar'></div>
145 </div>
146
147 </div>
148</body>
149</html>
diff --git a/public/js/fullcalendar/examples/full-height.html b/public/js/fullcalendar/examples/full-height.html
new file mode 100644
index 0000000..18b55f8
--- /dev/null
+++ b/public/js/fullcalendar/examples/full-height.html
@@ -0,0 +1,125 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 height: '100%',
13 expandRows: true,
14 slotMinTime: '08:00',
15 slotMaxTime: '20:00',
16 headerToolbar: {
17 left: 'prev,next today',
18 center: 'title',
19 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
20 },
21 initialView: 'dayGridMonth',
22 initialDate: '2023-01-12',
23 navLinks: true, // can click day/week names to navigate views
24 editable: true,
25 selectable: true,
26 nowIndicator: true,
27 dayMaxEvents: true, // allow "more" link when too many events
28 events: [
29 {
30 title: 'All Day Event',
31 start: '2023-01-01',
32 },
33 {
34 title: 'Long Event',
35 start: '2023-01-07',
36 end: '2023-01-10'
37 },
38 {
39 groupId: 999,
40 title: 'Repeating Event',
41 start: '2023-01-09T16:00:00'
42 },
43 {
44 groupId: 999,
45 title: 'Repeating Event',
46 start: '2023-01-16T16:00:00'
47 },
48 {
49 title: 'Conference',
50 start: '2023-01-11',
51 end: '2023-01-13'
52 },
53 {
54 title: 'Meeting',
55 start: '2023-01-12T10:30:00',
56 end: '2023-01-12T12:30:00'
57 },
58 {
59 title: 'Lunch',
60 start: '2023-01-12T12:00:00'
61 },
62 {
63 title: 'Meeting',
64 start: '2023-01-12T14:30:00'
65 },
66 {
67 title: 'Happy Hour',
68 start: '2023-01-12T17:30:00'
69 },
70 {
71 title: 'Dinner',
72 start: '2023-01-12T20:00:00'
73 },
74 {
75 title: 'Birthday Party',
76 start: '2023-01-13T07:00:00'
77 },
78 {
79 title: 'Click for Google',
80 url: 'http://google.com/',
81 start: '2023-01-28'
82 }
83 ]
84 });
85
86 calendar.render();
87 });
88
89</script>
90<style>
91
92 html, body {
93 overflow: hidden; /* don't do scrollbars */
94 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
95 font-size: 14px;
96 }
97
98 #calendar-container {
99 position: fixed;
100 top: 0;
101 left: 0;
102 right: 0;
103 bottom: 0;
104 }
105
106 .fc-header-toolbar {
107 /*
108 the calendar will be butting up against the edges,
109 but let's scoot in the header's buttons
110 */
111 padding-top: 1em;
112 padding-left: 1em;
113 padding-right: 1em;
114 }
115
116</style>
117</head>
118<body>
119
120 <div id='calendar-container'>
121 <div id='calendar'></div>
122 </div>
123
124</body>
125</html>
diff --git a/public/js/fullcalendar/examples/list-sticky-header.html b/public/js/fullcalendar/examples/list-sticky-header.html
new file mode 100644
index 0000000..487af31
--- /dev/null
+++ b/public/js/fullcalendar/examples/list-sticky-header.html
@@ -0,0 +1,76 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 height: 'auto',
13 // stickyHeaderDates: false, // for disabling
14
15 headerToolbar: {
16 left: 'prev,next today',
17 center: 'title',
18 right: 'listMonth,listYear'
19 },
20
21 // customize the button names,
22 // otherwise they'd all just say "list"
23 views: {
24 listMonth: { buttonText: 'list month' },
25 listYear: { buttonText: 'list year' }
26 },
27
28 initialView: 'listYear',
29 initialDate: '2023-01-12',
30 navLinks: true, // can click day/week names to navigate views
31 editable: true,
32 events: [
33 {
34 title: 'repeating event 1',
35 daysOfWeek: [ 1, 2, 3 ],
36 duration: '00:30'
37 },
38 {
39 title: 'repeating event 2',
40 daysOfWeek: [ 1, 2, 3 ],
41 duration: '00:30'
42 },
43 {
44 title: 'repeating event 3',
45 daysOfWeek: [ 1, 2, 3 ],
46 duration: '00:30'
47 }
48 ]
49 });
50
51 calendar.render();
52 });
53
54</script>
55<style>
56
57 body {
58 margin: 40px 10px;
59 padding: 0;
60 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
61 font-size: 14px;
62 }
63
64 #calendar {
65 max-width: 1100px;
66 margin: 0 auto;
67 }
68
69</style>
70</head>
71<body>
72
73 <div id='calendar'></div>
74
75</body>
76</html>
diff --git a/public/js/fullcalendar/examples/list-views.html b/public/js/fullcalendar/examples/list-views.html
new file mode 100644
index 0000000..cb219d0
--- /dev/null
+++ b/public/js/fullcalendar/examples/list-views.html
@@ -0,0 +1,114 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12
13 headerToolbar: {
14 left: 'prev,next today',
15 center: 'title',
16 right: 'listDay,listWeek'
17 },
18
19 // customize the button names,
20 // otherwise they'd all just say "list"
21 views: {
22 listDay: { buttonText: 'list day' },
23 listWeek: { buttonText: 'list week' }
24 },
25
26 initialView: 'listWeek',
27 initialDate: '2023-01-12',
28 navLinks: true, // can click day/week names to navigate views
29 editable: true,
30 dayMaxEvents: true, // allow "more" link when too many events
31 events: [
32 {
33 title: 'All Day Event',
34 start: '2023-01-01'
35 },
36 {
37 title: 'Long Event',
38 start: '2023-01-07',
39 end: '2023-01-10'
40 },
41 {
42 groupId: 999,
43 title: 'Repeating Event',
44 start: '2023-01-09T16:00:00'
45 },
46 {
47 groupId: 999,
48 title: 'Repeating Event',
49 start: '2023-01-16T16:00:00'
50 },
51 {
52 title: 'Conference',
53 start: '2023-01-11',
54 end: '2023-01-13'
55 },
56 {
57 title: 'Meeting',
58 start: '2023-01-12T10:30:00',
59 end: '2023-01-12T12:30:00'
60 },
61 {
62 title: 'Lunch',
63 start: '2023-01-12T12:00:00'
64 },
65 {
66 title: 'Meeting',
67 start: '2023-01-12T14:30:00'
68 },
69 {
70 title: 'Happy Hour',
71 start: '2023-01-12T17:30:00'
72 },
73 {
74 title: 'Dinner',
75 start: '2023-01-12T20:00:00'
76 },
77 {
78 title: 'Birthday Party',
79 start: '2023-01-13T07:00:00'
80 },
81 {
82 title: 'Click for Google',
83 url: 'http://google.com/',
84 start: '2023-01-28'
85 }
86 ]
87 });
88
89 calendar.render();
90 });
91
92</script>
93<style>
94
95 body {
96 margin: 40px 10px;
97 padding: 0;
98 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
99 font-size: 14px;
100 }
101
102 #calendar {
103 max-width: 1100px;
104 margin: 0 auto;
105 }
106
107</style>
108</head>
109<body>
110
111 <div id='calendar'></div>
112
113</body>
114</html>
diff --git a/public/js/fullcalendar/examples/month-view.html b/public/js/fullcalendar/examples/month-view.html
new file mode 100644
index 0000000..dbd8861
--- /dev/null
+++ b/public/js/fullcalendar/examples/month-view.html
@@ -0,0 +1,100 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 initialDate: '2023-01-12',
13 editable: true,
14 selectable: true,
15 businessHours: true,
16 dayMaxEvents: true, // allow "more" link when too many events
17 events: [
18 {
19 title: 'All Day Event',
20 start: '2023-01-01'
21 },
22 {
23 title: 'Long Event',
24 start: '2023-01-07',
25 end: '2023-01-10'
26 },
27 {
28 groupId: 999,
29 title: 'Repeating Event',
30 start: '2023-01-09T16:00:00'
31 },
32 {
33 groupId: 999,
34 title: 'Repeating Event',
35 start: '2023-01-16T16:00:00'
36 },
37 {
38 title: 'Conference',
39 start: '2023-01-11',
40 end: '2023-01-13'
41 },
42 {
43 title: 'Meeting',
44 start: '2023-01-12T10:30:00',
45 end: '2023-01-12T12:30:00'
46 },
47 {
48 title: 'Lunch',
49 start: '2023-01-12T12:00:00'
50 },
51 {
52 title: 'Meeting',
53 start: '2023-01-12T14:30:00'
54 },
55 {
56 title: 'Happy Hour',
57 start: '2023-01-12T17:30:00'
58 },
59 {
60 title: 'Dinner',
61 start: '2023-01-12T20:00:00'
62 },
63 {
64 title: 'Birthday Party',
65 start: '2023-01-13T07:00:00'
66 },
67 {
68 title: 'Click for Google',
69 url: 'http://google.com/',
70 start: '2023-01-28'
71 }
72 ]
73 });
74
75 calendar.render();
76 });
77
78</script>
79<style>
80
81 body {
82 margin: 40px 10px;
83 padding: 0;
84 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
85 font-size: 14px;
86 }
87
88 #calendar {
89 max-width: 1100px;
90 margin: 0 auto;
91 }
92
93</style>
94</head>
95<body>
96
97 <div id='calendar'></div>
98
99</body>
100</html>
diff --git a/public/js/fullcalendar/examples/multimonth-view.html b/public/js/fullcalendar/examples/multimonth-view.html
new file mode 100644
index 0000000..feb9d23
--- /dev/null
+++ b/public/js/fullcalendar/examples/multimonth-view.html
@@ -0,0 +1,110 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 headerToolbar: {
13 left: 'prev,next today',
14 center: 'title',
15 right: 'multiMonthYear,dayGridMonth,timeGridWeek'
16 },
17 initialView: 'multiMonthYear',
18 initialDate: '2023-01-12',
19 editable: true,
20 selectable: true,
21 dayMaxEvents: true, // allow "more" link when too many events
22 // multiMonthMaxColumns: 1, // guarantee single column
23 // showNonCurrentDates: true,
24 // fixedWeekCount: false,
25 // businessHours: true,
26 // weekends: false,
27 events: [
28 {
29 title: 'All Day Event',
30 start: '2023-01-01'
31 },
32 {
33 title: 'Long Event',
34 start: '2023-01-07',
35 end: '2023-01-10'
36 },
37 {
38 groupId: 999,
39 title: 'Repeating Event',
40 start: '2023-01-09T16:00:00'
41 },
42 {
43 groupId: 999,
44 title: 'Repeating Event',
45 start: '2023-01-16T16:00:00'
46 },
47 {
48 title: 'Conference',
49 start: '2023-01-11',
50 end: '2023-01-13'
51 },
52 {
53 title: 'Meeting',
54 start: '2023-01-12T10:30:00',
55 end: '2023-01-12T12:30:00'
56 },
57 {
58 title: 'Lunch',
59 start: '2023-01-12T12:00:00'
60 },
61 {
62 title: 'Meeting',
63 start: '2023-01-12T14:30:00'
64 },
65 {
66 title: 'Happy Hour',
67 start: '2023-01-12T17:30:00'
68 },
69 {
70 title: 'Dinner',
71 start: '2023-01-12T20:00:00'
72 },
73 {
74 title: 'Birthday Party',
75 start: '2023-01-13T07:00:00'
76 },
77 {
78 title: 'Click for Google',
79 url: 'http://google.com/',
80 start: '2023-01-28'
81 }
82 ]
83 });
84
85 calendar.render();
86 });
87
88</script>
89<style>
90
91 body {
92 margin: 40px 10px;
93 padding: 0;
94 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
95 font-size: 14px;
96 }
97
98 #calendar {
99 max-width: 1200px;
100 margin: 0 auto;
101 }
102
103</style>
104</head>
105<body>
106
107 <div id='calendar'></div>
108
109</body>
110</html>
diff --git a/public/js/fullcalendar/examples/multiweek-view.html b/public/js/fullcalendar/examples/multiweek-view.html
new file mode 100644
index 0000000..5a175fb
--- /dev/null
+++ b/public/js/fullcalendar/examples/multiweek-view.html
@@ -0,0 +1,107 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 headerToolbar: {
13 left: 'prev,next today',
14 center: 'title',
15 right: 'dayGridYear,dayGridMonth,timeGridWeek'
16 },
17 initialView: 'dayGridYear',
18 initialDate: '2023-01-12',
19 editable: true,
20 selectable: true,
21 dayMaxEvents: true, // allow "more" link when too many events
22 // businessHours: true,
23 // weekends: false,
24 events: [
25 {
26 title: 'All Day Event',
27 start: '2023-01-01'
28 },
29 {
30 title: 'Long Event',
31 start: '2023-01-07',
32 end: '2023-01-10'
33 },
34 {
35 groupId: 999,
36 title: 'Repeating Event',
37 start: '2023-01-09T16:00:00'
38 },
39 {
40 groupId: 999,
41 title: 'Repeating Event',
42 start: '2023-01-16T16:00:00'
43 },
44 {
45 title: 'Conference',
46 start: '2023-01-11',
47 end: '2023-01-13'
48 },
49 {
50 title: 'Meeting',
51 start: '2023-01-12T10:30:00',
52 end: '2023-01-12T12:30:00'
53 },
54 {
55 title: 'Lunch',
56 start: '2023-01-12T12:00:00'
57 },
58 {
59 title: 'Meeting',
60 start: '2023-01-12T14:30:00'
61 },
62 {
63 title: 'Happy Hour',
64 start: '2023-01-12T17:30:00'
65 },
66 {
67 title: 'Dinner',
68 start: '2023-01-12T20:00:00'
69 },
70 {
71 title: 'Birthday Party',
72 start: '2023-01-13T07:00:00'
73 },
74 {
75 title: 'Click for Google',
76 url: 'http://google.com/',
77 start: '2023-01-28'
78 }
79 ]
80 });
81
82 calendar.render();
83 });
84
85</script>
86<style>
87
88 body {
89 margin: 40px 10px;
90 padding: 0;
91 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
92 font-size: 14px;
93 }
94
95 #calendar {
96 max-width: 1200px;
97 margin: 0 auto;
98 }
99
100</style>
101</head>
102<body>
103
104 <div id='calendar'></div>
105
106</body>
107</html>
diff --git a/public/js/fullcalendar/examples/natural-height.html b/public/js/fullcalendar/examples/natural-height.html
new file mode 100644
index 0000000..b62c41d
--- /dev/null
+++ b/public/js/fullcalendar/examples/natural-height.html
@@ -0,0 +1,108 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 initialDate: '2023-01-12',
13 initialView: 'timeGridWeek',
14 headerToolbar: {
15 left: 'prev,next today',
16 center: 'title',
17 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
18 },
19 height: 'auto',
20 navLinks: true, // can click day/week names to navigate views
21 editable: true,
22 selectable: true,
23 selectMirror: true,
24 nowIndicator: true,
25 events: [
26 {
27 title: 'All Day Event',
28 start: '2023-01-01',
29 },
30 {
31 title: 'Long Event',
32 start: '2023-01-07',
33 end: '2023-01-10'
34 },
35 {
36 groupId: 999,
37 title: 'Repeating Event',
38 start: '2023-01-09T16:00:00'
39 },
40 {
41 groupId: 999,
42 title: 'Repeating Event',
43 start: '2023-01-16T16:00:00'
44 },
45 {
46 title: 'Conference',
47 start: '2023-01-11',
48 end: '2023-01-13'
49 },
50 {
51 title: 'Meeting',
52 start: '2023-01-12T10:30:00',
53 end: '2023-01-12T12:30:00'
54 },
55 {
56 title: 'Lunch',
57 start: '2023-01-12T12:00:00'
58 },
59 {
60 title: 'Meeting',
61 start: '2023-01-12T14:30:00'
62 },
63 {
64 title: 'Happy Hour',
65 start: '2023-01-12T17:30:00'
66 },
67 {
68 title: 'Dinner',
69 start: '2023-01-12T20:00:00'
70 },
71 {
72 title: 'Birthday Party',
73 start: '2023-01-13T07:00:00'
74 },
75 {
76 title: 'Click for Google',
77 url: 'http://google.com/',
78 start: '2023-01-28'
79 }
80 ]
81 });
82
83 calendar.render();
84 });
85
86</script>
87<style>
88
89 body {
90 margin: 40px 10px;
91 padding: 0;
92 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
93 font-size: 14px;
94 }
95
96 #calendar {
97 max-width: 1100px;
98 margin: 0 auto;
99 }
100
101</style>
102</head>
103<body>
104
105 <div id='calendar'></div>
106
107</body>
108</html>
diff --git a/public/js/fullcalendar/examples/selectable.html b/public/js/fullcalendar/examples/selectable.html
new file mode 100644
index 0000000..785e90e
--- /dev/null
+++ b/public/js/fullcalendar/examples/selectable.html
@@ -0,0 +1,123 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 headerToolbar: {
13 left: 'prev,next today',
14 center: 'title',
15 right: 'dayGridMonth,timeGridWeek,timeGridDay'
16 },
17 initialDate: '2023-01-12',
18 navLinks: true, // can click day/week names to navigate views
19 selectable: true,
20 selectMirror: true,
21 select: function(arg) {
22 var title = prompt('Event Title:');
23 if (title) {
24 calendar.addEvent({
25 title: title,
26 start: arg.start,
27 end: arg.end,
28 allDay: arg.allDay
29 })
30 }
31 calendar.unselect()
32 },
33 eventClick: function(arg) {
34 if (confirm('Are you sure you want to delete this event?')) {
35 arg.event.remove()
36 }
37 },
38 editable: true,
39 dayMaxEvents: true, // allow "more" link when too many events
40 events: [
41 {
42 title: 'All Day Event',
43 start: '2023-01-01'
44 },
45 {
46 title: 'Long Event',
47 start: '2023-01-07',
48 end: '2023-01-10'
49 },
50 {
51 groupId: 999,
52 title: 'Repeating Event',
53 start: '2023-01-09T16:00:00'
54 },
55 {
56 groupId: 999,
57 title: 'Repeating Event',
58 start: '2023-01-16T16:00:00'
59 },
60 {
61 title: 'Conference',
62 start: '2023-01-11',
63 end: '2023-01-13'
64 },
65 {
66 title: 'Meeting',
67 start: '2023-01-12T10:30:00',
68 end: '2023-01-12T12:30:00'
69 },
70 {
71 title: 'Lunch',
72 start: '2023-01-12T12:00:00'
73 },
74 {
75 title: 'Meeting',
76 start: '2023-01-12T14:30:00'
77 },
78 {
79 title: 'Happy Hour',
80 start: '2023-01-12T17:30:00'
81 },
82 {
83 title: 'Dinner',
84 start: '2023-01-12T20:00:00'
85 },
86 {
87 title: 'Birthday Party',
88 start: '2023-01-13T07:00:00'
89 },
90 {
91 title: 'Click for Google',
92 url: 'http://google.com/',
93 start: '2023-01-28'
94 }
95 ]
96 });
97
98 calendar.render();
99 });
100
101</script>
102<style>
103
104 body {
105 margin: 40px 10px;
106 padding: 0;
107 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
108 font-size: 14px;
109 }
110
111 #calendar {
112 max-width: 1100px;
113 margin: 0 auto;
114 }
115
116</style>
117</head>
118<body>
119
120 <div id='calendar'></div>
121
122</body>
123</html>
diff --git a/public/js/fullcalendar/examples/timegrid-views-modal.html b/public/js/fullcalendar/examples/timegrid-views-modal.html
new file mode 100644
index 0000000..3b4a0fc
--- /dev/null
+++ b/public/js/fullcalendar/examples/timegrid-views-modal.html
@@ -0,0 +1,180 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 /*
9 From https://github.com/fullcalendar/fullcalendar/issues/5026
10 */
11
12 document.addEventListener('DOMContentLoaded', function() {
13 var calendarOptions = {
14 initialDate: '2023-01-12',
15 initialView: 'timeGridWeek',
16 nowIndicator: true,
17 headerToolbar: {
18 left: 'prev,next today',
19 center: 'title',
20 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
21 },
22 navLinks: true, // can click day/week names to navigate views
23 editable: true,
24 selectable: true,
25 selectMirror: true,
26 dayMaxEvents: true, // allow "more" link when too many events
27 events: [
28 {
29 title: 'All Day Event',
30 start: '2023-01-01',
31 },
32 {
33 title: 'Long Event',
34 start: '2023-01-07',
35 end: '2023-01-10'
36 },
37 {
38 groupId: 999,
39 title: 'Repeating Event',
40 start: '2023-01-09T16:00:00'
41 },
42 {
43 groupId: 999,
44 title: 'Repeating Event',
45 start: '2023-01-16T16:00:00'
46 },
47 {
48 title: 'Conference',
49 start: '2023-01-11',
50 end: '2023-01-13'
51 },
52 {
53 title: 'Meeting',
54 start: '2023-01-12T10:30:00',
55 end: '2023-01-12T12:30:00'
56 },
57 {
58 title: 'Lunch',
59 start: '2023-01-12T12:00:00'
60 },
61 {
62 title: 'Meeting',
63 start: '2023-01-12T14:30:00'
64 },
65 {
66 title: 'Happy Hour',
67 start: '2023-01-12T17:30:00'
68 },
69 {
70 title: 'Dinner',
71 start: '2023-01-12T20:00:00'
72 },
73 {
74 title: 'Birthday Party',
75 start: '2023-01-13T07:00:00'
76 },
77 {
78 title: 'Click for Google',
79 url: 'http://google.com/',
80 start: '2023-01-28'
81 }
82 ]
83 };
84
85 var calendar = new FullCalendar.Calendar(document.getElementById('calendar'), calendarOptions);
86 calendar.render();
87
88 var calendar2 = new FullCalendar.Calendar(document.getElementById('calendar2'), calendarOptions);
89 calendar2.render();
90
91 /*
92 Modal
93 */
94
95 var modal = document.querySelector('.modal');
96 var modalTrigger = document.querySelector('.modal-trigger');
97 var modalOverlay = document.querySelector('.modal-overlay');
98
99 modalTrigger.addEventListener('click', function() {
100 modal.classList.add('is-visible');
101 calendar2.updateSize();
102 });
103 modalOverlay.addEventListener('click', function() {
104 modal.classList.remove('is-visible');
105 });
106 });
107
108</script>
109<style>
110
111 body {
112 margin: 10px;
113 padding: 0;
114 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
115 font-size: 14px;
116 }
117
118 #calendar {
119 max-width: 1100px;
120 margin: 0 auto;
121 }
122
123 .modal {
124 display: none;
125 position: absolute;
126 z-index: 10000;
127 top: 0;
128 left: 0;
129 width: 100%;
130 height: 100%;
131 }
132
133 .modal.is-visible {
134 display: block;
135 }
136
137 .modal-overlay {
138 position: fixed;
139 z-index: 10;
140 top: 0;
141 left: 0;
142 width: 100%;
143 height: 100%;
144 background: hsla(0, 0%, 0%, 0.5);
145 }
146
147 .modal-wrapper {
148 position: absolute;
149 z-index: 9999;
150 top: 6em;
151 left: 50%;
152 width: 600px;
153 margin-left: -16em;
154 background-color: #fff;
155 box-shadow: 0 0 1.5em hsla(0, 0%, 0%, 0.35);
156 }
157
158 .modal-content {
159 padding: 1em;
160 }
161
162</style>
163</head>
164<body>
165
166 <button class='modal-trigger'>Show modal</button>
167
168 <div id='calendar'></div>
169
170 <div class='modal'>
171 <div class='modal-overlay'></div>
172 <div class='modal-wrapper'>
173 <div class='modal-content'>
174 <div id='calendar2'></div>
175 </div>
176 </div>
177 </div>
178
179</body>
180</html>
diff --git a/public/js/fullcalendar/examples/timegrid-views.html b/public/js/fullcalendar/examples/timegrid-views.html
new file mode 100644
index 0000000..9cd2527
--- /dev/null
+++ b/public/js/fullcalendar/examples/timegrid-views.html
@@ -0,0 +1,108 @@
1<!DOCTYPE html>
2<html>
3<head>
4<meta charset='utf-8' />
5<script src='../dist/index.global.js'></script>
6<script>
7
8 document.addEventListener('DOMContentLoaded', function() {
9 var calendarEl = document.getElementById('calendar');
10
11 var calendar = new FullCalendar.Calendar(calendarEl, {
12 initialDate: '2023-01-12',
13 initialView: 'timeGridWeek',
14 nowIndicator: true,
15 headerToolbar: {
16 left: 'prev,next today',
17 center: 'title',
18 right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
19 },
20 navLinks: true, // can click day/week names to navigate views
21 editable: true,
22 selectable: true,
23 selectMirror: true,
24 dayMaxEvents: true, // allow "more" link when too many events
25 events: [
26 {
27 title: 'All Day Event',
28 start: '2023-01-01',
29 },
30 {
31 title: 'Long Event',
32 start: '2023-01-07',
33 end: '2023-01-10'
34 },
35 {
36 groupId: 999,
37 title: 'Repeating Event',
38 start: '2023-01-09T16:00:00'
39 },
40 {
41 groupId: 999,
42 title: 'Repeating Event',
43 start: '2023-01-16T16:00:00'
44 },
45 {
46 title: 'Conference',
47 start: '2023-01-11',
48 end: '2023-01-13'
49 },
50 {
51 title: 'Meeting',
52 start: '2023-01-12T10:30:00',
53 end: '2023-01-12T12:30:00'
54 },
55 {
56 title: 'Lunch',
57 start: '2023-01-12T12:00:00'
58 },
59 {
60 title: 'Meeting',
61 start: '2023-01-12T14:30:00'
62 },
63 {
64 title: 'Happy Hour',
65 start: '2023-01-12T17:30:00'
66 },
67 {
68 title: 'Dinner',
69 start: '2023-01-12T20:00:00'
70 },
71 {
72 title: 'Birthday Party',
73 start: '2023-01-13T07:00:00'
74 },
75 {
76 title: 'Click for Google',
77 url: 'http://google.com/',
78 start: '2023-01-28'
79 }
80 ]
81 });
82
83 calendar.render();
84 });
85
86</script>
87<style>
88
89 body {
90 margin: 40px 10px;
91 padding: 0;
92 font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
93 font-size: 14px;
94 }
95
96 #calendar {
97 max-width: 1100px;
98 margin: 0 auto;
99 }
100
101</style>
102</head>
103<body>
104
105 <div id='calendar'></div>
106
107</body>
108</html>
diff --git a/public/js/fullcalendar/packages/bootstrap4/index.global.js b/public/js/fullcalendar/packages/bootstrap4/index.global.js
new file mode 100644
index 0000000..a699c90
--- /dev/null
+++ b/public/js/fullcalendar/packages/bootstrap4/index.global.js
@@ -0,0 +1,64 @@
1/*!
2FullCalendar Bootstrap 4 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/bootstrap4
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Bootstrap = (function (exports, core, internal$1) {
7 'use strict';
8
9 class BootstrapTheme extends internal$1.Theme {
10 }
11 BootstrapTheme.prototype.classes = {
12 root: 'fc-theme-bootstrap',
13 table: 'table-bordered',
14 tableCellShaded: 'table-active',
15 buttonGroup: 'btn-group',
16 button: 'btn btn-primary',
17 buttonActive: 'active',
18 popover: 'popover',
19 popoverHeader: 'popover-header',
20 popoverContent: 'popover-body',
21 };
22 BootstrapTheme.prototype.baseIconClass = 'fa';
23 BootstrapTheme.prototype.iconClasses = {
24 close: 'fa-times',
25 prev: 'fa-chevron-left',
26 next: 'fa-chevron-right',
27 prevYear: 'fa-angle-double-left',
28 nextYear: 'fa-angle-double-right',
29 };
30 BootstrapTheme.prototype.rtlIconClasses = {
31 prev: 'fa-chevron-right',
32 next: 'fa-chevron-left',
33 prevYear: 'fa-angle-double-right',
34 nextYear: 'fa-angle-double-left',
35 };
36 BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome'; // TODO: make TS-friendly. move the option-processing into this plugin
37 BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome';
38 BootstrapTheme.prototype.iconOverridePrefix = 'fa-';
39
40 var css_248z = ".fc-theme-bootstrap a:not([href]){color:inherit}.fc-theme-bootstrap .fc-more-link:hover{text-decoration:none}";
41 internal$1.injectStyles(css_248z);
42
43 var plugin = core.createPlugin({
44 name: '@fullcalendar/bootstrap',
45 themeClasses: {
46 bootstrap: BootstrapTheme,
47 },
48 });
49
50 var internal = {
51 __proto__: null,
52 BootstrapTheme: BootstrapTheme
53 };
54
55 core.globalPlugins.push(plugin);
56
57 exports.Internal = internal;
58 exports["default"] = plugin;
59
60 Object.defineProperty(exports, '__esModule', { value: true });
61
62 return exports;
63
64})({}, FullCalendar, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/bootstrap4/index.global.min.js b/public/js/fullcalendar/packages/bootstrap4/index.global.min.js
new file mode 100644
index 0000000..80100d7
--- /dev/null
+++ b/public/js/fullcalendar/packages/bootstrap4/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Bootstrap 4 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/bootstrap4
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Bootstrap=function(e,t,o){"use strict";class r extends o.Theme{}r.prototype.classes={root:"fc-theme-bootstrap",table:"table-bordered",tableCellShaded:"table-active",buttonGroup:"btn-group",button:"btn btn-primary",buttonActive:"active",popover:"popover",popoverHeader:"popover-header",popoverContent:"popover-body"},r.prototype.baseIconClass="fa",r.prototype.iconClasses={close:"fa-times",prev:"fa-chevron-left",next:"fa-chevron-right",prevYear:"fa-angle-double-left",nextYear:"fa-angle-double-right"},r.prototype.rtlIconClasses={prev:"fa-chevron-right",next:"fa-chevron-left",prevYear:"fa-angle-double-right",nextYear:"fa-angle-double-left"},r.prototype.iconOverrideOption="bootstrapFontAwesome",r.prototype.iconOverrideCustomButtonOption="bootstrapFontAwesome",r.prototype.iconOverridePrefix="fa-";o.injectStyles(".fc-theme-bootstrap a:not([href]){color:inherit}.fc-theme-bootstrap .fc-more-link:hover{text-decoration:none}");var a=t.createPlugin({name:"@fullcalendar/bootstrap",themeClasses:{bootstrap:r}}),n={__proto__:null,BootstrapTheme:r};return t.globalPlugins.push(a),e.Internal=n,e.default=a,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/bootstrap5/index.global.js b/public/js/fullcalendar/packages/bootstrap5/index.global.js
new file mode 100644
index 0000000..0368f6a
--- /dev/null
+++ b/public/js/fullcalendar/packages/bootstrap5/index.global.js
@@ -0,0 +1,64 @@
1/*!
2FullCalendar Bootstrap 5 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/bootstrap5
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Bootstrap5 = (function (exports, core, internal$1) {
7 'use strict';
8
9 class BootstrapTheme extends internal$1.Theme {
10 }
11 BootstrapTheme.prototype.classes = {
12 root: 'fc-theme-bootstrap5',
13 tableCellShaded: 'fc-theme-bootstrap5-shaded',
14 buttonGroup: 'btn-group',
15 button: 'btn btn-primary',
16 buttonActive: 'active',
17 popover: 'popover',
18 popoverHeader: 'popover-header',
19 popoverContent: 'popover-body',
20 };
21 BootstrapTheme.prototype.baseIconClass = 'bi';
22 BootstrapTheme.prototype.iconClasses = {
23 close: 'bi-x-lg',
24 prev: 'bi-chevron-left',
25 next: 'bi-chevron-right',
26 prevYear: 'bi-chevron-double-left',
27 nextYear: 'bi-chevron-double-right',
28 };
29 BootstrapTheme.prototype.rtlIconClasses = {
30 prev: 'bi-chevron-right',
31 next: 'bi-chevron-left',
32 prevYear: 'bi-chevron-double-right',
33 nextYear: 'bi-chevron-double-left',
34 };
35 // wtf
36 BootstrapTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
37 BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'icon';
38 BootstrapTheme.prototype.iconOverridePrefix = 'bi-';
39
40 var css_248z = ".fc-theme-bootstrap5 a:not([href]){color:inherit;text-decoration:inherit}.fc-theme-bootstrap5 .fc-list,.fc-theme-bootstrap5 .fc-scrollgrid,.fc-theme-bootstrap5 td,.fc-theme-bootstrap5 th{border:1px solid var(--bs-gray-400)}.fc-theme-bootstrap5 .fc-scrollgrid{border-bottom-width:0;border-right-width:0}.fc-theme-bootstrap5-shaded{background-color:var(--bs-gray-200)}";
41 internal$1.injectStyles(css_248z);
42
43 var plugin = core.createPlugin({
44 name: '@fullcalendar/bootstrap5',
45 themeClasses: {
46 bootstrap5: BootstrapTheme,
47 },
48 });
49
50 var internal = {
51 __proto__: null,
52 BootstrapTheme: BootstrapTheme
53 };
54
55 core.globalPlugins.push(plugin);
56
57 exports.Internal = internal;
58 exports["default"] = plugin;
59
60 Object.defineProperty(exports, '__esModule', { value: true });
61
62 return exports;
63
64})({}, FullCalendar, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/bootstrap5/index.global.min.js b/public/js/fullcalendar/packages/bootstrap5/index.global.min.js
new file mode 100644
index 0000000..d3b54e1
--- /dev/null
+++ b/public/js/fullcalendar/packages/bootstrap5/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Bootstrap 5 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/bootstrap5
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Bootstrap5=function(e,t,o){"use strict";class r extends o.Theme{}r.prototype.classes={root:"fc-theme-bootstrap5",tableCellShaded:"fc-theme-bootstrap5-shaded",buttonGroup:"btn-group",button:"btn btn-primary",buttonActive:"active",popover:"popover",popoverHeader:"popover-header",popoverContent:"popover-body"},r.prototype.baseIconClass="bi",r.prototype.iconClasses={close:"bi-x-lg",prev:"bi-chevron-left",next:"bi-chevron-right",prevYear:"bi-chevron-double-left",nextYear:"bi-chevron-double-right"},r.prototype.rtlIconClasses={prev:"bi-chevron-right",next:"bi-chevron-left",prevYear:"bi-chevron-double-right",nextYear:"bi-chevron-double-left"},r.prototype.iconOverrideOption="buttonIcons",r.prototype.iconOverrideCustomButtonOption="icon",r.prototype.iconOverridePrefix="bi-";o.injectStyles(".fc-theme-bootstrap5 a:not([href]){color:inherit;text-decoration:inherit}.fc-theme-bootstrap5 .fc-list,.fc-theme-bootstrap5 .fc-scrollgrid,.fc-theme-bootstrap5 td,.fc-theme-bootstrap5 th{border:1px solid var(--bs-gray-400)}.fc-theme-bootstrap5 .fc-scrollgrid{border-bottom-width:0;border-right-width:0}.fc-theme-bootstrap5-shaded{background-color:var(--bs-gray-200)}");var a=t.createPlugin({name:"@fullcalendar/bootstrap5",themeClasses:{bootstrap5:r}}),n={__proto__:null,BootstrapTheme:r};return t.globalPlugins.push(a),e.Internal=n,e.default=a,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/index.global.js b/public/js/fullcalendar/packages/core/index.global.js
new file mode 100644
index 0000000..5c22940
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/index.global.js
@@ -0,0 +1,9929 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6var FullCalendar = (function (exports) {
7 'use strict';
8
9 const styleTexts = [];
10 const styleEls = new Map();
11 function injectStyles(styleText) {
12 styleTexts.push(styleText);
13 styleEls.forEach((styleEl) => {
14 appendStylesTo(styleEl, styleText);
15 });
16 }
17 function ensureElHasStyles(el) {
18 if (el.isConnected && // sometimes true if SSR system simulates DOM
19 el.getRootNode // sometimes undefined if SSR system simulates DOM
20 ) {
21 registerStylesRoot(el.getRootNode());
22 }
23 }
24 function registerStylesRoot(rootNode) {
25 let styleEl = styleEls.get(rootNode);
26 if (!styleEl || !styleEl.isConnected) {
27 styleEl = rootNode.querySelector('style[data-fullcalendar]');
28 if (!styleEl) {
29 styleEl = document.createElement('style');
30 styleEl.setAttribute('data-fullcalendar', '');
31 const nonce = getNonceValue();
32 if (nonce) {
33 styleEl.nonce = nonce;
34 }
35 const parentEl = rootNode === document ? document.head : rootNode;
36 const insertBefore = rootNode === document
37 ? parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style')
38 : parentEl.firstChild;
39 parentEl.insertBefore(styleEl, insertBefore);
40 }
41 styleEls.set(rootNode, styleEl);
42 hydrateStylesRoot(styleEl);
43 }
44 }
45 function hydrateStylesRoot(styleEl) {
46 for (const styleText of styleTexts) {
47 appendStylesTo(styleEl, styleText);
48 }
49 }
50 function appendStylesTo(styleEl, styleText) {
51 const { sheet } = styleEl;
52 const ruleCnt = sheet.cssRules.length;
53 styleText.split('}').forEach((styleStr, i) => {
54 styleStr = styleStr.trim();
55 if (styleStr) {
56 sheet.insertRule(styleStr + '}', ruleCnt + i);
57 }
58 });
59 }
60 // nonce
61 // -------------------------------------------------------------------------------------------------
62 let queriedNonceValue;
63 function getNonceValue() {
64 if (queriedNonceValue === undefined) {
65 queriedNonceValue = queryNonceValue();
66 }
67 return queriedNonceValue;
68 }
69 /*
70 TODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag
71 */
72 function queryNonceValue() {
73 const metaWithNonce = document.querySelector('meta[name="csp-nonce"]');
74 if (metaWithNonce && metaWithNonce.hasAttribute('content')) {
75 return metaWithNonce.getAttribute('content');
76 }
77 const elWithNonce = document.querySelector('script[nonce]');
78 if (elWithNonce) {
79 return elWithNonce.nonce || '';
80 }
81 return '';
82 }
83 // main
84 // -------------------------------------------------------------------------------------------------
85 if (typeof document !== 'undefined') {
86 registerStylesRoot(document);
87 }
88
89 var css_248z = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}";
90 injectStyles(css_248z);
91
92 function removeElement(el) {
93 if (el.parentNode) {
94 el.parentNode.removeChild(el);
95 }
96 }
97 // Querying
98 // ----------------------------------------------------------------------------------------------------------------
99 function elementClosest(el, selector) {
100 if (el.closest) {
101 return el.closest(selector);
102 // really bad fallback for IE
103 // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
104 }
105 if (!document.documentElement.contains(el)) {
106 return null;
107 }
108 do {
109 if (elementMatches(el, selector)) {
110 return el;
111 }
112 el = (el.parentElement || el.parentNode);
113 } while (el !== null && el.nodeType === 1);
114 return null;
115 }
116 function elementMatches(el, selector) {
117 let method = el.matches || el.matchesSelector || el.msMatchesSelector;
118 return method.call(el, selector);
119 }
120 // accepts multiple subject els
121 // returns a real array. good for methods like forEach
122 // TODO: accept the document
123 function findElements(container, selector) {
124 let containers = container instanceof HTMLElement ? [container] : container;
125 let allMatches = [];
126 for (let i = 0; i < containers.length; i += 1) {
127 let matches = containers[i].querySelectorAll(selector);
128 for (let j = 0; j < matches.length; j += 1) {
129 allMatches.push(matches[j]);
130 }
131 }
132 return allMatches;
133 }
134 // accepts multiple subject els
135 // only queries direct child elements // TODO: rename to findDirectChildren!
136 function findDirectChildren(parent, selector) {
137 let parents = parent instanceof HTMLElement ? [parent] : parent;
138 let allMatches = [];
139 for (let i = 0; i < parents.length; i += 1) {
140 let childNodes = parents[i].children; // only ever elements
141 for (let j = 0; j < childNodes.length; j += 1) {
142 let childNode = childNodes[j];
143 if (!selector || elementMatches(childNode, selector)) {
144 allMatches.push(childNode);
145 }
146 }
147 }
148 return allMatches;
149 }
150 // Style
151 // ----------------------------------------------------------------------------------------------------------------
152 const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;
153 function applyStyle(el, props) {
154 for (let propName in props) {
155 applyStyleProp(el, propName, props[propName]);
156 }
157 }
158 function applyStyleProp(el, name, val) {
159 if (val == null) {
160 el.style[name] = '';
161 }
162 else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
163 el.style[name] = `${val}px`;
164 }
165 else {
166 el.style[name] = val;
167 }
168 }
169 // Event Handling
170 // ----------------------------------------------------------------------------------------------------------------
171 // if intercepting bubbled events at the document/window/body level,
172 // and want to see originating element (the 'target'), use this util instead
173 // of `ev.target` because it goes within web-component boundaries.
174 function getEventTargetViaRoot(ev) {
175 var _a, _b;
176 return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
177 }
178 // Unique ID for DOM attribute
179 let guid$1 = 0;
180 function getUniqueDomId() {
181 guid$1 += 1;
182 return 'fc-dom-' + guid$1;
183 }
184
185 // Stops a mouse/touch event from doing it's native browser action
186 function preventDefault(ev) {
187 ev.preventDefault();
188 }
189 // Event Delegation
190 // ----------------------------------------------------------------------------------------------------------------
191 function buildDelegationHandler(selector, handler) {
192 return (ev) => {
193 let matchedChild = elementClosest(ev.target, selector);
194 if (matchedChild) {
195 handler.call(matchedChild, ev, matchedChild);
196 }
197 };
198 }
199 function listenBySelector(container, eventType, selector, handler) {
200 let attachedHandler = buildDelegationHandler(selector, handler);
201 container.addEventListener(eventType, attachedHandler);
202 return () => {
203 container.removeEventListener(eventType, attachedHandler);
204 };
205 }
206 function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
207 let currentMatchedChild;
208 return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
209 if (matchedChild !== currentMatchedChild) {
210 currentMatchedChild = matchedChild;
211 onMouseEnter(mouseOverEv, matchedChild);
212 let realOnMouseLeave = (mouseLeaveEv) => {
213 currentMatchedChild = null;
214 onMouseLeave(mouseLeaveEv, matchedChild);
215 matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
216 };
217 // listen to the next mouseleave, and then unattach
218 matchedChild.addEventListener('mouseleave', realOnMouseLeave);
219 }
220 });
221 }
222 // Animation
223 // ----------------------------------------------------------------------------------------------------------------
224 const transitionEventNames = [
225 'webkitTransitionEnd',
226 'otransitionend',
227 'oTransitionEnd',
228 'msTransitionEnd',
229 'transitionend',
230 ];
231 // triggered only when the next single subsequent transition finishes
232 function whenTransitionDone(el, callback) {
233 let realCallback = (ev) => {
234 callback(ev);
235 transitionEventNames.forEach((eventName) => {
236 el.removeEventListener(eventName, realCallback);
237 });
238 };
239 transitionEventNames.forEach((eventName) => {
240 el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
241 });
242 }
243 // ARIA workarounds
244 // ----------------------------------------------------------------------------------------------------------------
245 function createAriaClickAttrs(handler) {
246 return Object.assign({ onClick: handler }, createAriaKeyboardAttrs(handler));
247 }
248 function createAriaKeyboardAttrs(handler) {
249 return {
250 tabIndex: 0,
251 onKeyDown(ev) {
252 if (ev.key === 'Enter' || ev.key === ' ') {
253 handler(ev);
254 ev.preventDefault(); // if space, don't scroll down page
255 }
256 },
257 };
258 }
259
260 let guidNumber = 0;
261 function guid() {
262 guidNumber += 1;
263 return String(guidNumber);
264 }
265 /* FullCalendar-specific DOM Utilities
266 ----------------------------------------------------------------------------------------------------------------------*/
267 // Make the mouse cursor express that an event is not allowed in the current area
268 function disableCursor() {
269 document.body.classList.add('fc-not-allowed');
270 }
271 // Returns the mouse cursor to its original look
272 function enableCursor() {
273 document.body.classList.remove('fc-not-allowed');
274 }
275 /* Selection
276 ----------------------------------------------------------------------------------------------------------------------*/
277 function preventSelection(el) {
278 el.style.userSelect = 'none';
279 el.style.webkitUserSelect = 'none';
280 el.addEventListener('selectstart', preventDefault);
281 }
282 function allowSelection(el) {
283 el.style.userSelect = '';
284 el.style.webkitUserSelect = '';
285 el.removeEventListener('selectstart', preventDefault);
286 }
287 /* Context Menu
288 ----------------------------------------------------------------------------------------------------------------------*/
289 function preventContextMenu(el) {
290 el.addEventListener('contextmenu', preventDefault);
291 }
292 function allowContextMenu(el) {
293 el.removeEventListener('contextmenu', preventDefault);
294 }
295 function parseFieldSpecs(input) {
296 let specs = [];
297 let tokens = [];
298 let i;
299 let token;
300 if (typeof input === 'string') {
301 tokens = input.split(/\s*,\s*/);
302 }
303 else if (typeof input === 'function') {
304 tokens = [input];
305 }
306 else if (Array.isArray(input)) {
307 tokens = input;
308 }
309 for (i = 0; i < tokens.length; i += 1) {
310 token = tokens[i];
311 if (typeof token === 'string') {
312 specs.push(token.charAt(0) === '-' ?
313 { field: token.substring(1), order: -1 } :
314 { field: token, order: 1 });
315 }
316 else if (typeof token === 'function') {
317 specs.push({ func: token });
318 }
319 }
320 return specs;
321 }
322 function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
323 let i;
324 let cmp;
325 for (i = 0; i < fieldSpecs.length; i += 1) {
326 cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
327 if (cmp) {
328 return cmp;
329 }
330 }
331 return 0;
332 }
333 function compareByFieldSpec(obj0, obj1, fieldSpec) {
334 if (fieldSpec.func) {
335 return fieldSpec.func(obj0, obj1);
336 }
337 return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field])
338 * (fieldSpec.order || 1);
339 }
340 function flexibleCompare(a, b) {
341 if (!a && !b) {
342 return 0;
343 }
344 if (b == null) {
345 return -1;
346 }
347 if (a == null) {
348 return 1;
349 }
350 if (typeof a === 'string' || typeof b === 'string') {
351 return String(a).localeCompare(String(b));
352 }
353 return a - b;
354 }
355 /* String Utilities
356 ----------------------------------------------------------------------------------------------------------------------*/
357 function padStart(val, len) {
358 let s = String(val);
359 return '000'.substr(0, len - s.length) + s;
360 }
361 function formatWithOrdinals(formatter, args, fallbackText) {
362 if (typeof formatter === 'function') {
363 return formatter(...args);
364 }
365 if (typeof formatter === 'string') { // non-blank string
366 return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
367 }
368 return fallbackText;
369 }
370 /* Number Utilities
371 ----------------------------------------------------------------------------------------------------------------------*/
372 function compareNumbers(a, b) {
373 return a - b;
374 }
375 function isInt(n) {
376 return n % 1 === 0;
377 }
378 /* FC-specific DOM dimension stuff
379 ----------------------------------------------------------------------------------------------------------------------*/
380 function computeSmallestCellWidth(cellEl) {
381 let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
382 let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
383 if (!allWidthEl) {
384 throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
385 }
386 if (!contentWidthEl) {
387 throw new Error('needs fc-scrollgrid-shrink-cushion className');
388 }
389 return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
390 contentWidthEl.getBoundingClientRect().width;
391 }
392
393 const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
394 const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
395 // Parsing and Creation
396 function createDuration(input, unit) {
397 if (typeof input === 'string') {
398 return parseString(input);
399 }
400 if (typeof input === 'object' && input) { // non-null object
401 return parseObject(input);
402 }
403 if (typeof input === 'number') {
404 return parseObject({ [unit || 'milliseconds']: input });
405 }
406 return null;
407 }
408 function parseString(s) {
409 let m = PARSE_RE.exec(s);
410 if (m) {
411 let sign = m[1] ? -1 : 1;
412 return {
413 years: 0,
414 months: 0,
415 days: sign * (m[2] ? parseInt(m[2], 10) : 0),
416 milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
417 (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
418 (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
419 (m[6] ? parseInt(m[6], 10) : 0) // ms
420 ),
421 };
422 }
423 return null;
424 }
425 function parseObject(obj) {
426 let duration = {
427 years: obj.years || obj.year || 0,
428 months: obj.months || obj.month || 0,
429 days: obj.days || obj.day || 0,
430 milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
431 (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
432 (obj.seconds || obj.second || 0) * 1000 + // seconds
433 (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
434 };
435 let weeks = obj.weeks || obj.week;
436 if (weeks) {
437 duration.days += weeks * 7;
438 duration.specifiedWeeks = true;
439 }
440 return duration;
441 }
442 // Equality
443 function durationsEqual(d0, d1) {
444 return d0.years === d1.years &&
445 d0.months === d1.months &&
446 d0.days === d1.days &&
447 d0.milliseconds === d1.milliseconds;
448 }
449 function asCleanDays(dur) {
450 if (!dur.years && !dur.months && !dur.milliseconds) {
451 return dur.days;
452 }
453 return 0;
454 }
455 // Simple Math
456 function addDurations(d0, d1) {
457 return {
458 years: d0.years + d1.years,
459 months: d0.months + d1.months,
460 days: d0.days + d1.days,
461 milliseconds: d0.milliseconds + d1.milliseconds,
462 };
463 }
464 function subtractDurations(d1, d0) {
465 return {
466 years: d1.years - d0.years,
467 months: d1.months - d0.months,
468 days: d1.days - d0.days,
469 milliseconds: d1.milliseconds - d0.milliseconds,
470 };
471 }
472 function multiplyDuration(d, n) {
473 return {
474 years: d.years * n,
475 months: d.months * n,
476 days: d.days * n,
477 milliseconds: d.milliseconds * n,
478 };
479 }
480 // Conversions
481 // "Rough" because they are based on average-case Gregorian months/years
482 function asRoughYears(dur) {
483 return asRoughDays(dur) / 365;
484 }
485 function asRoughMonths(dur) {
486 return asRoughDays(dur) / 30;
487 }
488 function asRoughDays(dur) {
489 return asRoughMs(dur) / 864e5;
490 }
491 function asRoughMinutes(dur) {
492 return asRoughMs(dur) / (1000 * 60);
493 }
494 function asRoughSeconds(dur) {
495 return asRoughMs(dur) / 1000;
496 }
497 function asRoughMs(dur) {
498 return dur.years * (365 * 864e5) +
499 dur.months * (30 * 864e5) +
500 dur.days * 864e5 +
501 dur.milliseconds;
502 }
503 // Advanced Math
504 function wholeDivideDurations(numerator, denominator) {
505 let res = null;
506 for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
507 let unit = INTERNAL_UNITS[i];
508 if (denominator[unit]) {
509 let localRes = numerator[unit] / denominator[unit];
510 if (!isInt(localRes) || (res !== null && res !== localRes)) {
511 return null;
512 }
513 res = localRes;
514 }
515 else if (numerator[unit]) {
516 // needs to divide by something but can't!
517 return null;
518 }
519 }
520 return res;
521 }
522 function greatestDurationDenominator(dur) {
523 let ms = dur.milliseconds;
524 if (ms) {
525 if (ms % 1000 !== 0) {
526 return { unit: 'millisecond', value: ms };
527 }
528 if (ms % (1000 * 60) !== 0) {
529 return { unit: 'second', value: ms / 1000 };
530 }
531 if (ms % (1000 * 60 * 60) !== 0) {
532 return { unit: 'minute', value: ms / (1000 * 60) };
533 }
534 if (ms) {
535 return { unit: 'hour', value: ms / (1000 * 60 * 60) };
536 }
537 }
538 if (dur.days) {
539 if (dur.specifiedWeeks && dur.days % 7 === 0) {
540 return { unit: 'week', value: dur.days / 7 };
541 }
542 return { unit: 'day', value: dur.days };
543 }
544 if (dur.months) {
545 return { unit: 'month', value: dur.months };
546 }
547 if (dur.years) {
548 return { unit: 'year', value: dur.years };
549 }
550 return { unit: 'millisecond', value: 0 };
551 }
552
553 const { hasOwnProperty } = Object.prototype;
554 // Merges an array of objects into a single object.
555 // The second argument allows for an array of property names who's object values will be merged together.
556 function mergeProps(propObjs, complexPropsMap) {
557 let dest = {};
558 if (complexPropsMap) {
559 for (let name in complexPropsMap) {
560 if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable
561 let complexObjs = [];
562 // collect the trailing object values, stopping when a non-object is discovered
563 for (let i = propObjs.length - 1; i >= 0; i -= 1) {
564 let val = propObjs[i][name];
565 if (typeof val === 'object' && val) { // non-null object
566 complexObjs.unshift(val);
567 }
568 else if (val !== undefined) {
569 dest[name] = val; // if there were no objects, this value will be used
570 break;
571 }
572 }
573 // if the trailing values were objects, use the merged value
574 if (complexObjs.length) {
575 dest[name] = mergeProps(complexObjs);
576 }
577 }
578 }
579 }
580 // copy values into the destination, going from last to first
581 for (let i = propObjs.length - 1; i >= 0; i -= 1) {
582 let props = propObjs[i];
583 for (let name in props) {
584 if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
585 dest[name] = props[name];
586 }
587 }
588 }
589 return dest;
590 }
591 function filterHash(hash, func) {
592 let filtered = {};
593 for (let key in hash) {
594 if (func(hash[key], key)) {
595 filtered[key] = hash[key];
596 }
597 }
598 return filtered;
599 }
600 function mapHash(hash, func) {
601 let newHash = {};
602 for (let key in hash) {
603 newHash[key] = func(hash[key], key);
604 }
605 return newHash;
606 }
607 function arrayToHash(a) {
608 let hash = {};
609 for (let item of a) {
610 hash[item] = true;
611 }
612 return hash;
613 }
614 // TODO: reassess browser support
615 // https://caniuse.com/?search=object.values
616 function hashValuesToArray(obj) {
617 let a = [];
618 for (let key in obj) {
619 a.push(obj[key]);
620 }
621 return a;
622 }
623 function isPropsEqual(obj0, obj1) {
624 if (obj0 === obj1) {
625 return true;
626 }
627 for (let key in obj0) {
628 if (hasOwnProperty.call(obj0, key)) {
629 if (!(key in obj1)) {
630 return false;
631 }
632 }
633 }
634 for (let key in obj1) {
635 if (hasOwnProperty.call(obj1, key)) {
636 if (obj0[key] !== obj1[key]) {
637 return false;
638 }
639 }
640 }
641 return true;
642 }
643 const HANDLER_RE = /^on[A-Z]/;
644 function isNonHandlerPropsEqual(obj0, obj1) {
645 const keys = getUnequalProps(obj0, obj1);
646 for (let key of keys) {
647 if (!HANDLER_RE.test(key)) {
648 return false;
649 }
650 }
651 return true;
652 }
653 function getUnequalProps(obj0, obj1) {
654 let keys = [];
655 for (let key in obj0) {
656 if (hasOwnProperty.call(obj0, key)) {
657 if (!(key in obj1)) {
658 keys.push(key);
659 }
660 }
661 }
662 for (let key in obj1) {
663 if (hasOwnProperty.call(obj1, key)) {
664 if (obj0[key] !== obj1[key]) {
665 keys.push(key);
666 }
667 }
668 }
669 return keys;
670 }
671 function compareObjs(oldProps, newProps, equalityFuncs = {}) {
672 if (oldProps === newProps) {
673 return true;
674 }
675 for (let key in newProps) {
676 if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) ;
677 else {
678 return false;
679 }
680 }
681 // check for props that were omitted in the new
682 for (let key in oldProps) {
683 if (!(key in newProps)) {
684 return false;
685 }
686 }
687 return true;
688 }
689 /*
690 assumed "true" equality for handler names like "onReceiveSomething"
691 */
692 function isObjValsEqual(val0, val1, comparator) {
693 if (val0 === val1 || comparator === true) {
694 return true;
695 }
696 if (comparator) {
697 return comparator(val0, val1);
698 }
699 return false;
700 }
701 function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
702 let res = [];
703 if (endIndex == null) {
704 endIndex = Object.keys(hash).length;
705 }
706 for (let i = startIndex; i < endIndex; i += step) {
707 let val = hash[i];
708 if (val !== undefined) { // will disregard undefined for sparse arrays
709 res.push(val);
710 }
711 }
712 return res;
713 }
714
715 // TODO: new util arrayify?
716 function removeExact(array, exactVal) {
717 let removeCnt = 0;
718 let i = 0;
719 while (i < array.length) {
720 if (array[i] === exactVal) {
721 array.splice(i, 1);
722 removeCnt += 1;
723 }
724 else {
725 i += 1;
726 }
727 }
728 return removeCnt;
729 }
730 function isArraysEqual(a0, a1, equalityFunc) {
731 if (a0 === a1) {
732 return true;
733 }
734 let len = a0.length;
735 let i;
736 if (len !== a1.length) { // not array? or not same length?
737 return false;
738 }
739 for (i = 0; i < len; i += 1) {
740 if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
741 return false;
742 }
743 }
744 return true;
745 }
746
747 const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
748 // Adding
749 function addWeeks(m, n) {
750 let a = dateToUtcArray(m);
751 a[2] += n * 7;
752 return arrayToUtcDate(a);
753 }
754 function addDays(m, n) {
755 let a = dateToUtcArray(m);
756 a[2] += n;
757 return arrayToUtcDate(a);
758 }
759 function addMs(m, n) {
760 let a = dateToUtcArray(m);
761 a[6] += n;
762 return arrayToUtcDate(a);
763 }
764 // Diffing (all return floats)
765 // TODO: why not use ranges?
766 function diffWeeks(m0, m1) {
767 return diffDays(m0, m1) / 7;
768 }
769 function diffDays(m0, m1) {
770 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
771 }
772 function diffHours(m0, m1) {
773 return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
774 }
775 function diffMinutes(m0, m1) {
776 return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
777 }
778 function diffSeconds(m0, m1) {
779 return (m1.valueOf() - m0.valueOf()) / 1000;
780 }
781 function diffDayAndTime(m0, m1) {
782 let m0day = startOfDay(m0);
783 let m1day = startOfDay(m1);
784 return {
785 years: 0,
786 months: 0,
787 days: Math.round(diffDays(m0day, m1day)),
788 milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
789 };
790 }
791 // Diffing Whole Units
792 function diffWholeWeeks(m0, m1) {
793 let d = diffWholeDays(m0, m1);
794 if (d !== null && d % 7 === 0) {
795 return d / 7;
796 }
797 return null;
798 }
799 function diffWholeDays(m0, m1) {
800 if (timeAsMs(m0) === timeAsMs(m1)) {
801 return Math.round(diffDays(m0, m1));
802 }
803 return null;
804 }
805 // Start-Of
806 function startOfDay(m) {
807 return arrayToUtcDate([
808 m.getUTCFullYear(),
809 m.getUTCMonth(),
810 m.getUTCDate(),
811 ]);
812 }
813 function startOfHour(m) {
814 return arrayToUtcDate([
815 m.getUTCFullYear(),
816 m.getUTCMonth(),
817 m.getUTCDate(),
818 m.getUTCHours(),
819 ]);
820 }
821 function startOfMinute(m) {
822 return arrayToUtcDate([
823 m.getUTCFullYear(),
824 m.getUTCMonth(),
825 m.getUTCDate(),
826 m.getUTCHours(),
827 m.getUTCMinutes(),
828 ]);
829 }
830 function startOfSecond(m) {
831 return arrayToUtcDate([
832 m.getUTCFullYear(),
833 m.getUTCMonth(),
834 m.getUTCDate(),
835 m.getUTCHours(),
836 m.getUTCMinutes(),
837 m.getUTCSeconds(),
838 ]);
839 }
840 // Week Computation
841 function weekOfYear(marker, dow, doy) {
842 let y = marker.getUTCFullYear();
843 let w = weekOfGivenYear(marker, y, dow, doy);
844 if (w < 1) {
845 return weekOfGivenYear(marker, y - 1, dow, doy);
846 }
847 let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
848 if (nextW >= 1) {
849 return Math.min(w, nextW);
850 }
851 return w;
852 }
853 function weekOfGivenYear(marker, year, dow, doy) {
854 let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
855 let dayStart = startOfDay(marker);
856 let days = Math.round(diffDays(firstWeekStart, dayStart));
857 return Math.floor(days / 7) + 1; // zero-indexed
858 }
859 // start-of-first-week - start-of-year
860 function firstWeekOffset(year, dow, doy) {
861 // first-week day -- which january is always in the first week (4 for iso, 1 for other)
862 let fwd = 7 + dow - doy;
863 // first-week day local weekday -- which local weekday is fwd
864 let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
865 return -fwdlw + fwd - 1;
866 }
867 // Array Conversion
868 function dateToLocalArray(date) {
869 return [
870 date.getFullYear(),
871 date.getMonth(),
872 date.getDate(),
873 date.getHours(),
874 date.getMinutes(),
875 date.getSeconds(),
876 date.getMilliseconds(),
877 ];
878 }
879 function arrayToLocalDate(a) {
880 return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
881 a[3] || 0, a[4] || 0, a[5] || 0);
882 }
883 function dateToUtcArray(date) {
884 return [
885 date.getUTCFullYear(),
886 date.getUTCMonth(),
887 date.getUTCDate(),
888 date.getUTCHours(),
889 date.getUTCMinutes(),
890 date.getUTCSeconds(),
891 date.getUTCMilliseconds(),
892 ];
893 }
894 function arrayToUtcDate(a) {
895 // according to web standards (and Safari), a month index is required.
896 // massage if only given a year.
897 if (a.length === 1) {
898 a = a.concat([0]);
899 }
900 return new Date(Date.UTC(...a));
901 }
902 // Other Utils
903 function isValidDate(m) {
904 return !isNaN(m.valueOf());
905 }
906 function timeAsMs(m) {
907 return m.getUTCHours() * 1000 * 60 * 60 +
908 m.getUTCMinutes() * 1000 * 60 +
909 m.getUTCSeconds() * 1000 +
910 m.getUTCMilliseconds();
911 }
912
913 // timeZoneOffset is in minutes
914 function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
915 let s = marker.toISOString();
916 s = s.replace('.000', '');
917 if (stripZeroTime) {
918 s = s.replace('T00:00:00Z', '');
919 }
920 if (s.length > 10) { // time part wasn't stripped, can add timezone info
921 if (timeZoneOffset == null) {
922 s = s.replace('Z', '');
923 }
924 else if (timeZoneOffset !== 0) {
925 s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
926 }
927 // otherwise, its UTC-0 and we want to keep the Z
928 }
929 return s;
930 }
931 // formats the date, but with no time part
932 // TODO: somehow merge with buildIsoString and stripZeroTime
933 // TODO: rename. omit "string"
934 function formatDayString(marker) {
935 return marker.toISOString().replace(/T.*$/, '');
936 }
937 function formatIsoMonthStr(marker) {
938 return marker.toISOString().match(/^\d{4}-\d{2}/)[0];
939 }
940 // TODO: use Date::toISOString and use everything after the T?
941 function formatIsoTimeString(marker) {
942 return padStart(marker.getUTCHours(), 2) + ':' +
943 padStart(marker.getUTCMinutes(), 2) + ':' +
944 padStart(marker.getUTCSeconds(), 2);
945 }
946 function formatTimeZoneOffset(minutes, doIso = false) {
947 let sign = minutes < 0 ? '-' : '+';
948 let abs = Math.abs(minutes);
949 let hours = Math.floor(abs / 60);
950 let mins = Math.round(abs % 60);
951 if (doIso) {
952 return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
953 }
954 return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
955 }
956
957 function memoize(workerFunc, resEquality, teardownFunc) {
958 let currentArgs;
959 let currentRes;
960 return function (...newArgs) {
961 if (!currentArgs) {
962 currentRes = workerFunc.apply(this, newArgs);
963 }
964 else if (!isArraysEqual(currentArgs, newArgs)) {
965 if (teardownFunc) {
966 teardownFunc(currentRes);
967 }
968 let res = workerFunc.apply(this, newArgs);
969 if (!resEquality || !resEquality(res, currentRes)) {
970 currentRes = res;
971 }
972 }
973 currentArgs = newArgs;
974 return currentRes;
975 };
976 }
977 function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
978 let currentArg;
979 let currentRes;
980 return (newArg) => {
981 if (!currentArg) {
982 currentRes = workerFunc.call(this, newArg);
983 }
984 else if (!isPropsEqual(currentArg, newArg)) {
985 if (teardownFunc) {
986 teardownFunc(currentRes);
987 }
988 let res = workerFunc.call(this, newArg);
989 if (!resEquality || !resEquality(res, currentRes)) {
990 currentRes = res;
991 }
992 }
993 currentArg = newArg;
994 return currentRes;
995 };
996 }
997 function memoizeArraylike(// used at all?
998 workerFunc, resEquality, teardownFunc) {
999 let currentArgSets = [];
1000 let currentResults = [];
1001 return (newArgSets) => {
1002 let currentLen = currentArgSets.length;
1003 let newLen = newArgSets.length;
1004 let i = 0;
1005 for (; i < currentLen; i += 1) {
1006 if (!newArgSets[i]) { // one of the old sets no longer exists
1007 if (teardownFunc) {
1008 teardownFunc(currentResults[i]);
1009 }
1010 }
1011 else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
1012 if (teardownFunc) {
1013 teardownFunc(currentResults[i]);
1014 }
1015 let res = workerFunc.apply(this, newArgSets[i]);
1016 if (!resEquality || !resEquality(res, currentResults[i])) {
1017 currentResults[i] = res;
1018 }
1019 }
1020 }
1021 for (; i < newLen; i += 1) {
1022 currentResults[i] = workerFunc.apply(this, newArgSets[i]);
1023 }
1024 currentArgSets = newArgSets;
1025 currentResults.splice(newLen); // remove excess
1026 return currentResults;
1027 };
1028 }
1029 function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
1030 let currentArgHash = {};
1031 let currentResHash = {};
1032 return (newArgHash) => {
1033 let newResHash = {};
1034 for (let key in newArgHash) {
1035 if (!currentResHash[key]) {
1036 newResHash[key] = workerFunc.apply(this, newArgHash[key]);
1037 }
1038 else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
1039 if (teardownFunc) {
1040 teardownFunc(currentResHash[key]);
1041 }
1042 let res = workerFunc.apply(this, newArgHash[key]);
1043 newResHash[key] = (resEquality && resEquality(res, currentResHash[key]))
1044 ? currentResHash[key]
1045 : res;
1046 }
1047 else {
1048 newResHash[key] = currentResHash[key];
1049 }
1050 }
1051 currentArgHash = newArgHash;
1052 currentResHash = newResHash;
1053 return newResHash;
1054 };
1055 }
1056
1057 const EXTENDED_SETTINGS_AND_SEVERITIES = {
1058 week: 3,
1059 separator: 9,
1060 omitZeroMinute: 9,
1061 meridiem: 9,
1062 omitCommas: 9,
1063 };
1064 const STANDARD_DATE_PROP_SEVERITIES = {
1065 timeZoneName: 7,
1066 era: 6,
1067 year: 5,
1068 month: 4,
1069 day: 2,
1070 weekday: 2,
1071 hour: 1,
1072 minute: 1,
1073 second: 1,
1074 };
1075 const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
1076 const COMMA_RE = /,/g; // we need re for globalness
1077 const MULTI_SPACE_RE = /\s+/g;
1078 const LTR_RE = /\u200e/g; // control character
1079 const UTC_RE = /UTC|GMT/;
1080 class NativeFormatter {
1081 constructor(formatSettings) {
1082 let standardDateProps = {};
1083 let extendedSettings = {};
1084 let smallestUnitNum = 9; // the smallest unit in the formatter (9 is a sentinel, beyond max)
1085 for (let name in formatSettings) {
1086 if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
1087 extendedSettings[name] = formatSettings[name];
1088 const severity = EXTENDED_SETTINGS_AND_SEVERITIES[name];
1089 if (severity < 9) {
1090 smallestUnitNum = Math.min(EXTENDED_SETTINGS_AND_SEVERITIES[name], smallestUnitNum);
1091 }
1092 }
1093 else {
1094 standardDateProps[name] = formatSettings[name];
1095 if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
1096 smallestUnitNum = Math.min(STANDARD_DATE_PROP_SEVERITIES[name], smallestUnitNum);
1097 }
1098 }
1099 }
1100 this.standardDateProps = standardDateProps;
1101 this.extendedSettings = extendedSettings;
1102 this.smallestUnitNum = smallestUnitNum;
1103 this.buildFormattingFunc = memoize(buildFormattingFunc);
1104 }
1105 format(date, context) {
1106 return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
1107 }
1108 formatRange(start, end, context, betterDefaultSeparator) {
1109 let { standardDateProps, extendedSettings } = this;
1110 let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
1111 if (!diffSeverity) {
1112 return this.format(start, context);
1113 }
1114 let biggestUnitForPartial = diffSeverity;
1115 if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
1116 (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
1117 (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
1118 (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
1119 biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
1120 }
1121 let full0 = this.format(start, context);
1122 let full1 = this.format(end, context);
1123 if (full0 === full1) {
1124 return full0;
1125 }
1126 let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
1127 let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
1128 let partial0 = partialFormattingFunc(start);
1129 let partial1 = partialFormattingFunc(end);
1130 let insertion = findCommonInsertion(full0, partial0, full1, partial1);
1131 let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
1132 if (insertion) {
1133 return insertion.before + partial0 + separator + partial1 + insertion.after;
1134 }
1135 return full0 + separator + full1;
1136 }
1137 getSmallestUnit() {
1138 switch (this.smallestUnitNum) {
1139 case 7:
1140 case 6:
1141 case 5:
1142 return 'year';
1143 case 4:
1144 return 'month';
1145 case 3:
1146 return 'week';
1147 case 2:
1148 return 'day';
1149 default:
1150 return 'time'; // really?
1151 }
1152 }
1153 }
1154 function buildFormattingFunc(standardDateProps, extendedSettings, context) {
1155 let standardDatePropCnt = Object.keys(standardDateProps).length;
1156 if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
1157 return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
1158 }
1159 if (standardDatePropCnt === 0 && extendedSettings.week) {
1160 return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
1161 }
1162 return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
1163 }
1164 function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
1165 standardDateProps = Object.assign({}, standardDateProps); // copy
1166 extendedSettings = Object.assign({}, extendedSettings); // copy
1167 sanitizeSettings(standardDateProps, extendedSettings);
1168 standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
1169 let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
1170 let zeroFormat; // needed?
1171 if (extendedSettings.omitZeroMinute) {
1172 let zeroProps = Object.assign({}, standardDateProps);
1173 delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
1174 zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
1175 }
1176 return (date) => {
1177 let { marker } = date;
1178 let format;
1179 if (zeroFormat && !marker.getUTCMinutes()) {
1180 format = zeroFormat;
1181 }
1182 else {
1183 format = normalFormat;
1184 }
1185 let s = format.format(marker);
1186 return postProcess(s, date, standardDateProps, extendedSettings, context);
1187 };
1188 }
1189 function sanitizeSettings(standardDateProps, extendedSettings) {
1190 // deal with a browser inconsistency where formatting the timezone
1191 // requires that the hour/minute be present.
1192 if (standardDateProps.timeZoneName) {
1193 if (!standardDateProps.hour) {
1194 standardDateProps.hour = '2-digit';
1195 }
1196 if (!standardDateProps.minute) {
1197 standardDateProps.minute = '2-digit';
1198 }
1199 }
1200 // only support short timezone names
1201 if (standardDateProps.timeZoneName === 'long') {
1202 standardDateProps.timeZoneName = 'short';
1203 }
1204 // if requesting to display seconds, MUST display minutes
1205 if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
1206 delete extendedSettings.omitZeroMinute;
1207 }
1208 }
1209 function postProcess(s, date, standardDateProps, extendedSettings, context) {
1210 s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
1211 if (standardDateProps.timeZoneName === 'short') {
1212 s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
1213 'UTC' : // important to normalize for IE, which does "GMT"
1214 formatTimeZoneOffset(date.timeZoneOffset));
1215 }
1216 if (extendedSettings.omitCommas) {
1217 s = s.replace(COMMA_RE, '').trim();
1218 }
1219 if (extendedSettings.omitZeroMinute) {
1220 s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
1221 }
1222 // ^ do anything that might create adjacent spaces before this point,
1223 // because MERIDIEM_RE likes to eat up loading spaces
1224 if (extendedSettings.meridiem === false) {
1225 s = s.replace(MERIDIEM_RE, '').trim();
1226 }
1227 else if (extendedSettings.meridiem === 'narrow') { // a/p
1228 s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
1229 }
1230 else if (extendedSettings.meridiem === 'short') { // am/pm
1231 s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
1232 }
1233 else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
1234 s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
1235 }
1236 s = s.replace(MULTI_SPACE_RE, ' ');
1237 s = s.trim();
1238 return s;
1239 }
1240 function injectTzoStr(s, tzoStr) {
1241 let replaced = false;
1242 s = s.replace(UTC_RE, () => {
1243 replaced = true;
1244 return tzoStr;
1245 });
1246 // IE11 doesn't include UTC/GMT in the original string, so append to end
1247 if (!replaced) {
1248 s += ` ${tzoStr}`;
1249 }
1250 return s;
1251 }
1252 function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
1253 let parts = [];
1254 if (display === 'long') {
1255 parts.push(weekTextLong);
1256 }
1257 else if (display === 'short' || display === 'narrow') {
1258 parts.push(weekText);
1259 }
1260 if (display === 'long' || display === 'short') {
1261 parts.push(' ');
1262 }
1263 parts.push(locale.simpleNumberFormat.format(num));
1264 if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
1265 parts.reverse();
1266 }
1267 return parts.join('');
1268 }
1269 // Range Formatting Utils
1270 // 0 = exactly the same
1271 // 1 = different by time
1272 // and bigger
1273 function computeMarkerDiffSeverity(d0, d1, ca) {
1274 if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
1275 return 5;
1276 }
1277 if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
1278 return 4;
1279 }
1280 if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
1281 return 2;
1282 }
1283 if (timeAsMs(d0) !== timeAsMs(d1)) {
1284 return 1;
1285 }
1286 return 0;
1287 }
1288 function computePartialFormattingOptions(options, biggestUnit) {
1289 let partialOptions = {};
1290 for (let name in options) {
1291 if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
1292 STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
1293 partialOptions[name] = options[name];
1294 }
1295 }
1296 return partialOptions;
1297 }
1298 function findCommonInsertion(full0, partial0, full1, partial1) {
1299 let i0 = 0;
1300 while (i0 < full0.length) {
1301 let found0 = full0.indexOf(partial0, i0);
1302 if (found0 === -1) {
1303 break;
1304 }
1305 let before0 = full0.substr(0, found0);
1306 i0 = found0 + partial0.length;
1307 let after0 = full0.substr(i0);
1308 let i1 = 0;
1309 while (i1 < full1.length) {
1310 let found1 = full1.indexOf(partial1, i1);
1311 if (found1 === -1) {
1312 break;
1313 }
1314 let before1 = full1.substr(0, found1);
1315 i1 = found1 + partial1.length;
1316 let after1 = full1.substr(i1);
1317 if (before0 === before1 && after0 === after1) {
1318 return {
1319 before: before0,
1320 after: after0,
1321 };
1322 }
1323 }
1324 }
1325 return null;
1326 }
1327
1328 function expandZonedMarker(dateInfo, calendarSystem) {
1329 let a = calendarSystem.markerToArray(dateInfo.marker);
1330 return {
1331 marker: dateInfo.marker,
1332 timeZoneOffset: dateInfo.timeZoneOffset,
1333 array: a,
1334 year: a[0],
1335 month: a[1],
1336 day: a[2],
1337 hour: a[3],
1338 minute: a[4],
1339 second: a[5],
1340 millisecond: a[6],
1341 };
1342 }
1343
1344 function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
1345 let startInfo = expandZonedMarker(start, context.calendarSystem);
1346 let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
1347 return {
1348 date: startInfo,
1349 start: startInfo,
1350 end: endInfo,
1351 timeZone: context.timeZone,
1352 localeCodes: context.locale.codes,
1353 defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
1354 };
1355 }
1356
1357 /*
1358 TODO: fix the terminology of "formatter" vs "formatting func"
1359 */
1360 /*
1361 At the time of instantiation, this object does not know which cmd-formatting system it will use.
1362 It receives this at the time of formatting, as a setting.
1363 */
1364 class CmdFormatter {
1365 constructor(cmdStr) {
1366 this.cmdStr = cmdStr;
1367 }
1368 format(date, context, betterDefaultSeparator) {
1369 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1370 }
1371 formatRange(start, end, context, betterDefaultSeparator) {
1372 return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1373 }
1374 }
1375
1376 class FuncFormatter {
1377 constructor(func) {
1378 this.func = func;
1379 }
1380 format(date, context, betterDefaultSeparator) {
1381 return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
1382 }
1383 formatRange(start, end, context, betterDefaultSeparator) {
1384 return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
1385 }
1386 }
1387
1388 function createFormatter(input) {
1389 if (typeof input === 'object' && input) { // non-null object
1390 return new NativeFormatter(input);
1391 }
1392 if (typeof input === 'string') {
1393 return new CmdFormatter(input);
1394 }
1395 if (typeof input === 'function') {
1396 return new FuncFormatter(input);
1397 }
1398 return null;
1399 }
1400
1401 // base options
1402 // ------------
1403 const BASE_OPTION_REFINERS = {
1404 navLinkDayClick: identity,
1405 navLinkWeekClick: identity,
1406 duration: createDuration,
1407 bootstrapFontAwesome: identity,
1408 buttonIcons: identity,
1409 customButtons: identity,
1410 defaultAllDayEventDuration: createDuration,
1411 defaultTimedEventDuration: createDuration,
1412 nextDayThreshold: createDuration,
1413 scrollTime: createDuration,
1414 scrollTimeReset: Boolean,
1415 slotMinTime: createDuration,
1416 slotMaxTime: createDuration,
1417 dayPopoverFormat: createFormatter,
1418 slotDuration: createDuration,
1419 snapDuration: createDuration,
1420 headerToolbar: identity,
1421 footerToolbar: identity,
1422 defaultRangeSeparator: String,
1423 titleRangeSeparator: String,
1424 forceEventDuration: Boolean,
1425 dayHeaders: Boolean,
1426 dayHeaderFormat: createFormatter,
1427 dayHeaderClassNames: identity,
1428 dayHeaderContent: identity,
1429 dayHeaderDidMount: identity,
1430 dayHeaderWillUnmount: identity,
1431 dayCellClassNames: identity,
1432 dayCellContent: identity,
1433 dayCellDidMount: identity,
1434 dayCellWillUnmount: identity,
1435 initialView: String,
1436 aspectRatio: Number,
1437 weekends: Boolean,
1438 weekNumberCalculation: identity,
1439 weekNumbers: Boolean,
1440 weekNumberClassNames: identity,
1441 weekNumberContent: identity,
1442 weekNumberDidMount: identity,
1443 weekNumberWillUnmount: identity,
1444 editable: Boolean,
1445 viewClassNames: identity,
1446 viewDidMount: identity,
1447 viewWillUnmount: identity,
1448 nowIndicator: Boolean,
1449 nowIndicatorClassNames: identity,
1450 nowIndicatorContent: identity,
1451 nowIndicatorDidMount: identity,
1452 nowIndicatorWillUnmount: identity,
1453 showNonCurrentDates: Boolean,
1454 lazyFetching: Boolean,
1455 startParam: String,
1456 endParam: String,
1457 timeZoneParam: String,
1458 timeZone: String,
1459 locales: identity,
1460 locale: identity,
1461 themeSystem: String,
1462 dragRevertDuration: Number,
1463 dragScroll: Boolean,
1464 allDayMaintainDuration: Boolean,
1465 unselectAuto: Boolean,
1466 dropAccept: identity,
1467 eventOrder: parseFieldSpecs,
1468 eventOrderStrict: Boolean,
1469 handleWindowResize: Boolean,
1470 windowResizeDelay: Number,
1471 longPressDelay: Number,
1472 eventDragMinDistance: Number,
1473 expandRows: Boolean,
1474 height: identity,
1475 contentHeight: identity,
1476 direction: String,
1477 weekNumberFormat: createFormatter,
1478 eventResizableFromStart: Boolean,
1479 displayEventTime: Boolean,
1480 displayEventEnd: Boolean,
1481 weekText: String,
1482 weekTextLong: String,
1483 progressiveEventRendering: Boolean,
1484 businessHours: identity,
1485 initialDate: identity,
1486 now: identity,
1487 eventDataTransform: identity,
1488 stickyHeaderDates: identity,
1489 stickyFooterScrollbar: identity,
1490 viewHeight: identity,
1491 defaultAllDay: Boolean,
1492 eventSourceFailure: identity,
1493 eventSourceSuccess: identity,
1494 eventDisplay: String,
1495 eventStartEditable: Boolean,
1496 eventDurationEditable: Boolean,
1497 eventOverlap: identity,
1498 eventConstraint: identity,
1499 eventAllow: identity,
1500 eventBackgroundColor: String,
1501 eventBorderColor: String,
1502 eventTextColor: String,
1503 eventColor: String,
1504 eventClassNames: identity,
1505 eventContent: identity,
1506 eventDidMount: identity,
1507 eventWillUnmount: identity,
1508 selectConstraint: identity,
1509 selectOverlap: identity,
1510 selectAllow: identity,
1511 droppable: Boolean,
1512 unselectCancel: String,
1513 slotLabelFormat: identity,
1514 slotLaneClassNames: identity,
1515 slotLaneContent: identity,
1516 slotLaneDidMount: identity,
1517 slotLaneWillUnmount: identity,
1518 slotLabelClassNames: identity,
1519 slotLabelContent: identity,
1520 slotLabelDidMount: identity,
1521 slotLabelWillUnmount: identity,
1522 dayMaxEvents: identity,
1523 dayMaxEventRows: identity,
1524 dayMinWidth: Number,
1525 slotLabelInterval: createDuration,
1526 allDayText: String,
1527 allDayClassNames: identity,
1528 allDayContent: identity,
1529 allDayDidMount: identity,
1530 allDayWillUnmount: identity,
1531 slotMinWidth: Number,
1532 navLinks: Boolean,
1533 eventTimeFormat: createFormatter,
1534 rerenderDelay: Number,
1535 moreLinkText: identity,
1536 moreLinkHint: identity,
1537 selectMinDistance: Number,
1538 selectable: Boolean,
1539 selectLongPressDelay: Number,
1540 eventLongPressDelay: Number,
1541 selectMirror: Boolean,
1542 eventMaxStack: Number,
1543 eventMinHeight: Number,
1544 eventMinWidth: Number,
1545 eventShortHeight: Number,
1546 slotEventOverlap: Boolean,
1547 plugins: identity,
1548 firstDay: Number,
1549 dayCount: Number,
1550 dateAlignment: String,
1551 dateIncrement: createDuration,
1552 hiddenDays: identity,
1553 fixedWeekCount: Boolean,
1554 validRange: identity,
1555 visibleRange: identity,
1556 titleFormat: identity,
1557 eventInteractive: Boolean,
1558 // only used by list-view, but languages define the value, so we need it in base options
1559 noEventsText: String,
1560 viewHint: identity,
1561 navLinkHint: identity,
1562 closeHint: String,
1563 timeHint: String,
1564 eventHint: String,
1565 moreLinkClick: identity,
1566 moreLinkClassNames: identity,
1567 moreLinkContent: identity,
1568 moreLinkDidMount: identity,
1569 moreLinkWillUnmount: identity,
1570 monthStartFormat: createFormatter,
1571 // for connectors
1572 // (can't be part of plugin system b/c must be provided at runtime)
1573 handleCustomRendering: identity,
1574 customRenderingMetaMap: identity,
1575 customRenderingReplaces: Boolean,
1576 };
1577 // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
1578 // raw values.
1579 const BASE_OPTION_DEFAULTS = {
1580 eventDisplay: 'auto',
1581 defaultRangeSeparator: ' - ',
1582 titleRangeSeparator: ' \u2013 ',
1583 defaultTimedEventDuration: '01:00:00',
1584 defaultAllDayEventDuration: { day: 1 },
1585 forceEventDuration: false,
1586 nextDayThreshold: '00:00:00',
1587 dayHeaders: true,
1588 initialView: '',
1589 aspectRatio: 1.35,
1590 headerToolbar: {
1591 start: 'title',
1592 center: '',
1593 end: 'today prev,next',
1594 },
1595 weekends: true,
1596 weekNumbers: false,
1597 weekNumberCalculation: 'local',
1598 editable: false,
1599 nowIndicator: false,
1600 scrollTime: '06:00:00',
1601 scrollTimeReset: true,
1602 slotMinTime: '00:00:00',
1603 slotMaxTime: '24:00:00',
1604 showNonCurrentDates: true,
1605 lazyFetching: true,
1606 startParam: 'start',
1607 endParam: 'end',
1608 timeZoneParam: 'timeZone',
1609 timeZone: 'local',
1610 locales: [],
1611 locale: '',
1612 themeSystem: 'standard',
1613 dragRevertDuration: 500,
1614 dragScroll: true,
1615 allDayMaintainDuration: false,
1616 unselectAuto: true,
1617 dropAccept: '*',
1618 eventOrder: 'start,-duration,allDay,title',
1619 dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
1620 handleWindowResize: true,
1621 windowResizeDelay: 100,
1622 longPressDelay: 1000,
1623 eventDragMinDistance: 5,
1624 expandRows: false,
1625 navLinks: false,
1626 selectable: false,
1627 eventMinHeight: 15,
1628 eventMinWidth: 30,
1629 eventShortHeight: 30,
1630 monthStartFormat: { month: 'long', day: 'numeric' },
1631 };
1632 // calendar listeners
1633 // ------------------
1634 const CALENDAR_LISTENER_REFINERS = {
1635 datesSet: identity,
1636 eventsSet: identity,
1637 eventAdd: identity,
1638 eventChange: identity,
1639 eventRemove: identity,
1640 windowResize: identity,
1641 eventClick: identity,
1642 eventMouseEnter: identity,
1643 eventMouseLeave: identity,
1644 select: identity,
1645 unselect: identity,
1646 loading: identity,
1647 // internal
1648 _unmount: identity,
1649 _beforeprint: identity,
1650 _afterprint: identity,
1651 _noEventDrop: identity,
1652 _noEventResize: identity,
1653 _resize: identity,
1654 _scrollRequest: identity,
1655 };
1656 // calendar-specific options
1657 // -------------------------
1658 const CALENDAR_OPTION_REFINERS = {
1659 buttonText: identity,
1660 buttonHints: identity,
1661 views: identity,
1662 plugins: identity,
1663 initialEvents: identity,
1664 events: identity,
1665 eventSources: identity,
1666 };
1667 const COMPLEX_OPTION_COMPARATORS = {
1668 headerToolbar: isMaybeObjectsEqual,
1669 footerToolbar: isMaybeObjectsEqual,
1670 buttonText: isMaybeObjectsEqual,
1671 buttonHints: isMaybeObjectsEqual,
1672 buttonIcons: isMaybeObjectsEqual,
1673 dateIncrement: isMaybeObjectsEqual,
1674 plugins: isMaybeArraysEqual,
1675 events: isMaybeArraysEqual,
1676 eventSources: isMaybeArraysEqual,
1677 ['resources']: isMaybeArraysEqual,
1678 };
1679 function isMaybeObjectsEqual(a, b) {
1680 if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
1681 return isPropsEqual(a, b);
1682 }
1683 return a === b;
1684 }
1685 function isMaybeArraysEqual(a, b) {
1686 if (Array.isArray(a) && Array.isArray(b)) {
1687 return isArraysEqual(a, b);
1688 }
1689 return a === b;
1690 }
1691 // view-specific options
1692 // ---------------------
1693 const VIEW_OPTION_REFINERS = {
1694 type: String,
1695 component: identity,
1696 buttonText: String,
1697 buttonTextKey: String,
1698 dateProfileGeneratorClass: identity,
1699 usesMinMaxTime: Boolean,
1700 classNames: identity,
1701 content: identity,
1702 didMount: identity,
1703 willUnmount: identity,
1704 };
1705 // util funcs
1706 // ----------------------------------------------------------------------------------------------------
1707 function mergeRawOptions(optionSets) {
1708 return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
1709 }
1710 function refineProps(input, refiners) {
1711 let refined = {};
1712 let extra = {};
1713 for (let propName in refiners) {
1714 if (propName in input) {
1715 refined[propName] = refiners[propName](input[propName]);
1716 }
1717 }
1718 for (let propName in input) {
1719 if (!(propName in refiners)) {
1720 extra[propName] = input[propName];
1721 }
1722 }
1723 return { refined, extra };
1724 }
1725 function identity(raw) {
1726 return raw;
1727 }
1728
1729 function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
1730 return {
1731 instanceId: guid(),
1732 defId,
1733 range,
1734 forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
1735 forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
1736 };
1737 }
1738
1739 function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
1740 for (let i = 0; i < recurringTypes.length; i += 1) {
1741 let parsed = recurringTypes[i].parse(refined, dateEnv);
1742 if (parsed) {
1743 let { allDay } = refined;
1744 if (allDay == null) {
1745 allDay = defaultAllDay;
1746 if (allDay == null) {
1747 allDay = parsed.allDayGuess;
1748 if (allDay == null) {
1749 allDay = false;
1750 }
1751 }
1752 }
1753 return {
1754 allDay,
1755 duration: parsed.duration,
1756 typeData: parsed.typeData,
1757 typeId: i,
1758 };
1759 }
1760 }
1761 return null;
1762 }
1763 function expandRecurring(eventStore, framingRange, context) {
1764 let { dateEnv, pluginHooks, options } = context;
1765 let { defs, instances } = eventStore;
1766 // remove existing recurring instances
1767 // TODO: bad. always expand events as a second step
1768 instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
1769 for (let defId in defs) {
1770 let def = defs[defId];
1771 if (def.recurringDef) {
1772 let { duration } = def.recurringDef;
1773 if (!duration) {
1774 duration = def.allDay ?
1775 options.defaultAllDayEventDuration :
1776 options.defaultTimedEventDuration;
1777 }
1778 let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
1779 for (let start of starts) {
1780 let instance = createEventInstance(defId, {
1781 start,
1782 end: dateEnv.add(start, duration),
1783 });
1784 instances[instance.instanceId] = instance;
1785 }
1786 }
1787 }
1788 return { defs, instances };
1789 }
1790 /*
1791 Event MUST have a recurringDef
1792 */
1793 function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
1794 let typeDef = recurringTypes[eventDef.recurringDef.typeId];
1795 let markers = typeDef.expand(eventDef.recurringDef.typeData, {
1796 start: dateEnv.subtract(framingRange.start, duration),
1797 end: framingRange.end,
1798 }, dateEnv);
1799 // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
1800 if (eventDef.allDay) {
1801 markers = markers.map(startOfDay);
1802 }
1803 return markers;
1804 }
1805
1806 function parseEvents(rawEvents, eventSource, context, allowOpenRange, defIdMap, instanceIdMap) {
1807 let eventStore = createEmptyEventStore();
1808 let eventRefiners = buildEventRefiners(context);
1809 for (let rawEvent of rawEvents) {
1810 let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners, defIdMap, instanceIdMap);
1811 if (tuple) {
1812 eventTupleToStore(tuple, eventStore);
1813 }
1814 }
1815 return eventStore;
1816 }
1817 function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
1818 eventStore.defs[tuple.def.defId] = tuple.def;
1819 if (tuple.instance) {
1820 eventStore.instances[tuple.instance.instanceId] = tuple.instance;
1821 }
1822 return eventStore;
1823 }
1824 // retrieves events that have the same groupId as the instance specified by `instanceId`
1825 // or they are the same as the instance.
1826 // why might instanceId not be in the store? an event from another calendar?
1827 function getRelevantEvents(eventStore, instanceId) {
1828 let instance = eventStore.instances[instanceId];
1829 if (instance) {
1830 let def = eventStore.defs[instance.defId];
1831 // get events/instances with same group
1832 let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
1833 // add the original
1834 // TODO: wish we could use eventTupleToStore or something like it
1835 newStore.defs[def.defId] = def;
1836 newStore.instances[instance.instanceId] = instance;
1837 return newStore;
1838 }
1839 return createEmptyEventStore();
1840 }
1841 function isEventDefsGrouped(def0, def1) {
1842 return Boolean(def0.groupId && def0.groupId === def1.groupId);
1843 }
1844 function createEmptyEventStore() {
1845 return { defs: {}, instances: {} };
1846 }
1847 function mergeEventStores(store0, store1) {
1848 return {
1849 defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
1850 instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
1851 };
1852 }
1853 function filterEventStoreDefs(eventStore, filterFunc) {
1854 let defs = filterHash(eventStore.defs, filterFunc);
1855 let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
1856 ));
1857 return { defs, instances };
1858 }
1859 function excludeSubEventStore(master, sub) {
1860 let { defs, instances } = master;
1861 let filteredDefs = {};
1862 let filteredInstances = {};
1863 for (let defId in defs) {
1864 if (!sub.defs[defId]) { // not explicitly excluded
1865 filteredDefs[defId] = defs[defId];
1866 }
1867 }
1868 for (let instanceId in instances) {
1869 if (!sub.instances[instanceId] && // not explicitly excluded
1870 filteredDefs[instances[instanceId].defId] // def wasn't filtered away
1871 ) {
1872 filteredInstances[instanceId] = instances[instanceId];
1873 }
1874 }
1875 return {
1876 defs: filteredDefs,
1877 instances: filteredInstances,
1878 };
1879 }
1880
1881 function normalizeConstraint(input, context) {
1882 if (Array.isArray(input)) {
1883 return parseEvents(input, null, context, true); // allowOpenRange=true
1884 }
1885 if (typeof input === 'object' && input) { // non-null object
1886 return parseEvents([input], null, context, true); // allowOpenRange=true
1887 }
1888 if (input != null) {
1889 return String(input);
1890 }
1891 return null;
1892 }
1893
1894 function parseClassNames(raw) {
1895 if (Array.isArray(raw)) {
1896 return raw;
1897 }
1898 if (typeof raw === 'string') {
1899 return raw.split(/\s+/);
1900 }
1901 return [];
1902 }
1903
1904 // TODO: better called "EventSettings" or "EventConfig"
1905 // TODO: move this file into structs
1906 // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
1907 const EVENT_UI_REFINERS = {
1908 display: String,
1909 editable: Boolean,
1910 startEditable: Boolean,
1911 durationEditable: Boolean,
1912 constraint: identity,
1913 overlap: identity,
1914 allow: identity,
1915 className: parseClassNames,
1916 classNames: parseClassNames,
1917 color: String,
1918 backgroundColor: String,
1919 borderColor: String,
1920 textColor: String,
1921 };
1922 const EMPTY_EVENT_UI = {
1923 display: null,
1924 startEditable: null,
1925 durationEditable: null,
1926 constraints: [],
1927 overlap: null,
1928 allows: [],
1929 backgroundColor: '',
1930 borderColor: '',
1931 textColor: '',
1932 classNames: [],
1933 };
1934 function createEventUi(refined, context) {
1935 let constraint = normalizeConstraint(refined.constraint, context);
1936 return {
1937 display: refined.display || null,
1938 startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
1939 durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
1940 constraints: constraint != null ? [constraint] : [],
1941 overlap: refined.overlap != null ? refined.overlap : null,
1942 allows: refined.allow != null ? [refined.allow] : [],
1943 backgroundColor: refined.backgroundColor || refined.color || '',
1944 borderColor: refined.borderColor || refined.color || '',
1945 textColor: refined.textColor || '',
1946 classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
1947 };
1948 }
1949 // TODO: prevent against problems with <2 args!
1950 function combineEventUis(uis) {
1951 return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
1952 }
1953 function combineTwoEventUis(item0, item1) {
1954 return {
1955 display: item1.display != null ? item1.display : item0.display,
1956 startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
1957 durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
1958 constraints: item0.constraints.concat(item1.constraints),
1959 overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
1960 allows: item0.allows.concat(item1.allows),
1961 backgroundColor: item1.backgroundColor || item0.backgroundColor,
1962 borderColor: item1.borderColor || item0.borderColor,
1963 textColor: item1.textColor || item0.textColor,
1964 classNames: item0.classNames.concat(item1.classNames),
1965 };
1966 }
1967
1968 const EVENT_NON_DATE_REFINERS = {
1969 id: String,
1970 groupId: String,
1971 title: String,
1972 url: String,
1973 interactive: Boolean,
1974 };
1975 const EVENT_DATE_REFINERS = {
1976 start: identity,
1977 end: identity,
1978 date: identity,
1979 allDay: Boolean,
1980 };
1981 const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), { extendedProps: identity });
1982 function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context), defIdMap, instanceIdMap) {
1983 let { refined, extra } = refineEventDef(raw, context, refiners);
1984 let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
1985 let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
1986 if (recurringRes) {
1987 let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context, defIdMap);
1988 def.recurringDef = {
1989 typeId: recurringRes.typeId,
1990 typeData: recurringRes.typeData,
1991 duration: recurringRes.duration,
1992 };
1993 return { def, instance: null };
1994 }
1995 let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
1996 if (singleRes) {
1997 let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context, defIdMap);
1998 let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
1999 if (instanceIdMap && def.publicId && instanceIdMap[def.publicId]) {
2000 instance.instanceId = instanceIdMap[def.publicId];
2001 }
2002 return { def, instance };
2003 }
2004 return null;
2005 }
2006 function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
2007 return refineProps(raw, refiners);
2008 }
2009 function buildEventRefiners(context) {
2010 return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
2011 }
2012 /*
2013 Will NOT populate extendedProps with the leftover properties.
2014 Will NOT populate date-related props.
2015 */
2016 function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context, defIdMap) {
2017 let def = {
2018 title: refined.title || '',
2019 groupId: refined.groupId || '',
2020 publicId: refined.id || '',
2021 url: refined.url || '',
2022 recurringDef: null,
2023 defId: ((defIdMap && refined.id) ? defIdMap[refined.id] : '') || guid(),
2024 sourceId,
2025 allDay,
2026 hasEnd,
2027 interactive: refined.interactive,
2028 ui: createEventUi(refined, context),
2029 extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
2030 };
2031 for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
2032 Object.assign(def, memberAdder(refined));
2033 }
2034 // help out EventImpl from having user modify props
2035 Object.freeze(def.ui.classNames);
2036 Object.freeze(def.extendedProps);
2037 return def;
2038 }
2039 function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
2040 let { allDay } = refined;
2041 let startMeta;
2042 let startMarker = null;
2043 let hasEnd = false;
2044 let endMeta;
2045 let endMarker = null;
2046 let startInput = refined.start != null ? refined.start : refined.date;
2047 startMeta = context.dateEnv.createMarkerMeta(startInput);
2048 if (startMeta) {
2049 startMarker = startMeta.marker;
2050 }
2051 else if (!allowOpenRange) {
2052 return null;
2053 }
2054 if (refined.end != null) {
2055 endMeta = context.dateEnv.createMarkerMeta(refined.end);
2056 }
2057 if (allDay == null) {
2058 if (defaultAllDay != null) {
2059 allDay = defaultAllDay;
2060 }
2061 else {
2062 // fall back to the date props LAST
2063 allDay = (!startMeta || startMeta.isTimeUnspecified) &&
2064 (!endMeta || endMeta.isTimeUnspecified);
2065 }
2066 }
2067 if (allDay && startMarker) {
2068 startMarker = startOfDay(startMarker);
2069 }
2070 if (endMeta) {
2071 endMarker = endMeta.marker;
2072 if (allDay) {
2073 endMarker = startOfDay(endMarker);
2074 }
2075 if (startMarker && endMarker <= startMarker) {
2076 endMarker = null;
2077 }
2078 }
2079 if (endMarker) {
2080 hasEnd = true;
2081 }
2082 else if (!allowOpenRange) {
2083 hasEnd = context.options.forceEventDuration || false;
2084 endMarker = context.dateEnv.add(startMarker, allDay ?
2085 context.options.defaultAllDayEventDuration :
2086 context.options.defaultTimedEventDuration);
2087 }
2088 return {
2089 allDay,
2090 hasEnd,
2091 range: { start: startMarker, end: endMarker },
2092 forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
2093 forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
2094 };
2095 }
2096 function computeIsDefaultAllDay(eventSource, context) {
2097 let res = null;
2098 if (eventSource) {
2099 res = eventSource.defaultAllDay;
2100 }
2101 if (res == null) {
2102 res = context.options.defaultAllDay;
2103 }
2104 return res;
2105 }
2106
2107 const DEF_DEFAULTS = {
2108 startTime: '09:00',
2109 endTime: '17:00',
2110 daysOfWeek: [1, 2, 3, 4, 5],
2111 display: 'inverse-background',
2112 classNames: 'fc-non-business',
2113 groupId: '_businessHours', // so multiple defs get grouped
2114 };
2115 /*
2116 TODO: pass around as EventDefHash!!!
2117 */
2118 function parseBusinessHours(input, context) {
2119 return parseEvents(refineInputs(input), null, context);
2120 }
2121 function refineInputs(input) {
2122 let rawDefs;
2123 if (input === true) {
2124 rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
2125 }
2126 else if (Array.isArray(input)) {
2127 // if specifying an array, every sub-definition NEEDS a day-of-week
2128 rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
2129 }
2130 else if (typeof input === 'object' && input) { // non-null object
2131 rawDefs = [input];
2132 }
2133 else { // is probably false
2134 rawDefs = [];
2135 }
2136 rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
2137 return rawDefs;
2138 }
2139
2140 /* Date stuff that doesn't belong in datelib core
2141 ----------------------------------------------------------------------------------------------------------------------*/
2142 // given a timed range, computes an all-day range that has the same exact duration,
2143 // but whose start time is aligned with the start of the day.
2144 function computeAlignedDayRange(timedRange) {
2145 let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
2146 let start = startOfDay(timedRange.start);
2147 let end = addDays(start, dayCnt);
2148 return { start, end };
2149 }
2150 // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
2151 // TODO: give nextDayThreshold a default arg
2152 function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
2153 let startDay = null;
2154 let endDay = null;
2155 if (timedRange.end) {
2156 endDay = startOfDay(timedRange.end);
2157 let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
2158 // If the end time is actually inclusively part of the next day and is equal to or
2159 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
2160 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
2161 if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
2162 endDay = addDays(endDay, 1);
2163 }
2164 }
2165 if (timedRange.start) {
2166 startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
2167 // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
2168 if (endDay && endDay <= startDay) {
2169 endDay = addDays(startDay, 1);
2170 }
2171 }
2172 return { start: startDay, end: endDay };
2173 }
2174 // spans from one day into another?
2175 function isMultiDayRange(range) {
2176 let visibleRange = computeVisibleDayRange(range);
2177 return diffDays(visibleRange.start, visibleRange.end) > 1;
2178 }
2179 function diffDates(date0, date1, dateEnv, largeUnit) {
2180 if (largeUnit === 'year') {
2181 return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
2182 }
2183 if (largeUnit === 'month') {
2184 return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
2185 }
2186 return diffDayAndTime(date0, date1); // returns a duration
2187 }
2188
2189 function pointInsideRect(point, rect) {
2190 return point.left >= rect.left &&
2191 point.left < rect.right &&
2192 point.top >= rect.top &&
2193 point.top < rect.bottom;
2194 }
2195 // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
2196 function intersectRects(rect1, rect2) {
2197 let res = {
2198 left: Math.max(rect1.left, rect2.left),
2199 right: Math.min(rect1.right, rect2.right),
2200 top: Math.max(rect1.top, rect2.top),
2201 bottom: Math.min(rect1.bottom, rect2.bottom),
2202 };
2203 if (res.left < res.right && res.top < res.bottom) {
2204 return res;
2205 }
2206 return false;
2207 }
2208 function translateRect(rect, deltaX, deltaY) {
2209 return {
2210 left: rect.left + deltaX,
2211 right: rect.right + deltaX,
2212 top: rect.top + deltaY,
2213 bottom: rect.bottom + deltaY,
2214 };
2215 }
2216 // Returns a new point that will have been moved to reside within the given rectangle
2217 function constrainPoint(point, rect) {
2218 return {
2219 left: Math.min(Math.max(point.left, rect.left), rect.right),
2220 top: Math.min(Math.max(point.top, rect.top), rect.bottom),
2221 };
2222 }
2223 // Returns a point that is the center of the given rectangle
2224 function getRectCenter(rect) {
2225 return {
2226 left: (rect.left + rect.right) / 2,
2227 top: (rect.top + rect.bottom) / 2,
2228 };
2229 }
2230 // Subtracts point2's coordinates from point1's coordinates, returning a delta
2231 function diffPoints(point1, point2) {
2232 return {
2233 left: point1.left - point2.left,
2234 top: point1.top - point2.top,
2235 };
2236 }
2237
2238 let canVGrowWithinCell;
2239 function getCanVGrowWithinCell() {
2240 if (canVGrowWithinCell == null) {
2241 canVGrowWithinCell = computeCanVGrowWithinCell();
2242 }
2243 return canVGrowWithinCell;
2244 }
2245 function computeCanVGrowWithinCell() {
2246 // for SSR, because this function is call immediately at top-level
2247 // TODO: just make this logic execute top-level, immediately, instead of doing lazily
2248 if (typeof document === 'undefined') {
2249 return true;
2250 }
2251 let el = document.createElement('div');
2252 el.style.position = 'absolute';
2253 el.style.top = '0px';
2254 el.style.left = '0px';
2255 el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
2256 el.querySelector('table').style.height = '100px';
2257 el.querySelector('div').style.height = '100%';
2258 document.body.appendChild(el);
2259 let div = el.querySelector('div');
2260 let possible = div.offsetHeight > 0;
2261 document.body.removeChild(el);
2262 return possible;
2263 }
2264
2265 const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
2266 class Splitter {
2267 constructor() {
2268 this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
2269 this.splitDateSelection = memoize(this._splitDateSpan);
2270 this.splitEventStore = memoize(this._splitEventStore);
2271 this.splitIndividualUi = memoize(this._splitIndividualUi);
2272 this.splitEventDrag = memoize(this._splitInteraction);
2273 this.splitEventResize = memoize(this._splitInteraction);
2274 this.eventUiBuilders = {}; // TODO: typescript protection
2275 }
2276 splitProps(props) {
2277 let keyInfos = this.getKeyInfo(props);
2278 let defKeys = this.getKeysForEventDefs(props.eventStore);
2279 let dateSelections = this.splitDateSelection(props.dateSelection);
2280 let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
2281 let eventStores = this.splitEventStore(props.eventStore, defKeys);
2282 let eventDrags = this.splitEventDrag(props.eventDrag);
2283 let eventResizes = this.splitEventResize(props.eventResize);
2284 let splitProps = {};
2285 this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
2286 for (let key in keyInfos) {
2287 let keyInfo = keyInfos[key];
2288 let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
2289 let buildEventUi = this.eventUiBuilders[key];
2290 splitProps[key] = {
2291 businessHours: keyInfo.businessHours || props.businessHours,
2292 dateSelection: dateSelections[key] || null,
2293 eventStore,
2294 eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
2295 eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
2296 eventDrag: eventDrags[key] || null,
2297 eventResize: eventResizes[key] || null,
2298 };
2299 }
2300 return splitProps;
2301 }
2302 _splitDateSpan(dateSpan) {
2303 let dateSpans = {};
2304 if (dateSpan) {
2305 let keys = this.getKeysForDateSpan(dateSpan);
2306 for (let key of keys) {
2307 dateSpans[key] = dateSpan;
2308 }
2309 }
2310 return dateSpans;
2311 }
2312 _getKeysForEventDefs(eventStore) {
2313 return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
2314 }
2315 _splitEventStore(eventStore, defKeys) {
2316 let { defs, instances } = eventStore;
2317 let splitStores = {};
2318 for (let defId in defs) {
2319 for (let key of defKeys[defId]) {
2320 if (!splitStores[key]) {
2321 splitStores[key] = createEmptyEventStore();
2322 }
2323 splitStores[key].defs[defId] = defs[defId];
2324 }
2325 }
2326 for (let instanceId in instances) {
2327 let instance = instances[instanceId];
2328 for (let key of defKeys[instance.defId]) {
2329 if (splitStores[key]) { // must have already been created
2330 splitStores[key].instances[instanceId] = instance;
2331 }
2332 }
2333 }
2334 return splitStores;
2335 }
2336 _splitIndividualUi(eventUiBases, defKeys) {
2337 let splitHashes = {};
2338 for (let defId in eventUiBases) {
2339 if (defId) { // not the '' key
2340 for (let key of defKeys[defId]) {
2341 if (!splitHashes[key]) {
2342 splitHashes[key] = {};
2343 }
2344 splitHashes[key][defId] = eventUiBases[defId];
2345 }
2346 }
2347 }
2348 return splitHashes;
2349 }
2350 _splitInteraction(interaction) {
2351 let splitStates = {};
2352 if (interaction) {
2353 let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
2354 // can't rely on defKeys because event data is mutated
2355 let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
2356 let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
2357 let populate = (key) => {
2358 if (!splitStates[key]) {
2359 splitStates[key] = {
2360 affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
2361 mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
2362 isEvent: interaction.isEvent,
2363 };
2364 }
2365 };
2366 for (let key in affectedStores) {
2367 populate(key);
2368 }
2369 for (let key in mutatedStores) {
2370 populate(key);
2371 }
2372 }
2373 return splitStates;
2374 }
2375 }
2376 function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
2377 let baseParts = [];
2378 if (allUi) {
2379 baseParts.push(allUi);
2380 }
2381 if (eventUiForKey) {
2382 baseParts.push(eventUiForKey);
2383 }
2384 let stuff = {
2385 '': combineEventUis(baseParts),
2386 };
2387 if (individualUi) {
2388 Object.assign(stuff, individualUi);
2389 }
2390 return stuff;
2391 }
2392
2393 function parseRange(input, dateEnv) {
2394 let start = null;
2395 let end = null;
2396 if (input.start) {
2397 start = dateEnv.createMarker(input.start);
2398 }
2399 if (input.end) {
2400 end = dateEnv.createMarker(input.end);
2401 }
2402 if (!start && !end) {
2403 return null;
2404 }
2405 if (start && end && end < start) {
2406 return null;
2407 }
2408 return { start, end };
2409 }
2410 // SIDE-EFFECT: will mutate ranges.
2411 // Will return a new array result.
2412 function invertRanges(ranges, constraintRange) {
2413 let invertedRanges = [];
2414 let { start } = constraintRange; // the end of the previous range. the start of the new range
2415 let i;
2416 let dateRange;
2417 // ranges need to be in order. required for our date-walking algorithm
2418 ranges.sort(compareRanges);
2419 for (i = 0; i < ranges.length; i += 1) {
2420 dateRange = ranges[i];
2421 // add the span of time before the event (if there is any)
2422 if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
2423 invertedRanges.push({ start, end: dateRange.start });
2424 }
2425 if (dateRange.end > start) {
2426 start = dateRange.end;
2427 }
2428 }
2429 // add the span of time after the last event (if there is any)
2430 if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
2431 invertedRanges.push({ start, end: constraintRange.end });
2432 }
2433 return invertedRanges;
2434 }
2435 function compareRanges(range0, range1) {
2436 return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
2437 }
2438 function intersectRanges(range0, range1) {
2439 let { start, end } = range0;
2440 let newRange = null;
2441 if (range1.start !== null) {
2442 if (start === null) {
2443 start = range1.start;
2444 }
2445 else {
2446 start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
2447 }
2448 }
2449 if (range1.end != null) {
2450 if (end === null) {
2451 end = range1.end;
2452 }
2453 else {
2454 end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
2455 }
2456 }
2457 if (start === null || end === null || start < end) {
2458 newRange = { start, end };
2459 }
2460 return newRange;
2461 }
2462 function rangesEqual(range0, range1) {
2463 return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
2464 (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
2465 }
2466 function rangesIntersect(range0, range1) {
2467 return (range0.end === null || range1.start === null || range0.end > range1.start) &&
2468 (range0.start === null || range1.end === null || range0.start < range1.end);
2469 }
2470 function rangeContainsRange(outerRange, innerRange) {
2471 return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
2472 (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
2473 }
2474 function rangeContainsMarker(range, date) {
2475 return (range.start === null || date >= range.start) &&
2476 (range.end === null || date < range.end);
2477 }
2478 // If the given date is not within the given range, move it inside.
2479 // (If it's past the end, make it one millisecond before the end).
2480 function constrainMarkerToRange(date, range) {
2481 if (range.start != null && date < range.start) {
2482 return range.start;
2483 }
2484 if (range.end != null && date >= range.end) {
2485 return new Date(range.end.valueOf() - 1);
2486 }
2487 return date;
2488 }
2489
2490 function getDateMeta(date, todayRange, nowDate, dateProfile) {
2491 return {
2492 dow: date.getUTCDay(),
2493 isDisabled: Boolean(dateProfile && (!dateProfile.activeRange || !rangeContainsMarker(dateProfile.activeRange, date))),
2494 isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
2495 isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
2496 isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
2497 isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
2498 };
2499 }
2500 function getDayClassNames(meta, theme) {
2501 let classNames = [
2502 'fc-day',
2503 `fc-day-${DAY_IDS[meta.dow]}`,
2504 ];
2505 if (meta.isDisabled) {
2506 classNames.push('fc-day-disabled');
2507 }
2508 else {
2509 if (meta.isToday) {
2510 classNames.push('fc-day-today');
2511 classNames.push(theme.getClass('today'));
2512 }
2513 if (meta.isPast) {
2514 classNames.push('fc-day-past');
2515 }
2516 if (meta.isFuture) {
2517 classNames.push('fc-day-future');
2518 }
2519 if (meta.isOther) {
2520 classNames.push('fc-day-other');
2521 }
2522 }
2523 return classNames;
2524 }
2525 function getSlotClassNames(meta, theme) {
2526 let classNames = [
2527 'fc-slot',
2528 `fc-slot-${DAY_IDS[meta.dow]}`,
2529 ];
2530 if (meta.isDisabled) {
2531 classNames.push('fc-slot-disabled');
2532 }
2533 else {
2534 if (meta.isToday) {
2535 classNames.push('fc-slot-today');
2536 classNames.push(theme.getClass('today'));
2537 }
2538 if (meta.isPast) {
2539 classNames.push('fc-slot-past');
2540 }
2541 if (meta.isFuture) {
2542 classNames.push('fc-slot-future');
2543 }
2544 }
2545 return classNames;
2546 }
2547
2548 const DAY_FORMAT = createFormatter({ year: 'numeric', month: 'long', day: 'numeric' });
2549 const WEEK_FORMAT = createFormatter({ week: 'long' });
2550 function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
2551 const { dateEnv, options, calendarApi } = context;
2552 let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
2553 if (options.navLinks) {
2554 let zonedDate = dateEnv.toDate(dateMarker);
2555 const handleInteraction = (ev) => {
2556 let customAction = viewType === 'day' ? options.navLinkDayClick :
2557 viewType === 'week' ? options.navLinkWeekClick : null;
2558 if (typeof customAction === 'function') {
2559 customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
2560 }
2561 else {
2562 if (typeof customAction === 'string') {
2563 viewType = customAction;
2564 }
2565 calendarApi.zoomTo(dateMarker, viewType);
2566 }
2567 };
2568 return Object.assign({ title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr), 'data-navlink': '' }, (isTabbable
2569 ? createAriaClickAttrs(handleInteraction)
2570 : { onClick: handleInteraction }));
2571 }
2572 return { 'aria-label': dateStr };
2573 }
2574
2575 let _isRtlScrollbarOnLeft = null;
2576 function getIsRtlScrollbarOnLeft() {
2577 if (_isRtlScrollbarOnLeft === null) {
2578 _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
2579 }
2580 return _isRtlScrollbarOnLeft;
2581 }
2582 function computeIsRtlScrollbarOnLeft() {
2583 let outerEl = document.createElement('div');
2584 applyStyle(outerEl, {
2585 position: 'absolute',
2586 top: -1000,
2587 left: 0,
2588 border: 0,
2589 padding: 0,
2590 overflow: 'scroll',
2591 direction: 'rtl',
2592 });
2593 outerEl.innerHTML = '<div></div>';
2594 document.body.appendChild(outerEl);
2595 let innerEl = outerEl.firstChild;
2596 let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
2597 removeElement(outerEl);
2598 return res;
2599 }
2600
2601 let _scrollbarWidths;
2602 function getScrollbarWidths() {
2603 if (!_scrollbarWidths) {
2604 _scrollbarWidths = computeScrollbarWidths();
2605 }
2606 return _scrollbarWidths;
2607 }
2608 function computeScrollbarWidths() {
2609 let el = document.createElement('div');
2610 el.style.overflow = 'scroll';
2611 el.style.position = 'absolute';
2612 el.style.top = '-9999px';
2613 el.style.left = '-9999px';
2614 document.body.appendChild(el);
2615 let res = computeScrollbarWidthsForEl(el);
2616 document.body.removeChild(el);
2617 return res;
2618 }
2619 // WARNING: will include border
2620 function computeScrollbarWidthsForEl(el) {
2621 return {
2622 x: el.offsetHeight - el.clientHeight,
2623 y: el.offsetWidth - el.clientWidth,
2624 };
2625 }
2626
2627 function computeEdges(el, getPadding = false) {
2628 let computedStyle = window.getComputedStyle(el);
2629 let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
2630 let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
2631 let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
2632 let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
2633 let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
2634 let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
2635 let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
2636 let res = {
2637 borderLeft,
2638 borderRight,
2639 borderTop,
2640 borderBottom,
2641 scrollbarBottom,
2642 scrollbarLeft: 0,
2643 scrollbarRight: 0,
2644 };
2645 if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
2646 res.scrollbarLeft = scrollbarLeftRight;
2647 }
2648 else {
2649 res.scrollbarRight = scrollbarLeftRight;
2650 }
2651 if (getPadding) {
2652 res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
2653 res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
2654 res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
2655 res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
2656 }
2657 return res;
2658 }
2659 function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
2660 let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
2661 let edges = computeEdges(el, goWithinPadding);
2662 let res = {
2663 left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
2664 right: outerRect.right - edges.borderRight - edges.scrollbarRight,
2665 top: outerRect.top + edges.borderTop,
2666 bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
2667 };
2668 if (goWithinPadding) {
2669 res.left += edges.paddingLeft;
2670 res.right -= edges.paddingRight;
2671 res.top += edges.paddingTop;
2672 res.bottom -= edges.paddingBottom;
2673 }
2674 return res;
2675 }
2676 function computeRect(el) {
2677 let rect = el.getBoundingClientRect();
2678 return {
2679 left: rect.left + window.scrollX,
2680 top: rect.top + window.scrollY,
2681 right: rect.right + window.scrollX,
2682 bottom: rect.bottom + window.scrollY,
2683 };
2684 }
2685 function computeClippedClientRect(el) {
2686 let clippingParents = getClippingParents(el);
2687 let rect = el.getBoundingClientRect();
2688 for (let clippingParent of clippingParents) {
2689 let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
2690 if (intersection) {
2691 rect = intersection;
2692 }
2693 else {
2694 return null;
2695 }
2696 }
2697 return rect;
2698 }
2699 // does not return window
2700 function getClippingParents(el) {
2701 let parents = [];
2702 while (el instanceof HTMLElement) { // will stop when gets to document or null
2703 let computedStyle = window.getComputedStyle(el);
2704 if (computedStyle.position === 'fixed') {
2705 break;
2706 }
2707 if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
2708 parents.push(el);
2709 }
2710 el = el.parentNode;
2711 }
2712 return parents;
2713 }
2714
2715 /*
2716 given a function that resolves a result asynchronously.
2717 the function can either call passed-in success and failure callbacks,
2718 or it can return a promise.
2719 if you need to pass additional params to func, bind them first.
2720 */
2721 function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
2722 // guard against success/failure callbacks being called more than once
2723 // and guard against a promise AND callback being used together.
2724 let isResolved = false;
2725 let wrappedSuccess = function (res) {
2726 if (!isResolved) {
2727 isResolved = true;
2728 normalizedSuccessCallback(res);
2729 }
2730 };
2731 let wrappedFailure = function (error) {
2732 if (!isResolved) {
2733 isResolved = true;
2734 normalizedFailureCallback(error);
2735 }
2736 };
2737 let res = func(wrappedSuccess, wrappedFailure);
2738 if (res && typeof res.then === 'function') {
2739 res.then(wrappedSuccess, wrappedFailure);
2740 }
2741 }
2742
2743 class Emitter {
2744 constructor() {
2745 this.handlers = {};
2746 this.thisContext = null;
2747 }
2748 setThisContext(thisContext) {
2749 this.thisContext = thisContext;
2750 }
2751 setOptions(options) {
2752 this.options = options;
2753 }
2754 on(type, handler) {
2755 addToHash(this.handlers, type, handler);
2756 }
2757 off(type, handler) {
2758 removeFromHash(this.handlers, type, handler);
2759 }
2760 trigger(type, ...args) {
2761 let attachedHandlers = this.handlers[type] || [];
2762 let optionHandler = this.options && this.options[type];
2763 let handlers = [].concat(optionHandler || [], attachedHandlers);
2764 for (let handler of handlers) {
2765 handler.apply(this.thisContext, args);
2766 }
2767 }
2768 hasHandlers(type) {
2769 return Boolean((this.handlers[type] && this.handlers[type].length) ||
2770 (this.options && this.options[type]));
2771 }
2772 }
2773 function addToHash(hash, type, handler) {
2774 (hash[type] || (hash[type] = []))
2775 .push(handler);
2776 }
2777 function removeFromHash(hash, type, handler) {
2778 if (handler) {
2779 if (hash[type]) {
2780 hash[type] = hash[type].filter((func) => func !== handler);
2781 }
2782 }
2783 else {
2784 delete hash[type]; // remove all handler funcs for this type
2785 }
2786 }
2787
2788 /*
2789 Records offset information for a set of elements, relative to an origin element.
2790 Can record the left/right OR the top/bottom OR both.
2791 Provides methods for querying the cache by position.
2792 */
2793 class PositionCache {
2794 constructor(originEl, els, isHorizontal, isVertical) {
2795 this.els = els;
2796 let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
2797 if (isHorizontal) {
2798 this.buildElHorizontals(originClientRect.left);
2799 }
2800 if (isVertical) {
2801 this.buildElVerticals(originClientRect.top);
2802 }
2803 }
2804 // Populates the left/right internal coordinate arrays
2805 buildElHorizontals(originClientLeft) {
2806 let lefts = [];
2807 let rights = [];
2808 for (let el of this.els) {
2809 let rect = el.getBoundingClientRect();
2810 lefts.push(rect.left - originClientLeft);
2811 rights.push(rect.right - originClientLeft);
2812 }
2813 this.lefts = lefts;
2814 this.rights = rights;
2815 }
2816 // Populates the top/bottom internal coordinate arrays
2817 buildElVerticals(originClientTop) {
2818 let tops = [];
2819 let bottoms = [];
2820 for (let el of this.els) {
2821 let rect = el.getBoundingClientRect();
2822 tops.push(rect.top - originClientTop);
2823 bottoms.push(rect.bottom - originClientTop);
2824 }
2825 this.tops = tops;
2826 this.bottoms = bottoms;
2827 }
2828 // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
2829 // If no intersection is made, returns undefined.
2830 leftToIndex(leftPosition) {
2831 let { lefts, rights } = this;
2832 let len = lefts.length;
2833 let i;
2834 for (i = 0; i < len; i += 1) {
2835 if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
2836 return i;
2837 }
2838 }
2839 return undefined; // TODO: better
2840 }
2841 // Given a top offset (from document top), returns the index of the el that it vertically intersects.
2842 // If no intersection is made, returns undefined.
2843 topToIndex(topPosition) {
2844 let { tops, bottoms } = this;
2845 let len = tops.length;
2846 let i;
2847 for (i = 0; i < len; i += 1) {
2848 if (topPosition >= tops[i] && topPosition < bottoms[i]) {
2849 return i;
2850 }
2851 }
2852 return undefined; // TODO: better
2853 }
2854 // Gets the width of the element at the given index
2855 getWidth(leftIndex) {
2856 return this.rights[leftIndex] - this.lefts[leftIndex];
2857 }
2858 // Gets the height of the element at the given index
2859 getHeight(topIndex) {
2860 return this.bottoms[topIndex] - this.tops[topIndex];
2861 }
2862 similarTo(otherCache) {
2863 return similarNumArrays(this.tops || [], otherCache.tops || []) &&
2864 similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
2865 similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
2866 similarNumArrays(this.rights || [], otherCache.rights || []);
2867 }
2868 }
2869 function similarNumArrays(a, b) {
2870 const len = a.length;
2871 if (len !== b.length) {
2872 return false;
2873 }
2874 for (let i = 0; i < len; i++) {
2875 if (Math.round(a[i]) !== Math.round(b[i])) {
2876 return false;
2877 }
2878 }
2879 return true;
2880 }
2881
2882 /* eslint max-classes-per-file: "off" */
2883 /*
2884 An object for getting/setting scroll-related information for an element.
2885 Internally, this is done very differently for window versus DOM element,
2886 so this object serves as a common interface.
2887 */
2888 class ScrollController {
2889 getMaxScrollTop() {
2890 return this.getScrollHeight() - this.getClientHeight();
2891 }
2892 getMaxScrollLeft() {
2893 return this.getScrollWidth() - this.getClientWidth();
2894 }
2895 canScrollVertically() {
2896 return this.getMaxScrollTop() > 0;
2897 }
2898 canScrollHorizontally() {
2899 return this.getMaxScrollLeft() > 0;
2900 }
2901 canScrollUp() {
2902 return this.getScrollTop() > 0;
2903 }
2904 canScrollDown() {
2905 return this.getScrollTop() < this.getMaxScrollTop();
2906 }
2907 canScrollLeft() {
2908 return this.getScrollLeft() > 0;
2909 }
2910 canScrollRight() {
2911 return this.getScrollLeft() < this.getMaxScrollLeft();
2912 }
2913 }
2914 class ElementScrollController extends ScrollController {
2915 constructor(el) {
2916 super();
2917 this.el = el;
2918 }
2919 getScrollTop() {
2920 return this.el.scrollTop;
2921 }
2922 getScrollLeft() {
2923 return this.el.scrollLeft;
2924 }
2925 setScrollTop(top) {
2926 this.el.scrollTop = top;
2927 }
2928 setScrollLeft(left) {
2929 this.el.scrollLeft = left;
2930 }
2931 getScrollWidth() {
2932 return this.el.scrollWidth;
2933 }
2934 getScrollHeight() {
2935 return this.el.scrollHeight;
2936 }
2937 getClientHeight() {
2938 return this.el.clientHeight;
2939 }
2940 getClientWidth() {
2941 return this.el.clientWidth;
2942 }
2943 }
2944 class WindowScrollController extends ScrollController {
2945 getScrollTop() {
2946 return window.scrollY;
2947 }
2948 getScrollLeft() {
2949 return window.scrollX;
2950 }
2951 setScrollTop(n) {
2952 window.scroll(window.scrollX, n);
2953 }
2954 setScrollLeft(n) {
2955 window.scroll(n, window.scrollY);
2956 }
2957 getScrollWidth() {
2958 return document.documentElement.scrollWidth;
2959 }
2960 getScrollHeight() {
2961 return document.documentElement.scrollHeight;
2962 }
2963 getClientHeight() {
2964 return document.documentElement.clientHeight;
2965 }
2966 getClientWidth() {
2967 return document.documentElement.clientWidth;
2968 }
2969 }
2970
2971 class Theme {
2972 constructor(calendarOptions) {
2973 if (this.iconOverrideOption) {
2974 this.setIconOverride(calendarOptions[this.iconOverrideOption]);
2975 }
2976 }
2977 setIconOverride(iconOverrideHash) {
2978 let iconClassesCopy;
2979 let buttonName;
2980 if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
2981 iconClassesCopy = Object.assign({}, this.iconClasses);
2982 for (buttonName in iconOverrideHash) {
2983 iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
2984 }
2985 this.iconClasses = iconClassesCopy;
2986 }
2987 else if (iconOverrideHash === false) {
2988 this.iconClasses = {};
2989 }
2990 }
2991 applyIconOverridePrefix(className) {
2992 let prefix = this.iconOverridePrefix;
2993 if (prefix && className.indexOf(prefix) !== 0) { // if not already present
2994 className = prefix + className;
2995 }
2996 return className;
2997 }
2998 getClass(key) {
2999 return this.classes[key] || '';
3000 }
3001 getIconClass(buttonName, isRtl) {
3002 let className;
3003 if (isRtl && this.rtlIconClasses) {
3004 className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
3005 }
3006 else {
3007 className = this.iconClasses[buttonName];
3008 }
3009 if (className) {
3010 return `${this.baseIconClass} ${className}`;
3011 }
3012 return '';
3013 }
3014 getCustomButtonIconClass(customButtonProps) {
3015 let className;
3016 if (this.iconOverrideCustomButtonOption) {
3017 className = customButtonProps[this.iconOverrideCustomButtonOption];
3018 if (className) {
3019 return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
3020 }
3021 }
3022 return '';
3023 }
3024 }
3025 Theme.prototype.classes = {};
3026 Theme.prototype.iconClasses = {};
3027 Theme.prototype.baseIconClass = '';
3028 Theme.prototype.iconOverridePrefix = '';
3029
3030 var n,l$1,u$1,i$1,t,r$1,o,f$1,e$1,c$1={},s=[],a$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function h(n,l){for(var u in l)n[u]=l[u];return n}function v$1(n){var l=n.parentNode;l&&l.removeChild(n);}function y(l,u,i){var t,r,o,f={};for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps)void 0===f[o]&&(f[o]=l.defaultProps[o]);return p(l,f,t,r,null)}function p(n,i,t,r,o){var f={type:n,props:i,key:t,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++u$1:o};return null==o&&null!=l$1.vnode&&l$1.vnode(f),f}function d(){return {current:null}}function _(n){return n.children}function k$1(n,l,u,i,t){var r;for(r in u)"children"===r||"key"===r||r in l||g$2(n,r,null,u[r],i);for(r in l)t&&"function"!=typeof l[r]||"children"===r||"key"===r||"value"===r||"checked"===r||u[r]===l[r]||g$2(n,r,l[r],u[r],i);}function b$1(n,l,u){"-"===l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||a$1.test(l)?u:u+"px";}function g$2(n,l,u,i,t){var r;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof i&&(n.style.cssText=i=""),i)for(l in i)u&&l in u||b$1(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||b$1(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])r=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?i||n.addEventListener(l,r?w$2:m$1,r):n.removeEventListener(l,r?w$2:m$1,r);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==l&&"height"!==l&&"href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||!1===u&&-1==l.indexOf("-")?n.removeAttribute(l):n.setAttribute(l,u));}}function m$1(n){t=!0;try{return this.l[n.type+!1](l$1.event?l$1.event(n):n)}finally{t=!1;}}function w$2(n){t=!0;try{return this.l[n.type+!0](l$1.event?l$1.event(n):n)}finally{t=!1;}}function x$1(n,l){this.props=n,this.context=l;}function A(n,l){if(null==l)return n.__?A(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?A(n):null}function P$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return P$1(n)}}function C$1(n){t?setTimeout(n):f$1(n);}function T$1(n){(!n.__d&&(n.__d=!0)&&r$1.push(n)&&!$$1.__r++||o!==l$1.debounceRendering)&&((o=l$1.debounceRendering)||C$1)($$1);}function $$1(){var n,l,u,i,t,o,f,e;for(r$1.sort(function(n,l){return n.__v.__b-l.__v.__b});n=r$1.shift();)n.__d&&(l=r$1.length,i=void 0,t=void 0,f=(o=(u=n).__v).__e,(e=u.__P)&&(i=[],(t=h({},o)).__v=o.__v+1,M(e,o,t,u.__n,void 0!==e.ownerSVGElement,null!=o.__h?[f]:null,i,null==f?A(o):f,o.__h),N(i,o),o.__e!=f&&P$1(o)),r$1.length>l&&r$1.sort(function(n,l){return n.__v.__b-l.__v.__b}));$$1.__r=0;}function H$1(n,l,u,i,t,r,o,f,e,a){var h,v,y,d,k,b,g,m=i&&i.__k||s,w=m.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(d=u.__k[h]=null==(d=l[h])||"boolean"==typeof d?null:"string"==typeof d||"number"==typeof d||"bigint"==typeof d?p(null,d,null,null,d):Array.isArray(d)?p(_,{children:d},null,null,null):d.__b>0?p(d.type,d.props,d.key,d.ref?d.ref:null,d.__v):d)){if(d.__=u,d.__b=u.__b+1,null===(y=m[h])||y&&d.key==y.key&&d.type===y.type)m[h]=void 0;else for(v=0;v<w;v++){if((y=m[v])&&d.key==y.key&&d.type===y.type){m[v]=void 0;break}y=null;}M(n,d,y=y||c$1,t,r,o,f,e,a),k=d.__e,(v=d.ref)&&y.ref!=v&&(g||(g=[]),y.ref&&g.push(y.ref,null,d),g.push(v,d.__c||k,d)),null!=k?(null==b&&(b=k),"function"==typeof d.type&&d.__k===y.__k?d.__d=e=I$1(d,e,n):e=z$1(n,d,y,m,k,e),"function"==typeof u.type&&(u.__d=e)):e&&y.__e==e&&e.parentNode!=n&&(e=A(y));}for(u.__e=b,h=w;h--;)null!=m[h]&&("function"==typeof u.type&&null!=m[h].__e&&m[h].__e==u.__d&&(u.__d=L$1(i).nextSibling),q(m[h],m[h]));if(g)for(h=0;h<g.length;h++)S(g[h],g[++h],g[++h]);}function I$1(n,l,u){for(var i,t=n.__k,r=0;t&&r<t.length;r++)(i=t[r])&&(i.__=n,l="function"==typeof i.type?I$1(i,l,u):z$1(u,i,i,t,i.__e,l));return l}function j$2(n,l){return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some(function(n){j$2(n,l);}):l.push(n)),l}function z$1(n,l,u,i,t,r){var o,f,e;if(void 0!==l.__d)o=l.__d,l.__d=void 0;else if(null==u||t!=r||null==t.parentNode)n:if(null==r||r.parentNode!==n)n.appendChild(t),o=null;else {for(f=r,e=0;(f=f.nextSibling)&&e<i.length;e+=1)if(f==t)break n;n.insertBefore(t,r),o=r;}return void 0!==o?o:t.nextSibling}function L$1(n){var l,u,i;if(null==n.type||"string"==typeof n.type)return n.__e;if(n.__k)for(l=n.__k.length-1;l>=0;l--)if((u=n.__k[l])&&(i=L$1(u)))return i;return null}function M(n,u,i,t,r,o,f,e,c){var s,a,v,y,p,d,k,b,g,m,w,A,P,C,T,$=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,o=[e]),(s=l$1.__b)&&s(u);try{n:if("function"==typeof $){if(b=u.props,g=(s=$.contextType)&&t[s.__c],m=s?g?g.props.value:s.__:t,i.__c?k=(a=u.__c=i.__c).__=a.__E:("prototype"in $&&$.prototype.render?u.__c=a=new $(b,m):(u.__c=a=new x$1(b,m),a.constructor=$,a.render=B$1),g&&g.sub(a),a.props=b,a.state||(a.state={}),a.context=m,a.__n=t,v=a.__d=!0,a.__h=[],a._sb=[]),null==a.__s&&(a.__s=a.state),null!=$.getDerivedStateFromProps&&(a.__s==a.state&&(a.__s=h({},a.__s)),h(a.__s,$.getDerivedStateFromProps(b,a.__s))),y=a.props,p=a.state,a.__v=u,v)null==$.getDerivedStateFromProps&&null!=a.componentWillMount&&a.componentWillMount(),null!=a.componentDidMount&&a.__h.push(a.componentDidMount);else {if(null==$.getDerivedStateFromProps&&b!==y&&null!=a.componentWillReceiveProps&&a.componentWillReceiveProps(b,m),!a.__e&&null!=a.shouldComponentUpdate&&!1===a.shouldComponentUpdate(b,a.__s,m)||u.__v===i.__v){for(u.__v!==i.__v&&(a.props=b,a.state=a.__s,a.__d=!1),u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),w=0;w<a._sb.length;w++)a.__h.push(a._sb[w]);a._sb=[],a.__h.length&&f.push(a);break n}null!=a.componentWillUpdate&&a.componentWillUpdate(b,a.__s,m),null!=a.componentDidUpdate&&a.__h.push(function(){a.componentDidUpdate(y,p,d);});}if(a.context=m,a.props=b,a.__P=n,A=l$1.__r,P=0,"prototype"in $&&$.prototype.render){for(a.state=a.__s,a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),C=0;C<a._sb.length;C++)a.__h.push(a._sb[C]);a._sb=[];}else do{a.__d=!1,A&&A(u),s=a.render(a.props,a.state,a.context),a.state=a.__s;}while(a.__d&&++P<25);a.state=a.__s,null!=a.getChildContext&&(t=h(h({},t),a.getChildContext())),v||null==a.getSnapshotBeforeUpdate||(d=a.getSnapshotBeforeUpdate(y,p)),T=null!=s&&s.type===_&&null==s.key?s.props.children:s,H$1(n,Array.isArray(T)?T:[T],u,i,t,r,o,f,e,c),a.base=u.__e,u.__h=null,a.__h.length&&f.push(a),k&&(a.__E=a.__=null),a.__e=!1;}else null==o&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=O(i.__e,u,i,t,r,o,f,c);(s=l$1.diffed)&&s(u);}catch(n){u.__v=null,(c||null!=o)&&(u.__e=e,u.__h=!!c,o[o.indexOf(e)]=null),l$1.__e(n,u,i);}}function N(n,u){l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function O(l,u,i,t,r,o,f,e){var s,a,h,y=i.props,p=u.props,d=u.type,_=0;if("svg"===d&&(r=!0),null!=o)for(;_<o.length;_++)if((s=o[_])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,o[_]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=r?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),o=null,e=!1;}if(null===d)y===p||e&&l.data===p||(l.data=p);else {if(o=o&&n.call(l.childNodes),a=(y=i.props||c$1).dangerouslySetInnerHTML,h=p.dangerouslySetInnerHTML,!e){if(null!=o)for(y={},_=0;_<l.attributes.length;_++)y[l.attributes[_].name]=l.attributes[_].value;(h||a)&&(h&&(a&&h.__html==a.__html||h.__html===l.innerHTML)||(l.innerHTML=h&&h.__html||""));}if(k$1(l,p,y,r,e),h)u.__k=[];else if(_=u.props.children,H$1(l,Array.isArray(_)?_:[_],u,i,t,r&&"foreignObject"!==d,o,f,o?o[0]:i.__k&&A(i,0),e),null!=o)for(_=o.length;_--;)null!=o[_]&&v$1(o[_]);e||("value"in p&&void 0!==(_=p.value)&&(_!==l.value||"progress"===d&&!_||"option"===d&&_!==y.value)&&g$2(l,"value",_,y.value,!1),"checked"in p&&void 0!==(_=p.checked)&&_!==l.checked&&g$2(l,"checked",_,y.checked,!1));}return l}function S(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function q(n,u,i){var t,r;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||S(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(n){l$1.__e(n,u);}t.base=t.__P=null,n.__c=void 0;}if(t=n.__k)for(r=0;r<t.length;r++)t[r]&&q(t[r],u,i||"function"!=typeof n.type);i||null==n.__e||v$1(n.__e),n.__=n.__e=n.__d=void 0;}function B$1(n,l,u){return this.constructor(n,u)}function D$1(u,i,t){var r,o,f;l$1.__&&l$1.__(u,i),o=(r="function"==typeof t)?null:t&&t.__k||i.__k,f=[],M(i,u=(!r&&t||i).__k=y(_,null,[u]),o||c$1,c$1,void 0!==i.ownerSVGElement,!r&&t?[t]:o?null:i.firstChild?n.call(i.childNodes):null,f,!r&&t?t:o?o.__e:i.firstChild,r),N(f,u);}function E(n,l){D$1(n,l,E);}function F$1(l,u,i){var t,r,o,f=h({},l.props);for(o in u)"key"==o?t=u[o]:"ref"==o?r=u[o]:f[o]=u[o];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),p(l.type,f,t||l.key,r||l.ref,null)}function G$1(n,l){var u={__c:l="__cC"+e$1++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,i;return this.getChildContext||(u=[],(i={})[l]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(function(n){n.__e=!0,T$1(n);});},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n);};}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=s.slice,l$1={__e:function(n,l,u,i){for(var t,r,o;l=l.__;)if((t=l.__c)&&!t.__)try{if((r=t.constructor)&&null!=r.getDerivedStateFromError&&(t.setState(r.getDerivedStateFromError(n)),o=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),o=t.__d),o)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,i$1=function(n){return null!=n&&void 0===n.constructor},t=!1,x$1.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=h({},this.state),"function"==typeof n&&(n=n(h({},u),this.props)),n&&h(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),T$1(this));},x$1.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),T$1(this));},x$1.prototype.render=_,r$1=[],f$1="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,$$1.__r=0,e$1=0;
3031
3032 var r,u,i,f=[],c=[],e=l$1.__b,a=l$1.__r,v=l$1.diffed,l=l$1.__c,m=l$1.unmount;function b(){for(var t;t=f.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(k),t.__H.__h.forEach(w$1),t.__H.__h=[];}catch(r){t.__H.__h=[],l$1.__e(r,t.__v);}}l$1.__b=function(n){r=null,e&&e(n);},l$1.__r=function(n){a&&a(n);var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=c,n.__N=n.i=void 0;})):(i.__h.forEach(k),i.__h.forEach(w$1),i.__h=[])),u=r;},l$1.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==f.push(o)&&i===l$1.requestAnimationFrame||((i=l$1.requestAnimationFrame)||j$1)(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==c&&(n.__=n.__V),n.i=void 0,n.__V=c;})),u=r=null;},l$1.__c=function(t,r){r.some(function(t){try{t.__h.forEach(k),t.__h=t.__h.filter(function(n){return !n.__||w$1(n)});}catch(u){r.some(function(n){n.__h&&(n.__h=[]);}),r=[],l$1.__e(u,t.__v);}}),l&&l(t,r);},l$1.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{k(n);}catch(n){r=n;}}),u.__H=void 0,r&&l$1.__e(r,u.__v));};var g$1="function"==typeof requestAnimationFrame;function j$1(n){var t,r=function(){clearTimeout(u),g$1&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,100);g$1&&(t=requestAnimationFrame(r));}function k(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function w$1(n){var t=r;n.__c=n.__(),r=t;}
3033
3034 function g(n,t){for(var e in t)n[e]=t[e];return n}function C(n,t){for(var e in n)if("__source"!==e&&!(e in t))return !0;for(var r in t)if("__source"!==r&&n[r]!==t[r])return !0;return !1}function w(n){this.props=n;}(w.prototype=new x$1).isPureReactComponent=!0,w.prototype.shouldComponentUpdate=function(n,t){return C(this.props,n)||C(this.state,t)};var x=l$1.__b;l$1.__b=function(n){n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),x&&x(n);};var T=l$1.__e;l$1.__e=function(n,t,e,r){if(n.then)for(var u,o=t;o=o.__;)if((u=o.__c)&&u.__c)return null==t.__e&&(t.__e=e.__e,t.__k=e.__k),u.__c(n,t);T(n,t,e,r);};var I=l$1.unmount;function L(n,t,e){return n&&(n.__c&&n.__c.__H&&(n.__c.__H.__.forEach(function(n){"function"==typeof n.__c&&n.__c();}),n.__c.__H=null),null!=(n=g({},n)).__c&&(n.__c.__P===e&&(n.__c.__P=t),n.__c=null),n.__k=n.__k&&n.__k.map(function(n){return L(n,t,e)})),n}function U(n,t,e){return n&&(n.__v=null,n.__k=n.__k&&n.__k.map(function(n){return U(n,t,e)}),n.__c&&n.__c.__P===t&&(n.__e&&e.insertBefore(n.__e,n.__d),n.__c.__e=!0,n.__c.__P=e)),n}function D(){this.__u=0,this.t=null,this.__b=null;}function F(n){var t=n.__.__c;return t&&t.__a&&t.__a(n)}function V(){this.u=null,this.o=null;}l$1.unmount=function(n){var t=n.__c;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),I&&I(n);},(D.prototype=new x$1).__c=function(n,t){var e=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(e);var u=F(r.__v),o=!1,i=function(){o||(o=!0,e.__R=null,u?u(l):l());};e.__R=i;var l=function(){if(!--r.__u){if(r.state.__a){var n=r.state.__a;r.__v.__k[0]=U(n,n.__c.__P,n.__c.__O);}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate();}},c=!0===t.__h;r.__u++||c||r.setState({__a:r.__b=r.__v.__k[0]}),n.then(i,i);},D.prototype.componentWillUnmount=function(){this.t=[];},D.prototype.render=function(n,e){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),o=this.__v.__k[0].__c;this.__v.__k[0]=L(this.__b,r,o.__O=o.__P);}this.__b=null;}var i=e.__a&&y(_,null,n.fallback);return i&&(i.__h=null),[y(_,null,e.__a?null:n.children),i]};var W=function(n,t,e){if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&("t"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2];}};function P(n){return this.getChildContext=function(){return n.context},n.children}function $(n){var e=this,r=n.i;e.componentWillUnmount=function(){D$1(null,e.l),e.l=null,e.i=null;},e.i&&e.i!==r&&e.componentWillUnmount(),n.__v?(e.l||(e.i=r,e.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),e.i.appendChild(n);},insertBefore:function(n,t){this.childNodes.push(n),e.i.appendChild(n);},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),e.i.removeChild(n);}}),D$1(y(P,{context:e.context},n.__v),e.l)):e.l&&e.componentWillUnmount();}function j(n,e){var r=y($,{__v:n,i:e});return r.containerInfo=e,r}(V.prototype=new x$1).__a=function(n){var t=this,e=F(t.__v),r=t.o.get(n);return r[0]++,function(u){var o=function(){t.props.revealOrder?(r.push(u),W(t,n,r)):u();};e?e(o):o();}},V.prototype.render=function(n){this.u=null,this.o=new Map;var t=j$2(n.children);n.revealOrder&&"b"===n.revealOrder[0]&&t.reverse();for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children},V.prototype.componentDidUpdate=V.prototype.componentDidMount=function(){var n=this;this.o.forEach(function(t,e){W(n,e,t);});};var z="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,B=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,H="undefined"!=typeof document,Z=function(n){return ("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n)};x$1.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(x$1.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(n){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:n});}});});var G=l$1.event;function J(){}function K(){return this.cancelBubble}function Q(){return this.defaultPrevented}l$1.event=function(n){return G&&(n=G(n)),n.persist=J,n.isPropagationStopped=K,n.isDefaultPrevented=Q,n.nativeEvent=n};var nn={configurable:!0,get:function(){return this.class}},tn=l$1.vnode;l$1.vnode=function(n){var t=n.type,e=n.props,u=e;if("string"==typeof t){var o=-1===t.indexOf("-");for(var i in u={},e){var l=e[i];H&&"children"===i&&"noscript"===t||"value"===i&&"defaultValue"in e&&null==l||("defaultValue"===i&&"value"in e&&null==e.value?i="value":"download"===i&&!0===l?l="":/ondoubleclick/i.test(i)?i="ondblclick":/^onchange(textarea|input)/i.test(i+t)&&!Z(e.type)?i="oninput":/^onfocus$/i.test(i)?i="onfocusin":/^onblur$/i.test(i)?i="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i)?i=i.toLowerCase():o&&B.test(i)?i=i.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===l&&(l=void 0),/^oninput$/i.test(i)&&(i=i.toLowerCase(),u[i]&&(i="oninputCapture")),u[i]=l);}"select"==t&&u.multiple&&Array.isArray(u.value)&&(u.value=j$2(e.children).forEach(function(n){n.props.selected=-1!=u.value.indexOf(n.props.value);})),"select"==t&&null!=u.defaultValue&&(u.value=j$2(e.children).forEach(function(n){n.props.selected=u.multiple?-1!=u.defaultValue.indexOf(n.props.value):u.defaultValue==n.props.value;})),n.props=u,e.class!=e.className&&(nn.enumerable="className"in e,null!=e.className&&(u.class=e.className),Object.defineProperty(u,"className",nn));}n.$$typeof=z,tn&&tn(n);};var en=l$1.__r;l$1.__r=function(n){en&&en(n),n.__c;};
3035
3036 /*
3037 NOTE: this can be a public API, especially createElement for hooks.
3038 See examples/typescript-scheduler/src/index.ts
3039 */
3040 function flushSync(runBeforeFlush) {
3041 runBeforeFlush();
3042 let oldDebounceRendering = l$1.debounceRendering; // orig
3043 let callbackQ = [];
3044 function execCallbackSync(callback) {
3045 callbackQ.push(callback);
3046 }
3047 l$1.debounceRendering = execCallbackSync;
3048 D$1(y(FakeComponent, {}), document.createElement('div'));
3049 while (callbackQ.length) {
3050 callbackQ.shift()();
3051 }
3052 l$1.debounceRendering = oldDebounceRendering;
3053 }
3054 class FakeComponent extends x$1 {
3055 render() { return y('div', {}); }
3056 componentDidMount() { this.setState({}); }
3057 }
3058 // TODO: use preact/compat instead?
3059 function createContext(defaultValue) {
3060 let ContextType = G$1(defaultValue);
3061 let origProvider = ContextType.Provider;
3062 ContextType.Provider = function () {
3063 let isNew = !this.getChildContext;
3064 let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
3065 if (isNew) {
3066 let subs = [];
3067 this.shouldComponentUpdate = (_props) => {
3068 if (this.props.value !== _props.value) {
3069 subs.forEach((c) => {
3070 c.context = _props.value;
3071 c.forceUpdate();
3072 });
3073 }
3074 };
3075 this.sub = (c) => {
3076 subs.push(c);
3077 let old = c.componentWillUnmount;
3078 c.componentWillUnmount = () => {
3079 subs.splice(subs.indexOf(c), 1);
3080 old && old.call(c);
3081 };
3082 };
3083 }
3084 return children;
3085 };
3086 return ContextType;
3087 }
3088
3089 var preact = {
3090 __proto__: null,
3091 flushSync: flushSync,
3092 createContext: createContext,
3093 createPortal: j,
3094 Component: x$1,
3095 Fragment: _,
3096 cloneElement: F$1,
3097 createElement: y,
3098 createRef: d,
3099 h: y,
3100 hydrate: E,
3101 get isValidElement () { return i$1; },
3102 get options () { return l$1; },
3103 render: D$1,
3104 toChildArray: j$2
3105 };
3106
3107 class ScrollResponder {
3108 constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
3109 this.execFunc = execFunc;
3110 this.emitter = emitter;
3111 this.scrollTime = scrollTime;
3112 this.scrollTimeReset = scrollTimeReset;
3113 this.handleScrollRequest = (request) => {
3114 this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
3115 this.drain();
3116 };
3117 emitter.on('_scrollRequest', this.handleScrollRequest);
3118 this.fireInitialScroll();
3119 }
3120 detach() {
3121 this.emitter.off('_scrollRequest', this.handleScrollRequest);
3122 }
3123 update(isDatesNew) {
3124 if (isDatesNew && this.scrollTimeReset) {
3125 this.fireInitialScroll(); // will drain
3126 }
3127 else {
3128 this.drain();
3129 }
3130 }
3131 fireInitialScroll() {
3132 this.handleScrollRequest({
3133 time: this.scrollTime,
3134 });
3135 }
3136 drain() {
3137 if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
3138 this.queuedRequest = null;
3139 }
3140 }
3141 }
3142
3143 const ViewContextType = createContext({}); // for Components
3144 function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, nowManager, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
3145 return {
3146 dateEnv,
3147 nowManager,
3148 options: viewOptions,
3149 pluginHooks,
3150 emitter,
3151 dispatch,
3152 getCurrentData,
3153 calendarApi,
3154 viewSpec,
3155 viewApi,
3156 dateProfileGenerator,
3157 theme,
3158 isRtl: viewOptions.direction === 'rtl',
3159 addResizeHandler(handler) {
3160 emitter.on('_resize', handler);
3161 },
3162 removeResizeHandler(handler) {
3163 emitter.off('_resize', handler);
3164 },
3165 createScrollResponder(execFunc) {
3166 return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
3167 },
3168 registerInteractiveComponent,
3169 unregisterInteractiveComponent,
3170 };
3171 }
3172
3173 /* eslint max-classes-per-file: off */
3174 class PureComponent extends x$1 {
3175 shouldComponentUpdate(nextProps, nextState) {
3176 if (this.debug) {
3177 // eslint-disable-next-line no-console
3178 console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state));
3179 }
3180 return !compareObjs(this.props, nextProps, this.propEquality) ||
3181 !compareObjs(this.state, nextState, this.stateEquality);
3182 }
3183 // HACK for freakin' React StrictMode
3184 safeSetState(newState) {
3185 if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
3186 this.setState(newState);
3187 }
3188 }
3189 }
3190 PureComponent.addPropsEquality = addPropsEquality;
3191 PureComponent.addStateEquality = addStateEquality;
3192 PureComponent.contextType = ViewContextType;
3193 PureComponent.prototype.propEquality = {};
3194 PureComponent.prototype.stateEquality = {};
3195 class BaseComponent extends PureComponent {
3196 }
3197 BaseComponent.contextType = ViewContextType;
3198 function addPropsEquality(propEquality) {
3199 let hash = Object.create(this.prototype.propEquality);
3200 Object.assign(hash, propEquality);
3201 this.prototype.propEquality = hash;
3202 }
3203 function addStateEquality(stateEquality) {
3204 let hash = Object.create(this.prototype.stateEquality);
3205 Object.assign(hash, stateEquality);
3206 this.prototype.stateEquality = hash;
3207 }
3208 // use other one
3209 function setRef(ref, current) {
3210 if (typeof ref === 'function') {
3211 ref(current);
3212 }
3213 else if (ref) {
3214 // see https://github.com/facebook/react/issues/13029
3215 ref.current = current;
3216 }
3217 }
3218
3219 /*
3220 an INTERACTABLE date component
3221
3222 PURPOSES:
3223 - hook up to fg, fill, and mirror renderers
3224 - interface for dragging and hits
3225 */
3226 class DateComponent extends BaseComponent {
3227 constructor() {
3228 super(...arguments);
3229 this.uid = guid();
3230 }
3231 // Hit System
3232 // -----------------------------------------------------------------------------------------------------------------
3233 prepareHits() {
3234 }
3235 queryHit(positionLeft, positionTop, elWidth, elHeight) {
3236 return null; // this should be abstract
3237 }
3238 // Pointer Interaction Utils
3239 // -----------------------------------------------------------------------------------------------------------------
3240 isValidSegDownEl(el) {
3241 return !this.props.eventDrag && // HACK
3242 !this.props.eventResize && // HACK
3243 !elementClosest(el, '.fc-event-mirror');
3244 }
3245 isValidDateDownEl(el) {
3246 return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
3247 !elementClosest(el, '.fc-more-link') && // a "more.." link
3248 !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
3249 !elementClosest(el, '.fc-popover'); // hack
3250 }
3251 }
3252
3253 class DateProfileGenerator {
3254 constructor(props) {
3255 this.props = props;
3256 this.initHiddenDays();
3257 }
3258 /* Date Range Computation
3259 ------------------------------------------------------------------------------------------------------------------*/
3260 // Builds a structure with info about what the dates/ranges will be for the "prev" view.
3261 buildPrev(currentDateProfile, currentDate, forceToValid) {
3262 let { dateEnv } = this.props;
3263 let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
3264 currentDateProfile.dateIncrement);
3265 return this.build(prevDate, -1, forceToValid);
3266 }
3267 // Builds a structure with info about what the dates/ranges will be for the "next" view.
3268 buildNext(currentDateProfile, currentDate, forceToValid) {
3269 let { dateEnv } = this.props;
3270 let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
3271 currentDateProfile.dateIncrement);
3272 return this.build(nextDate, 1, forceToValid);
3273 }
3274 // Builds a structure holding dates/ranges for rendering around the given date.
3275 // Optional direction param indicates whether the date is being incremented/decremented
3276 // from its previous value. decremented = -1, incremented = 1 (default).
3277 build(currentDate, direction, forceToValid = true) {
3278 let { props } = this;
3279 let validRange;
3280 let currentInfo;
3281 let isRangeAllDay;
3282 let renderRange;
3283 let activeRange;
3284 let isValid;
3285 validRange = this.buildValidRange();
3286 validRange = this.trimHiddenDays(validRange);
3287 if (forceToValid) {
3288 currentDate = constrainMarkerToRange(currentDate, validRange);
3289 }
3290 currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
3291 isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
3292 renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
3293 renderRange = this.trimHiddenDays(renderRange);
3294 activeRange = renderRange;
3295 if (!props.showNonCurrentDates) {
3296 activeRange = intersectRanges(activeRange, currentInfo.range);
3297 }
3298 activeRange = this.adjustActiveRange(activeRange);
3299 activeRange = intersectRanges(activeRange, validRange); // might return null
3300 // it's invalid if the originally requested date is not contained,
3301 // or if the range is completely outside of the valid range.
3302 isValid = rangesIntersect(currentInfo.range, validRange);
3303 // HACK: constrain to render-range so `currentDate` is more useful to view rendering
3304 if (!rangeContainsMarker(renderRange, currentDate)) {
3305 currentDate = renderRange.start;
3306 }
3307 return {
3308 currentDate,
3309 // constraint for where prev/next operations can go and where events can be dragged/resized to.
3310 // an object with optional start and end properties.
3311 validRange,
3312 // range the view is formally responsible for.
3313 // for example, a month view might have 1st-31st, excluding padded dates
3314 currentRange: currentInfo.range,
3315 // name of largest unit being displayed, like "month" or "week"
3316 currentRangeUnit: currentInfo.unit,
3317 isRangeAllDay,
3318 // dates that display events and accept drag-n-drop
3319 // will be `null` if no dates accept events
3320 activeRange,
3321 // date range with a rendered skeleton
3322 // includes not-active days that need some sort of DOM
3323 renderRange,
3324 // Duration object that denotes the first visible time of any given day
3325 slotMinTime: props.slotMinTime,
3326 // Duration object that denotes the exclusive visible end time of any given day
3327 slotMaxTime: props.slotMaxTime,
3328 isValid,
3329 // how far the current date will move for a prev/next operation
3330 dateIncrement: this.buildDateIncrement(currentInfo.duration),
3331 // pass a fallback (might be null) ^
3332 };
3333 }
3334 // Builds an object with optional start/end properties.
3335 // Indicates the minimum/maximum dates to display.
3336 // not responsible for trimming hidden days.
3337 buildValidRange() {
3338 let input = this.props.validRangeInput;
3339 let simpleInput = typeof input === 'function'
3340 ? input.call(this.props.calendarApi, this.props.dateEnv.toDate(this.props.nowManager.getDateMarker()))
3341 : input;
3342 return this.refineRange(simpleInput) ||
3343 { start: null, end: null }; // completely open-ended
3344 }
3345 // Builds a structure with info about the "current" range, the range that is
3346 // highlighted as being the current month for example.
3347 // See build() for a description of `direction`.
3348 // Guaranteed to have `range` and `unit` properties. `duration` is optional.
3349 buildCurrentRangeInfo(date, direction) {
3350 let { props } = this;
3351 let duration = null;
3352 let unit = null;
3353 let range = null;
3354 let dayCount;
3355 if (props.duration) {
3356 duration = props.duration;
3357 unit = props.durationUnit;
3358 range = this.buildRangeFromDuration(date, direction, duration, unit);
3359 }
3360 else if ((dayCount = this.props.dayCount)) {
3361 unit = 'day';
3362 range = this.buildRangeFromDayCount(date, direction, dayCount);
3363 }
3364 else if ((range = this.buildCustomVisibleRange(date))) {
3365 unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
3366 }
3367 else {
3368 duration = this.getFallbackDuration();
3369 unit = greatestDurationDenominator(duration).unit;
3370 range = this.buildRangeFromDuration(date, direction, duration, unit);
3371 }
3372 return { duration, unit, range };
3373 }
3374 getFallbackDuration() {
3375 return createDuration({ day: 1 });
3376 }
3377 // Returns a new activeRange to have time values (un-ambiguate)
3378 // slotMinTime or slotMaxTime causes the range to expand.
3379 adjustActiveRange(range) {
3380 let { dateEnv, usesMinMaxTime, slotMinTime, slotMaxTime } = this.props;
3381 let { start, end } = range;
3382 if (usesMinMaxTime) {
3383 // expand active range if slotMinTime is negative (why not when positive?)
3384 if (asRoughDays(slotMinTime) < 0) {
3385 start = startOfDay(start); // necessary?
3386 start = dateEnv.add(start, slotMinTime);
3387 }
3388 // expand active range if slotMaxTime is beyond one day (why not when negative?)
3389 if (asRoughDays(slotMaxTime) > 1) {
3390 end = startOfDay(end); // necessary?
3391 end = addDays(end, -1);
3392 end = dateEnv.add(end, slotMaxTime);
3393 }
3394 }
3395 return { start, end };
3396 }
3397 // Builds the "current" range when it is specified as an explicit duration.
3398 // `unit` is the already-computed greatestDurationDenominator unit of duration.
3399 buildRangeFromDuration(date, direction, duration, unit) {
3400 let { dateEnv, dateAlignment } = this.props;
3401 let start;
3402 let end;
3403 let res;
3404 // compute what the alignment should be
3405 if (!dateAlignment) {
3406 let { dateIncrement } = this.props;
3407 if (dateIncrement) {
3408 // use the smaller of the two units
3409 if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
3410 dateAlignment = greatestDurationDenominator(dateIncrement).unit;
3411 }
3412 else {
3413 dateAlignment = unit;
3414 }
3415 }
3416 else {
3417 dateAlignment = unit;
3418 }
3419 }
3420 // if the view displays a single day or smaller
3421 if (asRoughDays(duration) <= 1) {
3422 if (this.isHiddenDay(start)) {
3423 start = this.skipHiddenDays(start, direction);
3424 start = startOfDay(start);
3425 }
3426 }
3427 function computeRes() {
3428 start = dateEnv.startOf(date, dateAlignment);
3429 end = dateEnv.add(start, duration);
3430 res = { start, end };
3431 }
3432 computeRes();
3433 // if range is completely enveloped by hidden days, go past the hidden days
3434 if (!this.trimHiddenDays(res)) {
3435 date = this.skipHiddenDays(date, direction);
3436 computeRes();
3437 }
3438 return res;
3439 }
3440 // Builds the "current" range when a dayCount is specified.
3441 buildRangeFromDayCount(date, direction, dayCount) {
3442 let { dateEnv, dateAlignment } = this.props;
3443 let runningCount = 0;
3444 let start = date;
3445 let end;
3446 if (dateAlignment) {
3447 start = dateEnv.startOf(start, dateAlignment);
3448 }
3449 start = startOfDay(start);
3450 start = this.skipHiddenDays(start, direction);
3451 end = start;
3452 do {
3453 end = addDays(end, 1);
3454 if (!this.isHiddenDay(end)) {
3455 runningCount += 1;
3456 }
3457 } while (runningCount < dayCount);
3458 return { start, end };
3459 }
3460 // Builds a normalized range object for the "visible" range,
3461 // which is a way to define the currentRange and activeRange at the same time.
3462 buildCustomVisibleRange(date) {
3463 let { props } = this;
3464 let input = props.visibleRangeInput;
3465 let simpleInput = typeof input === 'function'
3466 ? input.call(props.calendarApi, props.dateEnv.toDate(date))
3467 : input;
3468 let range = this.refineRange(simpleInput);
3469 if (range && (range.start == null || range.end == null)) {
3470 return null;
3471 }
3472 return range;
3473 }
3474 // Computes the range that will represent the element/cells for *rendering*,
3475 // but which may have voided days/times.
3476 // not responsible for trimming hidden days.
3477 buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
3478 return currentRange;
3479 }
3480 // Compute the duration value that should be added/substracted to the current date
3481 // when a prev/next operation happens.
3482 buildDateIncrement(fallback) {
3483 let { dateIncrement } = this.props;
3484 let customAlignment;
3485 if (dateIncrement) {
3486 return dateIncrement;
3487 }
3488 if ((customAlignment = this.props.dateAlignment)) {
3489 return createDuration(1, customAlignment);
3490 }
3491 if (fallback) {
3492 return fallback;
3493 }
3494 return createDuration({ days: 1 });
3495 }
3496 refineRange(rangeInput) {
3497 if (rangeInput) {
3498 let range = parseRange(rangeInput, this.props.dateEnv);
3499 if (range) {
3500 range = computeVisibleDayRange(range);
3501 }
3502 return range;
3503 }
3504 return null;
3505 }
3506 /* Hidden Days
3507 ------------------------------------------------------------------------------------------------------------------*/
3508 // Initializes internal variables related to calculating hidden days-of-week
3509 initHiddenDays() {
3510 let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
3511 let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
3512 let dayCnt = 0;
3513 let i;
3514 if (this.props.weekends === false) {
3515 hiddenDays.push(0, 6); // 0=sunday, 6=saturday
3516 }
3517 for (i = 0; i < 7; i += 1) {
3518 if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
3519 dayCnt += 1;
3520 }
3521 }
3522 if (!dayCnt) {
3523 throw new Error('invalid hiddenDays'); // all days were hidden? bad.
3524 }
3525 this.isHiddenDayHash = isHiddenDayHash;
3526 }
3527 // Remove days from the beginning and end of the range that are computed as hidden.
3528 // If the whole range is trimmed off, returns null
3529 trimHiddenDays(range) {
3530 let { start, end } = range;
3531 if (start) {
3532 start = this.skipHiddenDays(start);
3533 }
3534 if (end) {
3535 end = this.skipHiddenDays(end, -1, true);
3536 }
3537 if (start == null || end == null || start < end) {
3538 return { start, end };
3539 }
3540 return null;
3541 }
3542 // Is the current day hidden?
3543 // `day` is a day-of-week index (0-6), or a Date (used for UTC)
3544 isHiddenDay(day) {
3545 if (day instanceof Date) {
3546 day = day.getUTCDay();
3547 }
3548 return this.isHiddenDayHash[day];
3549 }
3550 // Incrementing the current day until it is no longer a hidden day, returning a copy.
3551 // DOES NOT CONSIDER validRange!
3552 // If the initial value of `date` is not a hidden day, don't do anything.
3553 // Pass `isExclusive` as `true` if you are dealing with an end date.
3554 // `inc` defaults to `1` (increment one day forward each time)
3555 skipHiddenDays(date, inc = 1, isExclusive = false) {
3556 while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
3557 date = addDays(date, inc);
3558 }
3559 return date;
3560 }
3561 }
3562
3563 function triggerDateSelect(selection, pev, context) {
3564 context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), { jsEvent: pev ? pev.origEvent : null, view: context.viewApi || context.calendarApi.view }));
3565 }
3566 function triggerDateUnselect(pev, context) {
3567 context.emitter.trigger('unselect', {
3568 jsEvent: pev ? pev.origEvent : null,
3569 view: context.viewApi || context.calendarApi.view,
3570 });
3571 }
3572 function buildDateSpanApiWithContext(dateSpan, context) {
3573 let props = {};
3574 for (let transform of context.pluginHooks.dateSpanTransforms) {
3575 Object.assign(props, transform(dateSpan, context));
3576 }
3577 Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
3578 return props;
3579 }
3580 // Given an event's allDay status and start date, return what its fallback end date should be.
3581 // TODO: rename to computeDefaultEventEnd
3582 function getDefaultEventEnd(allDay, marker, context) {
3583 let { dateEnv, options } = context;
3584 let end = marker;
3585 if (allDay) {
3586 end = startOfDay(end);
3587 end = dateEnv.add(end, options.defaultAllDayEventDuration);
3588 }
3589 else {
3590 end = dateEnv.add(end, options.defaultTimedEventDuration);
3591 }
3592 return end;
3593 }
3594
3595 // applies the mutation to ALL defs/instances within the event store
3596 function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
3597 let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
3598 let dest = createEmptyEventStore();
3599 for (let defId in eventStore.defs) {
3600 let def = eventStore.defs[defId];
3601 dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
3602 }
3603 for (let instanceId in eventStore.instances) {
3604 let instance = eventStore.instances[instanceId];
3605 let def = dest.defs[instance.defId]; // important to grab the newly modified def
3606 dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
3607 }
3608 return dest;
3609 }
3610 function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
3611 let standardProps = mutation.standardProps || {};
3612 // if hasEnd has not been specified, guess a good value based on deltas.
3613 // if duration will change, there's no way the default duration will persist,
3614 // and thus, we need to mark the event as having a real end
3615 if (standardProps.hasEnd == null &&
3616 eventConfig.durationEditable &&
3617 (mutation.startDelta || mutation.endDelta)) {
3618 standardProps.hasEnd = true; // TODO: is this mutation okay?
3619 }
3620 let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), { ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui) });
3621 if (mutation.extendedProps) {
3622 copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
3623 }
3624 for (let applier of context.pluginHooks.eventDefMutationAppliers) {
3625 applier(copy, mutation, context);
3626 }
3627 if (!copy.hasEnd && context.options.forceEventDuration) {
3628 copy.hasEnd = true;
3629 }
3630 return copy;
3631 }
3632 function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
3633 eventConfig, mutation, context) {
3634 let { dateEnv } = context;
3635 let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
3636 let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
3637 let copy = Object.assign({}, eventInstance);
3638 if (forceAllDay) {
3639 copy.range = computeAlignedDayRange(copy.range);
3640 }
3641 if (mutation.datesDelta && eventConfig.startEditable) {
3642 copy.range = {
3643 start: dateEnv.add(copy.range.start, mutation.datesDelta),
3644 end: dateEnv.add(copy.range.end, mutation.datesDelta),
3645 };
3646 }
3647 if (mutation.startDelta && eventConfig.durationEditable) {
3648 copy.range = {
3649 start: dateEnv.add(copy.range.start, mutation.startDelta),
3650 end: copy.range.end,
3651 };
3652 }
3653 if (mutation.endDelta && eventConfig.durationEditable) {
3654 copy.range = {
3655 start: copy.range.start,
3656 end: dateEnv.add(copy.range.end, mutation.endDelta),
3657 };
3658 }
3659 if (clearEnd) {
3660 copy.range = {
3661 start: copy.range.start,
3662 end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
3663 };
3664 }
3665 // in case event was all-day but the supplied deltas were not
3666 // better util for this?
3667 if (eventDef.allDay) {
3668 copy.range = {
3669 start: startOfDay(copy.range.start),
3670 end: startOfDay(copy.range.end),
3671 };
3672 }
3673 // handle invalid durations
3674 if (copy.range.end < copy.range.start) {
3675 copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
3676 }
3677 return copy;
3678 }
3679
3680 class EventSourceImpl {
3681 constructor(context, internalEventSource) {
3682 this.context = context;
3683 this.internalEventSource = internalEventSource;
3684 }
3685 remove() {
3686 this.context.dispatch({
3687 type: 'REMOVE_EVENT_SOURCE',
3688 sourceId: this.internalEventSource.sourceId,
3689 });
3690 }
3691 refetch() {
3692 this.context.dispatch({
3693 type: 'FETCH_EVENT_SOURCES',
3694 sourceIds: [this.internalEventSource.sourceId],
3695 isRefetch: true,
3696 });
3697 }
3698 get id() {
3699 return this.internalEventSource.publicId;
3700 }
3701 get url() {
3702 return this.internalEventSource.meta.url;
3703 }
3704 get format() {
3705 return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
3706 }
3707 }
3708
3709 class EventImpl {
3710 // instance will be null if expressing a recurring event that has no current instances,
3711 // OR if trying to validate an incoming external event that has no dates assigned
3712 constructor(context, def, instance) {
3713 this._context = context;
3714 this._def = def;
3715 this._instance = instance || null;
3716 }
3717 /*
3718 TODO: make event struct more responsible for this
3719 */
3720 setProp(name, val) {
3721 if (name in EVENT_DATE_REFINERS) {
3722 console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
3723 // TODO: make proper aliasing system?
3724 }
3725 else if (name === 'id') {
3726 val = EVENT_NON_DATE_REFINERS[name](val);
3727 this.mutate({
3728 standardProps: { publicId: val }, // hardcoded internal name
3729 });
3730 }
3731 else if (name in EVENT_NON_DATE_REFINERS) {
3732 val = EVENT_NON_DATE_REFINERS[name](val);
3733 this.mutate({
3734 standardProps: { [name]: val },
3735 });
3736 }
3737 else if (name in EVENT_UI_REFINERS) {
3738 let ui = EVENT_UI_REFINERS[name](val);
3739 if (name === 'color') {
3740 ui = { backgroundColor: val, borderColor: val };
3741 }
3742 else if (name === 'editable') {
3743 ui = { startEditable: val, durationEditable: val };
3744 }
3745 else {
3746 ui = { [name]: val };
3747 }
3748 this.mutate({
3749 standardProps: { ui },
3750 });
3751 }
3752 else {
3753 console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
3754 }
3755 }
3756 setExtendedProp(name, val) {
3757 this.mutate({
3758 extendedProps: { [name]: val },
3759 });
3760 }
3761 setStart(startInput, options = {}) {
3762 let { dateEnv } = this._context;
3763 let start = dateEnv.createMarker(startInput);
3764 if (start && this._instance) { // TODO: warning if parsed bad
3765 let instanceRange = this._instance.range;
3766 let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
3767 if (options.maintainDuration) {
3768 this.mutate({ datesDelta: startDelta });
3769 }
3770 else {
3771 this.mutate({ startDelta });
3772 }
3773 }
3774 }
3775 setEnd(endInput, options = {}) {
3776 let { dateEnv } = this._context;
3777 let end;
3778 if (endInput != null) {
3779 end = dateEnv.createMarker(endInput);
3780 if (!end) {
3781 return; // TODO: warning if parsed bad
3782 }
3783 }
3784 if (this._instance) {
3785 if (end) {
3786 let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
3787 this.mutate({ endDelta });
3788 }
3789 else {
3790 this.mutate({ standardProps: { hasEnd: false } });
3791 }
3792 }
3793 }
3794 setDates(startInput, endInput, options = {}) {
3795 let { dateEnv } = this._context;
3796 let standardProps = { allDay: options.allDay };
3797 let start = dateEnv.createMarker(startInput);
3798 let end;
3799 if (!start) {
3800 return; // TODO: warning if parsed bad
3801 }
3802 if (endInput != null) {
3803 end = dateEnv.createMarker(endInput);
3804 if (!end) { // TODO: warning if parsed bad
3805 return;
3806 }
3807 }
3808 if (this._instance) {
3809 let instanceRange = this._instance.range;
3810 // when computing the diff for an event being converted to all-day,
3811 // compute diff off of the all-day values the way event-mutation does.
3812 if (options.allDay === true) {
3813 instanceRange = computeAlignedDayRange(instanceRange);
3814 }
3815 let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
3816 if (end) {
3817 let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
3818 if (durationsEqual(startDelta, endDelta)) {
3819 this.mutate({ datesDelta: startDelta, standardProps });
3820 }
3821 else {
3822 this.mutate({ startDelta, endDelta, standardProps });
3823 }
3824 }
3825 else { // means "clear the end"
3826 standardProps.hasEnd = false;
3827 this.mutate({ datesDelta: startDelta, standardProps });
3828 }
3829 }
3830 }
3831 moveStart(deltaInput) {
3832 let delta = createDuration(deltaInput);
3833 if (delta) { // TODO: warning if parsed bad
3834 this.mutate({ startDelta: delta });
3835 }
3836 }
3837 moveEnd(deltaInput) {
3838 let delta = createDuration(deltaInput);
3839 if (delta) { // TODO: warning if parsed bad
3840 this.mutate({ endDelta: delta });
3841 }
3842 }
3843 moveDates(deltaInput) {
3844 let delta = createDuration(deltaInput);
3845 if (delta) { // TODO: warning if parsed bad
3846 this.mutate({ datesDelta: delta });
3847 }
3848 }
3849 setAllDay(allDay, options = {}) {
3850 let standardProps = { allDay };
3851 let { maintainDuration } = options;
3852 if (maintainDuration == null) {
3853 maintainDuration = this._context.options.allDayMaintainDuration;
3854 }
3855 if (this._def.allDay !== allDay) {
3856 standardProps.hasEnd = maintainDuration;
3857 }
3858 this.mutate({ standardProps });
3859 }
3860 formatRange(formatInput) {
3861 let { dateEnv } = this._context;
3862 let instance = this._instance;
3863 let formatter = createFormatter(formatInput);
3864 if (this._def.hasEnd) {
3865 return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
3866 forcedStartTzo: instance.forcedStartTzo,
3867 forcedEndTzo: instance.forcedEndTzo,
3868 });
3869 }
3870 return dateEnv.format(instance.range.start, formatter, {
3871 forcedTzo: instance.forcedStartTzo,
3872 });
3873 }
3874 mutate(mutation) {
3875 let instance = this._instance;
3876 if (instance) {
3877 let def = this._def;
3878 let context = this._context;
3879 let { eventStore } = context.getCurrentData();
3880 let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
3881 let eventConfigBase = {
3882 '': {
3883 display: '',
3884 startEditable: true,
3885 durationEditable: true,
3886 constraints: [],
3887 overlap: null,
3888 allows: [],
3889 backgroundColor: '',
3890 borderColor: '',
3891 textColor: '',
3892 classNames: [],
3893 },
3894 };
3895 relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
3896 let oldEvent = new EventImpl(context, def, instance); // snapshot
3897 this._def = relevantEvents.defs[def.defId];
3898 this._instance = relevantEvents.instances[instance.instanceId];
3899 context.dispatch({
3900 type: 'MERGE_EVENTS',
3901 eventStore: relevantEvents,
3902 });
3903 context.emitter.trigger('eventChange', {
3904 oldEvent,
3905 event: this,
3906 relatedEvents: buildEventApis(relevantEvents, context, instance),
3907 revert() {
3908 context.dispatch({
3909 type: 'RESET_EVENTS',
3910 eventStore, // the ORIGINAL store
3911 });
3912 },
3913 });
3914 }
3915 }
3916 remove() {
3917 let context = this._context;
3918 let asStore = eventApiToStore(this);
3919 context.dispatch({
3920 type: 'REMOVE_EVENTS',
3921 eventStore: asStore,
3922 });
3923 context.emitter.trigger('eventRemove', {
3924 event: this,
3925 relatedEvents: [],
3926 revert() {
3927 context.dispatch({
3928 type: 'MERGE_EVENTS',
3929 eventStore: asStore,
3930 });
3931 },
3932 });
3933 }
3934 get source() {
3935 let { sourceId } = this._def;
3936 if (sourceId) {
3937 return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
3938 }
3939 return null;
3940 }
3941 get start() {
3942 return this._instance ?
3943 this._context.dateEnv.toDate(this._instance.range.start) :
3944 null;
3945 }
3946 get end() {
3947 return (this._instance && this._def.hasEnd) ?
3948 this._context.dateEnv.toDate(this._instance.range.end) :
3949 null;
3950 }
3951 get startStr() {
3952 let instance = this._instance;
3953 if (instance) {
3954 return this._context.dateEnv.formatIso(instance.range.start, {
3955 omitTime: this._def.allDay,
3956 forcedTzo: instance.forcedStartTzo,
3957 });
3958 }
3959 return '';
3960 }
3961 get endStr() {
3962 let instance = this._instance;
3963 if (instance && this._def.hasEnd) {
3964 return this._context.dateEnv.formatIso(instance.range.end, {
3965 omitTime: this._def.allDay,
3966 forcedTzo: instance.forcedEndTzo,
3967 });
3968 }
3969 return '';
3970 }
3971 // computable props that all access the def
3972 // TODO: find a TypeScript-compatible way to do this at scale
3973 get id() { return this._def.publicId; }
3974 get groupId() { return this._def.groupId; }
3975 get allDay() { return this._def.allDay; }
3976 get title() { return this._def.title; }
3977 get url() { return this._def.url; }
3978 get display() { return this._def.ui.display || 'auto'; } // bad. just normalize the type earlier
3979 get startEditable() { return this._def.ui.startEditable; }
3980 get durationEditable() { return this._def.ui.durationEditable; }
3981 get constraint() { return this._def.ui.constraints[0] || null; }
3982 get overlap() { return this._def.ui.overlap; }
3983 get allow() { return this._def.ui.allows[0] || null; }
3984 get backgroundColor() { return this._def.ui.backgroundColor; }
3985 get borderColor() { return this._def.ui.borderColor; }
3986 get textColor() { return this._def.ui.textColor; }
3987 // NOTE: user can't modify these because Object.freeze was called in event-def parsing
3988 get classNames() { return this._def.ui.classNames; }
3989 get extendedProps() { return this._def.extendedProps; }
3990 toPlainObject(settings = {}) {
3991 let def = this._def;
3992 let { ui } = def;
3993 let { startStr, endStr } = this;
3994 let res = {
3995 allDay: def.allDay,
3996 };
3997 if (def.title) {
3998 res.title = def.title;
3999 }
4000 if (startStr) {
4001 res.start = startStr;
4002 }
4003 if (endStr) {
4004 res.end = endStr;
4005 }
4006 if (def.publicId) {
4007 res.id = def.publicId;
4008 }
4009 if (def.groupId) {
4010 res.groupId = def.groupId;
4011 }
4012 if (def.url) {
4013 res.url = def.url;
4014 }
4015 if (ui.display && ui.display !== 'auto') {
4016 res.display = ui.display;
4017 }
4018 // TODO: what about recurring-event properties???
4019 // TODO: include startEditable/durationEditable/constraint/overlap/allow
4020 if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
4021 res.color = ui.backgroundColor;
4022 }
4023 else {
4024 if (ui.backgroundColor) {
4025 res.backgroundColor = ui.backgroundColor;
4026 }
4027 if (ui.borderColor) {
4028 res.borderColor = ui.borderColor;
4029 }
4030 }
4031 if (ui.textColor) {
4032 res.textColor = ui.textColor;
4033 }
4034 if (ui.classNames.length) {
4035 res.classNames = ui.classNames;
4036 }
4037 if (Object.keys(def.extendedProps).length) {
4038 if (settings.collapseExtendedProps) {
4039 Object.assign(res, def.extendedProps);
4040 }
4041 else {
4042 res.extendedProps = def.extendedProps;
4043 }
4044 }
4045 return res;
4046 }
4047 toJSON() {
4048 return this.toPlainObject();
4049 }
4050 }
4051 function eventApiToStore(eventApi) {
4052 let def = eventApi._def;
4053 let instance = eventApi._instance;
4054 return {
4055 defs: { [def.defId]: def },
4056 instances: instance
4057 ? { [instance.instanceId]: instance }
4058 : {},
4059 };
4060 }
4061 function buildEventApis(eventStore, context, excludeInstance) {
4062 let { defs, instances } = eventStore;
4063 let eventApis = [];
4064 let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
4065 for (let id in instances) {
4066 let instance = instances[id];
4067 let def = defs[instance.defId];
4068 if (instance.instanceId !== excludeInstanceId) {
4069 eventApis.push(new EventImpl(context, def, instance));
4070 }
4071 }
4072 return eventApis;
4073 }
4074
4075 /*
4076 Specifying nextDayThreshold signals that all-day ranges should be sliced.
4077 */
4078 function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
4079 let inverseBgByGroupId = {};
4080 let inverseBgByDefId = {};
4081 let defByGroupId = {};
4082 let bgRanges = [];
4083 let fgRanges = [];
4084 let eventUis = compileEventUis(eventStore.defs, eventUiBases);
4085 for (let defId in eventStore.defs) {
4086 let def = eventStore.defs[defId];
4087 let ui = eventUis[def.defId];
4088 if (ui.display === 'inverse-background') {
4089 if (def.groupId) {
4090 inverseBgByGroupId[def.groupId] = [];
4091 if (!defByGroupId[def.groupId]) {
4092 defByGroupId[def.groupId] = def;
4093 }
4094 }
4095 else {
4096 inverseBgByDefId[defId] = [];
4097 }
4098 }
4099 }
4100 for (let instanceId in eventStore.instances) {
4101 let instance = eventStore.instances[instanceId];
4102 let def = eventStore.defs[instance.defId];
4103 let ui = eventUis[def.defId];
4104 let origRange = instance.range;
4105 let normalRange = (!def.allDay && nextDayThreshold) ?
4106 computeVisibleDayRange(origRange, nextDayThreshold) :
4107 origRange;
4108 let slicedRange = intersectRanges(normalRange, framingRange);
4109 if (slicedRange) {
4110 if (ui.display === 'inverse-background') {
4111 if (def.groupId) {
4112 inverseBgByGroupId[def.groupId].push(slicedRange);
4113 }
4114 else {
4115 inverseBgByDefId[instance.defId].push(slicedRange);
4116 }
4117 }
4118 else if (ui.display !== 'none') {
4119 (ui.display === 'background' ? bgRanges : fgRanges).push({
4120 def,
4121 ui,
4122 instance,
4123 range: slicedRange,
4124 isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
4125 isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
4126 });
4127 }
4128 }
4129 }
4130 for (let groupId in inverseBgByGroupId) { // BY GROUP
4131 let ranges = inverseBgByGroupId[groupId];
4132 let invertedRanges = invertRanges(ranges, framingRange);
4133 for (let invertedRange of invertedRanges) {
4134 let def = defByGroupId[groupId];
4135 let ui = eventUis[def.defId];
4136 bgRanges.push({
4137 def,
4138 ui,
4139 instance: null,
4140 range: invertedRange,
4141 isStart: false,
4142 isEnd: false,
4143 });
4144 }
4145 }
4146 for (let defId in inverseBgByDefId) {
4147 let ranges = inverseBgByDefId[defId];
4148 let invertedRanges = invertRanges(ranges, framingRange);
4149 for (let invertedRange of invertedRanges) {
4150 bgRanges.push({
4151 def: eventStore.defs[defId],
4152 ui: eventUis[defId],
4153 instance: null,
4154 range: invertedRange,
4155 isStart: false,
4156 isEnd: false,
4157 });
4158 }
4159 }
4160 return { bg: bgRanges, fg: fgRanges };
4161 }
4162 function hasBgRendering(def) {
4163 return def.ui.display === 'background' || def.ui.display === 'inverse-background';
4164 }
4165 function setElSeg(el, seg) {
4166 el.fcSeg = seg;
4167 }
4168 function getElSeg(el) {
4169 return el.fcSeg ||
4170 el.parentNode.fcSeg || // for the harness
4171 null;
4172 }
4173 // event ui computation
4174 function compileEventUis(eventDefs, eventUiBases) {
4175 return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
4176 }
4177 function compileEventUi(eventDef, eventUiBases) {
4178 let uis = [];
4179 if (eventUiBases['']) {
4180 uis.push(eventUiBases['']);
4181 }
4182 if (eventUiBases[eventDef.defId]) {
4183 uis.push(eventUiBases[eventDef.defId]);
4184 }
4185 uis.push(eventDef.ui);
4186 return combineEventUis(uis);
4187 }
4188 function sortEventSegs(segs, eventOrderSpecs) {
4189 let objs = segs.map(buildSegCompareObj);
4190 objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
4191 return objs.map((c) => c._seg);
4192 }
4193 // returns a object with all primitive props that can be compared
4194 function buildSegCompareObj(seg) {
4195 let { eventRange } = seg;
4196 let eventDef = eventRange.def;
4197 let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
4198 let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
4199 let end = range.end ? range.end.valueOf() : 0; // "
4200 return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), { id: eventDef.publicId, start,
4201 end, duration: end - start, allDay: Number(eventDef.allDay), _seg: seg });
4202 }
4203 function computeSegDraggable(seg, context) {
4204 let { pluginHooks } = context;
4205 let transformers = pluginHooks.isDraggableTransformers;
4206 let { def, ui } = seg.eventRange;
4207 let val = ui.startEditable;
4208 for (let transformer of transformers) {
4209 val = transformer(val, def, ui, context);
4210 }
4211 return val;
4212 }
4213 function computeSegStartResizable(seg, context) {
4214 return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
4215 }
4216 function computeSegEndResizable(seg, context) {
4217 return seg.isEnd && seg.eventRange.ui.durationEditable;
4218 }
4219 function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
4220 defaultDisplayEventEnd, // defaults to true
4221 startOverride, endOverride) {
4222 let { dateEnv, options } = context;
4223 let { displayEventTime, displayEventEnd } = options;
4224 let eventDef = seg.eventRange.def;
4225 let eventInstance = seg.eventRange.instance;
4226 if (displayEventTime == null) {
4227 displayEventTime = defaultDisplayEventTime !== false;
4228 }
4229 if (displayEventEnd == null) {
4230 displayEventEnd = defaultDisplayEventEnd !== false;
4231 }
4232 let wholeEventStart = eventInstance.range.start;
4233 let wholeEventEnd = eventInstance.range.end;
4234 let segStart = startOverride || seg.start || seg.eventRange.range.start;
4235 let segEnd = endOverride || seg.end || seg.eventRange.range.end;
4236 let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
4237 let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
4238 if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
4239 segStart = isStartDay ? wholeEventStart : segStart;
4240 segEnd = isEndDay ? wholeEventEnd : segEnd;
4241 if (displayEventEnd && eventDef.hasEnd) {
4242 return dateEnv.formatRange(segStart, segEnd, timeFormat, {
4243 forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
4244 forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
4245 });
4246 }
4247 return dateEnv.format(segStart, timeFormat, {
4248 forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
4249 });
4250 }
4251 return '';
4252 }
4253 function getSegMeta(seg, todayRange, nowDate) {
4254 let segRange = seg.eventRange.range;
4255 return {
4256 isPast: segRange.end <= (nowDate || todayRange.start),
4257 isFuture: segRange.start >= (nowDate || todayRange.end),
4258 isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
4259 };
4260 }
4261 function getEventClassNames(props) {
4262 let classNames = ['fc-event'];
4263 if (props.isMirror) {
4264 classNames.push('fc-event-mirror');
4265 }
4266 if (props.isDraggable) {
4267 classNames.push('fc-event-draggable');
4268 }
4269 if (props.isStartResizable || props.isEndResizable) {
4270 classNames.push('fc-event-resizable');
4271 }
4272 if (props.isDragging) {
4273 classNames.push('fc-event-dragging');
4274 }
4275 if (props.isResizing) {
4276 classNames.push('fc-event-resizing');
4277 }
4278 if (props.isSelected) {
4279 classNames.push('fc-event-selected');
4280 }
4281 if (props.isStart) {
4282 classNames.push('fc-event-start');
4283 }
4284 if (props.isEnd) {
4285 classNames.push('fc-event-end');
4286 }
4287 if (props.isPast) {
4288 classNames.push('fc-event-past');
4289 }
4290 if (props.isToday) {
4291 classNames.push('fc-event-today');
4292 }
4293 if (props.isFuture) {
4294 classNames.push('fc-event-future');
4295 }
4296 return classNames;
4297 }
4298 function buildEventRangeKey(eventRange) {
4299 return eventRange.instance
4300 ? eventRange.instance.instanceId
4301 : `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
4302 // inverse-background events don't have specific instances. TODO: better solution
4303 }
4304 function getSegAnchorAttrs(seg, context) {
4305 let { def, instance } = seg.eventRange;
4306 let { url } = def;
4307 if (url) {
4308 return { href: url };
4309 }
4310 let { emitter, options } = context;
4311 let { eventInteractive } = options;
4312 if (eventInteractive == null) {
4313 eventInteractive = def.interactive;
4314 if (eventInteractive == null) {
4315 eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
4316 }
4317 }
4318 // mock what happens in EventClicking
4319 if (eventInteractive) {
4320 // only attach keyboard-related handlers because click handler is already done in EventClicking
4321 return createAriaKeyboardAttrs((ev) => {
4322 emitter.trigger('eventClick', {
4323 el: ev.target,
4324 event: new EventImpl(context, def, instance),
4325 jsEvent: ev,
4326 view: context.viewApi,
4327 });
4328 });
4329 }
4330 return {};
4331 }
4332
4333 const STANDARD_PROPS = {
4334 start: identity,
4335 end: identity,
4336 allDay: Boolean,
4337 };
4338 function parseDateSpan(raw, dateEnv, defaultDuration) {
4339 let span = parseOpenDateSpan(raw, dateEnv);
4340 let { range } = span;
4341 if (!range.start) {
4342 return null;
4343 }
4344 if (!range.end) {
4345 if (defaultDuration == null) {
4346 return null;
4347 }
4348 range.end = dateEnv.add(range.start, defaultDuration);
4349 }
4350 return span;
4351 }
4352 /*
4353 TODO: somehow combine with parseRange?
4354 Will return null if the start/end props were present but parsed invalidly.
4355 */
4356 function parseOpenDateSpan(raw, dateEnv) {
4357 let { refined: standardProps, extra } = refineProps(raw, STANDARD_PROPS);
4358 let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
4359 let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
4360 let { allDay } = standardProps;
4361 if (allDay == null) {
4362 allDay = (startMeta && startMeta.isTimeUnspecified) &&
4363 (!endMeta || endMeta.isTimeUnspecified);
4364 }
4365 return Object.assign({ range: {
4366 start: startMeta ? startMeta.marker : null,
4367 end: endMeta ? endMeta.marker : null,
4368 }, allDay }, extra);
4369 }
4370 function isDateSpansEqual(span0, span1) {
4371 return rangesEqual(span0.range, span1.range) &&
4372 span0.allDay === span1.allDay &&
4373 isSpanPropsEqual(span0, span1);
4374 }
4375 // the NON-DATE-RELATED props
4376 function isSpanPropsEqual(span0, span1) {
4377 for (let propName in span1) {
4378 if (propName !== 'range' && propName !== 'allDay') {
4379 if (span0[propName] !== span1[propName]) {
4380 return false;
4381 }
4382 }
4383 }
4384 // are there any props that span0 has that span1 DOESN'T have?
4385 // both have range/allDay, so no need to special-case.
4386 for (let propName in span0) {
4387 if (!(propName in span1)) {
4388 return false;
4389 }
4390 }
4391 return true;
4392 }
4393 function buildDateSpanApi(span, dateEnv) {
4394 return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), { allDay: span.allDay });
4395 }
4396 function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
4397 return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), { timeZone: dateEnv.timeZone });
4398 }
4399 function buildRangeApi(range, dateEnv, omitTime) {
4400 return {
4401 start: dateEnv.toDate(range.start),
4402 end: dateEnv.toDate(range.end),
4403 startStr: dateEnv.formatIso(range.start, { omitTime }),
4404 endStr: dateEnv.formatIso(range.end, { omitTime }),
4405 };
4406 }
4407 function fabricateEventRange(dateSpan, eventUiBases, context) {
4408 let res = refineEventDef({ editable: false }, context);
4409 let def = parseEventDef(res.refined, res.extra, '', // sourceId
4410 dateSpan.allDay, true, // hasEnd
4411 context);
4412 return {
4413 def,
4414 ui: compileEventUi(def, eventUiBases),
4415 instance: createEventInstance(def.defId, dateSpan.range),
4416 range: dateSpan.range,
4417 isStart: true,
4418 isEnd: true,
4419 };
4420 }
4421
4422 let calendarSystemClassMap = {};
4423 function registerCalendarSystem(name, theClass) {
4424 calendarSystemClassMap[name] = theClass;
4425 }
4426 function createCalendarSystem(name) {
4427 return new calendarSystemClassMap[name]();
4428 }
4429 class GregorianCalendarSystem {
4430 getMarkerYear(d) {
4431 return d.getUTCFullYear();
4432 }
4433 getMarkerMonth(d) {
4434 return d.getUTCMonth();
4435 }
4436 getMarkerDay(d) {
4437 return d.getUTCDate();
4438 }
4439 arrayToMarker(arr) {
4440 return arrayToUtcDate(arr);
4441 }
4442 markerToArray(marker) {
4443 return dateToUtcArray(marker);
4444 }
4445 }
4446 registerCalendarSystem('gregory', GregorianCalendarSystem);
4447
4448 const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
4449 function parse(str) {
4450 let m = ISO_RE.exec(str);
4451 if (m) {
4452 let marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number(`0.${m[12]}`) * 1000 : 0));
4453 if (isValidDate(marker)) {
4454 let timeZoneOffset = null;
4455 if (m[13]) {
4456 timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
4457 Number(m[18] || 0));
4458 }
4459 return {
4460 marker,
4461 isTimeUnspecified: !m[6],
4462 timeZoneOffset,
4463 };
4464 }
4465 }
4466 return null;
4467 }
4468
4469 class DateEnv {
4470 constructor(settings) {
4471 let timeZone = this.timeZone = settings.timeZone;
4472 let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
4473 if (settings.namedTimeZoneImpl && isNamedTimeZone) {
4474 this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
4475 }
4476 this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
4477 this.calendarSystem = createCalendarSystem(settings.calendarSystem);
4478 this.locale = settings.locale;
4479 this.weekDow = settings.locale.week.dow;
4480 this.weekDoy = settings.locale.week.doy;
4481 if (settings.weekNumberCalculation === 'ISO') {
4482 this.weekDow = 1;
4483 this.weekDoy = 4;
4484 }
4485 if (typeof settings.firstDay === 'number') {
4486 this.weekDow = settings.firstDay;
4487 }
4488 if (typeof settings.weekNumberCalculation === 'function') {
4489 this.weekNumberFunc = settings.weekNumberCalculation;
4490 }
4491 this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
4492 this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
4493 this.cmdFormatter = settings.cmdFormatter;
4494 this.defaultSeparator = settings.defaultSeparator;
4495 }
4496 // Creating / Parsing
4497 createMarker(input) {
4498 let meta = this.createMarkerMeta(input);
4499 if (meta === null) {
4500 return null;
4501 }
4502 return meta.marker;
4503 }
4504 createNowMarker() {
4505 if (this.canComputeOffset) {
4506 return this.timestampToMarker(new Date().valueOf());
4507 }
4508 // if we can't compute the current date val for a timezone,
4509 // better to give the current local date vals than UTC
4510 return arrayToUtcDate(dateToLocalArray(new Date()));
4511 }
4512 createMarkerMeta(input) {
4513 if (typeof input === 'string') {
4514 return this.parse(input);
4515 }
4516 let marker = null;
4517 if (typeof input === 'number') {
4518 marker = this.timestampToMarker(input);
4519 }
4520 else if (input instanceof Date) {
4521 input = input.valueOf();
4522 if (!isNaN(input)) {
4523 marker = this.timestampToMarker(input);
4524 }
4525 }
4526 else if (Array.isArray(input)) {
4527 marker = arrayToUtcDate(input);
4528 }
4529 if (marker === null || !isValidDate(marker)) {
4530 return null;
4531 }
4532 return { marker, isTimeUnspecified: false, forcedTzo: null };
4533 }
4534 parse(s) {
4535 let parts = parse(s);
4536 if (parts === null) {
4537 return null;
4538 }
4539 let { marker } = parts;
4540 let forcedTzo = null;
4541 if (parts.timeZoneOffset !== null) {
4542 if (this.canComputeOffset) {
4543 marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
4544 }
4545 else {
4546 forcedTzo = parts.timeZoneOffset;
4547 }
4548 }
4549 return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
4550 }
4551 // Accessors
4552 getYear(marker) {
4553 return this.calendarSystem.getMarkerYear(marker);
4554 }
4555 getMonth(marker) {
4556 return this.calendarSystem.getMarkerMonth(marker);
4557 }
4558 getDay(marker) {
4559 return this.calendarSystem.getMarkerDay(marker);
4560 }
4561 // Adding / Subtracting
4562 add(marker, dur) {
4563 let a = this.calendarSystem.markerToArray(marker);
4564 a[0] += dur.years;
4565 a[1] += dur.months;
4566 a[2] += dur.days;
4567 a[6] += dur.milliseconds;
4568 return this.calendarSystem.arrayToMarker(a);
4569 }
4570 subtract(marker, dur) {
4571 let a = this.calendarSystem.markerToArray(marker);
4572 a[0] -= dur.years;
4573 a[1] -= dur.months;
4574 a[2] -= dur.days;
4575 a[6] -= dur.milliseconds;
4576 return this.calendarSystem.arrayToMarker(a);
4577 }
4578 addYears(marker, n) {
4579 let a = this.calendarSystem.markerToArray(marker);
4580 a[0] += n;
4581 return this.calendarSystem.arrayToMarker(a);
4582 }
4583 addMonths(marker, n) {
4584 let a = this.calendarSystem.markerToArray(marker);
4585 a[1] += n;
4586 return this.calendarSystem.arrayToMarker(a);
4587 }
4588 // Diffing Whole Units
4589 diffWholeYears(m0, m1) {
4590 let { calendarSystem } = this;
4591 if (timeAsMs(m0) === timeAsMs(m1) &&
4592 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
4593 calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
4594 return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
4595 }
4596 return null;
4597 }
4598 diffWholeMonths(m0, m1) {
4599 let { calendarSystem } = this;
4600 if (timeAsMs(m0) === timeAsMs(m1) &&
4601 calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
4602 return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
4603 (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
4604 }
4605 return null;
4606 }
4607 // Range / Duration
4608 greatestWholeUnit(m0, m1) {
4609 let n = this.diffWholeYears(m0, m1);
4610 if (n !== null) {
4611 return { unit: 'year', value: n };
4612 }
4613 n = this.diffWholeMonths(m0, m1);
4614 if (n !== null) {
4615 return { unit: 'month', value: n };
4616 }
4617 n = diffWholeWeeks(m0, m1);
4618 if (n !== null) {
4619 return { unit: 'week', value: n };
4620 }
4621 n = diffWholeDays(m0, m1);
4622 if (n !== null) {
4623 return { unit: 'day', value: n };
4624 }
4625 n = diffHours(m0, m1);
4626 if (isInt(n)) {
4627 return { unit: 'hour', value: n };
4628 }
4629 n = diffMinutes(m0, m1);
4630 if (isInt(n)) {
4631 return { unit: 'minute', value: n };
4632 }
4633 n = diffSeconds(m0, m1);
4634 if (isInt(n)) {
4635 return { unit: 'second', value: n };
4636 }
4637 return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
4638 }
4639 countDurationsBetween(m0, m1, d) {
4640 // TODO: can use greatestWholeUnit
4641 let diff;
4642 if (d.years) {
4643 diff = this.diffWholeYears(m0, m1);
4644 if (diff !== null) {
4645 return diff / asRoughYears(d);
4646 }
4647 }
4648 if (d.months) {
4649 diff = this.diffWholeMonths(m0, m1);
4650 if (diff !== null) {
4651 return diff / asRoughMonths(d);
4652 }
4653 }
4654 if (d.days) {
4655 diff = diffWholeDays(m0, m1);
4656 if (diff !== null) {
4657 return diff / asRoughDays(d);
4658 }
4659 }
4660 return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
4661 }
4662 // Start-Of
4663 // these DON'T return zoned-dates. only UTC start-of dates
4664 startOf(m, unit) {
4665 if (unit === 'year') {
4666 return this.startOfYear(m);
4667 }
4668 if (unit === 'month') {
4669 return this.startOfMonth(m);
4670 }
4671 if (unit === 'week') {
4672 return this.startOfWeek(m);
4673 }
4674 if (unit === 'day') {
4675 return startOfDay(m);
4676 }
4677 if (unit === 'hour') {
4678 return startOfHour(m);
4679 }
4680 if (unit === 'minute') {
4681 return startOfMinute(m);
4682 }
4683 if (unit === 'second') {
4684 return startOfSecond(m);
4685 }
4686 return null;
4687 }
4688 startOfYear(m) {
4689 return this.calendarSystem.arrayToMarker([
4690 this.calendarSystem.getMarkerYear(m),
4691 ]);
4692 }
4693 startOfMonth(m) {
4694 return this.calendarSystem.arrayToMarker([
4695 this.calendarSystem.getMarkerYear(m),
4696 this.calendarSystem.getMarkerMonth(m),
4697 ]);
4698 }
4699 startOfWeek(m) {
4700 return this.calendarSystem.arrayToMarker([
4701 this.calendarSystem.getMarkerYear(m),
4702 this.calendarSystem.getMarkerMonth(m),
4703 m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
4704 ]);
4705 }
4706 // Week Number
4707 computeWeekNumber(marker) {
4708 if (this.weekNumberFunc) {
4709 return this.weekNumberFunc(this.toDate(marker));
4710 }
4711 return weekOfYear(marker, this.weekDow, this.weekDoy);
4712 }
4713 // TODO: choke on timeZoneName: long
4714 format(marker, formatter, dateOptions = {}) {
4715 return formatter.format({
4716 marker,
4717 timeZoneOffset: dateOptions.forcedTzo != null ?
4718 dateOptions.forcedTzo :
4719 this.offsetForMarker(marker),
4720 }, this);
4721 }
4722 formatRange(start, end, formatter, dateOptions = {}) {
4723 if (dateOptions.isEndExclusive) {
4724 end = addMs(end, -1);
4725 }
4726 return formatter.formatRange({
4727 marker: start,
4728 timeZoneOffset: dateOptions.forcedStartTzo != null ?
4729 dateOptions.forcedStartTzo :
4730 this.offsetForMarker(start),
4731 }, {
4732 marker: end,
4733 timeZoneOffset: dateOptions.forcedEndTzo != null ?
4734 dateOptions.forcedEndTzo :
4735 this.offsetForMarker(end),
4736 }, this, dateOptions.defaultSeparator);
4737 }
4738 /*
4739 DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
4740 might as well use buildIsoString or some other util directly
4741 */
4742 formatIso(marker, extraOptions = {}) {
4743 let timeZoneOffset = null;
4744 if (!extraOptions.omitTimeZoneOffset) {
4745 if (extraOptions.forcedTzo != null) {
4746 timeZoneOffset = extraOptions.forcedTzo;
4747 }
4748 else {
4749 timeZoneOffset = this.offsetForMarker(marker);
4750 }
4751 }
4752 return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
4753 }
4754 // TimeZone
4755 timestampToMarker(ms) {
4756 if (this.timeZone === 'local') {
4757 return arrayToUtcDate(dateToLocalArray(new Date(ms)));
4758 }
4759 if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
4760 return new Date(ms);
4761 }
4762 return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
4763 }
4764 offsetForMarker(m) {
4765 if (this.timeZone === 'local') {
4766 return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
4767 }
4768 if (this.timeZone === 'UTC') {
4769 return 0;
4770 }
4771 if (this.namedTimeZoneImpl) {
4772 return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
4773 }
4774 return null;
4775 }
4776 // Conversion
4777 toDate(m, forcedTzo) {
4778 if (this.timeZone === 'local') {
4779 return arrayToLocalDate(dateToUtcArray(m));
4780 }
4781 if (this.timeZone === 'UTC') {
4782 return new Date(m.valueOf()); // make sure it's a copy
4783 }
4784 if (!this.namedTimeZoneImpl) {
4785 return new Date(m.valueOf() - (forcedTzo || 0));
4786 }
4787 return new Date(m.valueOf() -
4788 this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
4789 }
4790 }
4791
4792 class NamedTimeZoneImpl {
4793 constructor(timeZoneName) {
4794 this.timeZoneName = timeZoneName;
4795 }
4796 }
4797
4798 class SegHierarchy {
4799 constructor(getEntryThickness = (entry) => {
4800 // if no thickness known, assume 1 (if 0, so small it always fits)
4801 return entry.thickness || 1;
4802 }) {
4803 this.getEntryThickness = getEntryThickness;
4804 // settings
4805 this.strictOrder = false;
4806 this.allowReslicing = false;
4807 this.maxCoord = -1; // -1 means no max
4808 this.maxStackCnt = -1; // -1 means no max
4809 this.levelCoords = []; // ordered
4810 this.entriesByLevel = []; // parallel with levelCoords
4811 this.stackCnts = {}; // TODO: use better technique!?
4812 }
4813 addSegs(inputs) {
4814 let hiddenEntries = [];
4815 for (let input of inputs) {
4816 this.insertEntry(input, hiddenEntries);
4817 }
4818 return hiddenEntries;
4819 }
4820 insertEntry(entry, hiddenEntries) {
4821 let insertion = this.findInsertion(entry);
4822 if (this.isInsertionValid(insertion, entry)) {
4823 this.insertEntryAt(entry, insertion);
4824 }
4825 else {
4826 this.handleInvalidInsertion(insertion, entry, hiddenEntries);
4827 }
4828 }
4829 isInsertionValid(insertion, entry) {
4830 return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&
4831 (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
4832 }
4833 handleInvalidInsertion(insertion, entry, hiddenEntries) {
4834 if (this.allowReslicing && insertion.touchingEntry) {
4835 const hiddenEntry = Object.assign(Object.assign({}, entry), { span: intersectSpans(entry.span, insertion.touchingEntry.span) });
4836 hiddenEntries.push(hiddenEntry);
4837 this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
4838 }
4839 else {
4840 hiddenEntries.push(entry);
4841 }
4842 }
4843 /*
4844 Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.
4845 */
4846 splitEntry(entry, barrier, hiddenEntries) {
4847 let entrySpan = entry.span;
4848 let barrierSpan = barrier.span;
4849 if (entrySpan.start < barrierSpan.start) {
4850 this.insertEntry({
4851 index: entry.index,
4852 thickness: entry.thickness,
4853 span: { start: entrySpan.start, end: barrierSpan.start },
4854 }, hiddenEntries);
4855 }
4856 if (entrySpan.end > barrierSpan.end) {
4857 this.insertEntry({
4858 index: entry.index,
4859 thickness: entry.thickness,
4860 span: { start: barrierSpan.end, end: entrySpan.end },
4861 }, hiddenEntries);
4862 }
4863 }
4864 insertEntryAt(entry, insertion) {
4865 let { entriesByLevel, levelCoords } = this;
4866 if (insertion.lateral === -1) {
4867 // create a new level
4868 insertAt(levelCoords, insertion.level, insertion.levelCoord);
4869 insertAt(entriesByLevel, insertion.level, [entry]);
4870 }
4871 else {
4872 // insert into existing level
4873 insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
4874 }
4875 this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
4876 }
4877 /*
4878 does not care about limits
4879 */
4880 findInsertion(newEntry) {
4881 let { levelCoords, entriesByLevel, strictOrder, stackCnts } = this;
4882 let levelCnt = levelCoords.length;
4883 let candidateCoord = 0;
4884 let touchingLevel = -1;
4885 let touchingLateral = -1;
4886 let touchingEntry = null;
4887 let stackCnt = 0;
4888 for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
4889 const trackingCoord = levelCoords[trackingLevel];
4890 // if the current level is past the placed entry, we have found a good empty space and can stop.
4891 // if strictOrder, keep finding more lateral intersections.
4892 if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {
4893 break;
4894 }
4895 let trackingEntries = entriesByLevel[trackingLevel];
4896 let trackingEntry;
4897 let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
4898 let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
4899 while ( // loop through entries that horizontally intersect
4900 (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
4901 trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
4902 ) {
4903 let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
4904 // intersects into the top of the candidate?
4905 if (trackingEntryBottom > candidateCoord) {
4906 candidateCoord = trackingEntryBottom;
4907 touchingEntry = trackingEntry;
4908 touchingLevel = trackingLevel;
4909 touchingLateral = lateralIndex;
4910 }
4911 // butts up against top of candidate? (will happen if just intersected as well)
4912 if (trackingEntryBottom === candidateCoord) {
4913 // accumulate the highest possible stackCnt of the trackingEntries that butt up
4914 stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
4915 }
4916 lateralIndex += 1;
4917 }
4918 }
4919 // the destination level will be after touchingEntry's level. find it
4920 let destLevel = 0;
4921 if (touchingEntry) {
4922 destLevel = touchingLevel + 1;
4923 while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
4924 destLevel += 1;
4925 }
4926 }
4927 // if adding to an existing level, find where to insert
4928 let destLateral = -1;
4929 if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
4930 destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
4931 }
4932 return {
4933 touchingLevel,
4934 touchingLateral,
4935 touchingEntry,
4936 stackCnt,
4937 levelCoord: candidateCoord,
4938 level: destLevel,
4939 lateral: destLateral,
4940 };
4941 }
4942 // sorted by levelCoord (lowest to highest)
4943 toRects() {
4944 let { entriesByLevel, levelCoords } = this;
4945 let levelCnt = entriesByLevel.length;
4946 let rects = [];
4947 for (let level = 0; level < levelCnt; level += 1) {
4948 let entries = entriesByLevel[level];
4949 let levelCoord = levelCoords[level];
4950 for (let entry of entries) {
4951 rects.push(Object.assign(Object.assign({}, entry), { thickness: this.getEntryThickness(entry), levelCoord }));
4952 }
4953 }
4954 return rects;
4955 }
4956 }
4957 function getEntrySpanEnd(entry) {
4958 return entry.span.end;
4959 }
4960 function buildEntryKey(entry) {
4961 return entry.index + ':' + entry.span.start;
4962 }
4963 // returns groups with entries sorted by input order
4964 function groupIntersectingEntries(entries) {
4965 let merges = [];
4966 for (let entry of entries) {
4967 let filteredMerges = [];
4968 let hungryMerge = {
4969 span: entry.span,
4970 entries: [entry],
4971 };
4972 for (let merge of merges) {
4973 if (intersectSpans(merge.span, hungryMerge.span)) {
4974 hungryMerge = {
4975 entries: merge.entries.concat(hungryMerge.entries),
4976 span: joinSpans(merge.span, hungryMerge.span),
4977 };
4978 }
4979 else {
4980 filteredMerges.push(merge);
4981 }
4982 }
4983 filteredMerges.push(hungryMerge);
4984 merges = filteredMerges;
4985 }
4986 return merges;
4987 }
4988 function joinSpans(span0, span1) {
4989 return {
4990 start: Math.min(span0.start, span1.start),
4991 end: Math.max(span0.end, span1.end),
4992 };
4993 }
4994 function intersectSpans(span0, span1) {
4995 let start = Math.max(span0.start, span1.start);
4996 let end = Math.min(span0.end, span1.end);
4997 if (start < end) {
4998 return { start, end };
4999 }
5000 return null;
5001 }
5002 // general util
5003 // ---------------------------------------------------------------------------------------------------------------------
5004 function insertAt(arr, index, item) {
5005 arr.splice(index, 0, item);
5006 }
5007 function binarySearch(a, searchVal, getItemVal) {
5008 let startIndex = 0;
5009 let endIndex = a.length; // exclusive
5010 if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
5011 return [0, 0];
5012 }
5013 if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
5014 return [endIndex, 0];
5015 }
5016 while (startIndex < endIndex) {
5017 let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
5018 let middleVal = getItemVal(a[middleIndex]);
5019 if (searchVal < middleVal) {
5020 endIndex = middleIndex;
5021 }
5022 else if (searchVal > middleVal) {
5023 startIndex = middleIndex + 1;
5024 }
5025 else { // equal!
5026 return [middleIndex, 1];
5027 }
5028 }
5029 return [startIndex, 0];
5030 }
5031
5032 class Interaction {
5033 constructor(settings) {
5034 this.component = settings.component;
5035 this.isHitComboAllowed = settings.isHitComboAllowed || null;
5036 }
5037 destroy() {
5038 }
5039 }
5040 function parseInteractionSettings(component, input) {
5041 return {
5042 component,
5043 el: input.el,
5044 useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
5045 isHitComboAllowed: input.isHitComboAllowed || null,
5046 };
5047 }
5048 function interactionSettingsToStore(settings) {
5049 return {
5050 [settings.component.uid]: settings,
5051 };
5052 }
5053 // global state
5054 const interactionSettingsStore = {};
5055
5056 /*
5057 An abstraction for a dragging interaction originating on an event.
5058 Does higher-level things than PointerDragger, such as possibly:
5059 - a "mirror" that moves with the pointer
5060 - a minimum number of pixels or other criteria for a true drag to begin
5061
5062 subclasses must emit:
5063 - pointerdown
5064 - dragstart
5065 - dragmove
5066 - pointerup
5067 - dragend
5068 */
5069 class ElementDragging {
5070 constructor(el, selector) {
5071 this.emitter = new Emitter();
5072 }
5073 destroy() {
5074 }
5075 setMirrorIsVisible(bool) {
5076 // optional if subclass doesn't want to support a mirror
5077 }
5078 setMirrorNeedsRevert(bool) {
5079 // optional if subclass doesn't want to support a mirror
5080 }
5081 setAutoScrollEnabled(bool) {
5082 // optional
5083 }
5084 }
5085
5086 // TODO: get rid of this in favor of options system,
5087 // tho it's really easy to access this globally rather than pass thru options.
5088 const config = {};
5089
5090 /*
5091 Information about what will happen when an external element is dragged-and-dropped
5092 onto a calendar. Contains information for creating an event.
5093 */
5094 const DRAG_META_REFINERS = {
5095 startTime: createDuration,
5096 duration: createDuration,
5097 create: Boolean,
5098 sourceId: String,
5099 };
5100 function parseDragMeta(raw) {
5101 let { refined, extra } = refineProps(raw, DRAG_META_REFINERS);
5102 return {
5103 startTime: refined.startTime || null,
5104 duration: refined.duration || null,
5105 create: refined.create != null ? refined.create : true,
5106 sourceId: refined.sourceId,
5107 leftoverProps: extra,
5108 };
5109 }
5110
5111 class CalendarRoot extends BaseComponent {
5112 constructor() {
5113 super(...arguments);
5114 this.state = {
5115 forPrint: false,
5116 };
5117 this.handleBeforePrint = () => {
5118 flushSync(() => {
5119 this.setState({ forPrint: true });
5120 });
5121 };
5122 this.handleAfterPrint = () => {
5123 flushSync(() => {
5124 this.setState({ forPrint: false });
5125 });
5126 };
5127 }
5128 render() {
5129 let { props } = this;
5130 let { options } = props;
5131 let { forPrint } = this.state;
5132 let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
5133 let height = (!isHeightAuto && options.height != null) ? options.height : '';
5134 let classNames = [
5135 'fc',
5136 forPrint ? 'fc-media-print' : 'fc-media-screen',
5137 `fc-direction-${options.direction}`,
5138 props.theme.getClass('root'),
5139 ];
5140 if (!getCanVGrowWithinCell()) {
5141 classNames.push('fc-liquid-hack');
5142 }
5143 return props.children(classNames, height, isHeightAuto, forPrint);
5144 }
5145 componentDidMount() {
5146 let { emitter } = this.props;
5147 emitter.on('_beforeprint', this.handleBeforePrint);
5148 emitter.on('_afterprint', this.handleAfterPrint);
5149 }
5150 componentWillUnmount() {
5151 let { emitter } = this.props;
5152 emitter.off('_beforeprint', this.handleBeforePrint);
5153 emitter.off('_afterprint', this.handleAfterPrint);
5154 }
5155 }
5156
5157 // Computes a default column header formatting string if `colFormat` is not explicitly defined
5158 function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
5159 // if more than one week row, or if there are a lot of columns with not much space,
5160 // put just the day numbers will be in each cell
5161 if (!datesRepDistinctDays || dayCnt > 10) {
5162 return createFormatter({ weekday: 'short' }); // "Sat"
5163 }
5164 if (dayCnt > 1) {
5165 return createFormatter({ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }); // "Sat 11/12"
5166 }
5167 return createFormatter({ weekday: 'long' }); // "Saturday"
5168 }
5169
5170 const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
5171 function renderInner$1(renderProps) {
5172 return renderProps.text;
5173 }
5174
5175 class ContentInjector extends BaseComponent {
5176 constructor() {
5177 super(...arguments);
5178 this.id = guid();
5179 this.queuedDomNodes = [];
5180 this.currentDomNodes = [];
5181 this.handleEl = (el) => {
5182 const { options } = this.context;
5183 const { generatorName } = this.props;
5184 if (!options.customRenderingReplaces || !hasCustomRenderingHandler(generatorName, options)) {
5185 this.updateElRef(el);
5186 }
5187 };
5188 this.updateElRef = (el) => {
5189 if (this.props.elRef) {
5190 setRef(this.props.elRef, el);
5191 }
5192 };
5193 }
5194 render() {
5195 const { props, context } = this;
5196 const { options } = context;
5197 const { customGenerator, defaultGenerator, renderProps } = props;
5198 const attrs = buildElAttrs(props, [], this.handleEl);
5199 let useDefault = false;
5200 let innerContent;
5201 let queuedDomNodes = [];
5202 let currentGeneratorMeta;
5203 if (customGenerator != null) {
5204 const customGeneratorRes = typeof customGenerator === 'function' ?
5205 customGenerator(renderProps, y) :
5206 customGenerator;
5207 if (customGeneratorRes === true) {
5208 useDefault = true;
5209 }
5210 else {
5211 const isObject = customGeneratorRes && typeof customGeneratorRes === 'object'; // non-null
5212 if (isObject && ('html' in customGeneratorRes)) {
5213 attrs.dangerouslySetInnerHTML = { __html: customGeneratorRes.html };
5214 }
5215 else if (isObject && ('domNodes' in customGeneratorRes)) {
5216 queuedDomNodes = Array.prototype.slice.call(customGeneratorRes.domNodes);
5217 }
5218 else if (isObject
5219 ? i$1(customGeneratorRes) // vdom node
5220 : typeof customGeneratorRes !== 'function' // primitive value (like string or number)
5221 ) {
5222 // use in vdom
5223 innerContent = customGeneratorRes;
5224 }
5225 else {
5226 // an exotic object for handleCustomRendering
5227 currentGeneratorMeta = customGeneratorRes;
5228 }
5229 }
5230 }
5231 else {
5232 useDefault = !hasCustomRenderingHandler(props.generatorName, options);
5233 }
5234 if (useDefault && defaultGenerator) {
5235 innerContent = defaultGenerator(renderProps);
5236 }
5237 this.queuedDomNodes = queuedDomNodes;
5238 this.currentGeneratorMeta = currentGeneratorMeta;
5239 return y(props.elTag, attrs, innerContent);
5240 }
5241 componentDidMount() {
5242 this.applyQueueudDomNodes();
5243 this.triggerCustomRendering(true);
5244 }
5245 componentDidUpdate() {
5246 this.applyQueueudDomNodes();
5247 this.triggerCustomRendering(true);
5248 }
5249 componentWillUnmount() {
5250 this.triggerCustomRendering(false); // TODO: different API for removal?
5251 }
5252 triggerCustomRendering(isActive) {
5253 var _a;
5254 const { props, context } = this;
5255 const { handleCustomRendering, customRenderingMetaMap } = context.options;
5256 if (handleCustomRendering) {
5257 const generatorMeta = (_a = this.currentGeneratorMeta) !== null && _a !== void 0 ? _a : customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
5258 if (generatorMeta) {
5259 handleCustomRendering(Object.assign(Object.assign({ id: this.id, isActive, containerEl: this.base, reportNewContainerEl: this.updateElRef, // front-end framework tells us about new container els
5260 generatorMeta }, props), { elClasses: (props.elClasses || []).filter(isTruthy) }));
5261 }
5262 }
5263 }
5264 applyQueueudDomNodes() {
5265 const { queuedDomNodes, currentDomNodes } = this;
5266 const el = this.base;
5267 if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
5268 currentDomNodes.forEach(removeElement);
5269 for (let newNode of queuedDomNodes) {
5270 el.appendChild(newNode);
5271 }
5272 this.currentDomNodes = queuedDomNodes;
5273 }
5274 }
5275 }
5276 ContentInjector.addPropsEquality({
5277 elClasses: isArraysEqual,
5278 elStyle: isPropsEqual,
5279 elAttrs: isNonHandlerPropsEqual,
5280 renderProps: isPropsEqual,
5281 });
5282 // Util
5283 /*
5284 Does UI-framework provide custom way of rendering that does not use Preact VDOM
5285 AND does the calendar's options define custom rendering?
5286 AKA. Should we NOT render the default content?
5287 */
5288 function hasCustomRenderingHandler(generatorName, options) {
5289 var _a;
5290 return Boolean(options.handleCustomRendering &&
5291 generatorName &&
5292 ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
5293 }
5294 function buildElAttrs(props, extraClassNames, elRef) {
5295 const attrs = Object.assign(Object.assign({}, props.elAttrs), { ref: elRef });
5296 if (props.elClasses || extraClassNames) {
5297 attrs.className = (props.elClasses || [])
5298 .concat(extraClassNames || [])
5299 .concat(attrs.className || [])
5300 .filter(Boolean)
5301 .join(' ');
5302 }
5303 if (props.elStyle) {
5304 attrs.style = props.elStyle;
5305 }
5306 return attrs;
5307 }
5308 function isTruthy(val) {
5309 return Boolean(val);
5310 }
5311
5312 const RenderId = createContext(0);
5313
5314 class ContentContainer extends x$1 {
5315 constructor() {
5316 super(...arguments);
5317 this.InnerContent = InnerContentInjector.bind(undefined, this);
5318 this.handleEl = (el) => {
5319 this.el = el;
5320 if (this.props.elRef) {
5321 setRef(this.props.elRef, el);
5322 if (el && this.didMountMisfire) {
5323 this.componentDidMount();
5324 }
5325 }
5326 };
5327 }
5328 render() {
5329 const { props } = this;
5330 const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
5331 if (props.children) {
5332 const elAttrs = buildElAttrs(props, generatedClassNames, this.handleEl);
5333 const children = props.children(this.InnerContent, props.renderProps, elAttrs);
5334 if (props.elTag) {
5335 return y(props.elTag, elAttrs, children);
5336 }
5337 else {
5338 return children;
5339 }
5340 }
5341 else {
5342 return y((ContentInjector), Object.assign(Object.assign({}, props), { elRef: this.handleEl, elTag: props.elTag || 'div', elClasses: (props.elClasses || []).concat(generatedClassNames), renderId: this.context }));
5343 }
5344 }
5345 componentDidMount() {
5346 var _a, _b;
5347 if (this.el) {
5348 (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
5349 }
5350 else {
5351 this.didMountMisfire = true;
5352 }
5353 }
5354 componentWillUnmount() {
5355 var _a, _b;
5356 (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), { el: this.el }));
5357 }
5358 }
5359 ContentContainer.contextType = RenderId;
5360 function InnerContentInjector(containerComponent, props) {
5361 const parentProps = containerComponent.props;
5362 return y((ContentInjector), Object.assign({ renderProps: parentProps.renderProps, generatorName: parentProps.generatorName, customGenerator: parentProps.customGenerator, defaultGenerator: parentProps.defaultGenerator, renderId: containerComponent.context }, props));
5363 }
5364 // Utils
5365 function generateClassNames(classNameGenerator, renderProps) {
5366 const classNames = typeof classNameGenerator === 'function' ?
5367 classNameGenerator(renderProps) :
5368 classNameGenerator || [];
5369 return typeof classNames === 'string' ? [classNames] : classNames;
5370 }
5371
5372 // BAD name for this class now. used in the Header
5373 class TableDateCell extends BaseComponent {
5374 render() {
5375 let { dateEnv, options, theme, viewApi } = this.context;
5376 let { props } = this;
5377 let { date, dateProfile } = props;
5378 let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
5379 let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
5380 let text = dateEnv.format(date, props.dayHeaderFormat);
5381 // if colCnt is 1, we are already in a day-view and don't need a navlink
5382 let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1)
5383 ? buildNavLinkAttrs(this.context, date)
5384 : {};
5385 let publicDate = dateEnv.toDate(date);
5386 // workaround for Luxon (and maybe moment) returning prior-days when start-of-day
5387 // in DST gap: https://github.com/fullcalendar/fullcalendar/issues/7633
5388 if (dateEnv.namedTimeZoneImpl) {
5389 publicDate = addMs(publicDate, 3600000); // add an hour
5390 }
5391 let renderProps = Object.assign(Object.assign(Object.assign({ date: publicDate, view: viewApi }, props.extraRenderProps), { text }), dayMeta);
5392 return (y(ContentContainer, { elTag: "th", elClasses: classNames, elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan, 'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContainer) => (y("div", { className: "fc-scrollgrid-sync-inner" }, !dayMeta.isDisabled && (y(InnerContainer, { elTag: "a", elAttrs: navLinkAttrs, elClasses: [
5393 'fc-col-header-cell-cushion',
5394 props.isSticky && 'fc-sticky',
5395 ] }))))));
5396 }
5397 }
5398
5399 const WEEKDAY_FORMAT = createFormatter({ weekday: 'long' });
5400 class TableDowCell extends BaseComponent {
5401 render() {
5402 let { props } = this;
5403 let { dateEnv, theme, viewApi, options } = this.context;
5404 let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
5405 let dateMeta = {
5406 dow: props.dow,
5407 isDisabled: false,
5408 isFuture: false,
5409 isPast: false,
5410 isToday: false,
5411 isOther: false,
5412 };
5413 let text = dateEnv.format(date, props.dayHeaderFormat);
5414 let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
5415 date }, dateMeta), { view: viewApi }), props.extraRenderProps), { text });
5416 return (y(ContentContainer, { elTag: "th", elClasses: [
5417 CLASS_NAME,
5418 ...getDayClassNames(dateMeta, theme),
5419 ...(props.extraClassNames || []),
5420 ], elAttrs: Object.assign({ role: 'columnheader', colSpan: props.colSpan }, props.extraDataAttrs), renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInner$1, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => (y("div", { className: "fc-scrollgrid-sync-inner" },
5421 y(InnerContent, { elTag: "a", elClasses: [
5422 'fc-col-header-cell-cushion',
5423 props.isSticky && 'fc-sticky',
5424 ], elAttrs: {
5425 'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
5426 } })))));
5427 }
5428 }
5429
5430 class NowTimer extends x$1 {
5431 constructor(props, context) {
5432 super(props, context);
5433 this.handleRefresh = () => {
5434 let timing = this.computeTiming();
5435 if (timing.state.nowDate.valueOf() !== this.state.nowDate.valueOf()) {
5436 this.setState(timing.state);
5437 }
5438 this.clearTimeout();
5439 this.setTimeout(timing.waitMs);
5440 };
5441 this.handleVisibilityChange = () => {
5442 if (!document.hidden) {
5443 this.handleRefresh();
5444 }
5445 };
5446 this.state = this.computeTiming().state;
5447 }
5448 render() {
5449 let { props, state } = this;
5450 return props.children(state.nowDate, state.todayRange);
5451 }
5452 componentDidMount() {
5453 this.setTimeout();
5454 this.context.nowManager.addResetListener(this.handleRefresh);
5455 // fired tab becomes visible after being hidden
5456 document.addEventListener('visibilitychange', this.handleVisibilityChange);
5457 }
5458 componentDidUpdate(prevProps) {
5459 if (prevProps.unit !== this.props.unit) {
5460 this.clearTimeout();
5461 this.setTimeout();
5462 }
5463 }
5464 componentWillUnmount() {
5465 this.clearTimeout();
5466 this.context.nowManager.removeResetListener(this.handleRefresh);
5467 document.removeEventListener('visibilitychange', this.handleVisibilityChange);
5468 }
5469 computeTiming() {
5470 let { props, context } = this;
5471 let unroundedNow = context.nowManager.getDateMarker();
5472 let currentUnitStart = context.dateEnv.startOf(unroundedNow, props.unit);
5473 let nextUnitStart = context.dateEnv.add(currentUnitStart, createDuration(1, props.unit));
5474 let waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
5475 // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
5476 // ensure no longer than a day
5477 waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
5478 return {
5479 state: { nowDate: currentUnitStart, todayRange: buildDayRange(currentUnitStart) },
5480 waitMs,
5481 };
5482 }
5483 setTimeout(waitMs = this.computeTiming().waitMs) {
5484 // NOTE: timeout could take longer than expected if tab sleeps,
5485 // which is why we listen to 'visibilitychange'
5486 this.timeoutId = setTimeout(() => {
5487 // NOTE: timeout could also return *earlier* than expected, and we need to wait 2 ms more
5488 // This is why use use same waitMs from computeTiming, so we don't skip an interval while
5489 // .setState() is executing
5490 const timing = this.computeTiming();
5491 this.setState(timing.state, () => {
5492 this.setTimeout(timing.waitMs);
5493 });
5494 }, waitMs);
5495 }
5496 clearTimeout() {
5497 if (this.timeoutId) {
5498 clearTimeout(this.timeoutId);
5499 }
5500 }
5501 }
5502 NowTimer.contextType = ViewContextType;
5503 function buildDayRange(date) {
5504 let start = startOfDay(date);
5505 let end = addDays(start, 1);
5506 return { start, end };
5507 }
5508
5509 class DayHeader extends BaseComponent {
5510 constructor() {
5511 super(...arguments);
5512 this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
5513 }
5514 render() {
5515 let { context } = this;
5516 let { dates, dateProfile, datesRepDistinctDays, renderIntro } = this.props;
5517 let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
5518 return (y(NowTimer, { unit: "day" }, (nowDate, todayRange) => (y("tr", { role: "row" },
5519 renderIntro && renderIntro('day'),
5520 dates.map((date) => (datesRepDistinctDays ? (y(TableDateCell, { key: date.toISOString(), date: date, dateProfile: dateProfile, todayRange: todayRange, colCnt: dates.length, dayHeaderFormat: dayHeaderFormat })) : (y(TableDowCell, { key: date.getUTCDay(), dow: date.getUTCDay(), dayHeaderFormat: dayHeaderFormat }))))))));
5521 }
5522 }
5523 function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
5524 return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
5525 }
5526
5527 class DaySeriesModel {
5528 constructor(range, dateProfileGenerator) {
5529 let date = range.start;
5530 let { end } = range;
5531 let indices = [];
5532 let dates = [];
5533 let dayIndex = -1;
5534 while (date < end) { // loop each day from start to end
5535 if (dateProfileGenerator.isHiddenDay(date)) {
5536 indices.push(dayIndex + 0.5); // mark that it's between indices
5537 }
5538 else {
5539 dayIndex += 1;
5540 indices.push(dayIndex);
5541 dates.push(date);
5542 }
5543 date = addDays(date, 1);
5544 }
5545 this.dates = dates;
5546 this.indices = indices;
5547 this.cnt = dates.length;
5548 }
5549 sliceRange(range) {
5550 let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
5551 let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
5552 let clippedFirstIndex = Math.max(0, firstIndex);
5553 let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
5554 // deal with in-between indices
5555 clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
5556 clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
5557 if (clippedFirstIndex <= clippedLastIndex) {
5558 return {
5559 firstIndex: clippedFirstIndex,
5560 lastIndex: clippedLastIndex,
5561 isStart: firstIndex === clippedFirstIndex,
5562 isEnd: lastIndex === clippedLastIndex,
5563 };
5564 }
5565 return null;
5566 }
5567 // Given a date, returns its chronolocial cell-index from the first cell of the grid.
5568 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
5569 // If before the first offset, returns a negative number.
5570 // If after the last offset, returns an offset past the last cell offset.
5571 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
5572 getDateDayIndex(date) {
5573 let { indices } = this;
5574 let dayOffset = Math.floor(diffDays(this.dates[0], date));
5575 if (dayOffset < 0) {
5576 return indices[0] - 1;
5577 }
5578 if (dayOffset >= indices.length) {
5579 return indices[indices.length - 1] + 1;
5580 }
5581 return indices[dayOffset];
5582 }
5583 }
5584
5585 class DayTableModel {
5586 constructor(daySeries, breakOnWeeks) {
5587 let { dates } = daySeries;
5588 let daysPerRow;
5589 let firstDay;
5590 let rowCnt;
5591 if (breakOnWeeks) {
5592 // count columns until the day-of-week repeats
5593 firstDay = dates[0].getUTCDay();
5594 for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
5595 if (dates[daysPerRow].getUTCDay() === firstDay) {
5596 break;
5597 }
5598 }
5599 rowCnt = Math.ceil(dates.length / daysPerRow);
5600 }
5601 else {
5602 rowCnt = 1;
5603 daysPerRow = dates.length;
5604 }
5605 this.rowCnt = rowCnt;
5606 this.colCnt = daysPerRow;
5607 this.daySeries = daySeries;
5608 this.cells = this.buildCells();
5609 this.headerDates = this.buildHeaderDates();
5610 }
5611 buildCells() {
5612 let rows = [];
5613 for (let row = 0; row < this.rowCnt; row += 1) {
5614 let cells = [];
5615 for (let col = 0; col < this.colCnt; col += 1) {
5616 cells.push(this.buildCell(row, col));
5617 }
5618 rows.push(cells);
5619 }
5620 return rows;
5621 }
5622 buildCell(row, col) {
5623 let date = this.daySeries.dates[row * this.colCnt + col];
5624 return {
5625 key: date.toISOString(),
5626 date,
5627 };
5628 }
5629 buildHeaderDates() {
5630 let dates = [];
5631 for (let col = 0; col < this.colCnt; col += 1) {
5632 dates.push(this.cells[0][col].date);
5633 }
5634 return dates;
5635 }
5636 sliceRange(range) {
5637 let { colCnt } = this;
5638 let seriesSeg = this.daySeries.sliceRange(range);
5639 let segs = [];
5640 if (seriesSeg) {
5641 let { firstIndex, lastIndex } = seriesSeg;
5642 let index = firstIndex;
5643 while (index <= lastIndex) {
5644 let row = Math.floor(index / colCnt);
5645 let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
5646 segs.push({
5647 row,
5648 firstCol: index % colCnt,
5649 lastCol: (nextIndex - 1) % colCnt,
5650 isStart: seriesSeg.isStart && index === firstIndex,
5651 isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
5652 });
5653 index = nextIndex;
5654 }
5655 }
5656 return segs;
5657 }
5658 }
5659
5660 class Slicer {
5661 constructor() {
5662 this.sliceBusinessHours = memoize(this._sliceBusinessHours);
5663 this.sliceDateSelection = memoize(this._sliceDateSpan);
5664 this.sliceEventStore = memoize(this._sliceEventStore);
5665 this.sliceEventDrag = memoize(this._sliceInteraction);
5666 this.sliceEventResize = memoize(this._sliceInteraction);
5667 this.forceDayIfListItem = false; // hack
5668 }
5669 sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
5670 let { eventUiBases } = props;
5671 let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
5672 return {
5673 dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),
5674 businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
5675 fgEventSegs: eventSegs.fg,
5676 bgEventSegs: eventSegs.bg,
5677 eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
5678 eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
5679 eventSelection: props.eventSelection,
5680 }; // TODO: give interactionSegs?
5681 }
5682 sliceNowDate(// does not memoize
5683 date, dateProfile, nextDayThreshold, context, ...extraArgs) {
5684 return this._sliceDateSpan({ range: { start: date, end: addMs(date, 1) }, allDay: false }, // add 1 ms, protect against null range
5685 dateProfile, nextDayThreshold, {}, context, ...extraArgs);
5686 }
5687 _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
5688 if (!businessHours) {
5689 return [];
5690 }
5691 return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
5692 }
5693 _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
5694 if (eventStore) {
5695 let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
5696 return {
5697 bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
5698 fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
5699 };
5700 }
5701 return { bg: [], fg: [] };
5702 }
5703 _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
5704 if (!interaction) {
5705 return null;
5706 }
5707 let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
5708 return {
5709 segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
5710 affectedInstances: interaction.affectedEvents.instances,
5711 isEvent: interaction.isEvent,
5712 };
5713 }
5714 _sliceDateSpan(dateSpan, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs) {
5715 if (!dateSpan) {
5716 return [];
5717 }
5718 let activeRange = computeActiveRange(dateProfile, Boolean(nextDayThreshold));
5719 let activeDateSpanRange = intersectRanges(dateSpan.range, activeRange);
5720 if (activeDateSpanRange) {
5721 dateSpan = Object.assign(Object.assign({}, dateSpan), { range: activeDateSpanRange });
5722 let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
5723 let segs = this.sliceRange(dateSpan.range, ...extraArgs);
5724 for (let seg of segs) {
5725 seg.eventRange = eventRange;
5726 }
5727 return segs;
5728 }
5729 return [];
5730 }
5731 /*
5732 "complete" seg means it has component and eventRange
5733 */
5734 sliceEventRanges(eventRanges, extraArgs) {
5735 let segs = [];
5736 for (let eventRange of eventRanges) {
5737 segs.push(...this.sliceEventRange(eventRange, extraArgs));
5738 }
5739 return segs;
5740 }
5741 /*
5742 "complete" seg means it has component and eventRange
5743 */
5744 sliceEventRange(eventRange, extraArgs) {
5745 let dateRange = eventRange.range;
5746 // hack to make multi-day events that are being force-displayed as list-items to take up only one day
5747 if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
5748 dateRange = {
5749 start: dateRange.start,
5750 end: addDays(dateRange.start, 1),
5751 };
5752 }
5753 let segs = this.sliceRange(dateRange, ...extraArgs);
5754 for (let seg of segs) {
5755 seg.eventRange = eventRange;
5756 seg.isStart = eventRange.isStart && seg.isStart;
5757 seg.isEnd = eventRange.isEnd && seg.isEnd;
5758 }
5759 return segs;
5760 }
5761 }
5762 /*
5763 for incorporating slotMinTime/slotMaxTime if appropriate
5764 TODO: should be part of DateProfile!
5765 TimelineDateProfile already does this btw
5766 */
5767 function computeActiveRange(dateProfile, isComponentAllDay) {
5768 let range = dateProfile.activeRange;
5769 if (isComponentAllDay) {
5770 return range;
5771 }
5772 return {
5773 start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
5774 end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
5775 };
5776 }
5777
5778 function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
5779 switch (action.type) {
5780 case 'RECEIVE_EVENTS': // raw
5781 return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
5782 case 'RESET_RAW_EVENTS':
5783 return resetRawEvents(eventStore, eventSources[action.sourceId], action.rawEvents, dateProfile.activeRange, context);
5784 case 'ADD_EVENTS': // already parsed, but not expanded
5785 return addEvent(eventStore, action.eventStore, // new ones
5786 dateProfile ? dateProfile.activeRange : null, context);
5787 case 'RESET_EVENTS':
5788 return action.eventStore;
5789 case 'MERGE_EVENTS': // already parsed and expanded
5790 return mergeEventStores(eventStore, action.eventStore);
5791 case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
5792 case 'NEXT':
5793 case 'CHANGE_DATE':
5794 case 'CHANGE_VIEW_TYPE':
5795 if (dateProfile) {
5796 return expandRecurring(eventStore, dateProfile.activeRange, context);
5797 }
5798 return eventStore;
5799 case 'REMOVE_EVENTS':
5800 return excludeSubEventStore(eventStore, action.eventStore);
5801 case 'REMOVE_EVENT_SOURCE':
5802 return excludeEventsBySourceId(eventStore, action.sourceId);
5803 case 'REMOVE_ALL_EVENT_SOURCES':
5804 return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
5805 ));
5806 case 'REMOVE_ALL_EVENTS':
5807 return createEmptyEventStore();
5808 default:
5809 return eventStore;
5810 }
5811 }
5812 function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
5813 if (eventSource && // not already removed
5814 fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
5815 ) {
5816 let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
5817 if (fetchRange) {
5818 subset = expandRecurring(subset, fetchRange, context);
5819 }
5820 return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
5821 }
5822 return eventStore;
5823 }
5824 function resetRawEvents(existingEventStore, eventSource, rawEvents, activeRange, context) {
5825 const { defIdMap, instanceIdMap } = buildPublicIdMaps(existingEventStore);
5826 let newEventStore = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context, false, defIdMap, instanceIdMap);
5827 return expandRecurring(newEventStore, activeRange, context);
5828 }
5829 function transformRawEvents(rawEvents, eventSource, context) {
5830 let calEachTransform = context.options.eventDataTransform;
5831 let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
5832 if (sourceEachTransform) {
5833 rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
5834 }
5835 if (calEachTransform) {
5836 rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
5837 }
5838 return rawEvents;
5839 }
5840 function transformEachRawEvent(rawEvents, func) {
5841 let refinedEvents;
5842 if (!func) {
5843 refinedEvents = rawEvents;
5844 }
5845 else {
5846 refinedEvents = [];
5847 for (let rawEvent of rawEvents) {
5848 let refinedEvent = func(rawEvent);
5849 if (refinedEvent) {
5850 refinedEvents.push(refinedEvent);
5851 }
5852 else if (refinedEvent == null) {
5853 refinedEvents.push(rawEvent);
5854 } // if a different falsy value, do nothing
5855 }
5856 }
5857 return refinedEvents;
5858 }
5859 function addEvent(eventStore, subset, expandRange, context) {
5860 if (expandRange) {
5861 subset = expandRecurring(subset, expandRange, context);
5862 }
5863 return mergeEventStores(eventStore, subset);
5864 }
5865 function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
5866 let { defs } = eventStore;
5867 let instances = mapHash(eventStore.instances, (instance) => {
5868 let def = defs[instance.defId];
5869 if (def.allDay) {
5870 return instance; // isn't dependent on timezone
5871 }
5872 return Object.assign(Object.assign({}, instance), { range: {
5873 start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
5874 end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
5875 }, forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo, forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo });
5876 });
5877 return { defs, instances };
5878 }
5879 function excludeEventsBySourceId(eventStore, sourceId) {
5880 return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
5881 }
5882 // QUESTION: why not just return instances? do a general object-property-exclusion util
5883 function excludeInstances(eventStore, removals) {
5884 return {
5885 defs: eventStore.defs,
5886 instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
5887 };
5888 }
5889 function buildPublicIdMaps(eventStore) {
5890 const { defs, instances } = eventStore;
5891 const defIdMap = {};
5892 const instanceIdMap = {};
5893 for (let defId in defs) {
5894 const def = defs[defId];
5895 const { publicId } = def;
5896 if (publicId) {
5897 defIdMap[publicId] = defId;
5898 }
5899 }
5900 for (let instanceId in instances) {
5901 const instance = instances[instanceId];
5902 const def = defs[instance.defId];
5903 const { publicId } = def;
5904 if (publicId) {
5905 instanceIdMap[publicId] = instanceId;
5906 }
5907 }
5908 return { defIdMap, instanceIdMap };
5909 }
5910
5911 // high-level segmenting-aware tester functions
5912 // ------------------------------------------------------------------------------------------------------------------------
5913 function isInteractionValid(interaction, dateProfile, context) {
5914 let { instances } = interaction.mutatedEvents;
5915 for (let instanceId in instances) {
5916 if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
5917 return false;
5918 }
5919 }
5920 return isNewPropsValid({ eventDrag: interaction }, context); // HACK: the eventDrag props is used for ALL interactions
5921 }
5922 function isDateSelectionValid(dateSelection, dateProfile, context) {
5923 if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
5924 return false;
5925 }
5926 return isNewPropsValid({ dateSelection }, context);
5927 }
5928 function isNewPropsValid(newProps, context) {
5929 let calendarState = context.getCurrentData();
5930 let props = Object.assign({ businessHours: calendarState.businessHours, dateSelection: '', eventStore: calendarState.eventStore, eventUiBases: calendarState.eventUiBases, eventSelection: '', eventDrag: null, eventResize: null }, newProps);
5931 return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
5932 }
5933 function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
5934 if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
5935 return false;
5936 }
5937 if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
5938 return false;
5939 }
5940 return true;
5941 }
5942 // Moving Event Validation
5943 // ------------------------------------------------------------------------------------------------------------------------
5944 function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
5945 let currentState = context.getCurrentData();
5946 let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
5947 let subjectEventStore = interaction.mutatedEvents;
5948 let subjectDefs = subjectEventStore.defs;
5949 let subjectInstances = subjectEventStore.instances;
5950 let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
5951 state.eventUiBases :
5952 { '': currentState.selectionConfig });
5953 if (filterConfig) {
5954 subjectConfigs = mapHash(subjectConfigs, filterConfig);
5955 }
5956 // exclude the subject events. TODO: exclude defs too?
5957 let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
5958 let otherDefs = otherEventStore.defs;
5959 let otherInstances = otherEventStore.instances;
5960 let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
5961 for (let subjectInstanceId in subjectInstances) {
5962 let subjectInstance = subjectInstances[subjectInstanceId];
5963 let subjectRange = subjectInstance.range;
5964 let subjectConfig = subjectConfigs[subjectInstance.defId];
5965 let subjectDef = subjectDefs[subjectInstance.defId];
5966 // constraint
5967 if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
5968 return false;
5969 }
5970 // overlap
5971 let { eventOverlap } = context.options;
5972 let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
5973 for (let otherInstanceId in otherInstances) {
5974 let otherInstance = otherInstances[otherInstanceId];
5975 // intersect! evaluate
5976 if (rangesIntersect(subjectRange, otherInstance.range)) {
5977 let otherOverlap = otherConfigs[otherInstance.defId].overlap;
5978 // consider the other event's overlap. only do this if the subject event is a "real" event
5979 if (otherOverlap === false && interaction.isEvent) {
5980 return false;
5981 }
5982 if (subjectConfig.overlap === false) {
5983 return false;
5984 }
5985 if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
5986 new EventImpl(context, subjectDef, subjectInstance))) {
5987 return false;
5988 }
5989 }
5990 }
5991 // allow (a function)
5992 let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
5993 for (let subjectAllow of subjectConfig.allows) {
5994 let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), { range: subjectInstance.range, allDay: subjectDef.allDay });
5995 let origDef = calendarEventStore.defs[subjectDef.defId];
5996 let origInstance = calendarEventStore.instances[subjectInstanceId];
5997 let eventApi;
5998 if (origDef) { // was previously in the calendar
5999 eventApi = new EventImpl(context, origDef, origInstance);
6000 }
6001 else { // was an external event
6002 eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
6003 }
6004 if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
6005 return false;
6006 }
6007 }
6008 }
6009 return true;
6010 }
6011 // Date Selection Validation
6012 // ------------------------------------------------------------------------------------------------------------------------
6013 function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
6014 let relevantEventStore = state.eventStore;
6015 let relevantDefs = relevantEventStore.defs;
6016 let relevantInstances = relevantEventStore.instances;
6017 let selection = state.dateSelection;
6018 let selectionRange = selection.range;
6019 let { selectionConfig } = context.getCurrentData();
6020 if (filterConfig) {
6021 selectionConfig = filterConfig(selectionConfig);
6022 }
6023 // constraint
6024 if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
6025 return false;
6026 }
6027 // overlap
6028 let { selectOverlap } = context.options;
6029 let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
6030 for (let relevantInstanceId in relevantInstances) {
6031 let relevantInstance = relevantInstances[relevantInstanceId];
6032 // intersect! evaluate
6033 if (rangesIntersect(selectionRange, relevantInstance.range)) {
6034 if (selectionConfig.overlap === false) {
6035 return false;
6036 }
6037 if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
6038 return false;
6039 }
6040 }
6041 }
6042 // allow (a function)
6043 for (let selectionAllow of selectionConfig.allows) {
6044 let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
6045 if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
6046 return false;
6047 }
6048 }
6049 return true;
6050 }
6051 // Constraint Utils
6052 // ------------------------------------------------------------------------------------------------------------------------
6053 function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
6054 for (let constraint of constraints) {
6055 if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
6056 return false;
6057 }
6058 }
6059 return true;
6060 }
6061 function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
6062 otherEventStore, // for if constraint is an even group ID
6063 businessHoursUnexpanded, // for if constraint is 'businessHours'
6064 context) {
6065 if (constraint === 'businessHours') {
6066 return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
6067 }
6068 if (typeof constraint === 'string') { // an group ID
6069 return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
6070 }
6071 if (typeof constraint === 'object' && constraint) { // non-null object
6072 return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
6073 }
6074 return []; // if it's false
6075 }
6076 // TODO: move to event-store file?
6077 function eventStoreToRanges(eventStore) {
6078 let { instances } = eventStore;
6079 let ranges = [];
6080 for (let instanceId in instances) {
6081 ranges.push(instances[instanceId].range);
6082 }
6083 return ranges;
6084 }
6085 // TODO: move to geom file?
6086 function anyRangesContainRange(outerRanges, innerRange) {
6087 for (let outerRange of outerRanges) {
6088 if (rangeContainsRange(outerRange, innerRange)) {
6089 return true;
6090 }
6091 }
6092 return false;
6093 }
6094
6095 class JsonRequestError extends Error {
6096 constructor(message, response) {
6097 super(message);
6098 this.response = response;
6099 }
6100 }
6101 function requestJson(method, url, params) {
6102 method = method.toUpperCase();
6103 const fetchOptions = {
6104 method,
6105 };
6106 if (method === 'GET') {
6107 url += (url.indexOf('?') === -1 ? '?' : '&') +
6108 new URLSearchParams(params);
6109 }
6110 else {
6111 fetchOptions.body = new URLSearchParams(params);
6112 fetchOptions.headers = {
6113 'Content-Type': 'application/x-www-form-urlencoded',
6114 };
6115 }
6116 return fetch(url, fetchOptions).then((fetchRes) => {
6117 if (fetchRes.ok) {
6118 return fetchRes.json().then((parsedResponse) => {
6119 return [parsedResponse, fetchRes];
6120 }, () => {
6121 throw new JsonRequestError('Failure parsing JSON', fetchRes);
6122 });
6123 }
6124 else {
6125 throw new JsonRequestError('Request failed', fetchRes);
6126 }
6127 });
6128 }
6129
6130 class DelayedRunner {
6131 constructor(drainedOption) {
6132 this.drainedOption = drainedOption;
6133 this.isRunning = false;
6134 this.isDirty = false;
6135 this.pauseDepths = {};
6136 this.timeoutId = 0;
6137 }
6138 request(delay) {
6139 this.isDirty = true;
6140 if (!this.isPaused()) {
6141 this.clearTimeout();
6142 if (delay == null) {
6143 this.tryDrain();
6144 }
6145 else {
6146 this.timeoutId = setTimeout(// NOT OPTIMAL! TODO: look at debounce
6147 this.tryDrain.bind(this), delay);
6148 }
6149 }
6150 }
6151 pause(scope = '') {
6152 let { pauseDepths } = this;
6153 pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
6154 this.clearTimeout();
6155 }
6156 resume(scope = '', force) {
6157 let { pauseDepths } = this;
6158 if (scope in pauseDepths) {
6159 if (force) {
6160 delete pauseDepths[scope];
6161 }
6162 else {
6163 pauseDepths[scope] -= 1;
6164 let depth = pauseDepths[scope];
6165 if (depth <= 0) {
6166 delete pauseDepths[scope];
6167 }
6168 }
6169 this.tryDrain();
6170 }
6171 }
6172 isPaused() {
6173 return Object.keys(this.pauseDepths).length;
6174 }
6175 tryDrain() {
6176 if (!this.isRunning && !this.isPaused()) {
6177 this.isRunning = true;
6178 while (this.isDirty) {
6179 this.isDirty = false;
6180 this.drained(); // might set isDirty to true again
6181 }
6182 this.isRunning = false;
6183 }
6184 }
6185 clear() {
6186 this.clearTimeout();
6187 this.isDirty = false;
6188 this.pauseDepths = {};
6189 }
6190 clearTimeout() {
6191 if (this.timeoutId) {
6192 clearTimeout(this.timeoutId);
6193 this.timeoutId = 0;
6194 }
6195 }
6196 drained() {
6197 if (this.drainedOption) {
6198 this.drainedOption();
6199 }
6200 }
6201 }
6202
6203 const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
6204 class Scroller extends BaseComponent {
6205 constructor() {
6206 super(...arguments);
6207 this.handleEl = (el) => {
6208 this.el = el;
6209 setRef(this.props.elRef, el);
6210 };
6211 }
6212 render() {
6213 let { props } = this;
6214 let { liquid, liquidIsAbsolute } = props;
6215 let isAbsolute = liquid && liquidIsAbsolute;
6216 let className = ['fc-scroller'];
6217 if (liquid) {
6218 if (liquidIsAbsolute) {
6219 className.push('fc-scroller-liquid-absolute');
6220 }
6221 else {
6222 className.push('fc-scroller-liquid');
6223 }
6224 }
6225 return (y("div", { ref: this.handleEl, className: className.join(' '), style: {
6226 overflowX: props.overflowX,
6227 overflowY: props.overflowY,
6228 left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
6229 right: (isAbsolute && -(props.overcomeRight || 0)) || '',
6230 bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
6231 marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
6232 marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
6233 marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
6234 maxHeight: props.maxHeight || '',
6235 } }, props.children));
6236 }
6237 needsXScrolling() {
6238 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6239 return false;
6240 }
6241 // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
6242 // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6243 // inner-child margins and absolute positioning
6244 let { el } = this;
6245 let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
6246 let { children } = el;
6247 for (let i = 0; i < children.length; i += 1) {
6248 let childEl = children[i];
6249 if (childEl.getBoundingClientRect().width > realClientWidth) {
6250 return true;
6251 }
6252 }
6253 return false;
6254 }
6255 needsYScrolling() {
6256 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6257 return false;
6258 }
6259 // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
6260 // much more reliable to see if children are taller than the scroller, even tho doesn't account for
6261 // inner-child margins and absolute positioning
6262 let { el } = this;
6263 let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
6264 let { children } = el;
6265 for (let i = 0; i < children.length; i += 1) {
6266 let childEl = children[i];
6267 if (childEl.getBoundingClientRect().height > realClientHeight) {
6268 return true;
6269 }
6270 }
6271 return false;
6272 }
6273 getXScrollbarWidth() {
6274 if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
6275 return 0;
6276 }
6277 return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
6278 }
6279 getYScrollbarWidth() {
6280 if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
6281 return 0;
6282 }
6283 return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
6284 }
6285 }
6286
6287 /*
6288 TODO: somehow infer OtherArgs from masterCallback?
6289 TODO: infer RefType from masterCallback if provided
6290 */
6291 class RefMap {
6292 constructor(masterCallback) {
6293 this.masterCallback = masterCallback;
6294 this.currentMap = {};
6295 this.depths = {};
6296 this.callbackMap = {};
6297 this.handleValue = (val, key) => {
6298 let { depths, currentMap } = this;
6299 let removed = false;
6300 let added = false;
6301 if (val !== null) {
6302 // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
6303 removed = (key in currentMap);
6304 currentMap[key] = val;
6305 depths[key] = (depths[key] || 0) + 1;
6306 added = true;
6307 }
6308 else {
6309 depths[key] -= 1;
6310 if (!depths[key]) {
6311 delete currentMap[key];
6312 delete this.callbackMap[key];
6313 removed = true;
6314 }
6315 }
6316 if (this.masterCallback) {
6317 if (removed) {
6318 this.masterCallback(null, String(key));
6319 }
6320 if (added) {
6321 this.masterCallback(val, String(key));
6322 }
6323 }
6324 };
6325 }
6326 createRef(key) {
6327 let refCallback = this.callbackMap[key];
6328 if (!refCallback) {
6329 refCallback = this.callbackMap[key] = (val) => {
6330 this.handleValue(val, String(key));
6331 };
6332 }
6333 return refCallback;
6334 }
6335 // TODO: check callers that don't care about order. should use getAll instead
6336 // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
6337 // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
6338 collect(startIndex, endIndex, step) {
6339 return collectFromHash(this.currentMap, startIndex, endIndex, step);
6340 }
6341 getAll() {
6342 return hashValuesToArray(this.currentMap);
6343 }
6344 }
6345
6346 function computeShrinkWidth(chunkEls) {
6347 let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
6348 let largestWidth = 0;
6349 for (let shrinkCell of shrinkCells) {
6350 largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
6351 }
6352 return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
6353 }
6354 function getSectionHasLiquidHeight(props, sectionConfig) {
6355 return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
6356 }
6357 function getAllowYScrolling(props, sectionConfig) {
6358 return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
6359 getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
6360 }
6361 // TODO: ONLY use `arg`. force out internal function to use same API
6362 function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
6363 let { expandRows } = arg;
6364 let content = typeof chunkConfig.content === 'function' ?
6365 chunkConfig.content(arg) :
6366 y('table', {
6367 role: 'presentation',
6368 className: [
6369 chunkConfig.tableClassName,
6370 sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
6371 ].join(' '),
6372 style: {
6373 minWidth: arg.tableMinWidth,
6374 width: arg.clientWidth,
6375 height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
6376 },
6377 }, arg.tableColGroupNode, y(isHeader ? 'thead' : 'tbody', {
6378 role: 'presentation',
6379 }, typeof chunkConfig.rowContent === 'function'
6380 ? chunkConfig.rowContent(arg)
6381 : chunkConfig.rowContent));
6382 return content;
6383 }
6384 function isColPropsEqual(cols0, cols1) {
6385 return isArraysEqual(cols0, cols1, isPropsEqual);
6386 }
6387 function renderMicroColGroup(cols, shrinkWidth) {
6388 let colNodes = [];
6389 /*
6390 for ColProps with spans, it would have been great to make a single <col span="">
6391 HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
6392 SOLUTION: making individual <col> elements makes Chrome behave.
6393 */
6394 for (let colProps of cols) {
6395 let span = colProps.span || 1;
6396 for (let i = 0; i < span; i += 1) {
6397 colNodes.push(y("col", { style: {
6398 width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
6399 minWidth: colProps.minWidth || '',
6400 } }));
6401 }
6402 }
6403 return y('colgroup', {}, ...colNodes);
6404 }
6405 function sanitizeShrinkWidth(shrinkWidth) {
6406 /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
6407 4 accounts for 2 2-pixel borders. TODO: better solution? */
6408 return shrinkWidth == null ? 4 : shrinkWidth;
6409 }
6410 function hasShrinkWidth(cols) {
6411 for (let col of cols) {
6412 if (col.width === 'shrink') {
6413 return true;
6414 }
6415 }
6416 return false;
6417 }
6418 function getScrollGridClassNames(liquid, context) {
6419 let classNames = [
6420 'fc-scrollgrid',
6421 context.theme.getClass('table'),
6422 ];
6423 if (liquid) {
6424 classNames.push('fc-scrollgrid-liquid');
6425 }
6426 return classNames;
6427 }
6428 function getSectionClassNames(sectionConfig, wholeTableVGrow) {
6429 let classNames = [
6430 'fc-scrollgrid-section',
6431 `fc-scrollgrid-section-${sectionConfig.type}`,
6432 sectionConfig.className, // used?
6433 ];
6434 if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
6435 classNames.push('fc-scrollgrid-section-liquid');
6436 }
6437 if (sectionConfig.isSticky) {
6438 classNames.push('fc-scrollgrid-section-sticky');
6439 }
6440 return classNames;
6441 }
6442 function renderScrollShim(arg) {
6443 return (y("div", { className: "fc-scrollgrid-sticky-shim", style: {
6444 width: arg.clientWidth,
6445 minWidth: arg.tableMinWidth,
6446 } }));
6447 }
6448 function getStickyHeaderDates(options) {
6449 let { stickyHeaderDates } = options;
6450 if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
6451 stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
6452 }
6453 return stickyHeaderDates;
6454 }
6455 function getStickyFooterScrollbar(options) {
6456 let { stickyFooterScrollbar } = options;
6457 if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
6458 stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
6459 }
6460 return stickyFooterScrollbar;
6461 }
6462
6463 class SimpleScrollGrid extends BaseComponent {
6464 constructor() {
6465 super(...arguments);
6466 this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
6467 // yucky to memoize VNodes, but much more efficient for consumers
6468 this.renderMicroColGroup = memoize(renderMicroColGroup);
6469 this.scrollerRefs = new RefMap();
6470 this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
6471 this.state = {
6472 shrinkWidth: null,
6473 forceYScrollbars: false,
6474 scrollerClientWidths: {},
6475 scrollerClientHeights: {},
6476 };
6477 // TODO: can do a really simple print-view. dont need to join rows
6478 this.handleSizing = () => {
6479 this.safeSetState(Object.assign({ shrinkWidth: this.computeShrinkWidth() }, this.computeScrollerDims()));
6480 };
6481 }
6482 render() {
6483 let { props, state, context } = this;
6484 let sectionConfigs = props.sections || [];
6485 let cols = this.processCols(props.cols);
6486 let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
6487 let classNames = getScrollGridClassNames(props.liquid, context);
6488 if (props.collapsibleWidth) {
6489 classNames.push('fc-scrollgrid-collapsible');
6490 }
6491 // TODO: make DRY
6492 let configCnt = sectionConfigs.length;
6493 let configI = 0;
6494 let currentConfig;
6495 let headSectionNodes = [];
6496 let bodySectionNodes = [];
6497 let footSectionNodes = [];
6498 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
6499 headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6500 configI += 1;
6501 }
6502 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
6503 bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
6504 configI += 1;
6505 }
6506 while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
6507 footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
6508 configI += 1;
6509 }
6510 // firefox bug: when setting height on table and there is a thead or tfoot,
6511 // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
6512 // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
6513 // if so, use a simpler dom structure, jam everything into a lone tbody.
6514 let isBuggy = !getCanVGrowWithinCell();
6515 const roleAttrs = { role: 'rowgroup' };
6516 return y('table', {
6517 role: 'grid',
6518 className: classNames.join(' '),
6519 style: { height: props.height },
6520 }, Boolean(!isBuggy && headSectionNodes.length) && y('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && y('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && y('tfoot', roleAttrs, ...footSectionNodes), isBuggy && y('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
6521 }
6522 renderSection(sectionConfig, microColGroupNode, isHeader) {
6523 if ('outerContent' in sectionConfig) {
6524 return (y(_, { key: sectionConfig.key }, sectionConfig.outerContent));
6525 }
6526 return (y("tr", { key: sectionConfig.key, role: "presentation", className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
6527 }
6528 renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
6529 if ('outerContent' in chunkConfig) {
6530 return chunkConfig.outerContent;
6531 }
6532 let { props } = this;
6533 let { forceYScrollbars, scrollerClientWidths, scrollerClientHeights } = this.state;
6534 let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
6535 let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
6536 // for `!props.liquid` - is WHOLE scrollgrid natural height?
6537 // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
6538 let overflowY = !props.liquid ? 'visible' :
6539 forceYScrollbars ? 'scroll' :
6540 !needsYScrolling ? 'hidden' :
6541 'auto';
6542 let sectionKey = sectionConfig.key;
6543 let content = renderChunkContent(sectionConfig, chunkConfig, {
6544 tableColGroupNode: microColGroupNode,
6545 tableMinWidth: '',
6546 clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
6547 clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
6548 expandRows: sectionConfig.expandRows,
6549 syncRowHeights: false,
6550 rowSyncHeights: [],
6551 reportRowHeightChange: () => { },
6552 }, isHeader);
6553 return y(isHeader ? 'th' : 'td', {
6554 ref: chunkConfig.elRef,
6555 role: 'presentation',
6556 }, y("div", { className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}` },
6557 y(Scroller, { ref: this.scrollerRefs.createRef(sectionKey), elRef: this.scrollerElRefs.createRef(sectionKey), overflowY: overflowY, overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */, maxHeight: sectionConfig.maxHeight, liquid: isLiquid, liquidIsAbsolute // because its within a harness
6558 : true }, content)));
6559 }
6560 _handleScrollerEl(scrollerEl, key) {
6561 let section = getSectionByKey(this.props.sections, key);
6562 if (section) {
6563 setRef(section.chunk.scrollerElRef, scrollerEl);
6564 }
6565 }
6566 componentDidMount() {
6567 this.handleSizing();
6568 this.context.addResizeHandler(this.handleSizing);
6569 }
6570 componentDidUpdate() {
6571 // TODO: need better solution when state contains non-sizing things
6572 this.handleSizing();
6573 }
6574 componentWillUnmount() {
6575 this.context.removeResizeHandler(this.handleSizing);
6576 }
6577 computeShrinkWidth() {
6578 return hasShrinkWidth(this.props.cols)
6579 ? computeShrinkWidth(this.scrollerElRefs.getAll())
6580 : 0;
6581 }
6582 computeScrollerDims() {
6583 let scrollbarWidth = getScrollbarWidths();
6584 let { scrollerRefs, scrollerElRefs } = this;
6585 let forceYScrollbars = false;
6586 let scrollerClientWidths = {};
6587 let scrollerClientHeights = {};
6588 for (let sectionKey in scrollerRefs.currentMap) {
6589 let scroller = scrollerRefs.currentMap[sectionKey];
6590 if (scroller && scroller.needsYScrolling()) {
6591 forceYScrollbars = true;
6592 break;
6593 }
6594 }
6595 for (let section of this.props.sections) {
6596 let sectionKey = section.key;
6597 let scrollerEl = scrollerElRefs.currentMap[sectionKey];
6598 if (scrollerEl) {
6599 let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
6600 scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars
6601 ? scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
6602 : 0));
6603 scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
6604 }
6605 }
6606 return { forceYScrollbars, scrollerClientWidths, scrollerClientHeights };
6607 }
6608 }
6609 SimpleScrollGrid.addStateEquality({
6610 scrollerClientWidths: isPropsEqual,
6611 scrollerClientHeights: isPropsEqual,
6612 });
6613 function getSectionByKey(sections, key) {
6614 for (let section of sections) {
6615 if (section.key === key) {
6616 return section;
6617 }
6618 }
6619 return null;
6620 }
6621
6622 class EventContainer extends BaseComponent {
6623 constructor() {
6624 super(...arguments);
6625 this.handleEl = (el) => {
6626 this.el = el;
6627 if (el) {
6628 setElSeg(el, this.props.seg);
6629 }
6630 };
6631 }
6632 render() {
6633 const { props, context } = this;
6634 const { options } = context;
6635 const { seg } = props;
6636 const { eventRange } = seg;
6637 const { ui } = eventRange;
6638 const renderProps = {
6639 event: new EventImpl(context, eventRange.def, eventRange.instance),
6640 view: context.viewApi,
6641 timeText: props.timeText,
6642 textColor: ui.textColor,
6643 backgroundColor: ui.backgroundColor,
6644 borderColor: ui.borderColor,
6645 isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
6646 isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
6647 isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
6648 isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
6649 isStart: Boolean(seg.isStart),
6650 isEnd: Boolean(seg.isEnd),
6651 isPast: Boolean(props.isPast),
6652 isFuture: Boolean(props.isFuture),
6653 isToday: Boolean(props.isToday),
6654 isSelected: Boolean(props.isSelected),
6655 isDragging: Boolean(props.isDragging),
6656 isResizing: Boolean(props.isResizing),
6657 };
6658 return (y(ContentContainer, Object.assign({}, props /* contains children */, { elRef: this.handleEl, elClasses: [
6659 ...getEventClassNames(renderProps),
6660 ...seg.eventRange.ui.classNames,
6661 ...(props.elClasses || []),
6662 ], renderProps: renderProps, generatorName: "eventContent", customGenerator: options.eventContent, defaultGenerator: props.defaultGenerator, classNameGenerator: options.eventClassNames, didMount: options.eventDidMount, willUnmount: options.eventWillUnmount })));
6663 }
6664 componentDidUpdate(prevProps) {
6665 if (this.el && this.props.seg !== prevProps.seg) {
6666 setElSeg(this.el, this.props.seg);
6667 }
6668 }
6669 }
6670
6671 // should not be a purecomponent
6672 class StandardEvent extends BaseComponent {
6673 render() {
6674 let { props, context } = this;
6675 let { options } = context;
6676 let { seg } = props;
6677 let { ui } = seg.eventRange;
6678 let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
6679 let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
6680 return (y(EventContainer, Object.assign({}, props /* includes elRef */, { elTag: "a", elStyle: {
6681 borderColor: ui.borderColor,
6682 backgroundColor: ui.backgroundColor,
6683 }, elAttrs: getSegAnchorAttrs(seg, context), defaultGenerator: renderInnerContent$1, timeText: timeText }), (InnerContent, eventContentArg) => (y(_, null,
6684 y(InnerContent, { elTag: "div", elClasses: ['fc-event-main'], elStyle: { color: eventContentArg.textColor } }),
6685 Boolean(eventContentArg.isStartResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-start" })),
6686 Boolean(eventContentArg.isEndResizable) && (y("div", { className: "fc-event-resizer fc-event-resizer-end" }))))));
6687 }
6688 }
6689 function renderInnerContent$1(innerProps) {
6690 return (y("div", { className: "fc-event-main-frame" },
6691 innerProps.timeText && (y("div", { className: "fc-event-time" }, innerProps.timeText)),
6692 y("div", { className: "fc-event-title-container" },
6693 y("div", { className: "fc-event-title fc-sticky" }, innerProps.event.title || y(_, null, "\u00A0")))));
6694 }
6695
6696 const NowIndicatorContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
6697 let { options } = context;
6698 let renderProps = {
6699 isAxis: props.isAxis,
6700 date: context.dateEnv.toDate(props.date),
6701 view: context.viewApi,
6702 };
6703 return (y(ContentContainer, Object.assign({}, props /* includes children */, { elTag: props.elTag || 'div', renderProps: renderProps, generatorName: "nowIndicatorContent", customGenerator: options.nowIndicatorContent, classNameGenerator: options.nowIndicatorClassNames, didMount: options.nowIndicatorDidMount, willUnmount: options.nowIndicatorWillUnmount })));
6704 }));
6705
6706 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' });
6707 class DayCellContainer extends BaseComponent {
6708 constructor() {
6709 super(...arguments);
6710 this.refineRenderProps = memoizeObjArg(refineRenderProps);
6711 }
6712 render() {
6713 let { props, context } = this;
6714 let { options } = context;
6715 let renderProps = this.refineRenderProps({
6716 date: props.date,
6717 dateProfile: props.dateProfile,
6718 todayRange: props.todayRange,
6719 isMonthStart: props.isMonthStart || false,
6720 showDayNumber: props.showDayNumber,
6721 extraRenderProps: props.extraRenderProps,
6722 viewApi: context.viewApi,
6723 dateEnv: context.dateEnv,
6724 monthStartFormat: options.monthStartFormat,
6725 });
6726 return (y(ContentContainer, Object.assign({}, props /* includes children */, { elClasses: [
6727 ...getDayClassNames(renderProps, context.theme),
6728 ...(props.elClasses || []),
6729 ], elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : { 'data-date': formatDayString(props.date) })), renderProps: renderProps, generatorName: "dayCellContent", customGenerator: options.dayCellContent, defaultGenerator: props.defaultGenerator, classNameGenerator:
6730 // don't use custom classNames if disabled
6731 renderProps.isDisabled ? undefined : options.dayCellClassNames, didMount: options.dayCellDidMount, willUnmount: options.dayCellWillUnmount })));
6732 }
6733 }
6734 function hasCustomDayCellContent(options) {
6735 return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
6736 }
6737 function refineRenderProps(raw) {
6738 let { date, dateEnv, dateProfile, isMonthStart } = raw;
6739 let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
6740 let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
6741 return Object.assign(Object.assign(Object.assign({ date: dateEnv.toDate(date), view: raw.viewApi }, dayMeta), { isMonthStart,
6742 dayNumberText }), raw.extraRenderProps);
6743 }
6744
6745 class BgEvent extends BaseComponent {
6746 render() {
6747 let { props } = this;
6748 let { seg } = props;
6749 return (y(EventContainer, { elTag: "div", elClasses: ['fc-bg-event'], elStyle: { backgroundColor: seg.eventRange.ui.backgroundColor }, defaultGenerator: renderInnerContent, seg: seg, timeText: "", isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, isPast: props.isPast, isFuture: props.isFuture, isToday: props.isToday, disableDragging: true, disableResizing: true }));
6750 }
6751 }
6752 function renderInnerContent(props) {
6753 let { title } = props.event;
6754 return title && (y("div", { className: "fc-event-title" }, props.event.title));
6755 }
6756 function renderFill(fillType) {
6757 return (y("div", { className: `fc-${fillType}` }));
6758 }
6759
6760 const WeekNumberContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
6761 let { dateEnv, options } = context;
6762 let { date } = props;
6763 let format = options.weekNumberFormat || props.defaultFormat;
6764 let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
6765 let text = dateEnv.format(date, format);
6766 let renderProps = { num, text, date };
6767 return (y(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
6768 , Object.assign({}, props /* includes children */, { renderProps: renderProps, generatorName: "weekNumberContent", customGenerator: options.weekNumberContent, defaultGenerator: renderInner, classNameGenerator: options.weekNumberClassNames, didMount: options.weekNumberDidMount, willUnmount: options.weekNumberWillUnmount })));
6769 }));
6770 function renderInner(innerProps) {
6771 return innerProps.text;
6772 }
6773
6774 const PADDING_FROM_VIEWPORT = 10;
6775 class Popover extends BaseComponent {
6776 constructor() {
6777 super(...arguments);
6778 this.state = {
6779 titleId: getUniqueDomId(),
6780 };
6781 this.handleRootEl = (el) => {
6782 this.rootEl = el;
6783 if (this.props.elRef) {
6784 setRef(this.props.elRef, el);
6785 }
6786 };
6787 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
6788 this.handleDocumentMouseDown = (ev) => {
6789 // only hide the popover if the click happened outside the popover
6790 const target = getEventTargetViaRoot(ev);
6791 if (!this.rootEl.contains(target)) {
6792 this.handleCloseClick();
6793 }
6794 };
6795 this.handleDocumentKeyDown = (ev) => {
6796 if (ev.key === 'Escape') {
6797 this.handleCloseClick();
6798 }
6799 };
6800 this.handleCloseClick = () => {
6801 let { onClose } = this.props;
6802 if (onClose) {
6803 onClose();
6804 }
6805 };
6806 }
6807 render() {
6808 let { theme, options } = this.context;
6809 let { props, state } = this;
6810 let classNames = [
6811 'fc-popover',
6812 theme.getClass('popover'),
6813 ].concat(props.extraClassNames || []);
6814 return j(y("div", Object.assign({}, props.extraAttrs, { id: props.id, className: classNames.join(' '), "aria-labelledby": state.titleId, ref: this.handleRootEl }),
6815 y("div", { className: 'fc-popover-header ' + theme.getClass('popoverHeader') },
6816 y("span", { className: "fc-popover-title", id: state.titleId }, props.title),
6817 y("span", { className: 'fc-popover-close ' + theme.getIconClass('close'), title: options.closeHint, onClick: this.handleCloseClick })),
6818 y("div", { className: 'fc-popover-body ' + theme.getClass('popoverContent') }, props.children)), props.parentEl);
6819 }
6820 componentDidMount() {
6821 document.addEventListener('mousedown', this.handleDocumentMouseDown);
6822 document.addEventListener('keydown', this.handleDocumentKeyDown);
6823 this.updateSize();
6824 }
6825 componentWillUnmount() {
6826 document.removeEventListener('mousedown', this.handleDocumentMouseDown);
6827 document.removeEventListener('keydown', this.handleDocumentKeyDown);
6828 }
6829 updateSize() {
6830 let { isRtl } = this.context;
6831 let { alignmentEl, alignGridTop } = this.props;
6832 let { rootEl } = this;
6833 let alignmentRect = computeClippedClientRect(alignmentEl);
6834 if (alignmentRect) {
6835 let popoverDims = rootEl.getBoundingClientRect();
6836 // position relative to viewport
6837 let popoverTop = alignGridTop
6838 ? elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top
6839 : alignmentRect.top;
6840 let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
6841 // constrain
6842 popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
6843 popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
6844 popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
6845 let origin = rootEl.offsetParent.getBoundingClientRect();
6846 applyStyle(rootEl, {
6847 top: popoverTop - origin.top,
6848 left: popoverLeft - origin.left,
6849 });
6850 }
6851 }
6852 }
6853
6854 class MorePopover extends DateComponent {
6855 constructor() {
6856 super(...arguments);
6857 this.handleRootEl = (rootEl) => {
6858 this.rootEl = rootEl;
6859 if (rootEl) {
6860 this.context.registerInteractiveComponent(this, {
6861 el: rootEl,
6862 useEventCenter: false,
6863 });
6864 }
6865 else {
6866 this.context.unregisterInteractiveComponent(this);
6867 }
6868 };
6869 }
6870 render() {
6871 let { options, dateEnv } = this.context;
6872 let { props } = this;
6873 let { startDate, todayRange, dateProfile } = props;
6874 let title = dateEnv.format(startDate, options.dayPopoverFormat);
6875 return (y(DayCellContainer, { elRef: this.handleRootEl, date: startDate, dateProfile: dateProfile, todayRange: todayRange }, (InnerContent, renderProps, elAttrs) => (y(Popover, { elRef: elAttrs.ref, id: props.id, title: title, extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []), extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */, parentEl: props.parentEl, alignmentEl: props.alignmentEl, alignGridTop: props.alignGridTop, onClose: props.onClose },
6876 hasCustomDayCellContent(options) && (y(InnerContent, { elTag: "div", elClasses: ['fc-more-popover-misc'] })),
6877 props.children))));
6878 }
6879 queryHit(positionLeft, positionTop, elWidth, elHeight) {
6880 let { rootEl, props } = this;
6881 if (positionLeft >= 0 && positionLeft < elWidth &&
6882 positionTop >= 0 && positionTop < elHeight) {
6883 return {
6884 dateProfile: props.dateProfile,
6885 dateSpan: Object.assign({ allDay: !props.forceTimed, range: {
6886 start: props.startDate,
6887 end: props.endDate,
6888 } }, props.extraDateSpan),
6889 dayEl: rootEl,
6890 rect: {
6891 left: 0,
6892 top: 0,
6893 right: elWidth,
6894 bottom: elHeight,
6895 },
6896 layer: 1, // important when comparing with hits from other components
6897 };
6898 }
6899 return null;
6900 }
6901 }
6902
6903 class MoreLinkContainer extends BaseComponent {
6904 constructor() {
6905 super(...arguments);
6906 this.state = {
6907 isPopoverOpen: false,
6908 popoverId: getUniqueDomId(),
6909 };
6910 this.handleLinkEl = (linkEl) => {
6911 this.linkEl = linkEl;
6912 if (this.props.elRef) {
6913 setRef(this.props.elRef, linkEl);
6914 }
6915 };
6916 this.handleClick = (ev) => {
6917 let { props, context } = this;
6918 let { moreLinkClick } = context.options;
6919 let date = computeRange(props).start;
6920 function buildPublicSeg(seg) {
6921 let { def, instance, range } = seg.eventRange;
6922 return {
6923 event: new EventImpl(context, def, instance),
6924 start: context.dateEnv.toDate(range.start),
6925 end: context.dateEnv.toDate(range.end),
6926 isStart: seg.isStart,
6927 isEnd: seg.isEnd,
6928 };
6929 }
6930 if (typeof moreLinkClick === 'function') {
6931 moreLinkClick = moreLinkClick({
6932 date,
6933 allDay: Boolean(props.allDayDate),
6934 allSegs: props.allSegs.map(buildPublicSeg),
6935 hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
6936 jsEvent: ev,
6937 view: context.viewApi,
6938 });
6939 }
6940 if (!moreLinkClick || moreLinkClick === 'popover') {
6941 this.setState({ isPopoverOpen: true });
6942 }
6943 else if (typeof moreLinkClick === 'string') { // a view name
6944 context.calendarApi.zoomTo(date, moreLinkClick);
6945 }
6946 };
6947 this.handlePopoverClose = () => {
6948 this.setState({ isPopoverOpen: false });
6949 };
6950 }
6951 render() {
6952 let { props, state } = this;
6953 return (y(ViewContextType.Consumer, null, (context) => {
6954 let { viewApi, options, calendarApi } = context;
6955 let { moreLinkText } = options;
6956 let { moreCnt } = props;
6957 let range = computeRange(props);
6958 let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
6959 ? moreLinkText.call(calendarApi, moreCnt)
6960 : `+${moreCnt} ${moreLinkText}`;
6961 let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
6962 let renderProps = {
6963 num: moreCnt,
6964 shortText: `+${moreCnt}`,
6965 text,
6966 view: viewApi,
6967 };
6968 return (y(_, null,
6969 Boolean(props.moreCnt) && (y(ContentContainer, { elTag: props.elTag || 'a', elRef: this.handleLinkEl, elClasses: [
6970 ...(props.elClasses || []),
6971 'fc-more-link',
6972 ], elStyle: props.elStyle, elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), { title: hint, 'aria-expanded': state.isPopoverOpen, 'aria-controls': state.isPopoverOpen ? state.popoverId : '' }), renderProps: renderProps, generatorName: "moreLinkContent", customGenerator: options.moreLinkContent, defaultGenerator: props.defaultGenerator || renderMoreLinkInner, classNameGenerator: options.moreLinkClassNames, didMount: options.moreLinkDidMount, willUnmount: options.moreLinkWillUnmount }, props.children)),
6973 state.isPopoverOpen && (y(MorePopover, { id: state.popoverId, startDate: range.start, endDate: range.end, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: props.extraDateSpan, parentEl: this.parentEl, alignmentEl: props.alignmentElRef ?
6974 props.alignmentElRef.current :
6975 this.linkEl, alignGridTop: props.alignGridTop, forceTimed: props.forceTimed, onClose: this.handlePopoverClose }, props.popoverContent()))));
6976 }));
6977 }
6978 componentDidMount() {
6979 this.updateParentEl();
6980 }
6981 componentDidUpdate() {
6982 this.updateParentEl();
6983 }
6984 updateParentEl() {
6985 if (this.linkEl) {
6986 this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');
6987 }
6988 }
6989 }
6990 function renderMoreLinkInner(props) {
6991 return props.text;
6992 }
6993 function computeRange(props) {
6994 if (props.allDayDate) {
6995 return {
6996 start: props.allDayDate,
6997 end: addDays(props.allDayDate, 1),
6998 };
6999 }
7000 let { hiddenSegs } = props;
7001 return {
7002 start: computeEarliestSegStart(hiddenSegs),
7003 end: computeLatestSegEnd(hiddenSegs),
7004 };
7005 }
7006 function computeEarliestSegStart(segs) {
7007 return segs.reduce(pickEarliestStart).eventRange.range.start;
7008 }
7009 function pickEarliestStart(seg0, seg1) {
7010 return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
7011 }
7012 function computeLatestSegEnd(segs) {
7013 return segs.reduce(pickLatestEnd).eventRange.range.end;
7014 }
7015 function pickLatestEnd(seg0, seg1) {
7016 return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
7017 }
7018
7019 class ViewContainer extends BaseComponent {
7020 render() {
7021 let { props, context } = this;
7022 let { options } = context;
7023 let renderProps = { view: context.viewApi };
7024 return (y(ContentContainer, Object.assign({}, props, { elTag: props.elTag || 'div', elClasses: [
7025 ...buildViewClassNames(props.viewSpec),
7026 ...(props.elClasses || []),
7027 ], renderProps: renderProps, classNameGenerator: options.viewClassNames, generatorName: undefined, didMount: options.viewDidMount, willUnmount: options.viewWillUnmount }), () => props.children));
7028 }
7029 }
7030 function buildViewClassNames(viewSpec) {
7031 return [
7032 `fc-${viewSpec.type}-view`,
7033 'fc-view',
7034 ];
7035 }
7036
7037 const EVENT_SOURCE_REFINERS = {
7038 id: String,
7039 defaultAllDay: Boolean,
7040 url: String,
7041 format: String,
7042 events: identity,
7043 eventDataTransform: identity,
7044 // for any network-related sources
7045 success: identity,
7046 failure: identity,
7047 };
7048 function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
7049 let rawObj;
7050 if (typeof raw === 'string') {
7051 rawObj = { url: raw };
7052 }
7053 else if (typeof raw === 'function' || Array.isArray(raw)) {
7054 rawObj = { events: raw };
7055 }
7056 else if (typeof raw === 'object' && raw) { // not null
7057 rawObj = raw;
7058 }
7059 if (rawObj) {
7060 let { refined, extra } = refineProps(rawObj, refiners);
7061 let metaRes = buildEventSourceMeta(refined, context);
7062 if (metaRes) {
7063 return {
7064 _raw: raw,
7065 isFetching: false,
7066 latestFetchId: '',
7067 fetchRange: null,
7068 defaultAllDay: refined.defaultAllDay,
7069 eventDataTransform: refined.eventDataTransform,
7070 success: refined.success,
7071 failure: refined.failure,
7072 publicId: refined.id || '',
7073 sourceId: guid(),
7074 sourceDefId: metaRes.sourceDefId,
7075 meta: metaRes.meta,
7076 ui: createEventUi(refined, context),
7077 extendedProps: extra,
7078 };
7079 }
7080 }
7081 return null;
7082 }
7083 function buildEventSourceRefiners(context) {
7084 return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
7085 }
7086 function buildEventSourceMeta(raw, context) {
7087 let defs = context.pluginHooks.eventSourceDefs;
7088 for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
7089 let def = defs[i];
7090 let meta = def.parseMeta(raw);
7091 if (meta) {
7092 return { sourceDefId: i, meta };
7093 }
7094 }
7095 return null;
7096 }
7097
7098 class CalendarImpl {
7099 getCurrentData() {
7100 return this.currentDataManager.getCurrentData();
7101 }
7102 dispatch(action) {
7103 this.currentDataManager.dispatch(action);
7104 }
7105 get view() { return this.getCurrentData().viewApi; }
7106 batchRendering(callback) {
7107 callback();
7108 }
7109 updateSize() {
7110 this.trigger('_resize', true);
7111 }
7112 // Options
7113 // -----------------------------------------------------------------------------------------------------------------
7114 setOption(name, val) {
7115 this.dispatch({
7116 type: 'SET_OPTION',
7117 optionName: name,
7118 rawOptionValue: val,
7119 });
7120 }
7121 getOption(name) {
7122 return this.currentDataManager.currentCalendarOptionsInput[name];
7123 }
7124 getAvailableLocaleCodes() {
7125 return Object.keys(this.getCurrentData().availableRawLocales);
7126 }
7127 // Trigger
7128 // -----------------------------------------------------------------------------------------------------------------
7129 on(handlerName, handler) {
7130 let { currentDataManager } = this;
7131 if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
7132 currentDataManager.emitter.on(handlerName, handler);
7133 }
7134 else {
7135 console.warn(`Unknown listener name '${handlerName}'`);
7136 }
7137 }
7138 off(handlerName, handler) {
7139 this.currentDataManager.emitter.off(handlerName, handler);
7140 }
7141 // not meant for public use
7142 trigger(handlerName, ...args) {
7143 this.currentDataManager.emitter.trigger(handlerName, ...args);
7144 }
7145 // View
7146 // -----------------------------------------------------------------------------------------------------------------
7147 changeView(viewType, dateOrRange) {
7148 this.batchRendering(() => {
7149 this.unselect();
7150 if (dateOrRange) {
7151 if (dateOrRange.start && dateOrRange.end) { // a range
7152 this.dispatch({
7153 type: 'CHANGE_VIEW_TYPE',
7154 viewType,
7155 });
7156 this.dispatch({
7157 type: 'SET_OPTION',
7158 optionName: 'visibleRange',
7159 rawOptionValue: dateOrRange,
7160 });
7161 }
7162 else {
7163 let { dateEnv } = this.getCurrentData();
7164 this.dispatch({
7165 type: 'CHANGE_VIEW_TYPE',
7166 viewType,
7167 dateMarker: dateEnv.createMarker(dateOrRange),
7168 });
7169 }
7170 }
7171 else {
7172 this.dispatch({
7173 type: 'CHANGE_VIEW_TYPE',
7174 viewType,
7175 });
7176 }
7177 });
7178 }
7179 // Forces navigation to a view for the given date.
7180 // `viewType` can be a specific view name or a generic one like "week" or "day".
7181 // needs to change
7182 zoomTo(dateMarker, viewType) {
7183 let state = this.getCurrentData();
7184 let spec;
7185 viewType = viewType || 'day'; // day is default zoom
7186 spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
7187 this.unselect();
7188 if (spec) {
7189 this.dispatch({
7190 type: 'CHANGE_VIEW_TYPE',
7191 viewType: spec.type,
7192 dateMarker,
7193 });
7194 }
7195 else {
7196 this.dispatch({
7197 type: 'CHANGE_DATE',
7198 dateMarker,
7199 });
7200 }
7201 }
7202 // Given a duration singular unit, like "week" or "day", finds a matching view spec.
7203 // Preference is given to views that have corresponding buttons.
7204 getUnitViewSpec(unit) {
7205 let { viewSpecs, toolbarConfig } = this.getCurrentData();
7206 let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
7207 let i;
7208 let spec;
7209 for (let viewType in viewSpecs) {
7210 viewTypes.push(viewType);
7211 }
7212 for (i = 0; i < viewTypes.length; i += 1) {
7213 spec = viewSpecs[viewTypes[i]];
7214 if (spec) {
7215 if (spec.singleUnit === unit) {
7216 return spec;
7217 }
7218 }
7219 }
7220 return null;
7221 }
7222 // Current Date
7223 // -----------------------------------------------------------------------------------------------------------------
7224 prev() {
7225 this.unselect();
7226 this.dispatch({ type: 'PREV' });
7227 }
7228 next() {
7229 this.unselect();
7230 this.dispatch({ type: 'NEXT' });
7231 }
7232 prevYear() {
7233 let state = this.getCurrentData();
7234 this.unselect();
7235 this.dispatch({
7236 type: 'CHANGE_DATE',
7237 dateMarker: state.dateEnv.addYears(state.currentDate, -1),
7238 });
7239 }
7240 nextYear() {
7241 let state = this.getCurrentData();
7242 this.unselect();
7243 this.dispatch({
7244 type: 'CHANGE_DATE',
7245 dateMarker: state.dateEnv.addYears(state.currentDate, 1),
7246 });
7247 }
7248 today() {
7249 let state = this.getCurrentData();
7250 this.unselect();
7251 this.dispatch({
7252 type: 'CHANGE_DATE',
7253 dateMarker: state.nowManager.getDateMarker(),
7254 });
7255 }
7256 gotoDate(zonedDateInput) {
7257 let state = this.getCurrentData();
7258 this.unselect();
7259 this.dispatch({
7260 type: 'CHANGE_DATE',
7261 dateMarker: state.dateEnv.createMarker(zonedDateInput),
7262 });
7263 }
7264 incrementDate(deltaInput) {
7265 let state = this.getCurrentData();
7266 let delta = createDuration(deltaInput);
7267 if (delta) { // else, warn about invalid input?
7268 this.unselect();
7269 this.dispatch({
7270 type: 'CHANGE_DATE',
7271 dateMarker: state.dateEnv.add(state.currentDate, delta),
7272 });
7273 }
7274 }
7275 getDate() {
7276 let state = this.getCurrentData();
7277 return state.dateEnv.toDate(state.currentDate);
7278 }
7279 // Date Formatting Utils
7280 // -----------------------------------------------------------------------------------------------------------------
7281 formatDate(d, formatter) {
7282 let { dateEnv } = this.getCurrentData();
7283 return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
7284 }
7285 // `settings` is for formatter AND isEndExclusive
7286 formatRange(d0, d1, settings) {
7287 let { dateEnv } = this.getCurrentData();
7288 return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
7289 }
7290 formatIso(d, omitTime) {
7291 let { dateEnv } = this.getCurrentData();
7292 return dateEnv.formatIso(dateEnv.createMarker(d), { omitTime });
7293 }
7294 // Date Selection / Event Selection / DayClick
7295 // -----------------------------------------------------------------------------------------------------------------
7296 select(dateOrObj, endDate) {
7297 let selectionInput;
7298 if (endDate == null) {
7299 if (dateOrObj.start != null) {
7300 selectionInput = dateOrObj;
7301 }
7302 else {
7303 selectionInput = {
7304 start: dateOrObj,
7305 end: null,
7306 };
7307 }
7308 }
7309 else {
7310 selectionInput = {
7311 start: dateOrObj,
7312 end: endDate,
7313 };
7314 }
7315 let state = this.getCurrentData();
7316 let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({ days: 1 }));
7317 if (selection) { // throw parse error otherwise?
7318 this.dispatch({ type: 'SELECT_DATES', selection });
7319 triggerDateSelect(selection, null, state);
7320 }
7321 }
7322 unselect(pev) {
7323 let state = this.getCurrentData();
7324 if (state.dateSelection) {
7325 this.dispatch({ type: 'UNSELECT_DATES' });
7326 triggerDateUnselect(pev, state);
7327 }
7328 }
7329 // Public Events API
7330 // -----------------------------------------------------------------------------------------------------------------
7331 addEvent(eventInput, sourceInput) {
7332 if (eventInput instanceof EventImpl) {
7333 let def = eventInput._def;
7334 let instance = eventInput._instance;
7335 let currentData = this.getCurrentData();
7336 // not already present? don't want to add an old snapshot
7337 if (!currentData.eventStore.defs[def.defId]) {
7338 this.dispatch({
7339 type: 'ADD_EVENTS',
7340 eventStore: eventTupleToStore({ def, instance }), // TODO: better util for two args?
7341 });
7342 this.triggerEventAdd(eventInput);
7343 }
7344 return eventInput;
7345 }
7346 let state = this.getCurrentData();
7347 let eventSource;
7348 if (sourceInput instanceof EventSourceImpl) {
7349 eventSource = sourceInput.internalEventSource;
7350 }
7351 else if (typeof sourceInput === 'boolean') {
7352 if (sourceInput) { // true. part of the first event source
7353 [eventSource] = hashValuesToArray(state.eventSources);
7354 }
7355 }
7356 else if (sourceInput != null) { // an ID. accepts a number too
7357 let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
7358 if (!sourceApi) {
7359 console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
7360 return null;
7361 }
7362 eventSource = sourceApi.internalEventSource;
7363 }
7364 let tuple = parseEvent(eventInput, eventSource, state, false);
7365 if (tuple) {
7366 let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
7367 this.dispatch({
7368 type: 'ADD_EVENTS',
7369 eventStore: eventTupleToStore(tuple),
7370 });
7371 this.triggerEventAdd(newEventApi);
7372 return newEventApi;
7373 }
7374 return null;
7375 }
7376 triggerEventAdd(eventApi) {
7377 let { emitter } = this.getCurrentData();
7378 emitter.trigger('eventAdd', {
7379 event: eventApi,
7380 relatedEvents: [],
7381 revert: () => {
7382 this.dispatch({
7383 type: 'REMOVE_EVENTS',
7384 eventStore: eventApiToStore(eventApi),
7385 });
7386 },
7387 });
7388 }
7389 // TODO: optimize
7390 getEventById(id) {
7391 let state = this.getCurrentData();
7392 let { defs, instances } = state.eventStore;
7393 id = String(id);
7394 for (let defId in defs) {
7395 let def = defs[defId];
7396 if (def.publicId === id) {
7397 if (def.recurringDef) {
7398 return new EventImpl(state, def, null);
7399 }
7400 for (let instanceId in instances) {
7401 let instance = instances[instanceId];
7402 if (instance.defId === def.defId) {
7403 return new EventImpl(state, def, instance);
7404 }
7405 }
7406 }
7407 }
7408 return null;
7409 }
7410 getEvents() {
7411 let currentData = this.getCurrentData();
7412 return buildEventApis(currentData.eventStore, currentData);
7413 }
7414 removeAllEvents() {
7415 this.dispatch({ type: 'REMOVE_ALL_EVENTS' });
7416 }
7417 // Public Event Sources API
7418 // -----------------------------------------------------------------------------------------------------------------
7419 getEventSources() {
7420 let state = this.getCurrentData();
7421 let sourceHash = state.eventSources;
7422 let sourceApis = [];
7423 for (let internalId in sourceHash) {
7424 sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
7425 }
7426 return sourceApis;
7427 }
7428 getEventSourceById(id) {
7429 let state = this.getCurrentData();
7430 let sourceHash = state.eventSources;
7431 id = String(id);
7432 for (let sourceId in sourceHash) {
7433 if (sourceHash[sourceId].publicId === id) {
7434 return new EventSourceImpl(state, sourceHash[sourceId]);
7435 }
7436 }
7437 return null;
7438 }
7439 addEventSource(sourceInput) {
7440 let state = this.getCurrentData();
7441 if (sourceInput instanceof EventSourceImpl) {
7442 // not already present? don't want to add an old snapshot
7443 if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
7444 this.dispatch({
7445 type: 'ADD_EVENT_SOURCES',
7446 sources: [sourceInput.internalEventSource],
7447 });
7448 }
7449 return sourceInput;
7450 }
7451 let eventSource = parseEventSource(sourceInput, state);
7452 if (eventSource) { // TODO: error otherwise?
7453 this.dispatch({ type: 'ADD_EVENT_SOURCES', sources: [eventSource] });
7454 return new EventSourceImpl(state, eventSource);
7455 }
7456 return null;
7457 }
7458 removeAllEventSources() {
7459 this.dispatch({ type: 'REMOVE_ALL_EVENT_SOURCES' });
7460 }
7461 refetchEvents() {
7462 this.dispatch({ type: 'FETCH_EVENT_SOURCES', isRefetch: true });
7463 }
7464 // Scroll
7465 // -----------------------------------------------------------------------------------------------------------------
7466 scrollToTime(timeInput) {
7467 let time = createDuration(timeInput);
7468 if (time) {
7469 this.trigger('_scrollRequest', { time });
7470 }
7471 }
7472 }
7473
7474 class Store {
7475 constructor() {
7476 this.handlers = [];
7477 }
7478 set(value) {
7479 this.currentValue = value;
7480 for (let handler of this.handlers) {
7481 handler(value);
7482 }
7483 }
7484 subscribe(handler) {
7485 this.handlers.push(handler);
7486 if (this.currentValue !== undefined) {
7487 handler(this.currentValue);
7488 }
7489 }
7490 }
7491
7492 /*
7493 Subscribers will get a LIST of CustomRenderings
7494 */
7495 class CustomRenderingStore extends Store {
7496 constructor() {
7497 super(...arguments);
7498 this.map = new Map();
7499 }
7500 // for consistent order
7501 handle(customRendering) {
7502 const { map } = this;
7503 let updated = false;
7504 if (customRendering.isActive) {
7505 map.set(customRendering.id, customRendering);
7506 updated = true;
7507 }
7508 else if (map.has(customRendering.id)) {
7509 map.delete(customRendering.id);
7510 updated = true;
7511 }
7512 if (updated) {
7513 this.set(map);
7514 }
7515 }
7516 }
7517
7518 var internal = {
7519 __proto__: null,
7520 BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
7521 identity: identity,
7522 refineProps: refineProps,
7523 createEventInstance: createEventInstance,
7524 parseEventDef: parseEventDef,
7525 refineEventDef: refineEventDef,
7526 parseBusinessHours: parseBusinessHours,
7527 padStart: padStart,
7528 isInt: isInt,
7529 parseFieldSpecs: parseFieldSpecs,
7530 compareByFieldSpecs: compareByFieldSpecs,
7531 flexibleCompare: flexibleCompare,
7532 preventSelection: preventSelection,
7533 allowSelection: allowSelection,
7534 preventContextMenu: preventContextMenu,
7535 allowContextMenu: allowContextMenu,
7536 compareNumbers: compareNumbers,
7537 enableCursor: enableCursor,
7538 disableCursor: disableCursor,
7539 guid: guid,
7540 computeVisibleDayRange: computeVisibleDayRange,
7541 isMultiDayRange: isMultiDayRange,
7542 diffDates: diffDates,
7543 removeExact: removeExact,
7544 isArraysEqual: isArraysEqual,
7545 memoize: memoize,
7546 memoizeObjArg: memoizeObjArg,
7547 memoizeArraylike: memoizeArraylike,
7548 memoizeHashlike: memoizeHashlike,
7549 intersectRects: intersectRects,
7550 pointInsideRect: pointInsideRect,
7551 constrainPoint: constrainPoint,
7552 getRectCenter: getRectCenter,
7553 diffPoints: diffPoints,
7554 translateRect: translateRect,
7555 mapHash: mapHash,
7556 filterHash: filterHash,
7557 isPropsEqual: isPropsEqual,
7558 compareObjs: compareObjs,
7559 collectFromHash: collectFromHash,
7560 findElements: findElements,
7561 findDirectChildren: findDirectChildren,
7562 removeElement: removeElement,
7563 applyStyle: applyStyle,
7564 elementMatches: elementMatches,
7565 elementClosest: elementClosest,
7566 getEventTargetViaRoot: getEventTargetViaRoot,
7567 getUniqueDomId: getUniqueDomId,
7568 parseClassNames: parseClassNames,
7569 getCanVGrowWithinCell: getCanVGrowWithinCell,
7570 createEmptyEventStore: createEmptyEventStore,
7571 mergeEventStores: mergeEventStores,
7572 getRelevantEvents: getRelevantEvents,
7573 eventTupleToStore: eventTupleToStore,
7574 combineEventUis: combineEventUis,
7575 createEventUi: createEventUi,
7576 Splitter: Splitter,
7577 getDayClassNames: getDayClassNames,
7578 getDateMeta: getDateMeta,
7579 getSlotClassNames: getSlotClassNames,
7580 buildNavLinkAttrs: buildNavLinkAttrs,
7581 preventDefault: preventDefault,
7582 whenTransitionDone: whenTransitionDone,
7583 computeInnerRect: computeInnerRect,
7584 computeEdges: computeEdges,
7585 getClippingParents: getClippingParents,
7586 computeRect: computeRect,
7587 unpromisify: unpromisify,
7588 Emitter: Emitter,
7589 rangeContainsMarker: rangeContainsMarker,
7590 intersectRanges: intersectRanges,
7591 rangesEqual: rangesEqual,
7592 rangesIntersect: rangesIntersect,
7593 rangeContainsRange: rangeContainsRange,
7594 PositionCache: PositionCache,
7595 ScrollController: ScrollController,
7596 ElementScrollController: ElementScrollController,
7597 WindowScrollController: WindowScrollController,
7598 Theme: Theme,
7599 ViewContextType: ViewContextType,
7600 DateComponent: DateComponent,
7601 DateProfileGenerator: DateProfileGenerator,
7602 isDateSpansEqual: isDateSpansEqual,
7603 addDays: addDays,
7604 startOfDay: startOfDay,
7605 addMs: addMs,
7606 addWeeks: addWeeks,
7607 diffWeeks: diffWeeks,
7608 diffWholeWeeks: diffWholeWeeks,
7609 diffWholeDays: diffWholeDays,
7610 diffDayAndTime: diffDayAndTime,
7611 diffDays: diffDays,
7612 isValidDate: isValidDate,
7613 createDuration: createDuration,
7614 asCleanDays: asCleanDays,
7615 multiplyDuration: multiplyDuration,
7616 addDurations: addDurations,
7617 asRoughMinutes: asRoughMinutes,
7618 asRoughSeconds: asRoughSeconds,
7619 asRoughMs: asRoughMs,
7620 wholeDivideDurations: wholeDivideDurations,
7621 greatestDurationDenominator: greatestDurationDenominator,
7622 DateEnv: DateEnv,
7623 createFormatter: createFormatter,
7624 formatIsoTimeString: formatIsoTimeString,
7625 formatDayString: formatDayString,
7626 buildIsoString: buildIsoString,
7627 formatIsoMonthStr: formatIsoMonthStr,
7628 NamedTimeZoneImpl: NamedTimeZoneImpl,
7629 parseMarker: parse,
7630 SegHierarchy: SegHierarchy,
7631 buildEntryKey: buildEntryKey,
7632 getEntrySpanEnd: getEntrySpanEnd,
7633 binarySearch: binarySearch,
7634 groupIntersectingEntries: groupIntersectingEntries,
7635 intersectSpans: intersectSpans,
7636 Interaction: Interaction,
7637 interactionSettingsToStore: interactionSettingsToStore,
7638 interactionSettingsStore: interactionSettingsStore,
7639 ElementDragging: ElementDragging,
7640 config: config,
7641 parseDragMeta: parseDragMeta,
7642 CalendarRoot: CalendarRoot,
7643 DayHeader: DayHeader,
7644 computeFallbackHeaderFormat: computeFallbackHeaderFormat,
7645 TableDateCell: TableDateCell,
7646 TableDowCell: TableDowCell,
7647 DaySeriesModel: DaySeriesModel,
7648 sliceEventStore: sliceEventStore,
7649 hasBgRendering: hasBgRendering,
7650 getElSeg: getElSeg,
7651 buildSegTimeText: buildSegTimeText,
7652 sortEventSegs: sortEventSegs,
7653 getSegMeta: getSegMeta,
7654 buildEventRangeKey: buildEventRangeKey,
7655 getSegAnchorAttrs: getSegAnchorAttrs,
7656 DayTableModel: DayTableModel,
7657 Slicer: Slicer,
7658 applyMutationToEventStore: applyMutationToEventStore,
7659 isPropsValid: isPropsValid,
7660 isInteractionValid: isInteractionValid,
7661 isDateSelectionValid: isDateSelectionValid,
7662 requestJson: requestJson,
7663 BaseComponent: BaseComponent,
7664 setRef: setRef,
7665 DelayedRunner: DelayedRunner,
7666 SimpleScrollGrid: SimpleScrollGrid,
7667 hasShrinkWidth: hasShrinkWidth,
7668 renderMicroColGroup: renderMicroColGroup,
7669 getScrollGridClassNames: getScrollGridClassNames,
7670 getSectionClassNames: getSectionClassNames,
7671 getSectionHasLiquidHeight: getSectionHasLiquidHeight,
7672 getAllowYScrolling: getAllowYScrolling,
7673 renderChunkContent: renderChunkContent,
7674 computeShrinkWidth: computeShrinkWidth,
7675 sanitizeShrinkWidth: sanitizeShrinkWidth,
7676 isColPropsEqual: isColPropsEqual,
7677 renderScrollShim: renderScrollShim,
7678 getStickyFooterScrollbar: getStickyFooterScrollbar,
7679 getStickyHeaderDates: getStickyHeaderDates,
7680 Scroller: Scroller,
7681 getScrollbarWidths: getScrollbarWidths,
7682 RefMap: RefMap,
7683 getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
7684 NowTimer: NowTimer,
7685 ScrollResponder: ScrollResponder,
7686 StandardEvent: StandardEvent,
7687 NowIndicatorContainer: NowIndicatorContainer,
7688 DayCellContainer: DayCellContainer,
7689 hasCustomDayCellContent: hasCustomDayCellContent,
7690 EventContainer: EventContainer,
7691 renderFill: renderFill,
7692 BgEvent: BgEvent,
7693 WeekNumberContainer: WeekNumberContainer,
7694 MoreLinkContainer: MoreLinkContainer,
7695 computeEarliestSegStart: computeEarliestSegStart,
7696 ViewContainer: ViewContainer,
7697 triggerDateSelect: triggerDateSelect,
7698 getDefaultEventEnd: getDefaultEventEnd,
7699 injectStyles: injectStyles,
7700 CalendarImpl: CalendarImpl,
7701 EventImpl: EventImpl,
7702 buildEventApis: buildEventApis,
7703 buildElAttrs: buildElAttrs,
7704 ContentContainer: ContentContainer,
7705 CustomRenderingStore: CustomRenderingStore
7706 };
7707
7708 const globalLocales = [];
7709
7710 const MINIMAL_RAW_EN_LOCALE = {
7711 code: 'en',
7712 week: {
7713 dow: 0,
7714 doy: 4, // 4 days need to be within the year to be considered the first week
7715 },
7716 direction: 'ltr',
7717 buttonText: {
7718 prev: 'prev',
7719 next: 'next',
7720 prevYear: 'prev year',
7721 nextYear: 'next year',
7722 year: 'year',
7723 today: 'today',
7724 month: 'month',
7725 week: 'week',
7726 day: 'day',
7727 list: 'list',
7728 },
7729 weekText: 'W',
7730 weekTextLong: 'Week',
7731 closeHint: 'Close',
7732 timeHint: 'Time',
7733 eventHint: 'Event',
7734 allDayText: 'all-day',
7735 moreLinkText: 'more',
7736 noEventsText: 'No events to display',
7737 };
7738 const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
7739 // Includes things we don't want other locales to inherit,
7740 // things that derive from other translatable strings.
7741 buttonHints: {
7742 prev: 'Previous $0',
7743 next: 'Next $0',
7744 today(buttonText, unit) {
7745 return (unit === 'day')
7746 ? 'Today'
7747 : `This ${buttonText}`;
7748 },
7749 }, viewHint: '$0 view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
7750 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
7751 } });
7752 function organizeRawLocales(explicitRawLocales) {
7753 let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
7754 let allRawLocales = globalLocales.concat(explicitRawLocales);
7755 let rawLocaleMap = {
7756 en: RAW_EN_LOCALE,
7757 };
7758 for (let rawLocale of allRawLocales) {
7759 rawLocaleMap[rawLocale.code] = rawLocale;
7760 }
7761 return {
7762 map: rawLocaleMap,
7763 defaultCode,
7764 };
7765 }
7766 function buildLocale(inputSingular, available) {
7767 if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
7768 return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
7769 }
7770 return queryLocale(inputSingular, available);
7771 }
7772 function queryLocale(codeArg, available) {
7773 let codes = [].concat(codeArg || []); // will convert to array
7774 let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
7775 return parseLocale(codeArg, codes, raw);
7776 }
7777 function queryRawLocale(codes, available) {
7778 for (let i = 0; i < codes.length; i += 1) {
7779 let parts = codes[i].toLocaleLowerCase().split('-');
7780 for (let j = parts.length; j > 0; j -= 1) {
7781 let simpleId = parts.slice(0, j).join('-');
7782 if (available[simpleId]) {
7783 return available[simpleId];
7784 }
7785 }
7786 }
7787 return null;
7788 }
7789 function parseLocale(codeArg, codes, raw) {
7790 let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
7791 delete merged.code; // don't want this part of the options
7792 let { week } = merged;
7793 delete merged.week;
7794 return {
7795 codeArg,
7796 codes,
7797 week,
7798 simpleNumberFormat: new Intl.NumberFormat(codeArg),
7799 options: merged,
7800 };
7801 }
7802
7803 // TODO: easier way to add new hooks? need to update a million things
7804 function createPlugin(input) {
7805 return {
7806 id: guid(),
7807 name: input.name,
7808 premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
7809 deps: input.deps || [],
7810 reducers: input.reducers || [],
7811 isLoadingFuncs: input.isLoadingFuncs || [],
7812 contextInit: [].concat(input.contextInit || []),
7813 eventRefiners: input.eventRefiners || {},
7814 eventDefMemberAdders: input.eventDefMemberAdders || [],
7815 eventSourceRefiners: input.eventSourceRefiners || {},
7816 isDraggableTransformers: input.isDraggableTransformers || [],
7817 eventDragMutationMassagers: input.eventDragMutationMassagers || [],
7818 eventDefMutationAppliers: input.eventDefMutationAppliers || [],
7819 dateSelectionTransformers: input.dateSelectionTransformers || [],
7820 datePointTransforms: input.datePointTransforms || [],
7821 dateSpanTransforms: input.dateSpanTransforms || [],
7822 views: input.views || {},
7823 viewPropsTransformers: input.viewPropsTransformers || [],
7824 isPropsValid: input.isPropsValid || null,
7825 externalDefTransforms: input.externalDefTransforms || [],
7826 viewContainerAppends: input.viewContainerAppends || [],
7827 eventDropTransformers: input.eventDropTransformers || [],
7828 componentInteractions: input.componentInteractions || [],
7829 calendarInteractions: input.calendarInteractions || [],
7830 themeClasses: input.themeClasses || {},
7831 eventSourceDefs: input.eventSourceDefs || [],
7832 cmdFormatter: input.cmdFormatter,
7833 recurringTypes: input.recurringTypes || [],
7834 namedTimeZonedImpl: input.namedTimeZonedImpl,
7835 initialView: input.initialView || '',
7836 elementDraggingImpl: input.elementDraggingImpl,
7837 optionChangeHandlers: input.optionChangeHandlers || {},
7838 scrollGridImpl: input.scrollGridImpl || null,
7839 listenerRefiners: input.listenerRefiners || {},
7840 optionRefiners: input.optionRefiners || {},
7841 propSetHandlers: input.propSetHandlers || {},
7842 };
7843 }
7844 function buildPluginHooks(pluginDefs, globalDefs) {
7845 let currentPluginIds = {};
7846 let hooks = {
7847 premiumReleaseDate: undefined,
7848 reducers: [],
7849 isLoadingFuncs: [],
7850 contextInit: [],
7851 eventRefiners: {},
7852 eventDefMemberAdders: [],
7853 eventSourceRefiners: {},
7854 isDraggableTransformers: [],
7855 eventDragMutationMassagers: [],
7856 eventDefMutationAppliers: [],
7857 dateSelectionTransformers: [],
7858 datePointTransforms: [],
7859 dateSpanTransforms: [],
7860 views: {},
7861 viewPropsTransformers: [],
7862 isPropsValid: null,
7863 externalDefTransforms: [],
7864 viewContainerAppends: [],
7865 eventDropTransformers: [],
7866 componentInteractions: [],
7867 calendarInteractions: [],
7868 themeClasses: {},
7869 eventSourceDefs: [],
7870 cmdFormatter: null,
7871 recurringTypes: [],
7872 namedTimeZonedImpl: null,
7873 initialView: '',
7874 elementDraggingImpl: null,
7875 optionChangeHandlers: {},
7876 scrollGridImpl: null,
7877 listenerRefiners: {},
7878 optionRefiners: {},
7879 propSetHandlers: {},
7880 };
7881 function addDefs(defs) {
7882 for (let def of defs) {
7883 const pluginName = def.name;
7884 const currentId = currentPluginIds[pluginName];
7885 if (currentId === undefined) {
7886 currentPluginIds[pluginName] = def.id;
7887 addDefs(def.deps);
7888 hooks = combineHooks(hooks, def);
7889 }
7890 else if (currentId !== def.id) {
7891 // different ID than the one already added
7892 console.warn(`Duplicate plugin '${pluginName}'`);
7893 }
7894 }
7895 }
7896 if (pluginDefs) {
7897 addDefs(pluginDefs);
7898 }
7899 addDefs(globalDefs);
7900 return hooks;
7901 }
7902 function buildBuildPluginHooks() {
7903 let currentOverrideDefs = [];
7904 let currentGlobalDefs = [];
7905 let currentHooks;
7906 return (overrideDefs, globalDefs) => {
7907 if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
7908 currentHooks = buildPluginHooks(overrideDefs, globalDefs);
7909 }
7910 currentOverrideDefs = overrideDefs;
7911 currentGlobalDefs = globalDefs;
7912 return currentHooks;
7913 };
7914 }
7915 function combineHooks(hooks0, hooks1) {
7916 return {
7917 premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
7918 reducers: hooks0.reducers.concat(hooks1.reducers),
7919 isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
7920 contextInit: hooks0.contextInit.concat(hooks1.contextInit),
7921 eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
7922 eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
7923 eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
7924 isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
7925 eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
7926 eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
7927 dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
7928 datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
7929 dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
7930 views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
7931 viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
7932 isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
7933 externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
7934 viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
7935 eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
7936 calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
7937 componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
7938 themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
7939 eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
7940 cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
7941 recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
7942 namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
7943 initialView: hooks0.initialView || hooks1.initialView,
7944 elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
7945 optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
7946 scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
7947 listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
7948 optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
7949 propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
7950 };
7951 }
7952 function compareOptionalDates(date0, date1) {
7953 if (date0 === undefined) {
7954 return date1;
7955 }
7956 if (date1 === undefined) {
7957 return date0;
7958 }
7959 return new Date(Math.max(date0.valueOf(), date1.valueOf()));
7960 }
7961
7962 class StandardTheme extends Theme {
7963 }
7964 StandardTheme.prototype.classes = {
7965 root: 'fc-theme-standard',
7966 tableCellShaded: 'fc-cell-shaded',
7967 buttonGroup: 'fc-button-group',
7968 button: 'fc-button fc-button-primary',
7969 buttonActive: 'fc-button-active',
7970 };
7971 StandardTheme.prototype.baseIconClass = 'fc-icon';
7972 StandardTheme.prototype.iconClasses = {
7973 close: 'fc-icon-x',
7974 prev: 'fc-icon-chevron-left',
7975 next: 'fc-icon-chevron-right',
7976 prevYear: 'fc-icon-chevrons-left',
7977 nextYear: 'fc-icon-chevrons-right',
7978 };
7979 StandardTheme.prototype.rtlIconClasses = {
7980 prev: 'fc-icon-chevron-right',
7981 next: 'fc-icon-chevron-left',
7982 prevYear: 'fc-icon-chevrons-right',
7983 nextYear: 'fc-icon-chevrons-left',
7984 };
7985 StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
7986 StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
7987 StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
7988
7989 function compileViewDefs(defaultConfigs, overrideConfigs) {
7990 let hash = {};
7991 let viewType;
7992 for (viewType in defaultConfigs) {
7993 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7994 }
7995 for (viewType in overrideConfigs) {
7996 ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
7997 }
7998 return hash;
7999 }
8000 function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8001 if (hash[viewType]) {
8002 return hash[viewType];
8003 }
8004 let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
8005 if (viewDef) {
8006 hash[viewType] = viewDef;
8007 }
8008 return viewDef;
8009 }
8010 function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
8011 let defaultConfig = defaultConfigs[viewType];
8012 let overrideConfig = overrideConfigs[viewType];
8013 let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
8014 ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
8015 let theComponent = queryProp('component');
8016 let superType = queryProp('superType');
8017 let superDef = null;
8018 if (superType) {
8019 if (superType === viewType) {
8020 throw new Error('Can\'t have a custom view type that references itself');
8021 }
8022 superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
8023 }
8024 if (!theComponent && superDef) {
8025 theComponent = superDef.component;
8026 }
8027 if (!theComponent) {
8028 return null; // don't throw a warning, might be settings for a single-unit view
8029 }
8030 return {
8031 type: viewType,
8032 component: theComponent,
8033 defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
8034 overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
8035 };
8036 }
8037
8038 function parseViewConfigs(inputs) {
8039 return mapHash(inputs, parseViewConfig);
8040 }
8041 function parseViewConfig(input) {
8042 let rawOptions = typeof input === 'function' ?
8043 { component: input } :
8044 input;
8045 let { component } = rawOptions;
8046 if (rawOptions.content) {
8047 // TODO: remove content/classNames/didMount/etc from options?
8048 component = createViewHookComponent(rawOptions);
8049 }
8050 else if (component && !(component.prototype instanceof BaseComponent)) {
8051 // WHY?: people were using `component` property for `content`
8052 // TODO: converge on one setting name
8053 component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), { content: component }));
8054 }
8055 return {
8056 superType: rawOptions.type,
8057 component: component,
8058 rawOptions, // includes type and component too :(
8059 };
8060 }
8061 function createViewHookComponent(options) {
8062 return (viewProps) => (y(ViewContextType.Consumer, null, (context) => (y(ContentContainer, { elTag: "div", elClasses: buildViewClassNames(context.viewSpec), renderProps: Object.assign(Object.assign({}, viewProps), { nextDayThreshold: context.options.nextDayThreshold }), generatorName: undefined, customGenerator: options.content, classNameGenerator: options.classNames, didMount: options.didMount, willUnmount: options.willUnmount }))));
8063 }
8064
8065 function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8066 let defaultConfigs = parseViewConfigs(defaultInputs);
8067 let overrideConfigs = parseViewConfigs(optionOverrides.views);
8068 let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
8069 return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
8070 }
8071 function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
8072 let durationInput = viewDef.overrides.duration ||
8073 viewDef.defaults.duration ||
8074 dynamicOptionOverrides.duration ||
8075 optionOverrides.duration;
8076 let duration = null;
8077 let durationUnit = '';
8078 let singleUnit = '';
8079 let singleUnitOverrides = {};
8080 if (durationInput) {
8081 duration = createDurationCached(durationInput);
8082 if (duration) { // valid?
8083 let denom = greatestDurationDenominator(duration);
8084 durationUnit = denom.unit;
8085 if (denom.value === 1) {
8086 singleUnit = durationUnit;
8087 singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
8088 }
8089 }
8090 }
8091 let queryButtonText = (optionsSubset) => {
8092 let buttonTextMap = optionsSubset.buttonText || {};
8093 let buttonTextKey = viewDef.defaults.buttonTextKey;
8094 if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
8095 return buttonTextMap[buttonTextKey];
8096 }
8097 if (buttonTextMap[viewDef.type] != null) {
8098 return buttonTextMap[viewDef.type];
8099 }
8100 if (buttonTextMap[singleUnit] != null) {
8101 return buttonTextMap[singleUnit];
8102 }
8103 return null;
8104 };
8105 let queryButtonTitle = (optionsSubset) => {
8106 let buttonHints = optionsSubset.buttonHints || {};
8107 let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
8108 if (buttonKey != null && buttonHints[buttonKey] != null) {
8109 return buttonHints[buttonKey];
8110 }
8111 if (buttonHints[viewDef.type] != null) {
8112 return buttonHints[viewDef.type];
8113 }
8114 if (buttonHints[singleUnit] != null) {
8115 return buttonHints[singleUnit];
8116 }
8117 return null;
8118 };
8119 return {
8120 type: viewDef.type,
8121 component: viewDef.component,
8122 duration,
8123 durationUnit,
8124 singleUnit,
8125 optionDefaults: viewDef.defaults,
8126 optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
8127 buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
8128 queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
8129 viewDef.overrides.buttonText,
8130 buttonTextDefault: queryButtonText(localeDefaults) ||
8131 viewDef.defaults.buttonText ||
8132 queryButtonText(BASE_OPTION_DEFAULTS) ||
8133 viewDef.type,
8134 // not DRY
8135 buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
8136 queryButtonTitle(optionOverrides) ||
8137 viewDef.overrides.buttonHint,
8138 buttonTitleDefault: queryButtonTitle(localeDefaults) ||
8139 viewDef.defaults.buttonHint ||
8140 queryButtonTitle(BASE_OPTION_DEFAULTS),
8141 // will eventually fall back to buttonText
8142 };
8143 }
8144 // hack to get memoization working
8145 let durationInputMap = {};
8146 function createDurationCached(durationInput) {
8147 let json = JSON.stringify(durationInput);
8148 let res = durationInputMap[json];
8149 if (res === undefined) {
8150 res = createDuration(durationInput);
8151 durationInputMap[json] = res;
8152 }
8153 return res;
8154 }
8155
8156 function reduceViewType(viewType, action) {
8157 switch (action.type) {
8158 case 'CHANGE_VIEW_TYPE':
8159 viewType = action.viewType;
8160 }
8161 return viewType;
8162 }
8163
8164 function reduceCurrentDate(currentDate, action) {
8165 switch (action.type) {
8166 case 'CHANGE_DATE':
8167 return action.dateMarker;
8168 default:
8169 return currentDate;
8170 }
8171 }
8172 // should be initialized once and stay constant
8173 // this will change too
8174 function getInitialDate(options, dateEnv, nowManager) {
8175 let initialDateInput = options.initialDate;
8176 // compute the initial ambig-timezone date
8177 if (initialDateInput != null) {
8178 return dateEnv.createMarker(initialDateInput);
8179 }
8180 return nowManager.getDateMarker();
8181 }
8182
8183 function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
8184 switch (action.type) {
8185 case 'SET_OPTION':
8186 return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
8187 default:
8188 return dynamicOptionOverrides;
8189 }
8190 }
8191
8192 function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
8193 let dp;
8194 switch (action.type) {
8195 case 'CHANGE_VIEW_TYPE':
8196 return dateProfileGenerator.build(action.dateMarker || currentDate);
8197 case 'CHANGE_DATE':
8198 return dateProfileGenerator.build(action.dateMarker);
8199 case 'PREV':
8200 dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
8201 if (dp.isValid) {
8202 return dp;
8203 }
8204 break;
8205 case 'NEXT':
8206 dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
8207 if (dp.isValid) {
8208 return dp;
8209 }
8210 break;
8211 }
8212 return currentDateProfile;
8213 }
8214
8215 function initEventSources(calendarOptions, dateProfile, context) {
8216 let activeRange = dateProfile ? dateProfile.activeRange : null;
8217 return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
8218 }
8219 function reduceEventSources(eventSources, action, dateProfile, context) {
8220 let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8221 switch (action.type) {
8222 case 'ADD_EVENT_SOURCES': // already parsed
8223 return addSources(eventSources, action.sources, activeRange, context);
8224 case 'REMOVE_EVENT_SOURCE':
8225 return removeSource(eventSources, action.sourceId);
8226 case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
8227 case 'NEXT':
8228 case 'CHANGE_DATE':
8229 case 'CHANGE_VIEW_TYPE':
8230 if (dateProfile) {
8231 return fetchDirtySources(eventSources, activeRange, context);
8232 }
8233 return eventSources;
8234 case 'FETCH_EVENT_SOURCES':
8235 return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
8236 arrayToHash(action.sourceIds) :
8237 excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
8238 case 'RECEIVE_EVENTS':
8239 case 'RECEIVE_EVENT_ERROR':
8240 return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
8241 case 'REMOVE_ALL_EVENT_SOURCES':
8242 return {};
8243 default:
8244 return eventSources;
8245 }
8246 }
8247 function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
8248 let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
8249 return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
8250 }
8251 function computeEventSourcesLoading(eventSources) {
8252 for (let sourceId in eventSources) {
8253 if (eventSources[sourceId].isFetching) {
8254 return true;
8255 }
8256 }
8257 return false;
8258 }
8259 function addSources(eventSourceHash, sources, fetchRange, context) {
8260 let hash = {};
8261 for (let source of sources) {
8262 hash[source.sourceId] = source;
8263 }
8264 if (fetchRange) {
8265 hash = fetchDirtySources(hash, fetchRange, context);
8266 }
8267 return Object.assign(Object.assign({}, eventSourceHash), hash);
8268 }
8269 function removeSource(eventSourceHash, sourceId) {
8270 return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
8271 }
8272 function fetchDirtySources(sourceHash, fetchRange, context) {
8273 return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
8274 }
8275 function isSourceDirty(eventSource, fetchRange, context) {
8276 if (!doesSourceNeedRange(eventSource, context)) {
8277 return !eventSource.latestFetchId;
8278 }
8279 return !context.options.lazyFetching ||
8280 !eventSource.fetchRange ||
8281 eventSource.isFetching || // always cancel outdated in-progress fetches
8282 fetchRange.start < eventSource.fetchRange.start ||
8283 fetchRange.end > eventSource.fetchRange.end;
8284 }
8285 function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
8286 let nextSources = {};
8287 for (let sourceId in prevSources) {
8288 let source = prevSources[sourceId];
8289 if (sourceIdHash[sourceId]) {
8290 nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
8291 }
8292 else {
8293 nextSources[sourceId] = source;
8294 }
8295 }
8296 return nextSources;
8297 }
8298 function fetchSource(eventSource, fetchRange, isRefetch, context) {
8299 let { options, calendarApi } = context;
8300 let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
8301 let fetchId = guid();
8302 sourceDef.fetch({
8303 eventSource,
8304 range: fetchRange,
8305 isRefetch,
8306 context,
8307 }, (res) => {
8308 let { rawEvents } = res;
8309 if (options.eventSourceSuccess) {
8310 rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
8311 }
8312 if (eventSource.success) {
8313 rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
8314 }
8315 context.dispatch({
8316 type: 'RECEIVE_EVENTS',
8317 sourceId: eventSource.sourceId,
8318 fetchId,
8319 fetchRange,
8320 rawEvents,
8321 });
8322 }, (error) => {
8323 let errorHandled = false;
8324 if (options.eventSourceFailure) {
8325 options.eventSourceFailure.call(calendarApi, error);
8326 errorHandled = true;
8327 }
8328 if (eventSource.failure) {
8329 eventSource.failure(error);
8330 errorHandled = true;
8331 }
8332 if (!errorHandled) {
8333 console.warn(error.message, error);
8334 }
8335 context.dispatch({
8336 type: 'RECEIVE_EVENT_ERROR',
8337 sourceId: eventSource.sourceId,
8338 fetchId,
8339 fetchRange,
8340 error,
8341 });
8342 });
8343 return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
8344 }
8345 function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
8346 let eventSource = sourceHash[sourceId];
8347 if (eventSource && // not already removed
8348 fetchId === eventSource.latestFetchId) {
8349 return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
8350 }
8351 return sourceHash;
8352 }
8353 function excludeStaticSources(eventSources, context) {
8354 return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
8355 }
8356 function parseInitialSources(rawOptions, context) {
8357 let refiners = buildEventSourceRefiners(context);
8358 let rawSources = [].concat(rawOptions.eventSources || []);
8359 let sources = []; // parsed
8360 if (rawOptions.initialEvents) {
8361 rawSources.unshift(rawOptions.initialEvents);
8362 }
8363 if (rawOptions.events) {
8364 rawSources.unshift(rawOptions.events);
8365 }
8366 for (let rawSource of rawSources) {
8367 let source = parseEventSource(rawSource, context, refiners);
8368 if (source) {
8369 sources.push(source);
8370 }
8371 }
8372 return sources;
8373 }
8374 function doesSourceNeedRange(eventSource, context) {
8375 let defs = context.pluginHooks.eventSourceDefs;
8376 return !defs[eventSource.sourceDefId].ignoreRange;
8377 }
8378
8379 function reduceDateSelection(currentSelection, action) {
8380 switch (action.type) {
8381 case 'UNSELECT_DATES':
8382 return null;
8383 case 'SELECT_DATES':
8384 return action.selection;
8385 default:
8386 return currentSelection;
8387 }
8388 }
8389
8390 function reduceSelectedEvent(currentInstanceId, action) {
8391 switch (action.type) {
8392 case 'UNSELECT_EVENT':
8393 return '';
8394 case 'SELECT_EVENT':
8395 return action.eventInstanceId;
8396 default:
8397 return currentInstanceId;
8398 }
8399 }
8400
8401 function reduceEventDrag(currentDrag, action) {
8402 let newDrag;
8403 switch (action.type) {
8404 case 'UNSET_EVENT_DRAG':
8405 return null;
8406 case 'SET_EVENT_DRAG':
8407 newDrag = action.state;
8408 return {
8409 affectedEvents: newDrag.affectedEvents,
8410 mutatedEvents: newDrag.mutatedEvents,
8411 isEvent: newDrag.isEvent,
8412 };
8413 default:
8414 return currentDrag;
8415 }
8416 }
8417
8418 function reduceEventResize(currentResize, action) {
8419 let newResize;
8420 switch (action.type) {
8421 case 'UNSET_EVENT_RESIZE':
8422 return null;
8423 case 'SET_EVENT_RESIZE':
8424 newResize = action.state;
8425 return {
8426 affectedEvents: newResize.affectedEvents,
8427 mutatedEvents: newResize.mutatedEvents,
8428 isEvent: newResize.isEvent,
8429 };
8430 default:
8431 return currentResize;
8432 }
8433 }
8434
8435 function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8436 let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8437 let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
8438 return { header, footer };
8439 }
8440 function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
8441 let sectionWidgets = {};
8442 let viewsWithButtons = [];
8443 let hasTitle = false;
8444 for (let sectionName in sectionStrHash) {
8445 let sectionStr = sectionStrHash[sectionName];
8446 let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
8447 sectionWidgets[sectionName] = sectionRes.widgets;
8448 viewsWithButtons.push(...sectionRes.viewsWithButtons);
8449 hasTitle = hasTitle || sectionRes.hasTitle;
8450 }
8451 return { sectionWidgets, viewsWithButtons, hasTitle };
8452 }
8453 /*
8454 BAD: querying icons and text here. should be done at render time
8455 */
8456 function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
8457 calendarOptionOverrides, // overrides only!, unrefined :(
8458 theme, viewSpecs, calendarApi) {
8459 let isRtl = calendarOptions.direction === 'rtl';
8460 let calendarCustomButtons = calendarOptions.customButtons || {};
8461 let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
8462 let calendarButtonText = calendarOptions.buttonText || {};
8463 let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
8464 let calendarButtonHints = calendarOptions.buttonHints || {};
8465 let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
8466 let viewsWithButtons = [];
8467 let hasTitle = false;
8468 let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
8469 if (buttonName === 'title') {
8470 hasTitle = true;
8471 return { buttonName };
8472 }
8473 let customButtonProps;
8474 let viewSpec;
8475 let buttonClick;
8476 let buttonIcon; // only one of these will be set
8477 let buttonText; // "
8478 let buttonHint;
8479 // ^ for the title="" attribute, for accessibility
8480 if ((customButtonProps = calendarCustomButtons[buttonName])) {
8481 buttonClick = (ev) => {
8482 if (customButtonProps.click) {
8483 customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
8484 }
8485 };
8486 (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
8487 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8488 (buttonText = customButtonProps.text);
8489 buttonHint = customButtonProps.hint || customButtonProps.text;
8490 }
8491 else if ((viewSpec = viewSpecs[buttonName])) {
8492 viewsWithButtons.push(buttonName);
8493 buttonClick = () => {
8494 calendarApi.changeView(buttonName);
8495 };
8496 (buttonText = viewSpec.buttonTextOverride) ||
8497 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8498 (buttonText = viewSpec.buttonTextDefault);
8499 let textFallback = viewSpec.buttonTextOverride ||
8500 viewSpec.buttonTextDefault;
8501 buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
8502 viewSpec.buttonTitleDefault ||
8503 calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
8504 textFallback);
8505 }
8506 else if (calendarApi[buttonName]) { // a calendarApi method
8507 buttonClick = () => {
8508 calendarApi[buttonName]();
8509 };
8510 (buttonText = calendarButtonTextOverrides[buttonName]) ||
8511 (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
8512 (buttonText = calendarButtonText[buttonName]); // everything else is considered default
8513 if (buttonName === 'prevYear' || buttonName === 'nextYear') {
8514 let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
8515 buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
8516 calendarButtonHints[prevOrNext], [
8517 calendarButtonText.year || 'year',
8518 'year',
8519 ], calendarButtonText[buttonName]);
8520 }
8521 else {
8522 buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
8523 calendarButtonHints[buttonName], [
8524 calendarButtonText[navUnit] || navUnit,
8525 navUnit,
8526 ], calendarButtonText[buttonName]);
8527 }
8528 }
8529 return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint };
8530 })));
8531 return { widgets, viewsWithButtons, hasTitle };
8532 }
8533
8534 // always represents the current view. otherwise, it'd need to change value every time date changes
8535 class ViewImpl {
8536 constructor(type, getCurrentData, dateEnv) {
8537 this.type = type;
8538 this.getCurrentData = getCurrentData;
8539 this.dateEnv = dateEnv;
8540 }
8541 get calendar() {
8542 return this.getCurrentData().calendarApi;
8543 }
8544 get title() {
8545 return this.getCurrentData().viewTitle;
8546 }
8547 get activeStart() {
8548 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
8549 }
8550 get activeEnd() {
8551 return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
8552 }
8553 get currentStart() {
8554 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
8555 }
8556 get currentEnd() {
8557 return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
8558 }
8559 getOption(name) {
8560 return this.getCurrentData().options[name]; // are the view-specific options
8561 }
8562 }
8563
8564 let eventSourceDef$2 = {
8565 ignoreRange: true,
8566 parseMeta(refined) {
8567 if (Array.isArray(refined.events)) {
8568 return refined.events;
8569 }
8570 return null;
8571 },
8572 fetch(arg, successCallback) {
8573 successCallback({
8574 rawEvents: arg.eventSource.meta,
8575 });
8576 },
8577 };
8578 const arrayEventSourcePlugin = createPlugin({
8579 name: 'array-event-source',
8580 eventSourceDefs: [eventSourceDef$2],
8581 });
8582
8583 let eventSourceDef$1 = {
8584 parseMeta(refined) {
8585 if (typeof refined.events === 'function') {
8586 return refined.events;
8587 }
8588 return null;
8589 },
8590 fetch(arg, successCallback, errorCallback) {
8591 const { dateEnv } = arg.context;
8592 const func = arg.eventSource.meta;
8593 unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
8594 },
8595 };
8596 const funcEventSourcePlugin = createPlugin({
8597 name: 'func-event-source',
8598 eventSourceDefs: [eventSourceDef$1],
8599 });
8600
8601 const JSON_FEED_EVENT_SOURCE_REFINERS = {
8602 method: String,
8603 extraParams: identity,
8604 startParam: String,
8605 endParam: String,
8606 timeZoneParam: String,
8607 };
8608
8609 let eventSourceDef = {
8610 parseMeta(refined) {
8611 if (refined.url && (refined.format === 'json' || !refined.format)) {
8612 return {
8613 url: refined.url,
8614 format: 'json',
8615 method: (refined.method || 'GET').toUpperCase(),
8616 extraParams: refined.extraParams,
8617 startParam: refined.startParam,
8618 endParam: refined.endParam,
8619 timeZoneParam: refined.timeZoneParam,
8620 };
8621 }
8622 return null;
8623 },
8624 fetch(arg, successCallback, errorCallback) {
8625 const { meta } = arg.eventSource;
8626 const requestParams = buildRequestParams(meta, arg.range, arg.context);
8627 requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
8628 successCallback({ rawEvents, response });
8629 }, errorCallback);
8630 },
8631 };
8632 const jsonFeedEventSourcePlugin = createPlugin({
8633 name: 'json-event-source',
8634 eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
8635 eventSourceDefs: [eventSourceDef],
8636 });
8637 function buildRequestParams(meta, range, context) {
8638 let { dateEnv, options } = context;
8639 let startParam;
8640 let endParam;
8641 let timeZoneParam;
8642 let customRequestParams;
8643 let params = {};
8644 startParam = meta.startParam;
8645 if (startParam == null) {
8646 startParam = options.startParam;
8647 }
8648 endParam = meta.endParam;
8649 if (endParam == null) {
8650 endParam = options.endParam;
8651 }
8652 timeZoneParam = meta.timeZoneParam;
8653 if (timeZoneParam == null) {
8654 timeZoneParam = options.timeZoneParam;
8655 }
8656 // retrieve any outbound GET/POST data from the options
8657 if (typeof meta.extraParams === 'function') {
8658 // supplied as a function that returns a key/value object
8659 customRequestParams = meta.extraParams();
8660 }
8661 else {
8662 // probably supplied as a straight key/value object
8663 customRequestParams = meta.extraParams || {};
8664 }
8665 Object.assign(params, customRequestParams);
8666 params[startParam] = dateEnv.formatIso(range.start);
8667 params[endParam] = dateEnv.formatIso(range.end);
8668 if (dateEnv.timeZone !== 'local') {
8669 params[timeZoneParam] = dateEnv.timeZone;
8670 }
8671 return params;
8672 }
8673
8674 const SIMPLE_RECURRING_REFINERS = {
8675 daysOfWeek: identity,
8676 startTime: createDuration,
8677 endTime: createDuration,
8678 duration: createDuration,
8679 startRecur: identity,
8680 endRecur: identity,
8681 };
8682
8683 let recurring = {
8684 parse(refined, dateEnv) {
8685 if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
8686 let recurringData = {
8687 daysOfWeek: refined.daysOfWeek || null,
8688 startTime: refined.startTime || null,
8689 endTime: refined.endTime || null,
8690 startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
8691 endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
8692 dateEnv,
8693 };
8694 let duration;
8695 if (refined.duration) {
8696 duration = refined.duration;
8697 }
8698 if (!duration && refined.startTime && refined.endTime) {
8699 duration = subtractDurations(refined.endTime, refined.startTime);
8700 }
8701 return {
8702 allDayGuess: Boolean(!refined.startTime && !refined.endTime),
8703 duration,
8704 typeData: recurringData, // doesn't need endTime anymore but oh well
8705 };
8706 }
8707 return null;
8708 },
8709 expand(typeData, framingRange, dateEnv) {
8710 let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
8711 if (clippedFramingRange) {
8712 return expandRanges(typeData.daysOfWeek, typeData.startTime, typeData.dateEnv, dateEnv, clippedFramingRange);
8713 }
8714 return [];
8715 },
8716 };
8717 const simpleRecurringEventsPlugin = createPlugin({
8718 name: 'simple-recurring-event',
8719 recurringTypes: [recurring],
8720 eventRefiners: SIMPLE_RECURRING_REFINERS,
8721 });
8722 function expandRanges(daysOfWeek, startTime, eventDateEnv, calendarDateEnv, framingRange) {
8723 let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
8724 let dayMarker = startOfDay(framingRange.start);
8725 let endMarker = framingRange.end;
8726 let instanceStarts = [];
8727 while (dayMarker < endMarker) {
8728 let instanceStart;
8729 // if everyday, or this particular day-of-week
8730 if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
8731 if (startTime) {
8732 instanceStart = calendarDateEnv.add(dayMarker, startTime);
8733 }
8734 else {
8735 instanceStart = dayMarker;
8736 }
8737 instanceStarts.push(calendarDateEnv.createMarker(eventDateEnv.toDate(instanceStart)));
8738 }
8739 dayMarker = addDays(dayMarker, 1);
8740 }
8741 return instanceStarts;
8742 }
8743
8744 const changeHandlerPlugin = createPlugin({
8745 name: 'change-handler',
8746 optionChangeHandlers: {
8747 events(events, context) {
8748 handleEventSources([events], context);
8749 },
8750 eventSources: handleEventSources,
8751 },
8752 });
8753 /*
8754 BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
8755 */
8756 function handleEventSources(inputs, context) {
8757 let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
8758 if (unfoundSources.length === 1 &&
8759 inputs.length === 1 &&
8760 Array.isArray(unfoundSources[0]._raw) &&
8761 Array.isArray(inputs[0])) {
8762 context.dispatch({
8763 type: 'RESET_RAW_EVENTS',
8764 sourceId: unfoundSources[0].sourceId,
8765 rawEvents: inputs[0],
8766 });
8767 return;
8768 }
8769 let newInputs = [];
8770 for (let input of inputs) {
8771 let inputFound = false;
8772 for (let i = 0; i < unfoundSources.length; i += 1) {
8773 if (unfoundSources[i]._raw === input) {
8774 unfoundSources.splice(i, 1); // delete
8775 inputFound = true;
8776 break;
8777 }
8778 }
8779 if (!inputFound) {
8780 newInputs.push(input);
8781 }
8782 }
8783 for (let unfoundSource of unfoundSources) {
8784 context.dispatch({
8785 type: 'REMOVE_EVENT_SOURCE',
8786 sourceId: unfoundSource.sourceId,
8787 });
8788 }
8789 for (let newInput of newInputs) {
8790 context.calendarApi.addEventSource(newInput);
8791 }
8792 }
8793
8794 function handleDateProfile(dateProfile, context) {
8795 context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
8796 }
8797
8798 function handleEventStore(eventStore, context) {
8799 let { emitter } = context;
8800 if (emitter.hasHandlers('eventsSet')) {
8801 emitter.trigger('eventsSet', buildEventApis(eventStore, context));
8802 }
8803 }
8804
8805 /*
8806 this array is exposed on the root namespace so that UMD plugins can add to it.
8807 see the rollup-bundles script.
8808 */
8809 const globalPlugins = [
8810 arrayEventSourcePlugin,
8811 funcEventSourcePlugin,
8812 jsonFeedEventSourcePlugin,
8813 simpleRecurringEventsPlugin,
8814 changeHandlerPlugin,
8815 createPlugin({
8816 name: 'misc',
8817 isLoadingFuncs: [
8818 (state) => computeEventSourcesLoading(state.eventSources),
8819 ],
8820 propSetHandlers: {
8821 dateProfile: handleDateProfile,
8822 eventStore: handleEventStore,
8823 },
8824 }),
8825 ];
8826
8827 class TaskRunner {
8828 constructor(runTaskOption, drainedOption) {
8829 this.runTaskOption = runTaskOption;
8830 this.drainedOption = drainedOption;
8831 this.queue = [];
8832 this.delayedRunner = new DelayedRunner(this.drain.bind(this));
8833 }
8834 request(task, delay) {
8835 this.queue.push(task);
8836 this.delayedRunner.request(delay);
8837 }
8838 pause(scope) {
8839 this.delayedRunner.pause(scope);
8840 }
8841 resume(scope, force) {
8842 this.delayedRunner.resume(scope, force);
8843 }
8844 drain() {
8845 let { queue } = this;
8846 while (queue.length) {
8847 let completedTasks = [];
8848 let task;
8849 while ((task = queue.shift())) {
8850 this.runTask(task);
8851 completedTasks.push(task);
8852 }
8853 this.drained(completedTasks);
8854 } // keep going, in case new tasks were added in the drained handler
8855 }
8856 runTask(task) {
8857 if (this.runTaskOption) {
8858 this.runTaskOption(task);
8859 }
8860 }
8861 drained(completedTasks) {
8862 if (this.drainedOption) {
8863 this.drainedOption(completedTasks);
8864 }
8865 }
8866 }
8867
8868 // Computes what the title at the top of the calendarApi should be for this view
8869 function buildTitle(dateProfile, viewOptions, dateEnv) {
8870 let range;
8871 // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
8872 if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
8873 range = dateProfile.currentRange;
8874 }
8875 else { // for day units or smaller, use the actual day range
8876 range = dateProfile.activeRange;
8877 }
8878 return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
8879 isEndExclusive: dateProfile.isRangeAllDay,
8880 defaultSeparator: viewOptions.titleRangeSeparator,
8881 });
8882 }
8883 // Generates the format string that should be used to generate the title for the current date range.
8884 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
8885 function buildTitleFormat(dateProfile) {
8886 let { currentRangeUnit } = dateProfile;
8887 if (currentRangeUnit === 'year') {
8888 return { year: 'numeric' };
8889 }
8890 if (currentRangeUnit === 'month') {
8891 return { year: 'numeric', month: 'long' }; // like "September 2014"
8892 }
8893 let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
8894 if (days !== null && days > 1) {
8895 // multi-day range. shorter, like "Sep 9 - 10 2014"
8896 return { year: 'numeric', month: 'short', day: 'numeric' };
8897 }
8898 // one day. longer, like "September 9 2014"
8899 return { year: 'numeric', month: 'long', day: 'numeric' };
8900 }
8901
8902 /*
8903 TODO: test switching timezones when NO timezone plugin
8904 */
8905 class CalendarNowManager {
8906 constructor() {
8907 this.resetListeners = new Set();
8908 }
8909 handleInput(dateEnv, // will change if timezone setup changed
8910 nowInput) {
8911 const oldDateEnv = this.dateEnv;
8912 if (dateEnv !== oldDateEnv) {
8913 if (typeof nowInput === 'function') {
8914 this.nowFn = nowInput;
8915 }
8916 else if (!oldDateEnv) { // first time?
8917 this.nowAnchorDate = dateEnv.toDate(nowInput
8918 ? dateEnv.createMarker(nowInput)
8919 : dateEnv.createNowMarker());
8920 this.nowAnchorQueried = Date.now();
8921 }
8922 this.dateEnv = dateEnv;
8923 // not first time? fire reset handlers
8924 if (oldDateEnv) {
8925 for (const resetListener of this.resetListeners.values()) {
8926 resetListener();
8927 }
8928 }
8929 }
8930 }
8931 getDateMarker() {
8932 return this.nowAnchorDate
8933 ? this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf() +
8934 (Date.now() - this.nowAnchorQueried))
8935 : this.dateEnv.createMarker(this.nowFn());
8936 }
8937 addResetListener(handler) {
8938 this.resetListeners.add(handler);
8939 }
8940 removeResetListener(handler) {
8941 this.resetListeners.delete(handler);
8942 }
8943 }
8944
8945 // in future refactor, do the redux-style function(state=initial) for initial-state
8946 // also, whatever is happening in constructor, have it happen in action queue too
8947 class CalendarDataManager {
8948 constructor(props) {
8949 this.computeCurrentViewData = memoize(this._computeCurrentViewData);
8950 this.organizeRawLocales = memoize(organizeRawLocales);
8951 this.buildLocale = memoize(buildLocale);
8952 this.buildPluginHooks = buildBuildPluginHooks();
8953 this.buildDateEnv = memoize(buildDateEnv$1);
8954 this.buildTheme = memoize(buildTheme);
8955 this.parseToolbars = memoize(parseToolbars);
8956 this.buildViewSpecs = memoize(buildViewSpecs);
8957 this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
8958 this.buildViewApi = memoize(buildViewApi);
8959 this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
8960 this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
8961 this.buildEventUiBases = memoize(buildEventUiBases);
8962 this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
8963 this.buildTitle = memoize(buildTitle);
8964 this.nowManager = new CalendarNowManager();
8965 this.emitter = new Emitter();
8966 this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
8967 this.currentCalendarOptionsInput = {};
8968 this.currentCalendarOptionsRefined = {};
8969 this.currentViewOptionsInput = {};
8970 this.currentViewOptionsRefined = {};
8971 this.currentCalendarOptionsRefiners = {};
8972 this.optionsForRefining = [];
8973 this.optionsForHandling = [];
8974 this.getCurrentData = () => this.data;
8975 this.dispatch = (action) => {
8976 this.actionRunner.request(action); // protects against recursive calls to _handleAction
8977 };
8978 this.props = props;
8979 this.actionRunner.pause();
8980 this.nowManager = new CalendarNowManager();
8981 let dynamicOptionOverrides = {};
8982 let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
8983 let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
8984 let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
8985 // wire things up
8986 // TODO: not DRY
8987 props.calendarApi.currentDataManager = this;
8988 this.emitter.setThisContext(props.calendarApi);
8989 this.emitter.setOptions(currentViewData.options);
8990 let calendarContext = {
8991 nowManager: this.nowManager,
8992 dateEnv: optionsData.dateEnv,
8993 options: optionsData.calendarOptions,
8994 pluginHooks: optionsData.pluginHooks,
8995 calendarApi: props.calendarApi,
8996 dispatch: this.dispatch,
8997 emitter: this.emitter,
8998 getCurrentData: this.getCurrentData,
8999 };
9000 let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv, this.nowManager);
9001 let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9002 if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
9003 currentDate = dateProfile.currentRange.start;
9004 }
9005 // needs to be after setThisContext
9006 for (let callback of optionsData.pluginHooks.contextInit) {
9007 callback(calendarContext);
9008 }
9009 // NOT DRY
9010 let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
9011 let initialState = {
9012 dynamicOptionOverrides,
9013 currentViewType,
9014 currentDate,
9015 dateProfile,
9016 businessHours: this.parseContextBusinessHours(calendarContext),
9017 eventSources,
9018 eventUiBases: {},
9019 eventStore: createEmptyEventStore(),
9020 renderableEventStore: createEmptyEventStore(),
9021 dateSelection: null,
9022 eventSelection: '',
9023 eventDrag: null,
9024 eventResize: null,
9025 selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
9026 };
9027 let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
9028 for (let reducer of optionsData.pluginHooks.reducers) {
9029 Object.assign(initialState, reducer(null, null, contextAndState));
9030 }
9031 if (computeIsLoading(initialState, calendarContext)) {
9032 this.emitter.trigger('loading', true); // NOT DRY
9033 }
9034 this.state = initialState;
9035 this.updateData();
9036 this.actionRunner.resume();
9037 }
9038 resetOptions(optionOverrides, changedOptionNames) {
9039 let { props } = this;
9040 if (changedOptionNames === undefined) {
9041 props.optionOverrides = optionOverrides;
9042 }
9043 else {
9044 props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);
9045 this.optionsForRefining.push(...changedOptionNames);
9046 }
9047 if (changedOptionNames === undefined || changedOptionNames.length) {
9048 this.actionRunner.request({
9049 type: 'NOTHING',
9050 });
9051 }
9052 }
9053 _handleAction(action) {
9054 let { props, state, emitter } = this;
9055 let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
9056 let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
9057 let currentViewType = reduceViewType(state.currentViewType, action);
9058 let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
9059 // wire things up
9060 // TODO: not DRY
9061 props.calendarApi.currentDataManager = this;
9062 emitter.setThisContext(props.calendarApi);
9063 emitter.setOptions(currentViewData.options);
9064 let calendarContext = {
9065 nowManager: this.nowManager,
9066 dateEnv: optionsData.dateEnv,
9067 options: optionsData.calendarOptions,
9068 pluginHooks: optionsData.pluginHooks,
9069 calendarApi: props.calendarApi,
9070 dispatch: this.dispatch,
9071 emitter,
9072 getCurrentData: this.getCurrentData,
9073 };
9074 let { currentDate, dateProfile } = state;
9075 if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
9076 dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
9077 }
9078 currentDate = reduceCurrentDate(currentDate, action);
9079 dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
9080 if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
9081 action.type === 'NEXT' || // "
9082 !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
9083 currentDate = dateProfile.currentRange.start;
9084 }
9085 let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
9086 let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
9087 let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
9088 let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
9089 (state.renderableEventStore || eventStore) : // try from previous state
9090 eventStore;
9091 let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
9092 let eventUiBySource = this.buildEventUiBySource(eventSources);
9093 let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
9094 let newState = {
9095 dynamicOptionOverrides,
9096 currentViewType,
9097 currentDate,
9098 dateProfile,
9099 eventSources,
9100 eventStore,
9101 renderableEventStore,
9102 selectionConfig,
9103 eventUiBases,
9104 businessHours: this.parseContextBusinessHours(calendarContext),
9105 dateSelection: reduceDateSelection(state.dateSelection, action),
9106 eventSelection: reduceSelectedEvent(state.eventSelection, action),
9107 eventDrag: reduceEventDrag(state.eventDrag, action),
9108 eventResize: reduceEventResize(state.eventResize, action),
9109 };
9110 let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
9111 for (let reducer of optionsData.pluginHooks.reducers) {
9112 Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
9113 }
9114 let wasLoading = computeIsLoading(state, calendarContext);
9115 let isLoading = computeIsLoading(newState, calendarContext);
9116 // TODO: use propSetHandlers in plugin system
9117 if (!wasLoading && isLoading) {
9118 emitter.trigger('loading', true);
9119 }
9120 else if (wasLoading && !isLoading) {
9121 emitter.trigger('loading', false);
9122 }
9123 this.state = newState;
9124 if (props.onAction) {
9125 props.onAction(action);
9126 }
9127 }
9128 updateData() {
9129 let { props, state } = this;
9130 let oldData = this.data;
9131 let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
9132 let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
9133 let data = this.data = Object.assign(Object.assign(Object.assign({ nowManager: this.nowManager, viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
9134 let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
9135 let oldCalendarOptions = oldData && oldData.calendarOptions;
9136 let newCalendarOptions = optionsData.calendarOptions;
9137 if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
9138 if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
9139 // hack
9140 state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
9141 state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
9142 state.renderableEventStore = data.renderableEventStore = rezoneEventStoreDates(data.renderableEventStore, oldData.dateEnv, data.dateEnv);
9143 }
9144 for (let optionName in changeHandlers) {
9145 if (this.optionsForHandling.indexOf(optionName) !== -1 ||
9146 oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
9147 changeHandlers[optionName](newCalendarOptions[optionName], data);
9148 }
9149 }
9150 }
9151 this.optionsForHandling = [];
9152 if (props.onData) {
9153 props.onData(data);
9154 }
9155 }
9156 computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
9157 // TODO: blacklist options that are handled by optionChangeHandlers
9158 if (!this.optionsForRefining.length &&
9159 optionOverrides === this.stableOptionOverrides &&
9160 dynamicOptionOverrides === this.stableDynamicOptionOverrides) {
9161 return this.stableCalendarOptionsData;
9162 }
9163 let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
9164 warnUnknownOptions(extra);
9165 let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
9166 let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);
9167 let theme = this.buildTheme(refinedOptions, pluginHooks);
9168 let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);
9169 return this.stableCalendarOptionsData = {
9170 calendarOptions: refinedOptions,
9171 pluginHooks,
9172 dateEnv,
9173 viewSpecs,
9174 theme,
9175 toolbarConfig,
9176 localeDefaults,
9177 availableRawLocales: availableLocaleData.map,
9178 };
9179 }
9180 // always called from behind a memoizer
9181 processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
9182 let { locales, locale } = mergeRawOptions([
9183 BASE_OPTION_DEFAULTS,
9184 optionOverrides,
9185 dynamicOptionOverrides,
9186 ]);
9187 let availableLocaleData = this.organizeRawLocales(locales);
9188 let availableRawLocales = availableLocaleData.map;
9189 let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
9190 let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
9191 let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
9192 let extra = {};
9193 let raw = mergeRawOptions([
9194 BASE_OPTION_DEFAULTS,
9195 localeDefaults,
9196 optionOverrides,
9197 dynamicOptionOverrides,
9198 ]);
9199 let refined = {};
9200 let currentRaw = this.currentCalendarOptionsInput;
9201 let currentRefined = this.currentCalendarOptionsRefined;
9202 let anyChanges = false;
9203 for (let optionName in raw) {
9204 if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (COMPLEX_OPTION_COMPARATORS[optionName] &&
9205 (optionName in currentRaw) &&
9206 COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName])))) {
9207 refined[optionName] = currentRefined[optionName];
9208 }
9209 else if (refiners[optionName]) {
9210 refined[optionName] = refiners[optionName](raw[optionName]);
9211 anyChanges = true;
9212 }
9213 else {
9214 extra[optionName] = currentRaw[optionName];
9215 }
9216 }
9217 if (anyChanges) {
9218 this.currentCalendarOptionsInput = raw;
9219 this.currentCalendarOptionsRefined = refined;
9220 this.stableOptionOverrides = optionOverrides;
9221 this.stableDynamicOptionOverrides = dynamicOptionOverrides;
9222 }
9223 this.optionsForHandling.push(...this.optionsForRefining);
9224 this.optionsForRefining = [];
9225 return {
9226 rawOptions: this.currentCalendarOptionsInput,
9227 refinedOptions: this.currentCalendarOptionsRefined,
9228 pluginHooks,
9229 availableLocaleData,
9230 localeDefaults,
9231 extra,
9232 };
9233 }
9234 _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
9235 let viewSpec = optionsData.viewSpecs[viewType];
9236 if (!viewSpec) {
9237 throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
9238 }
9239 let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
9240 warnUnknownOptions(extra);
9241 this.nowManager.handleInput(optionsData.dateEnv, refinedOptions.now);
9242 let dateProfileGenerator = this.buildDateProfileGenerator({
9243 dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
9244 nowManager: this.nowManager,
9245 duration: viewSpec.duration,
9246 durationUnit: viewSpec.durationUnit,
9247 usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
9248 dateEnv: optionsData.dateEnv,
9249 calendarApi: this.props.calendarApi,
9250 slotMinTime: refinedOptions.slotMinTime,
9251 slotMaxTime: refinedOptions.slotMaxTime,
9252 showNonCurrentDates: refinedOptions.showNonCurrentDates,
9253 dayCount: refinedOptions.dayCount,
9254 dateAlignment: refinedOptions.dateAlignment,
9255 dateIncrement: refinedOptions.dateIncrement,
9256 hiddenDays: refinedOptions.hiddenDays,
9257 weekends: refinedOptions.weekends,
9258 validRangeInput: refinedOptions.validRange,
9259 visibleRangeInput: refinedOptions.visibleRange,
9260 fixedWeekCount: refinedOptions.fixedWeekCount,
9261 });
9262 let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
9263 return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
9264 }
9265 processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
9266 let raw = mergeRawOptions([
9267 BASE_OPTION_DEFAULTS,
9268 viewSpec.optionDefaults,
9269 localeDefaults,
9270 optionOverrides,
9271 viewSpec.optionOverrides,
9272 dynamicOptionOverrides,
9273 ]);
9274 let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
9275 let refined = {};
9276 let currentRaw = this.currentViewOptionsInput;
9277 let currentRefined = this.currentViewOptionsRefined;
9278 let anyChanges = false;
9279 let extra = {};
9280 for (let optionName in raw) {
9281 if (raw[optionName] === currentRaw[optionName] ||
9282 (COMPLEX_OPTION_COMPARATORS[optionName] &&
9283 COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
9284 refined[optionName] = currentRefined[optionName];
9285 }
9286 else {
9287 if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
9288 (COMPLEX_OPTION_COMPARATORS[optionName] &&
9289 COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
9290 if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
9291 refined[optionName] = this.currentCalendarOptionsRefined[optionName];
9292 }
9293 }
9294 else if (refiners[optionName]) {
9295 refined[optionName] = refiners[optionName](raw[optionName]);
9296 }
9297 else {
9298 extra[optionName] = raw[optionName];
9299 }
9300 anyChanges = true;
9301 }
9302 }
9303 if (anyChanges) {
9304 this.currentViewOptionsInput = raw;
9305 this.currentViewOptionsRefined = refined;
9306 }
9307 return {
9308 rawOptions: this.currentViewOptionsInput,
9309 refinedOptions: this.currentViewOptionsRefined,
9310 extra,
9311 };
9312 }
9313 }
9314 function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
9315 let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
9316 return new DateEnv({
9317 calendarSystem: 'gregory',
9318 timeZone,
9319 namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
9320 locale,
9321 weekNumberCalculation,
9322 firstDay,
9323 weekText,
9324 cmdFormatter: pluginHooks.cmdFormatter,
9325 defaultSeparator,
9326 });
9327 }
9328 function buildTheme(options, pluginHooks) {
9329 let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
9330 return new ThemeClass(options);
9331 }
9332 function buildDateProfileGenerator(props) {
9333 let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
9334 return new DateProfileGeneratorClass(props);
9335 }
9336 function buildViewApi(type, getCurrentData, dateEnv) {
9337 return new ViewImpl(type, getCurrentData, dateEnv);
9338 }
9339 function buildEventUiBySource(eventSources) {
9340 return mapHash(eventSources, (eventSource) => eventSource.ui);
9341 }
9342 function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
9343 let eventUiBases = { '': eventUiSingleBase };
9344 for (let defId in eventDefs) {
9345 let def = eventDefs[defId];
9346 if (def.sourceId && eventUiBySource[def.sourceId]) {
9347 eventUiBases[defId] = eventUiBySource[def.sourceId];
9348 }
9349 }
9350 return eventUiBases;
9351 }
9352 function buildViewUiProps(calendarContext) {
9353 let { options } = calendarContext;
9354 return {
9355 eventUiSingleBase: createEventUi({
9356 display: options.eventDisplay,
9357 editable: options.editable,
9358 startEditable: options.eventStartEditable,
9359 durationEditable: options.eventDurationEditable,
9360 constraint: options.eventConstraint,
9361 overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
9362 allow: options.eventAllow,
9363 backgroundColor: options.eventBackgroundColor,
9364 borderColor: options.eventBorderColor,
9365 textColor: options.eventTextColor,
9366 color: options.eventColor,
9367 // classNames: options.eventClassNames // render hook will handle this
9368 }, calendarContext),
9369 selectionConfig: createEventUi({
9370 constraint: options.selectConstraint,
9371 overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
9372 allow: options.selectAllow,
9373 }, calendarContext),
9374 };
9375 }
9376 function computeIsLoading(state, context) {
9377 for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
9378 if (isLoadingFunc(state)) {
9379 return true;
9380 }
9381 }
9382 return false;
9383 }
9384 function parseContextBusinessHours(calendarContext) {
9385 return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
9386 }
9387 function warnUnknownOptions(options, viewName) {
9388 for (let optionName in options) {
9389 console.warn(`Unknown option '${optionName}'` +
9390 (viewName ? ` for view '${viewName}'` : ''));
9391 }
9392 }
9393
9394 class ToolbarSection extends BaseComponent {
9395 render() {
9396 let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
9397 return y('div', { className: 'fc-toolbar-chunk' }, ...children);
9398 }
9399 renderWidgetGroup(widgetGroup) {
9400 let { props } = this;
9401 let { theme } = this.context;
9402 let children = [];
9403 let isOnlyButtons = true;
9404 for (let widget of widgetGroup) {
9405 let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
9406 if (buttonName === 'title') {
9407 isOnlyButtons = false;
9408 children.push(y("h2", { className: "fc-toolbar-title", id: props.titleId }, props.title));
9409 }
9410 else {
9411 let isPressed = buttonName === props.activeButton;
9412 let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
9413 (!props.isPrevEnabled && buttonName === 'prev') ||
9414 (!props.isNextEnabled && buttonName === 'next');
9415 let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
9416 if (isPressed) {
9417 buttonClasses.push(theme.getClass('buttonActive'));
9418 }
9419 children.push(y("button", { type: "button", title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, disabled: isDisabled, "aria-pressed": isPressed, className: buttonClasses.join(' '), onClick: buttonClick }, buttonText || (buttonIcon ? y("span", { className: buttonIcon, role: "img" }) : '')));
9420 }
9421 }
9422 if (children.length > 1) {
9423 let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
9424 return y('div', { className: groupClassName }, ...children);
9425 }
9426 return children[0];
9427 }
9428 }
9429
9430 class Toolbar extends BaseComponent {
9431 render() {
9432 let { model, extraClassName } = this.props;
9433 let forceLtr = false;
9434 let startContent;
9435 let endContent;
9436 let sectionWidgets = model.sectionWidgets;
9437 let centerContent = sectionWidgets.center;
9438 if (sectionWidgets.left) {
9439 forceLtr = true;
9440 startContent = sectionWidgets.left;
9441 }
9442 else {
9443 startContent = sectionWidgets.start;
9444 }
9445 if (sectionWidgets.right) {
9446 forceLtr = true;
9447 endContent = sectionWidgets.right;
9448 }
9449 else {
9450 endContent = sectionWidgets.end;
9451 }
9452 let classNames = [
9453 extraClassName || '',
9454 'fc-toolbar',
9455 forceLtr ? 'fc-toolbar-ltr' : '',
9456 ];
9457 return (y("div", { className: classNames.join(' ') },
9458 this.renderSection('start', startContent || []),
9459 this.renderSection('center', centerContent || []),
9460 this.renderSection('end', endContent || [])));
9461 }
9462 renderSection(key, widgetGroups) {
9463 let { props } = this;
9464 return (y(ToolbarSection, { key: key, widgetGroups: widgetGroups, title: props.title, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled, titleId: props.titleId }));
9465 }
9466 }
9467
9468 class ViewHarness extends BaseComponent {
9469 constructor() {
9470 super(...arguments);
9471 this.state = {
9472 availableWidth: null,
9473 };
9474 this.handleEl = (el) => {
9475 this.el = el;
9476 setRef(this.props.elRef, el);
9477 this.updateAvailableWidth();
9478 };
9479 this.handleResize = () => {
9480 this.updateAvailableWidth();
9481 };
9482 }
9483 render() {
9484 let { props, state } = this;
9485 let { aspectRatio } = props;
9486 let classNames = [
9487 'fc-view-harness',
9488 (aspectRatio || props.liquid || props.height)
9489 ? 'fc-view-harness-active' // harness controls the height
9490 : 'fc-view-harness-passive', // let the view do the height
9491 ];
9492 let height = '';
9493 let paddingBottom = '';
9494 if (aspectRatio) {
9495 if (state.availableWidth !== null) {
9496 height = state.availableWidth / aspectRatio;
9497 }
9498 else {
9499 // while waiting to know availableWidth, we can't set height to *zero*
9500 // because will cause lots of unnecessary scrollbars within scrollgrid.
9501 // BETTER: don't start rendering ANYTHING yet until we know container width
9502 // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
9503 paddingBottom = `${(1 / aspectRatio) * 100}%`;
9504 }
9505 }
9506 else {
9507 height = props.height || '';
9508 }
9509 return (y("div", { "aria-labelledby": props.labeledById, ref: this.handleEl, className: classNames.join(' '), style: { height, paddingBottom } }, props.children));
9510 }
9511 componentDidMount() {
9512 this.context.addResizeHandler(this.handleResize);
9513 }
9514 componentWillUnmount() {
9515 this.context.removeResizeHandler(this.handleResize);
9516 }
9517 updateAvailableWidth() {
9518 if (this.el && // needed. but why?
9519 this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
9520 ) {
9521 this.setState({ availableWidth: this.el.offsetWidth });
9522 }
9523 }
9524 }
9525
9526 /*
9527 Detects when the user clicks on an event within a DateComponent
9528 */
9529 class EventClicking extends Interaction {
9530 constructor(settings) {
9531 super(settings);
9532 this.handleSegClick = (ev, segEl) => {
9533 let { component } = this;
9534 let { context } = component;
9535 let seg = getElSeg(segEl);
9536 if (seg && // might be the <div> surrounding the more link
9537 component.isValidSegDownEl(ev.target)) {
9538 // our way to simulate a link click for elements that can't be <a> tags
9539 // grab before trigger fired in case trigger trashes DOM thru rerendering
9540 let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
9541 let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
9542 context.emitter.trigger('eventClick', {
9543 el: segEl,
9544 event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
9545 jsEvent: ev,
9546 view: context.viewApi,
9547 });
9548 if (url && !ev.defaultPrevented) {
9549 window.location.href = url;
9550 }
9551 }
9552 };
9553 this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
9554 this.handleSegClick);
9555 }
9556 }
9557
9558 /*
9559 Triggers events and adds/removes core classNames when the user's pointer
9560 enters/leaves event-elements of a component.
9561 */
9562 class EventHovering extends Interaction {
9563 constructor(settings) {
9564 super(settings);
9565 // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
9566 this.handleEventElRemove = (el) => {
9567 if (el === this.currentSegEl) {
9568 this.handleSegLeave(null, this.currentSegEl);
9569 }
9570 };
9571 this.handleSegEnter = (ev, segEl) => {
9572 if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
9573 this.currentSegEl = segEl;
9574 this.triggerEvent('eventMouseEnter', ev, segEl);
9575 }
9576 };
9577 this.handleSegLeave = (ev, segEl) => {
9578 if (this.currentSegEl) {
9579 this.currentSegEl = null;
9580 this.triggerEvent('eventMouseLeave', ev, segEl);
9581 }
9582 };
9583 this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
9584 this.handleSegEnter, this.handleSegLeave);
9585 }
9586 destroy() {
9587 this.removeHoverListeners();
9588 }
9589 triggerEvent(publicEvName, ev, segEl) {
9590 let { component } = this;
9591 let { context } = component;
9592 let seg = getElSeg(segEl);
9593 if (!ev || component.isValidSegDownEl(ev.target)) {
9594 context.emitter.trigger(publicEvName, {
9595 el: segEl,
9596 event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
9597 jsEvent: ev,
9598 view: context.viewApi,
9599 });
9600 }
9601 }
9602 }
9603
9604 class CalendarContent extends PureComponent {
9605 constructor() {
9606 super(...arguments);
9607 this.buildViewContext = memoize(buildViewContext);
9608 this.buildViewPropTransformers = memoize(buildViewPropTransformers);
9609 this.buildToolbarProps = memoize(buildToolbarProps);
9610 this.headerRef = d();
9611 this.footerRef = d();
9612 this.interactionsStore = {};
9613 // eslint-disable-next-line
9614 this.state = {
9615 viewLabelId: getUniqueDomId(),
9616 };
9617 // Component Registration
9618 // -----------------------------------------------------------------------------------------------------------------
9619 this.registerInteractiveComponent = (component, settingsInput) => {
9620 let settings = parseInteractionSettings(component, settingsInput);
9621 let DEFAULT_INTERACTIONS = [
9622 EventClicking,
9623 EventHovering,
9624 ];
9625 let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
9626 let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
9627 this.interactionsStore[component.uid] = interactions;
9628 interactionSettingsStore[component.uid] = settings;
9629 };
9630 this.unregisterInteractiveComponent = (component) => {
9631 let listeners = this.interactionsStore[component.uid];
9632 if (listeners) {
9633 for (let listener of listeners) {
9634 listener.destroy();
9635 }
9636 delete this.interactionsStore[component.uid];
9637 }
9638 delete interactionSettingsStore[component.uid];
9639 };
9640 // Resizing
9641 // -----------------------------------------------------------------------------------------------------------------
9642 this.resizeRunner = new DelayedRunner(() => {
9643 this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
9644 this.props.emitter.trigger('windowResize', { view: this.props.viewApi });
9645 });
9646 this.handleWindowResize = (ev) => {
9647 let { options } = this.props;
9648 if (options.handleWindowResize &&
9649 ev.target === window // avoid jqui events
9650 ) {
9651 this.resizeRunner.request(options.windowResizeDelay);
9652 }
9653 };
9654 }
9655 /*
9656 renders INSIDE of an outer div
9657 */
9658 render() {
9659 let { props } = this;
9660 let { toolbarConfig, options } = props;
9661 let viewVGrow = false;
9662 let viewHeight = '';
9663 let viewAspectRatio;
9664 if (props.isHeightAuto || props.forPrint) {
9665 viewHeight = '';
9666 }
9667 else if (options.height != null) {
9668 viewVGrow = true;
9669 }
9670 else if (options.contentHeight != null) {
9671 viewHeight = options.contentHeight;
9672 }
9673 else {
9674 viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
9675 }
9676 let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.nowManager, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
9677 let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle)
9678 ? this.state.viewLabelId
9679 : undefined;
9680 return (y(ViewContextType.Provider, { value: viewContext },
9681 y(NowTimer, { unit: "day" }, (nowDate) => {
9682 let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, nowDate, props.viewTitle);
9683 return (y(_, null,
9684 toolbarConfig.header && (y(Toolbar, Object.assign({ ref: this.headerRef, extraClassName: "fc-header-toolbar", model: toolbarConfig.header, titleId: viewLabelId }, toolbarProps))),
9685 y(ViewHarness, { liquid: viewVGrow, height: viewHeight, aspectRatio: viewAspectRatio, labeledById: viewLabelId },
9686 this.renderView(props),
9687 this.buildAppendContent()),
9688 toolbarConfig.footer && (y(Toolbar, Object.assign({ ref: this.footerRef, extraClassName: "fc-footer-toolbar", model: toolbarConfig.footer, titleId: "" }, toolbarProps)))));
9689 })));
9690 }
9691 componentDidMount() {
9692 let { props } = this;
9693 this.calendarInteractions = props.pluginHooks.calendarInteractions
9694 .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
9695 window.addEventListener('resize', this.handleWindowResize);
9696 let { propSetHandlers } = props.pluginHooks;
9697 for (let propName in propSetHandlers) {
9698 propSetHandlers[propName](props[propName], props);
9699 }
9700 }
9701 componentDidUpdate(prevProps) {
9702 let { props } = this;
9703 let { propSetHandlers } = props.pluginHooks;
9704 for (let propName in propSetHandlers) {
9705 if (props[propName] !== prevProps[propName]) {
9706 propSetHandlers[propName](props[propName], props);
9707 }
9708 }
9709 }
9710 componentWillUnmount() {
9711 window.removeEventListener('resize', this.handleWindowResize);
9712 this.resizeRunner.clear();
9713 for (let interaction of this.calendarInteractions) {
9714 interaction.destroy();
9715 }
9716 this.props.emitter.trigger('_unmount');
9717 }
9718 buildAppendContent() {
9719 let { props } = this;
9720 let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
9721 return y(_, {}, ...children);
9722 }
9723 renderView(props) {
9724 let { pluginHooks } = props;
9725 let { viewSpec } = props;
9726 let viewProps = {
9727 dateProfile: props.dateProfile,
9728 businessHours: props.businessHours,
9729 eventStore: props.renderableEventStore,
9730 eventUiBases: props.eventUiBases,
9731 dateSelection: props.dateSelection,
9732 eventSelection: props.eventSelection,
9733 eventDrag: props.eventDrag,
9734 eventResize: props.eventResize,
9735 isHeightAuto: props.isHeightAuto,
9736 forPrint: props.forPrint,
9737 };
9738 let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
9739 for (let transformer of transformers) {
9740 Object.assign(viewProps, transformer.transform(viewProps, props));
9741 }
9742 let ViewComponent = viewSpec.component;
9743 return (y(ViewComponent, Object.assign({}, viewProps)));
9744 }
9745 }
9746 function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
9747 // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
9748 let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
9749 let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
9750 let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
9751 return {
9752 title,
9753 activeButton: viewSpec.type,
9754 navUnit: viewSpec.singleUnit,
9755 isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
9756 isPrevEnabled: prevInfo.isValid,
9757 isNextEnabled: nextInfo.isValid,
9758 };
9759 }
9760 // Plugin
9761 // -----------------------------------------------------------------------------------------------------------------
9762 function buildViewPropTransformers(theClasses) {
9763 return theClasses.map((TheClass) => new TheClass());
9764 }
9765
9766 class Calendar extends CalendarImpl {
9767 constructor(el, optionOverrides = {}) {
9768 super();
9769 this.isRendering = false;
9770 this.isRendered = false;
9771 this.currentClassNames = [];
9772 this.customContentRenderId = 0;
9773 this.handleAction = (action) => {
9774 // actions we know we want to render immediately
9775 switch (action.type) {
9776 case 'SET_EVENT_DRAG':
9777 case 'SET_EVENT_RESIZE':
9778 this.renderRunner.tryDrain();
9779 }
9780 };
9781 this.handleData = (data) => {
9782 this.currentData = data;
9783 this.renderRunner.request(data.calendarOptions.rerenderDelay);
9784 };
9785 this.handleRenderRequest = () => {
9786 if (this.isRendering) {
9787 this.isRendered = true;
9788 let { currentData } = this;
9789 flushSync(() => {
9790 D$1(y(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, isHeightAuto, forPrint) => {
9791 this.setClassNames(classNames);
9792 this.setHeight(height);
9793 return (y(RenderId.Provider, { value: this.customContentRenderId },
9794 y(CalendarContent, Object.assign({ isHeightAuto: isHeightAuto, forPrint: forPrint }, currentData))));
9795 }), this.el);
9796 });
9797 }
9798 else if (this.isRendered) {
9799 this.isRendered = false;
9800 D$1(null, this.el);
9801 this.setClassNames([]);
9802 this.setHeight('');
9803 }
9804 };
9805 ensureElHasStyles(el);
9806 this.el = el;
9807 this.renderRunner = new DelayedRunner(this.handleRenderRequest);
9808 new CalendarDataManager({
9809 optionOverrides,
9810 calendarApi: this,
9811 onAction: this.handleAction,
9812 onData: this.handleData,
9813 });
9814 }
9815 render() {
9816 let wasRendering = this.isRendering;
9817 if (!wasRendering) {
9818 this.isRendering = true;
9819 }
9820 else {
9821 this.customContentRenderId += 1;
9822 }
9823 this.renderRunner.request();
9824 if (wasRendering) {
9825 this.updateSize();
9826 }
9827 }
9828 destroy() {
9829 if (this.isRendering) {
9830 this.isRendering = false;
9831 this.renderRunner.request();
9832 }
9833 }
9834 updateSize() {
9835 flushSync(() => {
9836 super.updateSize();
9837 });
9838 }
9839 batchRendering(func) {
9840 this.renderRunner.pause('batchRendering');
9841 func();
9842 this.renderRunner.resume('batchRendering');
9843 }
9844 pauseRendering() {
9845 this.renderRunner.pause('pauseRendering');
9846 }
9847 resumeRendering() {
9848 this.renderRunner.resume('pauseRendering', true);
9849 }
9850 resetOptions(optionOverrides, changedOptionNames) {
9851 this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);
9852 }
9853 setClassNames(classNames) {
9854 if (!isArraysEqual(classNames, this.currentClassNames)) {
9855 let { classList } = this.el;
9856 for (let className of this.currentClassNames) {
9857 classList.remove(className);
9858 }
9859 for (let className of classNames) {
9860 classList.add(className);
9861 }
9862 this.currentClassNames = classNames;
9863 }
9864 }
9865 setHeight(height) {
9866 applyStyleProp(this.el, 'height', height);
9867 }
9868 }
9869
9870 function formatDate(dateInput, options = {}) {
9871 let dateEnv = buildDateEnv(options);
9872 let formatter = createFormatter(options);
9873 let dateMeta = dateEnv.createMarkerMeta(dateInput);
9874 if (!dateMeta) { // TODO: warning?
9875 return '';
9876 }
9877 return dateEnv.format(dateMeta.marker, formatter, {
9878 forcedTzo: dateMeta.forcedTzo,
9879 });
9880 }
9881 function formatRange(startInput, endInput, options) {
9882 let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
9883 let formatter = createFormatter(options);
9884 let startMeta = dateEnv.createMarkerMeta(startInput);
9885 let endMeta = dateEnv.createMarkerMeta(endInput);
9886 if (!startMeta || !endMeta) { // TODO: warning?
9887 return '';
9888 }
9889 return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
9890 forcedStartTzo: startMeta.forcedTzo,
9891 forcedEndTzo: endMeta.forcedTzo,
9892 isEndExclusive: options.isEndExclusive,
9893 defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
9894 });
9895 }
9896 // TODO: more DRY and optimized
9897 function buildDateEnv(settings) {
9898 let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
9899 return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
9900 }
9901
9902 // HELPERS
9903 /*
9904 if nextDayThreshold is specified, slicing is done in an all-day fashion.
9905 you can get nextDayThreshold from context.nextDayThreshold
9906 */
9907 function sliceEvents(props, allDay) {
9908 return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
9909 }
9910
9911 const version = '6.1.17';
9912
9913 exports.Calendar = Calendar;
9914 exports.Internal = internal;
9915 exports.JsonRequestError = JsonRequestError;
9916 exports.Preact = preact;
9917 exports.createPlugin = createPlugin;
9918 exports.formatDate = formatDate;
9919 exports.formatRange = formatRange;
9920 exports.globalLocales = globalLocales;
9921 exports.globalPlugins = globalPlugins;
9922 exports.sliceEvents = sliceEvents;
9923 exports.version = version;
9924
9925 Object.defineProperty(exports, '__esModule', { value: true });
9926
9927 return exports;
9928
9929})({});
diff --git a/public/js/fullcalendar/packages/core/index.global.min.js b/public/js/fullcalendar/packages/core/index.global.min.js
new file mode 100644
index 0000000..a875d7a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6var FullCalendar=function(e){"use strict";const t=[],n=new Map;function r(e){t.push(e),n.forEach(t=>{o(t,e)})}function i(e){let r=n.get(e);if(!r||!r.isConnected){if(r=e.querySelector("style[data-fullcalendar]"),!r){r=document.createElement("style"),r.setAttribute("data-fullcalendar","");const t=function(){void 0===s&&(s=function(){const e=document.querySelector('meta[name="csp-nonce"]');if(e&&e.hasAttribute("content"))return e.getAttribute("content");const t=document.querySelector("script[nonce]");if(t)return t.nonce||"";return""}());return s}();t&&(r.nonce=t);const n=e===document?document.head:e,i=e===document?n.querySelector("script,link[rel=stylesheet],link[as=style],style"):n.firstChild;n.insertBefore(r,i)}n.set(e,r),function(e){for(const n of t)o(e,n)}(r)}}function o(e,t){const{sheet:n}=e,r=n.cssRules.length;t.split("}").forEach((e,t)=>{(e=e.trim())&&n.insertRule(e+"}",r+t)})}let s;"undefined"!=typeof document&&i(document);function a(e){e.parentNode&&e.parentNode.removeChild(e)}function l(e,t){if(e.closest)return e.closest(t);if(!document.documentElement.contains(e))return null;do{if(c(e,t))return e;e=e.parentElement||e.parentNode}while(null!==e&&1===e.nodeType);return null}function c(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector).call(e,t)}function u(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].querySelectorAll(t);for(let e=0;e<i.length;e+=1)r.push(i[e])}return r}r(':root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") format("truetype")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:"\\e900"}.fc-icon-chevron-right:before{content:"\\e901"}.fc-icon-chevrons-left:before{content:"\\e902"}.fc-icon-chevrons-right:before{content:"\\e903"}.fc-icon-minus-square:before{content:"\\e904"}.fc-icon-plus-square:before{content:"\\e905"}.fc-icon-x:before{content:"\\e906"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:"";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:"";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}');const d=/(top|left|right|bottom|width|height)$/i;function f(e,t){for(let n in t)h(e,n,t[n])}function h(e,t,n){null==n?e.style[t]="":"number"==typeof n&&d.test(t)?e.style[t]=n+"px":e.style[t]=n}function p(e){var t,n;return null!==(n=null===(t=e.composedPath)||void 0===t?void 0:t.call(e)[0])&&void 0!==n?n:e.target}let g=0;function m(){return g+=1,"fc-dom-"+g}function v(e){e.preventDefault()}function b(e,t,n,r){let i=function(e,t){return n=>{let r=l(n.target,e);r&&t.call(r,n,r)}}(n,r);return e.addEventListener(t,i),()=>{e.removeEventListener(t,i)}}const A=["webkitTransitionEnd","otransitionend","oTransitionEnd","msTransitionEnd","transitionend"];function y(e){return Object.assign({onClick:e},_(e))}function _(e){return{tabIndex:0,onKeyDown(t){"Enter"!==t.key&&" "!==t.key||(e(t),t.preventDefault())}}}let E=0;function D(){return E+=1,String(E)}function C(e){let t,n,r=[],i=[];for("string"==typeof e?i=e.split(/\s*,\s*/):"function"==typeof e?i=[e]:Array.isArray(e)&&(i=e),t=0;t<i.length;t+=1)n=i[t],"string"==typeof n?r.push("-"===n.charAt(0)?{field:n.substring(1),order:-1}:{field:n,order:1}):"function"==typeof n&&r.push({func:n});return r}function w(e,t,n){let r,i;for(r=0;r<n.length;r+=1)if(i=S(e,t,n[r]),i)return i;return 0}function S(e,t,n){return n.func?n.func(e,t):T(e[n.field],t[n.field])*(n.order||1)}function T(e,t){return e||t?null==t?-1:null==e?1:"string"==typeof e||"string"==typeof t?String(e).localeCompare(String(t)):e-t:0}function k(e,t){let n=String(e);return"000".substr(0,t-n.length)+n}function R(e,t,n){return"function"==typeof e?e(...t):"string"==typeof e?t.reduce((e,t,n)=>e.replace("$"+n,t||""),e):n}function x(e){return e%1==0}function O(e){let t=e.querySelector(".fc-scrollgrid-shrink-frame"),n=e.querySelector(".fc-scrollgrid-shrink-cushion");if(!t)throw new Error("needs fc-scrollgrid-shrink-frame className");if(!n)throw new Error("needs fc-scrollgrid-shrink-cushion className");return e.getBoundingClientRect().width-t.getBoundingClientRect().width+n.getBoundingClientRect().width}const M=["years","months","days","milliseconds"],I=/^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;function N(e,t){return"string"==typeof e?function(e){let t=I.exec(e);if(t){let e=t[1]?-1:1;return{years:0,months:0,days:e*(t[2]?parseInt(t[2],10):0),milliseconds:e*(60*(t[3]?parseInt(t[3],10):0)*60*1e3+60*(t[4]?parseInt(t[4],10):0)*1e3+1e3*(t[5]?parseInt(t[5],10):0)+(t[6]?parseInt(t[6],10):0))}}return null}(e):"object"==typeof e&&e?B(e):"number"==typeof e?B({[t||"milliseconds"]:e}):null}function B(e){let t={years:e.years||e.year||0,months:e.months||e.month||0,days:e.days||e.day||0,milliseconds:60*(e.hours||e.hour||0)*60*1e3+60*(e.minutes||e.minute||0)*1e3+1e3*(e.seconds||e.second||0)+(e.milliseconds||e.millisecond||e.ms||0)},n=e.weeks||e.week;return n&&(t.days+=7*n,t.specifiedWeeks=!0),t}function H(e){return P(e)/864e5}function P(e){return 31536e6*e.years+2592e6*e.months+864e5*e.days+e.milliseconds}function U(e){let t=e.milliseconds;if(t){if(t%1e3!=0)return{unit:"millisecond",value:t};if(t%6e4!=0)return{unit:"second",value:t/1e3};if(t%36e5!=0)return{unit:"minute",value:t/6e4};if(t)return{unit:"hour",value:t/36e5}}return e.days?e.specifiedWeeks&&e.days%7==0?{unit:"week",value:e.days/7}:{unit:"day",value:e.days}:e.months?{unit:"month",value:e.months}:e.years?{unit:"year",value:e.years}:{unit:"millisecond",value:0}}const{hasOwnProperty:j}=Object.prototype;function z(e,t){let n={};if(t)for(let r in t)if(t[r]===Ue){let t=[];for(let i=e.length-1;i>=0;i-=1){let o=e[i][r];if("object"==typeof o&&o)t.unshift(o);else if(void 0!==o){n[r]=o;break}}t.length&&(n[r]=z(t))}for(let t=e.length-1;t>=0;t-=1){let r=e[t];for(let e in r)e in n||(n[e]=r[e])}return n}function F(e,t){let n={};for(let r in e)t(e[r],r)&&(n[r]=e[r]);return n}function L(e,t){let n={};for(let r in e)n[r]=t(e[r],r);return n}function V(e){let t={};for(let n of e)t[n]=!0;return t}function W(e){let t=[];for(let n in e)t.push(e[n]);return t}function Q(e,t){if(e===t)return!0;for(let n in e)if(j.call(e,n)&&!(n in t))return!1;for(let n in t)if(j.call(t,n)&&e[n]!==t[n])return!1;return!0}const G=/^on[A-Z]/;function Z(e,t){let n=[];for(let r in e)j.call(e,r)&&(r in t||n.push(r));for(let r in t)j.call(t,r)&&e[r]!==t[r]&&n.push(r);return n}function q(e,t,n={}){if(e===t)return!0;for(let r in t)if(!(r in e)||!Y(e[r],t[r],n[r]))return!1;for(let n in e)if(!(n in t))return!1;return!0}function Y(e,t,n){return e===t||!0===n||!!n&&n(e,t)}function J(e,t=0,n,r=1){let i=[];null==n&&(n=Object.keys(e).length);for(let o=t;o<n;o+=r){let t=e[o];void 0!==t&&i.push(t)}return i}function $(e,t,n){if(e===t)return!0;let r,i=e.length;if(i!==t.length)return!1;for(r=0;r<i;r+=1)if(!(n?n(e[r],t[r]):e[r]===t[r]))return!1;return!0}const X=["sun","mon","tue","wed","thu","fri","sat"];function K(e,t){let n=ue(e);return n[2]+=t,de(n)}function ee(e,t){let n=ue(e);return n[6]+=t,de(n)}function te(e,t){return(t.valueOf()-e.valueOf())/864e5}function ne(e,t){let n=oe(e),r=oe(t);return{years:0,months:0,days:Math.round(te(n,r)),milliseconds:t.valueOf()-r.valueOf()-(e.valueOf()-n.valueOf())}}function re(e,t){let n=ie(e,t);return null!==n&&n%7==0?n/7:null}function ie(e,t){return he(e)===he(t)?Math.round(te(e,t)):null}function oe(e){return de([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()])}function se(e,t,n,r){let i=de([t,0,1+ae(t,n,r)]),o=oe(e),s=Math.round(te(i,o));return Math.floor(s/7)+1}function ae(e,t,n){let r=7+t-n;return-((7+de([e,0,r]).getUTCDay()-t)%7)+r-1}function le(e){return[e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()]}function ce(e){return new Date(e[0],e[1]||0,null==e[2]?1:e[2],e[3]||0,e[4]||0,e[5]||0)}function ue(e){return[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds()]}function de(e){return 1===e.length&&(e=e.concat([0])),new Date(Date.UTC(...e))}function fe(e){return!isNaN(e.valueOf())}function he(e){return 1e3*e.getUTCHours()*60*60+1e3*e.getUTCMinutes()*60+1e3*e.getUTCSeconds()+e.getUTCMilliseconds()}function pe(e,t,n=!1){let r=e.toISOString();return r=r.replace(".000",""),n&&(r=r.replace("T00:00:00Z","")),r.length>10&&(null==t?r=r.replace("Z",""):0!==t&&(r=r.replace("Z",me(t,!0)))),r}function ge(e){return e.toISOString().replace(/T.*$/,"")}function me(e,t=!1){let n=e<0?"-":"+",r=Math.abs(e),i=Math.floor(r/60),o=Math.round(r%60);return t?`${n+k(i,2)}:${k(o,2)}`:`GMT${n}${i}${o?":"+k(o,2):""}`}function ve(e,t,n){let r,i;return function(...o){if(r){if(!$(r,o)){n&&n(i);let r=e.apply(this,o);t&&t(r,i)||(i=r)}}else i=e.apply(this,o);return r=o,i}}function be(e,t,n){let r,i;return o=>{if(r){if(!Q(r,o)){n&&n(i);let r=e.call(this,o);t&&t(r,i)||(i=r)}}else i=e.call(this,o);return r=o,i}}const Ae={week:3,separator:9,omitZeroMinute:9,meridiem:9,omitCommas:9},ye={timeZoneName:7,era:6,year:5,month:4,day:2,weekday:2,hour:1,minute:1,second:1},_e=/\s*([ap])\.?m\.?/i,Ee=/,/g,De=/\s+/g,Ce=/\u200e/g,we=/UTC|GMT/;class Se{constructor(e){let t={},n={},r=9;for(let i in e)if(i in Ae){n[i]=e[i];Ae[i]<9&&(r=Math.min(Ae[i],r))}else t[i]=e[i],i in ye&&(r=Math.min(ye[i],r));this.standardDateProps=t,this.extendedSettings=n,this.smallestUnitNum=r,this.buildFormattingFunc=ve(Te)}format(e,t){return this.buildFormattingFunc(this.standardDateProps,this.extendedSettings,t)(e)}formatRange(e,t,n,r){let{standardDateProps:i,extendedSettings:o}=this,s=function(e,t,n){if(n.getMarkerYear(e)!==n.getMarkerYear(t))return 5;if(n.getMarkerMonth(e)!==n.getMarkerMonth(t))return 4;if(n.getMarkerDay(e)!==n.getMarkerDay(t))return 2;if(he(e)!==he(t))return 1;return 0}(e.marker,t.marker,n.calendarSystem);if(!s)return this.format(e,n);let a=s;!(a>1)||"numeric"!==i.year&&"2-digit"!==i.year||"numeric"!==i.month&&"2-digit"!==i.month||"numeric"!==i.day&&"2-digit"!==i.day||(a=1);let l=this.format(e,n),c=this.format(t,n);if(l===c)return l;let u=Te(function(e,t){let n={};for(let r in e)(!(r in ye)||ye[r]<=t)&&(n[r]=e[r]);return n}(i,a),o,n),d=u(e),f=u(t),h=function(e,t,n,r){let i=0;for(;i<e.length;){let o=e.indexOf(t,i);if(-1===o)break;let s=e.substr(0,o);i=o+t.length;let a=e.substr(i),l=0;for(;l<n.length;){let e=n.indexOf(r,l);if(-1===e)break;let t=n.substr(0,e);l=e+r.length;let i=n.substr(l);if(s===t&&a===i)return{before:s,after:a}}}return null}(l,d,c,f),p=o.separator||r||n.defaultSeparator||"";return h?h.before+d+p+f+h.after:l+p+c}getSmallestUnit(){switch(this.smallestUnitNum){case 7:case 6:case 5:return"year";case 4:return"month";case 3:return"week";case 2:return"day";default:return"time"}}}function Te(e,t,n){let r=Object.keys(e).length;return 1===r&&"short"===e.timeZoneName?e=>me(e.timeZoneOffset):0===r&&t.week?e=>function(e,t,n,r,i){let o=[];"long"===i?o.push(n):"short"!==i&&"narrow"!==i||o.push(t);"long"!==i&&"short"!==i||o.push(" ");o.push(r.simpleNumberFormat.format(e)),"rtl"===r.options.direction&&o.reverse();return o.join("")}(n.computeWeekNumber(e.marker),n.weekText,n.weekTextLong,n.locale,t.week):function(e,t,n){e=Object.assign({},e),t=Object.assign({},t),function(e,t){e.timeZoneName&&(e.hour||(e.hour="2-digit"),e.minute||(e.minute="2-digit"));"long"===e.timeZoneName&&(e.timeZoneName="short");t.omitZeroMinute&&(e.second||e.millisecond)&&delete t.omitZeroMinute}(e,t),e.timeZone="UTC";let r,i=new Intl.DateTimeFormat(n.locale.codes,e);if(t.omitZeroMinute){let t=Object.assign({},e);delete t.minute,r=new Intl.DateTimeFormat(n.locale.codes,t)}return o=>{let s,{marker:a}=o;return s=r&&!a.getUTCMinutes()?r:i,function(e,t,n,r,i){e=e.replace(Ce,""),"short"===n.timeZoneName&&(e=function(e,t){let n=!1;e=e.replace(we,()=>(n=!0,t)),n||(e+=" "+t);return e}(e,"UTC"===i.timeZone||null==t.timeZoneOffset?"UTC":me(t.timeZoneOffset)));r.omitCommas&&(e=e.replace(Ee,"").trim());r.omitZeroMinute&&(e=e.replace(":00",""));!1===r.meridiem?e=e.replace(_e,"").trim():"narrow"===r.meridiem?e=e.replace(_e,(e,t)=>t.toLocaleLowerCase()):"short"===r.meridiem?e=e.replace(_e,(e,t)=>t.toLocaleLowerCase()+"m"):"lowercase"===r.meridiem&&(e=e.replace(_e,e=>e.toLocaleLowerCase()));return e=(e=e.replace(De," ")).trim()}(s.format(a),o,e,t,n)}}(e,t,n)}function ke(e,t){let n=t.markerToArray(e.marker);return{marker:e.marker,timeZoneOffset:e.timeZoneOffset,array:n,year:n[0],month:n[1],day:n[2],hour:n[3],minute:n[4],second:n[5],millisecond:n[6]}}function Re(e,t,n,r){let i=ke(e,n.calendarSystem);return{date:i,start:i,end:t?ke(t,n.calendarSystem):null,timeZone:n.timeZone,localeCodes:n.locale.codes,defaultSeparator:r||n.defaultSeparator}}class xe{constructor(e){this.cmdStr=e}format(e,t,n){return t.cmdFormatter(this.cmdStr,Re(e,null,t,n))}formatRange(e,t,n,r){return n.cmdFormatter(this.cmdStr,Re(e,t,n,r))}}class Oe{constructor(e){this.func=e}format(e,t,n){return this.func(Re(e,null,t,n))}formatRange(e,t,n,r){return this.func(Re(e,t,n,r))}}function Me(e){return"object"==typeof e&&e?new Se(e):"string"==typeof e?new xe(e):"function"==typeof e?new Oe(e):null}const Ie={navLinkDayClick:Ve,navLinkWeekClick:Ve,duration:N,bootstrapFontAwesome:Ve,buttonIcons:Ve,customButtons:Ve,defaultAllDayEventDuration:N,defaultTimedEventDuration:N,nextDayThreshold:N,scrollTime:N,scrollTimeReset:Boolean,slotMinTime:N,slotMaxTime:N,dayPopoverFormat:Me,slotDuration:N,snapDuration:N,headerToolbar:Ve,footerToolbar:Ve,defaultRangeSeparator:String,titleRangeSeparator:String,forceEventDuration:Boolean,dayHeaders:Boolean,dayHeaderFormat:Me,dayHeaderClassNames:Ve,dayHeaderContent:Ve,dayHeaderDidMount:Ve,dayHeaderWillUnmount:Ve,dayCellClassNames:Ve,dayCellContent:Ve,dayCellDidMount:Ve,dayCellWillUnmount:Ve,initialView:String,aspectRatio:Number,weekends:Boolean,weekNumberCalculation:Ve,weekNumbers:Boolean,weekNumberClassNames:Ve,weekNumberContent:Ve,weekNumberDidMount:Ve,weekNumberWillUnmount:Ve,editable:Boolean,viewClassNames:Ve,viewDidMount:Ve,viewWillUnmount:Ve,nowIndicator:Boolean,nowIndicatorClassNames:Ve,nowIndicatorContent:Ve,nowIndicatorDidMount:Ve,nowIndicatorWillUnmount:Ve,showNonCurrentDates:Boolean,lazyFetching:Boolean,startParam:String,endParam:String,timeZoneParam:String,timeZone:String,locales:Ve,locale:Ve,themeSystem:String,dragRevertDuration:Number,dragScroll:Boolean,allDayMaintainDuration:Boolean,unselectAuto:Boolean,dropAccept:Ve,eventOrder:C,eventOrderStrict:Boolean,handleWindowResize:Boolean,windowResizeDelay:Number,longPressDelay:Number,eventDragMinDistance:Number,expandRows:Boolean,height:Ve,contentHeight:Ve,direction:String,weekNumberFormat:Me,eventResizableFromStart:Boolean,displayEventTime:Boolean,displayEventEnd:Boolean,weekText:String,weekTextLong:String,progressiveEventRendering:Boolean,businessHours:Ve,initialDate:Ve,now:Ve,eventDataTransform:Ve,stickyHeaderDates:Ve,stickyFooterScrollbar:Ve,viewHeight:Ve,defaultAllDay:Boolean,eventSourceFailure:Ve,eventSourceSuccess:Ve,eventDisplay:String,eventStartEditable:Boolean,eventDurationEditable:Boolean,eventOverlap:Ve,eventConstraint:Ve,eventAllow:Ve,eventBackgroundColor:String,eventBorderColor:String,eventTextColor:String,eventColor:String,eventClassNames:Ve,eventContent:Ve,eventDidMount:Ve,eventWillUnmount:Ve,selectConstraint:Ve,selectOverlap:Ve,selectAllow:Ve,droppable:Boolean,unselectCancel:String,slotLabelFormat:Ve,slotLaneClassNames:Ve,slotLaneContent:Ve,slotLaneDidMount:Ve,slotLaneWillUnmount:Ve,slotLabelClassNames:Ve,slotLabelContent:Ve,slotLabelDidMount:Ve,slotLabelWillUnmount:Ve,dayMaxEvents:Ve,dayMaxEventRows:Ve,dayMinWidth:Number,slotLabelInterval:N,allDayText:String,allDayClassNames:Ve,allDayContent:Ve,allDayDidMount:Ve,allDayWillUnmount:Ve,slotMinWidth:Number,navLinks:Boolean,eventTimeFormat:Me,rerenderDelay:Number,moreLinkText:Ve,moreLinkHint:Ve,selectMinDistance:Number,selectable:Boolean,selectLongPressDelay:Number,eventLongPressDelay:Number,selectMirror:Boolean,eventMaxStack:Number,eventMinHeight:Number,eventMinWidth:Number,eventShortHeight:Number,slotEventOverlap:Boolean,plugins:Ve,firstDay:Number,dayCount:Number,dateAlignment:String,dateIncrement:N,hiddenDays:Ve,fixedWeekCount:Boolean,validRange:Ve,visibleRange:Ve,titleFormat:Ve,eventInteractive:Boolean,noEventsText:String,viewHint:Ve,navLinkHint:Ve,closeHint:String,timeHint:String,eventHint:String,moreLinkClick:Ve,moreLinkClassNames:Ve,moreLinkContent:Ve,moreLinkDidMount:Ve,moreLinkWillUnmount:Ve,monthStartFormat:Me,handleCustomRendering:Ve,customRenderingMetaMap:Ve,customRenderingReplaces:Boolean},Ne={eventDisplay:"auto",defaultRangeSeparator:" - ",titleRangeSeparator:" – ",defaultTimedEventDuration:"01:00:00",defaultAllDayEventDuration:{day:1},forceEventDuration:!1,nextDayThreshold:"00:00:00",dayHeaders:!0,initialView:"",aspectRatio:1.35,headerToolbar:{start:"title",center:"",end:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberCalculation:"local",editable:!1,nowIndicator:!1,scrollTime:"06:00:00",scrollTimeReset:!0,slotMinTime:"00:00:00",slotMaxTime:"24:00:00",showNonCurrentDates:!0,lazyFetching:!0,startParam:"start",endParam:"end",timeZoneParam:"timeZone",timeZone:"local",locales:[],locale:"",themeSystem:"standard",dragRevertDuration:500,dragScroll:!0,allDayMaintainDuration:!1,unselectAuto:!0,dropAccept:"*",eventOrder:"start,-duration,allDay,title",dayPopoverFormat:{month:"long",day:"numeric",year:"numeric"},handleWindowResize:!0,windowResizeDelay:100,longPressDelay:1e3,eventDragMinDistance:5,expandRows:!1,navLinks:!1,selectable:!1,eventMinHeight:15,eventMinWidth:30,eventShortHeight:30,monthStartFormat:{month:"long",day:"numeric"}},Be={datesSet:Ve,eventsSet:Ve,eventAdd:Ve,eventChange:Ve,eventRemove:Ve,windowResize:Ve,eventClick:Ve,eventMouseEnter:Ve,eventMouseLeave:Ve,select:Ve,unselect:Ve,loading:Ve,_unmount:Ve,_beforeprint:Ve,_afterprint:Ve,_noEventDrop:Ve,_noEventResize:Ve,_resize:Ve,_scrollRequest:Ve},He={buttonText:Ve,buttonHints:Ve,views:Ve,plugins:Ve,initialEvents:Ve,events:Ve,eventSources:Ve},Pe={headerToolbar:Ue,footerToolbar:Ue,buttonText:Ue,buttonHints:Ue,buttonIcons:Ue,dateIncrement:Ue,plugins:je,events:je,eventSources:je,resources:je};function Ue(e,t){return"object"==typeof e&&"object"==typeof t&&e&&t?Q(e,t):e===t}function je(e,t){return Array.isArray(e)&&Array.isArray(t)?$(e,t):e===t}const ze={type:String,component:Ve,buttonText:String,buttonTextKey:String,dateProfileGeneratorClass:Ve,usesMinMaxTime:Boolean,classNames:Ve,content:Ve,didMount:Ve,willUnmount:Ve};function Fe(e){return z(e,Pe)}function Le(e,t){let n={},r={};for(let r in t)r in e&&(n[r]=t[r](e[r]));for(let n in e)n in t||(r[n]=e[n]);return{refined:n,extra:r}}function Ve(e){return e}function We(e,t,n,r){return{instanceId:D(),defId:e,range:t,forcedStartTzo:null==n?null:n,forcedEndTzo:null==r?null:r}}function Qe(e,t,n){let{dateEnv:r,pluginHooks:i,options:o}=n,{defs:s,instances:a}=e;a=F(a,e=>!s[e.defId].recurringDef);for(let e in s){let n=s[e];if(n.recurringDef){let{duration:s}=n.recurringDef;s||(s=n.allDay?o.defaultAllDayEventDuration:o.defaultTimedEventDuration);let l=Ge(n,s,t,r,i.recurringTypes);for(let t of l){let n=We(e,{start:t,end:r.add(t,s)});a[n.instanceId]=n}}}return{defs:s,instances:a}}function Ge(e,t,n,r,i){let o=i[e.recurringDef.typeId].expand(e.recurringDef.typeData,{start:r.subtract(n.start,t),end:n.end},r);return e.allDay&&(o=o.map(oe)),o}function Ze(e,t,n,r,i,o){let s={defs:{},instances:{}},a=ut(n);for(let l of e){let e=lt(l,t,n,r,a,i,o);e&&qe(e,s)}return s}function qe(e,t={defs:{},instances:{}}){return t.defs[e.def.defId]=e.def,e.instance&&(t.instances[e.instance.instanceId]=e.instance),t}function Ye(e,t){let n=e.instances[t];if(n){let t=e.defs[n.defId],r=Xe(e,e=>{return n=t,r=e,Boolean(n.groupId&&n.groupId===r.groupId);var n,r});return r.defs[t.defId]=t,r.instances[n.instanceId]=n,r}return{defs:{},instances:{}}}function Je(){return{defs:{},instances:{}}}function $e(e,t){return{defs:Object.assign(Object.assign({},e.defs),t.defs),instances:Object.assign(Object.assign({},e.instances),t.instances)}}function Xe(e,t){let n=F(e.defs,t),r=F(e.instances,e=>n[e.defId]);return{defs:n,instances:r}}function Ke(e){return Array.isArray(e)?e:"string"==typeof e?e.split(/\s+/):[]}const et={display:String,editable:Boolean,startEditable:Boolean,durationEditable:Boolean,constraint:Ve,overlap:Ve,allow:Ve,className:Ke,classNames:Ke,color:String,backgroundColor:String,borderColor:String,textColor:String},tt={display:null,startEditable:null,durationEditable:null,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]};function nt(e,t){let n=function(e,t){return Array.isArray(e)?Ze(e,null,t,!0):"object"==typeof e&&e?Ze([e],null,t,!0):null!=e?String(e):null}(e.constraint,t);return{display:e.display||null,startEditable:null!=e.startEditable?e.startEditable:e.editable,durationEditable:null!=e.durationEditable?e.durationEditable:e.editable,constraints:null!=n?[n]:[],overlap:null!=e.overlap?e.overlap:null,allows:null!=e.allow?[e.allow]:[],backgroundColor:e.backgroundColor||e.color||"",borderColor:e.borderColor||e.color||"",textColor:e.textColor||"",classNames:(e.className||[]).concat(e.classNames||[])}}function rt(e){return e.reduce(it,tt)}function it(e,t){return{display:null!=t.display?t.display:e.display,startEditable:null!=t.startEditable?t.startEditable:e.startEditable,durationEditable:null!=t.durationEditable?t.durationEditable:e.durationEditable,constraints:e.constraints.concat(t.constraints),overlap:"boolean"==typeof t.overlap?t.overlap:e.overlap,allows:e.allows.concat(t.allows),backgroundColor:t.backgroundColor||e.backgroundColor,borderColor:t.borderColor||e.borderColor,textColor:t.textColor||e.textColor,classNames:e.classNames.concat(t.classNames)}}const ot={id:String,groupId:String,title:String,url:String,interactive:Boolean},st={start:Ve,end:Ve,date:Ve,allDay:Boolean},at=Object.assign(Object.assign(Object.assign({},ot),st),{extendedProps:Ve});function lt(e,t,n,r,i=ut(n),o,s){let{refined:a,extra:l}=ct(e,n,i),c=function(e,t){let n=null;e&&(n=e.defaultAllDay);null==n&&(n=t.options.defaultAllDay);return n}(t,n),u=function(e,t,n,r){for(let i=0;i<r.length;i+=1){let o=r[i].parse(e,n);if(o){let{allDay:n}=e;return null==n&&(n=t,null==n&&(n=o.allDayGuess,null==n&&(n=!1))),{allDay:n,duration:o.duration,typeData:o.typeData,typeId:i}}}return null}(a,c,n.dateEnv,n.pluginHooks.recurringTypes);if(u){let e=dt(a,l,t?t.sourceId:"",u.allDay,Boolean(u.duration),n,o);return e.recurringDef={typeId:u.typeId,typeData:u.typeData,duration:u.duration},{def:e,instance:null}}let d=function(e,t,n,r){let i,o,{allDay:s}=e,a=null,l=!1,c=null,u=null!=e.start?e.start:e.date;if(i=n.dateEnv.createMarkerMeta(u),i)a=i.marker;else if(!r)return null;null!=e.end&&(o=n.dateEnv.createMarkerMeta(e.end));null==s&&(s=null!=t?t:(!i||i.isTimeUnspecified)&&(!o||o.isTimeUnspecified));s&&a&&(a=oe(a));o&&(c=o.marker,s&&(c=oe(c)),a&&c<=a&&(c=null));c?l=!0:r||(l=n.options.forceEventDuration||!1,c=n.dateEnv.add(a,s?n.options.defaultAllDayEventDuration:n.options.defaultTimedEventDuration));return{allDay:s,hasEnd:l,range:{start:a,end:c},forcedStartTzo:i?i.forcedTzo:null,forcedEndTzo:o?o.forcedTzo:null}}(a,c,n,r);if(d){let e=dt(a,l,t?t.sourceId:"",d.allDay,d.hasEnd,n,o),r=We(e.defId,d.range,d.forcedStartTzo,d.forcedEndTzo);return s&&e.publicId&&s[e.publicId]&&(r.instanceId=s[e.publicId]),{def:e,instance:r}}return null}function ct(e,t,n=ut(t)){return Le(e,n)}function ut(e){return Object.assign(Object.assign(Object.assign({},et),at),e.pluginHooks.eventRefiners)}function dt(e,t,n,r,i,o,s){let a={title:e.title||"",groupId:e.groupId||"",publicId:e.id||"",url:e.url||"",recurringDef:null,defId:(s&&e.id?s[e.id]:"")||D(),sourceId:n,allDay:r,hasEnd:i,interactive:e.interactive,ui:nt(e,o),extendedProps:Object.assign(Object.assign({},e.extendedProps||{}),t)};for(let t of o.pluginHooks.eventDefMemberAdders)Object.assign(a,t(e));return Object.freeze(a.ui.classNames),Object.freeze(a.extendedProps),a}const ft={startTime:"09:00",endTime:"17:00",daysOfWeek:[1,2,3,4,5],display:"inverse-background",classNames:"fc-non-business",groupId:"_businessHours"};function ht(e,t){return Ze(function(e){let t;t=!0===e?[{}]:Array.isArray(e)?e.filter(e=>e.daysOfWeek):"object"==typeof e&&e?[e]:[];return t=t.map(e=>Object.assign(Object.assign({},ft),e)),t}(e),null,t)}function pt(e){let t=Math.floor(te(e.start,e.end))||1,n=oe(e.start);return{start:n,end:K(n,t)}}function gt(e,t=N(0)){let n=null,r=null;if(e.end){r=oe(e.end);let n=e.end.valueOf()-r.valueOf();n&&n>=P(t)&&(r=K(r,1))}return e.start&&(n=oe(e.start),r&&r<=n&&(r=K(n,1))),{start:n,end:r}}function mt(e,t,n,r){return"year"===r?N(n.diffWholeYears(e,t),"year"):"month"===r?N(n.diffWholeMonths(e,t),"month"):ne(e,t)}function vt(e,t){let n={left:Math.max(e.left,t.left),right:Math.min(e.right,t.right),top:Math.max(e.top,t.top),bottom:Math.min(e.bottom,t.bottom)};return n.left<n.right&&n.top<n.bottom&&n}let bt;function At(){return null==bt&&(bt=function(){if("undefined"==typeof document)return!0;let e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.innerHTML="<table><tr><td><div></div></td></tr></table>",e.querySelector("table").style.height="100px",e.querySelector("div").style.height="100%",document.body.appendChild(e);let t=e.querySelector("div").offsetHeight>0;return document.body.removeChild(e),t}()),bt}const yt={defs:{},instances:{}};function _t(e,t,n){let r=[];e&&r.push(e),t&&r.push(t);let i={"":rt(r)};return n&&Object.assign(i,n),i}function Et(e,t){let n,r,i=[],{start:o}=t;for(e.sort(Dt),n=0;n<e.length;n+=1)r=e[n],r.start>o&&i.push({start:o,end:r.start}),r.end>o&&(o=r.end);return o<t.end&&i.push({start:o,end:t.end}),i}function Dt(e,t){return e.start.valueOf()-t.start.valueOf()}function Ct(e,t){let{start:n,end:r}=e,i=null;return null!==t.start&&(n=null===n?t.start:new Date(Math.max(n.valueOf(),t.start.valueOf()))),null!=t.end&&(r=null===r?t.end:new Date(Math.min(r.valueOf(),t.end.valueOf()))),(null===n||null===r||n<r)&&(i={start:n,end:r}),i}function wt(e,t){return(null===e.start?null:e.start.valueOf())===(null===t.start?null:t.start.valueOf())&&(null===e.end?null:e.end.valueOf())===(null===t.end?null:t.end.valueOf())}function St(e,t){return(null===e.end||null===t.start||e.end>t.start)&&(null===e.start||null===t.end||e.start<t.end)}function Tt(e,t){return(null===e.start||null!==t.start&&t.start>=e.start)&&(null===e.end||null!==t.end&&t.end<=e.end)}function kt(e,t){return(null===e.start||t>=e.start)&&(null===e.end||t<e.end)}function Rt(e,t,n,r){return{dow:e.getUTCDay(),isDisabled:Boolean(r&&(!r.activeRange||!kt(r.activeRange,e))),isOther:Boolean(r&&!kt(r.currentRange,e)),isToday:Boolean(t&&kt(t,e)),isPast:Boolean(n?e<n:!!t&&e<t.start),isFuture:Boolean(n?e>n:!!t&&e>=t.end)}}function xt(e,t){let n=["fc-day","fc-day-"+X[e.dow]];return e.isDisabled?n.push("fc-day-disabled"):(e.isToday&&(n.push("fc-day-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-day-past"),e.isFuture&&n.push("fc-day-future"),e.isOther&&n.push("fc-day-other")),n}const Ot=Me({year:"numeric",month:"long",day:"numeric"}),Mt=Me({week:"long"});function It(e,t,n="day",r=!0){const{dateEnv:i,options:o,calendarApi:s}=e;let a=i.format(t,"week"===n?Mt:Ot);if(o.navLinks){let e=i.toDate(t);const l=e=>{let r="day"===n?o.navLinkDayClick:"week"===n?o.navLinkWeekClick:null;"function"==typeof r?r.call(s,i.toDate(t),e):("string"==typeof r&&(n=r),s.zoomTo(t,n))};return Object.assign({title:R(o.navLinkHint,[a,e],a),"data-navlink":""},r?y(l):{onClick:l})}return{"aria-label":a}}let Nt,Bt=null;function Ht(){return null===Bt&&(Bt=function(){let e=document.createElement("div");f(e,{position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}),e.innerHTML="<div></div>",document.body.appendChild(e);let t=e.firstChild.getBoundingClientRect().left>e.getBoundingClientRect().left;return a(e),t}()),Bt}function Pt(){return Nt||(Nt=function(){let e=document.createElement("div");e.style.overflow="scroll",e.style.position="absolute",e.style.top="-9999px",e.style.left="-9999px",document.body.appendChild(e);let t=Ut(e);return document.body.removeChild(e),t}()),Nt}function Ut(e){return{x:e.offsetHeight-e.clientHeight,y:e.offsetWidth-e.clientWidth}}function jt(e,t=!1){let n=window.getComputedStyle(e),r=parseInt(n.borderLeftWidth,10)||0,i=parseInt(n.borderRightWidth,10)||0,o=parseInt(n.borderTopWidth,10)||0,s=parseInt(n.borderBottomWidth,10)||0,a=Ut(e),l=a.y-r-i,c={borderLeft:r,borderRight:i,borderTop:o,borderBottom:s,scrollbarBottom:a.x-o-s,scrollbarLeft:0,scrollbarRight:0};return Ht()&&"rtl"===n.direction?c.scrollbarLeft=l:c.scrollbarRight=l,t&&(c.paddingLeft=parseInt(n.paddingLeft,10)||0,c.paddingRight=parseInt(n.paddingRight,10)||0,c.paddingTop=parseInt(n.paddingTop,10)||0,c.paddingBottom=parseInt(n.paddingBottom,10)||0),c}function zt(e){let t=e.getBoundingClientRect();return{left:t.left+window.scrollX,top:t.top+window.scrollY,right:t.right+window.scrollX,bottom:t.bottom+window.scrollY}}function Ft(e){let t=[];for(;e instanceof HTMLElement;){let n=window.getComputedStyle(e);if("fixed"===n.position)break;/(auto|scroll)/.test(n.overflow+n.overflowY+n.overflowX)&&t.push(e),e=e.parentNode}return t}function Lt(e,t,n){let r=!1,i=function(e){r||(r=!0,t(e))},o=function(e){r||(r=!0,n(e))},s=e(i,o);s&&"function"==typeof s.then&&s.then(i,o)}class Vt{constructor(){this.handlers={},this.thisContext=null}setThisContext(e){this.thisContext=e}setOptions(e){this.options=e}on(e,t){!function(e,t,n){(e[t]||(e[t]=[])).push(n)}(this.handlers,e,t)}off(e,t){!function(e,t,n){n?e[t]&&(e[t]=e[t].filter(e=>e!==n)):delete e[t]}(this.handlers,e,t)}trigger(e,...t){let n=this.handlers[e]||[],r=this.options&&this.options[e],i=[].concat(r||[],n);for(let e of i)e.apply(this.thisContext,t)}hasHandlers(e){return Boolean(this.handlers[e]&&this.handlers[e].length||this.options&&this.options[e])}}function Wt(e,t){const n=e.length;if(n!==t.length)return!1;for(let r=0;r<n;r++)if(Math.round(e[r])!==Math.round(t[r]))return!1;return!0}class Qt{getMaxScrollTop(){return this.getScrollHeight()-this.getClientHeight()}getMaxScrollLeft(){return this.getScrollWidth()-this.getClientWidth()}canScrollVertically(){return this.getMaxScrollTop()>0}canScrollHorizontally(){return this.getMaxScrollLeft()>0}canScrollUp(){return this.getScrollTop()>0}canScrollDown(){return this.getScrollTop()<this.getMaxScrollTop()}canScrollLeft(){return this.getScrollLeft()>0}canScrollRight(){return this.getScrollLeft()<this.getMaxScrollLeft()}}class Gt{constructor(e){this.iconOverrideOption&&this.setIconOverride(e[this.iconOverrideOption])}setIconOverride(e){let t,n;if("object"==typeof e&&e){for(n in t=Object.assign({},this.iconClasses),e)t[n]=this.applyIconOverridePrefix(e[n]);this.iconClasses=t}else!1===e&&(this.iconClasses={})}applyIconOverridePrefix(e){let t=this.iconOverridePrefix;return t&&0!==e.indexOf(t)&&(e=t+e),e}getClass(e){return this.classes[e]||""}getIconClass(e,t){let n;return n=t&&this.rtlIconClasses&&this.rtlIconClasses[e]||this.iconClasses[e],n?`${this.baseIconClass} ${n}`:""}getCustomButtonIconClass(e){let t;return this.iconOverrideCustomButtonOption&&(t=e[this.iconOverrideCustomButtonOption],t)?`${this.baseIconClass} ${this.applyIconOverridePrefix(t)}`:""}}Gt.prototype.classes={},Gt.prototype.iconClasses={},Gt.prototype.baseIconClass="",Gt.prototype.iconOverridePrefix="";var Zt,qt,Yt,Jt,$t,Xt,Kt,en,tn,nn={},rn=[],on=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function sn(e,t){for(var n in t)e[n]=t[n];return e}function an(e){var t=e.parentNode;t&&t.removeChild(e)}function ln(e,t,n){var r,i,o,s={};for(o in t)"key"==o?r=t[o]:"ref"==o?i=t[o]:s[o]=t[o];if(arguments.length>2&&(s.children=arguments.length>3?Zt.call(arguments,2):n),"function"==typeof e&&null!=e.defaultProps)for(o in e.defaultProps)void 0===s[o]&&(s[o]=e.defaultProps[o]);return cn(e,s,r,i,null)}function cn(e,t,n,r,i){var o={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==i?++Yt:i};return null==i&&null!=qt.vnode&&qt.vnode(o),o}function un(){return{current:null}}function dn(e){return e.children}function fn(e,t,n){"-"===t[0]?e.setProperty(t,null==n?"":n):e[t]=null==n?"":"number"!=typeof n||on.test(t)?n:n+"px"}function hn(e,t,n,r,i){var o;e:if("style"===t)if("string"==typeof n)e.style.cssText=n;else{if("string"==typeof r&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||fn(e.style,t,"");if(n)for(t in n)r&&n[t]===r[t]||fn(e.style,t,n[t])}else if("o"===t[0]&&"n"===t[1])o=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in e?t.toLowerCase().slice(2):t.slice(2),e.l||(e.l={}),e.l[t+o]=n,n?r||e.addEventListener(t,o?gn:pn,o):e.removeEventListener(t,o?gn:pn,o);else if("dangerouslySetInnerHTML"!==t){if(i)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==t&&"height"!==t&&"href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in e)try{e[t]=null==n?"":n;break e}catch(e){}"function"==typeof n||(null==n||!1===n&&-1==t.indexOf("-")?e.removeAttribute(t):e.setAttribute(t,n))}}function pn(e){$t=!0;try{return this.l[e.type+!1](qt.event?qt.event(e):e)}finally{$t=!1}}function gn(e){$t=!0;try{return this.l[e.type+!0](qt.event?qt.event(e):e)}finally{$t=!1}}function mn(e,t){this.props=e,this.context=t}function vn(e,t){if(null==t)return e.__?vn(e.__,e.__.__k.indexOf(e)+1):null;for(var n;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e)return n.__e;return"function"==typeof e.type?vn(e):null}function bn(e){var t,n;if(null!=(e=e.__)&&null!=e.__c){for(e.__e=e.__c.base=null,t=0;t<e.__k.length;t++)if(null!=(n=e.__k[t])&&null!=n.__e){e.__e=e.__c.base=n.__e;break}return bn(e)}}function An(e){$t?setTimeout(e):en(e)}function yn(e){(!e.__d&&(e.__d=!0)&&Xt.push(e)&&!_n.__r++||Kt!==qt.debounceRendering)&&((Kt=qt.debounceRendering)||An)(_n)}function _n(){var e,t,n,r,i,o,s,a;for(Xt.sort((function(e,t){return e.__v.__b-t.__v.__b}));e=Xt.shift();)e.__d&&(t=Xt.length,r=void 0,i=void 0,s=(o=(n=e).__v).__e,(a=n.__P)&&(r=[],(i=sn({},o)).__v=o.__v+1,Tn(a,o,i,n.__n,void 0!==a.ownerSVGElement,null!=o.__h?[s]:null,r,null==s?vn(o):s,o.__h),kn(r,o),o.__e!=s&&bn(o)),Xt.length>t&&Xt.sort((function(e,t){return e.__v.__b-t.__v.__b})));_n.__r=0}function En(e,t,n,r,i,o,s,a,l,c){var u,d,f,h,p,g,m,v=r&&r.__k||rn,b=v.length;for(n.__k=[],u=0;u<t.length;u++)if(null!=(h=n.__k[u]=null==(h=t[u])||"boolean"==typeof h?null:"string"==typeof h||"number"==typeof h||"bigint"==typeof h?cn(null,h,null,null,h):Array.isArray(h)?cn(dn,{children:h},null,null,null):h.__b>0?cn(h.type,h.props,h.key,h.ref?h.ref:null,h.__v):h)){if(h.__=n,h.__b=n.__b+1,null===(f=v[u])||f&&h.key==f.key&&h.type===f.type)v[u]=void 0;else for(d=0;d<b;d++){if((f=v[d])&&h.key==f.key&&h.type===f.type){v[d]=void 0;break}f=null}Tn(e,h,f=f||nn,i,o,s,a,l,c),p=h.__e,(d=h.ref)&&f.ref!=d&&(m||(m=[]),f.ref&&m.push(f.ref,null,h),m.push(d,h.__c||p,h)),null!=p?(null==g&&(g=p),"function"==typeof h.type&&h.__k===f.__k?h.__d=l=Dn(h,l,e):l=wn(e,h,f,v,p,l),"function"==typeof n.type&&(n.__d=l)):l&&f.__e==l&&l.parentNode!=e&&(l=vn(f))}for(n.__e=g,u=b;u--;)null!=v[u]&&("function"==typeof n.type&&null!=v[u].__e&&v[u].__e==n.__d&&(n.__d=Sn(r).nextSibling),On(v[u],v[u]));if(m)for(u=0;u<m.length;u++)xn(m[u],m[++u],m[++u])}function Dn(e,t,n){for(var r,i=e.__k,o=0;i&&o<i.length;o++)(r=i[o])&&(r.__=e,t="function"==typeof r.type?Dn(r,t,n):wn(n,r,r,i,r.__e,t));return t}function Cn(e,t){return t=t||[],null==e||"boolean"==typeof e||(Array.isArray(e)?e.some((function(e){Cn(e,t)})):t.push(e)),t}function wn(e,t,n,r,i,o){var s,a,l;if(void 0!==t.__d)s=t.__d,t.__d=void 0;else if(null==n||i!=o||null==i.parentNode)e:if(null==o||o.parentNode!==e)e.appendChild(i),s=null;else{for(a=o,l=0;(a=a.nextSibling)&&l<r.length;l+=1)if(a==i)break e;e.insertBefore(i,o),s=o}return void 0!==s?s:i.nextSibling}function Sn(e){var t,n,r;if(null==e.type||"string"==typeof e.type)return e.__e;if(e.__k)for(t=e.__k.length-1;t>=0;t--)if((n=e.__k[t])&&(r=Sn(n)))return r;return null}function Tn(e,t,n,r,i,o,s,a,l){var c,u,d,f,h,p,g,m,v,b,A,y,_,E,D,C=t.type;if(void 0!==t.constructor)return null;null!=n.__h&&(l=n.__h,a=t.__e=n.__e,t.__h=null,o=[a]),(c=qt.__b)&&c(t);try{e:if("function"==typeof C){if(m=t.props,v=(c=C.contextType)&&r[c.__c],b=c?v?v.props.value:c.__:r,n.__c?g=(u=t.__c=n.__c).__=u.__E:("prototype"in C&&C.prototype.render?t.__c=u=new C(m,b):(t.__c=u=new mn(m,b),u.constructor=C,u.render=Mn),v&&v.sub(u),u.props=m,u.state||(u.state={}),u.context=b,u.__n=r,d=u.__d=!0,u.__h=[],u._sb=[]),null==u.__s&&(u.__s=u.state),null!=C.getDerivedStateFromProps&&(u.__s==u.state&&(u.__s=sn({},u.__s)),sn(u.__s,C.getDerivedStateFromProps(m,u.__s))),f=u.props,h=u.state,u.__v=t,d)null==C.getDerivedStateFromProps&&null!=u.componentWillMount&&u.componentWillMount(),null!=u.componentDidMount&&u.__h.push(u.componentDidMount);else{if(null==C.getDerivedStateFromProps&&m!==f&&null!=u.componentWillReceiveProps&&u.componentWillReceiveProps(m,b),!u.__e&&null!=u.shouldComponentUpdate&&!1===u.shouldComponentUpdate(m,u.__s,b)||t.__v===n.__v){for(t.__v!==n.__v&&(u.props=m,u.state=u.__s,u.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.forEach((function(e){e&&(e.__=t)})),A=0;A<u._sb.length;A++)u.__h.push(u._sb[A]);u._sb=[],u.__h.length&&s.push(u);break e}null!=u.componentWillUpdate&&u.componentWillUpdate(m,u.__s,b),null!=u.componentDidUpdate&&u.__h.push((function(){u.componentDidUpdate(f,h,p)}))}if(u.context=b,u.props=m,u.__P=e,y=qt.__r,_=0,"prototype"in C&&C.prototype.render){for(u.state=u.__s,u.__d=!1,y&&y(t),c=u.render(u.props,u.state,u.context),E=0;E<u._sb.length;E++)u.__h.push(u._sb[E]);u._sb=[]}else do{u.__d=!1,y&&y(t),c=u.render(u.props,u.state,u.context),u.state=u.__s}while(u.__d&&++_<25);u.state=u.__s,null!=u.getChildContext&&(r=sn(sn({},r),u.getChildContext())),d||null==u.getSnapshotBeforeUpdate||(p=u.getSnapshotBeforeUpdate(f,h)),D=null!=c&&c.type===dn&&null==c.key?c.props.children:c,En(e,Array.isArray(D)?D:[D],t,n,r,i,o,s,a,l),u.base=t.__e,t.__h=null,u.__h.length&&s.push(u),g&&(u.__E=u.__=null),u.__e=!1}else null==o&&t.__v===n.__v?(t.__k=n.__k,t.__e=n.__e):t.__e=Rn(n.__e,t,n,r,i,o,s,l);(c=qt.diffed)&&c(t)}catch(e){t.__v=null,(l||null!=o)&&(t.__e=a,t.__h=!!l,o[o.indexOf(a)]=null),qt.__e(e,t,n)}}function kn(e,t){qt.__c&&qt.__c(t,e),e.some((function(t){try{e=t.__h,t.__h=[],e.some((function(e){e.call(t)}))}catch(e){qt.__e(e,t.__v)}}))}function Rn(e,t,n,r,i,o,s,a){var l,c,u,d=n.props,f=t.props,h=t.type,p=0;if("svg"===h&&(i=!0),null!=o)for(;p<o.length;p++)if((l=o[p])&&"setAttribute"in l==!!h&&(h?l.localName===h:3===l.nodeType)){e=l,o[p]=null;break}if(null==e){if(null===h)return document.createTextNode(f);e=i?document.createElementNS("http://www.w3.org/2000/svg",h):document.createElement(h,f.is&&f),o=null,a=!1}if(null===h)d===f||a&&e.data===f||(e.data=f);else{if(o=o&&Zt.call(e.childNodes),c=(d=n.props||nn).dangerouslySetInnerHTML,u=f.dangerouslySetInnerHTML,!a){if(null!=o)for(d={},p=0;p<e.attributes.length;p++)d[e.attributes[p].name]=e.attributes[p].value;(u||c)&&(u&&(c&&u.__html==c.__html||u.__html===e.innerHTML)||(e.innerHTML=u&&u.__html||""))}if(function(e,t,n,r,i){var o;for(o in n)"children"===o||"key"===o||o in t||hn(e,o,null,n[o],r);for(o in t)i&&"function"!=typeof t[o]||"children"===o||"key"===o||"value"===o||"checked"===o||n[o]===t[o]||hn(e,o,t[o],n[o],r)}(e,f,d,i,a),u)t.__k=[];else if(p=t.props.children,En(e,Array.isArray(p)?p:[p],t,n,r,i&&"foreignObject"!==h,o,s,o?o[0]:n.__k&&vn(n,0),a),null!=o)for(p=o.length;p--;)null!=o[p]&&an(o[p]);a||("value"in f&&void 0!==(p=f.value)&&(p!==e.value||"progress"===h&&!p||"option"===h&&p!==d.value)&&hn(e,"value",p,d.value,!1),"checked"in f&&void 0!==(p=f.checked)&&p!==e.checked&&hn(e,"checked",p,d.checked,!1))}return e}function xn(e,t,n){try{"function"==typeof e?e(t):e.current=t}catch(e){qt.__e(e,n)}}function On(e,t,n){var r,i;if(qt.unmount&&qt.unmount(e),(r=e.ref)&&(r.current&&r.current!==e.__e||xn(r,null,t)),null!=(r=e.__c)){if(r.componentWillUnmount)try{r.componentWillUnmount()}catch(e){qt.__e(e,t)}r.base=r.__P=null,e.__c=void 0}if(r=e.__k)for(i=0;i<r.length;i++)r[i]&&On(r[i],t,n||"function"!=typeof e.type);n||null==e.__e||an(e.__e),e.__=e.__e=e.__d=void 0}function Mn(e,t,n){return this.constructor(e,n)}function In(e,t,n){var r,i,o;qt.__&&qt.__(e,t),i=(r="function"==typeof n)?null:n&&n.__k||t.__k,o=[],Tn(t,e=(!r&&n||t).__k=ln(dn,null,[e]),i||nn,nn,void 0!==t.ownerSVGElement,!r&&n?[n]:i?null:t.firstChild?Zt.call(t.childNodes):null,o,!r&&n?n:i?i.__e:t.firstChild,r),kn(o,e)}Zt=rn.slice,qt={__e:function(e,t,n,r){for(var i,o,s;t=t.__;)if((i=t.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(e)),s=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(e,r||{}),s=i.__d),s)return i.__E=i}catch(t){e=t}throw e}},Yt=0,Jt=function(e){return null!=e&&void 0===e.constructor},$t=!1,mn.prototype.setState=function(e,t){var n;n=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=sn({},this.state),"function"==typeof e&&(e=e(sn({},n),this.props)),e&&sn(n,e),null!=e&&this.__v&&(t&&this._sb.push(t),yn(this))},mn.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),yn(this))},mn.prototype.render=dn,Xt=[],en="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,_n.__r=0,tn=0;var Nn,Bn,Hn,Pn=[],Un=[],jn=qt.__b,zn=qt.__r,Fn=qt.diffed,Ln=qt.__c,Vn=qt.unmount;function Wn(){for(var e;e=Pn.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(Zn),e.__H.__h.forEach(qn),e.__H.__h=[]}catch(t){e.__H.__h=[],qt.__e(t,e.__v)}}qt.__b=function(e){Nn=null,jn&&jn(e)},qt.__r=function(e){zn&&zn(e);var t=(Nn=e.__c).__H;t&&(Bn===Nn?(t.__h=[],Nn.__h=[],t.__.forEach((function(e){e.__N&&(e.__=e.__N),e.__V=Un,e.__N=e.i=void 0}))):(t.__h.forEach(Zn),t.__h.forEach(qn),t.__h=[])),Bn=Nn},qt.diffed=function(e){Fn&&Fn(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(1!==Pn.push(t)&&Hn===qt.requestAnimationFrame||((Hn=qt.requestAnimationFrame)||Gn)(Wn)),t.__H.__.forEach((function(e){e.i&&(e.__H=e.i),e.__V!==Un&&(e.__=e.__V),e.i=void 0,e.__V=Un}))),Bn=Nn=null},qt.__c=function(e,t){t.some((function(e){try{e.__h.forEach(Zn),e.__h=e.__h.filter((function(e){return!e.__||qn(e)}))}catch(n){t.some((function(e){e.__h&&(e.__h=[])})),t=[],qt.__e(n,e.__v)}})),Ln&&Ln(e,t)},qt.unmount=function(e){Vn&&Vn(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.forEach((function(e){try{Zn(e)}catch(e){t=e}})),n.__H=void 0,t&&qt.__e(t,n.__v))};var Qn="function"==typeof requestAnimationFrame;function Gn(e){var t,n=function(){clearTimeout(r),Qn&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,100);Qn&&(t=requestAnimationFrame(n))}function Zn(e){var t=Nn,n=e.__c;"function"==typeof n&&(e.__c=void 0,n()),Nn=t}function qn(e){var t=Nn;e.__c=e.__(),Nn=t}function Yn(e,t){for(var n in e)if("__source"!==n&&!(n in t))return!0;for(var r in t)if("__source"!==r&&e[r]!==t[r])return!0;return!1}function Jn(e){this.props=e}(Jn.prototype=new mn).isPureReactComponent=!0,Jn.prototype.shouldComponentUpdate=function(e,t){return Yn(this.props,e)||Yn(this.state,t)};var $n=qt.__b;qt.__b=function(e){e.type&&e.type.__f&&e.ref&&(e.props.ref=e.ref,e.ref=null),$n&&$n(e)};var Xn=qt.__e;qt.__e=function(e,t,n,r){if(e.then)for(var i,o=t;o=o.__;)if((i=o.__c)&&i.__c)return null==t.__e&&(t.__e=n.__e,t.__k=n.__k),i.__c(e,t);Xn(e,t,n,r)};var Kn=qt.unmount;function er(){this.__u=0,this.t=null,this.__b=null}function tr(e){var t=e.__.__c;return t&&t.__a&&t.__a(e)}function nr(){this.u=null,this.o=null}qt.unmount=function(e){var t=e.__c;t&&t.__R&&t.__R(),t&&!0===e.__h&&(e.type=null),Kn&&Kn(e)},(er.prototype=new mn).__c=function(e,t){var n=t.__c,r=this;null==r.t&&(r.t=[]),r.t.push(n);var i=tr(r.__v),o=!1,s=function(){o||(o=!0,n.__R=null,i?i(a):a())};n.__R=s;var a=function(){if(!--r.__u){if(r.state.__a){var e=r.state.__a;r.__v.__k[0]=function e(t,n,r){return t&&(t.__v=null,t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)})),t.__c&&t.__c.__P===n&&(t.__e&&r.insertBefore(t.__e,t.__d),t.__c.__e=!0,t.__c.__P=r)),t}(e,e.__c.__P,e.__c.__O)}var t;for(r.setState({__a:r.__b=null});t=r.t.pop();)t.forceUpdate()}},l=!0===t.__h;r.__u++||l||r.setState({__a:r.__b=r.__v.__k[0]}),e.then(s,s)},er.prototype.componentWillUnmount=function(){this.t=[]},er.prototype.render=function(e,t){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),r=this.__v.__k[0].__c;this.__v.__k[0]=function e(t,n,r){return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach((function(e){"function"==typeof e.__c&&e.__c()})),t.__c.__H=null),null!=(t=function(e,t){for(var n in t)e[n]=t[n];return e}({},t)).__c&&(t.__c.__P===r&&(t.__c.__P=n),t.__c=null),t.__k=t.__k&&t.__k.map((function(t){return e(t,n,r)}))),t}(this.__b,n,r.__O=r.__P)}this.__b=null}var i=t.__a&&ln(dn,null,e.fallback);return i&&(i.__h=null),[ln(dn,null,t.__a?null:e.children),i]};var rr=function(e,t,n){if(++n[1]===n[0]&&e.o.delete(t),e.props.revealOrder&&("t"!==e.props.revealOrder[0]||!e.o.size))for(n=e.u;n;){for(;n.length>3;)n.pop()();if(n[1]<n[0])break;e.u=n=n[2]}};function ir(e){return this.getChildContext=function(){return e.context},e.children}function or(e){var t=this,n=e.i;t.componentWillUnmount=function(){In(null,t.l),t.l=null,t.i=null},t.i&&t.i!==n&&t.componentWillUnmount(),e.__v?(t.l||(t.i=n,t.l={nodeType:1,parentNode:n,childNodes:[],appendChild:function(e){this.childNodes.push(e),t.i.appendChild(e)},insertBefore:function(e,n){this.childNodes.push(e),t.i.appendChild(e)},removeChild:function(e){this.childNodes.splice(this.childNodes.indexOf(e)>>>1,1),t.i.removeChild(e)}}),In(ln(ir,{context:t.context},e.__v),t.l)):t.l&&t.componentWillUnmount()}function sr(e,t){var n=ln(or,{__v:e,i:t});return n.containerInfo=t,n}(nr.prototype=new mn).__a=function(e){var t=this,n=tr(t.__v),r=t.o.get(e);return r[0]++,function(i){var o=function(){t.props.revealOrder?(r.push(i),rr(t,e,r)):i()};n?n(o):o()}},nr.prototype.render=function(e){this.u=null,this.o=new Map;var t=Cn(e.children);e.revealOrder&&"b"===e.revealOrder[0]&&t.reverse();for(var n=t.length;n--;)this.o.set(t[n],this.u=[1,0,this.u]);return e.children},nr.prototype.componentDidUpdate=nr.prototype.componentDidMount=function(){var e=this;this.o.forEach((function(t,n){rr(e,n,t)}))};var ar="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,lr=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,cr="undefined"!=typeof document,ur=function(e){return("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(e)};mn.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach((function(e){Object.defineProperty(mn.prototype,e,{configurable:!0,get:function(){return this["UNSAFE_"+e]},set:function(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,value:t})}})}));var dr=qt.event;function fr(){}function hr(){return this.cancelBubble}function pr(){return this.defaultPrevented}qt.event=function(e){return dr&&(e=dr(e)),e.persist=fr,e.isPropagationStopped=hr,e.isDefaultPrevented=pr,e.nativeEvent=e};var gr={configurable:!0,get:function(){return this.class}},mr=qt.vnode;qt.vnode=function(e){var t=e.type,n=e.props,r=n;if("string"==typeof t){var i=-1===t.indexOf("-");for(var o in r={},n){var s=n[o];cr&&"children"===o&&"noscript"===t||"value"===o&&"defaultValue"in n&&null==s||("defaultValue"===o&&"value"in n&&null==n.value?o="value":"download"===o&&!0===s?s="":/ondoubleclick/i.test(o)?o="ondblclick":/^onchange(textarea|input)/i.test(o+t)&&!ur(n.type)?o="oninput":/^onfocus$/i.test(o)?o="onfocusin":/^onblur$/i.test(o)?o="onfocusout":/^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(o)?o=o.toLowerCase():i&&lr.test(o)?o=o.replace(/[A-Z0-9]/g,"-$&").toLowerCase():null===s&&(s=void 0),/^oninput$/i.test(o)&&(o=o.toLowerCase(),r[o]&&(o="oninputCapture")),r[o]=s)}"select"==t&&r.multiple&&Array.isArray(r.value)&&(r.value=Cn(n.children).forEach((function(e){e.props.selected=-1!=r.value.indexOf(e.props.value)}))),"select"==t&&null!=r.defaultValue&&(r.value=Cn(n.children).forEach((function(e){e.props.selected=r.multiple?-1!=r.defaultValue.indexOf(e.props.value):r.defaultValue==e.props.value}))),e.props=r,n.class!=n.className&&(gr.enumerable="className"in n,null!=n.className&&(r.class=n.className),Object.defineProperty(r,"className",gr))}e.$$typeof=ar,mr&&mr(e)};var vr=qt.__r;function br(e){e();let t=qt.debounceRendering,n=[];for(qt.debounceRendering=function(e){n.push(e)},In(ln(Ar,{}),document.createElement("div"));n.length;)n.shift()();qt.debounceRendering=t}qt.__r=function(e){vr&&vr(e),e.__c};class Ar extends mn{render(){return ln("div",{})}componentDidMount(){this.setState({})}}function yr(e){let t=function(e,t){var n={__c:t="__cC"+tn++,__:e,Consumer:function(e,t){return e.children(t)},Provider:function(e){var n,r;return this.getChildContext||(n=[],(r={})[t]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(e){this.props.value!==e.value&&n.some((function(e){e.__e=!0,yn(e)}))},this.sub=function(e){n.push(e);var t=e.componentWillUnmount;e.componentWillUnmount=function(){n.splice(n.indexOf(e),1),t&&t.call(e)}}),e.children}};return n.Provider.__=n.Consumer.contextType=n}(e),n=t.Provider;return t.Provider=function(){let e=!this.getChildContext,t=n.apply(this,arguments);if(e){let e=[];this.shouldComponentUpdate=t=>{this.props.value!==t.value&&e.forEach(e=>{e.context=t.value,e.forceUpdate()})},this.sub=t=>{e.push(t);let n=t.componentWillUnmount;t.componentWillUnmount=()=>{e.splice(e.indexOf(t),1),n&&n.call(t)}}}return t},t}var _r={__proto__:null,flushSync:br,createContext:yr,createPortal:sr,Component:mn,Fragment:dn,cloneElement:function(e,t,n){var r,i,o,s=sn({},e.props);for(o in t)"key"==o?r=t[o]:"ref"==o?i=t[o]:s[o]=t[o];return arguments.length>2&&(s.children=arguments.length>3?Zt.call(arguments,2):n),cn(e.type,s,r||e.key,i||e.ref,null)},createElement:ln,createRef:un,h:ln,hydrate:function e(t,n){In(t,n,e)},get isValidElement(){return Jt},get options(){return qt},render:In,toChildArray:Cn};class Er{constructor(e,t,n,r){this.execFunc=e,this.emitter=t,this.scrollTime=n,this.scrollTimeReset=r,this.handleScrollRequest=e=>{this.queuedRequest=Object.assign({},this.queuedRequest||{},e),this.drain()},t.on("_scrollRequest",this.handleScrollRequest),this.fireInitialScroll()}detach(){this.emitter.off("_scrollRequest",this.handleScrollRequest)}update(e){e&&this.scrollTimeReset?this.fireInitialScroll():this.drain()}fireInitialScroll(){this.handleScrollRequest({time:this.scrollTime})}drain(){this.queuedRequest&&this.execFunc(this.queuedRequest)&&(this.queuedRequest=null)}}const Dr=yr({});function Cr(e,t,n,r,i,o,s,a,l,c,u,d,f,h){return{dateEnv:i,nowManager:o,options:n,pluginHooks:a,emitter:u,dispatch:l,getCurrentData:c,calendarApi:d,viewSpec:e,viewApi:t,dateProfileGenerator:r,theme:s,isRtl:"rtl"===n.direction,addResizeHandler(e){u.on("_resize",e)},removeResizeHandler(e){u.off("_resize",e)},createScrollResponder:e=>new Er(e,u,N(n.scrollTime),n.scrollTimeReset),registerInteractiveComponent:f,unregisterInteractiveComponent:h}}class wr extends mn{shouldComponentUpdate(e,t){return this.debug&&console.log(Z(e,this.props),Z(t,this.state)),!q(this.props,e,this.propEquality)||!q(this.state,t,this.stateEquality)}safeSetState(e){q(this.state,Object.assign(Object.assign({},this.state),e),this.stateEquality)||this.setState(e)}}wr.addPropsEquality=function(e){let t=Object.create(this.prototype.propEquality);Object.assign(t,e),this.prototype.propEquality=t},wr.addStateEquality=function(e){let t=Object.create(this.prototype.stateEquality);Object.assign(t,e),this.prototype.stateEquality=t},wr.contextType=Dr,wr.prototype.propEquality={},wr.prototype.stateEquality={};class Sr extends wr{}function Tr(e,t){"function"==typeof e?e(t):e&&(e.current=t)}Sr.contextType=Dr;class kr extends Sr{constructor(){super(...arguments),this.uid=D()}prepareHits(){}queryHit(e,t,n,r){return null}isValidSegDownEl(e){return!this.props.eventDrag&&!this.props.eventResize&&!l(e,".fc-event-mirror")}isValidDateDownEl(e){return!(l(e,".fc-event:not(.fc-bg-event)")||l(e,".fc-more-link")||l(e,"a[data-navlink]")||l(e,".fc-popover"))}}class Rr{constructor(e){this.props=e,this.initHiddenDays()}buildPrev(e,t,n){let{dateEnv:r}=this.props,i=r.subtract(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,-1,n)}buildNext(e,t,n){let{dateEnv:r}=this.props,i=r.add(r.startOf(t,e.currentRangeUnit),e.dateIncrement);return this.build(i,1,n)}build(e,t,n=!0){let r,i,o,s,a,l,{props:c}=this;var u,d;return r=this.buildValidRange(),r=this.trimHiddenDays(r),n&&(u=e,e=null!=(d=r).start&&u<d.start?d.start:null!=d.end&&u>=d.end?new Date(d.end.valueOf()-1):u),i=this.buildCurrentRangeInfo(e,t),o=/^(year|month|week|day)$/.test(i.unit),s=this.buildRenderRange(this.trimHiddenDays(i.range),i.unit,o),s=this.trimHiddenDays(s),a=s,c.showNonCurrentDates||(a=Ct(a,i.range)),a=this.adjustActiveRange(a),a=Ct(a,r),l=St(i.range,r),kt(s,e)||(e=s.start),{currentDate:e,validRange:r,currentRange:i.range,currentRangeUnit:i.unit,isRangeAllDay:o,activeRange:a,renderRange:s,slotMinTime:c.slotMinTime,slotMaxTime:c.slotMaxTime,isValid:l,dateIncrement:this.buildDateIncrement(i.duration)}}buildValidRange(){let e=this.props.validRangeInput,t="function"==typeof e?e.call(this.props.calendarApi,this.props.dateEnv.toDate(this.props.nowManager.getDateMarker())):e;return this.refineRange(t)||{start:null,end:null}}buildCurrentRangeInfo(e,t){let n,{props:r}=this,i=null,o=null,s=null;return r.duration?(i=r.duration,o=r.durationUnit,s=this.buildRangeFromDuration(e,t,i,o)):(n=this.props.dayCount)?(o="day",s=this.buildRangeFromDayCount(e,t,n)):(s=this.buildCustomVisibleRange(e))?o=r.dateEnv.greatestWholeUnit(s.start,s.end).unit:(i=this.getFallbackDuration(),o=U(i).unit,s=this.buildRangeFromDuration(e,t,i,o)),{duration:i,unit:o,range:s}}getFallbackDuration(){return N({day:1})}adjustActiveRange(e){let{dateEnv:t,usesMinMaxTime:n,slotMinTime:r,slotMaxTime:i}=this.props,{start:o,end:s}=e;return n&&(H(r)<0&&(o=oe(o),o=t.add(o,r)),H(i)>1&&(s=oe(s),s=K(s,-1),s=t.add(s,i))),{start:o,end:s}}buildRangeFromDuration(e,t,n,r){let i,o,s,{dateEnv:a,dateAlignment:l}=this.props;if(!l){let{dateIncrement:e}=this.props;l=e&&P(e)<P(n)?U(e).unit:r}function c(){i=a.startOf(e,l),o=a.add(i,n),s={start:i,end:o}}return H(n)<=1&&this.isHiddenDay(i)&&(i=this.skipHiddenDays(i,t),i=oe(i)),c(),this.trimHiddenDays(s)||(e=this.skipHiddenDays(e,t),c()),s}buildRangeFromDayCount(e,t,n){let r,{dateEnv:i,dateAlignment:o}=this.props,s=0,a=e;o&&(a=i.startOf(a,o)),a=oe(a),a=this.skipHiddenDays(a,t),r=a;do{r=K(r,1),this.isHiddenDay(r)||(s+=1)}while(s<n);return{start:a,end:r}}buildCustomVisibleRange(e){let{props:t}=this,n=t.visibleRangeInput,r="function"==typeof n?n.call(t.calendarApi,t.dateEnv.toDate(e)):n,i=this.refineRange(r);return!i||null!=i.start&&null!=i.end?i:null}buildRenderRange(e,t,n){return e}buildDateIncrement(e){let t,{dateIncrement:n}=this.props;return n||((t=this.props.dateAlignment)?N(1,t):e||N({days:1}))}refineRange(e){if(e){let t=function(e,t){let n=null,r=null;return e.start&&(n=t.createMarker(e.start)),e.end&&(r=t.createMarker(e.end)),n||r?n&&r&&r<n?null:{start:n,end:r}:null}(e,this.props.dateEnv);return t&&(t=gt(t)),t}return null}initHiddenDays(){let e,t=this.props.hiddenDays||[],n=[],r=0;for(!1===this.props.weekends&&t.push(0,6),e=0;e<7;e+=1)(n[e]=-1!==t.indexOf(e))||(r+=1);if(!r)throw new Error("invalid hiddenDays");this.isHiddenDayHash=n}trimHiddenDays(e){let{start:t,end:n}=e;return t&&(t=this.skipHiddenDays(t)),n&&(n=this.skipHiddenDays(n,-1,!0)),null==t||null==n||t<n?{start:t,end:n}:null}isHiddenDay(e){return e instanceof Date&&(e=e.getUTCDay()),this.isHiddenDayHash[e]}skipHiddenDays(e,t=1,n=!1){for(;this.isHiddenDayHash[(e.getUTCDay()+(n?t:0)+7)%7];)e=K(e,t);return e}}function xr(e,t,n){n.emitter.trigger("select",Object.assign(Object.assign({},Or(e,n)),{jsEvent:t?t.origEvent:null,view:n.viewApi||n.calendarApi.view}))}function Or(e,t){let n={};for(let r of t.pluginHooks.dateSpanTransforms)Object.assign(n,r(e,t));var r,i;return Object.assign(n,(r=e,i=t.dateEnv,Object.assign(Object.assign({},ti(r.range,i,r.allDay)),{allDay:r.allDay}))),n}function Mr(e,t,n){let{dateEnv:r,options:i}=n,o=t;return e?(o=oe(o),o=r.add(o,i.defaultAllDayEventDuration)):o=r.add(o,i.defaultTimedEventDuration),o}function Ir(e,t,n,r){let i=Vr(e.defs,t),o={defs:{},instances:{}};for(let t in e.defs){let s=e.defs[t];o.defs[t]=Nr(s,i[t],n,r)}for(let t in e.instances){let s=e.instances[t],a=o.defs[s.defId];o.instances[t]=Br(s,a,i[s.defId],n,r)}return o}function Nr(e,t,n,r){let i=n.standardProps||{};null==i.hasEnd&&t.durationEditable&&(n.startDelta||n.endDelta)&&(i.hasEnd=!0);let o=Object.assign(Object.assign(Object.assign({},e),i),{ui:Object.assign(Object.assign({},e.ui),i.ui)});n.extendedProps&&(o.extendedProps=Object.assign(Object.assign({},o.extendedProps),n.extendedProps));for(let e of r.pluginHooks.eventDefMutationAppliers)e(o,n,r);return!o.hasEnd&&r.options.forceEventDuration&&(o.hasEnd=!0),o}function Br(e,t,n,r,i){let{dateEnv:o}=i,s=r.standardProps&&!0===r.standardProps.allDay,a=r.standardProps&&!1===r.standardProps.hasEnd,l=Object.assign({},e);return s&&(l.range=pt(l.range)),r.datesDelta&&n.startEditable&&(l.range={start:o.add(l.range.start,r.datesDelta),end:o.add(l.range.end,r.datesDelta)}),r.startDelta&&n.durationEditable&&(l.range={start:o.add(l.range.start,r.startDelta),end:l.range.end}),r.endDelta&&n.durationEditable&&(l.range={start:l.range.start,end:o.add(l.range.end,r.endDelta)}),a&&(l.range={start:l.range.start,end:Mr(t.allDay,l.range.start,i)}),t.allDay&&(l.range={start:oe(l.range.start),end:oe(l.range.end)}),l.range.end<l.range.start&&(l.range.end=Mr(t.allDay,l.range.start,i)),l}class Hr{constructor(e,t){this.context=e,this.internalEventSource=t}remove(){this.context.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:this.internalEventSource.sourceId})}refetch(){this.context.dispatch({type:"FETCH_EVENT_SOURCES",sourceIds:[this.internalEventSource.sourceId],isRefetch:!0})}get id(){return this.internalEventSource.publicId}get url(){return this.internalEventSource.meta.url}get format(){return this.internalEventSource.meta.format}}class Pr{constructor(e,t,n){this._context=e,this._def=t,this._instance=n||null}setProp(e,t){if(e in st)console.warn("Could not set date-related prop 'name'. Use one of the date-related methods instead.");else if("id"===e)t=ot[e](t),this.mutate({standardProps:{publicId:t}});else if(e in ot)t=ot[e](t),this.mutate({standardProps:{[e]:t}});else if(e in et){let n=et[e](t);n="color"===e?{backgroundColor:t,borderColor:t}:"editable"===e?{startEditable:t,durationEditable:t}:{[e]:t},this.mutate({standardProps:{ui:n}})}else console.warn(`Could not set prop '${e}'. Use setExtendedProp instead.`)}setExtendedProp(e,t){this.mutate({extendedProps:{[e]:t}})}setStart(e,t={}){let{dateEnv:n}=this._context,r=n.createMarker(e);if(r&&this._instance){let e=mt(this._instance.range.start,r,n,t.granularity);t.maintainDuration?this.mutate({datesDelta:e}):this.mutate({startDelta:e})}}setEnd(e,t={}){let n,{dateEnv:r}=this._context;if((null==e||(n=r.createMarker(e),n))&&this._instance)if(n){let e=mt(this._instance.range.end,n,r,t.granularity);this.mutate({endDelta:e})}else this.mutate({standardProps:{hasEnd:!1}})}setDates(e,t,n={}){let r,{dateEnv:i}=this._context,o={allDay:n.allDay},s=i.createMarker(e);var a,l;if(s&&((null==t||(r=i.createMarker(t),r))&&this._instance)){let e=this._instance.range;!0===n.allDay&&(e=pt(e));let t=mt(e.start,s,i,n.granularity);if(r){let s=mt(e.end,r,i,n.granularity);l=s,(a=t).years===l.years&&a.months===l.months&&a.days===l.days&&a.milliseconds===l.milliseconds?this.mutate({datesDelta:t,standardProps:o}):this.mutate({startDelta:t,endDelta:s,standardProps:o})}else o.hasEnd=!1,this.mutate({datesDelta:t,standardProps:o})}}moveStart(e){let t=N(e);t&&this.mutate({startDelta:t})}moveEnd(e){let t=N(e);t&&this.mutate({endDelta:t})}moveDates(e){let t=N(e);t&&this.mutate({datesDelta:t})}setAllDay(e,t={}){let n={allDay:e},{maintainDuration:r}=t;null==r&&(r=this._context.options.allDayMaintainDuration),this._def.allDay!==e&&(n.hasEnd=r),this.mutate({standardProps:n})}formatRange(e){let{dateEnv:t}=this._context,n=this._instance,r=Me(e);return this._def.hasEnd?t.formatRange(n.range.start,n.range.end,r,{forcedStartTzo:n.forcedStartTzo,forcedEndTzo:n.forcedEndTzo}):t.format(n.range.start,r,{forcedTzo:n.forcedStartTzo})}mutate(e){let t=this._instance;if(t){let n=this._def,r=this._context,{eventStore:i}=r.getCurrentData(),o=Ye(i,t.instanceId);o=Ir(o,{"":{display:"",startEditable:!0,durationEditable:!0,constraints:[],overlap:null,allows:[],backgroundColor:"",borderColor:"",textColor:"",classNames:[]}},e,r);let s=new Pr(r,n,t);this._def=o.defs[n.defId],this._instance=o.instances[t.instanceId],r.dispatch({type:"MERGE_EVENTS",eventStore:o}),r.emitter.trigger("eventChange",{oldEvent:s,event:this,relatedEvents:jr(o,r,t),revert(){r.dispatch({type:"RESET_EVENTS",eventStore:i})}})}}remove(){let e=this._context,t=Ur(this);e.dispatch({type:"REMOVE_EVENTS",eventStore:t}),e.emitter.trigger("eventRemove",{event:this,relatedEvents:[],revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:t})}})}get source(){let{sourceId:e}=this._def;return e?new Hr(this._context,this._context.getCurrentData().eventSources[e]):null}get start(){return this._instance?this._context.dateEnv.toDate(this._instance.range.start):null}get end(){return this._instance&&this._def.hasEnd?this._context.dateEnv.toDate(this._instance.range.end):null}get startStr(){let e=this._instance;return e?this._context.dateEnv.formatIso(e.range.start,{omitTime:this._def.allDay,forcedTzo:e.forcedStartTzo}):""}get endStr(){let e=this._instance;return e&&this._def.hasEnd?this._context.dateEnv.formatIso(e.range.end,{omitTime:this._def.allDay,forcedTzo:e.forcedEndTzo}):""}get id(){return this._def.publicId}get groupId(){return this._def.groupId}get allDay(){return this._def.allDay}get title(){return this._def.title}get url(){return this._def.url}get display(){return this._def.ui.display||"auto"}get startEditable(){return this._def.ui.startEditable}get durationEditable(){return this._def.ui.durationEditable}get constraint(){return this._def.ui.constraints[0]||null}get overlap(){return this._def.ui.overlap}get allow(){return this._def.ui.allows[0]||null}get backgroundColor(){return this._def.ui.backgroundColor}get borderColor(){return this._def.ui.borderColor}get textColor(){return this._def.ui.textColor}get classNames(){return this._def.ui.classNames}get extendedProps(){return this._def.extendedProps}toPlainObject(e={}){let t=this._def,{ui:n}=t,{startStr:r,endStr:i}=this,o={allDay:t.allDay};return t.title&&(o.title=t.title),r&&(o.start=r),i&&(o.end=i),t.publicId&&(o.id=t.publicId),t.groupId&&(o.groupId=t.groupId),t.url&&(o.url=t.url),n.display&&"auto"!==n.display&&(o.display=n.display),e.collapseColor&&n.backgroundColor&&n.backgroundColor===n.borderColor?o.color=n.backgroundColor:(n.backgroundColor&&(o.backgroundColor=n.backgroundColor),n.borderColor&&(o.borderColor=n.borderColor)),n.textColor&&(o.textColor=n.textColor),n.classNames.length&&(o.classNames=n.classNames),Object.keys(t.extendedProps).length&&(e.collapseExtendedProps?Object.assign(o,t.extendedProps):o.extendedProps=t.extendedProps),o}toJSON(){return this.toPlainObject()}}function Ur(e){let t=e._def,n=e._instance;return{defs:{[t.defId]:t},instances:n?{[n.instanceId]:n}:{}}}function jr(e,t,n){let{defs:r,instances:i}=e,o=[],s=n?n.instanceId:"";for(let e in i){let n=i[e],a=r[n.defId];n.instanceId!==s&&o.push(new Pr(t,a,n))}return o}function zr(e,t,n,r){let i={},o={},s={},a=[],l=[],c=Vr(e.defs,t);for(let t in e.defs){let n=e.defs[t];"inverse-background"===c[n.defId].display&&(n.groupId?(i[n.groupId]=[],s[n.groupId]||(s[n.groupId]=n)):o[t]=[])}for(let t in e.instances){let s=e.instances[t],u=e.defs[s.defId],d=c[u.defId],f=s.range,h=!u.allDay&&r?gt(f,r):f,p=Ct(h,n);p&&("inverse-background"===d.display?u.groupId?i[u.groupId].push(p):o[s.defId].push(p):"none"!==d.display&&("background"===d.display?a:l).push({def:u,ui:d,instance:s,range:p,isStart:h.start&&h.start.valueOf()===p.start.valueOf(),isEnd:h.end&&h.end.valueOf()===p.end.valueOf()}))}for(let e in i){let t=Et(i[e],n);for(let n of t){let t=s[e],r=c[t.defId];a.push({def:t,ui:r,instance:null,range:n,isStart:!1,isEnd:!1})}}for(let t in o){let r=Et(o[t],n);for(let n of r)a.push({def:e.defs[t],ui:c[t],instance:null,range:n,isStart:!1,isEnd:!1})}return{bg:a,fg:l}}function Fr(e,t){e.fcSeg=t}function Lr(e){return e.fcSeg||e.parentNode.fcSeg||null}function Vr(e,t){return L(e,e=>Wr(e,t))}function Wr(e,t){let n=[];return t[""]&&n.push(t[""]),t[e.defId]&&n.push(t[e.defId]),n.push(e.ui),rt(n)}function Qr(e){let{eventRange:t}=e,n=t.def,r=t.instance?t.instance.range:t.range,i=r.start?r.start.valueOf():0,o=r.end?r.end.valueOf():0;return Object.assign(Object.assign(Object.assign({},n.extendedProps),n),{id:n.publicId,start:i,end:o,duration:o-i,allDay:Number(n.allDay),_seg:e})}function Gr(e,t){let{pluginHooks:n}=t,r=n.isDraggableTransformers,{def:i,ui:o}=e.eventRange,s=o.startEditable;for(let e of r)s=e(s,i,o,t);return s}function Zr(e,t){return e.isStart&&e.eventRange.ui.durationEditable&&t.options.eventResizableFromStart}function qr(e,t){return e.isEnd&&e.eventRange.ui.durationEditable}function Yr(e,t,n,r,i,o,s){let{dateEnv:a,options:l}=n,{displayEventTime:c,displayEventEnd:u}=l,d=e.eventRange.def,f=e.eventRange.instance;null==c&&(c=!1!==r),null==u&&(u=!1!==i);let h=f.range.start,p=f.range.end,g=o||e.start||e.eventRange.range.start,m=s||e.end||e.eventRange.range.end,v=oe(h).valueOf()===oe(g).valueOf(),b=oe(ee(p,-1)).valueOf()===oe(ee(m,-1)).valueOf();return c&&!d.allDay&&(v||b)?(g=v?h:g,m=b?p:m,u&&d.hasEnd?a.formatRange(g,m,t,{forcedStartTzo:o?null:f.forcedStartTzo,forcedEndTzo:s?null:f.forcedEndTzo}):a.format(g,t,{forcedTzo:o?null:f.forcedStartTzo})):""}function Jr(e){let t=["fc-event"];return e.isMirror&&t.push("fc-event-mirror"),e.isDraggable&&t.push("fc-event-draggable"),(e.isStartResizable||e.isEndResizable)&&t.push("fc-event-resizable"),e.isDragging&&t.push("fc-event-dragging"),e.isResizing&&t.push("fc-event-resizing"),e.isSelected&&t.push("fc-event-selected"),e.isStart&&t.push("fc-event-start"),e.isEnd&&t.push("fc-event-end"),e.isPast&&t.push("fc-event-past"),e.isToday&&t.push("fc-event-today"),e.isFuture&&t.push("fc-event-future"),t}function $r(e,t){let{def:n,instance:r}=e.eventRange,{url:i}=n;if(i)return{href:i};let{emitter:o,options:s}=t,{eventInteractive:a}=s;return null==a&&(a=n.interactive,null==a&&(a=Boolean(o.hasHandlers("eventClick")))),a?_(e=>{o.trigger("eventClick",{el:e.target,event:new Pr(t,n,r),jsEvent:e,view:t.viewApi})}):{}}const Xr={start:Ve,end:Ve,allDay:Boolean};function Kr(e,t,n){let r=function(e,t){let{refined:n,extra:r}=Le(e,Xr),i=n.start?t.createMarkerMeta(n.start):null,o=n.end?t.createMarkerMeta(n.end):null,{allDay:s}=n;null==s&&(s=i&&i.isTimeUnspecified&&(!o||o.isTimeUnspecified));return Object.assign({range:{start:i?i.marker:null,end:o?o.marker:null},allDay:s},r)}(e,t),{range:i}=r;if(!i.start)return null;if(!i.end){if(null==n)return null;i.end=t.add(i.start,n)}return r}function ei(e,t,n){return Object.assign(Object.assign({},ti(e,t,n)),{timeZone:t.timeZone})}function ti(e,t,n){return{start:t.toDate(e.start),end:t.toDate(e.end),startStr:t.formatIso(e.start,{omitTime:n}),endStr:t.formatIso(e.end,{omitTime:n})}}let ni={};var ri,ii;ri="gregory",ii=class{getMarkerYear(e){return e.getUTCFullYear()}getMarkerMonth(e){return e.getUTCMonth()}getMarkerDay(e){return e.getUTCDate()}arrayToMarker(e){return de(e)}markerToArray(e){return ue(e)}},ni[ri]=ii;const oi=/^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;function si(e){let t=oi.exec(e);if(t){let e=new Date(Date.UTC(Number(t[1]),t[3]?Number(t[3])-1:0,Number(t[5]||1),Number(t[7]||0),Number(t[8]||0),Number(t[10]||0),t[12]?1e3*Number("0."+t[12]):0));if(fe(e)){let n=null;return t[13]&&(n=("-"===t[15]?-1:1)*(60*Number(t[16]||0)+Number(t[18]||0))),{marker:e,isTimeUnspecified:!t[6],timeZoneOffset:n}}}return null}class ai{constructor(e){let t=this.timeZone=e.timeZone,n="local"!==t&&"UTC"!==t;e.namedTimeZoneImpl&&n&&(this.namedTimeZoneImpl=new e.namedTimeZoneImpl(t)),this.canComputeOffset=Boolean(!n||this.namedTimeZoneImpl),this.calendarSystem=function(e){return new ni[e]}(e.calendarSystem),this.locale=e.locale,this.weekDow=e.locale.week.dow,this.weekDoy=e.locale.week.doy,"ISO"===e.weekNumberCalculation&&(this.weekDow=1,this.weekDoy=4),"number"==typeof e.firstDay&&(this.weekDow=e.firstDay),"function"==typeof e.weekNumberCalculation&&(this.weekNumberFunc=e.weekNumberCalculation),this.weekText=null!=e.weekText?e.weekText:e.locale.options.weekText,this.weekTextLong=(null!=e.weekTextLong?e.weekTextLong:e.locale.options.weekTextLong)||this.weekText,this.cmdFormatter=e.cmdFormatter,this.defaultSeparator=e.defaultSeparator}createMarker(e){let t=this.createMarkerMeta(e);return null===t?null:t.marker}createNowMarker(){return this.canComputeOffset?this.timestampToMarker((new Date).valueOf()):de(le(new Date))}createMarkerMeta(e){if("string"==typeof e)return this.parse(e);let t=null;return"number"==typeof e?t=this.timestampToMarker(e):e instanceof Date?(e=e.valueOf(),isNaN(e)||(t=this.timestampToMarker(e))):Array.isArray(e)&&(t=de(e)),null!==t&&fe(t)?{marker:t,isTimeUnspecified:!1,forcedTzo:null}:null}parse(e){let t=si(e);if(null===t)return null;let{marker:n}=t,r=null;return null!==t.timeZoneOffset&&(this.canComputeOffset?n=this.timestampToMarker(n.valueOf()-60*t.timeZoneOffset*1e3):r=t.timeZoneOffset),{marker:n,isTimeUnspecified:t.isTimeUnspecified,forcedTzo:r}}getYear(e){return this.calendarSystem.getMarkerYear(e)}getMonth(e){return this.calendarSystem.getMarkerMonth(e)}getDay(e){return this.calendarSystem.getMarkerDay(e)}add(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t.years,n[1]+=t.months,n[2]+=t.days,n[6]+=t.milliseconds,this.calendarSystem.arrayToMarker(n)}subtract(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]-=t.years,n[1]-=t.months,n[2]-=t.days,n[6]-=t.milliseconds,this.calendarSystem.arrayToMarker(n)}addYears(e,t){let n=this.calendarSystem.markerToArray(e);return n[0]+=t,this.calendarSystem.arrayToMarker(n)}addMonths(e,t){let n=this.calendarSystem.markerToArray(e);return n[1]+=t,this.calendarSystem.arrayToMarker(n)}diffWholeYears(e,t){let{calendarSystem:n}=this;return he(e)===he(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)&&n.getMarkerMonth(e)===n.getMarkerMonth(t)?n.getMarkerYear(t)-n.getMarkerYear(e):null}diffWholeMonths(e,t){let{calendarSystem:n}=this;return he(e)===he(t)&&n.getMarkerDay(e)===n.getMarkerDay(t)?n.getMarkerMonth(t)-n.getMarkerMonth(e)+12*(n.getMarkerYear(t)-n.getMarkerYear(e)):null}greatestWholeUnit(e,t){let n=this.diffWholeYears(e,t);return null!==n?{unit:"year",value:n}:(n=this.diffWholeMonths(e,t),null!==n?{unit:"month",value:n}:(n=re(e,t),null!==n?{unit:"week",value:n}:(n=ie(e,t),null!==n?{unit:"day",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/36e5}(e,t),x(n)?{unit:"hour",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/6e4}(e,t),x(n)?{unit:"minute",value:n}:(n=function(e,t){return(t.valueOf()-e.valueOf())/1e3}(e,t),x(n)?{unit:"second",value:n}:{unit:"millisecond",value:t.valueOf()-e.valueOf()}))))))}countDurationsBetween(e,t,n){let r;return n.years&&(r=this.diffWholeYears(e,t),null!==r)?r/(H(n)/365):n.months&&(r=this.diffWholeMonths(e,t),null!==r)?r/function(e){return H(e)/30}(n):n.days&&(r=ie(e,t),null!==r)?r/H(n):(t.valueOf()-e.valueOf())/P(n)}startOf(e,t){return"year"===t?this.startOfYear(e):"month"===t?this.startOfMonth(e):"week"===t?this.startOfWeek(e):"day"===t?oe(e):"hour"===t?function(e){return de([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours()])}(e):"minute"===t?function(e){return de([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes()])}(e):"second"===t?function(e){return de([e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds()])}(e):null}startOfYear(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e)])}startOfMonth(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e)])}startOfWeek(e){return this.calendarSystem.arrayToMarker([this.calendarSystem.getMarkerYear(e),this.calendarSystem.getMarkerMonth(e),e.getUTCDate()-(e.getUTCDay()-this.weekDow+7)%7])}computeWeekNumber(e){return this.weekNumberFunc?this.weekNumberFunc(this.toDate(e)):function(e,t,n){let r=e.getUTCFullYear(),i=se(e,r,t,n);if(i<1)return se(e,r-1,t,n);let o=se(e,r+1,t,n);return o>=1?Math.min(i,o):i}(e,this.weekDow,this.weekDoy)}format(e,t,n={}){return t.format({marker:e,timeZoneOffset:null!=n.forcedTzo?n.forcedTzo:this.offsetForMarker(e)},this)}formatRange(e,t,n,r={}){return r.isEndExclusive&&(t=ee(t,-1)),n.formatRange({marker:e,timeZoneOffset:null!=r.forcedStartTzo?r.forcedStartTzo:this.offsetForMarker(e)},{marker:t,timeZoneOffset:null!=r.forcedEndTzo?r.forcedEndTzo:this.offsetForMarker(t)},this,r.defaultSeparator)}formatIso(e,t={}){let n=null;return t.omitTimeZoneOffset||(n=null!=t.forcedTzo?t.forcedTzo:this.offsetForMarker(e)),pe(e,n,t.omitTime)}timestampToMarker(e){return"local"===this.timeZone?de(le(new Date(e))):"UTC"!==this.timeZone&&this.namedTimeZoneImpl?de(this.namedTimeZoneImpl.timestampToArray(e)):new Date(e)}offsetForMarker(e){return"local"===this.timeZone?-ce(ue(e)).getTimezoneOffset():"UTC"===this.timeZone?0:this.namedTimeZoneImpl?this.namedTimeZoneImpl.offsetForArray(ue(e)):null}toDate(e,t){return"local"===this.timeZone?ce(ue(e)):"UTC"===this.timeZone?new Date(e.valueOf()):this.namedTimeZoneImpl?new Date(e.valueOf()-1e3*this.namedTimeZoneImpl.offsetForArray(ue(e))*60):new Date(e.valueOf()-(t||0))}}function li(e){return e.span.end}function ci(e){return e.index+":"+e.span.start}function ui(e,t){let n=Math.max(e.start,t.start),r=Math.min(e.end,t.end);return n<r?{start:n,end:r}:null}function di(e,t,n){e.splice(t,0,n)}function fi(e,t,n){let r=0,i=e.length;if(!i||t<n(e[r]))return[0,0];if(t>n(e[i-1]))return[i,0];for(;r<i;){let o=Math.floor(r+(i-r)/2),s=n(e[o]);if(t<s)i=o;else{if(!(t>s))return[o,1];r=o+1}}return[r,0]}class hi{constructor(e){this.component=e.component,this.isHitComboAllowed=e.isHitComboAllowed||null}destroy(){}}const pi={};const gi={startTime:N,duration:N,create:Boolean,sourceId:String};class mi extends Sr{constructor(){super(...arguments),this.state={forPrint:!1},this.handleBeforePrint=()=>{br(()=>{this.setState({forPrint:!0})})},this.handleAfterPrint=()=>{br(()=>{this.setState({forPrint:!1})})}}render(){let{props:e}=this,{options:t}=e,{forPrint:n}=this.state,r=n||"auto"===t.height||"auto"===t.contentHeight,i=r||null==t.height?"":t.height,o=["fc",n?"fc-media-print":"fc-media-screen","fc-direction-"+t.direction,e.theme.getClass("root")];return At()||o.push("fc-liquid-hack"),e.children(o,i,r,n)}componentDidMount(){let{emitter:e}=this.props;e.on("_beforeprint",this.handleBeforePrint),e.on("_afterprint",this.handleAfterPrint)}componentWillUnmount(){let{emitter:e}=this.props;e.off("_beforeprint",this.handleBeforePrint),e.off("_afterprint",this.handleAfterPrint)}}function vi(e,t){return Me(!e||t>10?{weekday:"short"}:t>1?{weekday:"short",month:"numeric",day:"numeric",omitCommas:!0}:{weekday:"long"})}const bi="fc-col-header-cell";function Ai(e){return e.text}class yi extends Sr{constructor(){super(...arguments),this.id=D(),this.queuedDomNodes=[],this.currentDomNodes=[],this.handleEl=e=>{const{options:t}=this.context,{generatorName:n}=this.props;t.customRenderingReplaces&&_i(n,t)||this.updateElRef(e)},this.updateElRef=e=>{this.props.elRef&&Tr(this.props.elRef,e)}}render(){const{props:e,context:t}=this,{options:n}=t,{customGenerator:r,defaultGenerator:i,renderProps:o}=e,s=Ei(e,[],this.handleEl);let a,l,c=!1,u=[];if(null!=r){const e="function"==typeof r?r(o,ln):r;if(!0===e)c=!0;else{const t=e&&"object"==typeof e;t&&"html"in e?s.dangerouslySetInnerHTML={__html:e.html}:t&&"domNodes"in e?u=Array.prototype.slice.call(e.domNodes):(t?Jt(e):"function"!=typeof e)?a=e:l=e}}else c=!_i(e.generatorName,n);return c&&i&&(a=i(o)),this.queuedDomNodes=u,this.currentGeneratorMeta=l,ln(e.elTag,s,a)}componentDidMount(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentDidUpdate(){this.applyQueueudDomNodes(),this.triggerCustomRendering(!0)}componentWillUnmount(){this.triggerCustomRendering(!1)}triggerCustomRendering(e){var t;const{props:n,context:r}=this,{handleCustomRendering:i,customRenderingMetaMap:o}=r.options;if(i){const r=null!==(t=this.currentGeneratorMeta)&&void 0!==t?t:null==o?void 0:o[n.generatorName];r&&i(Object.assign(Object.assign({id:this.id,isActive:e,containerEl:this.base,reportNewContainerEl:this.updateElRef,generatorMeta:r},n),{elClasses:(n.elClasses||[]).filter(Di)}))}}applyQueueudDomNodes(){const{queuedDomNodes:e,currentDomNodes:t}=this,n=this.base;if(!$(e,t)){t.forEach(a);for(let t of e)n.appendChild(t);this.currentDomNodes=e}}}function _i(e,t){var n;return Boolean(t.handleCustomRendering&&e&&(null===(n=t.customRenderingMetaMap)||void 0===n?void 0:n[e]))}function Ei(e,t,n){const r=Object.assign(Object.assign({},e.elAttrs),{ref:n});return(e.elClasses||t)&&(r.className=(e.elClasses||[]).concat(t||[]).concat(r.className||[]).filter(Boolean).join(" ")),e.elStyle&&(r.style=e.elStyle),r}function Di(e){return Boolean(e)}yi.addPropsEquality({elClasses:$,elStyle:Q,elAttrs:function(e,t){const n=Z(e,t);for(let e of n)if(!G.test(e))return!1;return!0},renderProps:Q});const Ci=yr(0);class wi extends mn{constructor(){super(...arguments),this.InnerContent=Si.bind(void 0,this),this.handleEl=e=>{this.el=e,this.props.elRef&&(Tr(this.props.elRef,e),e&&this.didMountMisfire&&this.componentDidMount())}}render(){const{props:e}=this,t=function(e,t){const n="function"==typeof e?e(t):e||[];return"string"==typeof n?[n]:n}(e.classNameGenerator,e.renderProps);if(e.children){const n=Ei(e,t,this.handleEl),r=e.children(this.InnerContent,e.renderProps,n);return e.elTag?ln(e.elTag,n,r):r}return ln(yi,Object.assign(Object.assign({},e),{elRef:this.handleEl,elTag:e.elTag||"div",elClasses:(e.elClasses||[]).concat(t),renderId:this.context}))}componentDidMount(){var e,t;this.el?null===(t=(e=this.props).didMount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.el})):this.didMountMisfire=!0}componentWillUnmount(){var e,t;null===(t=(e=this.props).willUnmount)||void 0===t||t.call(e,Object.assign(Object.assign({},this.props.renderProps),{el:this.el}))}}function Si(e,t){const n=e.props;return ln(yi,Object.assign({renderProps:n.renderProps,generatorName:n.generatorName,customGenerator:n.customGenerator,defaultGenerator:n.defaultGenerator,renderId:e.context},t))}wi.contextType=Ci;class Ti extends Sr{render(){let{dateEnv:e,options:t,theme:n,viewApi:r}=this.context,{props:i}=this,{date:o,dateProfile:s}=i,a=Rt(o,i.todayRange,null,s),l=[bi].concat(xt(a,n)),c=e.format(o,i.dayHeaderFormat),u=!a.isDisabled&&i.colCnt>1?It(this.context,o):{},d=e.toDate(o);e.namedTimeZoneImpl&&(d=ee(d,36e5));let f=Object.assign(Object.assign(Object.assign({date:d,view:r},i.extraRenderProps),{text:c}),a);return ln(wi,{elTag:"th",elClasses:l,elAttrs:Object.assign({role:"columnheader",colSpan:i.colSpan,"data-date":a.isDisabled?void 0:ge(o)},i.extraDataAttrs),renderProps:f,generatorName:"dayHeaderContent",customGenerator:t.dayHeaderContent,defaultGenerator:Ai,classNameGenerator:t.dayHeaderClassNames,didMount:t.dayHeaderDidMount,willUnmount:t.dayHeaderWillUnmount},e=>ln("div",{className:"fc-scrollgrid-sync-inner"},!a.isDisabled&&ln(e,{elTag:"a",elAttrs:u,elClasses:["fc-col-header-cell-cushion",i.isSticky&&"fc-sticky"]})))}}const ki=Me({weekday:"long"});class Ri extends Sr{render(){let{props:e}=this,{dateEnv:t,theme:n,viewApi:r,options:i}=this.context,o=K(new Date(2592e5),e.dow),s={dow:e.dow,isDisabled:!1,isFuture:!1,isPast:!1,isToday:!1,isOther:!1},a=t.format(o,e.dayHeaderFormat),l=Object.assign(Object.assign(Object.assign(Object.assign({date:o},s),{view:r}),e.extraRenderProps),{text:a});return ln(wi,{elTag:"th",elClasses:[bi,...xt(s,n),...e.extraClassNames||[]],elAttrs:Object.assign({role:"columnheader",colSpan:e.colSpan},e.extraDataAttrs),renderProps:l,generatorName:"dayHeaderContent",customGenerator:i.dayHeaderContent,defaultGenerator:Ai,classNameGenerator:i.dayHeaderClassNames,didMount:i.dayHeaderDidMount,willUnmount:i.dayHeaderWillUnmount},n=>ln("div",{className:"fc-scrollgrid-sync-inner"},ln(n,{elTag:"a",elClasses:["fc-col-header-cell-cushion",e.isSticky&&"fc-sticky"],elAttrs:{"aria-label":t.format(o,ki)}})))}}class xi extends mn{constructor(e,t){super(e,t),this.handleRefresh=()=>{let e=this.computeTiming();e.state.nowDate.valueOf()!==this.state.nowDate.valueOf()&&this.setState(e.state),this.clearTimeout(),this.setTimeout(e.waitMs)},this.handleVisibilityChange=()=>{document.hidden||this.handleRefresh()},this.state=this.computeTiming().state}render(){let{props:e,state:t}=this;return e.children(t.nowDate,t.todayRange)}componentDidMount(){this.setTimeout(),this.context.nowManager.addResetListener(this.handleRefresh),document.addEventListener("visibilitychange",this.handleVisibilityChange)}componentDidUpdate(e){e.unit!==this.props.unit&&(this.clearTimeout(),this.setTimeout())}componentWillUnmount(){this.clearTimeout(),this.context.nowManager.removeResetListener(this.handleRefresh),document.removeEventListener("visibilitychange",this.handleVisibilityChange)}computeTiming(){let{props:e,context:t}=this,n=t.nowManager.getDateMarker(),r=t.dateEnv.startOf(n,e.unit),i=t.dateEnv.add(r,N(1,e.unit)).valueOf()-n.valueOf();return i=Math.min(864e5,i),{state:{nowDate:r,todayRange:Oi(r)},waitMs:i}}setTimeout(e=this.computeTiming().waitMs){this.timeoutId=setTimeout(()=>{const e=this.computeTiming();this.setState(e.state,()=>{this.setTimeout(e.waitMs)})},e)}clearTimeout(){this.timeoutId&&clearTimeout(this.timeoutId)}}function Oi(e){let t=oe(e);return{start:t,end:K(t,1)}}xi.contextType=Dr;function Mi(e,t,n){return e||vi(t,n)}function Ii(e,t){let n=e.activeRange;return t?n:{start:ee(n.start,e.slotMinTime.milliseconds),end:ee(n.end,e.slotMaxTime.milliseconds-864e5)}}function Ni(e,t,n,r,i){switch(t.type){case"RECEIVE_EVENTS":return function(e,t,n,r,i,o){if(t&&n===t.latestFetchId){let n=Ze(Bi(i,t,o),t,o);return r&&(n=Qe(n,r,o)),$e(Ui(e,t.sourceId),n)}return e}(e,n[t.sourceId],t.fetchId,t.fetchRange,t.rawEvents,i);case"RESET_RAW_EVENTS":return function(e,t,n,r,i){const{defIdMap:o,instanceIdMap:s}=function(e){const{defs:t,instances:n}=e,r={},i={};for(let e in t){const n=t[e],{publicId:i}=n;i&&(r[i]=e)}for(let e in n){const r=n[e],o=t[r.defId],{publicId:s}=o;s&&(i[s]=e)}return{defIdMap:r,instanceIdMap:i}}(e);return Qe(Ze(Bi(n,t,i),t,i,!1,o,s),r,i)}(e,n[t.sourceId],t.rawEvents,r.activeRange,i);case"ADD_EVENTS":return function(e,t,n,r){n&&(t=Qe(t,n,r));return $e(e,t)}(e,t.eventStore,r?r.activeRange:null,i);case"RESET_EVENTS":return t.eventStore;case"MERGE_EVENTS":return $e(e,t.eventStore);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return r?Qe(e,r.activeRange,i):e;case"REMOVE_EVENTS":return function(e,t){let{defs:n,instances:r}=e,i={},o={};for(let e in n)t.defs[e]||(i[e]=n[e]);for(let e in r)!t.instances[e]&&i[r[e].defId]&&(o[e]=r[e]);return{defs:i,instances:o}}(e,t.eventStore);case"REMOVE_EVENT_SOURCE":return Ui(e,t.sourceId);case"REMOVE_ALL_EVENT_SOURCES":return Xe(e,e=>!e.sourceId);case"REMOVE_ALL_EVENTS":return{defs:{},instances:{}};default:return e}}function Bi(e,t,n){let r=n.options.eventDataTransform,i=t?t.eventDataTransform:null;return i&&(e=Hi(e,i)),r&&(e=Hi(e,r)),e}function Hi(e,t){let n;if(t){n=[];for(let r of e){let e=t(r);e?n.push(e):null==e&&n.push(r)}}else n=e;return n}function Pi(e,t,n){let{defs:r}=e,i=L(e.instances,e=>r[e.defId].allDay?e:Object.assign(Object.assign({},e),{range:{start:n.createMarker(t.toDate(e.range.start,e.forcedStartTzo)),end:n.createMarker(t.toDate(e.range.end,e.forcedEndTzo))},forcedStartTzo:n.canComputeOffset?null:e.forcedStartTzo,forcedEndTzo:n.canComputeOffset?null:e.forcedEndTzo}));return{defs:r,instances:i}}function Ui(e,t){return Xe(e,e=>e.sourceId!==t)}function ji(e,t){let n=t.getCurrentData(),r=Object.assign({businessHours:n.businessHours,dateSelection:"",eventStore:n.eventStore,eventUiBases:n.eventUiBases,eventSelection:"",eventDrag:null,eventResize:null},e);return(t.pluginHooks.isPropsValid||zi)(r,t)}function zi(e,t,n={},r){return!(e.eventDrag&&!function(e,t,n,r){let i=t.getCurrentData(),o=e.eventDrag,s=o.mutatedEvents,a=s.defs,l=s.instances,c=Vr(a,o.isEvent?e.eventUiBases:{"":i.selectionConfig});r&&(c=L(c,r));let u=(p=e.eventStore,g=o.affectedEvents.instances,{defs:p.defs,instances:F(p.instances,e=>!g[e.instanceId])}),d=u.defs,f=u.instances,h=Vr(d,e.eventUiBases);var p,g;for(let r in l){let s=l[r],p=s.range,g=c[s.defId],m=a[s.defId];if(!Fi(g.constraints,p,u,e.businessHours,t))return!1;let{eventOverlap:v}=t.options,b="function"==typeof v?v:null;for(let e in f){let n=f[e];if(St(p,n.range)){if(!1===h[n.defId].overlap&&o.isEvent)return!1;if(!1===g.overlap)return!1;if(b&&!b(new Pr(t,d[n.defId],n),new Pr(t,m,s)))return!1}}let A=i.eventStore;for(let e of g.allows){let i,o=Object.assign(Object.assign({},n),{range:s.range,allDay:m.allDay}),a=A.defs[m.defId],l=A.instances[r];if(i=a?new Pr(t,a,l):new Pr(t,m),!e(Or(o,t),i))return!1}}return!0}(e,t,n,r))&&!(e.dateSelection&&!function(e,t,n,r){let i=e.eventStore,o=i.defs,s=i.instances,a=e.dateSelection,l=a.range,{selectionConfig:c}=t.getCurrentData();r&&(c=r(c));if(!Fi(c.constraints,l,i,e.businessHours,t))return!1;let{selectOverlap:u}=t.options,d="function"==typeof u?u:null;for(let e in s){let n=s[e];if(St(l,n.range)){if(!1===c.overlap)return!1;if(d&&!d(new Pr(t,o[n.defId],n),null))return!1}}for(let e of c.allows){let r=Object.assign(Object.assign({},n),a);if(!e(Or(r,t),null))return!1}return!0}(e,t,n,r))}function Fi(e,t,n,r,i){for(let o of e)if(!Wi(Li(o,t,n,r,i),t))return!1;return!0}function Li(e,t,n,r,i){return"businessHours"===e?Vi(Qe(r,t,i)):"string"==typeof e?Vi(Xe(n,t=>t.groupId===e)):"object"==typeof e&&e?Vi(Qe(e,t,i)):[]}function Vi(e){let{instances:t}=e,n=[];for(let e in t)n.push(t[e].range);return n}function Wi(e,t){for(let n of e)if(Tt(n,t))return!0;return!1}class Qi extends Error{constructor(e,t){super(e),this.response=t}}function Gi(e,t,n){const r={method:e=e.toUpperCase()};return"GET"===e?t+=(-1===t.indexOf("?")?"?":"&")+new URLSearchParams(n):(r.body=new URLSearchParams(n),r.headers={"Content-Type":"application/x-www-form-urlencoded"}),fetch(t,r).then(e=>{if(e.ok)return e.json().then(t=>[t,e],()=>{throw new Qi("Failure parsing JSON",e)});throw new Qi("Request failed",e)})}class Zi{constructor(e){this.drainedOption=e,this.isRunning=!1,this.isDirty=!1,this.pauseDepths={},this.timeoutId=0}request(e){this.isDirty=!0,this.isPaused()||(this.clearTimeout(),null==e?this.tryDrain():this.timeoutId=setTimeout(this.tryDrain.bind(this),e))}pause(e=""){let{pauseDepths:t}=this;t[e]=(t[e]||0)+1,this.clearTimeout()}resume(e="",t){let{pauseDepths:n}=this;if(e in n){if(t)delete n[e];else{n[e]-=1,n[e]<=0&&delete n[e]}this.tryDrain()}}isPaused(){return Object.keys(this.pauseDepths).length}tryDrain(){if(!this.isRunning&&!this.isPaused()){for(this.isRunning=!0;this.isDirty;)this.isDirty=!1,this.drained();this.isRunning=!1}}clear(){this.clearTimeout(),this.isDirty=!1,this.pauseDepths={}}clearTimeout(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=0)}drained(){this.drainedOption&&this.drainedOption()}}const qi=/^(visible|hidden)$/;class Yi extends Sr{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,Tr(this.props.elRef,e)}}render(){let{props:e}=this,{liquid:t,liquidIsAbsolute:n}=e,r=t&&n,i=["fc-scroller"];return t&&(n?i.push("fc-scroller-liquid-absolute"):i.push("fc-scroller-liquid")),ln("div",{ref:this.handleEl,className:i.join(" "),style:{overflowX:e.overflowX,overflowY:e.overflowY,left:r&&-(e.overcomeLeft||0)||"",right:r&&-(e.overcomeRight||0)||"",bottom:r&&-(e.overcomeBottom||0)||"",marginLeft:!r&&-(e.overcomeLeft||0)||"",marginRight:!r&&-(e.overcomeRight||0)||"",marginBottom:!r&&-(e.overcomeBottom||0)||"",maxHeight:e.maxHeight||""}},e.children)}needsXScrolling(){if(qi.test(this.props.overflowX))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().width-this.getYScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().width>t)return!0}return!1}needsYScrolling(){if(qi.test(this.props.overflowY))return!1;let{el:e}=this,t=this.el.getBoundingClientRect().height-this.getXScrollbarWidth(),{children:n}=e;for(let e=0;e<n.length;e+=1){if(n[e].getBoundingClientRect().height>t)return!0}return!1}getXScrollbarWidth(){return qi.test(this.props.overflowX)?0:this.el.offsetHeight-this.el.clientHeight}getYScrollbarWidth(){return qi.test(this.props.overflowY)?0:this.el.offsetWidth-this.el.clientWidth}}class Ji{constructor(e){this.masterCallback=e,this.currentMap={},this.depths={},this.callbackMap={},this.handleValue=(e,t)=>{let{depths:n,currentMap:r}=this,i=!1,o=!1;null!==e?(i=t in r,r[t]=e,n[t]=(n[t]||0)+1,o=!0):(n[t]-=1,n[t]||(delete r[t],delete this.callbackMap[t],i=!0)),this.masterCallback&&(i&&this.masterCallback(null,String(t)),o&&this.masterCallback(e,String(t)))}}createRef(e){let t=this.callbackMap[e];return t||(t=this.callbackMap[e]=t=>{this.handleValue(t,String(e))}),t}collect(e,t,n){return J(this.currentMap,e,t,n)}getAll(){return W(this.currentMap)}}function $i(e){let t=u(e,".fc-scrollgrid-shrink"),n=0;for(let e of t)n=Math.max(n,O(e));return Math.ceil(n)}function Xi(e,t){return e.liquid&&t.liquid}function Ki(e,t){return null!=t.maxHeight||Xi(e,t)}function eo(e,t,n,r){let{expandRows:i}=n;return"function"==typeof t.content?t.content(n):ln("table",{role:"presentation",className:[t.tableClassName,e.syncRowHeights?"fc-scrollgrid-sync-table":""].join(" "),style:{minWidth:n.tableMinWidth,width:n.clientWidth,height:i?n.clientHeight:""}},n.tableColGroupNode,ln(r?"thead":"tbody",{role:"presentation"},"function"==typeof t.rowContent?t.rowContent(n):t.rowContent))}function to(e,t){return $(e,t,Q)}function no(e,t){let n=[];for(let r of e){let e=r.span||1;for(let i=0;i<e;i+=1)n.push(ln("col",{style:{width:"shrink"===r.width?ro(t):r.width||"",minWidth:r.minWidth||""}}))}return ln("colgroup",{},...n)}function ro(e){return null==e?4:e}function io(e){for(let t of e)if("shrink"===t.width)return!0;return!1}function oo(e,t){let n=["fc-scrollgrid",t.theme.getClass("table")];return e&&n.push("fc-scrollgrid-liquid"),n}function so(e,t){let n=["fc-scrollgrid-section","fc-scrollgrid-section-"+e.type,e.className];return t&&e.liquid&&null==e.maxHeight&&n.push("fc-scrollgrid-section-liquid"),e.isSticky&&n.push("fc-scrollgrid-section-sticky"),n}class ao extends Sr{constructor(){super(...arguments),this.processCols=ve(e=>e,to),this.renderMicroColGroup=ve(no),this.scrollerRefs=new Ji,this.scrollerElRefs=new Ji(this._handleScrollerEl.bind(this)),this.state={shrinkWidth:null,forceYScrollbars:!1,scrollerClientWidths:{},scrollerClientHeights:{}},this.handleSizing=()=>{this.safeSetState(Object.assign({shrinkWidth:this.computeShrinkWidth()},this.computeScrollerDims()))}}render(){let{props:e,state:t,context:n}=this,r=e.sections||[],i=this.processCols(e.cols),o=this.renderMicroColGroup(i,t.shrinkWidth),s=oo(e.liquid,n);e.collapsibleWidth&&s.push("fc-scrollgrid-collapsible");let a,l=r.length,c=0,u=[],d=[],f=[];for(;c<l&&"header"===(a=r[c]).type;)u.push(this.renderSection(a,o,!0)),c+=1;for(;c<l&&"body"===(a=r[c]).type;)d.push(this.renderSection(a,o,!1)),c+=1;for(;c<l&&"footer"===(a=r[c]).type;)f.push(this.renderSection(a,o,!0)),c+=1;let h=!At();const p={role:"rowgroup"};return ln("table",{role:"grid",className:s.join(" "),style:{height:e.height}},Boolean(!h&&u.length)&&ln("thead",p,...u),Boolean(!h&&d.length)&&ln("tbody",p,...d),Boolean(!h&&f.length)&&ln("tfoot",p,...f),h&&ln("tbody",p,...u,...d,...f))}renderSection(e,t,n){return"outerContent"in e?ln(dn,{key:e.key},e.outerContent):ln("tr",{key:e.key,role:"presentation",className:so(e,this.props.liquid).join(" ")},this.renderChunkTd(e,t,e.chunk,n))}renderChunkTd(e,t,n,r){if("outerContent"in n)return n.outerContent;let{props:i}=this,{forceYScrollbars:o,scrollerClientWidths:s,scrollerClientHeights:a}=this.state,l=Ki(i,e),c=Xi(i,e),u=i.liquid?o?"scroll":l?"auto":"hidden":"visible",d=e.key,f=eo(e,n,{tableColGroupNode:t,tableMinWidth:"",clientWidth:i.collapsibleWidth||void 0===s[d]?null:s[d],clientHeight:void 0!==a[d]?a[d]:null,expandRows:e.expandRows,syncRowHeights:!1,rowSyncHeights:[],reportRowHeightChange:()=>{}},r);return ln(r?"th":"td",{ref:n.elRef,role:"presentation"},ln("div",{className:"fc-scroller-harness"+(c?" fc-scroller-harness-liquid":"")},ln(Yi,{ref:this.scrollerRefs.createRef(d),elRef:this.scrollerElRefs.createRef(d),overflowY:u,overflowX:i.liquid?"hidden":"visible",maxHeight:e.maxHeight,liquid:c,liquidIsAbsolute:!0},f)))}_handleScrollerEl(e,t){let n=function(e,t){for(let n of e)if(n.key===t)return n;return null}(this.props.sections,t);n&&Tr(n.chunk.scrollerElRef,e)}componentDidMount(){this.handleSizing(),this.context.addResizeHandler(this.handleSizing)}componentDidUpdate(){this.handleSizing()}componentWillUnmount(){this.context.removeResizeHandler(this.handleSizing)}computeShrinkWidth(){return io(this.props.cols)?$i(this.scrollerElRefs.getAll()):0}computeScrollerDims(){let e=Pt(),{scrollerRefs:t,scrollerElRefs:n}=this,r=!1,i={},o={};for(let e in t.currentMap){let n=t.currentMap[e];if(n&&n.needsYScrolling()){r=!0;break}}for(let t of this.props.sections){let s=t.key,a=n.currentMap[s];if(a){let t=a.parentNode;i[s]=Math.floor(t.getBoundingClientRect().width-(r?e.y:0)),o[s]=Math.floor(t.getBoundingClientRect().height)}}return{forceYScrollbars:r,scrollerClientWidths:i,scrollerClientHeights:o}}}ao.addStateEquality({scrollerClientWidths:Q,scrollerClientHeights:Q});class lo extends Sr{constructor(){super(...arguments),this.handleEl=e=>{this.el=e,e&&Fr(e,this.props.seg)}}render(){const{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{eventRange:i}=r,{ui:o}=i,s={event:new Pr(t,i.def,i.instance),view:t.viewApi,timeText:e.timeText,textColor:o.textColor,backgroundColor:o.backgroundColor,borderColor:o.borderColor,isDraggable:!e.disableDragging&&Gr(r,t),isStartResizable:!e.disableResizing&&Zr(r,t),isEndResizable:!e.disableResizing&&qr(r),isMirror:Boolean(e.isDragging||e.isResizing||e.isDateSelecting),isStart:Boolean(r.isStart),isEnd:Boolean(r.isEnd),isPast:Boolean(e.isPast),isFuture:Boolean(e.isFuture),isToday:Boolean(e.isToday),isSelected:Boolean(e.isSelected),isDragging:Boolean(e.isDragging),isResizing:Boolean(e.isResizing)};return ln(wi,Object.assign({},e,{elRef:this.handleEl,elClasses:[...Jr(s),...r.eventRange.ui.classNames,...e.elClasses||[]],renderProps:s,generatorName:"eventContent",customGenerator:n.eventContent,defaultGenerator:e.defaultGenerator,classNameGenerator:n.eventClassNames,didMount:n.eventDidMount,willUnmount:n.eventWillUnmount}))}componentDidUpdate(e){this.el&&this.props.seg!==e.seg&&Fr(this.el,this.props.seg)}}function co(e){return ln("div",{className:"fc-event-main-frame"},e.timeText&&ln("div",{className:"fc-event-time"},e.timeText),ln("div",{className:"fc-event-title-container"},ln("div",{className:"fc-event-title fc-sticky"},e.event.title||ln(dn,null," "))))}const uo=Me({day:"numeric"});class fo extends Sr{constructor(){super(...arguments),this.refineRenderProps=be(po)}render(){let{props:e,context:t}=this,{options:n}=t,r=this.refineRenderProps({date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,isMonthStart:e.isMonthStart||!1,showDayNumber:e.showDayNumber,extraRenderProps:e.extraRenderProps,viewApi:t.viewApi,dateEnv:t.dateEnv,monthStartFormat:n.monthStartFormat});return ln(wi,Object.assign({},e,{elClasses:[...xt(r,t.theme),...e.elClasses||[]],elAttrs:Object.assign(Object.assign({},e.elAttrs),r.isDisabled?{}:{"data-date":ge(e.date)}),renderProps:r,generatorName:"dayCellContent",customGenerator:n.dayCellContent,defaultGenerator:e.defaultGenerator,classNameGenerator:r.isDisabled?void 0:n.dayCellClassNames,didMount:n.dayCellDidMount,willUnmount:n.dayCellWillUnmount}))}}function ho(e){return Boolean(e.dayCellContent||_i("dayCellContent",e))}function po(e){let{date:t,dateEnv:n,dateProfile:r,isMonthStart:i}=e,o=Rt(t,e.todayRange,null,r),s=e.showDayNumber?n.format(t,i?e.monthStartFormat:uo):"";return Object.assign(Object.assign(Object.assign({date:n.toDate(t),view:e.viewApi},o),{isMonthStart:i,dayNumberText:s}),e.extraRenderProps)}function go(e){let{title:t}=e.event;return t&&ln("div",{className:"fc-event-title"},e.event.title)}function mo(e){return e.text}class vo extends Sr{constructor(){super(...arguments),this.state={titleId:m()},this.handleRootEl=e=>{this.rootEl=e,this.props.elRef&&Tr(this.props.elRef,e)},this.handleDocumentMouseDown=e=>{const t=p(e);this.rootEl.contains(t)||this.handleCloseClick()},this.handleDocumentKeyDown=e=>{"Escape"===e.key&&this.handleCloseClick()},this.handleCloseClick=()=>{let{onClose:e}=this.props;e&&e()}}render(){let{theme:e,options:t}=this.context,{props:n,state:r}=this,i=["fc-popover",e.getClass("popover")].concat(n.extraClassNames||[]);return sr(ln("div",Object.assign({},n.extraAttrs,{id:n.id,className:i.join(" "),"aria-labelledby":r.titleId,ref:this.handleRootEl}),ln("div",{className:"fc-popover-header "+e.getClass("popoverHeader")},ln("span",{className:"fc-popover-title",id:r.titleId},n.title),ln("span",{className:"fc-popover-close "+e.getIconClass("close"),title:t.closeHint,onClick:this.handleCloseClick})),ln("div",{className:"fc-popover-body "+e.getClass("popoverContent")},n.children)),n.parentEl)}componentDidMount(){document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown),this.updateSize()}componentWillUnmount(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown)}updateSize(){let{isRtl:e}=this.context,{alignmentEl:t,alignGridTop:n}=this.props,{rootEl:r}=this,i=function(e){let t=Ft(e),n=e.getBoundingClientRect();for(let e of t){let t=vt(n,e.getBoundingClientRect());if(!t)return null;n=t}return n}(t);if(i){let o=r.getBoundingClientRect(),s=n?l(t,".fc-scrollgrid").getBoundingClientRect().top:i.top,a=e?i.right-o.width:i.left;s=Math.max(s,10),a=Math.min(a,document.documentElement.clientWidth-10-o.width),a=Math.max(a,10);let c=r.offsetParent.getBoundingClientRect();f(r,{top:s-c.top,left:a-c.left})}}}class bo extends kr{constructor(){super(...arguments),this.handleRootEl=e=>{this.rootEl=e,e?this.context.registerInteractiveComponent(this,{el:e,useEventCenter:!1}):this.context.unregisterInteractiveComponent(this)}}render(){let{options:e,dateEnv:t}=this.context,{props:n}=this,{startDate:r,todayRange:i,dateProfile:o}=n,s=t.format(r,e.dayPopoverFormat);return ln(fo,{elRef:this.handleRootEl,date:r,dateProfile:o,todayRange:i},(t,r,i)=>ln(vo,{elRef:i.ref,id:n.id,title:s,extraClassNames:["fc-more-popover"].concat(i.className||[]),extraAttrs:i,parentEl:n.parentEl,alignmentEl:n.alignmentEl,alignGridTop:n.alignGridTop,onClose:n.onClose},ho(e)&&ln(t,{elTag:"div",elClasses:["fc-more-popover-misc"]}),n.children))}queryHit(e,t,n,r){let{rootEl:i,props:o}=this;return e>=0&&e<n&&t>=0&&t<r?{dateProfile:o.dateProfile,dateSpan:Object.assign({allDay:!o.forceTimed,range:{start:o.startDate,end:o.endDate}},o.extraDateSpan),dayEl:i,rect:{left:0,top:0,right:n,bottom:r},layer:1}:null}}function Ao(e){return e.text}function yo(e){if(e.allDayDate)return{start:e.allDayDate,end:K(e.allDayDate,1)};let{hiddenSegs:t}=e;return{start:_o(t),end:(n=t,n.reduce(Do).eventRange.range.end)};var n}function _o(e){return e.reduce(Eo).eventRange.range.start}function Eo(e,t){return e.eventRange.range.start<t.eventRange.range.start?e:t}function Do(e,t){return e.eventRange.range.end>t.eventRange.range.end?e:t}function Co(e){return[`fc-${e.type}-view`,"fc-view"]}const wo={id:String,defaultAllDay:Boolean,url:String,format:String,events:Ve,eventDataTransform:Ve,success:Ve,failure:Ve};function So(e,t,n=To(t)){let r;if("string"==typeof e?r={url:e}:"function"==typeof e||Array.isArray(e)?r={events:e}:"object"==typeof e&&e&&(r=e),r){let{refined:i,extra:o}=Le(r,n),s=function(e,t){let n=t.pluginHooks.eventSourceDefs;for(let t=n.length-1;t>=0;t-=1){let r=n[t].parseMeta(e);if(r)return{sourceDefId:t,meta:r}}return null}(i,t);if(s)return{_raw:e,isFetching:!1,latestFetchId:"",fetchRange:null,defaultAllDay:i.defaultAllDay,eventDataTransform:i.eventDataTransform,success:i.success,failure:i.failure,publicId:i.id||"",sourceId:D(),sourceDefId:s.sourceDefId,meta:s.meta,ui:nt(i,t),extendedProps:o}}return null}function To(e){return Object.assign(Object.assign(Object.assign({},et),wo),e.pluginHooks.eventSourceRefiners)}class ko{getCurrentData(){return this.currentDataManager.getCurrentData()}dispatch(e){this.currentDataManager.dispatch(e)}get view(){return this.getCurrentData().viewApi}batchRendering(e){e()}updateSize(){this.trigger("_resize",!0)}setOption(e,t){this.dispatch({type:"SET_OPTION",optionName:e,rawOptionValue:t})}getOption(e){return this.currentDataManager.currentCalendarOptionsInput[e]}getAvailableLocaleCodes(){return Object.keys(this.getCurrentData().availableRawLocales)}on(e,t){let{currentDataManager:n}=this;n.currentCalendarOptionsRefiners[e]?n.emitter.on(e,t):console.warn(`Unknown listener name '${e}'`)}off(e,t){this.currentDataManager.emitter.off(e,t)}trigger(e,...t){this.currentDataManager.emitter.trigger(e,...t)}changeView(e,t){this.batchRendering(()=>{if(this.unselect(),t)if(t.start&&t.end)this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e}),this.dispatch({type:"SET_OPTION",optionName:"visibleRange",rawOptionValue:t});else{let{dateEnv:n}=this.getCurrentData();this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e,dateMarker:n.createMarker(t)})}else this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:e})})}zoomTo(e,t){let n;t=t||"day",n=this.getCurrentData().viewSpecs[t]||this.getUnitViewSpec(t),this.unselect(),n?this.dispatch({type:"CHANGE_VIEW_TYPE",viewType:n.type,dateMarker:e}):this.dispatch({type:"CHANGE_DATE",dateMarker:e})}getUnitViewSpec(e){let t,n,{viewSpecs:r,toolbarConfig:i}=this.getCurrentData(),o=[].concat(i.header?i.header.viewsWithButtons:[],i.footer?i.footer.viewsWithButtons:[]);for(let e in r)o.push(e);for(t=0;t<o.length;t+=1)if(n=r[o[t]],n&&n.singleUnit===e)return n;return null}prev(){this.unselect(),this.dispatch({type:"PREV"})}next(){this.unselect(),this.dispatch({type:"NEXT"})}prevYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,-1)})}nextYear(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.dateEnv.addYears(e.currentDate,1)})}today(){let e=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:e.nowManager.getDateMarker()})}gotoDate(e){let t=this.getCurrentData();this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.createMarker(e)})}incrementDate(e){let t=this.getCurrentData(),n=N(e);n&&(this.unselect(),this.dispatch({type:"CHANGE_DATE",dateMarker:t.dateEnv.add(t.currentDate,n)}))}getDate(){let e=this.getCurrentData();return e.dateEnv.toDate(e.currentDate)}formatDate(e,t){let{dateEnv:n}=this.getCurrentData();return n.format(n.createMarker(e),Me(t))}formatRange(e,t,n){let{dateEnv:r}=this.getCurrentData();return r.formatRange(r.createMarker(e),r.createMarker(t),Me(n),n)}formatIso(e,t){let{dateEnv:n}=this.getCurrentData();return n.formatIso(n.createMarker(e),{omitTime:t})}select(e,t){let n;n=null==t?null!=e.start?e:{start:e,end:null}:{start:e,end:t};let r=this.getCurrentData(),i=Kr(n,r.dateEnv,N({days:1}));i&&(this.dispatch({type:"SELECT_DATES",selection:i}),xr(i,null,r))}unselect(e){let t=this.getCurrentData();t.dateSelection&&(this.dispatch({type:"UNSELECT_DATES"}),function(e,t){t.emitter.trigger("unselect",{jsEvent:e?e.origEvent:null,view:t.viewApi||t.calendarApi.view})}(e,t))}addEvent(e,t){if(e instanceof Pr){let t=e._def,n=e._instance;return this.getCurrentData().eventStore.defs[t.defId]||(this.dispatch({type:"ADD_EVENTS",eventStore:qe({def:t,instance:n})}),this.triggerEventAdd(e)),e}let n,r=this.getCurrentData();if(t instanceof Hr)n=t.internalEventSource;else if("boolean"==typeof t)t&&([n]=W(r.eventSources));else if(null!=t){let e=this.getEventSourceById(t);if(!e)return console.warn(`Could not find an event source with ID "${t}"`),null;n=e.internalEventSource}let i=lt(e,n,r,!1);if(i){let e=new Pr(r,i.def,i.def.recurringDef?null:i.instance);return this.dispatch({type:"ADD_EVENTS",eventStore:qe(i)}),this.triggerEventAdd(e),e}return null}triggerEventAdd(e){let{emitter:t}=this.getCurrentData();t.trigger("eventAdd",{event:e,relatedEvents:[],revert:()=>{this.dispatch({type:"REMOVE_EVENTS",eventStore:Ur(e)})}})}getEventById(e){let t=this.getCurrentData(),{defs:n,instances:r}=t.eventStore;e=String(e);for(let i in n){let o=n[i];if(o.publicId===e){if(o.recurringDef)return new Pr(t,o,null);for(let e in r){let n=r[e];if(n.defId===o.defId)return new Pr(t,o,n)}}}return null}getEvents(){let e=this.getCurrentData();return jr(e.eventStore,e)}removeAllEvents(){this.dispatch({type:"REMOVE_ALL_EVENTS"})}getEventSources(){let e=this.getCurrentData(),t=e.eventSources,n=[];for(let r in t)n.push(new Hr(e,t[r]));return n}getEventSourceById(e){let t=this.getCurrentData(),n=t.eventSources;e=String(e);for(let r in n)if(n[r].publicId===e)return new Hr(t,n[r]);return null}addEventSource(e){let t=this.getCurrentData();if(e instanceof Hr)return t.eventSources[e.internalEventSource.sourceId]||this.dispatch({type:"ADD_EVENT_SOURCES",sources:[e.internalEventSource]}),e;let n=So(e,t);return n?(this.dispatch({type:"ADD_EVENT_SOURCES",sources:[n]}),new Hr(t,n)):null}removeAllEventSources(){this.dispatch({type:"REMOVE_ALL_EVENT_SOURCES"})}refetchEvents(){this.dispatch({type:"FETCH_EVENT_SOURCES",isRefetch:!0})}scrollToTime(e){let t=N(e);t&&this.trigger("_scrollRequest",{time:t})}}var Ro={__proto__:null,BASE_OPTION_DEFAULTS:Ne,identity:Ve,refineProps:Le,createEventInstance:We,parseEventDef:dt,refineEventDef:ct,parseBusinessHours:ht,padStart:k,isInt:x,parseFieldSpecs:C,compareByFieldSpecs:w,flexibleCompare:T,preventSelection:function(e){e.style.userSelect="none",e.style.webkitUserSelect="none",e.addEventListener("selectstart",v)},allowSelection:function(e){e.style.userSelect="",e.style.webkitUserSelect="",e.removeEventListener("selectstart",v)},preventContextMenu:function(e){e.addEventListener("contextmenu",v)},allowContextMenu:function(e){e.removeEventListener("contextmenu",v)},compareNumbers:function(e,t){return e-t},enableCursor:function(){document.body.classList.remove("fc-not-allowed")},disableCursor:function(){document.body.classList.add("fc-not-allowed")},guid:D,computeVisibleDayRange:gt,isMultiDayRange:function(e){let t=gt(e);return te(t.start,t.end)>1},diffDates:mt,removeExact:function(e,t){let n=0,r=0;for(;r<e.length;)e[r]===t?(e.splice(r,1),n+=1):r+=1;return n},isArraysEqual:$,memoize:ve,memoizeObjArg:be,memoizeArraylike:function(e,t,n){let r=[],i=[];return o=>{let s=r.length,a=o.length,l=0;for(;l<s;l+=1)if(o[l]){if(!$(r[l],o[l])){n&&n(i[l]);let r=e.apply(this,o[l]);t&&t(r,i[l])||(i[l]=r)}}else n&&n(i[l]);for(;l<a;l+=1)i[l]=e.apply(this,o[l]);return r=o,i.splice(a),i}},memoizeHashlike:function(e,t,n){let r={},i={};return o=>{let s={};for(let a in o)if(i[a])if($(r[a],o[a]))s[a]=i[a];else{n&&n(i[a]);let r=e.apply(this,o[a]);s[a]=t&&t(r,i[a])?i[a]:r}else s[a]=e.apply(this,o[a]);return r=o,i=s,s}},intersectRects:vt,pointInsideRect:function(e,t){return e.left>=t.left&&e.left<t.right&&e.top>=t.top&&e.top<t.bottom},constrainPoint:function(e,t){return{left:Math.min(Math.max(e.left,t.left),t.right),top:Math.min(Math.max(e.top,t.top),t.bottom)}},getRectCenter:function(e){return{left:(e.left+e.right)/2,top:(e.top+e.bottom)/2}},diffPoints:function(e,t){return{left:e.left-t.left,top:e.top-t.top}},translateRect:function(e,t,n){return{left:e.left+t,right:e.right+t,top:e.top+n,bottom:e.bottom+n}},mapHash:L,filterHash:F,isPropsEqual:Q,compareObjs:q,collectFromHash:J,findElements:u,findDirectChildren:function(e,t){let n=e instanceof HTMLElement?[e]:e,r=[];for(let e=0;e<n.length;e+=1){let i=n[e].children;for(let e=0;e<i.length;e+=1){let n=i[e];t&&!c(n,t)||r.push(n)}}return r},removeElement:a,applyStyle:f,elementMatches:c,elementClosest:l,getEventTargetViaRoot:p,getUniqueDomId:m,parseClassNames:Ke,getCanVGrowWithinCell:At,createEmptyEventStore:Je,mergeEventStores:$e,getRelevantEvents:Ye,eventTupleToStore:qe,combineEventUis:rt,createEventUi:nt,Splitter:class{constructor(){this.getKeysForEventDefs=ve(this._getKeysForEventDefs),this.splitDateSelection=ve(this._splitDateSpan),this.splitEventStore=ve(this._splitEventStore),this.splitIndividualUi=ve(this._splitIndividualUi),this.splitEventDrag=ve(this._splitInteraction),this.splitEventResize=ve(this._splitInteraction),this.eventUiBuilders={}}splitProps(e){let t=this.getKeyInfo(e),n=this.getKeysForEventDefs(e.eventStore),r=this.splitDateSelection(e.dateSelection),i=this.splitIndividualUi(e.eventUiBases,n),o=this.splitEventStore(e.eventStore,n),s=this.splitEventDrag(e.eventDrag),a=this.splitEventResize(e.eventResize),l={};this.eventUiBuilders=L(t,(e,t)=>this.eventUiBuilders[t]||ve(_t));for(let n in t){let c=t[n],u=o[n]||yt,d=this.eventUiBuilders[n];l[n]={businessHours:c.businessHours||e.businessHours,dateSelection:r[n]||null,eventStore:u,eventUiBases:d(e.eventUiBases[""],c.ui,i[n]),eventSelection:u.instances[e.eventSelection]?e.eventSelection:"",eventDrag:s[n]||null,eventResize:a[n]||null}}return l}_splitDateSpan(e){let t={};if(e){let n=this.getKeysForDateSpan(e);for(let r of n)t[r]=e}return t}_getKeysForEventDefs(e){return L(e.defs,e=>this.getKeysForEventDef(e))}_splitEventStore(e,t){let{defs:n,instances:r}=e,i={};for(let e in n)for(let r of t[e])i[r]||(i[r]={defs:{},instances:{}}),i[r].defs[e]=n[e];for(let e in r){let n=r[e];for(let r of t[n.defId])i[r]&&(i[r].instances[e]=n)}return i}_splitIndividualUi(e,t){let n={};for(let r in e)if(r)for(let i of t[r])n[i]||(n[i]={}),n[i][r]=e[r];return n}_splitInteraction(e){let t={};if(e){let n=this._splitEventStore(e.affectedEvents,this._getKeysForEventDefs(e.affectedEvents)),r=this._getKeysForEventDefs(e.mutatedEvents),i=this._splitEventStore(e.mutatedEvents,r),o=r=>{t[r]||(t[r]={affectedEvents:n[r]||yt,mutatedEvents:i[r]||yt,isEvent:e.isEvent})};for(let e in n)o(e);for(let e in i)o(e)}return t}},getDayClassNames:xt,getDateMeta:Rt,getSlotClassNames:function(e,t){let n=["fc-slot","fc-slot-"+X[e.dow]];return e.isDisabled?n.push("fc-slot-disabled"):(e.isToday&&(n.push("fc-slot-today"),n.push(t.getClass("today"))),e.isPast&&n.push("fc-slot-past"),e.isFuture&&n.push("fc-slot-future")),n},buildNavLinkAttrs:It,preventDefault:v,whenTransitionDone:function(e,t){let n=r=>{t(r),A.forEach(t=>{e.removeEventListener(t,n)})};A.forEach(t=>{e.addEventListener(t,n)})},computeInnerRect:function(e,t=!1,n){let r=n?e.getBoundingClientRect():zt(e),i=jt(e,t),o={left:r.left+i.borderLeft+i.scrollbarLeft,right:r.right-i.borderRight-i.scrollbarRight,top:r.top+i.borderTop,bottom:r.bottom-i.borderBottom-i.scrollbarBottom};return t&&(o.left+=i.paddingLeft,o.right-=i.paddingRight,o.top+=i.paddingTop,o.bottom-=i.paddingBottom),o},computeEdges:jt,getClippingParents:Ft,computeRect:zt,unpromisify:Lt,Emitter:Vt,rangeContainsMarker:kt,intersectRanges:Ct,rangesEqual:wt,rangesIntersect:St,rangeContainsRange:Tt,PositionCache:class{constructor(e,t,n,r){this.els=t;let i=this.originClientRect=e.getBoundingClientRect();n&&this.buildElHorizontals(i.left),r&&this.buildElVerticals(i.top)}buildElHorizontals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.left-e),n.push(i.right-e)}this.lefts=t,this.rights=n}buildElVerticals(e){let t=[],n=[];for(let r of this.els){let i=r.getBoundingClientRect();t.push(i.top-e),n.push(i.bottom-e)}this.tops=t,this.bottoms=n}leftToIndex(e){let t,{lefts:n,rights:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}topToIndex(e){let t,{tops:n,bottoms:r}=this,i=n.length;for(t=0;t<i;t+=1)if(e>=n[t]&&e<r[t])return t}getWidth(e){return this.rights[e]-this.lefts[e]}getHeight(e){return this.bottoms[e]-this.tops[e]}similarTo(e){return Wt(this.tops||[],e.tops||[])&&Wt(this.bottoms||[],e.bottoms||[])&&Wt(this.lefts||[],e.lefts||[])&&Wt(this.rights||[],e.rights||[])}},ScrollController:Qt,ElementScrollController:class extends Qt{constructor(e){super(),this.el=e}getScrollTop(){return this.el.scrollTop}getScrollLeft(){return this.el.scrollLeft}setScrollTop(e){this.el.scrollTop=e}setScrollLeft(e){this.el.scrollLeft=e}getScrollWidth(){return this.el.scrollWidth}getScrollHeight(){return this.el.scrollHeight}getClientHeight(){return this.el.clientHeight}getClientWidth(){return this.el.clientWidth}},WindowScrollController:class extends Qt{getScrollTop(){return window.scrollY}getScrollLeft(){return window.scrollX}setScrollTop(e){window.scroll(window.scrollX,e)}setScrollLeft(e){window.scroll(e,window.scrollY)}getScrollWidth(){return document.documentElement.scrollWidth}getScrollHeight(){return document.documentElement.scrollHeight}getClientHeight(){return document.documentElement.clientHeight}getClientWidth(){return document.documentElement.clientWidth}},Theme:Gt,ViewContextType:Dr,DateComponent:kr,DateProfileGenerator:Rr,isDateSpansEqual:function(e,t){return wt(e.range,t.range)&&e.allDay===t.allDay&&function(e,t){for(let n in t)if("range"!==n&&"allDay"!==n&&e[n]!==t[n])return!1;for(let n in e)if(!(n in t))return!1;return!0}(e,t)},addDays:K,startOfDay:oe,addMs:ee,addWeeks:function(e,t){let n=ue(e);return n[2]+=7*t,de(n)},diffWeeks:function(e,t){return te(e,t)/7},diffWholeWeeks:re,diffWholeDays:ie,diffDayAndTime:ne,diffDays:te,isValidDate:fe,createDuration:N,asCleanDays:function(e){return e.years||e.months||e.milliseconds?0:e.days},multiplyDuration:function(e,t){return{years:e.years*t,months:e.months*t,days:e.days*t,milliseconds:e.milliseconds*t}},addDurations:function(e,t){return{years:e.years+t.years,months:e.months+t.months,days:e.days+t.days,milliseconds:e.milliseconds+t.milliseconds}},asRoughMinutes:function(e){return P(e)/6e4},asRoughSeconds:function(e){return P(e)/1e3},asRoughMs:P,wholeDivideDurations:function(e,t){let n=null;for(let r=0;r<M.length;r+=1){let i=M[r];if(t[i]){let r=e[i]/t[i];if(!x(r)||null!==n&&n!==r)return null;n=r}else if(e[i])return null}return n},greatestDurationDenominator:U,DateEnv:ai,createFormatter:Me,formatIsoTimeString:function(e){return k(e.getUTCHours(),2)+":"+k(e.getUTCMinutes(),2)+":"+k(e.getUTCSeconds(),2)},formatDayString:ge,buildIsoString:pe,formatIsoMonthStr:function(e){return e.toISOString().match(/^\d{4}-\d{2}/)[0]},NamedTimeZoneImpl:class{constructor(e){this.timeZoneName=e}},parseMarker:si,SegHierarchy:class{constructor(e=(e=>e.thickness||1)){this.getEntryThickness=e,this.strictOrder=!1,this.allowReslicing=!1,this.maxCoord=-1,this.maxStackCnt=-1,this.levelCoords=[],this.entriesByLevel=[],this.stackCnts={}}addSegs(e){let t=[];for(let n of e)this.insertEntry(n,t);return t}insertEntry(e,t){let n=this.findInsertion(e);this.isInsertionValid(n,e)?this.insertEntryAt(e,n):this.handleInvalidInsertion(n,e,t)}isInsertionValid(e,t){return(-1===this.maxCoord||e.levelCoord+this.getEntryThickness(t)<=this.maxCoord)&&(-1===this.maxStackCnt||e.stackCnt<this.maxStackCnt)}handleInvalidInsertion(e,t,n){if(this.allowReslicing&&e.touchingEntry){const r=Object.assign(Object.assign({},t),{span:ui(t.span,e.touchingEntry.span)});n.push(r),this.splitEntry(t,e.touchingEntry,n)}else n.push(t)}splitEntry(e,t,n){let r=e.span,i=t.span;r.start<i.start&&this.insertEntry({index:e.index,thickness:e.thickness,span:{start:r.start,end:i.start}},n),r.end>i.end&&this.insertEntry({index:e.index,thickness:e.thickness,span:{start:i.end,end:r.end}},n)}insertEntryAt(e,t){let{entriesByLevel:n,levelCoords:r}=this;-1===t.lateral?(di(r,t.level,t.levelCoord),di(n,t.level,[e])):di(n[t.level],t.lateral,e),this.stackCnts[ci(e)]=t.stackCnt}findInsertion(e){let{levelCoords:t,entriesByLevel:n,strictOrder:r,stackCnts:i}=this,o=t.length,s=0,a=-1,l=-1,c=null,u=0;for(let d=0;d<o;d+=1){const o=t[d];if(!r&&o>=s+this.getEntryThickness(e))break;let f,h=n[d],p=fi(h,e.span.start,li),g=p[0]+p[1];for(;(f=h[g])&&f.span.start<e.span.end;){let e=o+this.getEntryThickness(f);e>s&&(s=e,c=f,a=d,l=g),e===s&&(u=Math.max(u,i[ci(f)]+1)),g+=1}}let d=0;if(c)for(d=a+1;d<o&&t[d]<s;)d+=1;let f=-1;return d<o&&t[d]===s&&(f=fi(n[d],e.span.end,li)[0]),{touchingLevel:a,touchingLateral:l,touchingEntry:c,stackCnt:u,levelCoord:s,level:d,lateral:f}}toRects(){let{entriesByLevel:e,levelCoords:t}=this,n=e.length,r=[];for(let i=0;i<n;i+=1){let n=e[i],o=t[i];for(let e of n)r.push(Object.assign(Object.assign({},e),{thickness:this.getEntryThickness(e),levelCoord:o}))}return r}},buildEntryKey:ci,getEntrySpanEnd:li,binarySearch:fi,groupIntersectingEntries:function(e){let t=[];for(let i of e){let e=[],o={span:i.span,entries:[i]};for(let i of t)ui(i.span,o.span)?o={entries:i.entries.concat(o.entries),span:(n=i.span,r=o.span,{start:Math.min(n.start,r.start),end:Math.max(n.end,r.end)})}:e.push(i);e.push(o),t=e}var n,r;return t},intersectSpans:ui,Interaction:hi,interactionSettingsToStore:function(e){return{[e.component.uid]:e}},interactionSettingsStore:pi,ElementDragging:class{constructor(e,t){this.emitter=new Vt}destroy(){}setMirrorIsVisible(e){}setMirrorNeedsRevert(e){}setAutoScrollEnabled(e){}},config:{},parseDragMeta:function(e){let{refined:t,extra:n}=Le(e,gi);return{startTime:t.startTime||null,duration:t.duration||null,create:null==t.create||t.create,sourceId:t.sourceId,leftoverProps:n}},CalendarRoot:mi,DayHeader:class extends Sr{constructor(){super(...arguments),this.createDayHeaderFormatter=ve(Mi)}render(){let{context:e}=this,{dates:t,dateProfile:n,datesRepDistinctDays:r,renderIntro:i}=this.props,o=this.createDayHeaderFormatter(e.options.dayHeaderFormat,r,t.length);return ln(xi,{unit:"day"},(e,s)=>ln("tr",{role:"row"},i&&i("day"),t.map(e=>r?ln(Ti,{key:e.toISOString(),date:e,dateProfile:n,todayRange:s,colCnt:t.length,dayHeaderFormat:o}):ln(Ri,{key:e.getUTCDay(),dow:e.getUTCDay(),dayHeaderFormat:o}))))}},computeFallbackHeaderFormat:vi,TableDateCell:Ti,TableDowCell:Ri,DaySeriesModel:class{constructor(e,t){let n=e.start,{end:r}=e,i=[],o=[],s=-1;for(;n<r;)t.isHiddenDay(n)?i.push(s+.5):(s+=1,i.push(s),o.push(n)),n=K(n,1);this.dates=o,this.indices=i,this.cnt=o.length}sliceRange(e){let t=this.getDateDayIndex(e.start),n=this.getDateDayIndex(K(e.end,-1)),r=Math.max(0,t),i=Math.min(this.cnt-1,n);return r=Math.ceil(r),i=Math.floor(i),r<=i?{firstIndex:r,lastIndex:i,isStart:t===r,isEnd:n===i}:null}getDateDayIndex(e){let{indices:t}=this,n=Math.floor(te(this.dates[0],e));return n<0?t[0]-1:n>=t.length?t[t.length-1]+1:t[n]}},sliceEventStore:zr,hasBgRendering:function(e){return"background"===e.ui.display||"inverse-background"===e.ui.display},getElSeg:Lr,buildSegTimeText:Yr,sortEventSegs:function(e,t){let n=e.map(Qr);return n.sort((e,n)=>w(e,n,t)),n.map(e=>e._seg)},getSegMeta:function(e,t,n){let r=e.eventRange.range;return{isPast:r.end<=(n||t.start),isFuture:r.start>=(n||t.end),isToday:t&&kt(t,r.start)}},buildEventRangeKey:function(e){return e.instance?e.instance.instanceId:`${e.def.defId}:${e.range.start.toISOString()}`},getSegAnchorAttrs:$r,DayTableModel:class{constructor(e,t){let n,r,i,{dates:o}=e;if(t){for(r=o[0].getUTCDay(),n=1;n<o.length&&o[n].getUTCDay()!==r;n+=1);i=Math.ceil(o.length/n)}else i=1,n=o.length;this.rowCnt=i,this.colCnt=n,this.daySeries=e,this.cells=this.buildCells(),this.headerDates=this.buildHeaderDates()}buildCells(){let e=[];for(let t=0;t<this.rowCnt;t+=1){let n=[];for(let e=0;e<this.colCnt;e+=1)n.push(this.buildCell(t,e));e.push(n)}return e}buildCell(e,t){let n=this.daySeries.dates[e*this.colCnt+t];return{key:n.toISOString(),date:n}}buildHeaderDates(){let e=[];for(let t=0;t<this.colCnt;t+=1)e.push(this.cells[0][t].date);return e}sliceRange(e){let{colCnt:t}=this,n=this.daySeries.sliceRange(e),r=[];if(n){let{firstIndex:e,lastIndex:i}=n,o=e;for(;o<=i;){let s=Math.floor(o/t),a=Math.min((s+1)*t,i+1);r.push({row:s,firstCol:o%t,lastCol:(a-1)%t,isStart:n.isStart&&o===e,isEnd:n.isEnd&&a-1===i}),o=a}}return r}},Slicer:class{constructor(){this.sliceBusinessHours=ve(this._sliceBusinessHours),this.sliceDateSelection=ve(this._sliceDateSpan),this.sliceEventStore=ve(this._sliceEventStore),this.sliceEventDrag=ve(this._sliceInteraction),this.sliceEventResize=ve(this._sliceInteraction),this.forceDayIfListItem=!1}sliceProps(e,t,n,r,...i){let{eventUiBases:o}=e,s=this.sliceEventStore(e.eventStore,o,t,n,...i);return{dateSelectionSegs:this.sliceDateSelection(e.dateSelection,t,n,o,r,...i),businessHourSegs:this.sliceBusinessHours(e.businessHours,t,n,r,...i),fgEventSegs:s.fg,bgEventSegs:s.bg,eventDrag:this.sliceEventDrag(e.eventDrag,o,t,n,...i),eventResize:this.sliceEventResize(e.eventResize,o,t,n,...i),eventSelection:e.eventSelection}}sliceNowDate(e,t,n,r,...i){return this._sliceDateSpan({range:{start:e,end:ee(e,1)},allDay:!1},t,n,{},r,...i)}_sliceBusinessHours(e,t,n,r,...i){return e?this._sliceEventStore(Qe(e,Ii(t,Boolean(n)),r),{},t,n,...i).bg:[]}_sliceEventStore(e,t,n,r,...i){if(e){let o=zr(e,t,Ii(n,Boolean(r)),r);return{bg:this.sliceEventRanges(o.bg,i),fg:this.sliceEventRanges(o.fg,i)}}return{bg:[],fg:[]}}_sliceInteraction(e,t,n,r,...i){if(!e)return null;let o=zr(e.mutatedEvents,t,Ii(n,Boolean(r)),r);return{segs:this.sliceEventRanges(o.fg,i),affectedInstances:e.affectedEvents.instances,isEvent:e.isEvent}}_sliceDateSpan(e,t,n,r,i,...o){if(!e)return[];let s=Ii(t,Boolean(n)),a=Ct(e.range,s);if(a){let t=function(e,t,n){let r=ct({editable:!1},n),i=dt(r.refined,r.extra,"",e.allDay,!0,n);return{def:i,ui:Wr(i,t),instance:We(i.defId,e.range),range:e.range,isStart:!0,isEnd:!0}}(e=Object.assign(Object.assign({},e),{range:a}),r,i),n=this.sliceRange(e.range,...o);for(let e of n)e.eventRange=t;return n}return[]}sliceEventRanges(e,t){let n=[];for(let r of e)n.push(...this.sliceEventRange(r,t));return n}sliceEventRange(e,t){let n=e.range;this.forceDayIfListItem&&"list-item"===e.ui.display&&(n={start:n.start,end:K(n.start,1)});let r=this.sliceRange(n,...t);for(let t of r)t.eventRange=e,t.isStart=e.isStart&&t.isStart,t.isEnd=e.isEnd&&t.isEnd;return r}},applyMutationToEventStore:Ir,isPropsValid:zi,isInteractionValid:function(e,t,n){let{instances:r}=e.mutatedEvents;for(let e in r)if(!Tt(t.validRange,r[e].range))return!1;return ji({eventDrag:e},n)},isDateSelectionValid:function(e,t,n){return!!Tt(t.validRange,e.range)&&ji({dateSelection:e},n)},requestJson:Gi,BaseComponent:Sr,setRef:Tr,DelayedRunner:Zi,SimpleScrollGrid:ao,hasShrinkWidth:io,renderMicroColGroup:no,getScrollGridClassNames:oo,getSectionClassNames:so,getSectionHasLiquidHeight:Xi,getAllowYScrolling:Ki,renderChunkContent:eo,computeShrinkWidth:$i,sanitizeShrinkWidth:ro,isColPropsEqual:to,renderScrollShim:function(e){return ln("div",{className:"fc-scrollgrid-sticky-shim",style:{width:e.clientWidth,minWidth:e.tableMinWidth}})},getStickyFooterScrollbar:function(e){let{stickyFooterScrollbar:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t},getStickyHeaderDates:function(e){let{stickyHeaderDates:t}=e;return null!=t&&"auto"!==t||(t="auto"===e.height||"auto"===e.viewHeight),t},Scroller:Yi,getScrollbarWidths:Pt,RefMap:Ji,getIsRtlScrollbarOnLeft:Ht,NowTimer:xi,ScrollResponder:Er,StandardEvent:class extends Sr{render(){let{props:e,context:t}=this,{options:n}=t,{seg:r}=e,{ui:i}=r.eventRange,o=Yr(r,n.eventTimeFormat||e.defaultTimeFormat,t,e.defaultDisplayEventTime,e.defaultDisplayEventEnd);return ln(lo,Object.assign({},e,{elTag:"a",elStyle:{borderColor:i.borderColor,backgroundColor:i.backgroundColor},elAttrs:$r(r,t),defaultGenerator:co,timeText:o}),(e,t)=>ln(dn,null,ln(e,{elTag:"div",elClasses:["fc-event-main"],elStyle:{color:t.textColor}}),Boolean(t.isStartResizable)&&ln("div",{className:"fc-event-resizer fc-event-resizer-start"}),Boolean(t.isEndResizable)&&ln("div",{className:"fc-event-resizer fc-event-resizer-end"})))}},NowIndicatorContainer:e=>ln(Dr.Consumer,null,t=>{let{options:n}=t,r={isAxis:e.isAxis,date:t.dateEnv.toDate(e.date),view:t.viewApi};return ln(wi,Object.assign({},e,{elTag:e.elTag||"div",renderProps:r,generatorName:"nowIndicatorContent",customGenerator:n.nowIndicatorContent,classNameGenerator:n.nowIndicatorClassNames,didMount:n.nowIndicatorDidMount,willUnmount:n.nowIndicatorWillUnmount}))}),DayCellContainer:fo,hasCustomDayCellContent:ho,EventContainer:lo,renderFill:function(e){return ln("div",{className:"fc-"+e})},BgEvent:class extends Sr{render(){let{props:e}=this,{seg:t}=e;return ln(lo,{elTag:"div",elClasses:["fc-bg-event"],elStyle:{backgroundColor:t.eventRange.ui.backgroundColor},defaultGenerator:go,seg:t,timeText:"",isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,isPast:e.isPast,isFuture:e.isFuture,isToday:e.isToday,disableDragging:!0,disableResizing:!0})}},WeekNumberContainer:e=>ln(Dr.Consumer,null,t=>{let{dateEnv:n,options:r}=t,{date:i}=e,o=r.weekNumberFormat||e.defaultFormat,s={num:n.computeWeekNumber(i),text:n.format(i,o),date:i};return ln(wi,Object.assign({},e,{renderProps:s,generatorName:"weekNumberContent",customGenerator:r.weekNumberContent,defaultGenerator:mo,classNameGenerator:r.weekNumberClassNames,didMount:r.weekNumberDidMount,willUnmount:r.weekNumberWillUnmount}))}),MoreLinkContainer:class extends Sr{constructor(){super(...arguments),this.state={isPopoverOpen:!1,popoverId:m()},this.handleLinkEl=e=>{this.linkEl=e,this.props.elRef&&Tr(this.props.elRef,e)},this.handleClick=e=>{let{props:t,context:n}=this,{moreLinkClick:r}=n.options,i=yo(t).start;function o(e){let{def:t,instance:r,range:i}=e.eventRange;return{event:new Pr(n,t,r),start:n.dateEnv.toDate(i.start),end:n.dateEnv.toDate(i.end),isStart:e.isStart,isEnd:e.isEnd}}"function"==typeof r&&(r=r({date:i,allDay:Boolean(t.allDayDate),allSegs:t.allSegs.map(o),hiddenSegs:t.hiddenSegs.map(o),jsEvent:e,view:n.viewApi})),r&&"popover"!==r?"string"==typeof r&&n.calendarApi.zoomTo(i,r):this.setState({isPopoverOpen:!0})},this.handlePopoverClose=()=>{this.setState({isPopoverOpen:!1})}}render(){let{props:e,state:t}=this;return ln(Dr.Consumer,null,n=>{let{viewApi:r,options:i,calendarApi:o}=n,{moreLinkText:s}=i,{moreCnt:a}=e,l=yo(e),c="function"==typeof s?s.call(o,a):`+${a} ${s}`,u=R(i.moreLinkHint,[a],c),d={num:a,shortText:"+"+a,text:c,view:r};return ln(dn,null,Boolean(e.moreCnt)&&ln(wi,{elTag:e.elTag||"a",elRef:this.handleLinkEl,elClasses:[...e.elClasses||[],"fc-more-link"],elStyle:e.elStyle,elAttrs:Object.assign(Object.assign(Object.assign({},e.elAttrs),y(this.handleClick)),{title:u,"aria-expanded":t.isPopoverOpen,"aria-controls":t.isPopoverOpen?t.popoverId:""}),renderProps:d,generatorName:"moreLinkContent",customGenerator:i.moreLinkContent,defaultGenerator:e.defaultGenerator||Ao,classNameGenerator:i.moreLinkClassNames,didMount:i.moreLinkDidMount,willUnmount:i.moreLinkWillUnmount},e.children),t.isPopoverOpen&&ln(bo,{id:t.popoverId,startDate:l.start,endDate:l.end,dateProfile:e.dateProfile,todayRange:e.todayRange,extraDateSpan:e.extraDateSpan,parentEl:this.parentEl,alignmentEl:e.alignmentElRef?e.alignmentElRef.current:this.linkEl,alignGridTop:e.alignGridTop,forceTimed:e.forceTimed,onClose:this.handlePopoverClose},e.popoverContent()))})}componentDidMount(){this.updateParentEl()}componentDidUpdate(){this.updateParentEl()}updateParentEl(){this.linkEl&&(this.parentEl=l(this.linkEl,".fc-view-harness"))}},computeEarliestSegStart:_o,ViewContainer:class extends Sr{render(){let{props:e,context:t}=this,{options:n}=t,r={view:t.viewApi};return ln(wi,Object.assign({},e,{elTag:e.elTag||"div",elClasses:[...Co(e.viewSpec),...e.elClasses||[]],renderProps:r,classNameGenerator:n.viewClassNames,generatorName:void 0,didMount:n.viewDidMount,willUnmount:n.viewWillUnmount}),()=>e.children)}},triggerDateSelect:xr,getDefaultEventEnd:Mr,injectStyles:r,CalendarImpl:ko,EventImpl:Pr,buildEventApis:jr,buildElAttrs:Ei,ContentContainer:wi,CustomRenderingStore:class extends class{constructor(){this.handlers=[]}set(e){this.currentValue=e;for(let t of this.handlers)t(e)}subscribe(e){this.handlers.push(e),void 0!==this.currentValue&&e(this.currentValue)}}{constructor(){super(...arguments),this.map=new Map}handle(e){const{map:t}=this;let n=!1;e.isActive?(t.set(e.id,e),n=!0):t.has(e.id)&&(t.delete(e.id),n=!0),n&&this.set(t)}}};const xo=[],Oo={code:"en",week:{dow:0,doy:4},direction:"ltr",buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day",list:"list"},weekText:"W",weekTextLong:"Week",closeHint:"Close",timeHint:"Time",eventHint:"Event",allDayText:"all-day",moreLinkText:"more",noEventsText:"No events to display"},Mo=Object.assign(Object.assign({},Oo),{buttonHints:{prev:"Previous $0",next:"Next $0",today:(e,t)=>"day"===t?"Today":"This "+e},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`});function Io(e){let t=e.length>0?e[0].code:"en",n=xo.concat(e),r={en:Mo};for(let e of n)r[e.code]=e;return{map:r,defaultCode:t}}function No(e,t){return"object"!=typeof e||Array.isArray(e)?function(e,t){let n=[].concat(e||[]),r=function(e,t){for(let n=0;n<e.length;n+=1){let r=e[n].toLocaleLowerCase().split("-");for(let e=r.length;e>0;e-=1){let n=r.slice(0,e).join("-");if(t[n])return t[n]}}return null}(n,t)||Mo;return Bo(e,n,r)}(e,t):Bo(e.code,[e.code],e)}function Bo(e,t,n){let r=z([Oo,n],["buttonText"]);delete r.code;let{week:i}=r;return delete r.week,{codeArg:e,codes:t,week:i,simpleNumberFormat:new Intl.NumberFormat(e),options:r}}function Ho(e){return{id:D(),name:e.name,premiumReleaseDate:e.premiumReleaseDate?new Date(e.premiumReleaseDate):void 0,deps:e.deps||[],reducers:e.reducers||[],isLoadingFuncs:e.isLoadingFuncs||[],contextInit:[].concat(e.contextInit||[]),eventRefiners:e.eventRefiners||{},eventDefMemberAdders:e.eventDefMemberAdders||[],eventSourceRefiners:e.eventSourceRefiners||{},isDraggableTransformers:e.isDraggableTransformers||[],eventDragMutationMassagers:e.eventDragMutationMassagers||[],eventDefMutationAppliers:e.eventDefMutationAppliers||[],dateSelectionTransformers:e.dateSelectionTransformers||[],datePointTransforms:e.datePointTransforms||[],dateSpanTransforms:e.dateSpanTransforms||[],views:e.views||{},viewPropsTransformers:e.viewPropsTransformers||[],isPropsValid:e.isPropsValid||null,externalDefTransforms:e.externalDefTransforms||[],viewContainerAppends:e.viewContainerAppends||[],eventDropTransformers:e.eventDropTransformers||[],componentInteractions:e.componentInteractions||[],calendarInteractions:e.calendarInteractions||[],themeClasses:e.themeClasses||{},eventSourceDefs:e.eventSourceDefs||[],cmdFormatter:e.cmdFormatter,recurringTypes:e.recurringTypes||[],namedTimeZonedImpl:e.namedTimeZonedImpl,initialView:e.initialView||"",elementDraggingImpl:e.elementDraggingImpl,optionChangeHandlers:e.optionChangeHandlers||{},scrollGridImpl:e.scrollGridImpl||null,listenerRefiners:e.listenerRefiners||{},optionRefiners:e.optionRefiners||{},propSetHandlers:e.propSetHandlers||{}}}function Po(){let e,t=[],n=[];return(r,i)=>(e&&$(r,t)&&$(i,n)||(e=function(e,t){let n={},r={premiumReleaseDate:void 0,reducers:[],isLoadingFuncs:[],contextInit:[],eventRefiners:{},eventDefMemberAdders:[],eventSourceRefiners:{},isDraggableTransformers:[],eventDragMutationMassagers:[],eventDefMutationAppliers:[],dateSelectionTransformers:[],datePointTransforms:[],dateSpanTransforms:[],views:{},viewPropsTransformers:[],isPropsValid:null,externalDefTransforms:[],viewContainerAppends:[],eventDropTransformers:[],componentInteractions:[],calendarInteractions:[],themeClasses:{},eventSourceDefs:[],cmdFormatter:null,recurringTypes:[],namedTimeZonedImpl:null,initialView:"",elementDraggingImpl:null,optionChangeHandlers:{},scrollGridImpl:null,listenerRefiners:{},optionRefiners:{},propSetHandlers:{}};function i(e){for(let s of e){const e=s.name,a=n[e];void 0===a?(n[e]=s.id,i(s.deps),o=s,r={premiumReleaseDate:Uo((t=r).premiumReleaseDate,o.premiumReleaseDate),reducers:t.reducers.concat(o.reducers),isLoadingFuncs:t.isLoadingFuncs.concat(o.isLoadingFuncs),contextInit:t.contextInit.concat(o.contextInit),eventRefiners:Object.assign(Object.assign({},t.eventRefiners),o.eventRefiners),eventDefMemberAdders:t.eventDefMemberAdders.concat(o.eventDefMemberAdders),eventSourceRefiners:Object.assign(Object.assign({},t.eventSourceRefiners),o.eventSourceRefiners),isDraggableTransformers:t.isDraggableTransformers.concat(o.isDraggableTransformers),eventDragMutationMassagers:t.eventDragMutationMassagers.concat(o.eventDragMutationMassagers),eventDefMutationAppliers:t.eventDefMutationAppliers.concat(o.eventDefMutationAppliers),dateSelectionTransformers:t.dateSelectionTransformers.concat(o.dateSelectionTransformers),datePointTransforms:t.datePointTransforms.concat(o.datePointTransforms),dateSpanTransforms:t.dateSpanTransforms.concat(o.dateSpanTransforms),views:Object.assign(Object.assign({},t.views),o.views),viewPropsTransformers:t.viewPropsTransformers.concat(o.viewPropsTransformers),isPropsValid:o.isPropsValid||t.isPropsValid,externalDefTransforms:t.externalDefTransforms.concat(o.externalDefTransforms),viewContainerAppends:t.viewContainerAppends.concat(o.viewContainerAppends),eventDropTransformers:t.eventDropTransformers.concat(o.eventDropTransformers),calendarInteractions:t.calendarInteractions.concat(o.calendarInteractions),componentInteractions:t.componentInteractions.concat(o.componentInteractions),themeClasses:Object.assign(Object.assign({},t.themeClasses),o.themeClasses),eventSourceDefs:t.eventSourceDefs.concat(o.eventSourceDefs),cmdFormatter:o.cmdFormatter||t.cmdFormatter,recurringTypes:t.recurringTypes.concat(o.recurringTypes),namedTimeZonedImpl:o.namedTimeZonedImpl||t.namedTimeZonedImpl,initialView:t.initialView||o.initialView,elementDraggingImpl:t.elementDraggingImpl||o.elementDraggingImpl,optionChangeHandlers:Object.assign(Object.assign({},t.optionChangeHandlers),o.optionChangeHandlers),scrollGridImpl:o.scrollGridImpl||t.scrollGridImpl,listenerRefiners:Object.assign(Object.assign({},t.listenerRefiners),o.listenerRefiners),optionRefiners:Object.assign(Object.assign({},t.optionRefiners),o.optionRefiners),propSetHandlers:Object.assign(Object.assign({},t.propSetHandlers),o.propSetHandlers)}):a!==s.id&&console.warn(`Duplicate plugin '${e}'`)}var t,o}return e&&i(e),i(t),r}(r,i)),t=r,n=i,e)}function Uo(e,t){return void 0===e?t:void 0===t?e:new Date(Math.max(e.valueOf(),t.valueOf()))}class jo extends Gt{}function zo(e,t,n,r){if(t[e])return t[e];let i=function(e,t,n,r){let i=n[e],o=r[e],s=e=>i&&null!==i[e]?i[e]:o&&null!==o[e]?o[e]:null,a=s("component"),l=s("superType"),c=null;if(l){if(l===e)throw new Error("Can't have a custom view type that references itself");c=zo(l,t,n,r)}!a&&c&&(a=c.component);if(!a)return null;return{type:e,component:a,defaults:Object.assign(Object.assign({},c?c.defaults:{}),i?i.rawOptions:{}),overrides:Object.assign(Object.assign({},c?c.overrides:{}),o?o.rawOptions:{})}}(e,t,n,r);return i&&(t[e]=i),i}function Fo(e){return L(e,Lo)}function Lo(e){let t="function"==typeof e?{component:e}:e,{component:n}=t;return t.content?n=Vo(t):!n||n.prototype instanceof Sr||(n=Vo(Object.assign(Object.assign({},t),{content:n}))),{superType:t.type,component:n,rawOptions:t}}function Vo(e){return t=>ln(Dr.Consumer,null,n=>ln(wi,{elTag:"div",elClasses:Co(n.viewSpec),renderProps:Object.assign(Object.assign({},t),{nextDayThreshold:n.options.nextDayThreshold}),generatorName:void 0,customGenerator:e.content,classNameGenerator:e.classNames,didMount:e.didMount,willUnmount:e.willUnmount}))}function Wo(e,t,n,r){let i=Fo(e),o=Fo(t.views);return L(function(e,t){let n,r={};for(n in e)zo(n,r,e,t);for(n in t)zo(n,r,e,t);return r}(i,o),e=>function(e,t,n,r,i){let o=e.overrides.duration||e.defaults.duration||r.duration||n.duration,s=null,a="",l="",c={};if(o&&(s=function(e){let t=JSON.stringify(e),n=Qo[t];void 0===n&&(n=N(e),Qo[t]=n);return n}(o),s)){let e=U(s);a=e.unit,1===e.value&&(l=a,c=t[a]?t[a].rawOptions:{})}let u=t=>{let n=t.buttonText||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null},d=t=>{let n=t.buttonHints||{},r=e.defaults.buttonTextKey;return null!=r&&null!=n[r]?n[r]:null!=n[e.type]?n[e.type]:null!=n[l]?n[l]:null};return{type:e.type,component:e.component,duration:s,durationUnit:a,singleUnit:l,optionDefaults:e.defaults,optionOverrides:Object.assign(Object.assign({},c),e.overrides),buttonTextOverride:u(r)||u(n)||e.overrides.buttonText,buttonTextDefault:u(i)||e.defaults.buttonText||u(Ne)||e.type,buttonTitleOverride:d(r)||d(n)||e.overrides.buttonHint,buttonTitleDefault:d(i)||e.defaults.buttonHint||d(Ne)}}(e,o,t,n,r))}jo.prototype.classes={root:"fc-theme-standard",tableCellShaded:"fc-cell-shaded",buttonGroup:"fc-button-group",button:"fc-button fc-button-primary",buttonActive:"fc-button-active"},jo.prototype.baseIconClass="fc-icon",jo.prototype.iconClasses={close:"fc-icon-x",prev:"fc-icon-chevron-left",next:"fc-icon-chevron-right",prevYear:"fc-icon-chevrons-left",nextYear:"fc-icon-chevrons-right"},jo.prototype.rtlIconClasses={prev:"fc-icon-chevron-right",next:"fc-icon-chevron-left",prevYear:"fc-icon-chevrons-right",nextYear:"fc-icon-chevrons-left"},jo.prototype.iconOverrideOption="buttonIcons",jo.prototype.iconOverrideCustomButtonOption="icon",jo.prototype.iconOverridePrefix="fc-icon-";let Qo={};function Go(e,t,n){let r=t?t.activeRange:null;return Yo({},function(e,t){let n=To(t),r=[].concat(e.eventSources||[]),i=[];e.initialEvents&&r.unshift(e.initialEvents);e.events&&r.unshift(e.events);for(let e of r){let r=So(e,t,n);r&&i.push(r)}return i}(e,n),r,n)}function Zo(e,t,n,r){let i=n?n.activeRange:null;switch(t.type){case"ADD_EVENT_SOURCES":return Yo(e,t.sources,i,r);case"REMOVE_EVENT_SOURCE":return o=e,s=t.sourceId,F(o,e=>e.sourceId!==s);case"PREV":case"NEXT":case"CHANGE_DATE":case"CHANGE_VIEW_TYPE":return n?Jo(e,i,r):e;case"FETCH_EVENT_SOURCES":return $o(e,t.sourceIds?V(t.sourceIds):Ko(e,r),i,t.isRefetch||!1,r);case"RECEIVE_EVENTS":case"RECEIVE_EVENT_ERROR":return function(e,t,n,r){let i=e[t];if(i&&n===i.latestFetchId)return Object.assign(Object.assign({},e),{[t]:Object.assign(Object.assign({},i),{isFetching:!1,fetchRange:r})});return e}(e,t.sourceId,t.fetchId,t.fetchRange);case"REMOVE_ALL_EVENT_SOURCES":return{};default:return e}var o,s}function qo(e){for(let t in e)if(e[t].isFetching)return!0;return!1}function Yo(e,t,n,r){let i={};for(let e of t)i[e.sourceId]=e;return n&&(i=Jo(i,n,r)),Object.assign(Object.assign({},e),i)}function Jo(e,t,n){return $o(e,F(e,e=>function(e,t,n){if(!es(e,n))return!e.latestFetchId;return!n.options.lazyFetching||!e.fetchRange||e.isFetching||t.start<e.fetchRange.start||t.end>e.fetchRange.end}(e,t,n)),t,!1,n)}function $o(e,t,n,r,i){let o={};for(let s in e){let a=e[s];t[s]?o[s]=Xo(a,n,r,i):o[s]=a}return o}function Xo(e,t,n,r){let{options:i,calendarApi:o}=r,s=r.pluginHooks.eventSourceDefs[e.sourceDefId],a=D();return s.fetch({eventSource:e,range:t,isRefetch:n,context:r},n=>{let{rawEvents:s}=n;i.eventSourceSuccess&&(s=i.eventSourceSuccess.call(o,s,n.response)||s),e.success&&(s=e.success.call(o,s,n.response)||s),r.dispatch({type:"RECEIVE_EVENTS",sourceId:e.sourceId,fetchId:a,fetchRange:t,rawEvents:s})},n=>{let s=!1;i.eventSourceFailure&&(i.eventSourceFailure.call(o,n),s=!0),e.failure&&(e.failure(n),s=!0),s||console.warn(n.message,n),r.dispatch({type:"RECEIVE_EVENT_ERROR",sourceId:e.sourceId,fetchId:a,fetchRange:t,error:n})}),Object.assign(Object.assign({},e),{isFetching:!0,latestFetchId:a})}function Ko(e,t){return F(e,e=>es(e,t))}function es(e,t){return!t.pluginHooks.eventSourceDefs[e.sourceDefId].ignoreRange}function ts(e,t){switch(t.type){case"UNSELECT_DATES":return null;case"SELECT_DATES":return t.selection;default:return e}}function ns(e,t){switch(t.type){case"UNSELECT_EVENT":return"";case"SELECT_EVENT":return t.eventInstanceId;default:return e}}function rs(e,t){let n;switch(t.type){case"UNSET_EVENT_DRAG":return null;case"SET_EVENT_DRAG":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function is(e,t){let n;switch(t.type){case"UNSET_EVENT_RESIZE":return null;case"SET_EVENT_RESIZE":return n=t.state,{affectedEvents:n.affectedEvents,mutatedEvents:n.mutatedEvents,isEvent:n.isEvent};default:return e}}function os(e,t,n,r,i){return{header:e.headerToolbar?ss(e.headerToolbar,e,t,n,r,i):null,footer:e.footerToolbar?ss(e.footerToolbar,e,t,n,r,i):null}}function ss(e,t,n,r,i,o){let s={},a=[],l=!1;for(let c in e){let u=as(e[c],t,n,r,i,o);s[c]=u.widgets,a.push(...u.viewsWithButtons),l=l||u.hasTitle}return{sectionWidgets:s,viewsWithButtons:a,hasTitle:l}}function as(e,t,n,r,i,o){let s="rtl"===t.direction,a=t.customButtons||{},l=n.buttonText||{},c=t.buttonText||{},u=n.buttonHints||{},d=t.buttonHints||{},f=e?e.split(" "):[],h=[],p=!1;return{widgets:f.map(e=>e.split(",").map(e=>{if("title"===e)return p=!0,{buttonName:e};let n,f,g,m,v,b;if(n=a[e])g=e=>{n.click&&n.click.call(e.target,e,e.target)},(m=r.getCustomButtonIconClass(n))||(m=r.getIconClass(e,s))||(v=n.text),b=n.hint||n.text;else if(f=i[e]){h.push(e),g=()=>{o.changeView(e)},(v=f.buttonTextOverride)||(m=r.getIconClass(e,s))||(v=f.buttonTextDefault);let n=f.buttonTextOverride||f.buttonTextDefault;b=R(f.buttonTitleOverride||f.buttonTitleDefault||t.viewHint,[n,e],n)}else if(o[e])if(g=()=>{o[e]()},(v=l[e])||(m=r.getIconClass(e,s))||(v=c[e]),"prevYear"===e||"nextYear"===e){let t="prevYear"===e?"prev":"next";b=R(u[t]||d[t],[c.year||"year","year"],c[e])}else b=t=>R(u[e]||d[e],[c[t]||t,t],c[e]);return{buttonName:e,buttonClick:g,buttonIcon:m,buttonText:v,buttonHint:b}})),viewsWithButtons:h,hasTitle:p}}class ls{constructor(e,t,n){this.type=e,this.getCurrentData=t,this.dateEnv=n}get calendar(){return this.getCurrentData().calendarApi}get title(){return this.getCurrentData().viewTitle}get activeStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start)}get activeEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end)}get currentStart(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start)}get currentEnd(){return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end)}getOption(e){return this.getCurrentData().options[e]}}function cs(e,t){let n=W(t.getCurrentData().eventSources);if(1===n.length&&1===e.length&&Array.isArray(n[0]._raw)&&Array.isArray(e[0]))return void t.dispatch({type:"RESET_RAW_EVENTS",sourceId:n[0].sourceId,rawEvents:e[0]});let r=[];for(let t of e){let e=!1;for(let r=0;r<n.length;r+=1)if(n[r]._raw===t){n.splice(r,1),e=!0;break}e||r.push(t)}for(let e of n)t.dispatch({type:"REMOVE_EVENT_SOURCE",sourceId:e.sourceId});for(let e of r)t.calendarApi.addEventSource(e)}const us=[Ho({name:"array-event-source",eventSourceDefs:[{ignoreRange:!0,parseMeta:e=>Array.isArray(e.events)?e.events:null,fetch(e,t){t({rawEvents:e.eventSource.meta})}}]}),Ho({name:"func-event-source",eventSourceDefs:[{parseMeta:e=>"function"==typeof e.events?e.events:null,fetch(e,t,n){const{dateEnv:r}=e.context;Lt(e.eventSource.meta.bind(null,ei(e.range,r)),e=>t({rawEvents:e}),n)}}]}),Ho({name:"json-event-source",eventSourceRefiners:{method:String,extraParams:Ve,startParam:String,endParam:String,timeZoneParam:String},eventSourceDefs:[{parseMeta:e=>!e.url||"json"!==e.format&&e.format?null:{url:e.url,format:"json",method:(e.method||"GET").toUpperCase(),extraParams:e.extraParams,startParam:e.startParam,endParam:e.endParam,timeZoneParam:e.timeZoneParam},fetch(e,t,n){const{meta:r}=e.eventSource,i=function(e,t,n){let r,i,o,s,{dateEnv:a,options:l}=n,c={};r=e.startParam,null==r&&(r=l.startParam);i=e.endParam,null==i&&(i=l.endParam);o=e.timeZoneParam,null==o&&(o=l.timeZoneParam);s="function"==typeof e.extraParams?e.extraParams():e.extraParams||{};Object.assign(c,s),c[r]=a.formatIso(t.start),c[i]=a.formatIso(t.end),"local"!==a.timeZone&&(c[o]=a.timeZone);return c}(r,e.range,e.context);Gi(r.method,r.url,i).then(([e,n])=>{t({rawEvents:e,response:n})},n)}}]}),Ho({name:"simple-recurring-event",recurringTypes:[{parse(e,t){if(e.daysOfWeek||e.startTime||e.endTime||e.startRecur||e.endRecur){let i,o={daysOfWeek:e.daysOfWeek||null,startTime:e.startTime||null,endTime:e.endTime||null,startRecur:e.startRecur?t.createMarker(e.startRecur):null,endRecur:e.endRecur?t.createMarker(e.endRecur):null,dateEnv:t};return e.duration&&(i=e.duration),!i&&e.startTime&&e.endTime&&(n=e.endTime,r=e.startTime,i={years:n.years-r.years,months:n.months-r.months,days:n.days-r.days,milliseconds:n.milliseconds-r.milliseconds}),{allDayGuess:Boolean(!e.startTime&&!e.endTime),duration:i,typeData:o}}var n,r;return null},expand(e,t,n){let r=Ct(t,{start:e.startRecur,end:e.endRecur});return r?function(e,t,n,r,i){let o=e?V(e):null,s=oe(i.start),a=i.end,l=[];for(;s<a;){let e;o&&!o[s.getUTCDay()]||(e=t?r.add(s,t):s,l.push(r.createMarker(n.toDate(e)))),s=K(s,1)}return l}(e.daysOfWeek,e.startTime,e.dateEnv,n,r):[]}}],eventRefiners:{daysOfWeek:Ve,startTime:N,endTime:N,duration:N,startRecur:Ve,endRecur:Ve}}),Ho({name:"change-handler",optionChangeHandlers:{events(e,t){cs([e],t)},eventSources:cs}}),Ho({name:"misc",isLoadingFuncs:[e=>qo(e.eventSources)],propSetHandlers:{dateProfile:function(e,t){t.emitter.trigger("datesSet",Object.assign(Object.assign({},ei(e.activeRange,t.dateEnv)),{view:t.viewApi}))},eventStore:function(e,t){let{emitter:n}=t;n.hasHandlers("eventsSet")&&n.trigger("eventsSet",jr(e,t))}}})];class ds{constructor(e,t){this.runTaskOption=e,this.drainedOption=t,this.queue=[],this.delayedRunner=new Zi(this.drain.bind(this))}request(e,t){this.queue.push(e),this.delayedRunner.request(t)}pause(e){this.delayedRunner.pause(e)}resume(e,t){this.delayedRunner.resume(e,t)}drain(){let{queue:e}=this;for(;e.length;){let t,n=[];for(;t=e.shift();)this.runTask(t),n.push(t);this.drained(n)}}runTask(e){this.runTaskOption&&this.runTaskOption(e)}drained(e){this.drainedOption&&this.drainedOption(e)}}function fs(e,t,n){let r;return r=/^(year|month)$/.test(e.currentRangeUnit)?e.currentRange:e.activeRange,n.formatRange(r.start,r.end,Me(t.titleFormat||function(e){let{currentRangeUnit:t}=e;if("year"===t)return{year:"numeric"};if("month"===t)return{year:"numeric",month:"long"};let n=ie(e.currentRange.start,e.currentRange.end);if(null!==n&&n>1)return{year:"numeric",month:"short",day:"numeric"};return{year:"numeric",month:"long",day:"numeric"}}(e)),{isEndExclusive:e.isRangeAllDay,defaultSeparator:t.titleRangeSeparator})}class hs{constructor(){this.resetListeners=new Set}handleInput(e,t){const n=this.dateEnv;if(e!==n&&("function"==typeof t?this.nowFn=t:n||(this.nowAnchorDate=e.toDate(t?e.createMarker(t):e.createNowMarker()),this.nowAnchorQueried=Date.now()),this.dateEnv=e,n))for(const e of this.resetListeners.values())e()}getDateMarker(){return this.nowAnchorDate?this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf()+(Date.now()-this.nowAnchorQueried)):this.dateEnv.createMarker(this.nowFn())}addResetListener(e){this.resetListeners.add(e)}removeResetListener(e){this.resetListeners.delete(e)}}class ps{constructor(e){this.computeCurrentViewData=ve(this._computeCurrentViewData),this.organizeRawLocales=ve(Io),this.buildLocale=ve(No),this.buildPluginHooks=Po(),this.buildDateEnv=ve(gs),this.buildTheme=ve(ms),this.parseToolbars=ve(os),this.buildViewSpecs=ve(Wo),this.buildDateProfileGenerator=be(vs),this.buildViewApi=ve(bs),this.buildViewUiProps=be(_s),this.buildEventUiBySource=ve(As,Q),this.buildEventUiBases=ve(ys),this.parseContextBusinessHours=be(Ds),this.buildTitle=ve(fs),this.nowManager=new hs,this.emitter=new Vt,this.actionRunner=new ds(this._handleAction.bind(this),this.updateData.bind(this)),this.currentCalendarOptionsInput={},this.currentCalendarOptionsRefined={},this.currentViewOptionsInput={},this.currentViewOptionsRefined={},this.currentCalendarOptionsRefiners={},this.optionsForRefining=[],this.optionsForHandling=[],this.getCurrentData=()=>this.data,this.dispatch=e=>{this.actionRunner.request(e)},this.props=e,this.actionRunner.pause(),this.nowManager=new hs;let t={},n=this.computeOptionsData(e.optionOverrides,t,e.calendarApi),r=n.calendarOptions.initialView||n.pluginHooks.initialView,i=this.computeCurrentViewData(r,n,e.optionOverrides,t);e.calendarApi.currentDataManager=this,this.emitter.setThisContext(e.calendarApi),this.emitter.setOptions(i.options);let o={nowManager:this.nowManager,dateEnv:n.dateEnv,options:n.calendarOptions,pluginHooks:n.pluginHooks,calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData},s=function(e,t,n){let r=e.initialDate;return null!=r?t.createMarker(r):n.getDateMarker()}(n.calendarOptions,n.dateEnv,this.nowManager),a=i.dateProfileGenerator.build(s);kt(a.activeRange,s)||(s=a.currentRange.start);for(let e of n.pluginHooks.contextInit)e(o);let l=Go(n.calendarOptions,a,o),c={dynamicOptionOverrides:t,currentViewType:r,currentDate:s,dateProfile:a,businessHours:this.parseContextBusinessHours(o),eventSources:l,eventUiBases:{},eventStore:{defs:{},instances:{}},renderableEventStore:{defs:{},instances:{}},dateSelection:null,eventSelection:"",eventDrag:null,eventResize:null,selectionConfig:this.buildViewUiProps(o).selectionConfig},u=Object.assign(Object.assign({},o),c);for(let e of n.pluginHooks.reducers)Object.assign(c,e(null,null,u));Es(c,o)&&this.emitter.trigger("loading",!0),this.state=c,this.updateData(),this.actionRunner.resume()}resetOptions(e,t){let{props:n}=this;void 0===t?n.optionOverrides=e:(n.optionOverrides=Object.assign(Object.assign({},n.optionOverrides||{}),e),this.optionsForRefining.push(...t)),(void 0===t||t.length)&&this.actionRunner.request({type:"NOTHING"})}_handleAction(e){let{props:t,state:n,emitter:r}=this,i=function(e,t){switch(t.type){case"SET_OPTION":return Object.assign(Object.assign({},e),{[t.optionName]:t.rawOptionValue});default:return e}}(n.dynamicOptionOverrides,e),o=this.computeOptionsData(t.optionOverrides,i,t.calendarApi),s=function(e,t){switch(t.type){case"CHANGE_VIEW_TYPE":e=t.viewType}return e}(n.currentViewType,e),a=this.computeCurrentViewData(s,o,t.optionOverrides,i);t.calendarApi.currentDataManager=this,r.setThisContext(t.calendarApi),r.setOptions(a.options);let l={nowManager:this.nowManager,dateEnv:o.dateEnv,options:o.calendarOptions,pluginHooks:o.pluginHooks,calendarApi:t.calendarApi,dispatch:this.dispatch,emitter:r,getCurrentData:this.getCurrentData},{currentDate:c,dateProfile:u}=n;this.data&&this.data.dateProfileGenerator!==a.dateProfileGenerator&&(u=a.dateProfileGenerator.build(c)),c=function(e,t){switch(t.type){case"CHANGE_DATE":return t.dateMarker;default:return e}}(c,e),u=function(e,t,n,r){let i;switch(t.type){case"CHANGE_VIEW_TYPE":return r.build(t.dateMarker||n);case"CHANGE_DATE":return r.build(t.dateMarker);case"PREV":if(i=r.buildPrev(e,n),i.isValid)return i;break;case"NEXT":if(i=r.buildNext(e,n),i.isValid)return i}return e}(u,e,c,a.dateProfileGenerator),"PREV"!==e.type&&"NEXT"!==e.type&&kt(u.currentRange,c)||(c=u.currentRange.start);let d=Zo(n.eventSources,e,u,l),f=Ni(n.eventStore,e,d,u,l),h=qo(d)&&!a.options.progressiveEventRendering&&n.renderableEventStore||f,{eventUiSingleBase:p,selectionConfig:g}=this.buildViewUiProps(l),m=this.buildEventUiBySource(d),v={dynamicOptionOverrides:i,currentViewType:s,currentDate:c,dateProfile:u,eventSources:d,eventStore:f,renderableEventStore:h,selectionConfig:g,eventUiBases:this.buildEventUiBases(h.defs,p,m),businessHours:this.parseContextBusinessHours(l),dateSelection:ts(n.dateSelection,e),eventSelection:ns(n.eventSelection,e),eventDrag:rs(n.eventDrag,e),eventResize:is(n.eventResize,e)},b=Object.assign(Object.assign({},l),v);for(let t of o.pluginHooks.reducers)Object.assign(v,t(n,e,b));let A=Es(n,l),y=Es(v,l);!A&&y?r.trigger("loading",!0):A&&!y&&r.trigger("loading",!1),this.state=v,t.onAction&&t.onAction(e)}updateData(){let{props:e,state:t}=this,n=this.data,r=this.computeOptionsData(e.optionOverrides,t.dynamicOptionOverrides,e.calendarApi),i=this.computeCurrentViewData(t.currentViewType,r,e.optionOverrides,t.dynamicOptionOverrides),o=this.data=Object.assign(Object.assign(Object.assign({nowManager:this.nowManager,viewTitle:this.buildTitle(t.dateProfile,i.options,r.dateEnv),calendarApi:e.calendarApi,dispatch:this.dispatch,emitter:this.emitter,getCurrentData:this.getCurrentData},r),i),t),s=r.pluginHooks.optionChangeHandlers,a=n&&n.calendarOptions,l=r.calendarOptions;if(a&&a!==l){a.timeZone!==l.timeZone&&(t.eventSources=o.eventSources=function(e,t,n){let r=t?t.activeRange:null;return $o(e,Ko(e,n),r,!0,n)}(o.eventSources,t.dateProfile,o),t.eventStore=o.eventStore=Pi(o.eventStore,n.dateEnv,o.dateEnv),t.renderableEventStore=o.renderableEventStore=Pi(o.renderableEventStore,n.dateEnv,o.dateEnv));for(let e in s)-1===this.optionsForHandling.indexOf(e)&&a[e]===l[e]||s[e](l[e],o)}this.optionsForHandling=[],e.onData&&e.onData(o)}computeOptionsData(e,t,n){if(!this.optionsForRefining.length&&e===this.stableOptionOverrides&&t===this.stableDynamicOptionOverrides)return this.stableCalendarOptionsData;let{refinedOptions:r,pluginHooks:i,localeDefaults:o,availableLocaleData:s,extra:a}=this.processRawCalendarOptions(e,t);Cs(a);let l=this.buildDateEnv(r.timeZone,r.locale,r.weekNumberCalculation,r.firstDay,r.weekText,i,s,r.defaultRangeSeparator),c=this.buildViewSpecs(i.views,this.stableOptionOverrides,this.stableDynamicOptionOverrides,o),u=this.buildTheme(r,i),d=this.parseToolbars(r,this.stableOptionOverrides,u,c,n);return this.stableCalendarOptionsData={calendarOptions:r,pluginHooks:i,dateEnv:l,viewSpecs:c,theme:u,toolbarConfig:d,localeDefaults:o,availableRawLocales:s.map}}processRawCalendarOptions(e,t){let{locales:n,locale:r}=Fe([Ne,e,t]),i=this.organizeRawLocales(n),o=i.map,s=this.buildLocale(r||i.defaultCode,o).options,a=this.buildPluginHooks(e.plugins||[],us),l=this.currentCalendarOptionsRefiners=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},Ie),Be),He),a.listenerRefiners),a.optionRefiners),c={},u=Fe([Ne,s,e,t]),d={},f=this.currentCalendarOptionsInput,h=this.currentCalendarOptionsRefined,p=!1;for(let e in u)-1===this.optionsForRefining.indexOf(e)&&(u[e]===f[e]||Pe[e]&&e in f&&Pe[e](f[e],u[e]))?d[e]=h[e]:l[e]?(d[e]=l[e](u[e]),p=!0):c[e]=f[e];return p&&(this.currentCalendarOptionsInput=u,this.currentCalendarOptionsRefined=d,this.stableOptionOverrides=e,this.stableDynamicOptionOverrides=t),this.optionsForHandling.push(...this.optionsForRefining),this.optionsForRefining=[],{rawOptions:this.currentCalendarOptionsInput,refinedOptions:this.currentCalendarOptionsRefined,pluginHooks:a,availableLocaleData:i,localeDefaults:s,extra:c}}_computeCurrentViewData(e,t,n,r){let i=t.viewSpecs[e];if(!i)throw new Error(`viewType "${e}" is not available. Please make sure you've loaded all neccessary plugins`);let{refinedOptions:o,extra:s}=this.processRawViewOptions(i,t.pluginHooks,t.localeDefaults,n,r);return Cs(s),this.nowManager.handleInput(t.dateEnv,o.now),{viewSpec:i,options:o,dateProfileGenerator:this.buildDateProfileGenerator({dateProfileGeneratorClass:i.optionDefaults.dateProfileGeneratorClass,nowManager:this.nowManager,duration:i.duration,durationUnit:i.durationUnit,usesMinMaxTime:i.optionDefaults.usesMinMaxTime,dateEnv:t.dateEnv,calendarApi:this.props.calendarApi,slotMinTime:o.slotMinTime,slotMaxTime:o.slotMaxTime,showNonCurrentDates:o.showNonCurrentDates,dayCount:o.dayCount,dateAlignment:o.dateAlignment,dateIncrement:o.dateIncrement,hiddenDays:o.hiddenDays,weekends:o.weekends,validRangeInput:o.validRange,visibleRangeInput:o.visibleRange,fixedWeekCount:o.fixedWeekCount}),viewApi:this.buildViewApi(e,this.getCurrentData,t.dateEnv)}}processRawViewOptions(e,t,n,r,i){let o=Fe([Ne,e.optionDefaults,n,r,e.optionOverrides,i]),s=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},Ie),Be),He),ze),t.listenerRefiners),t.optionRefiners),a={},l=this.currentViewOptionsInput,c=this.currentViewOptionsRefined,u=!1,d={};for(let e in o)o[e]===l[e]||Pe[e]&&Pe[e](o[e],l[e])?a[e]=c[e]:(o[e]===this.currentCalendarOptionsInput[e]||Pe[e]&&Pe[e](o[e],this.currentCalendarOptionsInput[e])?e in this.currentCalendarOptionsRefined&&(a[e]=this.currentCalendarOptionsRefined[e]):s[e]?a[e]=s[e](o[e]):d[e]=o[e],u=!0);return u&&(this.currentViewOptionsInput=o,this.currentViewOptionsRefined=a),{rawOptions:this.currentViewOptionsInput,refinedOptions:this.currentViewOptionsRefined,extra:d}}}function gs(e,t,n,r,i,o,s,a){let l=No(t||s.defaultCode,s.map);return new ai({calendarSystem:"gregory",timeZone:e,namedTimeZoneImpl:o.namedTimeZonedImpl,locale:l,weekNumberCalculation:n,firstDay:r,weekText:i,cmdFormatter:o.cmdFormatter,defaultSeparator:a})}function ms(e,t){return new(t.themeClasses[e.themeSystem]||jo)(e)}function vs(e){return new(e.dateProfileGeneratorClass||Rr)(e)}function bs(e,t,n){return new ls(e,t,n)}function As(e){return L(e,e=>e.ui)}function ys(e,t,n){let r={"":t};for(let t in e){let i=e[t];i.sourceId&&n[i.sourceId]&&(r[t]=n[i.sourceId])}return r}function _s(e){let{options:t}=e;return{eventUiSingleBase:nt({display:t.eventDisplay,editable:t.editable,startEditable:t.eventStartEditable,durationEditable:t.eventDurationEditable,constraint:t.eventConstraint,overlap:"boolean"==typeof t.eventOverlap?t.eventOverlap:void 0,allow:t.eventAllow,backgroundColor:t.eventBackgroundColor,borderColor:t.eventBorderColor,textColor:t.eventTextColor,color:t.eventColor},e),selectionConfig:nt({constraint:t.selectConstraint,overlap:"boolean"==typeof t.selectOverlap?t.selectOverlap:void 0,allow:t.selectAllow},e)}}function Es(e,t){for(let n of t.pluginHooks.isLoadingFuncs)if(n(e))return!0;return!1}function Ds(e){return ht(e.options.businessHours,e)}function Cs(e,t){for(let n in e)console.warn(`Unknown option '${n}'`+(t?` for view '${t}'`:""))}class ws extends Sr{render(){return ln("div",{className:"fc-toolbar-chunk"},...this.props.widgetGroups.map(e=>this.renderWidgetGroup(e)))}renderWidgetGroup(e){let{props:t}=this,{theme:n}=this.context,r=[],i=!0;for(let o of e){let{buttonName:e,buttonClick:s,buttonText:a,buttonIcon:l,buttonHint:c}=o;if("title"===e)i=!1,r.push(ln("h2",{className:"fc-toolbar-title",id:t.titleId},t.title));else{let i=e===t.activeButton,o=!t.isTodayEnabled&&"today"===e||!t.isPrevEnabled&&"prev"===e||!t.isNextEnabled&&"next"===e,u=[`fc-${e}-button`,n.getClass("button")];i&&u.push(n.getClass("buttonActive")),r.push(ln("button",{type:"button",title:"function"==typeof c?c(t.navUnit):c,disabled:o,"aria-pressed":i,className:u.join(" "),onClick:s},a||(l?ln("span",{className:l,role:"img"}):"")))}}if(r.length>1){return ln("div",{className:i&&n.getClass("buttonGroup")||""},...r)}return r[0]}}class Ss extends Sr{render(){let e,t,{model:n,extraClassName:r}=this.props,i=!1,o=n.sectionWidgets,s=o.center;return o.left?(i=!0,e=o.left):e=o.start,o.right?(i=!0,t=o.right):t=o.end,ln("div",{className:[r||"","fc-toolbar",i?"fc-toolbar-ltr":""].join(" ")},this.renderSection("start",e||[]),this.renderSection("center",s||[]),this.renderSection("end",t||[]))}renderSection(e,t){let{props:n}=this;return ln(ws,{key:e,widgetGroups:t,title:n.title,navUnit:n.navUnit,activeButton:n.activeButton,isTodayEnabled:n.isTodayEnabled,isPrevEnabled:n.isPrevEnabled,isNextEnabled:n.isNextEnabled,titleId:n.titleId})}}class Ts extends Sr{constructor(){super(...arguments),this.state={availableWidth:null},this.handleEl=e=>{this.el=e,Tr(this.props.elRef,e),this.updateAvailableWidth()},this.handleResize=()=>{this.updateAvailableWidth()}}render(){let{props:e,state:t}=this,{aspectRatio:n}=e,r=["fc-view-harness",n||e.liquid||e.height?"fc-view-harness-active":"fc-view-harness-passive"],i="",o="";return n?null!==t.availableWidth?i=t.availableWidth/n:o=1/n*100+"%":i=e.height||"",ln("div",{"aria-labelledby":e.labeledById,ref:this.handleEl,className:r.join(" "),style:{height:i,paddingBottom:o}},e.children)}componentDidMount(){this.context.addResizeHandler(this.handleResize)}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}updateAvailableWidth(){this.el&&this.props.aspectRatio&&this.setState({availableWidth:this.el.offsetWidth})}}class ks extends hi{constructor(e){super(e),this.handleSegClick=(e,t)=>{let{component:n}=this,{context:r}=n,i=Lr(t);if(i&&n.isValidSegDownEl(e.target)){let o=l(e.target,".fc-event-forced-url"),s=o?o.querySelector("a[href]").href:"";r.emitter.trigger("eventClick",{el:t,event:new Pr(n.context,i.eventRange.def,i.eventRange.instance),jsEvent:e,view:r.viewApi}),s&&!e.defaultPrevented&&(window.location.href=s)}},this.destroy=b(e.el,"click",".fc-event",this.handleSegClick)}}class Rs extends hi{constructor(e){super(e),this.handleEventElRemove=e=>{e===this.currentSegEl&&this.handleSegLeave(null,this.currentSegEl)},this.handleSegEnter=(e,t)=>{Lr(t)&&(this.currentSegEl=t,this.triggerEvent("eventMouseEnter",e,t))},this.handleSegLeave=(e,t)=>{this.currentSegEl&&(this.currentSegEl=null,this.triggerEvent("eventMouseLeave",e,t))},this.removeHoverListeners=function(e,t,n,r){let i;return b(e,"mouseover",t,(e,t)=>{if(t!==i){i=t,n(e,t);let o=e=>{i=null,r(e,t),t.removeEventListener("mouseleave",o)};t.addEventListener("mouseleave",o)}})}(e.el,".fc-event",this.handleSegEnter,this.handleSegLeave)}destroy(){this.removeHoverListeners()}triggerEvent(e,t,n){let{component:r}=this,{context:i}=r,o=Lr(n);t&&!r.isValidSegDownEl(t.target)||i.emitter.trigger(e,{el:n,event:new Pr(i,o.eventRange.def,o.eventRange.instance),jsEvent:t,view:i.viewApi})}}class xs extends wr{constructor(){super(...arguments),this.buildViewContext=ve(Cr),this.buildViewPropTransformers=ve(Ms),this.buildToolbarProps=ve(Os),this.headerRef={current:null},this.footerRef={current:null},this.interactionsStore={},this.state={viewLabelId:m()},this.registerInteractiveComponent=(e,t)=>{let n=function(e,t){return{component:e,el:t.el,useEventCenter:null==t.useEventCenter||t.useEventCenter,isHitComboAllowed:t.isHitComboAllowed||null}}(e,t),r=[ks,Rs].concat(this.props.pluginHooks.componentInteractions).map(e=>new e(n));this.interactionsStore[e.uid]=r,pi[e.uid]=n},this.unregisterInteractiveComponent=e=>{let t=this.interactionsStore[e.uid];if(t){for(let e of t)e.destroy();delete this.interactionsStore[e.uid]}delete pi[e.uid]},this.resizeRunner=new Zi(()=>{this.props.emitter.trigger("_resize",!0),this.props.emitter.trigger("windowResize",{view:this.props.viewApi})}),this.handleWindowResize=e=>{let{options:t}=this.props;t.handleWindowResize&&e.target===window&&this.resizeRunner.request(t.windowResizeDelay)}}render(){let e,{props:t}=this,{toolbarConfig:n,options:r}=t,i=!1,o="";t.isHeightAuto||t.forPrint?o="":null!=r.height?i=!0:null!=r.contentHeight?o=r.contentHeight:e=Math.max(r.aspectRatio,.5);let s=this.buildViewContext(t.viewSpec,t.viewApi,t.options,t.dateProfileGenerator,t.dateEnv,t.nowManager,t.theme,t.pluginHooks,t.dispatch,t.getCurrentData,t.emitter,t.calendarApi,this.registerInteractiveComponent,this.unregisterInteractiveComponent),a=n.header&&n.header.hasTitle?this.state.viewLabelId:void 0;return ln(Dr.Provider,{value:s},ln(xi,{unit:"day"},r=>{let s=this.buildToolbarProps(t.viewSpec,t.dateProfile,t.dateProfileGenerator,t.currentDate,r,t.viewTitle);return ln(dn,null,n.header&&ln(Ss,Object.assign({ref:this.headerRef,extraClassName:"fc-header-toolbar",model:n.header,titleId:a},s)),ln(Ts,{liquid:i,height:o,aspectRatio:e,labeledById:a},this.renderView(t),this.buildAppendContent()),n.footer&&ln(Ss,Object.assign({ref:this.footerRef,extraClassName:"fc-footer-toolbar",model:n.footer,titleId:""},s)))}))}componentDidMount(){let{props:e}=this;this.calendarInteractions=e.pluginHooks.calendarInteractions.map(t=>new t(e)),window.addEventListener("resize",this.handleWindowResize);let{propSetHandlers:t}=e.pluginHooks;for(let n in t)t[n](e[n],e)}componentDidUpdate(e){let{props:t}=this,{propSetHandlers:n}=t.pluginHooks;for(let r in n)t[r]!==e[r]&&n[r](t[r],t)}componentWillUnmount(){window.removeEventListener("resize",this.handleWindowResize),this.resizeRunner.clear();for(let e of this.calendarInteractions)e.destroy();this.props.emitter.trigger("_unmount")}buildAppendContent(){let{props:e}=this;return ln(dn,{},...e.pluginHooks.viewContainerAppends.map(t=>t(e)))}renderView(e){let{pluginHooks:t}=e,{viewSpec:n}=e,r={dateProfile:e.dateProfile,businessHours:e.businessHours,eventStore:e.renderableEventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,isHeightAuto:e.isHeightAuto,forPrint:e.forPrint},i=this.buildViewPropTransformers(t.viewPropsTransformers);for(let t of i)Object.assign(r,t.transform(r,e));return ln(n.component,Object.assign({},r))}}function Os(e,t,n,r,i,o){let s=n.build(i,void 0,!1),a=n.buildPrev(t,r,!1),l=n.buildNext(t,r,!1);return{title:o,activeButton:e.type,navUnit:e.singleUnit,isTodayEnabled:s.isValid&&!kt(t.currentRange,i),isPrevEnabled:a.isValid,isNextEnabled:l.isValid}}function Ms(e){return e.map(e=>new e)}function Is(e){let t=No(e.locale||"en",Io([]).map);return new ai(Object.assign(Object.assign({timeZone:Ne.timeZone,calendarSystem:"gregory"},e),{locale:t}))}return e.Calendar=class extends ko{constructor(e,t={}){super(),this.isRendering=!1,this.isRendered=!1,this.currentClassNames=[],this.customContentRenderId=0,this.handleAction=e=>{switch(e.type){case"SET_EVENT_DRAG":case"SET_EVENT_RESIZE":this.renderRunner.tryDrain()}},this.handleData=e=>{this.currentData=e,this.renderRunner.request(e.calendarOptions.rerenderDelay)},this.handleRenderRequest=()=>{if(this.isRendering){this.isRendered=!0;let{currentData:e}=this;br(()=>{In(ln(mi,{options:e.calendarOptions,theme:e.theme,emitter:e.emitter},(t,n,r,i)=>(this.setClassNames(t),this.setHeight(n),ln(Ci.Provider,{value:this.customContentRenderId},ln(xs,Object.assign({isHeightAuto:r,forPrint:i},e))))),this.el)})}else this.isRendered&&(this.isRendered=!1,In(null,this.el),this.setClassNames([]),this.setHeight(""))},function(e){e.isConnected&&e.getRootNode&&i(e.getRootNode())}(e),this.el=e,this.renderRunner=new Zi(this.handleRenderRequest),new ps({optionOverrides:t,calendarApi:this,onAction:this.handleAction,onData:this.handleData})}render(){let e=this.isRendering;e?this.customContentRenderId+=1:this.isRendering=!0,this.renderRunner.request(),e&&this.updateSize()}destroy(){this.isRendering&&(this.isRendering=!1,this.renderRunner.request())}updateSize(){br(()=>{super.updateSize()})}batchRendering(e){this.renderRunner.pause("batchRendering"),e(),this.renderRunner.resume("batchRendering")}pauseRendering(){this.renderRunner.pause("pauseRendering")}resumeRendering(){this.renderRunner.resume("pauseRendering",!0)}resetOptions(e,t){this.currentDataManager.resetOptions(e,t)}setClassNames(e){if(!$(e,this.currentClassNames)){let{classList:t}=this.el;for(let e of this.currentClassNames)t.remove(e);for(let n of e)t.add(n);this.currentClassNames=e}}setHeight(e){h(this.el,"height",e)}},e.Internal=Ro,e.JsonRequestError=Qi,e.Preact=_r,e.createPlugin=Ho,e.formatDate=function(e,t={}){let n=Is(t),r=Me(t),i=n.createMarkerMeta(e);return i?n.format(i.marker,r,{forcedTzo:i.forcedTzo}):""},e.formatRange=function(e,t,n){let r=Is("object"==typeof n&&n?n:{}),i=Me(n),o=r.createMarkerMeta(e),s=r.createMarkerMeta(t);return o&&s?r.formatRange(o.marker,s.marker,i,{forcedStartTzo:o.forcedTzo,forcedEndTzo:s.forcedTzo,isEndExclusive:n.isEndExclusive,defaultSeparator:Ne.defaultRangeSeparator}):""},e.globalLocales=xo,e.globalPlugins=us,e.sliceEvents=function(e,t){return zr(e.eventStore,e.eventUiBases,e.dateProfile.activeRange,t?e.nextDayThreshold:null).fg},e.version="6.1.17",Object.defineProperty(e,"__esModule",{value:!0}),e}({}); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales-all.global.js b/public/js/fullcalendar/packages/core/locales-all.global.js
new file mode 100644
index 0000000..fcdb033
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales-all.global.js
@@ -0,0 +1,1933 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var l0 = {
10 code: 'af',
11 week: {
12 dow: 1,
13 doy: 4, // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
14 },
15 buttonText: {
16 prev: 'Vorige',
17 next: 'Volgende',
18 today: 'Vandag',
19 year: 'Jaar',
20 month: 'Maand',
21 week: 'Week',
22 day: 'Dag',
23 list: 'Agenda',
24 },
25 allDayText: 'Heeldag',
26 moreLinkText: 'Addisionele',
27 noEventsText: 'Daar is geen gebeurtenisse nie',
28 };
29
30 var l1 = {
31 code: 'ar-dz',
32 week: {
33 dow: 0,
34 doy: 4, // The week that contains Jan 1st is the first week of the year.
35 },
36 direction: 'rtl',
37 buttonText: {
38 prev: 'السابق',
39 next: 'التالي',
40 today: 'اليوم',
41 year: 'سنة',
42 month: 'شهر',
43 week: 'أسبوع',
44 day: 'يوم',
45 list: 'أجندة',
46 },
47 weekText: 'أسبوع',
48 allDayText: 'اليوم كله',
49 moreLinkText: 'أخرى',
50 noEventsText: 'أي أحداث لعرض',
51 };
52
53 var l2 = {
54 code: 'ar-kw',
55 week: {
56 dow: 0,
57 doy: 12, // The week that contains Jan 1st is the first week of the year.
58 },
59 direction: 'rtl',
60 buttonText: {
61 prev: 'السابق',
62 next: 'التالي',
63 today: 'اليوم',
64 year: 'سنة',
65 month: 'شهر',
66 week: 'أسبوع',
67 day: 'يوم',
68 list: 'أجندة',
69 },
70 weekText: 'أسبوع',
71 allDayText: 'اليوم كله',
72 moreLinkText: 'أخرى',
73 noEventsText: 'أي أحداث لعرض',
74 };
75
76 var l3 = {
77 code: 'ar-ly',
78 week: {
79 dow: 6,
80 doy: 12, // The week that contains Jan 1st is the first week of the year.
81 },
82 direction: 'rtl',
83 buttonText: {
84 prev: 'السابق',
85 next: 'التالي',
86 today: 'اليوم',
87 year: 'سنة',
88 month: 'شهر',
89 week: 'أسبوع',
90 day: 'يوم',
91 list: 'أجندة',
92 },
93 weekText: 'أسبوع',
94 allDayText: 'اليوم كله',
95 moreLinkText: 'أخرى',
96 noEventsText: 'أي أحداث لعرض',
97 };
98
99 var l4 = {
100 code: 'ar-ma',
101 week: {
102 dow: 6,
103 doy: 12, // The week that contains Jan 1st is the first week of the year.
104 },
105 direction: 'rtl',
106 buttonText: {
107 prev: 'السابق',
108 next: 'التالي',
109 today: 'اليوم',
110 year: 'سنة',
111 month: 'شهر',
112 week: 'أسبوع',
113 day: 'يوم',
114 list: 'أجندة',
115 },
116 weekText: 'أسبوع',
117 allDayText: 'اليوم كله',
118 moreLinkText: 'أخرى',
119 noEventsText: 'أي أحداث لعرض',
120 };
121
122 var l5 = {
123 code: 'ar-sa',
124 week: {
125 dow: 0,
126 doy: 6, // The week that contains Jan 1st is the first week of the year.
127 },
128 direction: 'rtl',
129 buttonText: {
130 prev: 'السابق',
131 next: 'التالي',
132 today: 'اليوم',
133 year: 'سنة',
134 month: 'شهر',
135 week: 'أسبوع',
136 day: 'يوم',
137 list: 'أجندة',
138 },
139 weekText: 'أسبوع',
140 allDayText: 'اليوم كله',
141 moreLinkText: 'أخرى',
142 noEventsText: 'أي أحداث لعرض',
143 };
144
145 var l6 = {
146 code: 'ar-tn',
147 week: {
148 dow: 1,
149 doy: 4, // The week that contains Jan 4th is the first week of the year.
150 },
151 direction: 'rtl',
152 buttonText: {
153 prev: 'السابق',
154 next: 'التالي',
155 today: 'اليوم',
156 year: 'سنة',
157 month: 'شهر',
158 week: 'أسبوع',
159 day: 'يوم',
160 list: 'أجندة',
161 },
162 weekText: 'أسبوع',
163 allDayText: 'اليوم كله',
164 moreLinkText: 'أخرى',
165 noEventsText: 'أي أحداث لعرض',
166 };
167
168 var l7 = {
169 code: 'ar',
170 week: {
171 dow: 6,
172 doy: 12, // The week that contains Jan 1st is the first week of the year.
173 },
174 direction: 'rtl',
175 buttonText: {
176 prev: 'السابق',
177 next: 'التالي',
178 today: 'اليوم',
179 year: 'سنة',
180 month: 'شهر',
181 week: 'أسبوع',
182 day: 'يوم',
183 list: 'أجندة',
184 },
185 weekText: 'أسبوع',
186 allDayText: 'اليوم كله',
187 moreLinkText: 'أخرى',
188 noEventsText: 'أي أحداث لعرض',
189 };
190
191 var l8 = {
192 code: 'az',
193 week: {
194 dow: 1,
195 doy: 4, // The week that contains Jan 4th is the first week of the year.
196 },
197 buttonText: {
198 prev: 'Əvvəl',
199 next: 'Sonra',
200 today: 'Bu Gün',
201 year: 'Il',
202 month: 'Ay',
203 week: 'Həftə',
204 day: 'Gün',
205 list: 'Gündəm',
206 },
207 weekText: 'Həftə',
208 allDayText: 'Bütün Gün',
209 moreLinkText(n) {
210 return '+ daha çox ' + n;
211 },
212 noEventsText: 'Göstərmək üçün hadisə yoxdur',
213 };
214
215 var l9 = {
216 code: 'bg',
217 week: {
218 dow: 1,
219 doy: 4, // The week that contains Jan 4th is the first week of the year.
220 },
221 buttonText: {
222 prev: 'назад',
223 next: 'напред',
224 today: 'днес',
225 year: 'година',
226 month: 'Месец',
227 week: 'Седмица',
228 day: 'Ден',
229 list: 'График',
230 },
231 allDayText: 'Цял ден',
232 moreLinkText(n) {
233 return '+още ' + n;
234 },
235 noEventsText: 'Няма събития за показване',
236 };
237
238 var l10 = {
239 code: 'bn',
240 week: {
241 dow: 0,
242 doy: 6, // The week that contains Jan 1st is the first week of the year.
243 },
244 buttonText: {
245 prev: 'পেছনে',
246 next: 'সামনে',
247 today: 'আজ',
248 year: 'বছর',
249 month: 'মাস',
250 week: 'সপ্তাহ',
251 day: 'দিন',
252 list: 'তালিকা',
253 },
254 weekText: 'সপ্তাহ',
255 allDayText: 'সারাদিন',
256 moreLinkText(n) {
257 return '+অন্যান্য ' + n;
258 },
259 noEventsText: 'কোনো ইভেন্ট নেই',
260 };
261
262 var l11 = {
263 code: 'bs',
264 week: {
265 dow: 1,
266 doy: 7, // The week that contains Jan 1st is the first week of the year.
267 },
268 buttonText: {
269 prev: 'Prošli',
270 next: 'Sljedeći',
271 today: 'Danas',
272 year: 'Godina',
273 month: 'Mjesec',
274 week: 'Sedmica',
275 day: 'Dan',
276 list: 'Raspored',
277 },
278 weekText: 'Sed',
279 allDayText: 'Cijeli dan',
280 moreLinkText(n) {
281 return '+ još ' + n;
282 },
283 noEventsText: 'Nema događaja za prikazivanje',
284 };
285
286 var l12 = {
287 code: 'ca',
288 week: {
289 dow: 1,
290 doy: 4, // The week that contains Jan 4th is the first week of the year.
291 },
292 buttonText: {
293 prev: 'Anterior',
294 next: 'Següent',
295 today: 'Avui',
296 year: 'Any',
297 month: 'Mes',
298 week: 'Setmana',
299 day: 'Dia',
300 list: 'Agenda',
301 },
302 weekText: 'Set',
303 allDayText: 'Tot el dia',
304 moreLinkText: 'més',
305 noEventsText: 'No hi ha esdeveniments per mostrar',
306 };
307
308 var l13 = {
309 code: 'cs',
310 week: {
311 dow: 1,
312 doy: 4, // The week that contains Jan 4th is the first week of the year.
313 },
314 buttonText: {
315 prev: 'Dříve',
316 next: 'Později',
317 today: 'Nyní',
318 year: 'Rok',
319 month: 'Měsíc',
320 week: 'Týden',
321 day: 'Den',
322 list: 'Agenda',
323 },
324 weekText: 'Týd',
325 allDayText: 'Celý den',
326 moreLinkText(n) {
327 return '+další: ' + n;
328 },
329 noEventsText: 'Žádné akce k zobrazení',
330 };
331
332 var l14 = {
333 code: 'cy',
334 week: {
335 dow: 1,
336 doy: 4, // The week that contains Jan 4th is the first week of the year.
337 },
338 buttonText: {
339 prev: 'Blaenorol',
340 next: 'Nesaf',
341 today: 'Heddiw',
342 year: 'Blwyddyn',
343 month: 'Mis',
344 week: 'Wythnos',
345 day: 'Dydd',
346 list: 'Rhestr',
347 },
348 weekText: 'Wythnos',
349 allDayText: 'Trwy\'r dydd',
350 moreLinkText: 'Mwy',
351 noEventsText: 'Dim digwyddiadau',
352 };
353
354 var l15 = {
355 code: 'da',
356 week: {
357 dow: 1,
358 doy: 4, // The week that contains Jan 4th is the first week of the year.
359 },
360 buttonText: {
361 prev: 'Forrige',
362 next: 'Næste',
363 today: 'I dag',
364 year: 'År',
365 month: 'Måned',
366 week: 'Uge',
367 day: 'Dag',
368 list: 'Agenda',
369 },
370 weekText: 'Uge',
371 allDayText: 'Hele dagen',
372 moreLinkText: 'flere',
373 noEventsText: 'Ingen arrangementer at vise',
374 };
375
376 function affix$1(buttonText) {
377 return (buttonText === 'Tag' || buttonText === 'Monat') ? 'r' :
378 buttonText === 'Jahr' ? 's' : '';
379 }
380 var l16 = {
381 code: 'de-at',
382 week: {
383 dow: 1,
384 doy: 4, // The week that contains Jan 4th is the first week of the year.
385 },
386 buttonText: {
387 prev: 'Zurück',
388 next: 'Vor',
389 today: 'Heute',
390 year: 'Jahr',
391 month: 'Monat',
392 week: 'Woche',
393 day: 'Tag',
394 list: 'Terminübersicht',
395 },
396 weekText: 'KW',
397 weekTextLong: 'Woche',
398 allDayText: 'Ganztägig',
399 moreLinkText(n) {
400 return '+ weitere ' + n;
401 },
402 noEventsText: 'Keine Ereignisse anzuzeigen',
403 buttonHints: {
404 prev(buttonText) {
405 return `Vorherige${affix$1(buttonText)} ${buttonText}`;
406 },
407 next(buttonText) {
408 return `Nächste${affix$1(buttonText)} ${buttonText}`;
409 },
410 today(buttonText) {
411 // → Heute, Diese Woche, Dieser Monat, Dieses Jahr
412 if (buttonText === 'Tag') {
413 return 'Heute';
414 }
415 return `Diese${affix$1(buttonText)} ${buttonText}`;
416 },
417 },
418 viewHint(buttonText) {
419 // → Tagesansicht, Wochenansicht, Monatsansicht, Jahresansicht
420 const glue = buttonText === 'Woche' ? 'n' : buttonText === 'Monat' ? 's' : 'es';
421 return buttonText + glue + 'ansicht';
422 },
423 navLinkHint: 'Gehe zu $0',
424 moreLinkHint(eventCnt) {
425 return 'Zeige ' + (eventCnt === 1 ?
426 'ein weiteres Ereignis' :
427 eventCnt + ' weitere Ereignisse');
428 },
429 closeHint: 'Schließen',
430 timeHint: 'Uhrzeit',
431 eventHint: 'Ereignis',
432 };
433
434 function affix(buttonText) {
435 return (buttonText === 'Tag' || buttonText === 'Monat') ? 'r' :
436 buttonText === 'Jahr' ? 's' : '';
437 }
438 var l17 = {
439 code: 'de',
440 week: {
441 dow: 1,
442 doy: 4, // The week that contains Jan 4th is the first week of the year.
443 },
444 buttonText: {
445 prev: 'Zurück',
446 next: 'Vor',
447 today: 'Heute',
448 year: 'Jahr',
449 month: 'Monat',
450 week: 'Woche',
451 day: 'Tag',
452 list: 'Terminübersicht',
453 },
454 weekText: 'KW',
455 weekTextLong: 'Woche',
456 allDayText: 'Ganztägig',
457 moreLinkText(n) {
458 return '+ weitere ' + n;
459 },
460 noEventsText: 'Keine Ereignisse anzuzeigen',
461 buttonHints: {
462 prev(buttonText) {
463 return `Vorherige${affix(buttonText)} ${buttonText}`;
464 },
465 next(buttonText) {
466 return `Nächste${affix(buttonText)} ${buttonText}`;
467 },
468 today(buttonText) {
469 // → Heute, Diese Woche, Dieser Monat, Dieses Jahr
470 if (buttonText === 'Tag') {
471 return 'Heute';
472 }
473 return `Diese${affix(buttonText)} ${buttonText}`;
474 },
475 },
476 viewHint(buttonText) {
477 // → Tagesansicht, Wochenansicht, Monatsansicht, Jahresansicht
478 const glue = buttonText === 'Woche' ? 'n' : buttonText === 'Monat' ? 's' : 'es';
479 return buttonText + glue + 'ansicht';
480 },
481 navLinkHint: 'Gehe zu $0',
482 moreLinkHint(eventCnt) {
483 return 'Zeige ' + (eventCnt === 1 ?
484 'ein weiteres Ereignis' :
485 eventCnt + ' weitere Ereignisse');
486 },
487 closeHint: 'Schließen',
488 timeHint: 'Uhrzeit',
489 eventHint: 'Ereignis',
490 };
491
492 var l18 = {
493 code: 'el',
494 week: {
495 dow: 1,
496 doy: 4, // The week that contains Jan 4st is the first week of the year.
497 },
498 buttonText: {
499 prev: 'Προηγούμενος',
500 next: 'Επόμενος',
501 today: 'Σήμερα',
502 year: 'Ετος',
503 month: 'Μήνας',
504 week: 'Εβδομάδα',
505 day: 'Ημέρα',
506 list: 'Ατζέντα',
507 },
508 weekText: 'Εβδ',
509 allDayText: 'Ολοήμερο',
510 moreLinkText: 'περισσότερα',
511 noEventsText: 'Δεν υπάρχουν γεγονότα προς εμφάνιση',
512 };
513
514 var l19 = {
515 code: 'en-au',
516 week: {
517 dow: 1,
518 doy: 4, // The week that contains Jan 4th is the first week of the year.
519 },
520 buttonHints: {
521 prev: 'Previous $0',
522 next: 'Next $0',
523 today: 'This $0',
524 },
525 viewHint: '$0 view',
526 navLinkHint: 'Go to $0',
527 moreLinkHint(eventCnt) {
528 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
529 },
530 };
531
532 var l20 = {
533 code: 'en-gb',
534 week: {
535 dow: 1,
536 doy: 4, // The week that contains Jan 4th is the first week of the year.
537 },
538 buttonHints: {
539 prev: 'Previous $0',
540 next: 'Next $0',
541 today: 'This $0',
542 },
543 viewHint: '$0 view',
544 navLinkHint: 'Go to $0',
545 moreLinkHint(eventCnt) {
546 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
547 },
548 };
549
550 var l21 = {
551 code: 'en-nz',
552 week: {
553 dow: 1,
554 doy: 4, // The week that contains Jan 4th is the first week of the year.
555 },
556 buttonHints: {
557 prev: 'Previous $0',
558 next: 'Next $0',
559 today: 'This $0',
560 },
561 viewHint: '$0 view',
562 navLinkHint: 'Go to $0',
563 moreLinkHint(eventCnt) {
564 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
565 },
566 };
567
568 var l22 = {
569 code: 'eo',
570 week: {
571 dow: 1,
572 doy: 4, // The week that contains Jan 4th is the first week of the year.
573 },
574 buttonText: {
575 prev: 'Antaŭa',
576 next: 'Sekva',
577 today: 'Hodiaŭ',
578 year: 'Jaro',
579 month: 'Monato',
580 week: 'Semajno',
581 day: 'Tago',
582 list: 'Tagordo',
583 },
584 weekText: 'Sm',
585 allDayText: 'Tuta tago',
586 moreLinkText: 'pli',
587 noEventsText: 'Neniuj eventoj por montri',
588 };
589
590 var l23 = {
591 code: 'es',
592 week: {
593 dow: 0,
594 doy: 6, // The week that contains Jan 1st is the first week of the year.
595 },
596 buttonText: {
597 prev: 'Ant',
598 next: 'Sig',
599 today: 'Hoy',
600 year: 'Año',
601 month: 'Mes',
602 week: 'Semana',
603 day: 'Día',
604 list: 'Agenda',
605 },
606 weekText: 'Sm',
607 allDayText: 'Todo el día',
608 moreLinkText: 'más',
609 noEventsText: 'No hay eventos para mostrar',
610 };
611
612 var l24 = {
613 code: 'es',
614 week: {
615 dow: 1,
616 doy: 4, // The week that contains Jan 4th is the first week of the year.
617 },
618 buttonText: {
619 prev: 'Ant',
620 next: 'Sig',
621 today: 'Hoy',
622 year: 'Año',
623 month: 'Mes',
624 week: 'Semana',
625 day: 'Día',
626 list: 'Agenda',
627 },
628 buttonHints: {
629 prev: '$0 antes',
630 next: '$0 siguiente',
631 today(buttonText) {
632 return (buttonText === 'Día') ? 'Hoy' :
633 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
634 },
635 },
636 viewHint(buttonText) {
637 return 'Vista ' + (buttonText === 'Semana' ? 'de la' : 'del') + ' ' + buttonText.toLocaleLowerCase();
638 },
639 weekText: 'Sm',
640 weekTextLong: 'Semana',
641 allDayText: 'Todo el día',
642 moreLinkText: 'más',
643 moreLinkHint(eventCnt) {
644 return `Mostrar ${eventCnt} eventos más`;
645 },
646 noEventsText: 'No hay eventos para mostrar',
647 navLinkHint: 'Ir al $0',
648 closeHint: 'Cerrar',
649 timeHint: 'La hora',
650 eventHint: 'Evento',
651 };
652
653 var l25 = {
654 code: 'et',
655 week: {
656 dow: 1,
657 doy: 4, // The week that contains Jan 4th is the first week of the year.
658 },
659 buttonText: {
660 prev: 'Eelnev',
661 next: 'Järgnev',
662 today: 'Täna',
663 year: 'Aasta',
664 month: 'Kuu',
665 week: 'Nädal',
666 day: 'Päev',
667 list: 'Päevakord',
668 },
669 weekText: 'näd',
670 allDayText: 'Kogu päev',
671 moreLinkText(n) {
672 return '+ veel ' + n;
673 },
674 noEventsText: 'Kuvamiseks puuduvad sündmused',
675 };
676
677 var l26 = {
678 code: 'eu',
679 week: {
680 dow: 1,
681 doy: 7, // The week that contains Jan 1st is the first week of the year.
682 },
683 buttonText: {
684 prev: 'Aur',
685 next: 'Hur',
686 today: 'Gaur',
687 year: 'Urtea',
688 month: 'Hilabetea',
689 week: 'Astea',
690 day: 'Eguna',
691 list: 'Agenda',
692 },
693 weekText: 'As',
694 allDayText: 'Egun osoa',
695 moreLinkText: 'gehiago',
696 noEventsText: 'Ez dago ekitaldirik erakusteko',
697 };
698
699 var l27 = {
700 code: 'fa',
701 week: {
702 dow: 6,
703 doy: 12, // The week that contains Jan 1st is the first week of the year.
704 },
705 direction: 'rtl',
706 buttonText: {
707 prev: 'قبلی',
708 next: 'بعدی',
709 today: 'امروز',
710 year: 'سال',
711 month: 'ماه',
712 week: 'هفته',
713 day: 'روز',
714 list: 'برنامه',
715 },
716 weekText: 'هف',
717 allDayText: 'تمام روز',
718 moreLinkText(n) {
719 return 'بیش از ' + n;
720 },
721 noEventsText: 'هیچ رویدادی به نمایش',
722 };
723
724 var l28 = {
725 code: 'fi',
726 week: {
727 dow: 1,
728 doy: 4, // The week that contains Jan 4th is the first week of the year.
729 },
730 buttonText: {
731 prev: 'Edellinen',
732 next: 'Seuraava',
733 today: 'Tänään',
734 year: 'Vuosi',
735 month: 'Kuukausi',
736 week: 'Viikko',
737 day: 'Päivä',
738 list: 'Tapahtumat',
739 },
740 weekText: 'Vk',
741 allDayText: 'Koko päivä',
742 moreLinkText: 'lisää',
743 noEventsText: 'Ei näytettäviä tapahtumia',
744 };
745
746 var l29 = {
747 code: 'fr',
748 buttonText: {
749 prev: 'Précédent',
750 next: 'Suivant',
751 today: 'Aujourd\'hui',
752 year: 'Année',
753 month: 'Mois',
754 week: 'Semaine',
755 day: 'Jour',
756 list: 'Mon planning',
757 },
758 weekText: 'Sem.',
759 allDayText: 'Toute la journée',
760 moreLinkText: 'en plus',
761 noEventsText: 'Aucun évènement à afficher',
762 };
763
764 var l30 = {
765 code: 'fr-ch',
766 week: {
767 dow: 1,
768 doy: 4, // The week that contains Jan 4th is the first week of the year.
769 },
770 buttonText: {
771 prev: 'Précédent',
772 next: 'Suivant',
773 today: 'Courant',
774 year: 'Année',
775 month: 'Mois',
776 week: 'Semaine',
777 day: 'Jour',
778 list: 'Mon planning',
779 },
780 weekText: 'Sm',
781 allDayText: 'Toute la journée',
782 moreLinkText: 'en plus',
783 noEventsText: 'Aucun évènement à afficher',
784 };
785
786 var l31 = {
787 code: 'fr',
788 week: {
789 dow: 1,
790 doy: 4, // The week that contains Jan 4th is the first week of the year.
791 },
792 buttonText: {
793 prev: 'Précédent',
794 next: 'Suivant',
795 today: 'Aujourd\'hui',
796 year: 'Année',
797 month: 'Mois',
798 week: 'Semaine',
799 day: 'Jour',
800 list: 'Planning',
801 },
802 weekText: 'Sem.',
803 weekTextLong: 'Semaine',
804 allDayText: 'Toute la journée',
805 moreLinkText: 'en plus',
806 noEventsText: 'Aucun évènement à afficher',
807 };
808
809 var l32 = {
810 code: 'gl',
811 week: {
812 dow: 1,
813 doy: 4, // The week that contains Jan 4th is the first week of the year.
814 },
815 buttonText: {
816 prev: 'Ant',
817 next: 'Seg',
818 today: 'Hoxe',
819 year: 'Ano',
820 month: 'Mes',
821 week: 'Semana',
822 day: 'Día',
823 list: 'Axenda',
824 },
825 buttonHints: {
826 prev: '$0 antes',
827 next: '$0 seguinte',
828 today(buttonText) {
829 return (buttonText === 'Día') ? 'Hoxe' :
830 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
831 },
832 },
833 viewHint(buttonText) {
834 return 'Vista ' + (buttonText === 'Semana' ? 'da' : 'do') + ' ' + buttonText.toLocaleLowerCase();
835 },
836 weekText: 'Sm',
837 weekTextLong: 'Semana',
838 allDayText: 'Todo o día',
839 moreLinkText: 'máis',
840 moreLinkHint(eventCnt) {
841 return `Amosar ${eventCnt} eventos máis`;
842 },
843 noEventsText: 'Non hai eventos para amosar',
844 navLinkHint: 'Ir ao $0',
845 closeHint: 'Pechar',
846 timeHint: 'A hora',
847 eventHint: 'Evento',
848 };
849
850 var l33 = {
851 code: 'he',
852 direction: 'rtl',
853 buttonText: {
854 prev: 'הקודם',
855 next: 'הבא',
856 today: 'היום',
857 year: 'שנה',
858 month: 'חודש',
859 week: 'שבוע',
860 day: 'יום',
861 list: 'סדר יום',
862 },
863 allDayText: 'כל היום',
864 moreLinkText: 'נוספים',
865 noEventsText: 'אין אירועים להצגה',
866 weekText: 'שבוע',
867 };
868
869 var l34 = {
870 code: 'hi',
871 week: {
872 dow: 0,
873 doy: 6, // The week that contains Jan 1st is the first week of the year.
874 },
875 buttonText: {
876 prev: 'पिछला',
877 next: 'अगला',
878 today: 'आज',
879 year: 'वर्ष',
880 month: 'महीना',
881 week: 'सप्ताह',
882 day: 'दिन',
883 list: 'कार्यसूची',
884 },
885 weekText: 'हफ्ता',
886 allDayText: 'सभी दिन',
887 moreLinkText(n) {
888 return '+अधिक ' + n;
889 },
890 noEventsText: 'कोई घटनाओं को प्रदर्शित करने के लिए',
891 };
892
893 var l35 = {
894 code: 'hr',
895 week: {
896 dow: 1,
897 doy: 7, // The week that contains Jan 1st is the first week of the year.
898 },
899 buttonText: {
900 prev: 'Prijašnji',
901 next: 'Sljedeći',
902 today: 'Danas',
903 year: 'Godina',
904 month: 'Mjesec',
905 week: 'Tjedan',
906 day: 'Dan',
907 list: 'Raspored',
908 },
909 weekText: 'Tje',
910 allDayText: 'Cijeli dan',
911 moreLinkText(n) {
912 return '+ još ' + n;
913 },
914 noEventsText: 'Nema događaja za prikaz',
915 };
916
917 var l36 = {
918 code: 'hu',
919 week: {
920 dow: 1,
921 doy: 4, // The week that contains Jan 4th is the first week of the year.
922 },
923 buttonText: {
924 prev: 'vissza',
925 next: 'előre',
926 today: 'ma',
927 year: 'Év',
928 month: 'Hónap',
929 week: 'Hét',
930 day: 'Nap',
931 list: 'Lista',
932 },
933 weekText: 'Hét',
934 allDayText: 'Egész nap',
935 moreLinkText: 'további',
936 noEventsText: 'Nincs megjeleníthető esemény',
937 };
938
939 var l37 = {
940 code: 'hy-am',
941 week: {
942 dow: 1,
943 doy: 4, // The week that contains Jan 4th is the first week of the year.
944 },
945 buttonText: {
946 prev: 'Նախորդ',
947 next: 'Հաջորդ',
948 today: 'Այսօր',
949 year: 'Տարի',
950 month: 'Ամիս',
951 week: 'Շաբաթ',
952 day: 'Օր',
953 list: 'Օրվա ցուցակ',
954 },
955 weekText: 'Շաբ',
956 allDayText: 'Ամբողջ օր',
957 moreLinkText(n) {
958 return '+ ևս ' + n;
959 },
960 noEventsText: 'Բացակայում է իրադարձությունը ցուցադրելու',
961 };
962
963 var l38 = {
964 code: 'id',
965 week: {
966 dow: 1,
967 doy: 7, // The week that contains Jan 1st is the first week of the year.
968 },
969 buttonText: {
970 prev: 'mundur',
971 next: 'maju',
972 today: 'hari ini',
973 year: 'Tahun',
974 month: 'Bulan',
975 week: 'Minggu',
976 day: 'Hari',
977 list: 'Agenda',
978 },
979 weekText: 'Mg',
980 allDayText: 'Sehari penuh',
981 moreLinkText: 'lebih',
982 noEventsText: 'Tidak ada acara untuk ditampilkan',
983 };
984
985 var l39 = {
986 code: 'is',
987 week: {
988 dow: 1,
989 doy: 4, // The week that contains Jan 4th is the first week of the year.
990 },
991 buttonText: {
992 prev: 'Fyrri',
993 next: 'Næsti',
994 today: 'Í dag',
995 year: 'Ár',
996 month: 'Mánuður',
997 week: 'Vika',
998 day: 'Dagur',
999 list: 'Dagskrá',
1000 },
1001 weekText: 'Vika',
1002 allDayText: 'Allan daginn',
1003 moreLinkText: 'meira',
1004 noEventsText: 'Engir viðburðir til að sýna',
1005 };
1006
1007 var l40 = {
1008 code: 'it',
1009 week: {
1010 dow: 1,
1011 doy: 4, // The week that contains Jan 4th is the first week of the year.
1012 },
1013 buttonText: {
1014 prev: 'Prec',
1015 next: 'Succ',
1016 today: 'Oggi',
1017 year: 'Anno',
1018 month: 'Mese',
1019 week: 'Settimana',
1020 day: 'Giorno',
1021 list: 'Agenda',
1022 },
1023 weekText: 'Sm',
1024 allDayText: 'Tutto il giorno',
1025 moreLinkText(n) {
1026 return '+altri ' + n;
1027 },
1028 noEventsText: 'Non ci sono eventi da visualizzare',
1029 };
1030
1031 var l41 = {
1032 code: 'ja',
1033 buttonText: {
1034 prev: '前',
1035 next: '次',
1036 today: '今日',
1037 year: '年',
1038 month: '月',
1039 week: '週',
1040 day: '日',
1041 list: '予定リスト',
1042 },
1043 weekText: '週',
1044 allDayText: '終日',
1045 moreLinkText(n) {
1046 return '他 ' + n + ' 件';
1047 },
1048 noEventsText: '表示する予定はありません',
1049 };
1050
1051 var l42 = {
1052 code: 'ka',
1053 week: {
1054 dow: 1,
1055 doy: 7,
1056 },
1057 buttonText: {
1058 prev: 'წინა',
1059 next: 'შემდეგი',
1060 today: 'დღეს',
1061 year: 'წელიწადი',
1062 month: 'თვე',
1063 week: 'კვირა',
1064 day: 'დღე',
1065 list: 'დღის წესრიგი',
1066 },
1067 weekText: 'კვ',
1068 allDayText: 'მთელი დღე',
1069 moreLinkText(n) {
1070 return '+ კიდევ ' + n;
1071 },
1072 noEventsText: 'ღონისძიებები არ არის',
1073 };
1074
1075 var l43 = {
1076 code: 'kk',
1077 week: {
1078 dow: 1,
1079 doy: 7, // The week that contains Jan 1st is the first week of the year.
1080 },
1081 buttonText: {
1082 prev: 'Алдыңғы',
1083 next: 'Келесі',
1084 today: 'Бүгін',
1085 year: 'Жыл',
1086 month: 'Ай',
1087 week: 'Апта',
1088 day: 'Күн',
1089 list: 'Күн тәртібі',
1090 },
1091 weekText: 'Не',
1092 allDayText: 'Күні бойы',
1093 moreLinkText(n) {
1094 return '+ тағы ' + n;
1095 },
1096 noEventsText: 'Көрсету үшін оқиғалар жоқ',
1097 };
1098
1099 var l44 = {
1100 code: 'km',
1101 week: {
1102 dow: 1,
1103 doy: 4, // The week that contains Jan 4th is the first week of the year.
1104 },
1105 buttonText: {
1106 prev: 'មុន',
1107 next: 'បន្ទាប់',
1108 today: 'ថ្ងៃនេះ',
1109 year: 'ឆ្នាំ',
1110 month: 'ខែ',
1111 week: 'សប្តាហ៍',
1112 day: 'ថ្ងៃ',
1113 list: 'បញ្ជី',
1114 },
1115 weekText: 'សប្តាហ៍',
1116 allDayText: 'ពេញមួយថ្ងៃ',
1117 moreLinkText: 'ច្រើនទៀត',
1118 noEventsText: 'គ្មានព្រឹត្តិការណ៍ត្រូវបង្ហាញ',
1119 };
1120
1121 var l45 = {
1122 code: 'ko',
1123 buttonText: {
1124 prev: '이전달',
1125 next: '다음달',
1126 today: '오늘',
1127 year: '년도',
1128 month: '월',
1129 week: '주',
1130 day: '일',
1131 list: '일정목록',
1132 },
1133 weekText: '주',
1134 allDayText: '종일',
1135 moreLinkText: '개',
1136 noEventsText: '일정이 없습니다',
1137 };
1138
1139 var l46 = {
1140 code: 'ku',
1141 week: {
1142 dow: 6,
1143 doy: 12, // The week that contains Jan 1st is the first week of the year.
1144 },
1145 direction: 'rtl',
1146 buttonText: {
1147 prev: 'پێشتر',
1148 next: 'دواتر',
1149 today: 'ئەمڕو',
1150 year: 'ساڵ',
1151 month: 'مانگ',
1152 week: 'هەفتە',
1153 day: 'ڕۆژ',
1154 list: 'بەرنامە',
1155 },
1156 weekText: 'هەفتە',
1157 allDayText: 'هەموو ڕۆژەکە',
1158 moreLinkText: 'زیاتر',
1159 noEventsText: 'هیچ ڕووداوێك نیە',
1160 };
1161
1162 var l47 = {
1163 code: 'lb',
1164 week: {
1165 dow: 1,
1166 doy: 4, // The week that contains Jan 4th is the first week of the year.
1167 },
1168 buttonText: {
1169 prev: 'Zréck',
1170 next: 'Weider',
1171 today: 'Haut',
1172 year: 'Joer',
1173 month: 'Mount',
1174 week: 'Woch',
1175 day: 'Dag',
1176 list: 'Terminiwwersiicht',
1177 },
1178 weekText: 'W',
1179 allDayText: 'Ganzen Dag',
1180 moreLinkText: 'méi',
1181 noEventsText: 'Nee Evenementer ze affichéieren',
1182 };
1183
1184 var l48 = {
1185 code: 'lt',
1186 week: {
1187 dow: 1,
1188 doy: 4, // The week that contains Jan 4th is the first week of the year.
1189 },
1190 buttonText: {
1191 prev: 'Atgal',
1192 next: 'Pirmyn',
1193 today: 'Šiandien',
1194 year: 'Metai',
1195 month: 'Mėnuo',
1196 week: 'Savaitė',
1197 day: 'Diena',
1198 list: 'Darbotvarkė',
1199 },
1200 weekText: 'SAV',
1201 allDayText: 'Visą dieną',
1202 moreLinkText: 'daugiau',
1203 noEventsText: 'Nėra įvykių rodyti',
1204 };
1205
1206 var l49 = {
1207 code: 'lv',
1208 week: {
1209 dow: 1,
1210 doy: 4, // The week that contains Jan 4th is the first week of the year.
1211 },
1212 buttonText: {
1213 prev: 'Iepr.',
1214 next: 'Nāk.',
1215 today: 'Šodien',
1216 year: 'Gads',
1217 month: 'Mēnesis',
1218 week: 'Nedēļa',
1219 day: 'Diena',
1220 list: 'Dienas kārtība',
1221 },
1222 weekText: 'Ned.',
1223 allDayText: 'Visu dienu',
1224 moreLinkText(n) {
1225 return '+vēl ' + n;
1226 },
1227 noEventsText: 'Nav notikumu',
1228 };
1229
1230 var l50 = {
1231 code: 'mk',
1232 buttonText: {
1233 prev: 'претходно',
1234 next: 'следно',
1235 today: 'Денес',
1236 year: 'година',
1237 month: 'Месец',
1238 week: 'Недела',
1239 day: 'Ден',
1240 list: 'График',
1241 },
1242 weekText: 'Сед',
1243 allDayText: 'Цел ден',
1244 moreLinkText(n) {
1245 return '+повеќе ' + n;
1246 },
1247 noEventsText: 'Нема настани за прикажување',
1248 };
1249
1250 var l51 = {
1251 code: 'ms',
1252 week: {
1253 dow: 1,
1254 doy: 7, // The week that contains Jan 1st is the first week of the year.
1255 },
1256 buttonText: {
1257 prev: 'Sebelum',
1258 next: 'Selepas',
1259 today: 'hari ini',
1260 year: 'Tahun',
1261 month: 'Bulan',
1262 week: 'Minggu',
1263 day: 'Hari',
1264 list: 'Agenda',
1265 },
1266 weekText: 'Mg',
1267 allDayText: 'Sepanjang hari',
1268 moreLinkText(n) {
1269 return 'masih ada ' + n + ' acara';
1270 },
1271 noEventsText: 'Tiada peristiwa untuk dipaparkan',
1272 };
1273
1274 var l52 = {
1275 code: 'nb',
1276 week: {
1277 dow: 1,
1278 doy: 4, // The week that contains Jan 4th is the first week of the year.
1279 },
1280 buttonText: {
1281 prev: 'Forrige',
1282 next: 'Neste',
1283 today: 'I dag',
1284 year: 'År',
1285 month: 'Måned',
1286 week: 'Uke',
1287 day: 'Dag',
1288 list: 'Agenda',
1289 },
1290 weekText: 'Uke',
1291 weekTextLong: 'Uke',
1292 allDayText: 'Hele dagen',
1293 moreLinkText: 'til',
1294 noEventsText: 'Ingen hendelser å vise',
1295 buttonHints: {
1296 prev: 'Forrige $0',
1297 next: 'Neste $0',
1298 today: 'Nåværende $0',
1299 },
1300 viewHint: '$0 visning',
1301 navLinkHint: 'Gå til $0',
1302 moreLinkHint(eventCnt) {
1303 return `Vis ${eventCnt} flere hendelse${eventCnt === 1 ? '' : 'r'}`;
1304 },
1305 };
1306
1307 var l53 = {
1308 code: 'ne',
1309 week: {
1310 dow: 7,
1311 doy: 1, // The week that contains Jan 1st is the first week of the year.
1312 },
1313 buttonText: {
1314 prev: 'अघिल्लो',
1315 next: 'अर्को',
1316 today: 'आज',
1317 year: 'वर्ष',
1318 month: 'महिना',
1319 week: 'हप्ता',
1320 day: 'दिन',
1321 list: 'सूची',
1322 },
1323 weekText: 'हप्ता',
1324 allDayText: 'दिनभरि',
1325 moreLinkText: 'थप लिंक',
1326 noEventsText: 'देखाउनको लागि कुनै घटनाहरू छैनन्',
1327 };
1328
1329 var l54 = {
1330 code: 'nl',
1331 week: {
1332 dow: 1,
1333 doy: 4, // The week that contains Jan 4th is the first week of the year.
1334 },
1335 buttonText: {
1336 prev: 'Vorige',
1337 next: 'Volgende',
1338 today: 'Vandaag',
1339 year: 'Jaar',
1340 month: 'Maand',
1341 week: 'Week',
1342 day: 'Dag',
1343 list: 'Lijst',
1344 },
1345 allDayText: 'Hele dag',
1346 moreLinkText: 'extra',
1347 noEventsText: 'Geen evenementen om te laten zien',
1348 };
1349
1350 var l55 = {
1351 code: 'nn',
1352 week: {
1353 dow: 1,
1354 doy: 4, // The week that contains Jan 4th is the first week of the year.
1355 },
1356 buttonText: {
1357 prev: 'Førre',
1358 next: 'Neste',
1359 today: 'I dag',
1360 year: 'År',
1361 month: 'Månad',
1362 week: 'Veke',
1363 day: 'Dag',
1364 list: 'Agenda',
1365 },
1366 weekText: 'Veke',
1367 allDayText: 'Heile dagen',
1368 moreLinkText: 'til',
1369 noEventsText: 'Ingen hendelser å vise',
1370 };
1371
1372 var l56 = {
1373 code: 'pl',
1374 week: {
1375 dow: 1,
1376 doy: 4, // The week that contains Jan 4th is the first week of the year.
1377 },
1378 buttonText: {
1379 prev: 'Poprzedni',
1380 next: 'Następny',
1381 today: 'Dziś',
1382 year: 'Rok',
1383 month: 'Miesiąc',
1384 week: 'Tydzień',
1385 day: 'Dzień',
1386 list: 'Plan dnia',
1387 },
1388 weekText: 'Tydz',
1389 allDayText: 'Cały dzień',
1390 moreLinkText: 'więcej',
1391 noEventsText: 'Brak wydarzeń do wyświetlenia',
1392 };
1393
1394 var l57 = {
1395 code: 'pt-br',
1396 buttonText: {
1397 prev: 'Anterior',
1398 next: 'Próximo',
1399 prevYear: 'Ano anterior',
1400 nextYear: 'Próximo ano',
1401 year: 'Ano',
1402 today: 'Hoje',
1403 month: 'Mês',
1404 week: 'Semana',
1405 day: 'Dia',
1406 list: 'Lista',
1407 },
1408 buttonHints: {
1409 prev: '$0 Anterior',
1410 next: 'Próximo $0',
1411 today(buttonText) {
1412 return (buttonText === 'Dia') ? 'Hoje' :
1413 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
1414 },
1415 },
1416 viewHint(buttonText) {
1417 return 'Visualizar ' + (buttonText === 'Semana' ? 'a' : 'o') + ' ' + buttonText.toLocaleLowerCase();
1418 },
1419 weekText: 'Sm',
1420 weekTextLong: 'Semana',
1421 allDayText: 'dia inteiro',
1422 moreLinkText(n) {
1423 return 'mais +' + n;
1424 },
1425 moreLinkHint(eventCnt) {
1426 return `Mostrar mais ${eventCnt} eventos`;
1427 },
1428 noEventsText: 'Não há eventos para mostrar',
1429 navLinkHint: 'Ir para $0',
1430 closeHint: 'Fechar',
1431 timeHint: 'A hora',
1432 eventHint: 'Evento',
1433 };
1434
1435 var l58 = {
1436 code: 'pt',
1437 week: {
1438 dow: 1,
1439 doy: 4, // The week that contains Jan 4th is the first week of the year.
1440 },
1441 buttonText: {
1442 prev: 'Anterior',
1443 next: 'Seguinte',
1444 today: 'Hoje',
1445 year: 'Ano',
1446 month: 'Mês',
1447 week: 'Semana',
1448 day: 'Dia',
1449 list: 'Agenda',
1450 },
1451 weekText: 'Sem',
1452 allDayText: 'Todo o dia',
1453 moreLinkText: 'mais',
1454 noEventsText: 'Não há eventos para mostrar',
1455 };
1456
1457 var l59 = {
1458 code: 'ro',
1459 week: {
1460 dow: 1,
1461 doy: 7, // The week that contains Jan 1st is the first week of the year.
1462 },
1463 buttonText: {
1464 prev: 'precedentă',
1465 next: 'următoare',
1466 today: 'Azi',
1467 year: 'An',
1468 month: 'Lună',
1469 week: 'Săptămână',
1470 day: 'Zi',
1471 list: 'Agendă',
1472 },
1473 weekText: 'Săpt',
1474 allDayText: 'Toată ziua',
1475 moreLinkText(n) {
1476 return '+alte ' + n;
1477 },
1478 noEventsText: 'Nu există evenimente de afișat',
1479 };
1480
1481 var l60 = {
1482 code: 'ru',
1483 week: {
1484 dow: 1,
1485 doy: 4, // The week that contains Jan 4th is the first week of the year.
1486 },
1487 buttonText: {
1488 prev: 'Пред',
1489 next: 'След',
1490 today: 'Сегодня',
1491 year: 'Год',
1492 month: 'Месяц',
1493 week: 'Неделя',
1494 day: 'День',
1495 list: 'Повестка дня',
1496 },
1497 weekText: 'Нед',
1498 allDayText: 'Весь день',
1499 moreLinkText(n) {
1500 return '+ ещё ' + n;
1501 },
1502 noEventsText: 'Нет событий для отображения',
1503 };
1504
1505 var l61 = {
1506 code: 'si-lk',
1507 week: {
1508 dow: 1,
1509 doy: 4, // The week that contains Jan 4th is the first week of the year.
1510 },
1511 buttonText: {
1512 prev: 'පෙර',
1513 next: 'පසු',
1514 today: 'අද',
1515 year: 'අවුරුදු',
1516 month: 'මාසය',
1517 week: 'සතිය',
1518 day: 'දවස',
1519 list: 'ලැයිස්තුව',
1520 },
1521 weekText: 'සති',
1522 allDayText: 'සියලු',
1523 moreLinkText: 'තවත්',
1524 noEventsText: 'මුකුත් නැත',
1525 };
1526
1527 var l62 = {
1528 code: 'sk',
1529 week: {
1530 dow: 1,
1531 doy: 4, // The week that contains Jan 4th is the first week of the year.
1532 },
1533 buttonText: {
1534 prev: 'Predchádzajúci',
1535 next: 'Nasledujúci',
1536 today: 'Dnes',
1537 year: 'Rok',
1538 month: 'Mesiac',
1539 week: 'Týždeň',
1540 day: 'Deň',
1541 list: 'Rozvrh',
1542 },
1543 weekText: 'Ty',
1544 allDayText: 'Celý deň',
1545 moreLinkText(n) {
1546 return '+ďalšie: ' + n;
1547 },
1548 noEventsText: 'Žiadne akcie na zobrazenie',
1549 };
1550
1551 var l63 = {
1552 code: 'sl',
1553 week: {
1554 dow: 1,
1555 doy: 7, // The week that contains Jan 1st is the first week of the year.
1556 },
1557 buttonText: {
1558 prev: 'Prejšnji',
1559 next: 'Naslednji',
1560 today: 'Trenutni',
1561 year: 'Leto',
1562 month: 'Mesec',
1563 week: 'Teden',
1564 day: 'Dan',
1565 list: 'Dnevni red',
1566 },
1567 weekText: 'Teden',
1568 allDayText: 'Ves dan',
1569 moreLinkText: 'več',
1570 noEventsText: 'Ni dogodkov za prikaz',
1571 };
1572
1573 var l64 = {
1574 code: 'sm',
1575 buttonText: {
1576 prev: 'Talu ai',
1577 next: 'Mulimuli atu',
1578 today: 'Aso nei',
1579 year: 'Tausaga',
1580 month: 'Masina',
1581 week: 'Vaiaso',
1582 day: 'Aso',
1583 list: 'Faasologa',
1584 },
1585 weekText: 'Vaiaso',
1586 allDayText: 'Aso atoa',
1587 moreLinkText: 'sili atu',
1588 noEventsText: 'Leai ni mea na tutupu',
1589 };
1590
1591 var l65 = {
1592 code: 'sq',
1593 week: {
1594 dow: 1,
1595 doy: 4, // The week that contains Jan 4th is the first week of the year.
1596 },
1597 buttonText: {
1598 prev: 'mbrapa',
1599 next: 'Përpara',
1600 today: 'Sot',
1601 year: 'Viti',
1602 month: 'Muaj',
1603 week: 'Javë',
1604 day: 'Ditë',
1605 list: 'Listë',
1606 },
1607 weekText: 'Ja',
1608 allDayText: 'Gjithë ditën',
1609 moreLinkText(n) {
1610 return '+më tepër ' + n;
1611 },
1612 noEventsText: 'Nuk ka evente për të shfaqur',
1613 };
1614
1615 var l66 = {
1616 code: 'sr-cyrl',
1617 week: {
1618 dow: 1,
1619 doy: 7, // The week that contains Jan 1st is the first week of the year.
1620 },
1621 buttonText: {
1622 prev: 'Претходна',
1623 next: 'следећи',
1624 today: 'Данас',
1625 year: 'Година',
1626 month: 'Месец',
1627 week: 'Недеља',
1628 day: 'Дан',
1629 list: 'Планер',
1630 },
1631 weekText: 'Сед',
1632 allDayText: 'Цео дан',
1633 moreLinkText(n) {
1634 return '+ још ' + n;
1635 },
1636 noEventsText: 'Нема догађаја за приказ',
1637 };
1638
1639 var l67 = {
1640 code: 'sr',
1641 week: {
1642 dow: 1,
1643 doy: 7, // The week that contains Jan 1st is the first week of the year.
1644 },
1645 buttonText: {
1646 prev: 'Prethodna',
1647 next: 'Sledeći',
1648 today: 'Danas',
1649 year: 'Godina',
1650 month: 'Mеsеc',
1651 week: 'Nеdеlja',
1652 day: 'Dan',
1653 list: 'Planеr',
1654 },
1655 weekText: 'Sed',
1656 allDayText: 'Cеo dan',
1657 moreLinkText(n) {
1658 return '+ još ' + n;
1659 },
1660 noEventsText: 'Nеma događaja za prikaz',
1661 };
1662
1663 var l68 = {
1664 code: 'sv',
1665 week: {
1666 dow: 1,
1667 doy: 4, // The week that contains Jan 4th is the first week of the year.
1668 },
1669 buttonText: {
1670 prev: 'Förra',
1671 next: 'Nästa',
1672 today: 'Idag',
1673 year: 'År',
1674 month: 'Månad',
1675 week: 'Vecka',
1676 day: 'Dag',
1677 list: 'Program',
1678 },
1679 buttonHints: {
1680 prev(buttonText) {
1681 return `Föregående ${buttonText.toLocaleLowerCase()}`;
1682 },
1683 next(buttonText) {
1684 return `Nästa ${buttonText.toLocaleLowerCase()}`;
1685 },
1686 today(buttonText) {
1687 return (buttonText === 'Program' ? 'Detta' : 'Denna') + ' ' + buttonText.toLocaleLowerCase();
1688 },
1689 },
1690 viewHint: '$0 vy',
1691 navLinkHint: 'Gå till $0',
1692 moreLinkHint(eventCnt) {
1693 return `Visa ytterligare ${eventCnt} händelse${eventCnt === 1 ? '' : 'r'}`;
1694 },
1695 weekText: 'v.',
1696 weekTextLong: 'Vecka',
1697 allDayText: 'Heldag',
1698 moreLinkText: 'till',
1699 noEventsText: 'Inga händelser att visa',
1700 closeHint: 'Stäng',
1701 timeHint: 'Klockan',
1702 eventHint: 'Händelse',
1703 };
1704
1705 var l69 = {
1706 code: 'ta-in',
1707 week: {
1708 dow: 1,
1709 doy: 4, // The week that contains Jan 4th is the first week of the year.
1710 },
1711 buttonText: {
1712 prev: 'முந்தைய',
1713 next: 'அடுத்தது',
1714 today: 'இன்று',
1715 year: 'ஆண்டு',
1716 month: 'மாதம்',
1717 week: 'வாரம்',
1718 day: 'நாள்',
1719 list: 'தினசரி அட்டவணை',
1720 },
1721 weekText: 'வாரம்',
1722 allDayText: 'நாள் முழுவதும்',
1723 moreLinkText(n) {
1724 return '+ மேலும் ' + n;
1725 },
1726 noEventsText: 'காண்பிக்க நிகழ்வுகள் இல்லை',
1727 };
1728
1729 var l70 = {
1730 code: 'th',
1731 week: {
1732 dow: 1,
1733 doy: 4, // The week that contains Jan 4th is the first week of the year.
1734 },
1735 buttonText: {
1736 prev: 'ก่อนหน้า',
1737 next: 'ถัดไป',
1738 prevYear: 'ปีก่อนหน้า',
1739 nextYear: 'ปีถัดไป',
1740 year: 'ปี',
1741 today: 'วันนี้',
1742 month: 'เดือน',
1743 week: 'สัปดาห์',
1744 day: 'วัน',
1745 list: 'กำหนดการ',
1746 },
1747 weekText: 'สัปดาห์',
1748 allDayText: 'ตลอดวัน',
1749 moreLinkText: 'เพิ่มเติม',
1750 noEventsText: 'ไม่มีกิจกรรมที่จะแสดง',
1751 };
1752
1753 var l71 = {
1754 code: 'tr',
1755 week: {
1756 dow: 1,
1757 doy: 7, // The week that contains Jan 1st is the first week of the year.
1758 },
1759 buttonText: {
1760 prev: 'geri',
1761 next: 'ileri',
1762 today: 'bugün',
1763 year: 'Yıl',
1764 month: 'Ay',
1765 week: 'Hafta',
1766 day: 'Gün',
1767 list: 'Ajanda',
1768 },
1769 weekText: 'Hf',
1770 allDayText: 'Tüm gün',
1771 moreLinkText: 'daha fazla',
1772 noEventsText: 'Gösterilecek etkinlik yok',
1773 };
1774
1775 var l72 = {
1776 code: 'ug',
1777 buttonText: {
1778 prev: 'ئالدىنقى',
1779 next: 'كېيىنكى',
1780 today: 'بۈگۈن',
1781 year: 'يىل',
1782 month: 'ئاي',
1783 week: 'ھەپتە',
1784 day: 'كۈن',
1785 list: 'كۈنتەرتىپ',
1786 },
1787 allDayText: 'پۈتۈن كۈن',
1788 };
1789
1790 var l73 = {
1791 code: 'uk',
1792 week: {
1793 dow: 1,
1794 doy: 7, // The week that contains Jan 1st is the first week of the year.
1795 },
1796 buttonText: {
1797 prev: 'Попередній',
1798 next: 'далі',
1799 today: 'Сьогодні',
1800 year: 'рік',
1801 month: 'Місяць',
1802 week: 'Тиждень',
1803 day: 'День',
1804 list: 'Порядок денний',
1805 },
1806 weekText: 'Тиж',
1807 allDayText: 'Увесь день',
1808 moreLinkText(n) {
1809 return '+ще ' + n + '...';
1810 },
1811 noEventsText: 'Немає подій для відображення',
1812 };
1813
1814 var l74 = {
1815 code: 'uz-cy',
1816 week: {
1817 dow: 1,
1818 doy: 4, // The week that contains Jan 4th is the first week of the year.
1819 },
1820 buttonText: {
1821 prev: 'Олин',
1822 next: 'Кейин',
1823 today: 'Бугун',
1824 month: 'Ой',
1825 week: 'Ҳафта',
1826 day: 'Кун',
1827 list: 'Кун тартиби',
1828 },
1829 weekText: 'Ҳафта',
1830 allDayText: 'Кун бўйича',
1831 moreLinkText(n) {
1832 return '+ яна ' + n;
1833 },
1834 noEventsText: 'Кўрсатиш учун воқеалар йўқ',
1835 };
1836
1837 var l75 = {
1838 code: 'uz',
1839 week: {
1840 dow: 1,
1841 doy: 4, // The week that contains Jan 4th is the first week of the year.
1842 },
1843 buttonText: {
1844 prev: 'Oldingi',
1845 next: 'Keyingi',
1846 today: 'Bugun',
1847 year: 'Yil',
1848 month: 'Oy',
1849 week: 'Xafta',
1850 day: 'Kun',
1851 list: 'Kun tartibi',
1852 },
1853 allDayText: 'Kun bo\'yi',
1854 moreLinkText(n) {
1855 return '+ yana ' + n;
1856 },
1857 noEventsText: 'Ko\'rsatish uchun voqealar yo\'q',
1858 };
1859
1860 var l76 = {
1861 code: 'vi',
1862 week: {
1863 dow: 1,
1864 doy: 4, // The week that contains Jan 4th is the first week of the year.
1865 },
1866 buttonText: {
1867 prev: 'Trước',
1868 next: 'Tiếp',
1869 today: 'Hôm nay',
1870 year: 'Năm',
1871 month: 'Tháng',
1872 week: 'Tuần',
1873 day: 'Ngày',
1874 list: 'Lịch biểu',
1875 },
1876 weekText: 'Tu',
1877 allDayText: 'Cả ngày',
1878 moreLinkText(n) {
1879 return '+ thêm ' + n;
1880 },
1881 noEventsText: 'Không có sự kiện để hiển thị',
1882 };
1883
1884 var l77 = {
1885 code: 'zh-cn',
1886 week: {
1887 // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
1888 dow: 1,
1889 doy: 4, // The week that contains Jan 4th is the first week of the year.
1890 },
1891 buttonText: {
1892 prev: '上月',
1893 next: '下月',
1894 today: '今天',
1895 year: '年',
1896 month: '月',
1897 week: '周',
1898 day: '日',
1899 list: '日程',
1900 },
1901 weekText: '周',
1902 allDayText: '全天',
1903 moreLinkText(n) {
1904 return '另外 ' + n + ' 个';
1905 },
1906 noEventsText: '没有事件显示',
1907 };
1908
1909 var l78 = {
1910 code: 'zh-tw',
1911 buttonText: {
1912 prev: '上個',
1913 next: '下個',
1914 today: '今天',
1915 year: '年',
1916 month: '月',
1917 week: '週',
1918 day: '天',
1919 list: '活動列表',
1920 },
1921 weekText: '週',
1922 allDayText: '整天',
1923 moreLinkText: '顯示更多',
1924 noEventsText: '沒有任何活動',
1925 };
1926
1927 var localesAll = [
1928 l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36, l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48, l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72, l73, l74, l75, l76, l77, l78,
1929 ];
1930
1931 index_js.globalLocales.push(...localesAll);
1932
1933})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales-all.global.min.js b/public/js/fullcalendar/packages/core/locales-all.global.min.js
new file mode 100644
index 0000000..046d0ee
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales-all.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";function t(e){return"Tag"===e||"Monat"===e?"r":"Jahr"===e?"s":""}function n(e){return"Tag"===e||"Monat"===e?"r":"Jahr"===e?"s":""}var o=[{code:"af",week:{dow:1,doy:4},buttonText:{prev:"Vorige",next:"Volgende",today:"Vandag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Heeldag",moreLinkText:"Addisionele",noEventsText:"Daar is geen gebeurtenisse nie"},{code:"ar-dz",week:{dow:0,doy:4},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar-kw",week:{dow:0,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar-ly",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar-ma",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar-sa",week:{dow:0,doy:6},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar-tn",week:{dow:1,doy:4},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"ar",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"},{code:"az",week:{dow:1,doy:4},buttonText:{prev:"Əvvəl",next:"Sonra",today:"Bu Gün",year:"Il",month:"Ay",week:"Həftə",day:"Gün",list:"Gündəm"},weekText:"Həftə",allDayText:"Bütün Gün",moreLinkText:e=>"+ daha çox "+e,noEventsText:"Göstərmək üçün hadisə yoxdur"},{code:"bg",week:{dow:1,doy:4},buttonText:{prev:"назад",next:"напред",today:"днес",year:"година",month:"Месец",week:"Седмица",day:"Ден",list:"График"},allDayText:"Цял ден",moreLinkText:e=>"+още "+e,noEventsText:"Няма събития за показване"},{code:"bn",week:{dow:0,doy:6},buttonText:{prev:"পেছনে",next:"সামনে",today:"আজ",year:"বছর",month:"মাস",week:"সপ্তাহ",day:"দিন",list:"তালিকা"},weekText:"সপ্তাহ",allDayText:"সারাদিন",moreLinkText:e=>"+অন্যান্য "+e,noEventsText:"কোনো ইভেন্ট নেই"},{code:"bs",week:{dow:1,doy:7},buttonText:{prev:"Prošli",next:"Sljedeći",today:"Danas",year:"Godina",month:"Mjesec",week:"Sedmica",day:"Dan",list:"Raspored"},weekText:"Sed",allDayText:"Cijeli dan",moreLinkText:e=>"+ još "+e,noEventsText:"Nema događaja za prikazivanje"},{code:"ca",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Següent",today:"Avui",year:"Any",month:"Mes",week:"Setmana",day:"Dia",list:"Agenda"},weekText:"Set",allDayText:"Tot el dia",moreLinkText:"més",noEventsText:"No hi ha esdeveniments per mostrar"},{code:"cs",week:{dow:1,doy:4},buttonText:{prev:"Dříve",next:"Později",today:"Nyní",year:"Rok",month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},weekText:"Týd",allDayText:"Celý den",moreLinkText:e=>"+další: "+e,noEventsText:"Žádné akce k zobrazení"},{code:"cy",week:{dow:1,doy:4},buttonText:{prev:"Blaenorol",next:"Nesaf",today:"Heddiw",year:"Blwyddyn",month:"Mis",week:"Wythnos",day:"Dydd",list:"Rhestr"},weekText:"Wythnos",allDayText:"Trwy'r dydd",moreLinkText:"Mwy",noEventsText:"Dim digwyddiadau"},{code:"da",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Næste",today:"I dag",year:"År",month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},weekText:"Uge",allDayText:"Hele dagen",moreLinkText:"flere",noEventsText:"Ingen arrangementer at vise"},{code:"de-at",week:{dow:1,doy:4},buttonText:{prev:"Zurück",next:"Vor",today:"Heute",year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},weekText:"KW",weekTextLong:"Woche",allDayText:"Ganztägig",moreLinkText:e=>"+ weitere "+e,noEventsText:"Keine Ereignisse anzuzeigen",buttonHints:{prev:e=>`Vorherige${t(e)} ${e}`,next:e=>`Nächste${t(e)} ${e}`,today:e=>"Tag"===e?"Heute":`Diese${t(e)} ${e}`},viewHint:e=>e+("Woche"===e?"n":"Monat"===e?"s":"es")+"ansicht",navLinkHint:"Gehe zu $0",moreLinkHint:e=>"Zeige "+(1===e?"ein weiteres Ereignis":e+" weitere Ereignisse"),closeHint:"Schließen",timeHint:"Uhrzeit",eventHint:"Ereignis"},{code:"de",week:{dow:1,doy:4},buttonText:{prev:"Zurück",next:"Vor",today:"Heute",year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},weekText:"KW",weekTextLong:"Woche",allDayText:"Ganztägig",moreLinkText:e=>"+ weitere "+e,noEventsText:"Keine Ereignisse anzuzeigen",buttonHints:{prev:e=>`Vorherige${n(e)} ${e}`,next:e=>`Nächste${n(e)} ${e}`,today:e=>"Tag"===e?"Heute":`Diese${n(e)} ${e}`},viewHint:e=>e+("Woche"===e?"n":"Monat"===e?"s":"es")+"ansicht",navLinkHint:"Gehe zu $0",moreLinkHint:e=>"Zeige "+(1===e?"ein weiteres Ereignis":e+" weitere Ereignisse"),closeHint:"Schließen",timeHint:"Uhrzeit",eventHint:"Ereignis"},{code:"el",week:{dow:1,doy:4},buttonText:{prev:"Προηγούμενος",next:"Επόμενος",today:"Σήμερα",year:"Ετος",month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},weekText:"Εβδ",allDayText:"Ολοήμερο",moreLinkText:"περισσότερα",noEventsText:"Δεν υπάρχουν γεγονότα προς εμφάνιση"},{code:"en-au",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`},{code:"en-gb",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`},{code:"en-nz",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`},{code:"eo",week:{dow:1,doy:4},buttonText:{prev:"Antaŭa",next:"Sekva",today:"Hodiaŭ",year:"Jaro",month:"Monato",week:"Semajno",day:"Tago",list:"Tagordo"},weekText:"Sm",allDayText:"Tuta tago",moreLinkText:"pli",noEventsText:"Neniuj eventoj por montri"},{code:"es",week:{dow:0,doy:6},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",year:"Año",month:"Mes",week:"Semana",day:"Día",list:"Agenda"},weekText:"Sm",allDayText:"Todo el día",moreLinkText:"más",noEventsText:"No hay eventos para mostrar"},{code:"es",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",year:"Año",month:"Mes",week:"Semana",day:"Día",list:"Agenda"},buttonHints:{prev:"$0 antes",next:"$0 siguiente",today:e=>"Día"===e?"Hoy":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Vista "+("Semana"===e?"de la":"del")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"Todo el día",moreLinkText:"más",moreLinkHint:e=>`Mostrar ${e} eventos más`,noEventsText:"No hay eventos para mostrar",navLinkHint:"Ir al $0",closeHint:"Cerrar",timeHint:"La hora",eventHint:"Evento"},{code:"et",week:{dow:1,doy:4},buttonText:{prev:"Eelnev",next:"Järgnev",today:"Täna",year:"Aasta",month:"Kuu",week:"Nädal",day:"Päev",list:"Päevakord"},weekText:"näd",allDayText:"Kogu päev",moreLinkText:e=>"+ veel "+e,noEventsText:"Kuvamiseks puuduvad sündmused"},{code:"eu",week:{dow:1,doy:7},buttonText:{prev:"Aur",next:"Hur",today:"Gaur",year:"Urtea",month:"Hilabetea",week:"Astea",day:"Eguna",list:"Agenda"},weekText:"As",allDayText:"Egun osoa",moreLinkText:"gehiago",noEventsText:"Ez dago ekitaldirik erakusteko"},{code:"fa",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"قبلی",next:"بعدی",today:"امروز",year:"سال",month:"ماه",week:"هفته",day:"روز",list:"برنامه"},weekText:"هف",allDayText:"تمام روز",moreLinkText:e=>"بیش از "+e,noEventsText:"هیچ رویدادی به نمایش"},{code:"fi",week:{dow:1,doy:4},buttonText:{prev:"Edellinen",next:"Seuraava",today:"Tänään",year:"Vuosi",month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},weekText:"Vk",allDayText:"Koko päivä",moreLinkText:"lisää",noEventsText:"Ei näytettäviä tapahtumia"},{code:"fr",buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekText:"Sem.",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"},{code:"fr-ch",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Courant",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekText:"Sm",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"},{code:"fr",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Planning"},weekText:"Sem.",weekTextLong:"Semaine",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"},{code:"gl",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Seg",today:"Hoxe",year:"Ano",month:"Mes",week:"Semana",day:"Día",list:"Axenda"},buttonHints:{prev:"$0 antes",next:"$0 seguinte",today:e=>"Día"===e?"Hoxe":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Vista "+("Semana"===e?"da":"do")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"Todo o día",moreLinkText:"máis",moreLinkHint:e=>`Amosar ${e} eventos máis`,noEventsText:"Non hai eventos para amosar",navLinkHint:"Ir ao $0",closeHint:"Pechar",timeHint:"A hora",eventHint:"Evento"},{code:"he",direction:"rtl",buttonText:{prev:"הקודם",next:"הבא",today:"היום",year:"שנה",month:"חודש",week:"שבוע",day:"יום",list:"סדר יום"},allDayText:"כל היום",moreLinkText:"נוספים",noEventsText:"אין אירועים להצגה",weekText:"שבוע"},{code:"hi",week:{dow:0,doy:6},buttonText:{prev:"पिछला",next:"अगला",today:"आज",year:"वर्ष",month:"महीना",week:"सप्ताह",day:"दिन",list:"कार्यसूची"},weekText:"हफ्ता",allDayText:"सभी दिन",moreLinkText:e=>"+अधिक "+e,noEventsText:"कोई घटनाओं को प्रदर्शित करने के लिए"},{code:"hr",week:{dow:1,doy:7},buttonText:{prev:"Prijašnji",next:"Sljedeći",today:"Danas",year:"Godina",month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},weekText:"Tje",allDayText:"Cijeli dan",moreLinkText:e=>"+ još "+e,noEventsText:"Nema događaja za prikaz"},{code:"hu",week:{dow:1,doy:4},buttonText:{prev:"vissza",next:"előre",today:"ma",year:"Év",month:"Hónap",week:"Hét",day:"Nap",list:"Lista"},weekText:"Hét",allDayText:"Egész nap",moreLinkText:"további",noEventsText:"Nincs megjeleníthető esemény"},{code:"hy-am",week:{dow:1,doy:4},buttonText:{prev:"Նախորդ",next:"Հաջորդ",today:"Այսօր",year:"Տարի",month:"Ամիս",week:"Շաբաթ",day:"Օր",list:"Օրվա ցուցակ"},weekText:"Շաբ",allDayText:"Ամբողջ օր",moreLinkText:e=>"+ ևս "+e,noEventsText:"Բացակայում է իրադարձությունը ցուցադրելու"},{code:"id",week:{dow:1,doy:7},buttonText:{prev:"mundur",next:"maju",today:"hari ini",year:"Tahun",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekText:"Mg",allDayText:"Sehari penuh",moreLinkText:"lebih",noEventsText:"Tidak ada acara untuk ditampilkan"},{code:"is",week:{dow:1,doy:4},buttonText:{prev:"Fyrri",next:"Næsti",today:"Í dag",year:"Ár",month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},weekText:"Vika",allDayText:"Allan daginn",moreLinkText:"meira",noEventsText:"Engir viðburðir til að sýna"},{code:"it",week:{dow:1,doy:4},buttonText:{prev:"Prec",next:"Succ",today:"Oggi",year:"Anno",month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},weekText:"Sm",allDayText:"Tutto il giorno",moreLinkText:e=>"+altri "+e,noEventsText:"Non ci sono eventi da visualizzare"},{code:"ja",buttonText:{prev:"前",next:"次",today:"今日",year:"年",month:"月",week:"週",day:"日",list:"予定リスト"},weekText:"週",allDayText:"終日",moreLinkText:e=>"他 "+e+" 件",noEventsText:"表示する予定はありません"},{code:"ka",week:{dow:1,doy:7},buttonText:{prev:"წინა",next:"შემდეგი",today:"დღეს",year:"წელიწადი",month:"თვე",week:"კვირა",day:"დღე",list:"დღის წესრიგი"},weekText:"კვ",allDayText:"მთელი დღე",moreLinkText:e=>"+ კიდევ "+e,noEventsText:"ღონისძიებები არ არის"},{code:"kk",week:{dow:1,doy:7},buttonText:{prev:"Алдыңғы",next:"Келесі",today:"Бүгін",year:"Жыл",month:"Ай",week:"Апта",day:"Күн",list:"Күн тәртібі"},weekText:"Не",allDayText:"Күні бойы",moreLinkText:e=>"+ тағы "+e,noEventsText:"Көрсету үшін оқиғалар жоқ"},{code:"km",week:{dow:1,doy:4},buttonText:{prev:"មុន",next:"បន្ទាប់",today:"ថ្ងៃនេះ",year:"ឆ្នាំ",month:"ខែ",week:"សប្តាហ៍",day:"ថ្ងៃ",list:"បញ្ជី"},weekText:"សប្តាហ៍",allDayText:"ពេញមួយថ្ងៃ",moreLinkText:"ច្រើនទៀត",noEventsText:"គ្មានព្រឹត្តិការណ៍ត្រូវបង្ហាញ"},{code:"ko",buttonText:{prev:"이전달",next:"다음달",today:"오늘",year:"년도",month:"월",week:"주",day:"일",list:"일정목록"},weekText:"주",allDayText:"종일",moreLinkText:"개",noEventsText:"일정이 없습니다"},{code:"ku",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"پێشتر",next:"دواتر",today:"ئەمڕو",year:"ساڵ",month:"مانگ",week:"هەفتە",day:"ڕۆژ",list:"بەرنامە"},weekText:"هەفتە",allDayText:"هەموو ڕۆژەکە",moreLinkText:"زیاتر",noEventsText:"هیچ ڕووداوێك نیە"},{code:"lb",week:{dow:1,doy:4},buttonText:{prev:"Zréck",next:"Weider",today:"Haut",year:"Joer",month:"Mount",week:"Woch",day:"Dag",list:"Terminiwwersiicht"},weekText:"W",allDayText:"Ganzen Dag",moreLinkText:"méi",noEventsText:"Nee Evenementer ze affichéieren"},{code:"lt",week:{dow:1,doy:4},buttonText:{prev:"Atgal",next:"Pirmyn",today:"Šiandien",year:"Metai",month:"Mėnuo",week:"Savaitė",day:"Diena",list:"Darbotvarkė"},weekText:"SAV",allDayText:"Visą dieną",moreLinkText:"daugiau",noEventsText:"Nėra įvykių rodyti"},{code:"lv",week:{dow:1,doy:4},buttonText:{prev:"Iepr.",next:"Nāk.",today:"Šodien",year:"Gads",month:"Mēnesis",week:"Nedēļa",day:"Diena",list:"Dienas kārtība"},weekText:"Ned.",allDayText:"Visu dienu",moreLinkText:e=>"+vēl "+e,noEventsText:"Nav notikumu"},{code:"mk",buttonText:{prev:"претходно",next:"следно",today:"Денес",year:"година",month:"Месец",week:"Недела",day:"Ден",list:"График"},weekText:"Сед",allDayText:"Цел ден",moreLinkText:e=>"+повеќе "+e,noEventsText:"Нема настани за прикажување"},{code:"ms",week:{dow:1,doy:7},buttonText:{prev:"Sebelum",next:"Selepas",today:"hari ini",year:"Tahun",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekText:"Mg",allDayText:"Sepanjang hari",moreLinkText:e=>"masih ada "+e+" acara",noEventsText:"Tiada peristiwa untuk dipaparkan"},{code:"nb",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Neste",today:"I dag",year:"År",month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},weekText:"Uke",weekTextLong:"Uke",allDayText:"Hele dagen",moreLinkText:"til",noEventsText:"Ingen hendelser å vise",buttonHints:{prev:"Forrige $0",next:"Neste $0",today:"Nåværende $0"},viewHint:"$0 visning",navLinkHint:"Gå til $0",moreLinkHint:e=>`Vis ${e} flere hendelse${1===e?"":"r"}`},{code:"ne",week:{dow:7,doy:1},buttonText:{prev:"अघिल्लो",next:"अर्को",today:"आज",year:"वर्ष",month:"महिना",week:"हप्ता",day:"दिन",list:"सूची"},weekText:"हप्ता",allDayText:"दिनभरि",moreLinkText:"थप लिंक",noEventsText:"देखाउनको लागि कुनै घटनाहरू छैनन्"},{code:"nl",week:{dow:1,doy:4},buttonText:{prev:"Vorige",next:"Volgende",today:"Vandaag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Lijst"},allDayText:"Hele dag",moreLinkText:"extra",noEventsText:"Geen evenementen om te laten zien"},{code:"nn",week:{dow:1,doy:4},buttonText:{prev:"Førre",next:"Neste",today:"I dag",year:"År",month:"Månad",week:"Veke",day:"Dag",list:"Agenda"},weekText:"Veke",allDayText:"Heile dagen",moreLinkText:"til",noEventsText:"Ingen hendelser å vise"},{code:"pl",week:{dow:1,doy:4},buttonText:{prev:"Poprzedni",next:"Następny",today:"Dziś",year:"Rok",month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},weekText:"Tydz",allDayText:"Cały dzień",moreLinkText:"więcej",noEventsText:"Brak wydarzeń do wyświetlenia"},{code:"pt-br",buttonText:{prev:"Anterior",next:"Próximo",prevYear:"Ano anterior",nextYear:"Próximo ano",year:"Ano",today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista"},buttonHints:{prev:"$0 Anterior",next:"Próximo $0",today:e=>"Dia"===e?"Hoje":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Visualizar "+("Semana"===e?"a":"o")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"dia inteiro",moreLinkText:e=>"mais +"+e,moreLinkHint:e=>`Mostrar mais ${e} eventos`,noEventsText:"Não há eventos para mostrar",navLinkHint:"Ir para $0",closeHint:"Fechar",timeHint:"A hora",eventHint:"Evento"},{code:"pt",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Seguinte",today:"Hoje",year:"Ano",month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},weekText:"Sem",allDayText:"Todo o dia",moreLinkText:"mais",noEventsText:"Não há eventos para mostrar"},{code:"ro",week:{dow:1,doy:7},buttonText:{prev:"precedentă",next:"următoare",today:"Azi",year:"An",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},weekText:"Săpt",allDayText:"Toată ziua",moreLinkText:e=>"+alte "+e,noEventsText:"Nu există evenimente de afișat"},{code:"ru",week:{dow:1,doy:4},buttonText:{prev:"Пред",next:"След",today:"Сегодня",year:"Год",month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},weekText:"Нед",allDayText:"Весь день",moreLinkText:e=>"+ ещё "+e,noEventsText:"Нет событий для отображения"},{code:"si-lk",week:{dow:1,doy:4},buttonText:{prev:"පෙර",next:"පසු",today:"අද",year:"අවුරුදු",month:"මාසය",week:"සතිය",day:"දවස",list:"ලැයිස්තුව"},weekText:"සති",allDayText:"සියලු",moreLinkText:"තවත්",noEventsText:"මුකුත් නැත"},{code:"sk",week:{dow:1,doy:4},buttonText:{prev:"Predchádzajúci",next:"Nasledujúci",today:"Dnes",year:"Rok",month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},weekText:"Ty",allDayText:"Celý deň",moreLinkText:e=>"+ďalšie: "+e,noEventsText:"Žiadne akcie na zobrazenie"},{code:"sl",week:{dow:1,doy:7},buttonText:{prev:"Prejšnji",next:"Naslednji",today:"Trenutni",year:"Leto",month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},weekText:"Teden",allDayText:"Ves dan",moreLinkText:"več",noEventsText:"Ni dogodkov za prikaz"},{code:"sm",buttonText:{prev:"Talu ai",next:"Mulimuli atu",today:"Aso nei",year:"Tausaga",month:"Masina",week:"Vaiaso",day:"Aso",list:"Faasologa"},weekText:"Vaiaso",allDayText:"Aso atoa",moreLinkText:"sili atu",noEventsText:"Leai ni mea na tutupu"},{code:"sq",week:{dow:1,doy:4},buttonText:{prev:"mbrapa",next:"Përpara",today:"Sot",year:"Viti",month:"Muaj",week:"Javë",day:"Ditë",list:"Listë"},weekText:"Ja",allDayText:"Gjithë ditën",moreLinkText:e=>"+më tepër "+e,noEventsText:"Nuk ka evente për të shfaqur"},{code:"sr-cyrl",week:{dow:1,doy:7},buttonText:{prev:"Претходна",next:"следећи",today:"Данас",year:"Година",month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},weekText:"Сед",allDayText:"Цео дан",moreLinkText:e=>"+ још "+e,noEventsText:"Нема догађаја за приказ"},{code:"sr",week:{dow:1,doy:7},buttonText:{prev:"Prethodna",next:"Sledeći",today:"Danas",year:"Godina",month:"Mеsеc",week:"Nеdеlja",day:"Dan",list:"Planеr"},weekText:"Sed",allDayText:"Cеo dan",moreLinkText:e=>"+ još "+e,noEventsText:"Nеma događaja za prikaz"},{code:"sv",week:{dow:1,doy:4},buttonText:{prev:"Förra",next:"Nästa",today:"Idag",year:"År",month:"Månad",week:"Vecka",day:"Dag",list:"Program"},buttonHints:{prev:e=>"Föregående "+e.toLocaleLowerCase(),next:e=>"Nästa "+e.toLocaleLowerCase(),today:e=>("Program"===e?"Detta":"Denna")+" "+e.toLocaleLowerCase()},viewHint:"$0 vy",navLinkHint:"Gå till $0",moreLinkHint:e=>`Visa ytterligare ${e} händelse${1===e?"":"r"}`,weekText:"v.",weekTextLong:"Vecka",allDayText:"Heldag",moreLinkText:"till",noEventsText:"Inga händelser att visa",closeHint:"Stäng",timeHint:"Klockan",eventHint:"Händelse"},{code:"ta-in",week:{dow:1,doy:4},buttonText:{prev:"முந்தைய",next:"அடுத்தது",today:"இன்று",year:"ஆண்டு",month:"மாதம்",week:"வாரம்",day:"நாள்",list:"தினசரி அட்டவணை"},weekText:"வாரம்",allDayText:"நாள் முழுவதும்",moreLinkText:e=>"+ மேலும் "+e,noEventsText:"காண்பிக்க நிகழ்வுகள் இல்லை"},{code:"th",week:{dow:1,doy:4},buttonText:{prev:"ก่อนหน้า",next:"ถัดไป",prevYear:"ปีก่อนหน้า",nextYear:"ปีถัดไป",year:"ปี",today:"วันนี้",month:"เดือน",week:"สัปดาห์",day:"วัน",list:"กำหนดการ"},weekText:"สัปดาห์",allDayText:"ตลอดวัน",moreLinkText:"เพิ่มเติม",noEventsText:"ไม่มีกิจกรรมที่จะแสดง"},{code:"tr",week:{dow:1,doy:7},buttonText:{prev:"geri",next:"ileri",today:"bugün",year:"Yıl",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},weekText:"Hf",allDayText:"Tüm gün",moreLinkText:"daha fazla",noEventsText:"Gösterilecek etkinlik yok"},{code:"ug",buttonText:{prev:"ئالدىنقى",next:"كېيىنكى",today:"بۈگۈن",year:"يىل",month:"ئاي",week:"ھەپتە",day:"كۈن",list:"كۈنتەرتىپ"},allDayText:"پۈتۈن كۈن"},{code:"uk",week:{dow:1,doy:7},buttonText:{prev:"Попередній",next:"далі",today:"Сьогодні",year:"рік",month:"Місяць",week:"Тиждень",day:"День",list:"Порядок денний"},weekText:"Тиж",allDayText:"Увесь день",moreLinkText:e=>"+ще "+e+"...",noEventsText:"Немає подій для відображення"},{code:"uz-cy",week:{dow:1,doy:4},buttonText:{prev:"Олин",next:"Кейин",today:"Бугун",month:"Ой",week:"Ҳафта",day:"Кун",list:"Кун тартиби"},weekText:"Ҳафта",allDayText:"Кун бўйича",moreLinkText:e=>"+ яна "+e,noEventsText:"Кўрсатиш учун воқеалар йўқ"},{code:"uz",week:{dow:1,doy:4},buttonText:{prev:"Oldingi",next:"Keyingi",today:"Bugun",year:"Yil",month:"Oy",week:"Xafta",day:"Kun",list:"Kun tartibi"},allDayText:"Kun bo'yi",moreLinkText:e=>"+ yana "+e,noEventsText:"Ko'rsatish uchun voqealar yo'q"},{code:"vi",week:{dow:1,doy:4},buttonText:{prev:"Trước",next:"Tiếp",today:"Hôm nay",year:"Năm",month:"Tháng",week:"Tuần",day:"Ngày",list:"Lịch biểu"},weekText:"Tu",allDayText:"Cả ngày",moreLinkText:e=>"+ thêm "+e,noEventsText:"Không có sự kiện để hiển thị"},{code:"zh-cn",week:{dow:1,doy:4},buttonText:{prev:"上月",next:"下月",today:"今天",year:"年",month:"月",week:"周",day:"日",list:"日程"},weekText:"周",allDayText:"全天",moreLinkText:e=>"另外 "+e+" 个",noEventsText:"没有事件显示"},{code:"zh-tw",buttonText:{prev:"上個",next:"下個",today:"今天",year:"年",month:"月",week:"週",day:"天",list:"活動列表"},weekText:"週",allDayText:"整天",moreLinkText:"顯示更多",noEventsText:"沒有任何活動"}];FullCalendar.globalLocales.push(...o)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/af.global.js b/public/js/fullcalendar/packages/core/locales/af.global.js
new file mode 100644
index 0000000..6ff6bf4
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/af.global.js
@@ -0,0 +1,32 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'af',
11 week: {
12 dow: 1,
13 doy: 4, // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
14 },
15 buttonText: {
16 prev: 'Vorige',
17 next: 'Volgende',
18 today: 'Vandag',
19 year: 'Jaar',
20 month: 'Maand',
21 week: 'Week',
22 day: 'Dag',
23 list: 'Agenda',
24 },
25 allDayText: 'Heeldag',
26 moreLinkText: 'Addisionele',
27 noEventsText: 'Daar is geen gebeurtenisse nie',
28 };
29
30 index_js.globalLocales.push(locale);
31
32})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/af.global.min.js b/public/js/fullcalendar/packages/core/locales/af.global.min.js
new file mode 100644
index 0000000..31c858b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/af.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"af",week:{dow:1,doy:4},buttonText:{prev:"Vorige",next:"Volgende",today:"Vandag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Heeldag",moreLinkText:"Addisionele",noEventsText:"Daar is geen gebeurtenisse nie"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-dz.global.js b/public/js/fullcalendar/packages/core/locales/ar-dz.global.js
new file mode 100644
index 0000000..9702ea1
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-dz.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-dz',
11 week: {
12 dow: 0,
13 doy: 4, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-dz.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-dz.global.min.js
new file mode 100644
index 0000000..560f65b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-dz.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-dz",week:{dow:0,doy:4},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-kw.global.js b/public/js/fullcalendar/packages/core/locales/ar-kw.global.js
new file mode 100644
index 0000000..bff8d23
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-kw.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-kw',
11 week: {
12 dow: 0,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-kw.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-kw.global.min.js
new file mode 100644
index 0000000..7cba542
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-kw.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-kw",week:{dow:0,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-ly.global.js b/public/js/fullcalendar/packages/core/locales/ar-ly.global.js
new file mode 100644
index 0000000..5c09881
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-ly.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-ly',
11 week: {
12 dow: 6,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-ly.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-ly.global.min.js
new file mode 100644
index 0000000..1919ece
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-ly.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-ly",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-ma.global.js b/public/js/fullcalendar/packages/core/locales/ar-ma.global.js
new file mode 100644
index 0000000..1a8432b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-ma.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-ma',
11 week: {
12 dow: 6,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-ma.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-ma.global.min.js
new file mode 100644
index 0000000..689cfd4
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-ma.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-ma",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-sa.global.js b/public/js/fullcalendar/packages/core/locales/ar-sa.global.js
new file mode 100644
index 0000000..7717edc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-sa.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-sa',
11 week: {
12 dow: 0,
13 doy: 6, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-sa.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-sa.global.min.js
new file mode 100644
index 0000000..e383373
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-sa.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-sa",week:{dow:0,doy:6},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar-tn.global.js b/public/js/fullcalendar/packages/core/locales/ar-tn.global.js
new file mode 100644
index 0000000..5a82d3e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-tn.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar-tn',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar-tn.global.min.js b/public/js/fullcalendar/packages/core/locales/ar-tn.global.min.js
new file mode 100644
index 0000000..2e94ddd
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar-tn.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar-tn",week:{dow:1,doy:4},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ar.global.js b/public/js/fullcalendar/packages/core/locales/ar.global.js
new file mode 100644
index 0000000..9eecbbd
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ar',
11 week: {
12 dow: 6,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'السابق',
18 next: 'التالي',
19 today: 'اليوم',
20 year: 'سنة',
21 month: 'شهر',
22 week: 'أسبوع',
23 day: 'يوم',
24 list: 'أجندة',
25 },
26 weekText: 'أسبوع',
27 allDayText: 'اليوم كله',
28 moreLinkText: 'أخرى',
29 noEventsText: 'أي أحداث لعرض',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ar.global.min.js b/public/js/fullcalendar/packages/core/locales/ar.global.min.js
new file mode 100644
index 0000000..bc89a1d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ar.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ar",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"السابق",next:"التالي",today:"اليوم",year:"سنة",month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},weekText:"أسبوع",allDayText:"اليوم كله",moreLinkText:"أخرى",noEventsText:"أي أحداث لعرض"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/az.global.js b/public/js/fullcalendar/packages/core/locales/az.global.js
new file mode 100644
index 0000000..24ec228
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/az.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'az',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Əvvəl',
17 next: 'Sonra',
18 today: 'Bu Gün',
19 year: 'Il',
20 month: 'Ay',
21 week: 'Həftə',
22 day: 'Gün',
23 list: 'Gündəm',
24 },
25 weekText: 'Həftə',
26 allDayText: 'Bütün Gün',
27 moreLinkText(n) {
28 return '+ daha çox ' + n;
29 },
30 noEventsText: 'Göstərmək üçün hadisə yoxdur',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/az.global.min.js b/public/js/fullcalendar/packages/core/locales/az.global.min.js
new file mode 100644
index 0000000..c8e74b6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/az.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"az",week:{dow:1,doy:4},buttonText:{prev:"Əvvəl",next:"Sonra",today:"Bu Gün",year:"Il",month:"Ay",week:"Həftə",day:"Gün",list:"Gündəm"},weekText:"Həftə",allDayText:"Bütün Gün",moreLinkText:e=>"+ daha çox "+e,noEventsText:"Göstərmək üçün hadisə yoxdur"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/bg.global.js b/public/js/fullcalendar/packages/core/locales/bg.global.js
new file mode 100644
index 0000000..271e2b6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bg.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'bg',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'назад',
17 next: 'напред',
18 today: 'днес',
19 year: 'година',
20 month: 'Месец',
21 week: 'Седмица',
22 day: 'Ден',
23 list: 'График',
24 },
25 allDayText: 'Цял ден',
26 moreLinkText(n) {
27 return '+още ' + n;
28 },
29 noEventsText: 'Няма събития за показване',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/bg.global.min.js b/public/js/fullcalendar/packages/core/locales/bg.global.min.js
new file mode 100644
index 0000000..d7ebb07
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bg.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"bg",week:{dow:1,doy:4},buttonText:{prev:"назад",next:"напред",today:"днес",year:"година",month:"Месец",week:"Седмица",day:"Ден",list:"График"},allDayText:"Цял ден",moreLinkText:e=>"+още "+e,noEventsText:"Няма събития за показване"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/bn.global.js b/public/js/fullcalendar/packages/core/locales/bn.global.js
new file mode 100644
index 0000000..7037805
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bn.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'bn',
11 week: {
12 dow: 0,
13 doy: 6, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'পেছনে',
17 next: 'সামনে',
18 today: 'আজ',
19 year: 'বছর',
20 month: 'মাস',
21 week: 'সপ্তাহ',
22 day: 'দিন',
23 list: 'তালিকা',
24 },
25 weekText: 'সপ্তাহ',
26 allDayText: 'সারাদিন',
27 moreLinkText(n) {
28 return '+অন্যান্য ' + n;
29 },
30 noEventsText: 'কোনো ইভেন্ট নেই',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/bn.global.min.js b/public/js/fullcalendar/packages/core/locales/bn.global.min.js
new file mode 100644
index 0000000..c721f2e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bn.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"bn",week:{dow:0,doy:6},buttonText:{prev:"পেছনে",next:"সামনে",today:"আজ",year:"বছর",month:"মাস",week:"সপ্তাহ",day:"দিন",list:"তালিকা"},weekText:"সপ্তাহ",allDayText:"সারাদিন",moreLinkText:e=>"+অন্যান্য "+e,noEventsText:"কোনো ইভেন্ট নেই"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/bs.global.js b/public/js/fullcalendar/packages/core/locales/bs.global.js
new file mode 100644
index 0000000..c9ffc51
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bs.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'bs',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Prošli',
17 next: 'Sljedeći',
18 today: 'Danas',
19 year: 'Godina',
20 month: 'Mjesec',
21 week: 'Sedmica',
22 day: 'Dan',
23 list: 'Raspored',
24 },
25 weekText: 'Sed',
26 allDayText: 'Cijeli dan',
27 moreLinkText(n) {
28 return '+ još ' + n;
29 },
30 noEventsText: 'Nema događaja za prikazivanje',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/bs.global.min.js b/public/js/fullcalendar/packages/core/locales/bs.global.min.js
new file mode 100644
index 0000000..f42c951
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/bs.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"bs",week:{dow:1,doy:7},buttonText:{prev:"Prošli",next:"Sljedeći",today:"Danas",year:"Godina",month:"Mjesec",week:"Sedmica",day:"Dan",list:"Raspored"},weekText:"Sed",allDayText:"Cijeli dan",moreLinkText:e=>"+ još "+e,noEventsText:"Nema događaja za prikazivanje"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ca.global.js b/public/js/fullcalendar/packages/core/locales/ca.global.js
new file mode 100644
index 0000000..7d2391e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ca.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ca',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Anterior',
17 next: 'Següent',
18 today: 'Avui',
19 year: 'Any',
20 month: 'Mes',
21 week: 'Setmana',
22 day: 'Dia',
23 list: 'Agenda',
24 },
25 weekText: 'Set',
26 allDayText: 'Tot el dia',
27 moreLinkText: 'més',
28 noEventsText: 'No hi ha esdeveniments per mostrar',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ca.global.min.js b/public/js/fullcalendar/packages/core/locales/ca.global.min.js
new file mode 100644
index 0000000..84932ef
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ca.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ca",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Següent",today:"Avui",year:"Any",month:"Mes",week:"Setmana",day:"Dia",list:"Agenda"},weekText:"Set",allDayText:"Tot el dia",moreLinkText:"més",noEventsText:"No hi ha esdeveniments per mostrar"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/cs.global.js b/public/js/fullcalendar/packages/core/locales/cs.global.js
new file mode 100644
index 0000000..367711e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/cs.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'cs',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Dříve',
17 next: 'Později',
18 today: 'Nyní',
19 year: 'Rok',
20 month: 'Měsíc',
21 week: 'Týden',
22 day: 'Den',
23 list: 'Agenda',
24 },
25 weekText: 'Týd',
26 allDayText: 'Celý den',
27 moreLinkText(n) {
28 return '+další: ' + n;
29 },
30 noEventsText: 'Žádné akce k zobrazení',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/cs.global.min.js b/public/js/fullcalendar/packages/core/locales/cs.global.min.js
new file mode 100644
index 0000000..5df71bc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/cs.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var n={code:"cs",week:{dow:1,doy:4},buttonText:{prev:"Dříve",next:"Později",today:"Nyní",year:"Rok",month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},weekText:"Týd",allDayText:"Celý den",moreLinkText:e=>"+další: "+e,noEventsText:"Žádné akce k zobrazení"};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/cy.global.js b/public/js/fullcalendar/packages/core/locales/cy.global.js
new file mode 100644
index 0000000..3ebb0e1
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/cy.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'cy',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Blaenorol',
17 next: 'Nesaf',
18 today: 'Heddiw',
19 year: 'Blwyddyn',
20 month: 'Mis',
21 week: 'Wythnos',
22 day: 'Dydd',
23 list: 'Rhestr',
24 },
25 weekText: 'Wythnos',
26 allDayText: 'Trwy\'r dydd',
27 moreLinkText: 'Mwy',
28 noEventsText: 'Dim digwyddiadau',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/cy.global.min.js b/public/js/fullcalendar/packages/core/locales/cy.global.min.js
new file mode 100644
index 0000000..75cea2a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/cy.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"cy",week:{dow:1,doy:4},buttonText:{prev:"Blaenorol",next:"Nesaf",today:"Heddiw",year:"Blwyddyn",month:"Mis",week:"Wythnos",day:"Dydd",list:"Rhestr"},weekText:"Wythnos",allDayText:"Trwy'r dydd",moreLinkText:"Mwy",noEventsText:"Dim digwyddiadau"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/da.global.js b/public/js/fullcalendar/packages/core/locales/da.global.js
new file mode 100644
index 0000000..d033e11
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/da.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'da',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Forrige',
17 next: 'Næste',
18 today: 'I dag',
19 year: 'År',
20 month: 'Måned',
21 week: 'Uge',
22 day: 'Dag',
23 list: 'Agenda',
24 },
25 weekText: 'Uge',
26 allDayText: 'Hele dagen',
27 moreLinkText: 'flere',
28 noEventsText: 'Ingen arrangementer at vise',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/da.global.min.js b/public/js/fullcalendar/packages/core/locales/da.global.min.js
new file mode 100644
index 0000000..28cd7cc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/da.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"da",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Næste",today:"I dag",year:"År",month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},weekText:"Uge",allDayText:"Hele dagen",moreLinkText:"flere",noEventsText:"Ingen arrangementer at vise"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/de-at.global.js b/public/js/fullcalendar/packages/core/locales/de-at.global.js
new file mode 100644
index 0000000..c01eeab
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/de-at.global.js
@@ -0,0 +1,69 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 function affix(buttonText) {
10 return (buttonText === 'Tag' || buttonText === 'Monat') ? 'r' :
11 buttonText === 'Jahr' ? 's' : '';
12 }
13 var locale = {
14 code: 'de-at',
15 week: {
16 dow: 1,
17 doy: 4, // The week that contains Jan 4th is the first week of the year.
18 },
19 buttonText: {
20 prev: 'Zurück',
21 next: 'Vor',
22 today: 'Heute',
23 year: 'Jahr',
24 month: 'Monat',
25 week: 'Woche',
26 day: 'Tag',
27 list: 'Terminübersicht',
28 },
29 weekText: 'KW',
30 weekTextLong: 'Woche',
31 allDayText: 'Ganztägig',
32 moreLinkText(n) {
33 return '+ weitere ' + n;
34 },
35 noEventsText: 'Keine Ereignisse anzuzeigen',
36 buttonHints: {
37 prev(buttonText) {
38 return `Vorherige${affix(buttonText)} ${buttonText}`;
39 },
40 next(buttonText) {
41 return `Nächste${affix(buttonText)} ${buttonText}`;
42 },
43 today(buttonText) {
44 // → Heute, Diese Woche, Dieser Monat, Dieses Jahr
45 if (buttonText === 'Tag') {
46 return 'Heute';
47 }
48 return `Diese${affix(buttonText)} ${buttonText}`;
49 },
50 },
51 viewHint(buttonText) {
52 // → Tagesansicht, Wochenansicht, Monatsansicht, Jahresansicht
53 const glue = buttonText === 'Woche' ? 'n' : buttonText === 'Monat' ? 's' : 'es';
54 return buttonText + glue + 'ansicht';
55 },
56 navLinkHint: 'Gehe zu $0',
57 moreLinkHint(eventCnt) {
58 return 'Zeige ' + (eventCnt === 1 ?
59 'ein weiteres Ereignis' :
60 eventCnt + ' weitere Ereignisse');
61 },
62 closeHint: 'Schließen',
63 timeHint: 'Uhrzeit',
64 eventHint: 'Ereignis',
65 };
66
67 index_js.globalLocales.push(locale);
68
69})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/de-at.global.min.js b/public/js/fullcalendar/packages/core/locales/de-at.global.min.js
new file mode 100644
index 0000000..2bccce2
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/de-at.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";function t(e){return"Tag"===e||"Monat"===e?"r":"Jahr"===e?"s":""}var n={code:"de-at",week:{dow:1,doy:4},buttonText:{prev:"Zurück",next:"Vor",today:"Heute",year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},weekText:"KW",weekTextLong:"Woche",allDayText:"Ganztägig",moreLinkText:e=>"+ weitere "+e,noEventsText:"Keine Ereignisse anzuzeigen",buttonHints:{prev:e=>`Vorherige${t(e)} ${e}`,next:e=>`Nächste${t(e)} ${e}`,today:e=>"Tag"===e?"Heute":`Diese${t(e)} ${e}`},viewHint:e=>e+("Woche"===e?"n":"Monat"===e?"s":"es")+"ansicht",navLinkHint:"Gehe zu $0",moreLinkHint:e=>"Zeige "+(1===e?"ein weiteres Ereignis":e+" weitere Ereignisse"),closeHint:"Schließen",timeHint:"Uhrzeit",eventHint:"Ereignis"};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/de.global.js b/public/js/fullcalendar/packages/core/locales/de.global.js
new file mode 100644
index 0000000..2b45fde
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/de.global.js
@@ -0,0 +1,69 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 function affix(buttonText) {
10 return (buttonText === 'Tag' || buttonText === 'Monat') ? 'r' :
11 buttonText === 'Jahr' ? 's' : '';
12 }
13 var locale = {
14 code: 'de',
15 week: {
16 dow: 1,
17 doy: 4, // The week that contains Jan 4th is the first week of the year.
18 },
19 buttonText: {
20 prev: 'Zurück',
21 next: 'Vor',
22 today: 'Heute',
23 year: 'Jahr',
24 month: 'Monat',
25 week: 'Woche',
26 day: 'Tag',
27 list: 'Terminübersicht',
28 },
29 weekText: 'KW',
30 weekTextLong: 'Woche',
31 allDayText: 'Ganztägig',
32 moreLinkText(n) {
33 return '+ weitere ' + n;
34 },
35 noEventsText: 'Keine Ereignisse anzuzeigen',
36 buttonHints: {
37 prev(buttonText) {
38 return `Vorherige${affix(buttonText)} ${buttonText}`;
39 },
40 next(buttonText) {
41 return `Nächste${affix(buttonText)} ${buttonText}`;
42 },
43 today(buttonText) {
44 // → Heute, Diese Woche, Dieser Monat, Dieses Jahr
45 if (buttonText === 'Tag') {
46 return 'Heute';
47 }
48 return `Diese${affix(buttonText)} ${buttonText}`;
49 },
50 },
51 viewHint(buttonText) {
52 // → Tagesansicht, Wochenansicht, Monatsansicht, Jahresansicht
53 const glue = buttonText === 'Woche' ? 'n' : buttonText === 'Monat' ? 's' : 'es';
54 return buttonText + glue + 'ansicht';
55 },
56 navLinkHint: 'Gehe zu $0',
57 moreLinkHint(eventCnt) {
58 return 'Zeige ' + (eventCnt === 1 ?
59 'ein weiteres Ereignis' :
60 eventCnt + ' weitere Ereignisse');
61 },
62 closeHint: 'Schließen',
63 timeHint: 'Uhrzeit',
64 eventHint: 'Ereignis',
65 };
66
67 index_js.globalLocales.push(locale);
68
69})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/de.global.min.js b/public/js/fullcalendar/packages/core/locales/de.global.min.js
new file mode 100644
index 0000000..57008c9
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/de.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";function t(e){return"Tag"===e||"Monat"===e?"r":"Jahr"===e?"s":""}var n={code:"de",week:{dow:1,doy:4},buttonText:{prev:"Zurück",next:"Vor",today:"Heute",year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},weekText:"KW",weekTextLong:"Woche",allDayText:"Ganztägig",moreLinkText:e=>"+ weitere "+e,noEventsText:"Keine Ereignisse anzuzeigen",buttonHints:{prev:e=>`Vorherige${t(e)} ${e}`,next:e=>`Nächste${t(e)} ${e}`,today:e=>"Tag"===e?"Heute":`Diese${t(e)} ${e}`},viewHint:e=>e+("Woche"===e?"n":"Monat"===e?"s":"es")+"ansicht",navLinkHint:"Gehe zu $0",moreLinkHint:e=>"Zeige "+(1===e?"ein weiteres Ereignis":e+" weitere Ereignisse"),closeHint:"Schließen",timeHint:"Uhrzeit",eventHint:"Ereignis"};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/el.global.js b/public/js/fullcalendar/packages/core/locales/el.global.js
new file mode 100644
index 0000000..1907aa2
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/el.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'el',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Προηγούμενος',
17 next: 'Επόμενος',
18 today: 'Σήμερα',
19 year: 'Ετος',
20 month: 'Μήνας',
21 week: 'Εβδομάδα',
22 day: 'Ημέρα',
23 list: 'Ατζέντα',
24 },
25 weekText: 'Εβδ',
26 allDayText: 'Ολοήμερο',
27 moreLinkText: 'περισσότερα',
28 noEventsText: 'Δεν υπάρχουν γεγονότα προς εμφάνιση',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/el.global.min.js b/public/js/fullcalendar/packages/core/locales/el.global.min.js
new file mode 100644
index 0000000..7b99513
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/el.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"el",week:{dow:1,doy:4},buttonText:{prev:"Προηγούμενος",next:"Επόμενος",today:"Σήμερα",year:"Ετος",month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},weekText:"Εβδ",allDayText:"Ολοήμερο",moreLinkText:"περισσότερα",noEventsText:"Δεν υπάρχουν γεγονότα προς εμφάνιση"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/en-au.global.js b/public/js/fullcalendar/packages/core/locales/en-au.global.js
new file mode 100644
index 0000000..3f4c00a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-au.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'en-au',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonHints: {
16 prev: 'Previous $0',
17 next: 'Next $0',
18 today: 'This $0',
19 },
20 viewHint: '$0 view',
21 navLinkHint: 'Go to $0',
22 moreLinkHint(eventCnt) {
23 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
24 },
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/en-au.global.min.js b/public/js/fullcalendar/packages/core/locales/en-au.global.min.js
new file mode 100644
index 0000000..46ff188
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-au.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var n={code:"en-au",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/en-gb.global.js b/public/js/fullcalendar/packages/core/locales/en-gb.global.js
new file mode 100644
index 0000000..b824123
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-gb.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'en-gb',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonHints: {
16 prev: 'Previous $0',
17 next: 'Next $0',
18 today: 'This $0',
19 },
20 viewHint: '$0 view',
21 navLinkHint: 'Go to $0',
22 moreLinkHint(eventCnt) {
23 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
24 },
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/en-gb.global.min.js b/public/js/fullcalendar/packages/core/locales/en-gb.global.min.js
new file mode 100644
index 0000000..63f7dc2
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-gb.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var n={code:"en-gb",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/en-nz.global.js b/public/js/fullcalendar/packages/core/locales/en-nz.global.js
new file mode 100644
index 0000000..8ad907d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-nz.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'en-nz',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonHints: {
16 prev: 'Previous $0',
17 next: 'Next $0',
18 today: 'This $0',
19 },
20 viewHint: '$0 view',
21 navLinkHint: 'Go to $0',
22 moreLinkHint(eventCnt) {
23 return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
24 },
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/en-nz.global.min.js b/public/js/fullcalendar/packages/core/locales/en-nz.global.min.js
new file mode 100644
index 0000000..ef59c0b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/en-nz.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var n={code:"en-nz",week:{dow:1,doy:4},buttonHints:{prev:"Previous $0",next:"Next $0",today:"This $0"},viewHint:"$0 view",navLinkHint:"Go to $0",moreLinkHint:e=>`Show ${e} more event${1===e?"":"s"}`};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/eo.global.js b/public/js/fullcalendar/packages/core/locales/eo.global.js
new file mode 100644
index 0000000..64cbe55
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/eo.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'eo',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Antaŭa',
17 next: 'Sekva',
18 today: 'Hodiaŭ',
19 year: 'Jaro',
20 month: 'Monato',
21 week: 'Semajno',
22 day: 'Tago',
23 list: 'Tagordo',
24 },
25 weekText: 'Sm',
26 allDayText: 'Tuta tago',
27 moreLinkText: 'pli',
28 noEventsText: 'Neniuj eventoj por montri',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/eo.global.min.js b/public/js/fullcalendar/packages/core/locales/eo.global.min.js
new file mode 100644
index 0000000..fcca6a2
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/eo.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"eo",week:{dow:1,doy:4},buttonText:{prev:"Antaŭa",next:"Sekva",today:"Hodiaŭ",year:"Jaro",month:"Monato",week:"Semajno",day:"Tago",list:"Tagordo"},weekText:"Sm",allDayText:"Tuta tago",moreLinkText:"pli",noEventsText:"Neniuj eventoj por montri"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/es-us.global.js b/public/js/fullcalendar/packages/core/locales/es-us.global.js
new file mode 100644
index 0000000..3760b56
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/es-us.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'es',
11 week: {
12 dow: 0,
13 doy: 6, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Ant',
17 next: 'Sig',
18 today: 'Hoy',
19 year: 'Año',
20 month: 'Mes',
21 week: 'Semana',
22 day: 'Día',
23 list: 'Agenda',
24 },
25 weekText: 'Sm',
26 allDayText: 'Todo el día',
27 moreLinkText: 'más',
28 noEventsText: 'No hay eventos para mostrar',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/es-us.global.min.js b/public/js/fullcalendar/packages/core/locales/es-us.global.min.js
new file mode 100644
index 0000000..6c95615
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/es-us.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"es",week:{dow:0,doy:6},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",year:"Año",month:"Mes",week:"Semana",day:"Día",list:"Agenda"},weekText:"Sm",allDayText:"Todo el día",moreLinkText:"más",noEventsText:"No hay eventos para mostrar"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/es.global.js b/public/js/fullcalendar/packages/core/locales/es.global.js
new file mode 100644
index 0000000..29e03f1
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/es.global.js
@@ -0,0 +1,52 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'es',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Ant',
17 next: 'Sig',
18 today: 'Hoy',
19 year: 'Año',
20 month: 'Mes',
21 week: 'Semana',
22 day: 'Día',
23 list: 'Agenda',
24 },
25 buttonHints: {
26 prev: '$0 antes',
27 next: '$0 siguiente',
28 today(buttonText) {
29 return (buttonText === 'Día') ? 'Hoy' :
30 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
31 },
32 },
33 viewHint(buttonText) {
34 return 'Vista ' + (buttonText === 'Semana' ? 'de la' : 'del') + ' ' + buttonText.toLocaleLowerCase();
35 },
36 weekText: 'Sm',
37 weekTextLong: 'Semana',
38 allDayText: 'Todo el día',
39 moreLinkText: 'más',
40 moreLinkHint(eventCnt) {
41 return `Mostrar ${eventCnt} eventos más`;
42 },
43 noEventsText: 'No hay eventos para mostrar',
44 navLinkHint: 'Ir al $0',
45 closeHint: 'Cerrar',
46 timeHint: 'La hora',
47 eventHint: 'Evento',
48 };
49
50 index_js.globalLocales.push(locale);
51
52})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/es.global.min.js b/public/js/fullcalendar/packages/core/locales/es.global.min.js
new file mode 100644
index 0000000..d5f0b31
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/es.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"es",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Sig",today:"Hoy",year:"Año",month:"Mes",week:"Semana",day:"Día",list:"Agenda"},buttonHints:{prev:"$0 antes",next:"$0 siguiente",today:e=>"Día"===e?"Hoy":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Vista "+("Semana"===e?"de la":"del")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"Todo el día",moreLinkText:"más",moreLinkHint:e=>`Mostrar ${e} eventos más`,noEventsText:"No hay eventos para mostrar",navLinkHint:"Ir al $0",closeHint:"Cerrar",timeHint:"La hora",eventHint:"Evento"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/et.global.js b/public/js/fullcalendar/packages/core/locales/et.global.js
new file mode 100644
index 0000000..d964bf3
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/et.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'et',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Eelnev',
17 next: 'Järgnev',
18 today: 'Täna',
19 year: 'Aasta',
20 month: 'Kuu',
21 week: 'Nädal',
22 day: 'Päev',
23 list: 'Päevakord',
24 },
25 weekText: 'näd',
26 allDayText: 'Kogu päev',
27 moreLinkText(n) {
28 return '+ veel ' + n;
29 },
30 noEventsText: 'Kuvamiseks puuduvad sündmused',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/et.global.min.js b/public/js/fullcalendar/packages/core/locales/et.global.min.js
new file mode 100644
index 0000000..43ce9db
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/et.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"et",week:{dow:1,doy:4},buttonText:{prev:"Eelnev",next:"Järgnev",today:"Täna",year:"Aasta",month:"Kuu",week:"Nädal",day:"Päev",list:"Päevakord"},weekText:"näd",allDayText:"Kogu päev",moreLinkText:e=>"+ veel "+e,noEventsText:"Kuvamiseks puuduvad sündmused"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/eu.global.js b/public/js/fullcalendar/packages/core/locales/eu.global.js
new file mode 100644
index 0000000..5084791
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/eu.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'eu',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Aur',
17 next: 'Hur',
18 today: 'Gaur',
19 year: 'Urtea',
20 month: 'Hilabetea',
21 week: 'Astea',
22 day: 'Eguna',
23 list: 'Agenda',
24 },
25 weekText: 'As',
26 allDayText: 'Egun osoa',
27 moreLinkText: 'gehiago',
28 noEventsText: 'Ez dago ekitaldirik erakusteko',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/eu.global.min.js b/public/js/fullcalendar/packages/core/locales/eu.global.min.js
new file mode 100644
index 0000000..b3bcd30
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/eu.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"eu",week:{dow:1,doy:7},buttonText:{prev:"Aur",next:"Hur",today:"Gaur",year:"Urtea",month:"Hilabetea",week:"Astea",day:"Eguna",list:"Agenda"},weekText:"As",allDayText:"Egun osoa",moreLinkText:"gehiago",noEventsText:"Ez dago ekitaldirik erakusteko"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/fa.global.js b/public/js/fullcalendar/packages/core/locales/fa.global.js
new file mode 100644
index 0000000..ca54ee3
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fa.global.js
@@ -0,0 +1,36 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'fa',
11 week: {
12 dow: 6,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'قبلی',
18 next: 'بعدی',
19 today: 'امروز',
20 year: 'سال',
21 month: 'ماه',
22 week: 'هفته',
23 day: 'روز',
24 list: 'برنامه',
25 },
26 weekText: 'هف',
27 allDayText: 'تمام روز',
28 moreLinkText(n) {
29 return 'بیش از ' + n;
30 },
31 noEventsText: 'هیچ رویدادی به نمایش',
32 };
33
34 index_js.globalLocales.push(locale);
35
36})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/fa.global.min.js b/public/js/fullcalendar/packages/core/locales/fa.global.min.js
new file mode 100644
index 0000000..b3d6019
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fa.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"fa",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"قبلی",next:"بعدی",today:"امروز",year:"سال",month:"ماه",week:"هفته",day:"روز",list:"برنامه"},weekText:"هف",allDayText:"تمام روز",moreLinkText:e=>"بیش از "+e,noEventsText:"هیچ رویدادی به نمایش"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/fi.global.js b/public/js/fullcalendar/packages/core/locales/fi.global.js
new file mode 100644
index 0000000..fae57ac
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fi.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'fi',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Edellinen',
17 next: 'Seuraava',
18 today: 'Tänään',
19 year: 'Vuosi',
20 month: 'Kuukausi',
21 week: 'Viikko',
22 day: 'Päivä',
23 list: 'Tapahtumat',
24 },
25 weekText: 'Vk',
26 allDayText: 'Koko päivä',
27 moreLinkText: 'lisää',
28 noEventsText: 'Ei näytettäviä tapahtumia',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/fi.global.min.js b/public/js/fullcalendar/packages/core/locales/fi.global.min.js
new file mode 100644
index 0000000..2b0bacc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fi.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"fi",week:{dow:1,doy:4},buttonText:{prev:"Edellinen",next:"Seuraava",today:"Tänään",year:"Vuosi",month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},weekText:"Vk",allDayText:"Koko päivä",moreLinkText:"lisää",noEventsText:"Ei näytettäviä tapahtumia"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/fr-ca.global.js b/public/js/fullcalendar/packages/core/locales/fr-ca.global.js
new file mode 100644
index 0000000..92f4bc4
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr-ca.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'fr',
11 buttonText: {
12 prev: 'Précédent',
13 next: 'Suivant',
14 today: 'Aujourd\'hui',
15 year: 'Année',
16 month: 'Mois',
17 week: 'Semaine',
18 day: 'Jour',
19 list: 'Mon planning',
20 },
21 weekText: 'Sem.',
22 allDayText: 'Toute la journée',
23 moreLinkText: 'en plus',
24 noEventsText: 'Aucun évènement à afficher',
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/fr-ca.global.min.js b/public/js/fullcalendar/packages/core/locales/fr-ca.global.min.js
new file mode 100644
index 0000000..339ce95
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr-ca.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"fr",buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekText:"Sem.",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/fr-ch.global.js b/public/js/fullcalendar/packages/core/locales/fr-ch.global.js
new file mode 100644
index 0000000..b5986b9
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr-ch.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'fr-ch',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Précédent',
17 next: 'Suivant',
18 today: 'Courant',
19 year: 'Année',
20 month: 'Mois',
21 week: 'Semaine',
22 day: 'Jour',
23 list: 'Mon planning',
24 },
25 weekText: 'Sm',
26 allDayText: 'Toute la journée',
27 moreLinkText: 'en plus',
28 noEventsText: 'Aucun évènement à afficher',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/fr-ch.global.min.js b/public/js/fullcalendar/packages/core/locales/fr-ch.global.min.js
new file mode 100644
index 0000000..de265b6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr-ch.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"fr-ch",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Courant",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},weekText:"Sm",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/fr.global.js b/public/js/fullcalendar/packages/core/locales/fr.global.js
new file mode 100644
index 0000000..0f6a712
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'fr',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Précédent',
17 next: 'Suivant',
18 today: 'Aujourd\'hui',
19 year: 'Année',
20 month: 'Mois',
21 week: 'Semaine',
22 day: 'Jour',
23 list: 'Planning',
24 },
25 weekText: 'Sem.',
26 weekTextLong: 'Semaine',
27 allDayText: 'Toute la journée',
28 moreLinkText: 'en plus',
29 noEventsText: 'Aucun évènement à afficher',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/fr.global.min.js b/public/js/fullcalendar/packages/core/locales/fr.global.min.js
new file mode 100644
index 0000000..7f0886c
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/fr.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"fr",week:{dow:1,doy:4},buttonText:{prev:"Précédent",next:"Suivant",today:"Aujourd'hui",year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Planning"},weekText:"Sem.",weekTextLong:"Semaine",allDayText:"Toute la journée",moreLinkText:"en plus",noEventsText:"Aucun évènement à afficher"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/gl.global.js b/public/js/fullcalendar/packages/core/locales/gl.global.js
new file mode 100644
index 0000000..cc297f4
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/gl.global.js
@@ -0,0 +1,52 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'gl',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Ant',
17 next: 'Seg',
18 today: 'Hoxe',
19 year: 'Ano',
20 month: 'Mes',
21 week: 'Semana',
22 day: 'Día',
23 list: 'Axenda',
24 },
25 buttonHints: {
26 prev: '$0 antes',
27 next: '$0 seguinte',
28 today(buttonText) {
29 return (buttonText === 'Día') ? 'Hoxe' :
30 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
31 },
32 },
33 viewHint(buttonText) {
34 return 'Vista ' + (buttonText === 'Semana' ? 'da' : 'do') + ' ' + buttonText.toLocaleLowerCase();
35 },
36 weekText: 'Sm',
37 weekTextLong: 'Semana',
38 allDayText: 'Todo o día',
39 moreLinkText: 'máis',
40 moreLinkHint(eventCnt) {
41 return `Amosar ${eventCnt} eventos máis`;
42 },
43 noEventsText: 'Non hai eventos para amosar',
44 navLinkHint: 'Ir ao $0',
45 closeHint: 'Pechar',
46 timeHint: 'A hora',
47 eventHint: 'Evento',
48 };
49
50 index_js.globalLocales.push(locale);
51
52})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/gl.global.min.js b/public/js/fullcalendar/packages/core/locales/gl.global.min.js
new file mode 100644
index 0000000..0464163
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/gl.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"gl",week:{dow:1,doy:4},buttonText:{prev:"Ant",next:"Seg",today:"Hoxe",year:"Ano",month:"Mes",week:"Semana",day:"Día",list:"Axenda"},buttonHints:{prev:"$0 antes",next:"$0 seguinte",today:e=>"Día"===e?"Hoxe":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Vista "+("Semana"===e?"da":"do")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"Todo o día",moreLinkText:"máis",moreLinkHint:e=>`Amosar ${e} eventos máis`,noEventsText:"Non hai eventos para amosar",navLinkHint:"Ir ao $0",closeHint:"Pechar",timeHint:"A hora",eventHint:"Evento"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/he.global.js b/public/js/fullcalendar/packages/core/locales/he.global.js
new file mode 100644
index 0000000..a48d134
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/he.global.js
@@ -0,0 +1,30 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'he',
11 direction: 'rtl',
12 buttonText: {
13 prev: 'הקודם',
14 next: 'הבא',
15 today: 'היום',
16 year: 'שנה',
17 month: 'חודש',
18 week: 'שבוע',
19 day: 'יום',
20 list: 'סדר יום',
21 },
22 allDayText: 'כל היום',
23 moreLinkText: 'נוספים',
24 noEventsText: 'אין אירועים להצגה',
25 weekText: 'שבוע',
26 };
27
28 index_js.globalLocales.push(locale);
29
30})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/he.global.min.js b/public/js/fullcalendar/packages/core/locales/he.global.min.js
new file mode 100644
index 0000000..459495b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/he.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"he",direction:"rtl",buttonText:{prev:"הקודם",next:"הבא",today:"היום",year:"שנה",month:"חודש",week:"שבוע",day:"יום",list:"סדר יום"},allDayText:"כל היום",moreLinkText:"נוספים",noEventsText:"אין אירועים להצגה",weekText:"שבוע"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/hi.global.js b/public/js/fullcalendar/packages/core/locales/hi.global.js
new file mode 100644
index 0000000..190515d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hi.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'hi',
11 week: {
12 dow: 0,
13 doy: 6, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'पिछला',
17 next: 'अगला',
18 today: 'आज',
19 year: 'वर्ष',
20 month: 'महीना',
21 week: 'सप्ताह',
22 day: 'दिन',
23 list: 'कार्यसूची',
24 },
25 weekText: 'हफ्ता',
26 allDayText: 'सभी दिन',
27 moreLinkText(n) {
28 return '+अधिक ' + n;
29 },
30 noEventsText: 'कोई घटनाओं को प्रदर्शित करने के लिए',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/hi.global.min.js b/public/js/fullcalendar/packages/core/locales/hi.global.min.js
new file mode 100644
index 0000000..cc115b0
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hi.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"hi",week:{dow:0,doy:6},buttonText:{prev:"पिछला",next:"अगला",today:"आज",year:"वर्ष",month:"महीना",week:"सप्ताह",day:"दिन",list:"कार्यसूची"},weekText:"हफ्ता",allDayText:"सभी दिन",moreLinkText:e=>"+अधिक "+e,noEventsText:"कोई घटनाओं को प्रदर्शित करने के लिए"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/hr.global.js b/public/js/fullcalendar/packages/core/locales/hr.global.js
new file mode 100644
index 0000000..4423c16
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hr.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'hr',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Prijašnji',
17 next: 'Sljedeći',
18 today: 'Danas',
19 year: 'Godina',
20 month: 'Mjesec',
21 week: 'Tjedan',
22 day: 'Dan',
23 list: 'Raspored',
24 },
25 weekText: 'Tje',
26 allDayText: 'Cijeli dan',
27 moreLinkText(n) {
28 return '+ još ' + n;
29 },
30 noEventsText: 'Nema događaja za prikaz',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/hr.global.min.js b/public/js/fullcalendar/packages/core/locales/hr.global.min.js
new file mode 100644
index 0000000..05e1388
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hr.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"hr",week:{dow:1,doy:7},buttonText:{prev:"Prijašnji",next:"Sljedeći",today:"Danas",year:"Godina",month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},weekText:"Tje",allDayText:"Cijeli dan",moreLinkText:e=>"+ još "+e,noEventsText:"Nema događaja za prikaz"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/hu.global.js b/public/js/fullcalendar/packages/core/locales/hu.global.js
new file mode 100644
index 0000000..89d48e6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hu.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'hu',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'vissza',
17 next: 'előre',
18 today: 'ma',
19 year: 'Év',
20 month: 'Hónap',
21 week: 'Hét',
22 day: 'Nap',
23 list: 'Lista',
24 },
25 weekText: 'Hét',
26 allDayText: 'Egész nap',
27 moreLinkText: 'további',
28 noEventsText: 'Nincs megjeleníthető esemény',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/hu.global.min.js b/public/js/fullcalendar/packages/core/locales/hu.global.min.js
new file mode 100644
index 0000000..d769d24
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hu.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"hu",week:{dow:1,doy:4},buttonText:{prev:"vissza",next:"előre",today:"ma",year:"Év",month:"Hónap",week:"Hét",day:"Nap",list:"Lista"},weekText:"Hét",allDayText:"Egész nap",moreLinkText:"további",noEventsText:"Nincs megjeleníthető esemény"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/hy-am.global.js b/public/js/fullcalendar/packages/core/locales/hy-am.global.js
new file mode 100644
index 0000000..528fef8
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hy-am.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'hy-am',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Նախորդ',
17 next: 'Հաջորդ',
18 today: 'Այսօր',
19 year: 'Տարի',
20 month: 'Ամիս',
21 week: 'Շաբաթ',
22 day: 'Օր',
23 list: 'Օրվա ցուցակ',
24 },
25 weekText: 'Շաբ',
26 allDayText: 'Ամբողջ օր',
27 moreLinkText(n) {
28 return '+ ևս ' + n;
29 },
30 noEventsText: 'Բացակայում է իրադարձությունը ցուցադրելու',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/hy-am.global.min.js b/public/js/fullcalendar/packages/core/locales/hy-am.global.min.js
new file mode 100644
index 0000000..3a3e4dc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/hy-am.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"hy-am",week:{dow:1,doy:4},buttonText:{prev:"Նախորդ",next:"Հաջորդ",today:"Այսօր",year:"Տարի",month:"Ամիս",week:"Շաբաթ",day:"Օր",list:"Օրվա ցուցակ"},weekText:"Շաբ",allDayText:"Ամբողջ օր",moreLinkText:e=>"+ ևս "+e,noEventsText:"Բացակայում է իրադարձությունը ցուցադրելու"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/id.global.js b/public/js/fullcalendar/packages/core/locales/id.global.js
new file mode 100644
index 0000000..5371826
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/id.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'id',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'mundur',
17 next: 'maju',
18 today: 'hari ini',
19 year: 'Tahun',
20 month: 'Bulan',
21 week: 'Minggu',
22 day: 'Hari',
23 list: 'Agenda',
24 },
25 weekText: 'Mg',
26 allDayText: 'Sehari penuh',
27 moreLinkText: 'lebih',
28 noEventsText: 'Tidak ada acara untuk ditampilkan',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/id.global.min.js b/public/js/fullcalendar/packages/core/locales/id.global.min.js
new file mode 100644
index 0000000..db80508
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/id.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(a){"use strict";FullCalendar.globalLocales.push({code:"id",week:{dow:1,doy:7},buttonText:{prev:"mundur",next:"maju",today:"hari ini",year:"Tahun",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekText:"Mg",allDayText:"Sehari penuh",moreLinkText:"lebih",noEventsText:"Tidak ada acara untuk ditampilkan"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/is.global.js b/public/js/fullcalendar/packages/core/locales/is.global.js
new file mode 100644
index 0000000..94387ff
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/is.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'is',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Fyrri',
17 next: 'Næsti',
18 today: 'Í dag',
19 year: 'Ár',
20 month: 'Mánuður',
21 week: 'Vika',
22 day: 'Dagur',
23 list: 'Dagskrá',
24 },
25 weekText: 'Vika',
26 allDayText: 'Allan daginn',
27 moreLinkText: 'meira',
28 noEventsText: 'Engir viðburðir til að sýna',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/is.global.min.js b/public/js/fullcalendar/packages/core/locales/is.global.min.js
new file mode 100644
index 0000000..b9e0b5d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/is.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"is",week:{dow:1,doy:4},buttonText:{prev:"Fyrri",next:"Næsti",today:"Í dag",year:"Ár",month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},weekText:"Vika",allDayText:"Allan daginn",moreLinkText:"meira",noEventsText:"Engir viðburðir til að sýna"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/it.global.js b/public/js/fullcalendar/packages/core/locales/it.global.js
new file mode 100644
index 0000000..aead14e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/it.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'it',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Prec',
17 next: 'Succ',
18 today: 'Oggi',
19 year: 'Anno',
20 month: 'Mese',
21 week: 'Settimana',
22 day: 'Giorno',
23 list: 'Agenda',
24 },
25 weekText: 'Sm',
26 allDayText: 'Tutto il giorno',
27 moreLinkText(n) {
28 return '+altri ' + n;
29 },
30 noEventsText: 'Non ci sono eventi da visualizzare',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/it.global.min.js b/public/js/fullcalendar/packages/core/locales/it.global.min.js
new file mode 100644
index 0000000..c5e4f8a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/it.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"it",week:{dow:1,doy:4},buttonText:{prev:"Prec",next:"Succ",today:"Oggi",year:"Anno",month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},weekText:"Sm",allDayText:"Tutto il giorno",moreLinkText:e=>"+altri "+e,noEventsText:"Non ci sono eventi da visualizzare"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ja.global.js b/public/js/fullcalendar/packages/core/locales/ja.global.js
new file mode 100644
index 0000000..9e2e7a6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ja.global.js
@@ -0,0 +1,31 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ja',
11 buttonText: {
12 prev: '前',
13 next: '次',
14 today: '今日',
15 year: '年',
16 month: '月',
17 week: '週',
18 day: '日',
19 list: '予定リスト',
20 },
21 weekText: '週',
22 allDayText: '終日',
23 moreLinkText(n) {
24 return '他 ' + n + ' 件';
25 },
26 noEventsText: '表示する予定はありません',
27 };
28
29 index_js.globalLocales.push(locale);
30
31})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ja.global.min.js b/public/js/fullcalendar/packages/core/locales/ja.global.min.js
new file mode 100644
index 0000000..b03bc39
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ja.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"ja",buttonText:{prev:"前",next:"次",today:"今日",year:"年",month:"月",week:"週",day:"日",list:"予定リスト"},weekText:"週",allDayText:"終日",moreLinkText:e=>"他 "+e+" 件",noEventsText:"表示する予定はありません"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ka.global.js b/public/js/fullcalendar/packages/core/locales/ka.global.js
new file mode 100644
index 0000000..ee54efb
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ka.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ka',
11 week: {
12 dow: 1,
13 doy: 7,
14 },
15 buttonText: {
16 prev: 'წინა',
17 next: 'შემდეგი',
18 today: 'დღეს',
19 year: 'წელიწადი',
20 month: 'თვე',
21 week: 'კვირა',
22 day: 'დღე',
23 list: 'დღის წესრიგი',
24 },
25 weekText: 'კვ',
26 allDayText: 'მთელი დღე',
27 moreLinkText(n) {
28 return '+ კიდევ ' + n;
29 },
30 noEventsText: 'ღონისძიებები არ არის',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ka.global.min.js b/public/js/fullcalendar/packages/core/locales/ka.global.min.js
new file mode 100644
index 0000000..01e3e82
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ka.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"ka",week:{dow:1,doy:7},buttonText:{prev:"წინა",next:"შემდეგი",today:"დღეს",year:"წელიწადი",month:"თვე",week:"კვირა",day:"დღე",list:"დღის წესრიგი"},weekText:"კვ",allDayText:"მთელი დღე",moreLinkText:e=>"+ კიდევ "+e,noEventsText:"ღონისძიებები არ არის"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/kk.global.js b/public/js/fullcalendar/packages/core/locales/kk.global.js
new file mode 100644
index 0000000..da17bf7
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/kk.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'kk',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Алдыңғы',
17 next: 'Келесі',
18 today: 'Бүгін',
19 year: 'Жыл',
20 month: 'Ай',
21 week: 'Апта',
22 day: 'Күн',
23 list: 'Күн тәртібі',
24 },
25 weekText: 'Не',
26 allDayText: 'Күні бойы',
27 moreLinkText(n) {
28 return '+ тағы ' + n;
29 },
30 noEventsText: 'Көрсету үшін оқиғалар жоқ',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/kk.global.min.js b/public/js/fullcalendar/packages/core/locales/kk.global.min.js
new file mode 100644
index 0000000..bdb4cad
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/kk.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"kk",week:{dow:1,doy:7},buttonText:{prev:"Алдыңғы",next:"Келесі",today:"Бүгін",year:"Жыл",month:"Ай",week:"Апта",day:"Күн",list:"Күн тәртібі"},weekText:"Не",allDayText:"Күні бойы",moreLinkText:e=>"+ тағы "+e,noEventsText:"Көрсету үшін оқиғалар жоқ"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/km.global.js b/public/js/fullcalendar/packages/core/locales/km.global.js
new file mode 100644
index 0000000..6aea51d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/km.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'km',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'មុន',
17 next: 'បន្ទាប់',
18 today: 'ថ្ងៃនេះ',
19 year: 'ឆ្នាំ',
20 month: 'ខែ',
21 week: 'សប្តាហ៍',
22 day: 'ថ្ងៃ',
23 list: 'បញ្ជី',
24 },
25 weekText: 'សប្តាហ៍',
26 allDayText: 'ពេញមួយថ្ងៃ',
27 moreLinkText: 'ច្រើនទៀត',
28 noEventsText: 'គ្មានព្រឹត្តិការណ៍ត្រូវបង្ហាញ',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/km.global.min.js b/public/js/fullcalendar/packages/core/locales/km.global.min.js
new file mode 100644
index 0000000..72bbd9d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/km.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"km",week:{dow:1,doy:4},buttonText:{prev:"មុន",next:"បន្ទាប់",today:"ថ្ងៃនេះ",year:"ឆ្នាំ",month:"ខែ",week:"សប្តាហ៍",day:"ថ្ងៃ",list:"បញ្ជី"},weekText:"សប្តាហ៍",allDayText:"ពេញមួយថ្ងៃ",moreLinkText:"ច្រើនទៀត",noEventsText:"គ្មានព្រឹត្តិការណ៍ត្រូវបង្ហាញ"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ko.global.js b/public/js/fullcalendar/packages/core/locales/ko.global.js
new file mode 100644
index 0000000..2879070
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ko.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ko',
11 buttonText: {
12 prev: '이전달',
13 next: '다음달',
14 today: '오늘',
15 year: '년도',
16 month: '월',
17 week: '주',
18 day: '일',
19 list: '일정목록',
20 },
21 weekText: '주',
22 allDayText: '종일',
23 moreLinkText: '개',
24 noEventsText: '일정이 없습니다',
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ko.global.min.js b/public/js/fullcalendar/packages/core/locales/ko.global.min.js
new file mode 100644
index 0000000..295e5fe
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ko.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ko",buttonText:{prev:"이전달",next:"다음달",today:"오늘",year:"년도",month:"월",week:"주",day:"일",list:"일정목록"},weekText:"주",allDayText:"종일",moreLinkText:"개",noEventsText:"일정이 없습니다"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ku.global.js b/public/js/fullcalendar/packages/core/locales/ku.global.js
new file mode 100644
index 0000000..69bcd62
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ku.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ku',
11 week: {
12 dow: 6,
13 doy: 12, // The week that contains Jan 1st is the first week of the year.
14 },
15 direction: 'rtl',
16 buttonText: {
17 prev: 'پێشتر',
18 next: 'دواتر',
19 today: 'ئەمڕو',
20 year: 'ساڵ',
21 month: 'مانگ',
22 week: 'هەفتە',
23 day: 'ڕۆژ',
24 list: 'بەرنامە',
25 },
26 weekText: 'هەفتە',
27 allDayText: 'هەموو ڕۆژەکە',
28 moreLinkText: 'زیاتر',
29 noEventsText: 'هیچ ڕووداوێك نیە',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ku.global.min.js b/public/js/fullcalendar/packages/core/locales/ku.global.min.js
new file mode 100644
index 0000000..2437d34
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ku.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ku",week:{dow:6,doy:12},direction:"rtl",buttonText:{prev:"پێشتر",next:"دواتر",today:"ئەمڕو",year:"ساڵ",month:"مانگ",week:"هەفتە",day:"ڕۆژ",list:"بەرنامە"},weekText:"هەفتە",allDayText:"هەموو ڕۆژەکە",moreLinkText:"زیاتر",noEventsText:"هیچ ڕووداوێك نیە"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/lb.global.js b/public/js/fullcalendar/packages/core/locales/lb.global.js
new file mode 100644
index 0000000..6df58ae
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lb.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'lb',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Zréck',
17 next: 'Weider',
18 today: 'Haut',
19 year: 'Joer',
20 month: 'Mount',
21 week: 'Woch',
22 day: 'Dag',
23 list: 'Terminiwwersiicht',
24 },
25 weekText: 'W',
26 allDayText: 'Ganzen Dag',
27 moreLinkText: 'méi',
28 noEventsText: 'Nee Evenementer ze affichéieren',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/lb.global.min.js b/public/js/fullcalendar/packages/core/locales/lb.global.min.js
new file mode 100644
index 0000000..7c9d383
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lb.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"lb",week:{dow:1,doy:4},buttonText:{prev:"Zréck",next:"Weider",today:"Haut",year:"Joer",month:"Mount",week:"Woch",day:"Dag",list:"Terminiwwersiicht"},weekText:"W",allDayText:"Ganzen Dag",moreLinkText:"méi",noEventsText:"Nee Evenementer ze affichéieren"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/lt.global.js b/public/js/fullcalendar/packages/core/locales/lt.global.js
new file mode 100644
index 0000000..c91c0ef
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lt.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'lt',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Atgal',
17 next: 'Pirmyn',
18 today: 'Šiandien',
19 year: 'Metai',
20 month: 'Mėnuo',
21 week: 'Savaitė',
22 day: 'Diena',
23 list: 'Darbotvarkė',
24 },
25 weekText: 'SAV',
26 allDayText: 'Visą dieną',
27 moreLinkText: 'daugiau',
28 noEventsText: 'Nėra įvykių rodyti',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/lt.global.min.js b/public/js/fullcalendar/packages/core/locales/lt.global.min.js
new file mode 100644
index 0000000..6f77a76
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lt.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"lt",week:{dow:1,doy:4},buttonText:{prev:"Atgal",next:"Pirmyn",today:"Šiandien",year:"Metai",month:"Mėnuo",week:"Savaitė",day:"Diena",list:"Darbotvarkė"},weekText:"SAV",allDayText:"Visą dieną",moreLinkText:"daugiau",noEventsText:"Nėra įvykių rodyti"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/lv.global.js b/public/js/fullcalendar/packages/core/locales/lv.global.js
new file mode 100644
index 0000000..4ec201a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lv.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'lv',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Iepr.',
17 next: 'Nāk.',
18 today: 'Šodien',
19 year: 'Gads',
20 month: 'Mēnesis',
21 week: 'Nedēļa',
22 day: 'Diena',
23 list: 'Dienas kārtība',
24 },
25 weekText: 'Ned.',
26 allDayText: 'Visu dienu',
27 moreLinkText(n) {
28 return '+vēl ' + n;
29 },
30 noEventsText: 'Nav notikumu',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/lv.global.min.js b/public/js/fullcalendar/packages/core/locales/lv.global.min.js
new file mode 100644
index 0000000..3b93150
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/lv.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"lv",week:{dow:1,doy:4},buttonText:{prev:"Iepr.",next:"Nāk.",today:"Šodien",year:"Gads",month:"Mēnesis",week:"Nedēļa",day:"Diena",list:"Dienas kārtība"},weekText:"Ned.",allDayText:"Visu dienu",moreLinkText:e=>"+vēl "+e,noEventsText:"Nav notikumu"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/mk.global.js b/public/js/fullcalendar/packages/core/locales/mk.global.js
new file mode 100644
index 0000000..1422017
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/mk.global.js
@@ -0,0 +1,31 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'mk',
11 buttonText: {
12 prev: 'претходно',
13 next: 'следно',
14 today: 'Денес',
15 year: 'година',
16 month: 'Месец',
17 week: 'Недела',
18 day: 'Ден',
19 list: 'График',
20 },
21 weekText: 'Сед',
22 allDayText: 'Цел ден',
23 moreLinkText(n) {
24 return '+повеќе ' + n;
25 },
26 noEventsText: 'Нема настани за прикажување',
27 };
28
29 index_js.globalLocales.push(locale);
30
31})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/mk.global.min.js b/public/js/fullcalendar/packages/core/locales/mk.global.min.js
new file mode 100644
index 0000000..5d4c3f9
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/mk.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"mk",buttonText:{prev:"претходно",next:"следно",today:"Денес",year:"година",month:"Месец",week:"Недела",day:"Ден",list:"График"},weekText:"Сед",allDayText:"Цел ден",moreLinkText:e=>"+повеќе "+e,noEventsText:"Нема настани за прикажување"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ms.global.js b/public/js/fullcalendar/packages/core/locales/ms.global.js
new file mode 100644
index 0000000..9d9f5fd
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ms.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ms',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Sebelum',
17 next: 'Selepas',
18 today: 'hari ini',
19 year: 'Tahun',
20 month: 'Bulan',
21 week: 'Minggu',
22 day: 'Hari',
23 list: 'Agenda',
24 },
25 weekText: 'Mg',
26 allDayText: 'Sepanjang hari',
27 moreLinkText(n) {
28 return 'masih ada ' + n + ' acara';
29 },
30 noEventsText: 'Tiada peristiwa untuk dipaparkan',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ms.global.min.js b/public/js/fullcalendar/packages/core/locales/ms.global.min.js
new file mode 100644
index 0000000..06644cf
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ms.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(a){"use strict";var e={code:"ms",week:{dow:1,doy:7},buttonText:{prev:"Sebelum",next:"Selepas",today:"hari ini",year:"Tahun",month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},weekText:"Mg",allDayText:"Sepanjang hari",moreLinkText:a=>"masih ada "+a+" acara",noEventsText:"Tiada peristiwa untuk dipaparkan"};FullCalendar.globalLocales.push(e)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/nb.global.js b/public/js/fullcalendar/packages/core/locales/nb.global.js
new file mode 100644
index 0000000..9283d70
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nb.global.js
@@ -0,0 +1,44 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'nb',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Forrige',
17 next: 'Neste',
18 today: 'I dag',
19 year: 'År',
20 month: 'Måned',
21 week: 'Uke',
22 day: 'Dag',
23 list: 'Agenda',
24 },
25 weekText: 'Uke',
26 weekTextLong: 'Uke',
27 allDayText: 'Hele dagen',
28 moreLinkText: 'til',
29 noEventsText: 'Ingen hendelser å vise',
30 buttonHints: {
31 prev: 'Forrige $0',
32 next: 'Neste $0',
33 today: 'Nåværende $0',
34 },
35 viewHint: '$0 visning',
36 navLinkHint: 'Gå til $0',
37 moreLinkHint(eventCnt) {
38 return `Vis ${eventCnt} flere hendelse${eventCnt === 1 ? '' : 'r'}`;
39 },
40 };
41
42 index_js.globalLocales.push(locale);
43
44})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/nb.global.min.js b/public/js/fullcalendar/packages/core/locales/nb.global.min.js
new file mode 100644
index 0000000..449f281
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nb.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var n={code:"nb",week:{dow:1,doy:4},buttonText:{prev:"Forrige",next:"Neste",today:"I dag",year:"År",month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},weekText:"Uke",weekTextLong:"Uke",allDayText:"Hele dagen",moreLinkText:"til",noEventsText:"Ingen hendelser å vise",buttonHints:{prev:"Forrige $0",next:"Neste $0",today:"Nåværende $0"},viewHint:"$0 visning",navLinkHint:"Gå til $0",moreLinkHint:e=>`Vis ${e} flere hendelse${1===e?"":"r"}`};FullCalendar.globalLocales.push(n)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ne.global.js b/public/js/fullcalendar/packages/core/locales/ne.global.js
new file mode 100644
index 0000000..93a07a2
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ne.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ne',
11 week: {
12 dow: 7,
13 doy: 1, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'अघिल्लो',
17 next: 'अर्को',
18 today: 'आज',
19 year: 'वर्ष',
20 month: 'महिना',
21 week: 'हप्ता',
22 day: 'दिन',
23 list: 'सूची',
24 },
25 weekText: 'हप्ता',
26 allDayText: 'दिनभरि',
27 moreLinkText: 'थप लिंक',
28 noEventsText: 'देखाउनको लागि कुनै घटनाहरू छैनन्',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ne.global.min.js b/public/js/fullcalendar/packages/core/locales/ne.global.min.js
new file mode 100644
index 0000000..a87c609
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ne.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ne",week:{dow:7,doy:1},buttonText:{prev:"अघिल्लो",next:"अर्को",today:"आज",year:"वर्ष",month:"महिना",week:"हप्ता",day:"दिन",list:"सूची"},weekText:"हप्ता",allDayText:"दिनभरि",moreLinkText:"थप लिंक",noEventsText:"देखाउनको लागि कुनै घटनाहरू छैनन्"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/nl.global.js b/public/js/fullcalendar/packages/core/locales/nl.global.js
new file mode 100644
index 0000000..9bfa4a1
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nl.global.js
@@ -0,0 +1,32 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'nl',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Vorige',
17 next: 'Volgende',
18 today: 'Vandaag',
19 year: 'Jaar',
20 month: 'Maand',
21 week: 'Week',
22 day: 'Dag',
23 list: 'Lijst',
24 },
25 allDayText: 'Hele dag',
26 moreLinkText: 'extra',
27 noEventsText: 'Geen evenementen om te laten zien',
28 };
29
30 index_js.globalLocales.push(locale);
31
32})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/nl.global.min.js b/public/js/fullcalendar/packages/core/locales/nl.global.min.js
new file mode 100644
index 0000000..157b489
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nl.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"nl",week:{dow:1,doy:4},buttonText:{prev:"Vorige",next:"Volgende",today:"Vandaag",year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Lijst"},allDayText:"Hele dag",moreLinkText:"extra",noEventsText:"Geen evenementen om te laten zien"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/nn.global.js b/public/js/fullcalendar/packages/core/locales/nn.global.js
new file mode 100644
index 0000000..685c02c
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nn.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'nn',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Førre',
17 next: 'Neste',
18 today: 'I dag',
19 year: 'År',
20 month: 'Månad',
21 week: 'Veke',
22 day: 'Dag',
23 list: 'Agenda',
24 },
25 weekText: 'Veke',
26 allDayText: 'Heile dagen',
27 moreLinkText: 'til',
28 noEventsText: 'Ingen hendelser å vise',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/nn.global.min.js b/public/js/fullcalendar/packages/core/locales/nn.global.min.js
new file mode 100644
index 0000000..a48d4a5
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/nn.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"nn",week:{dow:1,doy:4},buttonText:{prev:"Førre",next:"Neste",today:"I dag",year:"År",month:"Månad",week:"Veke",day:"Dag",list:"Agenda"},weekText:"Veke",allDayText:"Heile dagen",moreLinkText:"til",noEventsText:"Ingen hendelser å vise"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/pl.global.js b/public/js/fullcalendar/packages/core/locales/pl.global.js
new file mode 100644
index 0000000..5456866
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pl.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'pl',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Poprzedni',
17 next: 'Następny',
18 today: 'Dziś',
19 year: 'Rok',
20 month: 'Miesiąc',
21 week: 'Tydzień',
22 day: 'Dzień',
23 list: 'Plan dnia',
24 },
25 weekText: 'Tydz',
26 allDayText: 'Cały dzień',
27 moreLinkText: 'więcej',
28 noEventsText: 'Brak wydarzeń do wyświetlenia',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/pl.global.min.js b/public/js/fullcalendar/packages/core/locales/pl.global.min.js
new file mode 100644
index 0000000..cc5f1cc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pl.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"pl",week:{dow:1,doy:4},buttonText:{prev:"Poprzedni",next:"Następny",today:"Dziś",year:"Rok",month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},weekText:"Tydz",allDayText:"Cały dzień",moreLinkText:"więcej",noEventsText:"Brak wydarzeń do wyświetlenia"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/pt-br.global.js b/public/js/fullcalendar/packages/core/locales/pt-br.global.js
new file mode 100644
index 0000000..99b1633
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pt-br.global.js
@@ -0,0 +1,52 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'pt-br',
11 buttonText: {
12 prev: 'Anterior',
13 next: 'Próximo',
14 prevYear: 'Ano anterior',
15 nextYear: 'Próximo ano',
16 year: 'Ano',
17 today: 'Hoje',
18 month: 'Mês',
19 week: 'Semana',
20 day: 'Dia',
21 list: 'Lista',
22 },
23 buttonHints: {
24 prev: '$0 Anterior',
25 next: 'Próximo $0',
26 today(buttonText) {
27 return (buttonText === 'Dia') ? 'Hoje' :
28 ((buttonText === 'Semana') ? 'Esta' : 'Este') + ' ' + buttonText.toLocaleLowerCase();
29 },
30 },
31 viewHint(buttonText) {
32 return 'Visualizar ' + (buttonText === 'Semana' ? 'a' : 'o') + ' ' + buttonText.toLocaleLowerCase();
33 },
34 weekText: 'Sm',
35 weekTextLong: 'Semana',
36 allDayText: 'dia inteiro',
37 moreLinkText(n) {
38 return 'mais +' + n;
39 },
40 moreLinkHint(eventCnt) {
41 return `Mostrar mais ${eventCnt} eventos`;
42 },
43 noEventsText: 'Não há eventos para mostrar',
44 navLinkHint: 'Ir para $0',
45 closeHint: 'Fechar',
46 timeHint: 'A hora',
47 eventHint: 'Evento',
48 };
49
50 index_js.globalLocales.push(locale);
51
52})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/pt-br.global.min.js b/public/js/fullcalendar/packages/core/locales/pt-br.global.min.js
new file mode 100644
index 0000000..f2f63be
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pt-br.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"pt-br",buttonText:{prev:"Anterior",next:"Próximo",prevYear:"Ano anterior",nextYear:"Próximo ano",year:"Ano",today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista"},buttonHints:{prev:"$0 Anterior",next:"Próximo $0",today:e=>"Dia"===e?"Hoje":("Semana"===e?"Esta":"Este")+" "+e.toLocaleLowerCase()},viewHint:e=>"Visualizar "+("Semana"===e?"a":"o")+" "+e.toLocaleLowerCase(),weekText:"Sm",weekTextLong:"Semana",allDayText:"dia inteiro",moreLinkText:e=>"mais +"+e,moreLinkHint:e=>`Mostrar mais ${e} eventos`,noEventsText:"Não há eventos para mostrar",navLinkHint:"Ir para $0",closeHint:"Fechar",timeHint:"A hora",eventHint:"Evento"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/pt.global.js b/public/js/fullcalendar/packages/core/locales/pt.global.js
new file mode 100644
index 0000000..35b07ed
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pt.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'pt',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Anterior',
17 next: 'Seguinte',
18 today: 'Hoje',
19 year: 'Ano',
20 month: 'Mês',
21 week: 'Semana',
22 day: 'Dia',
23 list: 'Agenda',
24 },
25 weekText: 'Sem',
26 allDayText: 'Todo o dia',
27 moreLinkText: 'mais',
28 noEventsText: 'Não há eventos para mostrar',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/pt.global.min.js b/public/js/fullcalendar/packages/core/locales/pt.global.min.js
new file mode 100644
index 0000000..159ec8e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/pt.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"pt",week:{dow:1,doy:4},buttonText:{prev:"Anterior",next:"Seguinte",today:"Hoje",year:"Ano",month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},weekText:"Sem",allDayText:"Todo o dia",moreLinkText:"mais",noEventsText:"Não há eventos para mostrar"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ro.global.js b/public/js/fullcalendar/packages/core/locales/ro.global.js
new file mode 100644
index 0000000..cb9123f
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ro.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ro',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'precedentă',
17 next: 'următoare',
18 today: 'Azi',
19 year: 'An',
20 month: 'Lună',
21 week: 'Săptămână',
22 day: 'Zi',
23 list: 'Agendă',
24 },
25 weekText: 'Săpt',
26 allDayText: 'Toată ziua',
27 moreLinkText(n) {
28 return '+alte ' + n;
29 },
30 noEventsText: 'Nu există evenimente de afișat',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ro.global.min.js b/public/js/fullcalendar/packages/core/locales/ro.global.min.js
new file mode 100644
index 0000000..1b72c31
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ro.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"ro",week:{dow:1,doy:7},buttonText:{prev:"precedentă",next:"următoare",today:"Azi",year:"An",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},weekText:"Săpt",allDayText:"Toată ziua",moreLinkText:e=>"+alte "+e,noEventsText:"Nu există evenimente de afișat"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ru.global.js b/public/js/fullcalendar/packages/core/locales/ru.global.js
new file mode 100644
index 0000000..da6022a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ru.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ru',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Пред',
17 next: 'След',
18 today: 'Сегодня',
19 year: 'Год',
20 month: 'Месяц',
21 week: 'Неделя',
22 day: 'День',
23 list: 'Повестка дня',
24 },
25 weekText: 'Нед',
26 allDayText: 'Весь день',
27 moreLinkText(n) {
28 return '+ ещё ' + n;
29 },
30 noEventsText: 'Нет событий для отображения',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ru.global.min.js b/public/js/fullcalendar/packages/core/locales/ru.global.min.js
new file mode 100644
index 0000000..21bbddc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ru.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"ru",week:{dow:1,doy:4},buttonText:{prev:"Пред",next:"След",today:"Сегодня",year:"Год",month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},weekText:"Нед",allDayText:"Весь день",moreLinkText:e=>"+ ещё "+e,noEventsText:"Нет событий для отображения"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/si-lk.global.js b/public/js/fullcalendar/packages/core/locales/si-lk.global.js
new file mode 100644
index 0000000..c6a9b50
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/si-lk.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'si-lk',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'පෙර',
17 next: 'පසු',
18 today: 'අද',
19 year: 'අවුරුදු',
20 month: 'මාසය',
21 week: 'සතිය',
22 day: 'දවස',
23 list: 'ලැයිස්තුව',
24 },
25 weekText: 'සති',
26 allDayText: 'සියලු',
27 moreLinkText: 'තවත්',
28 noEventsText: 'මුකුත් නැත',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/si-lk.global.min.js b/public/js/fullcalendar/packages/core/locales/si-lk.global.min.js
new file mode 100644
index 0000000..110fd41
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/si-lk.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"si-lk",week:{dow:1,doy:4},buttonText:{prev:"පෙර",next:"පසු",today:"අද",year:"අවුරුදු",month:"මාසය",week:"සතිය",day:"දවස",list:"ලැයිස්තුව"},weekText:"සති",allDayText:"සියලු",moreLinkText:"තවත්",noEventsText:"මුකුත් නැත"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sk.global.js b/public/js/fullcalendar/packages/core/locales/sk.global.js
new file mode 100644
index 0000000..06995b9
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sk.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sk',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Predchádzajúci',
17 next: 'Nasledujúci',
18 today: 'Dnes',
19 year: 'Rok',
20 month: 'Mesiac',
21 week: 'Týždeň',
22 day: 'Deň',
23 list: 'Rozvrh',
24 },
25 weekText: 'Ty',
26 allDayText: 'Celý deň',
27 moreLinkText(n) {
28 return '+ďalšie: ' + n;
29 },
30 noEventsText: 'Žiadne akcie na zobrazenie',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sk.global.min.js b/public/js/fullcalendar/packages/core/locales/sk.global.min.js
new file mode 100644
index 0000000..dc2f029
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sk.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"sk",week:{dow:1,doy:4},buttonText:{prev:"Predchádzajúci",next:"Nasledujúci",today:"Dnes",year:"Rok",month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},weekText:"Ty",allDayText:"Celý deň",moreLinkText:e=>"+ďalšie: "+e,noEventsText:"Žiadne akcie na zobrazenie"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sl.global.js b/public/js/fullcalendar/packages/core/locales/sl.global.js
new file mode 100644
index 0000000..9f72659
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sl.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sl',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Prejšnji',
17 next: 'Naslednji',
18 today: 'Trenutni',
19 year: 'Leto',
20 month: 'Mesec',
21 week: 'Teden',
22 day: 'Dan',
23 list: 'Dnevni red',
24 },
25 weekText: 'Teden',
26 allDayText: 'Ves dan',
27 moreLinkText: 'več',
28 noEventsText: 'Ni dogodkov za prikaz',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sl.global.min.js b/public/js/fullcalendar/packages/core/locales/sl.global.min.js
new file mode 100644
index 0000000..f2b4d36
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sl.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"sl",week:{dow:1,doy:7},buttonText:{prev:"Prejšnji",next:"Naslednji",today:"Trenutni",year:"Leto",month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},weekText:"Teden",allDayText:"Ves dan",moreLinkText:"več",noEventsText:"Ni dogodkov za prikaz"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sm.global.js b/public/js/fullcalendar/packages/core/locales/sm.global.js
new file mode 100644
index 0000000..052e182
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sm.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sm',
11 buttonText: {
12 prev: 'Talu ai',
13 next: 'Mulimuli atu',
14 today: 'Aso nei',
15 year: 'Tausaga',
16 month: 'Masina',
17 week: 'Vaiaso',
18 day: 'Aso',
19 list: 'Faasologa',
20 },
21 weekText: 'Vaiaso',
22 allDayText: 'Aso atoa',
23 moreLinkText: 'sili atu',
24 noEventsText: 'Leai ni mea na tutupu',
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sm.global.min.js b/public/js/fullcalendar/packages/core/locales/sm.global.min.js
new file mode 100644
index 0000000..6945eba
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sm.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(a){"use strict";FullCalendar.globalLocales.push({code:"sm",buttonText:{prev:"Talu ai",next:"Mulimuli atu",today:"Aso nei",year:"Tausaga",month:"Masina",week:"Vaiaso",day:"Aso",list:"Faasologa"},weekText:"Vaiaso",allDayText:"Aso atoa",moreLinkText:"sili atu",noEventsText:"Leai ni mea na tutupu"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sq.global.js b/public/js/fullcalendar/packages/core/locales/sq.global.js
new file mode 100644
index 0000000..c4f4fb6
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sq.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sq',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'mbrapa',
17 next: 'Përpara',
18 today: 'Sot',
19 year: 'Viti',
20 month: 'Muaj',
21 week: 'Javë',
22 day: 'Ditë',
23 list: 'Listë',
24 },
25 weekText: 'Ja',
26 allDayText: 'Gjithë ditën',
27 moreLinkText(n) {
28 return '+më tepër ' + n;
29 },
30 noEventsText: 'Nuk ka evente për të shfaqur',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sq.global.min.js b/public/js/fullcalendar/packages/core/locales/sq.global.min.js
new file mode 100644
index 0000000..8e61a8a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sq.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"sq",week:{dow:1,doy:4},buttonText:{prev:"mbrapa",next:"Përpara",today:"Sot",year:"Viti",month:"Muaj",week:"Javë",day:"Ditë",list:"Listë"},weekText:"Ja",allDayText:"Gjithë ditën",moreLinkText:e=>"+më tepër "+e,noEventsText:"Nuk ka evente për të shfaqur"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.js b/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.js
new file mode 100644
index 0000000..a31a7c5
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sr-cyrl',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Претходна',
17 next: 'следећи',
18 today: 'Данас',
19 year: 'Година',
20 month: 'Месец',
21 week: 'Недеља',
22 day: 'Дан',
23 list: 'Планер',
24 },
25 weekText: 'Сед',
26 allDayText: 'Цео дан',
27 moreLinkText(n) {
28 return '+ још ' + n;
29 },
30 noEventsText: 'Нема догађаја за приказ',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.min.js b/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.min.js
new file mode 100644
index 0000000..3f93d6e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sr-cyrl.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"sr-cyrl",week:{dow:1,doy:7},buttonText:{prev:"Претходна",next:"следећи",today:"Данас",year:"Година",month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},weekText:"Сед",allDayText:"Цео дан",moreLinkText:e=>"+ још "+e,noEventsText:"Нема догађаја за приказ"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sr.global.js b/public/js/fullcalendar/packages/core/locales/sr.global.js
new file mode 100644
index 0000000..626d059
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sr.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sr',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Prethodna',
17 next: 'Sledeći',
18 today: 'Danas',
19 year: 'Godina',
20 month: 'Mеsеc',
21 week: 'Nеdеlja',
22 day: 'Dan',
23 list: 'Planеr',
24 },
25 weekText: 'Sed',
26 allDayText: 'Cеo dan',
27 moreLinkText(n) {
28 return '+ još ' + n;
29 },
30 noEventsText: 'Nеma događaja za prikaz',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sr.global.min.js b/public/js/fullcalendar/packages/core/locales/sr.global.min.js
new file mode 100644
index 0000000..338bb2e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sr.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(a){"use strict";var e={code:"sr",week:{dow:1,doy:7},buttonText:{prev:"Prethodna",next:"Sledeći",today:"Danas",year:"Godina",month:"Mеsеc",week:"Nеdеlja",day:"Dan",list:"Planеr"},weekText:"Sed",allDayText:"Cеo dan",moreLinkText:a=>"+ još "+a,noEventsText:"Nеma događaja za prikaz"};FullCalendar.globalLocales.push(e)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/sv.global.js b/public/js/fullcalendar/packages/core/locales/sv.global.js
new file mode 100644
index 0000000..2c5c4e4
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sv.global.js
@@ -0,0 +1,53 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'sv',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Förra',
17 next: 'Nästa',
18 today: 'Idag',
19 year: 'År',
20 month: 'Månad',
21 week: 'Vecka',
22 day: 'Dag',
23 list: 'Program',
24 },
25 buttonHints: {
26 prev(buttonText) {
27 return `Föregående ${buttonText.toLocaleLowerCase()}`;
28 },
29 next(buttonText) {
30 return `Nästa ${buttonText.toLocaleLowerCase()}`;
31 },
32 today(buttonText) {
33 return (buttonText === 'Program' ? 'Detta' : 'Denna') + ' ' + buttonText.toLocaleLowerCase();
34 },
35 },
36 viewHint: '$0 vy',
37 navLinkHint: 'Gå till $0',
38 moreLinkHint(eventCnt) {
39 return `Visa ytterligare ${eventCnt} händelse${eventCnt === 1 ? '' : 'r'}`;
40 },
41 weekText: 'v.',
42 weekTextLong: 'Vecka',
43 allDayText: 'Heldag',
44 moreLinkText: 'till',
45 noEventsText: 'Inga händelser att visa',
46 closeHint: 'Stäng',
47 timeHint: 'Klockan',
48 eventHint: 'Händelse',
49 };
50
51 index_js.globalLocales.push(locale);
52
53})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/sv.global.min.js b/public/js/fullcalendar/packages/core/locales/sv.global.min.js
new file mode 100644
index 0000000..e5472db
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/sv.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"sv",week:{dow:1,doy:4},buttonText:{prev:"Förra",next:"Nästa",today:"Idag",year:"År",month:"Månad",week:"Vecka",day:"Dag",list:"Program"},buttonHints:{prev:e=>"Föregående "+e.toLocaleLowerCase(),next:e=>"Nästa "+e.toLocaleLowerCase(),today:e=>("Program"===e?"Detta":"Denna")+" "+e.toLocaleLowerCase()},viewHint:"$0 vy",navLinkHint:"Gå till $0",moreLinkHint:e=>`Visa ytterligare ${e} händelse${1===e?"":"r"}`,weekText:"v.",weekTextLong:"Vecka",allDayText:"Heldag",moreLinkText:"till",noEventsText:"Inga händelser att visa",closeHint:"Stäng",timeHint:"Klockan",eventHint:"Händelse"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ta-in.global.js b/public/js/fullcalendar/packages/core/locales/ta-in.global.js
new file mode 100644
index 0000000..2e3d6bf
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ta-in.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ta-in',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'முந்தைய',
17 next: 'அடுத்தது',
18 today: 'இன்று',
19 year: 'ஆண்டு',
20 month: 'மாதம்',
21 week: 'வாரம்',
22 day: 'நாள்',
23 list: 'தினசரி அட்டவணை',
24 },
25 weekText: 'வாரம்',
26 allDayText: 'நாள் முழுவதும்',
27 moreLinkText(n) {
28 return '+ மேலும் ' + n;
29 },
30 noEventsText: 'காண்பிக்க நிகழ்வுகள் இல்லை',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ta-in.global.min.js b/public/js/fullcalendar/packages/core/locales/ta-in.global.min.js
new file mode 100644
index 0000000..6fa7117
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ta-in.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"ta-in",week:{dow:1,doy:4},buttonText:{prev:"முந்தைய",next:"அடுத்தது",today:"இன்று",year:"ஆண்டு",month:"மாதம்",week:"வாரம்",day:"நாள்",list:"தினசரி அட்டவணை"},weekText:"வாரம்",allDayText:"நாள் முழுவதும்",moreLinkText:e=>"+ மேலும் "+e,noEventsText:"காண்பிக்க நிகழ்வுகள் இல்லை"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/th.global.js b/public/js/fullcalendar/packages/core/locales/th.global.js
new file mode 100644
index 0000000..8383e1c
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/th.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'th',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'ก่อนหน้า',
17 next: 'ถัดไป',
18 prevYear: 'ปีก่อนหน้า',
19 nextYear: 'ปีถัดไป',
20 year: 'ปี',
21 today: 'วันนี้',
22 month: 'เดือน',
23 week: 'สัปดาห์',
24 day: 'วัน',
25 list: 'กำหนดการ',
26 },
27 weekText: 'สัปดาห์',
28 allDayText: 'ตลอดวัน',
29 moreLinkText: 'เพิ่มเติม',
30 noEventsText: 'ไม่มีกิจกรรมที่จะแสดง',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/th.global.min.js b/public/js/fullcalendar/packages/core/locales/th.global.min.js
new file mode 100644
index 0000000..fa82694
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/th.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"th",week:{dow:1,doy:4},buttonText:{prev:"ก่อนหน้า",next:"ถัดไป",prevYear:"ปีก่อนหน้า",nextYear:"ปีถัดไป",year:"ปี",today:"วันนี้",month:"เดือน",week:"สัปดาห์",day:"วัน",list:"กำหนดการ"},weekText:"สัปดาห์",allDayText:"ตลอดวัน",moreLinkText:"เพิ่มเติม",noEventsText:"ไม่มีกิจกรรมที่จะแสดง"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/tr.global.js b/public/js/fullcalendar/packages/core/locales/tr.global.js
new file mode 100644
index 0000000..4338516
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/tr.global.js
@@ -0,0 +1,33 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'tr',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'geri',
17 next: 'ileri',
18 today: 'bugün',
19 year: 'Yıl',
20 month: 'Ay',
21 week: 'Hafta',
22 day: 'Gün',
23 list: 'Ajanda',
24 },
25 weekText: 'Hf',
26 allDayText: 'Tüm gün',
27 moreLinkText: 'daha fazla',
28 noEventsText: 'Gösterilecek etkinlik yok',
29 };
30
31 index_js.globalLocales.push(locale);
32
33})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/tr.global.min.js b/public/js/fullcalendar/packages/core/locales/tr.global.min.js
new file mode 100644
index 0000000..7d67a7c
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/tr.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"tr",week:{dow:1,doy:7},buttonText:{prev:"geri",next:"ileri",today:"bugün",year:"Yıl",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},weekText:"Hf",allDayText:"Tüm gün",moreLinkText:"daha fazla",noEventsText:"Gösterilecek etkinlik yok"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/ug.global.js b/public/js/fullcalendar/packages/core/locales/ug.global.js
new file mode 100644
index 0000000..b62a917
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ug.global.js
@@ -0,0 +1,26 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'ug',
11 buttonText: {
12 prev: 'ئالدىنقى',
13 next: 'كېيىنكى',
14 today: 'بۈگۈن',
15 year: 'يىل',
16 month: 'ئاي',
17 week: 'ھەپتە',
18 day: 'كۈن',
19 list: 'كۈنتەرتىپ',
20 },
21 allDayText: 'پۈتۈن كۈن',
22 };
23
24 index_js.globalLocales.push(locale);
25
26})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/ug.global.min.js b/public/js/fullcalendar/packages/core/locales/ug.global.min.js
new file mode 100644
index 0000000..dfa983e
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/ug.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"ug",buttonText:{prev:"ئالدىنقى",next:"كېيىنكى",today:"بۈگۈن",year:"يىل",month:"ئاي",week:"ھەپتە",day:"كۈن",list:"كۈنتەرتىپ"},allDayText:"پۈتۈن كۈن"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/uk.global.js b/public/js/fullcalendar/packages/core/locales/uk.global.js
new file mode 100644
index 0000000..0c3e82f
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uk.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'uk',
11 week: {
12 dow: 1,
13 doy: 7, // The week that contains Jan 1st is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Попередній',
17 next: 'далі',
18 today: 'Сьогодні',
19 year: 'рік',
20 month: 'Місяць',
21 week: 'Тиждень',
22 day: 'День',
23 list: 'Порядок денний',
24 },
25 weekText: 'Тиж',
26 allDayText: 'Увесь день',
27 moreLinkText(n) {
28 return '+ще ' + n + '...';
29 },
30 noEventsText: 'Немає подій для відображення',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/uk.global.min.js b/public/js/fullcalendar/packages/core/locales/uk.global.min.js
new file mode 100644
index 0000000..64bff36
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uk.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"uk",week:{dow:1,doy:7},buttonText:{prev:"Попередній",next:"далі",today:"Сьогодні",year:"рік",month:"Місяць",week:"Тиждень",day:"День",list:"Порядок денний"},weekText:"Тиж",allDayText:"Увесь день",moreLinkText:e=>"+ще "+e+"...",noEventsText:"Немає подій для відображення"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/uz-cy.global.js b/public/js/fullcalendar/packages/core/locales/uz-cy.global.js
new file mode 100644
index 0000000..0a93d42
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uz-cy.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'uz-cy',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Олин',
17 next: 'Кейин',
18 today: 'Бугун',
19 month: 'Ой',
20 week: 'Ҳафта',
21 day: 'Кун',
22 list: 'Кун тартиби',
23 },
24 weekText: 'Ҳафта',
25 allDayText: 'Кун бўйича',
26 moreLinkText(n) {
27 return '+ яна ' + n;
28 },
29 noEventsText: 'Кўрсатиш учун воқеалар йўқ',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/uz-cy.global.min.js b/public/js/fullcalendar/packages/core/locales/uz-cy.global.min.js
new file mode 100644
index 0000000..461632a
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uz-cy.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"uz-cy",week:{dow:1,doy:4},buttonText:{prev:"Олин",next:"Кейин",today:"Бугун",month:"Ой",week:"Ҳафта",day:"Кун",list:"Кун тартиби"},weekText:"Ҳафта",allDayText:"Кун бўйича",moreLinkText:e=>"+ яна "+e,noEventsText:"Кўрсатиш учун воқеалар йўқ"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/uz.global.js b/public/js/fullcalendar/packages/core/locales/uz.global.js
new file mode 100644
index 0000000..e55e79b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uz.global.js
@@ -0,0 +1,34 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'uz',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Oldingi',
17 next: 'Keyingi',
18 today: 'Bugun',
19 year: 'Yil',
20 month: 'Oy',
21 week: 'Xafta',
22 day: 'Kun',
23 list: 'Kun tartibi',
24 },
25 allDayText: 'Kun bo\'yi',
26 moreLinkText(n) {
27 return '+ yana ' + n;
28 },
29 noEventsText: 'Ko\'rsatish uchun voqealar yo\'q',
30 };
31
32 index_js.globalLocales.push(locale);
33
34})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/uz.global.min.js b/public/js/fullcalendar/packages/core/locales/uz.global.min.js
new file mode 100644
index 0000000..89d1e2b
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/uz.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var a={code:"uz",week:{dow:1,doy:4},buttonText:{prev:"Oldingi",next:"Keyingi",today:"Bugun",year:"Yil",month:"Oy",week:"Xafta",day:"Kun",list:"Kun tartibi"},allDayText:"Kun bo'yi",moreLinkText:e=>"+ yana "+e,noEventsText:"Ko'rsatish uchun voqealar yo'q"};FullCalendar.globalLocales.push(a)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/vi.global.js b/public/js/fullcalendar/packages/core/locales/vi.global.js
new file mode 100644
index 0000000..13a447d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/vi.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'vi',
11 week: {
12 dow: 1,
13 doy: 4, // The week that contains Jan 4th is the first week of the year.
14 },
15 buttonText: {
16 prev: 'Trước',
17 next: 'Tiếp',
18 today: 'Hôm nay',
19 year: 'Năm',
20 month: 'Tháng',
21 week: 'Tuần',
22 day: 'Ngày',
23 list: 'Lịch biểu',
24 },
25 weekText: 'Tu',
26 allDayText: 'Cả ngày',
27 moreLinkText(n) {
28 return '+ thêm ' + n;
29 },
30 noEventsText: 'Không có sự kiện để hiển thị',
31 };
32
33 index_js.globalLocales.push(locale);
34
35})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/vi.global.min.js b/public/js/fullcalendar/packages/core/locales/vi.global.min.js
new file mode 100644
index 0000000..42690bc
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/vi.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"vi",week:{dow:1,doy:4},buttonText:{prev:"Trước",next:"Tiếp",today:"Hôm nay",year:"Năm",month:"Tháng",week:"Tuần",day:"Ngày",list:"Lịch biểu"},weekText:"Tu",allDayText:"Cả ngày",moreLinkText:e=>"+ thêm "+e,noEventsText:"Không có sự kiện để hiển thị"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/zh-cn.global.js b/public/js/fullcalendar/packages/core/locales/zh-cn.global.js
new file mode 100644
index 0000000..8517b34
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/zh-cn.global.js
@@ -0,0 +1,36 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'zh-cn',
11 week: {
12 // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
13 dow: 1,
14 doy: 4, // The week that contains Jan 4th is the first week of the year.
15 },
16 buttonText: {
17 prev: '上月',
18 next: '下月',
19 today: '今天',
20 year: '年',
21 month: '月',
22 week: '周',
23 day: '日',
24 list: '日程',
25 },
26 weekText: '周',
27 allDayText: '全天',
28 moreLinkText(n) {
29 return '另外 ' + n + ' 个';
30 },
31 noEventsText: '没有事件显示',
32 };
33
34 index_js.globalLocales.push(locale);
35
36})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/zh-cn.global.min.js b/public/js/fullcalendar/packages/core/locales/zh-cn.global.min.js
new file mode 100644
index 0000000..ff80a62
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/zh-cn.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";var t={code:"zh-cn",week:{dow:1,doy:4},buttonText:{prev:"上月",next:"下月",today:"今天",year:"年",month:"月",week:"周",day:"日",list:"日程"},weekText:"周",allDayText:"全天",moreLinkText:e=>"另外 "+e+" 个",noEventsText:"没有事件显示"};FullCalendar.globalLocales.push(t)}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/core/locales/zh-tw.global.js b/public/js/fullcalendar/packages/core/locales/zh-tw.global.js
new file mode 100644
index 0000000..6b3822d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/zh-tw.global.js
@@ -0,0 +1,29 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6(function (index_js) {
7 'use strict';
8
9 var locale = {
10 code: 'zh-tw',
11 buttonText: {
12 prev: '上個',
13 next: '下個',
14 today: '今天',
15 year: '年',
16 month: '月',
17 week: '週',
18 day: '天',
19 list: '活動列表',
20 },
21 weekText: '週',
22 allDayText: '整天',
23 moreLinkText: '顯示更多',
24 noEventsText: '沒有任何活動',
25 };
26
27 index_js.globalLocales.push(locale);
28
29})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/core/locales/zh-tw.global.min.js b/public/js/fullcalendar/packages/core/locales/zh-tw.global.min.js
new file mode 100644
index 0000000..5bae25d
--- /dev/null
+++ b/public/js/fullcalendar/packages/core/locales/zh-tw.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Core v6.1.17
3Docs & License: https://fullcalendar.io
4(c) 2024 Adam Shaw
5*/
6!function(e){"use strict";FullCalendar.globalLocales.push({code:"zh-tw",buttonText:{prev:"上個",next:"下個",today:"今天",year:"年",month:"月",week:"週",day:"天",list:"活動列表"},weekText:"週",allDayText:"整天",moreLinkText:"顯示更多",noEventsText:"沒有任何活動"})}(); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/daygrid/index.global.js b/public/js/fullcalendar/packages/daygrid/index.global.js
new file mode 100644
index 0000000..dc7eb01
--- /dev/null
+++ b/public/js/fullcalendar/packages/daygrid/index.global.js
@@ -0,0 +1,1040 @@
1/*!
2FullCalendar Day Grid Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/month-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.DayGrid = (function (exports, core, internal$1, preact) {
7 'use strict';
8
9 /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
10 ----------------------------------------------------------------------------------------------------------------------*/
11 // It is a manager for a Table subcomponent, which does most of the heavy lifting.
12 // It is responsible for managing width/height.
13 class TableView extends internal$1.DateComponent {
14 constructor() {
15 super(...arguments);
16 this.headerElRef = preact.createRef();
17 }
18 renderSimpleLayout(headerRowContent, bodyContent) {
19 let { props, context } = this;
20 let sections = [];
21 let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options);
22 if (headerRowContent) {
23 sections.push({
24 type: 'header',
25 key: 'header',
26 isSticky: stickyHeaderDates,
27 chunk: {
28 elRef: this.headerElRef,
29 tableClassName: 'fc-col-header',
30 rowContent: headerRowContent,
31 },
32 });
33 }
34 sections.push({
35 type: 'body',
36 key: 'body',
37 liquid: true,
38 chunk: { content: bodyContent },
39 });
40 return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
41 preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [] /* TODO: make optional? */, sections: sections })));
42 }
43 renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
44 let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
45 if (!ScrollGrid) {
46 throw new Error('No ScrollGrid implementation');
47 }
48 let { props, context } = this;
49 let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options);
50 let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options);
51 let sections = [];
52 if (headerRowContent) {
53 sections.push({
54 type: 'header',
55 key: 'header',
56 isSticky: stickyHeaderDates,
57 chunks: [{
58 key: 'main',
59 elRef: this.headerElRef,
60 tableClassName: 'fc-col-header',
61 rowContent: headerRowContent,
62 }],
63 });
64 }
65 sections.push({
66 type: 'body',
67 key: 'body',
68 liquid: true,
69 chunks: [{
70 key: 'main',
71 content: bodyContent,
72 }],
73 });
74 if (stickyFooterScrollbar) {
75 sections.push({
76 type: 'footer',
77 key: 'footer',
78 isSticky: true,
79 chunks: [{
80 key: 'main',
81 content: internal$1.renderScrollShim,
82 }],
83 });
84 }
85 return (preact.createElement(internal$1.ViewContainer, { elClasses: ['fc-daygrid'], viewSpec: context.viewSpec },
86 preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: props.forPrint, colGroups: [{ cols: [{ span: colCnt, minWidth: dayMinWidth }] }], sections: sections })));
87 }
88 }
89
90 function splitSegsByRow(segs, rowCnt) {
91 let byRow = [];
92 for (let i = 0; i < rowCnt; i += 1) {
93 byRow[i] = [];
94 }
95 for (let seg of segs) {
96 byRow[seg.row].push(seg);
97 }
98 return byRow;
99 }
100 function splitSegsByFirstCol(segs, colCnt) {
101 let byCol = [];
102 for (let i = 0; i < colCnt; i += 1) {
103 byCol[i] = [];
104 }
105 for (let seg of segs) {
106 byCol[seg.firstCol].push(seg);
107 }
108 return byCol;
109 }
110 function splitInteractionByRow(ui, rowCnt) {
111 let byRow = [];
112 if (!ui) {
113 for (let i = 0; i < rowCnt; i += 1) {
114 byRow[i] = null;
115 }
116 }
117 else {
118 for (let i = 0; i < rowCnt; i += 1) {
119 byRow[i] = {
120 affectedInstances: ui.affectedInstances,
121 isEvent: ui.isEvent,
122 segs: [],
123 };
124 }
125 for (let seg of ui.segs) {
126 byRow[seg.row].segs.push(seg);
127 }
128 }
129 return byRow;
130 }
131
132 const DEFAULT_TABLE_EVENT_TIME_FORMAT = internal$1.createFormatter({
133 hour: 'numeric',
134 minute: '2-digit',
135 omitZeroMinute: true,
136 meridiem: 'narrow',
137 });
138 function hasListItemDisplay(seg) {
139 let { display } = seg.eventRange.ui;
140 return display === 'list-item' || (display === 'auto' &&
141 !seg.eventRange.def.allDay &&
142 seg.firstCol === seg.lastCol && // can't be multi-day
143 seg.isStart && // "
144 seg.isEnd // "
145 );
146 }
147
148 class TableBlockEvent extends internal$1.BaseComponent {
149 render() {
150 let { props } = this;
151 return (preact.createElement(internal$1.StandardEvent, Object.assign({}, props, { elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT, defaultDisplayEventEnd: props.defaultDisplayEventEnd, disableResizing: !props.seg.eventRange.def.allDay })));
152 }
153 }
154
155 class TableListItemEvent extends internal$1.BaseComponent {
156 render() {
157 let { props, context } = this;
158 let { options } = context;
159 let { seg } = props;
160 let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
161 let timeText = internal$1.buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
162 return (preact.createElement(internal$1.EventContainer, Object.assign({}, props, { elTag: "a", elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'], elAttrs: internal$1.getSegAnchorAttrs(props.seg, context), defaultGenerator: renderInnerContent, timeText: timeText, isResizing: false, isDateSelecting: false })));
163 }
164 }
165 function renderInnerContent(renderProps) {
166 return (preact.createElement(preact.Fragment, null,
167 preact.createElement("div", { className: "fc-daygrid-event-dot", style: { borderColor: renderProps.borderColor || renderProps.backgroundColor } }),
168 renderProps.timeText && (preact.createElement("div", { className: "fc-event-time" }, renderProps.timeText)),
169 preact.createElement("div", { className: "fc-event-title" }, renderProps.event.title || preact.createElement(preact.Fragment, null, "\u00A0"))));
170 }
171
172 class TableCellMoreLink extends internal$1.BaseComponent {
173 constructor() {
174 super(...arguments);
175 this.compileSegs = internal$1.memoize(compileSegs);
176 }
177 render() {
178 let { props } = this;
179 let { allSegs, invisibleSegs } = this.compileSegs(props.singlePlacements);
180 return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-daygrid-more-link'], dateProfile: props.dateProfile, todayRange: props.todayRange, allDayDate: props.allDayDate, moreCnt: props.moreCnt, allSegs: allSegs, hiddenSegs: invisibleSegs, alignmentElRef: props.alignmentElRef, alignGridTop: props.alignGridTop, extraDateSpan: props.extraDateSpan, popoverContent: () => {
181 let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
182 (props.eventResize ? props.eventResize.affectedInstances : null) ||
183 {};
184 return (preact.createElement(preact.Fragment, null, allSegs.map((seg) => {
185 let instanceId = seg.eventRange.instance.instanceId;
186 return (preact.createElement("div", { className: "fc-daygrid-event-harness", key: instanceId, style: {
187 visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
188 } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection, defaultDisplayEventEnd: false }, internal$1.getSegMeta(seg, props.todayRange))))));
189 })));
190 } }));
191 }
192 }
193 function compileSegs(singlePlacements) {
194 let allSegs = [];
195 let invisibleSegs = [];
196 for (let placement of singlePlacements) {
197 allSegs.push(placement.seg);
198 if (!placement.isVisible) {
199 invisibleSegs.push(placement.seg);
200 }
201 }
202 return { allSegs, invisibleSegs };
203 }
204
205 const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'narrow' });
206 class TableCell extends internal$1.DateComponent {
207 constructor() {
208 super(...arguments);
209 this.rootElRef = preact.createRef();
210 this.state = {
211 dayNumberId: internal$1.getUniqueDomId(),
212 };
213 this.handleRootEl = (el) => {
214 internal$1.setRef(this.rootElRef, el);
215 internal$1.setRef(this.props.elRef, el);
216 };
217 }
218 render() {
219 let { context, props, state, rootElRef } = this;
220 let { options, dateEnv } = context;
221 let { date, dateProfile } = props;
222 // TODO: memoize this?
223 const isMonthStart = props.showDayNumber &&
224 shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
225 return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: this.handleRootEl, elClasses: [
226 'fc-daygrid-day',
227 ...(props.extraClassNames || []),
228 ], elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? { 'aria-labelledby': state.dayNumberId } : {})), { role: 'gridcell' }), defaultGenerator: renderTopInner, date: date, dateProfile: dateProfile, todayRange: props.todayRange, showDayNumber: props.showDayNumber, isMonthStart: isMonthStart, extraRenderProps: props.extraRenderProps }, (InnerContent, renderProps) => (preact.createElement("div", { ref: props.innerElRef, className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner", style: { minHeight: props.minHeight } },
229 props.showWeekNumber && (preact.createElement(internal$1.WeekNumberContainer, { elTag: "a", elClasses: ['fc-daygrid-week-number'], elAttrs: internal$1.buildNavLinkAttrs(context, date, 'week'), date: date, defaultFormat: DEFAULT_WEEK_NUM_FORMAT })),
230 !renderProps.isDisabled &&
231 (props.showDayNumber || internal$1.hasCustomDayCellContent(options) || props.forceDayTop) ? (preact.createElement("div", { className: "fc-daygrid-day-top" },
232 preact.createElement(InnerContent, { elTag: "a", elClasses: [
233 'fc-daygrid-day-number',
234 isMonthStart && 'fc-daygrid-month-start',
235 ], elAttrs: Object.assign(Object.assign({}, internal$1.buildNavLinkAttrs(context, date)), { id: state.dayNumberId }) }))) : props.showDayNumber ? (
236 // for creating correct amount of space (see issue #7162)
237 preact.createElement("div", { className: "fc-daygrid-day-top", style: { visibility: 'hidden' } },
238 preact.createElement("a", { className: "fc-daygrid-day-number" }, "\u00A0"))) : undefined,
239 preact.createElement("div", { className: "fc-daygrid-day-events", ref: props.fgContentElRef },
240 props.fgContent,
241 preact.createElement("div", { className: "fc-daygrid-day-bottom", style: { marginTop: props.moreMarginTop } },
242 preact.createElement(TableCellMoreLink, { allDayDate: date, singlePlacements: props.singlePlacements, moreCnt: props.moreCnt, alignmentElRef: rootElRef, alignGridTop: !props.showDayNumber, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange }))),
243 preact.createElement("div", { className: "fc-daygrid-day-bg" }, props.bgContent)))));
244 }
245 }
246 function renderTopInner(props) {
247 return props.dayNumberText || preact.createElement(preact.Fragment, null, "\u00A0");
248 }
249 function shouldDisplayMonthStart(date, currentRange, dateEnv) {
250 const { start: currentStart, end: currentEnd } = currentRange;
251 const currentEndIncl = internal$1.addMs(currentEnd, -1);
252 const currentFirstYear = dateEnv.getYear(currentStart);
253 const currentFirstMonth = dateEnv.getMonth(currentStart);
254 const currentLastYear = dateEnv.getYear(currentEndIncl);
255 const currentLastMonth = dateEnv.getMonth(currentEndIncl);
256 // spans more than one month?
257 return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
258 Boolean(
259 // first date in current view?
260 date.valueOf() === currentStart.valueOf() ||
261 // a month-start that's within the current range?
262 (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
263 }
264
265 function generateSegKey(seg) {
266 return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
267 }
268 function generateSegUid(seg) {
269 return generateSegKey(seg) + ':' + seg.lastCol;
270 }
271 function computeFgSegPlacement(segs, // assumed already sorted
272 dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
273 let hierarchy = new DayGridSegHierarchy((segEntry) => {
274 // TODO: more DRY with generateSegUid
275 let segUid = segs[segEntry.index].eventRange.instance.instanceId +
276 ':' + segEntry.span.start +
277 ':' + (segEntry.span.end - 1);
278 // if no thickness known, assume 1 (if 0, so small it always fits)
279 return segHeights[segUid] || 1;
280 });
281 hierarchy.allowReslicing = true;
282 hierarchy.strictOrder = strictOrder;
283 if (dayMaxEvents === true || dayMaxEventRows === true) {
284 hierarchy.maxCoord = maxContentHeight;
285 hierarchy.hiddenConsumes = true;
286 }
287 else if (typeof dayMaxEvents === 'number') {
288 hierarchy.maxStackCnt = dayMaxEvents;
289 }
290 else if (typeof dayMaxEventRows === 'number') {
291 hierarchy.maxStackCnt = dayMaxEventRows;
292 hierarchy.hiddenConsumes = true;
293 }
294 // create segInputs only for segs with known heights
295 let segInputs = [];
296 let unknownHeightSegs = [];
297 for (let i = 0; i < segs.length; i += 1) {
298 let seg = segs[i];
299 let segUid = generateSegUid(seg);
300 let eventHeight = segHeights[segUid];
301 if (eventHeight != null) {
302 segInputs.push({
303 index: i,
304 span: {
305 start: seg.firstCol,
306 end: seg.lastCol + 1,
307 },
308 });
309 }
310 else {
311 unknownHeightSegs.push(seg);
312 }
313 }
314 let hiddenEntries = hierarchy.addSegs(segInputs);
315 let segRects = hierarchy.toRects();
316 let { singleColPlacements, multiColPlacements, leftoverMargins } = placeRects(segRects, segs, cells);
317 let moreCnts = [];
318 let moreMarginTops = [];
319 // add segs with unknown heights
320 for (let seg of unknownHeightSegs) {
321 multiColPlacements[seg.firstCol].push({
322 seg,
323 isVisible: false,
324 isAbsolute: true,
325 absoluteTop: 0,
326 marginTop: 0,
327 });
328 for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
329 singleColPlacements[col].push({
330 seg: resliceSeg(seg, col, col + 1, cells),
331 isVisible: false,
332 isAbsolute: false,
333 absoluteTop: 0,
334 marginTop: 0,
335 });
336 }
337 }
338 // add the hidden entries
339 for (let col = 0; col < cells.length; col += 1) {
340 moreCnts.push(0);
341 }
342 for (let hiddenEntry of hiddenEntries) {
343 let seg = segs[hiddenEntry.index];
344 let hiddenSpan = hiddenEntry.span;
345 multiColPlacements[hiddenSpan.start].push({
346 seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
347 isVisible: false,
348 isAbsolute: true,
349 absoluteTop: 0,
350 marginTop: 0,
351 });
352 for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
353 moreCnts[col] += 1;
354 singleColPlacements[col].push({
355 seg: resliceSeg(seg, col, col + 1, cells),
356 isVisible: false,
357 isAbsolute: false,
358 absoluteTop: 0,
359 marginTop: 0,
360 });
361 }
362 }
363 // deal with leftover margins
364 for (let col = 0; col < cells.length; col += 1) {
365 moreMarginTops.push(leftoverMargins[col]);
366 }
367 return { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops };
368 }
369 // rects ordered by top coord, then left
370 function placeRects(allRects, segs, cells) {
371 let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
372 let singleColPlacements = [];
373 let multiColPlacements = [];
374 let leftoverMargins = [];
375 for (let col = 0; col < cells.length; col += 1) {
376 let rects = rectsByEachCol[col];
377 // compute all static segs in singlePlacements
378 let singlePlacements = [];
379 let currentHeight = 0;
380 let currentMarginTop = 0;
381 for (let rect of rects) {
382 let seg = segs[rect.index];
383 singlePlacements.push({
384 seg: resliceSeg(seg, col, col + 1, cells),
385 isVisible: true,
386 isAbsolute: false,
387 absoluteTop: rect.levelCoord,
388 marginTop: rect.levelCoord - currentHeight,
389 });
390 currentHeight = rect.levelCoord + rect.thickness;
391 }
392 // compute mixed static/absolute segs in multiPlacements
393 let multiPlacements = [];
394 currentHeight = 0;
395 currentMarginTop = 0;
396 for (let rect of rects) {
397 let seg = segs[rect.index];
398 let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
399 let isFirstCol = rect.span.start === col;
400 currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
401 currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
402 if (isAbsolute) {
403 currentMarginTop += rect.thickness;
404 if (isFirstCol) {
405 multiPlacements.push({
406 seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
407 isVisible: true,
408 isAbsolute: true,
409 absoluteTop: rect.levelCoord,
410 marginTop: 0,
411 });
412 }
413 }
414 else if (isFirstCol) {
415 multiPlacements.push({
416 seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
417 isVisible: true,
418 isAbsolute: false,
419 absoluteTop: rect.levelCoord,
420 marginTop: currentMarginTop, // claim the margin
421 });
422 currentMarginTop = 0;
423 }
424 }
425 singleColPlacements.push(singlePlacements);
426 multiColPlacements.push(multiPlacements);
427 leftoverMargins.push(currentMarginTop);
428 }
429 return { singleColPlacements, multiColPlacements, leftoverMargins };
430 }
431 function groupRectsByEachCol(rects, colCnt) {
432 let rectsByEachCol = [];
433 for (let col = 0; col < colCnt; col += 1) {
434 rectsByEachCol.push([]);
435 }
436 for (let rect of rects) {
437 for (let col = rect.span.start; col < rect.span.end; col += 1) {
438 rectsByEachCol[col].push(rect);
439 }
440 }
441 return rectsByEachCol;
442 }
443 function resliceSeg(seg, spanStart, spanEnd, cells) {
444 if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
445 return seg;
446 }
447 let eventRange = seg.eventRange;
448 let origRange = eventRange.range;
449 let slicedRange = internal$1.intersectRanges(origRange, {
450 start: cells[spanStart].date,
451 end: internal$1.addDays(cells[spanEnd - 1].date, 1),
452 });
453 return Object.assign(Object.assign({}, seg), { firstCol: spanStart, lastCol: spanEnd - 1, eventRange: {
454 def: eventRange.def,
455 ui: Object.assign(Object.assign({}, eventRange.ui), { durationEditable: false }),
456 instance: eventRange.instance,
457 range: slicedRange,
458 }, isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(), isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf() });
459 }
460 class DayGridSegHierarchy extends internal$1.SegHierarchy {
461 constructor() {
462 super(...arguments);
463 // config
464 this.hiddenConsumes = false;
465 // allows us to keep hidden entries in the hierarchy so they take up space
466 this.forceHidden = {};
467 }
468 addSegs(segInputs) {
469 const hiddenSegs = super.addSegs(segInputs);
470 const { entriesByLevel } = this;
471 const excludeHidden = (entry) => !this.forceHidden[internal$1.buildEntryKey(entry)];
472 // remove the forced-hidden segs
473 for (let level = 0; level < entriesByLevel.length; level += 1) {
474 entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
475 }
476 return hiddenSegs;
477 }
478 handleInvalidInsertion(insertion, entry, hiddenEntries) {
479 const { entriesByLevel, forceHidden } = this;
480 const { touchingEntry, touchingLevel, touchingLateral } = insertion;
481 // the entry that the new insertion is touching must be hidden
482 if (this.hiddenConsumes && touchingEntry) {
483 const touchingEntryId = internal$1.buildEntryKey(touchingEntry);
484 if (!forceHidden[touchingEntryId]) {
485 if (this.allowReslicing) {
486 // split up the touchingEntry, reinsert it
487 const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), { span: internal$1.intersectSpans(touchingEntry.span, entry.span) });
488 // reinsert the area that turned into a "more" link (so no other entries try to
489 // occupy the space) but mark it forced-hidden
490 const hiddenEntryId = internal$1.buildEntryKey(hiddenEntry);
491 forceHidden[hiddenEntryId] = true;
492 entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
493 hiddenEntries.push(hiddenEntry);
494 this.splitEntry(touchingEntry, entry, hiddenEntries);
495 }
496 else {
497 forceHidden[touchingEntryId] = true;
498 hiddenEntries.push(touchingEntry);
499 }
500 }
501 }
502 // will try to reslice...
503 super.handleInvalidInsertion(insertion, entry, hiddenEntries);
504 }
505 }
506
507 class TableRow extends internal$1.DateComponent {
508 constructor() {
509 super(...arguments);
510 this.cellElRefs = new internal$1.RefMap(); // the <td>
511 this.frameElRefs = new internal$1.RefMap(); // the fc-daygrid-day-frame
512 this.fgElRefs = new internal$1.RefMap(); // the fc-daygrid-day-events
513 this.segHarnessRefs = new internal$1.RefMap(); // indexed by "instanceId:firstCol"
514 this.rootElRef = preact.createRef();
515 this.state = {
516 framePositions: null,
517 maxContentHeight: null,
518 segHeights: {},
519 };
520 this.handleResize = (isForced) => {
521 if (isForced) {
522 this.updateSizing(true); // isExternal=true
523 }
524 };
525 }
526 render() {
527 let { props, state, context } = this;
528 let { options } = context;
529 let colCnt = props.cells.length;
530 let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
531 let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
532 let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
533 let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
534 let { singleColPlacements, multiColPlacements, moreCnts, moreMarginTops } = computeFgSegPlacement(internal$1.sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
535 let isForcedInvisible = // TODO: messy way to compute this
536 (props.eventDrag && props.eventDrag.affectedInstances) ||
537 (props.eventResize && props.eventResize.affectedInstances) ||
538 {};
539 return (preact.createElement("tr", { ref: this.rootElRef, role: "row" },
540 props.renderIntro && props.renderIntro(),
541 props.cells.map((cell, col) => {
542 let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
543 let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
544 return (preact.createElement(TableCell, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */, dateProfile: props.dateProfile, date: cell.date, showDayNumber: props.showDayNumbers, showWeekNumber: props.showWeekNumbers && col === 0, forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */, todayRange: props.todayRange, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, moreCnt: moreCnts[col], moreMarginTop: moreMarginTops[col], singlePlacements: singleColPlacements[col], fgContentElRef: this.fgElRefs.createRef(cell.key), fgContent: ( // Fragment scopes the keys
545 preact.createElement(preact.Fragment, null,
546 preact.createElement(preact.Fragment, null, normalFgNodes),
547 preact.createElement(preact.Fragment, null, mirrorFgNodes))), bgContent: ( // Fragment scopes the keys
548 preact.createElement(preact.Fragment, null,
549 this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
550 this.renderFillSegs(businessHoursByCol[col], 'non-business'),
551 this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))), minHeight: props.cellMinHeight }));
552 })));
553 }
554 componentDidMount() {
555 this.updateSizing(true);
556 this.context.addResizeHandler(this.handleResize);
557 }
558 componentDidUpdate(prevProps, prevState) {
559 let currentProps = this.props;
560 this.updateSizing(!internal$1.isPropsEqual(prevProps, currentProps));
561 }
562 componentWillUnmount() {
563 this.context.removeResizeHandler(this.handleResize);
564 }
565 getHighlightSegs() {
566 let { props } = this;
567 if (props.eventDrag && props.eventDrag.segs.length) { // messy check
568 return props.eventDrag.segs;
569 }
570 if (props.eventResize && props.eventResize.segs.length) { // messy check
571 return props.eventResize.segs;
572 }
573 return props.dateSelectionSegs;
574 }
575 getMirrorSegs() {
576 let { props } = this;
577 if (props.eventResize && props.eventResize.segs.length) { // messy check
578 return props.eventResize.segs;
579 }
580 return [];
581 }
582 renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
583 let { context } = this;
584 let { eventSelection } = this.props;
585 let { framePositions } = this.state;
586 let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
587 let isMirror = isDragging || isResizing || isDateSelecting;
588 let nodes = [];
589 if (framePositions) {
590 for (let placement of segPlacements) {
591 let { seg } = placement;
592 let { instanceId } = seg.eventRange.instance;
593 let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
594 let isAbsolute = placement.isAbsolute;
595 let left = '';
596 let right = '';
597 if (isAbsolute) {
598 if (context.isRtl) {
599 right = 0;
600 left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
601 }
602 else {
603 left = 0;
604 right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
605 }
606 }
607 /*
608 known bug: events that are force to be list-item but span multiple days still take up space in later columns
609 todo: in print view, for multi-day events, don't display title within non-start/end segs
610 */
611 nodes.push(preact.createElement("div", { className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''), key: generateSegKey(seg), ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)), style: {
612 visibility: isVisible ? '' : 'hidden',
613 marginTop: isAbsolute ? '' : placement.marginTop,
614 top: isAbsolute ? placement.absoluteTop : '',
615 left,
616 right,
617 } }, hasListItemDisplay(seg) ? (preact.createElement(TableListItemEvent, Object.assign({ seg: seg, isDragging: isDragging, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange)))) : (preact.createElement(TableBlockEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, defaultDisplayEventEnd: defaultDisplayEventEnd }, internal$1.getSegMeta(seg, todayRange))))));
618 }
619 }
620 return nodes;
621 }
622 renderFillSegs(segs, fillType) {
623 let { isRtl } = this.context;
624 let { todayRange } = this.props;
625 let { framePositions } = this.state;
626 let nodes = [];
627 if (framePositions) {
628 for (let seg of segs) {
629 let leftRightCss = isRtl ? {
630 right: 0,
631 left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
632 } : {
633 left: 0,
634 right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
635 };
636 nodes.push(preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-daygrid-bg-harness", style: leftRightCss }, fillType === 'bg-event' ?
637 preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, todayRange))) :
638 internal$1.renderFill(fillType)));
639 }
640 }
641 return preact.createElement(preact.Fragment, {}, ...nodes);
642 }
643 updateSizing(isExternalSizingChange) {
644 let { props, state, frameElRefs } = this;
645 if (!props.forPrint &&
646 props.clientWidth !== null // positioning ready?
647 ) {
648 if (isExternalSizingChange) {
649 let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
650 if (frameEls.length) {
651 let originEl = this.rootElRef.current;
652 let newPositionCache = new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal
653 false);
654 if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
655 this.setState({
656 framePositions: new internal$1.PositionCache(originEl, frameEls, true, // isHorizontal
657 false),
658 });
659 }
660 }
661 }
662 const oldSegHeights = this.state.segHeights;
663 const newSegHeights = this.querySegHeights();
664 const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
665 this.safeSetState({
666 // HACK to prevent oscillations of events being shown/hidden from max-event-rows
667 // Essentially, once you compute an element's height, never null-out.
668 // TODO: always display all events, as visibility:hidden?
669 segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
670 maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
671 });
672 }
673 }
674 querySegHeights() {
675 let segElMap = this.segHarnessRefs.currentMap;
676 let segHeights = {};
677 // get the max height amongst instance segs
678 for (let segUid in segElMap) {
679 let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
680 segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
681 }
682 return segHeights;
683 }
684 computeMaxContentHeight() {
685 let firstKey = this.props.cells[0].key;
686 let cellEl = this.cellElRefs.currentMap[firstKey];
687 let fcContainerEl = this.fgElRefs.currentMap[firstKey];
688 return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
689 }
690 getCellEls() {
691 let elMap = this.cellElRefs.currentMap;
692 return this.props.cells.map((cell) => elMap[cell.key]);
693 }
694 }
695 TableRow.addStateEquality({
696 segHeights: internal$1.isPropsEqual,
697 });
698 function buildMirrorPlacements(mirrorSegs, colPlacements) {
699 if (!mirrorSegs.length) {
700 return [];
701 }
702 let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
703 return mirrorSegs.map((seg) => ({
704 seg,
705 isVisible: true,
706 isAbsolute: true,
707 absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
708 marginTop: 0,
709 }));
710 }
711 function buildAbsoluteTopHash(colPlacements) {
712 let topsByInstanceId = {};
713 for (let placements of colPlacements) {
714 for (let placement of placements) {
715 topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
716 }
717 }
718 return topsByInstanceId;
719 }
720
721 class TableRows extends internal$1.DateComponent {
722 constructor() {
723 super(...arguments);
724 this.splitBusinessHourSegs = internal$1.memoize(splitSegsByRow);
725 this.splitBgEventSegs = internal$1.memoize(splitSegsByRow);
726 this.splitFgEventSegs = internal$1.memoize(splitSegsByRow);
727 this.splitDateSelectionSegs = internal$1.memoize(splitSegsByRow);
728 this.splitEventDrag = internal$1.memoize(splitInteractionByRow);
729 this.splitEventResize = internal$1.memoize(splitInteractionByRow);
730 this.rowRefs = new internal$1.RefMap();
731 }
732 render() {
733 let { props, context } = this;
734 let rowCnt = props.cells.length;
735 let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
736 let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
737 let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
738 let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
739 let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
740 let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
741 // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
742 // choose 7 because a month view will have max 6 rows
743 let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
744 props.clientWidth / context.options.aspectRatio / 6 :
745 null;
746 return (preact.createElement(internal$1.NowTimer, { unit: "day" }, (nowDate, todayRange) => (preact.createElement(preact.Fragment, null, props.cells.map((cells, row) => (preact.createElement(TableRow, { ref: this.rowRefs.createRef(row), key: cells.length
747 ? cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */
748 : row // in case there are no cells (like when resource view is loading)
749 , showDayNumbers: rowCnt > 1, showWeekNumbers: props.showWeekNumbers, todayRange: todayRange, dateProfile: props.dateProfile, cells: cells, renderIntro: props.renderRowIntro, businessHourSegs: businessHourSegsByRow[row], eventSelection: props.eventSelection, bgEventSegs: bgEventSegsByRow[row].filter(isSegAllDay) /* hack */, fgEventSegs: fgEventSegsByRow[row], dateSelectionSegs: dateSelectionSegsByRow[row], eventDrag: eventDragByRow[row], eventResize: eventResizeByRow[row], dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, clientWidth: props.clientWidth, clientHeight: props.clientHeight, cellMinHeight: cellMinHeight, forPrint: props.forPrint })))))));
750 }
751 componentDidMount() {
752 this.registerInteractiveComponent();
753 }
754 componentDidUpdate() {
755 // for if started with zero cells
756 this.registerInteractiveComponent();
757 }
758 registerInteractiveComponent() {
759 if (!this.rootEl) {
760 // HACK: need a daygrid wrapper parent to do positioning
761 // NOTE: a daygrid resource view w/o resources can have zero cells
762 const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
763 const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
764 if (rootEl) {
765 this.rootEl = rootEl;
766 this.context.registerInteractiveComponent(this, {
767 el: rootEl,
768 isHitComboAllowed: this.props.isHitComboAllowed,
769 });
770 }
771 }
772 }
773 componentWillUnmount() {
774 if (this.rootEl) {
775 this.context.unregisterInteractiveComponent(this);
776 this.rootEl = null;
777 }
778 }
779 // Hit System
780 // ----------------------------------------------------------------------------------------------------
781 prepareHits() {
782 this.rowPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
783 false, true);
784 this.colPositions = new internal$1.PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
785 true, // horizontal
786 false);
787 }
788 queryHit(positionLeft, positionTop) {
789 let { colPositions, rowPositions } = this;
790 let col = colPositions.leftToIndex(positionLeft);
791 let row = rowPositions.topToIndex(positionTop);
792 if (row != null && col != null) {
793 let cell = this.props.cells[row][col];
794 return {
795 dateProfile: this.props.dateProfile,
796 dateSpan: Object.assign({ range: this.getCellRange(row, col), allDay: true }, cell.extraDateSpan),
797 dayEl: this.getCellEl(row, col),
798 rect: {
799 left: colPositions.lefts[col],
800 right: colPositions.rights[col],
801 top: rowPositions.tops[row],
802 bottom: rowPositions.bottoms[row],
803 },
804 layer: 0,
805 };
806 }
807 return null;
808 }
809 getCellEl(row, col) {
810 return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
811 }
812 getCellRange(row, col) {
813 let start = this.props.cells[row][col].date;
814 let end = internal$1.addDays(start, 1);
815 return { start, end };
816 }
817 }
818 function isSegAllDay(seg) {
819 return seg.eventRange.def.allDay;
820 }
821
822 class Table extends internal$1.DateComponent {
823 constructor() {
824 super(...arguments);
825 this.elRef = preact.createRef();
826 this.needsScrollReset = false;
827 }
828 render() {
829 let { props } = this;
830 let { dayMaxEventRows, dayMaxEvents, expandRows } = props;
831 let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
832 // if rows can't expand to fill fixed height, can't do balanced-height event limit
833 // TODO: best place to normalize these options?
834 if (limitViaBalanced && !expandRows) {
835 limitViaBalanced = false;
836 dayMaxEventRows = null;
837 dayMaxEvents = null;
838 }
839 let classNames = [
840 'fc-daygrid-body',
841 limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
842 expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
843 ];
844 return (preact.createElement("div", { ref: this.elRef, className: classNames.join(' '), style: {
845 // these props are important to give this wrapper correct dimensions for interactions
846 // TODO: if we set it here, can we avoid giving to inner tables?
847 width: props.clientWidth,
848 minWidth: props.tableMinWidth,
849 } },
850 preact.createElement("table", { role: "presentation", className: "fc-scrollgrid-sync-table", style: {
851 width: props.clientWidth,
852 minWidth: props.tableMinWidth,
853 height: expandRows ? props.clientHeight : '',
854 } },
855 props.colGroupNode,
856 preact.createElement("tbody", { role: "presentation" },
857 preact.createElement(TableRows, { dateProfile: props.dateProfile, cells: props.cells, renderRowIntro: props.renderRowIntro, showWeekNumbers: props.showWeekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, dayMaxEvents: dayMaxEvents, dayMaxEventRows: dayMaxEventRows, forPrint: props.forPrint, isHitComboAllowed: props.isHitComboAllowed })))));
858 }
859 componentDidMount() {
860 this.requestScrollReset();
861 }
862 componentDidUpdate(prevProps) {
863 if (prevProps.dateProfile !== this.props.dateProfile) {
864 this.requestScrollReset();
865 }
866 else {
867 this.flushScrollReset();
868 }
869 }
870 requestScrollReset() {
871 this.needsScrollReset = true;
872 this.flushScrollReset();
873 }
874 flushScrollReset() {
875 if (this.needsScrollReset &&
876 this.props.clientWidth // sizes computed?
877 ) {
878 const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
879 if (subjectEl) {
880 const originEl = subjectEl.closest('.fc-daygrid-body');
881 const scrollEl = originEl.closest('.fc-scroller');
882 const scrollTop = subjectEl.getBoundingClientRect().top -
883 originEl.getBoundingClientRect().top;
884 scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
885 }
886 this.needsScrollReset = false;
887 }
888 }
889 }
890 function getScrollSubjectEl(containerEl, dateProfile) {
891 let el;
892 if (dateProfile.currentRangeUnit.match(/year|month/)) {
893 el = containerEl.querySelector(`[data-date="${internal$1.formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
894 // even if view is month-based, first-of-month might be hidden...
895 }
896 if (!el) {
897 el = containerEl.querySelector(`[data-date="${internal$1.formatDayString(dateProfile.currentDate)}"]`);
898 // could still be hidden if an interior-view hidden day
899 }
900 return el;
901 }
902
903 class DayTableSlicer extends internal$1.Slicer {
904 constructor() {
905 super(...arguments);
906 this.forceDayIfListItem = true;
907 }
908 sliceRange(dateRange, dayTableModel) {
909 return dayTableModel.sliceRange(dateRange);
910 }
911 }
912
913 class DayTable extends internal$1.DateComponent {
914 constructor() {
915 super(...arguments);
916 this.slicer = new DayTableSlicer();
917 this.tableRef = preact.createRef();
918 }
919 render() {
920 let { props, context } = this;
921 return (preact.createElement(Table, Object.assign({ ref: this.tableRef }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), { dateProfile: props.dateProfile, cells: props.dayTableModel.cells, colGroupNode: props.colGroupNode, tableMinWidth: props.tableMinWidth, renderRowIntro: props.renderRowIntro, dayMaxEvents: props.dayMaxEvents, dayMaxEventRows: props.dayMaxEventRows, showWeekNumbers: props.showWeekNumbers, expandRows: props.expandRows, headerAlignElRef: props.headerAlignElRef, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: props.forPrint })));
922 }
923 }
924
925 class DayTableView extends TableView {
926 constructor() {
927 super(...arguments);
928 this.buildDayTableModel = internal$1.memoize(buildDayTableModel);
929 this.headerRef = preact.createRef();
930 this.tableRef = preact.createRef();
931 // can't override any lifecycle methods from parent
932 }
933 render() {
934 let { options, dateProfileGenerator } = this.context;
935 let { props } = this;
936 let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
937 let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { ref: this.headerRef, dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: dayTableModel.rowCnt === 1 }));
938 let bodyContent = (contentArg) => (preact.createElement(DayTable, { ref: this.tableRef, dateProfile: props.dateProfile, dayTableModel: dayTableModel, businessHours: props.businessHours, dateSelection: props.dateSelection, eventStore: props.eventStore, eventUiBases: props.eventUiBases, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, nextDayThreshold: options.nextDayThreshold, colGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, dayMaxEvents: options.dayMaxEvents, dayMaxEventRows: options.dayMaxEventRows, showWeekNumbers: options.weekNumbers, expandRows: !props.isHeightAuto, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }));
939 return options.dayMinWidth
940 ? this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth)
941 : this.renderSimpleLayout(headerContent, bodyContent);
942 }
943 }
944 function buildDayTableModel(dateProfile, dateProfileGenerator) {
945 let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
946 return new internal$1.DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
947 }
948
949 class TableDateProfileGenerator extends internal$1.DateProfileGenerator {
950 // Computes the date range that will be rendered
951 buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
952 let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
953 let { props } = this;
954 return buildDayTableRenderRange({
955 currentRange: renderRange,
956 snapToWeek: /^(year|month)$/.test(currentRangeUnit),
957 fixedWeekCount: props.fixedWeekCount,
958 dateEnv: props.dateEnv,
959 });
960 }
961 }
962 function buildDayTableRenderRange(props) {
963 let { dateEnv, currentRange } = props;
964 let { start, end } = currentRange;
965 let endOfWeek;
966 // year and month views should be aligned with weeks. this is already done for week
967 if (props.snapToWeek) {
968 start = dateEnv.startOfWeek(start);
969 // make end-of-week if not already
970 endOfWeek = dateEnv.startOfWeek(end);
971 if (endOfWeek.valueOf() !== end.valueOf()) {
972 end = internal$1.addWeeks(endOfWeek, 1);
973 }
974 }
975 // ensure 6 weeks
976 if (props.fixedWeekCount) {
977 // TODO: instead of these date-math gymnastics (for multimonth view),
978 // compute dateprofiles of all months, then use start of first and end of last.
979 let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(internal$1.addDays(currentRange.end, -1)));
980 let rowCnt = Math.ceil(// could be partial weeks due to hiddenDays
981 internal$1.diffWeeks(lastMonthRenderStart, end));
982 end = internal$1.addWeeks(end, 6 - rowCnt);
983 }
984 return { start, end };
985 }
986
987 var css_248z = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
988 internal$1.injectStyles(css_248z);
989
990 var plugin = core.createPlugin({
991 name: '@fullcalendar/daygrid',
992 initialView: 'dayGridMonth',
993 views: {
994 dayGrid: {
995 component: DayTableView,
996 dateProfileGeneratorClass: TableDateProfileGenerator,
997 },
998 dayGridDay: {
999 type: 'dayGrid',
1000 duration: { days: 1 },
1001 },
1002 dayGridWeek: {
1003 type: 'dayGrid',
1004 duration: { weeks: 1 },
1005 },
1006 dayGridMonth: {
1007 type: 'dayGrid',
1008 duration: { months: 1 },
1009 fixedWeekCount: true,
1010 },
1011 dayGridYear: {
1012 type: 'dayGrid',
1013 duration: { years: 1 },
1014 },
1015 },
1016 });
1017
1018 var internal = {
1019 __proto__: null,
1020 DayTable: DayTable,
1021 DayTableSlicer: DayTableSlicer,
1022 TableDateProfileGenerator: TableDateProfileGenerator,
1023 buildDayTableRenderRange: buildDayTableRenderRange,
1024 Table: Table,
1025 TableRows: TableRows,
1026 TableView: TableView,
1027 buildDayTableModel: buildDayTableModel,
1028 DayGridView: DayTableView
1029 };
1030
1031 core.globalPlugins.push(plugin);
1032
1033 exports.Internal = internal;
1034 exports["default"] = plugin;
1035
1036 Object.defineProperty(exports, '__esModule', { value: true });
1037
1038 return exports;
1039
1040})({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact);
diff --git a/public/js/fullcalendar/packages/daygrid/index.global.min.js b/public/js/fullcalendar/packages/daygrid/index.global.min.js
new file mode 100644
index 0000000..3ad4721
--- /dev/null
+++ b/public/js/fullcalendar/packages/daygrid/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Day Grid Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/month-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.DayGrid=function(e,t,n,s){"use strict";class i extends n.DateComponent{constructor(){super(...arguments),this.headerElRef=s.createRef()}renderSimpleLayout(e,t){let{props:i,context:r}=this,a=[],l=n.getStickyHeaderDates(r.options);return e&&a.push({type:"header",key:"header",isSticky:l,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),a.push({type:"body",key:"body",liquid:!0,chunk:{content:t}}),s.createElement(n.ViewContainer,{elClasses:["fc-daygrid"],viewSpec:r.viewSpec},s.createElement(n.SimpleScrollGrid,{liquid:!i.isHeightAuto&&!i.forPrint,collapsibleWidth:i.forPrint,cols:[],sections:a}))}renderHScrollLayout(e,t,i,r){let a=this.context.pluginHooks.scrollGridImpl;if(!a)throw new Error("No ScrollGrid implementation");let{props:l,context:o}=this,d=!l.forPrint&&n.getStickyHeaderDates(o.options),c=!l.forPrint&&n.getStickyFooterScrollbar(o.options),g=[];return e&&g.push({type:"header",key:"header",isSticky:d,chunks:[{key:"main",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),g.push({type:"body",key:"body",liquid:!0,chunks:[{key:"main",content:t}]}),c&&g.push({type:"footer",key:"footer",isSticky:!0,chunks:[{key:"main",content:n.renderScrollShim}]}),s.createElement(n.ViewContainer,{elClasses:["fc-daygrid"],viewSpec:o.viewSpec},s.createElement(a,{liquid:!l.isHeightAuto&&!l.forPrint,forPrint:l.forPrint,collapsibleWidth:l.forPrint,colGroups:[{cols:[{span:i,minWidth:r}]}],sections:g}))}}function r(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.row].push(t);return n}function a(e,t){let n=[];for(let e=0;e<t;e+=1)n[e]=[];for(let t of e)n[t.firstCol].push(t);return n}function l(e,t){let n=[];if(e){for(let s=0;s<t;s+=1)n[s]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)n[t.row].segs.push(t)}else for(let e=0;e<t;e+=1)n[e]=null;return n}const o=n.createFormatter({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"});function d(e){let{display:t}=e.eventRange.ui;return"list-item"===t||"auto"===t&&!e.eventRange.def.allDay&&e.firstCol===e.lastCol&&e.isStart&&e.isEnd}class c extends n.BaseComponent{render(){let{props:e}=this;return s.createElement(n.StandardEvent,Object.assign({},e,{elClasses:["fc-daygrid-event","fc-daygrid-block-event","fc-h-event"],defaultTimeFormat:o,defaultDisplayEventEnd:e.defaultDisplayEventEnd,disableResizing:!e.seg.eventRange.def.allDay}))}}class g extends n.BaseComponent{render(){let{props:e,context:t}=this,{options:i}=t,{seg:r}=e,a=i.eventTimeFormat||o,l=n.buildSegTimeText(r,a,t,!0,e.defaultDisplayEventEnd);return s.createElement(n.EventContainer,Object.assign({},e,{elTag:"a",elClasses:["fc-daygrid-event","fc-daygrid-dot-event"],elAttrs:n.getSegAnchorAttrs(e.seg,t),defaultGenerator:f,timeText:l,isResizing:!1,isDateSelecting:!1}))}}function f(e){return s.createElement(s.Fragment,null,s.createElement("div",{className:"fc-daygrid-event-dot",style:{borderColor:e.borderColor||e.backgroundColor}}),e.timeText&&s.createElement("div",{className:"fc-event-time"},e.timeText),s.createElement("div",{className:"fc-event-title"},e.event.title||s.createElement(s.Fragment,null," ")))}class h extends n.BaseComponent{constructor(){super(...arguments),this.compileSegs=n.memoize(u)}render(){let{props:e}=this,{allSegs:t,invisibleSegs:i}=this.compileSegs(e.singlePlacements);return s.createElement(n.MoreLinkContainer,{elClasses:["fc-daygrid-more-link"],dateProfile:e.dateProfile,todayRange:e.todayRange,allDayDate:e.allDayDate,moreCnt:e.moreCnt,allSegs:t,hiddenSegs:i,alignmentElRef:e.alignmentElRef,alignGridTop:e.alignGridTop,extraDateSpan:e.extraDateSpan,popoverContent:()=>{let i=(e.eventDrag?e.eventDrag.affectedInstances:null)||(e.eventResize?e.eventResize.affectedInstances:null)||{};return s.createElement(s.Fragment,null,t.map(t=>{let r=t.eventRange.instance.instanceId;return s.createElement("div",{className:"fc-daygrid-event-harness",key:r,style:{visibility:i[r]?"hidden":""}},d(t)?s.createElement(g,Object.assign({seg:t,isDragging:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},n.getSegMeta(t,e.todayRange))):s.createElement(c,Object.assign({seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:r===e.eventSelection,defaultDisplayEventEnd:!1},n.getSegMeta(t,e.todayRange))))}))}})}}function u(e){let t=[],n=[];for(let s of e)t.push(s.seg),s.isVisible||n.push(s.seg);return{allSegs:t,invisibleSegs:n}}const p=n.createFormatter({week:"narrow"});class m extends n.DateComponent{constructor(){super(...arguments),this.rootElRef=s.createRef(),this.state={dayNumberId:n.getUniqueDomId()},this.handleRootEl=e=>{n.setRef(this.rootElRef,e),n.setRef(this.props.elRef,e)}}render(){let{context:e,props:t,state:i,rootElRef:r}=this,{options:a,dateEnv:l}=e,{date:o,dateProfile:d}=t;const c=t.showDayNumber&&function(e,t,s){const{start:i,end:r}=t,a=n.addMs(r,-1),l=s.getYear(i),o=s.getMonth(i),d=s.getYear(a),c=s.getMonth(a);return!(l===d&&o===c)&&Boolean(e.valueOf()===i.valueOf()||1===s.getDay(e)&&e.valueOf()<r.valueOf())}(o,d.currentRange,l);return s.createElement(n.DayCellContainer,{elTag:"td",elRef:this.handleRootEl,elClasses:["fc-daygrid-day",...t.extraClassNames||[]],elAttrs:Object.assign(Object.assign(Object.assign({},t.extraDataAttrs),t.showDayNumber?{"aria-labelledby":i.dayNumberId}:{}),{role:"gridcell"}),defaultGenerator:y,date:o,dateProfile:d,todayRange:t.todayRange,showDayNumber:t.showDayNumber,isMonthStart:c,extraRenderProps:t.extraRenderProps},(l,d)=>s.createElement("div",{ref:t.innerElRef,className:"fc-daygrid-day-frame fc-scrollgrid-sync-inner",style:{minHeight:t.minHeight}},t.showWeekNumber&&s.createElement(n.WeekNumberContainer,{elTag:"a",elClasses:["fc-daygrid-week-number"],elAttrs:n.buildNavLinkAttrs(e,o,"week"),date:o,defaultFormat:p}),!d.isDisabled&&(t.showDayNumber||n.hasCustomDayCellContent(a)||t.forceDayTop)?s.createElement("div",{className:"fc-daygrid-day-top"},s.createElement(l,{elTag:"a",elClasses:["fc-daygrid-day-number",c&&"fc-daygrid-month-start"],elAttrs:Object.assign(Object.assign({},n.buildNavLinkAttrs(e,o)),{id:i.dayNumberId})})):t.showDayNumber?s.createElement("div",{className:"fc-daygrid-day-top",style:{visibility:"hidden"}},s.createElement("a",{className:"fc-daygrid-day-number"}," ")):void 0,s.createElement("div",{className:"fc-daygrid-day-events",ref:t.fgContentElRef},t.fgContent,s.createElement("div",{className:"fc-daygrid-day-bottom",style:{marginTop:t.moreMarginTop}},s.createElement(h,{allDayDate:o,singlePlacements:t.singlePlacements,moreCnt:t.moreCnt,alignmentElRef:r,alignGridTop:!t.showDayNumber,extraDateSpan:t.extraDateSpan,dateProfile:t.dateProfile,eventSelection:t.eventSelection,eventDrag:t.eventDrag,eventResize:t.eventResize,todayRange:t.todayRange}))),s.createElement("div",{className:"fc-daygrid-day-bg"},t.bgContent)))}}function y(e){return e.dayNumberText||s.createElement(s.Fragment,null," ")}function v(e){return e.eventRange.instance.instanceId+":"+e.firstCol}function b(e){return v(e)+":"+e.lastCol}function R(e,t,n,s,i,r,a){let l=new S(t=>{let n=e[t.index].eventRange.instance.instanceId+":"+t.span.start+":"+(t.span.end-1);return i[n]||1});l.allowReslicing=!0,l.strictOrder=s,!0===t||!0===n?(l.maxCoord=r,l.hiddenConsumes=!0):"number"==typeof t?l.maxStackCnt=t:"number"==typeof n&&(l.maxStackCnt=n,l.hiddenConsumes=!0);let o=[],d=[];for(let t=0;t<e.length;t+=1){let n=e[t],s=b(n);null!=i[s]?o.push({index:t,span:{start:n.firstCol,end:n.lastCol+1}}):d.push(n)}let c=l.addSegs(o),g=l.toRects(),{singleColPlacements:f,multiColPlacements:h,leftoverMargins:u}=function(e,t,n){let s=function(e,t){let n=[];for(let e=0;e<t;e+=1)n.push([]);for(let t of e)for(let e=t.span.start;e<t.span.end;e+=1)n[e].push(t);return n}(e,n.length),i=[],r=[],a=[];for(let e=0;e<n.length;e+=1){let l=s[e],o=[],d=0,c=0;for(let s of l){let i=t[s.index];o.push({seg:E(i,e,e+1,n),isVisible:!0,isAbsolute:!1,absoluteTop:s.levelCoord,marginTop:s.levelCoord-d}),d=s.levelCoord+s.thickness}let g=[];d=0,c=0;for(let s of l){let i=t[s.index],r=s.span.end-s.span.start>1,a=s.span.start===e;c+=s.levelCoord-d,d=s.levelCoord+s.thickness,r?(c+=s.thickness,a&&g.push({seg:E(i,s.span.start,s.span.end,n),isVisible:!0,isAbsolute:!0,absoluteTop:s.levelCoord,marginTop:0})):a&&(g.push({seg:E(i,s.span.start,s.span.end,n),isVisible:!0,isAbsolute:!1,absoluteTop:s.levelCoord,marginTop:c}),c=0)}i.push(o),r.push(g),a.push(c)}return{singleColPlacements:i,multiColPlacements:r,leftoverMargins:a}}(g,e,a),p=[],m=[];for(let e of d){h[e.firstCol].push({seg:e,isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let t=e.firstCol;t<=e.lastCol;t+=1)f[t].push({seg:E(e,t,t+1,a),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<a.length;e+=1)p.push(0);for(let t of c){let n=e[t.index],s=t.span;h[s.start].push({seg:E(n,s.start,s.end,a),isVisible:!1,isAbsolute:!0,absoluteTop:0,marginTop:0});for(let e=s.start;e<s.end;e+=1)p[e]+=1,f[e].push({seg:E(n,e,e+1,a),isVisible:!1,isAbsolute:!1,absoluteTop:0,marginTop:0})}for(let e=0;e<a.length;e+=1)m.push(u[e]);return{singleColPlacements:f,multiColPlacements:h,moreCnts:p,moreMarginTops:m}}function E(e,t,s,i){if(e.firstCol===t&&e.lastCol===s-1)return e;let r=e.eventRange,a=r.range,l=n.intersectRanges(a,{start:i[t].date,end:n.addDays(i[s-1].date,1)});return Object.assign(Object.assign({},e),{firstCol:t,lastCol:s-1,eventRange:{def:r.def,ui:Object.assign(Object.assign({},r.ui),{durationEditable:!1}),instance:r.instance,range:l},isStart:e.isStart&&l.start.valueOf()===a.start.valueOf(),isEnd:e.isEnd&&l.end.valueOf()===a.end.valueOf()})}class S extends n.SegHierarchy{constructor(){super(...arguments),this.hiddenConsumes=!1,this.forceHidden={}}addSegs(e){const t=super.addSegs(e),{entriesByLevel:s}=this,i=e=>!this.forceHidden[n.buildEntryKey(e)];for(let e=0;e<s.length;e+=1)s[e]=s[e].filter(i);return t}handleInvalidInsertion(e,t,s){const{entriesByLevel:i,forceHidden:r}=this,{touchingEntry:a,touchingLevel:l,touchingLateral:o}=e;if(this.hiddenConsumes&&a){const e=n.buildEntryKey(a);if(!r[e])if(this.allowReslicing){const e=Object.assign(Object.assign({},a),{span:n.intersectSpans(a.span,t.span)});r[n.buildEntryKey(e)]=!0,i[l][o]=e,s.push(e),this.splitEntry(a,t,s)}else r[e]=!0,s.push(a)}super.handleInvalidInsertion(e,t,s)}}class x extends n.DateComponent{constructor(){super(...arguments),this.cellElRefs=new n.RefMap,this.frameElRefs=new n.RefMap,this.fgElRefs=new n.RefMap,this.segHarnessRefs=new n.RefMap,this.rootElRef=s.createRef(),this.state={framePositions:null,maxContentHeight:null,segHeights:{}},this.handleResize=e=>{e&&this.updateSizing(!0)}}render(){let{props:e,state:t,context:i}=this,{options:r}=i,l=e.cells.length,o=a(e.businessHourSegs,l),d=a(e.bgEventSegs,l),c=a(this.getHighlightSegs(),l),g=a(this.getMirrorSegs(),l),{singleColPlacements:f,multiColPlacements:h,moreCnts:u,moreMarginTops:p}=R(n.sortEventSegs(e.fgEventSegs,r.eventOrder),e.dayMaxEvents,e.dayMaxEventRows,r.eventOrderStrict,t.segHeights,t.maxContentHeight,e.cells),y=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{};return s.createElement("tr",{ref:this.rootElRef,role:"row"},e.renderIntro&&e.renderIntro(),e.cells.map((t,n)=>{let i=this.renderFgSegs(n,e.forPrint?f[n]:h[n],e.todayRange,y),r=this.renderFgSegs(n,function(e,t){if(!e.length)return[];let n=function(e){let t={};for(let n of e)for(let e of n)t[e.seg.eventRange.instance.instanceId]=e.absoluteTop;return t}(t);return e.map(e=>({seg:e,isVisible:!0,isAbsolute:!0,absoluteTop:n[e.eventRange.instance.instanceId],marginTop:0}))}(g[n],h),e.todayRange,{},Boolean(e.eventDrag),Boolean(e.eventResize),!1);return s.createElement(m,{key:t.key,elRef:this.cellElRefs.createRef(t.key),innerElRef:this.frameElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,showDayNumber:e.showDayNumbers,showWeekNumber:e.showWeekNumbers&&0===n,forceDayTop:e.showWeekNumbers,todayRange:e.todayRange,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,moreCnt:u[n],moreMarginTop:p[n],singlePlacements:f[n],fgContentElRef:this.fgElRefs.createRef(t.key),fgContent:s.createElement(s.Fragment,null,s.createElement(s.Fragment,null,i),s.createElement(s.Fragment,null,r)),bgContent:s.createElement(s.Fragment,null,this.renderFillSegs(c[n],"highlight"),this.renderFillSegs(o[n],"non-business"),this.renderFillSegs(d[n],"bg-event")),minHeight:e.cellMinHeight})}))}componentDidMount(){this.updateSizing(!0),this.context.addResizeHandler(this.handleResize)}componentDidUpdate(e,t){let s=this.props;this.updateSizing(!n.isPropsEqual(e,s))}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}getHighlightSegs(){let{props:e}=this;return e.eventDrag&&e.eventDrag.segs.length?e.eventDrag.segs:e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:e.dateSelectionSegs}getMirrorSegs(){let{props:e}=this;return e.eventResize&&e.eventResize.segs.length?e.eventResize.segs:[]}renderFgSegs(e,t,i,r,a,l,o){let{context:f}=this,{eventSelection:h}=this.props,{framePositions:u}=this.state,p=1===this.props.cells.length,m=a||l||o,y=[];if(u)for(let e of t){let{seg:t}=e,{instanceId:R}=t.eventRange.instance,E=e.isVisible&&!r[R],S=e.isAbsolute,x="",C="";S&&(f.isRtl?(C=0,x=u.lefts[t.lastCol]-u.lefts[t.firstCol]):(x=0,C=u.rights[t.firstCol]-u.rights[t.lastCol])),y.push(s.createElement("div",{className:"fc-daygrid-event-harness"+(S?" fc-daygrid-event-harness-abs":""),key:v(t),ref:m?null:this.segHarnessRefs.createRef(b(t)),style:{visibility:E?"":"hidden",marginTop:S?"":e.marginTop,top:S?e.absoluteTop:"",left:x,right:C}},d(t)?s.createElement(g,Object.assign({seg:t,isDragging:a,isSelected:R===h,defaultDisplayEventEnd:p},n.getSegMeta(t,i))):s.createElement(c,Object.assign({seg:t,isDragging:a,isResizing:l,isDateSelecting:o,isSelected:R===h,defaultDisplayEventEnd:p},n.getSegMeta(t,i)))))}return y}renderFillSegs(e,t){let{isRtl:i}=this.context,{todayRange:r}=this.props,{framePositions:a}=this.state,l=[];if(a)for(let o of e){let e=i?{right:0,left:a.lefts[o.lastCol]-a.lefts[o.firstCol]}:{left:0,right:a.rights[o.firstCol]-a.rights[o.lastCol]};l.push(s.createElement("div",{key:n.buildEventRangeKey(o.eventRange),className:"fc-daygrid-bg-harness",style:e},"bg-event"===t?s.createElement(n.BgEvent,Object.assign({seg:o},n.getSegMeta(o,r))):n.renderFill(t)))}return s.createElement(s.Fragment,{},...l)}updateSizing(e){let{props:t,state:s,frameElRefs:i}=this;if(!t.forPrint&&null!==t.clientWidth){if(e){let e=t.cells.map(e=>i.currentMap[e.key]);if(e.length){let t=this.rootElRef.current,i=new n.PositionCache(t,e,!0,!1);s.framePositions&&s.framePositions.similarTo(i)||this.setState({framePositions:new n.PositionCache(t,e,!0,!1)})}}const r=this.state.segHeights,a=this.querySegHeights(),l=!0===t.dayMaxEvents||!0===t.dayMaxEventRows;this.safeSetState({segHeights:Object.assign(Object.assign({},r),a),maxContentHeight:l?this.computeMaxContentHeight():null})}}querySegHeights(){let e=this.segHarnessRefs.currentMap,t={};for(let n in e){let s=Math.round(e[n].getBoundingClientRect().height);t[n]=Math.max(t[n]||0,s)}return t}computeMaxContentHeight(){let e=this.props.cells[0].key,t=this.cellElRefs.currentMap[e],n=this.fgElRefs.currentMap[e];return t.getBoundingClientRect().bottom-n.getBoundingClientRect().top}getCellEls(){let e=this.cellElRefs.currentMap;return this.props.cells.map(t=>e[t.key])}}x.addStateEquality({segHeights:n.isPropsEqual});class C extends n.DateComponent{constructor(){super(...arguments),this.splitBusinessHourSegs=n.memoize(r),this.splitBgEventSegs=n.memoize(r),this.splitFgEventSegs=n.memoize(r),this.splitDateSelectionSegs=n.memoize(r),this.splitEventDrag=n.memoize(l),this.splitEventResize=n.memoize(l),this.rowRefs=new n.RefMap}render(){let{props:e,context:t}=this,i=e.cells.length,r=this.splitBusinessHourSegs(e.businessHourSegs,i),a=this.splitBgEventSegs(e.bgEventSegs,i),l=this.splitFgEventSegs(e.fgEventSegs,i),o=this.splitDateSelectionSegs(e.dateSelectionSegs,i),d=this.splitEventDrag(e.eventDrag,i),c=this.splitEventResize(e.eventResize,i),g=i>=7&&e.clientWidth?e.clientWidth/t.options.aspectRatio/6:null;return s.createElement(n.NowTimer,{unit:"day"},(t,n)=>s.createElement(s.Fragment,null,e.cells.map((t,f)=>s.createElement(x,{ref:this.rowRefs.createRef(f),key:t.length?t[0].date.toISOString():f,showDayNumbers:i>1,showWeekNumbers:e.showWeekNumbers,todayRange:n,dateProfile:e.dateProfile,cells:t,renderIntro:e.renderRowIntro,businessHourSegs:r[f],eventSelection:e.eventSelection,bgEventSegs:a[f].filter(w),fgEventSegs:l[f],dateSelectionSegs:o[f],eventDrag:d[f],eventResize:c[f],dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,clientWidth:e.clientWidth,clientHeight:e.clientHeight,cellMinHeight:g,forPrint:e.forPrint}))))}componentDidMount(){this.registerInteractiveComponent()}componentDidUpdate(){this.registerInteractiveComponent()}registerInteractiveComponent(){if(!this.rootEl){const e=this.rowRefs.currentMap[0].getCellEls()[0],t=e?e.closest(".fc-daygrid-body"):null;t&&(this.rootEl=t,this.context.registerInteractiveComponent(this,{el:t,isHitComboAllowed:this.props.isHitComboAllowed}))}}componentWillUnmount(){this.rootEl&&(this.context.unregisterInteractiveComponent(this),this.rootEl=null)}prepareHits(){this.rowPositions=new n.PositionCache(this.rootEl,this.rowRefs.collect().map(e=>e.getCellEls()[0]),!1,!0),this.colPositions=new n.PositionCache(this.rootEl,this.rowRefs.currentMap[0].getCellEls(),!0,!1)}queryHit(e,t){let{colPositions:n,rowPositions:s}=this,i=n.leftToIndex(e),r=s.topToIndex(t);if(null!=r&&null!=i){let e=this.props.cells[r][i];return{dateProfile:this.props.dateProfile,dateSpan:Object.assign({range:this.getCellRange(r,i),allDay:!0},e.extraDateSpan),dayEl:this.getCellEl(r,i),rect:{left:n.lefts[i],right:n.rights[i],top:s.tops[r],bottom:s.bottoms[r]},layer:0}}return null}getCellEl(e,t){return this.rowRefs.currentMap[e].getCellEls()[t]}getCellRange(e,t){let s=this.props.cells[e][t].date;return{start:s,end:n.addDays(s,1)}}}function w(e){return e.eventRange.def.allDay}class D extends n.DateComponent{constructor(){super(...arguments),this.elRef=s.createRef(),this.needsScrollReset=!1}render(){let{props:e}=this,{dayMaxEventRows:t,dayMaxEvents:n,expandRows:i}=e,r=!0===n||!0===t;r&&!i&&(r=!1,t=null,n=null);let a=["fc-daygrid-body",r?"fc-daygrid-body-balanced":"fc-daygrid-body-unbalanced",i?"":"fc-daygrid-body-natural"];return s.createElement("div",{ref:this.elRef,className:a.join(" "),style:{width:e.clientWidth,minWidth:e.tableMinWidth}},s.createElement("table",{role:"presentation",className:"fc-scrollgrid-sync-table",style:{width:e.clientWidth,minWidth:e.tableMinWidth,height:i?e.clientHeight:""}},e.colGroupNode,s.createElement("tbody",{role:"presentation"},s.createElement(C,{dateProfile:e.dateProfile,cells:e.cells,renderRowIntro:e.renderRowIntro,showWeekNumbers:e.showWeekNumbers,clientWidth:e.clientWidth,clientHeight:e.clientHeight,businessHourSegs:e.businessHourSegs,bgEventSegs:e.bgEventSegs,fgEventSegs:e.fgEventSegs,dateSelectionSegs:e.dateSelectionSegs,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,dayMaxEvents:n,dayMaxEventRows:t,forPrint:e.forPrint,isHitComboAllowed:e.isHitComboAllowed}))))}componentDidMount(){this.requestScrollReset()}componentDidUpdate(e){e.dateProfile!==this.props.dateProfile?this.requestScrollReset():this.flushScrollReset()}requestScrollReset(){this.needsScrollReset=!0,this.flushScrollReset()}flushScrollReset(){if(this.needsScrollReset&&this.props.clientWidth){const e=function(e,t){let s;t.currentRangeUnit.match(/year|month/)&&(s=e.querySelector(`[data-date="${n.formatIsoMonthStr(t.currentDate)}-01"]`));s||(s=e.querySelector(`[data-date="${n.formatDayString(t.currentDate)}"]`));return s}(this.elRef.current,this.props.dateProfile);if(e){const t=e.closest(".fc-daygrid-body"),n=t.closest(".fc-scroller"),s=e.getBoundingClientRect().top-t.getBoundingClientRect().top;n.scrollTop=s?s+1:0}this.needsScrollReset=!1}}}class k extends n.Slicer{constructor(){super(...arguments),this.forceDayIfListItem=!0}sliceRange(e,t){return t.sliceRange(e)}}class P extends n.DateComponent{constructor(){super(...arguments),this.slicer=new k,this.tableRef=s.createRef()}render(){let{props:e,context:t}=this;return s.createElement(D,Object.assign({ref:this.tableRef},this.slicer.sliceProps(e,e.dateProfile,e.nextDayThreshold,t,e.dayTableModel),{dateProfile:e.dateProfile,cells:e.dayTableModel.cells,colGroupNode:e.colGroupNode,tableMinWidth:e.tableMinWidth,renderRowIntro:e.renderRowIntro,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.showWeekNumbers,expandRows:e.expandRows,headerAlignElRef:e.headerAlignElRef,clientWidth:e.clientWidth,clientHeight:e.clientHeight,forPrint:e.forPrint}))}}class M extends i{constructor(){super(...arguments),this.buildDayTableModel=n.memoize(T),this.headerRef=s.createRef(),this.tableRef=s.createRef()}render(){let{options:e,dateProfileGenerator:t}=this.context,{props:i}=this,r=this.buildDayTableModel(i.dateProfile,t),a=e.dayHeaders&&s.createElement(n.DayHeader,{ref:this.headerRef,dateProfile:i.dateProfile,dates:r.headerDates,datesRepDistinctDays:1===r.rowCnt}),l=t=>s.createElement(P,{ref:this.tableRef,dateProfile:i.dateProfile,dayTableModel:r,businessHours:i.businessHours,dateSelection:i.dateSelection,eventStore:i.eventStore,eventUiBases:i.eventUiBases,eventSelection:i.eventSelection,eventDrag:i.eventDrag,eventResize:i.eventResize,nextDayThreshold:e.nextDayThreshold,colGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,dayMaxEvents:e.dayMaxEvents,dayMaxEventRows:e.dayMaxEventRows,showWeekNumbers:e.weekNumbers,expandRows:!i.isHeightAuto,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:i.forPrint});return e.dayMinWidth?this.renderHScrollLayout(a,l,r.colCnt,e.dayMinWidth):this.renderSimpleLayout(a,l)}}function T(e,t){let s=new n.DaySeriesModel(e.renderRange,t);return new n.DayTableModel(s,/year|month|week/.test(e.currentRangeUnit))}class H extends n.DateProfileGenerator{buildRenderRange(e,t,n){let s=super.buildRenderRange(e,t,n),{props:i}=this;return z({currentRange:s,snapToWeek:/^(year|month)$/.test(t),fixedWeekCount:i.fixedWeekCount,dateEnv:i.dateEnv})}}function z(e){let t,{dateEnv:s,currentRange:i}=e,{start:r,end:a}=i;if(e.snapToWeek&&(r=s.startOfWeek(r),t=s.startOfWeek(a),t.valueOf()!==a.valueOf()&&(a=n.addWeeks(t,1))),e.fixedWeekCount){let e=s.startOfWeek(s.startOfMonth(n.addDays(i.end,-1))),t=Math.ceil(n.diffWeeks(e,a));a=n.addWeeks(a,6-t)}return{start:r,end:a}}n.injectStyles(':root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:"";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:"";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}');var N=t.createPlugin({name:"@fullcalendar/daygrid",initialView:"dayGridMonth",views:{dayGrid:{component:M,dateProfileGeneratorClass:H},dayGridDay:{type:"dayGrid",duration:{days:1}},dayGridWeek:{type:"dayGrid",duration:{weeks:1}},dayGridMonth:{type:"dayGrid",duration:{months:1},fixedWeekCount:!0},dayGridYear:{type:"dayGrid",duration:{years:1}}}}),W={__proto__:null,DayTable:P,DayTableSlicer:k,TableDateProfileGenerator:H,buildDayTableRenderRange:z,Table:D,TableRows:C,TableView:i,buildDayTableModel:T,DayGridView:M};return t.globalPlugins.push(N),e.Internal=W,e.default=N,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal,FullCalendar.Preact); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/google-calendar/index.global.js b/public/js/fullcalendar/packages/google-calendar/index.global.js
new file mode 100644
index 0000000..7c933c3
--- /dev/null
+++ b/public/js/fullcalendar/packages/google-calendar/index.global.js
@@ -0,0 +1,150 @@
1/*!
2FullCalendar Google Calendar Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/google-calendar
4(c) 2024 Adam Shaw
5*/
6FullCalendar.GoogleCalendar = (function (exports, core, internal) {
7 'use strict';
8
9 // TODO: expose somehow
10 const API_BASE = 'https://www.googleapis.com/calendar/v3/calendars';
11 const eventSourceDef = {
12 parseMeta(refined) {
13 let { googleCalendarId } = refined;
14 if (!googleCalendarId && refined.url) {
15 googleCalendarId = parseGoogleCalendarId(refined.url);
16 }
17 if (googleCalendarId) {
18 return {
19 googleCalendarId,
20 googleCalendarApiKey: refined.googleCalendarApiKey,
21 googleCalendarApiBase: refined.googleCalendarApiBase,
22 extraParams: refined.extraParams,
23 };
24 }
25 return null;
26 },
27 fetch(arg, successCallback, errorCallback) {
28 let { dateEnv, options } = arg.context;
29 let meta = arg.eventSource.meta;
30 let apiKey = meta.googleCalendarApiKey || options.googleCalendarApiKey;
31 if (!apiKey) {
32 errorCallback(new Error('Specify a googleCalendarApiKey. See https://fullcalendar.io/docs/google-calendar'));
33 }
34 else {
35 let url = buildUrl(meta);
36 // TODO: make DRY with json-feed-event-source
37 let { extraParams } = meta;
38 let extraParamsObj = typeof extraParams === 'function' ? extraParams() : extraParams;
39 let requestParams = buildRequestParams(arg.range, apiKey, extraParamsObj, dateEnv);
40 return internal.requestJson('GET', url, requestParams).then(([body, response]) => {
41 if (body.error) {
42 errorCallback(new core.JsonRequestError('Google Calendar API: ' + body.error.message, response));
43 }
44 else {
45 successCallback({
46 rawEvents: gcalItemsToRawEventDefs(body.items, requestParams.timeZone),
47 response,
48 });
49 }
50 }, errorCallback);
51 }
52 },
53 };
54 function parseGoogleCalendarId(url) {
55 let match;
56 // detect if the ID was specified as a single string.
57 // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars.
58 if (/^[^/]+@([^/.]+\.)*(google|googlemail|gmail)\.com$/.test(url)) {
59 return url;
60 }
61 if ((match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^/]*)/.exec(url)) ||
62 (match = /^https?:\/\/www.google.com\/calendar\/feeds\/([^/]*)/.exec(url))) {
63 return decodeURIComponent(match[1]);
64 }
65 return null;
66 }
67 function buildUrl(meta) {
68 let apiBase = meta.googleCalendarApiBase;
69 if (!apiBase) {
70 apiBase = API_BASE;
71 }
72 return apiBase + '/' + encodeURIComponent(meta.googleCalendarId) + '/events';
73 }
74 function buildRequestParams(range, apiKey, extraParams, dateEnv) {
75 let params;
76 let startStr;
77 let endStr;
78 if (dateEnv.canComputeOffset) {
79 // strings will naturally have offsets, which GCal needs
80 startStr = dateEnv.formatIso(range.start);
81 endStr = dateEnv.formatIso(range.end);
82 }
83 else {
84 // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day
85 // from the UTC day-start to guarantee we're getting all the events
86 // (start/end will be UTC-coerced dates, so toISOString is okay)
87 startStr = internal.addDays(range.start, -1).toISOString();
88 endStr = internal.addDays(range.end, 1).toISOString();
89 }
90 params = Object.assign(Object.assign({}, (extraParams || {})), { key: apiKey, timeMin: startStr, timeMax: endStr, singleEvents: true, maxResults: 9999 });
91 if (dateEnv.timeZone !== 'local') {
92 params.timeZone = dateEnv.timeZone;
93 }
94 return params;
95 }
96 function gcalItemsToRawEventDefs(items, gcalTimezone) {
97 return items.map((item) => gcalItemToRawEventDef(item, gcalTimezone));
98 }
99 function gcalItemToRawEventDef(item, gcalTimezone) {
100 let url = item.htmlLink || null;
101 // make the URLs for each event show times in the correct timezone
102 if (url && gcalTimezone) {
103 url = injectQsComponent(url, 'ctz=' + gcalTimezone);
104 }
105 return {
106 id: item.id,
107 title: item.summary,
108 start: item.start.dateTime || item.start.date,
109 end: item.end.dateTime || item.end.date,
110 url,
111 location: item.location,
112 description: item.description,
113 attachments: item.attachments || [],
114 extendedProps: (item.extendedProperties || {}).shared || {},
115 };
116 }
117 // Injects a string like "arg=value" into the querystring of a URL
118 // TODO: move to a general util file?
119 function injectQsComponent(url, component) {
120 // inject it after the querystring but before the fragment
121 return url.replace(/(\?.*?)?(#|$)/, (whole, qs, hash) => (qs ? qs + '&' : '?') + component + hash);
122 }
123
124 const OPTION_REFINERS = {
125 googleCalendarApiKey: String,
126 };
127
128 const EVENT_SOURCE_REFINERS = {
129 googleCalendarApiKey: String,
130 googleCalendarId: String,
131 googleCalendarApiBase: String,
132 extraParams: internal.identity,
133 };
134
135 var plugin = core.createPlugin({
136 name: '@fullcalendar/google-calendar',
137 eventSourceDefs: [eventSourceDef],
138 optionRefiners: OPTION_REFINERS,
139 eventSourceRefiners: EVENT_SOURCE_REFINERS,
140 });
141
142 core.globalPlugins.push(plugin);
143
144 exports["default"] = plugin;
145
146 Object.defineProperty(exports, '__esModule', { value: true });
147
148 return exports;
149
150})({}, FullCalendar, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/google-calendar/index.global.min.js b/public/js/fullcalendar/packages/google-calendar/index.global.min.js
new file mode 100644
index 0000000..e3f365b
--- /dev/null
+++ b/public/js/fullcalendar/packages/google-calendar/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Google Calendar Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/google-calendar
4(c) 2024 Adam Shaw
5*/
6FullCalendar.GoogleCalendar=function(e,a,t){"use strict";const n={parseMeta(e){let{googleCalendarId:a}=e;return!a&&e.url&&(a=function(e){let a;if(/^[^/]+@([^/.]+\.)*(google|googlemail|gmail)\.com$/.test(e))return e;if((a=/^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^/]*)/.exec(e))||(a=/^https?:\/\/www.google.com\/calendar\/feeds\/([^/]*)/.exec(e)))return decodeURIComponent(a[1]);return null}(e.url)),a?{googleCalendarId:a,googleCalendarApiKey:e.googleCalendarApiKey,googleCalendarApiBase:e.googleCalendarApiBase,extraParams:e.extraParams}:null},fetch(e,n,r){let{dateEnv:o,options:l}=e.context,s=e.eventSource.meta,i=s.googleCalendarApiKey||l.googleCalendarApiKey;if(i){let l=function(e){let a=e.googleCalendarApiBase;a||(a="https://www.googleapis.com/calendar/v3/calendars");return a+"/"+encodeURIComponent(e.googleCalendarId)+"/events"}(s),{extraParams:d}=s,g="function"==typeof d?d():d,c=function(e,a,n,r){let o,l,s;r.canComputeOffset?(l=r.formatIso(e.start),s=r.formatIso(e.end)):(l=t.addDays(e.start,-1).toISOString(),s=t.addDays(e.end,1).toISOString());o=Object.assign(Object.assign({},n||{}),{key:a,timeMin:l,timeMax:s,singleEvents:!0,maxResults:9999}),"local"!==r.timeZone&&(o.timeZone=r.timeZone);return o}(e.range,i,g,o);return t.requestJson("GET",l,c).then(([e,t])=>{var o,l;e.error?r(new a.JsonRequestError("Google Calendar API: "+e.error.message,t)):n({rawEvents:(o=e.items,l=c.timeZone,o.map(e=>function(e,a){let t=e.htmlLink||null;t&&a&&(t=function(e,a){return e.replace(/(\?.*?)?(#|$)/,(e,t,n)=>(t?t+"&":"?")+a+n)}(t,"ctz="+a));return{id:e.id,title:e.summary,start:e.start.dateTime||e.start.date,end:e.end.dateTime||e.end.date,url:t,location:e.location,description:e.description,attachments:e.attachments||[],extendedProps:(e.extendedProperties||{}).shared||{}}}(e,l))),response:t})},r)}r(new Error("Specify a googleCalendarApiKey. See https://fullcalendar.io/docs/google-calendar"))}};const r={googleCalendarApiKey:String},o={googleCalendarApiKey:String,googleCalendarId:String,googleCalendarApiBase:String,extraParams:t.identity};var l=a.createPlugin({name:"@fullcalendar/google-calendar",eventSourceDefs:[n],optionRefiners:r,eventSourceRefiners:o});return a.globalPlugins.push(l),e.default=l,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/icalendar/index.global.js b/public/js/fullcalendar/packages/icalendar/index.global.js
new file mode 100644
index 0000000..1c965f6
--- /dev/null
+++ b/public/js/fullcalendar/packages/icalendar/index.global.js
@@ -0,0 +1,225 @@
1/*!
2FullCalendar iCalendar Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/icalendar
4(c) 2024 Adam Shaw
5*/
6FullCalendar.ICalendar = (function (exports, core, internal, ICAL) {
7 'use strict';
8
9 function _interopNamespace(e) {
10 if (e && e.__esModule) return e;
11 var n = Object.create(null);
12 if (e) {
13 Object.keys(e).forEach(function (k) {
14 if (k !== 'default') {
15 var d = Object.getOwnPropertyDescriptor(e, k);
16 Object.defineProperty(n, k, d.get ? d : {
17 enumerable: true,
18 get: function () { return e[k]; }
19 });
20 }
21 });
22 }
23 n["default"] = e;
24 return n;
25 }
26
27 var ICAL__namespace = /*#__PURE__*/_interopNamespace(ICAL);
28
29 /* eslint-disable */
30 class IcalExpander {
31 constructor(opts) {
32 this.maxIterations = opts.maxIterations != null ? opts.maxIterations : 1000;
33 this.skipInvalidDates = opts.skipInvalidDates != null ? opts.skipInvalidDates : false;
34 this.jCalData = ICAL__namespace.parse(opts.ics);
35 this.component = new ICAL__namespace.Component(this.jCalData);
36 this.events = this.component.getAllSubcomponents('vevent').map(vevent => new ICAL__namespace.Event(vevent));
37 if (this.skipInvalidDates) {
38 this.events = this.events.filter((evt) => {
39 try {
40 evt.startDate.toJSDate();
41 evt.endDate.toJSDate();
42 return true;
43 }
44 catch (err) {
45 // skipping events with invalid time
46 return false;
47 }
48 });
49 }
50 }
51 between(after, before) {
52 function isEventWithinRange(startTime, endTime) {
53 return (!after || endTime >= after.getTime()) &&
54 (!before || startTime <= before.getTime());
55 }
56 function getTimes(eventOrOccurrence) {
57 const startTime = eventOrOccurrence.startDate.toJSDate().getTime();
58 let endTime = eventOrOccurrence.endDate.toJSDate().getTime();
59 // If it is an all day event, the end date is set to 00:00 of the next day
60 // So we need to make it be 23:59:59 to compare correctly with the given range
61 if (eventOrOccurrence.endDate.isDate && (endTime > startTime)) {
62 endTime -= 1;
63 }
64 return { startTime, endTime };
65 }
66 const exceptions = [];
67 this.events.forEach((event) => {
68 if (event.isRecurrenceException())
69 exceptions.push(event);
70 });
71 const ret = {
72 events: [],
73 occurrences: [],
74 };
75 this.events.filter(e => !e.isRecurrenceException()).forEach((event) => {
76 const exdates = [];
77 event.component.getAllProperties('exdate').forEach((exdateProp) => {
78 const exdate = exdateProp.getFirstValue();
79 exdates.push(exdate.toJSDate().getTime());
80 });
81 // Recurring event is handled differently
82 if (event.isRecurring()) {
83 const iterator = event.iterator();
84 let next;
85 let i = 0;
86 do {
87 i += 1;
88 next = iterator.next();
89 if (next) {
90 const occurrence = event.getOccurrenceDetails(next);
91 const { startTime, endTime } = getTimes(occurrence);
92 const isOccurrenceExcluded = exdates.indexOf(startTime) !== -1;
93 // TODO check that within same day?
94 const exception = exceptions.find(ex => ex.uid === event.uid && ex.recurrenceId.toJSDate().getTime() === occurrence.startDate.toJSDate().getTime());
95 // We have passed the max date, stop
96 if (before && startTime > before.getTime())
97 break;
98 // Check that we are within our range
99 if (isEventWithinRange(startTime, endTime)) {
100 if (exception) {
101 ret.events.push(exception);
102 }
103 else if (!isOccurrenceExcluded) {
104 ret.occurrences.push(occurrence);
105 }
106 }
107 }
108 } while (next && (!this.maxIterations || i < this.maxIterations));
109 return;
110 }
111 // Non-recurring event:
112 const { startTime, endTime } = getTimes(event);
113 if (isEventWithinRange(startTime, endTime))
114 ret.events.push(event);
115 });
116 return ret;
117 }
118 before(before) {
119 return this.between(undefined, before);
120 }
121 after(after) {
122 return this.between(after);
123 }
124 all() {
125 return this.between();
126 }
127 }
128
129 const eventSourceDef = {
130 parseMeta(refined) {
131 if (refined.url && refined.format === 'ics') {
132 return {
133 url: refined.url,
134 format: 'ics',
135 };
136 }
137 return null;
138 },
139 fetch(arg, successCallback, errorCallback) {
140 let meta = arg.eventSource.meta;
141 let { internalState } = meta;
142 /*
143 NOTE: isRefetch is a HACK. we would do the recurring-expanding in a separate plugin hook,
144 but we couldn't leverage built-in allDay-guessing, among other things.
145 */
146 if (!internalState || arg.isRefetch) {
147 internalState = meta.internalState = {
148 response: null,
149 iCalExpanderPromise: fetch(meta.url, { method: 'GET' }).then((response) => {
150 return response.text().then((icsText) => {
151 internalState.response = response;
152 return new IcalExpander({
153 ics: icsText,
154 skipInvalidDates: true,
155 });
156 });
157 }),
158 };
159 }
160 internalState.iCalExpanderPromise.then((iCalExpander) => {
161 successCallback({
162 rawEvents: expandICalEvents(iCalExpander, arg.range),
163 response: internalState.response,
164 });
165 }, errorCallback);
166 },
167 };
168 function expandICalEvents(iCalExpander, range) {
169 // expand the range. because our `range` is timeZone-agnostic UTC
170 // or maybe because ical.js always produces dates in local time? i forget
171 let rangeStart = internal.addDays(range.start, -1);
172 let rangeEnd = internal.addDays(range.end, 1);
173 let iCalRes = iCalExpander.between(rangeStart, rangeEnd); // end inclusive. will give extra results
174 let expanded = [];
175 // TODO: instead of using startDate/endDate.toString to communicate allDay,
176 // we can query startDate/endDate.isDate. More efficient to avoid formatting/reparsing.
177 // single events
178 for (let iCalEvent of iCalRes.events) {
179 expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalEvent.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalEvent.endDate)
180 ? iCalEvent.endDate.toString()
181 : null }));
182 }
183 // recurring event instances
184 for (let iCalOccurence of iCalRes.occurrences) {
185 let iCalEvent = iCalOccurence.item;
186 expanded.push(Object.assign(Object.assign({}, buildNonDateProps(iCalEvent)), { start: iCalOccurence.startDate.toString(), end: (specifiesEnd(iCalEvent) && iCalOccurence.endDate)
187 ? iCalOccurence.endDate.toString()
188 : null }));
189 }
190 return expanded;
191 }
192 function buildNonDateProps(iCalEvent) {
193 return {
194 title: iCalEvent.summary,
195 url: extractEventUrl(iCalEvent),
196 extendedProps: {
197 location: iCalEvent.location,
198 organizer: iCalEvent.organizer,
199 description: iCalEvent.description,
200 },
201 };
202 }
203 function extractEventUrl(iCalEvent) {
204 let urlProp = iCalEvent.component.getFirstProperty('url');
205 return urlProp ? urlProp.getFirstValue() : '';
206 }
207 function specifiesEnd(iCalEvent) {
208 return Boolean(iCalEvent.component.getFirstProperty('dtend')) ||
209 Boolean(iCalEvent.component.getFirstProperty('duration'));
210 }
211
212 var plugin = core.createPlugin({
213 name: '@fullcalendar/icalendar',
214 eventSourceDefs: [eventSourceDef],
215 });
216
217 core.globalPlugins.push(plugin);
218
219 exports["default"] = plugin;
220
221 Object.defineProperty(exports, '__esModule', { value: true });
222
223 return exports;
224
225})({}, FullCalendar, FullCalendar.Internal, ICAL);
diff --git a/public/js/fullcalendar/packages/icalendar/index.global.min.js b/public/js/fullcalendar/packages/icalendar/index.global.min.js
new file mode 100644
index 0000000..2b97493
--- /dev/null
+++ b/public/js/fullcalendar/packages/icalendar/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar iCalendar Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/icalendar
4(c) 2024 Adam Shaw
5*/
6FullCalendar.ICalendar=function(e,t,n,r){"use strict";function a(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,t}var s=a(r);class i{constructor(e){this.maxIterations=null!=e.maxIterations?e.maxIterations:1e3,this.skipInvalidDates=null!=e.skipInvalidDates&&e.skipInvalidDates,this.jCalData=s.parse(e.ics),this.component=new s.Component(this.jCalData),this.events=this.component.getAllSubcomponents("vevent").map(e=>new s.Event(e)),this.skipInvalidDates&&(this.events=this.events.filter(e=>{try{return e.startDate.toJSDate(),e.endDate.toJSDate(),!0}catch(e){return!1}}))}between(e,t){function n(n,r){return(!e||r>=e.getTime())&&(!t||n<=t.getTime())}function r(e){const t=e.startDate.toJSDate().getTime();let n=e.endDate.toJSDate().getTime();return e.endDate.isDate&&n>t&&(n-=1),{startTime:t,endTime:n}}const a=[];this.events.forEach(e=>{e.isRecurrenceException()&&a.push(e)});const s={events:[],occurrences:[]};return this.events.filter(e=>!e.isRecurrenceException()).forEach(e=>{const i=[];if(e.component.getAllProperties("exdate").forEach(e=>{const t=e.getFirstValue();i.push(t.toJSDate().getTime())}),e.isRecurring()){const o=e.iterator();let c,l=0;do{if(l+=1,c=o.next(),c){const o=e.getOccurrenceDetails(c),{startTime:l,endTime:u}=r(o),d=-1!==i.indexOf(l),p=a.find(t=>t.uid===e.uid&&t.recurrenceId.toJSDate().getTime()===o.startDate.toJSDate().getTime());if(t&&l>t.getTime())break;n(l,u)&&(p?s.events.push(p):d||s.occurrences.push(o))}}while(c&&(!this.maxIterations||l<this.maxIterations));return}const{startTime:o,endTime:c}=r(e);n(o,c)&&s.events.push(e)}),s}before(e){return this.between(void 0,e)}after(e){return this.between(e)}all(){return this.between()}}const o={parseMeta:e=>e.url&&"ics"===e.format?{url:e.url,format:"ics"}:null,fetch(e,t,n){let r=e.eventSource.meta,{internalState:a}=r;a&&!e.isRefetch||(a=r.internalState={response:null,iCalExpanderPromise:fetch(r.url,{method:"GET"}).then(e=>e.text().then(t=>(a.response=e,new i({ics:t,skipInvalidDates:!0}))))}),a.iCalExpanderPromise.then(n=>{t({rawEvents:c(n,e.range),response:a.response})},n)}};function c(e,t){let r=n.addDays(t.start,-1),a=n.addDays(t.end,1),s=e.between(r,a),i=[];for(let e of s.events)i.push(Object.assign(Object.assign({},l(e)),{start:e.startDate.toString(),end:d(e)&&e.endDate?e.endDate.toString():null}));for(let e of s.occurrences){let t=e.item;i.push(Object.assign(Object.assign({},l(t)),{start:e.startDate.toString(),end:d(t)&&e.endDate?e.endDate.toString():null}))}return i}function l(e){return{title:e.summary,url:u(e),extendedProps:{location:e.location,organizer:e.organizer,description:e.description}}}function u(e){let t=e.component.getFirstProperty("url");return t?t.getFirstValue():""}function d(e){return Boolean(e.component.getFirstProperty("dtend"))||Boolean(e.component.getFirstProperty("duration"))}var p=t.createPlugin({name:"@fullcalendar/icalendar",eventSourceDefs:[o]});return t.globalPlugins.push(p),e.default=p,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal,ICAL); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/interaction/index.global.js b/public/js/fullcalendar/packages/interaction/index.global.js
new file mode 100644
index 0000000..d05a22e
--- /dev/null
+++ b/public/js/fullcalendar/packages/interaction/index.global.js
@@ -0,0 +1,2141 @@
1/*!
2FullCalendar Interaction Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/editable
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Interaction = (function (exports, core, internal) {
7 'use strict';
8
9 internal.config.touchMouseIgnoreWait = 500;
10 let ignoreMouseDepth = 0;
11 let listenerCnt = 0;
12 let isWindowTouchMoveCancelled = false;
13 /*
14 Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
15 Tracks when the pointer "drags" on a certain element, meaning down+move+up.
16
17 Also, tracks if there was touch-scrolling.
18 Also, can prevent touch-scrolling from happening.
19 Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.
20
21 emits:
22 - pointerdown
23 - pointermove
24 - pointerup
25 */
26 class PointerDragging {
27 constructor(containerEl) {
28 this.subjectEl = null;
29 // options that can be directly assigned by caller
30 this.selector = ''; // will cause subjectEl in all emitted events to be this element
31 this.handleSelector = '';
32 this.shouldIgnoreMove = false;
33 this.shouldWatchScroll = true; // for simulating pointermove on scroll
34 // internal states
35 this.isDragging = false;
36 this.isTouchDragging = false;
37 this.wasTouchScroll = false;
38 // Mouse
39 // ----------------------------------------------------------------------------------------------------
40 this.handleMouseDown = (ev) => {
41 if (!this.shouldIgnoreMouse() &&
42 isPrimaryMouseButton(ev) &&
43 this.tryStart(ev)) {
44 let pev = this.createEventFromMouse(ev, true);
45 this.emitter.trigger('pointerdown', pev);
46 this.initScrollWatch(pev);
47 if (!this.shouldIgnoreMove) {
48 document.addEventListener('mousemove', this.handleMouseMove);
49 }
50 document.addEventListener('mouseup', this.handleMouseUp);
51 }
52 };
53 this.handleMouseMove = (ev) => {
54 let pev = this.createEventFromMouse(ev);
55 this.recordCoords(pev);
56 this.emitter.trigger('pointermove', pev);
57 };
58 this.handleMouseUp = (ev) => {
59 document.removeEventListener('mousemove', this.handleMouseMove);
60 document.removeEventListener('mouseup', this.handleMouseUp);
61 this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
62 this.cleanup(); // call last so that pointerup has access to props
63 };
64 // Touch
65 // ----------------------------------------------------------------------------------------------------
66 this.handleTouchStart = (ev) => {
67 if (this.tryStart(ev)) {
68 this.isTouchDragging = true;
69 let pev = this.createEventFromTouch(ev, true);
70 this.emitter.trigger('pointerdown', pev);
71 this.initScrollWatch(pev);
72 // unlike mouse, need to attach to target, not document
73 // https://stackoverflow.com/a/45760014
74 let targetEl = ev.target;
75 if (!this.shouldIgnoreMove) {
76 targetEl.addEventListener('touchmove', this.handleTouchMove);
77 }
78 targetEl.addEventListener('touchend', this.handleTouchEnd);
79 targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
80 // attach a handler to get called when ANY scroll action happens on the page.
81 // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
82 // http://stackoverflow.com/a/32954565/96342
83 window.addEventListener('scroll', this.handleTouchScroll, true);
84 }
85 };
86 this.handleTouchMove = (ev) => {
87 let pev = this.createEventFromTouch(ev);
88 this.recordCoords(pev);
89 this.emitter.trigger('pointermove', pev);
90 };
91 this.handleTouchEnd = (ev) => {
92 if (this.isDragging) { // done to guard against touchend followed by touchcancel
93 let targetEl = ev.target;
94 targetEl.removeEventListener('touchmove', this.handleTouchMove);
95 targetEl.removeEventListener('touchend', this.handleTouchEnd);
96 targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
97 window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
98 this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
99 this.cleanup(); // call last so that pointerup has access to props
100 this.isTouchDragging = false;
101 startIgnoringMouse();
102 }
103 };
104 this.handleTouchScroll = () => {
105 this.wasTouchScroll = true;
106 };
107 this.handleScroll = (ev) => {
108 if (!this.shouldIgnoreMove) {
109 let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX;
110 let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY;
111 this.emitter.trigger('pointermove', {
112 origEvent: ev,
113 isTouch: this.isTouchDragging,
114 subjectEl: this.subjectEl,
115 pageX,
116 pageY,
117 deltaX: pageX - this.origPageX,
118 deltaY: pageY - this.origPageY,
119 });
120 }
121 };
122 this.containerEl = containerEl;
123 this.emitter = new internal.Emitter();
124 containerEl.addEventListener('mousedown', this.handleMouseDown);
125 containerEl.addEventListener('touchstart', this.handleTouchStart, { passive: true });
126 listenerCreated();
127 }
128 destroy() {
129 this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
130 this.containerEl.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
131 listenerDestroyed();
132 }
133 tryStart(ev) {
134 let subjectEl = this.querySubjectEl(ev);
135 let downEl = ev.target;
136 if (subjectEl &&
137 (!this.handleSelector || internal.elementClosest(downEl, this.handleSelector))) {
138 this.subjectEl = subjectEl;
139 this.isDragging = true; // do this first so cancelTouchScroll will work
140 this.wasTouchScroll = false;
141 return true;
142 }
143 return false;
144 }
145 cleanup() {
146 isWindowTouchMoveCancelled = false;
147 this.isDragging = false;
148 this.subjectEl = null;
149 // keep wasTouchScroll around for later access
150 this.destroyScrollWatch();
151 }
152 querySubjectEl(ev) {
153 if (this.selector) {
154 return internal.elementClosest(ev.target, this.selector);
155 }
156 return this.containerEl;
157 }
158 shouldIgnoreMouse() {
159 return ignoreMouseDepth || this.isTouchDragging;
160 }
161 // can be called by user of this class, to cancel touch-based scrolling for the current drag
162 cancelTouchScroll() {
163 if (this.isDragging) {
164 isWindowTouchMoveCancelled = true;
165 }
166 }
167 // Scrolling that simulates pointermoves
168 // ----------------------------------------------------------------------------------------------------
169 initScrollWatch(ev) {
170 if (this.shouldWatchScroll) {
171 this.recordCoords(ev);
172 window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
173 }
174 }
175 recordCoords(ev) {
176 if (this.shouldWatchScroll) {
177 this.prevPageX = ev.pageX;
178 this.prevPageY = ev.pageY;
179 this.prevScrollX = window.scrollX;
180 this.prevScrollY = window.scrollY;
181 }
182 }
183 destroyScrollWatch() {
184 if (this.shouldWatchScroll) {
185 window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
186 }
187 }
188 // Event Normalization
189 // ----------------------------------------------------------------------------------------------------
190 createEventFromMouse(ev, isFirst) {
191 let deltaX = 0;
192 let deltaY = 0;
193 // TODO: repeat code
194 if (isFirst) {
195 this.origPageX = ev.pageX;
196 this.origPageY = ev.pageY;
197 }
198 else {
199 deltaX = ev.pageX - this.origPageX;
200 deltaY = ev.pageY - this.origPageY;
201 }
202 return {
203 origEvent: ev,
204 isTouch: false,
205 subjectEl: this.subjectEl,
206 pageX: ev.pageX,
207 pageY: ev.pageY,
208 deltaX,
209 deltaY,
210 };
211 }
212 createEventFromTouch(ev, isFirst) {
213 let touches = ev.touches;
214 let pageX;
215 let pageY;
216 let deltaX = 0;
217 let deltaY = 0;
218 // if touch coords available, prefer,
219 // because FF would give bad ev.pageX ev.pageY
220 if (touches && touches.length) {
221 pageX = touches[0].pageX;
222 pageY = touches[0].pageY;
223 }
224 else {
225 pageX = ev.pageX;
226 pageY = ev.pageY;
227 }
228 // TODO: repeat code
229 if (isFirst) {
230 this.origPageX = pageX;
231 this.origPageY = pageY;
232 }
233 else {
234 deltaX = pageX - this.origPageX;
235 deltaY = pageY - this.origPageY;
236 }
237 return {
238 origEvent: ev,
239 isTouch: true,
240 subjectEl: this.subjectEl,
241 pageX,
242 pageY,
243 deltaX,
244 deltaY,
245 };
246 }
247 }
248 // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
249 function isPrimaryMouseButton(ev) {
250 return ev.button === 0 && !ev.ctrlKey;
251 }
252 // Ignoring fake mouse events generated by touch
253 // ----------------------------------------------------------------------------------------------------
254 function startIgnoringMouse() {
255 ignoreMouseDepth += 1;
256 setTimeout(() => {
257 ignoreMouseDepth -= 1;
258 }, internal.config.touchMouseIgnoreWait);
259 }
260 // We want to attach touchmove as early as possible for Safari
261 // ----------------------------------------------------------------------------------------------------
262 function listenerCreated() {
263 listenerCnt += 1;
264 if (listenerCnt === 1) {
265 window.addEventListener('touchmove', onWindowTouchMove, { passive: false });
266 }
267 }
268 function listenerDestroyed() {
269 listenerCnt -= 1;
270 if (!listenerCnt) {
271 window.removeEventListener('touchmove', onWindowTouchMove, { passive: false });
272 }
273 }
274 function onWindowTouchMove(ev) {
275 if (isWindowTouchMoveCancelled) {
276 ev.preventDefault();
277 }
278 }
279
280 /*
281 An effect in which an element follows the movement of a pointer across the screen.
282 The moving element is a clone of some other element.
283 Must call start + handleMove + stop.
284 */
285 class ElementMirror {
286 constructor() {
287 this.isVisible = false; // must be explicitly enabled
288 this.sourceEl = null;
289 this.mirrorEl = null;
290 this.sourceElRect = null; // screen coords relative to viewport
291 // options that can be set directly by caller
292 this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
293 this.zIndex = 9999;
294 this.revertDuration = 0;
295 }
296 start(sourceEl, pageX, pageY) {
297 this.sourceEl = sourceEl;
298 this.sourceElRect = this.sourceEl.getBoundingClientRect();
299 this.origScreenX = pageX - window.scrollX;
300 this.origScreenY = pageY - window.scrollY;
301 this.deltaX = 0;
302 this.deltaY = 0;
303 this.updateElPosition();
304 }
305 handleMove(pageX, pageY) {
306 this.deltaX = (pageX - window.scrollX) - this.origScreenX;
307 this.deltaY = (pageY - window.scrollY) - this.origScreenY;
308 this.updateElPosition();
309 }
310 // can be called before start
311 setIsVisible(bool) {
312 if (bool) {
313 if (!this.isVisible) {
314 if (this.mirrorEl) {
315 this.mirrorEl.style.display = '';
316 }
317 this.isVisible = bool; // needs to happen before updateElPosition
318 this.updateElPosition(); // because was not updating the position while invisible
319 }
320 }
321 else if (this.isVisible) {
322 if (this.mirrorEl) {
323 this.mirrorEl.style.display = 'none';
324 }
325 this.isVisible = bool;
326 }
327 }
328 // always async
329 stop(needsRevertAnimation, callback) {
330 let done = () => {
331 this.cleanup();
332 callback();
333 };
334 if (needsRevertAnimation &&
335 this.mirrorEl &&
336 this.isVisible &&
337 this.revertDuration && // if 0, transition won't work
338 (this.deltaX || this.deltaY) // if same coords, transition won't work
339 ) {
340 this.doRevertAnimation(done, this.revertDuration);
341 }
342 else {
343 setTimeout(done, 0);
344 }
345 }
346 doRevertAnimation(callback, revertDuration) {
347 let mirrorEl = this.mirrorEl;
348 let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
349 mirrorEl.style.transition =
350 'top ' + revertDuration + 'ms,' +
351 'left ' + revertDuration + 'ms';
352 internal.applyStyle(mirrorEl, {
353 left: finalSourceElRect.left,
354 top: finalSourceElRect.top,
355 });
356 internal.whenTransitionDone(mirrorEl, () => {
357 mirrorEl.style.transition = '';
358 callback();
359 });
360 }
361 cleanup() {
362 if (this.mirrorEl) {
363 internal.removeElement(this.mirrorEl);
364 this.mirrorEl = null;
365 }
366 this.sourceEl = null;
367 }
368 updateElPosition() {
369 if (this.sourceEl && this.isVisible) {
370 internal.applyStyle(this.getMirrorEl(), {
371 left: this.sourceElRect.left + this.deltaX,
372 top: this.sourceElRect.top + this.deltaY,
373 });
374 }
375 }
376 getMirrorEl() {
377 let sourceElRect = this.sourceElRect;
378 let mirrorEl = this.mirrorEl;
379 if (!mirrorEl) {
380 mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
381 // we don't want long taps or any mouse interaction causing selection/menus.
382 // would use preventSelection(), but that prevents selectstart, causing problems.
383 mirrorEl.style.userSelect = 'none';
384 mirrorEl.style.webkitUserSelect = 'none';
385 mirrorEl.style.pointerEvents = 'none';
386 mirrorEl.classList.add('fc-event-dragging');
387 internal.applyStyle(mirrorEl, {
388 position: 'fixed',
389 zIndex: this.zIndex,
390 visibility: '',
391 boxSizing: 'border-box',
392 width: sourceElRect.right - sourceElRect.left,
393 height: sourceElRect.bottom - sourceElRect.top,
394 right: 'auto',
395 bottom: 'auto',
396 margin: 0,
397 });
398 this.parentNode.appendChild(mirrorEl);
399 }
400 return mirrorEl;
401 }
402 }
403
404 /*
405 Is a cache for a given element's scroll information (all the info that ScrollController stores)
406 in addition the "client rectangle" of the element.. the area within the scrollbars.
407
408 The cache can be in one of two modes:
409 - doesListening:false - ignores when the container is scrolled by someone else
410 - doesListening:true - watch for scrolling and update the cache
411 */
412 class ScrollGeomCache extends internal.ScrollController {
413 constructor(scrollController, doesListening) {
414 super();
415 this.handleScroll = () => {
416 this.scrollTop = this.scrollController.getScrollTop();
417 this.scrollLeft = this.scrollController.getScrollLeft();
418 this.handleScrollChange();
419 };
420 this.scrollController = scrollController;
421 this.doesListening = doesListening;
422 this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
423 this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
424 this.scrollWidth = scrollController.getScrollWidth();
425 this.scrollHeight = scrollController.getScrollHeight();
426 this.clientWidth = scrollController.getClientWidth();
427 this.clientHeight = scrollController.getClientHeight();
428 this.clientRect = this.computeClientRect(); // do last in case it needs cached values
429 if (this.doesListening) {
430 this.getEventTarget().addEventListener('scroll', this.handleScroll);
431 }
432 }
433 destroy() {
434 if (this.doesListening) {
435 this.getEventTarget().removeEventListener('scroll', this.handleScroll);
436 }
437 }
438 getScrollTop() {
439 return this.scrollTop;
440 }
441 getScrollLeft() {
442 return this.scrollLeft;
443 }
444 setScrollTop(top) {
445 this.scrollController.setScrollTop(top);
446 if (!this.doesListening) {
447 // we are not relying on the element to normalize out-of-bounds scroll values
448 // so we need to sanitize ourselves
449 this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
450 this.handleScrollChange();
451 }
452 }
453 setScrollLeft(top) {
454 this.scrollController.setScrollLeft(top);
455 if (!this.doesListening) {
456 // we are not relying on the element to normalize out-of-bounds scroll values
457 // so we need to sanitize ourselves
458 this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
459 this.handleScrollChange();
460 }
461 }
462 getClientWidth() {
463 return this.clientWidth;
464 }
465 getClientHeight() {
466 return this.clientHeight;
467 }
468 getScrollWidth() {
469 return this.scrollWidth;
470 }
471 getScrollHeight() {
472 return this.scrollHeight;
473 }
474 handleScrollChange() {
475 }
476 }
477
478 class ElementScrollGeomCache extends ScrollGeomCache {
479 constructor(el, doesListening) {
480 super(new internal.ElementScrollController(el), doesListening);
481 }
482 getEventTarget() {
483 return this.scrollController.el;
484 }
485 computeClientRect() {
486 return internal.computeInnerRect(this.scrollController.el);
487 }
488 }
489
490 class WindowScrollGeomCache extends ScrollGeomCache {
491 constructor(doesListening) {
492 super(new internal.WindowScrollController(), doesListening);
493 }
494 getEventTarget() {
495 return window;
496 }
497 computeClientRect() {
498 return {
499 left: this.scrollLeft,
500 right: this.scrollLeft + this.clientWidth,
501 top: this.scrollTop,
502 bottom: this.scrollTop + this.clientHeight,
503 };
504 }
505 // the window is the only scroll object that changes it's rectangle relative
506 // to the document's topleft as it scrolls
507 handleScrollChange() {
508 this.clientRect = this.computeClientRect();
509 }
510 }
511
512 // If available we are using native "performance" API instead of "Date"
513 // Read more about it on MDN:
514 // https://developer.mozilla.org/en-US/docs/Web/API/Performance
515 const getTime = typeof performance === 'function' ? performance.now : Date.now;
516 /*
517 For a pointer interaction, automatically scrolls certain scroll containers when the pointer
518 approaches the edge.
519
520 The caller must call start + handleMove + stop.
521 */
522 class AutoScroller {
523 constructor() {
524 // options that can be set by caller
525 this.isEnabled = true;
526 this.scrollQuery = [window, '.fc-scroller'];
527 this.edgeThreshold = 50; // pixels
528 this.maxVelocity = 300; // pixels per second
529 // internal state
530 this.pointerScreenX = null;
531 this.pointerScreenY = null;
532 this.isAnimating = false;
533 this.scrollCaches = null;
534 // protect against the initial pointerdown being too close to an edge and starting the scroll
535 this.everMovedUp = false;
536 this.everMovedDown = false;
537 this.everMovedLeft = false;
538 this.everMovedRight = false;
539 this.animate = () => {
540 if (this.isAnimating) { // wasn't cancelled between animation calls
541 let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY);
542 if (edge) {
543 let now = getTime();
544 this.handleSide(edge, (now - this.msSinceRequest) / 1000);
545 this.requestAnimation(now);
546 }
547 else {
548 this.isAnimating = false; // will stop animation
549 }
550 }
551 };
552 }
553 start(pageX, pageY, scrollStartEl) {
554 if (this.isEnabled) {
555 this.scrollCaches = this.buildCaches(scrollStartEl);
556 this.pointerScreenX = null;
557 this.pointerScreenY = null;
558 this.everMovedUp = false;
559 this.everMovedDown = false;
560 this.everMovedLeft = false;
561 this.everMovedRight = false;
562 this.handleMove(pageX, pageY);
563 }
564 }
565 handleMove(pageX, pageY) {
566 if (this.isEnabled) {
567 let pointerScreenX = pageX - window.scrollX;
568 let pointerScreenY = pageY - window.scrollY;
569 let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
570 let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
571 if (yDelta < 0) {
572 this.everMovedUp = true;
573 }
574 else if (yDelta > 0) {
575 this.everMovedDown = true;
576 }
577 if (xDelta < 0) {
578 this.everMovedLeft = true;
579 }
580 else if (xDelta > 0) {
581 this.everMovedRight = true;
582 }
583 this.pointerScreenX = pointerScreenX;
584 this.pointerScreenY = pointerScreenY;
585 if (!this.isAnimating) {
586 this.isAnimating = true;
587 this.requestAnimation(getTime());
588 }
589 }
590 }
591 stop() {
592 if (this.isEnabled) {
593 this.isAnimating = false; // will stop animation
594 for (let scrollCache of this.scrollCaches) {
595 scrollCache.destroy();
596 }
597 this.scrollCaches = null;
598 }
599 }
600 requestAnimation(now) {
601 this.msSinceRequest = now;
602 requestAnimationFrame(this.animate);
603 }
604 handleSide(edge, seconds) {
605 let { scrollCache } = edge;
606 let { edgeThreshold } = this;
607 let invDistance = edgeThreshold - edge.distance;
608 let velocity = // the closer to the edge, the faster we scroll
609 ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
610 this.maxVelocity * seconds;
611 let sign = 1;
612 switch (edge.name) {
613 case 'left':
614 sign = -1;
615 // falls through
616 case 'right':
617 scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
618 break;
619 case 'top':
620 sign = -1;
621 // falls through
622 case 'bottom':
623 scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
624 break;
625 }
626 }
627 // left/top are relative to document topleft
628 computeBestEdge(left, top) {
629 let { edgeThreshold } = this;
630 let bestSide = null;
631 let scrollCaches = this.scrollCaches || [];
632 for (let scrollCache of scrollCaches) {
633 let rect = scrollCache.clientRect;
634 let leftDist = left - rect.left;
635 let rightDist = rect.right - left;
636 let topDist = top - rect.top;
637 let bottomDist = rect.bottom - top;
638 // completely within the rect?
639 if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
640 if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
641 (!bestSide || bestSide.distance > topDist)) {
642 bestSide = { scrollCache, name: 'top', distance: topDist };
643 }
644 if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
645 (!bestSide || bestSide.distance > bottomDist)) {
646 bestSide = { scrollCache, name: 'bottom', distance: bottomDist };
647 }
648 /*
649 TODO: fix broken RTL scrolling. canScrollLeft always returning false
650 https://github.com/fullcalendar/fullcalendar/issues/4837
651 */
652 if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
653 (!bestSide || bestSide.distance > leftDist)) {
654 bestSide = { scrollCache, name: 'left', distance: leftDist };
655 }
656 if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
657 (!bestSide || bestSide.distance > rightDist)) {
658 bestSide = { scrollCache, name: 'right', distance: rightDist };
659 }
660 }
661 }
662 return bestSide;
663 }
664 buildCaches(scrollStartEl) {
665 return this.queryScrollEls(scrollStartEl).map((el) => {
666 if (el === window) {
667 return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
668 }
669 return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
670 });
671 }
672 queryScrollEls(scrollStartEl) {
673 let els = [];
674 for (let query of this.scrollQuery) {
675 if (typeof query === 'object') {
676 els.push(query);
677 }
678 else {
679 /*
680 TODO: in the future, always have auto-scroll happen on element where current Hit came from
681 Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593
682 */
683 els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query)));
684 }
685 }
686 return els;
687 }
688 }
689
690 /*
691 Monitors dragging on an element. Has a number of high-level features:
692 - minimum distance required before dragging
693 - minimum wait time ("delay") before dragging
694 - a mirror element that follows the pointer
695 */
696 class FeaturefulElementDragging extends internal.ElementDragging {
697 constructor(containerEl, selector) {
698 super(containerEl);
699 this.containerEl = containerEl;
700 // options that can be directly set by caller
701 // the caller can also set the PointerDragging's options as well
702 this.delay = null;
703 this.minDistance = 0;
704 this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
705 this.mirrorNeedsRevert = false;
706 this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
707 this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
708 this.isDelayEnded = false;
709 this.isDistanceSurpassed = false;
710 this.delayTimeoutId = null;
711 this.onPointerDown = (ev) => {
712 if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
713 this.isInteracting = true;
714 this.isDelayEnded = false;
715 this.isDistanceSurpassed = false;
716 internal.preventSelection(document.body);
717 internal.preventContextMenu(document.body);
718 // prevent links from being visited if there's an eventual drag.
719 // also prevents selection in older browsers (maybe?).
720 // not necessary for touch, besides, browser would complain about passiveness.
721 if (!ev.isTouch) {
722 ev.origEvent.preventDefault();
723 }
724 this.emitter.trigger('pointerdown', ev);
725 if (this.isInteracting && // not destroyed via pointerdown handler
726 !this.pointer.shouldIgnoreMove) {
727 // actions related to initiating dragstart+dragmove+dragend...
728 this.mirror.setIsVisible(false); // reset. caller must set-visible
729 this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
730 this.startDelay(ev);
731 if (!this.minDistance) {
732 this.handleDistanceSurpassed(ev);
733 }
734 }
735 }
736 };
737 this.onPointerMove = (ev) => {
738 if (this.isInteracting) {
739 this.emitter.trigger('pointermove', ev);
740 if (!this.isDistanceSurpassed) {
741 let minDistance = this.minDistance;
742 let distanceSq; // current distance from the origin, squared
743 let { deltaX, deltaY } = ev;
744 distanceSq = deltaX * deltaX + deltaY * deltaY;
745 if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
746 this.handleDistanceSurpassed(ev);
747 }
748 }
749 if (this.isDragging) {
750 // a real pointer move? (not one simulated by scrolling)
751 if (ev.origEvent.type !== 'scroll') {
752 this.mirror.handleMove(ev.pageX, ev.pageY);
753 this.autoScroller.handleMove(ev.pageX, ev.pageY);
754 }
755 this.emitter.trigger('dragmove', ev);
756 }
757 }
758 };
759 this.onPointerUp = (ev) => {
760 if (this.isInteracting) {
761 this.isInteracting = false;
762 internal.allowSelection(document.body);
763 internal.allowContextMenu(document.body);
764 this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
765 if (this.isDragging) {
766 this.autoScroller.stop();
767 this.tryStopDrag(ev); // which will stop the mirror
768 }
769 if (this.delayTimeoutId) {
770 clearTimeout(this.delayTimeoutId);
771 this.delayTimeoutId = null;
772 }
773 }
774 };
775 let pointer = this.pointer = new PointerDragging(containerEl);
776 pointer.emitter.on('pointerdown', this.onPointerDown);
777 pointer.emitter.on('pointermove', this.onPointerMove);
778 pointer.emitter.on('pointerup', this.onPointerUp);
779 if (selector) {
780 pointer.selector = selector;
781 }
782 this.mirror = new ElementMirror();
783 this.autoScroller = new AutoScroller();
784 }
785 destroy() {
786 this.pointer.destroy();
787 // HACK: simulate a pointer-up to end the current drag
788 // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
789 this.onPointerUp({});
790 }
791 startDelay(ev) {
792 if (typeof this.delay === 'number') {
793 this.delayTimeoutId = setTimeout(() => {
794 this.delayTimeoutId = null;
795 this.handleDelayEnd(ev);
796 }, this.delay); // not assignable to number!
797 }
798 else {
799 this.handleDelayEnd(ev);
800 }
801 }
802 handleDelayEnd(ev) {
803 this.isDelayEnded = true;
804 this.tryStartDrag(ev);
805 }
806 handleDistanceSurpassed(ev) {
807 this.isDistanceSurpassed = true;
808 this.tryStartDrag(ev);
809 }
810 tryStartDrag(ev) {
811 if (this.isDelayEnded && this.isDistanceSurpassed) {
812 if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
813 this.isDragging = true;
814 this.mirrorNeedsRevert = false;
815 this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
816 this.emitter.trigger('dragstart', ev);
817 if (this.touchScrollAllowed === false) {
818 this.pointer.cancelTouchScroll();
819 }
820 }
821 }
822 }
823 tryStopDrag(ev) {
824 // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
825 // that come from the document to fire beforehand. much more convenient this way.
826 this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
827 }
828 stopDrag(ev) {
829 this.isDragging = false;
830 this.emitter.trigger('dragend', ev);
831 }
832 // fill in the implementations...
833 setIgnoreMove(bool) {
834 this.pointer.shouldIgnoreMove = bool;
835 }
836 setMirrorIsVisible(bool) {
837 this.mirror.setIsVisible(bool);
838 }
839 setMirrorNeedsRevert(bool) {
840 this.mirrorNeedsRevert = bool;
841 }
842 setAutoScrollEnabled(bool) {
843 this.autoScroller.isEnabled = bool;
844 }
845 }
846
847 /*
848 When this class is instantiated, it records the offset of an element (relative to the document topleft),
849 and continues to monitor scrolling, updating the cached coordinates if it needs to.
850 Does not access the DOM after instantiation, so highly performant.
851
852 Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
853 and an determine if a given point is inside the combined clipping rectangle.
854 */
855 class OffsetTracker {
856 constructor(el) {
857 this.el = el;
858 this.origRect = internal.computeRect(el);
859 // will work fine for divs that have overflow:hidden
860 this.scrollCaches = internal.getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
861 }
862 destroy() {
863 for (let scrollCache of this.scrollCaches) {
864 scrollCache.destroy();
865 }
866 }
867 computeLeft() {
868 let left = this.origRect.left;
869 for (let scrollCache of this.scrollCaches) {
870 left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
871 }
872 return left;
873 }
874 computeTop() {
875 let top = this.origRect.top;
876 for (let scrollCache of this.scrollCaches) {
877 top += scrollCache.origScrollTop - scrollCache.getScrollTop();
878 }
879 return top;
880 }
881 isWithinClipping(pageX, pageY) {
882 let point = { left: pageX, top: pageY };
883 for (let scrollCache of this.scrollCaches) {
884 if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
885 !internal.pointInsideRect(point, scrollCache.clientRect)) {
886 return false;
887 }
888 }
889 return true;
890 }
891 }
892 // certain clipping containers should never constrain interactions, like <html> and <body>
893 // https://github.com/fullcalendar/fullcalendar/issues/3615
894 function isIgnoredClipping(node) {
895 let tagName = node.tagName;
896 return tagName === 'HTML' || tagName === 'BODY';
897 }
898
899 /*
900 Tracks movement over multiple droppable areas (aka "hits")
901 that exist in one or more DateComponents.
902 Relies on an existing draggable.
903
904 emits:
905 - pointerdown
906 - dragstart
907 - hitchange - fires initially, even if not over a hit
908 - pointerup
909 - (hitchange - again, to null, if ended over a hit)
910 - dragend
911 */
912 class HitDragging {
913 constructor(dragging, droppableStore) {
914 // options that can be set by caller
915 this.useSubjectCenter = false;
916 this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
917 this.disablePointCheck = false;
918 this.initialHit = null;
919 this.movingHit = null;
920 this.finalHit = null; // won't ever be populated if shouldIgnoreMove
921 this.handlePointerDown = (ev) => {
922 let { dragging } = this;
923 this.initialHit = null;
924 this.movingHit = null;
925 this.finalHit = null;
926 this.prepareHits();
927 this.processFirstCoord(ev);
928 if (this.initialHit || !this.requireInitial) {
929 dragging.setIgnoreMove(false);
930 // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
931 this.emitter.trigger('pointerdown', ev);
932 }
933 else {
934 dragging.setIgnoreMove(true);
935 }
936 };
937 this.handleDragStart = (ev) => {
938 this.emitter.trigger('dragstart', ev);
939 this.handleMove(ev, true); // force = fire even if initially null
940 };
941 this.handleDragMove = (ev) => {
942 this.emitter.trigger('dragmove', ev);
943 this.handleMove(ev);
944 };
945 this.handlePointerUp = (ev) => {
946 this.releaseHits();
947 this.emitter.trigger('pointerup', ev);
948 };
949 this.handleDragEnd = (ev) => {
950 if (this.movingHit) {
951 this.emitter.trigger('hitupdate', null, true, ev);
952 }
953 this.finalHit = this.movingHit;
954 this.movingHit = null;
955 this.emitter.trigger('dragend', ev);
956 };
957 this.droppableStore = droppableStore;
958 dragging.emitter.on('pointerdown', this.handlePointerDown);
959 dragging.emitter.on('dragstart', this.handleDragStart);
960 dragging.emitter.on('dragmove', this.handleDragMove);
961 dragging.emitter.on('pointerup', this.handlePointerUp);
962 dragging.emitter.on('dragend', this.handleDragEnd);
963 this.dragging = dragging;
964 this.emitter = new internal.Emitter();
965 }
966 // sets initialHit
967 // sets coordAdjust
968 processFirstCoord(ev) {
969 let origPoint = { left: ev.pageX, top: ev.pageY };
970 let adjustedPoint = origPoint;
971 let subjectEl = ev.subjectEl;
972 let subjectRect;
973 if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
974 subjectRect = internal.computeRect(subjectEl);
975 adjustedPoint = internal.constrainPoint(adjustedPoint, subjectRect);
976 }
977 let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
978 if (initialHit) {
979 if (this.useSubjectCenter && subjectRect) {
980 let slicedSubjectRect = internal.intersectRects(subjectRect, initialHit.rect);
981 if (slicedSubjectRect) {
982 adjustedPoint = internal.getRectCenter(slicedSubjectRect);
983 }
984 }
985 this.coordAdjust = internal.diffPoints(adjustedPoint, origPoint);
986 }
987 else {
988 this.coordAdjust = { left: 0, top: 0 };
989 }
990 }
991 handleMove(ev, forceHandle) {
992 let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
993 if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
994 this.movingHit = hit;
995 this.emitter.trigger('hitupdate', hit, false, ev);
996 }
997 }
998 prepareHits() {
999 this.offsetTrackers = internal.mapHash(this.droppableStore, (interactionSettings) => {
1000 interactionSettings.component.prepareHits();
1001 return new OffsetTracker(interactionSettings.el);
1002 });
1003 }
1004 releaseHits() {
1005 let { offsetTrackers } = this;
1006 for (let id in offsetTrackers) {
1007 offsetTrackers[id].destroy();
1008 }
1009 this.offsetTrackers = {};
1010 }
1011 queryHitForOffset(offsetLeft, offsetTop) {
1012 let { droppableStore, offsetTrackers } = this;
1013 let bestHit = null;
1014 for (let id in droppableStore) {
1015 let component = droppableStore[id].component;
1016 let offsetTracker = offsetTrackers[id];
1017 if (offsetTracker && // wasn't destroyed mid-drag
1018 offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
1019 let originLeft = offsetTracker.computeLeft();
1020 let originTop = offsetTracker.computeTop();
1021 let positionLeft = offsetLeft - originLeft;
1022 let positionTop = offsetTop - originTop;
1023 let { origRect } = offsetTracker;
1024 let width = origRect.right - origRect.left;
1025 let height = origRect.bottom - origRect.top;
1026 if (
1027 // must be within the element's bounds
1028 positionLeft >= 0 && positionLeft < width &&
1029 positionTop >= 0 && positionTop < height) {
1030 let hit = component.queryHit(positionLeft, positionTop, width, height);
1031 if (hit && (
1032 // make sure the hit is within activeRange, meaning it's not a dead cell
1033 internal.rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
1034 // Ensure the component we are querying for the hit is accessibly my the pointer
1035 // Prevents obscured calendars (ex: under a modal dialog) from accepting hit
1036 // https://github.com/fullcalendar/fullcalendar/issues/5026
1037 (this.disablePointCheck ||
1038 offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint(
1039 // add-back origins to get coordinate relative to top-left of window viewport
1040 positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) &&
1041 (!bestHit || hit.layer > bestHit.layer)) {
1042 hit.componentId = id;
1043 hit.context = component.context;
1044 // TODO: better way to re-orient rectangle
1045 hit.rect.left += originLeft;
1046 hit.rect.right += originLeft;
1047 hit.rect.top += originTop;
1048 hit.rect.bottom += originTop;
1049 bestHit = hit;
1050 }
1051 }
1052 }
1053 }
1054 return bestHit;
1055 }
1056 }
1057 function isHitsEqual(hit0, hit1) {
1058 if (!hit0 && !hit1) {
1059 return true;
1060 }
1061 if (Boolean(hit0) !== Boolean(hit1)) {
1062 return false;
1063 }
1064 return internal.isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
1065 }
1066
1067 function buildDatePointApiWithContext(dateSpan, context) {
1068 let props = {};
1069 for (let transform of context.pluginHooks.datePointTransforms) {
1070 Object.assign(props, transform(dateSpan, context));
1071 }
1072 Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
1073 return props;
1074 }
1075 function buildDatePointApi(span, dateEnv) {
1076 return {
1077 date: dateEnv.toDate(span.range.start),
1078 dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
1079 allDay: span.allDay,
1080 };
1081 }
1082
1083 /*
1084 Monitors when the user clicks on a specific date/time of a component.
1085 A pointerdown+pointerup on the same "hit" constitutes a click.
1086 */
1087 class DateClicking extends internal.Interaction {
1088 constructor(settings) {
1089 super(settings);
1090 this.handlePointerDown = (pev) => {
1091 let { dragging } = this;
1092 let downEl = pev.origEvent.target;
1093 // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
1094 dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
1095 };
1096 // won't even fire if moving was ignored
1097 this.handleDragEnd = (ev) => {
1098 let { component } = this;
1099 let { pointer } = this.dragging;
1100 if (!pointer.wasTouchScroll) {
1101 let { initialHit, finalHit } = this.hitDragging;
1102 if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
1103 let { context } = component;
1104 let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), { dayEl: initialHit.dayEl, jsEvent: ev.origEvent, view: context.viewApi || context.calendarApi.view });
1105 context.emitter.trigger('dateClick', arg);
1106 }
1107 }
1108 };
1109 // we DO want to watch pointer moves because otherwise finalHit won't get populated
1110 this.dragging = new FeaturefulElementDragging(settings.el);
1111 this.dragging.autoScroller.isEnabled = false;
1112 let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.interactionSettingsToStore(settings));
1113 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
1114 hitDragging.emitter.on('dragend', this.handleDragEnd);
1115 }
1116 destroy() {
1117 this.dragging.destroy();
1118 }
1119 }
1120
1121 /*
1122 Tracks when the user selects a portion of time of a component,
1123 constituted by a drag over date cells, with a possible delay at the beginning of the drag.
1124 */
1125 class DateSelecting extends internal.Interaction {
1126 constructor(settings) {
1127 super(settings);
1128 this.dragSelection = null;
1129 this.handlePointerDown = (ev) => {
1130 let { component, dragging } = this;
1131 let { options } = component.context;
1132 let canSelect = options.selectable &&
1133 component.isValidDateDownEl(ev.origEvent.target);
1134 // don't bother to watch expensive moves if component won't do selection
1135 dragging.setIgnoreMove(!canSelect);
1136 // if touch, require user to hold down
1137 dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
1138 };
1139 this.handleDragStart = (ev) => {
1140 this.component.context.calendarApi.unselect(ev); // unselect previous selections
1141 };
1142 this.handleHitUpdate = (hit, isFinal) => {
1143 let { context } = this.component;
1144 let dragSelection = null;
1145 let isInvalid = false;
1146 if (hit) {
1147 let initialHit = this.hitDragging.initialHit;
1148 let disallowed = hit.componentId === initialHit.componentId
1149 && this.isHitComboAllowed
1150 && !this.isHitComboAllowed(initialHit, hit);
1151 if (!disallowed) {
1152 dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
1153 }
1154 if (!dragSelection || !internal.isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
1155 isInvalid = true;
1156 dragSelection = null;
1157 }
1158 }
1159 if (dragSelection) {
1160 context.dispatch({ type: 'SELECT_DATES', selection: dragSelection });
1161 }
1162 else if (!isFinal) { // only unselect if moved away while dragging
1163 context.dispatch({ type: 'UNSELECT_DATES' });
1164 }
1165 if (!isInvalid) {
1166 internal.enableCursor();
1167 }
1168 else {
1169 internal.disableCursor();
1170 }
1171 if (!isFinal) {
1172 this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
1173 }
1174 };
1175 this.handlePointerUp = (pev) => {
1176 if (this.dragSelection) {
1177 // selection is already rendered, so just need to report selection
1178 internal.triggerDateSelect(this.dragSelection, pev, this.component.context);
1179 this.dragSelection = null;
1180 }
1181 };
1182 let { component } = settings;
1183 let { options } = component.context;
1184 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
1185 dragging.touchScrollAllowed = false;
1186 dragging.minDistance = options.selectMinDistance || 0;
1187 dragging.autoScroller.isEnabled = options.dragScroll;
1188 let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.interactionSettingsToStore(settings));
1189 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
1190 hitDragging.emitter.on('dragstart', this.handleDragStart);
1191 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
1192 hitDragging.emitter.on('pointerup', this.handlePointerUp);
1193 }
1194 destroy() {
1195 this.dragging.destroy();
1196 }
1197 }
1198 function getComponentTouchDelay$1(component) {
1199 let { options } = component.context;
1200 let delay = options.selectLongPressDelay;
1201 if (delay == null) {
1202 delay = options.longPressDelay;
1203 }
1204 return delay;
1205 }
1206 function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
1207 let dateSpan0 = hit0.dateSpan;
1208 let dateSpan1 = hit1.dateSpan;
1209 let ms = [
1210 dateSpan0.range.start,
1211 dateSpan0.range.end,
1212 dateSpan1.range.start,
1213 dateSpan1.range.end,
1214 ];
1215 ms.sort(internal.compareNumbers);
1216 let props = {};
1217 for (let transformer of dateSelectionTransformers) {
1218 let res = transformer(hit0, hit1);
1219 if (res === false) {
1220 return null;
1221 }
1222 if (res) {
1223 Object.assign(props, res);
1224 }
1225 }
1226 props.range = { start: ms[0], end: ms[3] };
1227 props.allDay = dateSpan0.allDay;
1228 return props;
1229 }
1230
1231 class EventDragging extends internal.Interaction {
1232 constructor(settings) {
1233 super(settings);
1234 // internal state
1235 this.subjectEl = null;
1236 this.subjectSeg = null; // the seg being selected/dragged
1237 this.isDragging = false;
1238 this.eventRange = null;
1239 this.relevantEvents = null; // the events being dragged
1240 this.receivingContext = null;
1241 this.validMutation = null;
1242 this.mutatedRelevantEvents = null;
1243 this.handlePointerDown = (ev) => {
1244 let origTarget = ev.origEvent.target;
1245 let { component, dragging } = this;
1246 let { mirror } = dragging;
1247 let { options } = component.context;
1248 let initialContext = component.context;
1249 this.subjectEl = ev.subjectEl;
1250 let subjectSeg = this.subjectSeg = internal.getElSeg(ev.subjectEl);
1251 let eventRange = this.eventRange = subjectSeg.eventRange;
1252 let eventInstanceId = eventRange.instance.instanceId;
1253 this.relevantEvents = internal.getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
1254 dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
1255 dragging.delay =
1256 // only do a touch delay if touch and this event hasn't been selected yet
1257 (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
1258 getComponentTouchDelay(component) :
1259 null;
1260 if (options.fixedMirrorParent) {
1261 mirror.parentNode = options.fixedMirrorParent;
1262 }
1263 else {
1264 mirror.parentNode = internal.elementClosest(origTarget, '.fc');
1265 }
1266 mirror.revertDuration = options.dragRevertDuration;
1267 let isValid = component.isValidSegDownEl(origTarget) &&
1268 !internal.elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
1269 dragging.setIgnoreMove(!isValid);
1270 // disable dragging for elements that are resizable (ie, selectable)
1271 // but are not draggable
1272 this.isDragging = isValid &&
1273 ev.subjectEl.classList.contains('fc-event-draggable');
1274 };
1275 this.handleDragStart = (ev) => {
1276 let initialContext = this.component.context;
1277 let eventRange = this.eventRange;
1278 let eventInstanceId = eventRange.instance.instanceId;
1279 if (ev.isTouch) {
1280 // need to select a different event?
1281 if (eventInstanceId !== this.component.props.eventSelection) {
1282 initialContext.dispatch({ type: 'SELECT_EVENT', eventInstanceId });
1283 }
1284 }
1285 else {
1286 // if now using mouse, but was previous touch interaction, clear selected event
1287 initialContext.dispatch({ type: 'UNSELECT_EVENT' });
1288 }
1289 if (this.isDragging) {
1290 initialContext.calendarApi.unselect(ev); // unselect *date* selection
1291 initialContext.emitter.trigger('eventDragStart', {
1292 el: this.subjectEl,
1293 event: new internal.EventImpl(initialContext, eventRange.def, eventRange.instance),
1294 jsEvent: ev.origEvent,
1295 view: initialContext.viewApi,
1296 });
1297 }
1298 };
1299 this.handleHitUpdate = (hit, isFinal) => {
1300 if (!this.isDragging) {
1301 return;
1302 }
1303 let relevantEvents = this.relevantEvents;
1304 let initialHit = this.hitDragging.initialHit;
1305 let initialContext = this.component.context;
1306 // states based on new hit
1307 let receivingContext = null;
1308 let mutation = null;
1309 let mutatedRelevantEvents = null;
1310 let isInvalid = false;
1311 let interaction = {
1312 affectedEvents: relevantEvents,
1313 mutatedEvents: internal.createEmptyEventStore(),
1314 isEvent: true,
1315 };
1316 if (hit) {
1317 receivingContext = hit.context;
1318 let receivingOptions = receivingContext.options;
1319 if (initialContext === receivingContext ||
1320 (receivingOptions.editable && receivingOptions.droppable)) {
1321 mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
1322 if (mutation) {
1323 mutatedRelevantEvents = internal.applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
1324 interaction.mutatedEvents = mutatedRelevantEvents;
1325 if (!internal.isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
1326 isInvalid = true;
1327 mutation = null;
1328 mutatedRelevantEvents = null;
1329 interaction.mutatedEvents = internal.createEmptyEventStore();
1330 }
1331 }
1332 }
1333 else {
1334 receivingContext = null;
1335 }
1336 }
1337 this.displayDrag(receivingContext, interaction);
1338 if (!isInvalid) {
1339 internal.enableCursor();
1340 }
1341 else {
1342 internal.disableCursor();
1343 }
1344 if (!isFinal) {
1345 if (initialContext === receivingContext && // TODO: write test for this
1346 isHitsEqual(initialHit, hit)) {
1347 mutation = null;
1348 }
1349 this.dragging.setMirrorNeedsRevert(!mutation);
1350 // render the mirror if no already-rendered mirror
1351 // TODO: wish we could somehow wait for dispatch to guarantee render
1352 this.dragging.setMirrorIsVisible(!hit || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror'));
1353 // assign states based on new hit
1354 this.receivingContext = receivingContext;
1355 this.validMutation = mutation;
1356 this.mutatedRelevantEvents = mutatedRelevantEvents;
1357 }
1358 };
1359 this.handlePointerUp = () => {
1360 if (!this.isDragging) {
1361 this.cleanup(); // because handleDragEnd won't fire
1362 }
1363 };
1364 this.handleDragEnd = (ev) => {
1365 if (this.isDragging) {
1366 let initialContext = this.component.context;
1367 let initialView = initialContext.viewApi;
1368 let { receivingContext, validMutation } = this;
1369 let eventDef = this.eventRange.def;
1370 let eventInstance = this.eventRange.instance;
1371 let eventApi = new internal.EventImpl(initialContext, eventDef, eventInstance);
1372 let relevantEvents = this.relevantEvents;
1373 let mutatedRelevantEvents = this.mutatedRelevantEvents;
1374 let { finalHit } = this.hitDragging;
1375 this.clearDrag(); // must happen after revert animation
1376 initialContext.emitter.trigger('eventDragStop', {
1377 el: this.subjectEl,
1378 event: eventApi,
1379 jsEvent: ev.origEvent,
1380 view: initialView,
1381 });
1382 if (validMutation) {
1383 // dropped within same calendar
1384 if (receivingContext === initialContext) {
1385 let updatedEventApi = new internal.EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
1386 initialContext.dispatch({
1387 type: 'MERGE_EVENTS',
1388 eventStore: mutatedRelevantEvents,
1389 });
1390 let eventChangeArg = {
1391 oldEvent: eventApi,
1392 event: updatedEventApi,
1393 relatedEvents: internal.buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
1394 revert() {
1395 initialContext.dispatch({
1396 type: 'MERGE_EVENTS',
1397 eventStore: relevantEvents, // the pre-change data
1398 });
1399 },
1400 };
1401 let transformed = {};
1402 for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
1403 Object.assign(transformed, transformer(validMutation, initialContext));
1404 }
1405 initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), { el: ev.subjectEl, delta: validMutation.datesDelta, jsEvent: ev.origEvent, view: initialView }));
1406 initialContext.emitter.trigger('eventChange', eventChangeArg);
1407 // dropped in different calendar
1408 }
1409 else if (receivingContext) {
1410 let eventRemoveArg = {
1411 event: eventApi,
1412 relatedEvents: internal.buildEventApis(relevantEvents, initialContext, eventInstance),
1413 revert() {
1414 initialContext.dispatch({
1415 type: 'MERGE_EVENTS',
1416 eventStore: relevantEvents,
1417 });
1418 },
1419 };
1420 initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), { draggedEl: ev.subjectEl, view: initialView }));
1421 initialContext.dispatch({
1422 type: 'REMOVE_EVENTS',
1423 eventStore: relevantEvents,
1424 });
1425 initialContext.emitter.trigger('eventRemove', eventRemoveArg);
1426 let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
1427 let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
1428 let addedEventApi = new internal.EventImpl(receivingContext, addedEventDef, addedEventInstance);
1429 receivingContext.dispatch({
1430 type: 'MERGE_EVENTS',
1431 eventStore: mutatedRelevantEvents,
1432 });
1433 let eventAddArg = {
1434 event: addedEventApi,
1435 relatedEvents: internal.buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
1436 revert() {
1437 receivingContext.dispatch({
1438 type: 'REMOVE_EVENTS',
1439 eventStore: mutatedRelevantEvents,
1440 });
1441 },
1442 };
1443 receivingContext.emitter.trigger('eventAdd', eventAddArg);
1444 if (ev.isTouch) {
1445 receivingContext.dispatch({
1446 type: 'SELECT_EVENT',
1447 eventInstanceId: eventInstance.instanceId,
1448 });
1449 }
1450 receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: ev.subjectEl, jsEvent: ev.origEvent, view: finalHit.context.viewApi }));
1451 receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), { draggedEl: ev.subjectEl, view: finalHit.context.viewApi }));
1452 }
1453 }
1454 else {
1455 initialContext.emitter.trigger('_noEventDrop');
1456 }
1457 }
1458 this.cleanup();
1459 };
1460 let { component } = this;
1461 let { options } = component.context;
1462 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
1463 dragging.pointer.selector = EventDragging.SELECTOR;
1464 dragging.touchScrollAllowed = false;
1465 dragging.autoScroller.isEnabled = options.dragScroll;
1466 let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.interactionSettingsStore);
1467 hitDragging.useSubjectCenter = settings.useEventCenter;
1468 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
1469 hitDragging.emitter.on('dragstart', this.handleDragStart);
1470 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
1471 hitDragging.emitter.on('pointerup', this.handlePointerUp);
1472 hitDragging.emitter.on('dragend', this.handleDragEnd);
1473 }
1474 destroy() {
1475 this.dragging.destroy();
1476 }
1477 // render a drag state on the next receivingCalendar
1478 displayDrag(nextContext, state) {
1479 let initialContext = this.component.context;
1480 let prevContext = this.receivingContext;
1481 // does the previous calendar need to be cleared?
1482 if (prevContext && prevContext !== nextContext) {
1483 // does the initial calendar need to be cleared?
1484 // if so, don't clear all the way. we still need to to hide the affectedEvents
1485 if (prevContext === initialContext) {
1486 prevContext.dispatch({
1487 type: 'SET_EVENT_DRAG',
1488 state: {
1489 affectedEvents: state.affectedEvents,
1490 mutatedEvents: internal.createEmptyEventStore(),
1491 isEvent: true,
1492 },
1493 });
1494 // completely clear the old calendar if it wasn't the initial
1495 }
1496 else {
1497 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
1498 }
1499 }
1500 if (nextContext) {
1501 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
1502 }
1503 }
1504 clearDrag() {
1505 let initialCalendar = this.component.context;
1506 let { receivingContext } = this;
1507 if (receivingContext) {
1508 receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
1509 }
1510 // the initial calendar might have an dummy drag state from displayDrag
1511 if (initialCalendar !== receivingContext) {
1512 initialCalendar.dispatch({ type: 'UNSET_EVENT_DRAG' });
1513 }
1514 }
1515 cleanup() {
1516 this.subjectSeg = null;
1517 this.isDragging = false;
1518 this.eventRange = null;
1519 this.relevantEvents = null;
1520 this.receivingContext = null;
1521 this.validMutation = null;
1522 this.mutatedRelevantEvents = null;
1523 }
1524 }
1525 // TODO: test this in IE11
1526 // QUESTION: why do we need it on the resizable???
1527 EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';
1528 function computeEventMutation(hit0, hit1, eventInstanceStart, massagers) {
1529 let dateSpan0 = hit0.dateSpan;
1530 let dateSpan1 = hit1.dateSpan;
1531 let date0 = dateSpan0.range.start;
1532 let date1 = dateSpan1.range.start;
1533 let standardProps = {};
1534 if (dateSpan0.allDay !== dateSpan1.allDay) {
1535 standardProps.allDay = dateSpan1.allDay;
1536 standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
1537 if (dateSpan1.allDay) {
1538 // means date1 is already start-of-day,
1539 // but date0 needs to be converted
1540 date0 = internal.startOfDay(eventInstanceStart);
1541 }
1542 else {
1543 // Moving from allDate->timed
1544 // Doesn't matter where on the event the drag began, mutate the event's start-date to date1
1545 date0 = eventInstanceStart;
1546 }
1547 }
1548 let delta = internal.diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
1549 hit0.largeUnit :
1550 null);
1551 if (delta.milliseconds) { // has hours/minutes/seconds
1552 standardProps.allDay = false;
1553 }
1554 let mutation = {
1555 datesDelta: delta,
1556 standardProps,
1557 };
1558 for (let massager of massagers) {
1559 massager(mutation, hit0, hit1);
1560 }
1561 return mutation;
1562 }
1563 function getComponentTouchDelay(component) {
1564 let { options } = component.context;
1565 let delay = options.eventLongPressDelay;
1566 if (delay == null) {
1567 delay = options.longPressDelay;
1568 }
1569 return delay;
1570 }
1571
1572 class EventResizing extends internal.Interaction {
1573 constructor(settings) {
1574 super(settings);
1575 // internal state
1576 this.draggingSegEl = null;
1577 this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
1578 this.eventRange = null;
1579 this.relevantEvents = null;
1580 this.validMutation = null;
1581 this.mutatedRelevantEvents = null;
1582 this.handlePointerDown = (ev) => {
1583 let { component } = this;
1584 let segEl = this.querySegEl(ev);
1585 let seg = internal.getElSeg(segEl);
1586 let eventRange = this.eventRange = seg.eventRange;
1587 this.dragging.minDistance = component.context.options.eventDragMinDistance;
1588 // if touch, need to be working with a selected event
1589 this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
1590 (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
1591 };
1592 this.handleDragStart = (ev) => {
1593 let { context } = this.component;
1594 let eventRange = this.eventRange;
1595 this.relevantEvents = internal.getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
1596 let segEl = this.querySegEl(ev);
1597 this.draggingSegEl = segEl;
1598 this.draggingSeg = internal.getElSeg(segEl);
1599 context.calendarApi.unselect();
1600 context.emitter.trigger('eventResizeStart', {
1601 el: segEl,
1602 event: new internal.EventImpl(context, eventRange.def, eventRange.instance),
1603 jsEvent: ev.origEvent,
1604 view: context.viewApi,
1605 });
1606 };
1607 this.handleHitUpdate = (hit, isFinal, ev) => {
1608 let { context } = this.component;
1609 let relevantEvents = this.relevantEvents;
1610 let initialHit = this.hitDragging.initialHit;
1611 let eventInstance = this.eventRange.instance;
1612 let mutation = null;
1613 let mutatedRelevantEvents = null;
1614 let isInvalid = false;
1615 let interaction = {
1616 affectedEvents: relevantEvents,
1617 mutatedEvents: internal.createEmptyEventStore(),
1618 isEvent: true,
1619 };
1620 if (hit) {
1621 let disallowed = hit.componentId === initialHit.componentId
1622 && this.isHitComboAllowed
1623 && !this.isHitComboAllowed(initialHit, hit);
1624 if (!disallowed) {
1625 mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
1626 }
1627 }
1628 if (mutation) {
1629 mutatedRelevantEvents = internal.applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
1630 interaction.mutatedEvents = mutatedRelevantEvents;
1631 if (!internal.isInteractionValid(interaction, hit.dateProfile, context)) {
1632 isInvalid = true;
1633 mutation = null;
1634 mutatedRelevantEvents = null;
1635 interaction.mutatedEvents = null;
1636 }
1637 }
1638 if (mutatedRelevantEvents) {
1639 context.dispatch({
1640 type: 'SET_EVENT_RESIZE',
1641 state: interaction,
1642 });
1643 }
1644 else {
1645 context.dispatch({ type: 'UNSET_EVENT_RESIZE' });
1646 }
1647 if (!isInvalid) {
1648 internal.enableCursor();
1649 }
1650 else {
1651 internal.disableCursor();
1652 }
1653 if (!isFinal) {
1654 if (mutation && isHitsEqual(initialHit, hit)) {
1655 mutation = null;
1656 }
1657 this.validMutation = mutation;
1658 this.mutatedRelevantEvents = mutatedRelevantEvents;
1659 }
1660 };
1661 this.handleDragEnd = (ev) => {
1662 let { context } = this.component;
1663 let eventDef = this.eventRange.def;
1664 let eventInstance = this.eventRange.instance;
1665 let eventApi = new internal.EventImpl(context, eventDef, eventInstance);
1666 let relevantEvents = this.relevantEvents;
1667 let mutatedRelevantEvents = this.mutatedRelevantEvents;
1668 context.emitter.trigger('eventResizeStop', {
1669 el: this.draggingSegEl,
1670 event: eventApi,
1671 jsEvent: ev.origEvent,
1672 view: context.viewApi,
1673 });
1674 if (this.validMutation) {
1675 let updatedEventApi = new internal.EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
1676 context.dispatch({
1677 type: 'MERGE_EVENTS',
1678 eventStore: mutatedRelevantEvents,
1679 });
1680 let eventChangeArg = {
1681 oldEvent: eventApi,
1682 event: updatedEventApi,
1683 relatedEvents: internal.buildEventApis(mutatedRelevantEvents, context, eventInstance),
1684 revert() {
1685 context.dispatch({
1686 type: 'MERGE_EVENTS',
1687 eventStore: relevantEvents, // the pre-change events
1688 });
1689 },
1690 };
1691 context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), { el: this.draggingSegEl, startDelta: this.validMutation.startDelta || internal.createDuration(0), endDelta: this.validMutation.endDelta || internal.createDuration(0), jsEvent: ev.origEvent, view: context.viewApi }));
1692 context.emitter.trigger('eventChange', eventChangeArg);
1693 }
1694 else {
1695 context.emitter.trigger('_noEventResize');
1696 }
1697 // reset all internal state
1698 this.draggingSeg = null;
1699 this.relevantEvents = null;
1700 this.validMutation = null;
1701 // okay to keep eventInstance around. useful to set it in handlePointerDown
1702 };
1703 let { component } = settings;
1704 let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
1705 dragging.pointer.selector = '.fc-event-resizer';
1706 dragging.touchScrollAllowed = false;
1707 dragging.autoScroller.isEnabled = component.context.options.dragScroll;
1708 let hitDragging = this.hitDragging = new HitDragging(this.dragging, internal.interactionSettingsToStore(settings));
1709 hitDragging.emitter.on('pointerdown', this.handlePointerDown);
1710 hitDragging.emitter.on('dragstart', this.handleDragStart);
1711 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
1712 hitDragging.emitter.on('dragend', this.handleDragEnd);
1713 }
1714 destroy() {
1715 this.dragging.destroy();
1716 }
1717 querySegEl(ev) {
1718 return internal.elementClosest(ev.subjectEl, '.fc-event');
1719 }
1720 }
1721 function computeMutation(hit0, hit1, isFromStart, instanceRange) {
1722 let dateEnv = hit0.context.dateEnv;
1723 let date0 = hit0.dateSpan.range.start;
1724 let date1 = hit1.dateSpan.range.start;
1725 let delta = internal.diffDates(date0, date1, dateEnv, hit0.largeUnit);
1726 if (isFromStart) {
1727 if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
1728 return { startDelta: delta };
1729 }
1730 }
1731 else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
1732 return { endDelta: delta };
1733 }
1734 return null;
1735 }
1736
1737 class UnselectAuto {
1738 constructor(context) {
1739 this.context = context;
1740 this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
1741 this.matchesCancel = false;
1742 this.matchesEvent = false;
1743 this.onSelect = (selectInfo) => {
1744 if (selectInfo.jsEvent) {
1745 this.isRecentPointerDateSelect = true;
1746 }
1747 };
1748 this.onDocumentPointerDown = (pev) => {
1749 let unselectCancel = this.context.options.unselectCancel;
1750 let downEl = internal.getEventTargetViaRoot(pev.origEvent);
1751 this.matchesCancel = !!internal.elementClosest(downEl, unselectCancel);
1752 this.matchesEvent = !!internal.elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
1753 };
1754 this.onDocumentPointerUp = (pev) => {
1755 let { context } = this;
1756 let { documentPointer } = this;
1757 let calendarState = context.getCurrentData();
1758 // touch-scrolling should never unfocus any type of selection
1759 if (!documentPointer.wasTouchScroll) {
1760 if (calendarState.dateSelection && // an existing date selection?
1761 !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
1762 ) {
1763 let unselectAuto = context.options.unselectAuto;
1764 if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
1765 context.calendarApi.unselect(pev);
1766 }
1767 }
1768 if (calendarState.eventSelection && // an existing event selected?
1769 !this.matchesEvent // interaction DIDN'T start on an event
1770 ) {
1771 context.dispatch({ type: 'UNSELECT_EVENT' });
1772 }
1773 }
1774 this.isRecentPointerDateSelect = false;
1775 };
1776 let documentPointer = this.documentPointer = new PointerDragging(document);
1777 documentPointer.shouldIgnoreMove = true;
1778 documentPointer.shouldWatchScroll = false;
1779 documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
1780 documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
1781 /*
1782 TODO: better way to know about whether there was a selection with the pointer
1783 */
1784 context.emitter.on('select', this.onSelect);
1785 }
1786 destroy() {
1787 this.context.emitter.off('select', this.onSelect);
1788 this.documentPointer.destroy();
1789 }
1790 }
1791
1792 const OPTION_REFINERS = {
1793 fixedMirrorParent: internal.identity,
1794 };
1795 const LISTENER_REFINERS = {
1796 dateClick: internal.identity,
1797 eventDragStart: internal.identity,
1798 eventDragStop: internal.identity,
1799 eventDrop: internal.identity,
1800 eventResizeStart: internal.identity,
1801 eventResizeStop: internal.identity,
1802 eventResize: internal.identity,
1803 drop: internal.identity,
1804 eventReceive: internal.identity,
1805 eventLeave: internal.identity,
1806 };
1807
1808 /*
1809 Given an already instantiated draggable object for one-or-more elements,
1810 Interprets any dragging as an attempt to drag an events that lives outside
1811 of a calendar onto a calendar.
1812 */
1813 class ExternalElementDragging {
1814 constructor(dragging, suppliedDragMeta) {
1815 this.receivingContext = null;
1816 this.droppableEvent = null; // will exist for all drags, even if create:false
1817 this.suppliedDragMeta = null;
1818 this.dragMeta = null;
1819 this.handleDragStart = (ev) => {
1820 this.dragMeta = this.buildDragMeta(ev.subjectEl);
1821 };
1822 this.handleHitUpdate = (hit, isFinal, ev) => {
1823 let { dragging } = this.hitDragging;
1824 let receivingContext = null;
1825 let droppableEvent = null;
1826 let isInvalid = false;
1827 let interaction = {
1828 affectedEvents: internal.createEmptyEventStore(),
1829 mutatedEvents: internal.createEmptyEventStore(),
1830 isEvent: this.dragMeta.create,
1831 };
1832 if (hit) {
1833 receivingContext = hit.context;
1834 if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
1835 droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
1836 interaction.mutatedEvents = internal.eventTupleToStore(droppableEvent);
1837 isInvalid = !internal.isInteractionValid(interaction, hit.dateProfile, receivingContext);
1838 if (isInvalid) {
1839 interaction.mutatedEvents = internal.createEmptyEventStore();
1840 droppableEvent = null;
1841 }
1842 }
1843 }
1844 this.displayDrag(receivingContext, interaction);
1845 // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
1846 // TODO: wish we could somehow wait for dispatch to guarantee render
1847 dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
1848 if (!isInvalid) {
1849 internal.enableCursor();
1850 }
1851 else {
1852 internal.disableCursor();
1853 }
1854 if (!isFinal) {
1855 dragging.setMirrorNeedsRevert(!droppableEvent);
1856 this.receivingContext = receivingContext;
1857 this.droppableEvent = droppableEvent;
1858 }
1859 };
1860 this.handleDragEnd = (pev) => {
1861 let { receivingContext, droppableEvent } = this;
1862 this.clearDrag();
1863 if (receivingContext && droppableEvent) {
1864 let finalHit = this.hitDragging.finalHit;
1865 let finalView = finalHit.context.viewApi;
1866 let dragMeta = this.dragMeta;
1867 receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), { draggedEl: pev.subjectEl, jsEvent: pev.origEvent, view: finalView }));
1868 if (dragMeta.create) {
1869 let addingEvents = internal.eventTupleToStore(droppableEvent);
1870 receivingContext.dispatch({
1871 type: 'MERGE_EVENTS',
1872 eventStore: addingEvents,
1873 });
1874 if (pev.isTouch) {
1875 receivingContext.dispatch({
1876 type: 'SELECT_EVENT',
1877 eventInstanceId: droppableEvent.instance.instanceId,
1878 });
1879 }
1880 // signal that an external event landed
1881 receivingContext.emitter.trigger('eventReceive', {
1882 event: new internal.EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
1883 relatedEvents: [],
1884 revert() {
1885 receivingContext.dispatch({
1886 type: 'REMOVE_EVENTS',
1887 eventStore: addingEvents,
1888 });
1889 },
1890 draggedEl: pev.subjectEl,
1891 view: finalView,
1892 });
1893 }
1894 }
1895 this.receivingContext = null;
1896 this.droppableEvent = null;
1897 };
1898 let hitDragging = this.hitDragging = new HitDragging(dragging, internal.interactionSettingsStore);
1899 hitDragging.requireInitial = false; // will start outside of a component
1900 hitDragging.emitter.on('dragstart', this.handleDragStart);
1901 hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
1902 hitDragging.emitter.on('dragend', this.handleDragEnd);
1903 this.suppliedDragMeta = suppliedDragMeta;
1904 }
1905 buildDragMeta(subjectEl) {
1906 if (typeof this.suppliedDragMeta === 'object') {
1907 return internal.parseDragMeta(this.suppliedDragMeta);
1908 }
1909 if (typeof this.suppliedDragMeta === 'function') {
1910 return internal.parseDragMeta(this.suppliedDragMeta(subjectEl));
1911 }
1912 return getDragMetaFromEl(subjectEl);
1913 }
1914 displayDrag(nextContext, state) {
1915 let prevContext = this.receivingContext;
1916 if (prevContext && prevContext !== nextContext) {
1917 prevContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
1918 }
1919 if (nextContext) {
1920 nextContext.dispatch({ type: 'SET_EVENT_DRAG', state });
1921 }
1922 }
1923 clearDrag() {
1924 if (this.receivingContext) {
1925 this.receivingContext.dispatch({ type: 'UNSET_EVENT_DRAG' });
1926 }
1927 }
1928 canDropElOnCalendar(el, receivingContext) {
1929 let dropAccept = receivingContext.options.dropAccept;
1930 if (typeof dropAccept === 'function') {
1931 return dropAccept.call(receivingContext.calendarApi, el);
1932 }
1933 if (typeof dropAccept === 'string' && dropAccept) {
1934 return Boolean(internal.elementMatches(el, dropAccept));
1935 }
1936 return true;
1937 }
1938 }
1939 // Utils for computing event store from the DragMeta
1940 // ----------------------------------------------------------------------------------------------------
1941 function computeEventForDateSpan(dateSpan, dragMeta, context) {
1942 let defProps = Object.assign({}, dragMeta.leftoverProps);
1943 for (let transform of context.pluginHooks.externalDefTransforms) {
1944 Object.assign(defProps, transform(dateSpan, dragMeta));
1945 }
1946 let { refined, extra } = internal.refineEventDef(defProps, context);
1947 let def = internal.parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
1948 context);
1949 let start = dateSpan.range.start;
1950 // only rely on time info if drop zone is all-day,
1951 // otherwise, we already know the time
1952 if (dateSpan.allDay && dragMeta.startTime) {
1953 start = context.dateEnv.add(start, dragMeta.startTime);
1954 }
1955 let end = dragMeta.duration ?
1956 context.dateEnv.add(start, dragMeta.duration) :
1957 internal.getDefaultEventEnd(dateSpan.allDay, start, context);
1958 let instance = internal.createEventInstance(def.defId, { start, end });
1959 return { def, instance };
1960 }
1961 // Utils for extracting data from element
1962 // ----------------------------------------------------------------------------------------------------
1963 function getDragMetaFromEl(el) {
1964 let str = getEmbeddedElData(el, 'event');
1965 let obj = str ?
1966 JSON.parse(str) :
1967 { create: false }; // if no embedded data, assume no event creation
1968 return internal.parseDragMeta(obj);
1969 }
1970 internal.config.dataAttrPrefix = '';
1971 function getEmbeddedElData(el, name) {
1972 let prefix = internal.config.dataAttrPrefix;
1973 let prefixedName = (prefix ? prefix + '-' : '') + name;
1974 return el.getAttribute('data-' + prefixedName) || '';
1975 }
1976
1977 /*
1978 Makes an element (that is *external* to any calendar) draggable.
1979 Can pass in data that determines how an event will be created when dropped onto a calendar.
1980 Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
1981 */
1982 class ExternalDraggable {
1983 constructor(el, settings = {}) {
1984 this.handlePointerDown = (ev) => {
1985 let { dragging } = this;
1986 let { minDistance, longPressDelay } = this.settings;
1987 dragging.minDistance =
1988 minDistance != null ?
1989 minDistance :
1990 (ev.isTouch ? 0 : internal.BASE_OPTION_DEFAULTS.eventDragMinDistance);
1991 dragging.delay =
1992 ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
1993 (longPressDelay != null ? longPressDelay : internal.BASE_OPTION_DEFAULTS.longPressDelay) :
1994 0;
1995 };
1996 this.handleDragStart = (ev) => {
1997 if (ev.isTouch &&
1998 this.dragging.delay &&
1999 ev.subjectEl.classList.contains('fc-event')) {
2000 this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
2001 }
2002 };
2003 this.settings = settings;
2004 let dragging = this.dragging = new FeaturefulElementDragging(el);
2005 dragging.touchScrollAllowed = false;
2006 if (settings.itemSelector != null) {
2007 dragging.pointer.selector = settings.itemSelector;
2008 }
2009 if (settings.appendTo != null) {
2010 dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
2011 }
2012 dragging.emitter.on('pointerdown', this.handlePointerDown);
2013 dragging.emitter.on('dragstart', this.handleDragStart);
2014 new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
2015 }
2016 destroy() {
2017 this.dragging.destroy();
2018 }
2019 }
2020
2021 /*
2022 Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
2023 The third-party system is responsible for drawing the visuals effects of the drag.
2024 This class simply monitors for pointer movements and fires events.
2025 It also has the ability to hide the moving element (the "mirror") during the drag.
2026 */
2027 class InferredElementDragging extends internal.ElementDragging {
2028 constructor(containerEl) {
2029 super(containerEl);
2030 this.shouldIgnoreMove = false;
2031 this.mirrorSelector = '';
2032 this.currentMirrorEl = null;
2033 this.handlePointerDown = (ev) => {
2034 this.emitter.trigger('pointerdown', ev);
2035 if (!this.shouldIgnoreMove) {
2036 // fire dragstart right away. does not support delay or min-distance
2037 this.emitter.trigger('dragstart', ev);
2038 }
2039 };
2040 this.handlePointerMove = (ev) => {
2041 if (!this.shouldIgnoreMove) {
2042 this.emitter.trigger('dragmove', ev);
2043 }
2044 };
2045 this.handlePointerUp = (ev) => {
2046 this.emitter.trigger('pointerup', ev);
2047 if (!this.shouldIgnoreMove) {
2048 // fire dragend right away. does not support a revert animation
2049 this.emitter.trigger('dragend', ev);
2050 }
2051 };
2052 let pointer = this.pointer = new PointerDragging(containerEl);
2053 pointer.emitter.on('pointerdown', this.handlePointerDown);
2054 pointer.emitter.on('pointermove', this.handlePointerMove);
2055 pointer.emitter.on('pointerup', this.handlePointerUp);
2056 }
2057 destroy() {
2058 this.pointer.destroy();
2059 }
2060 setIgnoreMove(bool) {
2061 this.shouldIgnoreMove = bool;
2062 }
2063 setMirrorIsVisible(bool) {
2064 if (bool) {
2065 // restore a previously hidden element.
2066 // use the reference in case the selector class has already been removed.
2067 if (this.currentMirrorEl) {
2068 this.currentMirrorEl.style.visibility = '';
2069 this.currentMirrorEl = null;
2070 }
2071 }
2072 else {
2073 let mirrorEl = this.mirrorSelector
2074 // TODO: somehow query FullCalendars WITHIN shadow-roots
2075 ? document.querySelector(this.mirrorSelector)
2076 : null;
2077 if (mirrorEl) {
2078 this.currentMirrorEl = mirrorEl;
2079 mirrorEl.style.visibility = 'hidden';
2080 }
2081 }
2082 }
2083 }
2084
2085 /*
2086 Bridges third-party drag-n-drop systems with FullCalendar.
2087 Must be instantiated and destroyed by caller.
2088 */
2089 class ThirdPartyDraggable {
2090 constructor(containerOrSettings, settings) {
2091 let containerEl = document;
2092 if (
2093 // wish we could just test instanceof EventTarget, but doesn't work in IE11
2094 containerOrSettings === document ||
2095 containerOrSettings instanceof Element) {
2096 containerEl = containerOrSettings;
2097 settings = settings || {};
2098 }
2099 else {
2100 settings = (containerOrSettings || {});
2101 }
2102 let dragging = this.dragging = new InferredElementDragging(containerEl);
2103 if (typeof settings.itemSelector === 'string') {
2104 dragging.pointer.selector = settings.itemSelector;
2105 }
2106 else if (containerEl === document) {
2107 dragging.pointer.selector = '[data-event]';
2108 }
2109 if (typeof settings.mirrorSelector === 'string') {
2110 dragging.mirrorSelector = settings.mirrorSelector;
2111 }
2112 let externalDragging = new ExternalElementDragging(dragging, settings.eventData);
2113 // The hit-detection system requires that the dnd-mirror-element be pointer-events:none,
2114 // but this can't be guaranteed for third-party draggables, so disable
2115 externalDragging.hitDragging.disablePointCheck = true;
2116 }
2117 destroy() {
2118 this.dragging.destroy();
2119 }
2120 }
2121
2122 var plugin = core.createPlugin({
2123 name: '@fullcalendar/interaction',
2124 componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
2125 calendarInteractions: [UnselectAuto],
2126 elementDraggingImpl: FeaturefulElementDragging,
2127 optionRefiners: OPTION_REFINERS,
2128 listenerRefiners: LISTENER_REFINERS,
2129 });
2130
2131 core.globalPlugins.push(plugin);
2132
2133 exports.Draggable = ExternalDraggable;
2134 exports.ThirdPartyDraggable = ThirdPartyDraggable;
2135 exports["default"] = plugin;
2136
2137 Object.defineProperty(exports, '__esModule', { value: true });
2138
2139 return exports;
2140
2141})({}, FullCalendar, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/interaction/index.global.min.js b/public/js/fullcalendar/packages/interaction/index.global.min.js
new file mode 100644
index 0000000..1522b55
--- /dev/null
+++ b/public/js/fullcalendar/packages/interaction/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Interaction Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/editable
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Interaction=function(t,e,i){"use strict";i.config.touchMouseIgnoreWait=500;let n=0,s=0,r=!1;class o{constructor(t){this.subjectEl=null,this.selector="",this.handleSelector="",this.shouldIgnoreMove=!1,this.shouldWatchScroll=!0,this.isDragging=!1,this.isTouchDragging=!1,this.wasTouchScroll=!1,this.handleMouseDown=t=>{if(!this.shouldIgnoreMouse()&&function(t){return 0===t.button&&!t.ctrlKey}(t)&&this.tryStart(t)){let e=this.createEventFromMouse(t,!0);this.emitter.trigger("pointerdown",e),this.initScrollWatch(e),this.shouldIgnoreMove||document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}},this.handleMouseMove=t=>{let e=this.createEventFromMouse(t);this.recordCoords(e),this.emitter.trigger("pointermove",e)},this.handleMouseUp=t=>{document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp),this.emitter.trigger("pointerup",this.createEventFromMouse(t)),this.cleanup()},this.handleTouchStart=t=>{if(this.tryStart(t)){this.isTouchDragging=!0;let e=this.createEventFromTouch(t,!0);this.emitter.trigger("pointerdown",e),this.initScrollWatch(e);let i=t.target;this.shouldIgnoreMove||i.addEventListener("touchmove",this.handleTouchMove),i.addEventListener("touchend",this.handleTouchEnd),i.addEventListener("touchcancel",this.handleTouchEnd),window.addEventListener("scroll",this.handleTouchScroll,!0)}},this.handleTouchMove=t=>{let e=this.createEventFromTouch(t);this.recordCoords(e),this.emitter.trigger("pointermove",e)},this.handleTouchEnd=t=>{if(this.isDragging){let e=t.target;e.removeEventListener("touchmove",this.handleTouchMove),e.removeEventListener("touchend",this.handleTouchEnd),e.removeEventListener("touchcancel",this.handleTouchEnd),window.removeEventListener("scroll",this.handleTouchScroll,!0),this.emitter.trigger("pointerup",this.createEventFromTouch(t)),this.cleanup(),this.isTouchDragging=!1,n+=1,setTimeout(()=>{n-=1},i.config.touchMouseIgnoreWait)}},this.handleTouchScroll=()=>{this.wasTouchScroll=!0},this.handleScroll=t=>{if(!this.shouldIgnoreMove){let e=window.scrollX-this.prevScrollX+this.prevPageX,i=window.scrollY-this.prevScrollY+this.prevPageY;this.emitter.trigger("pointermove",{origEvent:t,isTouch:this.isTouchDragging,subjectEl:this.subjectEl,pageX:e,pageY:i,deltaX:e-this.origPageX,deltaY:i-this.origPageY})}},this.containerEl=t,this.emitter=new i.Emitter,t.addEventListener("mousedown",this.handleMouseDown),t.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),s+=1,1===s&&window.addEventListener("touchmove",l,{passive:!1})}destroy(){this.containerEl.removeEventListener("mousedown",this.handleMouseDown),this.containerEl.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),s-=1,s||window.removeEventListener("touchmove",l,{passive:!1})}tryStart(t){let e=this.querySubjectEl(t),n=t.target;return!(!e||this.handleSelector&&!i.elementClosest(n,this.handleSelector))&&(this.subjectEl=e,this.isDragging=!0,this.wasTouchScroll=!1,!0)}cleanup(){r=!1,this.isDragging=!1,this.subjectEl=null,this.destroyScrollWatch()}querySubjectEl(t){return this.selector?i.elementClosest(t.target,this.selector):this.containerEl}shouldIgnoreMouse(){return n||this.isTouchDragging}cancelTouchScroll(){this.isDragging&&(r=!0)}initScrollWatch(t){this.shouldWatchScroll&&(this.recordCoords(t),window.addEventListener("scroll",this.handleScroll,!0))}recordCoords(t){this.shouldWatchScroll&&(this.prevPageX=t.pageX,this.prevPageY=t.pageY,this.prevScrollX=window.scrollX,this.prevScrollY=window.scrollY)}destroyScrollWatch(){this.shouldWatchScroll&&window.removeEventListener("scroll",this.handleScroll,!0)}createEventFromMouse(t,e){let i=0,n=0;return e?(this.origPageX=t.pageX,this.origPageY=t.pageY):(i=t.pageX-this.origPageX,n=t.pageY-this.origPageY),{origEvent:t,isTouch:!1,subjectEl:this.subjectEl,pageX:t.pageX,pageY:t.pageY,deltaX:i,deltaY:n}}createEventFromTouch(t,e){let i,n,s=t.touches,r=0,o=0;return s&&s.length?(i=s[0].pageX,n=s[0].pageY):(i=t.pageX,n=t.pageY),e?(this.origPageX=i,this.origPageY=n):(r=i-this.origPageX,o=n-this.origPageY),{origEvent:t,isTouch:!0,subjectEl:this.subjectEl,pageX:i,pageY:n,deltaX:r,deltaY:o}}}function l(t){r&&t.preventDefault()}class a{constructor(){this.isVisible=!1,this.sourceEl=null,this.mirrorEl=null,this.sourceElRect=null,this.parentNode=document.body,this.zIndex=9999,this.revertDuration=0}start(t,e,i){this.sourceEl=t,this.sourceElRect=this.sourceEl.getBoundingClientRect(),this.origScreenX=e-window.scrollX,this.origScreenY=i-window.scrollY,this.deltaX=0,this.deltaY=0,this.updateElPosition()}handleMove(t,e){this.deltaX=t-window.scrollX-this.origScreenX,this.deltaY=e-window.scrollY-this.origScreenY,this.updateElPosition()}setIsVisible(t){t?this.isVisible||(this.mirrorEl&&(this.mirrorEl.style.display=""),this.isVisible=t,this.updateElPosition()):this.isVisible&&(this.mirrorEl&&(this.mirrorEl.style.display="none"),this.isVisible=t)}stop(t,e){let i=()=>{this.cleanup(),e()};t&&this.mirrorEl&&this.isVisible&&this.revertDuration&&(this.deltaX||this.deltaY)?this.doRevertAnimation(i,this.revertDuration):setTimeout(i,0)}doRevertAnimation(t,e){let n=this.mirrorEl,s=this.sourceEl.getBoundingClientRect();n.style.transition="top "+e+"ms,left "+e+"ms",i.applyStyle(n,{left:s.left,top:s.top}),i.whenTransitionDone(n,()=>{n.style.transition="",t()})}cleanup(){this.mirrorEl&&(i.removeElement(this.mirrorEl),this.mirrorEl=null),this.sourceEl=null}updateElPosition(){this.sourceEl&&this.isVisible&&i.applyStyle(this.getMirrorEl(),{left:this.sourceElRect.left+this.deltaX,top:this.sourceElRect.top+this.deltaY})}getMirrorEl(){let t=this.sourceElRect,e=this.mirrorEl;return e||(e=this.mirrorEl=this.sourceEl.cloneNode(!0),e.style.userSelect="none",e.style.webkitUserSelect="none",e.style.pointerEvents="none",e.classList.add("fc-event-dragging"),i.applyStyle(e,{position:"fixed",zIndex:this.zIndex,visibility:"",boxSizing:"border-box",width:t.right-t.left,height:t.bottom-t.top,right:"auto",bottom:"auto",margin:0}),this.parentNode.appendChild(e)),e}}class h extends i.ScrollController{constructor(t,e){super(),this.handleScroll=()=>{this.scrollTop=this.scrollController.getScrollTop(),this.scrollLeft=this.scrollController.getScrollLeft(),this.handleScrollChange()},this.scrollController=t,this.doesListening=e,this.scrollTop=this.origScrollTop=t.getScrollTop(),this.scrollLeft=this.origScrollLeft=t.getScrollLeft(),this.scrollWidth=t.getScrollWidth(),this.scrollHeight=t.getScrollHeight(),this.clientWidth=t.getClientWidth(),this.clientHeight=t.getClientHeight(),this.clientRect=this.computeClientRect(),this.doesListening&&this.getEventTarget().addEventListener("scroll",this.handleScroll)}destroy(){this.doesListening&&this.getEventTarget().removeEventListener("scroll",this.handleScroll)}getScrollTop(){return this.scrollTop}getScrollLeft(){return this.scrollLeft}setScrollTop(t){this.scrollController.setScrollTop(t),this.doesListening||(this.scrollTop=Math.max(Math.min(t,this.getMaxScrollTop()),0),this.handleScrollChange())}setScrollLeft(t){this.scrollController.setScrollLeft(t),this.doesListening||(this.scrollLeft=Math.max(Math.min(t,this.getMaxScrollLeft()),0),this.handleScrollChange())}getClientWidth(){return this.clientWidth}getClientHeight(){return this.clientHeight}getScrollWidth(){return this.scrollWidth}getScrollHeight(){return this.scrollHeight}handleScrollChange(){}}class c extends h{constructor(t,e){super(new i.ElementScrollController(t),e)}getEventTarget(){return this.scrollController.el}computeClientRect(){return i.computeInnerRect(this.scrollController.el)}}class d extends h{constructor(t){super(new i.WindowScrollController,t)}getEventTarget(){return window}computeClientRect(){return{left:this.scrollLeft,right:this.scrollLeft+this.clientWidth,top:this.scrollTop,bottom:this.scrollTop+this.clientHeight}}handleScrollChange(){this.clientRect=this.computeClientRect()}}const g="function"==typeof performance?performance.now:Date.now;class u{constructor(){this.isEnabled=!0,this.scrollQuery=[window,".fc-scroller"],this.edgeThreshold=50,this.maxVelocity=300,this.pointerScreenX=null,this.pointerScreenY=null,this.isAnimating=!1,this.scrollCaches=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.animate=()=>{if(this.isAnimating){let t=this.computeBestEdge(this.pointerScreenX+window.scrollX,this.pointerScreenY+window.scrollY);if(t){let e=g();this.handleSide(t,(e-this.msSinceRequest)/1e3),this.requestAnimation(e)}else this.isAnimating=!1}}}start(t,e,i){this.isEnabled&&(this.scrollCaches=this.buildCaches(i),this.pointerScreenX=null,this.pointerScreenY=null,this.everMovedUp=!1,this.everMovedDown=!1,this.everMovedLeft=!1,this.everMovedRight=!1,this.handleMove(t,e))}handleMove(t,e){if(this.isEnabled){let i=t-window.scrollX,n=e-window.scrollY,s=null===this.pointerScreenY?0:n-this.pointerScreenY,r=null===this.pointerScreenX?0:i-this.pointerScreenX;s<0?this.everMovedUp=!0:s>0&&(this.everMovedDown=!0),r<0?this.everMovedLeft=!0:r>0&&(this.everMovedRight=!0),this.pointerScreenX=i,this.pointerScreenY=n,this.isAnimating||(this.isAnimating=!0,this.requestAnimation(g()))}}stop(){if(this.isEnabled){this.isAnimating=!1;for(let t of this.scrollCaches)t.destroy();this.scrollCaches=null}}requestAnimation(t){this.msSinceRequest=t,requestAnimationFrame(this.animate)}handleSide(t,e){let{scrollCache:i}=t,{edgeThreshold:n}=this,s=n-t.distance,r=s*s/(n*n)*this.maxVelocity*e,o=1;switch(t.name){case"left":o=-1;case"right":i.setScrollLeft(i.getScrollLeft()+r*o);break;case"top":o=-1;case"bottom":i.setScrollTop(i.getScrollTop()+r*o)}}computeBestEdge(t,e){let{edgeThreshold:i}=this,n=null,s=this.scrollCaches||[];for(let r of s){let s=r.clientRect,o=t-s.left,l=s.right-t,a=e-s.top,h=s.bottom-e;o>=0&&l>=0&&a>=0&&h>=0&&(a<=i&&this.everMovedUp&&r.canScrollUp()&&(!n||n.distance>a)&&(n={scrollCache:r,name:"top",distance:a}),h<=i&&this.everMovedDown&&r.canScrollDown()&&(!n||n.distance>h)&&(n={scrollCache:r,name:"bottom",distance:h}),o<=i&&this.everMovedLeft&&r.canScrollLeft()&&(!n||n.distance>o)&&(n={scrollCache:r,name:"left",distance:o}),l<=i&&this.everMovedRight&&r.canScrollRight()&&(!n||n.distance>l)&&(n={scrollCache:r,name:"right",distance:l}))}return n}buildCaches(t){return this.queryScrollEls(t).map(t=>t===window?new d(!1):new c(t,!1))}queryScrollEls(t){let e=[];for(let i of this.scrollQuery)"object"==typeof i?e.push(i):e.push(...Array.prototype.slice.call(t.getRootNode().querySelectorAll(i)));return e}}class p extends i.ElementDragging{constructor(t,e){super(t),this.containerEl=t,this.delay=null,this.minDistance=0,this.touchScrollAllowed=!0,this.mirrorNeedsRevert=!1,this.isInteracting=!1,this.isDragging=!1,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,this.delayTimeoutId=null,this.onPointerDown=t=>{this.isDragging||(this.isInteracting=!0,this.isDelayEnded=!1,this.isDistanceSurpassed=!1,i.preventSelection(document.body),i.preventContextMenu(document.body),t.isTouch||t.origEvent.preventDefault(),this.emitter.trigger("pointerdown",t),this.isInteracting&&!this.pointer.shouldIgnoreMove&&(this.mirror.setIsVisible(!1),this.mirror.start(t.subjectEl,t.pageX,t.pageY),this.startDelay(t),this.minDistance||this.handleDistanceSurpassed(t)))},this.onPointerMove=t=>{if(this.isInteracting){if(this.emitter.trigger("pointermove",t),!this.isDistanceSurpassed){let e,i=this.minDistance,{deltaX:n,deltaY:s}=t;e=n*n+s*s,e>=i*i&&this.handleDistanceSurpassed(t)}this.isDragging&&("scroll"!==t.origEvent.type&&(this.mirror.handleMove(t.pageX,t.pageY),this.autoScroller.handleMove(t.pageX,t.pageY)),this.emitter.trigger("dragmove",t))}},this.onPointerUp=t=>{this.isInteracting&&(this.isInteracting=!1,i.allowSelection(document.body),i.allowContextMenu(document.body),this.emitter.trigger("pointerup",t),this.isDragging&&(this.autoScroller.stop(),this.tryStopDrag(t)),this.delayTimeoutId&&(clearTimeout(this.delayTimeoutId),this.delayTimeoutId=null))};let n=this.pointer=new o(t);n.emitter.on("pointerdown",this.onPointerDown),n.emitter.on("pointermove",this.onPointerMove),n.emitter.on("pointerup",this.onPointerUp),e&&(n.selector=e),this.mirror=new a,this.autoScroller=new u}destroy(){this.pointer.destroy(),this.onPointerUp({})}startDelay(t){"number"==typeof this.delay?this.delayTimeoutId=setTimeout(()=>{this.delayTimeoutId=null,this.handleDelayEnd(t)},this.delay):this.handleDelayEnd(t)}handleDelayEnd(t){this.isDelayEnded=!0,this.tryStartDrag(t)}handleDistanceSurpassed(t){this.isDistanceSurpassed=!0,this.tryStartDrag(t)}tryStartDrag(t){this.isDelayEnded&&this.isDistanceSurpassed&&(this.pointer.wasTouchScroll&&!this.touchScrollAllowed||(this.isDragging=!0,this.mirrorNeedsRevert=!1,this.autoScroller.start(t.pageX,t.pageY,this.containerEl),this.emitter.trigger("dragstart",t),!1===this.touchScrollAllowed&&this.pointer.cancelTouchScroll()))}tryStopDrag(t){this.mirror.stop(this.mirrorNeedsRevert,this.stopDrag.bind(this,t))}stopDrag(t){this.isDragging=!1,this.emitter.trigger("dragend",t)}setIgnoreMove(t){this.pointer.shouldIgnoreMove=t}setMirrorIsVisible(t){this.mirror.setIsVisible(t)}setMirrorNeedsRevert(t){this.mirrorNeedsRevert=t}setAutoScrollEnabled(t){this.autoScroller.isEnabled=t}}class v{constructor(t){this.el=t,this.origRect=i.computeRect(t),this.scrollCaches=i.getClippingParents(t).map(t=>new c(t,!0))}destroy(){for(let t of this.scrollCaches)t.destroy()}computeLeft(){let t=this.origRect.left;for(let e of this.scrollCaches)t+=e.origScrollLeft-e.getScrollLeft();return t}computeTop(){let t=this.origRect.top;for(let e of this.scrollCaches)t+=e.origScrollTop-e.getScrollTop();return t}isWithinClipping(t,e){let n={left:t,top:e};for(let t of this.scrollCaches)if(!E(t.getEventTarget())&&!i.pointInsideRect(n,t.clientRect))return!1;return!0}}function E(t){let e=t.tagName;return"HTML"===e||"BODY"===e}class m{constructor(t,e){this.useSubjectCenter=!1,this.requireInitial=!0,this.disablePointCheck=!1,this.initialHit=null,this.movingHit=null,this.finalHit=null,this.handlePointerDown=t=>{let{dragging:e}=this;this.initialHit=null,this.movingHit=null,this.finalHit=null,this.prepareHits(),this.processFirstCoord(t),this.initialHit||!this.requireInitial?(e.setIgnoreMove(!1),this.emitter.trigger("pointerdown",t)):e.setIgnoreMove(!0)},this.handleDragStart=t=>{this.emitter.trigger("dragstart",t),this.handleMove(t,!0)},this.handleDragMove=t=>{this.emitter.trigger("dragmove",t),this.handleMove(t)},this.handlePointerUp=t=>{this.releaseHits(),this.emitter.trigger("pointerup",t)},this.handleDragEnd=t=>{this.movingHit&&this.emitter.trigger("hitupdate",null,!0,t),this.finalHit=this.movingHit,this.movingHit=null,this.emitter.trigger("dragend",t)},this.droppableStore=e,t.emitter.on("pointerdown",this.handlePointerDown),t.emitter.on("dragstart",this.handleDragStart),t.emitter.on("dragmove",this.handleDragMove),t.emitter.on("pointerup",this.handlePointerUp),t.emitter.on("dragend",this.handleDragEnd),this.dragging=t,this.emitter=new i.Emitter}processFirstCoord(t){let e,n={left:t.pageX,top:t.pageY},s=n,r=t.subjectEl;r instanceof HTMLElement&&(e=i.computeRect(r),s=i.constrainPoint(s,e));let o=this.initialHit=this.queryHitForOffset(s.left,s.top);if(o){if(this.useSubjectCenter&&e){let t=i.intersectRects(e,o.rect);t&&(s=i.getRectCenter(t))}this.coordAdjust=i.diffPoints(s,n)}else this.coordAdjust={left:0,top:0}}handleMove(t,e){let i=this.queryHitForOffset(t.pageX+this.coordAdjust.left,t.pageY+this.coordAdjust.top);!e&&S(this.movingHit,i)||(this.movingHit=i,this.emitter.trigger("hitupdate",i,!1,t))}prepareHits(){this.offsetTrackers=i.mapHash(this.droppableStore,t=>(t.component.prepareHits(),new v(t.el)))}releaseHits(){let{offsetTrackers:t}=this;for(let e in t)t[e].destroy();this.offsetTrackers={}}queryHitForOffset(t,e){let{droppableStore:n,offsetTrackers:s}=this,r=null;for(let o in n){let l=n[o].component,a=s[o];if(a&&a.isWithinClipping(t,e)){let n=a.computeLeft(),s=a.computeTop(),h=t-n,c=e-s,{origRect:d}=a,g=d.right-d.left,u=d.bottom-d.top;if(h>=0&&h<g&&c>=0&&c<u){let t=l.queryHit(h,c,g,u);t&&i.rangeContainsRange(t.dateProfile.activeRange,t.dateSpan.range)&&(this.disablePointCheck||a.el.contains(a.el.getRootNode().elementFromPoint(h+n-window.scrollX,c+s-window.scrollY)))&&(!r||t.layer>r.layer)&&(t.componentId=o,t.context=l.context,t.rect.left+=n,t.rect.right+=n,t.rect.top+=s,t.rect.bottom+=s,r=t)}}}return r}}function S(t,e){return!t&&!e||Boolean(t)===Boolean(e)&&i.isDateSpansEqual(t.dateSpan,e.dateSpan)}function D(t,e){let i={};for(let n of e.pluginHooks.datePointTransforms)Object.assign(i,n(t,e));var n,s;return Object.assign(i,(n=t,{date:(s=e.dateEnv).toDate(n.range.start),dateStr:s.formatIso(n.range.start,{omitTime:n.allDay}),allDay:n.allDay})),i}class f extends i.Interaction{constructor(t){super(t),this.handlePointerDown=t=>{let{dragging:e}=this,i=t.origEvent.target;e.setIgnoreMove(!this.component.isValidDateDownEl(i))},this.handleDragEnd=t=>{let{component:e}=this,{pointer:i}=this.dragging;if(!i.wasTouchScroll){let{initialHit:i,finalHit:n}=this.hitDragging;if(i&&n&&S(i,n)){let{context:n}=e,s=Object.assign(Object.assign({},D(i.dateSpan,n)),{dayEl:i.dayEl,jsEvent:t.origEvent,view:n.viewApi||n.calendarApi.view});n.emitter.trigger("dateClick",s)}}},this.dragging=new p(t.el),this.dragging.autoScroller.isEnabled=!1;let e=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}}class y extends i.Interaction{constructor(t){super(t),this.dragSelection=null,this.handlePointerDown=t=>{let{component:e,dragging:i}=this,{options:n}=e.context,s=n.selectable&&e.isValidDateDownEl(t.origEvent.target);i.setIgnoreMove(!s),i.delay=t.isTouch?function(t){let{options:e}=t.context,i=e.selectLongPressDelay;null==i&&(i=e.longPressDelay);return i}(e):null},this.handleDragStart=t=>{this.component.context.calendarApi.unselect(t)},this.handleHitUpdate=(t,e)=>{let{context:n}=this.component,s=null,r=!1;if(t){let e=this.hitDragging.initialHit;t.componentId===e.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(e,t)||(s=function(t,e,n){let s=t.dateSpan,r=e.dateSpan,o=[s.range.start,s.range.end,r.range.start,r.range.end];o.sort(i.compareNumbers);let l={};for(let i of n){let n=i(t,e);if(!1===n)return null;n&&Object.assign(l,n)}return l.range={start:o[0],end:o[3]},l.allDay=s.allDay,l}(e,t,n.pluginHooks.dateSelectionTransformers)),s&&i.isDateSelectionValid(s,t.dateProfile,n)||(r=!0,s=null)}s?n.dispatch({type:"SELECT_DATES",selection:s}):e||n.dispatch({type:"UNSELECT_DATES"}),r?i.disableCursor():i.enableCursor(),e||(this.dragSelection=s)},this.handlePointerUp=t=>{this.dragSelection&&(i.triggerDateSelect(this.dragSelection,t,this.component.context),this.dragSelection=null)};let{component:e}=t,{options:n}=e.context,s=this.dragging=new p(t.el);s.touchScrollAllowed=!1,s.minDistance=n.selectMinDistance||0,s.autoScroller.isEnabled=n.dragScroll;let r=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.dragging.destroy()}}class w extends i.Interaction{constructor(t){super(t),this.subjectEl=null,this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=t=>{let e=t.origEvent.target,{component:n,dragging:s}=this,{mirror:r}=s,{options:o}=n.context,l=n.context;this.subjectEl=t.subjectEl;let a=this.subjectSeg=i.getElSeg(t.subjectEl),h=(this.eventRange=a.eventRange).instance.instanceId;this.relevantEvents=i.getRelevantEvents(l.getCurrentData().eventStore,h),s.minDistance=t.isTouch?0:o.eventDragMinDistance,s.delay=t.isTouch&&h!==n.props.eventSelection?function(t){let{options:e}=t.context,i=e.eventLongPressDelay;null==i&&(i=e.longPressDelay);return i}(n):null,o.fixedMirrorParent?r.parentNode=o.fixedMirrorParent:r.parentNode=i.elementClosest(e,".fc"),r.revertDuration=o.dragRevertDuration;let c=n.isValidSegDownEl(e)&&!i.elementClosest(e,".fc-event-resizer");s.setIgnoreMove(!c),this.isDragging=c&&t.subjectEl.classList.contains("fc-event-draggable")},this.handleDragStart=t=>{let e=this.component.context,n=this.eventRange,s=n.instance.instanceId;t.isTouch?s!==this.component.props.eventSelection&&e.dispatch({type:"SELECT_EVENT",eventInstanceId:s}):e.dispatch({type:"UNSELECT_EVENT"}),this.isDragging&&(e.calendarApi.unselect(t),e.emitter.trigger("eventDragStart",{el:this.subjectEl,event:new i.EventImpl(e,n.def,n.instance),jsEvent:t.origEvent,view:e.viewApi}))},this.handleHitUpdate=(t,e)=>{if(!this.isDragging)return;let n=this.relevantEvents,s=this.hitDragging.initialHit,r=this.component.context,o=null,l=null,a=null,h=!1,c={affectedEvents:n,mutatedEvents:i.createEmptyEventStore(),isEvent:!0};if(t){o=t.context;let e=o.options;r===o||e.editable&&e.droppable?(l=function(t,e,n,s){let r=t.dateSpan,o=e.dateSpan,l=r.range.start,a=o.range.start,h={};r.allDay!==o.allDay&&(h.allDay=o.allDay,h.hasEnd=e.context.options.allDayMaintainDuration,l=o.allDay?i.startOfDay(n):n);let c=i.diffDates(l,a,t.context.dateEnv,t.componentId===e.componentId?t.largeUnit:null);c.milliseconds&&(h.allDay=!1);let d={datesDelta:c,standardProps:h};for(let i of s)i(d,t,e);return d}(s,t,this.eventRange.instance.range.start,o.getCurrentData().pluginHooks.eventDragMutationMassagers),l&&(a=i.applyMutationToEventStore(n,o.getCurrentData().eventUiBases,l,o),c.mutatedEvents=a,i.isInteractionValid(c,t.dateProfile,o)||(h=!0,l=null,a=null,c.mutatedEvents=i.createEmptyEventStore()))):o=null}this.displayDrag(o,c),h?i.disableCursor():i.enableCursor(),e||(r===o&&S(s,t)&&(l=null),this.dragging.setMirrorNeedsRevert(!l),this.dragging.setMirrorIsVisible(!t||!this.subjectEl.getRootNode().querySelector(".fc-event-mirror")),this.receivingContext=o,this.validMutation=l,this.mutatedRelevantEvents=a)},this.handlePointerUp=()=>{this.isDragging||this.cleanup()},this.handleDragEnd=t=>{if(this.isDragging){let e=this.component.context,n=e.viewApi,{receivingContext:s,validMutation:r}=this,o=this.eventRange.def,l=this.eventRange.instance,a=new i.EventImpl(e,o,l),h=this.relevantEvents,c=this.mutatedRelevantEvents,{finalHit:d}=this.hitDragging;if(this.clearDrag(),e.emitter.trigger("eventDragStop",{el:this.subjectEl,event:a,jsEvent:t.origEvent,view:n}),r){if(s===e){let s=new i.EventImpl(e,c.defs[o.defId],l?c.instances[l.instanceId]:null);e.dispatch({type:"MERGE_EVENTS",eventStore:c});let d={oldEvent:a,event:s,relatedEvents:i.buildEventApis(c,e,l),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:h})}},g={};for(let t of e.getCurrentData().pluginHooks.eventDropTransformers)Object.assign(g,t(r,e));e.emitter.trigger("eventDrop",Object.assign(Object.assign(Object.assign({},d),g),{el:t.subjectEl,delta:r.datesDelta,jsEvent:t.origEvent,view:n})),e.emitter.trigger("eventChange",d)}else if(s){let r={event:a,relatedEvents:i.buildEventApis(h,e,l),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:h})}};e.emitter.trigger("eventLeave",Object.assign(Object.assign({},r),{draggedEl:t.subjectEl,view:n})),e.dispatch({type:"REMOVE_EVENTS",eventStore:h}),e.emitter.trigger("eventRemove",r);let g=c.defs[o.defId],u=c.instances[l.instanceId],p=new i.EventImpl(s,g,u);s.dispatch({type:"MERGE_EVENTS",eventStore:c});let v={event:p,relatedEvents:i.buildEventApis(c,s,u),revert(){s.dispatch({type:"REMOVE_EVENTS",eventStore:c})}};s.emitter.trigger("eventAdd",v),t.isTouch&&s.dispatch({type:"SELECT_EVENT",eventInstanceId:l.instanceId}),s.emitter.trigger("drop",Object.assign(Object.assign({},D(d.dateSpan,s)),{draggedEl:t.subjectEl,jsEvent:t.origEvent,view:d.context.viewApi})),s.emitter.trigger("eventReceive",Object.assign(Object.assign({},v),{draggedEl:t.subjectEl,view:d.context.viewApi}))}}else e.emitter.trigger("_noEventDrop")}this.cleanup()};let{component:e}=this,{options:n}=e.context,s=this.dragging=new p(t.el);s.pointer.selector=w.SELECTOR,s.touchScrollAllowed=!1,s.autoScroller.isEnabled=n.dragScroll;let r=this.hitDragging=new m(this.dragging,i.interactionSettingsStore);r.useSubjectCenter=t.useEventCenter,r.emitter.on("pointerdown",this.handlePointerDown),r.emitter.on("dragstart",this.handleDragStart),r.emitter.on("hitupdate",this.handleHitUpdate),r.emitter.on("pointerup",this.handlePointerUp),r.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}displayDrag(t,e){let n=this.component.context,s=this.receivingContext;s&&s!==t&&(s===n?s.dispatch({type:"SET_EVENT_DRAG",state:{affectedEvents:e.affectedEvents,mutatedEvents:i.createEmptyEventStore(),isEvent:!0}}):s.dispatch({type:"UNSET_EVENT_DRAG"})),t&&t.dispatch({type:"SET_EVENT_DRAG",state:e})}clearDrag(){let t=this.component.context,{receivingContext:e}=this;e&&e.dispatch({type:"UNSET_EVENT_DRAG"}),t!==e&&t.dispatch({type:"UNSET_EVENT_DRAG"})}cleanup(){this.subjectSeg=null,this.isDragging=!1,this.eventRange=null,this.relevantEvents=null,this.receivingContext=null,this.validMutation=null,this.mutatedRelevantEvents=null}}w.SELECTOR=".fc-event-draggable, .fc-event-resizable";class T extends i.Interaction{constructor(t){super(t),this.draggingSegEl=null,this.draggingSeg=null,this.eventRange=null,this.relevantEvents=null,this.validMutation=null,this.mutatedRelevantEvents=null,this.handlePointerDown=t=>{let{component:e}=this,n=this.querySegEl(t),s=i.getElSeg(n),r=this.eventRange=s.eventRange;this.dragging.minDistance=e.context.options.eventDragMinDistance,this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(t.origEvent.target)||t.isTouch&&this.component.props.eventSelection!==r.instance.instanceId)},this.handleDragStart=t=>{let{context:e}=this.component,n=this.eventRange;this.relevantEvents=i.getRelevantEvents(e.getCurrentData().eventStore,this.eventRange.instance.instanceId);let s=this.querySegEl(t);this.draggingSegEl=s,this.draggingSeg=i.getElSeg(s),e.calendarApi.unselect(),e.emitter.trigger("eventResizeStart",{el:s,event:new i.EventImpl(e,n.def,n.instance),jsEvent:t.origEvent,view:e.viewApi})},this.handleHitUpdate=(t,e,n)=>{let{context:s}=this.component,r=this.relevantEvents,o=this.hitDragging.initialHit,l=this.eventRange.instance,a=null,h=null,c=!1,d={affectedEvents:r,mutatedEvents:i.createEmptyEventStore(),isEvent:!0};if(t){t.componentId===o.componentId&&this.isHitComboAllowed&&!this.isHitComboAllowed(o,t)||(a=function(t,e,n,s){let r=t.context.dateEnv,o=t.dateSpan.range.start,l=e.dateSpan.range.start,a=i.diffDates(o,l,r,t.largeUnit);if(n){if(r.add(s.start,a)<s.end)return{startDelta:a}}else if(r.add(s.end,a)>s.start)return{endDelta:a};return null}(o,t,n.subjectEl.classList.contains("fc-event-resizer-start"),l.range))}a&&(h=i.applyMutationToEventStore(r,s.getCurrentData().eventUiBases,a,s),d.mutatedEvents=h,i.isInteractionValid(d,t.dateProfile,s)||(c=!0,a=null,h=null,d.mutatedEvents=null)),h?s.dispatch({type:"SET_EVENT_RESIZE",state:d}):s.dispatch({type:"UNSET_EVENT_RESIZE"}),c?i.disableCursor():i.enableCursor(),e||(a&&S(o,t)&&(a=null),this.validMutation=a,this.mutatedRelevantEvents=h)},this.handleDragEnd=t=>{let{context:e}=this.component,n=this.eventRange.def,s=this.eventRange.instance,r=new i.EventImpl(e,n,s),o=this.relevantEvents,l=this.mutatedRelevantEvents;if(e.emitter.trigger("eventResizeStop",{el:this.draggingSegEl,event:r,jsEvent:t.origEvent,view:e.viewApi}),this.validMutation){let a=new i.EventImpl(e,l.defs[n.defId],s?l.instances[s.instanceId]:null);e.dispatch({type:"MERGE_EVENTS",eventStore:l});let h={oldEvent:r,event:a,relatedEvents:i.buildEventApis(l,e,s),revert(){e.dispatch({type:"MERGE_EVENTS",eventStore:o})}};e.emitter.trigger("eventResize",Object.assign(Object.assign({},h),{el:this.draggingSegEl,startDelta:this.validMutation.startDelta||i.createDuration(0),endDelta:this.validMutation.endDelta||i.createDuration(0),jsEvent:t.origEvent,view:e.viewApi})),e.emitter.trigger("eventChange",h)}else e.emitter.trigger("_noEventResize");this.draggingSeg=null,this.relevantEvents=null,this.validMutation=null};let{component:e}=t,n=this.dragging=new p(t.el);n.pointer.selector=".fc-event-resizer",n.touchScrollAllowed=!1,n.autoScroller.isEnabled=e.context.options.dragScroll;let s=this.hitDragging=new m(this.dragging,i.interactionSettingsToStore(t));s.emitter.on("pointerdown",this.handlePointerDown),s.emitter.on("dragstart",this.handleDragStart),s.emitter.on("hitupdate",this.handleHitUpdate),s.emitter.on("dragend",this.handleDragEnd)}destroy(){this.dragging.destroy()}querySegEl(t){return i.elementClosest(t.subjectEl,".fc-event")}}const b={fixedMirrorParent:i.identity},M={dateClick:i.identity,eventDragStart:i.identity,eventDragStop:i.identity,eventDrop:i.identity,eventResizeStart:i.identity,eventResizeStop:i.identity,eventResize:i.identity,drop:i.identity,eventReceive:i.identity,eventLeave:i.identity};class C{constructor(t,e){this.receivingContext=null,this.droppableEvent=null,this.suppliedDragMeta=null,this.dragMeta=null,this.handleDragStart=t=>{this.dragMeta=this.buildDragMeta(t.subjectEl)},this.handleHitUpdate=(t,e,n)=>{let{dragging:s}=this.hitDragging,r=null,o=null,l=!1,a={affectedEvents:i.createEmptyEventStore(),mutatedEvents:i.createEmptyEventStore(),isEvent:this.dragMeta.create};t&&(r=t.context,this.canDropElOnCalendar(n.subjectEl,r)&&(o=function(t,e,n){let s=Object.assign({},e.leftoverProps);for(let i of n.pluginHooks.externalDefTransforms)Object.assign(s,i(t,e));let{refined:r,extra:o}=i.refineEventDef(s,n),l=i.parseEventDef(r,o,e.sourceId,t.allDay,n.options.forceEventDuration||Boolean(e.duration),n),a=t.range.start;t.allDay&&e.startTime&&(a=n.dateEnv.add(a,e.startTime));let h=e.duration?n.dateEnv.add(a,e.duration):i.getDefaultEventEnd(t.allDay,a,n),c=i.createEventInstance(l.defId,{start:a,end:h});return{def:l,instance:c}}(t.dateSpan,this.dragMeta,r),a.mutatedEvents=i.eventTupleToStore(o),l=!i.isInteractionValid(a,t.dateProfile,r),l&&(a.mutatedEvents=i.createEmptyEventStore(),o=null))),this.displayDrag(r,a),s.setMirrorIsVisible(e||!o||!document.querySelector(".fc-event-mirror")),l?i.disableCursor():i.enableCursor(),e||(s.setMirrorNeedsRevert(!o),this.receivingContext=r,this.droppableEvent=o)},this.handleDragEnd=t=>{let{receivingContext:e,droppableEvent:n}=this;if(this.clearDrag(),e&&n){let s=this.hitDragging.finalHit,r=s.context.viewApi,o=this.dragMeta;if(e.emitter.trigger("drop",Object.assign(Object.assign({},D(s.dateSpan,e)),{draggedEl:t.subjectEl,jsEvent:t.origEvent,view:r})),o.create){let s=i.eventTupleToStore(n);e.dispatch({type:"MERGE_EVENTS",eventStore:s}),t.isTouch&&e.dispatch({type:"SELECT_EVENT",eventInstanceId:n.instance.instanceId}),e.emitter.trigger("eventReceive",{event:new i.EventImpl(e,n.def,n.instance),relatedEvents:[],revert(){e.dispatch({type:"REMOVE_EVENTS",eventStore:s})},draggedEl:t.subjectEl,view:r})}}this.receivingContext=null,this.droppableEvent=null};let n=this.hitDragging=new m(t,i.interactionSettingsStore);n.requireInitial=!1,n.emitter.on("dragstart",this.handleDragStart),n.emitter.on("hitupdate",this.handleHitUpdate),n.emitter.on("dragend",this.handleDragEnd),this.suppliedDragMeta=e}buildDragMeta(t){return"object"==typeof this.suppliedDragMeta?i.parseDragMeta(this.suppliedDragMeta):"function"==typeof this.suppliedDragMeta?i.parseDragMeta(this.suppliedDragMeta(t)):function(t){let e=function(t,e){let n=i.config.dataAttrPrefix,s=(n?n+"-":"")+e;return t.getAttribute("data-"+s)||""}(t,"event"),n=e?JSON.parse(e):{create:!1};return i.parseDragMeta(n)}(t)}displayDrag(t,e){let i=this.receivingContext;i&&i!==t&&i.dispatch({type:"UNSET_EVENT_DRAG"}),t&&t.dispatch({type:"SET_EVENT_DRAG",state:e})}clearDrag(){this.receivingContext&&this.receivingContext.dispatch({type:"UNSET_EVENT_DRAG"})}canDropElOnCalendar(t,e){let n=e.options.dropAccept;return"function"==typeof n?n.call(e.calendarApi,t):"string"!=typeof n||!n||Boolean(i.elementMatches(t,n))}}i.config.dataAttrPrefix="";class R extends i.ElementDragging{constructor(t){super(t),this.shouldIgnoreMove=!1,this.mirrorSelector="",this.currentMirrorEl=null,this.handlePointerDown=t=>{this.emitter.trigger("pointerdown",t),this.shouldIgnoreMove||this.emitter.trigger("dragstart",t)},this.handlePointerMove=t=>{this.shouldIgnoreMove||this.emitter.trigger("dragmove",t)},this.handlePointerUp=t=>{this.emitter.trigger("pointerup",t),this.shouldIgnoreMove||this.emitter.trigger("dragend",t)};let e=this.pointer=new o(t);e.emitter.on("pointerdown",this.handlePointerDown),e.emitter.on("pointermove",this.handlePointerMove),e.emitter.on("pointerup",this.handlePointerUp)}destroy(){this.pointer.destroy()}setIgnoreMove(t){this.shouldIgnoreMove=t}setMirrorIsVisible(t){if(t)this.currentMirrorEl&&(this.currentMirrorEl.style.visibility="",this.currentMirrorEl=null);else{let t=this.mirrorSelector?document.querySelector(this.mirrorSelector):null;t&&(this.currentMirrorEl=t,t.style.visibility="hidden")}}}var I=e.createPlugin({name:"@fullcalendar/interaction",componentInteractions:[f,y,w,T],calendarInteractions:[class{constructor(t){this.context=t,this.isRecentPointerDateSelect=!1,this.matchesCancel=!1,this.matchesEvent=!1,this.onSelect=t=>{t.jsEvent&&(this.isRecentPointerDateSelect=!0)},this.onDocumentPointerDown=t=>{let e=this.context.options.unselectCancel,n=i.getEventTargetViaRoot(t.origEvent);this.matchesCancel=!!i.elementClosest(n,e),this.matchesEvent=!!i.elementClosest(n,w.SELECTOR)},this.onDocumentPointerUp=t=>{let{context:e}=this,{documentPointer:i}=this,n=e.getCurrentData();if(!i.wasTouchScroll){if(n.dateSelection&&!this.isRecentPointerDateSelect){let i=e.options.unselectAuto;!i||i&&this.matchesCancel||e.calendarApi.unselect(t)}n.eventSelection&&!this.matchesEvent&&e.dispatch({type:"UNSELECT_EVENT"})}this.isRecentPointerDateSelect=!1};let e=this.documentPointer=new o(document);e.shouldIgnoreMove=!0,e.shouldWatchScroll=!1,e.emitter.on("pointerdown",this.onDocumentPointerDown),e.emitter.on("pointerup",this.onDocumentPointerUp),t.emitter.on("select",this.onSelect)}destroy(){this.context.emitter.off("select",this.onSelect),this.documentPointer.destroy()}}],elementDraggingImpl:p,optionRefiners:b,listenerRefiners:M});return e.globalPlugins.push(I),t.Draggable=class{constructor(t,e={}){this.handlePointerDown=t=>{let{dragging:e}=this,{minDistance:n,longPressDelay:s}=this.settings;e.minDistance=null!=n?n:t.isTouch?0:i.BASE_OPTION_DEFAULTS.eventDragMinDistance,e.delay=t.isTouch?null!=s?s:i.BASE_OPTION_DEFAULTS.longPressDelay:0},this.handleDragStart=t=>{t.isTouch&&this.dragging.delay&&t.subjectEl.classList.contains("fc-event")&&this.dragging.mirror.getMirrorEl().classList.add("fc-event-selected")},this.settings=e;let n=this.dragging=new p(t);n.touchScrollAllowed=!1,null!=e.itemSelector&&(n.pointer.selector=e.itemSelector),null!=e.appendTo&&(n.mirror.parentNode=e.appendTo),n.emitter.on("pointerdown",this.handlePointerDown),n.emitter.on("dragstart",this.handleDragStart),new C(n,e.eventData)}destroy(){this.dragging.destroy()}},t.ThirdPartyDraggable=class{constructor(t,e){let i=document;t===document||t instanceof Element?(i=t,e=e||{}):e=t||{};let n=this.dragging=new R(i);"string"==typeof e.itemSelector?n.pointer.selector=e.itemSelector:i===document&&(n.pointer.selector="[data-event]"),"string"==typeof e.mirrorSelector&&(n.mirrorSelector=e.mirrorSelector),new C(n,e.eventData).hitDragging.disablePointCheck=!0}destroy(){this.dragging.destroy()}},t.default=I,Object.defineProperty(t,"__esModule",{value:!0}),t}({},FullCalendar,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/list/index.global.js b/public/js/fullcalendar/packages/list/index.global.js
new file mode 100644
index 0000000..930a554
--- /dev/null
+++ b/public/js/fullcalendar/packages/list/index.global.js
@@ -0,0 +1,332 @@
1/*!
2FullCalendar List View Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/list-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.List = (function (exports, core, internal$1, preact) {
7 'use strict';
8
9 class ListViewHeaderRow extends internal$1.BaseComponent {
10 constructor() {
11 super(...arguments);
12 this.state = {
13 textId: internal$1.getUniqueDomId(),
14 };
15 }
16 render() {
17 let { theme, dateEnv, options, viewApi } = this.context;
18 let { cellId, dayDate, todayRange } = this.props;
19 let { textId } = this.state;
20 let dayMeta = internal$1.getDateMeta(dayDate, todayRange);
21 // will ever be falsy?
22 let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
23 // will ever be falsy? also, BAD NAME "alt"
24 let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
25 let renderProps = Object.assign({ date: dateEnv.toDate(dayDate), view: viewApi, textId,
26 text,
27 sideText, navLinkAttrs: internal$1.buildNavLinkAttrs(this.context, dayDate), sideNavLinkAttrs: internal$1.buildNavLinkAttrs(this.context, dayDate, 'day', false) }, dayMeta);
28 // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
29 return (preact.createElement(internal$1.ContentContainer, { elTag: "tr", elClasses: [
30 'fc-list-day',
31 ...internal$1.getDayClassNames(dayMeta, theme),
32 ], elAttrs: {
33 'data-date': internal$1.formatDayString(dayDate),
34 }, renderProps: renderProps, generatorName: "dayHeaderContent", customGenerator: options.dayHeaderContent, defaultGenerator: renderInnerContent, classNameGenerator: options.dayHeaderClassNames, didMount: options.dayHeaderDidMount, willUnmount: options.dayHeaderWillUnmount }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
35 preact.createElement("th", { scope: "colgroup", colSpan: 3, id: cellId, "aria-labelledby": textId },
36 preact.createElement(InnerContent, { elTag: "div", elClasses: [
37 'fc-list-day-cushion',
38 theme.getClass('tableCellShaded'),
39 ] })))));
40 }
41 }
42 function renderInnerContent(props) {
43 return (preact.createElement(preact.Fragment, null,
44 props.text && (preact.createElement("a", Object.assign({ id: props.textId, className: "fc-list-day-text" }, props.navLinkAttrs), props.text)),
45 props.sideText && ( /* not keyboard tabbable */preact.createElement("a", Object.assign({ "aria-hidden": true, className: "fc-list-day-side-text" }, props.sideNavLinkAttrs), props.sideText))));
46 }
47
48 const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
49 hour: 'numeric',
50 minute: '2-digit',
51 meridiem: 'short',
52 });
53 class ListViewEventRow extends internal$1.BaseComponent {
54 render() {
55 let { props, context } = this;
56 let { options } = context;
57 let { seg, timeHeaderId, eventHeaderId, dateHeaderId } = props;
58 let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
59 return (preact.createElement(internal$1.EventContainer, Object.assign({}, props, { elTag: "tr", elClasses: [
60 'fc-list-event',
61 seg.eventRange.def.url && 'fc-event-forced-url',
62 ], defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */, seg: seg, timeText: "", disableDragging: true, disableResizing: true }), (InnerContent, eventContentArg) => (preact.createElement(preact.Fragment, null,
63 buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
64 preact.createElement("td", { "aria-hidden": true, className: "fc-list-event-graphic" },
65 preact.createElement("span", { className: "fc-list-event-dot", style: {
66 borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
67 } })),
68 preact.createElement(InnerContent, { elTag: "td", elClasses: ['fc-list-event-title'], elAttrs: { headers: `${eventHeaderId} ${dateHeaderId}` } })))));
69 }
70 }
71 function renderEventInnerContent(seg, context) {
72 let interactiveAttrs = internal$1.getSegAnchorAttrs(seg, context);
73 return (preact.createElement("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
74 }
75 function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
76 let { options } = context;
77 if (options.displayEventTime !== false) {
78 let eventDef = seg.eventRange.def;
79 let eventInstance = seg.eventRange.instance;
80 let doAllDay = false;
81 let timeText;
82 if (eventDef.allDay) {
83 doAllDay = true;
84 }
85 else if (internal$1.isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
86 if (seg.isStart) {
87 timeText = internal$1.buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
88 }
89 else if (seg.isEnd) {
90 timeText = internal$1.buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
91 }
92 else {
93 doAllDay = true;
94 }
95 }
96 else {
97 timeText = internal$1.buildSegTimeText(seg, timeFormat, context);
98 }
99 if (doAllDay) {
100 let renderProps = {
101 text: context.options.allDayText,
102 view: context.viewApi,
103 };
104 return (preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: ['fc-list-event-time'], elAttrs: {
105 headers: `${timeHeaderId} ${dateHeaderId}`,
106 }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }));
107 }
108 return (preact.createElement("td", { className: "fc-list-event-time" }, timeText));
109 }
110 return null;
111 }
112 function renderAllDayInner(renderProps) {
113 return renderProps.text;
114 }
115
116 /*
117 Responsible for the scroller, and forwarding event-related actions into the "grid".
118 */
119 class ListView extends internal$1.DateComponent {
120 constructor() {
121 super(...arguments);
122 this.computeDateVars = internal$1.memoize(computeDateVars);
123 this.eventStoreToSegs = internal$1.memoize(this._eventStoreToSegs);
124 this.state = {
125 timeHeaderId: internal$1.getUniqueDomId(),
126 eventHeaderId: internal$1.getUniqueDomId(),
127 dateHeaderIdRoot: internal$1.getUniqueDomId(),
128 };
129 this.setRootEl = (rootEl) => {
130 if (rootEl) {
131 this.context.registerInteractiveComponent(this, {
132 el: rootEl,
133 });
134 }
135 else {
136 this.context.unregisterInteractiveComponent(this);
137 }
138 };
139 }
140 render() {
141 let { props, context } = this;
142 let { dayDates, dayRanges } = this.computeDateVars(props.dateProfile);
143 let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
144 return (preact.createElement(internal$1.ViewContainer, { elRef: this.setRootEl, elClasses: [
145 'fc-list',
146 context.theme.getClass('table'),
147 context.options.stickyHeaderDates !== false ?
148 'fc-list-sticky' :
149 '',
150 ], viewSpec: context.viewSpec },
151 preact.createElement(internal$1.Scroller, { liquid: !props.isHeightAuto, overflowX: props.isHeightAuto ? 'visible' : 'hidden', overflowY: props.isHeightAuto ? 'visible' : 'auto' }, eventSegs.length > 0 ?
152 this.renderSegList(eventSegs, dayDates) :
153 this.renderEmptyMessage())));
154 }
155 renderEmptyMessage() {
156 let { options, viewApi } = this.context;
157 let renderProps = {
158 text: options.noEventsText,
159 view: viewApi,
160 };
161 return (preact.createElement(internal$1.ContentContainer, { elTag: "div", elClasses: ['fc-list-empty'], renderProps: renderProps, generatorName: "noEventsContent", customGenerator: options.noEventsContent, defaultGenerator: renderNoEventsInner, classNameGenerator: options.noEventsClassNames, didMount: options.noEventsDidMount, willUnmount: options.noEventsWillUnmount }, (InnerContent) => (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-list-empty-cushion'] }))));
162 }
163 renderSegList(allSegs, dayDates) {
164 let { theme, options } = this.context;
165 let { timeHeaderId, eventHeaderId, dateHeaderIdRoot } = this.state;
166 let segsByDay = groupSegsByDay(allSegs); // sparse array
167 return (preact.createElement(internal$1.NowTimer, { unit: "day" }, (nowDate, todayRange) => {
168 let innerNodes = [];
169 for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
170 let daySegs = segsByDay[dayIndex];
171 if (daySegs) { // sparse array, so might be undefined
172 let dayStr = internal$1.formatDayString(dayDates[dayIndex]);
173 let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
174 // append a day header
175 innerNodes.push(preact.createElement(ListViewHeaderRow, { key: dayStr, cellId: dateHeaderId, dayDate: dayDates[dayIndex], todayRange: todayRange }));
176 daySegs = internal$1.sortEventSegs(daySegs, options.eventOrder);
177 for (let seg of daySegs) {
178 innerNodes.push(preact.createElement(ListViewEventRow, Object.assign({ key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: false, timeHeaderId: timeHeaderId, eventHeaderId: eventHeaderId, dateHeaderId: dateHeaderId }, internal$1.getSegMeta(seg, todayRange, nowDate))));
179 }
180 }
181 }
182 return (preact.createElement("table", { className: 'fc-list-table ' + theme.getClass('table') },
183 preact.createElement("thead", null,
184 preact.createElement("tr", null,
185 preact.createElement("th", { scope: "col", id: timeHeaderId }, options.timeHint),
186 preact.createElement("th", { scope: "col", "aria-hidden": true }),
187 preact.createElement("th", { scope: "col", id: eventHeaderId }, options.eventHint))),
188 preact.createElement("tbody", null, innerNodes)));
189 }));
190 }
191 _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
192 return this.eventRangesToSegs(internal$1.sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
193 }
194 eventRangesToSegs(eventRanges, dayRanges) {
195 let segs = [];
196 for (let eventRange of eventRanges) {
197 segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
198 }
199 return segs;
200 }
201 eventRangeToSegs(eventRange, dayRanges) {
202 let { dateEnv } = this.context;
203 let { nextDayThreshold } = this.context.options;
204 let range = eventRange.range;
205 let allDay = eventRange.def.allDay;
206 let dayIndex;
207 let segRange;
208 let seg;
209 let segs = [];
210 for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
211 segRange = internal$1.intersectRanges(range, dayRanges[dayIndex]);
212 if (segRange) {
213 seg = {
214 component: this,
215 eventRange,
216 start: segRange.start,
217 end: segRange.end,
218 isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
219 isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
220 dayIndex,
221 };
222 segs.push(seg);
223 // detect when range won't go fully into the next day,
224 // and mutate the latest seg to the be the end.
225 if (!seg.isEnd && !allDay &&
226 dayIndex + 1 < dayRanges.length &&
227 range.end <
228 dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
229 seg.end = range.end;
230 seg.isEnd = true;
231 break;
232 }
233 }
234 }
235 return segs;
236 }
237 }
238 function renderNoEventsInner(renderProps) {
239 return renderProps.text;
240 }
241 function computeDateVars(dateProfile) {
242 let dayStart = internal$1.startOfDay(dateProfile.renderRange.start);
243 let viewEnd = dateProfile.renderRange.end;
244 let dayDates = [];
245 let dayRanges = [];
246 while (dayStart < viewEnd) {
247 dayDates.push(dayStart);
248 dayRanges.push({
249 start: dayStart,
250 end: internal$1.addDays(dayStart, 1),
251 });
252 dayStart = internal$1.addDays(dayStart, 1);
253 }
254 return { dayDates, dayRanges };
255 }
256 // Returns a sparse array of arrays, segs grouped by their dayIndex
257 function groupSegsByDay(segs) {
258 let segsByDay = []; // sparse array
259 let i;
260 let seg;
261 for (i = 0; i < segs.length; i += 1) {
262 seg = segs[i];
263 (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
264 .push(seg);
265 }
266 return segsByDay;
267 }
268
269 const OPTION_REFINERS = {
270 listDayFormat: createFalsableFormatter,
271 listDaySideFormat: createFalsableFormatter,
272 noEventsClassNames: internal$1.identity,
273 noEventsContent: internal$1.identity,
274 noEventsDidMount: internal$1.identity,
275 noEventsWillUnmount: internal$1.identity,
276 // noEventsText is defined in base options
277 };
278 function createFalsableFormatter(input) {
279 return input === false ? null : internal$1.createFormatter(input);
280 }
281
282 var css_248z = ":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\"\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}";
283 internal$1.injectStyles(css_248z);
284
285 var plugin = core.createPlugin({
286 name: '@fullcalendar/list',
287 optionRefiners: OPTION_REFINERS,
288 views: {
289 list: {
290 component: ListView,
291 buttonTextKey: 'list',
292 listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
293 },
294 listDay: {
295 type: 'list',
296 duration: { days: 1 },
297 listDayFormat: { weekday: 'long' }, // day-of-week is all we need. full date is probably in headerToolbar
298 },
299 listWeek: {
300 type: 'list',
301 duration: { weeks: 1 },
302 listDayFormat: { weekday: 'long' },
303 listDaySideFormat: { month: 'long', day: 'numeric', year: 'numeric' },
304 },
305 listMonth: {
306 type: 'list',
307 duration: { month: 1 },
308 listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
309 },
310 listYear: {
311 type: 'list',
312 duration: { year: 1 },
313 listDaySideFormat: { weekday: 'long' }, // day-of-week is nice-to-have
314 },
315 },
316 });
317
318 var internal = {
319 __proto__: null,
320 ListView: ListView
321 };
322
323 core.globalPlugins.push(plugin);
324
325 exports.Internal = internal;
326 exports["default"] = plugin;
327
328 Object.defineProperty(exports, '__esModule', { value: true });
329
330 return exports;
331
332})({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact);
diff --git a/public/js/fullcalendar/packages/list/index.global.min.js b/public/js/fullcalendar/packages/list/index.global.min.js
new file mode 100644
index 0000000..6efca61
--- /dev/null
+++ b/public/js/fullcalendar/packages/list/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar List View Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/list-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.List=function(e,t,n,a){"use strict";class r extends n.BaseComponent{constructor(){super(...arguments),this.state={textId:n.getUniqueDomId()}}render(){let{theme:e,dateEnv:t,options:r,viewApi:s}=this.context,{cellId:l,dayDate:o,todayRange:d}=this.props,{textId:c}=this.state,f=n.getDateMeta(o,d),u=r.listDayFormat?t.format(o,r.listDayFormat):"",g=r.listDaySideFormat?t.format(o,r.listDaySideFormat):"",m=Object.assign({date:t.toDate(o),view:s,textId:c,text:u,sideText:g,navLinkAttrs:n.buildNavLinkAttrs(this.context,o),sideNavLinkAttrs:n.buildNavLinkAttrs(this.context,o,"day",!1)},f);return a.createElement(n.ContentContainer,{elTag:"tr",elClasses:["fc-list-day",...n.getDayClassNames(f,e)],elAttrs:{"data-date":n.formatDayString(o)},renderProps:m,generatorName:"dayHeaderContent",customGenerator:r.dayHeaderContent,defaultGenerator:i,classNameGenerator:r.dayHeaderClassNames,didMount:r.dayHeaderDidMount,willUnmount:r.dayHeaderWillUnmount},t=>a.createElement("th",{scope:"colgroup",colSpan:3,id:l,"aria-labelledby":c},a.createElement(t,{elTag:"div",elClasses:["fc-list-day-cushion",e.getClass("tableCellShaded")]})))}}function i(e){return a.createElement(a.Fragment,null,e.text&&a.createElement("a",Object.assign({id:e.textId,className:"fc-list-day-text"},e.navLinkAttrs),e.text),e.sideText&&a.createElement("a",Object.assign({"aria-hidden":!0,className:"fc-list-day-side-text"},e.sideNavLinkAttrs),e.sideText))}const s=n.createFormatter({hour:"numeric",minute:"2-digit",meridiem:"short"});class l extends n.BaseComponent{render(){let{props:e,context:t}=this,{options:r}=t,{seg:i,timeHeaderId:l,eventHeaderId:d,dateHeaderId:c}=e,f=r.eventTimeFormat||s;return a.createElement(n.EventContainer,Object.assign({},e,{elTag:"tr",elClasses:["fc-list-event",i.eventRange.def.url&&"fc-event-forced-url"],defaultGenerator:()=>function(e,t){let r=n.getSegAnchorAttrs(e,t);return a.createElement("a",Object.assign({},r),e.eventRange.def.title)}(i,t),seg:i,timeText:"",disableDragging:!0,disableResizing:!0}),(e,r)=>a.createElement(a.Fragment,null,function(e,t,r,i,s){let{options:l}=r;if(!1!==l.displayEventTime){let d,c=e.eventRange.def,f=e.eventRange.instance,u=!1;if(c.allDay?u=!0:n.isMultiDayRange(e.eventRange.range)?e.isStart?d=n.buildSegTimeText(e,t,r,null,null,f.range.start,e.end):e.isEnd?d=n.buildSegTimeText(e,t,r,null,null,e.start,f.range.end):u=!0:d=n.buildSegTimeText(e,t,r),u){let e={text:r.options.allDayText,view:r.viewApi};return a.createElement(n.ContentContainer,{elTag:"td",elClasses:["fc-list-event-time"],elAttrs:{headers:`${i} ${s}`},renderProps:e,generatorName:"allDayContent",customGenerator:l.allDayContent,defaultGenerator:o,classNameGenerator:l.allDayClassNames,didMount:l.allDayDidMount,willUnmount:l.allDayWillUnmount})}return a.createElement("td",{className:"fc-list-event-time"},d)}return null}(i,f,t,l,c),a.createElement("td",{"aria-hidden":!0,className:"fc-list-event-graphic"},a.createElement("span",{className:"fc-list-event-dot",style:{borderColor:r.borderColor||r.backgroundColor}})),a.createElement(e,{elTag:"td",elClasses:["fc-list-event-title"],elAttrs:{headers:`${d} ${c}`}})))}}function o(e){return e.text}class d extends n.DateComponent{constructor(){super(...arguments),this.computeDateVars=n.memoize(f),this.eventStoreToSegs=n.memoize(this._eventStoreToSegs),this.state={timeHeaderId:n.getUniqueDomId(),eventHeaderId:n.getUniqueDomId(),dateHeaderIdRoot:n.getUniqueDomId()},this.setRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e}):this.context.unregisterInteractiveComponent(this)}}render(){let{props:e,context:t}=this,{dayDates:r,dayRanges:i}=this.computeDateVars(e.dateProfile),s=this.eventStoreToSegs(e.eventStore,e.eventUiBases,i);return a.createElement(n.ViewContainer,{elRef:this.setRootEl,elClasses:["fc-list",t.theme.getClass("table"),!1!==t.options.stickyHeaderDates?"fc-list-sticky":""],viewSpec:t.viewSpec},a.createElement(n.Scroller,{liquid:!e.isHeightAuto,overflowX:e.isHeightAuto?"visible":"hidden",overflowY:e.isHeightAuto?"visible":"auto"},s.length>0?this.renderSegList(s,r):this.renderEmptyMessage()))}renderEmptyMessage(){let{options:e,viewApi:t}=this.context,r={text:e.noEventsText,view:t};return a.createElement(n.ContentContainer,{elTag:"div",elClasses:["fc-list-empty"],renderProps:r,generatorName:"noEventsContent",customGenerator:e.noEventsContent,defaultGenerator:c,classNameGenerator:e.noEventsClassNames,didMount:e.noEventsDidMount,willUnmount:e.noEventsWillUnmount},e=>a.createElement(e,{elTag:"div",elClasses:["fc-list-empty-cushion"]}))}renderSegList(e,t){let{theme:i,options:s}=this.context,{timeHeaderId:o,eventHeaderId:d,dateHeaderIdRoot:c}=this.state,f=function(e){let t,n,a=[];for(t=0;t<e.length;t+=1)n=e[t],(a[n.dayIndex]||(a[n.dayIndex]=[])).push(n);return a}(e);return a.createElement(n.NowTimer,{unit:"day"},(e,u)=>{let g=[];for(let i=0;i<f.length;i+=1){let m=f[i];if(m){let f=n.formatDayString(t[i]),h=c+"-"+f;g.push(a.createElement(r,{key:f,cellId:h,dayDate:t[i],todayRange:u})),m=n.sortEventSegs(m,s.eventOrder);for(let t of m)g.push(a.createElement(l,Object.assign({key:f+":"+t.eventRange.instance.instanceId,seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:!1,timeHeaderId:o,eventHeaderId:d,dateHeaderId:h},n.getSegMeta(t,u,e))))}}return a.createElement("table",{className:"fc-list-table "+i.getClass("table")},a.createElement("thead",null,a.createElement("tr",null,a.createElement("th",{scope:"col",id:o},s.timeHint),a.createElement("th",{scope:"col","aria-hidden":!0}),a.createElement("th",{scope:"col",id:d},s.eventHint))),a.createElement("tbody",null,g))})}_eventStoreToSegs(e,t,a){return this.eventRangesToSegs(n.sliceEventStore(e,t,this.props.dateProfile.activeRange,this.context.options.nextDayThreshold).fg,a)}eventRangesToSegs(e,t){let n=[];for(let a of e)n.push(...this.eventRangeToSegs(a,t));return n}eventRangeToSegs(e,t){let a,r,i,{dateEnv:s}=this.context,{nextDayThreshold:l}=this.context.options,o=e.range,d=e.def.allDay,c=[];for(a=0;a<t.length;a+=1)if(r=n.intersectRanges(o,t[a]),r&&(i={component:this,eventRange:e,start:r.start,end:r.end,isStart:e.isStart&&r.start.valueOf()===o.start.valueOf(),isEnd:e.isEnd&&r.end.valueOf()===o.end.valueOf(),dayIndex:a},c.push(i),!i.isEnd&&!d&&a+1<t.length&&o.end<s.add(t[a+1].start,l))){i.end=o.end,i.isEnd=!0;break}return c}}function c(e){return e.text}function f(e){let t=n.startOfDay(e.renderRange.start),a=e.renderRange.end,r=[],i=[];for(;t<a;)r.push(t),i.push({start:t,end:n.addDays(t,1)}),t=n.addDays(t,1);return{dayDates:r,dayRanges:i}}const u={listDayFormat:g,listDaySideFormat:g,noEventsClassNames:n.identity,noEventsContent:n.identity,noEventsDidMount:n.identity,noEventsWillUnmount:n.identity};function g(e){return!1===e?null:n.createFormatter(e)}n.injectStyles(':root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:"";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}');var m=t.createPlugin({name:"@fullcalendar/list",optionRefiners:u,views:{list:{component:d,buttonTextKey:"list",listDayFormat:{month:"long",day:"numeric",year:"numeric"}},listDay:{type:"list",duration:{days:1},listDayFormat:{weekday:"long"}},listWeek:{type:"list",duration:{weeks:1},listDayFormat:{weekday:"long"},listDaySideFormat:{month:"long",day:"numeric",year:"numeric"}},listMonth:{type:"list",duration:{month:1},listDaySideFormat:{weekday:"long"}},listYear:{type:"list",duration:{year:1},listDaySideFormat:{weekday:"long"}}}}),h={__proto__:null,ListView:d};return t.globalPlugins.push(m),e.Internal=h,e.default=m,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal,FullCalendar.Preact); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/luxon1/index.global.js b/public/js/fullcalendar/packages/luxon1/index.global.js
new file mode 100644
index 0000000..1b3ac69
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon1/index.global.js
@@ -0,0 +1,128 @@
1/*!
2FullCalendar Luxon 1 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon1
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon = (function (exports, core, luxon, internal) {
7 'use strict';
8
9 function toLuxonDateTime(date, calendar) {
10 if (!(calendar instanceof internal.CalendarImpl)) {
11 throw new Error('must supply a CalendarApi instance');
12 }
13 let { dateEnv } = calendar.getCurrentData();
14 return luxon.DateTime.fromJSDate(date, {
15 zone: dateEnv.timeZone,
16 locale: dateEnv.locale.codes[0],
17 });
18 }
19 function toLuxonDuration(duration, calendar) {
20 if (!(calendar instanceof internal.CalendarImpl)) {
21 throw new Error('must supply a CalendarApi instance');
22 }
23 let { dateEnv } = calendar.getCurrentData();
24 return luxon.Duration.fromObject(Object.assign(Object.assign({}, duration), { locale: dateEnv.locale.codes[0] }));
25 }
26 // Internal Utils
27 function luxonToArray(datetime) {
28 return [
29 datetime.year,
30 datetime.month - 1,
31 datetime.day,
32 datetime.hour,
33 datetime.minute,
34 datetime.second,
35 datetime.millisecond,
36 ];
37 }
38 function arrayToLuxon(arr, timeZone, locale) {
39 return luxon.DateTime.fromObject({
40 zone: timeZone,
41 locale,
42 year: arr[0],
43 month: arr[1] + 1,
44 day: arr[2],
45 hour: arr[3],
46 minute: arr[4],
47 second: arr[5],
48 millisecond: arr[6],
49 });
50 }
51
52 class LuxonNamedTimeZone extends internal.NamedTimeZoneImpl {
53 offsetForArray(a) {
54 return arrayToLuxon(a, this.timeZoneName).offset;
55 }
56 timestampToArray(ms) {
57 return luxonToArray(luxon.DateTime.fromMillis(ms, {
58 zone: this.timeZoneName,
59 }));
60 }
61 }
62
63 function formatWithCmdStr(cmdStr, arg) {
64 let cmd = parseCmdStr(cmdStr);
65 if (arg.end) {
66 let start = arrayToLuxon(arg.start.array, arg.timeZone, arg.localeCodes[0]);
67 let end = arrayToLuxon(arg.end.array, arg.timeZone, arg.localeCodes[0]);
68 return formatRange(cmd, start.toFormat.bind(start), end.toFormat.bind(end), arg.defaultSeparator);
69 }
70 return arrayToLuxon(arg.date.array, arg.timeZone, arg.localeCodes[0]).toFormat(cmd.whole);
71 }
72 function parseCmdStr(cmdStr) {
73 let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters
74 if (parts) {
75 let middle = parseCmdStr(parts[2]);
76 return {
77 head: parts[1],
78 middle,
79 tail: parts[3],
80 whole: parts[1] + middle.whole + parts[3],
81 };
82 }
83 return {
84 head: null,
85 middle: null,
86 tail: null,
87 whole: cmdStr,
88 };
89 }
90 function formatRange(cmd, formatStart, formatEnd, separator) {
91 if (cmd.middle) {
92 let startHead = formatStart(cmd.head);
93 let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
94 let startTail = formatStart(cmd.tail);
95 let endHead = formatEnd(cmd.head);
96 let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
97 let endTail = formatEnd(cmd.tail);
98 if (startHead === endHead && startTail === endTail) {
99 return startHead +
100 (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) +
101 startTail;
102 }
103 }
104 let startWhole = formatStart(cmd.whole);
105 let endWhole = formatEnd(cmd.whole);
106 if (startWhole === endWhole) {
107 return startWhole;
108 }
109 return startWhole + separator + endWhole;
110 }
111
112 var plugin = core.createPlugin({
113 name: '@fullcalendar/luxon',
114 cmdFormatter: formatWithCmdStr,
115 namedTimeZonedImpl: LuxonNamedTimeZone,
116 });
117
118 core.globalPlugins.push(plugin);
119
120 exports["default"] = plugin;
121 exports.toLuxonDateTime = toLuxonDateTime;
122 exports.toLuxonDuration = toLuxonDuration;
123
124 Object.defineProperty(exports, '__esModule', { value: true });
125
126 return exports;
127
128})({}, FullCalendar, luxon, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/luxon1/index.global.min.js b/public/js/fullcalendar/packages/luxon1/index.global.min.js
new file mode 100644
index 0000000..66a6558
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon1/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Luxon 1 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon1
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon=function(e,t,n,a){"use strict";function l(e,t,a){return n.DateTime.fromObject({zone:t,locale:a,year:e[0],month:e[1]+1,day:e[2],hour:e[3],minute:e[4],second:e[5],millisecond:e[6]})}class r extends a.NamedTimeZoneImpl{offsetForArray(e){return l(e,this.timeZoneName).offset}timestampToArray(e){return[(t=n.DateTime.fromMillis(e,{zone:this.timeZoneName})).year,t.month-1,t.day,t.hour,t.minute,t.second,t.millisecond];var t}}var o=t.createPlugin({name:"@fullcalendar/luxon",cmdFormatter:function(e,t){let n=function e(t){let n=t.match(/^(.*?)\{(.*)\}(.*)$/);if(n){let t=e(n[2]);return{head:n[1],middle:t,tail:n[3],whole:n[1]+t.whole+n[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){let e=l(t.start.array,t.timeZone,t.localeCodes[0]),a=l(t.end.array,t.timeZone,t.localeCodes[0]);return function e(t,n,a,l){if(t.middle){let r=n(t.head),o=e(t.middle,n,a,l),i=n(t.tail),u=a(t.head),d=e(t.middle,n,a,l),m=a(t.tail);if(r===u&&i===m)return r+(o===d?o:o+l+d)+i}let r=n(t.whole),o=a(t.whole);if(r===o)return r;return r+l+o}(n,e.toFormat.bind(e),a.toFormat.bind(a),t.defaultSeparator)}return l(t.date.array,t.timeZone,t.localeCodes[0]).toFormat(n.whole)},namedTimeZonedImpl:r});return t.globalPlugins.push(o),e.default=o,e.toLuxonDateTime=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.DateTime.fromJSDate(e,{zone:l.timeZone,locale:l.locale.codes[0]})},e.toLuxonDuration=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.Duration.fromObject(Object.assign(Object.assign({},e),{locale:l.locale.codes[0]}))},Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,luxon,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/luxon2/index.global.js b/public/js/fullcalendar/packages/luxon2/index.global.js
new file mode 100644
index 0000000..7bdbf71
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon2/index.global.js
@@ -0,0 +1,131 @@
1/*!
2FullCalendar Luxon 2 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon2
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon2 = (function (exports, core, luxon, internal) {
7 'use strict';
8
9 function toLuxonDateTime(date, calendar) {
10 if (!(calendar instanceof internal.CalendarImpl)) {
11 throw new Error('must supply a CalendarApi instance');
12 }
13 let { dateEnv } = calendar.getCurrentData();
14 return luxon.DateTime.fromJSDate(date, {
15 zone: dateEnv.timeZone,
16 locale: dateEnv.locale.codes[0],
17 });
18 }
19 function toLuxonDuration(duration, calendar) {
20 if (!(calendar instanceof internal.CalendarImpl)) {
21 throw new Error('must supply a CalendarApi instance');
22 }
23 let { dateEnv } = calendar.getCurrentData();
24 return luxon.Duration.fromObject(duration, {
25 locale: dateEnv.locale.codes[0],
26 });
27 }
28 // Internal Utils
29 function luxonToArray(datetime) {
30 return [
31 datetime.year,
32 datetime.month - 1,
33 datetime.day,
34 datetime.hour,
35 datetime.minute,
36 datetime.second,
37 datetime.millisecond,
38 ];
39 }
40 function arrayToLuxon(arr, timeZone, locale) {
41 return luxon.DateTime.fromObject({
42 year: arr[0],
43 month: arr[1] + 1,
44 day: arr[2],
45 hour: arr[3],
46 minute: arr[4],
47 second: arr[5],
48 millisecond: arr[6],
49 }, {
50 locale,
51 zone: timeZone,
52 });
53 }
54
55 class LuxonNamedTimeZone extends internal.NamedTimeZoneImpl {
56 offsetForArray(a) {
57 return arrayToLuxon(a, this.timeZoneName).offset;
58 }
59 timestampToArray(ms) {
60 return luxonToArray(luxon.DateTime.fromMillis(ms, {
61 zone: this.timeZoneName,
62 }));
63 }
64 }
65
66 function formatWithCmdStr(cmdStr, arg) {
67 let cmd = parseCmdStr(cmdStr);
68 if (arg.end) {
69 let start = arrayToLuxon(arg.start.array, arg.timeZone, arg.localeCodes[0]);
70 let end = arrayToLuxon(arg.end.array, arg.timeZone, arg.localeCodes[0]);
71 return formatRange(cmd, start.toFormat.bind(start), end.toFormat.bind(end), arg.defaultSeparator);
72 }
73 return arrayToLuxon(arg.date.array, arg.timeZone, arg.localeCodes[0]).toFormat(cmd.whole);
74 }
75 function parseCmdStr(cmdStr) {
76 let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters
77 if (parts) {
78 let middle = parseCmdStr(parts[2]);
79 return {
80 head: parts[1],
81 middle,
82 tail: parts[3],
83 whole: parts[1] + middle.whole + parts[3],
84 };
85 }
86 return {
87 head: null,
88 middle: null,
89 tail: null,
90 whole: cmdStr,
91 };
92 }
93 function formatRange(cmd, formatStart, formatEnd, separator) {
94 if (cmd.middle) {
95 let startHead = formatStart(cmd.head);
96 let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
97 let startTail = formatStart(cmd.tail);
98 let endHead = formatEnd(cmd.head);
99 let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
100 let endTail = formatEnd(cmd.tail);
101 if (startHead === endHead && startTail === endTail) {
102 return startHead +
103 (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) +
104 startTail;
105 }
106 }
107 let startWhole = formatStart(cmd.whole);
108 let endWhole = formatEnd(cmd.whole);
109 if (startWhole === endWhole) {
110 return startWhole;
111 }
112 return startWhole + separator + endWhole;
113 }
114
115 var plugin = core.createPlugin({
116 name: '@fullcalendar/luxon2',
117 cmdFormatter: formatWithCmdStr,
118 namedTimeZonedImpl: LuxonNamedTimeZone,
119 });
120
121 core.globalPlugins.push(plugin);
122
123 exports["default"] = plugin;
124 exports.toLuxonDateTime = toLuxonDateTime;
125 exports.toLuxonDuration = toLuxonDuration;
126
127 Object.defineProperty(exports, '__esModule', { value: true });
128
129 return exports;
130
131})({}, FullCalendar, luxon, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/luxon2/index.global.min.js b/public/js/fullcalendar/packages/luxon2/index.global.min.js
new file mode 100644
index 0000000..9bf3fda
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon2/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Luxon 2 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon2
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon2=function(e,t,n,a){"use strict";function l(e,t,a){return n.DateTime.fromObject({year:e[0],month:e[1]+1,day:e[2],hour:e[3],minute:e[4],second:e[5],millisecond:e[6]},{locale:a,zone:t})}class r extends a.NamedTimeZoneImpl{offsetForArray(e){return l(e,this.timeZoneName).offset}timestampToArray(e){return[(t=n.DateTime.fromMillis(e,{zone:this.timeZoneName})).year,t.month-1,t.day,t.hour,t.minute,t.second,t.millisecond];var t}}var o=t.createPlugin({name:"@fullcalendar/luxon2",cmdFormatter:function(e,t){let n=function e(t){let n=t.match(/^(.*?)\{(.*)\}(.*)$/);if(n){let t=e(n[2]);return{head:n[1],middle:t,tail:n[3],whole:n[1]+t.whole+n[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){let e=l(t.start.array,t.timeZone,t.localeCodes[0]),a=l(t.end.array,t.timeZone,t.localeCodes[0]);return function e(t,n,a,l){if(t.middle){let r=n(t.head),o=e(t.middle,n,a,l),i=n(t.tail),u=a(t.head),d=e(t.middle,n,a,l),m=a(t.tail);if(r===u&&i===m)return r+(o===d?o:o+l+d)+i}let r=n(t.whole),o=a(t.whole);if(r===o)return r;return r+l+o}(n,e.toFormat.bind(e),a.toFormat.bind(a),t.defaultSeparator)}return l(t.date.array,t.timeZone,t.localeCodes[0]).toFormat(n.whole)},namedTimeZonedImpl:r});return t.globalPlugins.push(o),e.default=o,e.toLuxonDateTime=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.DateTime.fromJSDate(e,{zone:l.timeZone,locale:l.locale.codes[0]})},e.toLuxonDuration=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.Duration.fromObject(e,{locale:l.locale.codes[0]})},Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,luxon,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/luxon3/index.global.js b/public/js/fullcalendar/packages/luxon3/index.global.js
new file mode 100644
index 0000000..222e8f6
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon3/index.global.js
@@ -0,0 +1,131 @@
1/*!
2FullCalendar Luxon 3 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon3 = (function (exports, core, luxon, internal) {
7 'use strict';
8
9 function toLuxonDateTime(date, calendar) {
10 if (!(calendar instanceof internal.CalendarImpl)) {
11 throw new Error('must supply a CalendarApi instance');
12 }
13 let { dateEnv } = calendar.getCurrentData();
14 return luxon.DateTime.fromJSDate(date, {
15 zone: dateEnv.timeZone,
16 locale: dateEnv.locale.codes[0],
17 });
18 }
19 function toLuxonDuration(duration, calendar) {
20 if (!(calendar instanceof internal.CalendarImpl)) {
21 throw new Error('must supply a CalendarApi instance');
22 }
23 let { dateEnv } = calendar.getCurrentData();
24 return luxon.Duration.fromObject(duration, {
25 locale: dateEnv.locale.codes[0],
26 });
27 }
28 // Internal Utils
29 function luxonToArray(datetime) {
30 return [
31 datetime.year,
32 datetime.month - 1,
33 datetime.day,
34 datetime.hour,
35 datetime.minute,
36 datetime.second,
37 datetime.millisecond,
38 ];
39 }
40 function arrayToLuxon(arr, timeZone, locale) {
41 return luxon.DateTime.fromObject({
42 year: arr[0],
43 month: arr[1] + 1,
44 day: arr[2],
45 hour: arr[3],
46 minute: arr[4],
47 second: arr[5],
48 millisecond: arr[6],
49 }, {
50 locale,
51 zone: timeZone,
52 });
53 }
54
55 class LuxonNamedTimeZone extends internal.NamedTimeZoneImpl {
56 offsetForArray(a) {
57 return arrayToLuxon(a, this.timeZoneName).offset;
58 }
59 timestampToArray(ms) {
60 return luxonToArray(luxon.DateTime.fromMillis(ms, {
61 zone: this.timeZoneName,
62 }));
63 }
64 }
65
66 function formatWithCmdStr(cmdStr, arg) {
67 let cmd = parseCmdStr(cmdStr);
68 if (arg.end) {
69 let start = arrayToLuxon(arg.start.array, arg.timeZone, arg.localeCodes[0]);
70 let end = arrayToLuxon(arg.end.array, arg.timeZone, arg.localeCodes[0]);
71 return formatRange(cmd, start.toFormat.bind(start), end.toFormat.bind(end), arg.defaultSeparator);
72 }
73 return arrayToLuxon(arg.date.array, arg.timeZone, arg.localeCodes[0]).toFormat(cmd.whole);
74 }
75 function parseCmdStr(cmdStr) {
76 let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters
77 if (parts) {
78 let middle = parseCmdStr(parts[2]);
79 return {
80 head: parts[1],
81 middle,
82 tail: parts[3],
83 whole: parts[1] + middle.whole + parts[3],
84 };
85 }
86 return {
87 head: null,
88 middle: null,
89 tail: null,
90 whole: cmdStr,
91 };
92 }
93 function formatRange(cmd, formatStart, formatEnd, separator) {
94 if (cmd.middle) {
95 let startHead = formatStart(cmd.head);
96 let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
97 let startTail = formatStart(cmd.tail);
98 let endHead = formatEnd(cmd.head);
99 let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
100 let endTail = formatEnd(cmd.tail);
101 if (startHead === endHead && startTail === endTail) {
102 return startHead +
103 (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) +
104 startTail;
105 }
106 }
107 let startWhole = formatStart(cmd.whole);
108 let endWhole = formatEnd(cmd.whole);
109 if (startWhole === endWhole) {
110 return startWhole;
111 }
112 return startWhole + separator + endWhole;
113 }
114
115 var plugin = core.createPlugin({
116 name: '@fullcalendar/luxon3',
117 cmdFormatter: formatWithCmdStr,
118 namedTimeZonedImpl: LuxonNamedTimeZone,
119 });
120
121 core.globalPlugins.push(plugin);
122
123 exports["default"] = plugin;
124 exports.toLuxonDateTime = toLuxonDateTime;
125 exports.toLuxonDuration = toLuxonDuration;
126
127 Object.defineProperty(exports, '__esModule', { value: true });
128
129 return exports;
130
131})({}, FullCalendar, luxon, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/luxon3/index.global.min.js b/public/js/fullcalendar/packages/luxon3/index.global.min.js
new file mode 100644
index 0000000..7c5aa9c
--- /dev/null
+++ b/public/js/fullcalendar/packages/luxon3/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Luxon 3 Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/luxon
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Luxon3=function(e,t,n,a){"use strict";function l(e,t,a){return n.DateTime.fromObject({year:e[0],month:e[1]+1,day:e[2],hour:e[3],minute:e[4],second:e[5],millisecond:e[6]},{locale:a,zone:t})}class r extends a.NamedTimeZoneImpl{offsetForArray(e){return l(e,this.timeZoneName).offset}timestampToArray(e){return[(t=n.DateTime.fromMillis(e,{zone:this.timeZoneName})).year,t.month-1,t.day,t.hour,t.minute,t.second,t.millisecond];var t}}var o=t.createPlugin({name:"@fullcalendar/luxon3",cmdFormatter:function(e,t){let n=function e(t){let n=t.match(/^(.*?)\{(.*)\}(.*)$/);if(n){let t=e(n[2]);return{head:n[1],middle:t,tail:n[3],whole:n[1]+t.whole+n[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){let e=l(t.start.array,t.timeZone,t.localeCodes[0]),a=l(t.end.array,t.timeZone,t.localeCodes[0]);return function e(t,n,a,l){if(t.middle){let r=n(t.head),o=e(t.middle,n,a,l),i=n(t.tail),u=a(t.head),d=e(t.middle,n,a,l),m=a(t.tail);if(r===u&&i===m)return r+(o===d?o:o+l+d)+i}let r=n(t.whole),o=a(t.whole);if(r===o)return r;return r+l+o}(n,e.toFormat.bind(e),a.toFormat.bind(a),t.defaultSeparator)}return l(t.date.array,t.timeZone,t.localeCodes[0]).toFormat(n.whole)},namedTimeZonedImpl:r});return t.globalPlugins.push(o),e.default=o,e.toLuxonDateTime=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.DateTime.fromJSDate(e,{zone:l.timeZone,locale:l.locale.codes[0]})},e.toLuxonDuration=function(e,t){if(!(t instanceof a.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return n.Duration.fromObject(e,{locale:l.locale.codes[0]})},Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,luxon,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/moment-timezone/index.global.js b/public/js/fullcalendar/packages/moment-timezone/index.global.js
new file mode 100644
index 0000000..3f72e00
--- /dev/null
+++ b/public/js/fullcalendar/packages/moment-timezone/index.global.js
@@ -0,0 +1,35 @@
1/*!
2FullCalendar Moment Timezone Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/moment-timezone-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.MomentTimezone = (function (exports, core, moment, internal) {
7 'use strict';
8
9 function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
11 var moment__default = /*#__PURE__*/_interopDefault(moment);
12
13 class MomentNamedTimeZone extends internal.NamedTimeZoneImpl {
14 offsetForArray(a) {
15 return moment__default["default"].tz(a, this.timeZoneName).utcOffset();
16 }
17 timestampToArray(ms) {
18 return moment__default["default"].tz(ms, this.timeZoneName).toArray();
19 }
20 }
21
22 var plugin = core.createPlugin({
23 name: '@fullcalendar/moment-timezone',
24 namedTimeZonedImpl: MomentNamedTimeZone,
25 });
26
27 core.globalPlugins.push(plugin);
28
29 exports["default"] = plugin;
30
31 Object.defineProperty(exports, '__esModule', { value: true });
32
33 return exports;
34
35})({}, FullCalendar, moment, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/moment-timezone/index.global.min.js b/public/js/fullcalendar/packages/moment-timezone/index.global.min.js
new file mode 100644
index 0000000..b5cf8ce
--- /dev/null
+++ b/public/js/fullcalendar/packages/moment-timezone/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Moment Timezone Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/moment-timezone-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.MomentTimezone=function(e,t,n,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}var r=l(n);class u extends a.NamedTimeZoneImpl{offsetForArray(e){return r.default.tz(e,this.timeZoneName).utcOffset()}timestampToArray(e){return r.default.tz(e,this.timeZoneName).toArray()}}var m=t.createPlugin({name:"@fullcalendar/moment-timezone",namedTimeZonedImpl:u});return t.globalPlugins.push(m),e.default=m,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,moment,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/moment/index.global.js b/public/js/fullcalendar/packages/moment/index.global.js
new file mode 100644
index 0000000..0133d4a
--- /dev/null
+++ b/public/js/fullcalendar/packages/moment/index.global.js
@@ -0,0 +1,113 @@
1/*!
2FullCalendar Moment Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/moment-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Moment = (function (exports, core, moment, internal) {
7 'use strict';
8
9 function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
10
11 var moment__default = /*#__PURE__*/_interopDefault(moment);
12
13 function toMoment(date, calendar) {
14 if (!(calendar instanceof internal.CalendarImpl)) {
15 throw new Error('must supply a CalendarApi instance');
16 }
17 let { dateEnv } = calendar.getCurrentData();
18 return convertToMoment(date, dateEnv.timeZone, null, dateEnv.locale.codes[0]);
19 }
20 function toMomentDuration(fcDuration) {
21 return moment__default["default"].duration(fcDuration); // moment accepts all the props that fc.Duration already has!
22 }
23 // Internal Utils
24 function convertToMoment(input, timeZone, timeZoneOffset, locale) {
25 let mom;
26 if (timeZone === 'local') {
27 mom = moment__default["default"](input);
28 }
29 else if (timeZone === 'UTC') {
30 mom = moment__default["default"].utc(input);
31 }
32 else if (moment__default["default"].tz) {
33 mom = moment__default["default"].tz(input, timeZone);
34 }
35 else {
36 mom = moment__default["default"].utc(input);
37 if (timeZoneOffset != null) {
38 mom.utcOffset(timeZoneOffset);
39 }
40 }
41 mom.locale(locale);
42 return mom;
43 }
44
45 function formatWithCmdStr(cmdStr, arg) {
46 let cmd = parseCmdStr(cmdStr);
47 if (arg.end) {
48 let startMom = convertToMoment(arg.start.array, arg.timeZone, arg.start.timeZoneOffset, arg.localeCodes[0]);
49 let endMom = convertToMoment(arg.end.array, arg.timeZone, arg.end.timeZoneOffset, arg.localeCodes[0]);
50 return formatRange(cmd, createMomentFormatFunc(startMom), createMomentFormatFunc(endMom), arg.defaultSeparator);
51 }
52 return convertToMoment(arg.date.array, arg.timeZone, arg.date.timeZoneOffset, arg.localeCodes[0]).format(cmd.whole); // TODO: test for this
53 }
54 function createMomentFormatFunc(mom) {
55 return (cmdStr) => (cmdStr ? mom.format(cmdStr) : '' // because calling with blank string results in ISO8601 :(
56 );
57 }
58 function parseCmdStr(cmdStr) {
59 let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters
60 if (parts) {
61 let middle = parseCmdStr(parts[2]);
62 return {
63 head: parts[1],
64 middle,
65 tail: parts[3],
66 whole: parts[1] + middle.whole + parts[3],
67 };
68 }
69 return {
70 head: null,
71 middle: null,
72 tail: null,
73 whole: cmdStr,
74 };
75 }
76 function formatRange(cmd, formatStart, formatEnd, separator) {
77 if (cmd.middle) {
78 let startHead = formatStart(cmd.head);
79 let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
80 let startTail = formatStart(cmd.tail);
81 let endHead = formatEnd(cmd.head);
82 let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
83 let endTail = formatEnd(cmd.tail);
84 if (startHead === endHead && startTail === endTail) {
85 return startHead +
86 (startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) +
87 startTail;
88 }
89 }
90 let startWhole = formatStart(cmd.whole);
91 let endWhole = formatEnd(cmd.whole);
92 if (startWhole === endWhole) {
93 return startWhole;
94 }
95 return startWhole + separator + endWhole;
96 }
97
98 var plugin = core.createPlugin({
99 name: '@fullcalendar/moment',
100 cmdFormatter: formatWithCmdStr,
101 });
102
103 core.globalPlugins.push(plugin);
104
105 exports["default"] = plugin;
106 exports.toMoment = toMoment;
107 exports.toMomentDuration = toMomentDuration;
108
109 Object.defineProperty(exports, '__esModule', { value: true });
110
111 return exports;
112
113})({}, FullCalendar, moment, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/moment/index.global.min.js b/public/js/fullcalendar/packages/moment/index.global.min.js
new file mode 100644
index 0000000..73be539
--- /dev/null
+++ b/public/js/fullcalendar/packages/moment/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Moment Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/moment-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.Moment=function(e,t,l,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}var r=a(l);function u(e,t,l,n){let a;return"local"===t?a=r.default(e):"UTC"===t?a=r.default.utc(e):r.default.tz?a=r.default.tz(e,t):(a=r.default.utc(e),null!=l&&a.utcOffset(l)),a.locale(n),a}function o(e){return t=>t?e.format(t):""}var d=t.createPlugin({name:"@fullcalendar/moment",cmdFormatter:function(e,t){let l=function e(t){let l=t.match(/^(.*?)\{(.*)\}(.*)$/);if(l){let t=e(l[2]);return{head:l[1],middle:t,tail:l[3],whole:l[1]+t.whole+l[3]}}return{head:null,middle:null,tail:null,whole:t}}(e);if(t.end){let e=u(t.start.array,t.timeZone,t.start.timeZoneOffset,t.localeCodes[0]),n=u(t.end.array,t.timeZone,t.end.timeZoneOffset,t.localeCodes[0]);return function e(t,l,n,a){if(t.middle){let r=l(t.head),u=e(t.middle,l,n,a),o=l(t.tail),d=n(t.head),i=e(t.middle,l,n,a),f=n(t.tail);if(r===d&&o===f)return r+(u===i?u:u+a+i)+o}let r=l(t.whole),u=n(t.whole);if(r===u)return r;return r+a+u}(l,o(e),o(n),t.defaultSeparator)}return u(t.date.array,t.timeZone,t.date.timeZoneOffset,t.localeCodes[0]).format(l.whole)}});return t.globalPlugins.push(d),e.default=d,e.toMoment=function(e,t){if(!(t instanceof n.CalendarImpl))throw new Error("must supply a CalendarApi instance");let{dateEnv:l}=t.getCurrentData();return u(e,l.timeZone,null,l.locale.codes[0])},e.toMomentDuration=function(e){return r.default.duration(e)},Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,moment,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/multimonth/index.global.js b/public/js/fullcalendar/packages/multimonth/index.global.js
new file mode 100644
index 0000000..2748d04
--- /dev/null
+++ b/public/js/fullcalendar/packages/multimonth/index.global.js
@@ -0,0 +1,252 @@
1/*!
2FullCalendar Multi-Month Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/multimonth-grid
4(c) 2024 Adam Shaw
5*/
6FullCalendar.MultiMonth = (function (exports, core, internal$1, internal, preact) {
7 'use strict';
8
9 class SingleMonth extends internal.DateComponent {
10 constructor() {
11 super(...arguments);
12 this.buildDayTableModel = internal.memoize(internal$1.buildDayTableModel);
13 this.slicer = new internal$1.DayTableSlicer();
14 this.state = {
15 labelId: internal.getUniqueDomId(),
16 };
17 }
18 render() {
19 const { props, state, context } = this;
20 const { dateProfile, forPrint } = props;
21 const { options } = context;
22 const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
23 const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
24 // ensure single-month has aspect ratio
25 const tableHeight = props.tableWidth != null ? props.tableWidth / options.aspectRatio : null;
26 const rowCnt = dayTableModel.cells.length;
27 const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
28 return (preact.createElement("div", { ref: props.elRef, "data-date": props.isoDateStr, className: "fc-multimonth-month", style: { width: props.width }, role: "grid", "aria-labelledby": state.labelId },
29 preact.createElement("div", { className: "fc-multimonth-header", style: { marginBottom: rowHeight }, role: "presentation" },
30 preact.createElement("div", { className: "fc-multimonth-title", id: state.labelId }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
31 preact.createElement("table", { className: [
32 'fc-multimonth-header-table',
33 context.theme.getClass('table'),
34 ].join(' '), role: "presentation" },
35 preact.createElement("thead", { role: "rowgroup" },
36 preact.createElement(internal.DayHeader, { dateProfile: props.dateProfile, dates: dayTableModel.headerDates, datesRepDistinctDays: false })))),
37 preact.createElement("div", { className: [
38 'fc-multimonth-daygrid',
39 'fc-daygrid',
40 'fc-daygrid-body',
41 !forPrint && 'fc-daygrid-body-balanced',
42 forPrint && 'fc-daygrid-body-unbalanced',
43 forPrint && 'fc-daygrid-body-natural',
44 ].join(' '), style: { marginTop: -rowHeight } },
45 preact.createElement("table", { className: [
46 'fc-multimonth-daygrid-table',
47 context.theme.getClass('table'),
48 ].join(' '), style: { height: forPrint ? '' : tableHeight }, role: "presentation" },
49 preact.createElement("tbody", { role: "rowgroup" },
50 preact.createElement(internal$1.TableRows, Object.assign({}, slicedProps, { dateProfile: dateProfile, cells: dayTableModel.cells, eventSelection: props.eventSelection, dayMaxEvents: !forPrint, dayMaxEventRows: !forPrint, showWeekNumbers: options.weekNumbers, clientWidth: props.clientWidth, clientHeight: props.clientHeight, forPrint: forPrint })))))));
51 }
52 }
53
54 class MultiMonthView extends internal.DateComponent {
55 constructor() {
56 super(...arguments);
57 this.splitDateProfileByMonth = internal.memoize(splitDateProfileByMonth);
58 this.buildMonthFormat = internal.memoize(buildMonthFormat);
59 this.scrollElRef = preact.createRef();
60 this.firstMonthElRef = preact.createRef();
61 this.needsScrollReset = false;
62 this.handleSizing = (isForced) => {
63 if (isForced) {
64 this.updateSize();
65 }
66 };
67 }
68 render() {
69 const { context, props, state } = this;
70 const { options } = context;
71 const { clientWidth, clientHeight } = state;
72 const monthHPadding = state.monthHPadding || 0;
73 const colCount = Math.min(clientWidth != null ?
74 Math.floor(clientWidth / (options.multiMonthMinWidth + monthHPadding)) :
75 1, options.multiMonthMaxColumns) || 1;
76 const monthWidthPct = (100 / colCount) + '%';
77 const monthTableWidth = clientWidth == null ? null :
78 (clientWidth / colCount) - monthHPadding;
79 const isLegitSingleCol = clientWidth != null && colCount === 1;
80 const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, isLegitSingleCol ? false : options.fixedWeekCount, options.showNonCurrentDates);
81 const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
82 const rootClassNames = [
83 'fc-multimonth',
84 isLegitSingleCol ?
85 'fc-multimonth-singlecol' :
86 'fc-multimonth-multicol',
87 (monthTableWidth != null && monthTableWidth < 400) ?
88 'fc-multimonth-compact' :
89 '',
90 props.isHeightAuto ?
91 '' :
92 'fc-scroller', // for AutoScroller
93 ];
94 return (preact.createElement(internal.ViewContainer, { elRef: this.scrollElRef, elClasses: rootClassNames, viewSpec: context.viewSpec }, monthDateProfiles.map((monthDateProfile, i) => {
95 const monthStr = internal.formatIsoMonthStr(monthDateProfile.currentRange.start);
96 return (preact.createElement(SingleMonth, Object.assign({}, props, { key: monthStr, isoDateStr: monthStr, elRef: i === 0 ? this.firstMonthElRef : undefined, titleFormat: monthTitleFormat, dateProfile: monthDateProfile, width: monthWidthPct, tableWidth: monthTableWidth, clientWidth: clientWidth, clientHeight: clientHeight })));
97 })));
98 }
99 componentDidMount() {
100 this.updateSize();
101 this.context.addResizeHandler(this.handleSizing);
102 this.requestScrollReset();
103 }
104 componentDidUpdate(prevProps) {
105 if (!internal.isPropsEqual(prevProps, this.props)) { // an external change?
106 this.handleSizing(false);
107 }
108 if (prevProps.dateProfile !== this.props.dateProfile) {
109 this.requestScrollReset();
110 }
111 else {
112 this.flushScrollReset();
113 }
114 }
115 componentWillUnmount() {
116 this.context.removeResizeHandler(this.handleSizing);
117 }
118 updateSize() {
119 const scrollEl = this.scrollElRef.current;
120 const firstMonthEl = this.firstMonthElRef.current;
121 if (scrollEl) {
122 this.setState({
123 clientWidth: scrollEl.clientWidth,
124 clientHeight: scrollEl.clientHeight,
125 });
126 }
127 if (firstMonthEl && scrollEl) {
128 if (this.state.monthHPadding == null) { // always remember initial non-zero value
129 this.setState({
130 monthHPadding: scrollEl.clientWidth - // go within padding
131 firstMonthEl.firstChild.offsetWidth,
132 });
133 }
134 }
135 }
136 requestScrollReset() {
137 this.needsScrollReset = true;
138 this.flushScrollReset();
139 }
140 flushScrollReset() {
141 if (this.needsScrollReset &&
142 this.state.monthHPadding != null // indicates sizing already happened
143 ) {
144 const { currentDate } = this.props.dateProfile;
145 const scrollEl = this.scrollElRef.current;
146 const monthEl = scrollEl.querySelector(`[data-date="${internal.formatIsoMonthStr(currentDate)}"]`);
147 scrollEl.scrollTop = monthEl.getBoundingClientRect().top -
148 this.firstMonthElRef.current.getBoundingClientRect().top;
149 this.needsScrollReset = false;
150 }
151 }
152 // workaround for when queued setState render (w/ clientWidth) gets cancelled because
153 // subsequent update and shouldComponentUpdate says not to render :(
154 shouldComponentUpdate() {
155 return true;
156 }
157 }
158 // date profile
159 // -------------------------------------------------------------------------------------------------
160 const oneMonthDuration = internal.createDuration(1, 'month');
161 function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
162 const { start, end } = dateProfile.currentRange;
163 let monthStart = start;
164 const monthDateProfiles = [];
165 while (monthStart.valueOf() < end.valueOf()) {
166 const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
167 const currentRange = {
168 // yuck
169 start: dateProfileGenerator.skipHiddenDays(monthStart),
170 end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
171 };
172 let renderRange = internal$1.buildDayTableRenderRange({
173 currentRange,
174 snapToWeek: true,
175 fixedWeekCount,
176 dateEnv,
177 });
178 renderRange = {
179 // yuck
180 start: dateProfileGenerator.skipHiddenDays(renderRange.start),
181 end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
182 };
183 const activeRange = dateProfile.activeRange ?
184 internal.intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
185 null;
186 monthDateProfiles.push({
187 currentDate: dateProfile.currentDate,
188 isValid: dateProfile.isValid,
189 validRange: dateProfile.validRange,
190 renderRange,
191 activeRange,
192 currentRange,
193 currentRangeUnit: 'month',
194 isRangeAllDay: true,
195 dateIncrement: dateProfile.dateIncrement,
196 slotMinTime: dateProfile.slotMaxTime,
197 slotMaxTime: dateProfile.slotMinTime,
198 });
199 monthStart = monthEnd;
200 }
201 return monthDateProfiles;
202 }
203 // date formatting
204 // -------------------------------------------------------------------------------------------------
205 const YEAR_MONTH_FORMATTER = internal.createFormatter({ year: 'numeric', month: 'long' });
206 const YEAR_FORMATTER = internal.createFormatter({ month: 'long' });
207 function buildMonthFormat(formatOverride, monthDateProfiles) {
208 return formatOverride ||
209 ((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
210 monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear())
211 ? YEAR_MONTH_FORMATTER
212 : YEAR_FORMATTER);
213 }
214
215 const OPTION_REFINERS = {
216 multiMonthTitleFormat: internal.createFormatter,
217 multiMonthMaxColumns: Number,
218 multiMonthMinWidth: Number,
219 };
220
221 var css_248z = ".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}";
222 internal.injectStyles(css_248z);
223
224 var plugin = core.createPlugin({
225 name: '@fullcalendar/multimonth',
226 initialView: 'multiMonthYear',
227 optionRefiners: OPTION_REFINERS,
228 views: {
229 multiMonth: {
230 component: MultiMonthView,
231 dateProfileGeneratorClass: internal$1.TableDateProfileGenerator,
232 multiMonthMinWidth: 350,
233 multiMonthMaxColumns: 3,
234 },
235 multiMonthYear: {
236 type: 'multiMonth',
237 duration: { years: 1 },
238 fixedWeekCount: true,
239 showNonCurrentDates: false,
240 },
241 },
242 });
243
244 core.globalPlugins.push(plugin);
245
246 exports["default"] = plugin;
247
248 Object.defineProperty(exports, '__esModule', { value: true });
249
250 return exports;
251
252})({}, FullCalendar, FullCalendar.DayGrid.Internal, FullCalendar.Internal, FullCalendar.Preact);
diff --git a/public/js/fullcalendar/packages/multimonth/index.global.min.js b/public/js/fullcalendar/packages/multimonth/index.global.min.js
new file mode 100644
index 0000000..6646926
--- /dev/null
+++ b/public/js/fullcalendar/packages/multimonth/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Multi-Month Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/multimonth-grid
4(c) 2024 Adam Shaw
5*/
6FullCalendar.MultiMonth=function(t,e,l,i,n){"use strict";class o extends i.DateComponent{constructor(){super(...arguments),this.buildDayTableModel=i.memoize(l.buildDayTableModel),this.slicer=new l.DayTableSlicer,this.state={labelId:i.getUniqueDomId()}}render(){const{props:t,state:e,context:o}=this,{dateProfile:a,forPrint:r}=t,{options:s}=o,c=this.buildDayTableModel(a,o.dateProfileGenerator),d=this.slicer.sliceProps(t,a,s.nextDayThreshold,o,c),m=null!=t.tableWidth?t.tableWidth/s.aspectRatio:null,h=c.cells.length,u=null!=m?m/h:null;return n.createElement("div",{ref:t.elRef,"data-date":t.isoDateStr,className:"fc-multimonth-month",style:{width:t.width},role:"grid","aria-labelledby":e.labelId},n.createElement("div",{className:"fc-multimonth-header",style:{marginBottom:u},role:"presentation"},n.createElement("div",{className:"fc-multimonth-title",id:e.labelId},o.dateEnv.format(t.dateProfile.currentRange.start,t.titleFormat)),n.createElement("table",{className:["fc-multimonth-header-table",o.theme.getClass("table")].join(" "),role:"presentation"},n.createElement("thead",{role:"rowgroup"},n.createElement(i.DayHeader,{dateProfile:t.dateProfile,dates:c.headerDates,datesRepDistinctDays:!1})))),n.createElement("div",{className:["fc-multimonth-daygrid","fc-daygrid","fc-daygrid-body",!r&&"fc-daygrid-body-balanced",r&&"fc-daygrid-body-unbalanced",r&&"fc-daygrid-body-natural"].join(" "),style:{marginTop:-u}},n.createElement("table",{className:["fc-multimonth-daygrid-table",o.theme.getClass("table")].join(" "),style:{height:r?"":m},role:"presentation"},n.createElement("tbody",{role:"rowgroup"},n.createElement(l.TableRows,Object.assign({},d,{dateProfile:a,cells:c.cells,eventSelection:t.eventSelection,dayMaxEvents:!r,dayMaxEventRows:!r,showWeekNumbers:s.weekNumbers,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:r}))))))}}class a extends i.DateComponent{constructor(){super(...arguments),this.splitDateProfileByMonth=i.memoize(s),this.buildMonthFormat=i.memoize(m),this.scrollElRef=n.createRef(),this.firstMonthElRef=n.createRef(),this.needsScrollReset=!1,this.handleSizing=t=>{t&&this.updateSize()}}render(){const{context:t,props:e,state:l}=this,{options:a}=t,{clientWidth:r,clientHeight:s}=l,c=l.monthHPadding||0,d=Math.min(null!=r?Math.floor(r/(a.multiMonthMinWidth+c)):1,a.multiMonthMaxColumns)||1,m=100/d+"%",h=null==r?null:r/d-c,u=null!=r&&1===d,f=this.splitDateProfileByMonth(t.dateProfileGenerator,e.dateProfile,t.dateEnv,!u&&a.fixedWeekCount,a.showNonCurrentDates),g=this.buildMonthFormat(a.multiMonthTitleFormat,f),p=["fc-multimonth",u?"fc-multimonth-singlecol":"fc-multimonth-multicol",null!=h&&h<400?"fc-multimonth-compact":"",e.isHeightAuto?"":"fc-scroller"];return n.createElement(i.ViewContainer,{elRef:this.scrollElRef,elClasses:p,viewSpec:t.viewSpec},f.map((t,l)=>{const a=i.formatIsoMonthStr(t.currentRange.start);return n.createElement(o,Object.assign({},e,{key:a,isoDateStr:a,elRef:0===l?this.firstMonthElRef:void 0,titleFormat:g,dateProfile:t,width:m,tableWidth:h,clientWidth:r,clientHeight:s}))}))}componentDidMount(){this.updateSize(),this.context.addResizeHandler(this.handleSizing),this.requestScrollReset()}componentDidUpdate(t){i.isPropsEqual(t,this.props)||this.handleSizing(!1),t.dateProfile!==this.props.dateProfile?this.requestScrollReset():this.flushScrollReset()}componentWillUnmount(){this.context.removeResizeHandler(this.handleSizing)}updateSize(){const t=this.scrollElRef.current,e=this.firstMonthElRef.current;t&&this.setState({clientWidth:t.clientWidth,clientHeight:t.clientHeight}),e&&t&&null==this.state.monthHPadding&&this.setState({monthHPadding:t.clientWidth-e.firstChild.offsetWidth})}requestScrollReset(){this.needsScrollReset=!0,this.flushScrollReset()}flushScrollReset(){if(this.needsScrollReset&&null!=this.state.monthHPadding){const{currentDate:t}=this.props.dateProfile,e=this.scrollElRef.current,l=e.querySelector(`[data-date="${i.formatIsoMonthStr(t)}"]`);e.scrollTop=l.getBoundingClientRect().top-this.firstMonthElRef.current.getBoundingClientRect().top,this.needsScrollReset=!1}}shouldComponentUpdate(){return!0}}const r=i.createDuration(1,"month");function s(t,e,n,o,a){const{start:s,end:c}=e.currentRange;let d=s;const m=[];for(;d.valueOf()<c.valueOf();){const s=n.add(d,r),c={start:t.skipHiddenDays(d),end:t.skipHiddenDays(s,-1,!0)};let h=l.buildDayTableRenderRange({currentRange:c,snapToWeek:!0,fixedWeekCount:o,dateEnv:n});h={start:t.skipHiddenDays(h.start),end:t.skipHiddenDays(h.end,-1,!0)};const u=e.activeRange?i.intersectRanges(e.activeRange,a?h:c):null;m.push({currentDate:e.currentDate,isValid:e.isValid,validRange:e.validRange,renderRange:h,activeRange:u,currentRange:c,currentRangeUnit:"month",isRangeAllDay:!0,dateIncrement:e.dateIncrement,slotMinTime:e.slotMaxTime,slotMaxTime:e.slotMinTime}),d=s}return m}const c=i.createFormatter({year:"numeric",month:"long"}),d=i.createFormatter({month:"long"});function m(t,e){return t||(e[0].currentRange.start.getUTCFullYear()!==e[e.length-1].currentRange.start.getUTCFullYear()?c:d)}const h={multiMonthTitleFormat:i.createFormatter,multiMonthMaxColumns:Number,multiMonthMinWidth:Number};i.injectStyles(".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}");var u=e.createPlugin({name:"@fullcalendar/multimonth",initialView:"multiMonthYear",optionRefiners:h,views:{multiMonth:{component:a,dateProfileGeneratorClass:l.TableDateProfileGenerator,multiMonthMinWidth:350,multiMonthMaxColumns:3},multiMonthYear:{type:"multiMonth",duration:{years:1},fixedWeekCount:!0,showNonCurrentDates:!1}}});return e.globalPlugins.push(u),t.default=u,Object.defineProperty(t,"__esModule",{value:!0}),t}({},FullCalendar,FullCalendar.DayGrid.Internal,FullCalendar.Internal,FullCalendar.Preact); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/rrule/index.global.js b/public/js/fullcalendar/packages/rrule/index.global.js
new file mode 100644
index 0000000..750be32
--- /dev/null
+++ b/public/js/fullcalendar/packages/rrule/index.global.js
@@ -0,0 +1,169 @@
1/*!
2FullCalendar RRule Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/rrule-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.RRule = (function (exports, core, rruleLib, internal) {
7 'use strict';
8
9 function _interopNamespace(e) {
10 if (e && e.__esModule) return e;
11 var n = Object.create(null);
12 if (e) {
13 Object.keys(e).forEach(function (k) {
14 if (k !== 'default') {
15 var d = Object.getOwnPropertyDescriptor(e, k);
16 Object.defineProperty(n, k, d.get ? d : {
17 enumerable: true,
18 get: function () { return e[k]; }
19 });
20 }
21 });
22 }
23 n["default"] = e;
24 return n;
25 }
26
27 var rruleLib__namespace = /*#__PURE__*/_interopNamespace(rruleLib);
28
29 const recurringType = {
30 parse(eventProps, dateEnv) {
31 if (eventProps.rrule != null) {
32 let eventRRuleData = parseEventRRule(eventProps, dateEnv);
33 if (eventRRuleData) {
34 return {
35 typeData: {
36 rruleSet: eventRRuleData.rruleSet,
37 dateEnv: eventRRuleData.isTimeZoneSpecified ? undefined : dateEnv,
38 },
39 allDayGuess: !eventRRuleData.isTimeSpecified,
40 duration: eventProps.duration,
41 };
42 }
43 }
44 return null;
45 },
46 expand(eventRRuleData, framingRange, calendarDateEnv) {
47 return eventRRuleData.rruleSet.between(
48 // Add one-day leeway since rrule lib only operates in UTC,
49 // but the zoned variant of framingRange is not.
50 // Also overcomes this rrule bug:
51 // https://github.com/jakubroztocil/rrule/issues/84)
52 internal.addDays(framingRange.start, -1), internal.addDays(framingRange.end, 1)).map((date) => {
53 // convert to plain-datetime
54 return calendarDateEnv.createMarker(
55 // convert to epoch-milliseconds in original timezone
56 eventRRuleData.dateEnv
57 ? eventRRuleData.dateEnv.toDate(date)
58 : date);
59 });
60 },
61 };
62 function parseEventRRule(eventProps, dateEnv) {
63 let rruleSet;
64 let isTimeSpecified = false;
65 let isTimeZoneSpecified = false;
66 if (typeof eventProps.rrule === 'string') {
67 let res = parseRRuleString(eventProps.rrule);
68 rruleSet = res.rruleSet;
69 isTimeSpecified = res.isTimeSpecified;
70 isTimeZoneSpecified = res.isTimeZoneSpecified;
71 }
72 if (typeof eventProps.rrule === 'object' && eventProps.rrule) { // non-null object
73 let res = parseRRuleObject(eventProps.rrule, dateEnv);
74 rruleSet = new rruleLib__namespace.RRuleSet();
75 rruleSet.rrule(res.rrule);
76 isTimeSpecified = res.isTimeSpecified;
77 isTimeZoneSpecified = res.isTimeZoneSpecified;
78 }
79 // convery to arrays. TODO: general util?
80 let exdateInputs = [].concat(eventProps.exdate || []);
81 let exruleInputs = [].concat(eventProps.exrule || []);
82 for (let exdateInput of exdateInputs) {
83 let res = internal.parseMarker(exdateInput);
84 isTimeSpecified = isTimeSpecified || !res.isTimeUnspecified;
85 isTimeZoneSpecified = isTimeZoneSpecified || res.timeZoneOffset !== null;
86 rruleSet.exdate(new Date(res.marker.valueOf() - (res.timeZoneOffset || 0) * 60 * 1000));
87 }
88 // TODO: exrule is deprecated. what to do? (https://icalendar.org/iCalendar-RFC-5545/a-3-deprecated-features.html)
89 for (let exruleInput of exruleInputs) {
90 let res = parseRRuleObject(exruleInput, dateEnv);
91 isTimeSpecified = isTimeSpecified || res.isTimeSpecified;
92 isTimeZoneSpecified = isTimeZoneSpecified || res.isTimeZoneSpecified;
93 rruleSet.exrule(res.rrule);
94 }
95 return { rruleSet, isTimeSpecified, isTimeZoneSpecified };
96 }
97 function parseRRuleObject(rruleInput, dateEnv) {
98 let isTimeSpecified = false;
99 let isTimeZoneSpecified = false;
100 function processDateInput(dateInput) {
101 if (typeof dateInput === 'string') {
102 let markerData = internal.parseMarker(dateInput);
103 if (markerData) {
104 isTimeSpecified = isTimeSpecified || !markerData.isTimeUnspecified;
105 isTimeZoneSpecified = isTimeZoneSpecified || markerData.timeZoneOffset !== null;
106 return new Date(markerData.marker.valueOf() - (markerData.timeZoneOffset || 0) * 60 * 1000); // NOT DRY
107 }
108 return null;
109 }
110 return dateInput; // TODO: what about number timestamps?
111 }
112 let rruleOptions = Object.assign(Object.assign({}, rruleInput), { dtstart: processDateInput(rruleInput.dtstart), until: processDateInput(rruleInput.until), freq: convertConstant(rruleInput.freq), wkst: rruleInput.wkst == null
113 ? (dateEnv.weekDow - 1 + 7) % 7 // convert Sunday-first to Monday-first
114 : convertConstant(rruleInput.wkst), byweekday: convertConstants(rruleInput.byweekday) });
115 return { rrule: new rruleLib__namespace.RRule(rruleOptions), isTimeSpecified, isTimeZoneSpecified };
116 }
117 function parseRRuleString(str) {
118 let rruleSet = rruleLib__namespace.rrulestr(str, { forceset: true });
119 let analysis = analyzeRRuleString(str);
120 return Object.assign({ rruleSet }, analysis);
121 }
122 function analyzeRRuleString(str) {
123 let isTimeSpecified = false;
124 let isTimeZoneSpecified = false;
125 function processMatch(whole, introPart, datePart) {
126 let result = internal.parseMarker(datePart);
127 isTimeSpecified = isTimeSpecified || !result.isTimeUnspecified;
128 isTimeZoneSpecified = isTimeZoneSpecified || result.timeZoneOffset !== null;
129 }
130 str.replace(/\b(DTSTART:)([^\n]*)/, processMatch);
131 str.replace(/\b(EXDATE:)([^\n]*)/, processMatch);
132 str.replace(/\b(UNTIL=)([^;\n]*)/, processMatch);
133 return { isTimeSpecified, isTimeZoneSpecified };
134 }
135 function convertConstants(input) {
136 if (Array.isArray(input)) {
137 return input.map(convertConstant);
138 }
139 return convertConstant(input);
140 }
141 function convertConstant(input) {
142 if (typeof input === 'string') {
143 return rruleLib__namespace.RRule[input.toUpperCase()];
144 }
145 return input;
146 }
147
148 const RRULE_EVENT_REFINERS = {
149 rrule: internal.identity,
150 exrule: internal.identity,
151 exdate: internal.identity,
152 duration: internal.createDuration,
153 };
154
155 var plugin = core.createPlugin({
156 name: '@fullcalendar/rrule',
157 recurringTypes: [recurringType],
158 eventRefiners: RRULE_EVENT_REFINERS,
159 });
160
161 core.globalPlugins.push(plugin);
162
163 exports["default"] = plugin;
164
165 Object.defineProperty(exports, '__esModule', { value: true });
166
167 return exports;
168
169})({}, FullCalendar, rrule, FullCalendar.Internal);
diff --git a/public/js/fullcalendar/packages/rrule/index.global.min.js b/public/js/fullcalendar/packages/rrule/index.global.min.js
new file mode 100644
index 0000000..c80ec01
--- /dev/null
+++ b/public/js/fullcalendar/packages/rrule/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar RRule Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/rrule-plugin
4(c) 2024 Adam Shaw
5*/
6FullCalendar.RRule=function(e,r,t,i){"use strict";function n(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var i=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,i.get?i:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,r}var l=n(t);const u={parse(e,r){if(null!=e.rrule){let t=function(e,r){let t,n=!1,u=!1;if("string"==typeof e.rrule){let r=function(e){let r=l.rrulestr(e,{forceset:!0}),t=function(e){let r=!1,t=!1;function n(e,n,l){let u=i.parseMarker(l);r=r||!u.isTimeUnspecified,t=t||null!==u.timeZoneOffset}return e.replace(/\b(DTSTART:)([^\n]*)/,n),e.replace(/\b(EXDATE:)([^\n]*)/,n),e.replace(/\b(UNTIL=)([^;\n]*)/,n),{isTimeSpecified:r,isTimeZoneSpecified:t}}(e);return Object.assign({rruleSet:r},t)}(e.rrule);t=r.rruleSet,n=r.isTimeSpecified,u=r.isTimeZoneSpecified}if("object"==typeof e.rrule&&e.rrule){let i=a(e.rrule,r);t=new l.RRuleSet,t.rrule(i.rrule),n=i.isTimeSpecified,u=i.isTimeZoneSpecified}let f=[].concat(e.exdate||[]),s=[].concat(e.exrule||[]);for(let e of f){let r=i.parseMarker(e);n=n||!r.isTimeUnspecified,u=u||null!==r.timeZoneOffset,t.exdate(new Date(r.marker.valueOf()-60*(r.timeZoneOffset||0)*1e3))}for(let e of s){let i=a(e,r);n=n||i.isTimeSpecified,u=u||i.isTimeZoneSpecified,t.exrule(i.rrule)}return{rruleSet:t,isTimeSpecified:n,isTimeZoneSpecified:u}}(e,r);if(t)return{typeData:{rruleSet:t.rruleSet,dateEnv:t.isTimeZoneSpecified?void 0:r},allDayGuess:!t.isTimeSpecified,duration:e.duration}}return null},expand:(e,r,t)=>e.rruleSet.between(i.addDays(r.start,-1),i.addDays(r.end,1)).map(r=>t.createMarker(e.dateEnv?e.dateEnv.toDate(r):r))};function a(e,r){let t=!1,n=!1;function u(e){if("string"==typeof e){let r=i.parseMarker(e);return r?(t=t||!r.isTimeUnspecified,n=n||null!==r.timeZoneOffset,new Date(r.marker.valueOf()-60*(r.timeZoneOffset||0)*1e3)):null}return e}let a=Object.assign(Object.assign({},e),{dtstart:u(e.dtstart),until:u(e.until),freq:s(e.freq),wkst:null==e.wkst?(r.weekDow-1+7)%7:s(e.wkst),byweekday:f(e.byweekday)});return{rrule:new l.RRule(a),isTimeSpecified:t,isTimeZoneSpecified:n}}function f(e){return Array.isArray(e)?e.map(s):s(e)}function s(e){return"string"==typeof e?l.RRule[e.toUpperCase()]:e}const c={rrule:i.identity,exrule:i.identity,exdate:i.identity,duration:i.createDuration};var o=r.createPlugin({name:"@fullcalendar/rrule",recurringTypes:[u],eventRefiners:c});return r.globalPlugins.push(o),e.default=o,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,rrule,FullCalendar.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/timegrid/index.global.js b/public/js/fullcalendar/packages/timegrid/index.global.js
new file mode 100644
index 0000000..2221662
--- /dev/null
+++ b/public/js/fullcalendar/packages/timegrid/index.global.js
@@ -0,0 +1,1198 @@
1/*!
2FullCalendar Time Grid Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/timegrid-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.TimeGrid = (function (exports, core, internal$1, preact, internal$2) {
7 'use strict';
8
9 class AllDaySplitter extends internal$1.Splitter {
10 getKeyInfo() {
11 return {
12 allDay: {},
13 timed: {},
14 };
15 }
16 getKeysForDateSpan(dateSpan) {
17 if (dateSpan.allDay) {
18 return ['allDay'];
19 }
20 return ['timed'];
21 }
22 getKeysForEventDef(eventDef) {
23 if (!eventDef.allDay) {
24 return ['timed'];
25 }
26 if (internal$1.hasBgRendering(eventDef)) {
27 return ['timed', 'allDay'];
28 }
29 return ['allDay'];
30 }
31 }
32
33 const DEFAULT_SLAT_LABEL_FORMAT = internal$1.createFormatter({
34 hour: 'numeric',
35 minute: '2-digit',
36 omitZeroMinute: true,
37 meridiem: 'short',
38 });
39 function TimeColsAxisCell(props) {
40 let classNames = [
41 'fc-timegrid-slot',
42 'fc-timegrid-slot-label',
43 props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
44 ];
45 return (preact.createElement(internal$1.ViewContextType.Consumer, null, (context) => {
46 if (!props.isLabeled) {
47 return (preact.createElement("td", { className: classNames.join(' '), "data-time": props.isoTimeStr }));
48 }
49 let { dateEnv, options, viewApi } = context;
50 let labelFormat = // TODO: fully pre-parse
51 options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
52 Array.isArray(options.slotLabelFormat) ? internal$1.createFormatter(options.slotLabelFormat[0]) :
53 internal$1.createFormatter(options.slotLabelFormat);
54 let renderProps = {
55 level: 0,
56 time: props.time,
57 date: dateEnv.toDate(props.date),
58 view: viewApi,
59 text: dateEnv.format(props.date, labelFormat),
60 };
61 return (preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: classNames, elAttrs: {
62 'data-time': props.isoTimeStr,
63 }, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame" },
64 preact.createElement(InnerContent, { elTag: "div", elClasses: [
65 'fc-timegrid-slot-label-cushion',
66 'fc-scrollgrid-shrink-cushion',
67 ] })))));
68 }));
69 }
70 function renderInnerContent(props) {
71 return props.text;
72 }
73
74 class TimeBodyAxis extends internal$1.BaseComponent {
75 render() {
76 return this.props.slatMetas.map((slatMeta) => (preact.createElement("tr", { key: slatMeta.key },
77 preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta)))));
78 }
79 }
80
81 const DEFAULT_WEEK_NUM_FORMAT = internal$1.createFormatter({ week: 'short' });
82 const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
83 class TimeColsView extends internal$1.DateComponent {
84 constructor() {
85 super(...arguments);
86 this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
87 this.headerElRef = preact.createRef();
88 this.rootElRef = preact.createRef();
89 this.scrollerElRef = preact.createRef();
90 this.state = {
91 slatCoords: null,
92 };
93 this.handleScrollTopRequest = (scrollTop) => {
94 let scrollerEl = this.scrollerElRef.current;
95 if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
96 scrollerEl.scrollTop = scrollTop;
97 }
98 };
99 /* Header Render Methods
100 ------------------------------------------------------------------------------------------------------------------*/
101 this.renderHeadAxis = (rowKey, frameHeight = '') => {
102 let { options } = this.context;
103 let { dateProfile } = this.props;
104 let range = dateProfile.renderRange;
105 let dayCnt = internal$1.diffDays(range.start, range.end);
106 // only do in day views (to avoid doing in week views that dont need it)
107 let navLinkAttrs = (dayCnt === 1)
108 ? internal$1.buildNavLinkAttrs(this.context, range.start, 'week')
109 : {};
110 if (options.weekNumbers && rowKey === 'day') {
111 return (preact.createElement(internal$1.WeekNumberContainer, { elTag: "th", elClasses: [
112 'fc-timegrid-axis',
113 'fc-scrollgrid-shrink',
114 ], elAttrs: {
115 'aria-hidden': true,
116 }, date: range.start, defaultFormat: DEFAULT_WEEK_NUM_FORMAT }, (InnerContent) => (preact.createElement("div", { className: [
117 'fc-timegrid-axis-frame',
118 'fc-scrollgrid-shrink-frame',
119 'fc-timegrid-axis-frame-liquid',
120 ].join(' '), style: { height: frameHeight } },
121 preact.createElement(InnerContent, { elTag: "a", elClasses: [
122 'fc-timegrid-axis-cushion',
123 'fc-scrollgrid-shrink-cushion',
124 'fc-scrollgrid-sync-inner',
125 ], elAttrs: navLinkAttrs })))));
126 }
127 return (preact.createElement("th", { "aria-hidden": true, className: "fc-timegrid-axis" },
128 preact.createElement("div", { className: "fc-timegrid-axis-frame", style: { height: frameHeight } })));
129 };
130 /* Table Component Render Methods
131 ------------------------------------------------------------------------------------------------------------------*/
132 // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
133 // but DayGrid still needs to have classNames on inner elements in order to measure.
134 this.renderTableRowAxis = (rowHeight) => {
135 let { options, viewApi } = this.context;
136 let renderProps = {
137 text: options.allDayText,
138 view: viewApi,
139 };
140 return (
141 // TODO: make reusable hook. used in list view too
142 preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
143 'fc-timegrid-axis',
144 'fc-scrollgrid-shrink',
145 ], elAttrs: {
146 'aria-hidden': true,
147 }, renderProps: renderProps, generatorName: "allDayContent", customGenerator: options.allDayContent, defaultGenerator: renderAllDayInner, classNameGenerator: options.allDayClassNames, didMount: options.allDayDidMount, willUnmount: options.allDayWillUnmount }, (InnerContent) => (preact.createElement("div", { className: [
148 'fc-timegrid-axis-frame',
149 'fc-scrollgrid-shrink-frame',
150 rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
151 ].join(' '), style: { height: rowHeight } },
152 preact.createElement(InnerContent, { elTag: "span", elClasses: [
153 'fc-timegrid-axis-cushion',
154 'fc-scrollgrid-shrink-cushion',
155 'fc-scrollgrid-sync-inner',
156 ] })))));
157 };
158 this.handleSlatCoords = (slatCoords) => {
159 this.setState({ slatCoords });
160 };
161 }
162 // rendering
163 // ----------------------------------------------------------------------------------------------------
164 renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
165 let { context, props } = this;
166 let sections = [];
167 let stickyHeaderDates = internal$1.getStickyHeaderDates(context.options);
168 if (headerRowContent) {
169 sections.push({
170 type: 'header',
171 key: 'header',
172 isSticky: stickyHeaderDates,
173 chunk: {
174 elRef: this.headerElRef,
175 tableClassName: 'fc-col-header',
176 rowContent: headerRowContent,
177 },
178 });
179 }
180 if (allDayContent) {
181 sections.push({
182 type: 'body',
183 key: 'all-day',
184 chunk: { content: allDayContent },
185 });
186 sections.push({
187 type: 'body',
188 key: 'all-day-divider',
189 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
190 preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
191 preact.createElement("td", { className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
192 });
193 }
194 sections.push({
195 type: 'body',
196 key: 'body',
197 liquid: true,
198 expandRows: Boolean(context.options.expandRows),
199 chunk: {
200 scrollerElRef: this.scrollerElRef,
201 content: timeContent,
202 },
203 });
204 return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
205 preact.createElement(internal$1.SimpleScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, collapsibleWidth: props.forPrint, cols: [{ width: 'shrink' }], sections: sections })));
206 }
207 renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
208 let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
209 if (!ScrollGrid) {
210 throw new Error('No ScrollGrid implementation');
211 }
212 let { context, props } = this;
213 let stickyHeaderDates = !props.forPrint && internal$1.getStickyHeaderDates(context.options);
214 let stickyFooterScrollbar = !props.forPrint && internal$1.getStickyFooterScrollbar(context.options);
215 let sections = [];
216 if (headerRowContent) {
217 sections.push({
218 type: 'header',
219 key: 'header',
220 isSticky: stickyHeaderDates,
221 syncRowHeights: true,
222 chunks: [
223 {
224 key: 'axis',
225 rowContent: (arg) => (preact.createElement("tr", { role: "presentation" }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
226 },
227 {
228 key: 'cols',
229 elRef: this.headerElRef,
230 tableClassName: 'fc-col-header',
231 rowContent: headerRowContent,
232 },
233 ],
234 });
235 }
236 if (allDayContent) {
237 sections.push({
238 type: 'body',
239 key: 'all-day',
240 syncRowHeights: true,
241 chunks: [
242 {
243 key: 'axis',
244 rowContent: (contentArg) => (preact.createElement("tr", { role: "presentation" }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
245 },
246 {
247 key: 'cols',
248 content: allDayContent,
249 },
250 ],
251 });
252 sections.push({
253 key: 'all-day-divider',
254 type: 'body',
255 outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
256 preact.createElement("tr", { role: "presentation", className: "fc-scrollgrid-section" },
257 preact.createElement("td", { colSpan: 2, className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded') }))),
258 });
259 }
260 let isNowIndicator = context.options.nowIndicator;
261 sections.push({
262 type: 'body',
263 key: 'body',
264 liquid: true,
265 expandRows: Boolean(context.options.expandRows),
266 chunks: [
267 {
268 key: 'axis',
269 content: (arg) => (
270 // TODO: make this now-indicator arrow more DRY with TimeColsContent
271 preact.createElement("div", { className: "fc-timegrid-axis-chunk" },
272 preact.createElement("table", { "aria-hidden": true, style: { height: arg.expandRows ? arg.clientHeight : '' } },
273 arg.tableColGroupNode,
274 preact.createElement("tbody", null,
275 preact.createElement(TimeBodyAxis, { slatMetas: slatMetas }))),
276 preact.createElement("div", { className: "fc-timegrid-now-indicator-container" },
277 preact.createElement(internal$1.NowTimer, { unit: isNowIndicator ? 'minute' : 'day' /* hacky */ }, (nowDate) => {
278 let nowIndicatorTop = isNowIndicator &&
279 slatCoords &&
280 slatCoords.safeComputeTop(nowDate); // might return void
281 if (typeof nowIndicatorTop === 'number') {
282 return (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: nowDate }));
283 }
284 return null;
285 })))),
286 },
287 {
288 key: 'cols',
289 scrollerElRef: this.scrollerElRef,
290 content: timeContent,
291 },
292 ],
293 });
294 if (stickyFooterScrollbar) {
295 sections.push({
296 key: 'footer',
297 type: 'footer',
298 isSticky: true,
299 chunks: [
300 {
301 key: 'axis',
302 content: internal$1.renderScrollShim,
303 },
304 {
305 key: 'cols',
306 content: internal$1.renderScrollShim,
307 },
308 ],
309 });
310 }
311 return (preact.createElement(internal$1.ViewContainer, { elRef: this.rootElRef, elClasses: ['fc-timegrid'], viewSpec: context.viewSpec },
312 preact.createElement(ScrollGrid, { liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [
313 { width: 'shrink', cols: [{ width: 'shrink' }] },
314 { cols: [{ span: colCnt, minWidth: dayMinWidth }] },
315 ], sections: sections })));
316 }
317 /* Dimensions
318 ------------------------------------------------------------------------------------------------------------------*/
319 getAllDayMaxEventProps() {
320 let { dayMaxEvents, dayMaxEventRows } = this.context.options;
321 if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
322 dayMaxEvents = undefined;
323 dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
324 }
325 return { dayMaxEvents, dayMaxEventRows };
326 }
327 }
328 function renderAllDayInner(renderProps) {
329 return renderProps.text;
330 }
331
332 class TimeColsSlatsCoords {
333 constructor(positions, dateProfile, slotDuration) {
334 this.positions = positions;
335 this.dateProfile = dateProfile;
336 this.slotDuration = slotDuration;
337 }
338 safeComputeTop(date) {
339 let { dateProfile } = this;
340 if (internal$1.rangeContainsMarker(dateProfile.currentRange, date)) {
341 let startOfDayDate = internal$1.startOfDay(date);
342 let timeMs = date.valueOf() - startOfDayDate.valueOf();
343 if (timeMs >= internal$1.asRoughMs(dateProfile.slotMinTime) &&
344 timeMs < internal$1.asRoughMs(dateProfile.slotMaxTime)) {
345 return this.computeTimeTop(internal$1.createDuration(timeMs));
346 }
347 }
348 return null;
349 }
350 // Computes the top coordinate, relative to the bounds of the grid, of the given date.
351 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
352 computeDateTop(when, startOfDayDate) {
353 if (!startOfDayDate) {
354 startOfDayDate = internal$1.startOfDay(when);
355 }
356 return this.computeTimeTop(internal$1.createDuration(when.valueOf() - startOfDayDate.valueOf()));
357 }
358 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
359 // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
360 // Eventually allow computation with arbirary slat dates.
361 computeTimeTop(duration) {
362 let { positions, dateProfile } = this;
363 let len = positions.els.length;
364 // floating-point value of # of slots covered
365 let slatCoverage = (duration.milliseconds - internal$1.asRoughMs(dateProfile.slotMinTime)) / internal$1.asRoughMs(this.slotDuration);
366 let slatIndex;
367 let slatRemainder;
368 // compute a floating-point number for how many slats should be progressed through.
369 // from 0 to number of slats (inclusive)
370 // constrained because slotMinTime/slotMaxTime might be customized.
371 slatCoverage = Math.max(0, slatCoverage);
372 slatCoverage = Math.min(len, slatCoverage);
373 // an integer index of the furthest whole slat
374 // from 0 to number slats (*exclusive*, so len-1)
375 slatIndex = Math.floor(slatCoverage);
376 slatIndex = Math.min(slatIndex, len - 1);
377 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
378 // could be 1.0 if slatCoverage is covering *all* the slots
379 slatRemainder = slatCoverage - slatIndex;
380 return positions.tops[slatIndex] +
381 positions.getHeight(slatIndex) * slatRemainder;
382 }
383 }
384
385 class TimeColsSlatsBody extends internal$1.BaseComponent {
386 render() {
387 let { props, context } = this;
388 let { options } = context;
389 let { slatElRefs } = props;
390 return (preact.createElement("tbody", null, props.slatMetas.map((slatMeta, i) => {
391 let renderProps = {
392 time: slatMeta.time,
393 date: context.dateEnv.toDate(slatMeta.date),
394 view: context.viewApi,
395 };
396 return (preact.createElement("tr", { key: slatMeta.key, ref: slatElRefs.createRef(slatMeta.key) },
397 props.axis && (preact.createElement(TimeColsAxisCell, Object.assign({}, slatMeta))),
398 preact.createElement(internal$1.ContentContainer, { elTag: "td", elClasses: [
399 'fc-timegrid-slot',
400 'fc-timegrid-slot-lane',
401 !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
402 ], elAttrs: {
403 'data-time': slatMeta.isoTimeStr,
404 }, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount })));
405 })));
406 }
407 }
408
409 /*
410 for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
411 */
412 class TimeColsSlats extends internal$1.BaseComponent {
413 constructor() {
414 super(...arguments);
415 this.rootElRef = preact.createRef();
416 this.slatElRefs = new internal$1.RefMap();
417 }
418 render() {
419 let { props, context } = this;
420 return (preact.createElement("div", { ref: this.rootElRef, className: "fc-timegrid-slots" },
421 preact.createElement("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: {
422 minWidth: props.tableMinWidth,
423 width: props.clientWidth,
424 height: props.minHeight,
425 } },
426 props.tableColGroupNode /* relies on there only being a single <col> for the axis */,
427 preact.createElement(TimeColsSlatsBody, { slatElRefs: this.slatElRefs, axis: props.axis, slatMetas: props.slatMetas }))));
428 }
429 componentDidMount() {
430 this.updateSizing();
431 }
432 componentDidUpdate() {
433 this.updateSizing();
434 }
435 componentWillUnmount() {
436 if (this.props.onCoords) {
437 this.props.onCoords(null);
438 }
439 }
440 updateSizing() {
441 let { context, props } = this;
442 if (props.onCoords &&
443 props.clientWidth !== null // means sizing has stabilized
444 ) {
445 let rootEl = this.rootElRef.current;
446 if (rootEl.offsetHeight) { // not hidden by css
447 props.onCoords(new TimeColsSlatsCoords(new internal$1.PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
448 }
449 }
450 }
451 }
452 function collectSlatEls(elMap, slatMetas) {
453 return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
454 }
455
456 function splitSegsByCol(segs, colCnt) {
457 let segsByCol = [];
458 let i;
459 for (i = 0; i < colCnt; i += 1) {
460 segsByCol.push([]);
461 }
462 if (segs) {
463 for (i = 0; i < segs.length; i += 1) {
464 segsByCol[segs[i].col].push(segs[i]);
465 }
466 }
467 return segsByCol;
468 }
469 function splitInteractionByCol(ui, colCnt) {
470 let byRow = [];
471 if (!ui) {
472 for (let i = 0; i < colCnt; i += 1) {
473 byRow[i] = null;
474 }
475 }
476 else {
477 for (let i = 0; i < colCnt; i += 1) {
478 byRow[i] = {
479 affectedInstances: ui.affectedInstances,
480 isEvent: ui.isEvent,
481 segs: [],
482 };
483 }
484 for (let seg of ui.segs) {
485 byRow[seg.col].segs.push(seg);
486 }
487 }
488 return byRow;
489 }
490
491 class TimeColMoreLink extends internal$1.BaseComponent {
492 render() {
493 let { props } = this;
494 return (preact.createElement(internal$1.MoreLinkContainer, { elClasses: ['fc-timegrid-more-link'], elStyle: {
495 top: props.top,
496 bottom: props.bottom,
497 }, allDayDate: null, moreCnt: props.hiddenSegs.length, allSegs: props.hiddenSegs, hiddenSegs: props.hiddenSegs, extraDateSpan: props.extraDateSpan, dateProfile: props.dateProfile, todayRange: props.todayRange, popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props), defaultGenerator: renderMoreLinkInner, forceTimed: true }, (InnerContent) => (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky'] }))));
498 }
499 }
500 function renderMoreLinkInner(props) {
501 return props.shortText;
502 }
503
504 // segInputs assumed sorted
505 function buildPositioning(segInputs, strictOrder, maxStackCnt) {
506 let hierarchy = new internal$1.SegHierarchy();
507 if (strictOrder != null) {
508 hierarchy.strictOrder = strictOrder;
509 }
510 if (maxStackCnt != null) {
511 hierarchy.maxStackCnt = maxStackCnt;
512 }
513 let hiddenEntries = hierarchy.addSegs(segInputs);
514 let hiddenGroups = internal$1.groupIntersectingEntries(hiddenEntries);
515 let web = buildWeb(hierarchy);
516 web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
517 let segRects = webToRects(web);
518 return { segRects, hiddenGroups };
519 }
520 function buildWeb(hierarchy) {
521 const { entriesByLevel } = hierarchy;
522 const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
523 let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
524 let nextLevelRes = buildNodes(siblingRange, buildNode);
525 let entry = entriesByLevel[level][lateral];
526 return [
527 Object.assign(Object.assign({}, entry), { nextLevelNodes: nextLevelRes[0] }),
528 entry.thickness + nextLevelRes[1], // the pressure builds
529 ];
530 });
531 return buildNodes(entriesByLevel.length
532 ? { level: 0, lateralStart: 0, lateralEnd: entriesByLevel[0].length }
533 : null, buildNode)[0];
534 }
535 function buildNodes(siblingRange, buildNode) {
536 if (!siblingRange) {
537 return [[], 0];
538 }
539 let { level, lateralStart, lateralEnd } = siblingRange;
540 let lateral = lateralStart;
541 let pairs = [];
542 while (lateral < lateralEnd) {
543 pairs.push(buildNode(level, lateral));
544 lateral += 1;
545 }
546 pairs.sort(cmpDescPressures);
547 return [
548 pairs.map(extractNode),
549 pairs[0][1], // first item's pressure
550 ];
551 }
552 function cmpDescPressures(a, b) {
553 return b[1] - a[1];
554 }
555 function extractNode(a) {
556 return a[0];
557 }
558 function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
559 let { levelCoords, entriesByLevel } = hierarchy;
560 let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
561 let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
562 let levelCnt = levelCoords.length;
563 let level = subjectLevel;
564 // skip past levels that are too high up
565 for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
566 ; // do nothing
567 for (; level < levelCnt; level += 1) {
568 let entries = entriesByLevel[level];
569 let entry;
570 let searchIndex = internal$1.binarySearch(entries, subjectEntry.span.start, internal$1.getEntrySpanEnd);
571 let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
572 let lateralEnd = lateralStart;
573 while ( // loop through entries that horizontally intersect
574 (entry = entries[lateralEnd]) && // but not past the whole seg list
575 entry.span.start < subjectEntry.span.end) {
576 lateralEnd += 1;
577 }
578 if (lateralStart < lateralEnd) {
579 return { level, lateralStart, lateralEnd };
580 }
581 }
582 return null;
583 }
584 function stretchWeb(topLevelNodes, totalThickness) {
585 const stretchNode = cacheable((node, startCoord, prevThickness) => internal$1.buildEntryKey(node), (node, startCoord, prevThickness) => {
586 let { nextLevelNodes, thickness } = node;
587 let allThickness = thickness + prevThickness;
588 let thicknessFraction = thickness / allThickness;
589 let endCoord;
590 let newChildren = [];
591 if (!nextLevelNodes.length) {
592 endCoord = totalThickness;
593 }
594 else {
595 for (let childNode of nextLevelNodes) {
596 if (endCoord === undefined) {
597 let res = stretchNode(childNode, startCoord, allThickness);
598 endCoord = res[0];
599 newChildren.push(res[1]);
600 }
601 else {
602 let res = stretchNode(childNode, endCoord, 0);
603 newChildren.push(res[1]);
604 }
605 }
606 }
607 let newThickness = (endCoord - startCoord) * thicknessFraction;
608 return [endCoord - newThickness, Object.assign(Object.assign({}, node), { thickness: newThickness, nextLevelNodes: newChildren })];
609 });
610 return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
611 }
612 // not sorted in any particular order
613 function webToRects(topLevelNodes) {
614 let rects = [];
615 const processNode = cacheable((node, levelCoord, stackDepth) => internal$1.buildEntryKey(node), (node, levelCoord, stackDepth) => {
616 let rect = Object.assign(Object.assign({}, node), { levelCoord,
617 stackDepth, stackForward: 0 });
618 rects.push(rect);
619 return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
620 });
621 function processNodes(nodes, levelCoord, stackDepth) {
622 let stackForward = 0;
623 for (let node of nodes) {
624 stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
625 }
626 return stackForward;
627 }
628 processNodes(topLevelNodes, 0, 0);
629 return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
630 }
631 // TODO: move to general util
632 function cacheable(keyFunc, workFunc) {
633 const cache = {};
634 return (...args) => {
635 let key = keyFunc(...args);
636 return (key in cache)
637 ? cache[key]
638 : (cache[key] = workFunc(...args));
639 };
640 }
641
642 function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
643 let vcoords = [];
644 if (slatCoords) {
645 for (let i = 0; i < segs.length; i += 1) {
646 let seg = segs[i];
647 let spanStart = slatCoords.computeDateTop(seg.start, colDate);
648 let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
649 slatCoords.computeDateTop(seg.end, colDate));
650 vcoords.push({
651 start: Math.round(spanStart),
652 end: Math.round(spanEnd), //
653 });
654 }
655 }
656 return vcoords;
657 }
658 function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
659 eventOrderStrict, eventMaxStack) {
660 let segInputs = [];
661 let dumbSegs = []; // segs without coords
662 for (let i = 0; i < segs.length; i += 1) {
663 let vcoords = segVCoords[i];
664 if (vcoords) {
665 segInputs.push({
666 index: i,
667 thickness: 1,
668 span: vcoords,
669 });
670 }
671 else {
672 dumbSegs.push(segs[i]);
673 }
674 }
675 let { segRects, hiddenGroups } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
676 let segPlacements = [];
677 for (let segRect of segRects) {
678 segPlacements.push({
679 seg: segs[segRect.index],
680 rect: segRect,
681 });
682 }
683 for (let dumbSeg of dumbSegs) {
684 segPlacements.push({ seg: dumbSeg, rect: null });
685 }
686 return { segPlacements, hiddenGroups };
687 }
688
689 const DEFAULT_TIME_FORMAT = internal$1.createFormatter({
690 hour: 'numeric',
691 minute: '2-digit',
692 meridiem: false,
693 });
694 class TimeColEvent extends internal$1.BaseComponent {
695 render() {
696 return (preact.createElement(internal$1.StandardEvent, Object.assign({}, this.props, { elClasses: [
697 'fc-timegrid-event',
698 'fc-v-event',
699 this.props.isShort && 'fc-timegrid-event-short',
700 ], defaultTimeFormat: DEFAULT_TIME_FORMAT })));
701 }
702 }
703
704 class TimeCol extends internal$1.BaseComponent {
705 constructor() {
706 super(...arguments);
707 this.sortEventSegs = internal$1.memoize(internal$1.sortEventSegs);
708 }
709 // TODO: memoize event-placement?
710 render() {
711 let { props, context } = this;
712 let { options } = context;
713 let isSelectMirror = options.selectMirror;
714 let mirrorSegs = // yuck
715 (props.eventDrag && props.eventDrag.segs) ||
716 (props.eventResize && props.eventResize.segs) ||
717 (isSelectMirror && props.dateSelectionSegs) ||
718 [];
719 let interactionAffectedInstances = // TODO: messy way to compute this
720 (props.eventDrag && props.eventDrag.affectedInstances) ||
721 (props.eventResize && props.eventResize.affectedInstances) ||
722 {};
723 let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
724 return (preact.createElement(internal$1.DayCellContainer, { elTag: "td", elRef: props.elRef, elClasses: [
725 'fc-timegrid-col',
726 ...(props.extraClassNames || []),
727 ], elAttrs: Object.assign({ role: 'gridcell' }, props.extraDataAttrs), date: props.date, dateProfile: props.dateProfile, todayRange: props.todayRange, extraRenderProps: props.extraRenderProps }, (InnerContent) => (preact.createElement("div", { className: "fc-timegrid-col-frame" },
728 preact.createElement("div", { className: "fc-timegrid-col-bg" },
729 this.renderFillSegs(props.businessHourSegs, 'non-business'),
730 this.renderFillSegs(props.bgEventSegs, 'bg-event'),
731 this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
732 preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
733 preact.createElement("div", { className: "fc-timegrid-col-events" }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),
734 preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, this.renderNowIndicator(props.nowIndicatorSegs)),
735 internal$1.hasCustomDayCellContent(options) && (preact.createElement(InnerContent, { elTag: "div", elClasses: ['fc-timegrid-col-misc'] }))))));
736 }
737 renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
738 let { props } = this;
739 if (props.forPrint) {
740 return renderPlainFgSegs(sortedFgSegs, props);
741 }
742 return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);
743 }
744 renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
745 segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
746 let { eventMaxStack, eventShortHeight, eventOrderStrict, eventMinHeight } = this.context.options;
747 let { date, slatCoords, eventSelection, todayRange, nowDate } = this.props;
748 let isMirror = isDragging || isResizing || isDateSelecting;
749 let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
750 let { segPlacements, hiddenGroups } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
751 return (preact.createElement(preact.Fragment, null,
752 this.renderHiddenGroups(hiddenGroups, segs),
753 segPlacements.map((segPlacement) => {
754 let { seg, rect } = segPlacement;
755 let instanceId = seg.eventRange.instance.instanceId;
756 let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
757 let vStyle = computeSegVStyle(rect && rect.span);
758 let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : { left: 0, right: 0 };
759 let isInset = Boolean(rect) && rect.stackForward > 0;
760 let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
761 return (preact.createElement("div", { className: 'fc-timegrid-event-harness' +
762 (isInset ? ' fc-timegrid-event-harness-inset' : ''), key: forcedKey || instanceId, style: Object.assign(Object.assign({ visibility: isVisible ? '' : 'hidden' }, vStyle), hStyle) },
763 preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === eventSelection, isShort: isShort }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
764 })));
765 }
766 // will already have eventMinHeight applied because segInputs already had it
767 renderHiddenGroups(hiddenGroups, segs) {
768 let { extraDateSpan, dateProfile, todayRange, nowDate, eventSelection, eventDrag, eventResize } = this.props;
769 return (preact.createElement(preact.Fragment, null, hiddenGroups.map((hiddenGroup) => {
770 let positionCss = computeSegVStyle(hiddenGroup.span);
771 let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
772 return (preact.createElement(TimeColMoreLink, { key: internal$1.buildIsoString(internal$1.computeEarliestSegStart(hiddenSegs)), hiddenSegs: hiddenSegs, top: positionCss.top, bottom: positionCss.bottom, extraDateSpan: extraDateSpan, dateProfile: dateProfile, todayRange: todayRange, nowDate: nowDate, eventSelection: eventSelection, eventDrag: eventDrag, eventResize: eventResize }));
773 })));
774 }
775 renderFillSegs(segs, fillType) {
776 let { props, context } = this;
777 let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
778 let children = segVCoords.map((vcoords, i) => {
779 let seg = segs[i];
780 return (preact.createElement("div", { key: internal$1.buildEventRangeKey(seg.eventRange), className: "fc-timegrid-bg-harness", style: computeSegVStyle(vcoords) }, fillType === 'bg-event' ?
781 preact.createElement(internal$1.BgEvent, Object.assign({ seg: seg }, internal$1.getSegMeta(seg, props.todayRange, props.nowDate))) :
782 internal$1.renderFill(fillType)));
783 });
784 return preact.createElement(preact.Fragment, null, children);
785 }
786 renderNowIndicator(segs) {
787 let { slatCoords, date } = this.props;
788 if (!slatCoords) {
789 return null;
790 }
791 return segs.map((seg, i) => (preact.createElement(internal$1.NowIndicatorContainer
792 // key doesn't matter. will only ever be one
793 , {
794 // key doesn't matter. will only ever be one
795 key: i, elClasses: ['fc-timegrid-now-indicator-line'], elStyle: {
796 top: slatCoords.computeDateTop(seg.start, date),
797 }, isAxis: false, date: date })));
798 }
799 computeSegHStyle(segHCoords) {
800 let { isRtl, options } = this.context;
801 let shouldOverlap = options.slotEventOverlap;
802 let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
803 let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
804 let left; // amount of space from left edge, a fraction of the total width
805 let right; // amount of space from right edge, a fraction of the total width
806 if (shouldOverlap) {
807 // double the width, but don't go beyond the maximum forward coordinate (1.0)
808 farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
809 }
810 if (isRtl) {
811 left = 1 - farCoord;
812 right = nearCoord;
813 }
814 else {
815 left = nearCoord;
816 right = 1 - farCoord;
817 }
818 let props = {
819 zIndex: segHCoords.stackDepth + 1,
820 left: left * 100 + '%',
821 right: right * 100 + '%',
822 };
823 if (shouldOverlap && !segHCoords.stackForward) {
824 // add padding to the edge so that forward stacked events don't cover the resizer's icon
825 props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
826 }
827 return props;
828 }
829 }
830 function renderPlainFgSegs(sortedFgSegs, { todayRange, nowDate, eventSelection, eventDrag, eventResize }) {
831 let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
832 (eventResize ? eventResize.affectedInstances : null) ||
833 {};
834 return (preact.createElement(preact.Fragment, null, sortedFgSegs.map((seg) => {
835 let instanceId = seg.eventRange.instance.instanceId;
836 return (preact.createElement("div", { key: instanceId, style: { visibility: hiddenInstances[instanceId] ? 'hidden' : '' } },
837 preact.createElement(TimeColEvent, Object.assign({ seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === eventSelection, isShort: false }, internal$1.getSegMeta(seg, todayRange, nowDate)))));
838 })));
839 }
840 function computeSegVStyle(segVCoords) {
841 if (!segVCoords) {
842 return { top: '', bottom: '' };
843 }
844 return {
845 top: segVCoords.start,
846 bottom: -segVCoords.end,
847 };
848 }
849 function compileSegsFromEntries(segEntries, allSegs) {
850 return segEntries.map((segEntry) => allSegs[segEntry.index]);
851 }
852
853 class TimeColsContent extends internal$1.BaseComponent {
854 constructor() {
855 super(...arguments);
856 this.splitFgEventSegs = internal$1.memoize(splitSegsByCol);
857 this.splitBgEventSegs = internal$1.memoize(splitSegsByCol);
858 this.splitBusinessHourSegs = internal$1.memoize(splitSegsByCol);
859 this.splitNowIndicatorSegs = internal$1.memoize(splitSegsByCol);
860 this.splitDateSelectionSegs = internal$1.memoize(splitSegsByCol);
861 this.splitEventDrag = internal$1.memoize(splitInteractionByCol);
862 this.splitEventResize = internal$1.memoize(splitInteractionByCol);
863 this.rootElRef = preact.createRef();
864 this.cellElRefs = new internal$1.RefMap();
865 }
866 render() {
867 let { props, context } = this;
868 let nowIndicatorTop = context.options.nowIndicator &&
869 props.slatCoords &&
870 props.slatCoords.safeComputeTop(props.nowDate); // might return void
871 let colCnt = props.cells.length;
872 let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
873 let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
874 let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
875 let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
876 let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
877 let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
878 let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
879 return (preact.createElement("div", { className: "fc-timegrid-cols", ref: this.rootElRef },
880 preact.createElement("table", { role: "presentation", style: {
881 minWidth: props.tableMinWidth,
882 width: props.clientWidth,
883 } },
884 props.tableColGroupNode,
885 preact.createElement("tbody", { role: "presentation" },
886 preact.createElement("tr", { role: "row" },
887 props.axis && (preact.createElement("td", { "aria-hidden": true, className: "fc-timegrid-col fc-timegrid-axis" },
888 preact.createElement("div", { className: "fc-timegrid-col-frame" },
889 preact.createElement("div", { className: "fc-timegrid-now-indicator-container" }, typeof nowIndicatorTop === 'number' && (preact.createElement(internal$1.NowIndicatorContainer, { elClasses: ['fc-timegrid-now-indicator-arrow'], elStyle: { top: nowIndicatorTop }, isAxis: true, date: props.nowDate })))))),
890 props.cells.map((cell, i) => (preact.createElement(TimeCol, { key: cell.key, elRef: this.cellElRefs.createRef(cell.key), dateProfile: props.dateProfile, date: cell.date, nowDate: props.nowDate, todayRange: props.todayRange, extraRenderProps: cell.extraRenderProps, extraDataAttrs: cell.extraDataAttrs, extraClassNames: cell.extraClassNames, extraDateSpan: cell.extraDateSpan, fgEventSegs: fgEventSegsByRow[i], bgEventSegs: bgEventSegsByRow[i], businessHourSegs: businessHourSegsByRow[i], nowIndicatorSegs: nowIndicatorSegsByRow[i], dateSelectionSegs: dateSelectionSegsByRow[i], eventDrag: eventDragByRow[i], eventResize: eventResizeByRow[i], slatCoords: props.slatCoords, eventSelection: props.eventSelection, forPrint: props.forPrint }))))))));
891 }
892 componentDidMount() {
893 this.updateCoords();
894 }
895 componentDidUpdate() {
896 this.updateCoords();
897 }
898 updateCoords() {
899 let { props } = this;
900 if (props.onColCoords &&
901 props.clientWidth !== null // means sizing has stabilized
902 ) {
903 props.onColCoords(new internal$1.PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
904 false));
905 }
906 }
907 }
908 function collectCellEls(elMap, cells) {
909 return cells.map((cell) => elMap[cell.key]);
910 }
911
912 /* A component that renders one or more columns of vertical time slots
913 ----------------------------------------------------------------------------------------------------------------------*/
914 class TimeCols extends internal$1.DateComponent {
915 constructor() {
916 super(...arguments);
917 this.processSlotOptions = internal$1.memoize(processSlotOptions);
918 this.state = {
919 slatCoords: null,
920 };
921 this.handleRootEl = (el) => {
922 if (el) {
923 this.context.registerInteractiveComponent(this, {
924 el,
925 isHitComboAllowed: this.props.isHitComboAllowed,
926 });
927 }
928 else {
929 this.context.unregisterInteractiveComponent(this);
930 }
931 };
932 this.handleScrollRequest = (request) => {
933 let { onScrollTopRequest } = this.props;
934 let { slatCoords } = this.state;
935 if (onScrollTopRequest && slatCoords) {
936 if (request.time) {
937 let top = slatCoords.computeTimeTop(request.time);
938 top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
939 if (top) {
940 top += 1; // to overcome top border that slots beyond the first have. looks better
941 }
942 onScrollTopRequest(top);
943 }
944 return true;
945 }
946 return false;
947 };
948 this.handleColCoords = (colCoords) => {
949 this.colCoords = colCoords;
950 };
951 this.handleSlatCoords = (slatCoords) => {
952 this.setState({ slatCoords });
953 if (this.props.onSlatCoords) {
954 this.props.onSlatCoords(slatCoords);
955 }
956 };
957 }
958 render() {
959 let { props, state } = this;
960 return (preact.createElement("div", { className: "fc-timegrid-body", ref: this.handleRootEl, style: {
961 // these props are important to give this wrapper correct dimensions for interactions
962 // TODO: if we set it here, can we avoid giving to inner tables?
963 width: props.clientWidth,
964 minWidth: props.tableMinWidth,
965 } },
966 preact.createElement(TimeColsSlats, { axis: props.axis, dateProfile: props.dateProfile, slatMetas: props.slatMetas, clientWidth: props.clientWidth, minHeight: props.expandRows ? props.clientHeight : '', tableMinWidth: props.tableMinWidth, tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */, onCoords: this.handleSlatCoords }),
967 preact.createElement(TimeColsContent, { cells: props.cells, axis: props.axis, dateProfile: props.dateProfile, businessHourSegs: props.businessHourSegs, bgEventSegs: props.bgEventSegs, fgEventSegs: props.fgEventSegs, dateSelectionSegs: props.dateSelectionSegs, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, todayRange: props.todayRange, nowDate: props.nowDate, nowIndicatorSegs: props.nowIndicatorSegs, clientWidth: props.clientWidth, tableMinWidth: props.tableMinWidth, tableColGroupNode: props.tableColGroupNode, slatCoords: state.slatCoords, onColCoords: this.handleColCoords, forPrint: props.forPrint })));
968 }
969 componentDidMount() {
970 this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
971 }
972 componentDidUpdate(prevProps) {
973 this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
974 }
975 componentWillUnmount() {
976 this.scrollResponder.detach();
977 }
978 queryHit(positionLeft, positionTop) {
979 let { dateEnv, options } = this.context;
980 let { colCoords } = this;
981 let { dateProfile } = this.props;
982 let { slatCoords } = this.state;
983 let { snapDuration, snapsPerSlot } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
984 let colIndex = colCoords.leftToIndex(positionLeft);
985 let slatIndex = slatCoords.positions.topToIndex(positionTop);
986 if (colIndex != null && slatIndex != null) {
987 let cell = this.props.cells[colIndex];
988 let slatTop = slatCoords.positions.tops[slatIndex];
989 let slatHeight = slatCoords.positions.getHeight(slatIndex);
990 let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
991 let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
992 let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
993 let dayDate = this.props.cells[colIndex].date;
994 let time = internal$1.addDurations(dateProfile.slotMinTime, internal$1.multiplyDuration(snapDuration, snapIndex));
995 let start = dateEnv.add(dayDate, time);
996 let end = dateEnv.add(start, snapDuration);
997 return {
998 dateProfile,
999 dateSpan: Object.assign({ range: { start, end }, allDay: false }, cell.extraDateSpan),
1000 dayEl: colCoords.els[colIndex],
1001 rect: {
1002 left: colCoords.lefts[colIndex],
1003 right: colCoords.rights[colIndex],
1004 top: slatTop,
1005 bottom: slatTop + slatHeight,
1006 },
1007 layer: 0,
1008 };
1009 }
1010 return null;
1011 }
1012 }
1013 function processSlotOptions(slotDuration, snapDurationOverride) {
1014 let snapDuration = snapDurationOverride || slotDuration;
1015 let snapsPerSlot = internal$1.wholeDivideDurations(slotDuration, snapDuration);
1016 if (snapsPerSlot === null) {
1017 snapDuration = slotDuration;
1018 snapsPerSlot = 1;
1019 // TODO: say warning?
1020 }
1021 return { snapDuration, snapsPerSlot };
1022 }
1023
1024 class DayTimeColsSlicer extends internal$1.Slicer {
1025 sliceRange(range, dayRanges) {
1026 let segs = [];
1027 for (let col = 0; col < dayRanges.length; col += 1) {
1028 let segRange = internal$1.intersectRanges(range, dayRanges[col]);
1029 if (segRange) {
1030 segs.push({
1031 start: segRange.start,
1032 end: segRange.end,
1033 isStart: segRange.start.valueOf() === range.start.valueOf(),
1034 isEnd: segRange.end.valueOf() === range.end.valueOf(),
1035 col,
1036 });
1037 }
1038 }
1039 return segs;
1040 }
1041 }
1042
1043 class DayTimeCols extends internal$1.DateComponent {
1044 constructor() {
1045 super(...arguments);
1046 this.buildDayRanges = internal$1.memoize(buildDayRanges);
1047 this.slicer = new DayTimeColsSlicer();
1048 this.timeColsRef = preact.createRef();
1049 }
1050 render() {
1051 let { props, context } = this;
1052 let { dateProfile, dayTableModel } = props;
1053 let { nowIndicator, nextDayThreshold } = context.options;
1054 let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
1055 // give it the first row of cells
1056 // TODO: would move this further down hierarchy, but sliceNowDate needs it
1057 return (preact.createElement(internal$1.NowTimer, { unit: nowIndicator ? 'minute' : 'day' }, (nowDate, todayRange) => (preact.createElement(TimeCols, Object.assign({ ref: this.timeColsRef }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), { forPrint: props.forPrint, axis: props.axis, dateProfile: dateProfile, slatMetas: props.slatMetas, slotDuration: props.slotDuration, cells: dayTableModel.cells[0], tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, clientWidth: props.clientWidth, clientHeight: props.clientHeight, expandRows: props.expandRows, nowDate: nowDate, nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges), todayRange: todayRange, onScrollTopRequest: props.onScrollTopRequest, onSlatCoords: props.onSlatCoords })))));
1058 }
1059 }
1060 function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
1061 let ranges = [];
1062 for (let date of dayTableModel.headerDates) {
1063 ranges.push({
1064 start: dateEnv.add(date, dateProfile.slotMinTime),
1065 end: dateEnv.add(date, dateProfile.slotMaxTime),
1066 });
1067 }
1068 return ranges;
1069 }
1070
1071 // potential nice values for the slot-duration and interval-duration
1072 // from largest to smallest
1073 const STOCK_SUB_DURATIONS = [
1074 { hours: 1 },
1075 { minutes: 30 },
1076 { minutes: 15 },
1077 { seconds: 30 },
1078 { seconds: 15 },
1079 ];
1080 function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
1081 let dayStart = new Date(0);
1082 let slatTime = slotMinTime;
1083 let slatIterator = internal$1.createDuration(0);
1084 let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
1085 let metas = [];
1086 while (internal$1.asRoughMs(slatTime) < internal$1.asRoughMs(slotMaxTime)) {
1087 let date = dateEnv.add(dayStart, slatTime);
1088 let isLabeled = internal$1.wholeDivideDurations(slatIterator, labelInterval) !== null;
1089 metas.push({
1090 date,
1091 time: slatTime,
1092 key: date.toISOString(),
1093 isoTimeStr: internal$1.formatIsoTimeString(date),
1094 isLabeled,
1095 });
1096 slatTime = internal$1.addDurations(slatTime, slotDuration);
1097 slatIterator = internal$1.addDurations(slatIterator, slotDuration);
1098 }
1099 return metas;
1100 }
1101 // Computes an automatic value for slotLabelInterval
1102 function computeLabelInterval(slotDuration) {
1103 let i;
1104 let labelInterval;
1105 let slotsPerLabel;
1106 // find the smallest stock label interval that results in more than one slots-per-label
1107 for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
1108 labelInterval = internal$1.createDuration(STOCK_SUB_DURATIONS[i]);
1109 slotsPerLabel = internal$1.wholeDivideDurations(labelInterval, slotDuration);
1110 if (slotsPerLabel !== null && slotsPerLabel > 1) {
1111 return labelInterval;
1112 }
1113 }
1114 return slotDuration; // fall back
1115 }
1116
1117 class DayTimeColsView extends TimeColsView {
1118 constructor() {
1119 super(...arguments);
1120 this.buildTimeColsModel = internal$1.memoize(buildTimeColsModel);
1121 this.buildSlatMetas = internal$1.memoize(buildSlatMetas);
1122 }
1123 render() {
1124 let { options, dateEnv, dateProfileGenerator } = this.context;
1125 let { props } = this;
1126 let { dateProfile } = props;
1127 let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
1128 let splitProps = this.allDaySplitter.splitProps(props);
1129 let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
1130 let { dayMinWidth } = options;
1131 let hasAttachedAxis = !dayMinWidth;
1132 let hasDetachedAxis = dayMinWidth;
1133 let headerContent = options.dayHeaders && (preact.createElement(internal$1.DayHeader, { dates: dayTableModel.headerDates, dateProfile: dateProfile, datesRepDistinctDays: true, renderIntro: hasAttachedAxis ? this.renderHeadAxis : null }));
1134 let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (preact.createElement(internal$2.DayTable, Object.assign({}, splitProps.allDay, { dateProfile: dateProfile, dayTableModel: dayTableModel, nextDayThreshold: options.nextDayThreshold, tableMinWidth: contentArg.tableMinWidth, colGroupNode: contentArg.tableColGroupNode, renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null, showWeekNumbers: false, expandRows: false, headerAlignElRef: this.headerElRef, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, forPrint: props.forPrint }, this.getAllDayMaxEventProps()))));
1135 let timeGridContent = (contentArg) => (preact.createElement(DayTimeCols, Object.assign({}, splitProps.timed, { dayTableModel: dayTableModel, dateProfile: dateProfile, axis: hasAttachedAxis, slotDuration: options.slotDuration, slatMetas: slatMetas, forPrint: props.forPrint, tableColGroupNode: contentArg.tableColGroupNode, tableMinWidth: contentArg.tableMinWidth, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, onSlatCoords: this.handleSlatCoords, expandRows: contentArg.expandRows, onScrollTopRequest: this.handleScrollTopRequest })));
1136 return hasDetachedAxis
1137 ? this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords)
1138 : this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
1139 }
1140 }
1141 function buildTimeColsModel(dateProfile, dateProfileGenerator) {
1142 let daySeries = new internal$1.DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
1143 return new internal$1.DayTableModel(daySeries, false);
1144 }
1145
1146 const OPTION_REFINERS = {
1147 allDaySlot: Boolean,
1148 };
1149
1150 var css_248z = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
1151 internal$1.injectStyles(css_248z);
1152
1153 var plugin = core.createPlugin({
1154 name: '@fullcalendar/timegrid',
1155 initialView: 'timeGridWeek',
1156 optionRefiners: OPTION_REFINERS,
1157 views: {
1158 timeGrid: {
1159 component: DayTimeColsView,
1160 usesMinMaxTime: true,
1161 allDaySlot: true,
1162 slotDuration: '00:30:00',
1163 slotEventOverlap: true, // a bad name. confused with overlap/constraint system
1164 },
1165 timeGridDay: {
1166 type: 'timeGrid',
1167 duration: { days: 1 },
1168 },
1169 timeGridWeek: {
1170 type: 'timeGrid',
1171 duration: { weeks: 1 },
1172 },
1173 },
1174 });
1175
1176 var internal = {
1177 __proto__: null,
1178 TimeColsView: TimeColsView,
1179 DayTimeColsView: DayTimeColsView,
1180 buildTimeColsModel: buildTimeColsModel,
1181 DayTimeCols: DayTimeCols,
1182 buildDayRanges: buildDayRanges,
1183 DayTimeColsSlicer: DayTimeColsSlicer,
1184 TimeCols: TimeCols,
1185 buildSlatMetas: buildSlatMetas,
1186 TimeColsSlatsCoords: TimeColsSlatsCoords
1187 };
1188
1189 core.globalPlugins.push(plugin);
1190
1191 exports.Internal = internal;
1192 exports["default"] = plugin;
1193
1194 Object.defineProperty(exports, '__esModule', { value: true });
1195
1196 return exports;
1197
1198})({}, FullCalendar, FullCalendar.Internal, FullCalendar.Preact, FullCalendar.DayGrid.Internal);
diff --git a/public/js/fullcalendar/packages/timegrid/index.global.min.js b/public/js/fullcalendar/packages/timegrid/index.global.min.js
new file mode 100644
index 0000000..48bde7a
--- /dev/null
+++ b/public/js/fullcalendar/packages/timegrid/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Time Grid Plugin v6.1.17
3Docs & License: https://fullcalendar.io/docs/timegrid-view
4(c) 2024 Adam Shaw
5*/
6FullCalendar.TimeGrid=function(e,t,i,r,n){"use strict";class o extends i.Splitter{getKeyInfo(){return{allDay:{},timed:{}}}getKeysForDateSpan(e){return e.allDay?["allDay"]:["timed"]}getKeysForEventDef(e){return e.allDay?i.hasBgRendering(e)?["timed","allDay"]:["allDay"]:["timed"]}}const s=i.createFormatter({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"});function l(e){let t=["fc-timegrid-slot","fc-timegrid-slot-label",e.isLabeled?"fc-scrollgrid-shrink":"fc-timegrid-slot-minor"];return r.createElement(i.ViewContextType.Consumer,null,n=>{if(!e.isLabeled)return r.createElement("td",{className:t.join(" "),"data-time":e.isoTimeStr});let{dateEnv:o,options:l,viewApi:c}=n,d=null==l.slotLabelFormat?s:Array.isArray(l.slotLabelFormat)?i.createFormatter(l.slotLabelFormat[0]):i.createFormatter(l.slotLabelFormat),m={level:0,time:e.time,date:o.toDate(e.date),view:c,text:o.format(e.date,d)};return r.createElement(i.ContentContainer,{elTag:"td",elClasses:t,elAttrs:{"data-time":e.isoTimeStr},renderProps:m,generatorName:"slotLabelContent",customGenerator:l.slotLabelContent,defaultGenerator:a,classNameGenerator:l.slotLabelClassNames,didMount:l.slotLabelDidMount,willUnmount:l.slotLabelWillUnmount},e=>r.createElement("div",{className:"fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame"},r.createElement(e,{elTag:"div",elClasses:["fc-timegrid-slot-label-cushion","fc-scrollgrid-shrink-cushion"]})))})}function a(e){return e.text}class c extends i.BaseComponent{render(){return this.props.slatMetas.map(e=>r.createElement("tr",{key:e.key},r.createElement(l,Object.assign({},e))))}}const d=i.createFormatter({week:"short"});class m extends i.DateComponent{constructor(){super(...arguments),this.allDaySplitter=new o,this.headerElRef=r.createRef(),this.rootElRef=r.createRef(),this.scrollerElRef=r.createRef(),this.state={slatCoords:null},this.handleScrollTopRequest=e=>{let t=this.scrollerElRef.current;t&&(t.scrollTop=e)},this.renderHeadAxis=(e,t="")=>{let{options:n}=this.context,{dateProfile:o}=this.props,s=o.renderRange,l=1===i.diffDays(s.start,s.end)?i.buildNavLinkAttrs(this.context,s.start,"week"):{};return n.weekNumbers&&"day"===e?r.createElement(i.WeekNumberContainer,{elTag:"th",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},date:s.start,defaultFormat:d},e=>r.createElement("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame","fc-timegrid-axis-frame-liquid"].join(" "),style:{height:t}},r.createElement(e,{elTag:"a",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"],elAttrs:l}))):r.createElement("th",{"aria-hidden":!0,className:"fc-timegrid-axis"},r.createElement("div",{className:"fc-timegrid-axis-frame",style:{height:t}}))},this.renderTableRowAxis=e=>{let{options:t,viewApi:n}=this.context,o={text:t.allDayText,view:n};return r.createElement(i.ContentContainer,{elTag:"td",elClasses:["fc-timegrid-axis","fc-scrollgrid-shrink"],elAttrs:{"aria-hidden":!0},renderProps:o,generatorName:"allDayContent",customGenerator:t.allDayContent,defaultGenerator:f,classNameGenerator:t.allDayClassNames,didMount:t.allDayDidMount,willUnmount:t.allDayWillUnmount},t=>r.createElement("div",{className:["fc-timegrid-axis-frame","fc-scrollgrid-shrink-frame",null==e?" fc-timegrid-axis-frame-liquid":""].join(" "),style:{height:e}},r.createElement(t,{elTag:"span",elClasses:["fc-timegrid-axis-cushion","fc-scrollgrid-shrink-cushion","fc-scrollgrid-sync-inner"]})))},this.handleSlatCoords=e=>{this.setState({slatCoords:e})}}renderSimpleLayout(e,t,n){let{context:o,props:s}=this,l=[],a=i.getStickyHeaderDates(o.options);return e&&l.push({type:"header",key:"header",isSticky:a,chunk:{elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}}),t&&(l.push({type:"body",key:"all-day",chunk:{content:t}}),l.push({type:"body",key:"all-day-divider",outerContent:r.createElement("tr",{role:"presentation",className:"fc-scrollgrid-section"},r.createElement("td",{className:"fc-timegrid-divider "+o.theme.getClass("tableCellShaded")}))})),l.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(o.options.expandRows),chunk:{scrollerElRef:this.scrollerElRef,content:n}}),r.createElement(i.ViewContainer,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:o.viewSpec},r.createElement(i.SimpleScrollGrid,{liquid:!s.isHeightAuto&&!s.forPrint,collapsibleWidth:s.forPrint,cols:[{width:"shrink"}],sections:l}))}renderHScrollLayout(e,t,n,o,s,l,a){let d=this.context.pluginHooks.scrollGridImpl;if(!d)throw new Error("No ScrollGrid implementation");let{context:m,props:f}=this,h=!f.forPrint&&i.getStickyHeaderDates(m.options),g=!f.forPrint&&i.getStickyFooterScrollbar(m.options),u=[];e&&u.push({type:"header",key:"header",isSticky:h,syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>r.createElement("tr",{role:"presentation"},this.renderHeadAxis("day",e.rowSyncHeights[0]))},{key:"cols",elRef:this.headerElRef,tableClassName:"fc-col-header",rowContent:e}]}),t&&(u.push({type:"body",key:"all-day",syncRowHeights:!0,chunks:[{key:"axis",rowContent:e=>r.createElement("tr",{role:"presentation"},this.renderTableRowAxis(e.rowSyncHeights[0]))},{key:"cols",content:t}]}),u.push({key:"all-day-divider",type:"body",outerContent:r.createElement("tr",{role:"presentation",className:"fc-scrollgrid-section"},r.createElement("td",{colSpan:2,className:"fc-timegrid-divider "+m.theme.getClass("tableCellShaded")}))}));let p=m.options.nowIndicator;return u.push({type:"body",key:"body",liquid:!0,expandRows:Boolean(m.options.expandRows),chunks:[{key:"axis",content:e=>r.createElement("div",{className:"fc-timegrid-axis-chunk"},r.createElement("table",{"aria-hidden":!0,style:{height:e.expandRows?e.clientHeight:""}},e.tableColGroupNode,r.createElement("tbody",null,r.createElement(c,{slatMetas:l}))),r.createElement("div",{className:"fc-timegrid-now-indicator-container"},r.createElement(i.NowTimer,{unit:p?"minute":"day"},e=>{let t=p&&a&&a.safeComputeTop(e);return"number"==typeof t?r.createElement(i.NowIndicatorContainer,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:t},isAxis:!0,date:e}):null})))},{key:"cols",scrollerElRef:this.scrollerElRef,content:n}]}),g&&u.push({key:"footer",type:"footer",isSticky:!0,chunks:[{key:"axis",content:i.renderScrollShim},{key:"cols",content:i.renderScrollShim}]}),r.createElement(i.ViewContainer,{elRef:this.rootElRef,elClasses:["fc-timegrid"],viewSpec:m.viewSpec},r.createElement(d,{liquid:!f.isHeightAuto&&!f.forPrint,forPrint:f.forPrint,collapsibleWidth:!1,colGroups:[{width:"shrink",cols:[{width:"shrink"}]},{cols:[{span:o,minWidth:s}]}],sections:u}))}getAllDayMaxEventProps(){let{dayMaxEvents:e,dayMaxEventRows:t}=this.context.options;return!0!==e&&!0!==t||(e=void 0,t=5),{dayMaxEvents:e,dayMaxEventRows:t}}}function f(e){return e.text}class h{constructor(e,t,i){this.positions=e,this.dateProfile=t,this.slotDuration=i}safeComputeTop(e){let{dateProfile:t}=this;if(i.rangeContainsMarker(t.currentRange,e)){let r=i.startOfDay(e),n=e.valueOf()-r.valueOf();if(n>=i.asRoughMs(t.slotMinTime)&&n<i.asRoughMs(t.slotMaxTime))return this.computeTimeTop(i.createDuration(n))}return null}computeDateTop(e,t){return t||(t=i.startOfDay(e)),this.computeTimeTop(i.createDuration(e.valueOf()-t.valueOf()))}computeTimeTop(e){let t,r,{positions:n,dateProfile:o}=this,s=n.els.length,l=(e.milliseconds-i.asRoughMs(o.slotMinTime))/i.asRoughMs(this.slotDuration);return l=Math.max(0,l),l=Math.min(s,l),t=Math.floor(l),t=Math.min(t,s-1),r=l-t,n.tops[t]+n.getHeight(t)*r}}class g extends i.BaseComponent{render(){let{props:e,context:t}=this,{options:n}=t,{slatElRefs:o}=e;return r.createElement("tbody",null,e.slatMetas.map((s,a)=>{let c={time:s.time,date:t.dateEnv.toDate(s.date),view:t.viewApi};return r.createElement("tr",{key:s.key,ref:o.createRef(s.key)},e.axis&&r.createElement(l,Object.assign({},s)),r.createElement(i.ContentContainer,{elTag:"td",elClasses:["fc-timegrid-slot","fc-timegrid-slot-lane",!s.isLabeled&&"fc-timegrid-slot-minor"],elAttrs:{"data-time":s.isoTimeStr},renderProps:c,generatorName:"slotLaneContent",customGenerator:n.slotLaneContent,classNameGenerator:n.slotLaneClassNames,didMount:n.slotLaneDidMount,willUnmount:n.slotLaneWillUnmount}))}))}}class u extends i.BaseComponent{constructor(){super(...arguments),this.rootElRef=r.createRef(),this.slatElRefs=new i.RefMap}render(){let{props:e,context:t}=this;return r.createElement("div",{ref:this.rootElRef,className:"fc-timegrid-slots"},r.createElement("table",{"aria-hidden":!0,className:t.theme.getClass("table"),style:{minWidth:e.tableMinWidth,width:e.clientWidth,height:e.minHeight}},e.tableColGroupNode,r.createElement(g,{slatElRefs:this.slatElRefs,axis:e.axis,slatMetas:e.slatMetas})))}componentDidMount(){this.updateSizing()}componentDidUpdate(){this.updateSizing()}componentWillUnmount(){this.props.onCoords&&this.props.onCoords(null)}updateSizing(){let{context:e,props:t}=this;if(t.onCoords&&null!==t.clientWidth){this.rootElRef.current.offsetHeight&&t.onCoords(new h(new i.PositionCache(this.rootElRef.current,(r=this.slatElRefs.currentMap,t.slatMetas.map(e=>r[e.key])),!1,!0),this.props.dateProfile,e.options.slotDuration))}var r}}function p(e,t){let i,r=[];for(i=0;i<t;i+=1)r.push([]);if(e)for(i=0;i<e.length;i+=1)r[e[i].col].push(e[i]);return r}function v(e,t){let i=[];if(e){for(let r=0;r<t;r+=1)i[r]={affectedInstances:e.affectedInstances,isEvent:e.isEvent,segs:[]};for(let t of e.segs)i[t.col].segs.push(t)}else for(let e=0;e<t;e+=1)i[e]=null;return i}class b extends i.BaseComponent{render(){let{props:e}=this;return r.createElement(i.MoreLinkContainer,{elClasses:["fc-timegrid-more-link"],elStyle:{top:e.top,bottom:e.bottom},allDayDate:null,moreCnt:e.hiddenSegs.length,allSegs:e.hiddenSegs,hiddenSegs:e.hiddenSegs,extraDateSpan:e.extraDateSpan,dateProfile:e.dateProfile,todayRange:e.todayRange,popoverContent:()=>T(e.hiddenSegs,e),defaultGenerator:y,forceTimed:!0},e=>r.createElement(e,{elTag:"div",elClasses:["fc-timegrid-more-link-inner","fc-sticky"]}))}}function y(e){return e.shortText}function x(e,t,r){let n=new i.SegHierarchy;null!=t&&(n.strictOrder=t),null!=r&&(n.maxStackCnt=r);let o=n.addSegs(e),s=i.groupIntersectingEntries(o),l=function(e){const{entriesByLevel:t}=e,r=w((e,t)=>e+":"+t,(n,o)=>{let s=S(function(e,t,r){let{levelCoords:n,entriesByLevel:o}=e,s=o[t][r],l=n[t]+s.thickness,a=n.length,c=t;for(;c<a&&n[c]<l;c+=1);for(;c<a;c+=1){let e,t=o[c],r=i.binarySearch(t,s.span.start,i.getEntrySpanEnd),n=r[0]+r[1],l=n;for(;(e=t[l])&&e.span.start<s.span.end;)l+=1;if(n<l)return{level:c,lateralStart:n,lateralEnd:l}}return null}(e,n,o),r),l=t[n][o];return[Object.assign(Object.assign({},l),{nextLevelNodes:s[0]}),l.thickness+s[1]]});return S(t.length?{level:0,lateralStart:0,lateralEnd:t[0].length}:null,r)[0]}(n);return l=function(e,t){const r=w((e,t,r)=>i.buildEntryKey(e),(e,i,n)=>{let o,{nextLevelNodes:s,thickness:l}=e,a=l+n,c=l/a,d=[];if(s.length)for(let e of s)if(void 0===o){let t=r(e,i,a);o=t[0],d.push(t[1])}else{let t=r(e,o,0);d.push(t[1])}else o=t;let m=(o-i)*c;return[o-m,Object.assign(Object.assign({},e),{thickness:m,nextLevelNodes:d})]});return e.map(e=>r(e,0,0)[1])}(l,1),{segRects:function(e){let t=[];const r=w((e,t,r)=>i.buildEntryKey(e),(e,i,r)=>{let o=Object.assign(Object.assign({},e),{levelCoord:i,stackDepth:r,stackForward:0});return t.push(o),o.stackForward=n(e.nextLevelNodes,i+e.thickness,r+1)+1});function n(e,t,i){let n=0;for(let o of e)n=Math.max(r(o,t,i),n);return n}return n(e,0,0),t}(l),hiddenGroups:s}}function S(e,t){if(!e)return[[],0];let{level:i,lateralStart:r,lateralEnd:n}=e,o=r,s=[];for(;o<n;)s.push(t(i,o)),o+=1;return s.sort(C),[s.map(E),s[0][1]]}function C(e,t){return t[1]-e[1]}function E(e){return e[0]}function w(e,t){const i={};return(...r)=>{let n=e(...r);return n in i?i[n]:i[n]=t(...r)}}function D(e,t,i=null,r=0){let n=[];if(i)for(let o=0;o<e.length;o+=1){let s=e[o],l=i.computeDateTop(s.start,t),a=Math.max(l+(r||0),i.computeDateTop(s.end,t));n.push({start:Math.round(l),end:Math.round(a)})}return n}const R=i.createFormatter({hour:"numeric",minute:"2-digit",meridiem:!1});class k extends i.BaseComponent{render(){return r.createElement(i.StandardEvent,Object.assign({},this.props,{elClasses:["fc-timegrid-event","fc-v-event",this.props.isShort&&"fc-timegrid-event-short"],defaultTimeFormat:R}))}}class M extends i.BaseComponent{constructor(){super(...arguments),this.sortEventSegs=i.memoize(i.sortEventSegs)}render(){let{props:e,context:t}=this,{options:n}=t,o=n.selectMirror,s=e.eventDrag&&e.eventDrag.segs||e.eventResize&&e.eventResize.segs||o&&e.dateSelectionSegs||[],l=e.eventDrag&&e.eventDrag.affectedInstances||e.eventResize&&e.eventResize.affectedInstances||{},a=this.sortEventSegs(e.fgEventSegs,n.eventOrder);return r.createElement(i.DayCellContainer,{elTag:"td",elRef:e.elRef,elClasses:["fc-timegrid-col",...e.extraClassNames||[]],elAttrs:Object.assign({role:"gridcell"},e.extraDataAttrs),date:e.date,dateProfile:e.dateProfile,todayRange:e.todayRange,extraRenderProps:e.extraRenderProps},t=>r.createElement("div",{className:"fc-timegrid-col-frame"},r.createElement("div",{className:"fc-timegrid-col-bg"},this.renderFillSegs(e.businessHourSegs,"non-business"),this.renderFillSegs(e.bgEventSegs,"bg-event"),this.renderFillSegs(e.dateSelectionSegs,"highlight")),r.createElement("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(a,l,!1,!1,!1)),r.createElement("div",{className:"fc-timegrid-col-events"},this.renderFgSegs(s,{},Boolean(e.eventDrag),Boolean(e.eventResize),Boolean(o),"mirror")),r.createElement("div",{className:"fc-timegrid-now-indicator-container"},this.renderNowIndicator(e.nowIndicatorSegs)),i.hasCustomDayCellContent(n)&&r.createElement(t,{elTag:"div",elClasses:["fc-timegrid-col-misc"]})))}renderFgSegs(e,t,i,r,n,o){let{props:s}=this;return s.forPrint?T(e,s):this.renderPositionedFgSegs(e,t,i,r,n,o)}renderPositionedFgSegs(e,t,n,o,s,l){let{eventMaxStack:a,eventShortHeight:c,eventOrderStrict:d,eventMinHeight:m}=this.context.options,{date:f,slatCoords:h,eventSelection:g,todayRange:u,nowDate:p}=this.props,v=n||o||s,b=D(e,f,h,m),{segPlacements:y,hiddenGroups:S}=function(e,t,i,r){let n=[],o=[];for(let i=0;i<e.length;i+=1){let r=t[i];r?n.push({index:i,thickness:1,span:r}):o.push(e[i])}let{segRects:s,hiddenGroups:l}=x(n,i,r),a=[];for(let t of s)a.push({seg:e[t.index],rect:t});for(let e of o)a.push({seg:e,rect:null});return{segPlacements:a,hiddenGroups:l}}(e,b,d,a);return r.createElement(r.Fragment,null,this.renderHiddenGroups(S,e),y.map(e=>{let{seg:a,rect:d}=e,m=a.eventRange.instance.instanceId,f=v||Boolean(!t[m]&&d),h=N(d&&d.span),b=!v&&d?this.computeSegHStyle(d):{left:0,right:0},y=Boolean(d)&&d.stackForward>0,x=Boolean(d)&&d.span.end-d.span.start<c;return r.createElement("div",{className:"fc-timegrid-event-harness"+(y?" fc-timegrid-event-harness-inset":""),key:l||m,style:Object.assign(Object.assign({visibility:f?"":"hidden"},h),b)},r.createElement(k,Object.assign({seg:a,isDragging:n,isResizing:o,isDateSelecting:s,isSelected:m===g,isShort:x},i.getSegMeta(a,u,p))))}))}renderHiddenGroups(e,t){let{extraDateSpan:n,dateProfile:o,todayRange:s,nowDate:l,eventSelection:a,eventDrag:c,eventResize:d}=this.props;return r.createElement(r.Fragment,null,e.map(e=>{let m=N(e.span),f=(h=e.entries,g=t,h.map(e=>g[e.index]));var h,g;return r.createElement(b,{key:i.buildIsoString(i.computeEarliestSegStart(f)),hiddenSegs:f,top:m.top,bottom:m.bottom,extraDateSpan:n,dateProfile:o,todayRange:s,nowDate:l,eventSelection:a,eventDrag:c,eventResize:d})}))}renderFillSegs(e,t){let{props:n,context:o}=this,s=D(e,n.date,n.slatCoords,o.options.eventMinHeight).map((o,s)=>{let l=e[s];return r.createElement("div",{key:i.buildEventRangeKey(l.eventRange),className:"fc-timegrid-bg-harness",style:N(o)},"bg-event"===t?r.createElement(i.BgEvent,Object.assign({seg:l},i.getSegMeta(l,n.todayRange,n.nowDate))):i.renderFill(t))});return r.createElement(r.Fragment,null,s)}renderNowIndicator(e){let{slatCoords:t,date:n}=this.props;return t?e.map((e,o)=>r.createElement(i.NowIndicatorContainer,{key:o,elClasses:["fc-timegrid-now-indicator-line"],elStyle:{top:t.computeDateTop(e.start,n)},isAxis:!1,date:n})):null}computeSegHStyle(e){let t,i,{isRtl:r,options:n}=this.context,o=n.slotEventOverlap,s=e.levelCoord,l=e.levelCoord+e.thickness;o&&(l=Math.min(1,s+2*(l-s))),r?(t=1-l,i=s):(t=s,i=1-l);let a={zIndex:e.stackDepth+1,left:100*t+"%",right:100*i+"%"};return o&&!e.stackForward&&(a[r?"marginLeft":"marginRight"]=20),a}}function T(e,{todayRange:t,nowDate:n,eventSelection:o,eventDrag:s,eventResize:l}){let a=(s?s.affectedInstances:null)||(l?l.affectedInstances:null)||{};return r.createElement(r.Fragment,null,e.map(e=>{let s=e.eventRange.instance.instanceId;return r.createElement("div",{key:s,style:{visibility:a[s]?"hidden":""}},r.createElement(k,Object.assign({seg:e,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:s===o,isShort:!1},i.getSegMeta(e,t,n))))}))}function N(e){return e?{top:e.start,bottom:-e.end}:{top:"",bottom:""}}class P extends i.BaseComponent{constructor(){super(...arguments),this.splitFgEventSegs=i.memoize(p),this.splitBgEventSegs=i.memoize(p),this.splitBusinessHourSegs=i.memoize(p),this.splitNowIndicatorSegs=i.memoize(p),this.splitDateSelectionSegs=i.memoize(p),this.splitEventDrag=i.memoize(v),this.splitEventResize=i.memoize(v),this.rootElRef=r.createRef(),this.cellElRefs=new i.RefMap}render(){let{props:e,context:t}=this,n=t.options.nowIndicator&&e.slatCoords&&e.slatCoords.safeComputeTop(e.nowDate),o=e.cells.length,s=this.splitFgEventSegs(e.fgEventSegs,o),l=this.splitBgEventSegs(e.bgEventSegs,o),a=this.splitBusinessHourSegs(e.businessHourSegs,o),c=this.splitNowIndicatorSegs(e.nowIndicatorSegs,o),d=this.splitDateSelectionSegs(e.dateSelectionSegs,o),m=this.splitEventDrag(e.eventDrag,o),f=this.splitEventResize(e.eventResize,o);return r.createElement("div",{className:"fc-timegrid-cols",ref:this.rootElRef},r.createElement("table",{role:"presentation",style:{minWidth:e.tableMinWidth,width:e.clientWidth}},e.tableColGroupNode,r.createElement("tbody",{role:"presentation"},r.createElement("tr",{role:"row"},e.axis&&r.createElement("td",{"aria-hidden":!0,className:"fc-timegrid-col fc-timegrid-axis"},r.createElement("div",{className:"fc-timegrid-col-frame"},r.createElement("div",{className:"fc-timegrid-now-indicator-container"},"number"==typeof n&&r.createElement(i.NowIndicatorContainer,{elClasses:["fc-timegrid-now-indicator-arrow"],elStyle:{top:n},isAxis:!0,date:e.nowDate})))),e.cells.map((t,i)=>r.createElement(M,{key:t.key,elRef:this.cellElRefs.createRef(t.key),dateProfile:e.dateProfile,date:t.date,nowDate:e.nowDate,todayRange:e.todayRange,extraRenderProps:t.extraRenderProps,extraDataAttrs:t.extraDataAttrs,extraClassNames:t.extraClassNames,extraDateSpan:t.extraDateSpan,fgEventSegs:s[i],bgEventSegs:l[i],businessHourSegs:a[i],nowIndicatorSegs:c[i],dateSelectionSegs:d[i],eventDrag:m[i],eventResize:f[i],slatCoords:e.slatCoords,eventSelection:e.eventSelection,forPrint:e.forPrint}))))))}componentDidMount(){this.updateCoords()}componentDidUpdate(){this.updateCoords()}updateCoords(){let{props:e}=this;var t;e.onColCoords&&null!==e.clientWidth&&e.onColCoords(new i.PositionCache(this.rootElRef.current,(t=this.cellElRefs.currentMap,e.cells.map(e=>t[e.key])),!0,!1))}}class z extends i.DateComponent{constructor(){super(...arguments),this.processSlotOptions=i.memoize(H),this.state={slatCoords:null},this.handleRootEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e,isHitComboAllowed:this.props.isHitComboAllowed}):this.context.unregisterInteractiveComponent(this)},this.handleScrollRequest=e=>{let{onScrollTopRequest:t}=this.props,{slatCoords:i}=this.state;if(t&&i){if(e.time){let r=i.computeTimeTop(e.time);r=Math.ceil(r),r&&(r+=1),t(r)}return!0}return!1},this.handleColCoords=e=>{this.colCoords=e},this.handleSlatCoords=e=>{this.setState({slatCoords:e}),this.props.onSlatCoords&&this.props.onSlatCoords(e)}}render(){let{props:e,state:t}=this;return r.createElement("div",{className:"fc-timegrid-body",ref:this.handleRootEl,style:{width:e.clientWidth,minWidth:e.tableMinWidth}},r.createElement(u,{axis:e.axis,dateProfile:e.dateProfile,slatMetas:e.slatMetas,clientWidth:e.clientWidth,minHeight:e.expandRows?e.clientHeight:"",tableMinWidth:e.tableMinWidth,tableColGroupNode:e.axis?e.tableColGroupNode:null,onCoords:this.handleSlatCoords}),r.createElement(P,{cells:e.cells,axis:e.axis,dateProfile:e.dateProfile,businessHourSegs:e.businessHourSegs,bgEventSegs:e.bgEventSegs,fgEventSegs:e.fgEventSegs,dateSelectionSegs:e.dateSelectionSegs,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,todayRange:e.todayRange,nowDate:e.nowDate,nowIndicatorSegs:e.nowIndicatorSegs,clientWidth:e.clientWidth,tableMinWidth:e.tableMinWidth,tableColGroupNode:e.tableColGroupNode,slatCoords:t.slatCoords,onColCoords:this.handleColCoords,forPrint:e.forPrint}))}componentDidMount(){this.scrollResponder=this.context.createScrollResponder(this.handleScrollRequest)}componentDidUpdate(e){this.scrollResponder.update(e.dateProfile!==this.props.dateProfile)}componentWillUnmount(){this.scrollResponder.detach()}queryHit(e,t){let{dateEnv:r,options:n}=this.context,{colCoords:o}=this,{dateProfile:s}=this.props,{slatCoords:l}=this.state,{snapDuration:a,snapsPerSlot:c}=this.processSlotOptions(this.props.slotDuration,n.snapDuration),d=o.leftToIndex(e),m=l.positions.topToIndex(t);if(null!=d&&null!=m){let e=this.props.cells[d],n=l.positions.tops[m],f=l.positions.getHeight(m),h=(t-n)/f,g=m*c+Math.floor(h*c),u=this.props.cells[d].date,p=i.addDurations(s.slotMinTime,i.multiplyDuration(a,g)),v=r.add(u,p),b=r.add(v,a);return{dateProfile:s,dateSpan:Object.assign({range:{start:v,end:b},allDay:!1},e.extraDateSpan),dayEl:o.els[d],rect:{left:o.lefts[d],right:o.rights[d],top:n,bottom:n+f},layer:0}}return null}}function H(e,t){let r=t||e,n=i.wholeDivideDurations(e,r);return null===n&&(r=e,n=1),{snapDuration:r,snapsPerSlot:n}}class W extends i.Slicer{sliceRange(e,t){let r=[];for(let n=0;n<t.length;n+=1){let o=i.intersectRanges(e,t[n]);o&&r.push({start:o.start,end:o.end,isStart:o.start.valueOf()===e.start.valueOf(),isEnd:o.end.valueOf()===e.end.valueOf(),col:n})}return r}}class G extends i.DateComponent{constructor(){super(...arguments),this.buildDayRanges=i.memoize(I),this.slicer=new W,this.timeColsRef=r.createRef()}render(){let{props:e,context:t}=this,{dateProfile:n,dayTableModel:o}=e,{nowIndicator:s,nextDayThreshold:l}=t.options,a=this.buildDayRanges(o,n,t.dateEnv);return r.createElement(i.NowTimer,{unit:s?"minute":"day"},(i,c)=>r.createElement(z,Object.assign({ref:this.timeColsRef},this.slicer.sliceProps(e,n,null,t,a),{forPrint:e.forPrint,axis:e.axis,dateProfile:n,slatMetas:e.slatMetas,slotDuration:e.slotDuration,cells:o.cells[0],tableColGroupNode:e.tableColGroupNode,tableMinWidth:e.tableMinWidth,clientWidth:e.clientWidth,clientHeight:e.clientHeight,expandRows:e.expandRows,nowDate:i,nowIndicatorSegs:s&&this.slicer.sliceNowDate(i,n,l,t,a),todayRange:c,onScrollTopRequest:e.onScrollTopRequest,onSlatCoords:e.onSlatCoords})))}}function I(e,t,i){let r=[];for(let n of e.headerDates)r.push({start:i.add(n,t.slotMinTime),end:i.add(n,t.slotMaxTime)});return r}const F=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];function O(e,t,r,n,o){let s=new Date(0),l=e,a=i.createDuration(0),c=r||function(e){let t,r,n;for(t=F.length-1;t>=0;t-=1)if(r=i.createDuration(F[t]),n=i.wholeDivideDurations(r,e),null!==n&&n>1)return r;return e}(n),d=[];for(;i.asRoughMs(l)<i.asRoughMs(t);){let e=o.add(s,l),t=null!==i.wholeDivideDurations(a,c);d.push({date:e,time:l,key:e.toISOString(),isoTimeStr:i.formatIsoTimeString(e),isLabeled:t}),l=i.addDurations(l,n),a=i.addDurations(a,n)}return d}class L extends m{constructor(){super(...arguments),this.buildTimeColsModel=i.memoize(A),this.buildSlatMetas=i.memoize(O)}render(){let{options:e,dateEnv:t,dateProfileGenerator:o}=this.context,{props:s}=this,{dateProfile:l}=s,a=this.buildTimeColsModel(l,o),c=this.allDaySplitter.splitProps(s),d=this.buildSlatMetas(l.slotMinTime,l.slotMaxTime,e.slotLabelInterval,e.slotDuration,t),{dayMinWidth:m}=e,f=!m,h=m,g=e.dayHeaders&&r.createElement(i.DayHeader,{dates:a.headerDates,dateProfile:l,datesRepDistinctDays:!0,renderIntro:f?this.renderHeadAxis:null}),u=!1!==e.allDaySlot&&(t=>r.createElement(n.DayTable,Object.assign({},c.allDay,{dateProfile:l,dayTableModel:a,nextDayThreshold:e.nextDayThreshold,tableMinWidth:t.tableMinWidth,colGroupNode:t.tableColGroupNode,renderRowIntro:f?this.renderTableRowAxis:null,showWeekNumbers:!1,expandRows:!1,headerAlignElRef:this.headerElRef,clientWidth:t.clientWidth,clientHeight:t.clientHeight,forPrint:s.forPrint},this.getAllDayMaxEventProps()))),p=t=>r.createElement(G,Object.assign({},c.timed,{dayTableModel:a,dateProfile:l,axis:f,slotDuration:e.slotDuration,slatMetas:d,forPrint:s.forPrint,tableColGroupNode:t.tableColGroupNode,tableMinWidth:t.tableMinWidth,clientWidth:t.clientWidth,clientHeight:t.clientHeight,onSlatCoords:this.handleSlatCoords,expandRows:t.expandRows,onScrollTopRequest:this.handleScrollTopRequest}));return h?this.renderHScrollLayout(g,u,p,a.colCnt,m,d,this.state.slatCoords):this.renderSimpleLayout(g,u,p)}}function A(e,t){let r=new i.DaySeriesModel(e.renderRange,t);return new i.DayTableModel(r,!1)}const j={allDaySlot:Boolean};i.injectStyles('.fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:"\\00a0"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:"\\00a0-\\00a0"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}');var B=t.createPlugin({name:"@fullcalendar/timegrid",initialView:"timeGridWeek",optionRefiners:j,views:{timeGrid:{component:L,usesMinMaxTime:!0,allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0},timeGridDay:{type:"timeGrid",duration:{days:1}},timeGridWeek:{type:"timeGrid",duration:{weeks:1}}}}),q={__proto__:null,TimeColsView:m,DayTimeColsView:L,buildTimeColsModel:A,DayTimeCols:G,buildDayRanges:I,DayTimeColsSlicer:W,TimeCols:z,buildSlatMetas:O,TimeColsSlatsCoords:h};return t.globalPlugins.push(B),e.Internal=q,e.default=B,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.Internal,FullCalendar.Preact,FullCalendar.DayGrid.Internal); \ No newline at end of file
diff --git a/public/js/fullcalendar/packages/web-component/index.global.js b/public/js/fullcalendar/packages/web-component/index.global.js
new file mode 100644
index 0000000..450b052
--- /dev/null
+++ b/public/js/fullcalendar/packages/web-component/index.global.js
@@ -0,0 +1,79 @@
1/*!
2FullCalendar Web Component v6.1.17
3Docs & License: https://fullcalendar.io/docs/web-component
4(c) 2024 Adam Shaw
5*/
6(function (core) {
7 'use strict';
8
9 class FullCalendarElement extends HTMLElement {
10 constructor() {
11 super(...arguments);
12 this._calendar = null;
13 this._options = null;
14 }
15 connectedCallback() {
16 this._handleOptionsStr(this.getAttribute('options'));
17 }
18 disconnectedCallback() {
19 this._handleOptionsStr(null);
20 }
21 attributeChangedCallback(name, oldVal, newVal) {
22 if (name === 'options' &&
23 this._calendar // initial render happened
24 ) {
25 this._handleOptionsStr(newVal);
26 }
27 }
28 get options() {
29 return this._options;
30 }
31 set options(options) {
32 this._handleOptions(options);
33 }
34 getApi() {
35 return this._calendar;
36 }
37 _handleOptionsStr(optionsStr) {
38 this._handleOptions(optionsStr ? JSON.parse(optionsStr) : null);
39 }
40 _handleOptions(options) {
41 if (options) {
42 if (this._calendar) {
43 this._calendar.resetOptions(options);
44 }
45 else {
46 let root;
47 if (this.hasAttribute('shadow')) {
48 this.attachShadow({ mode: 'open' });
49 root = this.shadowRoot;
50 }
51 else {
52 // eslint-disable-next-line @typescript-eslint/no-this-alias
53 root = this;
54 }
55 root.innerHTML = '<div></div>';
56 let calendarEl = root.querySelector('div');
57 let calendar = new core.Calendar(calendarEl, options);
58 calendar.render();
59 this._calendar = calendar;
60 }
61 this._options = options;
62 }
63 else {
64 if (this._calendar) {
65 this._calendar.destroy();
66 this._calendar = null;
67 }
68 this._options = null;
69 }
70 }
71 static get observedAttributes() {
72 return ['options'];
73 }
74 }
75
76 globalThis.FullCalendarElement = FullCalendarElement;
77 customElements.define('full-calendar', FullCalendarElement);
78
79})(FullCalendar);
diff --git a/public/js/fullcalendar/packages/web-component/index.global.min.js b/public/js/fullcalendar/packages/web-component/index.global.min.js
new file mode 100644
index 0000000..321e59b
--- /dev/null
+++ b/public/js/fullcalendar/packages/web-component/index.global.min.js
@@ -0,0 +1,6 @@
1/*!
2FullCalendar Web Component v6.1.17
3Docs & License: https://fullcalendar.io/docs/web-component
4(c) 2024 Adam Shaw
5*/
6!function(t){"use strict";class e extends HTMLElement{constructor(){super(...arguments),this._calendar=null,this._options=null}connectedCallback(){this._handleOptionsStr(this.getAttribute("options"))}disconnectedCallback(){this._handleOptionsStr(null)}attributeChangedCallback(t,e,n){"options"===t&&this._calendar&&this._handleOptionsStr(n)}get options(){return this._options}set options(t){this._handleOptions(t)}getApi(){return this._calendar}_handleOptionsStr(t){this._handleOptions(t?JSON.parse(t):null)}_handleOptions(e){if(e){if(this._calendar)this._calendar.resetOptions(e);else{let n;this.hasAttribute("shadow")?(this.attachShadow({mode:"open"}),n=this.shadowRoot):n=this,n.innerHTML="<div></div>";let s=n.querySelector("div"),i=new t.Calendar(s,e);i.render(),this._calendar=i}this._options=e}else this._calendar&&(this._calendar.destroy(),this._calendar=null),this._options=null}static get observedAttributes(){return["options"]}}globalThis.FullCalendarElement=e,customElements.define("full-calendar",e)}(FullCalendar); \ No newline at end of file