{"version":3,"file":"ngwr-loading-bar.mjs","sources":["../../../projects/lib/loading-bar/services/loading-bar.ts","../../../projects/lib/loading-bar/loading-bar.component.ts","../../../projects/lib/loading-bar/loading-bar.component.html","../../../projects/lib/loading-bar/ngwr-loading-bar.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Service, type Signal, computed, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';\n\nimport { filter } from 'rxjs';\n\nimport type { WrLoadingState } from '../interfaces';\n\n/**\n * Singleton state machine for a top-of-page progress indicator. Driven\n * by router events out of the box, plus a manual `start()` / `complete()`\n * API for HTTP-interceptor-style usage.\n *\n * Pair with `<wr-loading-bar>` to render the bar at the top of your shell.\n *\n * @example\n * ```ts\n * // From an HttpInterceptor:\n * const bar = inject(WrLoadingBar);\n * bar.start();\n * return next(req).pipe(finalize(() => bar.complete()));\n * ```\n *\n * @see https://ngwr.dev/services/loading-bar\n */\n@Service()\nexport class WrLoadingBar {\n  private readonly router = inject(Router, { optional: true });\n\n  /** Live count of pending \"tasks\" (manual + router). */\n  private readonly count = signal(0);\n\n  /** Tween value `[0, 1]` — the bar's actual width. */\n  private readonly _progress = signal(0);\n  readonly progress: Signal<number> = this._progress.asReadonly();\n\n  readonly state: Signal<WrLoadingState> = computed(() => {\n    if (this.count() > 0) return 'running';\n    return this._progress() > 0 ? 'completing' : 'idle';\n  });\n\n  private timer: ReturnType<typeof setInterval> | null = null;\n\n  constructor() {\n    if (this.router) {\n      // Mirror router events: any in-flight navigation starts the bar,\n      // each terminal event releases one slot.\n      toSignal(\n        this.router.events.pipe(\n          filter(\n            e =>\n              e instanceof NavigationStart ||\n              e instanceof NavigationEnd ||\n              e instanceof NavigationCancel ||\n              e instanceof NavigationError\n          )\n        ),\n        { manualCleanup: true }\n      );\n      this.router.events.subscribe(event => {\n        if (event instanceof NavigationStart) this.start();\n        else if (\n          event instanceof NavigationEnd ||\n          event instanceof NavigationCancel ||\n          event instanceof NavigationError\n        ) {\n          this.complete();\n        }\n      });\n    }\n  }\n\n  /** Reserve a slot. The bar starts trickling as long as `count > 0`. */\n  start(): void {\n    if (this.count() === 0) this.beginTrickle();\n    this.count.update(v => v + 1);\n  }\n\n  /** Release a slot. When the last one closes, the bar fast-forwards to 100% then resets. */\n  complete(): void {\n    this.count.update(v => Math.max(0, v - 1));\n    if (this.count() === 0) this.finish();\n  }\n\n  /** Cancel without animating the bar to 100%. Resets immediately. */\n  reset(): void {\n    this.count.set(0);\n    this.stopTrickle();\n    this._progress.set(0);\n  }\n\n  // Internals\n\n  private beginTrickle(): void {\n    this.stopTrickle();\n    if (this._progress() === 0) this._progress.set(0.08);\n    this.timer = setInterval(() => {\n      const p = this._progress();\n      // Approach 90% asymptotically — we want the user-visible final jump\n      // to clearly indicate completion.\n      const next = p + (0.9 - p) * 0.08;\n      this._progress.set(next);\n    }, 150);\n  }\n\n  private stopTrickle(): void {\n    if (this.timer === null) return;\n    clearInterval(this.timer);\n    this.timer = null;\n  }\n\n  private finish(): void {\n    this.stopTrickle();\n    this._progress.set(1);\n    // Give the bar a moment to render the final 100% width before resetting.\n    setTimeout(() => {\n      if (this.count() === 0) this._progress.set(0);\n    }, 220);\n  }\n}\n\nexport type { WrLoadingState } from '../interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation, computed, inject, input } from '@angular/core';\n\nimport { WrLoadingBar } from './services/loading-bar';\n\n/**\n * Thin progress bar fixed to the top of the viewport.\n *\n * Drop one at the root of your shell. Reads the singleton {@link WrLoadingBar}\n * — every router navigation drives it automatically; HTTP interceptors\n * can call `start()` / `complete()` to add their own slots.\n *\n * @example\n * ```html\n * <wr-loading-bar />               <!-- top, primary color -->\n * <wr-loading-bar color=\"#9b51e0\" height=\"3px\" />\n * ```\n */\n@Component({\n  selector: 'wr-loading-bar',\n  templateUrl: './loading-bar.component.html',\n  styleUrl: './loading-bar.scss',\n  encapsulation: ViewEncapsulation.None,\n  host: { class: 'wr-loading-bar' },\n})\nexport class WrLoadingBarComponent {\n  /** Bar colour. Defaults to the primary brand colour. */\n  readonly color = input<string>('var(--wr-color-primary)');\n\n  /** Bar height. */\n  readonly height = input<string>('2px');\n\n  protected readonly bar = inject(WrLoadingBar);\n\n  protected readonly active = computed(() => this.bar.state() !== 'idle');\n}\n","<div class=\"wr-loading-bar__track\" [class.wr-loading-bar--active]=\"active()\">\n  <div\n    class=\"wr-loading-bar__fill\"\n    [style.width.%]=\"bar.progress() * 100\"\n    [style.background]=\"color()\"\n    [style.height]=\"height()\"\n  ></div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}