/** * @license Angular v17.1.3 * (c) 2010-2022 Google LLC. https://angular.io/ * License: MIT */ import { DOCUMENT } from '@angular/common'; import * as i0 from '@angular/core'; import { inject, ɵChangeDetectionScheduler, ɵRuntimeError, Injectable, makeEnvironmentProviders, RendererFactory2, NgZone, ANIMATION_MODULE_TYPE } from '@angular/core'; import { ɵDomRendererFactory2 } from '@angular/platform-browser'; const ANIMATION_PREFIX = '@'; class AsyncAnimationRendererFactory { /** * * @param moduleImpl allows to provide a mock implmentation (or will load the animation module) */ constructor(doc, delegate, zone, animationType, moduleImpl) { this.doc = doc; this.delegate = delegate; this.zone = zone; this.animationType = animationType; this.moduleImpl = moduleImpl; this._rendererFactoryPromise = null; this.scheduler = inject(ɵChangeDetectionScheduler, { optional: true }); } /** @nodoc */ ngOnDestroy() { // When the root view is removed, the renderer defers the actual work to the // `TransitionAnimationEngine` to do this, and the `TransitionAnimationEngine` doesn't actually // remove the DOM node, but just calls `markElementAsRemoved()`. The actual DOM node is not // removed until `TransitionAnimationEngine` "flushes". // Note: we already flush on destroy within the `InjectableAnimationEngine`. The injectable // engine is not provided when async animations are used. this._engine?.flush(); } /** * @internal */ loadImpl() { const moduleImpl = this.moduleImpl ?? import('@angular/animations/browser'); return moduleImpl .catch((e) => { throw new ɵRuntimeError(5300 /* RuntimeErrorCode.ANIMATION_RENDERER_ASYNC_LOADING_FAILURE */, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Async loading for animations package was ' + 'enabled, but loading failed. Angular falls back to using regular rendering. ' + 'No animations will be displayed and their styles won\'t be applied.'); }) .then(({ ɵcreateEngine, ɵAnimationRendererFactory }) => { // We can't create the renderer yet because we might need the hostElement and the type // Both are provided in createRenderer(). this._engine = ɵcreateEngine(this.animationType, this.doc, this.scheduler); const rendererFactory = new ɵAnimationRendererFactory(this.delegate, this._engine, this.zone); this.delegate = rendererFactory; return rendererFactory; }); } /** * This method is delegating the renderer creation to the factories. * It uses default factory while the animation factory isn't loaded * and will rely on the animation factory once it is loaded. * * Calling this method will trigger as side effect the loading of the animation module * if the renderered component uses animations. */ createRenderer(hostElement, rendererType) { const renderer = this.delegate.createRenderer(hostElement, rendererType); if (renderer.ɵtype === 0 /* AnimationRendererType.Regular */) { // The factory is already loaded, this is an animation renderer return renderer; } // We need to prevent the DomRenderer to throw an error because of synthetic properties if (typeof renderer.throwOnSyntheticProps === 'boolean') { renderer.throwOnSyntheticProps = false; } // Using a dynamic renderer to switch the renderer implementation once the module is loaded. const dynamicRenderer = new DynamicDelegationRenderer(renderer); // Kick off the module loading if the component uses animations but the module hasn't been // loaded yet. if (rendererType?.data?.['animation'] && !this._rendererFactoryPromise) { this._rendererFactoryPromise = this.loadImpl(); } this._rendererFactoryPromise ?.then((animationRendererFactory) => { const animationRenderer = animationRendererFactory.createRenderer(hostElement, rendererType); dynamicRenderer.use(animationRenderer); }) .catch(e => { // Permanently use regular renderer when loading fails. dynamicRenderer.use(renderer); }); return dynamicRenderer; } begin() { this.delegate.begin?.(); } end() { this.delegate.end?.(); } whenRenderingDone() { return this.delegate.whenRenderingDone?.() ?? Promise.resolve(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AsyncAnimationRendererFactory, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AsyncAnimationRendererFactory }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AsyncAnimationRendererFactory, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: Document }, { type: i0.RendererFactory2 }, { type: i0.NgZone }, { type: undefined }, { type: Promise }] }); /** * The class allows to dynamicly switch between different renderer implementations * by changing the delegate renderer. */ class DynamicDelegationRenderer { constructor(delegate) { this.delegate = delegate; // List of callbacks that need to be replayed on the animation renderer once its loaded this.replay = []; this.ɵtype = 1 /* AnimationRendererType.Delegated */; } use(impl) { this.delegate = impl; if (this.replay !== null) { // Replay queued actions using the animation renderer to apply // all events and properties collected while loading was in progress. for (const fn of this.replay) { fn(impl); } // Set to `null` to indicate that the queue was processed // and we no longer need to collect events and properties. this.replay = null; } } get data() { return this.delegate.data; } destroy() { this.replay = null; this.delegate.destroy(); } createElement(name, namespace) { return this.delegate.createElement(name, namespace); } createComment(value) { return this.delegate.createComment(value); } createText(value) { return this.delegate.createText(value); } get destroyNode() { return this.delegate.destroyNode; } appendChild(parent, newChild) { this.delegate.appendChild(parent, newChild); } insertBefore(parent, newChild, refChild, isMove) { this.delegate.insertBefore(parent, newChild, refChild, isMove); } removeChild(parent, oldChild, isHostElement) { this.delegate.removeChild(parent, oldChild, isHostElement); } selectRootElement(selectorOrNode, preserveContent) { return this.delegate.selectRootElement(selectorOrNode, preserveContent); } parentNode(node) { return this.delegate.parentNode(node); } nextSibling(node) { return this.delegate.nextSibling(node); } setAttribute(el, name, value, namespace) { this.delegate.setAttribute(el, name, value, namespace); } removeAttribute(el, name, namespace) { this.delegate.removeAttribute(el, name, namespace); } addClass(el, name) { this.delegate.addClass(el, name); } removeClass(el, name) { this.delegate.removeClass(el, name); } setStyle(el, style, value, flags) { this.delegate.setStyle(el, style, value, flags); } removeStyle(el, style, flags) { this.delegate.removeStyle(el, style, flags); } setProperty(el, name, value) { // We need to keep track of animation properties set on default renderer // So we can also set them also on the animation renderer if (this.shouldReplay(name)) { this.replay.push((renderer) => renderer.setProperty(el, name, value)); } this.delegate.setProperty(el, name, value); } setValue(node, value) { this.delegate.setValue(node, value); } listen(target, eventName, callback) { // We need to keep track of animation events registred by the default renderer // So we can also register them against the animation renderer if (this.shouldReplay(eventName)) { this.replay.push((renderer) => renderer.listen(target, eventName, callback)); } return this.delegate.listen(target, eventName, callback); } shouldReplay(propOrEventName) { //`null` indicates that we no longer need to collect events and properties return this.replay !== null && propOrEventName.startsWith(ANIMATION_PREFIX); } } /** * Returns the set of [dependency-injection providers](guide/glossary#provider) * to enable animations in an application. See [animations guide](guide/animations) * to learn more about animations in Angular. * * When you use this function instead of the eager `provideAnimations()`, animations won't be * renderered until the renderer is loaded. * * @usageNotes * * The function is useful when you want to enable animations in an application * bootstrapped using the `bootstrapApplication` function. In this scenario there * is no need to import the `BrowserAnimationsModule` NgModule at all, just add * providers returned by this function to the `providers` list as show below. * * ```typescript * bootstrapApplication(RootComponent, { * providers: [ * provideAnimationsAsync() * ] * }); * ``` * * @param type pass `'noop'` as argument to disable animations. * * @publicApi * @developerPreview */ function provideAnimationsAsync(type = 'animations') { return makeEnvironmentProviders([ { provide: RendererFactory2, useFactory: (doc, renderer, zone) => { return new AsyncAnimationRendererFactory(doc, renderer, zone, type); }, deps: [DOCUMENT, ɵDomRendererFactory2, NgZone], }, { provide: ANIMATION_MODULE_TYPE, useValue: type === 'noop' ? 'NoopAnimations' : 'BrowserAnimations', }, ]); } /** * @module * @description * Entry point for all animation APIs of the animation browser package. */ /** * @module * @description * Entry point for all public APIs of this package. */ // This file is not used to build this module. It is only used during editing /** * Generated bundle index. Do not edit. */ export { provideAnimationsAsync, AsyncAnimationRendererFactory as ɵAsyncAnimationRendererFactory }; //# sourceMappingURL=async.mjs.map