@fullcalendar/core 4.3.1 → 4.4.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.
package/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- FullCalendar Core Package v4.3.1
2
+ FullCalendar Core Package v4.4.0
3
3
  Docs & License: https://fullcalendar.io/
4
4
  (c) 2019 Adam Shaw
5
5
  */
@@ -2392,12 +2392,13 @@ Docs & License: https://fullcalendar.io/
2392
2392
  function hasBgRendering(def) {
2393
2393
  return def.rendering === 'background' || def.rendering === 'inverse-background';
2394
2394
  }
2395
- function filterSegsViaEls(view, segs, isMirror) {
2396
- if (view.hasPublicHandlers('eventRender')) {
2395
+ function filterSegsViaEls(context, segs, isMirror) {
2396
+ var calendar = context.calendar, view = context.view;
2397
+ if (calendar.hasPublicHandlers('eventRender')) {
2397
2398
  segs = segs.filter(function (seg) {
2398
- var custom = view.publiclyTrigger('eventRender', [
2399
+ var custom = calendar.publiclyTrigger('eventRender', [
2399
2400
  {
2400
- event: new EventApi(view.calendar, seg.eventRange.def, seg.eventRange.instance),
2401
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
2401
2402
  isMirror: isMirror,
2402
2403
  isStart: seg.isStart,
2403
2404
  isEnd: seg.isEnd,
@@ -2444,6 +2445,65 @@ Docs & License: https://fullcalendar.io/
2444
2445
  uis.push(eventDef.ui);
2445
2446
  return combineEventUis(uis);
2446
2447
  }
2448
+ // triggers
2449
+ function triggerRenderedSegs(context, segs, isMirrors) {
2450
+ var calendar = context.calendar, view = context.view;
2451
+ if (calendar.hasPublicHandlers('eventPositioned')) {
2452
+ for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
2453
+ var seg = segs_2[_i];
2454
+ calendar.publiclyTriggerAfterSizing('eventPositioned', [
2455
+ {
2456
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
2457
+ isMirror: isMirrors,
2458
+ isStart: seg.isStart,
2459
+ isEnd: seg.isEnd,
2460
+ el: seg.el,
2461
+ view: view
2462
+ }
2463
+ ]);
2464
+ }
2465
+ }
2466
+ if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
2467
+ calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once
2468
+ }
2469
+ }
2470
+ function triggerWillRemoveSegs(context, segs, isMirrors) {
2471
+ var calendar = context.calendar, view = context.view;
2472
+ for (var _i = 0, segs_3 = segs; _i < segs_3.length; _i++) {
2473
+ var seg = segs_3[_i];
2474
+ calendar.trigger('eventElRemove', seg.el);
2475
+ }
2476
+ if (calendar.hasPublicHandlers('eventDestroy')) {
2477
+ for (var _a = 0, segs_4 = segs; _a < segs_4.length; _a++) {
2478
+ var seg = segs_4[_a];
2479
+ calendar.publiclyTrigger('eventDestroy', [
2480
+ {
2481
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
2482
+ isMirror: isMirrors,
2483
+ el: seg.el,
2484
+ view: view
2485
+ }
2486
+ ]);
2487
+ }
2488
+ }
2489
+ }
2490
+ // is-interactable
2491
+ function computeEventDraggable(context, eventDef, eventUi) {
2492
+ var calendar = context.calendar, view = context.view;
2493
+ var transformers = calendar.pluginSystem.hooks.isDraggableTransformers;
2494
+ var val = eventUi.startEditable;
2495
+ for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
2496
+ var transformer = transformers_1[_i];
2497
+ val = transformer(val, eventDef, eventUi, view);
2498
+ }
2499
+ return val;
2500
+ }
2501
+ function computeEventStartResizable(context, eventDef, eventUi) {
2502
+ return eventUi.durationEditable && context.options.eventResizableFromStart;
2503
+ }
2504
+ function computeEventEndResizable(context, eventDef, eventUi) {
2505
+ return eventUi.durationEditable;
2506
+ }
2447
2507
 
2448
2508
  // applies the mutation to ALL defs/instances within the event store
2449
2509
  function applyMutationToEventStore(eventStore, eventConfigBase, mutation, calendar) {
@@ -3345,8 +3405,7 @@ Docs & License: https://fullcalendar.io/
3345
3405
  // { date, type, forceOff }
3346
3406
  // `type` is a view-type like "day" or "week". default value is "day".
3347
3407
  // `attrs` and `innerHtml` are use to generate the rest of the HTML tag.
3348
- function buildGotoAnchorHtml(component, gotoOptions, attrs, innerHtml) {
3349
- var dateEnv = component.dateEnv;
3408
+ function buildGotoAnchorHtml(allOptions, dateEnv, gotoOptions, attrs, innerHtml) {
3350
3409
  var date;
3351
3410
  var type;
3352
3411
  var forceOff;
@@ -3369,7 +3428,7 @@ Docs & License: https://fullcalendar.io/
3369
3428
  }
3370
3429
  attrs = attrs ? ' ' + attrsToStr(attrs) : ''; // will have a leading space
3371
3430
  innerHtml = innerHtml || '';
3372
- if (!forceOff && component.opt('navLinks')) {
3431
+ if (!forceOff && allOptions.navLinks) {
3373
3432
  return '<a' + attrs +
3374
3433
  ' data-goto="' + htmlEscape(JSON.stringify(finalOptions)) + '">' +
3375
3434
  innerHtml +
@@ -3381,12 +3440,12 @@ Docs & License: https://fullcalendar.io/
3381
3440
  '</span>';
3382
3441
  }
3383
3442
  }
3384
- function getAllDayHtml(component) {
3385
- return component.opt('allDayHtml') || htmlEscape(component.opt('allDayText'));
3443
+ function getAllDayHtml(allOptions) {
3444
+ return allOptions.allDayHtml || htmlEscape(allOptions.allDayText);
3386
3445
  }
3387
3446
  // Computes HTML classNames for a single-day element
3388
3447
  function getDayClasses(date, dateProfile, context, noThemeHighlight) {
3389
- var calendar = context.calendar, view = context.view, theme = context.theme, dateEnv = context.dateEnv;
3448
+ var calendar = context.calendar, options = context.options, theme = context.theme, dateEnv = context.dateEnv;
3390
3449
  var classes = [];
3391
3450
  var todayStart;
3392
3451
  var todayEnd;
@@ -3395,7 +3454,7 @@ Docs & License: https://fullcalendar.io/
3395
3454
  }
3396
3455
  else {
3397
3456
  classes.push('fc-' + DAY_IDS[date.getUTCDay()]);
3398
- if (view.opt('monthMode') &&
3457
+ if (options.monthMode &&
3399
3458
  dateEnv.getMonth(date) !== dateEnv.getMonth(dateProfile.currentRange.start)) {
3400
3459
  classes.push('fc-other-month');
3401
3460
  }
@@ -3860,34 +3919,54 @@ Docs & License: https://fullcalendar.io/
3860
3919
  Theme.prototype.iconOverridePrefix = '';
3861
3920
 
3862
3921
  var guid = 0;
3922
+ var ComponentContext = /** @class */ (function () {
3923
+ function ComponentContext(calendar, theme, dateEnv, options, view) {
3924
+ this.calendar = calendar;
3925
+ this.theme = theme;
3926
+ this.dateEnv = dateEnv;
3927
+ this.options = options;
3928
+ this.view = view;
3929
+ this.isRtl = options.dir === 'rtl';
3930
+ this.eventOrderSpecs = parseFieldSpecs(options.eventOrder);
3931
+ this.nextDayThreshold = createDuration(options.nextDayThreshold);
3932
+ }
3933
+ ComponentContext.prototype.extend = function (options, view) {
3934
+ return new ComponentContext(this.calendar, this.theme, this.dateEnv, options || this.options, view || this.view);
3935
+ };
3936
+ return ComponentContext;
3937
+ }());
3863
3938
  var Component = /** @class */ (function () {
3864
- function Component(context, isView) {
3865
- // HACK to populate view at top of component instantiation call chain
3866
- if (isView) {
3867
- context.view = this;
3868
- }
3939
+ function Component() {
3869
3940
  this.uid = String(guid++);
3870
- this.context = context;
3871
- this.dateEnv = context.dateEnv;
3872
- this.theme = context.theme;
3873
- this.view = context.view;
3874
- this.calendar = context.calendar;
3875
- this.isRtl = this.opt('dir') === 'rtl';
3876
3941
  }
3877
3942
  Component.addEqualityFuncs = function (newFuncs) {
3878
3943
  this.prototype.equalityFuncs = __assign({}, this.prototype.equalityFuncs, newFuncs);
3879
3944
  };
3880
- Component.prototype.opt = function (name) {
3881
- return this.context.options[name];
3882
- };
3883
- Component.prototype.receiveProps = function (props) {
3945
+ Component.prototype.receiveProps = function (props, context) {
3946
+ var oldContext = this.context;
3947
+ this.context = context;
3948
+ if (!oldContext) {
3949
+ this.firstContext(context);
3950
+ }
3884
3951
  var _a = recycleProps(this.props || {}, props, this.equalityFuncs), anyChanges = _a.anyChanges, comboProps = _a.comboProps;
3885
3952
  this.props = comboProps;
3886
3953
  if (anyChanges) {
3887
- this.render(comboProps);
3954
+ if (oldContext) {
3955
+ this.beforeUpdate();
3956
+ }
3957
+ this.render(comboProps, context);
3958
+ if (oldContext) {
3959
+ this.afterUpdate();
3960
+ }
3888
3961
  }
3889
3962
  };
3890
- Component.prototype.render = function (props) {
3963
+ Component.prototype.render = function (props, context) {
3964
+ };
3965
+ Component.prototype.firstContext = function (context) {
3966
+ };
3967
+ Component.prototype.beforeUpdate = function () {
3968
+ };
3969
+ Component.prototype.afterUpdate = function () {
3891
3970
  };
3892
3971
  // after destroy is called, this component won't ever be used again
3893
3972
  Component.prototype.destroy = function () {
@@ -3929,8 +4008,8 @@ Docs & License: https://fullcalendar.io/
3929
4008
  */
3930
4009
  var DateComponent = /** @class */ (function (_super) {
3931
4010
  __extends(DateComponent, _super);
3932
- function DateComponent(context, el, isView) {
3933
- var _this = _super.call(this, context, isView) || this;
4011
+ function DateComponent(el) {
4012
+ var _this = _super.call(this) || this;
3934
4013
  _this.el = el;
3935
4014
  return _this;
3936
4015
  }
@@ -3938,38 +4017,6 @@ Docs & License: https://fullcalendar.io/
3938
4017
  _super.prototype.destroy.call(this);
3939
4018
  removeElement(this.el);
3940
4019
  };
3941
- // TODO: WHAT ABOUT (sourceSeg && sourceSeg.component.doesDragMirror)
3942
- //
3943
- // Event Drag-n-Drop Rendering (for both events and external elements)
3944
- // ---------------------------------------------------------------------------------------------------------------
3945
- /*
3946
- renderEventDragSegs(state: EventSegUiInteractionState) {
3947
- if (state) {
3948
- let { isEvent, segs, sourceSeg } = state
3949
-
3950
- if (this.eventRenderer) {
3951
- this.eventRenderer.hideByHash(state.affectedInstances)
3952
- }
3953
-
3954
- // if the user is dragging something that is considered an event with real event data,
3955
- // and this component likes to do drag mirrors OR the component where the seg came from
3956
- // likes to do drag mirrors, then render a drag mirror.
3957
- if (isEvent && (this.doesDragMirror || sourceSeg && sourceSeg.component.doesDragMirror)) {
3958
- if (this.mirrorRenderer) {
3959
- this.mirrorRenderer.renderSegs(segs, { isDragging: true, sourceSeg })
3960
- }
3961
- }
3962
-
3963
- // if it would be impossible to render a drag mirror OR this component likes to render
3964
- // highlights, then render a highlight.
3965
- if (!isEvent || this.doesDragHighlight) {
3966
- if (this.fillRenderer) {
3967
- this.fillRenderer.renderSegs('highlight', segs)
3968
- }
3969
- }
3970
- }
3971
- }
3972
- */
3973
4020
  // Hit System
3974
4021
  // -----------------------------------------------------------------------------------------------------------------
3975
4022
  DateComponent.prototype.buildPositionCaches = function () {
@@ -3980,7 +4027,7 @@ Docs & License: https://fullcalendar.io/
3980
4027
  // Validation
3981
4028
  // -----------------------------------------------------------------------------------------------------------------
3982
4029
  DateComponent.prototype.isInteractionValid = function (interaction) {
3983
- var calendar = this.calendar;
4030
+ var calendar = this.context.calendar;
3984
4031
  var dateProfile = this.props.dateProfile; // HACK
3985
4032
  var instances = interaction.mutatedEvents.instances;
3986
4033
  if (dateProfile) { // HACK for DayTile
@@ -3993,68 +4040,13 @@ Docs & License: https://fullcalendar.io/
3993
4040
  return isInteractionValid(interaction, calendar);
3994
4041
  };
3995
4042
  DateComponent.prototype.isDateSelectionValid = function (selection) {
4043
+ var calendar = this.context.calendar;
3996
4044
  var dateProfile = this.props.dateProfile; // HACK
3997
4045
  if (dateProfile && // HACK for DayTile
3998
4046
  !rangeContainsRange(dateProfile.validRange, selection.range)) {
3999
4047
  return false;
4000
4048
  }
4001
- return isDateSelectionValid(selection, this.calendar);
4002
- };
4003
- // Triggering
4004
- // -----------------------------------------------------------------------------------------------------------------
4005
- // TODO: move to Calendar
4006
- DateComponent.prototype.publiclyTrigger = function (name, args) {
4007
- var calendar = this.calendar;
4008
- return calendar.publiclyTrigger(name, args);
4009
- };
4010
- DateComponent.prototype.publiclyTriggerAfterSizing = function (name, args) {
4011
- var calendar = this.calendar;
4012
- return calendar.publiclyTriggerAfterSizing(name, args);
4013
- };
4014
- DateComponent.prototype.hasPublicHandlers = function (name) {
4015
- var calendar = this.calendar;
4016
- return calendar.hasPublicHandlers(name);
4017
- };
4018
- DateComponent.prototype.triggerRenderedSegs = function (segs, isMirrors) {
4019
- var calendar = this.calendar;
4020
- if (this.hasPublicHandlers('eventPositioned')) {
4021
- for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {
4022
- var seg = segs_1[_i];
4023
- this.publiclyTriggerAfterSizing('eventPositioned', [
4024
- {
4025
- event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
4026
- isMirror: isMirrors,
4027
- isStart: seg.isStart,
4028
- isEnd: seg.isEnd,
4029
- el: seg.el,
4030
- view: this // safe to cast because this method is only called on context.view
4031
- }
4032
- ]);
4033
- }
4034
- }
4035
- if (!calendar.state.loadingLevel) { // avoid initial empty state while pending
4036
- calendar.afterSizingTriggers._eventsPositioned = [null]; // fire once
4037
- }
4038
- };
4039
- DateComponent.prototype.triggerWillRemoveSegs = function (segs, isMirrors) {
4040
- var calendar = this.calendar;
4041
- for (var _i = 0, segs_2 = segs; _i < segs_2.length; _i++) {
4042
- var seg = segs_2[_i];
4043
- calendar.trigger('eventElRemove', seg.el);
4044
- }
4045
- if (this.hasPublicHandlers('eventDestroy')) {
4046
- for (var _a = 0, segs_3 = segs; _a < segs_3.length; _a++) {
4047
- var seg = segs_3[_a];
4048
- this.publiclyTrigger('eventDestroy', [
4049
- {
4050
- event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
4051
- isMirror: isMirrors,
4052
- el: seg.el,
4053
- view: this // safe to cast because this method is only called on context.view
4054
- }
4055
- ]);
4056
- }
4057
- }
4049
+ return isDateSelectionValid(selection, calendar);
4058
4050
  };
4059
4051
  // Pointer Interaction Utils
4060
4052
  // -----------------------------------------------------------------------------------------------------------------
@@ -4669,6 +4661,9 @@ Docs & License: https://fullcalendar.io/
4669
4661
  this.compute();
4670
4662
  }
4671
4663
  OptionsManager.prototype.mutate = function (updates, removals, isDynamic) {
4664
+ if (!Object.keys(updates).length && !removals.length) {
4665
+ return;
4666
+ }
4672
4667
  var overrideHash = isDynamic ? this.dynamicOverrides : this.overrides;
4673
4668
  __assign(overrideHash, updates);
4674
4669
  for (var _i = 0, removals_1 = removals; _i < removals_1.length; _i++) {
@@ -5179,6 +5174,7 @@ Docs & License: https://fullcalendar.io/
5179
5174
  else {
5180
5175
  return !calendar.opt('lazyFetching') ||
5181
5176
  !eventSource.fetchRange ||
5177
+ eventSource.isFetching || // always cancel outdated in-progress fetches
5182
5178
  fetchRange.start < eventSource.fetchRange.start ||
5183
5179
  fetchRange.end > eventSource.fetchRange.end;
5184
5180
  }
@@ -5246,7 +5242,8 @@ Docs & License: https://fullcalendar.io/
5246
5242
  var eventSource = sourceHash[sourceId];
5247
5243
  if (eventSource && // not already removed
5248
5244
  fetchId === eventSource.latestFetchId) {
5249
- return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange }), _a));
5245
+ return __assign({}, sourceHash, (_a = {}, _a[sourceId] = __assign({}, eventSource, { isFetching: false, fetchRange: fetchRange // also serves as a marker that at least one fetch has completed
5246
+ }), _a));
5250
5247
  }
5251
5248
  return sourceHash;
5252
5249
  }
@@ -5984,8 +5981,8 @@ Docs & License: https://fullcalendar.io/
5984
5981
 
5985
5982
  var Toolbar = /** @class */ (function (_super) {
5986
5983
  __extends(Toolbar, _super);
5987
- function Toolbar(context, extraClassName) {
5988
- var _this = _super.call(this, context) || this;
5984
+ function Toolbar(extraClassName) {
5985
+ var _this = _super.call(this) || this;
5989
5986
  _this._renderLayout = memoizeRendering(_this.renderLayout, _this.unrenderLayout);
5990
5987
  _this._updateTitle = memoizeRendering(_this.updateTitle, null, [_this._renderLayout]);
5991
5988
  _this._updateActiveButton = memoizeRendering(_this.updateActiveButton, null, [_this._renderLayout]);
@@ -6020,7 +6017,7 @@ Docs & License: https://fullcalendar.io/
6020
6017
  };
6021
6018
  Toolbar.prototype.renderSection = function (position, buttonStr) {
6022
6019
  var _this = this;
6023
- var _a = this, theme = _a.theme, calendar = _a.calendar;
6020
+ var _a = this.context, theme = _a.theme, calendar = _a.calendar;
6024
6021
  var optionsManager = calendar.optionsManager;
6025
6022
  var viewSpecs = calendar.viewSpecs;
6026
6023
  var sectionEl = createElement('div', { className: 'fc-' + position });
@@ -6128,7 +6125,8 @@ Docs & License: https://fullcalendar.io/
6128
6125
  });
6129
6126
  };
6130
6127
  Toolbar.prototype.updateActiveButton = function (buttonName) {
6131
- var className = this.theme.getClass('buttonActive');
6128
+ var theme = this.context.theme;
6129
+ var className = theme.getClass('buttonActive');
6132
6130
  findElements(this.el, 'button').forEach(function (buttonEl) {
6133
6131
  if (buttonName && buttonEl.classList.contains('fc-' + buttonName + '-button')) {
6134
6132
  buttonEl.classList.add(className);
@@ -6148,24 +6146,29 @@ Docs & License: https://fullcalendar.io/
6148
6146
 
6149
6147
  var CalendarComponent = /** @class */ (function (_super) {
6150
6148
  __extends(CalendarComponent, _super);
6151
- function CalendarComponent(context, el) {
6152
- var _this = _super.call(this, context) || this;
6153
- _this._renderToolbars = memoizeRendering(_this.renderToolbars);
6149
+ function CalendarComponent(el) {
6150
+ var _this = _super.call(this) || this;
6151
+ _this.elClassNames = [];
6152
+ _this.renderSkeleton = memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
6153
+ _this.renderToolbars = memoizeRendering(_this._renderToolbars, _this._unrenderToolbars, [_this.renderSkeleton]);
6154
+ _this.buildComponentContext = memoize(buildComponentContext);
6154
6155
  _this.buildViewPropTransformers = memoize(buildViewPropTransformers);
6155
6156
  _this.el = el;
6156
- prependToElement(el, _this.contentEl = createElement('div', { className: 'fc-view-container' }));
6157
- var calendar = _this.calendar;
6158
- for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) {
6159
- var modifyViewContainer = _a[_i];
6160
- modifyViewContainer(_this.contentEl, calendar);
6161
- }
6162
- _this.toggleElClassNames(true);
6163
6157
  _this.computeTitle = memoize(computeTitle);
6164
6158
  _this.parseBusinessHours = memoize(function (input) {
6165
- return parseBusinessHours(input, _this.calendar);
6159
+ return parseBusinessHours(input, _this.context.calendar);
6166
6160
  });
6167
6161
  return _this;
6168
6162
  }
6163
+ CalendarComponent.prototype.render = function (props, context) {
6164
+ this.freezeHeight();
6165
+ var title = this.computeTitle(props.dateProfile, props.viewSpec.options);
6166
+ this.renderSkeleton(context);
6167
+ this.renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, title);
6168
+ this.renderView(props, title);
6169
+ this.updateSize();
6170
+ this.thawHeight();
6171
+ };
6169
6172
  CalendarComponent.prototype.destroy = function () {
6170
6173
  if (this.header) {
6171
6174
  this.header.destroy();
@@ -6173,40 +6176,57 @@ Docs & License: https://fullcalendar.io/
6173
6176
  if (this.footer) {
6174
6177
  this.footer.destroy();
6175
6178
  }
6179
+ this.renderSkeleton.unrender(); // will call destroyView
6180
+ _super.prototype.destroy.call(this);
6181
+ };
6182
+ CalendarComponent.prototype._renderSkeleton = function (context) {
6183
+ this.updateElClassNames(context);
6184
+ prependToElement(this.el, this.contentEl = createElement('div', { className: 'fc-view-container' }));
6185
+ var calendar = context.calendar;
6186
+ for (var _i = 0, _a = calendar.pluginSystem.hooks.viewContainerModifiers; _i < _a.length; _i++) {
6187
+ var modifyViewContainer = _a[_i];
6188
+ modifyViewContainer(this.contentEl, calendar);
6189
+ }
6190
+ };
6191
+ CalendarComponent.prototype._unrenderSkeleton = function () {
6192
+ // weird to have this here
6176
6193
  if (this.view) {
6194
+ this.savedScroll = this.view.queryScroll();
6177
6195
  this.view.destroy();
6196
+ this.view = null;
6178
6197
  }
6179
6198
  removeElement(this.contentEl);
6180
- this.toggleElClassNames(false);
6181
- _super.prototype.destroy.call(this);
6199
+ this.removeElClassNames();
6182
6200
  };
6183
- CalendarComponent.prototype.toggleElClassNames = function (bool) {
6201
+ CalendarComponent.prototype.removeElClassNames = function () {
6184
6202
  var classList = this.el.classList;
6185
- var dirClassName = 'fc-' + this.opt('dir');
6186
- var themeClassName = this.theme.getClass('widget');
6187
- if (bool) {
6188
- classList.add('fc');
6189
- classList.add(dirClassName);
6190
- classList.add(themeClassName);
6191
- }
6192
- else {
6193
- classList.remove('fc');
6194
- classList.remove(dirClassName);
6195
- classList.remove(themeClassName);
6196
- }
6197
- };
6198
- CalendarComponent.prototype.render = function (props) {
6199
- this.freezeHeight();
6200
- var title = this.computeTitle(props.dateProfile, props.viewSpec.options);
6201
- this._renderToolbars(props.viewSpec, props.dateProfile, props.currentDate, props.dateProfileGenerator, title);
6202
- this.renderView(props, title);
6203
- this.updateSize();
6204
- this.thawHeight();
6205
- };
6206
- CalendarComponent.prototype.renderToolbars = function (viewSpec, dateProfile, currentDate, dateProfileGenerator, title) {
6207
- var headerLayout = this.opt('header');
6208
- var footerLayout = this.opt('footer');
6209
- var now = this.calendar.getNow();
6203
+ for (var _i = 0, _a = this.elClassNames; _i < _a.length; _i++) {
6204
+ var className = _a[_i];
6205
+ classList.remove(className);
6206
+ }
6207
+ this.elClassNames = [];
6208
+ };
6209
+ CalendarComponent.prototype.updateElClassNames = function (context) {
6210
+ this.removeElClassNames();
6211
+ var theme = context.theme, options = context.options;
6212
+ this.elClassNames = [
6213
+ 'fc',
6214
+ 'fc-' + options.dir,
6215
+ theme.getClass('widget')
6216
+ ];
6217
+ var classList = this.el.classList;
6218
+ for (var _i = 0, _a = this.elClassNames; _i < _a.length; _i++) {
6219
+ var className = _a[_i];
6220
+ classList.add(className);
6221
+ }
6222
+ };
6223
+ CalendarComponent.prototype._renderToolbars = function (viewSpec, dateProfile, currentDate, title) {
6224
+ var _a = this, context = _a.context, header = _a.header, footer = _a.footer;
6225
+ var options = context.options, calendar = context.calendar;
6226
+ var headerLayout = options.header;
6227
+ var footerLayout = options.footer;
6228
+ var dateProfileGenerator = this.props.dateProfileGenerator;
6229
+ var now = calendar.getNow();
6210
6230
  var todayInfo = dateProfileGenerator.build(now);
6211
6231
  var prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate);
6212
6232
  var nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate);
@@ -6218,48 +6238,55 @@ Docs & License: https://fullcalendar.io/
6218
6238
  isNextEnabled: nextInfo.isValid
6219
6239
  };
6220
6240
  if (headerLayout) {
6221
- if (!this.header) {
6222
- this.header = new Toolbar(this.context, 'fc-header-toolbar');
6223
- prependToElement(this.el, this.header.el);
6241
+ if (!header) {
6242
+ header = this.header = new Toolbar('fc-header-toolbar');
6243
+ prependToElement(this.el, header.el);
6224
6244
  }
6225
- this.header.receiveProps(__assign({ layout: headerLayout }, toolbarProps));
6245
+ header.receiveProps(__assign({ layout: headerLayout }, toolbarProps), context);
6226
6246
  }
6227
- else if (this.header) {
6228
- this.header.destroy();
6229
- this.header = null;
6247
+ else if (header) {
6248
+ header.destroy();
6249
+ header = this.header = null;
6230
6250
  }
6231
6251
  if (footerLayout) {
6232
- if (!this.footer) {
6233
- this.footer = new Toolbar(this.context, 'fc-footer-toolbar');
6234
- appendToElement(this.el, this.footer.el);
6252
+ if (!footer) {
6253
+ footer = this.footer = new Toolbar('fc-footer-toolbar');
6254
+ appendToElement(this.el, footer.el);
6235
6255
  }
6236
- this.footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps));
6256
+ footer.receiveProps(__assign({ layout: footerLayout }, toolbarProps), context);
6257
+ }
6258
+ else if (footer) {
6259
+ footer.destroy();
6260
+ footer = this.footer = null;
6261
+ }
6262
+ };
6263
+ CalendarComponent.prototype._unrenderToolbars = function () {
6264
+ if (this.header) {
6265
+ this.header.destroy();
6266
+ this.header = null;
6237
6267
  }
6238
- else if (this.footer) {
6268
+ if (this.footer) {
6239
6269
  this.footer.destroy();
6240
6270
  this.footer = null;
6241
6271
  }
6242
6272
  };
6243
6273
  CalendarComponent.prototype.renderView = function (props, title) {
6244
6274
  var view = this.view;
6275
+ var _a = this.context, calendar = _a.calendar, options = _a.options;
6245
6276
  var viewSpec = props.viewSpec, dateProfileGenerator = props.dateProfileGenerator;
6246
6277
  if (!view || view.viewSpec !== viewSpec) {
6247
6278
  if (view) {
6248
6279
  view.destroy();
6249
6280
  }
6250
- view = this.view = new viewSpec['class']({
6251
- calendar: this.calendar,
6252
- view: null,
6253
- dateEnv: this.dateEnv,
6254
- theme: this.theme,
6255
- options: viewSpec.options
6256
- }, viewSpec, dateProfileGenerator, this.contentEl);
6257
- }
6258
- else {
6259
- view.addScroll(view.queryScroll());
6281
+ view = this.view = new viewSpec['class'](viewSpec, this.contentEl);
6282
+ if (this.savedScroll) {
6283
+ view.addScroll(this.savedScroll, true);
6284
+ this.savedScroll = null;
6285
+ }
6260
6286
  }
6261
6287
  view.title = title; // for the API
6262
6288
  var viewProps = {
6289
+ dateProfileGenerator: dateProfileGenerator,
6263
6290
  dateProfile: props.dateProfile,
6264
6291
  businessHours: this.parseBusinessHours(viewSpec.options.businessHours),
6265
6292
  eventStore: props.eventStore,
@@ -6269,20 +6296,20 @@ Docs & License: https://fullcalendar.io/
6269
6296
  eventDrag: props.eventDrag,
6270
6297
  eventResize: props.eventResize
6271
6298
  };
6272
- var transformers = this.buildViewPropTransformers(this.calendar.pluginSystem.hooks.viewPropsTransformers);
6299
+ var transformers = this.buildViewPropTransformers(calendar.pluginSystem.hooks.viewPropsTransformers);
6273
6300
  for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
6274
6301
  var transformer = transformers_1[_i];
6275
- __assign(viewProps, transformer.transform(viewProps, viewSpec, props, view));
6302
+ __assign(viewProps, transformer.transform(viewProps, viewSpec, props, options));
6276
6303
  }
6277
- view.receiveProps(viewProps);
6304
+ view.receiveProps(viewProps, this.buildComponentContext(this.context, viewSpec, view));
6278
6305
  };
6279
6306
  // Sizing
6280
6307
  // -----------------------------------------------------------------------------------------------------------------
6281
6308
  CalendarComponent.prototype.updateSize = function (isResize) {
6282
6309
  if (isResize === void 0) { isResize = false; }
6283
6310
  var view = this.view;
6284
- if (isResize) {
6285
- view.addScroll(view.queryScroll());
6311
+ if (!view) {
6312
+ return; // why?
6286
6313
  }
6287
6314
  if (isResize || this.isHeightAuto == null) {
6288
6315
  this.computeHeightVars();
@@ -6292,7 +6319,7 @@ Docs & License: https://fullcalendar.io/
6292
6319
  view.popScroll(isResize);
6293
6320
  };
6294
6321
  CalendarComponent.prototype.computeHeightVars = function () {
6295
- var calendar = this.calendar; // yuck. need to handle dynamic options
6322
+ var calendar = this.context.calendar; // yuck. need to handle dynamic options
6296
6323
  var heightInput = calendar.opt('height');
6297
6324
  var contentHeightInput = calendar.opt('contentHeight');
6298
6325
  this.isHeightAuto = heightInput === 'auto' || contentHeightInput === 'auto';
@@ -6355,7 +6382,7 @@ Docs & License: https://fullcalendar.io/
6355
6382
  else { // for day units or smaller, use the actual day range
6356
6383
  range = dateProfile.activeRange;
6357
6384
  }
6358
- return this.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
6385
+ return this.context.dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || computeTitleFormat(dateProfile), viewOptions.titleRangeSeparator), { isEndExclusive: dateProfile.isRangeAllDay });
6359
6386
  }
6360
6387
  // Generates the format string that should be used to generate the title for the current date range.
6361
6388
  // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
@@ -6379,6 +6406,10 @@ Docs & License: https://fullcalendar.io/
6379
6406
  }
6380
6407
  }
6381
6408
  }
6409
+ // build a context scoped to the view
6410
+ function buildComponentContext(context, viewSpec, view) {
6411
+ return context.extend(viewSpec.options, view);
6412
+ }
6382
6413
  // Plugin
6383
6414
  // -----------------------------------------------------------------------------------------------------------------
6384
6415
  function buildViewPropTransformers(theClasses) {
@@ -6420,6 +6451,7 @@ Docs & License: https://fullcalendar.io/
6420
6451
  var _this = _super.call(this, settings) || this;
6421
6452
  _this.handleSegClick = function (ev, segEl) {
6422
6453
  var component = _this.component;
6454
+ var _a = component.context, calendar = _a.calendar, view = _a.view;
6423
6455
  var seg = getElSeg(segEl);
6424
6456
  if (seg && // might be the <div> surrounding the more link
6425
6457
  component.isValidSegDownEl(ev.target)) {
@@ -6427,12 +6459,12 @@ Docs & License: https://fullcalendar.io/
6427
6459
  // grab before trigger fired in case trigger trashes DOM thru rerendering
6428
6460
  var hasUrlContainer = elementClosest(ev.target, '.fc-has-url');
6429
6461
  var url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
6430
- component.publiclyTrigger('eventClick', [
6462
+ calendar.publiclyTrigger('eventClick', [
6431
6463
  {
6432
6464
  el: segEl,
6433
- event: new EventApi(component.calendar, seg.eventRange.def, seg.eventRange.instance),
6465
+ event: new EventApi(component.context.calendar, seg.eventRange.def, seg.eventRange.instance),
6434
6466
  jsEvent: ev,
6435
- view: component.view
6467
+ view: view
6436
6468
  }
6437
6469
  ]);
6438
6470
  if (url && !ev.defaultPrevented) {
@@ -6477,23 +6509,25 @@ Docs & License: https://fullcalendar.io/
6477
6509
  };
6478
6510
  var component = settings.component;
6479
6511
  _this.removeHoverListeners = listenToHoverBySelector(component.el, component.fgSegSelector + ',' + component.bgSegSelector, _this.handleSegEnter, _this.handleSegLeave);
6480
- component.calendar.on('eventElRemove', _this.handleEventElRemove);
6512
+ // how to make sure component already has context?
6513
+ component.context.calendar.on('eventElRemove', _this.handleEventElRemove);
6481
6514
  return _this;
6482
6515
  }
6483
6516
  EventHovering.prototype.destroy = function () {
6484
6517
  this.removeHoverListeners();
6485
- this.component.calendar.off('eventElRemove', this.handleEventElRemove);
6518
+ this.component.context.calendar.off('eventElRemove', this.handleEventElRemove);
6486
6519
  };
6487
6520
  EventHovering.prototype.triggerEvent = function (publicEvName, ev, segEl) {
6488
6521
  var component = this.component;
6522
+ var _a = component.context, calendar = _a.calendar, view = _a.view;
6489
6523
  var seg = getElSeg(segEl);
6490
6524
  if (!ev || component.isValidSegDownEl(ev.target)) {
6491
- component.publiclyTrigger(publicEvName, [
6525
+ calendar.publiclyTrigger(publicEvName, [
6492
6526
  {
6493
6527
  el: segEl,
6494
- event: new EventApi(this.component.calendar, seg.eventRange.def, seg.eventRange.instance),
6528
+ event: new EventApi(calendar, seg.eventRange.def, seg.eventRange.instance),
6495
6529
  jsEvent: ev,
6496
- view: component.view
6530
+ view: view
6497
6531
  }
6498
6532
  ]);
6499
6533
  }
@@ -6538,6 +6572,7 @@ Docs & License: https://fullcalendar.io/
6538
6572
  var Calendar = /** @class */ (function () {
6539
6573
  function Calendar(el, overrides) {
6540
6574
  var _this = this;
6575
+ this.buildComponentContext = memoize(buildComponentContext$1);
6541
6576
  this.parseRawLocales = memoize(parseRawLocales);
6542
6577
  this.buildLocale = memoize(buildLocale);
6543
6578
  this.buildDateEnv = memoize(buildDateEnv);
@@ -6551,7 +6586,6 @@ Docs & License: https://fullcalendar.io/
6551
6586
  this.isReducing = false;
6552
6587
  // isDisplaying: boolean = false // installed in DOM? accepting renders?
6553
6588
  this.needsRerender = false; // needs a render?
6554
- this.needsFullRerender = false;
6555
6589
  this.isRendering = false; // currently in the executeRender function?
6556
6590
  this.renderingPauseDepth = 0;
6557
6591
  this.buildDelayedRerender = memoize(buildDelayedRerender);
@@ -6591,12 +6625,13 @@ Docs & License: https://fullcalendar.io/
6591
6625
  // -----------------------------------------------------------------------------------------------------------------
6592
6626
  Calendar.prototype.render = function () {
6593
6627
  if (!this.component) {
6628
+ this.component = new CalendarComponent(this.el);
6594
6629
  this.renderableEventStore = createEmptyEventStore();
6595
6630
  this.bindHandlers();
6596
6631
  this.executeRender();
6597
6632
  }
6598
6633
  else {
6599
- this.requestRerender(true);
6634
+ this.requestRerender();
6600
6635
  }
6601
6636
  };
6602
6637
  Calendar.prototype.destroy = function () {
@@ -6705,12 +6740,12 @@ Docs & License: https://fullcalendar.io/
6705
6740
  this.publiclyTrigger('loading', [false]);
6706
6741
  }
6707
6742
  var view = this.component && this.component.view;
6708
- if (oldState.eventStore !== newState.eventStore || this.needsFullRerender) {
6743
+ if (oldState.eventStore !== newState.eventStore) {
6709
6744
  if (oldState.eventStore) {
6710
6745
  this.isEventsUpdated = true;
6711
6746
  }
6712
6747
  }
6713
- if (oldState.dateProfile !== newState.dateProfile || this.needsFullRerender) {
6748
+ if (oldState.dateProfile !== newState.dateProfile) {
6714
6749
  if (oldState.dateProfile && view) { // why would view be null!?
6715
6750
  this.publiclyTrigger('datesDestroy', [
6716
6751
  {
@@ -6721,7 +6756,7 @@ Docs & License: https://fullcalendar.io/
6721
6756
  }
6722
6757
  this.isDatesUpdated = true;
6723
6758
  }
6724
- if (oldState.viewType !== newState.viewType || this.needsFullRerender) {
6759
+ if (oldState.viewType !== newState.viewType) {
6725
6760
  if (oldState.viewType && view) { // why would view be null!?
6726
6761
  this.publiclyTrigger('viewSkeletonDestroy', [
6727
6762
  {
@@ -6740,10 +6775,8 @@ Docs & License: https://fullcalendar.io/
6740
6775
  };
6741
6776
  // Render Queue
6742
6777
  // -----------------------------------------------------------------------------------------------------------------
6743
- Calendar.prototype.requestRerender = function (needsFull) {
6744
- if (needsFull === void 0) { needsFull = false; }
6778
+ Calendar.prototype.requestRerender = function () {
6745
6779
  this.needsRerender = true;
6746
- this.needsFullRerender = this.needsFullRerender || needsFull;
6747
6780
  this.delayedRerender(); // will call a debounced-version of tryRerender
6748
6781
  };
6749
6782
  Calendar.prototype.tryRerender = function () {
@@ -6766,12 +6799,10 @@ Docs & License: https://fullcalendar.io/
6766
6799
  // Rendering
6767
6800
  // -----------------------------------------------------------------------------------------------------------------
6768
6801
  Calendar.prototype.executeRender = function () {
6769
- var needsFullRerender = this.needsFullRerender; // save before clearing
6770
6802
  // clear these BEFORE the render so that new values will accumulate during render
6771
6803
  this.needsRerender = false;
6772
- this.needsFullRerender = false;
6773
6804
  this.isRendering = true;
6774
- this.renderComponent(needsFullRerender);
6805
+ this.renderComponent();
6775
6806
  this.isRendering = false;
6776
6807
  // received a rerender request while rendering
6777
6808
  if (this.needsRerender) {
@@ -6781,11 +6812,10 @@ Docs & License: https://fullcalendar.io/
6781
6812
  /*
6782
6813
  don't call this directly. use executeRender instead
6783
6814
  */
6784
- Calendar.prototype.renderComponent = function (needsFull) {
6815
+ Calendar.prototype.renderComponent = function () {
6785
6816
  var _a = this, state = _a.state, component = _a.component;
6786
6817
  var viewType = state.viewType;
6787
6818
  var viewSpec = this.viewSpecs[viewType];
6788
- var savedScroll = (needsFull && component) ? component.view.queryScroll() : null;
6789
6819
  if (!viewSpec) {
6790
6820
  throw new Error("View type \"" + viewType + "\" is not valid");
6791
6821
  }
@@ -6798,26 +6828,7 @@ Docs & License: https://fullcalendar.io/
6798
6828
  var eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options);
6799
6829
  var eventUiBySource = this.buildEventUiBySource(state.eventSources);
6800
6830
  var eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
6801
- if (needsFull || !component) {
6802
- if (component) {
6803
- component.freezeHeight(); // next component will unfreeze it
6804
- component.destroy();
6805
- }
6806
- component = this.component = new CalendarComponent({
6807
- calendar: this,
6808
- view: null,
6809
- dateEnv: this.dateEnv,
6810
- theme: this.theme,
6811
- options: this.optionsManager.computed
6812
- }, this.el);
6813
- this.isViewUpdated = true;
6814
- this.isDatesUpdated = true;
6815
- this.isEventsUpdated = true;
6816
- }
6817
- component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfile: state.dateProfile, dateProfileGenerator: this.dateProfileGenerators[viewType], eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize }));
6818
- if (savedScroll) {
6819
- component.view.applyScroll(savedScroll, false);
6820
- }
6831
+ component.receiveProps(__assign({}, state, { viewSpec: viewSpec, dateProfileGenerator: this.dateProfileGenerators[viewType], dateProfile: state.dateProfile, eventStore: renderableEventStore, eventUiBases: eventUiBases, dateSelection: state.dateSelection, eventSelection: state.eventSelection, eventDrag: state.eventDrag, eventResize: state.eventResize }), this.buildComponentContext(this.theme, this.dateEnv, this.optionsManager.computed));
6821
6832
  if (this.isViewUpdated) {
6822
6833
  this.isViewUpdated = false;
6823
6834
  this.publiclyTrigger('viewSkeletonRender', [
@@ -6894,7 +6905,6 @@ Docs & License: https://fullcalendar.io/
6894
6905
  this.optionsManager.mutate(normalUpdates, removals, isDynamic);
6895
6906
  if (anyDifficultOptions) {
6896
6907
  this.handleOptions(this.optionsManager.computed);
6897
- this.needsFullRerender = true;
6898
6908
  }
6899
6909
  this.batchRendering(function () {
6900
6910
  if (anyDifficultOptions) {
@@ -6905,7 +6915,7 @@ Docs & License: https://fullcalendar.io/
6905
6915
  });
6906
6916
  }
6907
6917
  /* HACK
6908
- has the same effect as calling this.requestRerender(true)
6918
+ has the same effect as calling this.requestRerender()
6909
6919
  but recomputes the state's dateProfile
6910
6920
  */
6911
6921
  _this.dispatch({
@@ -7411,6 +7421,9 @@ Docs & License: https://fullcalendar.io/
7411
7421
  EmitterMixin.mixInto(Calendar);
7412
7422
  // for memoizers
7413
7423
  // -----------------------------------------------------------------------------------------------------------------
7424
+ function buildComponentContext$1(theme, dateEnv, options) {
7425
+ return new ComponentContext(this, theme, dateEnv, options, null);
7426
+ }
7414
7427
  function buildDateEnv(locale, timeZone, namedTimeZoneImpl, firstDay, weekNumberCalculation, weekLabel, cmdFormatter) {
7415
7428
  return new DateEnv({
7416
7429
  calendarSystem: 'gregory',
@@ -7452,9 +7465,8 @@ Docs & License: https://fullcalendar.io/
7452
7465
 
7453
7466
  var View = /** @class */ (function (_super) {
7454
7467
  __extends(View, _super);
7455
- function View(context, viewSpec, dateProfileGenerator, parentEl) {
7456
- var _this = _super.call(this, context, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' }), true // isView (HACK)
7457
- ) || this;
7468
+ function View(viewSpec, parentEl) {
7469
+ var _this = _super.call(this, createElement('div', { className: 'fc-view fc-' + viewSpec.type + '-view' })) || this;
7458
7470
  _this.renderDatesMem = memoizeRendering(_this.renderDatesWrap, _this.unrenderDatesWrap);
7459
7471
  _this.renderBusinessHoursMem = memoizeRendering(_this.renderBusinessHours, _this.unrenderBusinessHours, [_this.renderDatesMem]);
7460
7472
  _this.renderDateSelectionMem = memoizeRendering(_this.renderDateSelectionWrap, _this.unrenderDateSelectionWrap, [_this.renderDatesMem]);
@@ -7463,10 +7475,7 @@ Docs & License: https://fullcalendar.io/
7463
7475
  _this.renderEventDragMem = memoizeRendering(_this.renderEventDragWrap, _this.unrenderEventDragWrap, [_this.renderDatesMem]);
7464
7476
  _this.renderEventResizeMem = memoizeRendering(_this.renderEventResizeWrap, _this.unrenderEventResizeWrap, [_this.renderDatesMem]);
7465
7477
  _this.viewSpec = viewSpec;
7466
- _this.dateProfileGenerator = dateProfileGenerator;
7467
7478
  _this.type = viewSpec.type;
7468
- _this.eventOrderSpecs = parseFieldSpecs(_this.opt('eventOrder'));
7469
- _this.nextDayThreshold = createDuration(_this.opt('nextDayThreshold'));
7470
7479
  parentEl.appendChild(_this.el);
7471
7480
  _this.initialize();
7472
7481
  return _this;
@@ -7477,35 +7486,35 @@ Docs & License: https://fullcalendar.io/
7477
7486
  // Date Setting/Unsetting
7478
7487
  // -----------------------------------------------------------------------------------------------------------------
7479
7488
  get: function () {
7480
- return this.dateEnv.toDate(this.props.dateProfile.activeRange.start);
7489
+ return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.start);
7481
7490
  },
7482
7491
  enumerable: true,
7483
7492
  configurable: true
7484
7493
  });
7485
7494
  Object.defineProperty(View.prototype, "activeEnd", {
7486
7495
  get: function () {
7487
- return this.dateEnv.toDate(this.props.dateProfile.activeRange.end);
7496
+ return this.context.dateEnv.toDate(this.props.dateProfile.activeRange.end);
7488
7497
  },
7489
7498
  enumerable: true,
7490
7499
  configurable: true
7491
7500
  });
7492
7501
  Object.defineProperty(View.prototype, "currentStart", {
7493
7502
  get: function () {
7494
- return this.dateEnv.toDate(this.props.dateProfile.currentRange.start);
7503
+ return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.start);
7495
7504
  },
7496
7505
  enumerable: true,
7497
7506
  configurable: true
7498
7507
  });
7499
7508
  Object.defineProperty(View.prototype, "currentEnd", {
7500
7509
  get: function () {
7501
- return this.dateEnv.toDate(this.props.dateProfile.currentRange.end);
7510
+ return this.context.dateEnv.toDate(this.props.dateProfile.currentRange.end);
7502
7511
  },
7503
7512
  enumerable: true,
7504
7513
  configurable: true
7505
7514
  });
7506
7515
  // General Rendering
7507
7516
  // -----------------------------------------------------------------------------------------------------------------
7508
- View.prototype.render = function (props) {
7517
+ View.prototype.render = function (props, context) {
7509
7518
  this.renderDatesMem(props.dateProfile);
7510
7519
  this.renderBusinessHoursMem(props.businessHours);
7511
7520
  this.renderDateSelectionMem(props.dateSelection);
@@ -7514,6 +7523,9 @@ Docs & License: https://fullcalendar.io/
7514
7523
  this.renderEventDragMem(props.eventDrag);
7515
7524
  this.renderEventResizeMem(props.eventResize);
7516
7525
  };
7526
+ View.prototype.beforeUpdate = function () {
7527
+ this.addScroll(this.queryScroll());
7528
+ };
7517
7529
  View.prototype.destroy = function () {
7518
7530
  _super.prototype.destroy.call(this);
7519
7531
  this.renderDatesMem.unrender(); // should unrender everything else
@@ -7521,7 +7533,10 @@ Docs & License: https://fullcalendar.io/
7521
7533
  // Sizing
7522
7534
  // -----------------------------------------------------------------------------------------------------------------
7523
7535
  View.prototype.updateSize = function (isResize, viewHeight, isAuto) {
7524
- var calendar = this.calendar;
7536
+ var calendar = this.context.calendar;
7537
+ if (isResize) {
7538
+ this.addScroll(this.queryScroll()); // NOTE: same code as in beforeUpdate
7539
+ }
7525
7540
  if (isResize || // HACKS...
7526
7541
  calendar.isViewUpdated ||
7527
7542
  calendar.isDatesUpdated ||
@@ -7530,6 +7545,7 @@ Docs & License: https://fullcalendar.io/
7530
7545
  // anything that might cause dimension changes
7531
7546
  this.updateBaseSize(isResize, viewHeight, isAuto);
7532
7547
  }
7548
+ // NOTE: popScroll is called by CalendarComponent
7533
7549
  };
7534
7550
  View.prototype.updateBaseSize = function (isResize, viewHeight, isAuto) {
7535
7551
  };
@@ -7538,9 +7554,8 @@ Docs & License: https://fullcalendar.io/
7538
7554
  View.prototype.renderDatesWrap = function (dateProfile) {
7539
7555
  this.renderDates(dateProfile);
7540
7556
  this.addScroll({
7541
- duration: createDuration(this.opt('scrollTime'))
7557
+ duration: createDuration(this.context.options.scrollTime)
7542
7558
  });
7543
- this.startNowIndicator(dateProfile); // shouldn't render yet because updateSize will be called soon
7544
7559
  };
7545
7560
  View.prototype.unrenderDatesWrap = function () {
7546
7561
  this.stopNowIndicator();
@@ -7573,22 +7588,7 @@ Docs & License: https://fullcalendar.io/
7573
7588
  // util for subclasses
7574
7589
  View.prototype.sliceEvents = function (eventStore, allDay) {
7575
7590
  var props = this.props;
7576
- return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.nextDayThreshold : null).fg;
7577
- };
7578
- View.prototype.computeEventDraggable = function (eventDef, eventUi) {
7579
- var transformers = this.calendar.pluginSystem.hooks.isDraggableTransformers;
7580
- var val = eventUi.startEditable;
7581
- for (var _i = 0, transformers_1 = transformers; _i < transformers_1.length; _i++) {
7582
- var transformer = transformers_1[_i];
7583
- val = transformer(val, eventDef, eventUi, this);
7584
- }
7585
- return val;
7586
- };
7587
- View.prototype.computeEventStartResizable = function (eventDef, eventUi) {
7588
- return eventUi.durationEditable && this.opt('eventResizableFromStart');
7589
- };
7590
- View.prototype.computeEventEndResizable = function (eventDef, eventUi) {
7591
- return eventUi.durationEditable;
7591
+ return sliceEventStore(eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? this.context.nextDayThreshold : null).fg;
7592
7592
  };
7593
7593
  // Event Selection
7594
7594
  // -----------------------------------------------------------------------------------------------------------------
@@ -7637,17 +7637,18 @@ Docs & License: https://fullcalendar.io/
7637
7637
  // Immediately render the current time indicator and begins re-rendering it at an interval,
7638
7638
  // which is defined by this.getNowIndicatorUnit().
7639
7639
  // TODO: somehow do this for the current whole day's background too
7640
- View.prototype.startNowIndicator = function (dateProfile) {
7640
+ // USAGE: must be called manually from subclasses' render methods! don't need to call stopNowIndicator tho
7641
+ View.prototype.startNowIndicator = function (dateProfile, dateProfileGenerator) {
7641
7642
  var _this = this;
7642
- var dateEnv = this.dateEnv;
7643
+ var _a = this.context, calendar = _a.calendar, dateEnv = _a.dateEnv, options = _a.options;
7643
7644
  var unit;
7644
7645
  var update;
7645
7646
  var delay; // ms wait value
7646
- if (this.opt('nowIndicator')) {
7647
- unit = this.getNowIndicatorUnit(dateProfile);
7647
+ if (options.nowIndicator && !this.initialNowDate) {
7648
+ unit = this.getNowIndicatorUnit(dateProfile, dateProfileGenerator);
7648
7649
  if (unit) {
7649
7650
  update = this.updateNowIndicator.bind(this);
7650
- this.initialNowDate = this.calendar.getNow();
7651
+ this.initialNowDate = calendar.getNow();
7651
7652
  this.initialNowQueriedMs = new Date().valueOf();
7652
7653
  // wait until the beginning of the next interval
7653
7654
  delay = dateEnv.add(dateEnv.startOf(this.initialNowDate, unit), createDuration(1, unit)).valueOf() - this.initialNowDate.valueOf();
@@ -7681,20 +7682,20 @@ Docs & License: https://fullcalendar.io/
7681
7682
  // Immediately unrenders the view's current time indicator and stops any re-rendering timers.
7682
7683
  // Won't cause side effects if indicator isn't rendered.
7683
7684
  View.prototype.stopNowIndicator = function () {
7685
+ if (this.nowIndicatorTimeoutID) {
7686
+ clearTimeout(this.nowIndicatorTimeoutID);
7687
+ this.nowIndicatorTimeoutID = null;
7688
+ }
7689
+ if (this.nowIndicatorIntervalID) {
7690
+ clearInterval(this.nowIndicatorIntervalID);
7691
+ this.nowIndicatorIntervalID = null;
7692
+ }
7684
7693
  if (this.isNowIndicatorRendered) {
7685
- if (this.nowIndicatorTimeoutID) {
7686
- clearTimeout(this.nowIndicatorTimeoutID);
7687
- this.nowIndicatorTimeoutID = null;
7688
- }
7689
- if (this.nowIndicatorIntervalID) {
7690
- clearInterval(this.nowIndicatorIntervalID);
7691
- this.nowIndicatorIntervalID = null;
7692
- }
7693
7694
  this.unrenderNowIndicator();
7694
7695
  this.isNowIndicatorRendered = false;
7695
7696
  }
7696
7697
  };
7697
- View.prototype.getNowIndicatorUnit = function (dateProfile) {
7698
+ View.prototype.getNowIndicatorUnit = function (dateProfile, dateProfileGenerator) {
7698
7699
  // subclasses should implement
7699
7700
  };
7700
7701
  // Renders a current time indicator at the given datetime
@@ -7707,16 +7708,20 @@ Docs & License: https://fullcalendar.io/
7707
7708
  };
7708
7709
  /* Scroller
7709
7710
  ------------------------------------------------------------------------------------------------------------------*/
7710
- View.prototype.addScroll = function (scroll) {
7711
- var queuedScroll = this.queuedScroll || (this.queuedScroll = {});
7712
- __assign(queuedScroll, scroll);
7711
+ View.prototype.addScroll = function (scroll, isForced) {
7712
+ if (isForced) {
7713
+ scroll.isForced = isForced;
7714
+ }
7715
+ __assign(this.queuedScroll || (this.queuedScroll = {}), scroll);
7713
7716
  };
7714
7717
  View.prototype.popScroll = function (isResize) {
7715
7718
  this.applyQueuedScroll(isResize);
7716
7719
  this.queuedScroll = null;
7717
7720
  };
7718
7721
  View.prototype.applyQueuedScroll = function (isResize) {
7719
- this.applyScroll(this.queuedScroll || {}, isResize);
7722
+ if (this.queuedScroll) {
7723
+ this.applyScroll(this.queuedScroll, isResize);
7724
+ }
7720
7725
  };
7721
7726
  View.prototype.queryScroll = function () {
7722
7727
  var scroll = {};
@@ -7726,8 +7731,8 @@ Docs & License: https://fullcalendar.io/
7726
7731
  return scroll;
7727
7732
  };
7728
7733
  View.prototype.applyScroll = function (scroll, isResize) {
7729
- var duration = scroll.duration;
7730
- if (duration != null) {
7734
+ var duration = scroll.duration, isForced = scroll.isForced;
7735
+ if (duration != null && !isForced) {
7731
7736
  delete scroll.duration;
7732
7737
  if (this.props.dateProfile) { // dates rendered yet?
7733
7738
  __assign(scroll, this.computeDateScroll(duration));
@@ -7757,12 +7762,12 @@ Docs & License: https://fullcalendar.io/
7757
7762
  View.prototype.dateProfileGeneratorClass = DateProfileGenerator;
7758
7763
 
7759
7764
  var FgEventRenderer = /** @class */ (function () {
7760
- function FgEventRenderer(context) {
7765
+ function FgEventRenderer() {
7761
7766
  this.segs = [];
7762
7767
  this.isSizeDirty = false;
7763
- this.context = context;
7764
7768
  }
7765
- FgEventRenderer.prototype.renderSegs = function (segs, mirrorInfo) {
7769
+ FgEventRenderer.prototype.renderSegs = function (context, segs, mirrorInfo) {
7770
+ this.context = context;
7766
7771
  this.rangeUpdated(); // called too frequently :(
7767
7772
  // render an `.el` on each seg
7768
7773
  // returns a subset of the segs. segs that were actually rendered
@@ -7770,10 +7775,10 @@ Docs & License: https://fullcalendar.io/
7770
7775
  this.segs = segs;
7771
7776
  this.attachSegs(segs, mirrorInfo);
7772
7777
  this.isSizeDirty = true;
7773
- this.context.view.triggerRenderedSegs(this.segs, Boolean(mirrorInfo));
7778
+ triggerRenderedSegs(this.context, this.segs, Boolean(mirrorInfo));
7774
7779
  };
7775
- FgEventRenderer.prototype.unrender = function (_segs, mirrorInfo) {
7776
- this.context.view.triggerWillRemoveSegs(this.segs, Boolean(mirrorInfo));
7780
+ FgEventRenderer.prototype.unrender = function (context, _segs, mirrorInfo) {
7781
+ triggerWillRemoveSegs(this.context, this.segs, Boolean(mirrorInfo));
7777
7782
  this.detachSegs(this.segs);
7778
7783
  this.segs = [];
7779
7784
  };
@@ -7812,7 +7817,7 @@ Docs & License: https://fullcalendar.io/
7812
7817
  seg.el = el;
7813
7818
  }
7814
7819
  });
7815
- segs = filterSegsViaEls(this.context.view, segs, Boolean(mirrorInfo));
7820
+ segs = filterSegsViaEls(this.context, segs, Boolean(mirrorInfo));
7816
7821
  }
7817
7822
  return segs;
7818
7823
  };
@@ -7894,7 +7899,7 @@ Docs & License: https://fullcalendar.io/
7894
7899
  };
7895
7900
  };
7896
7901
  FgEventRenderer.prototype.sortEventSegs = function (segs) {
7897
- var specs = this.context.view.eventOrderSpecs;
7902
+ var specs = this.context.eventOrderSpecs;
7898
7903
  var objs = segs.map(buildSegCompareObj);
7899
7904
  objs.sort(function (obj0, obj1) {
7900
7905
  return compareByFieldSpecs(obj0, obj1, specs);
@@ -7975,19 +7980,22 @@ Docs & License: https://fullcalendar.io/
7975
7980
  });
7976
7981
  }
7977
7982
 
7983
+ /*
7984
+ TODO: when refactoring this class, make a new FillRenderer instance for each `type`
7985
+ */
7978
7986
  var FillRenderer = /** @class */ (function () {
7979
- function FillRenderer(context) {
7987
+ function FillRenderer() {
7980
7988
  this.fillSegTag = 'div';
7981
7989
  this.dirtySizeFlags = {};
7982
- this.context = context;
7983
7990
  this.containerElsByType = {};
7984
7991
  this.segsByType = {};
7985
7992
  }
7986
7993
  FillRenderer.prototype.getSegsByType = function (type) {
7987
7994
  return this.segsByType[type] || [];
7988
7995
  };
7989
- FillRenderer.prototype.renderSegs = function (type, segs) {
7996
+ FillRenderer.prototype.renderSegs = function (type, context, segs) {
7990
7997
  var _a;
7998
+ this.context = context;
7991
7999
  var renderedSegs = this.renderSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs
7992
8000
  var containerEls = this.attachSegs(type, renderedSegs);
7993
8001
  if (containerEls) {
@@ -7995,16 +8003,16 @@ Docs & License: https://fullcalendar.io/
7995
8003
  }
7996
8004
  this.segsByType[type] = renderedSegs;
7997
8005
  if (type === 'bgEvent') {
7998
- this.context.view.triggerRenderedSegs(renderedSegs, false); // isMirror=false
8006
+ triggerRenderedSegs(context, renderedSegs, false); // isMirror=false
7999
8007
  }
8000
8008
  this.dirtySizeFlags[type] = true;
8001
8009
  };
8002
8010
  // Unrenders a specific type of fill that is currently rendered on the grid
8003
- FillRenderer.prototype.unrender = function (type) {
8011
+ FillRenderer.prototype.unrender = function (type, context) {
8004
8012
  var segs = this.segsByType[type];
8005
8013
  if (segs) {
8006
8014
  if (type === 'bgEvent') {
8007
- this.context.view.triggerWillRemoveSegs(segs, false); // isMirror=false
8015
+ triggerWillRemoveSegs(context, segs, false); // isMirror=false
8008
8016
  }
8009
8017
  this.detachSegs(type, segs);
8010
8018
  }
@@ -8029,7 +8037,7 @@ Docs & License: https://fullcalendar.io/
8029
8037
  }
8030
8038
  });
8031
8039
  if (type === 'bgEvent') {
8032
- segs = filterSegsViaEls(this.context.view, segs, false // isMirror. background events can never be mirror elements
8040
+ segs = filterSegsViaEls(this.context, segs, false // isMirror. background events can never be mirror elements
8033
8041
  );
8034
8042
  }
8035
8043
  // correct element type? (would be bad if a non-TD were inserted into a table for example)
@@ -8195,7 +8203,7 @@ Docs & License: https://fullcalendar.io/
8195
8203
  }
8196
8204
  }
8197
8205
  function renderDateCell(dateMarker, dateProfile, datesRepDistinctDays, colCnt, colHeadFormat, context, colspan, otherAttrs) {
8198
- var view = context.view, dateEnv = context.dateEnv, theme = context.theme, options = context.options;
8206
+ var dateEnv = context.dateEnv, theme = context.theme, options = context.options;
8199
8207
  var isDateValid = rangeContainsMarker(dateProfile.activeRange, dateMarker); // TODO: called too frequently. cache somehow.
8200
8208
  var classNames = [
8201
8209
  'fc-day-header',
@@ -8235,7 +8243,7 @@ Docs & License: https://fullcalendar.io/
8235
8243
  '>' +
8236
8244
  (isDateValid ?
8237
8245
  // don't make a link if the heading could represent multiple days, or if there's only one day (forceOff)
8238
- buildGotoAnchorHtml(view, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
8246
+ buildGotoAnchorHtml(options, dateEnv, { date: dateMarker, forceOff: !datesRepDistinctDays || colCnt === 1 }, innerHtml) :
8239
8247
  // if not valid, display text, but no link
8240
8248
  innerHtml) +
8241
8249
  '</th>';
@@ -8243,37 +8251,48 @@ Docs & License: https://fullcalendar.io/
8243
8251
 
8244
8252
  var DayHeader = /** @class */ (function (_super) {
8245
8253
  __extends(DayHeader, _super);
8246
- function DayHeader(context, parentEl) {
8247
- var _this = _super.call(this, context) || this;
8248
- parentEl.innerHTML = ''; // because might be nbsp
8249
- parentEl.appendChild(_this.el = htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' +
8250
- '<table class="' + _this.theme.getClass('tableGrid') + '">' +
8251
- '<thead></thead>' +
8252
- '</table>' +
8253
- '</div>'));
8254
- _this.thead = _this.el.querySelector('thead');
8254
+ function DayHeader(parentEl) {
8255
+ var _this = _super.call(this) || this;
8256
+ _this.renderSkeleton = memoizeRendering(_this._renderSkeleton, _this._unrenderSkeleton);
8257
+ _this.parentEl = parentEl;
8255
8258
  return _this;
8256
8259
  }
8257
- DayHeader.prototype.destroy = function () {
8258
- removeElement(this.el);
8259
- };
8260
- DayHeader.prototype.render = function (props) {
8260
+ DayHeader.prototype.render = function (props, context) {
8261
8261
  var dates = props.dates, datesRepDistinctDays = props.datesRepDistinctDays;
8262
8262
  var parts = [];
8263
+ this.renderSkeleton(context);
8263
8264
  if (props.renderIntroHtml) {
8264
8265
  parts.push(props.renderIntroHtml());
8265
8266
  }
8266
- var colHeadFormat = createFormatter(this.opt('columnHeaderFormat') ||
8267
+ var colHeadFormat = createFormatter(context.options.columnHeaderFormat ||
8267
8268
  computeFallbackHeaderFormat(datesRepDistinctDays, dates.length));
8268
8269
  for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {
8269
8270
  var date = dates_1[_i];
8270
- parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, this.context));
8271
+ parts.push(renderDateCell(date, props.dateProfile, datesRepDistinctDays, dates.length, colHeadFormat, context));
8271
8272
  }
8272
- if (this.isRtl) {
8273
+ if (context.isRtl) {
8273
8274
  parts.reverse();
8274
8275
  }
8275
8276
  this.thead.innerHTML = '<tr>' + parts.join('') + '</tr>';
8276
8277
  };
8278
+ DayHeader.prototype.destroy = function () {
8279
+ _super.prototype.destroy.call(this);
8280
+ this.renderSkeleton.unrender();
8281
+ };
8282
+ DayHeader.prototype._renderSkeleton = function (context) {
8283
+ var theme = context.theme;
8284
+ var parentEl = this.parentEl;
8285
+ parentEl.innerHTML = ''; // because might be nbsp
8286
+ parentEl.appendChild(this.el = htmlToElement('<div class="fc-row ' + theme.getClass('headerRow') + '">' +
8287
+ '<table class="' + theme.getClass('tableGrid') + '">' +
8288
+ '<thead></thead>' +
8289
+ '</table>' +
8290
+ '</div>'));
8291
+ this.thead = this.el.querySelector('thead');
8292
+ };
8293
+ DayHeader.prototype._unrenderSkeleton = function () {
8294
+ removeElement(this.el);
8295
+ };
8277
8296
  return DayHeader;
8278
8297
  }(Component));
8279
8298
 
@@ -8422,16 +8441,16 @@ Docs & License: https://fullcalendar.io/
8422
8441
  this.sliceEventDrag = memoize(this._sliceInteraction);
8423
8442
  this.sliceEventResize = memoize(this._sliceInteraction);
8424
8443
  }
8425
- Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, component) {
8444
+ Slicer.prototype.sliceProps = function (props, dateProfile, nextDayThreshold, calendar, component) {
8426
8445
  var extraArgs = [];
8427
- for (var _i = 4; _i < arguments.length; _i++) {
8428
- extraArgs[_i - 4] = arguments[_i];
8446
+ for (var _i = 5; _i < arguments.length; _i++) {
8447
+ extraArgs[_i - 5] = arguments[_i];
8429
8448
  }
8430
8449
  var eventUiBases = props.eventUiBases;
8431
8450
  var eventSegs = this.sliceEventStore.apply(this, [props.eventStore, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs));
8432
8451
  return {
8433
8452
  dateSelectionSegs: this.sliceDateSelection.apply(this, [props.dateSelection, eventUiBases, component].concat(extraArgs)),
8434
- businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, component].concat(extraArgs)),
8453
+ businessHourSegs: this.sliceBusinessHours.apply(this, [props.businessHours, dateProfile, nextDayThreshold, calendar, component].concat(extraArgs)),
8435
8454
  fgEventSegs: eventSegs.fg,
8436
8455
  bgEventSegs: eventSegs.bg,
8437
8456
  eventDrag: this.sliceEventDrag.apply(this, [props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, component].concat(extraArgs)),
@@ -8449,15 +8468,15 @@ Docs & License: https://fullcalendar.io/
8449
8468
  {},
8450
8469
  component].concat(extraArgs));
8451
8470
  };
8452
- Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, component) {
8471
+ Slicer.prototype._sliceBusinessHours = function (businessHours, dateProfile, nextDayThreshold, calendar, component) {
8453
8472
  var extraArgs = [];
8454
- for (var _i = 4; _i < arguments.length; _i++) {
8455
- extraArgs[_i - 4] = arguments[_i];
8473
+ for (var _i = 5; _i < arguments.length; _i++) {
8474
+ extraArgs[_i - 5] = arguments[_i];
8456
8475
  }
8457
8476
  if (!businessHours) {
8458
8477
  return [];
8459
8478
  }
8460
- return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), component.calendar),
8479
+ return this._sliceEventStore.apply(this, [expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), calendar),
8461
8480
  {},
8462
8481
  dateProfile,
8463
8482
  nextDayThreshold,
@@ -8503,7 +8522,7 @@ Docs & License: https://fullcalendar.io/
8503
8522
  if (!dateSpan) {
8504
8523
  return [];
8505
8524
  }
8506
- var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.calendar);
8525
+ var eventRange = fabricateEventRange(dateSpan, eventUiBases, component.context.calendar);
8507
8526
  var segs = this.sliceRange.apply(this, [dateSpan.range].concat(extraArgs));
8508
8527
  for (var _a = 0, segs_1 = segs; _a < segs_1.length; _a++) {
8509
8528
  var seg = segs_1[_a];
@@ -8559,10 +8578,11 @@ Docs & License: https://fullcalendar.io/
8559
8578
 
8560
8579
  // exports
8561
8580
  // --------------------------------------------------------------------------------------------------
8562
- var version = '4.3.1';
8581
+ var version = '4.4.0';
8563
8582
 
8564
8583
  exports.Calendar = Calendar;
8565
8584
  exports.Component = Component;
8585
+ exports.ComponentContext = ComponentContext;
8566
8586
  exports.DateComponent = DateComponent;
8567
8587
  exports.DateEnv = DateEnv;
8568
8588
  exports.DateProfileGenerator = DateProfileGenerator;
@@ -8610,6 +8630,9 @@ Docs & License: https://fullcalendar.io/
8610
8630
  exports.compensateScroll = compensateScroll;
8611
8631
  exports.computeClippingRect = computeClippingRect;
8612
8632
  exports.computeEdges = computeEdges;
8633
+ exports.computeEventDraggable = computeEventDraggable;
8634
+ exports.computeEventEndResizable = computeEventEndResizable;
8635
+ exports.computeEventStartResizable = computeEventStartResizable;
8613
8636
  exports.computeFallbackHeaderFormat = computeFallbackHeaderFormat;
8614
8637
  exports.computeHeightAndMargins = computeHeightAndMargins;
8615
8638
  exports.computeInnerRect = computeInnerRect;