@clr/angular
Version:
Angular components for Clarity
198 lines • 24 kB
JavaScript
/*
* 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, ContentChildren, EventEmitter, HostListener, Input, Output, } from '@angular/core';
import { Keys } from '../../enums/keys.enum';
import { ClrFocusDirection } from './enums/focus-direction.enum';
import { ClrKeyFocusItem } from './key-focus-item';
import { normalizeKey, preventArrowKeyScroll } from './util';
import * as i0 from "@angular/core";
export class ClrKeyFocus {
constructor(elementRef) {
this.elementRef = elementRef;
this.direction = ClrFocusDirection.VERTICAL;
this.focusOnLoad = false;
this.subscriptions = [];
this.focusChange = new EventEmitter();
this._current = 0;
}
/**
* Here we use `any` cause any other type require reworking all methods below and a lot of more ifs.
* this method will only work with array with FocusableItems anyway so any other value will be ignored.
*/
get focusableItems() {
if (this._focusableItems) {
return this._focusableItems;
}
else if (this.clrKeyFocusItems) {
return this.clrKeyFocusItems.toArray();
}
return [];
}
set focusableItems(elements) {
// We accept a list of focusable elements (HTMLElements or existing Directives) or auto query for clrKeyFocusItem
// We accept a list reference in the cases where we cannot use ContentChildren to query
// ContentChildren can be unavailable if content is projected outside the scope of the component (see tabs).
if (Array.isArray(elements) && elements.length) {
this._focusableItems = elements;
this.initializeFocus();
}
}
get nativeElement() {
return this.elementRef.nativeElement;
}
get current() {
return this._current;
}
set current(value) {
if (this._current !== value) {
this._current = value;
}
}
get currentItem() {
return this.focusableItems[this._current];
}
get currentItemElement() {
return this.currentItem.nativeElement ? this.currentItem.nativeElement : this.currentItem;
}
ngAfterContentInit() {
this.subscriptions.push(this.listenForItemUpdates());
this.initializeFocus();
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
handleKeyboardEvent(event) {
// Make sure event was originated on the current item's element
if (this.currentItemElement !== event.target) {
const position = this.getItemPosition(event.target);
if (this.positionInRange(position)) {
this.current = position;
}
}
if (this.prevKeyPressed(event) && this.currentFocusIsNotFirstItem()) {
this.moveTo(this.current - 1);
}
else if (this.nextKeyPressed(event) && this.currentFocusIsNotLastItem()) {
this.moveTo(this.current + 1);
}
else if (event.code === Keys.Home) {
this.moveTo(0);
}
else if (event.code === Keys.End) {
this.moveTo(this.focusableItems.length - 1);
}
preventArrowKeyScroll(event);
}
setClickedItemCurrent(event) {
const position = this.getItemPosition(event.target);
if (position > -1) {
this.moveTo(position);
}
}
focusCurrent() {
this.currentItem.focus();
this.focusChange.next(this._current);
}
moveTo(position) {
if (this.positionInRange(position)) {
this.current = position;
this.focusCurrent();
}
}
positionInRange(position) {
return position >= 0 && position < this.focusableItems.length;
}
currentFocusIsNotFirstItem() {
return this._current - 1 >= 0;
}
currentFocusIsNotLastItem() {
return this._current + 1 < this.focusableItems.length;
}
initializeFocus() {
if (this.focusableItems && this.focusableItems.length) {
// It is possible that the focus was on an element, whose index is no longer available.
// This can happen when some of the focusable elements are being removed.
// In such cases, the new focus is initialized on the last focusable element.
if (this._current >= this.focusableItems.length) {
this._current = this.focusableItems.length - 1;
}
if (this.focusOnLoad) {
this.currentItem.focus();
this.focusChange.next();
}
}
}
nextKeyPressed(event) {
const key = normalizeKey(event.key);
switch (this.direction) {
case ClrFocusDirection.VERTICAL:
return key === Keys.ArrowDown;
case ClrFocusDirection.HORIZONTAL:
return key === Keys.ArrowRight;
case ClrFocusDirection.BOTH:
return key === Keys.ArrowDown || key === Keys.ArrowRight;
default:
return false;
}
}
prevKeyPressed(event) {
const key = normalizeKey(event.key);
switch (this.direction) {
case ClrFocusDirection.VERTICAL:
return key === Keys.ArrowUp;
case ClrFocusDirection.HORIZONTAL:
return key === Keys.ArrowLeft;
case ClrFocusDirection.BOTH:
return key === Keys.ArrowUp || key === Keys.ArrowLeft;
default:
return false;
}
}
getItemPosition(item) {
if (this._focusableItems) {
return this.focusableItems.indexOf(item);
}
else {
return this.focusableItems.map(_item => _item.nativeElement).indexOf(item);
}
}
listenForItemUpdates() {
return this.clrKeyFocusItems.changes.subscribe(() => {
this.initializeFocus();
});
}
}
ClrKeyFocus.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrKeyFocus, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
ClrKeyFocus.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrKeyFocus, selector: "[clrKeyFocus]", inputs: { direction: ["clrDirection", "direction"], focusOnLoad: ["clrFocusOnLoad", "focusOnLoad"], focusableItems: ["clrKeyFocus", "focusableItems"] }, outputs: { focusChange: "clrFocusChange" }, host: { listeners: { "keydown": "handleKeyboardEvent($event)", "click": "setClickedItemCurrent($event)" } }, queries: [{ propertyName: "clrKeyFocusItems", predicate: ClrKeyFocusItem, descendants: true }], ngImport: i0, template: '<ng-content></ng-content>', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrKeyFocus, decorators: [{
type: Component,
args: [{
selector: '[clrKeyFocus]',
template: '<ng-content></ng-content>',
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { direction: [{
type: Input,
args: ['clrDirection']
}], focusOnLoad: [{
type: Input,
args: ['clrFocusOnLoad']
}], clrKeyFocusItems: [{
type: ContentChildren,
args: [ClrKeyFocusItem, { descendants: true }]
}], focusChange: [{
type: Output,
args: ['clrFocusChange']
}], focusableItems: [{
type: Input,
args: ['clrKeyFocus']
}], handleKeyboardEvent: [{
type: HostListener,
args: ['keydown', ['$event']]
}], setClickedItemCurrent: [{
type: HostListener,
args: ['click', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LWZvY3VzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci9zcmMvdXRpbHMvZm9jdXMva2V5LWZvY3VzL2tleS1mb2N1cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUgsT0FBTyxFQUNMLFNBQVMsRUFDVCxlQUFlLEVBRWYsWUFBWSxFQUNaLFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM3QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUVqRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxxQkFBcUIsRUFBRSxNQUFNLFFBQVEsQ0FBQzs7QUFNN0QsTUFBTSxPQUFPLFdBQVc7SUFhdEIsWUFBb0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQVpuQixjQUFTLEdBQStCLGlCQUFpQixDQUFDLFFBQVEsQ0FBQztRQUNqRSxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUluQyxrQkFBYSxHQUFtQixFQUFFLENBQUM7UUFFWCxnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFbkUsYUFBUSxHQUFHLENBQUMsQ0FBQztJQUd3QixDQUFDO0lBRTlDOzs7T0FHRztJQUNILElBQ0ksY0FBYztRQUNoQixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDeEIsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDO1NBQzdCO2FBQU0sSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDaEMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDeEM7UUFDRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFDRCxJ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QUN2QyxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDeEIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMxQzthQUFNO1lBQ0wsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDNUU7SUFDSCxDQUFDO0lBRU8sb0JBQW9CO1FBQzFCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2xELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7O3dHQXRMVSxXQUFXOzRGQUFYLFdBQVcsd1lBSUwsZUFBZSxnREFOdEIsMkJBQTJCOzJGQUUxQixXQUFXO2tCQUp2QixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxlQUFlO29CQUN6QixRQUFRLEVBQUUsMkJBQTJCO2lCQUN0QztpR0FFd0IsU0FBUztzQkFBL0IsS0FBSzt1QkFBQyxjQUFjO2dCQUNJLFdBQVc7c0JBQW5DLEtBQUs7dUJBQUMsZ0JBQWdCO2dCQUU0QyxnQkFBZ0I7c0JBQWxGLGVBQWU7dUJBQUMsZUFBZSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRTtnQkFJckIsV0FBVztzQkFBNUMsTUFBTTt1QkFBQyxnQkFBZ0I7Z0JBWXBCLGNBQWM7c0JBRGpCLEtBQUs7dUJBQUMsYUFBYTtnQkFrRHBCLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBd0JuQyxxQkFBcUI7c0JBRHBCLFlBQVk7dUJBQUMsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxNi0yMDIzIFZNd2FyZSwgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZS5cbiAqIFRoZSBmdWxsIGxpY2Vuc2UgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGluIExJQ0VOU0UgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgcHJvamVjdC5cbiAqL1xuXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZHJlbixcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgS2V5cyB9IGZyb20gJy4uLy4uL2VudW1zL2tleXMuZW51bSc7XG5pbXBvcnQgeyBDbHJGb2N1c0RpcmVjdGlvbiB9IGZyb20gJy4vZW51bXMvZm9jdXMtZGlyZWN0aW9uLmVudW0nO1xuaW1wb3J0IHsgRm9jdXNhYmxlSXRlbSB9IGZyb20gJy4vaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBDbHJLZXlGb2N1c0l0ZW0gfSBmcm9tICcuL2tleS1mb2N1cy1pdGVtJztcbmltcG9ydCB7IG5vcm1hbGl6ZUtleSwgcHJldmVudEFycm93S2V5U2Nyb2xsIH0gZnJvbSAnLi91dGlsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnW2NscktleUZvY3VzXScsXG4gIHRlbXBsYXRlOiAnPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PicsXG59KVxuZXhwb3J0IGNsYXNzIENscktleUZvY3VzIHtcbiAgQElucHV0KCdjbHJEaXJlY3Rpb24nKSBkaXJlY3Rpb246IENsckZvY3VzRGlyZWN0aW9uIHwgc3RyaW5nID0gQ2xyRm9jdXNEaXJlY3Rpb24uVkVSVElDQUw7XG4gIEBJbnB1dCgnY2xyRm9jdXNPbkxvYWQnKSBmb2N1c09uTG9hZCA9IGZhbHNlO1xuXG4gIEBDb250ZW50Q2hpbGRyZW4oQ2xyS2V5Rm9jdXNJdGVtLCB7IGRlc2NlbmRhbnRzOiB0cnVlIH0pIHByb3RlY3RlZCBjbHJLZXlGb2N1c0l0ZW1zOiBRdWVyeUxpc3Q8Q2xyS2V5Rm9jdXNJdGVtPjtcblxuICBwcm90ZWN0ZWQgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBAT3V0cHV0KCdjbHJGb2N1c0NoYW5nZScpIHByaXZhdGUgZm9jdXNDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcblxuICBwcml2YXRlIF9jdXJyZW50ID0gMDtcbiAgcHJpdmF0ZSBfZm9jdXNhYmxlSXRlbXM6IEFycmF5PEZvY3VzYWJsZUl0ZW0+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge31cblxuICAvKipcbiAgICogSGVyZSB3ZSB1c2UgYGFueWAgY2F1c2UgYW55IG90aGVyIHR5cGUgcmVxdWlyZSByZXdvcmtpbmcgYWxsIG1ldGhvZHMgYmVsb3cgYW5kIGEgbG90IG9mIG1vcmUgaWZzLlxuICAgKiB0aGlzIG1ldGhvZCB3aWxsIG9ubHkgd29yayB3aXRoIGFycmF5IHdpdGggRm9jdXNhYmxlSXRlbXMgYW55d2F5IHNvIGFueSBvdGhlciB2YWx1ZSB3aWxsIGJlIGlnbm9yZWQuXG4gICAqL1xuICBASW5wdXQoJ2NscktleUZvY3VzJylcbiAgZ2V0IGZvY3VzYWJsZUl0ZW1zKCkge1xuICAgIGlmICh0aGlzLl9mb2N1c2FibGVJdGVtcykge1xuICAgICAgcmV0dXJuIHRoaXMuX2ZvY3VzYWJsZUl0ZW1zO1xuICAgIH0gZWxzZSBpZiAodGhpcy5jbHJLZXlGb2N1c0l0ZW1zKSB7XG4gICAgICByZXR1cm4gdGhpcy5jbHJLZXlGb2N1c0l0ZW1zLnRvQXJyYXkoKTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHNldCBmb2N1c2FibGVJdGVtcyhlbGVtZW50czogQXJyYXk8Rm9jdXNhYmxlSXRlbT4gfCBhbnkpIHtcbiAgICAvLyBXZSBhY2NlcHQgYSBsaXN0IG9mIGZvY3VzYWJsZSBlbGVtZW50cyAoSFRNTEVsZW1lbnRzIG9yIGV4aXN0aW5nIERpcmVjdGl2ZXMpIG9yIGF1dG8gcXVlcnkgZm9yIGNscktleUZvY3VzSXRlbVxuICAgIC8vIFdlIGFjY2VwdCBhIGxpc3QgcmVmZXJlbmNlIGluIHRoZSBjYXNlcyB3aGVyZSB3ZSBjYW5ub3QgdXNlIENvbnRlbnRDaGlsZHJlbiB0byBxdWVyeVxuICAgIC8vIENvbnRlbnRDaGlsZHJlbiBjYW4gYmUgdW5hdmFpbGFibGUgaWYgY29udGVudCBpcyBwcm9qZWN0ZWQgb3V0c2lkZSB0aGUgc2NvcGUgb2YgdGhlIGNvbXBvbmVudCAoc2VlIHRhYnMpLlxuICAgIGlmIChBcnJheS5pc0FycmF5KGVsZW1lbnRzKSAmJiBlbGVtZW50cy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuX2ZvY3VzYWJsZUl0ZW1zID0gZWxlbWVudHMgYXMgQXJyYXk8Rm9jdXNhYmxlSXRlbT47XG4gICAgICB0aGlzLmluaXRpYWxpemVGb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBuYXRpdmVFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBnZXQgY3VycmVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5fY3VycmVudDtcbiAgfVxuICBzZXQgY3VycmVudCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuX2N1cnJlbnQgIT09IHZhbHVlKSB7XG4gICAgICB0aGlzLl9jdXJyZW50ID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGN1cnJlbnRJdGVtKCkge1xuICAgIHJldHVybiB0aGlzLmZvY3VzYWJsZUl0ZW1zW3RoaXMuX2N1cnJlbnRdO1xuICB9XG5cbiAgZ2V0IGN1cnJlbnRJdGVtRWxlbWVudCgpOiBIVE1MRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudEl0ZW0ubmF0aXZlRWxlbWVudCA/IHRoaXMuY3VycmVudEl0ZW0ubmF0aXZlRWxlbWVudCA6ICh0aGlzLmN1cnJlbnRJdGVtIGFzIEhUTUxFbGVtZW50KTtcbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaCh0aGlzLmxpc3RlbkZvckl0ZW1VcGRhdGVzKCkpO1xuICAgIHRoaXMuaW5pdGlhbGl6ZUZvY3VzKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaChzID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdrZXlkb3duJywgWyckZXZlbnQnXSlcbiAgaGFuZGxlS2V5Ym9hcmRFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIC8vIE1ha2Ugc3VyZSBldmVudCB3YXMgb3JpZ2luYXRlZCBvbiB0aGUgY3VycmVudCBpdGVtJ3MgZWxlbWVudFxuICAgIGlmICh0aGlzLmN1cnJlbnRJdGVtRWxlbWVudCAhPT0gZXZlbnQudGFyZ2V0KSB7XG4gICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0SXRlbVBvc2l0aW9uKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCk7XG4gICAgICBpZiAodGhpcy5wb3NpdGlvbkluUmFuZ2UocG9zaXRpb24pKSB7XG4gICAgICAgIHRoaXMuY3VycmVudCA9IHBvc2l0aW9uO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnByZXZLZXlQcmVzc2VkKGV2ZW50KSAmJiB0aGlzLmN1cnJlbnRGb2N1c0lzTm90Rmlyc3RJdGVtKCkpIHtcbiAgICAgIHRoaXMubW92ZVRvKHRoaXMuY3VycmVudCAtIDEpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0S2V5UHJlc3NlZChldmVudCkgJiYgdGhpcy5jdXJyZW50Rm9jdXNJc05vdExhc3RJdGVtKCkpIHtcbiAgICAgIHRoaXMubW92ZVRvKHRoaXMuY3VycmVudCArIDEpO1xuICAgIH0gZWxzZSBpZiAoZXZlbnQuY29kZSA9PT0gS2V5cy5Ib21lKSB7XG4gICAgICB0aGlzLm1vdmVUbygwKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50LmNvZGUgPT09IEtleXMuRW5kKSB7XG4gICAgICB0aGlzLm1vdmVUbyh0aGlzLmZvY3VzYWJsZUl0ZW1zLmxlbmd0aCAtIDEpO1xuICAgIH1cblxuICAgIHByZXZlbnRBcnJvd0tleVNjcm9sbChldmVudCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdjbGljaycsIFsnJGV2ZW50J10pXG4gIHNldENsaWNrZWRJdGVtQ3VycmVudChldmVudDogYW55KSB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldEl0ZW1Qb3NpdGlvbihldmVudC50YXJnZXQpO1xuXG4gICAgaWYgKHBvc2l0aW9uID4gLTEpIHtcbiAgICAgIHRoaXMubW92ZVRvKHBvc2l0aW9uKTtcbiAgICB9XG4gIH1cblxuICBmb2N1c0N1cnJlbnQoKSB7XG4gICAgdGhpcy5jdXJyZW50SXRlbS5mb2N1cygpO1xuICAgIHRoaXMuZm9jdXNDaGFuZ2UubmV4dCh0aGlzLl9jdXJyZW50KTtcbiAgfVxuXG4gIG1vdmVUbyhwb3NpdGlvbjogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMucG9zaXRpb25JblJhbmdlKHBvc2l0aW9uKSkge1xuICAgICAgdGhpcy5jdXJyZW50ID0gcG9zaXRpb247XG4gICAgICB0aGlzLmZvY3VzQ3VycmVudCgpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBwb3NpdGlvbkluUmFuZ2UocG9zaXRpb246IG51bWJlcikge1xuICAgIHJldHVybiBwb3NpdGlvbiA+PSAwICYmIHBvc2l0aW9uIDwgdGhpcy5mb2N1c2FibGVJdGVtcy5sZW5ndGg7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3VycmVudEZvY3VzSXNOb3RGaXJzdEl0ZW0oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnQgLSAxID49IDA7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3VycmVudEZvY3VzSXNOb3RMYXN0SXRlbSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY3VycmVudCArIDEgPCB0aGlzLmZvY3VzYWJsZUl0ZW1zLmxlbmd0aDtcbiAgfVxuXG4gIHByb3RlY3RlZCBpbml0aWFsaXplRm9jdXMoKSB7XG4gICAgaWYgKHRoaXMuZm9jdXNhYmxlSXRlbXMgJiYgdGhpcy5mb2N1c2FibGVJdGVtcy5sZW5ndGgpIHtcbiAgICAgIC8vIEl0IGlzIHBvc3NpYmxlIHRoYXQgdGhlIGZvY3VzIHdhcyBvbiBhbiBlbGVtZW50LCB3aG9zZSBpbmRleCBpcyBubyBsb25nZXIgYXZhaWxhYmxlLlxuICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIHdoZW4gc29tZSBvZiB0aGUgZm9jdXNhYmxlIGVsZW1lbnRzIGFyZSBiZWluZyByZW1vdmVkLlxuICAgICAgLy8gSW4gc3VjaCBjYXNlcywgdGhlIG5ldyBmb2N1cyBpcyBpbml0aWFsaXplZCBvbiB0aGUgbGFzdCBmb2N1c2FibGUgZWxlbWVudC5cbiAgICAgIGlmICh0aGlzLl9jdXJyZW50ID49IHRoaXMuZm9jdXNhYmxlSXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnQgPSB0aGlzLmZvY3VzYWJsZUl0ZW1zLmxlbmd0aCAtIDE7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmZvY3VzT25Mb2FkKSB7XG4gICAgICAgIHRoaXMuY3VycmVudEl0ZW0uZm9jdXMoKTtcbiAgICAgICAgdGhpcy5mb2N1c0NoYW5nZS5uZXh0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIG5leHRLZXlQcmVzc2VkKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgY29uc3Qga2V5ID0gbm9ybWFsaXplS2V5KGV2ZW50LmtleSk7XG5cbiAgICBzd2l0Y2ggKHRoaXMuZGlyZWN0aW9uKSB7XG4gICAgICBjYXNlIENsckZvY3VzRGlyZWN0aW9uLlZFUlRJQ0FMOlxuICAgICAgICByZXR1cm4ga2V5ID09PSBLZXlzLkFycm93RG93bjtcbiAgICAgIGNhc2UgQ2xyRm9jdXNEaXJlY3Rpb24uSE9SSVpPTlRBTDpcbiAgICAgICAgcmV0dXJuIGtleSA9PT0gS2V5cy5BcnJvd1JpZ2h0O1xuICAgICAgY2FzZSBDbHJGb2N1c0RpcmVjdGlvbi5CT1RIOlxuICAgICAgICByZXR1cm4ga2V5ID09PSBLZXlzLkFycm93RG93biB8fCBrZXkgPT09IEtleXMuQXJyb3dSaWdodDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgcHJldktleVByZXNzZWQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBjb25zdCBrZXkgPSBub3JtYWxpemVLZXkoZXZlbnQua2V5KTtcblxuICAgIHN3aXRjaCAodGhpcy5kaXJlY3Rpb24pIHtcbiAgICAgIGNhc2UgQ2xyRm9jdXNEaXJlY3Rpb24uVkVSVElDQUw6XG4gICAgICAgIHJldHVybiBrZXkgPT09IEtleXMuQXJyb3dVcDtcbiAgICAgIGNhc2UgQ2xyRm9jdXNEaXJlY3Rpb24uSE9SSVpPTlRBTDpcbiAgICAgICAgcmV0dXJuIGtleSA9PT0gS2V5cy5BcnJvd0xlZnQ7XG4gICAgICBjYXNlIENsckZvY3VzRGlyZWN0aW9uLkJPVEg6XG4gICAgICAgIHJldHVybiBrZXkgPT09IEtleXMuQXJyb3dVcCB8fCBrZXkgPT09IEtleXMuQXJyb3dMZWZ0O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0SXRlbVBvc2l0aW9uKGl0ZW06IEhUTUxFbGVtZW50KSB7XG4gICAgaWYgKHRoaXMuX2ZvY3VzYWJsZUl0ZW1zKSB7XG4gICAgICByZXR1cm4gdGhpcy5mb2N1c2FibGVJdGVtcy5pbmRleE9mKGl0ZW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5mb2N1c2FibGVJdGVtcy5tYXAoX2l0ZW0gPT4gX2l0ZW0ubmF0aXZlRWxlbWVudCkuaW5kZXhPZihpdGVtKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxpc3RlbkZvckl0ZW1VcGRhdGVzKCkge1xuICAgIHJldHVybiB0aGlzLmNscktleUZvY3VzSXRlbXMuY2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5pbml0aWFsaXplRm9jdXMoKTtcbiAgICB9KTtcbiAgfVxufVxuIl19