{"version":3,"file":"ngxtension-inject-is-intersecting.mjs","sources":["../../../../libs/ngxtension/inject-is-intersecting/src/is-in-viewport.service.ts","../../../../libs/ngxtension/inject-is-intersecting/src/inject-is-intersecting.ts","../../../../libs/ngxtension/inject-is-intersecting/src/ngxtension-inject-is-intersecting.ts"],"sourcesContent":["import { isPlatformBrowser } from '@angular/common';\nimport { inject, Injectable, NgZone, PLATFORM_ID } from '@angular/core';\nimport { Observable, Subject } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class IsInViewportService implements IsInViewportServiceInterface {\n\tprivate readonly ngZone = inject(NgZone);\n\tprivate readonly platformId = inject(PLATFORM_ID);\n\n\tprivate observerListeners = new Map<\n\t\tElement,\n\t\tSubject<IntersectionObserverEntry>\n\t>();\n\tprivate observerCounts = new Map<Element, number>(); // ref count per element\n\tprivate observer?: IntersectionObserver;\n\n\tprivate createObserver() {\n\t\tif (!isPlatformBrowser(this.platformId)) return; // IntersectionObserver is not available on the server\n\t\tthis.observer = this.ngZone.runOutsideAngular(() => {\n\t\t\treturn new IntersectionObserver((entries) => {\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tthis.intersect(entry.target, entry);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tobserve(element: Element): Observable<IntersectionObserverEntry> {\n\t\tif (!this.observer) {\n\t\t\tthis.createObserver();\n\t\t}\n\n\t\t// Increment ref count regardless of whether the element is already observed\n\t\tthis.observerCounts.set(\n\t\t\telement,\n\t\t\t(this.observerCounts.get(element) ?? 0) + 1,\n\t\t);\n\n\t\tif (this.observerListeners.has(element)) {\n\t\t\treturn this.observerListeners.get(element)!.asObservable();\n\t\t}\n\n\t\tthis.observerListeners.set(\n\t\t\telement,\n\t\t\tnew Subject<IntersectionObserverEntry>(),\n\t\t);\n\t\tthis.observer?.observe(element);\n\n\t\treturn this.observerListeners.get(element)!.asObservable();\n\t}\n\n\tunobserve(element: Element): void {\n\t\tif (!this.observerCounts.has(element)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst count = this.observerCounts.get(element)! - 1;\n\n\t\tif (count > 0) {\n\t\t\t// Other consumers are still alive — just decrement and bail\n\t\t\tthis.observerCounts.set(element, count);\n\t\t\treturn;\n\t\t}\n\n\t\t// Last consumer gone — fully tear down this element\n\t\tthis.observerCounts.delete(element);\n\t\tthis.observer?.unobserve(element);\n\n\t\tthis.observerListeners.get(element)?.complete();\n\t\tthis.observerListeners.delete(element);\n\n\t\tif (this.observerListeners.size === 0) {\n\t\t\tthis.disconnect();\n\t\t}\n\t}\n\n\tprivate intersect(element: Element, entry: IntersectionObserverEntry): void {\n\t\tconst subject = this.observerListeners.get(element);\n\t\tif (subject?.observed) {\n\t\t\tthis.ngZone.run(() => subject.next(entry));\n\t\t}\n\t}\n\n\tprivate disconnect(): void {\n\t\tthis.observer?.disconnect();\n\t\tthis.observer = undefined;\n\t}\n}\n\nexport interface IsInViewportServiceInterface {\n\tobserve(element: Element): Observable<IntersectionObserverEntry>;\n\tunobserve(element: Element): void;\n}\n","import { DestroyRef, ElementRef, inject, Injector } from '@angular/core';\nimport { assertInjector } from 'ngxtension/assert-injector';\nimport { Observable } from 'rxjs';\nimport { IsInViewportService } from './is-in-viewport.service';\n\nexport interface InjectIsIntersectingOptions {\n\tinjector?: Injector;\n\telement?: Element;\n}\n\n/**\n * Injects an observable that emits whenever the element is intersecting the viewport.\n * The observable will complete when the element is destroyed.\n * @param options\n *\n * @example\n * export class MyComponent {\n *   private destroyRef = inject(DestroyRef);\n *\n *   isIntersecting$ = injectIsIntersecting();\n *   isInViewport$ = this.isIntersecting$.pipe(\n *     filter(x => x.intersectionRatio > 0),\n *     take(1),\n *   );\n *\n *   ngOnInit() {\n *     this.getData().subscribe();\n *   }\n *\n *   getData() {\n *     // Only fetch data when the element is in the viewport\n *     return this.isInViewport$.pipe(\n *       switchMap(() => this.service.getData()),\n *       takeUntil(this.destroy$)\n *     );\n *   }\n * }\n */\nexport const injectIsIntersecting = ({\n\tinjector,\n\telement,\n}: InjectIsIntersectingOptions = {}): Observable<IntersectionObserverEntry> => {\n\treturn assertInjector(injectIsIntersecting, injector, () => {\n\t\tconst el = element ?? inject(ElementRef<Element>).nativeElement;\n\t\tconst isInViewportService = inject(IsInViewportService);\n\t\tconst destroyRef = inject(DestroyRef);\n\n\t\tconst obs$ = isInViewportService.observe(el);\n\n\t\tdestroyRef.onDestroy(() => isInViewportService.unobserve(el));\n\n\t\treturn obs$;\n\t});\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAKa,mBAAmB,CAAA;AADhC,IAAA,WAAA,GAAA;AAEkB,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AACxB,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAE1C,QAAA,IAAA,CAAA,iBAAiB,GAAG,IAAI,GAAG,EAGhC,CAAC;AACI,QAAA,IAAA,CAAA,cAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;AA0EpD,KAAA;IAvEQ,cAAc,GAAA;AACrB,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;AAAE,YAAA,OAAO;QAChD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAK;AAClD,YAAA,OAAO,IAAI,oBAAoB,CAAC,CAAC,OAAO,KAAI;AAC3C,gBAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;oBAC5B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;iBACpC;AACF,aAAC,CAAC,CAAC;AACJ,SAAC,CAAC,CAAC;KACH;AAED,IAAA,OAAO,CAAC,OAAgB,EAAA;AACvB,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACnB,IAAI,CAAC,cAAc,EAAE,CAAC;SACtB;;QAGD,IAAI,CAAC,cAAc,CAAC,GAAG,CACtB,OAAO,EACP,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3C,CAAC;QAEF,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACxC,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,YAAY,EAAE,CAAC;SAC3D;QAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CACzB,OAAO,EACP,IAAI,OAAO,EAA6B,CACxC,CAAC;AACF,QAAA,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEhC,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,YAAY,EAAE,CAAC;KAC3D;AAED,IAAA,SAAS,CAAC,OAAgB,EAAA;QACzB,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACtC,OAAO;SACP;AAED,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAE,GAAG,CAAC,CAAC;AAEpD,QAAA,IAAI,KAAK,GAAG,CAAC,EAAE;;YAEd,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACxC,OAAO;SACP;;AAGD,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACpC,QAAA,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QAElC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;AAChD,QAAA,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEvC,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,EAAE;YACtC,IAAI,CAAC,UAAU,EAAE,CAAC;SAClB;KACD;IAEO,SAAS,CAAC,OAAgB,EAAE,KAAgC,EAAA;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACpD,QAAA,IAAI,OAAO,EAAE,QAAQ,EAAE;AACtB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;SAC3C;KACD;IAEO,UAAU,GAAA;AACjB,QAAA,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;AAC5B,QAAA,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;KAC1B;8GAjFW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA,EAAA;AAAnB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cADN,MAAM,EAAA,CAAA,CAAA,EAAA;;2FACnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;;;ACMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACI,MAAM,oBAAoB,GAAG,CAAC,EACpC,QAAQ,EACR,OAAO,GAAA,GACyB,EAAE,KAA2C;AAC7E,IAAA,OAAO,cAAc,CAAC,oBAAoB,EAAE,QAAQ,EAAE,MAAK;AAC1D,QAAA,MAAM,EAAE,GAAG,OAAO,IAAI,MAAM,EAAC,UAAmB,EAAC,CAAC,aAAa,CAAC;AAChE,QAAA,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AACxD,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAEtC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAE7C,QAAA,UAAU,CAAC,SAAS,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;AAE9D,QAAA,OAAO,IAAI,CAAC;AACb,KAAC,CAAC,CAAC;AACJ;;ACrDA;;AAEG;;;;"}