@fullcalendar/core 7.0.0-rc.0 → 7.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +3 -42
  3. package/index.d.ts +0 -46
  4. package/index.js +1 -2066
  5. package/package.json +13 -42
  6. package/protected-api.d.ts +28 -0
  7. package/protected-api.js +39 -0
  8. package/index.cjs +0 -2077
  9. package/index.global.js +0 -9657
  10. package/index.global.min.js +0 -6
  11. package/internal-common.cjs +0 -7600
  12. package/internal-common.d.ts +0 -2729
  13. package/internal-common.js +0 -7374
  14. package/internal.cjs +0 -183
  15. package/internal.d.ts +0 -4
  16. package/internal.js +0 -3
  17. package/locales/af.cjs +0 -26
  18. package/locales/af.d.ts +0 -6
  19. package/locales/af.global.js +0 -32
  20. package/locales/af.global.min.js +0 -6
  21. package/locales/af.js +0 -22
  22. package/locales/ar-dz.cjs +0 -28
  23. package/locales/ar-dz.d.ts +0 -6
  24. package/locales/ar-dz.global.js +0 -34
  25. package/locales/ar-dz.global.min.js +0 -6
  26. package/locales/ar-dz.js +0 -24
  27. package/locales/ar-kw.cjs +0 -28
  28. package/locales/ar-kw.d.ts +0 -6
  29. package/locales/ar-kw.global.js +0 -34
  30. package/locales/ar-kw.global.min.js +0 -6
  31. package/locales/ar-kw.js +0 -24
  32. package/locales/ar-ly.cjs +0 -28
  33. package/locales/ar-ly.d.ts +0 -6
  34. package/locales/ar-ly.global.js +0 -34
  35. package/locales/ar-ly.global.min.js +0 -6
  36. package/locales/ar-ly.js +0 -24
  37. package/locales/ar-ma.cjs +0 -28
  38. package/locales/ar-ma.d.ts +0 -6
  39. package/locales/ar-ma.global.js +0 -34
  40. package/locales/ar-ma.global.min.js +0 -6
  41. package/locales/ar-ma.js +0 -24
  42. package/locales/ar-sa.cjs +0 -28
  43. package/locales/ar-sa.d.ts +0 -6
  44. package/locales/ar-sa.global.js +0 -34
  45. package/locales/ar-sa.global.min.js +0 -6
  46. package/locales/ar-sa.js +0 -24
  47. package/locales/ar-tn.cjs +0 -28
  48. package/locales/ar-tn.d.ts +0 -6
  49. package/locales/ar-tn.global.js +0 -34
  50. package/locales/ar-tn.global.min.js +0 -6
  51. package/locales/ar-tn.js +0 -24
  52. package/locales/ar.cjs +0 -28
  53. package/locales/ar.d.ts +0 -6
  54. package/locales/ar.global.js +0 -34
  55. package/locales/ar.global.min.js +0 -6
  56. package/locales/ar.js +0 -24
  57. package/locales/az.cjs +0 -29
  58. package/locales/az.d.ts +0 -6
  59. package/locales/az.global.js +0 -35
  60. package/locales/az.global.min.js +0 -6
  61. package/locales/az.js +0 -25
  62. package/locales/bg.cjs +0 -28
  63. package/locales/bg.d.ts +0 -6
  64. package/locales/bg.global.js +0 -34
  65. package/locales/bg.global.min.js +0 -6
  66. package/locales/bg.js +0 -24
  67. package/locales/bn.cjs +0 -29
  68. package/locales/bn.d.ts +0 -6
  69. package/locales/bn.global.js +0 -35
  70. package/locales/bn.global.min.js +0 -6
  71. package/locales/bn.js +0 -25
  72. package/locales/bs.cjs +0 -29
  73. package/locales/bs.d.ts +0 -6
  74. package/locales/bs.global.js +0 -35
  75. package/locales/bs.global.min.js +0 -6
  76. package/locales/bs.js +0 -25
  77. package/locales/ca.cjs +0 -27
  78. package/locales/ca.d.ts +0 -6
  79. package/locales/ca.global.js +0 -33
  80. package/locales/ca.global.min.js +0 -6
  81. package/locales/ca.js +0 -23
  82. package/locales/cs.cjs +0 -29
  83. package/locales/cs.d.ts +0 -6
  84. package/locales/cs.global.js +0 -35
  85. package/locales/cs.global.min.js +0 -6
  86. package/locales/cs.js +0 -25
  87. package/locales/cy.cjs +0 -27
  88. package/locales/cy.d.ts +0 -6
  89. package/locales/cy.global.js +0 -33
  90. package/locales/cy.global.min.js +0 -6
  91. package/locales/cy.js +0 -23
  92. package/locales/da.cjs +0 -27
  93. package/locales/da.d.ts +0 -6
  94. package/locales/da.global.js +0 -33
  95. package/locales/da.global.min.js +0 -6
  96. package/locales/da.js +0 -23
  97. package/locales/de-at.cjs +0 -62
  98. package/locales/de-at.d.ts +0 -6
  99. package/locales/de-at.global.js +0 -68
  100. package/locales/de-at.global.min.js +0 -6
  101. package/locales/de-at.js +0 -58
  102. package/locales/de.cjs +0 -62
  103. package/locales/de.d.ts +0 -6
  104. package/locales/de.global.js +0 -68
  105. package/locales/de.global.min.js +0 -6
  106. package/locales/de.js +0 -58
  107. package/locales/el.cjs +0 -27
  108. package/locales/el.d.ts +0 -6
  109. package/locales/el.global.js +0 -33
  110. package/locales/el.global.min.js +0 -6
  111. package/locales/el.js +0 -23
  112. package/locales/en-au.cjs +0 -23
  113. package/locales/en-au.d.ts +0 -6
  114. package/locales/en-au.global.js +0 -29
  115. package/locales/en-au.global.min.js +0 -6
  116. package/locales/en-au.js +0 -19
  117. package/locales/en-gb.cjs +0 -23
  118. package/locales/en-gb.d.ts +0 -6
  119. package/locales/en-gb.global.js +0 -29
  120. package/locales/en-gb.global.min.js +0 -6
  121. package/locales/en-gb.js +0 -19
  122. package/locales/en-nz.cjs +0 -23
  123. package/locales/en-nz.d.ts +0 -6
  124. package/locales/en-nz.global.js +0 -29
  125. package/locales/en-nz.global.min.js +0 -6
  126. package/locales/en-nz.js +0 -19
  127. package/locales/eo.cjs +0 -27
  128. package/locales/eo.d.ts +0 -6
  129. package/locales/eo.global.js +0 -33
  130. package/locales/eo.global.min.js +0 -6
  131. package/locales/eo.js +0 -23
  132. package/locales/es-us.cjs +0 -27
  133. package/locales/es-us.d.ts +0 -6
  134. package/locales/es-us.global.js +0 -33
  135. package/locales/es-us.global.min.js +0 -6
  136. package/locales/es-us.js +0 -23
  137. package/locales/es.cjs +0 -45
  138. package/locales/es.d.ts +0 -6
  139. package/locales/es.global.js +0 -51
  140. package/locales/es.global.min.js +0 -6
  141. package/locales/es.js +0 -41
  142. package/locales/et.cjs +0 -29
  143. package/locales/et.d.ts +0 -6
  144. package/locales/et.global.js +0 -35
  145. package/locales/et.global.min.js +0 -6
  146. package/locales/et.js +0 -25
  147. package/locales/eu.cjs +0 -27
  148. package/locales/eu.d.ts +0 -6
  149. package/locales/eu.global.js +0 -33
  150. package/locales/eu.global.min.js +0 -6
  151. package/locales/eu.js +0 -23
  152. package/locales/fa.cjs +0 -30
  153. package/locales/fa.d.ts +0 -6
  154. package/locales/fa.global.js +0 -36
  155. package/locales/fa.global.min.js +0 -6
  156. package/locales/fa.js +0 -26
  157. package/locales/fi.cjs +0 -27
  158. package/locales/fi.d.ts +0 -6
  159. package/locales/fi.global.js +0 -33
  160. package/locales/fi.global.min.js +0 -6
  161. package/locales/fi.js +0 -23
  162. package/locales/fr-ca.cjs +0 -23
  163. package/locales/fr-ca.d.ts +0 -6
  164. package/locales/fr-ca.global.js +0 -29
  165. package/locales/fr-ca.global.min.js +0 -6
  166. package/locales/fr-ca.js +0 -19
  167. package/locales/fr-ch.cjs +0 -27
  168. package/locales/fr-ch.d.ts +0 -6
  169. package/locales/fr-ch.global.js +0 -33
  170. package/locales/fr-ch.global.min.js +0 -6
  171. package/locales/fr-ch.js +0 -23
  172. package/locales/fr.cjs +0 -28
  173. package/locales/fr.d.ts +0 -6
  174. package/locales/fr.global.js +0 -34
  175. package/locales/fr.global.min.js +0 -6
  176. package/locales/fr.js +0 -24
  177. package/locales/gl.cjs +0 -45
  178. package/locales/gl.d.ts +0 -6
  179. package/locales/gl.global.js +0 -51
  180. package/locales/gl.global.min.js +0 -6
  181. package/locales/gl.js +0 -41
  182. package/locales/he.cjs +0 -24
  183. package/locales/he.d.ts +0 -6
  184. package/locales/he.global.js +0 -30
  185. package/locales/he.global.min.js +0 -6
  186. package/locales/he.js +0 -20
  187. package/locales/hi.cjs +0 -29
  188. package/locales/hi.d.ts +0 -6
  189. package/locales/hi.global.js +0 -35
  190. package/locales/hi.global.min.js +0 -6
  191. package/locales/hi.js +0 -25
  192. package/locales/hr.cjs +0 -29
  193. package/locales/hr.d.ts +0 -6
  194. package/locales/hr.global.js +0 -35
  195. package/locales/hr.global.min.js +0 -6
  196. package/locales/hr.js +0 -25
  197. package/locales/hu.cjs +0 -27
  198. package/locales/hu.d.ts +0 -6
  199. package/locales/hu.global.js +0 -33
  200. package/locales/hu.global.min.js +0 -6
  201. package/locales/hu.js +0 -23
  202. package/locales/hy-am.cjs +0 -29
  203. package/locales/hy-am.d.ts +0 -6
  204. package/locales/hy-am.global.js +0 -35
  205. package/locales/hy-am.global.min.js +0 -6
  206. package/locales/hy-am.js +0 -25
  207. package/locales/id.cjs +0 -27
  208. package/locales/id.d.ts +0 -6
  209. package/locales/id.global.js +0 -33
  210. package/locales/id.global.min.js +0 -6
  211. package/locales/id.js +0 -23
  212. package/locales/is.cjs +0 -27
  213. package/locales/is.d.ts +0 -6
  214. package/locales/is.global.js +0 -33
  215. package/locales/is.global.min.js +0 -6
  216. package/locales/is.js +0 -23
  217. package/locales/it.cjs +0 -29
  218. package/locales/it.d.ts +0 -6
  219. package/locales/it.global.js +0 -35
  220. package/locales/it.global.min.js +0 -6
  221. package/locales/it.js +0 -25
  222. package/locales/ja.cjs +0 -25
  223. package/locales/ja.d.ts +0 -6
  224. package/locales/ja.global.js +0 -31
  225. package/locales/ja.global.min.js +0 -6
  226. package/locales/ja.js +0 -21
  227. package/locales/ka.cjs +0 -29
  228. package/locales/ka.d.ts +0 -6
  229. package/locales/ka.global.js +0 -35
  230. package/locales/ka.global.min.js +0 -6
  231. package/locales/ka.js +0 -25
  232. package/locales/kk.cjs +0 -29
  233. package/locales/kk.d.ts +0 -6
  234. package/locales/kk.global.js +0 -35
  235. package/locales/kk.global.min.js +0 -6
  236. package/locales/kk.js +0 -25
  237. package/locales/km.cjs +0 -27
  238. package/locales/km.d.ts +0 -6
  239. package/locales/km.global.js +0 -33
  240. package/locales/km.global.min.js +0 -6
  241. package/locales/km.js +0 -23
  242. package/locales/ko.cjs +0 -23
  243. package/locales/ko.d.ts +0 -6
  244. package/locales/ko.global.js +0 -29
  245. package/locales/ko.global.min.js +0 -6
  246. package/locales/ko.js +0 -19
  247. package/locales/ku.cjs +0 -28
  248. package/locales/ku.d.ts +0 -6
  249. package/locales/ku.global.js +0 -34
  250. package/locales/ku.global.min.js +0 -6
  251. package/locales/ku.js +0 -24
  252. package/locales/lb.cjs +0 -27
  253. package/locales/lb.d.ts +0 -6
  254. package/locales/lb.global.js +0 -33
  255. package/locales/lb.global.min.js +0 -6
  256. package/locales/lb.js +0 -23
  257. package/locales/lt.cjs +0 -27
  258. package/locales/lt.d.ts +0 -6
  259. package/locales/lt.global.js +0 -33
  260. package/locales/lt.global.min.js +0 -6
  261. package/locales/lt.js +0 -23
  262. package/locales/lv.cjs +0 -29
  263. package/locales/lv.d.ts +0 -6
  264. package/locales/lv.global.js +0 -35
  265. package/locales/lv.global.min.js +0 -6
  266. package/locales/lv.js +0 -25
  267. package/locales/mk.cjs +0 -25
  268. package/locales/mk.d.ts +0 -6
  269. package/locales/mk.global.js +0 -31
  270. package/locales/mk.global.min.js +0 -6
  271. package/locales/mk.js +0 -21
  272. package/locales/ms.cjs +0 -29
  273. package/locales/ms.d.ts +0 -6
  274. package/locales/ms.global.js +0 -35
  275. package/locales/ms.global.min.js +0 -6
  276. package/locales/ms.js +0 -25
  277. package/locales/nb.cjs +0 -38
  278. package/locales/nb.d.ts +0 -6
  279. package/locales/nb.global.js +0 -44
  280. package/locales/nb.global.min.js +0 -6
  281. package/locales/nb.js +0 -34
  282. package/locales/ne.cjs +0 -27
  283. package/locales/ne.d.ts +0 -6
  284. package/locales/ne.global.js +0 -33
  285. package/locales/ne.global.min.js +0 -6
  286. package/locales/ne.js +0 -23
  287. package/locales/nl.cjs +0 -26
  288. package/locales/nl.d.ts +0 -6
  289. package/locales/nl.global.js +0 -32
  290. package/locales/nl.global.min.js +0 -6
  291. package/locales/nl.js +0 -22
  292. package/locales/nn.cjs +0 -27
  293. package/locales/nn.d.ts +0 -6
  294. package/locales/nn.global.js +0 -33
  295. package/locales/nn.global.min.js +0 -6
  296. package/locales/nn.js +0 -23
  297. package/locales/pl.cjs +0 -27
  298. package/locales/pl.d.ts +0 -6
  299. package/locales/pl.global.js +0 -33
  300. package/locales/pl.global.min.js +0 -6
  301. package/locales/pl.js +0 -23
  302. package/locales/pt-br.cjs +0 -45
  303. package/locales/pt-br.d.ts +0 -6
  304. package/locales/pt-br.global.js +0 -51
  305. package/locales/pt-br.global.min.js +0 -6
  306. package/locales/pt-br.js +0 -41
  307. package/locales/pt.cjs +0 -27
  308. package/locales/pt.d.ts +0 -6
  309. package/locales/pt.global.js +0 -33
  310. package/locales/pt.global.min.js +0 -6
  311. package/locales/pt.js +0 -23
  312. package/locales/ro.cjs +0 -29
  313. package/locales/ro.d.ts +0 -6
  314. package/locales/ro.global.js +0 -35
  315. package/locales/ro.global.min.js +0 -6
  316. package/locales/ro.js +0 -25
  317. package/locales/ru.cjs +0 -29
  318. package/locales/ru.d.ts +0 -6
  319. package/locales/ru.global.js +0 -35
  320. package/locales/ru.global.min.js +0 -6
  321. package/locales/ru.js +0 -25
  322. package/locales/si-lk.cjs +0 -27
  323. package/locales/si-lk.d.ts +0 -6
  324. package/locales/si-lk.global.js +0 -33
  325. package/locales/si-lk.global.min.js +0 -6
  326. package/locales/si-lk.js +0 -23
  327. package/locales/sk.cjs +0 -29
  328. package/locales/sk.d.ts +0 -6
  329. package/locales/sk.global.js +0 -35
  330. package/locales/sk.global.min.js +0 -6
  331. package/locales/sk.js +0 -25
  332. package/locales/sl.cjs +0 -27
  333. package/locales/sl.d.ts +0 -6
  334. package/locales/sl.global.js +0 -33
  335. package/locales/sl.global.min.js +0 -6
  336. package/locales/sl.js +0 -23
  337. package/locales/sm.cjs +0 -23
  338. package/locales/sm.d.ts +0 -6
  339. package/locales/sm.global.js +0 -29
  340. package/locales/sm.global.min.js +0 -6
  341. package/locales/sm.js +0 -19
  342. package/locales/sq.cjs +0 -29
  343. package/locales/sq.d.ts +0 -6
  344. package/locales/sq.global.js +0 -35
  345. package/locales/sq.global.min.js +0 -6
  346. package/locales/sq.js +0 -25
  347. package/locales/sr-cyrl.cjs +0 -29
  348. package/locales/sr-cyrl.d.ts +0 -6
  349. package/locales/sr-cyrl.global.js +0 -35
  350. package/locales/sr-cyrl.global.min.js +0 -6
  351. package/locales/sr-cyrl.js +0 -25
  352. package/locales/sr.cjs +0 -29
  353. package/locales/sr.d.ts +0 -6
  354. package/locales/sr.global.js +0 -35
  355. package/locales/sr.global.min.js +0 -6
  356. package/locales/sr.js +0 -25
  357. package/locales/sv.cjs +0 -46
  358. package/locales/sv.d.ts +0 -6
  359. package/locales/sv.global.js +0 -52
  360. package/locales/sv.global.min.js +0 -6
  361. package/locales/sv.js +0 -42
  362. package/locales/ta-in.cjs +0 -29
  363. package/locales/ta-in.d.ts +0 -6
  364. package/locales/ta-in.global.js +0 -35
  365. package/locales/ta-in.global.min.js +0 -6
  366. package/locales/ta-in.js +0 -25
  367. package/locales/th.cjs +0 -29
  368. package/locales/th.d.ts +0 -6
  369. package/locales/th.global.js +0 -35
  370. package/locales/th.global.min.js +0 -6
  371. package/locales/th.js +0 -25
  372. package/locales/tr.cjs +0 -27
  373. package/locales/tr.d.ts +0 -6
  374. package/locales/tr.global.js +0 -33
  375. package/locales/tr.global.min.js +0 -6
  376. package/locales/tr.js +0 -23
  377. package/locales/ug.cjs +0 -20
  378. package/locales/ug.d.ts +0 -6
  379. package/locales/ug.global.js +0 -26
  380. package/locales/ug.global.min.js +0 -6
  381. package/locales/ug.js +0 -16
  382. package/locales/uk.cjs +0 -29
  383. package/locales/uk.d.ts +0 -6
  384. package/locales/uk.global.js +0 -35
  385. package/locales/uk.global.min.js +0 -6
  386. package/locales/uk.js +0 -25
  387. package/locales/uz-cy.cjs +0 -28
  388. package/locales/uz-cy.d.ts +0 -6
  389. package/locales/uz-cy.global.js +0 -34
  390. package/locales/uz-cy.global.min.js +0 -6
  391. package/locales/uz-cy.js +0 -24
  392. package/locales/uz.cjs +0 -28
  393. package/locales/uz.d.ts +0 -6
  394. package/locales/uz.global.js +0 -34
  395. package/locales/uz.global.min.js +0 -6
  396. package/locales/uz.js +0 -24
  397. package/locales/vi.cjs +0 -29
  398. package/locales/vi.d.ts +0 -6
  399. package/locales/vi.global.js +0 -35
  400. package/locales/vi.global.min.js +0 -6
  401. package/locales/vi.js +0 -25
  402. package/locales/zh-cn.cjs +0 -30
  403. package/locales/zh-cn.d.ts +0 -6
  404. package/locales/zh-cn.global.js +0 -36
  405. package/locales/zh-cn.global.min.js +0 -6
  406. package/locales/zh-cn.js +0 -26
  407. package/locales/zh-tw.cjs +0 -23
  408. package/locales/zh-tw.d.ts +0 -6
  409. package/locales/zh-tw.global.js +0 -29
  410. package/locales/zh-tw.global.min.js +0 -6
  411. package/locales/zh-tw.js +0 -19
  412. package/locales-all.cjs +0 -89
  413. package/locales-all.d.ts +0 -6
  414. package/locales-all.global.js +0 -1927
  415. package/locales-all.global.min.js +0 -6
  416. package/locales-all.js +0 -85
  417. package/preact.cjs +0 -24
  418. package/preact.d.ts +0 -16
  419. package/preact.js +0 -3
