import * as i0 from '@angular/core';
import { Component, ViewEncapsulation, Input, ViewChild, ContentChild, NgModule } from '@angular/core';
import { Calendar } from '@fullcalendar/core';
import { CustomRenderingStore } from '@fullcalendar/core/internal';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
const OPTION_IS_DEEP = {
headerToolbar: true,
footerToolbar: true,
events: true,
eventSources: true,
resources: true
};
/*
NOTE: keep synced with component
*/
const OPTION_INPUT_NAMES = [
'events',
'eventSources',
'resources',
];
const hasOwnProperty = Object.prototype.hasOwnProperty;
/*
Really simple clone utility. Only copies plain arrays, objects, and Dates. Transfers everything else as-is.
Wanted to use a third-party lib, but none did exactly this.
*/
function deepCopy(input) {
if (Array.isArray(input)) {
return input.map(deepCopy);
}
else if (input instanceof Date) {
return new Date(input.valueOf());
}
else if (typeof input === 'object' && input) { // non-null object
return mapHash(input, deepCopy);
}
else { // everything else (null, function, etc)
return input;
}
}
function mapHash(input, func) {
const output = {};
for (const key in input) {
if (hasOwnProperty.call(input, key)) {
output[key] = func(input[key], key);
}
}
return output;
}
/*
Forked from https://github.com/epoberezkin/fast-deep-equal (also has MIT license)
Needed ESM support or else Angular complains about treeshaking
(https://github.com/fullcalendar/fullcalendar-angular/issues/421)
*/
function deepEqual(a, b) {
if (a === b)
return true;
if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor)
return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length)
return false;
for (i = length; i-- !== 0;)
if (!deepEqual(a[i], b[i]))
return false;
return true;
}
if (a.constructor === RegExp)
return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf)
return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString)
return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length)
return false;
for (i = length; i-- !== 0;)
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!deepEqual(a[key], b[key]))
return false;
}
return true;
}
// true if both NaN, false otherwise
return a !== a && b !== b;
}
const dummyContainer$1 = typeof document !== 'undefined' ? document.createDocumentFragment() : null;
class OffscreenFragmentComponent {
constructor(element) {
this.element = element;
}
ngAfterViewInit() {
if (dummyContainer$1) {
dummyContainer$1.appendChild(this.element.nativeElement);
}
}
// invoked BEFORE component removed from DOM
ngOnDestroy() {
if (dummyContainer$1) {
dummyContainer$1.removeChild(this.element.nativeElement);
}
}
}
OffscreenFragmentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: OffscreenFragmentComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
OffscreenFragmentComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: OffscreenFragmentComponent, selector: "offscreen-fragment", ngImport: i0, template: '', isInline: true, encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: OffscreenFragmentComponent, decorators: [{
type: Component,
args: [{
selector: 'offscreen-fragment',
template: '',
encapsulation: ViewEncapsulation.None
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; } });
const dummyContainer = typeof document !== 'undefined' ? document.createDocumentFragment() : null;
class TransportContainerComponent {
ngAfterViewInit() {
const rootEl = this.rootElRef?.nativeElement; // assumed defined
replaceEl(rootEl, this.inPlaceOf);
applyElAttrs(rootEl, undefined, this.elAttrs);
// insurance for if Preact recreates and reroots inPlaceOf element
this.inPlaceOf.style.display = 'none';
this.reportEl(rootEl);
}
ngOnChanges(changes) {
const rootEl = this.rootElRef?.nativeElement;
// ngOnChanges is called before ngAfterViewInit (and before DOM initializes)
// so make sure rootEl is defined before doing anything
if (rootEl) {
// If the ContentContainer's tagName changed, it will create a new DOM element in its
// original place. Detect this and re-replace.
if (this.inPlaceOf.parentNode !== dummyContainer) {
replaceEl(rootEl, this.inPlaceOf);
applyElAttrs(rootEl, undefined, this.elAttrs);
this.reportEl(rootEl);
}
else {
const elAttrsChange = changes['elAttrs'];
if (elAttrsChange) {
applyElAttrs(rootEl, elAttrsChange.previousValue, elAttrsChange.currentValue);
}
}
}
}
// invoked BEFORE component removed from DOM
ngOnDestroy() {
if (
// protect against Preact recreating and rerooting inPlaceOf element
this.inPlaceOf.parentNode === dummyContainer &&
dummyContainer) {
dummyContainer.removeChild(this.inPlaceOf);
}
this.reportEl(null);
}
}
TransportContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: TransportContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
TransportContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: TransportContainerComponent, selector: "transport-container", inputs: { inPlaceOf: "inPlaceOf", reportEl: "reportEl", elTag: "elTag", elClasses: "elClasses", elStyle: "elStyle", elAttrs: "elAttrs", template: "template", renderProps: "renderProps" }, viewQueries: [{ propertyName: "rootElRef", first: true, predicate: ["rootEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "\n \n \n
\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n
\n\n\n \n \n | \n\n\n \n \n | \n\n", directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: TransportContainerComponent, decorators: [{
type: Component,
args: [{ selector: 'transport-container', encapsulation: ViewEncapsulation.None, template: "\n \n \n
\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n
\n\n\n \n \n | \n\n\n \n \n | \n\n" }]
}], propDecorators: { inPlaceOf: [{
type: Input
}], reportEl: [{
type: Input
}], elTag: [{
type: Input
}], elClasses: [{
type: Input
}], elStyle: [{
type: Input
}], elAttrs: [{
type: Input
}], template: [{
type: Input
}], renderProps: [{
type: Input
}], rootElRef: [{
type: ViewChild,
args: ['rootEl']
}] } });
function replaceEl(subject, inPlaceOf) {
inPlaceOf.parentNode?.insertBefore(subject, inPlaceOf.nextSibling);
if (dummyContainer) {
dummyContainer.appendChild(inPlaceOf);
}
}
function applyElAttrs(el, previousAttrs = {}, currentAttrs = {}) {
// these are called "attributes" but they manipulate DOM node *properties*
for (const attrName in previousAttrs) {
if (!(attrName in currentAttrs)) {
el[attrName] = null;
}
}
for (const attrName in currentAttrs) {
el[attrName] = currentAttrs[attrName];
}
}
class FullCalendarComponent {
constructor(element, changeDetector) {
this.element = element;
this.calendar = null;
this.optionSnapshot = {}; // for diffing
this.customRenderingMap = new Map();
this.templateMap = {};
const customRenderingStore = new CustomRenderingStore();
customRenderingStore.subscribe((customRenderingMap) => {
this.customRenderingMap = customRenderingMap;
this.customRenderingArray = undefined; // clear cache
changeDetector.detectChanges();
});
this.handleCustomRendering = customRenderingStore.handle.bind(customRenderingStore);
this.templateMap = this; // alias to this
}
ngAfterViewInit() {
const { deepChangeDetection } = this;
const options = {
...this.options,
...this.buildInputOptions(),
};
// initialize snapshot
this.optionSnapshot = mapHash(options, (optionVal, optionName) => ((deepChangeDetection && OPTION_IS_DEEP[optionName])
? deepCopy(optionVal)
: optionVal));
const calendarEl = this.element.nativeElement;
const calendar = this.calendar = new Calendar(calendarEl, {
...options,
...this.buildExtraOptions(),
});
// Ionic dimensions hack
// https://github.com/fullcalendar/fullcalendar/issues/4976
const ionContent = calendarEl.closest('ion-content');
if (ionContent && ionContent.componentOnReady) {
ionContent.componentOnReady().then(() => {
window.requestAnimationFrame(() => {
calendar.render();
});
});
}
else {
calendar.render();
}
}
/*
allows us to manually detect complex input changes, internal mutations to certain options.
called before ngOnChanges. called much more often than ngOnChanges.
*/
ngDoCheck() {
if (this.calendar) { // not the initial render
const { deepChangeDetection, optionSnapshot } = this;
const newOptions = {
...this.options,
...this.buildInputOptions(),
};
const newProcessedOptions = {};
const changedOptionNames = [];
// detect adds and updates (and update snapshot)
for (const optionName in newOptions) {
if (newOptions.hasOwnProperty(optionName)) {
let optionVal = newOptions[optionName];
if (deepChangeDetection && OPTION_IS_DEEP[optionName]) {
if (!deepEqual(optionSnapshot[optionName], optionVal)) {
optionSnapshot[optionName] = deepCopy(optionVal);
changedOptionNames.push(optionName);
}
}
else {
if (optionSnapshot[optionName] !== optionVal) {
optionSnapshot[optionName] = optionVal;
changedOptionNames.push(optionName);
}
}
newProcessedOptions[optionName] = optionVal;
}
}
const oldOptionNames = Object.keys(optionSnapshot);
// detect removals (and update snapshot)
for (const optionName of oldOptionNames) {
if (!(optionName in newOptions)) { // doesn't exist in new options?
delete optionSnapshot[optionName];
changedOptionNames.push(optionName);
}
}
if (changedOptionNames.length) {
this.calendar.pauseRendering();
this.calendar.resetOptions({
...newProcessedOptions,
...this.buildExtraOptions(),
}, changedOptionNames);
}
}
}
ngAfterContentChecked() {
if (this.calendar) { // too defensive?
this.calendar.resumeRendering();
}
}
ngOnDestroy() {
if (this.calendar) { // too defensive?
this.calendar.destroy();
this.calendar = null;
}
}
get customRenderings() {
return this.customRenderingArray ||
(this.customRenderingArray = [...this.customRenderingMap.values()]);
}
getApi() {
return this.calendar;
}
buildInputOptions() {
const options = {};
for (const inputName of OPTION_INPUT_NAMES) {
const inputValue = this[inputName];
if (inputValue != null) { // exclude both null and undefined
options[inputName] = inputValue;
}
}
return options;
}
buildExtraOptions() {
return {
handleCustomRendering: this.handleCustomRendering,
customRenderingMetaMap: this.templateMap,
customRenderingReplaces: true,
};
}
// for `trackBy` in loop
trackCustomRendering(index, customRendering) {
return customRendering.id;
}
}
FullCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
FullCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.12", type: FullCalendarComponent, selector: "full-calendar", inputs: { options: "options", deepChangeDetection: "deepChangeDetection", events: "events", eventSources: "eventSources", resources: "resources" }, queries: [{ propertyName: "dayHeaderContent", first: true, predicate: ["dayHeaderContent"], descendants: true, static: true }, { propertyName: "dayCellContent", first: true, predicate: ["dayCellContent"], descendants: true, static: true }, { propertyName: "weekNumberContent", first: true, predicate: ["weekNumberContent"], descendants: true, static: true }, { propertyName: "nowIndicatorContent", first: true, predicate: ["nowIndicatorContent"], descendants: true, static: true }, { propertyName: "eventContent", first: true, predicate: ["eventContent"], descendants: true, static: true }, { propertyName: "slotLaneContent", first: true, predicate: ["slotLaneContent"], descendants: true, static: true }, { propertyName: "slotLabelContent", first: true, predicate: ["slotLabelContent"], descendants: true, static: true }, { propertyName: "allDayContent", first: true, predicate: ["allDayContent"], descendants: true, static: true }, { propertyName: "moreLinkContent", first: true, predicate: ["moreLinkContent"], descendants: true, static: true }, { propertyName: "noEventsContent", first: true, predicate: ["noEventsContent"], descendants: true, static: true }, { propertyName: "resourceAreaHeaderContent", first: true, predicate: ["resourceAreaHeaderContent"], descendants: true, static: true }, { propertyName: "resourceGroupLabelContent", first: true, predicate: ["resourceGroupLabelContent"], descendants: true, static: true }, { propertyName: "resourceLabelContent", first: true, predicate: ["resourceLabelContent"], descendants: true, static: true }, { propertyName: "resourceLaneContent", first: true, predicate: ["resourceLaneContent"], descendants: true, static: true }, { propertyName: "resourceGroupLaneContent", first: true, predicate: ["resourceGroupLaneContent"], descendants: true, static: true }], ngImport: i0, template: "\n \n\n", components: [{ type: OffscreenFragmentComponent, selector: "offscreen-fragment" }, { type: TransportContainerComponent, selector: "transport-container", inputs: ["inPlaceOf", "reportEl", "elTag", "elClasses", "elStyle", "elAttrs", "template", "renderProps"] }], directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarComponent, decorators: [{
type: Component,
args: [{ selector: 'full-calendar', encapsulation: ViewEncapsulation.None // the styles are root-level, not scoped within the component
, template: "\n \n\n" }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { options: [{
type: Input
}], deepChangeDetection: [{
type: Input
}], events: [{
type: Input
}], eventSources: [{
type: Input
}], resources: [{
type: Input
}], dayHeaderContent: [{
type: ContentChild,
args: ['dayHeaderContent', { static: true }]
}], dayCellContent: [{
type: ContentChild,
args: ['dayCellContent', { static: true }]
}], weekNumberContent: [{
type: ContentChild,
args: ['weekNumberContent', { static: true }]
}], nowIndicatorContent: [{
type: ContentChild,
args: ['nowIndicatorContent', { static: true }]
}], eventContent: [{
type: ContentChild,
args: ['eventContent', { static: true }]
}], slotLaneContent: [{
type: ContentChild,
args: ['slotLaneContent', { static: true }]
}], slotLabelContent: [{
type: ContentChild,
args: ['slotLabelContent', { static: true }]
}], allDayContent: [{
type: ContentChild,
args: ['allDayContent', { static: true }]
}], moreLinkContent: [{
type: ContentChild,
args: ['moreLinkContent', { static: true }]
}], noEventsContent: [{
type: ContentChild,
args: ['noEventsContent', { static: true }]
}], resourceAreaHeaderContent: [{
type: ContentChild,
args: ['resourceAreaHeaderContent', { static: true }]
}], resourceGroupLabelContent: [{
type: ContentChild,
args: ['resourceGroupLabelContent', { static: true }]
}], resourceLabelContent: [{
type: ContentChild,
args: ['resourceLabelContent', { static: true }]
}], resourceLaneContent: [{
type: ContentChild,
args: ['resourceLaneContent', { static: true }]
}], resourceGroupLaneContent: [{
type: ContentChild,
args: ['resourceGroupLaneContent', { static: true }]
}] } });
class FullCalendarModule {
}
FullCalendarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
FullCalendarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarModule, declarations: [FullCalendarComponent,
OffscreenFragmentComponent,
TransportContainerComponent], imports: [CommonModule], exports: [FullCalendarComponent] });
FullCalendarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarModule, imports: [[
CommonModule
]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImport: i0, type: FullCalendarModule, decorators: [{
type: NgModule,
args: [{
declarations: [
FullCalendarComponent,
OffscreenFragmentComponent,
TransportContainerComponent
],
imports: [
CommonModule
],
exports: [
FullCalendarComponent
]
}]
}] });
/*
* Public API Surface of lib
*/
/**
* Generated bundle index. Do not edit.
*/
export { FullCalendarComponent, FullCalendarModule };
//# sourceMappingURL=fullcalendar-angular.mjs.map