UNPKG

@tanstack/angular-table

Version:

Headless UI for building powerful tables & datagrids for Angular.

208 lines 30.6 kB
import { ChangeDetectorRef, Directive, effect, Inject, inject, Injector, Input, runInInjectionContext, TemplateRef, ViewContainerRef, } from '@angular/core'; import { FlexRenderComponentProps } from './flex-render/context'; import { FlexRenderFlags } from './flex-render/flags'; import { flexRenderComponent, } from './flex-render/flex-render-component'; import { FlexRenderComponentFactory } from './flex-render/flex-render-component-ref'; import { FlexRenderComponentView, FlexRenderTemplateView, mapToFlexRenderTypedContent, } from './flex-render/view'; import { memo } from '@tanstack/table-core'; import * as i0 from "@angular/core"; export { injectFlexRenderContext, } from './flex-render/context'; export class FlexRenderDirective { viewContainerRef; templateRef; #flexRenderComponentFactory = inject(FlexRenderComponentFactory); #changeDetectorRef = inject(ChangeDetectorRef); content = undefined; props = {}; injector = inject(Injector); renderFlags = FlexRenderFlags.ViewFirstRender; renderView = null; #latestContent = () => { const { content, props } = this; return typeof content !== 'function' ? content : runInInjectionContext(this.injector, () => content(props)); }; #getContentValue = memo(() => [this.#latestContent(), this.props, this.content], latestContent => { return mapToFlexRenderTypedContent(latestContent); }, { key: 'flexRenderContentValue', debug: () => false }); constructor(viewContainerRef, templateRef) { this.viewContainerRef = viewContainerRef; this.templateRef = templateRef; } ngOnChanges(changes) { if (changes['props']) { this.renderFlags |= FlexRenderFlags.PropsReferenceChanged; } if (changes['content']) { this.renderFlags |= FlexRenderFlags.ContentChanged | FlexRenderFlags.ViewFirstRender; this.update(); } } ngDoCheck() { if (this.renderFlags & FlexRenderFlags.ViewFirstRender) { // On the initial render, the view is created during the `ngOnChanges` hook. // Since `ngDoCheck` is called immediately afterward, there's no need to check for changes in this phase. this.renderFlags &= ~FlexRenderFlags.ViewFirstRender; return; } this.renderFlags |= FlexRenderFlags.DirtyCheck; const latestContent = this.#getContentValue(); if (latestContent.kind === 'null' || !this.renderView) { this.renderFlags |= FlexRenderFlags.ContentChanged; } else { this.renderView.content = latestContent; const { kind: previousKind } = this.renderView.previousContent; if (latestContent.kind !== previousKind) { this.renderFlags |= FlexRenderFlags.ContentChanged; } } this.update(); } update() { if (this.renderFlags & (FlexRenderFlags.ContentChanged | FlexRenderFlags.ViewFirstRender)) { this.render(); return; } if (this.renderFlags & FlexRenderFlags.PropsReferenceChanged) { if (this.renderView) this.renderView.updateProps(this.props); this.renderFlags &= ~FlexRenderFlags.PropsReferenceChanged; } if (this.renderFlags & (FlexRenderFlags.DirtyCheck | FlexRenderFlags.DirtySignal)) { if (this.renderView) this.renderView.dirtyCheck(); this.renderFlags &= ~(FlexRenderFlags.DirtyCheck | FlexRenderFlags.DirtySignal); } } #currentEffectRef = null; render() { if (this.#shouldRecreateEntireView() && this.#currentEffectRef) { this.#currentEffectRef.destroy(); this.#currentEffectRef = null; this.renderFlags &= ~FlexRenderFlags.RenderEffectChecked; } this.viewContainerRef.clear(); this.renderFlags = FlexRenderFlags.Pristine | (this.renderFlags & FlexRenderFlags.ViewFirstRender) | (this.renderFlags & FlexRenderFlags.RenderEffectChecked); const resolvedContent = this.#getContentValue(); if (resolvedContent.kind === 'null') { this.renderView = null; } else { this.renderView = this.#renderViewByContent(resolvedContent); } // If the content is a function `content(props)`, we initialize an effect // in order to react to changes if the given definition use signals. if (!this.#currentEffectRef && typeof this.content === 'function') { this.#currentEffectRef = effect(() => { this.#latestContent(); if (!(this.renderFlags & FlexRenderFlags.RenderEffectChecked)) { this.renderFlags |= FlexRenderFlags.RenderEffectChecked; return; } this.renderFlags |= FlexRenderFlags.DirtySignal; // This will mark the view as changed, // so we'll try to check for updates into ngDoCheck this.#changeDetectorRef.markForCheck(); }, { injector: this.viewContainerRef.injector }); } } #shouldRecreateEntireView() { return (this.renderFlags & FlexRenderFlags.ContentChanged & FlexRenderFlags.ViewFirstRender); } #renderViewByContent(content) { if (content.kind === 'primitive') { return this.#renderStringContent(content); } else if (content.kind === 'templateRef') { return this.#renderTemplateRefContent(content); } else if (content.kind === 'flexRenderComponent') { return this.#renderComponent(content); } else if (content.kind === 'component') { return this.#renderCustomComponent(content); } else { return null; } } #renderStringContent(template) { const context = () => { return typeof this.content === 'string' || typeof this.content === 'number' ? this.content : this.content?.(this.props); }; const ref = this.viewContainerRef.createEmbeddedView(this.templateRef, { get $implicit() { return context(); }, }); return new FlexRenderTemplateView(template, ref); } #renderTemplateRefContent(template) { const latestContext = () => this.props; const view = this.viewContainerRef.createEmbeddedView(template.content, { get $implicit() { return latestContext(); }, }); return new FlexRenderTemplateView(template, view); } #renderComponent(flexRenderComponent) { const { inputs, outputs, injector } = flexRenderComponent.content; const getContext = () => this.props; const proxy = new Proxy(this.props, { get: (_, key) => getContext()[key], }); const componentInjector = Injector.create({ parent: injector ?? this.injector, providers: [{ provide: FlexRenderComponentProps, useValue: proxy }], }); const view = this.#flexRenderComponentFactory.createComponent(flexRenderComponent.content, componentInjector); return new FlexRenderComponentView(flexRenderComponent, view); } #renderCustomComponent(component) { const view = this.#flexRenderComponentFactory.createComponent(flexRenderComponent(component.content, { inputs: this.props, injector: this.injector, }), this.injector); return new FlexRenderComponentView(component, view); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: FlexRenderDirective, deps: [{ token: ViewContainerRef }, { token: TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.11", type: FlexRenderDirective, isStandalone: true, selector: "[flexRender]", inputs: { content: ["flexRender", "content"], props: ["flexRenderProps", "props"], injector: ["flexRenderInjector", "injector"] }, providers: [FlexRenderComponentFactory], usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: FlexRenderDirective, decorators: [{ type: Directive, args: [{ selector: '[flexRender]', standalone: true, providers: [FlexRenderComponentFactory], }] }], ctorParameters: () => [{ type: i0.ViewContainerRef, decorators: [{ type: Inject, args: [ViewContainerRef] }] }, { type: i0.TemplateRef, decorators: [{ type: Inject, args: [TemplateRef] }] }], propDecorators: { content: [{ type: Input, args: [{ required: true, alias: 'flexRender' }] }], props: [{ type: Input, args: [{ required: true, alias: 'flexRenderProps' }] }], injector: [{ type: Input, args: [{ required: false, alias: 'flexRenderInjector' }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxleC1yZW5kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZmxleC1yZW5kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixTQUFTLEVBRVQsTUFBTSxFQUVOLE1BQU0sRUFDTixNQUFNLEVBQ04sUUFBUSxFQUNSLEtBQUssRUFFTCxxQkFBcUIsRUFFckIsV0FBVyxFQUVYLGdCQUFnQixHQUNqQixNQUFNLGVBQWUsQ0FBQTtBQUN0QixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUNoRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDckQsT0FBTyxFQUNMLG1CQUFtQixHQUVwQixNQUFNLHFDQUFxQyxDQUFBO0FBQzVDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHlDQUF5QyxDQUFBO0FBQ3BGLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsc0JBQXNCLEVBR3RCLDJCQUEyQixHQUM1QixNQUFNLG9CQUFvQixDQUFBO0FBQzNCLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTs7QUFFM0MsT0FBTyxFQUNMLHVCQUF1QixHQUV4QixNQUFNLHVCQUF1QixDQUFBO0FBaUI5QixNQUFNLE9BQU8sbUJBQW1CO0lBd0NYO0lBRUE7SUF2Q1YsMkJBQTJCLEdBQUcsTUFBTSxDQUFDLDBCQUEwQixDQUFDLENBQUE7SUFDaEUsa0JBQWtCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUE7SUFHdkQsT0FBTyxHQUtTLFNBQVMsQ0FBQTtJQUd6QixLQUFLLEdBQVcsRUFBWSxDQUFBO0lBRzVCLFFBQVEsR0FBYSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFckMsV0FBVyxHQUFHLGVBQWUsQ0FBQyxlQUFlLENBQUE7SUFDN0MsVUFBVSxHQUErQixJQUFJLENBQUE7SUFFcEMsY0FBYyxHQUFHLEdBQUcs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LENBQUMsT0FBTyxFQUFFO1lBQ3JDLE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSztZQUNsQixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7U0FDeEIsQ0FBQyxFQUNGLElBQUksQ0FBQyxRQUFRLENBQ2QsQ0FBQTtRQUNELE9BQU8sSUFBSSx1QkFBdUIsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUE7SUFDckQsQ0FBQzt3R0F2T1UsbUJBQW1CLGtCQXVDcEIsZ0JBQWdCLGFBRWhCLFdBQVc7NEZBekNWLG1CQUFtQiw4TEFGbkIsQ0FBQywwQkFBMEIsQ0FBQzs7NEZBRTVCLG1CQUFtQjtrQkFML0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsY0FBYztvQkFDeEIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFNBQVMsRUFBRSxDQUFDLDBCQUEwQixDQUFDO2lCQUN4Qzs7MEJBd0NJLE1BQU07MkJBQUMsZ0JBQWdCOzswQkFFdkIsTUFBTTsyQkFBQyxXQUFXO3lDQWxDckIsT0FBTztzQkFETixLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFO2dCQVM5QyxLQUFLO3NCQURKLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRTtnQkFJbkQsUUFBUTtzQkFEUCxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgRGlyZWN0aXZlLFxuICBEb0NoZWNrLFxuICBlZmZlY3QsXG4gIHR5cGUgRWZmZWN0UmVmLFxuICBJbmplY3QsXG4gIGluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIHJ1bkluSW5qZWN0aW9uQ29udGV4dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFR5cGUsXG4gIFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBGbGV4UmVuZGVyQ29tcG9uZW50UHJvcHMgfSBmcm9tICcuL2ZsZXgtcmVuZGVyL2NvbnRleHQnXG5pbXBvcnQgeyBGbGV4UmVuZGVyRmxhZ3MgfSBmcm9tICcuL2ZsZXgtcmVuZGVyL2ZsYWdzJ1xuaW1wb3J0IHtcbiAgZmxleFJlbmRlckNvbXBvbmVudCxcbiAgRmxleFJlbmRlckNvbXBvbmVudCxcbn0gZnJvbSAnLi9mbGV4LXJlbmRlci9mbGV4LXJlbmRlci1jb21wb25lbnQnXG5pbXBvcnQgeyBGbGV4UmVuZGVyQ29tcG9uZW50RmFjdG9yeSB9IGZyb20gJy4vZmxleC1yZW5kZXIvZmxleC1yZW5kZXItY29tcG9uZW50LXJlZidcbmltcG9ydCB7XG4gIEZsZXhSZW5kZXJDb21wb25lbnRWaWV3LFxuICBGbGV4UmVuZGVyVGVtcGxhdGVWaWV3LFxuICB0eXBlIEZsZXhSZW5kZXJUeXBlZENvbnRlbnQsXG4gIEZsZXhSZW5kZXJWaWV3LFxuICBtYXBUb0ZsZXhSZW5kZXJUeXBlZENvbnRlbnQsXG59IGZyb20gJy4vZmxleC1yZW5kZXIvdmlldydcbmltcG9ydCB7IG1lbW8gfSBmcm9tICdAdGFuc3RhY2svdGFibGUtY29yZSdcblxuZXhwb3J0IHtcbiAgaW5qZWN0RmxleFJlbmRlckNvbnRleHQsXG4gIHR5cGUgRmxleFJlbmRlckNvbXBvbmVudFByb3BzLFxufSBmcm9tICcuL2ZsZXgtcmVuZGVyL2NvbnRleHQnXG5cbmV4cG9ydCB0eXBlIEZsZXhSZW5kZXJDb250ZW50PFRQcm9wcyBleHRlbmRzIE5vbk51bGxhYmxlPHVua25vd24+PiA9XG4gIHwgc3RyaW5nXG4gIHwgbnVtYmVyXG4gIHwgVHlwZTxUUHJvcHM+XG4gIHwgRmxleFJlbmRlckNvbXBvbmVudDxUUHJvcHM+XG4gIHwgVGVtcGxhdGVSZWY8eyAkaW1wbGljaXQ6IFRQcm9wcyB9PlxuICB8IG51bGxcbiAgfCBSZWNvcmQ8YW55LCBhbnk+XG4gIHwgdW5kZWZpbmVkXG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tmbGV4UmVuZGVyXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW0ZsZXhSZW5kZXJDb21wb25lbnRGYWN0b3J5XSxcbn0pXG5leHBvcnQgY2xhc3MgRmxleFJlbmRlckRpcmVjdGl2ZTxUUHJvcHMgZXh0ZW5kcyBOb25OdWxsYWJsZTx1bmtub3duPj5cbiAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIERvQ2hlY2tcbntcbiAgcmVhZG9ubHkgI2ZsZXhSZW5kZXJDb21wb25lbnRGYWN0b3J5ID0gaW5qZWN0KEZsZXhSZW5kZXJDb21wb25lbnRGYWN0b3J5KVxuICByZWFkb25seSAjY2hhbmdlRGV0ZWN0b3JSZWYgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpXG5cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUsIGFsaWFzOiAnZmxleFJlbmRlcicgfSlcbiAgY29udGVudDpcbiAgICB8IG51bWJlclxuICAgIHwgc3RyaW5nXG4gICAgfCAoKHByb3BzOiBUUHJvcHMpID0+IEZsZXhSZW5kZXJDb250ZW50PFRQcm9wcz4pXG4gICAgfCBudWxsXG4gICAgfCB1bmRlZmluZWQgPSB1bmRlZmluZWRcblxuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSwgYWxpYXM6ICdmbGV4UmVuZGVyUHJvcHMnIH0pXG4gIHByb3BzOiBUUHJvcHMgPSB7fSBhcyBUUHJvcHNcblxuICBASW5wdXQoeyByZXF1aXJlZDogZmFsc2UsIGFsaWFzOiAnZmxleFJlbmRlckluamVjdG9yJyB9KVxuICBpbmplY3RvcjogSW5qZWN0b3IgPSBpbmplY3QoSW5qZWN0b3IpXG5cbiAgcmVuZGVyRmxhZ3MgPSBGbGV4UmVuZGVyRmxhZ3MuVmlld0ZpcnN0UmVuZGVyXG4gIHJlbmRlclZpZXc6IEZsZXhSZW5kZXJWaWV3PGFueT4gfCBudWxsID0gbnVsbFxuXG4gIHJlYWRvbmx5ICNsYXRlc3RDb250ZW50ID0gKCkgPT4ge1xuICAgIGNvbnN0IHsgY29udGVudCwgcHJvcHMgfSA9IHRoaXNcbiAgICByZXR1cm4gdHlwZW9mIGNvbnRlbnQgIT09ICdmdW5jdGlvbidcbiAgICAgID8gY29udGVudFxuICAgICAgOiBydW5JbkluamVjdGlvbkNvbnRleHQodGhpcy5pbmplY3RvciwgKCkgPT4gY29udGVudChwcm9wcykpXG4gIH1cblxuICAjZ2V0Q29udGVudFZhbHVlID0gbWVtbyhcbiAgICAoKSA9PiBbdGhpcy4jbGF0ZXN0Q29udGVudCgpLCB0aGlzLnByb3BzLCB0aGlzLmNvbnRlbnRdLFxuICAgIGxhdGVzdENvbnRlbnQgPT4ge1xuICAgICAgcmV0dXJuIG1hcFRvRmxleFJlbmRlclR5cGVkQ29udGVudChsYXRlc3RDb250ZW50KVxuICAgIH0sXG4gICAgeyBrZXk6ICdmbGV4UmVuZGVyQ29udGVudFZhbHVlJywgZGVidWc6ICgpID0+IGZhbHNlIH1cbiAgKVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoVmlld0NvbnRhaW5lclJlZilcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG4gICAgQEluamVjdChUZW1wbGF0ZVJlZilcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRlbXBsYXRlUmVmOiBUZW1wbGF0ZVJlZjxhbnk+XG4gICkge31cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXNbJ3Byb3BzJ10pIHtcbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgfD0gRmxleFJlbmRlckZsYWdzLlByb3BzUmVmZXJlbmNlQ2hhbmdlZFxuICAgIH1cbiAgICBpZiAoY2hhbmdlc1snY29udGVudCddKSB7XG4gICAgICB0aGlzLnJlbmRlckZsYWdzIHw9XG4gICAgICAgIEZsZXhSZW5kZXJGbGFncy5Db250ZW50Q2hhbmdlZCB8IEZsZXhSZW5kZXJGbGFncy5WaWV3Rmlyc3RSZW5kZXJcbiAgICAgIHRoaXMudXBkYXRlKClcbiAgICB9XG4gIH1cblxuICBuZ0RvQ2hlY2soKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVuZGVyRmxhZ3MgJiBGbGV4UmVuZGVyRmxhZ3MuVmlld0ZpcnN0UmVuZGVyKSB7XG4gICAgICAvLyBPbiB0aGUgaW5pdGlhbCByZW5kZXIsIHRoZSB2aWV3IGlzIGNyZWF0ZWQgZHVyaW5nIHRoZSBgbmdPbkNoYW5nZXNgIGhvb2suXG4gICAgICAvLyBTaW5jZSBgbmdEb0NoZWNrYCBpcyBjYWxsZWQgaW1tZWRpYXRlbHkgYWZ0ZXJ3YXJkLCB0aGVyZSdzIG5vIG5lZWQgdG8gY2hlY2sgZm9yIGNoYW5nZXMgaW4gdGhpcyBwaGFzZS5cbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgJj0gfkZsZXhSZW5kZXJGbGFncy5WaWV3Rmlyc3RSZW5kZXJcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHRoaXMucmVuZGVyRmxhZ3MgfD0gRmxleFJlbmRlckZsYWdzLkRpcnR5Q2hlY2tcblxuICAgIGNvbnN0IGxhdGVzdENvbnRlbnQgPSB0aGlzLiNnZXRDb250ZW50VmFsdWUoKVxuICAgIGlmIChsYXRlc3RDb250ZW50LmtpbmQgPT09ICdudWxsJyB8fCAhdGhpcy5yZW5kZXJWaWV3KSB7XG4gICAgICB0aGlzLnJlbmRlckZsYWdzIHw9IEZsZXhSZW5kZXJGbGFncy5Db250ZW50Q2hhbmdlZFxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlbmRlclZpZXcuY29udGVudCA9IGxhdGVzdENvbnRlbnRcbiAgICAgIGNvbnN0IHsga2luZDogcHJldmlvdXNLaW5kIH0gPSB0aGlzLnJlbmRlclZpZXcucHJldmlvdXNDb250ZW50XG4gICAgICBpZiAobGF0ZXN0Q29udGVudC5raW5kICE9PSBwcmV2aW91c0tpbmQpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJGbGFncyB8PSBGbGV4UmVuZGVyRmxhZ3MuQ29udGVudENoYW5nZWRcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy51cGRhdGUoKVxuICB9XG5cbiAgdXBkYXRlKCkge1xuICAgIGlmIChcbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgJlxuICAgICAgKEZsZXhSZW5kZXJGbGFncy5Db250ZW50Q2hhbmdlZCB8IEZsZXhSZW5kZXJGbGFncy5WaWV3Rmlyc3RSZW5kZXIpXG4gICAgKSB7XG4gICAgICB0aGlzLnJlbmRlcigpXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKHRoaXMucmVuZGVyRmxhZ3MgJiBGbGV4UmVuZGVyRmxhZ3MuUHJvcHNSZWZlcmVuY2VDaGFuZ2VkKSB7XG4gICAgICBpZiAodGhpcy5yZW5kZXJWaWV3KSB0aGlzLnJlbmRlclZpZXcudXBkYXRlUHJvcHModGhpcy5wcm9wcylcbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgJj0gfkZsZXhSZW5kZXJGbGFncy5Qcm9wc1JlZmVyZW5jZUNoYW5nZWRcbiAgICB9XG4gICAgaWYgKFxuICAgICAgdGhpcy5yZW5kZXJGbGFncyAmXG4gICAgICAoRmxleFJlbmRlckZsYWdzLkRpcnR5Q2hlY2sgfCBGbGV4UmVuZGVyRmxhZ3MuRGlydHlTaWduYWwpXG4gICAgKSB7XG4gICAgICBpZiAodGhpcy5yZW5kZXJWaWV3KSB0aGlzLnJlbmRlclZpZXcuZGlydHlDaGVjaygpXG4gICAgICB0aGlzLnJlbmRlckZsYWdzICY9IH4oXG4gICAgICAgIEZsZXhSZW5kZXJGbGFncy5EaXJ0eUNoZWNrIHwgRmxleFJlbmRlckZsYWdzLkRpcnR5U2lnbmFsXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgI2N1cnJlbnRFZmZlY3RSZWY6IEVmZmVjdFJlZiB8IG51bGwgPSBudWxsXG5cbiAgcmVuZGVyKCkge1xuICAgIGlmICh0aGlzLiNzaG91bGRSZWNyZWF0ZUVudGlyZVZpZXcoKSAmJiB0aGlzLiNjdXJyZW50RWZmZWN0UmVmKSB7XG4gICAgICB0aGlzLiNjdXJyZW50RWZmZWN0UmVmLmRlc3Ryb3koKVxuICAgICAgdGhpcy4jY3VycmVudEVmZmVjdFJlZiA9IG51bGxcbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgJj0gfkZsZXhSZW5kZXJGbGFncy5SZW5kZXJFZmZlY3RDaGVja2VkXG4gICAgfVxuXG4gICAgdGhpcy52aWV3Q29udGFpbmVyUmVmLmNsZWFyKClcbiAgICB0aGlzLnJlbmRlckZsYWdzID1cbiAgICAgIEZsZXhSZW5kZXJGbGFncy5QcmlzdGluZSB8XG4gICAgICAodGhpcy5yZW5kZXJGbGFncyAmIEZsZXhSZW5kZXJGbGFncy5WaWV3Rmlyc3RSZW5kZXIpIHxcbiAgICAgICh0aGlzLnJlbmRlckZsYWdzICYgRmxleFJlbmRlckZsYWdzLlJlbmRlckVmZmVjdENoZWNrZWQpXG5cbiAgICBjb25zdCByZXNvbHZlZENvbnRlbnQgPSB0aGlzLiNnZXRDb250ZW50VmFsdWUoKVxuICAgIGlmIChyZXNvbHZlZENvbnRlbnQua2luZCA9PT0gJ251bGwnKSB7XG4gICAgICB0aGlzLnJlbmRlclZpZXcgPSBudWxsXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVuZGVyVmlldyA9IHRoaXMuI3JlbmRlclZpZXdCeUNvbnRlbnQocmVzb2x2ZWRDb250ZW50KVxuICAgIH1cblxuICAgIC8vIElmIHRoZSBjb250ZW50IGlzIGEgZnVuY3Rpb24gYGNvbnRlbnQocHJvcHMpYCwgd2UgaW5pdGlhbGl6ZSBhbiBlZmZlY3RcbiAgICAvLyBpbiBvcmRlciB0byByZWFjdCB0byBjaGFuZ2VzIGlmIHRoZSBnaXZlbiBkZWZpbml0aW9uIHVzZSBzaWduYWxzLlxuICAgIGlmICghdGhpcy4jY3VycmVudEVmZmVjdFJlZiAmJiB0eXBlb2YgdGhpcy5jb250ZW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLiNjdXJyZW50RWZmZWN0UmVmID0gZWZmZWN0KFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhpcy4jbGF0ZXN0Q29udGVudCgpXG4gICAgICAgICAgaWYgKCEodGhpcy5yZW5kZXJGbGFncyAmIEZsZXhSZW5kZXJGbGFncy5SZW5kZXJFZmZlY3RDaGVja2VkKSkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJGbGFncyB8PSBGbGV4UmVuZGVyRmxhZ3MuUmVuZGVyRWZmZWN0Q2hlY2tlZFxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMucmVuZGVyRmxhZ3MgfD0gRmxleFJlbmRlckZsYWdzLkRpcnR5U2lnbmFsXG4gICAgICAgICAgLy8gVGhpcyB3aWxsIG1hcmsgdGhlIHZpZXcgYXMgY2hhbmdlZCxcbiAgICAgICAgICAvLyBzbyB3ZSdsbCB0cnkgdG8gY2hlY2sgZm9yIHVwZGF0ZXMgaW50byBuZ0RvQ2hlY2tcbiAgICAgICAgICB0aGlzLiNjaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKVxuICAgICAgICB9LFxuICAgICAgICB7IGluamVjdG9yOiB0aGlzLnZpZXdDb250YWluZXJSZWYuaW5qZWN0b3IgfVxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gICNzaG91bGRSZWNyZWF0ZUVudGlyZVZpZXcoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMucmVuZGVyRmxhZ3MgJlxuICAgICAgRmxleFJlbmRlckZsYWdzLkNvbnRlbnRDaGFuZ2VkICZcbiAgICAgIEZsZXhSZW5kZXJGbGFncy5WaWV3Rmlyc3RSZW5kZXJcbiAgICApXG4gIH1cblxuICAjcmVuZGVyVmlld0J5Q29udGVudChcbiAgICBjb250ZW50OiBGbGV4UmVuZGVyVHlwZWRDb250ZW50XG4gICk6IEZsZXhSZW5kZXJWaWV3PGFueT4gfCBudWxsIHtcbiAgICBpZiAoY29udGVudC5raW5kID09PSAncHJpbWl0aXZlJykge1xuICAgICAgcmV0dXJuIHRoaXMuI3JlbmRlclN0cmluZ0NvbnRlbnQoY29udGVudClcbiAgICB9IGVsc2UgaWYgKGNvbnRlbnQua2luZCA9PT0gJ3RlbXBsYXRlUmVmJykge1xuICAgICAgcmV0dXJuIHRoaXMuI3JlbmRlclRlbXBsYXRlUmVmQ29udGVudChjb250ZW50KVxuICAgIH0gZWxzZSBpZiAoY29udGVudC5raW5kID09PSAnZmxleFJlbmRlckNvbXBvbmVudCcpIHtcbiAgICAgIHJldHVybiB0aGlzLiNyZW5kZXJDb21wb25lbnQoY29udGVudClcbiAgICB9IGVsc2UgaWYgKGNvbnRlbnQua2luZCA9PT0gJ2NvbXBvbmVudCcpIHtcbiAgICAgIHJldHVybiB0aGlzLiNyZW5kZXJDdXN0b21Db21wb25lbnQoY29udGVudClcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gIH1cblxuICAjcmVuZGVyU3RyaW5nQ29udGVudChcbiAgICB0ZW1wbGF0ZTogRXh0cmFjdDxGbGV4UmVuZGVyVHlwZWRDb250ZW50LCB7IGtpbmQ6ICdwcmltaXRpdmUnIH0+XG4gICk6IEZsZXhSZW5kZXJUZW1wbGF0ZVZpZXcge1xuICAgIGNvbnN0IGNvbnRleHQgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gdHlwZW9mIHRoaXMuY29udGVudCA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgdHlwZW9mIHRoaXMuY29udGVudCA9PT0gJ251bWJlcidcbiAgICAgICAgPyB0aGlzLmNvbnRlbnRcbiAgICAgICAgOiB0aGlzLmNvbnRlbnQ/Lih0aGlzLnByb3BzKVxuICAgIH1cbiAgICBjb25zdCByZWYgPSB0aGlzLnZpZXdDb250YWluZXJSZWYuY3JlYXRlRW1iZWRkZWRWaWV3KHRoaXMudGVtcGxhdGVSZWYsIHtcbiAgICAgIGdldCAkaW1wbGljaXQoKSB7XG4gICAgICAgIHJldHVybiBjb250ZXh0KClcbiAgICAgIH0sXG4gICAgfSlcbiAgICByZXR1cm4gbmV3IEZsZXhSZW5kZXJUZW1wbGF0ZVZpZXcodGVtcGxhdGUsIHJlZilcbiAgfVxuXG4gICNyZW5kZXJUZW1wbGF0ZVJlZkNvbnRlbnQoXG4gICAgdGVtcGxhdGU6IEV4dHJhY3Q8RmxleFJlbmRlclR5cGVkQ29udGVudCwgeyBraW5kOiAndGVtcGxhdGVSZWYnIH0+XG4gICk6IEZsZXhSZW5kZXJUZW1wbGF0ZVZpZXcge1xuICAgIGNvbnN0IGxhdGVzdENvbnRleHQgPSAoKSA9PiB0aGlzLnByb3BzXG4gICAgY29uc3QgdmlldyA9IHRoaXMudmlld0NvbnRhaW5lclJlZi5jcmVhdGVFbWJlZGRlZFZpZXcodGVtcGxhdGUuY29udGVudCwge1xuICAgICAgZ2V0ICRpbXBsaWNpdCgpIHtcbiAgICAgICAgcmV0dXJuIGxhdGVzdENvbnRleHQoKVxuICAgICAgfSxcbiAgICB9KVxuICAgIHJldHVybiBuZXcgRmxleFJlbmRlclRlbXBsYXRlVmlldyh0ZW1wbGF0ZSwgdmlldylcbiAgfVxuXG4gICNyZW5kZXJDb21wb25lbnQoXG4gICAgZmxleFJlbmRlckNvbXBvbmVudDogRXh0cmFjdDxcbiAgICAgIEZsZXhSZW5kZXJUeXBlZENvbnRlbnQsXG4gICAgICB7IGtpbmQ6ICdmbGV4UmVuZGVyQ29tcG9uZW50JyB9XG4gICAgPlxuICApOiBGbGV4UmVuZGVyQ29tcG9uZW50VmlldyB7XG4gICAgY29uc3QgeyBpbnB1dHMsIG91dHB1dHMsIGluamVjdG9yIH0gPSBmbGV4UmVuZGVyQ29tcG9uZW50LmNvbnRlbnRcblxuICAgIGNvbnN0IGdldENvbnRleHQgPSAoKSA9PiB0aGlzLnByb3BzXG4gICAgY29uc3QgcHJveHkgPSBuZXcgUHJveHkodGhpcy5wcm9wcywge1xuICAgICAgZ2V0OiAoXywga2V5KSA9PiBnZXRDb250ZXh0KClba2V5IGFzIGtleW9mIHR5cGVvZiBfXSxcbiAgICB9KVxuICAgIGNvbnN0IGNvbXBvbmVudEluamVjdG9yID0gSW5qZWN0b3IuY3JlYXRlKHtcbiAgICAgIHBhcmVudDogaW5qZWN0b3IgPz8gdGhpcy5pbmplY3RvcixcbiAgICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogRmxleFJlbmRlckNvbXBvbmVudFByb3BzLCB1c2VWYWx1ZTogcHJveHkgfV0sXG4gICAgfSlcbiAgICBjb25zdCB2aWV3ID0gdGhpcy4jZmxleFJlbmRlckNvbXBvbmVudEZhY3RvcnkuY3JlYXRlQ29tcG9uZW50KFxuICAgICAgZmxleFJlbmRlckNvbXBvbmVudC5jb250ZW50LFxuICAgICAgY29tcG9uZW50SW5qZWN0b3JcbiAgICApXG4gICAgcmV0dXJuIG5ldyBGbGV4UmVuZGVyQ29tcG9uZW50VmlldyhmbGV4UmVuZGVyQ29tcG9uZW50LCB2aWV3KVxuICB9XG5cbiAgI3JlbmRlckN1c3RvbUNvbXBvbmVudChcbiAgICBjb21wb25lbnQ6IEV4dHJhY3Q8RmxleFJlbmRlclR5cGVkQ29udGVudCwgeyBraW5kOiAnY29tcG9uZW50JyB9PlxuICApOiBGbGV4UmVuZGVyQ29tcG9uZW50VmlldyB7XG4gICAgY29uc3QgdmlldyA9IHRoaXMuI2ZsZXhSZW5kZXJDb21wb25lbnRGYWN0b3J5LmNyZWF0ZUNvbXBvbmVudChcbiAgICAgIGZsZXhSZW5kZXJDb21wb25lbnQoY29tcG9uZW50LmNvbnRlbnQsIHtcbiAgICAgICAgaW5wdXRzOiB0aGlzLnByb3BzLFxuICAgICAgICBpbmplY3RvcjogdGhpcy5pbmplY3RvcixcbiAgICAgIH0pLFxuICAgICAgdGhpcy5pbmplY3RvclxuICAgIClcbiAgICByZXR1cm4gbmV3IEZsZXhSZW5kZXJDb21wb25lbnRWaWV3KGNvbXBvbmVudCwgdmlldylcbiAgfVxufVxuIl19