@tanstack/angular-table
Version:
Headless UI for building powerful tables & datagrids for Angular.
208 lines • 30.6 kB
JavaScript
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