package/index.js CHANGED
@@ -1,2066 +1 @@
1
- import { m as mergeProps, g as guid, i as isArraysEqual, T as Theme, a as mapHash, B as BaseComponent, V as ViewContextType, C as ContentContainer, b as buildViewClassName, c as greatestDurationDenominator, d as createDuration, e as BASE_OPTION_DEFAULTS, f as arrayToHash, h as filterHash, j as buildEventSourceRefiners, p as parseEventSource, k as formatWithOrdinals, u as unpromisify, l as buildRangeApiWithTimeZone, n as identity, r as requestJson, s as subtractDurations, o as intersectRanges, q as startOfDay, t as addDays, v as hashValuesToArray, w as buildEventApis, D as DelayedRunner, x as createFormatter, y as diffWholeDays, z as memoize, A as memoizeObjArg, E as isPropsEqual, F as Emitter, G as getInitialDate, H as rangeContainsMarker, I as createEmptyEventStore, J as reduceCurrentDate, K as reduceEventStore, L as rezoneEventStoreDates, M as mergeRawOptions, N as BASE_OPTION_REFINERS, O as CALENDAR_LISTENER_REFINERS, P as CALENDAR_OPTION_REFINERS, Q as COMPLEX_OPTION_COMPARATORS, R as VIEW_OPTION_REFINERS, S as DateEnv, U as DateProfileGenerator, W as createEventUi, X as parseBusinessHours, Y as joinClassNames, Z as Interaction, _ as getElEventRange, $ as EventImpl, a0 as listenBySelector, a1 as listenToHoverBySelector, a2 as PureComponent, a3 as buildViewContext, a4 as getUniqueDomId, a5 as parseInteractionSettings, a6 as interactionSettingsStore, a7 as getNow, a8 as getIsHeightAuto, a9 as CalendarImpl, aa as flushSync, ab as CalendarRoot, ac as RenderId, ad as ensureElHasStyles, ae as applyStyleProp, af as sliceEventStore } from './internal-common.js';
2
- export { ag as JsonRequestError } from './internal-common.js';
3
- import { createElement, Component, Fragment, render } from 'preact';
4
- import 'preact/compat';
5
-
6
- const globalLocales = [];
7
-
8
- const MINIMAL_RAW_EN_LOCALE = {
9
- code: 'en',
10
- week: {
11
- dow: 0,
12
- doy: 4, // 4 days need to be within the year to be considered the first week
13
- },
14
- direction: 'ltr',
15
- buttonText: {
16
- prev: 'prev',
17
- next: 'next',
18
- prevYear: 'prev year',
19
- nextYear: 'next year',
20
- year: 'year',
21
- today: 'today',
22
- month: 'month',
23
- week: 'week',
24
- day: 'day',
25
- list: 'list',
26
- },
27
- weekText: 'W',
28
- weekTextLong: 'Week',
29
- closeHint: 'Close',
30
- eventsHint: 'Events',
31
- allDayText: 'all-day',
32
- timedText: 'timed',
33
- moreLinkText: 'more',
34
- noEventsText: 'No events to display',
35
- };
36
- const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
37
- // Includes things we don't want other locales to inherit,
38
- // things that derive from other translatable strings.
39
- buttonHints: {
40
- prev: 'Previous $0',
41
- next: 'Next $0',
42
- today(buttonText, unit) {
43
- return (unit === 'day')
44
- ? 'Today'
45
- : `This ${buttonText}`;
46
- },
47
- }, viewHint: '$0 view', viewChangeHint: 'Change view', navLinkHint: 'Go to $0', moreLinkHint(eventCnt) {
48
- return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
49
- } });
50
- function organizeRawLocales(explicitRawLocales) {
51
- let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
52
- let allRawLocales = globalLocales.concat(explicitRawLocales);
53
- let rawLocaleMap = {
54
- en: RAW_EN_LOCALE,
55
- };
56
- for (let rawLocale of allRawLocales) {
57
- rawLocaleMap[rawLocale.code] = rawLocale;
58
- }
59
- return {
60
- map: rawLocaleMap,
61
- defaultCode,
62
- };
63
- }
64
- function buildLocale(inputSingular, available) {
65
- if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
66
- return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
67
- }
68
- return queryLocale(inputSingular, available);
69
- }
70
- function queryLocale(codeArg, available) {
71
- let codes = [].concat(codeArg || []); // will convert to array
72
- let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
73
- return parseLocale(codeArg, codes, raw);
74
- }
75
- function queryRawLocale(codes, available) {
76
- for (let i = 0; i < codes.length; i += 1) {
77
- let parts = codes[i].toLocaleLowerCase().split('-');
78
- for (let j = parts.length; j > 0; j -= 1) {
79
- let simpleId = parts.slice(0, j).join('-');
80
- if (available[simpleId]) {
81
- return available[simpleId];
82
- }
83
- }
84
- }
85
- return null;
86
- }
87
- function parseLocale(codeArg, codes, raw) {
88
- let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
89
- delete merged.code; // don't want this part of the options
90
- let { week } = merged;
91
- delete merged.week;
92
- return {
93
- codeArg,
94
- codes,
95
- week,
96
- simpleNumberFormat: new Intl.NumberFormat(codeArg),
97
- options: merged,
98
- };
99
- }
100
-
101
- // TODO: easier way to add new hooks? need to update a million things
102
- function createPlugin(input) {
103
- return {
104
- id: guid(),
105
- name: input.name,
106
- premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
107
- deps: input.deps || [],
108
- reducers: input.reducers || [],
109
- isLoadingFuncs: input.isLoadingFuncs || [],
110
- contextInit: [].concat(input.contextInit || []),
111
- eventRefiners: input.eventRefiners || {},
112
- eventDefMemberAdders: input.eventDefMemberAdders || [],
113
- eventSourceRefiners: input.eventSourceRefiners || {},
114
- isDraggableTransformers: input.isDraggableTransformers || [],
115
- eventDragMutationMassagers: input.eventDragMutationMassagers || [],
116
- eventDefMutationAppliers: input.eventDefMutationAppliers || [],
117
- dateSelectionTransformers: input.dateSelectionTransformers || [],
118
- datePointTransforms: input.datePointTransforms || [],
119
- dateSpanTransforms: input.dateSpanTransforms || [],
120
- views: input.views || {},
121
- viewPropsTransformers: input.viewPropsTransformers || [],
122
- isPropsValid: input.isPropsValid || null,
123
- externalDefTransforms: input.externalDefTransforms || [],
124
- viewContainerAppends: input.viewContainerAppends || [],
125
- eventDropTransformers: input.eventDropTransformers || [],
126
- componentInteractions: input.componentInteractions || [],
127
- calendarInteractions: input.calendarInteractions || [],
128
- themeClasses: input.themeClasses || {},
129
- eventSourceDefs: input.eventSourceDefs || [],
130
- cmdFormatter: input.cmdFormatter,
131
- recurringTypes: input.recurringTypes || [],
132
- namedTimeZonedImpl: input.namedTimeZonedImpl,
133
- initialView: input.initialView || '',
134
- elementDraggingImpl: input.elementDraggingImpl,
135
- optionChangeHandlers: input.optionChangeHandlers || {},
136
- scrollerSyncerClass: input.scrollerSyncerClass || null,
137
- listenerRefiners: input.listenerRefiners || {},
138
- optionRefiners: input.optionRefiners || {},
139
- propSetHandlers: input.propSetHandlers || {},
140
- };
141
- }
142
- function buildPluginHooks(pluginDefs, globalDefs) {
143
- let currentPluginIds = {};
144
- let hooks = {
145
- premiumReleaseDate: undefined,
146
- reducers: [],
147
- isLoadingFuncs: [],
148
- contextInit: [],
149
- eventRefiners: {},
150
- eventDefMemberAdders: [],
151
- eventSourceRefiners: {},
152
- isDraggableTransformers: [],
153
- eventDragMutationMassagers: [],
154
- eventDefMutationAppliers: [],
155
- dateSelectionTransformers: [],
156
- datePointTransforms: [],
157
- dateSpanTransforms: [],
158
- views: {},
159
- viewPropsTransformers: [],
160
- isPropsValid: null,
161
- externalDefTransforms: [],
162
- viewContainerAppends: [],
163
- eventDropTransformers: [],
164
- componentInteractions: [],
165
- calendarInteractions: [],
166
- themeClasses: {},
167
- eventSourceDefs: [],
168
- cmdFormatter: null,
169
- recurringTypes: [],
170
- namedTimeZonedImpl: null,
171
- initialView: '',
172
- elementDraggingImpl: null,
173
- optionChangeHandlers: {},
174
- scrollerSyncerClass: null,
175
- listenerRefiners: {},
176
- optionRefiners: {},
177
- propSetHandlers: {},
178
- };
179
- function addDefs(defs) {
180
- for (let def of defs) {
181
- const pluginName = def.name;
182
- const currentId = currentPluginIds[pluginName];
183
- if (currentId === undefined) {
184
- currentPluginIds[pluginName] = def.id;
185
- addDefs(def.deps);
186
- hooks = combineHooks(hooks, def);
187
- }
188
- else if (currentId !== def.id) {
189
- // different ID than the one already added
190
- console.warn(`Duplicate plugin '${pluginName}'`);
191
- }
192
- }
193
- }
194
- if (pluginDefs) {
195
- addDefs(pluginDefs);
196
- }
197
- addDefs(globalDefs);
198
- return hooks;
199
- }
200
- function buildBuildPluginHooks() {
201
- let currentOverrideDefs = [];
202
- let currentGlobalDefs = [];
203
- let currentHooks;
204
- return (overrideDefs, globalDefs) => {
205
- if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
206
- currentHooks = buildPluginHooks(overrideDefs, globalDefs);
207
- }
208
- currentOverrideDefs = overrideDefs;
209
- currentGlobalDefs = globalDefs;
210
- return currentHooks;
211
- };
212
- }
213
- function combineHooks(hooks0, hooks1) {
214
- return {
215
- premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
216
- reducers: hooks0.reducers.concat(hooks1.reducers),
217
- isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
218
- contextInit: hooks0.contextInit.concat(hooks1.contextInit),
219
- eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
220
- eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
221
- eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
222
- isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
223
- eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
224
- eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
225
- dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
226
- datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
227
- dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
228
- views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
229
- viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
230
- isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
231
- externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
232
- viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
233
- eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
234
- calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
235
- componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
236
- themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
237
- eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
238
- cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
239
- recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
240
- namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
241
- initialView: hooks0.initialView || hooks1.initialView,
242
- elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
243
- optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
244
- scrollerSyncerClass: hooks0.scrollerSyncerClass || hooks1.scrollerSyncerClass,
245
- listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
246
- optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
247
- propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
248
- };
249
- }
250
- function compareOptionalDates(date0, date1) {
251
- if (date0 === undefined) {
252
- return date1;
253
- }
254
- if (date1 === undefined) {
255
- return date0;
256
- }
257
- return new Date(Math.max(date0.valueOf(), date1.valueOf()));
258
- }
259
-
260
- class StandardTheme extends Theme {
261
- }
262
- StandardTheme.prototype.classes = {
263
- root: 'fc-theme-standard',
264
- buttonGroup: 'fc-button-group',
265
- button: 'fc-button fc-button-primary',
266
- buttonActive: 'fc-button-active',
267
- };
268
- StandardTheme.prototype.baseIconClass = 'fc-icon';
269
- StandardTheme.prototype.iconClasses = {
270
- close: 'fc-icon-x',
271
- prev: 'fc-icon-chevron-left',
272
- next: 'fc-icon-chevron-right',
273
- prevYear: 'fc-icon-chevrons-left',
274
- nextYear: 'fc-icon-chevrons-right',
275
- };
276
- StandardTheme.prototype.rtlIconClasses = {
277
- prev: 'fc-icon-chevron-right',
278
- next: 'fc-icon-chevron-left',
279
- prevYear: 'fc-icon-chevrons-right',
280
- nextYear: 'fc-icon-chevrons-left',
281
- };
282
- StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
283
- StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
284
- StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';
285
-
286
- function compileViewDefs(defaultConfigs, overrideConfigs) {
287
- let hash = {};
288
- let viewType;
289
- for (viewType in defaultConfigs) {
290
- ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
291
- }
292
- for (viewType in overrideConfigs) {
293
- ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
294
- }
295
- return hash;
296
- }
297
- function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
298
- if (hash[viewType]) {
299
- return hash[viewType];
300
- }
301
- let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
302
- if (viewDef) {
303
- hash[viewType] = viewDef;
304
- }
305
- return viewDef;
306
- }
307
- function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
308
- let defaultConfig = defaultConfigs[viewType];
309
- let overrideConfig = overrideConfigs[viewType];
310
- let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
311
- ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
312
- let theComponent = queryProp('component');
313
- let superType = queryProp('superType');
314
- let superDef = null;
315
- if (superType) {
316
- if (superType === viewType) {
317
- throw new Error('Can\'t have a custom view type that references itself');
318
- }
319
- superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
320
- }
321
- if (!theComponent && superDef) {
322
- theComponent = superDef.component;
323
- }
324
- if (!theComponent) {
325
- return null; // don't throw a warning, might be settings for a single-unit view
326
- }
327
- return {
328
- type: viewType,
329
- component: theComponent,
330
- defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
331
- overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
332
- };
333
- }
334
-
335
- function parseViewConfigs(inputs) {
336
- return mapHash(inputs, parseViewConfig);
337
- }
338
- function parseViewConfig(input) {
339
- let rawOptions = typeof input === 'function' ?
340
- { component: input } :
341
- input;
342
- let { component } = rawOptions;
343
- if (rawOptions.content) {
344
- // TODO: remove content/classNames/didMount/etc from options?
345
- component = createViewHookComponent(rawOptions);
346
- }
347
- else if (component && !(component.prototype instanceof BaseComponent)) {
348
- // WHY?: people were using `component` property for `content`
349
- // TODO: converge on one setting name
350
- component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), { content: component }));
351
- }
352
- return {
353
- superType: rawOptions.type,
354
- component: component,
355
- rawOptions, // includes type and component too :(
356
- };
357
- }
358
- function createViewHookComponent(options) {
359
- return (viewProps) => (createElement(ViewContextType.Consumer, null, (context) => (createElement(ContentContainer, { tag: "div", className: buildViewClassName(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 }))));
360
- }
361
-
362
- function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
363
- let defaultConfigs = parseViewConfigs(defaultInputs);
364
- let overrideConfigs = parseViewConfigs(optionOverrides.views);
365
- let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
366
- return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
367
- }
368
- function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
369
- let durationInput = viewDef.overrides.duration ||
370
- viewDef.defaults.duration ||
371
- dynamicOptionOverrides.duration ||
372
- optionOverrides.duration;
373
- let duration = null;
374
- let durationUnit = '';
375
- let singleUnit = '';
376
- let singleUnitOverrides = {};
377
- if (durationInput) {
378
- duration = createDurationCached(durationInput);
379
- if (duration) { // valid?
380
- let denom = greatestDurationDenominator(duration);
381
- durationUnit = denom.unit;
382
- if (denom.value === 1) {
383
- singleUnit = durationUnit;
384
- singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
385
- }
386
- }
387
- }
388
- let queryButtonText = (optionsSubset) => {
389
- let buttonTextMap = optionsSubset.buttonText || {};
390
- let buttonTextKey = viewDef.defaults.buttonTextKey;
391
- if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
392
- return buttonTextMap[buttonTextKey];
393
- }
394
- if (buttonTextMap[viewDef.type] != null) {
395
- return buttonTextMap[viewDef.type];
396
- }
397
- if (buttonTextMap[singleUnit] != null) {
398
- return buttonTextMap[singleUnit];
399
- }
400
- return null;
401
- };
402
- let queryButtonTitle = (optionsSubset) => {
403
- let buttonHints = optionsSubset.buttonHints || {};
404
- let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
405
- if (buttonKey != null && buttonHints[buttonKey] != null) {
406
- return buttonHints[buttonKey];
407
- }
408
- if (buttonHints[viewDef.type] != null) {
409
- return buttonHints[viewDef.type];
410
- }
411
- if (buttonHints[singleUnit] != null) {
412
- return buttonHints[singleUnit];
413
- }
414
- return null;
415
- };
416
- return {
417
- type: viewDef.type,
418
- component: viewDef.component,
419
- duration,
420
- durationUnit,
421
- singleUnit,
422
- optionDefaults: viewDef.defaults,
423
- optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
424
- buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
425
- queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
426
- viewDef.overrides.buttonText,
427
- buttonTextDefault: queryButtonText(localeDefaults) ||
428
- viewDef.defaults.buttonText ||
429
- queryButtonText(BASE_OPTION_DEFAULTS) ||
430
- viewDef.type,
431
- // not DRY
432
- buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
433
- queryButtonTitle(optionOverrides) ||
434
- viewDef.overrides.buttonHint,
435
- buttonTitleDefault: queryButtonTitle(localeDefaults) ||
436
- viewDef.defaults.buttonHint ||
437
- queryButtonTitle(BASE_OPTION_DEFAULTS),
438
- // will eventually fall back to buttonText
439
- };
440
- }
441
- // hack to get memoization working
442
- let durationInputMap = {};
443
- function createDurationCached(durationInput) {
444
- let json = JSON.stringify(durationInput);
445
- let res = durationInputMap[json];
446
- if (res === undefined) {
447
- res = createDuration(durationInput);
448
- durationInputMap[json] = res;
449
- }
450
- return res;
451
- }
452
-
453
- function reduceViewType(viewType, action) {
454
- switch (action.type) {
455
- case 'CHANGE_VIEW_TYPE':
456
- viewType = action.viewType;
457
- }
458
- return viewType;
459
- }
460
-
461
- function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
462
- switch (action.type) {
463
- case 'SET_OPTION':
464
- return Object.assign(Object.assign({}, dynamicOptionOverrides), { [action.optionName]: action.rawOptionValue });
465
- default:
466
- return dynamicOptionOverrides;
467
- }
468
- }
469
-
470
- function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
471
- let dp;
472
- switch (action.type) {
473
- case 'CHANGE_VIEW_TYPE':
474
- return dateProfileGenerator.build(action.dateMarker || currentDate);
475
- case 'CHANGE_DATE':
476
- return dateProfileGenerator.build(action.dateMarker);
477
- case 'PREV':
478
- dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
479
- if (dp.isValid) {
480
- return dp;
481
- }
482
- break;
483
- case 'NEXT':
484
- dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
485
- if (dp.isValid) {
486
- return dp;
487
- }
488
- break;
489
- }
490
- return currentDateProfile;
491
- }
492
-
493
- function initEventSources(calendarOptions, dateProfile, context) {
494
- let activeRange = dateProfile ? dateProfile.activeRange : null;
495
- return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
496
- }
497
- function reduceEventSources(eventSources, action, dateProfile, context) {
498
- let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
499
- switch (action.type) {
500
- case 'ADD_EVENT_SOURCES': // already parsed
501
- return addSources(eventSources, action.sources, activeRange, context);
502
- case 'REMOVE_EVENT_SOURCE':
503
- return removeSource(eventSources, action.sourceId);
504
- case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
505
- case 'NEXT':
506
- case 'CHANGE_DATE':
507
- case 'CHANGE_VIEW_TYPE':
508
- if (dateProfile) {
509
- return fetchDirtySources(eventSources, activeRange, context);
510
- }
511
- return eventSources;
512
- case 'FETCH_EVENT_SOURCES':
513
- return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
514
- arrayToHash(action.sourceIds) :
515
- excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
516
- case 'RECEIVE_EVENTS':
517
- case 'RECEIVE_EVENT_ERROR':
518
- return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
519
- case 'REMOVE_ALL_EVENT_SOURCES':
520
- return {};
521
- default:
522
- return eventSources;
523
- }
524
- }
525
- function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
526
- let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
527
- return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
528
- }
529
- function computeEventSourcesLoading(eventSources) {
530
- for (let sourceId in eventSources) {
531
- if (eventSources[sourceId].isFetching) {
532
- return true;
533
- }
534
- }
535
- return false;
536
- }
537
- function addSources(eventSourceHash, sources, fetchRange, context) {
538
- let hash = {};
539
- for (let source of sources) {
540
- hash[source.sourceId] = source;
541
- }
542
- if (fetchRange) {
543
- hash = fetchDirtySources(hash, fetchRange, context);
544
- }
545
- return Object.assign(Object.assign({}, eventSourceHash), hash);
546
- }
547
- function removeSource(eventSourceHash, sourceId) {
548
- return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
549
- }
550
- function fetchDirtySources(sourceHash, fetchRange, context) {
551
- return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
552
- }
553
- function isSourceDirty(eventSource, fetchRange, context) {
554
- if (!doesSourceNeedRange(eventSource, context)) {
555
- return !eventSource.latestFetchId;
556
- }
557
- return !context.options.lazyFetching ||
558
- !eventSource.fetchRange ||
559
- eventSource.isFetching || // always cancel outdated in-progress fetches
560
- fetchRange.start < eventSource.fetchRange.start ||
561
- fetchRange.end > eventSource.fetchRange.end;
562
- }
563
- function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
564
- let nextSources = {};
565
- for (let sourceId in prevSources) {
566
- let source = prevSources[sourceId];
567
- if (sourceIdHash[sourceId]) {
568
- nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
569
- }
570
- else {
571
- nextSources[sourceId] = source;
572
- }
573
- }
574
- return nextSources;
575
- }
576
- function fetchSource(eventSource, fetchRange, isRefetch, context) {
577
- let { options, calendarApi } = context;
578
- let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
579
- let fetchId = guid();
580
- sourceDef.fetch({
581
- eventSource,
582
- range: fetchRange,
583
- isRefetch,
584
- context,
585
- }, (res) => {
586
- let { rawEvents } = res;
587
- if (options.eventSourceSuccess) {
588
- rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
589
- }
590
- if (eventSource.success) {
591
- rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
592
- }
593
- context.dispatch({
594
- type: 'RECEIVE_EVENTS',
595
- sourceId: eventSource.sourceId,
596
- fetchId,
597
- fetchRange,
598
- rawEvents,
599
- });
600
- }, (error) => {
601
- let errorHandled = false;
602
- if (options.eventSourceFailure) {
603
- options.eventSourceFailure.call(calendarApi, error);
604
- errorHandled = true;
605
- }
606
- if (eventSource.failure) {
607
- eventSource.failure(error);
608
- errorHandled = true;
609
- }
610
- if (!errorHandled) {
611
- console.warn(error.message, error);
612
- }
613
- context.dispatch({
614
- type: 'RECEIVE_EVENT_ERROR',
615
- sourceId: eventSource.sourceId,
616
- fetchId,
617
- fetchRange,
618
- error,
619
- });
620
- });
621
- return Object.assign(Object.assign({}, eventSource), { isFetching: true, latestFetchId: fetchId });
622
- }
623
- function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
624
- let eventSource = sourceHash[sourceId];
625
- if (eventSource && // not already removed
626
- fetchId === eventSource.latestFetchId) {
627
- return Object.assign(Object.assign({}, sourceHash), { [sourceId]: Object.assign(Object.assign({}, eventSource), { isFetching: false, fetchRange }) });
628
- }
629
- return sourceHash;
630
- }
631
- function excludeStaticSources(eventSources, context) {
632
- return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
633
- }
634
- function parseInitialSources(rawOptions, context) {
635
- let refiners = buildEventSourceRefiners(context);
636
- let rawSources = [].concat(rawOptions.eventSources || []);
637
- let sources = []; // parsed
638
- if (rawOptions.initialEvents) {
639
- rawSources.unshift(rawOptions.initialEvents);
640
- }
641
- if (rawOptions.events) {
642
- rawSources.unshift(rawOptions.events);
643
- }
644
- for (let rawSource of rawSources) {
645
- let source = parseEventSource(rawSource, context, refiners);
646
- if (source) {
647
- sources.push(source);
648
- }
649
- }
650
- return sources;
651
- }
652
- function doesSourceNeedRange(eventSource, context) {
653
- let defs = context.pluginHooks.eventSourceDefs;
654
- return !defs[eventSource.sourceDefId].ignoreRange;
655
- }
656
-
657
- function reduceDateSelection(currentSelection, action) {
658
- switch (action.type) {
659
- case 'UNSELECT_DATES':
660
- return null;
661
- case 'SELECT_DATES':
662
- return action.selection;
663
- default:
664
- return currentSelection;
665
- }
666
- }
667
-
668
- function reduceSelectedEvent(currentInstanceId, action) {
669
- switch (action.type) {
670
- case 'UNSELECT_EVENT':
671
- return '';
672
- case 'SELECT_EVENT':
673
- return action.eventInstanceId;
674
- default:
675
- return currentInstanceId;
676
- }
677
- }
678
-
679
- function reduceEventDrag(currentDrag, action) {
680
- let newDrag;
681
- switch (action.type) {
682
- case 'UNSET_EVENT_DRAG':
683
- return null;
684
- case 'SET_EVENT_DRAG':
685
- newDrag = action.state;
686
- return {
687
- affectedEvents: newDrag.affectedEvents,
688
- mutatedEvents: newDrag.mutatedEvents,
689
- isEvent: newDrag.isEvent,
690
- };
691
- default:
692
- return currentDrag;
693
- }
694
- }
695
-
696
- function reduceEventResize(currentResize, action) {
697
- let newResize;
698
- switch (action.type) {
699
- case 'UNSET_EVENT_RESIZE':
700
- return null;
701
- case 'SET_EVENT_RESIZE':
702
- newResize = action.state;
703
- return {
704
- affectedEvents: newResize.affectedEvents,
705
- mutatedEvents: newResize.mutatedEvents,
706
- isEvent: newResize.isEvent,
707
- };
708
- default:
709
- return currentResize;
710
- }
711
- }
712
-
713
- function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
714
- let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
715
- let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
716
- return { header, footer };
717
- }
718
- function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
719
- let isRtl = calendarOptions.direction === 'rtl';
720
- let viewsWithButtons = [];
721
- let hasTitle = false;
722
- function processSectionStr(sectionStr) {
723
- let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
724
- viewsWithButtons.push(...sectionRes.viewsWithButtons);
725
- hasTitle = hasTitle || sectionRes.hasTitle;
726
- return sectionRes.widgets;
727
- }
728
- const sectionWidgets = {
729
- start: processSectionStr(sectionStrHash[isRtl ? 'right' : 'left'] || sectionStrHash.start || ''),
730
- center: processSectionStr(sectionStrHash.center || ''),
731
- end: processSectionStr(sectionStrHash[isRtl ? 'left' : 'right'] || sectionStrHash.end || ''),
732
- };
733
- return {
734
- sectionWidgets,
735
- viewsWithButtons,
736
- hasTitle,
737
- };
738
- }
739
- /*
740
- BAD: querying icons and text here. should be done at render time
741
- */
742
- function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
743
- calendarOptionOverrides, // overrides only!, unrefined :(
744
- theme, viewSpecs, calendarApi) {
745
- let isRtl = calendarOptions.direction === 'rtl';
746
- let calendarCustomButtons = calendarOptions.customButtons || {};
747
- let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
748
- let calendarButtonText = calendarOptions.buttonText || {};
749
- let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
750
- let calendarButtonHints = calendarOptions.buttonHints || {};
751
- let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
752
- let viewsWithButtons = [];
753
- let hasTitle = false;
754
- let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
755
- if (buttonName === 'title') {
756
- hasTitle = true;
757
- return { buttonName };
758
- }
759
- let customButtonProps;
760
- let viewSpec;
761
- let buttonClick;
762
- let buttonIcon; // only one of these will be set
763
- let buttonText; // "
764
- let buttonHint;
765
- let isView = false;
766
- // ^ for the title="" attribute, for accessibility
767
- if ((customButtonProps = calendarCustomButtons[buttonName])) {
768
- buttonClick = (ev) => {
769
- if (customButtonProps.click) {
770
- customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
771
- }
772
- };
773
- (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
774
- (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
775
- (buttonText = customButtonProps.text);
776
- buttonHint = customButtonProps.hint || customButtonProps.text;
777
- }
778
- else if ((viewSpec = viewSpecs[buttonName])) {
779
- isView = true;
780
- viewsWithButtons.push(buttonName);
781
- buttonClick = () => {
782
- calendarApi.changeView(buttonName);
783
- };
784
- (buttonText = viewSpec.buttonTextOverride) ||
785
- (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
786
- (buttonText = viewSpec.buttonTextDefault);
787
- let textFallback = viewSpec.buttonTextOverride ||
788
- viewSpec.buttonTextDefault;
789
- buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
790
- viewSpec.buttonTitleDefault ||
791
- calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
792
- textFallback);
793
- }
794
- else if (calendarApi[buttonName]) { // a calendarApi method
795
- buttonClick = () => {
796
- calendarApi[buttonName]();
797
- };
798
- (buttonText = calendarButtonTextOverrides[buttonName]) ||
799
- (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
800
- (buttonText = calendarButtonText[buttonName]); // everything else is considered default
801
- if (buttonName === 'prevYear' || buttonName === 'nextYear') {
802
- let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
803
- buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
804
- calendarButtonHints[prevOrNext], [
805
- calendarButtonText.year || 'year',
806
- 'year',
807
- ], calendarButtonText[buttonName]);
808
- }
809
- else {
810
- buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
811
- calendarButtonHints[buttonName], [
812
- calendarButtonText[navUnit] || navUnit,
813
- navUnit,
814
- ], calendarButtonText[buttonName]);
815
- }
816
- }
817
- return { buttonName, buttonClick, buttonIcon, buttonText, buttonHint, isView };
818
- })));
819
- return { widgets, viewsWithButtons, hasTitle };
820
- }
821
-
822
- // always represents the current view. otherwise, it'd need to change value every time date changes
823
- class ViewImpl {
824
- constructor(type, getCurrentData, dateEnv) {
825
- this.type = type;
826
- this.getCurrentData = getCurrentData;
827
- this.dateEnv = dateEnv;
828
- }
829
- get calendar() {
830
- return this.getCurrentData().calendarApi;
831
- }
832
- get title() {
833
- return this.getCurrentData().viewTitle;
834
- }
835
- get activeStart() {
836
- return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
837
- }
838
- get activeEnd() {
839
- return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
840
- }
841
- get currentStart() {
842
- return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
843
- }
844
- get currentEnd() {
845
- return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
846
- }
847
- getOption(name) {
848
- return this.getCurrentData().options[name]; // are the view-specific options
849
- }
850
- }
851
-
852
- let eventSourceDef$2 = {
853
- ignoreRange: true,
854
- parseMeta(refined) {
855
- if (Array.isArray(refined.events)) {
856
- return refined.events;
857
- }
858
- return null;
859
- },
860
- fetch(arg, successCallback) {
861
- successCallback({
862
- rawEvents: arg.eventSource.meta,
863
- });
864
- },
865
- };
866
- const arrayEventSourcePlugin = createPlugin({
867
- name: 'array-event-source',
868
- eventSourceDefs: [eventSourceDef$2],
869
- });
870
-
871
- let eventSourceDef$1 = {
872
- parseMeta(refined) {
873
- if (typeof refined.events === 'function') {
874
- return refined.events;
875
- }
876
- return null;
877
- },
878
- fetch(arg, successCallback, errorCallback) {
879
- const { dateEnv } = arg.context;
880
- const func = arg.eventSource.meta;
881
- unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({ rawEvents }), errorCallback);
882
- },
883
- };
884
- const funcEventSourcePlugin = createPlugin({
885
- name: 'func-event-source',
886
- eventSourceDefs: [eventSourceDef$1],
887
- });
888
-
889
- const JSON_FEED_EVENT_SOURCE_REFINERS = {
890
- method: String,
891
- extraParams: identity,
892
- startParam: String,
893
- endParam: String,
894
- timeZoneParam: String,
895
- };
896
-
897
- let eventSourceDef = {
898
- parseMeta(refined) {
899
- if (refined.url && (refined.format === 'json' || !refined.format)) {
900
- return {
901
- url: refined.url,
902
- format: 'json',
903
- method: (refined.method || 'GET').toUpperCase(),
904
- extraParams: refined.extraParams,
905
- startParam: refined.startParam,
906
- endParam: refined.endParam,
907
- timeZoneParam: refined.timeZoneParam,
908
- };
909
- }
910
- return null;
911
- },
912
- fetch(arg, successCallback, errorCallback) {
913
- const { meta } = arg.eventSource;
914
- const requestParams = buildRequestParams(meta, arg.range, arg.context);
915
- requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
916
- successCallback({ rawEvents, response });
917
- }, errorCallback);
918
- },
919
- };
920
- const jsonFeedEventSourcePlugin = createPlugin({
921
- name: 'json-event-source',
922
- eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
923
- eventSourceDefs: [eventSourceDef],
924
- });
925
- function buildRequestParams(meta, range, context) {
926
- let { dateEnv, options } = context;
927
- let startParam;
928
- let endParam;
929
- let timeZoneParam;
930
- let customRequestParams;
931
- let params = {};
932
- startParam = meta.startParam;
933
- if (startParam == null) {
934
- startParam = options.startParam;
935
- }
936
- endParam = meta.endParam;
937
- if (endParam == null) {
938
- endParam = options.endParam;
939
- }
940
- timeZoneParam = meta.timeZoneParam;
941
- if (timeZoneParam == null) {
942
- timeZoneParam = options.timeZoneParam;
943
- }
944
- // retrieve any outbound GET/POST data from the options
945
- if (typeof meta.extraParams === 'function') {
946
- // supplied as a function that returns a key/value object
947
- customRequestParams = meta.extraParams();
948
- }
949
- else {
950
- // probably supplied as a straight key/value object
951
- customRequestParams = meta.extraParams || {};
952
- }
953
- Object.assign(params, customRequestParams);
954
- params[startParam] = dateEnv.formatIso(range.start);
955
- params[endParam] = dateEnv.formatIso(range.end);
956
- if (dateEnv.timeZone !== 'local') {
957
- params[timeZoneParam] = dateEnv.timeZone;
958
- }
959
- return params;
960
- }
961
-
962
- const SIMPLE_RECURRING_REFINERS = {
963
- daysOfWeek: identity,
964
- startTime: createDuration,
965
- endTime: createDuration,
966
- duration: createDuration,
967
- startRecur: identity,
968
- endRecur: identity,
969
- };
970
-
971
- let recurring = {
972
- parse(refined, dateEnv) {
973
- if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
974
- let recurringData = {
975
- daysOfWeek: refined.daysOfWeek || null,
976
- startTime: refined.startTime || null,
977
- endTime: refined.endTime || null,
978
- startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
979
- endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
980
- };
981
- let duration;
982
- if (refined.duration) {
983
- duration = refined.duration;
984
- }
985
- if (!duration && refined.startTime && refined.endTime) {
986
- duration = subtractDurations(refined.endTime, refined.startTime);
987
- }
988
- return {
989
- allDayGuess: Boolean(!refined.startTime && !refined.endTime),
990
- duration,
991
- typeData: recurringData, // doesn't need endTime anymore but oh well
992
- };
993
- }
994
- return null;
995
- },
996
- expand(typeData, framingRange, dateEnv) {
997
- let clippedFramingRange = intersectRanges(framingRange, { start: typeData.startRecur, end: typeData.endRecur });
998
- if (clippedFramingRange) {
999
- return expandRanges(typeData.daysOfWeek, typeData.startTime, clippedFramingRange, dateEnv);
1000
- }
1001
- return [];
1002
- },
1003
- };
1004
- const simpleRecurringEventsPlugin = createPlugin({
1005
- name: 'simple-recurring-event',
1006
- recurringTypes: [recurring],
1007
- eventRefiners: SIMPLE_RECURRING_REFINERS,
1008
- });
1009
- function expandRanges(daysOfWeek, startTime, framingRange, dateEnv) {
1010
- let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
1011
- let dayMarker = startOfDay(framingRange.start);
1012
- let endMarker = framingRange.end;
1013
- let instanceStarts = [];
1014
- while (dayMarker < endMarker) {
1015
- let instanceStart;
1016
- // if everyday, or this particular day-of-week
1017
- if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
1018
- if (startTime) {
1019
- instanceStart = dateEnv.add(dayMarker, startTime);
1020
- }
1021
- else {
1022
- instanceStart = dayMarker;
1023
- }
1024
- instanceStarts.push(instanceStart);
1025
- }
1026
- dayMarker = addDays(dayMarker, 1);
1027
- }
1028
- return instanceStarts;
1029
- }
1030
-
1031
- const changeHandlerPlugin = createPlugin({
1032
- name: 'change-handler',
1033
- optionChangeHandlers: {
1034
- events(events, context) {
1035
- handleEventSources([events], context);
1036
- },
1037
- eventSources: handleEventSources,
1038
- },
1039
- });
1040
- /*
1041
- BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
1042
- */
1043
- function handleEventSources(inputs, context) {
1044
- let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
1045
- if (unfoundSources.length === 1 &&
1046
- inputs.length === 1 &&
1047
- Array.isArray(unfoundSources[0]._raw) &&
1048
- Array.isArray(inputs[0])) {
1049
- context.dispatch({
1050
- type: 'RESET_RAW_EVENTS',
1051
- sourceId: unfoundSources[0].sourceId,
1052
- rawEvents: inputs[0],
1053
- });
1054
- return;
1055
- }
1056
- let newInputs = [];
1057
- for (let input of inputs) {
1058
- let inputFound = false;
1059
- for (let i = 0; i < unfoundSources.length; i += 1) {
1060
- if (unfoundSources[i]._raw === input) {
1061
- unfoundSources.splice(i, 1); // delete
1062
- inputFound = true;
1063
- break;
1064
- }
1065
- }
1066
- if (!inputFound) {
1067
- newInputs.push(input);
1068
- }
1069
- }
1070
- for (let unfoundSource of unfoundSources) {
1071
- context.dispatch({
1072
- type: 'REMOVE_EVENT_SOURCE',
1073
- sourceId: unfoundSource.sourceId,
1074
- });
1075
- }
1076
- for (let newInput of newInputs) {
1077
- context.calendarApi.addEventSource(newInput);
1078
- }
1079
- }
1080
-
1081
- function handleDateProfile(dateProfile, context) {
1082
- context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), { view: context.viewApi }));
1083
- }
1084
-
1085
- function handleEventStore(eventStore, context) {
1086
- let { emitter } = context;
1087
- if (emitter.hasHandlers('eventsSet')) {
1088
- emitter.trigger('eventsSet', buildEventApis(eventStore, context));
1089
- }
1090
- }
1091
-
1092
- /*
1093
- this array is exposed on the root namespace so that UMD plugins can add to it.
1094
- see the rollup-bundles script.
1095
- */
1096
- const globalPlugins = [
1097
- arrayEventSourcePlugin,
1098
- funcEventSourcePlugin,
1099
- jsonFeedEventSourcePlugin,
1100
- simpleRecurringEventsPlugin,
1101
- changeHandlerPlugin,
1102
- createPlugin({
1103
- name: 'misc',
1104
- isLoadingFuncs: [
1105
- (state) => computeEventSourcesLoading(state.eventSources),
1106
- ],
1107
- propSetHandlers: {
1108
- dateProfile: handleDateProfile,
1109
- eventStore: handleEventStore,
1110
- },
1111
- }),
1112
- ];
1113
-
1114
- class TaskRunner {
1115
- constructor(runTaskOption, drainedOption) {
1116
- this.runTaskOption = runTaskOption;
1117
- this.drainedOption = drainedOption;
1118
- this.queue = [];
1119
- this.delayedRunner = new DelayedRunner(this.drain.bind(this));
1120
- }
1121
- request(task, delay) {
1122
- this.queue.push(task);
1123
- this.delayedRunner.request(delay);
1124
- }
1125
- pause(scope) {
1126
- this.delayedRunner.pause(scope);
1127
- }
1128
- resume(scope, force) {
1129
- this.delayedRunner.resume(scope, force);
1130
- }
1131
- drain() {
1132
- let { queue } = this;
1133
- while (queue.length) {
1134
- let completedTasks = [];
1135
- let task;
1136
- while ((task = queue.shift())) {
1137
- this.runTask(task);
1138
- completedTasks.push(task);
1139
- }
1140
- this.drained(completedTasks);
1141
- } // keep going, in case new tasks were added in the drained handler
1142
- }
1143
- runTask(task) {
1144
- if (this.runTaskOption) {
1145
- this.runTaskOption(task);
1146
- }
1147
- }
1148
- drained(completedTasks) {
1149
- if (this.drainedOption) {
1150
- this.drainedOption(completedTasks);
1151
- }
1152
- }
1153
- }
1154
-
1155
- // Computes what the title at the top of the calendarApi should be for this view
1156
- function buildTitle(dateProfile, viewOptions, dateEnv) {
1157
- let range;
1158
- // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
1159
- if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
1160
- range = dateProfile.currentRange;
1161
- }
1162
- else { // for day units or smaller, use the actual day range
1163
- range = dateProfile.activeRange;
1164
- }
1165
- return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
1166
- isEndExclusive: dateProfile.isRangeAllDay,
1167
- defaultSeparator: viewOptions.titleRangeSeparator,
1168
- });
1169
- }
1170
- // Generates the format string that should be used to generate the title for the current date range.
1171
- // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
1172
- function buildTitleFormat(dateProfile) {
1173
- let { currentRangeUnit } = dateProfile;
1174
- if (currentRangeUnit === 'year') {
1175
- return { year: 'numeric' };
1176
- }
1177
- if (currentRangeUnit === 'month') {
1178
- return { year: 'numeric', month: 'long' }; // like "September 2014"
1179
- }
1180
- let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
1181
- if (days !== null && days > 1) {
1182
- // multi-day range. shorter, like "Sep 9 - 10 2014"
1183
- return { year: 'numeric', month: 'short', day: 'numeric' };
1184
- }
1185
- // one day. longer, like "September 9 2014"
1186
- return { year: 'numeric', month: 'long', day: 'numeric' };
1187
- }
1188
-
1189
- // in future refactor, do the redux-style function(state=initial) for initial-state
1190
- // also, whatever is happening in constructor, have it happen in action queue too
1191
- class CalendarDataManager {
1192
- constructor(props) {
1193
- this.computeCurrentViewData = memoize(this._computeCurrentViewData);
1194
- this.organizeRawLocales = memoize(organizeRawLocales);
1195
- this.buildLocale = memoize(buildLocale);
1196
- this.buildPluginHooks = buildBuildPluginHooks();
1197
- this.buildDateEnv = memoize(buildDateEnv$1);
1198
- this.buildTheme = memoize(buildTheme);
1199
- this.parseToolbars = memoize(parseToolbars);
1200
- this.buildViewSpecs = memoize(buildViewSpecs);
1201
- this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
1202
- this.buildViewApi = memoize(buildViewApi);
1203
- this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
1204
- this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
1205
- this.buildEventUiBases = memoize(buildEventUiBases);
1206
- this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
1207
- this.buildTitle = memoize(buildTitle);
1208
- this.emitter = new Emitter();
1209
- this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
1210
- this.currentCalendarOptionsInput = {};
1211
- this.currentCalendarOptionsRefined = {};
1212
- this.currentViewOptionsInput = {};
1213
- this.currentViewOptionsRefined = {};
1214
- this.currentCalendarOptionsRefiners = {};
1215
- this.optionsForRefining = [];
1216
- this.optionsForHandling = [];
1217
- this.getCurrentData = () => this.data;
1218
- this.dispatch = (action) => {
1219
- this.actionRunner.request(action); // protects against recursive calls to _handleAction
1220
- };
1221
- this.props = props;
1222
- this.actionRunner.pause();
1223
- let dynamicOptionOverrides = {};
1224
- let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
1225
- let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
1226
- let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
1227
- // wire things up
1228
- // TODO: not DRY
1229
- props.calendarApi.currentDataManager = this;
1230
- this.emitter.setThisContext(props.calendarApi);
1231
- this.emitter.setOptions(currentViewData.options);
1232
- let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv);
1233
- let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
1234
- if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
1235
- currentDate = dateProfile.currentRange.start;
1236
- }
1237
- let calendarContext = {
1238
- dateEnv: optionsData.dateEnv,
1239
- options: optionsData.calendarOptions,
1240
- pluginHooks: optionsData.pluginHooks,
1241
- calendarApi: props.calendarApi,
1242
- dispatch: this.dispatch,
1243
- emitter: this.emitter,
1244
- getCurrentData: this.getCurrentData,
1245
- };
1246
- // needs to be after setThisContext
1247
- for (let callback of optionsData.pluginHooks.contextInit) {
1248
- callback(calendarContext);
1249
- }
1250
- // NOT DRY
1251
- let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
1252
- let initialState = {
1253
- dynamicOptionOverrides,
1254
- currentViewType,
1255
- currentDate,
1256
- dateProfile,
1257
- businessHours: this.parseContextBusinessHours(calendarContext),
1258
- eventSources,
1259
- eventUiBases: {},
1260
- eventStore: createEmptyEventStore(),
1261
- renderableEventStore: createEmptyEventStore(),
1262
- dateSelection: null,
1263
- eventSelection: '',
1264
- eventDrag: null,
1265
- eventResize: null,
1266
- selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
1267
- };
1268
- let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
1269
- for (let reducer of optionsData.pluginHooks.reducers) {
1270
- Object.assign(initialState, reducer(null, null, contextAndState));
1271
- }
1272
- if (computeIsLoading(initialState, calendarContext)) {
1273
- this.emitter.trigger('loading', true); // NOT DRY
1274
- }
1275
- this.state = initialState;
1276
- this.updateData();
1277
- this.actionRunner.resume();
1278
- }
1279
- resetOptions(optionOverrides, changedOptionNames) {
1280
- let { props } = this;
1281
- if (changedOptionNames === undefined) {
1282
- props.optionOverrides = optionOverrides;
1283
- }
1284
- else {
1285
- props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);
1286
- this.optionsForRefining.push(...changedOptionNames);
1287
- }
1288
- if (changedOptionNames === undefined || changedOptionNames.length) {
1289
- this.actionRunner.request({
1290
- type: 'NOTHING',
1291
- });
1292
- }
1293
- }
1294
- _handleAction(action) {
1295
- let { props, state, emitter } = this;
1296
- let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
1297
- let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
1298
- let currentViewType = reduceViewType(state.currentViewType, action);
1299
- let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
1300
- // wire things up
1301
- // TODO: not DRY
1302
- props.calendarApi.currentDataManager = this;
1303
- emitter.setThisContext(props.calendarApi);
1304
- emitter.setOptions(currentViewData.options);
1305
- let calendarContext = {
1306
- dateEnv: optionsData.dateEnv,
1307
- options: optionsData.calendarOptions,
1308
- pluginHooks: optionsData.pluginHooks,
1309
- calendarApi: props.calendarApi,
1310
- dispatch: this.dispatch,
1311
- emitter,
1312
- getCurrentData: this.getCurrentData,
1313
- };
1314
- let { currentDate, dateProfile } = state;
1315
- if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
1316
- dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
1317
- }
1318
- currentDate = reduceCurrentDate(currentDate, action);
1319
- dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
1320
- if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
1321
- action.type === 'NEXT' || // "
1322
- !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
1323
- currentDate = dateProfile.currentRange.start;
1324
- }
1325
- let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
1326
- let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
1327
- let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
1328
- let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
1329
- (state.renderableEventStore || eventStore) : // try from previous state
1330
- eventStore;
1331
- let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext); // will memoize obj
1332
- let eventUiBySource = this.buildEventUiBySource(eventSources);
1333
- let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
1334
- let newState = {
1335
- dynamicOptionOverrides,
1336
- currentViewType,
1337
- currentDate,
1338
- dateProfile,
1339
- eventSources,
1340
- eventStore,
1341
- renderableEventStore,
1342
- selectionConfig,
1343
- eventUiBases,
1344
- businessHours: this.parseContextBusinessHours(calendarContext),
1345
- dateSelection: reduceDateSelection(state.dateSelection, action),
1346
- eventSelection: reduceSelectedEvent(state.eventSelection, action),
1347
- eventDrag: reduceEventDrag(state.eventDrag, action),
1348
- eventResize: reduceEventResize(state.eventResize, action),
1349
- };
1350
- let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
1351
- for (let reducer of optionsData.pluginHooks.reducers) {
1352
- Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
1353
- }
1354
- let wasLoading = computeIsLoading(state, calendarContext);
1355
- let isLoading = computeIsLoading(newState, calendarContext);
1356
- // TODO: use propSetHandlers in plugin system
1357
- if (!wasLoading && isLoading) {
1358
- emitter.trigger('loading', true);
1359
- }
1360
- else if (wasLoading && !isLoading) {
1361
- emitter.trigger('loading', false);
1362
- }
1363
- this.state = newState;
1364
- if (props.onAction) {
1365
- props.onAction(action);
1366
- }
1367
- }
1368
- updateData() {
1369
- let { props, state } = this;
1370
- let oldData = this.data;
1371
- let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
1372
- let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
1373
- let data = this.data = Object.assign(Object.assign(Object.assign({ viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv), calendarApi: props.calendarApi, dispatch: this.dispatch, emitter: this.emitter, getCurrentData: this.getCurrentData }, optionsData), currentViewData), state);
1374
- let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
1375
- let oldCalendarOptions = oldData && oldData.calendarOptions;
1376
- let newCalendarOptions = optionsData.calendarOptions;
1377
- if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
1378
- if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
1379
- // hack
1380
- state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
1381
- state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
1382
- state.renderableEventStore = data.renderableEventStore = rezoneEventStoreDates(data.renderableEventStore, oldData.dateEnv, data.dateEnv);
1383
- }
1384
- for (let optionName in changeHandlers) {
1385
- if (this.optionsForHandling.indexOf(optionName) !== -1 ||
1386
- oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
1387
- changeHandlers[optionName](newCalendarOptions[optionName], data);
1388
- }
1389
- }
1390
- }
1391
- this.optionsForHandling = [];
1392
- if (props.onData) {
1393
- props.onData(data);
1394
- }
1395
- }
1396
- computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
1397
- // TODO: blacklist options that are handled by optionChangeHandlers
1398
- if (!this.optionsForRefining.length &&
1399
- optionOverrides === this.stableOptionOverrides &&
1400
- dynamicOptionOverrides === this.stableDynamicOptionOverrides) {
1401
- return this.stableCalendarOptionsData;
1402
- }
1403
- let { refinedOptions, pluginHooks, localeDefaults, availableLocaleData, extra, } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
1404
- warnUnknownOptions(extra);
1405
- let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
1406
- let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);
1407
- let theme = this.buildTheme(refinedOptions, pluginHooks);
1408
- let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);
1409
- return this.stableCalendarOptionsData = {
1410
- calendarOptions: refinedOptions,
1411
- pluginHooks,
1412
- dateEnv,
1413
- viewSpecs,
1414
- theme,
1415
- toolbarConfig,
1416
- localeDefaults,
1417
- availableRawLocales: availableLocaleData.map,
1418
- };
1419
- }
1420
- // always called from behind a memoizer
1421
- processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
1422
- let { locales, locale } = mergeRawOptions([
1423
- BASE_OPTION_DEFAULTS,
1424
- optionOverrides,
1425
- dynamicOptionOverrides,
1426
- ]);
1427
- let availableLocaleData = this.organizeRawLocales(locales);
1428
- let availableRawLocales = availableLocaleData.map;
1429
- let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
1430
- let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
1431
- 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);
1432
- let extra = {};
1433
- let raw = mergeRawOptions([
1434
- BASE_OPTION_DEFAULTS,
1435
- localeDefaults,
1436
- optionOverrides,
1437
- dynamicOptionOverrides,
1438
- ]);
1439
- let refined = {};
1440
- let currentRaw = this.currentCalendarOptionsInput;
1441
- let currentRefined = this.currentCalendarOptionsRefined;
1442
- let anyChanges = false;
1443
- for (let optionName in raw) {
1444
- if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (COMPLEX_OPTION_COMPARATORS[optionName] &&
1445
- (optionName in currentRaw) &&
1446
- COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName])))) {
1447
- refined[optionName] = currentRefined[optionName];
1448
- }
1449
- else if (refiners[optionName]) {
1450
- refined[optionName] = refiners[optionName](raw[optionName]);
1451
- anyChanges = true;
1452
- }
1453
- else {
1454
- extra[optionName] = currentRaw[optionName];
1455
- }
1456
- }
1457
- if (anyChanges) {
1458
- this.currentCalendarOptionsInput = raw;
1459
- this.currentCalendarOptionsRefined = refined;
1460
- this.stableOptionOverrides = optionOverrides;
1461
- this.stableDynamicOptionOverrides = dynamicOptionOverrides;
1462
- }
1463
- this.optionsForHandling.push(...this.optionsForRefining);
1464
- this.optionsForRefining = [];
1465
- return {
1466
- rawOptions: this.currentCalendarOptionsInput,
1467
- refinedOptions: this.currentCalendarOptionsRefined,
1468
- pluginHooks,
1469
- availableLocaleData,
1470
- localeDefaults,
1471
- extra,
1472
- };
1473
- }
1474
- _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
1475
- let viewSpec = optionsData.viewSpecs[viewType];
1476
- if (!viewSpec) {
1477
- throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
1478
- }
1479
- let { refinedOptions, extra } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
1480
- warnUnknownOptions(extra);
1481
- let dateProfileGenerator = this.buildDateProfileGenerator({
1482
- dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
1483
- duration: viewSpec.duration,
1484
- durationUnit: viewSpec.durationUnit,
1485
- usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
1486
- dateEnv: optionsData.dateEnv,
1487
- calendarApi: this.props.calendarApi,
1488
- slotMinTime: refinedOptions.slotMinTime,
1489
- slotMaxTime: refinedOptions.slotMaxTime,
1490
- showNonCurrentDates: refinedOptions.showNonCurrentDates,
1491
- dayCount: refinedOptions.dayCount,
1492
- dateAlignment: refinedOptions.dateAlignment,
1493
- dateIncrement: refinedOptions.dateIncrement,
1494
- hiddenDays: refinedOptions.hiddenDays,
1495
- weekends: refinedOptions.weekends,
1496
- nowInput: refinedOptions.now,
1497
- validRangeInput: refinedOptions.validRange,
1498
- visibleRangeInput: refinedOptions.visibleRange,
1499
- fixedWeekCount: refinedOptions.fixedWeekCount,
1500
- });
1501
- let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
1502
- return { viewSpec, options: refinedOptions, dateProfileGenerator, viewApi };
1503
- }
1504
- processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
1505
- let raw = mergeRawOptions([
1506
- BASE_OPTION_DEFAULTS,
1507
- viewSpec.optionDefaults,
1508
- localeDefaults,
1509
- optionOverrides,
1510
- viewSpec.optionOverrides,
1511
- dynamicOptionOverrides,
1512
- ]);
1513
- 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);
1514
- let refined = {};
1515
- let currentRaw = this.currentViewOptionsInput;
1516
- let currentRefined = this.currentViewOptionsRefined;
1517
- let anyChanges = false;
1518
- let extra = {};
1519
- for (let optionName in raw) {
1520
- if (raw[optionName] === currentRaw[optionName] ||
1521
- (COMPLEX_OPTION_COMPARATORS[optionName] &&
1522
- COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
1523
- refined[optionName] = currentRefined[optionName];
1524
- }
1525
- else {
1526
- if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
1527
- (COMPLEX_OPTION_COMPARATORS[optionName] &&
1528
- COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
1529
- if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
1530
- refined[optionName] = this.currentCalendarOptionsRefined[optionName];
1531
- }
1532
- }
1533
- else if (refiners[optionName]) {
1534
- refined[optionName] = refiners[optionName](raw[optionName]);
1535
- }
1536
- else {
1537
- extra[optionName] = raw[optionName];
1538
- }
1539
- anyChanges = true;
1540
- }
1541
- }
1542
- if (anyChanges) {
1543
- this.currentViewOptionsInput = raw;
1544
- this.currentViewOptionsRefined = refined;
1545
- }
1546
- return {
1547
- rawOptions: this.currentViewOptionsInput,
1548
- refinedOptions: this.currentViewOptionsRefined,
1549
- extra,
1550
- };
1551
- }
1552
- }
1553
- function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
1554
- let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
1555
- return new DateEnv({
1556
- calendarSystem: 'gregory',
1557
- timeZone,
1558
- namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
1559
- locale,
1560
- weekNumberCalculation,
1561
- firstDay,
1562
- weekText,
1563
- cmdFormatter: pluginHooks.cmdFormatter,
1564
- defaultSeparator,
1565
- });
1566
- }
1567
- function buildTheme(options, pluginHooks) {
1568
- let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
1569
- return new ThemeClass(options);
1570
- }
1571
- function buildDateProfileGenerator(props) {
1572
- let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
1573
- return new DateProfileGeneratorClass(props);
1574
- }
1575
- function buildViewApi(type, getCurrentData, dateEnv) {
1576
- return new ViewImpl(type, getCurrentData, dateEnv);
1577
- }
1578
- function buildEventUiBySource(eventSources) {
1579
- return mapHash(eventSources, (eventSource) => eventSource.ui);
1580
- }
1581
- function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
1582
- let eventUiBases = { '': eventUiSingleBase };
1583
- for (let defId in eventDefs) {
1584
- let def = eventDefs[defId];
1585
- if (def.sourceId && eventUiBySource[def.sourceId]) {
1586
- eventUiBases[defId] = eventUiBySource[def.sourceId];
1587
- }
1588
- }
1589
- return eventUiBases;
1590
- }
1591
- function buildViewUiProps(calendarContext) {
1592
- let { options } = calendarContext;
1593
- return {
1594
- eventUiSingleBase: createEventUi({
1595
- display: options.eventDisplay,
1596
- editable: options.editable,
1597
- startEditable: options.eventStartEditable,
1598
- durationEditable: options.eventDurationEditable,
1599
- constraint: options.eventConstraint,
1600
- overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
1601
- allow: options.eventAllow,
1602
- backgroundColor: options.eventBackgroundColor,
1603
- borderColor: options.eventBorderColor,
1604
- textColor: options.eventTextColor,
1605
- color: options.eventColor,
1606
- // classNames: options.eventClassNames // render hook will handle this
1607
- }, calendarContext),
1608
- selectionConfig: createEventUi({
1609
- constraint: options.selectConstraint,
1610
- overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
1611
- allow: options.selectAllow,
1612
- }, calendarContext),
1613
- };
1614
- }
1615
- function computeIsLoading(state, context) {
1616
- for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
1617
- if (isLoadingFunc(state)) {
1618
- return true;
1619
- }
1620
- }
1621
- return false;
1622
- }
1623
- function parseContextBusinessHours(calendarContext) {
1624
- return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
1625
- }
1626
- function warnUnknownOptions(options, viewName) {
1627
- for (let optionName in options) {
1628
- console.warn(`Unknown option '${optionName}'` +
1629
- (viewName ? ` for view '${viewName}'` : ''));
1630
- }
1631
- }
1632
-
1633
- class ToolbarSection extends BaseComponent {
1634
- render() {
1635
- let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
1636
- return createElement('div', {
1637
- className: 'fc-toolbar-section fc-toolbar-' + this.props.name
1638
- }, ...children);
1639
- }
1640
- renderWidgetGroup(widgetGroup) {
1641
- let { props, context } = this;
1642
- let { options, theme } = context;
1643
- let children = [];
1644
- let isOnlyButtons = true;
1645
- let isOnlyView = true;
1646
- for (const widget of widgetGroup) {
1647
- const { buttonName, isView } = widget;
1648
- if (buttonName === 'title') {
1649
- isOnlyButtons = false;
1650
- }
1651
- else if (!isView) {
1652
- isOnlyView = false;
1653
- }
1654
- }
1655
- for (let widget of widgetGroup) {
1656
- let { buttonName, buttonClick, buttonText, buttonIcon, buttonHint } = widget;
1657
- if (buttonName === 'title') {
1658
- children.push(createElement("div", { role: 'heading', "aria-level": options.headingLevel, id: props.titleId, className: 'fc-toolbar-title' }, props.title));
1659
- }
1660
- else {
1661
- let isPressed = buttonName === props.activeButton;
1662
- let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
1663
- (!props.isPrevEnabled && buttonName === 'prev') ||
1664
- (!props.isNextEnabled && buttonName === 'next');
1665
- children.push(createElement("button", Object.assign({ type: "button", disabled: isDisabled }, ((isOnlyButtons && isOnlyView)
1666
- ? { 'role': 'tab', 'aria-selected': isPressed }
1667
- : { 'aria-pressed': isPressed }), { "aria-label": typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint, className: joinClassNames(`fc-${buttonName}-button`, theme.getClassName('button'), isPressed && theme.getClassName('buttonActive')), onClick: buttonClick }), buttonText || (buttonIcon ? createElement("span", { className: buttonIcon, "aria-hidden": true }) : '')));
1668
- }
1669
- }
1670
- if (children.length > 1) {
1671
- return createElement('div', {
1672
- role: (isOnlyButtons && isOnlyView) ? 'tablist' : undefined,
1673
- 'aria-label': (isOnlyButtons && isOnlyView) ? options.viewChangeHint : undefined,
1674
- className: isOnlyButtons ? theme.getClassName('buttonGroup') : undefined,
1675
- }, ...children);
1676
- }
1677
- return children[0];
1678
- }
1679
- }
1680
-
1681
- class Toolbar extends BaseComponent {
1682
- render() {
1683
- let { model, className } = this.props;
1684
- let { sectionWidgets } = model;
1685
- return (createElement("div", { className: joinClassNames(className, 'fc-toolbar') },
1686
- this.renderSection('start', sectionWidgets.start),
1687
- this.renderSection('center', sectionWidgets.center),
1688
- this.renderSection('end', sectionWidgets.end)));
1689
- }
1690
- renderSection(key, widgetGroups) {
1691
- let { props } = this;
1692
- return (createElement(ToolbarSection, { key: key, name: key, widgetGroups: widgetGroups, title: props.title, titleId: props.titleId, navUnit: props.navUnit, activeButton: props.activeButton, isTodayEnabled: props.isTodayEnabled, isPrevEnabled: props.isPrevEnabled, isNextEnabled: props.isNextEnabled }));
1693
- }
1694
- }
1695
-
1696
- /*
1697
- Detects when the user clicks on an event within a DateComponent
1698
- */
1699
- class EventClicking extends Interaction {
1700
- constructor(settings) {
1701
- super(settings);
1702
- this.handleSegClick = (ev, segEl) => {
1703
- let { component } = this;
1704
- let { context } = component;
1705
- let eventRange = getElEventRange(segEl);
1706
- if (eventRange && // might be the <div> surrounding the more link
1707
- component.isValidSegDownEl(ev.target)) {
1708
- context.emitter.trigger('eventClick', {
1709
- el: segEl,
1710
- event: new EventImpl(component.context, eventRange.def, eventRange.instance),
1711
- jsEvent: ev,
1712
- view: context.viewApi,
1713
- });
1714
- }
1715
- };
1716
- this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
1717
- this.handleSegClick);
1718
- }
1719
- }
1720
-
1721
- /*
1722
- Triggers events and adds/removes core classNames when the user's pointer
1723
- enters/leaves event-elements of a component.
1724
- */
1725
- class EventHovering extends Interaction {
1726
- constructor(settings) {
1727
- super(settings);
1728
- // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
1729
- this.handleEventElRemove = (el) => {
1730
- if (el === this.currentSegEl) {
1731
- this.handleSegLeave(null, this.currentSegEl);
1732
- }
1733
- };
1734
- this.handleSegEnter = (ev, segEl) => {
1735
- if (getElEventRange(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
1736
- this.currentSegEl = segEl;
1737
- this.triggerEvent('eventMouseEnter', ev, segEl);
1738
- }
1739
- };
1740
- this.handleSegLeave = (ev, segEl) => {
1741
- if (this.currentSegEl) {
1742
- this.currentSegEl = null;
1743
- this.triggerEvent('eventMouseLeave', ev, segEl);
1744
- }
1745
- };
1746
- this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
1747
- this.handleSegEnter, this.handleSegLeave);
1748
- }
1749
- destroy() {
1750
- this.removeHoverListeners();
1751
- }
1752
- triggerEvent(publicEvName, ev, segEl) {
1753
- let { component } = this;
1754
- let { context } = component;
1755
- let eventRange = getElEventRange(segEl);
1756
- if (!ev || component.isValidSegDownEl(ev.target)) {
1757
- context.emitter.trigger(publicEvName, {
1758
- el: segEl,
1759
- event: new EventImpl(context, eventRange.def, eventRange.instance),
1760
- jsEvent: ev,
1761
- view: context.viewApi,
1762
- });
1763
- }
1764
- }
1765
- }
1766
-
1767
- class ViewHarness extends Component {
1768
- render() {
1769
- const { props } = this;
1770
- return (createElement("div", { className: joinClassNames('fc-view-outer', props.height != null
1771
- ? 'fc-view-outer-static'
1772
- : props.heightLiquid
1773
- ? 'fc-view-outer-liquid'
1774
- : props.aspectRatio != null
1775
- && 'fc-view-outer-aspect-ratio'), style: {
1776
- height: props.height,
1777
- paddingBottom: props.aspectRatio != null
1778
- ? `${(1 / props.aspectRatio) * 100}%`
1779
- : undefined
1780
- } }, props.children));
1781
- }
1782
- }
1783
-
1784
- class CalendarContent extends PureComponent {
1785
- constructor() {
1786
- super(...arguments);
1787
- this.buildViewContext = memoize(buildViewContext);
1788
- this.buildViewPropTransformers = memoize(buildViewPropTransformers);
1789
- this.buildToolbarProps = memoize(buildToolbarProps);
1790
- this.interactionsStore = {};
1791
- this.viewTitleId = getUniqueDomId();
1792
- // Component Registration
1793
- // -----------------------------------------------------------------------------------------------------------------
1794
- this.registerInteractiveComponent = (component, settingsInput) => {
1795
- let settings = parseInteractionSettings(component, settingsInput);
1796
- let DEFAULT_INTERACTIONS = [
1797
- EventClicking,
1798
- EventHovering,
1799
- ];
1800
- let interactionClasses = DEFAULT_INTERACTIONS;
1801
- if (!settingsInput.disableHits) {
1802
- interactionClasses = interactionClasses.concat(this.props.pluginHooks.componentInteractions);
1803
- }
1804
- let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
1805
- this.interactionsStore[component.uid] = interactions;
1806
- interactionSettingsStore[component.uid] = settings;
1807
- };
1808
- this.unregisterInteractiveComponent = (component) => {
1809
- let listeners = this.interactionsStore[component.uid];
1810
- if (listeners) {
1811
- for (let listener of listeners) {
1812
- listener.destroy();
1813
- }
1814
- delete this.interactionsStore[component.uid];
1815
- }
1816
- delete interactionSettingsStore[component.uid];
1817
- };
1818
- }
1819
- /*
1820
- renders INSIDE of an outer div
1821
- */
1822
- render() {
1823
- let { props } = this;
1824
- let { toolbarConfig, options } = props;
1825
- let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, getNow(props.options.now, props.dateEnv), // TODO: use NowTimer????
1826
- props.viewTitle);
1827
- let viewHeight;
1828
- let viewHeightLiquid = false;
1829
- let viewAspectRatio;
1830
- if (props.forPrint || getIsHeightAuto(options)) ;
1831
- else if (options.height != null) {
1832
- viewHeightLiquid = true;
1833
- }
1834
- else if (options.contentHeight != null) {
1835
- viewHeight = options.contentHeight;
1836
- }
1837
- else {
1838
- viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
1839
- }
1840
- let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
1841
- return (createElement(ViewContextType.Provider, { value: viewContext },
1842
- toolbarConfig.header && (createElement(Toolbar, Object.assign({ className: "fc-header-toolbar", model: toolbarConfig.header, titleId: this.viewTitleId }, toolbarProps))),
1843
- createElement(ViewHarness, { height: viewHeight, heightLiquid: viewHeightLiquid, aspectRatio: viewAspectRatio },
1844
- this.renderView(props, toolbarProps.title),
1845
- this.buildAppendContent()),
1846
- toolbarConfig.footer && (createElement(Toolbar, Object.assign({ className: "fc-footer-toolbar", model: toolbarConfig.footer }, toolbarProps)))));
1847
- }
1848
- componentDidMount() {
1849
- let { props } = this;
1850
- this.calendarInteractions = props.pluginHooks.calendarInteractions
1851
- .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
1852
- let { propSetHandlers } = props.pluginHooks;
1853
- for (let propName in propSetHandlers) {
1854
- propSetHandlers[propName](props[propName], props);
1855
- }
1856
- }
1857
- componentDidUpdate(prevProps) {
1858
- let { props } = this;
1859
- let { propSetHandlers } = props.pluginHooks;
1860
- for (let propName in propSetHandlers) {
1861
- if (props[propName] !== prevProps[propName]) {
1862
- propSetHandlers[propName](props[propName], props);
1863
- }
1864
- }
1865
- }
1866
- componentWillUnmount() {
1867
- for (let interaction of this.calendarInteractions) {
1868
- interaction.destroy();
1869
- }
1870
- this.props.emitter.trigger('_unmount');
1871
- }
1872
- buildAppendContent() {
1873
- let { props } = this;
1874
- let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
1875
- return createElement(Fragment, {}, ...children);
1876
- }
1877
- renderView(props, title) {
1878
- let { pluginHooks } = props;
1879
- let { viewSpec, toolbarConfig } = props;
1880
- let viewProps = {
1881
- dateProfile: props.dateProfile,
1882
- businessHours: props.businessHours,
1883
- eventStore: props.renderableEventStore,
1884
- eventUiBases: props.eventUiBases,
1885
- dateSelection: props.dateSelection,
1886
- eventSelection: props.eventSelection,
1887
- eventDrag: props.eventDrag,
1888
- eventResize: props.eventResize,
1889
- forPrint: props.forPrint,
1890
- labelId: toolbarConfig.header && toolbarConfig.header.hasTitle ? this.viewTitleId : undefined,
1891
- labelStr: toolbarConfig.header && toolbarConfig.header.hasTitle ? undefined : title,
1892
- };
1893
- let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
1894
- for (let transformer of transformers) {
1895
- Object.assign(viewProps, transformer.transform(viewProps, props));
1896
- }
1897
- let ViewComponent = viewSpec.component;
1898
- return (createElement(ViewComponent, Object.assign({}, viewProps)));
1899
- }
1900
- }
1901
- function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
1902
- // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
1903
- let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
1904
- let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
1905
- let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
1906
- return {
1907
- title,
1908
- activeButton: viewSpec.type,
1909
- navUnit: viewSpec.singleUnit,
1910
- isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
1911
- isPrevEnabled: prevInfo.isValid,
1912
- isNextEnabled: nextInfo.isValid,
1913
- };
1914
- }
1915
- // Plugin
1916
- // -----------------------------------------------------------------------------------------------------------------
1917
- function buildViewPropTransformers(theClasses) {
1918
- return theClasses.map((TheClass) => new TheClass());
1919
- }
1920
-
1921
- /*
1922
- Vanilla JS API
1923
- */
1924
- class Calendar extends CalendarImpl {
1925
- constructor(el, optionOverrides = {}) {
1926
- super();
1927
- this.isRendering = false;
1928
- this.isRendered = false;
1929
- this.currentClassNames = [];
1930
- this.customContentRenderId = 0;
1931
- this.handleAction = (action) => {
1932
- // actions we know we want to render immediately
1933
- switch (action.type) {
1934
- case 'SET_EVENT_DRAG':
1935
- case 'SET_EVENT_RESIZE':
1936
- this.renderRunner.tryDrain();
1937
- }
1938
- };
1939
- this.handleData = (data) => {
1940
- this.currentData = data;
1941
- this.renderRunner.request(data.calendarOptions.rerenderDelay);
1942
- };
1943
- this.handleRenderRequest = () => {
1944
- if (this.isRendering) {
1945
- this.isRendered = true;
1946
- let { currentData } = this;
1947
- flushSync(() => {
1948
- render(createElement(CalendarRoot, { options: currentData.calendarOptions, theme: currentData.theme, emitter: currentData.emitter }, (classNames, height, forPrint) => {
1949
- this.setClassNames(classNames);
1950
- this.setHeight(height);
1951
- return (createElement(RenderId.Provider, { value: this.customContentRenderId },
1952
- createElement(CalendarContent, Object.assign({ forPrint: forPrint }, currentData))));
1953
- }), this.el);
1954
- });
1955
- }
1956
- else if (this.isRendered) {
1957
- this.isRendered = false;
1958
- render(null, this.el);
1959
- this.setClassNames([]);
1960
- this.setHeight('');
1961
- }
1962
- };
1963
- ensureElHasStyles(el);
1964
- this.el = el;
1965
- this.renderRunner = new DelayedRunner(this.handleRenderRequest);
1966
- new CalendarDataManager({
1967
- optionOverrides,
1968
- calendarApi: this,
1969
- onAction: this.handleAction,
1970
- onData: this.handleData,
1971
- });
1972
- }
1973
- render() {
1974
- let wasRendering = this.isRendering;
1975
- if (!wasRendering) {
1976
- this.isRendering = true;
1977
- }
1978
- else {
1979
- this.customContentRenderId += 1;
1980
- }
1981
- this.renderRunner.request();
1982
- if (wasRendering) {
1983
- this.updateSize();
1984
- }
1985
- }
1986
- destroy() {
1987
- if (this.isRendering) {
1988
- this.isRendering = false;
1989
- this.renderRunner.request();
1990
- }
1991
- }
1992
- batchRendering(func) {
1993
- this.renderRunner.pause('batchRendering');
1994
- func();
1995
- this.renderRunner.resume('batchRendering');
1996
- }
1997
- pauseRendering() {
1998
- this.renderRunner.pause('pauseRendering');
1999
- }
2000
- resumeRendering() {
2001
- this.renderRunner.resume('pauseRendering', true);
2002
- }
2003
- resetOptions(optionOverrides, changedOptionNames) {
2004
- this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);
2005
- }
2006
- setClassNames(classNames) {
2007
- if (!isArraysEqual(classNames, this.currentClassNames)) {
2008
- let { classList } = this.el;
2009
- for (let className of this.currentClassNames) {
2010
- classList.remove(className);
2011
- }
2012
- for (let className of classNames) {
2013
- classList.add(className);
2014
- }
2015
- this.currentClassNames = classNames;
2016
- }
2017
- }
2018
- setHeight(height) {
2019
- applyStyleProp(this.el, 'height', height);
2020
- }
2021
- }
2022
-
2023
- function formatDate(dateInput, options = {}) {
2024
- let dateEnv = buildDateEnv(options);
2025
- let formatter = createFormatter(options);
2026
- let dateMeta = dateEnv.createMarkerMeta(dateInput);
2027
- if (!dateMeta) { // TODO: warning?
2028
- return '';
2029
- }
2030
- return dateEnv.format(dateMeta.marker, formatter, {
2031
- forcedTzo: dateMeta.forcedTzo,
2032
- });
2033
- }
2034
- function formatRange(startInput, endInput, options) {
2035
- let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
2036
- let formatter = createFormatter(options);
2037
- let startMeta = dateEnv.createMarkerMeta(startInput);
2038
- let endMeta = dateEnv.createMarkerMeta(endInput);
2039
- if (!startMeta || !endMeta) { // TODO: warning?
2040
- return '';
2041
- }
2042
- return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
2043
- forcedStartTzo: startMeta.forcedTzo,
2044
- forcedEndTzo: endMeta.forcedTzo,
2045
- isEndExclusive: options.isEndExclusive,
2046
- defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
2047
- });
2048
- }
2049
- // TODO: more DRY and optimized
2050
- function buildDateEnv(settings) {
2051
- let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
2052
- return new DateEnv(Object.assign(Object.assign({ timeZone: BASE_OPTION_DEFAULTS.timeZone, calendarSystem: 'gregory' }, settings), { locale }));
2053
- }
2054
-
2055
- // HELPERS
2056
- /*
2057
- if nextDayThreshold is specified, slicing is done in an all-day fashion.
2058
- you can get nextDayThreshold from context.nextDayThreshold
2059
- */
2060
- function sliceEvents(props, allDay) {
2061
- return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
2062
- }
2063
-
2064
- const version = '7.0.0-rc.0';
2065
-
2066
- export { Calendar, createPlugin, formatDate, formatRange, globalLocales, globalPlugins, sliceEvents, version };
1
+ console.log('@fullcalendar/core should not be imported directly');