import { ElementRef, Directive, TemplateRef, ViewContainerRef, EventEmitter, ComponentFactoryResolver, Inject, Output, NgModule } from '@angular/core'; import { DOCUMENT } from '@angular/common'; /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/portal-errors.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @license * Copyright Google LLC All Rights Reserved. * * 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 */ /** * Throws an exception when attempting to attach a null portal to a host. * \@docs-private * @return {?} */ function throwNullPortalError() { throw Error('Must provide a portal to attach'); } /** * Throws an exception when attempting to attach a portal to a host that is already attached. * \@docs-private * @return {?} */ function throwPortalAlreadyAttachedError() { throw Error('Host already has a portal attached'); } /** * Throws an exception when attempting to attach a portal to an already-disposed host. * \@docs-private * @return {?} */ function throwPortalOutletAlreadyDisposedError() { throw Error('This PortalOutlet has already been disposed'); } /** * Throws an exception when attempting to attach an unknown portal type. * \@docs-private * @return {?} */ function throwUnknownPortalTypeError() { throw Error('Attempting to attach an unknown Portal type. BasePortalOutlet accepts either ' + 'a ComponentPortal or a TemplatePortal.'); } /** * Throws an exception when attempting to attach a portal to a null host. * \@docs-private * @return {?} */ function throwNullPortalOutletError() { throw Error('Attempting to attach a portal to a null PortalOutlet'); } /** * Throws an exception when attempting to detach a portal that is not attached. * \@docs-private * @return {?} */ function throwNoPortalAttachedError() { throw Error('Attempting to detach a portal that is not attached to a host'); } /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/portal.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Interface that can be used to generically type a class. * @record * @template T */ function ComponentType() { } /** * A `Portal` is something that you want to render somewhere else. * It can be attach to / detached from a `PortalOutlet`. * @abstract * @template T */ class Portal { /** * Attach this portal to a host. * @param {?} host * @return {?} */ attach(host) { if (host == null) { throwNullPortalOutletError(); } if (host.hasAttached()) { throwPortalAlreadyAttachedError(); } this._attachedHost = host; return (/** @type {?} */ (host.attach(this))); } /** * Detach this portal from its host * @return {?} */ detach() { /** @type {?} */ let host = this._attachedHost; if (host == null) { throwNoPortalAttachedError(); } else { this._attachedHost = null; host.detach(); } } /** * Whether this portal is attached to a host. * @return {?} */ get isAttached() { return this._attachedHost != null; } /** * Sets the PortalOutlet reference without performing `attach()`. This is used directly by * the PortalOutlet when it is performing an `attach()` or `detach()`. * @param {?} host * @return {?} */ setAttachedHost(host) { this._attachedHost = host; } } if (false) { /** * @type {?} * @private */ Portal.prototype._attachedHost; } /** * A `ComponentPortal` is a portal that instantiates some Component upon attachment. * @template T */ class ComponentPortal extends Portal { /** * @param {?} component * @param {?=} viewContainerRef * @param {?=} injector * @param {?=} componentFactoryResolver */ constructor(component, viewContainerRef, injector, componentFactoryResolver) { super(); this.component = component; this.viewContainerRef = viewContainerRef; this.injector = injector; this.componentFactoryResolver = componentFactoryResolver; } } if (false) { /** * The type of the component that will be instantiated for attachment. * @type {?} */ ComponentPortal.prototype.component; /** * [Optional] Where the attached component should live in Angular's *logical* component tree. * This is different from where the component *renders*, which is determined by the PortalOutlet. * The origin is necessary when the host is outside of the Angular application context. * @type {?} */ ComponentPortal.prototype.viewContainerRef; /** * [Optional] Injector used for the instantiation of the component. * @type {?} */ ComponentPortal.prototype.injector; /** * Alternate `ComponentFactoryResolver` to use when resolving the associated component. * Defaults to using the resolver from the outlet that the portal is attached to. * @type {?} */ ComponentPortal.prototype.componentFactoryResolver; } /** * A `TemplatePortal` is a portal that represents some embedded template (TemplateRef). * @template C */ class TemplatePortal extends Portal { /** * @param {?} template * @param {?} viewContainerRef * @param {?=} context */ constructor(template, viewContainerRef, context) { super(); this.templateRef = template; this.viewContainerRef = viewContainerRef; this.context = context; } /** * @return {?} */ get origin() { return this.templateRef.elementRef; } /** * Attach the portal to the provided `PortalOutlet`. * When a context is provided it will override the `context` property of the `TemplatePortal` * instance. * @param {?} host * @param {?=} context * @return {?} */ attach(host, context = this.context) { this.context = context; return super.attach(host); } /** * @return {?} */ detach() { this.context = undefined; return super.detach(); } } if (false) { /** * The embedded template that will be used to instantiate an embedded View in the host. * @type {?} */ TemplatePortal.prototype.templateRef; /** * Reference to the ViewContainer into which the template will be stamped out. * @type {?} */ TemplatePortal.prototype.viewContainerRef; /** * Contextual data to be passed in to the embedded view. * @type {?} */ TemplatePortal.prototype.context; } /** * A `DomPortal` is a portal whose DOM element will be taken from its current position * in the DOM and moved into a portal outlet, when it is attached. On detach, the content * will be restored to its original position. * @template T */ class DomPortal extends Portal { /** * @param {?} element */ constructor(element) { super(); this.element = element instanceof ElementRef ? element.nativeElement : element; } } if (false) { /** * DOM node hosting the portal's content. * @type {?} */ DomPortal.prototype.element; } /** * A `PortalOutlet` is an space that can contain a single `Portal`. * @record */ function PortalOutlet() { } if (false) { /** * Attaches a portal to this outlet. * @param {?} portal * @return {?} */ PortalOutlet.prototype.attach = function (portal) { }; /** * Detaches the currently attached portal from this outlet. * @return {?} */ PortalOutlet.prototype.detach = function () { }; /** * Performs cleanup before the outlet is destroyed. * @return {?} */ PortalOutlet.prototype.dispose = function () { }; /** * Whether there is currently a portal attached to this outlet. * @return {?} */ PortalOutlet.prototype.hasAttached = function () { }; } /** * Partial implementation of PortalOutlet that handles attaching * ComponentPortal and TemplatePortal. * @abstract */ class BasePortalOutlet { constructor() { /** * Whether this host has already been permanently disposed. */ this._isDisposed = false; // @breaking-change 10.0.0 `attachDomPortal` to become a required abstract method. this.attachDomPortal = null; } /** * Whether this host has an attached portal. * @return {?} */ hasAttached() { return !!this._attachedPortal; } /** * Attaches a portal. * @param {?} portal * @return {?} */ attach(portal) { if (!portal) { throwNullPortalError(); } if (this.hasAttached()) { throwPortalAlreadyAttachedError(); } if (this._isDisposed) { throwPortalOutletAlreadyDisposedError(); } if (portal instanceof ComponentPortal) { this._attachedPortal = portal; return this.attachComponentPortal(portal); } else if (portal instanceof TemplatePortal) { this._attachedPortal = portal; return this.attachTemplatePortal(portal); // @breaking-change 10.0.0 remove null check for `this.attachDomPortal`. } else if (this.attachDomPortal && portal instanceof DomPortal) { this._attachedPortal = portal; return this.attachDomPortal(portal); } throwUnknownPortalTypeError(); } /** * Detaches a previously attached portal. * @return {?} */ detach() { if (this._attachedPortal) { this._attachedPortal.setAttachedHost(null); this._attachedPortal = null; } this._invokeDisposeFn(); } /** * Permanently dispose of this portal host. * @return {?} */ dispose() { if (this.hasAttached()) { this.detach(); } this._invokeDisposeFn(); this._isDisposed = true; } /** * \@docs-private * @param {?} fn * @return {?} */ setDisposeFn(fn) { this._disposeFn = fn; } /** * @private * @return {?} */ _invokeDisposeFn() { if (this._disposeFn) { this._disposeFn(); this._disposeFn = null; } } } if (false) { /** * The portal currently attached to the host. * @type {?} * @protected */ BasePortalOutlet.prototype._attachedPortal; /** * A function that will permanently dispose this host. * @type {?} * @private */ BasePortalOutlet.prototype._disposeFn; /** * Whether this host has already been permanently disposed. * @type {?} * @private */ BasePortalOutlet.prototype._isDisposed; /** @type {?} */ BasePortalOutlet.prototype.attachDomPortal; /** * @abstract * @template T * @param {?} portal * @return {?} */ BasePortalOutlet.prototype.attachComponentPortal = function (portal) { }; /** * @abstract * @template C * @param {?} portal * @return {?} */ BasePortalOutlet.prototype.attachTemplatePortal = function (portal) { }; } /** * @deprecated Use `BasePortalOutlet` instead. * \@breaking-change 9.0.0 * @abstract */ class BasePortalHost extends BasePortalOutlet { } /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/dom-portal-outlet.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * A PortalOutlet for attaching portals to an arbitrary DOM element outside of the Angular * application context. */ class DomPortalOutlet extends BasePortalOutlet { /** * @param {?} outletElement * @param {?} _componentFactoryResolver * @param {?} _appRef * @param {?} _defaultInjector * @param {?=} _document */ constructor(outletElement, _componentFactoryResolver, _appRef, _defaultInjector, /** * @deprecated `_document` Parameter to be made required. * @breaking-change 10.0.0 */ _document) { super(); this.outletElement = outletElement; this._componentFactoryResolver = _componentFactoryResolver; this._appRef = _appRef; this._defaultInjector = _defaultInjector; /** * Attaches a DOM portal by transferring its content into the outlet. * @param portal Portal to be attached. * @deprecated To be turned into a method. * \@breaking-change 10.0.0 */ this.attachDomPortal = (/** * @param {?} portal * @return {?} */ (portal) => { // @breaking-change 10.0.0 Remove check and error once the // `_document` constructor parameter is required. if (!this._document) { throw Error('Cannot attach DOM portal without _document constructor parameter'); } /** @type {?} */ const element = portal.element; if (!element.parentNode) { throw Error('DOM portal content must be attached to a parent node.'); } // Anchor used to save the element's previous position so // that we can restore it when the portal is detached. /** @type {?} */ const anchorNode = this._document.createComment('dom-portal'); element.parentNode.insertBefore(anchorNode, element); this.outletElement.appendChild(element); super.setDisposeFn((/** * @return {?} */ () => { // We can't use `replaceWith` here because IE doesn't support it. if (anchorNode.parentNode) { anchorNode.parentNode.replaceChild(element, anchorNode); } })); }); this._document = _document; } /** * Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. * @template T * @param {?} portal Portal to be attached * @return {?} Reference to the created component. */ attachComponentPortal(portal) { /** @type {?} */ const resolver = portal.componentFactoryResolver || this._componentFactoryResolver; /** @type {?} */ const componentFactory = resolver.resolveComponentFactory(portal.component); /** @type {?} */ let componentRef; // If the portal specifies a ViewContainerRef, we will use that as the attachment point // for the component (in terms of Angular's component tree, not rendering). // When the ViewContainerRef is missing, we use the factory to create the component directly // and then manually attach the view to the application. if (portal.viewContainerRef) { componentRef = portal.viewContainerRef.createComponent(componentFactory, portal.viewContainerRef.length, portal.injector || portal.viewContainerRef.injector); this.setDisposeFn((/** * @return {?} */ () => componentRef.destroy())); } else { componentRef = componentFactory.create(portal.injector || this._defaultInjector); this._appRef.attachView(componentRef.hostView); this.setDisposeFn((/** * @return {?} */ () => { this._appRef.detachView(componentRef.hostView); componentRef.destroy(); })); } // At this point the component has been instantiated, so we move it to the location in the DOM // where we want it to be rendered. this.outletElement.appendChild(this._getComponentRootNode(componentRef)); return componentRef; } /** * Attaches a template portal to the DOM as an embedded view. * @template C * @param {?} portal Portal to be attached. * @return {?} Reference to the created embedded view. */ attachTemplatePortal(portal) { /** @type {?} */ let viewContainer = portal.viewContainerRef; /** @type {?} */ let viewRef = viewContainer.createEmbeddedView(portal.templateRef, portal.context); viewRef.detectChanges(); // The method `createEmbeddedView` will add the view as a child of the viewContainer. // But for the DomPortalOutlet the view can be added everywhere in the DOM // (e.g Overlay Container) To move the view to the specified host element. We just // re-append the existing root nodes. viewRef.rootNodes.forEach((/** * @param {?} rootNode * @return {?} */ rootNode => this.outletElement.appendChild(rootNode))); this.setDisposeFn(((/** * @return {?} */ () => { /** @type {?} */ let index = viewContainer.indexOf(viewRef); if (index !== -1) { viewContainer.remove(index); } }))); // TODO(jelbourn): Return locals from view. return viewRef; } /** * Clears out a portal from the DOM. * @return {?} */ dispose() { super.dispose(); if (this.outletElement.parentNode != null) { this.outletElement.parentNode.removeChild(this.outletElement); } } /** * Gets the root HTMLElement for an instantiated component. * @private * @param {?} componentRef * @return {?} */ _getComponentRootNode(componentRef) { return (/** @type {?} */ (((/** @type {?} */ (componentRef.hostView))).rootNodes[0])); } } if (false) { /** * @type {?} * @private */ DomPortalOutlet.prototype._document; /** * Attaches a DOM portal by transferring its content into the outlet. * \@param portal Portal to be attached. * @deprecated To be turned into a method. * \@breaking-change 10.0.0 * @type {?} */ DomPortalOutlet.prototype.attachDomPortal; /** * Element into which the content is projected. * @type {?} */ DomPortalOutlet.prototype.outletElement; /** * @type {?} * @private */ DomPortalOutlet.prototype._componentFactoryResolver; /** * @type {?} * @private */ DomPortalOutlet.prototype._appRef; /** * @type {?} * @private */ DomPortalOutlet.prototype._defaultInjector; } /** * @deprecated Use `DomPortalOutlet` instead. * \@breaking-change 9.0.0 */ class DomPortalHost extends DomPortalOutlet { } /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/portal-directives.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal, * the directive instance itself can be attached to a host, enabling declarative use of portals. */ class CdkPortal extends TemplatePortal { /** * @param {?} templateRef * @param {?} viewContainerRef */ constructor(templateRef, viewContainerRef) { super(templateRef, viewContainerRef); } } CdkPortal.decorators = [ { type: Directive, args: [{ selector: '[cdkPortal]', exportAs: 'cdkPortal', },] } ]; /** @nocollapse */ CdkPortal.ctorParameters = () => [ { type: TemplateRef }, { type: ViewContainerRef } ]; /** * @deprecated Use `CdkPortal` instead. * \@breaking-change 9.0.0 */ class TemplatePortalDirective extends CdkPortal { } TemplatePortalDirective.decorators = [ { type: Directive, args: [{ selector: '[cdk-portal], [portal]', exportAs: 'cdkPortal', providers: [{ provide: CdkPortal, useExisting: TemplatePortalDirective }] },] } ]; /** * Directive version of a PortalOutlet. Because the directive *is* a PortalOutlet, portals can be * directly attached to it, enabling declarative use. * * Usage: * `` */ class CdkPortalOutlet extends BasePortalOutlet { /** * @param {?} _componentFactoryResolver * @param {?} _viewContainerRef * @param {?=} _document */ constructor(_componentFactoryResolver, _viewContainerRef, /** * @deprecated `_document` parameter to be made required. * @breaking-change 9.0.0 */ _document) { super(); this._componentFactoryResolver = _componentFactoryResolver; this._viewContainerRef = _viewContainerRef; /** * Whether the portal component is initialized. */ this._isInitialized = false; /** * Emits when a portal is attached to the outlet. */ this.attached = new EventEmitter(); /** * Attaches the given DomPortal to this PortalHost by moving all of the portal content into it. * @param portal Portal to be attached. * @deprecated To be turned into a method. * \@breaking-change 10.0.0 */ this.attachDomPortal = (/** * @param {?} portal * @return {?} */ (portal) => { // @breaking-change 9.0.0 Remove check and error once the // `_document` constructor parameter is required. if (!this._document) { throw Error('Cannot attach DOM portal without _document constructor parameter'); } /** @type {?} */ const element = portal.element; if (!element.parentNode) { throw Error('DOM portal content must be attached to a parent node.'); } // Anchor used to save the element's previous position so // that we can restore it when the portal is detached. /** @type {?} */ const anchorNode = this._document.createComment('dom-portal'); portal.setAttachedHost(this); element.parentNode.insertBefore(anchorNode, element); this._getRootNode().appendChild(element); super.setDisposeFn((/** * @return {?} */ () => { if (anchorNode.parentNode) { (/** @type {?} */ (anchorNode.parentNode)).replaceChild(element, anchorNode); } })); }); this._document = _document; } /** * Portal associated with the Portal outlet. * @return {?} */ get portal() { return this._attachedPortal; } /** * @param {?} portal * @return {?} */ set portal(portal) { // Ignore the cases where the `portal` is set to a falsy value before the lifecycle hooks have // run. This handles the cases where the user might do something like `
` // and attach a portal programmatically in the parent component. When Angular does the first CD // round, it will fire the setter with empty string, causing the user's content to be cleared. if (this.hasAttached() && !portal && !this._isInitialized) { return; } if (this.hasAttached()) { super.detach(); } if (portal) { super.attach(portal); } this._attachedPortal = portal; } /** * Component or view reference that is attached to the portal. * @return {?} */ get attachedRef() { return this._attachedRef; } /** * @return {?} */ ngOnInit() { this._isInitialized = true; } /** * @return {?} */ ngOnDestroy() { super.dispose(); this._attachedPortal = null; this._attachedRef = null; } /** * Attach the given ComponentPortal to this PortalOutlet using the ComponentFactoryResolver. * * @template T * @param {?} portal Portal to be attached to the portal outlet. * @return {?} Reference to the created component. */ attachComponentPortal(portal) { portal.setAttachedHost(this); // If the portal specifies an origin, use that as the logical location of the component // in the application tree. Otherwise use the location of this PortalOutlet. /** @type {?} */ const viewContainerRef = portal.viewContainerRef != null ? portal.viewContainerRef : this._viewContainerRef; /** @type {?} */ const resolver = portal.componentFactoryResolver || this._componentFactoryResolver; /** @type {?} */ const componentFactory = resolver.resolveComponentFactory(portal.component); /** @type {?} */ const ref = viewContainerRef.createComponent(componentFactory, viewContainerRef.length, portal.injector || viewContainerRef.injector); // If we're using a view container that's different from the injected one (e.g. when the portal // specifies its own) we need to move the component into the outlet, otherwise it'll be rendered // inside of the alternate view container. if (viewContainerRef !== this._viewContainerRef) { this._getRootNode().appendChild(((/** @type {?} */ (ref.hostView))).rootNodes[0]); } super.setDisposeFn((/** * @return {?} */ () => ref.destroy())); this._attachedPortal = portal; this._attachedRef = ref; this.attached.emit(ref); return ref; } /** * Attach the given TemplatePortal to this PortalHost as an embedded View. * @template C * @param {?} portal Portal to be attached. * @return {?} Reference to the created embedded view. */ attachTemplatePortal(portal) { portal.setAttachedHost(this); /** @type {?} */ const viewRef = this._viewContainerRef.createEmbeddedView(portal.templateRef, portal.context); super.setDisposeFn((/** * @return {?} */ () => this._viewContainerRef.clear())); this._attachedPortal = portal; this._attachedRef = viewRef; this.attached.emit(viewRef); return viewRef; } /** * Gets the root node of the portal outlet. * @private * @return {?} */ _getRootNode() { /** @type {?} */ const nativeElement = this._viewContainerRef.element.nativeElement; // The directive could be set on a template which will result in a comment // node being the root. Use the comment's parent node if that is the case. return (/** @type {?} */ ((nativeElement.nodeType === nativeElement.ELEMENT_NODE ? nativeElement : (/** @type {?} */ (nativeElement.parentNode))))); } } CdkPortalOutlet.decorators = [ { type: Directive, args: [{ selector: '[cdkPortalOutlet]', exportAs: 'cdkPortalOutlet', inputs: ['portal: cdkPortalOutlet'] },] } ]; /** @nocollapse */ CdkPortalOutlet.ctorParameters = () => [ { type: ComponentFactoryResolver }, { type: ViewContainerRef }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } ]; CdkPortalOutlet.propDecorators = { attached: [{ type: Output }] }; if (false) { /** @type {?} */ CdkPortalOutlet.ngAcceptInputType_portal; /** * @type {?} * @private */ CdkPortalOutlet.prototype._document; /** * Whether the portal component is initialized. * @type {?} * @private */ CdkPortalOutlet.prototype._isInitialized; /** * Reference to the currently-attached component/view ref. * @type {?} * @private */ CdkPortalOutlet.prototype._attachedRef; /** * Emits when a portal is attached to the outlet. * @type {?} */ CdkPortalOutlet.prototype.attached; /** * Attaches the given DomPortal to this PortalHost by moving all of the portal content into it. * \@param portal Portal to be attached. * @deprecated To be turned into a method. * \@breaking-change 10.0.0 * @type {?} */ CdkPortalOutlet.prototype.attachDomPortal; /** * @type {?} * @private */ CdkPortalOutlet.prototype._componentFactoryResolver; /** * @type {?} * @private */ CdkPortalOutlet.prototype._viewContainerRef; } /** * @deprecated Use `CdkPortalOutlet` instead. * \@breaking-change 9.0.0 */ class PortalHostDirective extends CdkPortalOutlet { } PortalHostDirective.decorators = [ { type: Directive, args: [{ selector: '[cdkPortalHost], [portalHost]', exportAs: 'cdkPortalHost', inputs: ['portal: cdkPortalHost'], providers: [{ provide: CdkPortalOutlet, useExisting: PortalHostDirective }] },] } ]; class PortalModule { } PortalModule.decorators = [ { type: NgModule, args: [{ exports: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective], declarations: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective], },] } ]; /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/portal-injector.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @license * Copyright Google LLC All Rights Reserved. * * 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 */ /** * Custom injector to be used when providing custom * injection tokens to components inside a portal. * \@docs-private */ class PortalInjector { /** * @param {?} _parentInjector * @param {?} _customTokens */ constructor(_parentInjector, _customTokens) { this._parentInjector = _parentInjector; this._customTokens = _customTokens; } /** * @param {?} token * @param {?=} notFoundValue * @return {?} */ get(token, notFoundValue) { /** @type {?} */ const value = this._customTokens.get(token); if (typeof value !== 'undefined') { return value; } return this._parentInjector.get(token, notFoundValue); } } if (false) { /** * @type {?} * @private */ PortalInjector.prototype._parentInjector; /** * @type {?} * @private */ PortalInjector.prototype._customTokens; } /** * @fileoverview added by tsickle * Generated from: src/cdk/portal/public-api.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Generated bundle index. Do not edit. */ export { BasePortalHost, BasePortalOutlet, CdkPortal, CdkPortalOutlet, ComponentPortal, DomPortal, DomPortalHost, DomPortalOutlet, Portal, PortalHostDirective, PortalInjector, PortalModule, TemplatePortal, TemplatePortalDirective }; //# sourceMappingURL=portal.js.map