ngx-masonry
Version:
Angular Module for displaying a feed of items in a masonry layout using https://github.com/desandro/masonry
255 lines (248 loc) • 10.6 kB
JavaScript
import { isPlatformBrowser } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, PLATFORM_ID, Component, Inject, Input, Output, forwardRef, Directive, NgModule } from '@angular/core';
import * as i1 from '@angular/animations';
import { style, animate } from '@angular/animations';
let masonryConstructor;
class NgxMasonryComponent {
constructor(platformId, _element) {
this.platformId = platformId;
this._element = _element;
this.updateLayout = false;
this.ordered = false;
// Outputs
this.layoutComplete = new EventEmitter();
this.removeComplete = new EventEmitter();
this.itemsLoaded = new EventEmitter();
this.pendingItems = [];
}
ngOnInit() {
if (isPlatformBrowser(this.platformId) && masonryConstructor === undefined) {
masonryConstructor = require('masonry-layout');
}
// Create masonry options object
if (!this.options) {
this.options = {};
}
// Set default itemSelector
if (!this.options.itemSelector) {
this.options.itemSelector = '[ngxMasonryItem], ngxMasonryItem';
}
this.options['transitionDuration'] = '0s';
if (isPlatformBrowser(this.platformId)) {
// Initialize Masonry
this.masonryInstance = new masonryConstructor(this._element.nativeElement, this.options);
// Bind to events
this.masonryInstance.on('layoutComplete', (items) => {
this.layoutComplete.emit(items);
});
this.masonryInstance.on('removeComplete', (items) => {
this.removeComplete.emit(items);
});
this.masonryInstance.items = [];
}
}
ngOnChanges(changes) {
// only update layout if it's not the first change
if (changes.updateLayout) {
if (!changes.updateLayout.firstChange) {
this.layout();
}
}
}
ngOnDestroy() {
if (this.masonryInstance) {
this.masonryInstance.destroy();
}
}
layout() {
setTimeout(() => {
this.masonryInstance.layout();
});
}
reloadItems() {
setTimeout(() => {
this.masonryInstance.reloadItems();
});
}
addPendingItem(item) {
this.pendingItems.push(item);
}
add(newItem) {
if (this.ordered) {
for (const [index, item] of this.pendingItems.entries()) {
if (item) {
if (item.images && item.images.size === 0) {
this.pendingItems[index] = undefined;
this.itemLoaded(item);
if (index + 1 === this.pendingItems.length) {
// All items are loaded
this.itemsLoaded.emit(this.pendingItems.length);
this.pendingItems = [];
}
}
else {
return;
}
}
}
}
else {
this.itemLoaded(newItem);
}
}
itemLoaded(item) {
if (isPlatformBrowser(this.platformId)) {
// Tell Masonry that a child element has been added
if (item.prepend) {
this.masonryInstance.prepended(item.element.nativeElement);
}
else {
this.masonryInstance.appended(item.element.nativeElement);
}
// Check if first item
if (this.masonryInstance.items.length === 1) {
this.masonryInstance.layout();
}
item.playAnimation(true);
}
}
remove(element) {
if (isPlatformBrowser(this.platformId)) {
// Tell Masonry that a child element has been removed
this.masonryInstance.remove(element);
// Layout items
this.layout();
}
}
}
NgxMasonryComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryComponent, deps: [{ token: PLATFORM_ID }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
NgxMasonryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.7", type: NgxMasonryComponent, selector: "[ngx-masonry], ngx-masonry", inputs: { options: "options", updateLayout: "updateLayout", ordered: "ordered" }, outputs: { layoutComplete: "layoutComplete", removeComplete: "removeComplete", itemsLoaded: "itemsLoaded" }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{display:block}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryComponent, decorators: [{
type: Component,
args: [{ selector: '[ngx-masonry], ngx-masonry', template: '<ng-content></ng-content>', styles: [":host{display:block}\n"] }]
}], ctorParameters: function () {
return [{ type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.ElementRef }];
}, propDecorators: { options: [{
type: Input
}], updateLayout: [{
type: Input
}], ordered: [{
type: Input
}], layoutComplete: [{
type: Output
}], removeComplete: [{
type: Output
}], itemsLoaded: [{
type: Output
}] } });
class NgxMasonryDirective {
constructor(element, builder, parent, renderer) {
this.element = element;
this.builder = builder;
this.parent = parent;
this.renderer = renderer;
this.prepend = false;
this.animations = {
show: [
style({ opacity: 0 }),
animate('400ms ease-in', style({ opacity: 1 })),
],
hide: [
style({ opacity: '*' }),
animate('400ms ease-in', style({ opacity: 0 })),
]
};
}
ngOnInit() {
if (this.parent.options.animations !== undefined) {
this.animations = this.parent.options.animations;
}
this.renderer.setStyle(this.element.nativeElement, 'position', 'fixed');
this.renderer.setStyle(this.element.nativeElement, 'right', '-150vw');
this.parent.addPendingItem(this);
}
ngAfterViewInit() {
const images = Array.from(this.element.nativeElement.getElementsByTagName('img'));
this.images = new Set(images);
if (images.length === 0) {
setTimeout(() => {
this.parent.add(this);
});
}
else {
for (const imageRef of images) {
// skip image render check if image has `masonryLazy` attribute
if (imageRef.hasAttribute('masonryLazy')) {
this.imageLoaded(imageRef);
}
else {
this.renderer.listen(imageRef, 'load', _ => {
this.imageLoaded(imageRef);
});
this.renderer.listen(imageRef, 'error', _ => {
this.imageLoaded(imageRef);
});
}
}
}
}
ngOnDestroy() {
if (this.images && this.images.size === 0 && this.element.nativeElement.parentNode) {
this.playAnimation(false);
this.parent.remove(this.element.nativeElement);
}
}
imageLoaded(image) {
this.images.delete(image);
if (this.images.size === 0) {
this.parent.add(this);
}
}
playAnimation(show) {
const metadata = show ? this.animations.show : this.animations.hide;
if (metadata) {
const player = this.builder.build(metadata).create(this.element.nativeElement);
player.play();
}
}
}
NgxMasonryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryDirective, deps: [{ token: i0.ElementRef }, { token: i1.AnimationBuilder }, { token: forwardRef(() => NgxMasonryComponent) }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
NgxMasonryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.7", type: NgxMasonryDirective, selector: "[ngxMasonryItem], ngxMasonryItem", inputs: { prepend: "prepend" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryDirective, decorators: [{
type: Directive,
args: [{
selector: '[ngxMasonryItem], ngxMasonryItem'
}]
}], ctorParameters: function () {
return [{ type: i0.ElementRef }, { type: i1.AnimationBuilder }, { type: NgxMasonryComponent, decorators: [{
type: Inject,
args: [forwardRef(() => NgxMasonryComponent)]
}] }, { type: i0.Renderer2 }];
}, propDecorators: { prepend: [{
type: Input
}] } });
class NgxMasonryModule {
}
NgxMasonryModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
NgxMasonryModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryModule, declarations: [NgxMasonryComponent, NgxMasonryDirective], exports: [NgxMasonryComponent, NgxMasonryDirective] });
NgxMasonryModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.7", ngImport: i0, type: NgxMasonryModule, decorators: [{
type: NgModule,
args: [{
imports: [],
declarations: [NgxMasonryComponent, NgxMasonryDirective],
exports: [NgxMasonryComponent, NgxMasonryDirective]
}]
}] });
/*
* Public API Surface of ngx-masonry
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxMasonryComponent, NgxMasonryDirective, NgxMasonryModule };
//# sourceMappingURL=ngx-masonry.mjs.map