@visa/nova-angular
Version:
Visa Product Design System Nova Angular library
517 lines • 62.6 kB
JavaScript
/**
* Copyright (c) 2025 Visa, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ChangeDetectorRef, ContentChildren, Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, QueryList, forwardRef, signal } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { AppReadyService } from '../_utilities/services/app-stable-check.service';
import { UUIDService } from '../_utilities/services/uuid.service';
import { ListboxItemComponent } from '../listbox-item/listbox-item.component';
import { NovaLibService } from '../nova-lib.service';
import { ListboxService } from './listbox.service';
import * as i0 from "@angular/core";
import * as i1 from "../_utilities/services/uuid.service";
import * as i2 from "../nova-lib.service";
import * as i3 from "./listbox.service";
import * as i4 from "../_utilities/services/app-stable-check.service";
export class ListboxDirective {
/**
* Provides custom class(es) for custom styling.
* @default .v-listbox
*/
get class() {
return [this._class, 'v-listbox', this.containHeight ? 'v-listbox-scroll' : ''].join(' ');
}
set class(value) {
this._class = value;
}
get hostClass() {
return this.class;
}
get hostId() {
return this.id;
}
/**
* Sets listbox to multiselect variant when true.
* @default false
*/
get multiselect() {
return this._multiselect;
}
set multiselect(value) {
this._multiselect = coerceBooleanProperty(value);
}
/**
* Sets component and any ListboxItemComponent children as disabled when true. <br>
* Will automatically become true if all children are disabled.
* @default false
*/
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = coerceBooleanProperty(value);
if (this.listItems && this.disabled !== this._childrenDisabled)
this.setChildrenDisabled();
this.informState();
}
/** Fires when a formControl's disabled state updates */
setDisabledState(isDisabled) {
this.disabled = isDisabled;
if (this.listItems && this.disabled !== this._childrenDisabled)
this.setChildrenDisabled();
this.informState();
}
/**
* Sets component and any ListboxItemComponent children as invalid when true. <br>
* Will automatically become true if any child is invalid.
* @default false
*/
get invalid() {
return this._invalid;
}
set invalid(value) {
this._invalid = coerceBooleanProperty(value);
if (this.listItems && this.invalid !== this._childrenInvalid)
this.setChildrenInvalid();
this.informState();
}
/**
* Marks component as required when true.
* @default false
*/
get required() {
return this._required;
}
set required(value) {
this._required = coerceBooleanProperty(value);
this.informState();
}
get hostRole() {
if (this._isRoleListboxVariant() && !this.role) {
this.role = 'group';
}
return this.role;
}
/**
* Sets CSS variable <code>--v-listbox-block-size-scroll</code>. <br />
* If true, the default 180px will be the listbox's <code>max-block-size</code>. <br />
* If set to a number or string representing a number (ie <code>[containHeight]="250"</code>), the variable will be set to that amount of pixels.
*/
get containHeight() {
return this._containHeight;
}
set containHeight(value) {
if (value && value !== true) {
this._containHeight = value;
}
else {
this._containHeight = coerceBooleanProperty(value);
}
}
get scrollHeight() {
if (this.containHeight && this.containHeight !== true) {
return parseInt(this.containHeight.toString()) + 'px'; // allows "250" or "250px" for example
}
}
/**
* Value of listbox.
*/
get value() {
return this._value;
}
set value(value) {
this.setValue(value);
}
// keep val for backwards compatibility
get val() {
return this._value;
}
set val(value) {
this.setValue(value);
}
setValue(value) {
this._value = value;
if (this.appReadyService.isBrowserAndDomAvailable()) {
this.el.nativeElement.value = value;
}
if (this.listItems && this._internalValue !== value) {
if (Array.isArray(value)) {
// multiselect
this.listItems
.filter((item) => value?.includes(item.value))
.forEach((item) => {
item.active = true;
});
}
else if (value) {
// single select
const selectedItem = this.listItems.find((item) => item.value === value);
if (selectedItem)
selectedItem.active = true;
}
this._internalValue = value;
}
if (!value || (this.multiselect && Array.isArray(value) && value.length === 0)) {
// reset items
this.resetListbox();
}
this.valueUpdated.emit(this.value);
this.onChange(value);
}
/**
* Overrides default scroll control behavior. <br />
* By default the listbox will scroll to the last selected item.
* @default false
*/
get customScrollControl() {
return this._customScrollControl;
}
set customScrollControl(value) {
this._customScrollControl = coerceBooleanProperty(value);
}
constructor(uuidService, novaLibService, listboxService, cdRef, el, appReadyService) {
this.uuidService = uuidService;
this.novaLibService = novaLibService;
this.listboxService = listboxService;
this.cdRef = cdRef;
this.el = el;
this.appReadyService = appReadyService;
this._isRoleListboxVariant = signal(false);
this._childrenDisabled = false;
this._childrenInvalid = false;
this._inCombobox = false;
this._listboxScrollStylesSet = false;
this._keyword = '';
this._highlightIndex = null;
this._isHotkeyEvent = false;
this._recentSelectedIndex = null;
this._timeoutId = 0;
this.ariaActiveDescendant = signal(null);
this._class = '';
/**
* Sets custom id.
* @default uuidService.getUUID('v-listbox-')
* @builtin true
*/
this.id = this.uuidService.getUUID('v-listbox-');
this._multiselect = false;
this._disabled = false;
this._invalid = false;
this._required = false;
this._customScrollControl = false;
/**
* Emits disabled, invalid, and required state of input when updated.
*/
this.communicateState = new EventEmitter();
/**
* Emits new listbox value.
*/
this.valueUpdated = new EventEmitter();
this.onChange = (_) => { };
this.onTouched = (_) => { };
}
handleFocus(event) {
this.onTouched(event);
}
handleBlur(event) { }
ngAfterContentInit() {
if (this.listItems) {
this.setUpListbox();
this.listItems.changes.subscribe(() => {
this.setUpListbox();
});
}
}
setUpListbox() {
if (this.disabled) {
// if listbox disabled is true, disable all items
this.setChildrenDisabled();
}
else if (
// if all items are disabled, set listbox disabled to true
this.listItems.length > 0 &&
this.listItems.toArray().length === this.listItems.toArray().filter((item) => item.disabled).length) {
this._childrenDisabled = true;
this.disabled = true;
}
else {
this._childrenDisabled = false;
this.disabled = false;
}
if (this.invalid) {
// if listbox invalid is true, set children as invalid
this.setChildrenInvalid();
}
else if (this.listItems.find((item) => item.invalid)) {
// if any item is invalid, set invalid class
this._childrenInvalid = true;
this.invalid = true;
}
else {
this._childrenInvalid = false;
this.invalid = false;
}
this._invalid = this.listItems.find((item) => item.invalid) ? true : false;
this.addListItemSubscriptions();
this.setInitialValue();
// if standard listbox and not in combobox, add arrow key navigation
if (this._isRoleListboxVariant() && !this._inCombobox) {
this.listboxService.setUpListbox(this);
}
if (!this.customScrollControl) {
setTimeout(() => {
this.listboxService.scrollItemIntoView(this);
}, 500); // on initial load, extra time is needed for getComputedStyle
}
}
setInitialValue() {
if (
/**
* If value is an array, make sure the array is not empty
* If value is not an array, make sure value exists.
* This check ensures the function isn't called when value = []
*/
(this.multiselect && Array.isArray(this.value) && this.value.length > 0) ||
(!this.multiselect && this.value)) {
this.updateItemsFromValue();
}
else {
// if no value is given, find any active items and set value to those
this.updateValueFromItems();
}
this.cdRef.detectChanges();
}
addListItemSubscriptions() {
this.listItems.forEach((item, index) => {
item.onFocus.subscribe((event) => {
if (this._highlightIndex === null)
this._highlightIndex = this.novaLibService.firstEnabledItem(this.listItems.toArray());
});
// subscribe to changes in disabled and invalid
item._disabledEmitter.subscribe(() => {
// if ALL children are disabled, entire listbox is disabled
if (this.listItems.toArray().length === this.listItems.filter((item) => item.disabled).length) {
this._childrenDisabled = true;
this.disabled = true;
}
else {
this._childrenDisabled = false;
this.disabled = false;
}
});
item._invalidEmitter.subscribe(() => {
// if ANY child is invalid, listbox shows as invalid
if (this.listItems.find((item) => item.invalid)) {
this._childrenInvalid = true;
this.invalid = true;
}
else {
this._childrenInvalid = false;
this.invalid = false;
}
});
// if standard listbox, add role="listbox" and change underlying class to radio or checkbox accordingly
if (item._isRoleOptionVariant) {
if (!this._isRoleListboxVariant())
this._isRoleListboxVariant.set(true);
item._multi = this.multiselect;
item.index = index;
// subscribe to when item is selected or clicked
item.itemChanged.subscribe((isSelected) => {
if (index !== item.index)
return; // subscription is still being triggered for old rendered item
this.novaLibService.deselectItems(this.listItems.toArray(), index, 'highlighted');
if (!this.multiselect && isSelected) {
this.novaLibService.deselectItems(this.listItems.toArray(), index);
this.updateValueFromItems();
}
else if (this.multiselect) {
// not calling update value because we need to maintain order
if (isSelected) {
if (Array.isArray(this.value)) {
if (!this.value.includes(item.value))
this.value = [...this.value, item.value];
}
else {
this.value = [item.value];
}
}
else {
if (Array.isArray(this.value)) {
this.value = this.value.filter((val) => val !== item.value);
}
else {
this.value = [];
}
}
// set aria-activedescendant to first value
this.ariaActiveDescendant.set(this.listItems.find((item) => item.active)?.id || null);
}
// Update highlight index if indexes do not match and click event is not triggered by hot key
// Used for click event
if (this._highlightIndex !== index && !this._isHotkeyEvent) {
this._highlightIndex = index;
// item.highlighted = true;
this._recentSelectedIndex = item.index;
}
});
this.cdRef.detectChanges();
}
});
}
// value is given, update items so active items reflect listbox value
updateItemsFromValue() {
if (this.multiselect && Array.isArray(this.value) && this.value.length > 0) {
// if value is an array, select all items that match the value
this.listItems
.filter((item) => this.value.includes(item.value))
.forEach((item) => {
item.active = true;
});
}
else if (!this.multiselect && this.value) {
// if item is string, select item that matches the value
this.listItems
.filter((item) => this.value === item.value)
.forEach((item) => {
item.active = true;
});
}
// set aria-activedescendant to first value
this.ariaActiveDescendant.set(this.listItems.find((item) => item.active)?.id || null);
}
// no value is given, update value so it reflects active items
updateValueFromItems() {
// if multiselect, return value in array
if (this.multiselect) {
this.value = this.listItems.filter((item) => item.active).map((item) => item.value);
}
else {
// if single select, return single value
this.value = this.listItems.find((item) => item.active)?.value || null;
}
// set aria-activedescendant to first value
this.ariaActiveDescendant.set(this.listItems.find((item) => item.active)?.id || null);
}
setChildrenDisabled() {
this.listItems.forEach((item) => item.checkbox
? (item.checkbox.disabled = this.disabled)
: item.radio
? (item.radio.disabled = this.disabled)
: (item.disabled = this.disabled));
this._childrenDisabled = this.listItems.toArray().length === this.listItems.filter((item) => item.disabled).length;
}
setChildrenInvalid() {
this.listItems.forEach((item) => item.checkbox
? (item.checkbox.invalid = this.invalid)
: item.radio
? (item.radio.invalid = this.invalid)
: (item.invalid = this.invalid));
this._childrenInvalid = this.listItems.some((item) => item.invalid);
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
writeValue(value) {
this.value = value;
}
resetListbox() {
if (this.listItems?.find((item) => item.active)) {
// reset items
this.novaLibService.deselectItems(this.listItems.toArray());
}
this.ariaActiveDescendant.set(null);
}
informState() {
this.communicateState.emit({
disabled: this.disabled,
invalid: this.invalid,
required: this.required
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ListboxDirective, deps: [{ token: i1.UUIDService }, { token: i2.NovaLibService }, { token: i3.ListboxService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i4.AppReadyService }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ListboxDirective, isStandalone: true, selector: "[v-listbox] ", inputs: { class: "class", id: "id", multiselect: "multiselect", disabled: "disabled", invalid: "invalid", required: "required", role: "role", containHeight: "containHeight", value: "value", customScrollControl: "customScrollControl" }, outputs: { communicateState: "communicateState", valueUpdated: "valueUpdated" }, host: { listeners: { "focus": "handleFocus($event)", "blur": "handleBlur($event)" }, properties: { "class": "this.hostClass", "attr.id": "this.hostId", "attr.role": "this.hostRole", "style.--v-listbox-block-size-scroll": "this.scrollHeight" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ListboxDirective),
multi: true
}
], queries: [{ propertyName: "listItems", predicate: ListboxItemComponent }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ListboxDirective, decorators: [{
type: Directive,
args: [{
standalone: true,
selector: '[v-listbox] ',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ListboxDirective),
multi: true
}
]
}]
}], ctorParameters: () => [{ type: i1.UUIDService }, { type: i2.NovaLibService }, { type: i3.ListboxService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i4.AppReadyService }], propDecorators: { listItems: [{
type: ContentChildren,
args: [ListboxItemComponent]
}], class: [{
type: Input
}], hostClass: [{
type: HostBinding,
args: ['class']
}], id: [{
type: Input
}], hostId: [{
type: HostBinding,
args: ['attr.id']
}], multiselect: [{
type: Input
}], disabled: [{
type: Input
}], invalid: [{
type: Input
}], required: [{
type: Input
}], role: [{
type: Input
}], hostRole: [{
type: HostBinding,
args: ['attr.role']
}], containHeight: [{
type: Input
}], scrollHeight: [{
type: HostBinding,
args: ['style.--v-listbox-block-size-scroll']
}], value: [{
type: Input
}], customScrollControl: [{
type: Input
}], communicateState: [{
type: Output
}], valueUpdated: [{
type: Output
}], handleFocus: [{
type: HostListener,
args: ['focus', ['$event']]
}], handleBlur: [{
type: HostListener,
args: ['blur', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdGJveC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL25vdmEtbGliL3NyYy9saWIvbGlzdGJveC9saXN0Ym94LmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0lBZUk7QUFDSixPQUFPLEVBQTZCLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDekYsT0FBTyxFQUVMLGlCQUFpQixFQUNqQixlQUFlLEVBQ2YsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsRUFFVCxVQUFVLEVBQ1YsTUFBTSxFQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saURBQWlELENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7Ozs7OztBQWFuRCxNQUFNLE9BQU8sZ0JBQWdCO0lBcUIzQjs7O09BR0c7SUFDSCxJQUNJLEtBQUs7UUFDUCxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1RixDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsS0FBYTtRQUNyQixJQUFJLENBQUMsTUFB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QVg1QixTQUFTO21CQUFDO29CQUNULFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUUsY0FBYztvQkFDeEIsU0FBUyxFQUFFO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLGlCQUFpQixDQUFDOzRCQUMvQyxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjtpQkFDRjtpT0FFd0MsU0FBUztzQkFBL0MsZUFBZTt1QkFBQyxvQkFBb0I7Z0JBeUJqQyxLQUFLO3NCQURSLEtBQUs7Z0JBU0YsU0FBUztzQkFEWixXQUFXO3VCQUFDLE9BQU87Z0JBV3BCLEVBQUU7c0JBREQsS0FBSztnQkFHRixNQUFNO3NCQURULFdBQVc7dUJBQUMsU0FBUztnQkFVbEIsV0FBVztzQkFEZCxLQUFLO2dCQWVGLFFBQVE7c0JBRFgsS0FBSztnQkF1QkYsT0FBTztzQkFEVixLQUFLO2dCQWdCRixRQUFRO3NCQURYLEtBQUs7Z0JBZ0JHLElBQUk7c0JBQVosS0FBSztnQkFFRixRQUFRO3NCQURYLFdBQVc7dUJBQUMsV0FBVztnQkFjcEIsYUFBYTtzQkFEaEIsS0FBSztnQkFhRixZQUFZO3NCQURmLFdBQVc7dUJBQUMscUNBQXFDO2dCQVc5QyxLQUFLO3NCQURSLEtBQUs7Z0JBcURGLG1CQUFtQjtzQkFEdEIsS0FBSztnQkFZSSxnQkFBZ0I7c0JBQXpCLE1BQU07Z0JBS0csWUFBWTtzQkFBckIsTUFBTTtnQkFZUCxXQUFXO3NCQURWLFlBQVk7dUJBQUMsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQUtqQyxVQUFVO3NCQURULFlBQVk7dUJBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgICAgICAgICAgICAgQ29weXJpZ2h0IChjKSAyMDI1IFZpc2EsIEluYy5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqKi9cbmltcG9ydCB7IEJvb2xlYW5JbnB1dCwgTnVtYmVySW5wdXQsIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29udGVudENoaWxkcmVuLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBXcml0YWJsZVNpZ25hbCxcbiAgZm9yd2FyZFJlZixcbiAgc2lnbmFsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQXBwUmVhZHlTZXJ2aWNlIH0gZnJvbSAnLi4vX3V0aWxpdGllcy9zZXJ2aWNlcy9hcHAtc3RhYmxlLWNoZWNrLnNlcnZpY2UnO1xuaW1wb3J0IHsgVVVJRFNlcnZpY2UgfSBmcm9tICcuLi9fdXRpbGl0aWVzL3NlcnZpY2VzL3V1aWQuc2VydmljZSc7XG5pbXBvcnQgeyBMaXN0Ym94SXRlbUNvbXBvbmVudCB9IGZyb20gJy4uL2xpc3Rib3gtaXRlbS9saXN0Ym94LWl0ZW0uY29tcG9uZW50JztcbmltcG9ydCB7IE5vdmFMaWJTZXJ2aWNlIH0gZnJvbSAnLi4vbm92YS1saWIuc2VydmljZSc7XG5pbXBvcnQgeyBMaXN0Ym94U2VydmljZSB9IGZyb20gJy4vbGlzdGJveC5zZXJ2aWNlJztcblxuQERpcmVjdGl2ZSh7XG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHNlbGVjdG9yOiAnW3YtbGlzdGJveF0gJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBMaXN0Ym94RGlyZWN0aXZlKSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIExpc3Rib3hEaXJlY3RpdmUgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgQWZ0ZXJDb250ZW50SW5pdCB7XG4gIEBDb250ZW50Q2hpbGRyZW4oTGlzdGJveEl0ZW1Db21wb25lbnQpIGxpc3RJdGVtczogUXVlcnlMaXN0PExpc3Rib3hJdGVtQ29tcG9uZW50PjtcbiAgX2lzUm9sZUxpc3Rib3hWYXJpYW50ID0gc2lnbmFsKGZhbHNlKTtcbiAgX2NoaWxkcmVuRGlzYWJsZWQgPSBmYWxzZTtcbiAgX2NoaWxkcmVuSW52YWxpZCA9IGZhbHNlO1xuICBfaW50ZXJuYWxWYWx1ZTogKHN0cmluZyB8IG51bWJlcilbXSB8IHN0cmluZyB8IG51bWJlciB8IG51bGw7XG4gIF9pbkNvbWJvYm94ID0gZmFsc2U7XG5cbiAgLy8gdXNlZCBpbiBzZXJ2aWNlXG4gIF9saXN0Ym94SGVpZ2h0OiBudW1iZXI7XG4gIF9saXN0Ym94SXRlbUhlaWdodDogbnVtYmVyO1xuICBfbGlzdGJveEdhcDogbnVtYmVyO1xuICBfbGlzdGJveFNjcm9sbFN0eWxlc1NldDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIF9rZXl3b3JkOiBTdHJpbmcgPSAnJztcbiAgX2hpZ2hsaWdodEluZGV4OiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgX2lzSG90a2V5RXZlbnQ6IEJvb2xlYW4gPSBmYWxzZTtcbiAgX3JlY2VudFNlbGVjdGVkSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBfdGltZW91dElkOiBudW1iZXIgPSAwO1xuICBhcmlhQWN0aXZlRGVzY2VuZGFudDogV3JpdGFibGVTaWduYWw8c3RyaW5nIHwgbnVsbD4gPSBzaWduYWwobnVsbCk7XG5cbiAgLyoqXG4gICAqIFByb3ZpZGVzIGN1c3RvbSBjbGFzcyYjNDA7ZXMmIzQxOyBmb3IgY3VzdG9tIHN0eWxpbmcuXG4gICAqIEBkZWZhdWx0IC52LWxpc3Rib3hcbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCBjbGFzcygpOiBzdHJpbmcge1xuICAgIHJldHVybiBbdGhpcy5fY2xhc3MsICd2LWxpc3Rib3gnLCB0aGlzLmNvbnRhaW5IZWlnaHQgPyAndi1saXN0Ym94LXNjcm9sbCcgOiAnJ10uam9pbignICcpO1xuICB9XG4gIHNldCBjbGFzcyh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fY2xhc3MgPSB2YWx1ZTtcbiAgfVxuICBfY2xhc3M6IHN0cmluZyA9ICcnO1xuICBASG9zdEJpbmRpbmcoJ2NsYXNzJylcbiAgZ2V0IGhvc3RDbGFzcygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNsYXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY3VzdG9tIGlkLlxuICAgKiBAZGVmYXVsdCB1dWlkU2VydmljZS5nZXRVVUlEKCd2LWxpc3Rib3gtJylcbiAgICogQGJ1aWx0aW4gdHJ1ZVxuICAgKi9cbiAgQElucHV0KClcbiAgaWQ6IHN0cmluZyA9IHRoaXMudXVpZFNlcnZpY2UuZ2V0VVVJRCgndi1saXN0Ym94LScpO1xuICBASG9zdEJpbmRpbmcoJ2F0dHIuaWQnKVxuICBnZXQgaG9zdElkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaWQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBsaXN0Ym94IHRvIG11bHRpc2VsZWN0IHZhcmlhbnQgd2hlbiB0cnVlLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IG11bHRpc2VsZWN0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9tdWx0aXNlbGVjdDtcbiAgfVxuICBzZXQgbXVsdGlzZWxlY3QodmFsdWU6IEJvb2xlYW5JbnB1dCkge1xuICAgIHRoaXMuX211bHRpc2VsZWN0ID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBfbXVsdGlzZWxlY3Q6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogU2V0cyBjb21wb25lbnQgYW5kIGFueSBMaXN0Ym94SXRlbUNvbXBvbmVudCBjaGlsZHJlbiBhcyBkaXNhYmxlZCB3aGVuIHRydWUuIDxicj5cbiAgICogV2lsbCBhdXRvbWF0aWNhbGx5IGJlY29tZSB0cnVlIGlmIGFsbCBjaGlsZHJlbiBhcmUgZGlzYWJsZWQuXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgZGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkO1xuICB9XG4gIHNldCBkaXNhYmxlZCh2YWx1ZTogQm9vbGVhbklucHV0KSB7XG4gICAgdGhpcy5fZGlzYWJsZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICAgIGlmICh0aGlzLmxpc3RJdGVtcyAmJiB0aGlzLmRpc2FibGVkICE9PSB0aGlzLl9jaGlsZHJlbkRpc2FibGVkKSB0aGlzLnNldENoaWxkcmVuRGlzYWJsZWQoKTtcbiAgICB0aGlzLmluZm9ybVN0YXRlKCk7XG4gIH1cbiAgX2Rpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG4gIC8qKiBGaXJlcyB3aGVuIGEgZm9ybUNvbnRyb2wncyBkaXNhYmxlZCBzdGF0ZSB1cGRhdGVzICAqL1xuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICBpZiAodGhpcy5saXN0SXRlbXMgJiYgdGhpcy5kaXNhYmxlZCAhPT0gdGhpcy5fY2hpbGRyZW5EaXNhYmxlZCkgdGhpcy5zZXRDaGlsZHJlbkRpc2FibGVkKCk7XG4gICAgdGhpcy5pbmZvcm1TdGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY29tcG9uZW50IGFuZCBhbnkgTGlzdGJveEl0ZW1Db21wb25lbnQgY2hpbGRyZW4gYXMgaW52YWxpZCB3aGVuIHRydWUuIDxicj5cbiAgICogV2lsbCBhdXRvbWF0aWNhbGx5IGJlY29tZSB0cnVlIGlmIGFueSBjaGlsZCBpcyBpbnZhbGlkLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgQElucHV0KClcbiAgZ2V0IGludmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2ludmFsaWQ7XG4gIH1cbiAgc2V0IGludmFsaWQodmFsdWU6IEJvb2xlYW5JbnB1dCkge1xuICAgIHRoaXMuX2ludmFsaWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICAgIGlmICh0aGlzLmxpc3RJdGVtcyAmJiB0aGlzLmludmFsaWQgIT09IHRoaXMuX2NoaWxkcmVuSW52YWxpZCkgdGhpcy5zZXRDaGlsZHJlbkludmFsaWQoKTtcbiAgICB0aGlzLmluZm9ybVN0YXRlKCk7XG4gIH1cbiAgX2ludmFsaWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogTWFya3MgY29tcG9uZW50IGFzIHJlcXVpcmVkIHdoZW4gdHJ1ZS5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCByZXF1aXJlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fcmVxdWlyZWQ7XG4gIH1cbiAgc2V0IHJlcXVpcmVkKHZhbHVlOiBCb29sZWFuSW5wdXQpIHtcbiAgICB0aGlzLl9yZXF1aXJlZCA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gICAgdGhpcy5pbmZvcm1TdGF0ZSgpO1xuICB9XG4gIF9yZXF1aXJlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBTZXRzIGN1c3RvbSByb2xlLlxuICAgKiBAZGVmYXVsdCAnZ3JvdXAnIGlmIG5vIGNoaWxkIGxpc3QgaXRlbSBjb250YWlucyBhIGNoaWxkIHJhZGlvIG9yIGNoZWNrYm94LlxuICAgKiBAZGVmYXVsdCBub3QgcHJlc2VudCBpZiBhbnkgY2hpbGQgbGlzdCBpdGVtIGNvbnRhaW5zIGEgY2hpbGQgcmFkaW8gb3IgY2hlY2tib3guXG4gICAqIEBidWlsdGluIHRydWVcbiAgICovXG4gIEBJbnB1dCgpIHJvbGU6IHN0cmluZztcbiAgQEhvc3RCaW5kaW5nKCdhdHRyLnJvbGUnKVxuICBnZXQgaG9zdFJvbGUoKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5faXNSb2xlTGlzdGJveFZhcmlhbnQoKSAmJiAhdGhpcy5yb2xlKSB7XG4gICAgICB0aGlzLnJvbGUgPSAnZ3JvdXAnO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5yb2xlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgQ1NTIHZhcmlhYmxlIDxjb2RlPi0tdi1saXN0Ym94LWJsb2NrLXNpemUtc2Nyb2xsPC9jb2RlPi4gPGJyIC8+XG4gICAqIElmIHRydWUsIHRoZSBkZWZhdWx0IDE4MHB4IHdpbGwgYmUgdGhlIGxpc3Rib3gncyA8Y29kZT5tYXgtYmxvY2stc2l6ZTwvY29kZT4uIDxiciAvPlxuICAgKiBJZiBzZXQgdG8gYSBudW1iZXIgb3Igc3RyaW5nIHJlcHJlc2VudGluZyBhIG51bWJlciAoaWUgPGNvZGU+W2NvbnRhaW5IZWlnaHRdPVwiMjUwXCI8L2NvZGU+KSwgdGhlIHZhcmlhYmxlIHdpbGwgYmUgc2V0IHRvIHRoYXQgYW1vdW50IG9mIHBpeGVscy5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCBjb250YWluSGVpZ2h0KCk6IE51bWJlcklucHV0IHwgQm9vbGVhbklucHV0IHtcbiAgICByZXR1cm4gdGhpcy5fY29udGFpbkhlaWdodDtcbiAgfVxuICBzZXQgY29udGFpbkhlaWdodCh2YWx1ZTogTnVtYmVySW5wdXQgfCBCb29sZWFuSW5wdXQpIHtcbiAgICBpZiAodmFsdWUgJiYgdmFsdWUgIT09IHRydWUpIHtcbiAgICAgIHRoaXMuX2NvbnRhaW5IZWlnaHQgPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fY29udGFpbkhlaWdodCA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIF9jb250YWluSGVpZ2h0OiBOdW1iZXJJbnB1dCB8IEJvb2xlYW5JbnB1dDtcbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS4tLXYtbGlzdGJveC1ibG9jay1zaXplLXNjcm9sbCcpXG4gIGdldCBzY3JvbGxIZWlnaHQoKTogTnVtYmVySW5wdXQgfCB2b2lkIHwgYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuY29udGFpbkhlaWdodCAmJiB0aGlzLmNvbnRhaW5IZWlnaHQgIT09IHRydWUpIHtcbiAgICAgIHJldHVybiBwYXJzZUludCh0aGlzLmNvbnRhaW5IZWlnaHQudG9TdHJpbmcoKSkgKyAncHgnOyAvLyBhbGxvd3MgXCIyNTBcIiBvciBcIjI1MHB4XCIgZm9yIGV4YW1wbGVcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsdWUgb2YgbGlzdGJveC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cbiAgc2V0IHZhbHVlKHZhbHVlOiAoc3RyaW5nIHwgbnVtYmVyKVtdIHwgc3RyaW5nIHwgbnVtYmVyIHwgbnVsbCkge1xuICAgIHRoaXMuc2V0VmFsdWUodmFsdWUpO1xuICB9XG5cbiAgLy8ga2VlcCB2YWwgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gIGdldCB2YWwoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICB9XG4gIHNldCB2YWwodmFsdWU6IChzdHJpbmcgfCBudW1iZXIpW10gfCBzdHJpbmcgfCBudW1iZXIgfCBudWxsKSB7XG4gICAgdGhpcy5zZXRWYWx1ZSh2YWx1ZSk7XG4gIH1cblxuICBzZXRWYWx1ZSh2YWx1ZTogKHN0cmluZyB8IG51bWJlcilbXSB8IHN0cmluZyB8IG51bWJlciB8IG51bGwpIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKHRoaXMuYXBwUmVhZHlTZXJ2aWNlLmlzQnJvd3NlckFuZERvbUF2YWlsYWJsZSgpKSB7XG4gICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5saXN0SXRlbXMgJiYgdGhpcy5faW50ZXJuYWxWYWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAvLyBtdWx0aXNlbGVjdFxuICAgICAgICB0aGlzLmxpc3RJdGVtc1xuICAgICAgICAgIC5maWx0ZXIoKGl0ZW0pID0+IHZhbHVlPy5pbmNsdWRlcyhpdGVtLnZhbHVlKSlcbiAgICAgICAgICAuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaXRlbS5hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSkge1xuICAgICAgICAvLyBzaW5nbGUgc2VsZWN0XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkSXRlbSA9IHRoaXMubGlzdEl0ZW1zLmZpbmQoKGl0ZW0pID0+IGl0ZW0udmFsdWUgPT09IHZhbHVlKTtcbiAgICAgICAgaWYgKHNlbGVjdGVkSXRlbSkgc2VsZWN0ZWRJdGVtLmFjdGl2ZSA9IHRydWU7XG4gICAgICB9XG4gICAgICB0aGlzLl9pbnRlcm5hbFZhbHVlID0gdmFsdWU7XG4gICAgfVxuICAgIGlmICghdmFsdWUgfHwgKHRoaXMubXVsdGlzZWxlY3QgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSkge1xuICAgICAgLy8gcmVzZXQgaXRlbXNcbiAgIC