⚡ pl-loading-trace
June 3, 2026 · View on GitHub
⚡ pl-loading-trace
The Angular loading overlay you actually want to use.
Zero boilerplate · 76 built-in animations · HTTP auto-tracking · Router tracking · Named overlays · Determinate progress bars · Runtime config API · Angular Signals
🔴 Live Interactive Demo →
Try every animation, tweak config live, trigger HTTP / router events — all in the browser.
👆 Click the image to open the live demo
Table of Contents
- ⚡ pl-loading-trace
- 🔴 Live Interactive Demo →
- Table of Contents
- 1. Why pl-loading-trace?
- 2. Requirements
- 3. Installation
- 4. Setup
- 5. Quick start
- 6. Component inputs
- 7. Configuration reference
- 8. Animation types
- 9. Services
- 10. Runtime config override API
- 11. Practical examples
- 11.1 Full-screen HTTP spinner
- 11.2 Router navigation bar
- 11.3 HTTP spinner + router bar combined
- 11.4 Contained card spinner
- 11.5 Named overlay — manual control
- 11.6 Named overlay on a button
- 11.7 Determinate progress bar
- 11.8 Dynamic progress with registry
- 11.9 Runtime config change
- 11.10 Label text
- 11.11 Custom GIF
- 11.12 Debounce (avoid flicker)
- 11.13 Exclude URLs from tracking
- 11.14 Split http / router config
- 11.15 Multiple named cards grid
- 11.16 spinnerOpacity — transparent animation
- 12. Exported symbols
- 13. Building & Publishing
1. Why pl-loading-trace?
Most loading libraries make you choose: either a full-screen spinner or a progress bar or per-component loaders. pl-loading-trace does all three, with a single component and a single config.
| Feature | pl-loading-trace | Typical spinner lib |
|---|---|---|
| HTTP auto-tracking (functional interceptor) | ✅ | ❌ |
| Router navigation tracking | ✅ | ❌ |
| Named overlays (per-card, per-button) | ✅ | ❌ |
| 76 built-in CSS animations | ✅ | ~5 |
| 23 determinate progress bar types | ✅ | ❌ |
| Runtime config override via service | ✅ | ❌ |
| Angular 19 Signals-native | ✅ | ❌ |
| Zero dependencies | ✅ | ✅ |
| Tree-shakeable | ✅ | ⚠️ |
2. Requirements
| Package | Version |
|---|---|
@angular/core | ^19.2.0 |
@angular/common | ^19.2.0 |
@angular/router | compatible with Angular 19 |
Router tracking requires
provideRouter(routes)(orRouterModule). If your app has no router, setenableRouterTracer: false.
3. Installation
npm install pl-loading-trace
4. Setup
4.1 Standalone app (Angular 17+)
app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { routes } from './app.routes';
import { providePlLoadingTrace, plLoadingHttpInterceptor } from 'pl-loading-trace';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([plLoadingHttpInterceptor])),
providePlLoadingTrace({
shared: { debounceMs: 200 },
http: { animationType: 'spinner', modal: true },
router: { animationType: 'bar' },
}),
],
};
plLoadingHttpInterceptoris a functional interceptor (Angular 15+ style). For class-based interceptors, usePlLoadingHttpInterceptorwithHTTP_INTERCEPTORS.
4.2 NgModule app
app.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { PlLoadingTraceModule, PlLoadingHttpInterceptor } from 'pl-loading-trace';
@NgModule({
imports: [
HttpClientModule,
PlLoadingTraceModule.forRoot({
shared: { debounceMs: 200 },
http: { animationType: 'spinner', modal: true },
router: { animationType: 'bar' },
}),
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: PlLoadingHttpInterceptor,
multi: true,
},
],
})
export class AppModule {}
5. Quick start
Drop <pl-loading-overlay> once in your root layout — that's it:
<!-- app.component.html -->
<!-- Top-of-page router bar -->
<pl-loading-overlay source="router" />
<!-- Full-screen HTTP overlay -->
<pl-loading-overlay source="http" />
<router-outlet />
Every HttpClient request and every router navigation will now trigger the appropriate overlay automatically.
6. Component inputs
| Input | Type | Default | Description |
|---|---|---|---|
source | LoadingSource | 'http' | Which stream triggers this overlay |
contained | boolean | false | Fill nearest position: relative ancestor instead of the viewport |
name | string | '' | Register in PlLoadingRegistryService for manual/imperative control |
config | Partial<PlLoadingTraceConfig> | {} | Per-instance config (merged over global) |
progress | number | null | null | Determinate progress value 0–100 (takes priority over config.progressValue) |
source values
| Value | Triggers when… |
|---|---|
'http' | Any tracked HttpClient request is pending |
'router' | A router navigation is in progress |
'both' | Either HTTP or router is active |
'none' | Only via PlLoadingRegistryService — fully manual |
7. Configuration reference
7.1 PlLoadingTraceConfig — full reference
All properties are optional. Any omitted key falls back to its default.
| Property | Type | Default | Description |
|---|---|---|---|
enableHttpTracer | boolean | true | Intercept HttpClient requests |
enableRouterTracer | boolean | true | Track router navigations |
animationType | AnimationType | 'spinner' | CSS animation to display (see §8) |
animationSpeed | number | 1000 | Animation cycle duration in ms |
position | LoadingPosition | 'center' | Where to place the spinner (ignored for bar type) |
modal | boolean | true | Show a semi-transparent backdrop |
backdropColor | string | 'rgba(0,0,0,0.55)' | Backdrop background (any CSS color) |
backdropBlur | number | 2 | Backdrop backdrop-filter: blur(Npx) |
color | string | '#3498db' | Primary animation color |
size | number | 40 | Animation size in px |
spinnerOpacity | number | 1 | Animation element opacity 0–1 |
barHeight | number | 5 | Track height in px (for bar type) |
barColorStart | string | (same as color) | Gradient start color for bar |
barColorEnd | string | '#2ecc71' | Gradient end color for bar |
label | string | '' | Text shown below the animation |
labelColor | string | (auto-contrast) | Label color; auto = white on modal, color on no-modal |
debounceMs | number | 150 | Start-only debounce in ms — requests shorter than this won't show the overlay. Configurable independently per source via http/router sections. |
excludeUrls | string[] | [] | URL substrings to skip in HTTP tracking |
customGifUrl | string | '' | GIF/image to use instead of CSS animation |
zIndex | number | 9999 | CSS z-index |
wrapperBg | string | 'transparent' | Spinner card background |
wrapperRadius | number | 12 | Spinner card border-radius in px |
wrapperPadding | number | 20 | Spinner card padding in px |
progressValue | number | 0 | Determinate progress 0–100 (static, for progress types) |
progressSegments | number | 20 | Segment / dot count for segmented progress types |
position values
'center' | 'top' | 'bottom' | 'top-left' | 'top-right'
7.2 PlLoadingTraceOptions — split config
interface PlLoadingTraceOptions {
shared?: Partial<PlLoadingTraceConfig>; // applied to ALL overlays
http?: Partial<PlLoadingTraceConfig>; // HTTP overlays only (overrides shared)
router?: Partial<PlLoadingTraceConfig>; // router overlays only (overrides shared)
}
7.3 Config resolution order
From lowest to highest priority — later entries win:
DEFAULT_CONFIG
← shared
← http (source='http') ┐
← router (source='router') ┘
← [config] (per-instance input binding, only defined keys)
← registry.setConfig / patchConfig (runtime override — highest priority)
Named overlays (source="none") inherit from shared only.
8. Animation types
8.1 Indeterminate loaders (53)
All are CSS-only, have transparent backgrounds, and respect spinnerOpacity and animationSpeed.
| Name | Style | Best for |
|---|---|---|
spinner | Classic rotating ring | HTTP requests |
dots | Three bouncing dots | Routing |
bar | Full-width gradient bar at top | Router navigation |
ring-fade | Segmented ring fading in/out | Dashboard |
pulse | Pulsing expanding circle | Manual trace |
ripple | Two expanding concentric rings | Save action |
orbit | Dot orbiting a center dot | Long task |
wave | Five vertical bars (audio wave) | Sync data |
bounce-bar | Three bars with staggered bounce | Inline card |
flip | Square flipping on 3 axes | Admin panel |
square-spin | Square rotating on multiple axes | Developer tool |
chase | Six dots chasing in a circle | Full overlay |
dna | Two interleaved vertical sine waves | Showcase |
ellipsis | Three dots expanding horizontally | Small widgets |
hourglass | Rotating hourglass shape | Processing |
infinity | Animated figure-eight (∞) | Background sync |
meteor | Comet streaking diagonally | Route change |
morph | Shape-morphing blob | Dashboard card |
neon-ring | Glowing neon spinning ring | Dark mode |
skeleton | Shimmer placeholder bar | Content loading |
typing | Three chat-bubble typing dots | Chat / logs |
windmill | Four-blade windmill | Demo |
| `cube-grid$ | 3 \times 3 \text{cubes} \text{pulsing} \text{in} \text{cascade} | \text{Grid} \text{data} |
| $fading-circle` | 12 dots around a clock face | Generic loading |
double-ring | Two concentric rings, opposite directions | Modal overlay |
radar | Radar sweep sector | Network trace |
jelly | Squash-and-stretch blob | Friendly UI |
rotate-plane | Single plane rotating in 3D | Admin action |
wandering-cubes | Two squares orbiting each other | Showcase |
| `grid-fade$ | 3 \times 3 \text{grid} \text{fading} \text{in} \text{cascade} | \text{Tables} |
| $three-bounce` | Three balls bouncing horizontally | Button loading |
arc | SVG arc with animated stroke-dashoffset | Default choice |
google-line | Material-style indeterminate bar | Router top bar |
route-progress | Progressive fill bar | Router navigation |
matrix-rain | Falling code characters | Dark / network |
terminal-cursor | Blinking block cursor | Developer UI |
cyber-scan | Horizontal scan line | Network tracing |
liquid-orb | Liquid blob orbiting | Full overlay |
elastic-dots | Elastically bouncing dots | HTTP loading |
gradient-ring | Ring with conic gradient | Modal loading |
data-stream | Flowing data particles | API calls |
network-nodes | Connected nodes pulsing | Network trace |
loading-stripes | Animated diagonal stripes bar | Progress bar |
glitch | RGB-offset glitch effect | Dark showcase |
halo-pulse | Dot with pulsing halo | Small loading |
ios-dots | iOS-style activity indicator | Inline loading |
android-bar | Material indeterminate bar | Top loading |
neon-bars | Neon equalizer bars | Dark UI |
rotating-dashes | Rotating dashed circle | Generic loading |
ping-dot | Network ping indicator | Network ping |
progress-pill | Animated pill bar | Button / card |
angular-orbit | Angular logo orbital animation | Angular library |
copilot-border | Glowing border that travels the container | AI / Chat box |
8.2 Determinate progress bars (23)
These types consume a progress value 0–100 and render it visually.
Feed the value via [progress] input, config.progressValue, or registry.setProgress(name, value).
| Name | Visual | Best for |
|---|---|---|
progress-ring | SVG circular arc fill | File upload |
progress-segments | Rectangular segments ring | Batch operation |
progress-dots | High-density dot ring | Loading stage |
progress-bar | Horizontal fill bar with glow | File upload |
progress-striped | Animated diagonal stripes fill | Long operation |
progress-thin | 3 px NProgress-style line + glowing dot | Page transition |
progress-steps | Horizontal step circles | Wizard / onboarding |
progress-blocks | Vertical equalizer columns | Audio / media |
progress-battery | Battery shape with charging fill | Charge / energy |
progress-dial | Conic-gradient donut with % label | Dashboard metric |
progress-level | Liquid fill circle (bottom→top) | Liquid / fluid |
progress-arc | SVG half-circle speedometer gauge | Speed / score |
progress-counter | Large % number + thin conic ring | KPI / stat card |
progress-wave-bar | Wavy leading-edge fill bar | Liquid / upload |
| `progress-pixel$ | \text{LED} 10 \times 2 \text{pixel} \text{grid} | \text{Retro} / \text{game} \text{UI} |
| $progress-clock` | Conic dial + rotating clock hand | Timer / schedule |
progress-tower | Narrow vertical column fill | Storage / capacity |
progress-dots-row | Horizontal row of dot indicators | Step indicator |
progress-gradient-ring | SVG ring with linear-gradient stroke | Profile / avatar |
progress-text-fill | Giant % text filled bottom-up | Score / stat |
progress-neon-bar | Ultra-glow neon bar (multi-layer bloom) | Cyberpunk / game |
progress-scan | Fill bar with scanline on leading edge | Scan / process |
progress-split-bar | Symmetric fill from center outward | Symmetric load |
9. Services
9.1 PlLoadingStateService
Inject this to manually trigger the global loading state, or to read the resolved config signals.
import { inject } from '@angular/core';
import { PlLoadingStateService } from 'pl-loading-trace';
@Component({ ... })
export class MyComponent {
private readonly loadingState = inject(PlLoadingStateService);
async generateReport() {
this.loadingState.setHttpLoading(true);
try {
await this.reportService.generate();
} finally {
this.loadingState.setHttpLoading(false);
}
}
}
Members
| Member | Type | Description |
|---|---|---|
config | Signal<Required<PlLoadingTraceConfig>> | Resolved shared config |
httpConfig | Signal<Required<PlLoadingTraceConfig>> | Resolved HTTP config |
routerConfig | Signal<Required<PlLoadingTraceConfig>> | Resolved router config |
loading$ | Observable<boolean> | Combined HTTP + router stream |
httpLoading$ | Observable<boolean> | HTTP stream only |
routerLoading$ | Observable<boolean> | Router stream only |
setHttpLoading(v) | void | Manually set HTTP loading state |
setRouterLoading(v) | void | Manually set router loading state |
9.2 PlLoadingRegistryService
Full imperative control over any named overlay instance.
private readonly registry = inject(PlLoadingRegistryService);
Methods — loading control
| Method | Signature | Description |
|---|---|---|
start | (name, label?) => void | Start loading; optionally set a dynamic label |
stop | (name) => void | Stop loading and clear the dynamic label |
toggle | (name, label?) => void | Toggle state |
isActive | (name) => boolean | Returns current active state (synchronous) |
register | (name) => Signal<boolean> | Read-only active signal (used by the component) |
registerLabel | (name) => Signal<string> | Read-only label signal |
Methods — determinate progress
| Method | Signature | Description |
|---|---|---|
setProgress | (name, value: 0–100) => void | Set progress value |
resetProgress | (name) => void | Revert to config.progressValue |
startProgress | (name, label?) => void | start() + setProgress(0) combined |
completeProgress | (name, delayMs? = 300) => void | Set 100%, then stop after delay |
registerProgress | (name) => Signal<number | null> | Read-only progress signal |
Methods — runtime config override
See §10 for full details.
| Method | Signature | Description |
|---|---|---|
setConfig | (name, config) => void | Replace config override entirely. label is routed to the label signal |
patchConfig | (name, config) => void | Shallow-merge into existing override. Passing { label: '…' } alone is valid |
getConfig | (name) => Partial<PlLoadingTraceConfig> | Snapshot of current override including active label — use to save before a temporary change |
resetConfig | (name) => void | Remove all overrides and clear the dynamic label (revert to defaults) |
registerConfigOverride | (name) => Signal<…> | Read-only override signal (used by component) |
10. Runtime config override API
Every named overlay can have its config overridden at runtime via the registry — independently of the global config and the [config] input binding.
The priority chain is:
Global defaults ← [config] input ← registry.setConfig / patchConfig
The registry always wins. This means you can change any property — including animationType — without touching the template.
private readonly registry = inject(PlLoadingRegistryService);
// Replace the whole config override (label is routed to the label signal)
registry.setConfig('upload', {
animationType: 'progress-neon-bar',
color: '#ef4444',
size: 80,
label: 'Uploading…',
});
// Update only specific keys — passing { label } alone is valid
registry.patchConfig('upload', { color: '#10b981' }); // change color only
registry.patchConfig('upload', { label: '2 of 5…' }); // change label only
// Revert to template / global defaults (also clears dynamic label)
registry.resetConfig('upload');
Save and restore
Use getConfig() to snapshot the current state before a temporary change so it can be restored exactly:
// Save current state
const saved = this.registry.getConfig('status-badge');
// Temporary change
this.registry.patchConfig('status-badge', { color: '#ef4444', label: 'Error!' });
// Restore
this.registry.setConfig('status-badge', saved);
getConfig returns a Partial<PlLoadingTraceConfig> that includes the active label key so nothing is lost on restore.
Practical use: change animation on the fly
onUploadStart() {
this.registry.setConfig('file-task', { animationType: 'progress-bar', color: '#3b82f6' });
this.registry.startProgress('file-task');
}
onUploadProgress(pct: number) {
this.registry.setProgress('file-task', pct);
}
onUploadDone() {
this.registry.patchConfig('file-task', { color: '#22c55e' }); // go green
this.registry.completeProgress('file-task', 600);
}
onUploadError() {
this.registry.setConfig('file-task', { animationType: 'spinner', color: '#ef4444' });
setTimeout(() => this.registry.stop('file-task'), 2000);
}
11. Practical examples
11.1 Full-screen HTTP spinner
<!-- app.component.html -->
<pl-loading-overlay source="http" />
<router-outlet />
providePlLoadingTrace({
http: {
animationType: 'spinner',
color: '#6c63ff',
size: 56,
modal: true,
backdropColor: 'rgba(0, 0, 0, 0.6)',
backdropBlur: 4,
},
})
11.2 Router navigation bar
<pl-loading-overlay source="router" />
providePlLoadingTrace({
router: {
animationType: 'bar',
modal: false,
barColorStart: '#6c63ff',
barColorEnd: '#ff6584',
barHeight: 3,
},
})
11.3 HTTP spinner + router bar combined
<pl-loading-overlay source="router" />
<pl-loading-overlay source="http" />
<router-outlet />
providePlLoadingTrace({
shared: { debounceMs: 150 },
http: {
animationType: 'cube-grid',
color: '#3b82f6',
modal: true,
backdropColor: 'rgba(15, 23, 42, 0.65)',
},
router: {
animationType: 'bar',
modal: false,
barColorStart: '#818cf8',
barColorEnd: '#f472b6',
barHeight: 4,
},
})
11.4 Contained card spinner
The overlay fills the nearest position: relative ancestor instead of the viewport.
<div style="position: relative; width: 300px; height: 200px;">
<pl-loading-overlay
source="http"
[contained]="true"
[config]="{ animationType: 'ripple', color: '#10b981', size: 48, modal: false }" />
<h3>Card title</h3>
<p>Card content loaded via HTTP</p>
</div>
11.5 Named overlay — manual control
Use source="none" so the overlay only responds to registry calls.
<div class="product-card" style="position: relative; min-height: 100px;">
<pl-loading-overlay
name="save-product"
source="none"
[contained]="true"
[config]="{ animationType: 'dots', color: '#f59e0b', modal: false }" />
<h4>Product details</h4>
<button (click)="save()">Save</button>
</div>
save() {
this.registry.start('save-product', 'Saving…');
this.api.saveProduct().subscribe({
complete: () => this.registry.stop('save-product'),
error: () => this.registry.stop('save-product'),
});
}
11.6 Named overlay on a button
<button style="position: relative; overflow: hidden; min-width: 110px;" (click)="upload()">
<pl-loading-overlay
name="upload-btn"
source="none"
[contained]="true"
[config]="{ animationType: 'arc', color: '#fff', size: 18, modal: false, spinnerOpacity: 0.9 }" />
Upload
</button>
upload() {
this.registry.start('upload-btn');
this.fileService.upload(file).pipe(
finalize(() => this.registry.stop('upload-btn'))
).subscribe();
}
11.7 Determinate progress bar
Static value via [config] — useful for declarative templates:
<pl-loading-overlay
source="none"
name="install-progress"
[config]="{
animationType: 'progress-ring',
color: '#3b82f6',
size: 72,
modal: false,
progressValue: 42
}" />
Or via the [progress] input (reactive):
<pl-loading-overlay
source="none"
name="install-progress"
[config]="{ animationType: 'progress-ring', color: '#3b82f6', size: 72, modal: false }"
[progress]="uploadPercent()" />
11.8 Dynamic progress with registry
startUpload() {
this.registry.startProgress('upload', 'Uploading…');
this.uploader.progress$.subscribe(pct => {
this.registry.setProgress('upload', pct);
});
this.uploader.complete$.subscribe(() => {
this.registry.completeProgress('upload', 500); // show 100% for 500ms, then hide
});
}
<pl-loading-overlay
name="upload"
source="none"
[contained]="true"
[config]="{ animationType: 'progress-bar', color: '#3b82f6', size: 80, modal: false }" />
11.9 Runtime config change
// Show as indeterminate spinner while connecting
this.registry.setConfig('ws-status', { animationType: 'pulse', color: '#f59e0b', label: 'Connecting…' });
this.registry.start('ws-status');
// Connection established — switch to green progress ring
this.registry.setConfig('ws-status', { animationType: 'progress-ring', color: '#22c55e', label: 'Syncing…' });
// Change only the label without touching any other property
this.registry.patchConfig('ws-status', { label: 'Live' });
// Revert to template defaults (clears label too)
this.registry.resetConfig('ws-status');
Save / restore pattern
// Save state before a temporary error highlight
const saved = this.registry.getConfig('ws-status');
this.registry.patchConfig('ws-status', { color: '#ef4444', label: 'Reconnecting…' });
// After recovery, restore exact prior appearance
this.registry.setConfig('ws-status', saved);
11.10 Label text
<!-- Static label via [config] input -->
<pl-loading-overlay source="http" [config]="{ label: 'Loading data…', labelColor: '#ffffff' }" />
// Dynamic label — set on start, cleared automatically on stop
this.registry.start('my-overlay', 'Uploading file 1 of 3…');
// Change label only at any point (no other properties affected)
this.registry.patchConfig('my-overlay', { label: 'Uploading file 2 of 3…' });
// Label via setConfig / patchConfig has the same priority as start(name, label)
// — both route through the same internal label signal
this.registry.patchConfig('my-overlay', { label: 'Almost done…', color: '#10b981' });
Auto-contrast rules:
modal: true→ label is white (readable on dark backdrop)modal: false→ label matchescolor(readable on page background)- Override with explicit
labelColorwhen needed
11.11 Custom GIF
<pl-loading-overlay
source="http"
[config]="{ customGifUrl: '/assets/loading.gif', size: 80 }" />
11.12 Debounce (avoid flicker)
Requests shorter than debounceMs will not show the overlay at all. The overlay hides immediately when loading stops (start-only debounce). Default is 150 ms.
debounceMs can be set globally via shared, or overridden independently per source via the http / router sections:
providePlLoadingTrace({
shared: { debounceMs: 150 }, // default for both
http: { debounceMs: 300 }, // HTTP overlay: only shows for requests > 300 ms
router: { debounceMs: 0 }, // router bar: appears instantly
})
11.13 Exclude URLs from tracking
providePlLoadingTrace({
http: {
excludeUrls: ['/api/health', '/api/ping', 'analytics.google.com'],
},
})
11.14 Split http / router config
providePlLoadingTrace({
shared: {
enableHttpTracer: true,
enableRouterTracer: true,
debounceMs: 200,
},
http: {
animationType: 'fading-circle',
color: '#6366f1',
size: 52,
modal: true,
label: 'Loading…',
},
router: {
animationType: 'bar',
modal: false,
barColorStart: '#6366f1',
barColorEnd: '#ec4899',
barHeight: 3,
},
})
11.15 Multiple named cards grid
interface DemoCard {
name: string;
type: AnimationType;
color: string;
label?: string;
}
@Component({ ... })
export class DashboardComponent {
readonly registry = inject(PlLoadingRegistryService);
readonly cards: DemoCard[] = [
{ name: 'card-users', type: 'spinner', color: '#3b82f6', label: 'Loading users…' },
{ name: 'card-orders', type: 'dots', color: '#f59e0b' },
{ name: 'card-products', type: 'cube-grid', color: '#10b981' },
{ name: 'card-stats', type: 'fading-circle', color: '#ec4899' },
];
start(card: DemoCard, ms = 3000) {
this.registry.start(card.name, card.label);
setTimeout(() => this.registry.stop(card.name), ms);
}
}
<div class="cards-grid">
@for (card of cards; track card.name) {
<div class="card">
<pl-loading-overlay
[name]="card.name"
source="none"
[contained]="true"
[config]="{ animationType: card.type, color: card.color, modal: false }" />
<h4>{{ card.name }}</h4>
<button (click)="start(card)">▶ Start</button>
<button (click)="registry.stop(card.name)">■ Stop</button>
</div>
}
</div>
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 1rem;
}
.card {
position: relative; /* required for [contained]="true" */
min-height: 130px;
border: 1px solid #e2e8f0;
border-radius: 14px;
padding: 1rem;
}
11.16 spinnerOpacity — transparent animation
<!-- Semi-transparent neon ring on a blurred backdrop -->
<pl-loading-overlay
source="http"
[config]="{
animationType: 'neon-ring',
spinnerOpacity: 0.6,
modal: true,
backdropColor: 'rgba(0, 0, 0, 0.4)'
}" />
<!-- Ghost shimmer — no backdrop, partially transparent skeleton -->
<pl-loading-overlay
source="http"
[contained]="true"
[config]="{
animationType: 'skeleton',
spinnerOpacity: 0.35,
modal: false
}" />
12. Exported symbols
| Symbol | Kind | Description |
|---|---|---|
providePlLoadingTrace | function | Standalone provider factory |
PlLoadingTraceModule | NgModule | For NgModule apps (forRoot(options)) |
PlLoadingOverlayComponent | Component | The overlay component |
PlLoadingStateService | Injectable | Global loading state + config signals |
PlLoadingRegistryService | Injectable | Named overlay control + progress + runtime config |
PlLoadingHttpInterceptor | Injectable | Class-based HTTP interceptor |
plLoadingHttpInterceptor | HttpInterceptorFn | Functional HTTP interceptor |
PlRoutingTrackerService | Injectable | Router navigation tracker |
PL_LOADING_TRACE_CONFIG | InjectionToken | Config injection token |
PL_LOADING_TRACE_DEFAULT_CONFIG | const | Default config values |
PlLoadingTraceConfig | interface | Full config interface |
PlLoadingTraceOptions | interface | Split config interface |
AnimationType | type | Union of all 74 animation names |
AnimationSpeed | type | number (ms) |
LoadingPosition | type | 'center' | 'top' | 'bottom' | 'top-left' | 'top-right' |
LoadingSource | type | 'http' | 'router' | 'both' | 'none' |
13. Building & Publishing
Build the library
npx ng build pl-loading-trace
Build artifacts land in dist/pl-loading-trace/.
Publish to npm
cd dist/pl-loading-trace
npm publish
Run the demo app
npm start # development server → http://localhost:4200
npm run build # production build
npm run deploy:demo # deploy to GitHub Pages
Run tests
ng test
Made with ❤️ by Luca Piciollo · MIT License
