/* esm-bundle - @angular/elements@18.1.3 - system format - Use of this source code is governed by an MIT-style license that can be found in the LICENSE file at https://angular.io/license */
System.register(['@angular/core', 'rxjs', 'rxjs/operators'], (function (exports) {
    'use strict';
    var Version, ComponentFactoryResolver, NgZone, Injector, ChangeDetectorRef, ApplicationRef, SimpleChange, ReplaySubject, merge, switchMap, map;
    return {
        setters: [function (module) {
            Version = module.Version;
            ComponentFactoryResolver = module.ComponentFactoryResolver;
            NgZone = module.NgZone;
            Injector = module.Injector;
            ChangeDetectorRef = module.ChangeDetectorRef;
            ApplicationRef = module.ApplicationRef;
            SimpleChange = module.SimpleChange;
        }, function (module) {
            ReplaySubject = module.ReplaySubject;
            merge = module.merge;
        }, function (module) {
            switchMap = module.switchMap;
            map = module.map;
        }],
        execute: (function () {

            exports("createCustomElement", createCustomElement);

            /**
             * @license Angular v18.1.3
             * (c) 2010-2024 Google LLC. https://angular.io/
             * License: MIT
             */


            /**
             * Provide methods for scheduling the execution of a callback.
             */
            const scheduler = {
              /**
               * Schedule a callback to be called after some delay.
               *
               * Returns a function that when executed will cancel the scheduled function.
               */
              schedule(taskFn, delay) {
                const id = setTimeout(taskFn, delay);
                return () => clearTimeout(id);
              },
              /**
               * Schedule a callback to be called before the next render.
               * (If `window.requestAnimationFrame()` is not available, use `scheduler.schedule()` instead.)
               *
               * Returns a function that when executed will cancel the scheduled function.
               */
              scheduleBeforeRender(taskFn) {
                // TODO(gkalpak): Implement a better way of accessing `requestAnimationFrame()`
                //                (e.g. accounting for vendor prefix, SSR-compatibility, etc).
                if (typeof window === 'undefined') {
                  // For SSR just schedule immediately.
                  return scheduler.schedule(taskFn, 0);
                }
                if (typeof window.requestAnimationFrame === 'undefined') {
                  const frameMs = 16;
                  return scheduler.schedule(taskFn, frameMs);
                }
                const id = window.requestAnimationFrame(taskFn);
                return () => window.cancelAnimationFrame(id);
              }
            };
            /**
             * Convert a camelCased string to kebab-cased.
             */
            function camelToDashCase(input) {
              return input.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`);
            }
            /**
             * Check whether the input is an `Element`.
             */
            function isElement(node) {
              return !!node && node.nodeType === Node.ELEMENT_NODE;
            }
            /**
             * Check whether the input is a function.
             */
            function isFunction(value) {
              return typeof value === 'function';
            }
            let _matches;
            /**
             * Check whether an `Element` matches a CSS selector.
             * NOTE: this is duplicated from @angular/upgrade, and can
             * be consolidated in the future
             */
            function matchesSelector(el, selector) {
              if (!_matches) {
                const elProto = Element.prototype;
                _matches = elProto.matches || elProto.matchesSelector || elProto.mozMatchesSelector || elProto.msMatchesSelector || elProto.oMatchesSelector || elProto.webkitMatchesSelector;
              }
              return el.nodeType === Node.ELEMENT_NODE ? _matches.call(el, selector) : false;
            }
            /**
             * Test two values for strict equality, accounting for the fact that `NaN !== NaN`.
             */
            function strictEquals(value1, value2) {
              return value1 === value2 || value1 !== value1 && value2 !== value2;
            }
            /** Gets a map of default set of attributes to observe and the properties they affect. */
            function getDefaultAttributeToPropertyInputs(inputs) {
              const attributeToPropertyInputs = {};
              inputs.forEach(({
                propName,
                templateName,
                transform
              }) => {
                attributeToPropertyInputs[camelToDashCase(templateName)] = [propName, transform];
              });
              return attributeToPropertyInputs;
            }
            /**
             * Gets a component's set of inputs. Uses the injector to get the component factory where the inputs
             * are defined.
             */
            function getComponentInputs(component, injector) {
              const componentFactoryResolver = injector.get(ComponentFactoryResolver);
              const componentFactory = componentFactoryResolver.resolveComponentFactory(component);
              return componentFactory.inputs;
            }

            // NOTE: This is a (slightly improved) version of what is used in ngUpgrade's
            function extractProjectableNodes(host, ngContentSelectors) {
              const nodes = host.childNodes;
              const projectableNodes = ngContentSelectors.map(() => []);
              let wildcardIndex = -1;
              ngContentSelectors.some((selector, i) => {
                if (selector === '*') {
                  wildcardIndex = i;
                  return true;
                }
                return false;
              });
              for (let i = 0, ii = nodes.length; i < ii; ++i) {
                const node = nodes[i];
                const ngContentIndex = findMatchingIndex(node, ngContentSelectors, wildcardIndex);
                if (ngContentIndex !== -1) {
                  projectableNodes[ngContentIndex].push(node);
                }
              }
              return projectableNodes;
            }
            function findMatchingIndex(node, selectors, defaultIndex) {
              let matchingIndex = defaultIndex;
              if (isElement(node)) {
                selectors.some((selector, i) => {
                  if (selector !== '*' && matchesSelector(node, selector)) {
                    matchingIndex = i;
                    return true;
                  }
                  return false;
                });
              }
              return matchingIndex;
            }

            /** Time in milliseconds to wait before destroying the component ref when disconnected. */
            const DESTROY_DELAY = 10;
            /**
             * Factory that creates new ComponentNgElementStrategy instance. Gets the component factory with the
             * constructor's injector's factory resolver and passes that factory to each strategy.
             */
            class ComponentNgElementStrategyFactory {
              constructor(component, injector) {
                this.componentFactory = injector.get(ComponentFactoryResolver).resolveComponentFactory(component);
              }
              create(injector) {
                return new ComponentNgElementStrategy(this.componentFactory, injector);
              }
            }
            /**
             * Creates and destroys a component ref using a component factory and handles change detection
             * in response to input changes.
             */
            class ComponentNgElementStrategy {
              constructor(componentFactory, injector) {
                this.componentFactory = componentFactory;
                this.injector = injector;
                // Subject of `NgElementStrategyEvent` observables corresponding to the component's outputs.
                this.eventEmitters = new ReplaySubject(1);
                /** Merged stream of the component's output events. */
                this.events = this.eventEmitters.pipe(switchMap(emitters => merge(...emitters)));
                /** Reference to the component that was created on connect. */
                this.componentRef = null;
                /** Reference to the component view's `ChangeDetectorRef`. */
                this.viewChangeDetectorRef = null;
                /**
                 * Changes that have been made to component inputs since the last change detection run.
                 * (NOTE: These are only recorded if the component implements the `OnChanges` interface.)
                 */
                this.inputChanges = null;
                /** Whether changes have been made to component inputs since the last change detection run. */
                this.hasInputChanges = false;
                /** Whether the created component implements the `OnChanges` interface. */
                this.implementsOnChanges = false;
                /** Whether a change detection has been scheduled to run on the component. */
                this.scheduledChangeDetectionFn = null;
                /** Callback function that when called will cancel a scheduled destruction on the component. */
                this.scheduledDestroyFn = null;
                /** Initial input values that were set before the component was created. */
                this.initialInputValues = new Map();
                this.unchangedInputs = new Set(this.componentFactory.inputs.map(({
                  propName
                }) => propName));
                this.ngZone = this.injector.get(NgZone);
                this.elementZone = typeof Zone === 'undefined' ? null : this.ngZone.run(() => Zone.current);
              }
              /**
               * Initializes a new component if one has not yet been created and cancels any scheduled
               * destruction.
               */
              connect(element) {
                this.runInZone(() => {
                  // If the element is marked to be destroyed, cancel the task since the component was
                  // reconnected
                  if (this.scheduledDestroyFn !== null) {
                    this.scheduledDestroyFn();
                    this.scheduledDestroyFn = null;
                    return;
                  }
                  if (this.componentRef === null) {
                    this.initializeComponent(element);
                  }
                });
              }
              /**
               * Schedules the component to be destroyed after some small delay in case the element is just
               * being moved across the DOM.
               */
              disconnect() {
                this.runInZone(() => {
                  // Return if there is no componentRef or the component is already scheduled for destruction
                  if (this.componentRef === null || this.scheduledDestroyFn !== null) {
                    return;
                  }
                  // Schedule the component to be destroyed after a small timeout in case it is being
                  // moved elsewhere in the DOM
                  this.scheduledDestroyFn = scheduler.schedule(() => {
                    if (this.componentRef !== null) {
                      this.componentRef.destroy();
                      this.componentRef = null;
                      this.viewChangeDetectorRef = null;
                    }
                  }, DESTROY_DELAY);
                });
              }
              /**
               * Returns the component property value. If the component has not yet been created, the value is
               * retrieved from the cached initialization values.
               */
              getInputValue(property) {
                return this.runInZone(() => {
                  if (this.componentRef === null) {
                    return this.initialInputValues.get(property);
                  }
                  return this.componentRef.instance[property];
                });
              }
              /**
               * Sets the input value for the property. If the component has not yet been created, the value is
               * cached and set when the component is created.
               */
              setInputValue(property, value, transform) {
                this.runInZone(() => {
                  if (transform) {
                    value = transform.call(this.componentRef?.instance, value);
                  }
                  if (this.componentRef === null) {
                    this.initialInputValues.set(property, value);
                    return;
                  }
                  // Ignore the value if it is strictly equal to the current value, except if it is `undefined`
                  // and this is the first change to the value (because an explicit `undefined` _is_ strictly
                  // equal to not having a value set at all, but we still need to record this as a change).
                  if (strictEquals(value, this.getInputValue(property)) && !(value === undefined && this.unchangedInputs.has(property))) {
                    return;
                  }
                  // Record the changed value and update internal state to reflect the fact that this input has
                  // changed.
                  this.recordInputChange(property, value);
                  this.unchangedInputs.delete(property);
                  this.hasInputChanges = true;
                  // Update the component instance and schedule change detection.
                  this.componentRef.instance[property] = value;
                  this.scheduleDetectChanges();
                });
              }
              /**
               * Creates a new component through the component factory with the provided element host and
               * sets up its initial inputs, listens for outputs changes, and runs an initial change detection.
               */
              initializeComponent(element) {
                const childInjector = Injector.create({
                  providers: [],
                  parent: this.injector
                });
                const projectableNodes = extractProjectableNodes(element, this.componentFactory.ngContentSelectors);
                this.componentRef = this.componentFactory.create(childInjector, projectableNodes, element);
                this.viewChangeDetectorRef = this.componentRef.injector.get(ChangeDetectorRef);
                this.implementsOnChanges = isFunction(this.componentRef.instance.ngOnChanges);
                this.initializeInputs();
                this.initializeOutputs(this.componentRef);
                this.detectChanges();
                const applicationRef = this.injector.get(ApplicationRef);
                applicationRef.attachView(this.componentRef.hostView);
              }
              /** Set any stored initial inputs on the component's properties. */
              initializeInputs() {
                this.componentFactory.inputs.forEach(({
                  propName,
                  transform
                }) => {
                  if (this.initialInputValues.has(propName)) {
                    // Call `setInputValue()` now that the component has been instantiated to update its
                    // properties and fire `ngOnChanges()`.
                    this.setInputValue(propName, this.initialInputValues.get(propName), transform);
                  }
                });
                this.initialInputValues.clear();
              }
              /** Sets up listeners for the component's outputs so that the events stream emits the events. */
              initializeOutputs(componentRef) {
                const eventEmitters = this.componentFactory.outputs.map(({
                  propName,
                  templateName
                }) => {
                  const emitter = componentRef.instance[propName];
                  return emitter.pipe(map(value => ({
                    name: templateName,
                    value
                  })));
                });
                this.eventEmitters.next(eventEmitters);
              }
              /** Calls ngOnChanges with all the inputs that have changed since the last call. */
              callNgOnChanges(componentRef) {
                if (!this.implementsOnChanges || this.inputChanges === null) {
                  return;
                }
                // Cache the changes and set inputChanges to null to capture any changes that might occur
                // during ngOnChanges.
                const inputChanges = this.inputChanges;
                this.inputChanges = null;
                componentRef.instance.ngOnChanges(inputChanges);
              }
              /**
               * Marks the component view for check, if necessary.
               * (NOTE: This is required when the `ChangeDetectionStrategy` is set to `OnPush`.)
               */
              markViewForCheck(viewChangeDetectorRef) {
                if (this.hasInputChanges) {
                  this.hasInputChanges = false;
                  viewChangeDetectorRef.markForCheck();
                }
              }
              /**
               * Schedules change detection to run on the component.
               * Ignores subsequent calls if already scheduled.
               */
              scheduleDetectChanges() {
                if (this.scheduledChangeDetectionFn) {
                  return;
                }
                this.scheduledChangeDetectionFn = scheduler.scheduleBeforeRender(() => {
                  this.scheduledChangeDetectionFn = null;
                  this.detectChanges();
                });
              }
              /**
               * Records input changes so that the component receives SimpleChanges in its onChanges function.
               */
              recordInputChange(property, currentValue) {
                // Do not record the change if the component does not implement `OnChanges`.
                if (!this.implementsOnChanges) {
                  return;
                }
                if (this.inputChanges === null) {
                  this.inputChanges = {};
                }
                // If there already is a change, modify the current value to match but leave the values for
                // `previousValue` and `isFirstChange`.
                const pendingChange = this.inputChanges[property];
                if (pendingChange) {
                  pendingChange.currentValue = currentValue;
                  return;
                }
                const isFirstChange = this.unchangedInputs.has(property);
                const previousValue = isFirstChange ? undefined : this.getInputValue(property);
                this.inputChanges[property] = new SimpleChange(previousValue, currentValue, isFirstChange);
              }
              /** Runs change detection on the component. */
              detectChanges() {
                if (this.componentRef === null) {
                  return;
                }
                this.callNgOnChanges(this.componentRef);
                this.markViewForCheck(this.viewChangeDetectorRef);
                this.componentRef.changeDetectorRef.detectChanges();
              }
              /** Runs in the angular zone, if present. */
              runInZone(fn) {
                return this.elementZone && Zone.current !== this.elementZone ? this.ngZone.run(fn) : fn();
              }
            }

            /**
             * Implements the functionality needed for a custom element.
             *
             * @publicApi
             */
            class NgElement extends HTMLElement {
              constructor() {
                super(...arguments);
                /**
                 * A subscription to change, connect, and disconnect events in the custom element.
                 */
                this.ngElementEventsSubscription = null;
              }
            } exports("NgElement", NgElement);
            /**
             *  @description Creates a custom element class based on an Angular component.
             *
             * Builds a class that encapsulates the functionality of the provided component and
             * uses the configuration information to provide more context to the class.
             * Takes the component factory's inputs and outputs to convert them to the proper
             * custom element API and add hooks to input changes.
             *
             * The configuration's injector is the initial injector set on the class,
             * and used by default for each created instance.This behavior can be overridden with the
             * static property to affect all newly created instances, or as a constructor argument for
             * one-off creations.
             *
             * @see [Angular Elements Overview](guide/elements "Turning Angular components into custom elements")
             *
             * @param component The component to transform.
             * @param config A configuration that provides initialization information to the created class.
             * @returns The custom-element construction class, which can be registered with
             * a browser's `CustomElementRegistry`.
             *
             * @publicApi
             */
            function createCustomElement(component, config) {
              const inputs = getComponentInputs(component, config.injector);
              const strategyFactory = config.strategyFactory || new ComponentNgElementStrategyFactory(component, config.injector);
              const attributeToPropertyInputs = getDefaultAttributeToPropertyInputs(inputs);
              class NgElementImpl extends NgElement {
                // Work around a bug in closure typed optimizations(b/79557487) where it is not honoring static
                // field externs. So using quoted access to explicitly prevent renaming.
                static {
                  this['observedAttributes'] = Object.keys(attributeToPropertyInputs);
                }
                get ngElementStrategy() {
                  // TODO(andrewseguin): Add e2e tests that cover cases where the constructor isn't called. For
                  // now this is tested using a Google internal test suite.
                  if (!this._ngElementStrategy) {
                    const strategy = this._ngElementStrategy = strategyFactory.create(this.injector || config.injector);
                    // Re-apply pre-existing input values (set as properties on the element) through the
                    // strategy.
                    inputs.forEach(({
                      propName,
                      transform
                    }) => {
                      if (!this.hasOwnProperty(propName)) {
                        // No pre-existing value for `propName`.
                        return;
                      }
                      // Delete the property from the instance and re-apply it through the strategy.
                      const value = this[propName];
                      delete this[propName];
                      strategy.setInputValue(propName, value, transform);
                    });
                  }
                  return this._ngElementStrategy;
                }
                constructor(injector) {
                  super();
                  this.injector = injector;
                }
                attributeChangedCallback(attrName, oldValue, newValue, namespace) {
                  const [propName, transform] = attributeToPropertyInputs[attrName];
                  this.ngElementStrategy.setInputValue(propName, newValue, transform);
                }
                connectedCallback() {
                  // For historical reasons, some strategies may not have initialized the `events` property
                  // until after `connect()` is run. Subscribe to `events` if it is available before running
                  // `connect()` (in order to capture events emitted during initialization), otherwise subscribe
                  // afterwards.
                  //
                  // TODO: Consider deprecating/removing the post-connect subscription in a future major version
                  //       (e.g. v11).
                  let subscribedToEvents = false;
                  if (this.ngElementStrategy.events) {
                    // `events` are already available: Subscribe to it asap.
                    this.subscribeToEvents();
                    subscribedToEvents = true;
                  }
                  this.ngElementStrategy.connect(this);
                  if (!subscribedToEvents) {
                    // `events` were not initialized before running `connect()`: Subscribe to them now.
                    // The events emitted during the component initialization have been missed, but at least
                    // future events will be captured.
                    this.subscribeToEvents();
                  }
                }
                disconnectedCallback() {
                  // Not using `this.ngElementStrategy` to avoid unnecessarily creating the `NgElementStrategy`.
                  if (this._ngElementStrategy) {
                    this._ngElementStrategy.disconnect();
                  }
                  if (this.ngElementEventsSubscription) {
                    this.ngElementEventsSubscription.unsubscribe();
                    this.ngElementEventsSubscription = null;
                  }
                }
                subscribeToEvents() {
                  // Listen for events from the strategy and dispatch them as custom events.
                  this.ngElementEventsSubscription = this.ngElementStrategy.events.subscribe(e => {
                    const customEvent = new CustomEvent(e.name, {
                      detail: e.value
                    });
                    this.dispatchEvent(customEvent);
                  });
                }
              }
              // Add getters and setters to the prototype for each property input.
              inputs.forEach(({
                propName,
                transform
              }) => {
                Object.defineProperty(NgElementImpl.prototype, propName, {
                  get() {
                    return this.ngElementStrategy.getInputValue(propName);
                  },
                  set(newValue) {
                    this.ngElementStrategy.setInputValue(propName, newValue, transform);
                  },
                  configurable: true,
                  enumerable: true
                });
              });
              return NgElementImpl;
            }

            /**
             * @publicApi
             */
            const VERSION = exports("VERSION", new Version('18.1.3'));

        })
    };
}));
//# sourceMappingURL=angular-elements.js.map
