ngx-spinner-loading
Version:
A lightweight Angular loading spinner package with full customization and HTTP interceptor support.
170 lines (160 loc) • 8.99 kB
JavaScript
import * as i0 from '@angular/core';
import { signal, Injectable, inject, effect, TemplateRef, ContentChild, Input, Component, ViewContainerRef, Directive } from '@angular/core';
import { NgStyle, NgClass, NgIf, NgTemplateOutlet } from '@angular/common';
import { finalize } from 'rxjs';
class NgxSpinnerLoadingService {
loadingCount = signal(0);
isLoading = signal(false);
show() {
this.loadingCount.update((count) => count + 1);
this.isLoading.set(true);
}
hide() {
this.loadingCount.update((count) => Math.max(0, count - 1));
if (this.loadingCount() === 0)
this.isLoading.set(false);
}
reset() {
this.loadingCount.set(0);
this.isLoading.set(false);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoadingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoadingService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoadingService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
class NgxSpinnerLoaderComponent {
service = inject(NgxSpinnerLoadingService);
manual = false;
type = 'spinner';
size = 'md';
color = '#3498db';
mode = 'fullscreen';
speed = 1;
timeout;
zIndex = 9999;
template;
visible = this.manual ? () => true : this.service.isLoading;
timeoutStarted = false;
constructor() {
if (!this.manual && this.timeout) {
effect(() => {
if (this.visible() && !this.timeoutStarted) {
this.timeoutStarted = true;
setTimeout(() => {
this.service.hide();
this.timeoutStarted = false;
}, this.timeout);
}
});
}
}
get containerClass() {
switch (this.mode) {
case 'fullscreen': return 'ngx-loader-fullscreen';
case 'section': return 'ngx-loader-section';
case 'inline': return 'ngx-loader-inline';
}
}
get typeClass() {
const validTypes = ['spinner', 'dots', 'bar', 'circle'];
return validTypes.includes(this.type) ? `loader-${this.type}` : 'loader-spinner';
}
loaderStyle() {
const sizeMap = {
xs: '20px', sm: '30px', md: '40px', lg: '50px', xl: '70px'
};
return {
border: '4px solid #ccc',
borderTopColor: this.color,
width: sizeMap[this.size],
height: sizeMap[this.size],
animationDuration: `${1 / this.speed}s`
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: NgxSpinnerLoaderComponent, isStandalone: true, selector: "ngx-spinner-loader", inputs: { manual: "manual", type: "type", size: "size", color: "color", mode: "mode", speed: "speed", timeout: "timeout", zIndex: "zIndex" }, queries: [{ propertyName: "template", first: true, predicate: TemplateRef, descendants: true }], ngImport: i0, template: `
<div *ngIf="visible()" [ngClass]="containerClass" [style.zIndex]="zIndex">
<ng-container *ngIf="type === 'custom' && template; else builtInLoader"
[ngTemplateOutlet]="template"></ng-container>
<ng-template #builtInLoader>
<div class="loader" [ngStyle]="loaderStyle()" [ngClass]="typeClass"></div>
</ng-template>
</div>
`, isInline: true, styles: [".ngx-loader-fullscreen{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background-color:#ffffffb3}.ngx-loader-section{position:relative;min-height:60px}.ngx-loader-inline{display:inline-flex;align-items:center;justify-content:center}.loader{border:4px solid #ccc;border-radius:50%;border-top-color:#3498db;animation:spin 1s linear infinite}.loader-dots:after{content:\"...\";animation:blink 1s step-start infinite}.loader-bar{width:100px;height:6px;background:linear-gradient(to right,#ccc,currentColor,#ccc);animation:slide 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@keyframes blink{50%{opacity:.3}}@keyframes slide{0%{background-position:0% 50%}to{background-position:100% 50%}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoaderComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-spinner-loader', standalone: true, imports: [NgStyle, NgClass, NgIf, NgTemplateOutlet], template: `
<div *ngIf="visible()" [ngClass]="containerClass" [style.zIndex]="zIndex">
<ng-container *ngIf="type === 'custom' && template; else builtInLoader"
[ngTemplateOutlet]="template"></ng-container>
<ng-template #builtInLoader>
<div class="loader" [ngStyle]="loaderStyle()" [ngClass]="typeClass"></div>
</ng-template>
</div>
`, styles: [".ngx-loader-fullscreen{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background-color:#ffffffb3}.ngx-loader-section{position:relative;min-height:60px}.ngx-loader-inline{display:inline-flex;align-items:center;justify-content:center}.loader{border:4px solid #ccc;border-radius:50%;border-top-color:#3498db;animation:spin 1s linear infinite}.loader-dots:after{content:\"...\";animation:blink 1s step-start infinite}.loader-bar{width:100px;height:6px;background:linear-gradient(to right,#ccc,currentColor,#ccc);animation:slide 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@keyframes blink{50%{opacity:.3}}@keyframes slide{0%{background-position:0% 50%}to{background-position:100% 50%}}\n"] }]
}], ctorParameters: () => [], propDecorators: { manual: [{
type: Input
}], type: [{
type: Input
}], size: [{
type: Input
}], color: [{
type: Input
}], mode: [{
type: Input
}], speed: [{
type: Input
}], timeout: [{
type: Input
}], zIndex: [{
type: Input
}], template: [{
type: ContentChild,
args: [TemplateRef]
}] } });
class NgxSpinnerLoadingDirective {
tmpl = inject((TemplateRef));
vcr = inject(ViewContainerRef);
service = inject(NgxSpinnerLoadingService);
set loading(condition) {
this.vcr.clear();
if (condition) {
this.service.show();
// Optionally show spinner markup here
}
else {
this.service.hide();
this.vcr.createEmbeddedView(this.tmpl);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoadingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: NgxSpinnerLoadingDirective, isStandalone: true, selector: "[ngxSpinnerLoading]", inputs: { loading: ["ngxSpinnerLoading", "loading"] }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxSpinnerLoadingDirective, decorators: [{
type: Directive,
args: [{
selector: '[ngxSpinnerLoading]',
standalone: true
}]
}], propDecorators: { loading: [{
type: Input,
args: ['ngxSpinnerLoading']
}] } });
// ngx-spinner-loading.interceptor.ts
const NgxSpinnerLoadingInterceptor = (req, next) => {
const loadingService = inject(NgxSpinnerLoadingService);
loadingService.show();
return next(req).pipe(finalize(() => loadingService.hide()));
};
/*
* Public API Surface of ngx-spinner-loading
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxSpinnerLoaderComponent, NgxSpinnerLoadingDirective, NgxSpinnerLoadingInterceptor, NgxSpinnerLoadingService };
//# sourceMappingURL=ngx-spinner-loading.mjs.map