UNPKG

@edugouvfr/ngx-dsfr-ext

Version:

NgxDsfrExt est une extension au package @edugouvfr/ngx-dsfr (portage Angular des éléments DSFR)

199 lines 32 kB
import { ScrollingModule } from '@angular/cdk/scrolling'; import { CommonModule } from '@angular/common'; import { afterNextRender, Component, ContentChild, EventEmitter, inject, Input, Output, Renderer2, ViewChild, ViewEncapsulation, } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { EduClickOutsideDirective } from '../../directives'; import { DsfrDropdownPositionDirective } from './dropdown-position.directive'; import { DropdownUtils } from './dropdown.utils'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class DropdownContainerComponent { constructor() { /** Activer le virtual scroll */ this.virtualScroll = false; /** Surcharger la hauteur d'un item dans le cas du virtual scroll. Par défaut 24px. */ this.virtualScrollItemHeight = 24; this.hasOptions = false; /** Hauteur maximale avant le scroll sur la liste déroulante. */ this.scrollHeight = '224px'; this.classToWrap = 'dsfrx-multiselect'; this.hasToolBar = false; /** Set focus on list on opening */ this.autofocus = false; /** La dropdown prend la taille des éléments qu'il contient (par défaut : taille du select) */ this.autoWidthDropdown = false; this.hideList = new EventEmitter(); this.focusOnList = new EventEmitter(); this.dropdownAttached = new EventEmitter(); // la box est append et positionnée this._displayDropdown = false; this._renderer = inject(Renderer2); // Recherche du container parent apres initialisation complete du DOM (= afterViewInit non suffisant) afterNextRender(() => { if (this.appendTo && this.comboBoxElement) { this.containerToAttach = DropdownUtils.setParentContainer(this.appendTo, this.comboBoxElement); } }); } get displayDropdown() { return this._displayDropdown; } /* Element auquel attacher visuellement le container de la dropdown (ex. la box contenant le fr-select) */ get comboBoxElement() { return this.comboBox.nativeElement; } set displayDropdown(value) { this._displayDropdown = value; if (!this.displayDropdown && this.comboBox && this.autofocus) { this.comboBox.nativeElement?.querySelector('.fr-select')?.focus(); } } /** * Fermer la liste déroulante en cas de clic en dehors du composant et detruire le composant si il a été ajouté en appendTo * @internal */ onClickOutside() { this.hideList.emit(); } /** La dropdown est visible et positionnée */ onDropdownAttached() { this.dropdownAttached.emit(); this.setFocus(); } /** * Positionne le focus sur la toolbar si elle existe ou un élément de la liste à l'ouverture de la dropdown * @internal */ setFocus() { if (!this.autofocus) return; if (this.hasToolBar && !this._toolBarFirstElement) { const elem = this.toolbarWrapper.nativeElement.querySelector('.fr-btn--select-all'); this._toolBarFirstElement = elem ? elem : this.toolbarWrapper.nativeElement.querySelector('.fr-input'); } if (this.listbox && !this.hasToolBar) { this.focusOnListElement(); } else if (this._toolBarFirstElement) { this._toolBarFirstElement.focus(); } } /** * Gestion des événements clavier sur la toolbar * - "flèche bas" : le focus est positionné sur la liste. * - "TAB" : si dernier élément focusable de la toolbar, fermer la dropdown et aller sur l'element suivant * - "SHIFT TAB": si premier élément focusable de la toolbar, fermer la dropdown et aller sur l'element suivant * - "ECHAP" : fermer la dropdown et conserver le focus sur le select */ onKeyDownToolbar(event) { switch (event.key) { case 'ArrowDown': if (this.listbox) { event.preventDefault(); this.focusOnListElement(); } break; case 'Tab': if ((event.shiftKey && event.target == this._toolBarFirstElement) || (!event.shiftKey && this.isLastFocusableOnToolBar(event.target, this.toolbarWrapper.nativeElement))) { this.hideList.emit(); } break; case 'Escape': event.preventDefault(); this.comboBoxElement.querySelector('.fr-select')?.focus(); this.hideList.emit(); break; } } /** * Positionne le focus sur un élément de la liste lors de l'ouverture ou après "flèche bas" depuis le champ de recherche. * - Si un élément est déjà sélectionné, le focus est positionné sur celui-ci. * - Sinon, le focus est placé sur le premier élément de la liste. */ focusOnListElement() { // en virtualScroll le premier container est cdk-virtualscroll const listboxNode = this.virtualScroll ? this.listbox.nativeElement?.querySelector('ul') : this.listbox.nativeElement; let elementToFocus = listboxNode?.firstElementChild; if (this.indexFirstSelected && this.indexFirstSelected !== -1) { elementToFocus = listboxNode?.children[this.indexFirstSelected] ?? listboxNode?.firstElementChild; } if (elementToFocus) { this.setAriaActiveDescendant(listboxNode, elementToFocus.getAttribute('id')); elementToFocus.focus(); this.focusOnList.emit(elementToFocus); } } /** * cas TAB : L'élément est le dernier élément focusable de la toolbar : * - l'élément est la croix pour vider la recherche * - l'élément est la barre de recherche et la croix n'est pas présente * - la barre de recherche n'est pas présente (un seul élément focusable : tout sélectionner) */ isLastFocusableOnToolBar(element, toolBarWrapper) { return (element.className.includes('fr-icon-close-line') || (!toolBarWrapper.querySelector('.fr-icon-close-line') && element.className.includes('fr-input')) || !toolBarWrapper.querySelector('.fr-input')); } /** * Attribut aria-activedescendant sur l'input égal à l'option qui a le focus * @internal */ setAriaActiveDescendant(listboxNode, optionId) { if (optionId) { this._renderer.setAttribute(listboxNode, 'aria-activedescendant', optionId); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DropdownContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DropdownContainerComponent, isStandalone: true, selector: "edu-dropdown-container", inputs: { virtualScroll: "virtualScroll", virtualScrollItemHeight: "virtualScrollItemHeight", appendTo: "appendTo", hasOptions: "hasOptions", zIndex: "zIndex", scrollHeight: "scrollHeight", classToWrap: "classToWrap", hasToolBar: "hasToolBar", indexFirstSelected: "indexFirstSelected", autofocus: "autofocus", autoWidthDropdown: "autoWidthDropdown", displayDropdown: "displayDropdown" }, outputs: { hideList: "hideList", focusOnList: "focusOnList", dropdownAttached: "dropdownAttached" }, queries: [{ propertyName: "listbox", first: true, predicate: ["listbox"], descendants: true }], viewQueries: [{ propertyName: "comboBox", first: true, predicate: ["combobox"], descendants: true }, { propertyName: "toolbarWrapper", first: true, predicate: ["toolbarWrapper"], descendants: true }], ngImport: i0, template: "<div\n #combobox\n [attr.data-expanded]=\"displayDropdown ? displayDropdown : null\"\n clickOutside\n class=\"{{ classToWrap }}\"\n (clickOutsideEvent)=\"onClickOutside()\">\n <ng-content select=\"control\"></ng-content>\n\n @if (displayDropdown) {\n <div\n #dropdown\n dsfrxDropdown\n (appendDropdown)=\"onDropdownAttached()\"\n [comboBox]=\"comboBoxElement\"\n [parentContainer]=\"containerToAttach\"\n [autoWidth]=\"autoWidthDropdown\"\n [ngClass]=\"{ 'dsfrx-dropdown--auto-width': autoWidthDropdown }\"\n class=\"dsfrx-dropdown {{ classToWrap ? classToWrap + '__wrapper' : '' }} \"\n [ngStyle]=\"{ 'z-index': zIndex }\">\n @if (hasToolBar) {\n <div #toolbarWrapper (keydown)=\"onKeyDownToolbar($event)\" class=\"{{ classToWrap }}__toolbar\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </div>\n }\n <ng-content select=\"empty\"> </ng-content>\n <ng-content></ng-content>\n </div>\n }\n</div>\n", styles: [".dsfrx-dropdown{position:absolute;left:auto;top:auto;width:100%;z-index:2001;container-type:inline-size;background-color:var(--background-overlap-grey);filter:drop-shadow(var(--overlap-shadow))}.dsfrx-dropdown--auto-width{min-width:fit-content;container-type:initial;width:auto}.dsfrx-multiselect{display:block;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: EduClickOutsideDirective, selector: "[clickOutside]", outputs: ["clickOutsideEvent"] }, { kind: "directive", type: DsfrDropdownPositionDirective, selector: "[dsfrxDropdown]", inputs: ["autoWidth", "parentContainer", "comboBox"], outputs: ["appendDropdown"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DropdownContainerComponent, decorators: [{ type: Component, args: [{ selector: 'edu-dropdown-container', encapsulation: ViewEncapsulation.None, standalone: true, imports: [ CommonModule, FormsModule, ReactiveFormsModule, ScrollingModule, EduClickOutsideDirective, DsfrDropdownPositionDirective, ], template: "<div\n #combobox\n [attr.data-expanded]=\"displayDropdown ? displayDropdown : null\"\n clickOutside\n class=\"{{ classToWrap }}\"\n (clickOutsideEvent)=\"onClickOutside()\">\n <ng-content select=\"control\"></ng-content>\n\n @if (displayDropdown) {\n <div\n #dropdown\n dsfrxDropdown\n (appendDropdown)=\"onDropdownAttached()\"\n [comboBox]=\"comboBoxElement\"\n [parentContainer]=\"containerToAttach\"\n [autoWidth]=\"autoWidthDropdown\"\n [ngClass]=\"{ 'dsfrx-dropdown--auto-width': autoWidthDropdown }\"\n class=\"dsfrx-dropdown {{ classToWrap ? classToWrap + '__wrapper' : '' }} \"\n [ngStyle]=\"{ 'z-index': zIndex }\">\n @if (hasToolBar) {\n <div #toolbarWrapper (keydown)=\"onKeyDownToolbar($event)\" class=\"{{ classToWrap }}__toolbar\">\n <ng-content select=\"[toolbar]\"></ng-content>\n </div>\n }\n <ng-content select=\"empty\"> </ng-content>\n <ng-content></ng-content>\n </div>\n }\n</div>\n", styles: [".dsfrx-dropdown{position:absolute;left:auto;top:auto;width:100%;z-index:2001;container-type:inline-size;background-color:var(--background-overlap-grey);filter:drop-shadow(var(--overlap-shadow))}.dsfrx-dropdown--auto-width{min-width:fit-content;container-type:initial;width:auto}.dsfrx-multiselect{display:block;position:relative}\n"] }] }], ctorParameters: () => [], propDecorators: { comboBox: [{ type: ViewChild, args: ['combobox'] }], toolbarWrapper: [{ type: ViewChild, args: ['toolbarWrapper'] }], listbox: [{ type: ContentChild, args: ['listbox'] }], virtualScroll: [{ type: Input }], virtualScrollItemHeight: [{ type: Input }], appendTo: [{ type: Input }], hasOptions: [{ type: Input }], zIndex: [{ type: Input }], scrollHeight: [{ type: Input }], classToWrap: [{ type: Input }], hasToolBar: [{ type: Input }], indexFirstSelected: [{ type: Input }], autofocus: [{ type: Input }], autoWidthDropdown: [{ type: Input }], hideList: [{ type: Output }], focusOnList: [{ type: Output }], dropdownAttached: [{ type: Output }], displayDropdown: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tY29udGFpbmVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWV4dC9zcmMvbGliL3NoYXJlZC9jb21wb25lbnRzL2Ryb3Bkb3duLWNvbnRhaW5lci9kcm9wZG93bi1jb250YWluZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItZXh0L3NyYy9saWIvc2hhcmVkL2NvbXBvbmVudHMvZHJvcGRvd24tY29udGFpbmVyL2Ryb3Bkb3duLWNvbnRhaW5lci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFDTCxlQUFlLEVBQ2YsU0FBUyxFQUNULFlBQVksRUFFWixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsRUFDVCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzlFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7O0FBaUJqRCxNQUFNLE9BQU8sMEJBQTBCO0lBK0NyQztRQXpDQSxpQ0FBaUM7UUFDeEIsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFFeEMsc0ZBQXNGO1FBQzdFLDRCQUF1QixHQUFXLEVBQUUsQ0FBQztRQUtyQyxlQUFVLEdBQVksS0FBSyxDQUFDO1FB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QUFpQixDQUFDLElBQUksY0FDekIsSUFBSSxXQUVQO3dCQUNQLFlBQVk7d0JBQ1osV0FBVzt3QkFDWCxtQkFBbUI7d0JBQ25CLGVBQWU7d0JBQ2Ysd0JBQXdCO3dCQUN4Qiw2QkFBNkI7cUJBQzlCO3dEQUdzQixRQUFRO3NCQUE5QixTQUFTO3VCQUFDLFVBQVU7Z0JBQ1EsY0FBYztzQkFBMUMsU0FBUzt1QkFBQyxnQkFBZ0I7Z0JBRUYsT0FBTztzQkFBL0IsWUFBWTt1QkFBQyxTQUFTO2dCQUdkLGFBQWE7c0JBQXJCLEtBQUs7Z0JBR0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUdHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFHRyxNQUFNO3NCQUFkLEtBQUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUdHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVJLFFBQVE7c0JBQWpCLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxnQkFBZ0I7c0JBQXpCLE1BQU07Z0JBNkJILGVBQWU7c0JBRGxCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTY3JvbGxpbmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBhZnRlck5leHRSZW5kZXIsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgUmVuZGVyZXIyLFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgRWR1Q2xpY2tPdXRzaWRlRGlyZWN0aXZlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcyc7XG5pbXBvcnQgeyBEc2ZyRHJvcGRvd25Qb3NpdGlvbkRpcmVjdGl2ZSB9IGZyb20gJy4vZHJvcGRvd24tcG9zaXRpb24uZGlyZWN0aXZlJztcbmltcG9ydCB7IERyb3Bkb3duVXRpbHMgfSBmcm9tICcuL2Ryb3Bkb3duLnV0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZWR1LWRyb3Bkb3duLWNvbnRhaW5lcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9kcm9wZG93bi1jb250YWluZXIuY29tcG9uZW50Lmh0bWwnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBzdHlsZVVybHM6IFsnLi9kcm9wZG93bi1jb250YWluZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFNjcm9sbGluZ01vZHVsZSxcbiAgICBFZHVDbGlja091dHNpZGVEaXJlY3RpdmUsXG4gICAgRHNmckRyb3Bkb3duUG9zaXRpb25EaXJlY3RpdmUsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIERyb3Bkb3duQ29udGFpbmVyQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgnY29tYm9ib3gnKSBjb21ib0JveDogRWxlbWVudFJlZjtcbiAgQFZpZXdDaGlsZCgndG9vbGJhcldyYXBwZXInKSB0b29sYmFyV3JhcHBlcjogRWxlbWVudFJlZjtcblxuICBAQ29udGVudENoaWxkKCdsaXN0Ym94JykgbGlzdGJveDogRWxlbWVudFJlZjtcblxuICAvKiogQWN0aXZlciBsZSB2aXJ0dWFsIHNjcm9sbCAgKi9cbiAgQElucHV0KCkgdmlydHVhbFNjcm9sbDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBTdXJjaGFyZ2VyIGxhIGhhdXRldXIgZCd1biBpdGVtIGRhbnMgbGUgY2FzIGR1IHZpcnR1YWwgc2Nyb2xsLiBQYXIgZMOpZmF1dCAyNHB4LiAqL1xuICBASW5wdXQoKSB2aXJ0dWFsU2Nyb2xsSXRlbUhlaWdodDogbnVtYmVyID0gMjQ7XG5cbiAgLyoqIEF0dGFjaGVyIGwnw6lsw6ltZW50IGRlIGxpc3RlIGTDqXJvdWxhbnRlIGF1ICdib2R5JyBvdSBhIHVuIGNvbnRhaW5lciAocsOpZi4gdmVycyB1biDDqWzDqW1lbnQgI2RpdiBvdSBub20gZGUgbGEgY2xhc3NlIGR1IHBhcmVudCkgKi9cbiAgQElucHV0KCkgYXBwZW5kVG86ICdib2R5JyB8IEhUTUxFbGVtZW50IHwgc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIEBJbnB1dCgpIGhhc09wdGlvbnM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogUHJvcHJpw6l0w6kgQ1NTIHotaW5kZXggZGUgbGEgbGlzdGUsIHBhciBkw6lmYXV0IHN1cMOpcmlldXIgYXV4IGNvbXBvc2FudHMgJ2xpZnRlZCcgRFNGUiAqL1xuICBASW5wdXQoKSB6SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuICAvKiogSGF1dGV1ciBtYXhpbWFsZSBhdmFudCBsZSBzY3JvbGwgc3VyIGxhIGxpc3RlIGTDqXJvdWxhbnRlLiAqL1xuICBASW5wdXQoKSBzY3JvbGxIZWlnaHQ6IHN0cmluZyA9ICcyMjRweCc7XG5cbiAgQElucHV0KCkgY2xhc3NUb1dyYXA6IHN0cmluZyA9ICdkc2ZyeC1tdWx0aXNlbGVjdCc7XG5cbiAgQElucHV0KCkgaGFzVG9vbEJhcjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGluZGV4Rmlyc3RTZWxlY3RlZDogbnVtYmVyIHwgbnVsbDtcblxuICAvKiogU2V0IGZvY3VzIG9uIGxpc3Qgb24gb3BlbmluZyAqL1xuICBASW5wdXQoKSBhdXRvZm9jdXM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogTGEgZHJvcGRvd24gcHJlbmQgbGEgdGFpbGxlIGRlcyDDqWzDqW1lbnRzIHF1J2lsIGNvbnRpZW50IChwYXIgZMOpZmF1dCA6IHRhaWxsZSBkdSBzZWxlY3QpICovXG4gIEBJbnB1dCgpIGF1dG9XaWR0aERyb3Bkb3duOiBib29sZWFuID0gZmFsc2U7XG5cbiAgQE91dHB1dCgpIGhpZGVMaXN0OiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBmb2N1c09uTGlzdDogRXZlbnRFbWl0dGVyPEhUTUxFbGVtZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGRyb3Bkb3duQXR0YWNoZWQ6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTsgLy8gbGEgYm94IGVzdCBhcHBlbmQgZXQgcG9zaXRpb25uw6llXG5cbiAgLyoqIEVsZW1lbnQgYXVxdWVsIGxhIGxpc3RlIGVzdCBhdHRhY2jDqWUgcHJvZ3JhbW1hdGlxdWVtZW50IHNpIGFwcGVuZFRvIGTDqWZpbmkgKi9cbiAgcHJvdGVjdGVkIGNvbnRhaW5lclRvQXR0YWNoOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIF90b29sQmFyRmlyc3RFbGVtZW50OiBIVE1MRWxlbWVudDsgLy8gZmlyc3QgZm9jdXNhYmxlIGVsZW1lbnQgb24gdG9vbGJhclxuICBwcml2YXRlIF9kaXNwbGF5RHJvcGRvd246IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJlciA9IGluamVjdChSZW5kZXJlcjIpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIFJlY2hlcmNoZSBkdSBjb250YWluZXIgcGFyZW50IGFwcmVzIGluaXRpYWxpc2F0aW9uIGNvbXBsZXRlIGR1IERPTSAoPSBhZnRlclZpZXdJbml0IG5vbiBzdWZmaXNhbnQpXG4gICAgYWZ0ZXJOZXh0UmVuZGVyKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmFwcGVuZFRvICYmIHRoaXMuY29tYm9Cb3hFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyVG9BdHRhY2ggPSBEcm9wZG93blV0aWxzLnNldFBhcmVudENvbnRhaW5lcih0aGlzLmFwcGVuZFRvLCB0aGlzLmNvbWJvQm94RWxlbWVudCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBnZXQgZGlzcGxheURyb3Bkb3duKCkge1xuICAgIHJldHVybiB0aGlzLl9kaXNwbGF5RHJvcGRvd247XG4gIH1cblxuICAvKiBFbGVtZW50IGF1cXVlbCBhdHRhY2hlciB2aXN1ZWxsZW1lbnQgbGUgY29udGFpbmVyIGRlIGxhIGRyb3Bkb3duIChleC4gbGEgYm94IGNvbnRlbmFudCBsZSBmci1zZWxlY3QpICovXG4gIGdldCBjb21ib0JveEVsZW1lbnQoKTogSFRNTEVsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmNvbWJvQm94Lm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBASW5wdXQoKVxuICBzZXQgZGlzcGxheURyb3Bkb3duKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fZGlzcGxheURyb3Bkb3duID0gdmFsdWU7XG4gICAgaWYgKCF0aGlzLmRpc3BsYXlEcm9wZG93biAmJiB0aGlzLmNvbWJvQm94ICYmIHRoaXMuYXV0b2ZvY3VzKSB7XG4gICAgICB0aGlzLmNvbWJvQm94Lm5hdGl2ZUVsZW1lbnQ/LnF1ZXJ5U2VsZWN0b3IoJy5mci1zZWxlY3QnKT8uZm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmVybWVyIGxhIGxpc3RlIGTDqXJvdWxhbnRlIGVuIGNhcyBkZSBjbGljIGVuIGRlaG9ycyBkdSBjb21wb3NhbnQgZXQgZGV0cnVpcmUgbGUgY29tcG9zYW50IHNpIGlsIGEgw6l0w6kgYWpvdXTDqSBlbiBhcHBlbmRUb1xuICAgKiAgQGludGVybmFsICovXG4gIHB1YmxpYyBvbkNsaWNrT3V0c2lkZSgpOiB2b2lkIHtcbiAgICB0aGlzLmhpZGVMaXN0LmVtaXQoKTtcbiAgfVxuXG4gIC8qKiBMYSBkcm9wZG93biBlc3QgdmlzaWJsZSBldCBwb3NpdGlvbm7DqWUgKi9cbiAgcHVibGljIG9uRHJvcGRvd25BdHRhY2hlZCgpOiB2b2lkIHtcbiAgICB0aGlzLmRyb3Bkb3duQXR0YWNoZWQuZW1pdCgpO1xuICAgIHRoaXMuc2V0Rm9jdXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3NpdGlvbm5lIGxlIGZvY3VzIHN1ciBsYSB0b29sYmFyIHNpIGVsbGUgZXhpc3RlIG91IHVuIMOpbMOpbWVudCBkZSBsYSBsaXN0ZSDDoCBsJ291dmVydHVyZSBkZSBsYSBkcm9wZG93blxuICAgKiBAaW50ZXJuYWwgKi9cbiAgcHVibGljIHNldEZvY3VzKCkge1xuICAgIGlmICghdGhpcy5hdXRvZm9jdXMpIHJldHVybjtcblxuICAgIGlmICh0aGlzLmhhc1Rvb2xCYXIgJiYgIXRoaXMuX3Rvb2xCYXJGaXJzdEVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IGVsZW0gPSB0aGlzLnRvb2xiYXJXcmFwcGVyLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLmZyLWJ0bi0tc2VsZWN0LWFsbCcpO1xuICAgICAgdGhpcy5fdG9vbEJhckZpcnN0RWxlbWVudCA9IGVsZW0gPyBlbGVtIDogdGhpcy50b29sYmFyV3JhcHBlci5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5mci1pbnB1dCcpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmxpc3Rib3ggJiYgIXRoaXMuaGFzVG9vbEJhcikge1xuICAgICAgdGhpcy5mb2N1c09uTGlzdEVsZW1lbnQoKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuX3Rvb2xCYXJGaXJzdEVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3Rvb2xCYXJGaXJzdEVsZW1lbnQuZm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2VzdGlvbiBkZXMgw6l2w6luZW1lbnRzIGNsYXZpZXIgc3VyIGxhIHRvb2xiYXJcbiAgICogLSBcImZsw6hjaGUgYmFzXCIgOiBsZSBmb2N1cyBlc3QgcG9zaXRpb25uw6kgc3VyIGxhIGxpc3RlLlxuICAgKiAtIFwiVEFCXCIgOiBzaSBkZXJuaWVyIMOpbMOpbWVudCBmb2N1c2FibGUgZGUgbGEgdG9vbGJhciwgZmVybWVyIGxhIGRyb3Bkb3duIGV0IGFsbGVyIHN1ciBsJ2VsZW1lbnQgc3VpdmFudFxuICAgKiAtIFwiU0hJRlQgVEFCXCI6IHNpIHByZW1pZXIgw6lsw6ltZW50IGZvY3VzYWJsZSBkZSBsYSB0b29sYmFyLCBmZXJtZXIgbGEgZHJvcGRvd24gIGV0IGFsbGVyIHN1ciBsJ2VsZW1lbnQgc3VpdmFudFxuICAgKiAtIFwiRUNIQVBcIiA6IGZlcm1lciBsYSBkcm9wZG93biBldCBjb25zZXJ2ZXIgbGUgZm9jdXMgc3VyIGxlIHNlbGVjdFxuICAgKi9cbiAgcHJvdGVjdGVkIG9uS2V5RG93blRvb2xiYXIoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgY2FzZSAnQXJyb3dEb3duJzpcbiAgICAgICAgaWYgKHRoaXMubGlzdGJveCkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgdGhpcy5mb2N1c09uTGlzdEVsZW1lbnQoKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnVGFiJzpcbiAgICAgICAgaWYgKFxuICAgICAgICAgIChldmVudC5zaGlmdEtleSAmJiBldmVudC50YXJnZXQgPT0gdGhpcy5fdG9vbEJhckZpcnN0RWxlbWVudCkgfHxcbiAgICAgICAgICAoIWV2ZW50LnNoaWZ0S2V5ICYmXG4gICAgICAgICAgICB0aGlzLmlzTGFzdEZvY3VzYWJsZU9uVG9vbEJhcihldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQsIHRoaXMudG9vbGJhcldyYXBwZXIubmF0aXZlRWxlbWVudCkpXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMuaGlkZUxpc3QuZW1pdCgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdFc2NhcGUnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAodGhpcy5jb21ib0JveEVsZW1lbnQucXVlcnlTZWxlY3RvcignLmZyLXNlbGVjdCcpIGFzIEhUTUxFbGVtZW50KT8uZm9jdXMoKTtcbiAgICAgICAgdGhpcy5oaWRlTGlzdC5lbWl0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQb3NpdGlvbm5lIGxlIGZvY3VzIHN1ciB1biDDqWzDqW1lbnQgZGUgbGEgbGlzdGUgbG9ycyBkZSBsJ291dmVydHVyZSBvdSBhcHLDqHMgXCJmbMOoY2hlIGJhc1wiIGRlcHVpcyBsZSBjaGFtcCBkZSByZWNoZXJjaGUuXG4gICAqIC0gU2kgdW4gw6lsw6ltZW50IGVzdCBkw6lqw6Agc8OpbGVjdGlvbm7DqSwgbGUgZm9jdXMgZXN0IHBvc2l0aW9ubsOpIHN1ciBjZWx1aS1jaS5cbiAgICogLSBTaW5vbiwgbGUgZm9jdXMgZXN0IHBsYWPDqSBzdXIgbGUgcHJlbWllciDDqWzDqW1lbnQgZGUgbGEgbGlzdGUuXG4gICAqL1xuICBwcml2YXRlIGZvY3VzT25MaXN0RWxlbWVudCgpIHtcbiAgICAvLyBlbiB2aXJ0dWFsU2Nyb2xsIGxlIHByZW1pZXIgY29udGFpbmVyIGVzdCBjZGstdmlydHVhbHNjcm9sbFxuICAgIGNvbnN0IGxpc3Rib3hOb2RlID0gdGhpcy52aXJ0dWFsU2Nyb2xsXG4gICAgICA/IHRoaXMubGlzdGJveC5uYXRpdmVFbGVtZW50Py5xdWVyeVNlbGVjdG9yKCd1bCcpXG4gICAgICA6IHRoaXMubGlzdGJveC5uYXRpdmVFbGVtZW50O1xuXG4gICAgbGV0IGVsZW1lbnRUb0ZvY3VzOiBIVE1MRWxlbWVudCA9IGxpc3Rib3hOb2RlPy5maXJzdEVsZW1lbnRDaGlsZDtcblxuICAgIGlmICh0aGlzLmluZGV4Rmlyc3RTZWxlY3RlZCAmJiB0aGlzLmluZGV4Rmlyc3RTZWxlY3RlZCAhPT0gLTEpIHtcbiAgICAgIGVsZW1lbnRUb0ZvY3VzID0gbGlzdGJveE5vZGU/LmNoaWxkcmVuW3RoaXMuaW5kZXhGaXJzdFNlbGVjdGVkXSA/PyBsaXN0Ym94Tm9kZT8uZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgfVxuXG4gICAgaWYgKGVsZW1lbnRUb0ZvY3VzKSB7XG4gICAgICB0aGlzLnNldEFyaWFBY3RpdmVEZXNjZW5kYW50KGxpc3Rib3hOb2RlLCBlbGVtZW50VG9Gb2N1cy5nZXRBdHRyaWJ1dGUoJ2lkJykpO1xuICAgICAgZWxlbWVudFRvRm9jdXMuZm9jdXMoKTtcbiAgICAgIHRoaXMuZm9jdXNPbkxpc3QuZW1pdChlbGVtZW50VG9Gb2N1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGNhcyBUQUIgOiBMJ8OpbMOpbWVudCBlc3QgbGUgZGVybmllciDDqWzDqW1lbnQgZm9jdXNhYmxlIGRlIGxhIHRvb2xiYXIgOlxuICAgKiAtIGwnw6lsw6ltZW50IGVzdCBsYSBjcm9peCBwb3VyIHZpZGVyIGxhIHJlY2hlcmNoZVxuICAgKiAtIGwnw6lsw6ltZW50IGVzdCBsYSBiYXJyZSBkZSByZWNoZXJjaGUgZXQgbGEgY3JvaXggbidlc3QgcGFzIHByw6lzZW50ZVxuICAgKiAtIGxhIGJhcnJlIGRlIHJlY2hlcmNoZSBuJ2VzdCBwYXMgcHLDqXNlbnRlICh1biBzZXVsIMOpbMOpbWVudCBmb2N1c2FibGUgOiB0b3V0IHPDqWxlY3Rpb25uZXIpXG4gICAqL1xuICBwcml2YXRlIGlzTGFzdEZvY3VzYWJsZU9uVG9vbEJhcihlbGVtZW50OiBIVE1MRWxlbWVudCwgdG9vbEJhcldyYXBwZXI6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGVsZW1lbnQuY2xhc3NOYW1lLmluY2x1ZGVzKCdmci1pY29uLWNsb3NlLWxpbmUnKSB8fFxuICAgICAgKCF0b29sQmFyV3JhcHBlci5xdWVyeVNlbGVjdG9yKCcuZnItaWNvbi1jbG9zZS1saW5lJykgJiYgZWxlbWVudC5jbGFzc05hbWUuaW5jbHVkZXMoJ2ZyLWlucHV0JykpIHx8XG4gICAgICAhdG9vbEJhcldyYXBwZXIucXVlcnlTZWxlY3RvcignLmZyLWlucHV0JylcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dHJpYnV0IGFyaWEtYWN0aXZlZGVzY2VuZGFudCBzdXIgbCdpbnB1dCDDqWdhbCDDoCBsJ29wdGlvbiBxdWkgYSBsZSBmb2N1c1xuICAgKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBzZXRBcmlhQWN0aXZlRGVzY2VuZGFudChsaXN0Ym94Tm9kZTogSFRNTEVsZW1lbnQsIG9wdGlvbklkOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgaWYgKG9wdGlvbklkKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5zZXRBdHRyaWJ1dGUobGlzdGJveE5vZGUsICdhcmlhLWFjdGl2ZWRlc2NlbmRhbnQnLCBvcHRpb25JZCk7XG4gICAgfVxuICB9XG59XG4iLCI8ZGl2XG4gICNjb21ib2JveFxuICBbYXR0ci5kYXRhLWV4cGFuZGVkXT1cImRpc3BsYXlEcm9wZG93biA/IGRpc3BsYXlEcm9wZG93biA6IG51bGxcIlxuICBjbGlja091dHNpZGVcbiAgY2xhc3M9XCJ7eyBjbGFzc1RvV3JhcCB9fVwiXG4gIChjbGlja091dHNpZGVFdmVudCk9XCJvbkNsaWNrT3V0c2lkZSgpXCI+XG4gIDxuZy1jb250ZW50IHNlbGVjdD1cImNvbnRyb2xcIj48L25nLWNvbnRlbnQ+XG5cbiAgQGlmIChkaXNwbGF5RHJvcGRvd24pIHtcbiAgICA8ZGl2XG4gICAgICAjZHJvcGRvd25cbiAgICAgIGRzZnJ4RHJvcGRvd25cbiAgICAgIChhcHBlbmREcm9wZG93bik9XCJvbkRyb3Bkb3duQXR0YWNoZWQoKVwiXG4gICAgICBbY29tYm9Cb3hdPVwiY29tYm9Cb3hFbGVtZW50XCJcbiAgICAgIFtwYXJlbnRDb250YWluZXJdPVwiY29udGFpbmVyVG9BdHRhY2hcIlxuICAgICAgW2F1dG9XaWR0aF09XCJhdXRvV2lkdGhEcm9wZG93blwiXG4gICAgICBbbmdDbGFzc109XCJ7ICdkc2ZyeC1kcm9wZG93bi0tYXV0by13aWR0aCc6IGF1dG9XaWR0aERyb3Bkb3duIH1cIlxuICAgICAgY2xhc3M9XCJkc2ZyeC1kcm9wZG93biB7eyBjbGFzc1RvV3JhcCA/IGNsYXNzVG9XcmFwICsgJ19fd3JhcHBlcicgOiAnJyB9fSBcIlxuICAgICAgW25nU3R5bGVdPVwieyAnei1pbmRleCc6IHpJbmRleCB9XCI+XG4gICAgICBAaWYgKGhhc1Rvb2xCYXIpIHtcbiAgICAgICAgPGRpdiAjdG9vbGJhcldyYXBwZXIgKGtleWRvd24pPVwib25LZXlEb3duVG9vbGJhcigkZXZlbnQpXCIgY2xhc3M9XCJ7eyBjbGFzc1RvV3JhcCB9fV9fdG9vbGJhclwiPlxuICAgICAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlt0b29sYmFyXVwiPjwvbmctY29udGVudD5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJlbXB0eVwiPiA8L25nLWNvbnRlbnQ+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19