@angular/cdk
Version:
Angular Material Component Development Kit
1 lines • 15 kB
Source Map (JSON)
{"version":3,"file":"observers.mjs","sources":["../../../../../darwin_arm64-fastbuild-ST-fdfa778d11ba/bin/src/cdk/observers/observe-content.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\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://angular.dev/license\n */\n\nimport {NumberInput, coerceElement, coerceNumberProperty} from '../coercion';\nimport {\n AfterContentInit,\n Directive,\n ElementRef,\n EventEmitter,\n Service,\n Input,\n NgModule,\n NgZone,\n OnDestroy,\n Output,\n booleanAttribute,\n inject,\n} from '@angular/core';\nimport {Observable, Observer, Subject, Subscription} from 'rxjs';\nimport {debounceTime, filter, map} from 'rxjs/operators';\n\n// Angular may add, remove, or edit comment nodes during change detection. We don't care about\n// these changes because they don't affect the user-preceived content, and worse it can cause\n// infinite change detection cycles where the change detection updates a comment, triggering the\n// MutationObserver, triggering another change detection and kicking the cycle off again.\nfunction shouldIgnoreRecord(record: MutationRecord) {\n // Ignore changes to comment text.\n if (record.type === 'characterData' && record.target instanceof Comment) {\n return true;\n }\n // Ignore addition / removal of comments.\n if (record.type === 'childList') {\n for (let i = 0; i < record.addedNodes.length; i++) {\n if (!(record.addedNodes[i] instanceof Comment)) {\n return false;\n }\n }\n for (let i = 0; i < record.removedNodes.length; i++) {\n if (!(record.removedNodes[i] instanceof Comment)) {\n return false;\n }\n }\n return true;\n }\n // Observe everything else.\n return false;\n}\n\n/**\n * Factory that creates a new MutationObserver and allows us to stub it out in unit tests.\n * @docs-private\n */\n@Service()\nexport class MutationObserverFactory {\n create(callback: MutationCallback): MutationObserver | null {\n return typeof MutationObserver === 'undefined' ? null : new MutationObserver(callback);\n }\n}\n\n/** An injectable service that allows watching elements for changes to their content. */\n@Service()\nexport class ContentObserver implements OnDestroy {\n private _mutationObserverFactory = inject(MutationObserverFactory);\n\n /** Keeps track of the existing MutationObservers so they can be reused. */\n private _observedElements = new Map<\n Element,\n {\n observer: MutationObserver | null;\n readonly stream: Subject<MutationRecord[]>;\n count: number;\n }\n >();\n\n private _ngZone = inject(NgZone);\n\n ngOnDestroy() {\n this._observedElements.forEach((_, element) => this._cleanupObserver(element));\n }\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: Element): Observable<MutationRecord[]>;\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: ElementRef<Element>): Observable<MutationRecord[]>;\n\n observe(elementOrRef: Element | ElementRef<Element>): Observable<MutationRecord[]> {\n const element = coerceElement(elementOrRef);\n\n return new Observable((observer: Observer<MutationRecord[]>) => {\n const stream = this._observeElement(element);\n const subscription = stream\n .pipe(\n map(records => records.filter(record => !shouldIgnoreRecord(record))),\n filter(records => !!records.length),\n )\n .subscribe(records => {\n this._ngZone.run(() => {\n observer.next(records);\n });\n });\n\n return () => {\n subscription.unsubscribe();\n this._unobserveElement(element);\n };\n });\n }\n\n /**\n * Observes the given element by using the existing MutationObserver if available, or creating a\n * new one if not.\n */\n private _observeElement(element: Element): Subject<MutationRecord[]> {\n return this._ngZone.runOutsideAngular(() => {\n if (!this._observedElements.has(element)) {\n const stream = new Subject<MutationRecord[]>();\n const observer = this._mutationObserverFactory.create(mutations => stream.next(mutations));\n if (observer) {\n observer.observe(element, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n }\n this._observedElements.set(element, {observer, stream, count: 1});\n } else {\n this._observedElements.get(element)!.count++;\n }\n return this._observedElements.get(element)!.stream;\n });\n }\n\n /**\n * Un-observes the given element and cleans up the underlying MutationObserver if nobody else is\n * observing this element.\n */\n private _unobserveElement(element: Element) {\n if (this._observedElements.has(element)) {\n this._observedElements.get(element)!.count--;\n if (!this._observedElements.get(element)!.count) {\n this._cleanupObserver(element);\n }\n }\n }\n\n /** Clean up the underlying MutationObserver for the specified element. */\n private _cleanupObserver(element: Element) {\n if (this._observedElements.has(element)) {\n const {observer, stream} = this._observedElements.get(element)!;\n if (observer) {\n observer.disconnect();\n }\n stream.complete();\n this._observedElements.delete(element);\n }\n }\n}\n\n/**\n * Directive that triggers a callback whenever the content of\n * its associated element has changed.\n */\n@Directive({\n selector: '[cdkObserveContent]',\n exportAs: 'cdkObserveContent',\n})\nexport class CdkObserveContent implements AfterContentInit, OnDestroy {\n private _contentObserver = inject(ContentObserver);\n private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Event emitted for each change in the element's content. */\n @Output('cdkObserveContent') readonly event = new EventEmitter<MutationRecord[]>();\n\n /**\n * Whether observing content is disabled. This option can be used\n * to disconnect the underlying MutationObserver until it is needed.\n */\n @Input({alias: 'cdkObserveContentDisabled', transform: booleanAttribute})\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value: boolean) {\n this._disabled = value;\n this._disabled ? this._unsubscribe() : this._subscribe();\n }\n private _disabled = false;\n\n /** Debounce interval for emitting the changes. */\n @Input()\n get debounce(): number {\n return this._debounce!;\n }\n set debounce(value: NumberInput) {\n this._debounce = coerceNumberProperty(value);\n this._subscribe();\n }\n private _debounce: number | undefined;\n\n private _currentSubscription: Subscription | null = null;\n\n ngAfterContentInit() {\n if (!this._currentSubscription && !this.disabled) {\n this._subscribe();\n }\n }\n\n ngOnDestroy() {\n this._unsubscribe();\n }\n\n private _subscribe() {\n this._unsubscribe();\n const stream = this._contentObserver.observe(this._elementRef);\n\n this._currentSubscription = (\n this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream\n ).subscribe(this.event);\n }\n\n private _unsubscribe() {\n this._currentSubscription?.unsubscribe();\n }\n}\n\n@NgModule({\n imports: [CdkObserveContent],\n exports: [CdkObserveContent],\n providers: [MutationObserverFactory],\n})\nexport class ObserversModule {}\n"],"names":["shouldIgnoreRecord","record","type","target","Comment","i","addedNodes","length","removedNodes","MutationObserverFactory","create","callback","MutationObserver","deps","i0","ɵɵFactoryTarget","Service","decorators","ContentObserver","_mutationObserverFactory","inject","_observedElements","Map","_ngZone","NgZone","ngOnDestroy","forEach","_","element","_cleanupObserver","observe","elementOrRef","coerceElement","Observable","observer","stream","_observeElement","subscription","pipe","map","records","filter","subscribe","run","next","unsubscribe","_unobserveElement","runOutsideAngular","has","Subject","mutations","characterData","childList","subtree","set","count","get","disconnect","complete","delete","CdkObserveContent","_contentObserver","_elementRef","ElementRef","event","EventEmitter","disabled","_disabled","value","_unsubscribe","_subscribe","debounce","_debounce","coerceNumberProperty","_currentSubscription","ngAfterContentInit","debounceTime","Directive","ɵdir","ɵɵngDeclareDirective","minVersion","version","booleanAttribute","outputs","exportAs","ngImport","args","selector","Output","Input","alias","transform","ObserversModule","NgModule","imports","exports","providers"],"mappings":";;;;;;AA8BA,SAASA,kBAAkBA,CAACC,MAAsB,EAAA;EAEhD,IAAIA,MAAM,CAACC,IAAI,KAAK,eAAe,IAAID,MAAM,CAACE,MAAM,YAAYC,OAAO,EAAE;AACvE,IAAA,OAAO,IAAI;AACb,EAAA;AAEA,EAAA,IAAIH,MAAM,CAACC,IAAI,KAAK,WAAW,EAAE;AAC/B,IAAA,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,MAAM,CAACK,UAAU,CAACC,MAAM,EAAEF,CAAC,EAAE,EAAE;MACjD,IAAI,EAAEJ,MAAM,CAACK,UAAU,CAACD,CAAC,CAAC,YAAYD,OAAO,CAAC,EAAE;AAC9C,QAAA,OAAO,KAAK;AACd,MAAA;AACF,IAAA;AACA,IAAA,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,MAAM,CAACO,YAAY,CAACD,MAAM,EAAEF,CAAC,EAAE,EAAE;MACnD,IAAI,EAAEJ,MAAM,CAACO,YAAY,CAACH,CAAC,CAAC,YAAYD,OAAO,CAAC,EAAE;AAChD,QAAA,OAAO,KAAK;AACd,MAAA;AACF,IAAA;AACA,IAAA,OAAO,IAAI;AACb,EAAA;AAEA,EAAA,OAAO,KAAK;AACd;MAOaK,uBAAuB,CAAA;EAClCC,MAAMA,CAACC,QAA0B,EAAA;IAC/B,OAAO,OAAOC,gBAAgB,KAAK,WAAW,GAAG,IAAI,GAAG,IAAIA,gBAAgB,CAACD,QAAQ,CAAC;AACxF,EAAA;;;;;UAHWF,uBAAuB;AAAAI,IAAAA,IAAA,EAAA,EAAA;AAAAV,IAAAA,MAAA,EAAAW,EAAA,CAAAC,eAAA,CAAAC;AAAA,GAAA,CAAA;;;;;UAAvBP;AAAuB,GAAA,CAAA;;;;;;QAAvBA,uBAAuB;AAAAQ,EAAAA,UAAA,EAAA,CAAA;UADnCD;;;MASYE,eAAe,CAAA;AAClBC,EAAAA,wBAAwB,GAAGC,MAAM,CAACX,uBAAuB,CAAC;AAG1DY,EAAAA,iBAAiB,GAAG,IAAIC,GAAG,EAOhC;AAEKC,EAAAA,OAAO,GAAGH,MAAM,CAACI,MAAM,CAAC;AAEhCC,EAAAA,WAAWA,GAAA;AACT,IAAA,IAAI,CAACJ,iBAAiB,CAACK,OAAO,CAAC,CAACC,CAAC,EAAEC,OAAO,KAAK,IAAI,CAACC,gBAAgB,CAACD,OAAO,CAAC,CAAC;AAChF,EAAA;EAcAE,OAAOA,CAACC,YAA2C,EAAA;AACjD,IAAA,MAAMH,OAAO,GAAGI,aAAa,CAACD,YAAY,CAAC;AAE3C,IAAA,OAAO,IAAIE,UAAU,CAAEC,QAAoC,IAAI;AAC7D,MAAA,MAAMC,MAAM,GAAG,IAAI,CAACC,eAAe,CAACR,OAAO,CAAC;AAC5C,MAAA,MAAMS,YAAY,GAAGF,MAAA,CAClBG,IAAI,CACHC,GAAG,CAACC,OAAO,IAAIA,OAAO,CAACC,MAAM,CAACxC,MAAM,IAAI,CAACD,kBAAkB,CAACC,MAAM,CAAC,CAAC,CAAC,EACrEwC,MAAM,CAACD,OAAO,IAAI,CAAC,CAACA,OAAO,CAACjC,MAAM,CAAC,CAAA,CAEpCmC,SAAS,CAACF,OAAO,IAAG;AACnB,QAAA,IAAI,CAACjB,OAAO,CAACoB,GAAG,CAAC,MAAK;AACpBT,UAAAA,QAAQ,CAACU,IAAI,CAACJ,OAAO,CAAC;AACxB,QAAA,CAAC,CAAC;AACJ,MAAA,CAAC,CAAC;AAEJ,MAAA,OAAO,MAAK;QACVH,YAAY,CAACQ,WAAW,EAAE;AAC1B,QAAA,IAAI,CAACC,iBAAiB,CAAClB,OAAO,CAAC;MACjC,CAAC;AACH,IAAA,CAAC,CAAC;AACJ,EAAA;EAMQQ,eAAeA,CAACR,OAAgB,EAAA;AACtC,IAAA,OAAO,IAAI,CAACL,OAAO,CAACwB,iBAAiB,CAAC,MAAK;MACzC,IAAI,CAAC,IAAI,CAAC1B,iBAAiB,CAAC2B,GAAG,CAACpB,OAAO,CAAC,EAAE;AACxC,QAAA,MAAMO,MAAM,GAAG,IAAIc,OAAO,EAAoB;AAC9C,QAAA,MAAMf,QAAQ,GAAG,IAAI,CAACf,wBAAwB,CAACT,MAAM,CAACwC,SAAS,IAAIf,MAAM,CAACS,IAAI,CAACM,SAAS,CAAC,CAAC;AAC1F,QAAA,IAAIhB,QAAQ,EAAE;AACZA,UAAAA,QAAQ,CAACJ,OAAO,CAACF,OAAO,EAAE;AACxBuB,YAAAA,aAAa,EAAE,IAAI;AACnBC,YAAAA,SAAS,EAAE,IAAI;AACfC,YAAAA,OAAO,EAAE;AACV,WAAA,CAAC;AACJ,QAAA;AACA,QAAA,IAAI,CAAChC,iBAAiB,CAACiC,GAAG,CAAC1B,OAAO,EAAE;UAACM,QAAQ;UAAEC,MAAM;AAAEoB,UAAAA,KAAK,EAAE;AAAC,SAAC,CAAC;AACnE,MAAA,CAAA,MAAO;QACL,IAAI,CAAClC,iBAAiB,CAACmC,GAAG,CAAC5B,OAAO,CAAE,CAAC2B,KAAK,EAAE;AAC9C,MAAA;MACA,OAAO,IAAI,CAAClC,iBAAiB,CAACmC,GAAG,CAAC5B,OAAO,CAAE,CAACO,MAAM;AACpD,IAAA,CAAC,CAAC;AACJ,EAAA;EAMQW,iBAAiBA,CAAClB,OAAgB,EAAA;IACxC,IAAI,IAAI,CAACP,iBAAiB,CAAC2B,GAAG,CAACpB,OAAO,CAAC,EAAE;MACvC,IAAI,CAACP,iBAAiB,CAACmC,GAAG,CAAC5B,OAAO,CAAE,CAAC2B,KAAK,EAAE;MAC5C,IAAI,CAAC,IAAI,CAAClC,iBAAiB,CAACmC,GAAG,CAAC5B,OAAO,CAAE,CAAC2B,KAAK,EAAE;AAC/C,QAAA,IAAI,CAAC1B,gBAAgB,CAACD,OAAO,CAAC;AAChC,MAAA;AACF,IAAA;AACF,EAAA;EAGQC,gBAAgBA,CAACD,OAAgB,EAAA;IACvC,IAAI,IAAI,CAACP,iBAAiB,CAAC2B,GAAG,CAACpB,OAAO,CAAC,EAAE;MACvC,MAAM;QAACM,QAAQ;AAAEC,QAAAA;OAAO,GAAG,IAAI,CAACd,iBAAiB,CAACmC,GAAG,CAAC5B,OAAO,CAAE;AAC/D,MAAA,IAAIM,QAAQ,EAAE;QACZA,QAAQ,CAACuB,UAAU,EAAE;AACvB,MAAA;MACAtB,MAAM,CAACuB,QAAQ,EAAE;AACjB,MAAA,IAAI,CAACrC,iBAAiB,CAACsC,MAAM,CAAC/B,OAAO,CAAC;AACxC,IAAA;AACF,EAAA;;;;;UArGWV,eAAe;AAAAL,IAAAA,IAAA,EAAA,EAAA;AAAAV,IAAAA,MAAA,EAAAW,EAAA,CAAAC,eAAA,CAAAC;AAAA,GAAA,CAAA;;;;;UAAfE;AAAe,GAAA,CAAA;;;;;;QAAfA,eAAe;AAAAD,EAAAA,UAAA,EAAA,CAAA;UAD3BD;;;MAiHY4C,iBAAiB,CAAA;AACpBC,EAAAA,gBAAgB,GAAGzC,MAAM,CAACF,eAAe,CAAC;AAC1C4C,EAAAA,WAAW,GAAG1C,MAAM,CAA0B2C,UAAU,CAAC;AAG3BC,EAAAA,KAAK,GAAG,IAAIC,YAAY,EAAoB;EAMlF,IACIC,QAAQA,GAAA;IACV,OAAO,IAAI,CAACC,SAAS;AACvB,EAAA;EACA,IAAID,QAAQA,CAACE,KAAc,EAAA;IACzB,IAAI,CAACD,SAAS,GAAGC,KAAK;AACtB,IAAA,IAAI,CAACD,SAAS,GAAG,IAAI,CAACE,YAAY,EAAE,GAAG,IAAI,CAACC,UAAU,EAAE;AAC1D,EAAA;AACQH,EAAAA,SAAS,GAAG,KAAK;EAGzB,IACII,QAAQA,GAAA;IACV,OAAO,IAAI,CAACC,SAAU;AACxB,EAAA;EACA,IAAID,QAAQA,CAACH,KAAkB,EAAA;AAC7B,IAAA,IAAI,CAACI,SAAS,GAAGC,oBAAoB,CAACL,KAAK,CAAC;IAC5C,IAAI,CAACE,UAAU,EAAE;AACnB,EAAA;EACQE,SAAS;AAETE,EAAAA,oBAAoB,GAAwB,IAAI;AAExDC,EAAAA,kBAAkBA,GAAA;IAChB,IAAI,CAAC,IAAI,CAACD,oBAAoB,IAAI,CAAC,IAAI,CAACR,QAAQ,EAAE;MAChD,IAAI,CAACI,UAAU,EAAE;AACnB,IAAA;AACF,EAAA;AAEA7C,EAAAA,WAAWA,GAAA;IACT,IAAI,CAAC4C,YAAY,EAAE;AACrB,EAAA;AAEQC,EAAAA,UAAUA,GAAA;IAChB,IAAI,CAACD,YAAY,EAAE;IACnB,MAAMlC,MAAM,GAAG,IAAI,CAAC0B,gBAAgB,CAAC/B,OAAO,CAAC,IAAI,CAACgC,WAAW,CAAC;IAE9D,IAAI,CAACY,oBAAoB,GAAG,CAC1B,IAAI,CAACH,QAAQ,GAAGpC,MAAM,CAACG,IAAI,CAACsC,YAAY,CAAC,IAAI,CAACL,QAAQ,CAAC,CAAC,GAAGpC,MAAM,EACjEO,SAAS,CAAC,IAAI,CAACsB,KAAK,CAAC;AACzB,EAAA;AAEQK,EAAAA,YAAYA,GAAA;AAClB,IAAA,IAAI,CAACK,oBAAoB,EAAE7B,WAAW,EAAE;AAC1C,EAAA;;;;;UAvDWe,iBAAiB;AAAA/C,IAAAA,IAAA,EAAA,EAAA;AAAAV,IAAAA,MAAA,EAAAW,EAAA,CAAAC,eAAA,CAAA8D;AAAA,GAAA,CAAA;AAAjB,EAAA,OAAAC,IAAA,GAAAhE,EAAA,CAAAiE,oBAAA,CAAA;AAAAC,IAAAA,UAAA,EAAA,QAAA;AAAAC,IAAAA,OAAA,EAAA,aAAA;AAAA/E,IAAAA,IAAA,EAAA0D,iBAAiB;;;;0DAW2BsB,gBAAgB,CAAA;AAAAX,MAAAA,QAAA,EAAA;KAAA;AAAAY,IAAAA,OAAA,EAAA;AAAAnB,MAAAA,KAAA,EAAA;KAAA;IAAAoB,QAAA,EAAA,CAAA,mBAAA,CAAA;AAAAC,IAAAA,QAAA,EAAAvE;AAAA,GAAA,CAAA;;;;;;QAX5D8C,iBAAiB;AAAA3C,EAAAA,UAAA,EAAA,CAAA;UAJ7B4D,SAAS;AAACS,IAAAA,IAAA,EAAA,CAAA;AACTC,MAAAA,QAAQ,EAAE,qBAAqB;AAC/BH,MAAAA,QAAQ,EAAE;KACX;;;;YAMEI,MAAM;aAAC,mBAAmB;;;YAM1BC,KAAK;AAACH,MAAAA,IAAA,EAAA,CAAA;AAACI,QAAAA,KAAK,EAAE,2BAA2B;AAAEC,QAAAA,SAAS,EAAET;OAAiB;;;YAWvEO;;;;MAyCUG,eAAe,CAAA;;;;;UAAfA,eAAe;AAAA/E,IAAAA,IAAA,EAAA,EAAA;AAAAV,IAAAA,MAAA,EAAAW,EAAA,CAAAC,eAAA,CAAA8E;AAAA,GAAA,CAAA;;;;;UAAfD,eAAe;IAAAE,OAAA,EAAA,CA/DflC,iBAAiB,CAAA;IAAAmC,OAAA,EAAA,CAAjBnC,iBAAiB;AAAA,GAAA,CAAA;;;;;UA+DjBgC,eAAe;IAAAI,SAAA,EAFf,CAACvF,uBAAuB;AAAC,GAAA,CAAA;;;;;;QAEzBmF,eAAe;AAAA3E,EAAAA,UAAA,EAAA,CAAA;UAL3B4E,QAAQ;AAACP,IAAAA,IAAA,EAAA,CAAA;MACRQ,OAAO,EAAE,CAAClC,iBAAiB,CAAC;MAC5BmC,OAAO,EAAE,CAACnC,iBAAiB,CAAC;MAC5BoC,SAAS,EAAE,CAACvF,uBAAuB;KACpC;;;;;;"}