index.cjs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var index_cjs = require('@fullcalendar/core/index.cjs');
  5. var internal_cjs = require('@fullcalendar/core/internal.cjs');
  6. const OPTION_IS_COMPLEX = {
  7. headerToolbar: true,
  8. footerToolbar: true,
  9. events: true,
  10. eventSources: true,
  11. resources: true
  12. };
  13. const FullCalendar = vue.defineComponent({
  14. props: {
  15. options: Object
  16. },
  17. data() {
  18. return {
  19. renderId: 0,
  20. customRenderingMap: new Map()
  21. };
  22. },
  23. methods: {
  24. getApi() {
  25. return getSecret(this).calendar;
  26. },
  27. buildOptions(suppliedOptions) {
  28. return {
  29. ...suppliedOptions,
  30. customRenderingMetaMap: kebabToCamelKeys(this.$slots),
  31. handleCustomRendering: getSecret(this).handleCustomRendering,
  32. };
  33. },
  34. },
  35. render() {
  36. const customRenderingNodes = [];
  37. for (const customRendering of this.customRenderingMap.values()) {
  38. customRenderingNodes.push(vue.h(CustomRenderingComponent, {
  39. key: customRendering.id,
  40. customRendering,
  41. }));
  42. }
  43. return vue.h('div', {
  44. // when renderId is changed, Vue will trigger a real-DOM async rerender, calling beforeUpdate/updated
  45. attrs: { 'data-fc-render-id': this.renderId }
  46. }, vue.h(vue.Fragment, customRenderingNodes)); // for containing CustomRendering keys
  47. },
  48. mounted() {
  49. const customRenderingStore = new internal_cjs.CustomRenderingStore();
  50. getSecret(this).handleCustomRendering = customRenderingStore.handle.bind(customRenderingStore);
  51. const calendarOptions = this.buildOptions(this.options);
  52. const calendar = new index_cjs.Calendar(this.$el, calendarOptions);
  53. getSecret(this).calendar = calendar;
  54. calendar.render();
  55. customRenderingStore.subscribe((customRenderingMap) => {
  56. this.customRenderingMap = customRenderingMap; // likely same reference, so won't rerender
  57. this.renderId++; // force rerender
  58. getSecret(this).needCustomRenderingResize = true;
  59. });
  60. },
  61. beforeUpdate() {
  62. this.getApi().resumeRendering(); // the watcher handlers paused it
  63. },
  64. updated() {
  65. if (getSecret(this).needCustomRenderingResize) {
  66. getSecret(this).needCustomRenderingResize = false;
  67. this.getApi().updateSize();
  68. }
  69. },
  70. beforeUnmount() {
  71. this.getApi().destroy();
  72. },
  73. watch: buildWatchers()
  74. });
  75. // Custom Rendering
  76. // -------------------------------------------------------------------------------------------------
  77. const CustomRenderingComponent = vue.defineComponent({
  78. props: {
  79. customRendering: Object
  80. },
  81. render() {
  82. const customRendering = this.customRendering;
  83. const innerContent = typeof customRendering.generatorMeta === 'function' ?
  84. customRendering.generatorMeta(customRendering.renderProps) : // vue-normalized slot function
  85. customRendering.generatorMeta; // probably a vue JSX node returned from content-inject func
  86. return vue.h(vue.Teleport, { to: customRendering.containerEl }, innerContent);
  87. }
  88. });
  89. // storing internal state:
  90. // https://github.com/vuejs/vue/issues/1988#issuecomment-163013818
  91. function getSecret(inst) {
  92. return inst;
  93. }
  94. function buildWatchers() {
  95. let watchers = {
  96. // watches changes of ALL options and their nested objects,
  97. // but this is only a means to be notified of top-level non-complex options changes.
  98. options: {
  99. deep: true,
  100. handler(options) {
  101. let calendar = this.getApi();
  102. calendar.pauseRendering();
  103. let calendarOptions = this.buildOptions(options);
  104. calendar.resetOptions(calendarOptions);
  105. this.renderId++; // will queue a rerender
  106. }
  107. }
  108. };
  109. for (let complexOptionName in OPTION_IS_COMPLEX) {
  110. // handlers called when nested objects change
  111. watchers[`options.${complexOptionName}`] = {
  112. deep: true,
  113. handler(val) {
  114. // unfortunately the handler is called with undefined if new props were set, but the complex one wasn't ever set
  115. if (val !== undefined) {
  116. let calendar = this.getApi();
  117. calendar.pauseRendering();
  118. calendar.resetOptions({
  119. [complexOptionName]: val
  120. }, [complexOptionName]);
  121. this.renderId++; // will queue a rerender
  122. }
  123. }
  124. };
  125. }
  126. return watchers;
  127. }
  128. // General Utils
  129. // -------------------------------------------------------------------------------------------------
  130. function kebabToCamelKeys(map) {
  131. const newMap = {};
  132. for (const key in map) {
  133. newMap[kebabToCamel(key)] = map[key];
  134. }
  135. return newMap;
  136. }
  137. function kebabToCamel(s) {
  138. return s
  139. .split('-')
  140. .map((word, index) => index ? capitalize(word) : word)
  141. .join('');
  142. }
  143. function capitalize(s) {
  144. return s.charAt(0).toUpperCase() + s.slice(1);
  145. }
  146. exports["default"] = FullCalendar;