UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

150 lines 21.4 kB
import { inject, Injectable, RendererFactory2 } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import * as i0 from "@angular/core"; export class ManagedFocusContainerService { constructor() { this.rendererFactory = inject(RendererFactory2); this._containers = []; // programmatically create a renderer as it can't be injected into a service this._renderer = this.rendererFactory.createRenderer(null, null); } /** * Create or get an existing object which manages the tabindex of descendants. * @param element The element containing focusable descendants. * @param component The component requesting the managed focus container. */ register(element, component) { // Only create a new instance if no other component has created a container on the same element let containerRef = this._containers.find(ref => ref.container.element.isEqualNode(element)); if (!containerRef) { containerRef = new ManagedFocusContainerWithReferences(new ManagedFocusContainer(element, this._renderer)); this._containers.push(containerRef); // Start listening for focus containerRef.container.register(); } // Track references to dispose correctly if (component) { containerRef.addReference(component); } } /** * Remove the container object. This will call `unregister` on the container if `component` is the last reference * to it. * @param element The element containing focusable descendants. * @param component The component requesting the managed focus container. */ unregister(element, component) { // Remove the container's reference to the source component const containerRef = this._containers.find(ref => ref.container.element.isEqualNode(element)); // technically this function can be called before the register function if ngOnDestroy runs before it // is fully initialized so we should stop here if there is no containRef. if (!containerRef) { return; } containerRef.removeReference(component); if (!containerRef.isAlive()) { // Last reference was removed, so unregister the listeners containerRef.container.unregister(); // Clean up the reference tracking array this._containers = this._containers.filter(c => c !== containerRef); } } /** * Get an observable which can be used to determine when the element or one of its descendants has focus. * @param element The element containing focusable descendants. */ hasFocus(element) { const container = this.getContainer(element); return container ? container.hasFocus$.asObservable() : null; } getContainer(element) { const containerRef = this._containers.find(ref => ref.container.element.isEqualNode(element)); return containerRef ? containerRef.container : null; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ManagedFocusContainerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ManagedFocusContainerService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ManagedFocusContainerService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); class ManagedFocusContainer { constructor(element, _renderer) { this.element = element; this._renderer = _renderer; /** Whether the container or one of its descendants has focus. */ this.hasFocus$ = new BehaviorSubject(false); this._modifiedElements = []; this._unlisten = []; } /** Start managing the focus of child elements. */ register() { this._unlisten.push(this._renderer.listen(this.element, 'focusin', this.onFocusIn.bind(this))); this._unlisten.push(this._renderer.listen(this.element, 'focusout', this.onFocusOut.bind(this))); // Check if the container already has focus setTimeout(() => { if (!this.element.contains(document.activeElement)) { this.removeTabFocus(); } }); } /** Stop managing the focus of child elements. */ unregister() { // Dispose the event handlers this._unlisten.forEach(unlisten => unlisten()); this._unlisten = []; // Undo any tabindex modifications this.restoreTabFocus(); } onFocusIn() { this.restoreTabFocus(); } onFocusOut() { this.removeTabFocus(); } removeTabFocus() { this.hasFocus$.next(false); // Clear the list of affected elements this._modifiedElements = []; // Get all focusable children const focusable = this.element.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); // Remove focusable children from the tab ring Array.from(focusable).forEach(element => { const originalTabIndex = element.getAttribute('tabindex'); this._renderer.setAttribute(element, 'tabindex', '-1'); this._modifiedElements.push({ element, tabindex: originalTabIndex }); }); } restoreTabFocus() { this.hasFocus$.next(true); // Restore tab focus ability by removing the custom `tabindex` attribute this._modifiedElements.forEach(elementInfo => { if (elementInfo.tabindex === null) { this._renderer.removeAttribute(elementInfo.element, 'tabindex'); } else { this._renderer.setAttribute(elementInfo.element, 'tabindex', elementInfo.tabindex); } }); // Clear the list of affected elements this._modifiedElements = []; } } class ManagedFocusContainerWithReferences { constructor(container) { this.container = container; this._components = []; } addReference(component) { this._components.push(component); } removeReference(component) { this._components = this._components.filter(c => c !== component); } isAlive() { return this._components.length > 0; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZC1mb2N1cy1jb250YWluZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9kaXJlY3RpdmVzL2FjY2Vzc2liaWxpdHkvbWFuYWdlZC1mb2N1cy1jb250YWluZXIvbWFuYWdlZC1mb2N1cy1jb250YWluZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBYSxnQkFBZ0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRixPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDOztBQUduRCxNQUFNLE9BQU8sNEJBQTRCO0lBTXJDO1FBTFMsb0JBQWUsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUU1QyxnQkFBVyxHQUEwQyxFQUFFLENBQUM7UUFJNUQsNEVBQTRFO1FBQzVFLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsUUFBUSxDQUFDLE9BQW9CLEVBQUUsU0FBa0I7UUFFN0MsK0ZBQStGO1FBQy9GLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ2hCLFlBQVksR0FBRyxJQUFJLG1DQUFtQyxDQUFDLElBQUkscUJBQXFCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1lBQzNHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXBDLDRCQUE0QjtZ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ImltcG9ydCB7IGluamVjdCwgSW5qZWN0YWJsZSwgUmVuZGVyZXIyLCBSZW5kZXJlckZhY3RvcnkyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE1hbmFnZWRGb2N1c0NvbnRhaW5lclNlcnZpY2Uge1xuICAgIHJlYWRvbmx5IHJlbmRlcmVyRmFjdG9yeSA9IGluamVjdChSZW5kZXJlckZhY3RvcnkyKTtcblxuICAgIHByaXZhdGUgX2NvbnRhaW5lcnM6IE1hbmFnZWRGb2N1c0NvbnRhaW5lcldpdGhSZWZlcmVuY2VzW10gPSBbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJlcjogUmVuZGVyZXIyO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIC8vIHByb2dyYW1tYXRpY2FsbHkgY3JlYXRlIGEgcmVuZGVyZXIgYXMgaXQgY2FuJ3QgYmUgaW5qZWN0ZWQgaW50byBhIHNlcnZpY2VcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSB0aGlzLnJlbmRlcmVyRmFjdG9yeS5jcmVhdGVSZW5kZXJlcihudWxsLCBudWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgb3IgZ2V0IGFuIGV4aXN0aW5nIG9iamVjdCB3aGljaCBtYW5hZ2VzIHRoZSB0YWJpbmRleCBvZiBkZXNjZW5kYW50cy5cbiAgICAgKiBAcGFyYW0gZWxlbWVudCBUaGUgZWxlbWVudCBjb250YWluaW5nIGZvY3VzYWJsZSBkZXNjZW5kYW50cy5cbiAgICAgKiBAcGFyYW0gY29tcG9uZW50IFRoZSBjb21wb25lbnQgcmVxdWVzdGluZyB0aGUgbWFuYWdlZCBmb2N1cyBjb250YWluZXIuXG4gICAgICovXG4gICAgcmVnaXN0ZXIoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNvbXBvbmVudDogdW5rbm93bik6IHZvaWQge1xuXG4gICAgICAgIC8vIE9ubHkgY3JlYXRlIGEgbmV3IGluc3RhbmNlIGlmIG5vIG90aGVyIGNvbXBvbmVudCBoYXMgY3JlYXRlZCBhIGNvbnRhaW5lciBvbiB0aGUgc2FtZSBlbGVtZW50XG4gICAgICAgIGxldCBjb250YWluZXJSZWYgPSB0aGlzLl9jb250YWluZXJzLmZpbmQocmVmID0+IHJlZi5jb250YWluZXIuZWxlbWVudC5pc0VxdWFsTm9kZShlbGVtZW50KSk7XG4gICAgICAgIGlmICghY29udGFpbmVyUmVmKSB7XG4gICAgICAgICAgICBjb250YWluZXJSZWYgPSBuZXcgTWFuYWdlZEZvY3VzQ29udGFpbmVyV2l0aFJlZmVyZW5jZXMobmV3IE1hbmFnZWRGb2N1c0NvbnRhaW5lcihlbGVtZW50LCB0aGlzLl9yZW5kZXJlcikpO1xuICAgICAgICAgICAgdGhpcy5fY29udGFpbmVycy5wdXNoKGNvbnRhaW5lclJlZik7XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IGxpc3RlbmluZyBmb3IgZm9jdXNcbiAgICAgICAgICAgIGNvbnRhaW5lclJlZi5jb250YWluZXIucmVnaXN0ZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyYWNrIHJlZmVyZW5jZXMgdG8gZGlzcG9zZSBjb3JyZWN0bHlcbiAgICAgICAgaWYgKGNvbXBvbmVudCkge1xuICAgICAgICAgICAgY29udGFpbmVyUmVmLmFkZFJlZmVyZW5jZShjb21wb25lbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBjb250YWluZXIgb2JqZWN0LiBUaGlzIHdpbGwgY2FsbCBgdW5yZWdpc3RlcmAgb24gdGhlIGNvbnRhaW5lciBpZiBgY29tcG9uZW50YCBpcyB0aGUgbGFzdCByZWZlcmVuY2VcbiAgICAgKiB0byBpdC5cbiAgICAgKiBAcGFyYW0gZWxlbWVudCBUaGUgZWxlbWVudCBjb250YWluaW5nIGZvY3VzYWJsZSBkZXNjZW5kYW50cy5cbiAgICAgKiBAcGFyYW0gY29tcG9uZW50IFRoZSBjb21wb25lbnQgcmVxdWVzdGluZyB0aGUgbWFuYWdlZCBmb2N1cyBjb250YWluZXIuXG4gICAgICovXG4gICAgdW5yZWdpc3RlcihlbGVtZW50OiBIVE1MRWxlbWVudCwgY29tcG9uZW50OiB1bmtub3duKTogdm9pZCB7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBjb250YWluZXIncyByZWZlcmVuY2UgdG8gdGhlIHNvdXJjZSBjb21wb25lbnRcbiAgICAgICAgY29uc3QgY29udGFpbmVyUmVmID0gdGhpcy5fY29udGFpbmVycy5maW5kKHJlZiA9PiByZWYuY29udGFpbmVyLmVsZW1lbnQuaXNFcXVhbE5vZGUoZWxlbWVudCkpO1xuXG4gICAgICAgIC8vIHRlY2huaWNhbGx5IHRoaXMgZnVuY3Rpb24gY2FuIGJlIGNhbGxlZCBiZWZvcmUgdGhlIHJlZ2lzdGVyIGZ1bmN0aW9uIGlmIG5nT25EZXN0cm95IHJ1bnMgYmVmb3JlIGl0XG4gICAgICAgIC8vIGlzIGZ1bGx5IGluaXRpYWxpemVkIHNvIHdlIHNob3VsZCBzdG9wIGhlcmUgaWYgdGhlcmUgaXMgbm8gY29udGFpblJlZi5cbiAgICAgICAgaWYgKCFjb250YWluZXJSZWYpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRhaW5lclJlZi5yZW1vdmVSZWZlcmVuY2UoY29tcG9uZW50KTtcblxuICAgICAgICBpZiAoIWNvbnRhaW5lclJlZi5pc0FsaXZlKCkpIHtcblxuICAgICAgICAgICAgLy8gTGFzdCByZWZlcmVuY2Ugd2FzIHJlbW92ZWQsIHNvIHVucmVnaXN0ZXIgdGhlIGxpc3RlbmVyc1xuICAgICAgICAgICAgY29udGFpbmVyUmVmLmNvbnRhaW5lci51bnJlZ2lzdGVyKCk7XG5cbiAgICAgICAgICAgIC8vIENsZWFuIHVwIHRoZSByZWZlcmVuY2UgdHJhY2tpbmcgYXJyYXlcbiAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lcnMgPSB0aGlzLl9jb250YWluZXJzLmZpbHRlcihjID0+IGMgIT09IGNvbnRhaW5lclJlZik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYW4gb2JzZXJ2YWJsZSB3aGljaCBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmUgd2hlbiB0aGUgZWxlbWVudCBvciBvbmUgb2YgaXRzIGRlc2NlbmRhbnRzIGhhcyBmb2N1cy5cbiAgICAgKiBAcGFyYW0gZWxlbWVudCBUaGUgZWxlbWVudCBjb250YWluaW5nIGZvY3VzYWJsZSBkZXNjZW5kYW50cy5cbiAgICAgKi9cbiAgICBoYXNGb2N1cyhlbGVtZW50OiBIVE1MRWxlbWVudCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmdldENvbnRhaW5lcihlbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lciA/IGNvbnRhaW5lci5oYXNGb2N1cyQuYXNPYnNlcnZhYmxlKCkgOiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q29udGFpbmVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogTWFuYWdlZEZvY3VzQ29udGFpbmVyIHtcbiAgICAgICAgY29uc3QgY29udGFpbmVyUmVmID0gdGhpcy5fY29udGFpbmVycy5maW5kKHJlZiA9PiByZWYuY29udGFpbmVyLmVsZW1lbnQuaXNFcXVhbE5vZGUoZWxlbWVudCkpO1xuICAgICAgICByZXR1cm4gY29udGFpbmVyUmVmID8gY29udGFpbmVyUmVmLmNvbnRhaW5lciA6IG51bGw7XG4gICAgfVxufVxuXG5jbGFzcyBNYW5hZ2VkRm9jdXNDb250YWluZXIge1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGNvbnRhaW5lciBvciBvbmUgb2YgaXRzIGRlc2NlbmRhbnRzIGhhcyBmb2N1cy4gKi9cbiAgICByZWFkb25seSBoYXNGb2N1cyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAgIHByaXZhdGUgX21vZGlmaWVkRWxlbWVudHM6IE1hbmFnZWRGb2N1c0VsZW1lbnRJbmZvW10gPSBbXTtcbiAgICBwcml2YXRlIF91bmxpc3RlbjogKCgpID0+IHZvaWQpW10gPSBbXTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgcmVhZG9ubHkgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgX3JlbmRlcmVyOiBSZW5kZXJlcjJcbiAgICApIHsgfVxuXG4gICAgLyoqIFN0YXJ0IG1hbmFnaW5nIHRoZSBmb2N1cyBvZiBjaGlsZCBlbGVtZW50cy4gKi9cbiAgICByZWdpc3RlcigpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLl91bmxpc3Rlbi5wdXNoKHRoaXMuX3JlbmRlcmVyLmxpc3Rlbih0aGlzLmVsZW1lbnQsICdmb2N1c2luJywgdGhpcy5vbkZvY3VzSW4uYmluZCh0aGlzKSkpO1xuICAgICAgICB0aGlzLl91bmxpc3Rlbi5wdXNoKHRoaXMuX3JlbmRlcmVyLmxpc3Rlbih0aGlzLmVsZW1lbnQsICdmb2N1c291dCcsIHRoaXMub25Gb2N1c091dC5iaW5kKHRoaXMpKSk7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGNvbnRhaW5lciBhbHJlYWR5IGhhcyBmb2N1c1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5lbGVtZW50LmNvbnRhaW5zKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVUYWJGb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogU3RvcCBtYW5hZ2luZyB0aGUgZm9jdXMgb2YgY2hpbGQgZWxlbWVudHMuICovXG4gICAgdW5yZWdpc3RlcigpOiB2b2lkIHtcblxuICAgICAgICAvLyBEaXNwb3NlIHRoZSBldmVudCBoYW5kbGVyc1xuICAgICAgICB0aGlzLl91bmxpc3Rlbi5mb3JFYWNoKHVubGlzdGVuID0+IHVubGlzdGVuKCkpO1xuICAgICAgICB0aGlzLl91bmxpc3RlbiA9IFtdO1xuXG4gICAgICAgIC8vIFVuZG8gYW55IHRhYmluZGV4IG1vZGlmaWNhdGlvbnNcbiAgICAgICAgdGhpcy5yZXN0b3JlVGFiRm9jdXMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRm9jdXNJbigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZXN0b3JlVGFiRm9jdXMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRm9jdXNPdXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVtb3ZlVGFiRm9jdXMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW92ZVRhYkZvY3VzKCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMuaGFzRm9jdXMkLm5leHQoZmFsc2UpO1xuXG4gICAgICAgIC8vIENsZWFyIHRoZSBsaXN0IG9mIGFmZmVjdGVkIGVsZW1lbnRzXG4gICAgICAgIHRoaXMuX21vZGlmaWVkRWxlbWVudHMgPSBbXTtcblxuICAgICAgICAvLyBHZXQgYWxsIGZvY3VzYWJsZSBjaGlsZHJlblxuICAgICAgICBjb25zdCBmb2N1c2FibGUgPSB0aGlzLmVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChcbiAgICAgICAgICAgICdidXR0b24sIFtocmVmXSwgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIFt0YWJpbmRleF06bm90KFt0YWJpbmRleD1cIi0xXCJdKSdcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBSZW1vdmUgZm9jdXNhYmxlIGNoaWxkcmVuIGZyb20gdGhlIHRhYiByaW5nXG4gICAgICAgIEFycmF5LmZyb20oZm9jdXNhYmxlKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxUYWJJbmRleCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd0YWJpbmRleCcpO1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKGVsZW1lbnQsICd0YWJpbmRleCcsICctMScpO1xuICAgICAgICAgICAgdGhpcy5fbW9kaWZpZWRFbGVtZW50cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgIHRhYmluZGV4OiBvcmlnaW5hbFRhYkluZGV4XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXN0b3JlVGFiRm9jdXMoKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5oYXNGb2N1cyQubmV4dCh0cnVlKTtcblxuICAgICAgICAvLyBSZXN0b3JlIHRhYiBmb2N1cyBhYmlsaXR5IGJ5IHJlbW92aW5nIHRoZSBjdXN0b20gYHRhYmluZGV4YCBhdHRyaWJ1dGVcbiAgICAgICAgdGhpcy5fbW9kaWZpZWRFbGVtZW50cy5mb3JFYWNoKGVsZW1lbnRJbmZvID0+IHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50SW5mby50YWJpbmRleCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnJlbW92ZUF0dHJpYnV0ZShlbGVtZW50SW5mby5lbGVtZW50LCAndGFiaW5kZXgnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKGVsZW1lbnRJbmZvLmVsZW1lbnQsICd0YWJpbmRleCcsIGVsZW1lbnRJbmZvLnRhYmluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQ2xlYXIgdGhlIGxpc3Qgb2YgYWZmZWN0ZWQgZWxlbWVudHNcbiAgICAgICAgdGhpcy5fbW9kaWZpZWRFbGVtZW50cyA9IFtdO1xuICAgIH1cbn1cblxuaW50ZXJmYWNlIE1hbmFnZWRGb2N1c0VsZW1lbnRJbmZvIHtcbiAgICBlbGVtZW50OiBFbGVtZW50O1xuICAgIHRhYmluZGV4OiBzdHJpbmc7XG59XG5cbmNsYXNzIE1hbmFnZWRGb2N1c0NvbnRhaW5lcldpdGhSZWZlcmVuY2VzIHtcblxuICAgIHByaXZhdGUgX2NvbXBvbmVudHM6IHVua25vd25bXSA9IFtdO1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIGNvbnRhaW5lcjogTWFuYWdlZEZvY3VzQ29udGFpbmVyKSB7IH1cblxuICAgIGFkZFJlZmVyZW5jZShjb21wb25lbnQ6IHVua25vd24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fY29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7XG4gICAgfVxuXG4gICAgcmVtb3ZlUmVmZXJlbmNlKGNvbXBvbmVudDogdW5rbm93bik6IHZvaWQge1xuICAgICAgICB0aGlzLl9jb21wb25lbnRzID0gdGhpcy5fY29tcG9uZW50cy5maWx0ZXIoYyA9PiBjICE9PSBjb21wb25lbnQpO1xuICAgIH1cblxuICAgIGlzQWxpdmUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb21wb25lbnRzLmxlbmd0aCA+IDA7XG4gICAgfVxufSJdfQ==