123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import * as i0 from '@angular/core';
- import { inject, NgZone, RendererFactory2, Injectable } from '@angular/core';
- import { Subject, Observable } from 'rxjs';
- import { filter, shareReplay, takeUntil } from 'rxjs/operators';
- /**
- * Handler that logs "ResizeObserver loop limit exceeded" errors.
- * These errors are not shown in the Chrome console, so we log them to ensure developers are aware.
- * @param e The error
- */
- const loopLimitExceededErrorHandler = (e) => {
- if (e instanceof ErrorEvent && e.message === 'ResizeObserver loop limit exceeded') {
- console.error(`${e.message}. This could indicate a performance issue with your app. See https://github.com/WICG/resize-observer/blob/master/explainer.md#error-handling`);
- }
- };
- /**
- * A shared ResizeObserver to be used for a particular box type (content-box, border-box, or
- * device-pixel-content-box)
- */
- class SingleBoxSharedResizeObserver {
- _box;
- /** Stream that emits when the shared observer is destroyed. */
- _destroyed = new Subject();
- /** Stream of all events from the ResizeObserver. */
- _resizeSubject = new Subject();
- /** ResizeObserver used to observe element resize events. */
- _resizeObserver;
- /** A map of elements to streams of their resize events. */
- _elementObservables = new Map();
- constructor(
- /** The box type to observe for resizes. */
- _box) {
- this._box = _box;
- if (typeof ResizeObserver !== 'undefined') {
- this._resizeObserver = new ResizeObserver(entries => this._resizeSubject.next(entries));
- }
- }
- /**
- * Gets a stream of resize events for the given element.
- * @param target The element to observe.
- * @return The stream of resize events for the element.
- */
- observe(target) {
- if (!this._elementObservables.has(target)) {
- this._elementObservables.set(target, new Observable(observer => {
- const subscription = this._resizeSubject.subscribe(observer);
- this._resizeObserver?.observe(target, { box: this._box });
- return () => {
- this._resizeObserver?.unobserve(target);
- subscription.unsubscribe();
- this._elementObservables.delete(target);
- };
- }).pipe(filter(entries => entries.some(entry => entry.target === target)),
- // Share a replay of the last event so that subsequent calls to observe the same element
- // receive initial sizing info like the first one. Also enable ref counting so the
- // element will be automatically unobserved when there are no more subscriptions.
- shareReplay({ bufferSize: 1, refCount: true }), takeUntil(this._destroyed)));
- }
- return this._elementObservables.get(target);
- }
- /** Destroys this instance. */
- destroy() {
- this._destroyed.next();
- this._destroyed.complete();
- this._resizeSubject.complete();
- this._elementObservables.clear();
- }
- }
- /**
- * Allows observing resize events on multiple elements using a shared set of ResizeObserver.
- * Sharing a ResizeObserver instance is recommended for better performance (see
- * https://github.com/WICG/resize-observer/issues/59).
- *
- * Rather than share a single `ResizeObserver`, this class creates one `ResizeObserver` per type
- * of observed box ('content-box', 'border-box', and 'device-pixel-content-box'). This avoids
- * later calls to `observe` with a different box type from influencing the events dispatched to
- * earlier calls.
- */
- class SharedResizeObserver {
- _cleanupErrorListener;
- /** Map of box type to shared resize observer. */
- _observers = new Map();
- /** The Angular zone. */
- _ngZone = inject(NgZone);
- constructor() {
- if (typeof ResizeObserver !== 'undefined' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
- this._ngZone.runOutsideAngular(() => {
- const renderer = inject(RendererFactory2).createRenderer(null, null);
- this._cleanupErrorListener = renderer.listen('window', 'error', loopLimitExceededErrorHandler);
- });
- }
- }
- ngOnDestroy() {
- for (const [, observer] of this._observers) {
- observer.destroy();
- }
- this._observers.clear();
- this._cleanupErrorListener?.();
- }
- /**
- * Gets a stream of resize events for the given target element and box type.
- * @param target The element to observe for resizes.
- * @param options Options to pass to the `ResizeObserver`
- * @return The stream of resize events for the element.
- */
- observe(target, options) {
- const box = options?.box || 'content-box';
- if (!this._observers.has(box)) {
- this._observers.set(box, new SingleBoxSharedResizeObserver(box));
- }
- return this._observers.get(box).observe(target);
- }
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SharedResizeObserver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SharedResizeObserver, providedIn: 'root' });
- }
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SharedResizeObserver, decorators: [{
- type: Injectable,
- args: [{
- providedIn: 'root',
- }]
- }], ctorParameters: () => [] });
- export { SharedResizeObserver };
- //# sourceMappingURL=private.mjs.map
|