@handsontable/angular-wrapper
Version:
Best Data Grid for Angular with Spreadsheet Look and Feel.
151 lines • 21.2 kB
JavaScript
import { createComponent, Injectable } from '@angular/core';
import { baseRenderer } from 'handsontable/renderers';
import Handsontable from 'handsontable/base';
import { HotCellRendererComponent } from './hot-cell-renderer.component';
import * as i0 from "@angular/core";
export const INVALID_RENDERER_WARNING = 'The provided renderer component was not recognized as a valid custom renderer. ' +
'It must either extend HotCellRendererComponent or be a valid TemplateRef. ' +
'Please ensure that your custom renderer is implemented correctly and imported from the proper source.';
/**
* Type guard that checks if the given object is a TemplateRef.
*
* @param obj - The object to check.
* @returns True if the object is a TemplateRef; otherwise, false.
*/
export function isTemplateRef(obj) {
return obj && typeof obj.createEmbeddedView === 'function';
}
/**
* Type guard to check if an object is an instance of HotCellRendererComponent.
*
* @param obj - The object to check.
* @returns True if the object is a HotCellRendererComponent, false otherwise.
*/
export function isHotCellRendererComponent(obj) {
return obj?.RENDERER_MARKER === HotCellRendererComponent.RENDERER_MARKER;
}
/**
* Service for dynamically creating Angular components or templates as custom renderers for Handsontable.
*
* This service allows you to create a renderer function that wraps a given Angular component or TemplateRef
* so that it can be used as a Handsontable renderer.
*
* @example
* const customRenderer = dynamicComponentService.createRendererFromComponent(MyRendererComponent, { someProp: value });
* // Use customRenderer in your Handsontable configuration
*/
export class DynamicComponentService {
appRef;
environmentInjector;
constructor(appRef, environmentInjector) {
this.appRef = appRef;
this.environmentInjector = environmentInjector;
}
/**
* Creates a custom renderer function for Handsontable from an Angular component or TemplateRef.
* The generated renderer function will be used by Handsontable to render cell content.
*
* @param component - The Angular component type or TemplateRef to use as renderer.
* @param componentProps - An object containing additional properties to use by the renderer.
* @param register - If true, registers the renderer with Handsontable using the component's name.
* @returns A renderer function that can be used in Handsontable's configuration.
*/
createRendererFromComponent(component, componentProps = {}, register = false) {
return (instance, td, row, col, prop, value, cellProperties) => {
const properties = {
value, instance, td, row, col, prop, cellProperties
};
if (componentProps) {
Object.assign(cellProperties, { rendererProps: componentProps });
}
const rendererParameters = [
instance, td, row, col, prop, value, cellProperties
];
baseRenderer.apply(this, rendererParameters);
td.innerHTML = '';
if (isTemplateRef(component)) {
this.attachTemplateToElement(component, td, properties);
}
else if (isHotCellRendererComponent(component)) {
const componentRef = this.createComponent(component, properties);
this.attachComponentToElement(componentRef, td);
}
else {
console.warn(INVALID_RENDERER_WARNING);
}
if (register && isHotCellRendererComponent(component)) {
Handsontable.renderers.registerRenderer(component.constructor.name, component);
}
return td;
};
}
/**
* Attaches an embedded view created from a TemplateRef to a given DOM element.
*
* @param template - The TemplateRef to create an embedded view from.
* @param tdEl - The target DOM element (a table cell) to which the view will be appended.
* @param properties - Context object providing properties to be used within the template.
*/
attachTemplateToElement(template, tdEl, properties) {
const embeddedView = template.createEmbeddedView({
$implicit: properties.value,
...properties,
});
embeddedView.detectChanges();
embeddedView.rootNodes.forEach((node) => {
tdEl.appendChild(node);
});
}
/**
* Dynamically creates an Angular component of the given type.
*
* @param component - The Angular component type to be created.
* @param rendererParameters - An object containing input properties to assign to the component instance.
* @returns The ComponentRef of the dynamically created component.
*/
createComponent(component, rendererParameters) {
const componentRef = createComponent(component, {
environmentInjector: this.environmentInjector
});
Object.keys(rendererParameters).forEach(key => {
if (rendererParameters.hasOwnProperty(key)) {
componentRef.setInput(key, rendererParameters[key]);
}
else {
console.warn(`Input property "${key}" does not exist on component instance: ${component?.name}.`);
}
});
componentRef.changeDetectorRef.detectChanges();
this.appRef.attachView(componentRef.hostView);
return componentRef;
}
/**
* Attaches a dynamically created component's view to a specified DOM container element.
*
* @param componentRef - The reference to the dynamically created component.
* @param container - The target DOM element to which the component's root node will be appended.
*/
attachComponentToElement(componentRef, container) {
const domElem = componentRef.hostView
.rootNodes[0];
container.appendChild(domElem);
}
/**
* Destroys a dynamically created component and detaches its view from the Angular application.
*
* @param componentRef - The reference to the component to be destroyed.
*/
destroyComponent(componentRef) {
this.appRef.detachView(componentRef.hostView);
componentRef.destroy();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicComponentService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicComponentService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DynamicComponentService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG90LWR5bmFtaWMtcmVuZGVyZXItY29tcG9uZW50LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ob3QtdGFibGUvc3JjL2xpYi9yZW5kZXJlci9ob3QtZHluYW1pYy1yZW5kZXJlci1jb21wb25lbnQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ3lCLGVBQWUsRUFDUCxVQUFVLEVBRWpELE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxZQUFZLEVBQWUsTUFBTSx3QkFBd0IsQ0FBQztBQUNsRSxPQUFPLFlBQVksTUFBTSxtQkFBbUIsQ0FBQztBQUM3QyxPQUFPLEVBQUMsd0JBQXdCLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQzs7QUFJdkUsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQ25DLGlGQUFpRjtJQUNqRiw0RUFBNEU7SUFDNUUsdUdBQXVHLENBQUM7QUFlMUc7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFJLEdBQVE7SUFDdkMsT0FBTyxHQUFHLElBQUksT0FBTyxHQUFHLENBQUMsa0JBQWtCLEtBQUssVUFBVSxDQUFDO0FBQzdELENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxHQUFRO0lBQ2pELE9BQU8sR0FBRyxFQUFFLGVBQWUsS0FBSyx3QkFBd0IsQ0FBQyxlQUFlLENBQUM7QUFDM0UsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUlILE1BQU0sT0FBTyx1QkFBdUI7SUFFeEI7SUFDQTtJQUZWLFlBQ1UsTUFBc0IsRUFDdEIsbUJBQXdDO1FBRHhDLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ3RCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7SUFDL0MsQ0FBQztJQUVKOzs7Ozs7OztPQVFHO0lBQ0gsMkJBQTJCLENBQ3pCLFNBQTRELEVBQzVELGlCQUFzQyxFQUFFLEVBQ3hDLFdBQW9C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Q0FBQyxhQUFhLEVBQUUsQ0FBQztRQUUvQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFOUMsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssd0JBQXdCLENBQzlCLFlBQTZCLEVBQzdCLFNBQXNCO1FBRXRCLE1BQU0sT0FBTyxHQUFJLFlBQVksQ0FBQyxRQUErQjthQUMxRCxTQUFTLENBQUMsQ0FBQyxDQUFnQixDQUFDO1FBQy9CLFNBQVMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxnQkFBZ0IsQ0FBSSxZQUE2QjtRQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3pCLENBQUM7d0dBNUlVLHVCQUF1Qjs0R0FBdkIsdUJBQXVCLGNBRnRCLE1BQU07OzRGQUVQLHVCQUF1QjtrQkFIbkMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBcHBsaWNhdGlvblJlZiwgQ29tcG9uZW50UmVmLCBjcmVhdGVDb21wb25lbnQsXG4gIEVtYmVkZGVkVmlld1JlZiwgRW52aXJvbm1lbnRJbmplY3RvciwgSW5qZWN0YWJsZSxcbiAgVGVtcGxhdGVSZWYsIFR5cGVcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge2Jhc2VSZW5kZXJlciwgQmFzZVJlbmRlcmVyfSBmcm9tICdoYW5kc29udGFibGUvcmVuZGVyZXJzJztcbmltcG9ydCBIYW5kc29udGFibGUgZnJvbSAnaGFuZHNvbnRhYmxlL2Jhc2UnO1xuaW1wb3J0IHtIb3RDZWxsUmVuZGVyZXJDb21wb25lbnR9IGZyb20gJy4vaG90LWNlbGwtcmVuZGVyZXIuY29tcG9uZW50JztcblxudHlwZSBCYXNlUmVuZGVyZXJQYXJhbWV0ZXJzID0gUGFyYW1ldGVyczxCYXNlUmVuZGVyZXI+O1xuXG5leHBvcnQgY29uc3QgSU5WQUxJRF9SRU5ERVJFUl9XQVJOSU5HID1cbiAgJ1RoZSBwcm92aWRlZCByZW5kZXJlciBjb21wb25lbnQgd2FzIG5vdCByZWNvZ25pemVkIGFzIGEgdmFsaWQgY3VzdG9tIHJlbmRlcmVyLiAnICtcbiAgJ0l0IG11c3QgZWl0aGVyIGV4dGVuZCBIb3RDZWxsUmVuZGVyZXJDb21wb25lbnQgb3IgYmUgYSB2YWxpZCBUZW1wbGF0ZVJlZi4gJyArXG4gICdQbGVhc2UgZW5zdXJlIHRoYXQgeW91ciBjdXN0b20gcmVuZGVyZXIgaXMgaW1wbGVtZW50ZWQgY29ycmVjdGx5IGFuZCBpbXBvcnRlZCBmcm9tIHRoZSBwcm9wZXIgc291cmNlLic7XG5cbi8qKlxuICogQW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgcGFyYW1ldGVycyBwYXNzZWQgdG8gYSBIYW5kc29udGFibGUgcmVuZGVyZXIuXG4gKi9cbmludGVyZmFjZSBCYXNlUmVuZGVyZXJQYXJhbWV0ZXJzT2JqZWN0IHtcbiAgaW5zdGFuY2U6IEhhbmRzb250YWJsZS5Db3JlO1xuICB0ZDogSFRNTFRhYmxlQ2VsbEVsZW1lbnQ7XG4gIHJvdzogbnVtYmVyO1xuICBjb2w6IG51bWJlcjtcbiAgcHJvcDogc3RyaW5nIHwgbnVtYmVyO1xuICB2YWx1ZTogYW55O1xuICBjZWxsUHJvcGVydGllczogSGFuZHNvbnRhYmxlLkNlbGxQcm9wZXJ0aWVzO1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdGhhdCBjaGVja3MgaWYgdGhlIGdpdmVuIG9iamVjdCBpcyBhIFRlbXBsYXRlUmVmLlxuICpcbiAqIEBwYXJhbSBvYmogLSBUaGUgb2JqZWN0IHRvIGNoZWNrLlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgb2JqZWN0IGlzIGEgVGVtcGxhdGVSZWY7IG90aGVyd2lzZSwgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1RlbXBsYXRlUmVmPFQ+KG9iajogYW55KTogb2JqIGlzIFRlbXBsYXRlUmVmPFQ+IHtcbiAgcmV0dXJuIG9iaiAmJiB0eXBlb2Ygb2JqLmNyZWF0ZUVtYmVkZGVkVmlldyA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIGNoZWNrIGlmIGFuIG9iamVjdCBpcyBhbiBpbnN0YW5jZSBvZiBIb3RDZWxsUmVuZGVyZXJDb21wb25lbnQuXG4gKlxuICogQHBhcmFtIG9iaiAtIFRoZSBvYmplY3QgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBvYmplY3QgaXMgYSBIb3RDZWxsUmVuZGVyZXJDb21wb25lbnQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzSG90Q2VsbFJlbmRlcmVyQ29tcG9uZW50KG9iajogYW55KTogb2JqIGlzIFR5cGU8SG90Q2VsbFJlbmRlcmVyQ29tcG9uZW50PiB7XG4gIHJldHVybiBvYmo/LlJFTkRFUkVSX01BUktFUiA9PT0gSG90Q2VsbFJlbmRlcmVyQ29tcG9uZW50LlJFTkRFUkVSX01BUktFUjtcbn1cblxuLyoqXG4gKiBTZXJ2aWNlIGZvciBkeW5hbWljYWxseSBjcmVhdGluZyBBbmd1bGFyIGNvbXBvbmVudHMgb3IgdGVtcGxhdGVzIGFzIGN1c3RvbSByZW5kZXJlcnMgZm9yIEhhbmRzb250YWJsZS5cbiAqXG4gKiBUaGlzIHNlcnZpY2UgYWxsb3dzIHlvdSB0byBjcmVhdGUgYSByZW5kZXJlciBmdW5jdGlvbiB0aGF0IHdyYXBzIGEgZ2l2ZW4gQW5ndWxhciBjb21wb25lbnQgb3IgVGVtcGxhdGVSZWZcbiAqIHNvIHRoYXQgaXQgY2FuIGJlIHVzZWQgYXMgYSBIYW5kc29udGFibGUgcmVuZGVyZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGN1c3RvbVJlbmRlcmVyID0gZHluYW1pY0NvbXBvbmVudFNlcnZpY2UuY3JlYXRlUmVuZGVyZXJGcm9tQ29tcG9uZW50KE15UmVuZGVyZXJDb21wb25lbnQsIHsgc29tZVByb3A6IHZhbHVlIH0pO1xuICogLy8gVXNlIGN1c3RvbVJlbmRlcmVyIGluIHlvdXIgSGFuZHNvbnRhYmxlIGNvbmZpZ3VyYXRpb25cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIER5bmFtaWNDb21wb25lbnRTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhcHBSZWY6IEFwcGxpY2F0aW9uUmVmLFxuICAgIHByaXZhdGUgZW52aXJvbm1lbnRJbmplY3RvcjogRW52aXJvbm1lbnRJbmplY3RvclxuICApIHt9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjdXN0b20gcmVuZGVyZXIgZnVuY3Rpb24gZm9yIEhhbmRzb250YWJsZSBmcm9tIGFuIEFuZ3VsYXIgY29tcG9uZW50IG9yIFRlbXBsYXRlUmVmLlxuICAgKiBUaGUgZ2VuZXJhdGVkIHJlbmRlcmVyIGZ1bmN0aW9uIHdpbGwgYmUgdXNlZCBieSBIYW5kc29udGFibGUgdG8gcmVuZGVyIGNlbGwgY29udGVudC5cbiAgICpcbiAgICogQHBhcmFtIGNvbXBvbmVudCAtIFRoZSBBbmd1bGFyIGNvbXBvbmVudCB0eXBlIG9yIFRlbXBsYXRlUmVmIHRvIHVzZSBhcyByZW5kZXJlci5cbiAgICogQHBhcmFtIGNvbXBvbmVudFByb3BzIC0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIHVzZSBieSB0aGUgcmVuZGVyZXIuXG4gICAqIEBwYXJhbSByZWdpc3RlciAtIElmIHRydWUsIHJlZ2lzdGVycyB0aGUgcmVuZGVyZXIgd2l0aCBIYW5kc29udGFibGUgdXNpbmcgdGhlIGNvbXBvbmVudCdzIG5hbWUuXG4gICAqIEByZXR1cm5zIEEgcmVuZGVyZXIgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCBpbiBIYW5kc29udGFibGUncyBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgY3JlYXRlUmVuZGVyZXJGcm9tQ29tcG9uZW50KFxuICAgIGNvbXBvbmVudDogVHlwZTxIb3RDZWxsUmVuZGVyZXJDb21wb25lbnQ+IHwgVGVtcGxhdGVSZWY8YW55PixcbiAgICBjb21wb25lbnRQcm9wczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9LFxuICAgIHJlZ2lzdGVyOiBib29sZWFuID0gZmFsc2VcbiAgKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGluc3RhbmNlOiBIYW5kc29udGFibGUuQ29yZSxcbiAgICAgIHRkOiBIVE1MVGFibGVDZWxsRWxlbWVudCxcbiAgICAgIHJvdzogbnVtYmVyLFxuICAgICAgY29sOiBudW1iZXIsXG4gICAgICBwcm9wOiBzdHJpbmcgfCBudW1iZXIsXG4gICAgICB2YWx1ZTogYW55LFxuICAgICAgY2VsbFByb3BlcnRpZXM6IEhhbmRzb250YWJsZS5DZWxsUHJvcGVydGllc1xuICAgICkgPT4ge1xuICAgICAgY29uc3QgcHJvcGVydGllczogQmFzZVJlbmRlcmVyUGFyYW1ldGVyc09iamVjdCA9IHtcbiAgICAgICAgdmFsdWUsIGluc3RhbmNlLCB0ZCwgcm93LCBjb2wsIHByb3AsIGNlbGxQcm9wZXJ0aWVzXG4gICAgICB9O1xuXG4gICAgICBpZiAoY29tcG9uZW50UHJvcHMpIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihjZWxsUHJvcGVydGllcywge3JlbmRlcmVyUHJvcHM6IGNvbXBvbmVudFByb3BzfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlbmRlcmVyUGFyYW1ldGVyczogQmFzZVJlbmRlcmVyUGFyYW1ldGVycyA9IFtcbiAgICAgICAgaW5zdGFuY2UsIHRkLCByb3csIGNvbCwgcHJvcCwgdmFsdWUsIGNlbGxQcm9wZXJ0aWVzXG4gICAgICBdO1xuXG4gICAgICBiYXNlUmVuZGVyZXIuYXBwbHkodGhpcywgcmVuZGVyZXJQYXJhbWV0ZXJzKTtcblxuICAgICAgdGQuaW5uZXJIVE1MID0gJyc7XG5cbiAgICAgIGlmIChpc1RlbXBsYXRlUmVmKGNvbXBvbmVudCkpIHtcbiAgICAgICAgdGhpcy5hdHRhY2hUZW1wbGF0ZVRvRWxlbWVudChjb21wb25lbnQsIHRkLCBwcm9wZXJ0aWVzKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNIb3RDZWxsUmVuZGVyZXJDb21wb25lbnQoY29tcG9uZW50KSl7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IHRoaXMuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIHRoaXMuYXR0YWNoQ29tcG9uZW50VG9FbGVtZW50KGNvbXBvbmVudFJlZiwgdGQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKElOVkFMSURfUkVOREVSRVJfV0FSTklORylcbiAgICAgIH1cblxuICAgICAgaWYgKHJlZ2lzdGVyICYmIGlzSG90Q2VsbFJlbmRlcmVyQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICAgICAgSGFuZHNvbnRhYmxlLnJlbmRlcmVycy5yZWdpc3RlclJlbmRlcmVyKFxuICAgICAgICAgIGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgICAgIGNvbXBvbmVudCBhcyBhbnkgYXMgQmFzZVJlbmRlcmVyXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0ZDtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGFjaGVzIGFuIGVtYmVkZGVkIHZpZXcgY3JlYXRlZCBmcm9tIGEgVGVtcGxhdGVSZWYgdG8gYSBnaXZlbiBET00gZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIHRlbXBsYXRlIC0gVGhlIFRlbXBsYXRlUmVmIHRvIGNyZWF0ZSBhbiBlbWJlZGRlZCB2aWV3IGZyb20uXG4gICAqIEBwYXJhbSB0ZEVsIC0gVGhlIHRhcmdldCBET00gZWxlbWVudCAoYSB0YWJsZSBjZWxsKSB0byB3aGljaCB0aGUgdmlldyB3aWxsIGJlIGFwcGVuZGVkLlxuICAgKiBAcGFyYW0gcHJvcGVydGllcyAtIENvbnRleHQgb2JqZWN0IHByb3ZpZGluZyBwcm9wZXJ0aWVzIHRvIGJlIHVzZWQgd2l0aGluIHRoZSB0ZW1wbGF0ZS5cbiAgICovXG4gIHByaXZhdGUgYXR0YWNoVGVtcGxhdGVUb0VsZW1lbnQoXG4gICAgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sXG4gICAgdGRFbDogSFRNTFRhYmxlQ2VsbEVsZW1lbnQsXG4gICAgcHJvcGVydGllczogQmFzZVJlbmRlcmVyUGFyYW1ldGVyc09iamVjdFxuICApIHtcbiAgICBjb25zdCBlbWJlZGRlZFZpZXc6IEVtYmVkZGVkVmlld1JlZjxhbnk+ID0gdGVtcGxhdGUuY3JlYXRlRW1iZWRkZWRWaWV3KHtcbiAgICAgICRpbXBsaWNpdDogcHJvcGVydGllcy52YWx1ZSxcbiAgICAgIC4uLnByb3BlcnRpZXMsXG4gICAgfSk7XG4gICAgZW1iZWRkZWRWaWV3LmRldGVjdENoYW5nZXMoKTtcblxuICAgIGVtYmVkZGVkVmlldy5yb290Tm9kZXMuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgdGRFbC5hcHBlbmRDaGlsZChub2RlKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEeW5hbWljYWxseSBjcmVhdGVzIGFuIEFuZ3VsYXIgY29tcG9uZW50IG9mIHRoZSBnaXZlbiB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0gY29tcG9uZW50IC0gVGhlIEFuZ3VsYXIgY29tcG9uZW50IHR5cGUgdG8gYmUgY3JlYXRlZC5cbiAgICogQHBhcmFtIHJlbmRlcmVyUGFyYW1ldGVycyAtIEFuIG9iamVjdCBjb250YWluaW5nIGlucHV0IHByb3BlcnRpZXMgdG8gYXNzaWduIHRvIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIFRoZSBDb21wb25lbnRSZWYgb2YgdGhlIGR5bmFtaWNhbGx5IGNyZWF0ZWQgY29tcG9uZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVDb21wb25lbnQ8VCBleHRlbmRzIEhvdENlbGxSZW5kZXJlckNvbXBvbmVudD4oXG4gICAgY29tcG9uZW50OiBUeXBlPFQ+LFxuICAgIHJlbmRlcmVyUGFyYW1ldGVyczogQmFzZVJlbmRlcmVyUGFyYW1ldGVyc09iamVjdFxuICApOiBDb21wb25lbnRSZWY8VD4ge1xuICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IGNyZWF0ZUNvbXBvbmVudChjb21wb25lbnQsIHtcbiAgICAgIGVudmlyb25tZW50SW5qZWN0b3I6IHRoaXMuZW52aXJvbm1lbnRJbmplY3RvclxuICAgIH0pO1xuXG4gICAgT2JqZWN0LmtleXMocmVuZGVyZXJQYXJhbWV0ZXJzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBpZiAocmVuZGVyZXJQYXJhbWV0ZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgY29tcG9uZW50UmVmLnNldElucHV0KGtleSwgcmVuZGVyZXJQYXJhbWV0ZXJzW2tleV0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4oYElucHV0IHByb3BlcnR5IFwiJHtrZXl9XCIgZG9lcyBub3QgZXhpc3Qgb24gY29tcG9uZW50IGluc3RhbmNlOiAke2NvbXBvbmVudD8ubmFtZX0uYCk7XG4gICAgICB9XG4gICAgfSlcbiAgICBjb21wb25lbnRSZWYuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgdGhpcy5hcHBSZWYuYXR0YWNoVmlldyhjb21wb25lbnRSZWYuaG9zdFZpZXcpO1xuXG4gICAgcmV0dXJuIGNvbXBvbmVudFJlZjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRhY2hlcyBhIGR5bmFtaWNhbGx5IGNyZWF0ZWQgY29tcG9uZW50J3MgdmlldyB0byBhIHNwZWNpZmllZCBET00gY29udGFpbmVyIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBjb21wb25lbnRSZWYgLSBUaGUgcmVmZXJlbmNlIHRvIHRoZSBkeW5hbWljYWxseSBjcmVhdGVkIGNvbXBvbmVudC5cbiAgICogQHBhcmFtIGNvbnRhaW5lciAtIFRoZSB0YXJnZXQgRE9NIGVsZW1lbnQgdG8gd2hpY2ggdGhlIGNvbXBvbmVudCdzIHJvb3Qgbm9kZSB3aWxsIGJlIGFwcGVuZGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBhdHRhY2hDb21wb25lbnRUb0VsZW1lbnQ8VD4oXG4gICAgY29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8VD4sXG4gICAgY29udGFpbmVyOiBIVE1MRWxlbWVudFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBkb21FbGVtID0gKGNvbXBvbmVudFJlZi5ob3N0VmlldyBhcyBFbWJlZGRlZFZpZXdSZWY8VD4pXG4gICAgICAucm9vdE5vZGVzWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChkb21FbGVtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cm95cyBhIGR5bmFtaWNhbGx5IGNyZWF0ZWQgY29tcG9uZW50IGFuZCBkZXRhY2hlcyBpdHMgdmlldyBmcm9tIHRoZSBBbmd1bGFyIGFwcGxpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gY29tcG9uZW50UmVmIC0gVGhlIHJlZmVyZW5jZSB0byB0aGUgY29tcG9uZW50IHRvIGJlIGRlc3Ryb3llZC5cbiAgICovXG4gIGRlc3Ryb3lDb21wb25lbnQ8VD4oY29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8VD4pOiB2b2lkIHtcbiAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KGNvbXBvbmVudFJlZi5ob3N0Vmlldyk7XG4gICAgY29tcG9uZW50UmVmLmRlc3Ryb3koKTtcbiAgfVxufVxuIl19