@xui/components
Version:
xUI Components for Angular
243 lines • 33.5 kB
JavaScript
import { Injectable, Injector, Optional, SkipSelf, TemplateRef } from '@angular/core';
import { SnackBarConfig } from '../config';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
import { SimpleSnackBar } from './simple-snack-bar';
import { SnackBarRef } from './snack-bar-ref';
import { SnackBarContainer } from './snack-bar-container';
import { XUI_SNACK_BAR_DATA } from './snack-bar.types';
import { LiveAnnouncer } from '@angular/cdk/a11y';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
import { takeUntil } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/overlay";
import * as i2 from "@angular/cdk/a11y";
import * as i3 from "@angular/cdk/layout";
export class XuiSnackBar {
/** Reference to the currently opened snackbar at *any* level. */
get openedSnackBarRef() {
const parent = this.parentSnackBar;
return parent ? parent.openedSnackBarRef : this.snackBarRefAtThisLevel;
}
set openedSnackBarRef(value) {
if (this.parentSnackBar) {
this.parentSnackBar.openedSnackBarRef = value;
}
else {
this.snackBarRefAtThisLevel = value;
}
}
constructor(overlay, live, injector, breakpointObserver, parentSnackBar
// @Inject(XUI_SNACK_BAR_DEFAULT_OPTIONS) defaultConfig: XuiSnackBarConfig
) {
this.overlay = overlay;
this.live = live;
this.injector = injector;
this.breakpointObserver = breakpointObserver;
this.parentSnackBar = parentSnackBar;
/**
* Reference to the current snack bar in the view *at this level* (in the Angular injector tree).
* If there is a parent snack-bar service, all operations should delegate to that parent
* via `openedSnackBarRef`.
*/
this.snackBarRefAtThisLevel = null;
/** The component that should be rendered as the snack bar's simple component. */
this.simpleSnackBarComponent = SimpleSnackBar;
/** The container component that attaches the provided template or component. */
this.snackBarContainerComponent = SnackBarContainer;
/** The CSS class to apply for handset mode. */
this.handsetCssClass = 'x-snack-bar-handset';
}
/**
* Creates and dispatches a snack bar with a custom component for the content, removing any
* currently opened snack bars.
*
* @param component Component to be instantiated.
* @param config Extra configuration for the snack bar.
*/
openFromComponent(component, config) {
return this.attach(component, config);
}
/**
* Creates and dispatches a snack bar with a custom template for the content, removing any
* currently opened snack bars.
*
* @param template Template to be instantiated.
* @param config Extra configuration for the snack bar.
*/
openFromTemplate(template, config) {
return this.attach(template, config);
}
open(message, action, config) {
// TODO
// const _config = {...this._defaultConfig, ...config};
const _config = { ...config };
_config.data = { message, action };
// Since the snack bar has `role="alert"`, we don't
// want to announce the same message twice.
if (_config.announcementMessage === message) {
_config.announcementMessage = undefined;
}
return this.openFromComponent(this.simpleSnackBarComponent, _config);
}
/**
* Dismisses the currently-visible snack bar.
*/
dismiss() {
if (this.openedSnackBarRef) {
this.openedSnackBarRef.dismiss();
}
}
ngOnDestroy() {
// Only dismiss the snack bar at the current level on destroy.
if (this.snackBarRefAtThisLevel) {
this.snackBarRefAtThisLevel.dismiss();
}
}
/**
* Attaches the snack bar container component to the overlay.
*/
attachSnackBarContainer(overlayRef, config) {
const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
const injector = Injector.create({
parent: userInjector || this.injector,
providers: [{ provide: SnackBarConfig, useValue: config }]
});
const containerPortal = new ComponentPortal(this.snackBarContainerComponent, config.viewContainerRef, injector);
const containerRef = overlayRef.attach(containerPortal);
// TODO: check if this was already provided by Injector
// containerRef.instance.snackBarConfig = config;
return containerRef.instance;
}
/**
* Places a new component or a template as the content of the snack bar container.
*/
attach(content, userConfig) {
// TODO
// const config = {...new SnackBarConfig(), ...this.defaultConfig, ...userConfig};
const config = { ...new SnackBarConfig(), ...userConfig };
const overlayRef = this.createOverlay(config);
const container = this.attachSnackBarContainer(overlayRef, config);
const snackBarRef = new SnackBarRef(container, overlayRef);
if (content instanceof TemplateRef) {
const portal = new TemplatePortal(content, null, {
$implicit: config.data,
snackBarRef
});
snackBarRef.instance = container.attachTemplatePortal(portal);
}
else {
const injector = this.createInjector(config, snackBarRef);
const portal = new ComponentPortal(content, undefined, injector);
const contentRef = container.attachComponentPortal(portal);
// We can't pass this via the injector, because the injector is created earlier.
snackBarRef.instance = contentRef.instance;
}
// Subscribe to the breakpoint observer and attach the mat-snack-bar-handset class as
// appropriate. This class is applied to the overlay element because the overlay must expand to
// fill the width with the screen for full width snackbars.
this.breakpointObserver
.observe(Breakpoints.HandsetPortrait)
.pipe(takeUntil(overlayRef.detachments()))
.subscribe(state => {
overlayRef.overlayElement.classList.toggle(this.handsetCssClass, state.matches);
});
if (config.announcementMessage) {
// Wait until the snack bar contents have been announced then deliver this message.
container.onAnnounce.subscribe(() => {
this.live.announce(config.announcementMessage, config.politeness);
});
}
this.animateSnackBar(snackBarRef, config);
this.openedSnackBarRef = snackBarRef;
return this.openedSnackBarRef;
}
/** Animates the old snack bar out and the new one in. */
animateSnackBar(snackBarRef, config) {
// When the snackbar is dismissed, clear the reference to it.
snackBarRef.afterDismissed().subscribe(() => {
// Clear the snackbar ref if it hasn't already been replaced by a newer snackbar.
if (this.openedSnackBarRef == snackBarRef) {
this.openedSnackBarRef = null;
}
if (config.announcementMessage) {
this.live.clear();
}
});
if (this.openedSnackBarRef) {
// If a snack bar is already in view, dismiss it and enter the
// new snack bar after exit animation is complete.
this.openedSnackBarRef.afterDismissed().subscribe(() => {
snackBarRef.containerInstance.enter();
});
this.openedSnackBarRef.dismiss();
}
else {
// If no snack bar is in view, enter the new snack bar.
snackBarRef.containerInstance.enter();
}
// If a dismiss timeout is provided, set up dismiss based on after the snackbar is opened.
if (config.duration && config.duration > 0) {
snackBarRef.afterOpened().subscribe(() => snackBarRef._dismissAfter(config.duration));
}
}
/**
* Creates a new overlay and places it in the correct location.
* @param config The user-specified snack bar config.
*/
createOverlay(config) {
const overlayConfig = new OverlayConfig();
overlayConfig.direction = config.direction;
const positionStrategy = this.overlay.position().global();
// Set horizontal position.
const isRtl = config.direction === 'rtl';
const isLeft = config.horizontalPosition === 'left' ||
(config.horizontalPosition === 'start' && !isRtl) ||
(config.horizontalPosition === 'end' && isRtl);
const isRight = !isLeft && config.horizontalPosition !== 'center';
if (isLeft) {
positionStrategy.left('0');
}
else if (isRight) {
positionStrategy.right('0');
}
else {
positionStrategy.centerHorizontally();
}
// Set horizontal position.
if (config.verticalPosition === 'top') {
positionStrategy.top('0');
}
else {
positionStrategy.bottom('0');
}
overlayConfig.positionStrategy = positionStrategy;
return this.overlay.create(overlayConfig);
}
/**
* Creates an injector to be used inside a snack bar component.
* @param config Config that was used to create the snack bar.
* @param snackBarRef Reference to the snack bar.
*/
createInjector(config, snackBarRef) {
const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
return Injector.create({
parent: userInjector || this.injector,
providers: [
{ provide: SnackBarRef, useValue: snackBarRef },
{ provide: XUI_SNACK_BAR_DATA, useValue: config.data }
]
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: XuiSnackBar, deps: [{ token: i1.Overlay }, { token: i2.LiveAnnouncer }, { token: i0.Injector }, { token: i3.BreakpointObserver }, { token: XuiSnackBar, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: XuiSnackBar, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: XuiSnackBar, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.Overlay }, { type: i2.LiveAnnouncer }, { type: i0.Injector }, { type: i3.BreakpointObserver }, { type: XuiSnackBar, decorators: [{
type: Optional
}, {
type: SkipSelf
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hY2stYmFyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy94dWkvc3JjL3NuYWNrLWJhci9zbmFjay1iYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFVBQVUsRUFDVixRQUFRLEVBRVIsUUFBUSxFQUNSLFFBQVEsRUFDUixXQUFXLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMzQyxPQUFPLEVBQWlCLE9BQU8sRUFBRSxhQUFhLEVBQWMsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RixPQUFPLEVBQUUsY0FBYyxFQUFvQixNQUFNLG9CQUFvQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7QUFHakMsTUFBTSxPQUFPLFdBQVc7SUFpQnRCLGlFQUFpRTtJQUNqRSxJQUFJLGlCQUFpQjtRQUNuQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ25DLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQztJQUN6RSxDQUFDO0lBRUQsSUFBSSxpQkFBaUIsQ0FBQyxL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QU0sRUFBRSxZQUFZLElBQUksSUFBSSxDQUFDLFFBQVE7WUFDckMsU0FBUyxFQUFFO2dCQUNULEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFO2dCQUMvQyxFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRTthQUN2RDtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7OEdBdFBVLFdBQVc7a0hBQVgsV0FBVyxjQURFLE1BQU07OzJGQUNuQixXQUFXO2tCQUR2QixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7MEJBcUM3QixRQUFROzswQkFBSSxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50UmVmLFxuICBFbWJlZGRlZFZpZXdSZWYsXG4gIEluamVjdGFibGUsXG4gIEluamVjdG9yLFxuICBPbkRlc3Ryb3ksXG4gIE9wdGlvbmFsLFxuICBTa2lwU2VsZixcbiAgVGVtcGxhdGVSZWZcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTbmFja0JhckNvbmZpZyB9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgeyBDb21wb25lbnRUeXBlLCBPdmVybGF5LCBPdmVybGF5Q29uZmlnLCBPdmVybGF5UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgU2ltcGxlU25hY2tCYXIsIFRleHRPbmx5U25hY2tCYXIgfSBmcm9tICcuL3NpbXBsZS1zbmFjay1iYXInO1xuaW1wb3J0IHsgU25hY2tCYXJSZWYgfSBmcm9tICcuL3NuYWNrLWJhci1yZWYnO1xuaW1wb3J0IHsgU25hY2tCYXJDb250YWluZXIgfSBmcm9tICcuL3NuYWNrLWJhci1jb250YWluZXInO1xuaW1wb3J0IHsgWFVJX1NOQUNLX0JBUl9EQVRBIH0gZnJvbSAnLi9zbmFjay1iYXIudHlwZXMnO1xuaW1wb3J0IHsgTGl2ZUFubm91bmNlciB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IEJyZWFrcG9pbnRPYnNlcnZlciwgQnJlYWtwb2ludHMgfSBmcm9tICdAYW5ndWxhci9jZGsvbGF5b3V0JztcbmltcG9ydCB7IENvbXBvbmVudFBvcnRhbCwgVGVtcGxhdGVQb3J0YWwgfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFh1aVNuYWNrQmFyIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBzbmFjayBiYXIgaW4gdGhlIHZpZXcgKmF0IHRoaXMgbGV2ZWwqIChpbiB0aGUgQW5ndWxhciBpbmplY3RvciB0cmVlKS5cbiAgICogSWYgdGhlcmUgaXMgYSBwYXJlbnQgc25hY2stYmFyIHNlcnZpY2UsIGFsbCBvcGVyYXRpb25zIHNob3VsZCBkZWxlZ2F0ZSB0byB0aGF0IHBhcmVudFxuICAgKiB2aWEgYG9wZW5lZFNuYWNrQmFyUmVmYC5cbiAgICovXG4gIHByaXZhdGUgc25hY2tCYXJSZWZBdFRoaXNMZXZlbDogU25hY2tCYXJSZWY8YW55PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgY29tcG9uZW50IHRoYXQgc2hvdWxkIGJlIHJlbmRlcmVkIGFzIHRoZSBzbmFjayBiYXIncyBzaW1wbGUgY29tcG9uZW50LiAqL1xuICBzaW1wbGVTbmFja0JhckNvbXBvbmVudCA9IFNpbXBsZVNuYWNrQmFyO1xuXG4gIC8qKiBUaGUgY29udGFpbmVyIGNvbXBvbmVudCB0aGF0IGF0dGFjaGVzIHRoZSBwcm92aWRlZCB0ZW1wbGF0ZSBvciBjb21wb25lbnQuICovXG4gIHNuYWNrQmFyQ29udGFpbmVyQ29tcG9uZW50ID0gU25hY2tCYXJDb250YWluZXI7XG5cbiAgLyoqIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgZm9yIGhhbmRzZXQgbW9kZS4gKi9cbiAgaGFuZHNldENzc0NsYXNzID0gJ3gtc25hY2stYmFyLWhhbmRzZXQnO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIGN1cnJlbnRseSBvcGVuZWQgc25hY2tiYXIgYXQgKmFueSogbGV2ZWwuICovXG4gIGdldCBvcGVuZWRTbmFja0JhclJlZigpOiBTbmFja0JhclJlZjxhbnk+IHwgbnVsbCB7XG4gICAgY29uc3QgcGFyZW50ID0gdGhpcy5wYXJlbnRTbmFja0JhcjtcbiAgICByZXR1cm4gcGFyZW50ID8gcGFyZW50Lm9wZW5lZFNuYWNrQmFyUmVmIDogdGhpcy5zbmFja0JhclJlZkF0VGhpc0xldmVsO1xuICB9XG5cbiAgc2V0IG9wZW5lZFNuYWNrQmFyUmVmKHZhbHVlOiBTbmFja0JhclJlZjxhbnk+IHwgbnVsbCkge1xuICAgIGlmICh0aGlzLnBhcmVudFNuYWNrQmFyKSB7XG4gICAgICB0aGlzLnBhcmVudFNuYWNrQmFyLm9wZW5lZFNuYWNrQmFyUmVmID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc25hY2tCYXJSZWZBdFRoaXNMZXZlbCA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgb3ZlcmxheTogT3ZlcmxheSxcbiAgICBwcml2YXRlIGxpdmU6IExpdmVBbm5vdW5jZXIsXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBicmVha3BvaW50T2JzZXJ2ZXI6IEJyZWFrcG9pbnRPYnNlcnZlcixcbiAgICBAT3B0aW9uYWwoKSBAU2tpcFNlbGYoKSBwcml2YXRlIHBhcmVudFNuYWNrQmFyOiBYdWlTbmFja0JhclxuICAgIC8vIEBJbmplY3QoWFVJX1NOQUNLX0JBUl9ERUZBVUxUX09QVElPTlMpIGRlZmF1bHRDb25maWc6IFh1aVNuYWNrQmFyQ29uZmlnXG4gICkge31cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbmQgZGlzcGF0Y2hlcyBhIHNuYWNrIGJhciB3aXRoIGEgY3VzdG9tIGNvbXBvbmVudCBmb3IgdGhlIGNvbnRlbnQsIHJlbW92aW5nIGFueVxuICAgKiBjdXJyZW50bHkgb3BlbmVkIHNuYWNrIGJhcnMuXG4gICAqXG4gICAqIEBwYXJhbSBjb21wb25lbnQgQ29tcG9uZW50IHRvIGJlIGluc3RhbnRpYXRlZC5cbiAgICogQHBhcmFtIGNvbmZpZyBFeHRyYSBjb25maWd1cmF0aW9uIGZvciB0aGUgc25hY2sgYmFyLlxuICAgKi9cbiAgb3BlbkZyb21Db21wb25lbnQ8VCwgRCA9IGFueT4oY29tcG9uZW50OiBDb21wb25lbnRUeXBlPFQ+LCBjb25maWc/OiBTbmFja0JhckNvbmZpZzxEPik6IFNuYWNrQmFyUmVmPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5hdHRhY2goY29tcG9uZW50LCBjb25maWcpIGFzIFNuYWNrQmFyUmVmPFQ+O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW5kIGRpc3BhdGNoZXMgYSBzbmFjayBiYXIgd2l0aCBhIGN1c3RvbSB0ZW1wbGF0ZSBmb3IgdGhlIGNvbnRlbnQsIHJlbW92aW5nIGFueVxuICAgKiBjdXJyZW50bHkgb3BlbmVkIHNuYWNrIGJhcnMuXG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZSBUZW1wbGF0ZSB0byBiZSBpbnN0YW50aWF0ZWQuXG4gICAqIEBwYXJhbSBjb25maWcgRXh0cmEgY29uZmlndXJhdGlvbiBmb3IgdGhlIHNuYWNrIGJhci5cbiAgICovXG4gIG9wZW5Gcm9tVGVtcGxhdGUodGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sIGNvbmZpZz86IFNuYWNrQmFyQ29uZmlnKTogU25hY2tCYXJSZWY8RW1iZWRkZWRWaWV3UmVmPGFueT4+IHtcbiAgICByZXR1cm4gdGhpcy5hdHRhY2godGVtcGxhdGUsIGNvbmZpZyk7XG4gIH1cblxuICBvcGVuKG1lc3NhZ2U6IHN0cmluZywgYWN0aW9uPzogc3RyaW5nLCBjb25maWc/OiBTbmFja0JhckNvbmZpZyk6IFNuYWNrQmFyUmVmPFRleHRPbmx5U25hY2tCYXI+IHtcbiAgICAvLyBUT0RPXG4gICAgLy8gY29uc3QgX2NvbmZpZyA9IHsuLi50aGlzLl9kZWZhdWx0Q29uZmlnLCAuLi5jb25maWd9O1xuICAgIGNvbnN0IF9jb25maWc6IFNuYWNrQmFyQ29uZmlnID0geyAuLi5jb25maWcgfTtcbiAgICBfY29uZmlnLmRhdGEgPSB7IG1lc3NhZ2UsIGFjdGlvbiB9O1xuXG4gICAgLy8gU2luY2UgdGhlIHNuYWNrIGJhciBoYXMgYHJvbGU9XCJhbGVydFwiYCwgd2UgZG9uJ3RcbiAgICAvLyB3YW50IHRvIGFubm91bmNlIHRoZSBzYW1lIG1lc3NhZ2UgdHdpY2UuXG4gICAgaWYgKF9jb25maWcuYW5ub3VuY2VtZW50TWVzc2FnZSA9PT0gbWVzc2FnZSkge1xuICAgICAgX2NvbmZpZy5hbm5vdW5jZW1lbnRNZXNzYWdlID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm9wZW5Gcm9tQ29tcG9uZW50KHRoaXMuc2ltcGxlU25hY2tCYXJDb21wb25lbnQsIF9jb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc21pc3NlcyB0aGUgY3VycmVudGx5LXZpc2libGUgc25hY2sgYmFyLlxuICAgKi9cbiAgZGlzbWlzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5vcGVuZWRTbmFja0JhclJlZikge1xuICAgICAgdGhpcy5vcGVuZWRTbmFja0JhclJlZi5kaXNtaXNzKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgLy8gT25seSBkaXNtaXNzIHRoZSBzbmFjayBiYXIgYXQgdGhlIGN1cnJlbnQgbGV2ZWwgb24gZGVzdHJveS5cbiAgICBpZiAodGhpcy5zbmFja0JhclJlZkF0VGhpc0xldmVsKSB7XG4gICAgICB0aGlzLnNuYWNrQmFyUmVmQXRUaGlzTGV2ZWwuZGlzbWlzcygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRhY2hlcyB0aGUgc25hY2sgYmFyIGNvbnRhaW5lciBjb21wb25lbnQgdG8gdGhlIG92ZXJsYXkuXG4gICAqL1xuICBwcml2YXRlIGF0dGFjaFNuYWNrQmFyQ29udGFpbmVyKG92ZXJsYXlSZWY6IE92ZXJsYXlSZWYsIGNvbmZpZzogU25hY2tCYXJDb25maWcpOiBTbmFja0JhckNvbnRhaW5lciB7XG4gICAgY29uc3QgdXNlckluamVjdG9yID0gY29uZmlnICYmIGNvbmZpZy52aWV3Q29udGFpbmVyUmVmICYmIGNvbmZpZy52aWV3Q29udGFpbmVyUmVmLmluamVjdG9yO1xuICAgIGNvbnN0IGluamVjdG9yID0gSW5qZWN0b3IuY3JlYXRlKHtcbiAgICAgIHBhcmVudDogdXNlckluamVjdG9yIHx8IHRoaXMuaW5qZWN0b3IsXG4gICAgICBwcm92aWRlcnM6IFt7IHByb3ZpZGU6IFNuYWNrQmFyQ29uZmlnLCB1c2VWYWx1ZTogY29uZmlnIH1dXG4gICAgfSk7XG5cbiAgICBjb25zdCBjb250YWluZXJQb3J0YWwgPSBuZXcgQ29tcG9uZW50UG9ydGFsKHRoaXMuc25hY2tCYXJDb250YWluZXJDb21wb25lbnQsIGNvbmZpZy52aWV3Q29udGFpbmVyUmVmLCBpbmplY3Rvcik7XG4gICAgY29uc3QgY29udGFpbmVyUmVmOiBDb21wb25lbnRSZWY8U25hY2tCYXJDb250YWluZXI+ID0gb3ZlcmxheVJlZi5hdHRhY2goY29udGFpbmVyUG9ydGFsKTtcbiAgICAvLyBUT0RPOiBjaGVjayBpZiB0aGlzIHdhcyBhbHJlYWR5IHByb3ZpZGVkIGJ5IEluamVjdG9yXG4gICAgLy8gY29udGFpbmVyUmVmLmluc3RhbmNlLnNuYWNrQmFyQ29uZmlnID0gY29uZmlnO1xuICAgIHJldHVybiBjb250YWluZXJSZWYuaW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogUGxhY2VzIGEgbmV3IGNvbXBvbmVudCBvciBhIHRlbXBsYXRlIGFzIHRoZSBjb250ZW50IG9mIHRoZSBzbmFjayBiYXIgY29udGFpbmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBhdHRhY2g8VD4oXG4gICAgY29udGVudDogQ29tcG9uZW50VHlwZTxUPiB8IFRlbXBsYXRlUmVmPFQ+LFxuICAgIHVzZXJDb25maWc/OiBTbmFja0JhckNvbmZpZ1xuICApOiBTbmFja0JhclJlZjxUIHwgRW1iZWRkZWRWaWV3UmVmPGFueT4+IHtcbiAgICAvLyBUT0RPXG4gICAgLy8gY29uc3QgY29uZmlnID0gey4uLm5ldyBTbmFja0JhckNvbmZpZygpLCAuLi50aGlzLmRlZmF1bHRDb25maWcsIC4uLnVzZXJDb25maWd9O1xuICAgIGNvbnN0IGNvbmZpZyA9IHsgLi4ubmV3IFNuYWNrQmFyQ29uZmlnKCksIC4uLnVzZXJDb25maWcgfTtcbiAgICBjb25zdCBvdmVybGF5UmVmID0gdGhpcy5jcmVhdGVPdmVybGF5KGNvbmZpZyk7XG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5hdHRhY2hTbmFja0JhckNvbnRhaW5lcihvdmVybGF5UmVmLCBjb25maWcpO1xuICAgIGNvbnN0IHNuYWNrQmFyUmVmID0gbmV3IFNuYWNrQmFyUmVmPFQgfCBFbWJlZGRlZFZpZXdSZWY8YW55Pj4oY29udGFpbmVyLCBvdmVybGF5UmVmKTtcblxuICAgIGlmIChjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYpIHtcbiAgICAgIGNvbnN0IHBvcnRhbCA9IG5ldyBUZW1wbGF0ZVBvcnRhbChjb250ZW50LCBudWxsISwge1xuICAgICAgICAkaW1wbGljaXQ6IGNvbmZpZy5kYXRhLFxuICAgICAgICBzbmFja0JhclJlZlxuICAgICAgfSBhcyBhbnkpO1xuXG4gICAgICBzbmFja0JhclJlZi5pbnN0YW5jZSA9IGNvbnRhaW5lci5hdHRhY2hUZW1wbGF0ZVBvcnRhbChwb3J0YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBpbmplY3RvciA9IHRoaXMuY3JlYXRlSW5qZWN0b3IoY29uZmlnLCBzbmFja0JhclJlZik7XG4gICAgICBjb25zdCBwb3J0YWwgPSBuZXcgQ29tcG9uZW50UG9ydGFsKGNvbnRlbnQsIHVuZGVmaW5lZCEsIGluamVjdG9yKTtcbiAgICAgIGNvbnN0IGNvbnRlbnRSZWYgPSBjb250YWluZXIuYXR0YWNoQ29tcG9uZW50UG9ydGFsPFQ+KHBvcnRhbCk7XG5cbiAgICAgIC8vIFdlIGNhbid0IHBhc3MgdGhpcyB2aWEgdGhlIGluamVjdG9yLCBiZWNhdXNlIHRoZSBpbmplY3RvciBpcyBjcmVhdGVkIGVhcmxpZXIuXG4gICAgICBzbmFja0JhclJlZi5pbnN0YW5jZSA9IGNvbnRlbnRSZWYuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLy8gU3Vic2NyaWJlIHRvIHRoZSBicmVha3BvaW50IG9ic2VydmVyIGFuZCBhdHRhY2ggdGhlIG1hdC1zbmFjay1iYXItaGFuZHNldCBjbGFzcyBhc1xuICAgIC8vIGFwcHJvcHJpYXRlLiBUaGlzIGNsYXNzIGlzIGFwcGxpZWQgdG8gdGhlIG92ZXJsYXkgZWxlbWVudCBiZWNhdXNlIHRoZSBvdmVybGF5IG11c3QgZXhwYW5kIHRvXG4gICAgLy8gZmlsbCB0aGUgd2lkdGggd2l0aCB0aGUgc2NyZWVuIGZvciBmdWxsIHdpZHRoIHNuYWNrYmFycy5cbiAgICB0aGlzLmJyZWFrcG9pbnRPYnNlcnZlclxuICAgICAgLm9ic2VydmUoQnJlYWtwb2ludHMuSGFuZHNldFBvcnRyYWl0KVxuICAgICAgLnBpcGUodGFrZVVudGlsKG92ZXJsYXlSZWYuZGV0YWNobWVudHMoKSkpXG4gICAgICAuc3Vic2NyaWJlKHN0YXRlID0+IHtcbiAgICAgICAgb3ZlcmxheVJlZi5vdmVybGF5RWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKHRoaXMuaGFuZHNldENzc0NsYXNzLCBzdGF0ZS5tYXRjaGVzKTtcbiAgICAgIH0pO1xuXG4gICAgaWYgKGNvbmZpZy5hbm5vdW5jZW1lbnRNZXNzYWdlKSB7XG4gICAgICAvLyBXYWl0IHVudGlsIHRoZSBzbmFjayBiYXIgY29udGVudHMgaGF2ZSBiZWVuIGFubm91bmNlZCB0aGVuIGRlbGl2ZXIgdGhpcyBtZXNzYWdlLlxuICAgICAgY29udGFpbmVyLm9uQW5ub3VuY2Uuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5saXZlLmFubm91bmNlKGNvbmZpZy5hbm5vdW5jZW1lbnRNZXNzYWdlISwgY29uZmlnLnBvbGl0ZW5lc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5hbmltYXRlU25hY2tCYXIoc25hY2tCYXJSZWYsIGNvbmZpZyk7XG4gICAgdGhpcy5vcGVuZWRTbmFja0JhclJlZiA9IHNuYWNrQmFyUmVmO1xuXG4gICAgcmV0dXJuIHRoaXMub3BlbmVkU25hY2tCYXJSZWY7XG4gIH1cblxuICAvKiogQW5pbWF0ZXMgdGhlIG9sZCBzbmFjayBiYXIgb3V0IGFuZCB0aGUgbmV3IG9uZSBpbi4gKi9cbiAgcHJpdmF0ZSBhbmltYXRlU25hY2tCYXIoc25hY2tCYXJSZWY6IFNuYWNrQmFyUmVmPGFueT4sIGNvbmZpZzogU25hY2tCYXJDb25maWcpIHtcbiAgICAvLyBXaGVuIHRoZSBzbmFja2JhciBpcyBkaXNtaXNzZWQsIGNsZWFyIHRoZSByZWZlcmVuY2UgdG8gaXQuXG4gICAgc25hY2tCYXJSZWYuYWZ0ZXJEaXNtaXNzZWQoKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgLy8gQ2xlYXIgdGhlIHNuYWNrYmFyIHJlZiBpZiBpdCBoYXNuJ3QgYWxyZWFkeSBiZWVuIHJlcGxhY2VkIGJ5IGEgbmV3ZXIgc25hY2tiYXIuXG4gICAgICBpZiAodGhpcy5vcGVuZWRTbmFja0JhclJlZiA9PSBzbmFja0JhclJlZikge1xuICAgICAgICB0aGlzLm9wZW5lZFNuYWNrQmFyUmVmID0gbnVsbDtcbiAgICAgIH1cblxuICAgICAgaWYgKGNvbmZpZy5hbm5vdW5jZW1lbnRNZXNzYWdlKSB7XG4gICAgICAgIHRoaXMubGl2ZS5jbGVhcigpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMub3BlbmVkU25hY2tCYXJSZWYpIHtcbiAgICAgIC8vIElmIGEgc25hY2sgYmFyIGlzIGFscmVhZHkgaW4gdmlldywgZGlzbWlzcyBpdCBhbmQgZW50ZXIgdGhlXG4gICAgICAvLyBuZXcgc25hY2sgYmFyIGFmdGVyIGV4aXQgYW5pbWF0aW9uIGlzIGNvbXBsZXRlLlxuICAgICAgdGhpcy5vcGVuZWRTbmFja0JhclJlZi5hZnRlckRpc21pc3NlZCgpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHNuYWNrQmFyUmVmLmNvbnRhaW5lckluc3RhbmNlLmVudGVyKCk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMub3BlbmVkU25hY2tCYXJSZWYuZGlzbWlzcygpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiBubyBzbmFjayBiYXIgaXMgaW4gdmlldywgZW50ZXIgdGhlIG5ldyBzbmFjayBiYXIuXG4gICAgICBzbmFja0JhclJlZi5jb250YWluZXJJbnN0YW5jZS5lbnRlcigpO1xuICAgIH1cblxuICAgIC8vIElmIGEgZGlzbWlzcyB0aW1lb3V0IGlzIHByb3ZpZGVkLCBzZXQgdXAgZGlzbWlzcyBiYXNlZCBvbiBhZnRlciB0aGUgc25hY2tiYXIgaXMgb3BlbmVkLlxuICAgIGlmIChjb25maWcuZHVyYXRpb24gJiYgY29uZmlnLmR1cmF0aW9uID4gMCkge1xuICAgICAgc25hY2tCYXJSZWYuYWZ0ZXJPcGVuZWQoKS5zdWJzY3JpYmUoKCkgPT4gc25hY2tCYXJSZWYuX2Rpc21pc3NBZnRlcihjb25maWcuZHVyYXRpb24hKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgb3ZlcmxheSBhbmQgcGxhY2VzIGl0IGluIHRoZSBjb3JyZWN0IGxvY2F0aW9uLlxuICAgKiBAcGFyYW0gY29uZmlnIFRoZSB1c2VyLXNwZWNpZmllZCBzbmFjayBiYXIgY29uZmlnLlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVPdmVybGF5KGNvbmZpZzogU25hY2tCYXJDb25maWcpOiBPdmVybGF5UmVmIHtcbiAgICBjb25zdCBvdmVybGF5Q29uZmlnID0gbmV3IE92ZXJsYXlDb25maWcoKTtcbiAgICBvdmVybGF5Q29uZmlnLmRpcmVjdGlvbiA9IGNvbmZpZy5kaXJlY3Rpb247XG5cbiAgICBjb25zdCBwb3NpdGlvblN0cmF0ZWd5ID0gdGhpcy5vdmVybGF5LnBvc2l0aW9uKCkuZ2xvYmFsKCk7XG4gICAgLy8gU2V0IGhvcml6b250YWwgcG9zaXRpb24uXG4gICAgY29uc3QgaXNSdGwgPSBjb25maWcuZGlyZWN0aW9uID09PSAncnRsJztcbiAgICBjb25zdCBpc0xlZnQgPVxuICAgICAgY29uZmlnLmhvcml6b250YWxQb3NpdGlvbiA9PT0gJ2xlZnQnIHx8XG4gICAgICAoY29uZmlnLmhvcml6b250YWxQb3NpdGlvbiA9PT0gJ3N0YXJ0JyAmJiAhaXNSdGwpIHx8XG4gICAgICAoY29uZmlnLmhvcml6b250YWxQb3NpdGlvbiA9PT0gJ2VuZCcgJiYgaXNSdGwpO1xuICAgIGNvbnN0IGlzUmlnaHQgPSAhaXNMZWZ0ICYmIGNvbmZpZy5ob3Jpem9udGFsUG9zaXRpb24gIT09ICdjZW50ZXInO1xuXG4gICAgaWYgKGlzTGVmdCkge1xuICAgICAgcG9zaXRpb25TdHJhdGVneS5sZWZ0KCcwJyk7XG4gICAgfSBlbHNlIGlmIChpc1JpZ2h0KSB7XG4gICAgICBwb3NpdGlvblN0cmF0ZWd5LnJpZ2h0KCcwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBvc2l0aW9uU3RyYXRlZ3kuY2VudGVySG9yaXpvbnRhbGx5KCk7XG4gICAgfVxuXG4gICAgLy8gU2V0IGhvcml6b250YWwgcG9zaXRpb24uXG4gICAgaWYgKGNvbmZpZy52ZXJ0aWNhbFBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgcG9zaXRpb25TdHJhdGVneS50b3AoJzAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcG9zaXRpb25TdHJhdGVneS5ib3R0b20oJzAnKTtcbiAgICB9XG5cbiAgICBvdmVybGF5Q29uZmlnLnBvc2l0aW9uU3RyYXRlZ3kgPSBwb3NpdGlvblN0cmF0ZWd5O1xuICAgIHJldHVybiB0aGlzLm92ZXJsYXkuY3JlYXRlKG92ZXJsYXlDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5qZWN0b3IgdG8gYmUgdXNlZCBpbnNpZGUgYSBzbmFjayBiYXIgY29tcG9uZW50LlxuICAgKiBAcGFyYW0gY29uZmlnIENvbmZpZyB0aGF0IHdhcyB1c2VkIHRvIGNyZWF0ZSB0aGUgc25hY2sgYmFyLlxuICAgKiBAcGFyYW0gc25hY2tCYXJSZWYgUmVmZXJlbmNlIHRvIHRoZSBzbmFjayBiYXIuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUluamVjdG9yPFQ+KGNvbmZpZzogU25hY2tCYXJDb25maWcsIHNuYWNrQmFyUmVmOiBTbmFja0JhclJlZjxUPik6IEluamVjdG9yIHtcbiAgICBjb25zdCB1c2VySW5qZWN0b3IgPSBjb25maWcgJiYgY29uZmlnLnZpZXdDb250YWluZXJSZWYgJiYgY29uZmlnLnZpZXdDb250YWluZXJSZWYuaW5qZWN0b3I7XG5cbiAgICByZXR1cm4gSW5qZWN0b3IuY3JlYXRlKHtcbiAgICAgIHBhcmVudDogdXNlckluamVjdG9yIHx8IHRoaXMuaW5qZWN0b3IsXG4gICAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgeyBwcm92aWRlOiBTbmFja0JhclJlZiwgdXNlVmFsdWU6IHNuYWNrQmFyUmVmIH0sXG4gICAgICAgIHsgcHJvdmlkZTogWFVJX1NOQUNLX0JBUl9EQVRBLCB1c2VWYWx1ZTogY29uZmlnLmRhdGEgfVxuICAgICAgXVxuICAgIH0pO1xuICB9XG59XG4iXX0=