UNPKG

@clr/angular

Version:

Angular components for Clarity

233 lines (231 loc) 22.5 kB
/* * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { Component, ContentChild, EventEmitter, HostBinding, Input, Optional, Output, SkipSelf, } from '@angular/core'; import { uniqueIdFactory } from '../../utils/id-generator/id-generator.service'; import { ClrStackViewLabel } from './stack-view-custom-tags'; import * as i0 from "@angular/core"; import * as i1 from "../../utils/i18n/common-strings.service"; import * as i2 from "@angular/common"; import * as i3 from "../../icon/icon"; import * as i4 from "../../utils/animations/expandable-animation/expandable-animation"; export class ClrStackBlock { /* * This would be more efficient with @ContentChildren, with the parent ClrStackBlock * querying for children StackBlocks, but this feature is not available when downgrading * the component for Angular 1. */ constructor(parent, commonStrings) { this.parent = parent; this.commonStrings = commonStrings; this.expanded = false; this.expandable = false; this.expandedChange = new EventEmitter(false); this.focused = false; this.uniqueId = uniqueIdFactory(); this._changedChildren = 0; this._fullyInitialized = false; this._changed = false; if (parent) { parent.addChild(); } } set setChangedValue(value) { this._changed = value; if (this.parent && this._fullyInitialized) { if (value) { this.parent._changedChildren++; } else { this.parent._changedChildren--; } } } get getChangedValue() { return this._changed || (this._changedChildren > 0 && !this.expanded); } get onStackLabelFocus() { return this.expandable && !this.expanded && this.focused; } get labelledById() { return this.stackBlockTitle.id; } get headingLevel() { if (this.ariaLevel) { return this.ariaLevel + ''; } return this.parent ? '4' : '3'; } get caretDirection() { return this.expanded ? 'down' : 'right'; } get role() { return this.expandable ? 'button' : null; } get tabIndex() { return this.expandable ? '0' : null; } get ariaExpanded() { if (!this.expandable) { return null; } else { return this.expanded ? 'true' : 'false'; } } ngOnInit() { // in order to access the parent ClrStackBlock's properties, // the child ClrStackBlock has to be fully initialized at first. this._fullyInitialized = true; } addChild() { this.expandable = true; } toggleExpand(event) { if (eventIsInputEvent(event)) { return; } if (this.expandable) { this.expanded = !this.expanded; this.expandedChange.emit(this.expanded); } } getStackChildrenId() { return this.expanded ? `clr-stack-children-${this.uniqueId}` : null; } preventDefaultIfNotInputEvent(event) { if (eventIsInputEvent(event)) { return; } event.preventDefault(); } } ClrStackBlock.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrStackBlock, deps: [{ token: ClrStackBlock, optional: true, skipSelf: true }, { token: i1.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); ClrStackBlock.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrStackBlock, selector: "clr-stack-block", inputs: { expanded: ["clrSbExpanded", "expanded"], expandable: ["clrSbExpandable", "expandable"], ariaLevel: ["clrStackViewLevel", "ariaLevel"], setChangedValue: ["clrSbNotifyChange", "setChangedValue"] }, outputs: { expandedChange: "clrSbExpandedChange" }, host: { properties: { "class.stack-block": "true", "attr.role": "\"heading\"", "attr.aria-level": "headingLevel", "class.stack-block-expanded": "this.expanded", "class.stack-block-expandable": "this.expandable", "class.stack-block-changed": "this.getChangedValue", "class.on-focus": "this.onStackLabelFocus" } }, queries: [{ propertyName: "stackBlockTitle", first: true, predicate: ClrStackViewLabel, descendants: true }], ngImport: i0, template: ` <!-- The 'preventDefault' for the space keydown event prevents the page from scrolling when a stack block is toggled via the space key. --> <div class="stack-block-label" (click)="toggleExpand($event)" (keyup.enter)="toggleExpand($event)" (keyup.space)="toggleExpand($event)" (keydown.space)="preventDefaultIfNotInputEvent($event)" (focus)="focused = true" (blur)="focused = false" [id]="uniqueId" [attr.role]="role" [attr.tabindex]="tabIndex" [attr.aria-expanded]="ariaExpanded" [attr.aria-controls]="getStackChildrenId()" > <cds-icon shape="angle" class="stack-block-caret" *ngIf="expandable" [attr.direction]="caretDirection"></cds-icon> <span class="clr-sr-only" *ngIf="getChangedValue">{{ commonStrings.keys.stackViewChanged }}</span> <div class="stack-view-key"> <!-- This structure changed to fix #3567 and the a11y request was to move away from dl's --> <!-- I added the key class to update css targets for the original component style --> <ng-content select="clr-stack-label"></ng-content> </div> <div class="stack-block-content"> <ng-content></ng-content> </div> </div> <clr-expandable-animation [clrExpandTrigger]="expanded" class="stack-children"> <div [style.height]="expanded ? 'auto' : 0" role="region" *ngIf="expanded" [attr.id]="getStackChildrenId()" [attr.aria-labelledby]="labelledById" > <ng-content select="clr-stack-block"></ng-content> </div> </clr-expandable-animation> `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.CdsIconCustomTag, selector: "cds-icon" }, { kind: "component", type: i4.ClrExpandableAnimation, selector: "clr-expandable-animation", inputs: ["clrExpandTrigger"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrStackBlock, decorators: [{ type: Component, args: [{ selector: 'clr-stack-block', template: ` <!-- The 'preventDefault' for the space keydown event prevents the page from scrolling when a stack block is toggled via the space key. --> <div class="stack-block-label" (click)="toggleExpand($event)" (keyup.enter)="toggleExpand($event)" (keyup.space)="toggleExpand($event)" (keydown.space)="preventDefaultIfNotInputEvent($event)" (focus)="focused = true" (blur)="focused = false" [id]="uniqueId" [attr.role]="role" [attr.tabindex]="tabIndex" [attr.aria-expanded]="ariaExpanded" [attr.aria-controls]="getStackChildrenId()" > <cds-icon shape="angle" class="stack-block-caret" *ngIf="expandable" [attr.direction]="caretDirection"></cds-icon> <span class="clr-sr-only" *ngIf="getChangedValue">{{ commonStrings.keys.stackViewChanged }}</span> <div class="stack-view-key"> <!-- This structure changed to fix #3567 and the a11y request was to move away from dl's --> <!-- I added the key class to update css targets for the original component style --> <ng-content select="clr-stack-label"></ng-content> </div> <div class="stack-block-content"> <ng-content></ng-content> </div> </div> <clr-expandable-animation [clrExpandTrigger]="expanded" class="stack-children"> <div [style.height]="expanded ? 'auto' : 0" role="region" *ngIf="expanded" [attr.id]="getStackChildrenId()" [attr.aria-labelledby]="labelledById" > <ng-content select="clr-stack-block"></ng-content> </div> </clr-expandable-animation> `, host: { '[class.stack-block]': 'true', '[attr.role]': '"heading"', '[attr.aria-level]': 'headingLevel', }, styles: [":host{display:block}\n"] }] }], ctorParameters: function () { return [{ type: ClrStackBlock, decorators: [{ type: SkipSelf }, { type: Optional }] }, { type: i1.ClrCommonStringsService }]; }, propDecorators: { expanded: [{ type: Input, args: ['clrSbExpanded'] }, { type: HostBinding, args: ['class.stack-block-expanded'] }], expandable: [{ type: Input, args: ['clrSbExpandable'] }, { type: HostBinding, args: ['class.stack-block-expandable'] }], ariaLevel: [{ type: Input, args: ['clrStackViewLevel'] }], expandedChange: [{ type: Output, args: ['clrSbExpandedChange'] }], stackBlockTitle: [{ type: ContentChild, args: [ClrStackViewLabel] }], setChangedValue: [{ type: Input, args: ['clrSbNotifyChange'] }], getChangedValue: [{ type: HostBinding, args: ['class.stack-block-changed'] }], onStackLabelFocus: [{ type: HostBinding, args: ['class.on-focus'] }] } }); function eventIsInputEvent(event) { const targetElement = event?.target; return targetElement?.tagName === 'INPUT'; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stYmxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyL3NyYy9kYXRhL3N0YWNrLXZpZXcvc3RhY2stYmxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUVMLFFBQVEsRUFDUixNQUFNLEVBQ04sUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQUNoRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7O0FBNEQ3RCxNQUFNLE9BQU8sYUFBYTtJQW9CeEI7Ozs7T0FJRztJQUNILFlBR1UsTUFBcUIsRUFDdEIsYUFBc0M7UUFEckMsV0FBTSxHQUFOLE1BQU0sQ0FBZTtRQUN0QixrQkFBYSxHQUFiLGFBQWEsQ0FBeUI7UUE1Qm9CLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDYixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBTzNELG1CQUFjLEdBQUcsSUFBSSxZQUFZLENBQVUsS0FBSyxDQUFDLENBQUM7UUFJakYsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQixhQUFRLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFFckIscUJBQWdCLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUMxQixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBYXZCLElBQUksTUFBTSxFQUFFO1lBQ1YsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ25CO0lBQ0gsQ0FBQztJQUVELElBQ0ksZUFBZSxDQUFDLEtBQWM7UUFDaEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFFdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxp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LGlCQUFpQixZQUNqQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdDVCxRQVVLO3dCQUNKLHFCQUFxQixFQUFFLE1BQU07d0JBQzdCLGFBQWEsRUFBRSxXQUFXO3dCQUMxQixtQkFBbUIsRUFBRSxjQUFjO3FCQUNwQzs7MEJBNEJFLFFBQVE7OzBCQUNSLFFBQVE7a0ZBMUJ3RCxRQUFRO3NCQUExRSxLQUFLO3VCQUFDLGVBQWU7O3NCQUFHLFdBQVc7dUJBQUMsNEJBQTRCO2dCQUNNLFVBQVU7c0JBQWhGLEtBQUs7dUJBQUMsaUJBQWlCOztzQkFBRyxXQUFXO3VCQUFDLDhCQUE4QjtnQkFLekMsU0FBUztzQkFBcEMsS0FBSzt1QkFBQyxtQkFBbUI7Z0JBRUssY0FBYztzQkFBNUMsTUFBTTt1QkFBQyxxQkFBcUI7Z0JBRUksZUFBZTtzQkFBL0MsWUFBWTt1QkFBQyxpQkFBaUI7Z0JBMEIzQixlQUFlO3NCQURsQixLQUFLO3VCQUFDLG1CQUFtQjtnQkFjdEIsZUFBZTtzQkFEbEIsV0FBVzt1QkFBQywyQkFBMkI7Z0JBTXBDLGlCQUFpQjtzQkFEcEIsV0FBVzt1QkFBQyxnQkFBZ0I7O0FBdUUvQixTQUFTLGlCQUFpQixDQUFDLEtBQWE7SUFDdEMsTUFBTSxhQUFhLEdBQUcsS0FBSyxFQUFFLE1BQXFCLENBQUM7SUFFbkQsT0FBTyxhQUFhLEVBQUUsT0FBTyxLQUFLLE9BQU8sQ0FBQztBQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxNi0yMDIzIFZNd2FyZSwgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZS5cbiAqIFRoZSBmdWxsIGxpY2Vuc2UgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGluIExJQ0VOU0UgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgcHJvamVjdC5cbiAqL1xuXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgU2tpcFNlbGYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBDbHJDb21tb25TdHJpbmdzU2VydmljZSB9IGZyb20gJy4uLy4uL3V0aWxzL2kxOG4vY29tbW9uLXN0cmluZ3Muc2VydmljZSc7XG5pbXBvcnQgeyB1bmlxdWVJZEZhY3RvcnkgfSBmcm9tICcuLi8uLi91dGlscy9pZC1nZW5lcmF0b3IvaWQtZ2VuZXJhdG9yLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2xyU3RhY2tWaWV3TGFiZWwgfSBmcm9tICcuL3N0YWNrLXZpZXctY3VzdG9tLXRhZ3MnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjbHItc3RhY2stYmxvY2snLFxuICB0ZW1wbGF0ZTogYFxuICAgIDwhLS0gVGhlICdwcmV2ZW50RGVmYXVsdCcgZm9yIHRoZSBzcGFjZSBrZXlkb3duIGV2ZW50IHByZXZlbnRzIHRoZSBwYWdlXG4gICAgICAgICBmcm9tIHNjcm9sbGluZyB3aGVuIGEgc3RhY2sgYmxvY2sgaXMgdG9nZ2xlZCB2aWEgdGhlIHNwYWNlIGtleS4gLS0+XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJzdGFjay1ibG9jay1sYWJlbFwiXG4gICAgICAoY2xpY2spPVwidG9nZ2xlRXhwYW5kKCRldmVudClcIlxuICAgICAgKGtleXVwLmVudGVyKT1cInRvZ2dsZUV4cGFuZCgkZXZlbnQpXCJcbiAgICAgIChrZXl1cC5zcGFjZSk9XCJ0b2dnbGVFeHBhbmQoJGV2ZW50KVwiXG4gICAgICAoa2V5ZG93bi5zcGFjZSk9XCJwcmV2ZW50RGVmYXVsdElmTm90SW5wdXRFdmVudCgkZXZlbnQpXCJcbiAgICAgIChmb2N1cyk9XCJmb2N1c2VkID0gdHJ1ZVwiXG4gICAgICAoYmx1cik9XCJmb2N1c2VkID0gZmFsc2VcIlxuICAgICAgW2lkXT1cInVuaXF1ZUlkXCJcbiAgICAgIFthdHRyLnJvbGVdPVwicm9sZVwiXG4gICAgICBbYXR0ci50YWJpbmRleF09XCJ0YWJJbmRleFwiXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImFyaWFFeHBhbmRlZFwiXG4gICAgICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImdldFN0YWNrQ2hpbGRyZW5JZCgpXCJcbiAgICA+XG4gICAgICA8Y2RzLWljb24gc2hhcGU9XCJhbmdsZVwiIGNsYXNzPVwic3RhY2stYmxvY2stY2FyZXRcIiAqbmdJZj1cImV4cGFuZGFibGVcIiBbYXR0ci5kaXJlY3Rpb25dPVwiY2FyZXREaXJlY3Rpb25cIj48L2Nkcy1pY29uPlxuICAgICAgPHNwYW4gY2xhc3M9XCJjbHItc3Itb25seVwiICpuZ0lmPVwiZ2V0Q2hhbmdlZFZhbHVlXCI+e3sgY29tbW9uU3RyaW5ncy5rZXlzLnN0YWNrVmlld0NoYW5nZWQgfX08L3NwYW4+XG4gICAgICA8ZGl2IGNsYXNzPVwic3RhY2stdmlldy1rZXlcIj5cbiAgICAgICAgPCEtLSBUaGlzIHN0cnVjdHVyZSBjaGFuZ2VkIHRvIGZpeCAjMzU2NyBhbmQgdGhlIGExMXkgcmVxdWVzdCB3YXMgdG8gbW92ZSBhd2F5IGZyb20gZGwncyAtLT5cbiAgICAgICAgPCEtLSBJIGFkZGVkIHRoZSBrZXkgY2xhc3MgdG8gdXBkYXRlIGNzcyB0YXJnZXRzIGZvciB0aGUgb3JpZ2luYWwgY29tcG9uZW50IHN0eWxlIC0tPlxuICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJjbHItc3RhY2stbGFiZWxcIj48L25nLWNvbnRlbnQ+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzdGFjay1ibG9jay1jb250ZW50XCI+XG4gICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGNsci1leHBhbmRhYmxlLWFuaW1hdGlvbiBbY2xyRXhwYW5kVHJpZ2dlcl09XCJleHBhbmRlZFwiIGNsYXNzPVwic3RhY2stY2hpbGRyZW5cIj5cbiAgICAgIDxkaXZcbiAgICAgICAgW3N0eWxlLmhlaWdodF09XCJleHBhbmRlZCA/ICdhdXRvJyA6IDBcIlxuICAgICAgICByb2xlPVwicmVnaW9uXCJcbiAgICAgICAgKm5nSWY9XCJleHBhbmRlZFwiXG4gICAgICAgIFthdHRyLmlkXT1cImdldFN0YWNrQ2hpbGRyZW5JZCgpXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cImxhYmVsbGVkQnlJZFwiXG4gICAgICA+XG4gICAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cImNsci1zdGFjay1ibG9ja1wiPjwvbmctY29udGVudD5cbiAgICAgIDwvZGl2PlxuICAgIDwvY2xyLWV4cGFuZGFibGUtYW5pbWF0aW9uPlxuICBgLFxuICAvLyBDdXN0b20gZWxlbWVudHMgYXJlIGlubGluZSBieSBkZWZhdWx0XG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIDpob3N0IHtcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbiAgLy8gTWFrZSBzdXJlIHRoZSBob3N0IGhhcyB0aGUgcHJvcGVyIGNsYXNzIGZvciBzdHlsaW5nIHB1cnBvc2VzXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLnN0YWNrLWJsb2NrXSc6ICd0cnVlJyxcbiAgICAnW2F0dHIucm9sZV0nOiAnXCJoZWFkaW5nXCInLFxuICAgICdbYXR0ci5hcmlhLWxldmVsXSc6ICdoZWFkaW5nTGV2ZWwnLFxuICB9LFxufSlcbmV4cG9ydCBjbGFzcyBDbHJTdGFja0Jsb2NrIGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KCdjbHJTYkV4cGFuZGVkJykgQEhvc3RCaW5kaW5nKCdjbGFzcy5zdGFjay1ibG9jay1leHBhbmRlZCcpIGV4cGFuZGVkID0gZmFsc2U7XG4gIEBJbnB1dCgnY2xyU2JFeHBhbmRhYmxlJykgQEhvc3RCaW5kaW5nKCdjbGFzcy5zdGFjay1ibG9jay1leHBhbmRhYmxlJykgZXhwYW5kYWJsZSA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBEZXB0aCBvZiB0aGUgc3RhY2sgdmlldyBzdGFydGluZyBmcm9tIDEgZm9yIGZpcnN0IGxldmVsXG4gICAqL1xuICBASW5wdXQoJ2NsclN0YWNrVmlld0xldmVsJykgYXJpYUxldmVsOiBudW1iZXI7XG5cbiAgQE91dHB1dCgnY2xyU2JFeHBhbmRlZENoYW5nZScpIGV4cGFuZGVkQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPihmYWxzZSk7XG5cbiAgQENvbnRlbnRDaGlsZChDbHJTdGFja1ZpZXdMYWJlbCkgc3RhY2tCbG9ja1RpdGxlOiBhbnk7XG5cbiAgZm9jdXNlZCA9IGZhbHNlO1xuICB1bmlxdWVJZCA9IHVuaXF1ZUlkRmFjdG9yeSgpO1xuXG4gIHByaXZhdGUgX2NoYW5nZWRDaGlsZHJlbiA9IDA7XG4gIHByaXZhdGUgX2Z1bGx5SW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBfY2hhbmdlZCA9IGZhbHNlO1xuXG4gIC8qXG4gICAqIFRoaXMgd291bGQgYmUgbW9yZSBlZmZpY2llbnQgd2l0aCBAQ29udGVudENoaWxkcmVuLCB3aXRoIHRoZSBwYXJlbnQgQ2xyU3RhY2tCbG9ja1xuICAgKiBxdWVyeWluZyBmb3IgY2hpbGRyZW4gU3RhY2tCbG9ja3MsIGJ1dCB0aGlzIGZlYXR1cmUgaXMgbm90IGF2YWlsYWJsZSB3aGVuIGRvd25ncmFkaW5nXG4gICAqIHRoZSBjb21wb25lbnQgZm9yIEFuZ3VsYXIgMS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBTa2lwU2VsZigpXG4gICAgQE9wdGlvbmFsKClcbiAgICBwcml2YXRlIHBhcmVudDogQ2xyU3RhY2tCbG9jayxcbiAgICBwdWJsaWMgY29tbW9uU3RyaW5nczogQ2xyQ29tbW9uU3RyaW5nc1NlcnZpY2VcbiAgKSB7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgcGFyZW50LmFkZENoaWxkKCk7XG4gICAgfVxuICB9XG5cbiAgQElucHV0KCdjbHJTYk5vdGlmeUNoYW5nZScpXG4gIHNldCBzZXRDaGFuZ2VkVmFsdWUodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9jaGFuZ2VkID0gdmFsdWU7XG5cbiAgICBpZiAodGhpcy5wYXJlbnQgJiYgdGhpcy5fZnVsbHlJbml0aWFsaXplZCkge1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHRoaXMucGFyZW50Ll9jaGFuZ2VkQ2hpbGRyZW4rKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGFyZW50Ll9jaGFuZ2VkQ2hpbGRyZW4tLTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLnN0YWNrLWJsb2NrLWNoYW5nZWQnKVxuICBnZXQgZ2V0Q2hhbmdlZFZhbHVlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9jaGFuZ2VkIHx8ICh0aGlzLl9jaGFuZ2VkQ2hpbGRyZW4gPiAwICYmICF0aGlzLmV4cGFuZGVkKTtcbiAgfVxuXG4gIEBIb3N0QmluZGluZygnY2xhc3Mub24tZm9jdXMnKVxuICBnZXQgb25TdGFja0xhYmVsRm9jdXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZXhwYW5kYWJsZSAmJiAhdGhpcy5leHBhbmRlZCAmJiB0aGlzLmZvY3VzZWQ7XG4gIH1cblxuICBnZXQgbGFiZWxsZWRCeUlkKCkge1xuICAgIHJldHVybiB0aGlzLnN0YWNrQmxvY2tUaXRsZS5pZDtcbiAgfVxuXG4gIGdldCBoZWFkaW5nTGV2ZWwoKSB7XG4gICAgaWYgKHRoaXMuYXJpYUxldmVsKSB7XG4gICAgICByZXR1cm4gdGhpcy5hcmlhTGV2ZWwgKyAnJztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wYXJlbnQgPyAnNCcgOiAnMyc7XG4gIH1cblxuICBnZXQgY2FyZXREaXJlY3Rpb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5leHBhbmRlZCA/ICdkb3duJyA6ICdyaWdodCc7XG4gIH1cblxuICBnZXQgcm9sZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmV4cGFuZGFibGUgPyAnYnV0dG9uJyA6IG51bGw7XG4gIH1cblxuICBnZXQgdGFiSW5kZXgoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5leHBhbmRhYmxlID8gJzAnIDogbnVsbDtcbiAgfVxuXG4gIGdldCBhcmlhRXhwYW5kZWQoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuZXhwYW5kYWJsZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmV4cGFuZGVkID8gJ3RydWUnIDogJ2ZhbHNlJztcbiAgICB9XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBpbiBvcmRlciB0byBhY2Nlc3MgdGhlIHBhcmVudCBDbHJTdGFja0Jsb2NrJ3MgcHJvcGVydGllcyxcbiAgICAvLyB0aGUgY2hpbGQgQ2xyU3RhY2tCbG9jayBoYXMgdG8gYmUgZnVsbHkgaW5pdGlhbGl6ZWQgYXQgZmlyc3QuXG4gICAgdGhpcy5fZnVsbHlJbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICBhZGRDaGlsZCgpOiB2b2lkIHtcbiAgICB0aGlzLmV4cGFuZGFibGUgPSB0cnVlO1xuICB9XG5cbiAgdG9nZ2xlRXhwYW5kKGV2ZW50PzogRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoZXZlbnRJc0lucHV0RXZlbnQoZXZlbnQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXhwYW5kYWJsZSkge1xuICAgICAgdGhpcy5leHBhbmRlZCA9ICF0aGlzLmV4cGFuZGVkO1xuICAgICAgdGhpcy5leHBhbmRlZENoYW5nZS5lbWl0KHRoaXMuZXhwYW5kZWQpO1xuICAgIH1cbiAgfVxuXG4gIGdldFN0YWNrQ2hpbGRyZW5JZCgpIHtcbiAgICByZXR1cm4gdGhpcy5leHBhbmRlZCA/IGBjbHItc3RhY2stY2hpbGRyZW4tJHt0aGlzLnVuaXF1ZUlkfWAgOiBudWxsO1xuICB9XG5cbiAgcHJvdGVjdGVkIHByZXZlbnREZWZhdWx0SWZOb3RJbnB1dEV2ZW50KGV2ZW50OiBFdmVudCkge1xuICAgIGlmIChldmVudElzSW5wdXRFdmVudChldmVudCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGV2ZW50SXNJbnB1dEV2ZW50KGV2ZW50PzogRXZlbnQpIHtcbiAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IGV2ZW50Py50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgcmV0dXJuIHRhcmdldEVsZW1lbnQ/LnRhZ05hbWUgPT09ICdJTlBVVCc7XG59XG4iXX0=