carbon-components-angular
Version:
Next generation components
309 lines • 34.9 kB
JavaScript
import { Component, Input, EventEmitter, Output, HostBinding, HostListener, ViewChild } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import * as i0 from "@angular/core";
import * as i1 from "carbon-components-angular/i18n";
import * as i2 from "@angular/common";
import * as i3 from "carbon-components-angular/icon";
/**
* Get started with importing the module:
*
* ```typescript
* import { SearchModule } from 'carbon-components-angular';
* ```
*
* [See demo](../../?path=/story/components-search--basic)
*/
export class Search {
/**
* Creates an instance of `Search`.
* @param i18n The i18n translations.
*/
constructor(elementRef, i18n) {
this.elementRef = elementRef;
this.i18n = i18n;
/**
* @deprecated since v5 - Use `cdsLayer` directive instead
* `light` or `dark` search theme.
*/
this.theme = "dark";
/**
* Size of the search field.
*/
this.size = "md";
/**
* Set to `true` for a disabled search input.
*/
this.disabled = false;
/**
* Set to `true` for a toolbar search component.
*/
this.toolbar = false;
/**
* Set to `true` to make the search component expandable.
* `expandable` would override `toolbar` property behaviours.
*/
this.expandable = false;
/**
* Set to `true` for a loading search component.
*/
this.skeleton = false;
/**
* Set to `true` to expand the toolbar search component.
*/
this.active = false;
/**
* Specifies whether the search component is used in the table toolbar.
*/
this.tableSearch = false;
/**
* The unique id for the search component.
*/
this.id = `search-${Search.searchCount}`;
/**
* Sets the value attribute on the `input` element.
*/
this.value = "";
/**
* Sets the autocomplete attribute on the `input` element.
* For reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#Values
*/
this.autocomplete = "on";
/**
* Sets the text inside the `label` tag.
*/
this.label = this.i18n.get().SEARCH.LABEL;
/**
* Sets the placeholder attribute on the `input` element.
*/
this.placeholder = this.i18n.get().SEARCH.PLACEHOLDER;
/**
* Used to set the `title` attribute of the clear button.
*/
this.clearButtonTitle = this.i18n.get().SEARCH.CLEAR_BUTTON;
/**
* Title for the search trigger
*/
this.searchTitle = "";
/**
* Emits an event when value is changed.
*/
this.valueChange = new EventEmitter();
this.open = new EventEmitter();
/**
* Emits an event when the clear button is clicked.
*/
this.clear = new EventEmitter();
/**
* Emits an event on enter.
*/
this.search = new EventEmitter();
/**
* Sets `true` when composing text via IME.
*/
this.isComposing = false;
/**
* Called when search input is blurred. Needed to properly implement `ControlValueAccessor`.
*/
this.onTouched = () => { };
/**
* Method set in `registerOnChange` to propagate changes back to the form.
*/
this.propagateChange = (_) => { };
Search.searchCount++;
}
get containerClass() {
return !(this.toolbar || this.expandable);
}
/**
* This is the initial value set to the component
* @param value The input value.
*/
writeValue(value) {
this.value = value;
}
/**
* Sets a method in order to propagate changes back to the form.
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
/**
* Registers a callback to be triggered when the control has been touched.
* @param fn Callback to be triggered when the search input is touched.
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Called when text is written in the input.
* @param search The input text.
*/
onSearch(search) {
if (this.isComposing) { // check for IME use
return;
}
this.value = search;
this.doValueChange();
}
/**
* Called on enter.
*/
onEnter() {
this.search.emit(this.value);
}
/**
* Called when clear button is clicked.
*/
clearSearch() {
this.value = "";
this.clear.emit();
this.propagateChange(this.value);
}
doValueChange() {
this.valueChange.emit(this.value);
this.propagateChange(this.value);
}
openSearch() {
this.active = true;
this.open.emit(this.active);
setTimeout(() => this.inputRef.nativeElement.focus());
}
keyDown(event) {
if (this.toolbar || this.expandable) {
if (event.key === "Escape") {
if (this.value === "") {
this.active = false;
this.open.emit(this.active);
}
}
else if (event.key === "Enter") {
this.openSearch();
}
}
if (event.key === "Escape") {
if (this.value !== "") {
this.clearSearch();
}
}
}
focusOut(event) {
this.onTouched();
if ((this.expandable || this.toolbar) &&
this.inputRef &&
this.inputRef.nativeElement.value === "" &&
!this.elementRef.nativeElement.contains(event.relatedTarget)) {
this.active = false;
this.open.emit(this.active);
}
}
focusIn(event) {
this.onTouched();
// set input focus if search icon get focus from tab key press event.
if ((this.expandable || this.toolbar) &&
this.inputRef && !event.relatedTarget &&
!this.elementRef.nativeElement.contains(event.relatedTarget)) {
this.openSearch();
}
}
/**
* Called when using IME composition.
*/
compositionStart(event) {
this.isComposing = true;
}
/**
* Called when IME composition finishes.
*/
compositionEnd(event) {
this.isComposing = false;
this.onSearch(this.value + event.data);
}
}
/**
* Variable used for creating unique ids for search components.
*/
Search.searchCount = 0;
Search.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Search, deps: [{ token: i0.ElementRef }, { token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component });
Search.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Search, selector: "cds-search, ibm-search", inputs: { theme: "theme", size: "size", disabled: "disabled", toolbar: "toolbar", expandable: "expandable", skeleton: "skeleton", active: "active", tableSearch: "tableSearch", name: "name", id: "id", required: "required", value: "value", autocomplete: "autocomplete", label: "label", placeholder: "placeholder", clearButtonTitle: "clearButtonTitle", searchTitle: "searchTitle", ariaLabel: "ariaLabel" }, outputs: { valueChange: "valueChange", open: "open", clear: "clear", search: "search" }, host: { listeners: { "keydown": "keyDown($event)", "focusout": "focusOut($event)", "focusin": "focusIn($event)", "compositionstart": "compositionStart($event)", "compositionend": "compositionEnd($event)" }, properties: { "class.cds--form-item": "this.containerClass" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: Search,
multi: true
}
], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: "<div\n\tclass=\"cds--search\"\n\t[ngClass]=\"{\n\t\t'cds--search--sm': size === 'sm',\n\t\t'cds--search--md': size === 'md',\n\t\t'cds--search--lg': size === 'lg',\n\t\t'cds--search--light': theme === 'light',\n\t\t'cds--skeleton': skeleton,\n\t\t'cds--search--expandable': expandable && !tableSearch,\n\t\t'cds--search--expanded': expandable && !tableSearch && active,\n\t\t'cds--toolbar-search': toolbar && !expandable,\n\t\t'cds--toolbar-search--active': toolbar && !expandable && active,\n\t\t'cds--toolbar-search-container-persistent': tableSearch && !expandable,\n\t\t'cds--toolbar-search-container-expandable': tableSearch && expandable,\n\t\t'cds--toolbar-search-container-active': tableSearch && expandable && active\n\t}\"\n\trole=\"search\"\n\t[attr.aria-label]=\"ariaLabel\"\n\t(click)=\"openSearch()\">\n\t<label class=\"cds--label\" [for]=\"id\">{{label}}</label>\n\n\t<div *ngIf=\"skeleton; else enableInput\" class=\"cds--search-input\"></div>\n\t<ng-template #enableInput>\n\t\t<input\n\t\t\t#input\n\t\t\tclass=\"cds--search-input\"\n\t\t\t[type]=\"tableSearch || !toolbar ? 'text' : 'search'\"\n\t\t\t[id]=\"id\"\n\t\t\t[value]=\"value\"\n\t\t\t[autocomplete]=\"autocomplete\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[required]=\"required\"\n\t\t\t(input)=\"onSearch($event.target.value)\"\n\t\t\t(keyup.enter)=\"onEnter()\"/>\n\t\t<button\n\t\t\t*ngIf=\"!tableSearch && toolbar\"\n\t\t\tclass=\"cds--toolbar-search__btn\"\n\t\t\t(click)=\"openSearch()\"\n\t\t\taria-label=\"Open search\">\n\t\t\t<svg cdsIcon=\"search\" size=\"16\" class=\"cds--search-magnifier-icon\"></svg>\n\t\t</button>\n\t\t<svg\n\t\t\tcdsIcon=\"search\"\n\t\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\t\tclass=\"cds--search-magnifier-icon\"\n\t\t\tsize=\"16\">\n\t\t</svg>\n\t</ng-template>\n\n\t<button\n\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\tclass=\"cds--search-close\"\n\t\t[ngClass]=\"{\n\t\t\t'cds--search-close--hidden': !value || value.length === 0\n\t\t}\"\n\t\t[title]=\"clearButtonTitle\"\n\t\t(click)=\"clearSearch()\">\n\t\t<span class=\"cds--visually-hidden\">{{ clearButtonTitle }}</span>\n\t\t<svg cdsIcon=\"close\" size=\"16\"></svg>\n\t</button>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Search, decorators: [{
type: Component,
args: [{ selector: "cds-search, ibm-search", providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: Search,
multi: true
}
], template: "<div\n\tclass=\"cds--search\"\n\t[ngClass]=\"{\n\t\t'cds--search--sm': size === 'sm',\n\t\t'cds--search--md': size === 'md',\n\t\t'cds--search--lg': size === 'lg',\n\t\t'cds--search--light': theme === 'light',\n\t\t'cds--skeleton': skeleton,\n\t\t'cds--search--expandable': expandable && !tableSearch,\n\t\t'cds--search--expanded': expandable && !tableSearch && active,\n\t\t'cds--toolbar-search': toolbar && !expandable,\n\t\t'cds--toolbar-search--active': toolbar && !expandable && active,\n\t\t'cds--toolbar-search-container-persistent': tableSearch && !expandable,\n\t\t'cds--toolbar-search-container-expandable': tableSearch && expandable,\n\t\t'cds--toolbar-search-container-active': tableSearch && expandable && active\n\t}\"\n\trole=\"search\"\n\t[attr.aria-label]=\"ariaLabel\"\n\t(click)=\"openSearch()\">\n\t<label class=\"cds--label\" [for]=\"id\">{{label}}</label>\n\n\t<div *ngIf=\"skeleton; else enableInput\" class=\"cds--search-input\"></div>\n\t<ng-template #enableInput>\n\t\t<input\n\t\t\t#input\n\t\t\tclass=\"cds--search-input\"\n\t\t\t[type]=\"tableSearch || !toolbar ? 'text' : 'search'\"\n\t\t\t[id]=\"id\"\n\t\t\t[value]=\"value\"\n\t\t\t[autocomplete]=\"autocomplete\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[required]=\"required\"\n\t\t\t(input)=\"onSearch($event.target.value)\"\n\t\t\t(keyup.enter)=\"onEnter()\"/>\n\t\t<button\n\t\t\t*ngIf=\"!tableSearch && toolbar\"\n\t\t\tclass=\"cds--toolbar-search__btn\"\n\t\t\t(click)=\"openSearch()\"\n\t\t\taria-label=\"Open search\">\n\t\t\t<svg cdsIcon=\"search\" size=\"16\" class=\"cds--search-magnifier-icon\"></svg>\n\t\t</button>\n\t\t<svg\n\t\t\tcdsIcon=\"search\"\n\t\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\t\tclass=\"cds--search-magnifier-icon\"\n\t\t\tsize=\"16\">\n\t\t</svg>\n\t</ng-template>\n\n\t<button\n\t\t*ngIf=\"tableSearch || !toolbar\"\n\t\tclass=\"cds--search-close\"\n\t\t[ngClass]=\"{\n\t\t\t'cds--search-close--hidden': !value || value.length === 0\n\t\t}\"\n\t\t[title]=\"clearButtonTitle\"\n\t\t(click)=\"clearSearch()\">\n\t\t<span class=\"cds--visually-hidden\">{{ clearButtonTitle }}</span>\n\t\t<svg cdsIcon=\"close\" size=\"16\"></svg>\n\t</button>\n</div>\n" }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.I18n }]; }, propDecorators: { containerClass: [{
type: HostBinding,
args: ["class.cds--form-item"]
}], theme: [{
type: Input
}], size: [{
type: Input
}], disabled: [{
type: Input
}], toolbar: [{
type: Input
}], expandable: [{
type: Input
}], skeleton: [{
type: Input
}], active: [{
type: Input
}], tableSearch: [{
type: Input
}], name: [{
type: Input
}], id: [{
type: Input
}], required: [{
type: Input
}], value: [{
type: Input
}], autocomplete: [{
type: Input
}], label: [{
type: Input
}], placeholder: [{
type: Input
}], clearButtonTitle: [{
type: Input
}], searchTitle: [{
type: Input
}], ariaLabel: [{
type: Input
}], valueChange: [{
type: Output
}], open: [{
type: Output
}], clear: [{
type: Output
}], search: [{
type: Output
}], inputRef: [{
type: ViewChild,
args: ["input"]
}], keyDown: [{
type: HostListener,
args: ["keydown", ["$event"]]
}], focusOut: [{
type: HostListener,
args: ["focusout", ["$event"]]
}], focusIn: [{
type: HostListener,
args: ["focusin", ["$event"]]
}], compositionStart: [{
type: HostListener,
args: ["compositionstart", ["$event"]]
}], compositionEnd: [{
type: HostListener,
args: ["compositionend", ["$event"]]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZWFyY2gvc2VhcmNoLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uL3NyYy9zZWFyY2gvc2VhcmNoLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTixTQUFTLEVBQ1QsS0FBSyxFQUNMLFlBQVksRUFDWixNQUFNLEVBQ04sV0FBVyxFQUVYLFlBQVksRUFDWixTQUFTLEVBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDOzs7OztBQUd6RTs7Ozs7Ozs7R0FRRztBQVlILE1BQU0sT0FBTyxNQUFNO0lBNEdsQjs7O09BR0c7SUFDSCxZQUFzQixVQUFzQixFQUFZLElBQVU7UUFBNUMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUFZLFNBQUksR0FBSixJQUFJLENBQU07UUF0R2xFOzs7V0FHRztRQUNNLFVBQUssR0FBcUIsTUFBTSxDQUFDO1FBRTFDOztXQUVHO1FBQ00sU0FBSSxHQUF1QixJQUFJLENBQUM7UUFFekM7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sWUFBTyxHQUFHLEtBQUssQ0FBQztRQUN6Qjs7O1dBR0c7UUFDTSxlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzVCOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQUMxQjs7V0FFRztRQUNNLFdBQU0sR0FBRyxLQUFLLENBQUM7UUFDeEI7O1dBRUc7UUFDTSxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUs3Qjs7V0FFRztRQUNNLE9BQUUsR0FBRyxVQUFVLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUs3Qzs7V0FFRztRQUNNLFVBQUssR0FBRyxFQUFFLENBQUM7UUFDcEI7OztXQUdHO1FBQ00saUJBQVksR0FBRyxJQUFJLENBQUM7UUFDN0I7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c0JBQW5CLEtBQUs7Z0JBSUcsSUFBSTtzQkFBWixLQUFLO2dCQUlHLEVBQUU7c0JBQVYsS0FBSztnQkFJRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLEtBQUs7c0JBQWIsS0FBSztnQkFLRyxZQUFZO3NCQUFwQixLQUFLO2dCQUlHLEtBQUs7c0JBQWIsS0FBSztnQkFJRyxXQUFXO3NCQUFuQixLQUFLO2dCQUlHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFJRyxXQUFXO3NCQUFuQixLQUFLO2dCQUlHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBSUksV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxJQUFJO3NCQUFiLE1BQU07Z0JBSUcsS0FBSztzQkFBZCxNQUFNO2dCQUlHLE1BQU07c0JBQWYsTUFBTTtnQkFFYSxRQUFRO3NCQUEzQixTQUFTO3VCQUFDLE9BQU87Z0JBd0ZsQixPQUFPO3NCQUROLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQXFCbkMsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLFVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFhcEMsT0FBTztzQkFETixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFlbkMsZ0JBQWdCO3NCQURmLFlBQVk7dUJBQUMsa0JBQWtCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBUzVDLGNBQWM7c0JBRGIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0SW5wdXQsXG5cdEV2ZW50RW1pdHRlcixcblx0T3V0cHV0LFxuXHRIb3N0QmluZGluZyxcblx0RWxlbWVudFJlZixcblx0SG9zdExpc3RlbmVyLFxuXHRWaWV3Q2hpbGRcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBDb250cm9sVmFsdWVBY2Nlc3NvciB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgSTE4biB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL2kxOG5cIjtcblxuLyoqXG4gKiBHZXQgc3RhcnRlZCB3aXRoIGltcG9ydGluZyB0aGUgbW9kdWxlOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFNlYXJjaE1vZHVsZSB9IGZyb20gJ2NhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXInO1xuICogYGBgXG4gKlxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy1zZWFyY2gtLWJhc2ljKVxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLXNlYXJjaCwgaWJtLXNlYXJjaFwiLFxuXHR0ZW1wbGF0ZVVybDogXCJzZWFyY2guY29tcG9uZW50Lmh0bWxcIixcblx0cHJvdmlkZXJzOiBbXG5cdFx0e1xuXHRcdFx0cHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG5cdFx0XHR1c2VFeGlzdGluZzogU2VhcmNoLFxuXHRcdFx0bXVsdGk6IHRydWVcblx0XHR9XG5cdF1cbn0pXG5leHBvcnQgY2xhc3MgU2VhcmNoIGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuXHQvKipcblx0ICogVmFyaWFibGUgdXNlZCBmb3IgY3JlYXRpbmcgdW5pcXVlIGlkcyBmb3Igc2VhcmNoIGNvbXBvbmVudHMuXG5cdCAqL1xuXHRzdGF0aWMgc2VhcmNoQ291bnQgPSAwO1xuXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tZm9ybS1pdGVtXCIpIGdldCBjb250YWluZXJDbGFzcygpIHtcblx0XHRyZXR1cm4gISh0aGlzLnRvb2xiYXIgfHwgdGhpcy5leHBhbmRhYmxlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAZGVwcmVjYXRlZCBzaW5jZSB2NSAtIFVzZSBgY2RzTGF5ZXJgIGRpcmVjdGl2ZSBpbnN0ZWFkXG5cdCAqIGBsaWdodGAgb3IgYGRhcmtgIHNlYXJjaCB0aGVtZS5cblx0ICovXG5cdEBJbnB1dCgpIHRoZW1lOiBcImxpZ2h0XCIgfCBcImRhcmtcIiA9IFwiZGFya1wiO1xuXG5cdC8qKlxuXHQgKiBTaXplIG9mIHRoZSBzZWFyY2ggZmllbGQuXG5cdCAqL1xuXHRASW5wdXQoKSBzaXplOiBcInNtXCIgfCBcIm1kXCIgfCBcImxnXCIgPSBcIm1kXCI7XG5cblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgZm9yIGEgZGlzYWJsZWQgc2VhcmNoIGlucHV0LlxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgZm9yIGEgdG9vbGJhciBzZWFyY2ggY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgdG9vbGJhciA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byBtYWtlIHRoZSBzZWFyY2ggY29tcG9uZW50IGV4cGFuZGFibGUuXG5cdCAqIGBleHBhbmRhYmxlYCB3b3VsZCBvdmVycmlkZSBgdG9vbGJhcmAgcHJvcGVydHkgYmVoYXZpb3Vycy5cblx0ICovXG5cdEBJbnB1dCgpIGV4cGFuZGFibGUgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgZm9yIGEgbG9hZGluZyBzZWFyY2ggY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgc2tlbGV0b24gPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgdG8gZXhwYW5kIHRoZSB0b29sYmFyIHNlYXJjaCBjb21wb25lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBhY3RpdmUgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNwZWNpZmllcyB3aGV0aGVyIHRoZSBzZWFyY2ggY29tcG9uZW50IGlzIHVzZWQgaW4gdGhlIHRhYmxlIHRvb2xiYXIuXG5cdCAqL1xuXHRASW5wdXQoKSB0YWJsZVNlYXJjaCA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0cyB0aGUgbmFtZSBhdHRyaWJ1dGUgb24gdGhlIGBpbnB1dGAgZWxlbWVudC5cblx0ICovXG5cdEBJbnB1dCgpIG5hbWU6IHN0cmluZztcblx0LyoqXG5cdCAqIFRoZSB1bmlxdWUgaWQgZm9yIHRoZSBzZWFyY2ggY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgaWQgPSBgc2VhcmNoLSR7U2VhcmNoLnNlYXJjaENvdW50fWA7XG5cdC8qKlxuXHQgKiBSZWZsZWN0cyB0aGUgcmVxdWlyZWQgYXR0cmlidXRlIG9mIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbjtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgdmFsdWUgPSBcIlwiO1xuXHQvKipcblx0ICogU2V0cyB0aGUgYXV0b2NvbXBsZXRlIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKiBGb3IgcmVmZXJlbmNlOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0F0dHJpYnV0ZXMvYXV0b2NvbXBsZXRlI1ZhbHVlc1xuXHQgKi9cblx0QElucHV0KCkgYXV0b2NvbXBsZXRlID0gXCJvblwiO1xuXHQvKipcblx0ICogU2V0cyB0aGUgdGV4dCBpbnNpZGUgdGhlIGBsYWJlbGAgdGFnLlxuXHQgKi9cblx0QElucHV0KCkgbGFiZWwgPSB0aGlzLmkxOG4uZ2V0KCkuU0VBUkNILkxBQkVMO1xuXHQvKipcblx0ICogU2V0cyB0aGUgcGxhY2Vob2xkZXIgYXR0cmlidXRlIG9uIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBwbGFjZWhvbGRlciA9IHRoaXMuaTE4bi5nZXQoKS5TRUFSQ0guUExBQ0VIT0xERVI7XG5cdC8qKlxuXHQgKiBVc2VkIHRvIHNldCB0aGUgYHRpdGxlYCBhdHRyaWJ1dGUgb2YgdGhlIGNsZWFyIGJ1dHRvbi5cblx0ICovXG5cdEBJbnB1dCgpIGNsZWFyQnV0dG9uVGl0bGUgPSB0aGlzLmkxOG4uZ2V0KCkuU0VBUkNILkNMRUFSX0JVVFRPTjtcblx0LyoqXG5cdCAqIFRpdGxlIGZvciB0aGUgc2VhcmNoIHRyaWdnZXJcblx0ICovXG5cdEBJbnB1dCgpIHNlYXJjaFRpdGxlID0gXCJcIjtcblx0LyoqXG5cdCAqIFNldHMgdGhlIGFyaWEgbGFiZWwgb24gdGhlIGBkaXZgIGVsZW1lbnQgd2l0aCB0aGUgYHNlYXJjaGAgcm9sZS5cblx0ICovXG5cdEBJbnB1dCgpIGFyaWFMYWJlbDogc3RyaW5nO1xuXHQvKipcblx0ICogRW1pdHMgYW4gZXZlbnQgd2hlbiB2YWx1ZSBpcyBjaGFuZ2VkLlxuXHQgKi9cblx0QE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cdEBPdXRwdXQoKSBvcGVuID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXHQvKipcblx0ICogRW1pdHMgYW4gZXZlbnQgd2hlbiB0aGUgY2xlYXIgYnV0dG9uIGlzIGNsaWNrZWQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgY2xlYXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cdC8qKlxuXHQgKiBFbWl0cyBhbiBldmVudCBvbiBlbnRlci5cblx0ICovXG5cdEBPdXRwdXQoKSBzZWFyY2ggPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuXHRAVmlld0NoaWxkKFwiaW5wdXRcIikgaW5wdXRSZWY6IEVsZW1lbnRSZWY7XG5cblx0LyoqXG5cdCAqIFNldHMgYHRydWVgIHdoZW4gY29tcG9zaW5nIHRleHQgdmlhIElNRS5cblx0ICovXG5cdHByb3RlY3RlZCBpc0NvbXBvc2luZyA9IGZhbHNlO1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIGBTZWFyY2hgLlxuXHQgKiBAcGFyYW0gaTE4biBUaGUgaTE4biB0cmFuc2xhdGlvbnMuXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgZWxlbWVudFJlZjogRWxlbWVudFJlZiwgcHJvdGVjdGVkIGkxOG46IEkxOG4pIHtcblx0XHRTZWFyY2guc2VhcmNoQ291bnQrKztcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGlzIGlzIHRoZSBpbml0aWFsIHZhbHVlIHNldCB0byB0aGUgY29tcG9uZW50XG5cdCAqIEBwYXJhbSB2YWx1ZSBUaGUgaW5wdXQgdmFsdWUuXG5cdCAqL1xuXHRwdWJsaWMgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KSB7XG5cdFx0dGhpcy52YWx1ZSA9IHZhbHVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgYSBtZXRob2QgaW4gb3JkZXIgdG8gcHJvcGFnYXRlIGNoYW5nZXMgYmFjayB0byB0aGUgZm9ybS5cblx0ICovXG5cdHB1YmxpYyByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpIHtcblx0XHR0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIHRvIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSBjb250cm9sIGhhcyBiZWVuIHRvdWNoZWQuXG5cdCAqIEBwYXJhbSBmbiBDYWxsYmFjayB0byBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgc2VhcmNoIGlucHV0IGlzIHRvdWNoZWQuXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSkge1xuXHRcdHRoaXMub25Ub3VjaGVkID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gc2VhcmNoIGlucHV0IGlzIGJsdXJyZWQuIE5lZWRlZCB0byBwcm9wZXJseSBpbXBsZW1lbnQgYENvbnRyb2xWYWx1ZUFjY2Vzc29yYC5cblx0ICovXG5cdG9uVG91Y2hlZDogKCkgPT4gYW55ID0gKCkgPT4ge307XG5cblx0LyoqXG5cdCAqIE1ldGhvZCBzZXQgaW4gYHJlZ2lzdGVyT25DaGFuZ2VgIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7fTtcblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gdGV4dCBpcyB3cml0dGVuIGluIHRoZSBpbnB1dC5cblx0ICogQHBhcmFtIHNlYXJjaCBUaGUgaW5wdXQgdGV4dC5cblx0ICovXG5cdG9uU2VhcmNoKHNlYXJjaDogc3RyaW5nKSB7XG5cdFx0aWYgKHRoaXMuaXNDb21wb3NpbmcpIHsgLy8gY2hlY2sgZm9yIElNRSB1c2Vcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy52YWx1ZSA9IHNlYXJjaDtcblx0XHR0aGlzLmRvVmFsdWVDaGFuZ2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxsZWQgb24gZW50ZXIuXG5cdCAqL1xuXHRvbkVudGVyKCkge1xuXHRcdHRoaXMuc2VhcmNoLmVtaXQodGhpcy52YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsbGVkIHdoZW4gY2xlYXIgYnV0dG9uIGlzIGNsaWNrZWQuXG5cdCAqL1xuXHRjbGVhclNlYXJjaCgpOiB2b2lkIHtcblx0XHR0aGlzLnZhbHVlID0gXCJcIjtcblx0XHR0aGlzLmNsZWFyLmVtaXQoKTtcblx0XHR0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLnZhbHVlKTtcblx0fVxuXG5cdGRvVmFsdWVDaGFuZ2UoKSB7XG5cdFx0dGhpcy52YWx1ZUNoYW5nZS5lbWl0KHRoaXMudmFsdWUpO1xuXHRcdHRoaXMucHJvcGFnYXRlQ2hhbmdlKHRoaXMudmFsdWUpO1xuXHR9XG5cblx0b3BlblNlYXJjaCgpIHtcblx0XHR0aGlzLmFjdGl2ZSA9IHRydWU7XG5cdFx0dGhpcy5vcGVuLmVtaXQodGhpcy5hY3RpdmUpO1xuXHRcdHNldFRpbWVvdXQoKCkgPT4gdGhpcy5pbnB1dFJlZi5uYXRpdmVFbGVtZW50LmZvY3VzKCkpO1xuXHR9XG5cblx0QEhvc3RMaXN0ZW5lcihcImtleWRvd25cIiwgW1wiJGV2ZW50XCJdKVxuXHRrZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG5cdFx0aWYgKHRoaXMudG9vbGJhciB8fCB0aGlzLmV4cGFuZGFibGUpIHtcblx0XHRcdGlmIChldmVudC5rZXkgPT09IFwiRXNjYXBlXCIpIHtcblx0XHRcdFx0aWYgKHRoaXMudmFsdWUgPT09IFwiXCIpIHtcblx0XHRcdFx0XHR0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuXHRcdFx0XHRcdHRoaXMub3Blbi5lbWl0KHRoaXMuYWN0aXZlKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChldmVudC5rZXkgPT09IFwiRW50ZXJcIikge1xuXHRcdFx0XHR0aGlzLm9wZW5TZWFyY2goKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkVzY2FwZVwiKSB7XG5cdFx0XHRpZiAodGhpcy52YWx1ZSAhPT0gXCJcIikge1xuXHRcdFx0XHR0aGlzLmNsZWFyU2VhcmNoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0QEhvc3RMaXN0ZW5lcihcImZvY3Vzb3V0XCIsIFtcIiRldmVudFwiXSlcblx0Zm9jdXNPdXQoZXZlbnQpIHtcblx0XHR0aGlzLm9uVG91Y2hlZCgpO1xuXHRcdGlmICgodGhpcy5leHBhbmRhYmxlIHx8IHRoaXMudG9vbGJhcikgJiZcblx0XHRcdHRoaXMuaW5wdXRSZWYgJiZcblx0XHRcdHRoaXMuaW5wdXRSZWYubmF0aXZlRWxlbWVudC52YWx1ZSA9PT0gXCJcIiAmJlxuXHRcdFx0ISh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudCkuY29udGFpbnMoZXZlbnQucmVsYXRlZFRhcmdldCkpIHtcblx0XHRcdHRoaXMuYWN0aXZlID0gZmFsc2U7XG5cdFx0XHR0aGlzLm9wZW4uZW1pdCh0aGlzLmFjdGl2ZSk7XG5cdFx0fVxuXHR9XG5cblx0QEhvc3RMaXN0ZW5lcihcImZvY3VzaW5cIiwgW1wiJGV2ZW50XCJdKVxuXHRmb2N1c0luKGV2ZW50KSB7XG5cdFx0dGhpcy5vblRvdWNoZWQoKTtcblx0XHQvLyBzZXQgaW5wdXQgZm9jdXMgaWYgc2VhcmNoIGljb24gZ2V0IGZvY3VzIGZyb20gdGFiIGtleSBwcmVzcyBldmVudC5cblx0XHRpZiAoKHRoaXMuZXhwYW5kYWJsZSB8fCB0aGlzLnRvb2xiYXIpICYmXG5cdFx0XHR0aGlzLmlucHV0UmVmICYmICFldmVudC5yZWxhdGVkVGFyZ2V0ICYmXG5cdFx0XHQhKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50KS5jb250YWlucyhldmVudC5yZWxhdGVkVGFyZ2V0KSApIHtcblx0XHRcdHRoaXMub3BlblNlYXJjaCgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxsZWQgd2hlbiB1c2luZyBJTUUgY29tcG9zaXRpb24uXG5cdCAqL1xuXHRASG9zdExpc3RlbmVyKFwiY29tcG9zaXRpb25zdGFydFwiLCBbXCIkZXZlbnRcIl0pXG5cdGNvbXBvc2l0aW9uU3RhcnQoZXZlbnQpIHtcblx0XHR0aGlzLmlzQ29tcG9zaW5nID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxsZWQgd2hlbiBJTUUgY29tcG9zaXRpb24gZmluaXNoZXMuXG5cdCAqL1xuXHRASG9zdExpc3RlbmVyKFwiY29tcG9zaXRpb25lbmRcIiwgW1wiJGV2ZW50XCJdKVxuXHRjb21wb3NpdGlvbkVuZChldmVudCkge1xuXHRcdHRoaXMuaXNDb21wb3NpbmcgPSBmYWxzZTtcblx0XHR0aGlzLm9uU2VhcmNoKHRoaXMudmFsdWUgKyBldmVudC5kYXRhKTtcblx0fVxufVxuIiwiPGRpdlxuXHRjbGFzcz1cImNkcy0tc2VhcmNoXCJcblx0W25nQ2xhc3NdPVwie1xuXHRcdCdjZHMtLXNlYXJjaC0tc20nOiBzaXplID09PSAnc20nLFxuXHRcdCdjZHMtLXNlYXJjaC0tbWQnOiBzaXplID09PSAnbWQnLFxuXHRcdCdjZHMtLXNlYXJjaC0tbGcnOiBzaXplID09PSAnbGcnLFxuXHRcdCdjZHMtLXNlYXJjaC0tbGlnaHQnOiB0aGVtZSA9PT0gJ2xpZ2h0Jyxcblx0XHQnY2RzLS1za2VsZXRvbic6IHNrZWxldG9uLFxuXHRcdCdjZHMtLXNlYXJjaC0tZXhwYW5kYWJsZSc6IGV4cGFuZGFibGUgJiYgIXRhYmxlU2VhcmNoLFxuXHRcdCdjZHMtLXNlYXJjaC0tZXhwYW5kZWQnOiBleHBhbmRhYmxlICYmICF0YWJsZVNlYXJjaCAmJiBhY3RpdmUsXG5cdFx0J2Nkcy0tdG9vbGJhci1zZWFyY2gnOiB0b29sYmFyICYmICFleHBhbmRhYmxlLFxuXHRcdCdjZHMtLXRvb2xiYXItc2VhcmNoLS1hY3RpdmUnOiB0b29sYmFyICYmICFleHBhbmRhYmxlICYmIGFjdGl2ZSxcblx0XHQnY2RzLS10b29sYmFyLXNlYXJjaC1jb250YWluZXItcGVyc2lzdGVudCc6IHRhYmxlU2VhcmNoICYmICFleHBhbmRhYmxlLFxuXHRcdCdjZHMtLXRvb2xiYXItc2VhcmNoLWNvbnRhaW5lci1leHBhbmRhYmxlJzogdGFibGVTZWFyY2ggJiYgZXhwYW5kYWJsZSxcblx0XHQnY2RzLS10b29sYmFyLXNlYXJjaC1jb250YWluZXItYWN0aXZlJzogdGFibGVTZWFyY2ggJiYgZXhwYW5kYWJsZSAmJiBhY3RpdmVcblx0fVwiXG5cdHJvbGU9XCJzZWFyY2hcIlxuXHRbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG5cdChjbGljayk9XCJvcGVuU2VhcmNoKClcIj5cblx0PGxhYmVsIGNsYXNzPVwiY2RzLS1sYWJlbFwiIFtmb3JdPVwiaWRcIj57e2xhYmVsfX08L2xhYmVsPlxuXG5cdDxkaXYgKm5nSWY9XCJza2VsZXRvbjsgZWxzZSBlbmFibGVJbnB1dFwiIGNsYXNzPVwiY2RzLS1zZWFyY2gtaW5wdXRcIj48L2Rpdj5cblx0PG5nLXRlbXBsYXRlICNlbmFibGVJbnB1dD5cblx0XHQ8aW5wdXRcblx0XHRcdCNpbnB1dFxuXHRcdFx0Y2xhc3M9XCJjZHMtLXNlYXJjaC1pbnB1dFwiXG5cdFx0XHRbdHlwZV09XCJ0YWJsZVNlYXJjaCB8fCAhdG9vbGJhciA/ICd0ZXh0JyA6ICdzZWFyY2gnXCJcblx0XHRcdFtpZF09XCJpZFwiXG5cdFx0XHRbdmFsdWVdPVwidmFsdWVcIlxuXHRcdFx0W2F1dG9jb21wbGV0ZV09XCJhdXRvY29tcGxldGVcIlxuXHRcdFx0W3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcblx0XHRcdFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG5cdFx0XHRbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuXHRcdFx0KGlucHV0KT1cIm9uU2VhcmNoKCRldmVudC50YXJnZXQudmFsdWUpXCJcblx0XHRcdChrZXl1cC5lbnRlcik9XCJvbkVudGVyKClcIi8+XG5cdFx0PGJ1dHRvblxuXHRcdFx0Km5nSWY9XCIhdGFibGVTZWFyY2ggJiYgdG9vbGJhclwiXG5cdFx0XHRjbGFzcz1cImNkcy0tdG9vbGJhci1zZWFyY2hfX2J0blwiXG5cdFx0XHQoY2xpY2spPVwib3BlblNlYXJjaCgpXCJcblx0XHRcdGFyaWEtbGFiZWw9XCJPcGVuIHNlYXJjaFwiPlxuXHRcdFx0PHN2ZyBjZHNJY29uPVwic2VhcmNoXCIgc2l6ZT1cIjE2XCIgY2xhc3M9XCJjZHMtLXNlYXJjaC1tYWduaWZpZXItaWNvblwiPjwvc3ZnPlxuXHRcdDwvYnV0dG9uPlxuXHRcdDxzdmdcblx0XHRcdGNkc0ljb249XCJzZWFyY2hcIlxuXHRcdFx0Km5nSWY9XCJ0YWJsZVNlYXJjaCB8fCAhdG9vbGJhclwiXG5cdFx0XHRjbGFzcz1cImNkcy0tc2VhcmNoLW1hZ25pZmllci1pY29uXCJcblx0XHRcdHNpemU9XCIxNlwiPlxuXHRcdDwvc3ZnPlxuXHQ8L25nLXRlbXBsYXRlPlxuXG5cdDxidXR0b25cblx0XHQqbmdJZj1cInRhYmxlU2VhcmNoIHx8ICF0b29sYmFyXCJcblx0XHRjbGFzcz1cImNkcy0tc2VhcmNoLWNsb3NlXCJcblx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHQnY2RzLS1zZWFyY2gtY2xvc2UtLWhpZGRlbic6ICF2YWx1ZSB8fCB2YWx1ZS5sZW5ndGggPT09IDBcblx0XHR9XCJcblx0XHRbdGl0bGVdPVwiY2xlYXJCdXR0b25UaXRsZVwiXG5cdFx0KGNsaWNrKT1cImNsZWFyU2VhcmNoKClcIj5cblx0XHQ8c3BhbiBjbGFzcz1cImNkcy0tdmlzdWFsbHktaGlkZGVuXCI+e3sgY2xlYXJCdXR0b25UaXRsZSB9fTwvc3Bhbj5cblx0XHQ8c3ZnIGNkc0ljb249XCJjbG9zZVwiIHNpemU9XCIxNlwiPjwvc3ZnPlxuXHQ8L2J1dHRvbj5cbjwvZGl2PlxuIl19