1 | /**
|
2 | * @license Angular v13.3.9
|
3 | * (c) 2010-2022 Google LLC. https://angular.io/
|
4 | * License: MIT
|
5 | */
|
6 |
|
7 | import { ComponentFactoryResolver, NgZone, Injector, ChangeDetectorRef, ApplicationRef, SimpleChange, Version } from '@angular/core';
|
8 | import { ReplaySubject, merge } from 'rxjs';
|
9 | import { switchMap, map } from 'rxjs/operators';
|
10 |
|
11 | /**
|
12 | * @license
|
13 | * Copyright Google LLC All Rights Reserved.
|
14 | *
|
15 | * Use of this source code is governed by an MIT-style license that can be
|
16 | * found in the LICENSE file at https://angular.io/license
|
17 | */
|
18 | /**
|
19 | * Provide methods for scheduling the execution of a callback.
|
20 | */
|
21 | const scheduler = {
|
22 | /**
|
23 | * Schedule a callback to be called after some delay.
|
24 | *
|
25 | * Returns a function that when executed will cancel the scheduled function.
|
26 | */
|
27 | schedule(taskFn, delay) {
|
28 | const id = setTimeout(taskFn, delay);
|
29 | return () => clearTimeout(id);
|
30 | },
|
31 | /**
|
32 | * Schedule a callback to be called before the next render.
|
33 | * (If `window.requestAnimationFrame()` is not available, use `scheduler.schedule()` instead.)
|
34 | *
|
35 | * Returns a function that when executed will cancel the scheduled function.
|
36 | */
|
37 | scheduleBeforeRender(taskFn) {
|
38 | // TODO(gkalpak): Implement a better way of accessing `requestAnimationFrame()`
|
39 | // (e.g. accounting for vendor prefix, SSR-compatibility, etc).
|
40 | if (typeof window === 'undefined') {
|
41 | // For SSR just schedule immediately.
|
42 | return scheduler.schedule(taskFn, 0);
|
43 | }
|
44 | if (typeof window.requestAnimationFrame === 'undefined') {
|
45 | const frameMs = 16;
|
46 | return scheduler.schedule(taskFn, frameMs);
|
47 | }
|
48 | const id = window.requestAnimationFrame(taskFn);
|
49 | return () => window.cancelAnimationFrame(id);
|
50 | },
|
51 | };
|
52 | /**
|
53 | * Convert a camelCased string to kebab-cased.
|
54 | */
|
55 | function camelToDashCase(input) {
|
56 | return input.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`);
|
57 | }
|
58 | /**
|
59 | * Check whether the input is an `Element`.
|
60 | */
|
61 | function isElement(node) {
|
62 | return !!node && node.nodeType === Node.ELEMENT_NODE;
|
63 | }
|
64 | /**
|
65 | * Check whether the input is a function.
|
66 | */
|
67 | function isFunction(value) {
|
68 | return typeof value === 'function';
|
69 | }
|
70 | /**
|
71 | * Convert a kebab-cased string to camelCased.
|
72 | */
|
73 | function kebabToCamelCase(input) {
|
74 | return input.replace(/-([a-z\d])/g, (_, char) => char.toUpperCase());
|
75 | }
|
76 | let _matches;
|
77 | /**
|
78 | * Check whether an `Element` matches a CSS selector.
|
79 | * NOTE: this is duplicated from @angular/upgrade, and can
|
80 | * be consolidated in the future
|
81 | */
|
82 | function matchesSelector(el, selector) {
|
83 | if (!_matches) {
|
84 | const elProto = Element.prototype;
|
85 | _matches = elProto.matches || elProto.matchesSelector || elProto.mozMatchesSelector ||
|
86 | elProto.msMatchesSelector || elProto.oMatchesSelector || elProto.webkitMatchesSelector;
|
87 | }
|
88 | return el.nodeType === Node.ELEMENT_NODE ? _matches.call(el, selector) : false;
|
89 | }
|
90 | /**
|
91 | * Test two values for strict equality, accounting for the fact that `NaN !== NaN`.
|
92 | */
|
93 | function strictEquals(value1, value2) {
|
94 | return value1 === value2 || (value1 !== value1 && value2 !== value2);
|
95 | }
|
96 | /** Gets a map of default set of attributes to observe and the properties they affect. */
|
97 | function getDefaultAttributeToPropertyInputs(inputs) {
|
98 | const attributeToPropertyInputs = {};
|
99 | inputs.forEach(({ propName, templateName }) => {
|
100 | attributeToPropertyInputs[camelToDashCase(templateName)] = propName;
|
101 | });
|
102 | return attributeToPropertyInputs;
|
103 | }
|
104 | /**
|
105 | * Gets a component's set of inputs. Uses the injector to get the component factory where the inputs
|
106 | * are defined.
|
107 | */
|
108 | function getComponentInputs(component, injector) {
|
109 | const componentFactoryResolver = injector.get(ComponentFactoryResolver);
|
110 | const componentFactory = componentFactoryResolver.resolveComponentFactory(component);
|
111 | return componentFactory.inputs;
|
112 | }
|
113 |
|
114 | /**
|
115 | * @license
|
116 | * Copyright Google LLC All Rights Reserved.
|
117 | *
|
118 | * Use of this source code is governed by an MIT-style license that can be
|
119 | * found in the LICENSE file at https://angular.io/license
|
120 | */
|
121 | function extractProjectableNodes(host, ngContentSelectors) {
|
122 | const nodes = host.childNodes;
|
123 | const projectableNodes = ngContentSelectors.map(() => []);
|
124 | let wildcardIndex = -1;
|
125 | ngContentSelectors.some((selector, i) => {
|
126 | if (selector === '*') {
|
127 | wildcardIndex = i;
|
128 | return true;
|
129 | }
|
130 | return false;
|
131 | });
|
132 | for (let i = 0, ii = nodes.length; i < ii; ++i) {
|
133 | const node = nodes[i];
|
134 | const ngContentIndex = findMatchingIndex(node, ngContentSelectors, wildcardIndex);
|
135 | if (ngContentIndex !== -1) {
|
136 | projectableNodes[ngContentIndex].push(node);
|
137 | }
|
138 | }
|
139 | return projectableNodes;
|
140 | }
|
141 | function findMatchingIndex(node, selectors, defaultIndex) {
|
142 | let matchingIndex = defaultIndex;
|
143 | if (isElement(node)) {
|
144 | selectors.some((selector, i) => {
|
145 | if ((selector !== '*') && matchesSelector(node, selector)) {
|
146 | matchingIndex = i;
|
147 | return true;
|
148 | }
|
149 | return false;
|
150 | });
|
151 | }
|
152 | return matchingIndex;
|
153 | }
|
154 |
|
155 | /**
|
156 | * @license
|
157 | * Copyright Google LLC All Rights Reserved.
|
158 | *
|
159 | * Use of this source code is governed by an MIT-style license that can be
|
160 | * found in the LICENSE file at https://angular.io/license
|
161 | */
|
162 | /** Time in milliseconds to wait before destroying the component ref when disconnected. */
|
163 | const DESTROY_DELAY = 10;
|
164 | /**
|
165 | * Factory that creates new ComponentNgElementStrategy instance. Gets the component factory with the
|
166 | * constructor's injector's factory resolver and passes that factory to each strategy.
|
167 | *
|
168 | * @publicApi
|
169 | */
|
170 | class ComponentNgElementStrategyFactory {
|
171 | constructor(component, injector) {
|
172 | this.componentFactory =
|
173 | injector.get(ComponentFactoryResolver).resolveComponentFactory(component);
|
174 | }
|
175 | create(injector) {
|
176 | return new ComponentNgElementStrategy(this.componentFactory, injector);
|
177 | }
|
178 | }
|
179 | /**
|
180 | * Creates and destroys a component ref using a component factory and handles change detection
|
181 | * in response to input changes.
|
182 | *
|
183 | * @publicApi
|
184 | */
|
185 | class ComponentNgElementStrategy {
|
186 | constructor(componentFactory, injector) {
|
187 | this.componentFactory = componentFactory;
|
188 | this.injector = injector;
|
189 | // Subject of `NgElementStrategyEvent` observables corresponding to the component's outputs.
|
190 | this.eventEmitters = new ReplaySubject(1);
|
191 | /** Merged stream of the component's output events. */
|
192 | this.events = this.eventEmitters.pipe(switchMap(emitters => merge(...emitters)));
|
193 | /** Reference to the component that was created on connect. */
|
194 | this.componentRef = null;
|
195 | /** Reference to the component view's `ChangeDetectorRef`. */
|
196 | this.viewChangeDetectorRef = null;
|
197 | /**
|
198 | * Changes that have been made to component inputs since the last change detection run.
|
199 | * (NOTE: These are only recorded if the component implements the `OnChanges` interface.)
|
200 | */
|
201 | this.inputChanges = null;
|
202 | /** Whether changes have been made to component inputs since the last change detection run. */
|
203 | this.hasInputChanges = false;
|
204 | /** Whether the created component implements the `OnChanges` interface. */
|
205 | this.implementsOnChanges = false;
|
206 | /** Whether a change detection has been scheduled to run on the component. */
|
207 | this.scheduledChangeDetectionFn = null;
|
208 | /** Callback function that when called will cancel a scheduled destruction on the component. */
|
209 | this.scheduledDestroyFn = null;
|
210 | /** Initial input values that were set before the component was created. */
|
211 | this.initialInputValues = new Map();
|
212 | /**
|
213 | * Set of component inputs that have not yet changed, i.e. for which `recordInputChange()` has not
|
214 | * fired.
|
215 | * (This helps detect the first change of an input, even if it is explicitly set to `undefined`.)
|
216 | */
|
217 | this.unchangedInputs = new Set(this.componentFactory.inputs.map(({ propName }) => propName));
|
218 | /** Service for setting zone context. */
|
219 | this.ngZone = this.injector.get(NgZone);
|
220 | /** The zone the element was created in or `null` if Zone.js is not loaded. */
|
221 | this.elementZone = (typeof Zone === 'undefined') ? null : this.ngZone.run(() => Zone.current);
|
222 | }
|
223 | /**
|
224 | * Initializes a new component if one has not yet been created and cancels any scheduled
|
225 | * destruction.
|
226 | */
|
227 | connect(element) {
|
228 | this.runInZone(() => {
|
229 | // If the element is marked to be destroyed, cancel the task since the component was
|
230 | // reconnected
|
231 | if (this.scheduledDestroyFn !== null) {
|
232 | this.scheduledDestroyFn();
|
233 | this.scheduledDestroyFn = null;
|
234 | return;
|
235 | }
|
236 | if (this.componentRef === null) {
|
237 | this.initializeComponent(element);
|
238 | }
|
239 | });
|
240 | }
|
241 | /**
|
242 | * Schedules the component to be destroyed after some small delay in case the element is just
|
243 | * being moved across the DOM.
|
244 | */
|
245 | disconnect() {
|
246 | this.runInZone(() => {
|
247 | // Return if there is no componentRef or the component is already scheduled for destruction
|
248 | if (this.componentRef === null || this.scheduledDestroyFn !== null) {
|
249 | return;
|
250 | }
|
251 | // Schedule the component to be destroyed after a small timeout in case it is being
|
252 | // moved elsewhere in the DOM
|
253 | this.scheduledDestroyFn = scheduler.schedule(() => {
|
254 | if (this.componentRef !== null) {
|
255 | this.componentRef.destroy();
|
256 | this.componentRef = null;
|
257 | this.viewChangeDetectorRef = null;
|
258 | }
|
259 | }, DESTROY_DELAY);
|
260 | });
|
261 | }
|
262 | /**
|
263 | * Returns the component property value. If the component has not yet been created, the value is
|
264 | * retrieved from the cached initialization values.
|
265 | */
|
266 | getInputValue(property) {
|
267 | return this.runInZone(() => {
|
268 | if (this.componentRef === null) {
|
269 | return this.initialInputValues.get(property);
|
270 | }
|
271 | return this.componentRef.instance[property];
|
272 | });
|
273 | }
|
274 | /**
|
275 | * Sets the input value for the property. If the component has not yet been created, the value is
|
276 | * cached and set when the component is created.
|
277 | */
|
278 | setInputValue(property, value) {
|
279 | this.runInZone(() => {
|
280 | if (this.componentRef === null) {
|
281 | this.initialInputValues.set(property, value);
|
282 | return;
|
283 | }
|
284 | // Ignore the value if it is strictly equal to the current value, except if it is `undefined`
|
285 | // and this is the first change to the value (because an explicit `undefined` _is_ strictly
|
286 | // equal to not having a value set at all, but we still need to record this as a change).
|
287 | if (strictEquals(value, this.getInputValue(property)) &&
|
288 | !((value === undefined) && this.unchangedInputs.has(property))) {
|
289 | return;
|
290 | }
|
291 | // Record the changed value and update internal state to reflect the fact that this input has
|
292 | // changed.
|
293 | this.recordInputChange(property, value);
|
294 | this.unchangedInputs.delete(property);
|
295 | this.hasInputChanges = true;
|
296 | // Update the component instance and schedule change detection.
|
297 | this.componentRef.instance[property] = value;
|
298 | this.scheduleDetectChanges();
|
299 | });
|
300 | }
|
301 | /**
|
302 | * Creates a new component through the component factory with the provided element host and
|
303 | * sets up its initial inputs, listens for outputs changes, and runs an initial change detection.
|
304 | */
|
305 | initializeComponent(element) {
|
306 | const childInjector = Injector.create({ providers: [], parent: this.injector });
|
307 | const projectableNodes = extractProjectableNodes(element, this.componentFactory.ngContentSelectors);
|
308 | this.componentRef = this.componentFactory.create(childInjector, projectableNodes, element);
|
309 | this.viewChangeDetectorRef = this.componentRef.injector.get(ChangeDetectorRef);
|
310 | this.implementsOnChanges = isFunction(this.componentRef.instance.ngOnChanges);
|
311 | this.initializeInputs();
|
312 | this.initializeOutputs(this.componentRef);
|
313 | this.detectChanges();
|
314 | const applicationRef = this.injector.get(ApplicationRef);
|
315 | applicationRef.attachView(this.componentRef.hostView);
|
316 | }
|
317 | /** Set any stored initial inputs on the component's properties. */
|
318 | initializeInputs() {
|
319 | this.componentFactory.inputs.forEach(({ propName }) => {
|
320 | if (this.initialInputValues.has(propName)) {
|
321 | // Call `setInputValue()` now that the component has been instantiated to update its
|
322 | // properties and fire `ngOnChanges()`.
|
323 | this.setInputValue(propName, this.initialInputValues.get(propName));
|
324 | }
|
325 | });
|
326 | this.initialInputValues.clear();
|
327 | }
|
328 | /** Sets up listeners for the component's outputs so that the events stream emits the events. */
|
329 | initializeOutputs(componentRef) {
|
330 | const eventEmitters = this.componentFactory.outputs.map(({ propName, templateName }) => {
|
331 | const emitter = componentRef.instance[propName];
|
332 | return emitter.pipe(map(value => ({ name: templateName, value })));
|
333 | });
|
334 | this.eventEmitters.next(eventEmitters);
|
335 | }
|
336 | /** Calls ngOnChanges with all the inputs that have changed since the last call. */
|
337 | callNgOnChanges(componentRef) {
|
338 | if (!this.implementsOnChanges || this.inputChanges === null) {
|
339 | return;
|
340 | }
|
341 | // Cache the changes and set inputChanges to null to capture any changes that might occur
|
342 | // during ngOnChanges.
|
343 | const inputChanges = this.inputChanges;
|
344 | this.inputChanges = null;
|
345 | componentRef.instance.ngOnChanges(inputChanges);
|
346 | }
|
347 | /**
|
348 | * Marks the component view for check, if necessary.
|
349 | * (NOTE: This is required when the `ChangeDetectionStrategy` is set to `OnPush`.)
|
350 | */
|
351 | markViewForCheck(viewChangeDetectorRef) {
|
352 | if (this.hasInputChanges) {
|
353 | this.hasInputChanges = false;
|
354 | viewChangeDetectorRef.markForCheck();
|
355 | }
|
356 | }
|
357 | /**
|
358 | * Schedules change detection to run on the component.
|
359 | * Ignores subsequent calls if already scheduled.
|
360 | */
|
361 | scheduleDetectChanges() {
|
362 | if (this.scheduledChangeDetectionFn) {
|
363 | return;
|
364 | }
|
365 | this.scheduledChangeDetectionFn = scheduler.scheduleBeforeRender(() => {
|
366 | this.scheduledChangeDetectionFn = null;
|
367 | this.detectChanges();
|
368 | });
|
369 | }
|
370 | /**
|
371 | * Records input changes so that the component receives SimpleChanges in its onChanges function.
|
372 | */
|
373 | recordInputChange(property, currentValue) {
|
374 | // Do not record the change if the component does not implement `OnChanges`.
|
375 | if (!this.implementsOnChanges) {
|
376 | return;
|
377 | }
|
378 | if (this.inputChanges === null) {
|
379 | this.inputChanges = {};
|
380 | }
|
381 | // If there already is a change, modify the current value to match but leave the values for
|
382 | // `previousValue` and `isFirstChange`.
|
383 | const pendingChange = this.inputChanges[property];
|
384 | if (pendingChange) {
|
385 | pendingChange.currentValue = currentValue;
|
386 | return;
|
387 | }
|
388 | const isFirstChange = this.unchangedInputs.has(property);
|
389 | const previousValue = isFirstChange ? undefined : this.getInputValue(property);
|
390 | this.inputChanges[property] = new SimpleChange(previousValue, currentValue, isFirstChange);
|
391 | }
|
392 | /** Runs change detection on the component. */
|
393 | detectChanges() {
|
394 | if (this.componentRef === null) {
|
395 | return;
|
396 | }
|
397 | this.callNgOnChanges(this.componentRef);
|
398 | this.markViewForCheck(this.viewChangeDetectorRef);
|
399 | this.componentRef.changeDetectorRef.detectChanges();
|
400 | }
|
401 | /** Runs in the angular zone, if present. */
|
402 | runInZone(fn) {
|
403 | return (this.elementZone && Zone.current !== this.elementZone) ? this.ngZone.run(fn) : fn();
|
404 | }
|
405 | }
|
406 |
|
407 | /**
|
408 | * @license
|
409 | * Copyright Google LLC All Rights Reserved.
|
410 | *
|
411 | * Use of this source code is governed by an MIT-style license that can be
|
412 | * found in the LICENSE file at https://angular.io/license
|
413 | */
|
414 | /**
|
415 | * Implements the functionality needed for a custom element.
|
416 | *
|
417 | * @publicApi
|
418 | */
|
419 | class NgElement extends HTMLElement {
|
420 | constructor() {
|
421 | super(...arguments);
|
422 | /**
|
423 | * A subscription to change, connect, and disconnect events in the custom element.
|
424 | */
|
425 | this.ngElementEventsSubscription = null;
|
426 | }
|
427 | }
|
428 | /**
|
429 | * @description Creates a custom element class based on an Angular component.
|
430 | *
|
431 | * Builds a class that encapsulates the functionality of the provided component and
|
432 | * uses the configuration information to provide more context to the class.
|
433 | * Takes the component factory's inputs and outputs to convert them to the proper
|
434 | * custom element API and add hooks to input changes.
|
435 | *
|
436 | * The configuration's injector is the initial injector set on the class,
|
437 | * and used by default for each created instance.This behavior can be overridden with the
|
438 | * static property to affect all newly created instances, or as a constructor argument for
|
439 | * one-off creations.
|
440 | *
|
441 | * @see [Angular Elements Overview](guide/elements "Turning Angular components into custom elements")
|
442 | *
|
443 | * @param component The component to transform.
|
444 | * @param config A configuration that provides initialization information to the created class.
|
445 | * @returns The custom-element construction class, which can be registered with
|
446 | * a browser's `CustomElementRegistry`.
|
447 | *
|
448 | * @publicApi
|
449 | */
|
450 | function createCustomElement(component, config) {
|
451 | const inputs = getComponentInputs(component, config.injector);
|
452 | const strategyFactory = config.strategyFactory || new ComponentNgElementStrategyFactory(component, config.injector);
|
453 | const attributeToPropertyInputs = getDefaultAttributeToPropertyInputs(inputs);
|
454 | class NgElementImpl extends NgElement {
|
455 | constructor(injector) {
|
456 | super();
|
457 | this.injector = injector;
|
458 | }
|
459 | get ngElementStrategy() {
|
460 | // NOTE:
|
461 | // Some polyfills (e.g. `document-register-element`) do not call the constructor, therefore
|
462 | // it is not safe to set `ngElementStrategy` in the constructor and assume it will be
|
463 | // available inside the methods.
|
464 | //
|
465 | // TODO(andrewseguin): Add e2e tests that cover cases where the constructor isn't called. For
|
466 | // now this is tested using a Google internal test suite.
|
467 | if (!this._ngElementStrategy) {
|
468 | const strategy = this._ngElementStrategy =
|
469 | strategyFactory.create(this.injector || config.injector);
|
470 | // Re-apply pre-existing input values (set as properties on the element) through the
|
471 | // strategy.
|
472 | inputs.forEach(({ propName }) => {
|
473 | if (!this.hasOwnProperty(propName)) {
|
474 | // No pre-existing value for `propName`.
|
475 | return;
|
476 | }
|
477 | // Delete the property from the instance and re-apply it through the strategy.
|
478 | const value = this[propName];
|
479 | delete this[propName];
|
480 | strategy.setInputValue(propName, value);
|
481 | });
|
482 | }
|
483 | return this._ngElementStrategy;
|
484 | }
|
485 | attributeChangedCallback(attrName, oldValue, newValue, namespace) {
|
486 | const propName = attributeToPropertyInputs[attrName];
|
487 | this.ngElementStrategy.setInputValue(propName, newValue);
|
488 | }
|
489 | connectedCallback() {
|
490 | // For historical reasons, some strategies may not have initialized the `events` property
|
491 | // until after `connect()` is run. Subscribe to `events` if it is available before running
|
492 | // `connect()` (in order to capture events emitted during initialization), otherwise subscribe
|
493 | // afterwards.
|
494 | //
|
495 | // TODO: Consider deprecating/removing the post-connect subscription in a future major version
|
496 | // (e.g. v11).
|
497 | let subscribedToEvents = false;
|
498 | if (this.ngElementStrategy.events) {
|
499 | // `events` are already available: Subscribe to it asap.
|
500 | this.subscribeToEvents();
|
501 | subscribedToEvents = true;
|
502 | }
|
503 | this.ngElementStrategy.connect(this);
|
504 | if (!subscribedToEvents) {
|
505 | // `events` were not initialized before running `connect()`: Subscribe to them now.
|
506 | // The events emitted during the component initialization have been missed, but at least
|
507 | // future events will be captured.
|
508 | this.subscribeToEvents();
|
509 | }
|
510 | }
|
511 | disconnectedCallback() {
|
512 | // Not using `this.ngElementStrategy` to avoid unnecessarily creating the `NgElementStrategy`.
|
513 | if (this._ngElementStrategy) {
|
514 | this._ngElementStrategy.disconnect();
|
515 | }
|
516 | if (this.ngElementEventsSubscription) {
|
517 | this.ngElementEventsSubscription.unsubscribe();
|
518 | this.ngElementEventsSubscription = null;
|
519 | }
|
520 | }
|
521 | subscribeToEvents() {
|
522 | // Listen for events from the strategy and dispatch them as custom events.
|
523 | this.ngElementEventsSubscription = this.ngElementStrategy.events.subscribe(e => {
|
524 | const customEvent = new CustomEvent(e.name, { detail: e.value });
|
525 | this.dispatchEvent(customEvent);
|
526 | });
|
527 | }
|
528 | }
|
529 | // Work around a bug in closure typed optimizations(b/79557487) where it is not honoring static
|
530 | // field externs. So using quoted access to explicitly prevent renaming.
|
531 | NgElementImpl['observedAttributes'] = Object.keys(attributeToPropertyInputs);
|
532 | // Add getters and setters to the prototype for each property input.
|
533 | inputs.forEach(({ propName }) => {
|
534 | Object.defineProperty(NgElementImpl.prototype, propName, {
|
535 | get() {
|
536 | return this.ngElementStrategy.getInputValue(propName);
|
537 | },
|
538 | set(newValue) {
|
539 | this.ngElementStrategy.setInputValue(propName, newValue);
|
540 | },
|
541 | configurable: true,
|
542 | enumerable: true,
|
543 | });
|
544 | });
|
545 | return NgElementImpl;
|
546 | }
|
547 |
|
548 | /**
|
549 | * @license
|
550 | * Copyright Google LLC All Rights Reserved.
|
551 | *
|
552 | * Use of this source code is governed by an MIT-style license that can be
|
553 | * found in the LICENSE file at https://angular.io/license
|
554 | */
|
555 | /**
|
556 | * @publicApi
|
557 | */
|
558 | const VERSION = new Version('13.3.9');
|
559 |
|
560 | /**
|
561 | * @license
|
562 | * Copyright Google LLC All Rights Reserved.
|
563 | *
|
564 | * Use of this source code is governed by an MIT-style license that can be
|
565 | * found in the LICENSE file at https://angular.io/license
|
566 | */
|
567 | // This file only reexports content of the `src` folder. Keep it that way.
|
568 |
|
569 | /**
|
570 | * @license
|
571 | * Copyright Google LLC All Rights Reserved.
|
572 | *
|
573 | * Use of this source code is governed by an MIT-style license that can be
|
574 | * found in the LICENSE file at https://angular.io/license
|
575 | */
|
576 |
|
577 | /**
|
578 | * Generated bundle index. Do not edit.
|
579 | */
|
580 |
|
581 | export { NgElement, VERSION, createCustomElement };
|
582 | //# sourceMappingURL=elements.mjs.map
|