@ngrdt/tabs 0.0.3 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,8 +1,218 @@
1
- export * from './lib/components/tab-container/rdt-tab-container.component';
2
- export * from './lib/components/tab/rdt-tab.component';
3
- export * from './lib/directives/rdt-destroy-inactive.directive';
4
- export * from './lib/directives/rdt-tab-controller.directive';
5
- export * from './lib/rdt-tabs-models';
6
- export * from './lib/rdt-tabs.module';
7
- export * from './lib/strategies/rdt-tabs-shortcut-strategy';
8
- export * from './lib/strategies/static-rdt-tabs-shortcut-strategy';
1
+ import * as i0 from '@angular/core';
2
+ import { OnChanges, OnInit, DestroyRef, TemplateRef, SimpleChanges, AfterContentInit, OnDestroy, QueryList, EventEmitter, ElementRef, ChangeDetectorRef, Renderer2 } from '@angular/core';
3
+ import * as i1 from '@ngrdt/core';
4
+ import { RdtIsActive, RdtContainerDirective } from '@ngrdt/core';
5
+ import { RdtShortcut } from '@ngrdt/shortcuts';
6
+ import { Nullable } from '@ngrdt/utils';
7
+ import * as i5 from '@angular/common';
8
+
9
+ interface RdtTabContainerState {
10
+ id: any;
11
+ value: any;
12
+ tabStates: RdtTabState[];
13
+ }
14
+ interface RdtTabState {
15
+ id: any;
16
+ containerStates: RdtTabContainerState[];
17
+ }
18
+ declare enum RdtTabMode {
19
+ }
20
+
21
+ declare class RdtTabComponent implements OnChanges, OnInit, RdtIsActive {
22
+ private readonly injector;
23
+ readonly destroyRef: DestroyRef;
24
+ private _contDir;
25
+ get contDir(): RdtContainerDirective;
26
+ get stateId(): string;
27
+ set stateId(value: string);
28
+ private _stateId;
29
+ disabled: boolean;
30
+ visible: boolean;
31
+ label: string;
32
+ formAutofocus: boolean;
33
+ buttonClass: Nullable<string>;
34
+ private readonly implicitContent;
35
+ private readonly explicitContent;
36
+ get templateRef(): TemplateRef<any>;
37
+ readonly tabContainer: RdtTabContainerComponent;
38
+ get childContainers(): RdtTabContainerComponent[];
39
+ rdtIsActive(): boolean;
40
+ ngOnInit(): void;
41
+ ngOnChanges(changes: SimpleChanges): void;
42
+ get isTopLevel(): boolean;
43
+ getState(): RdtTabState;
44
+ applyState(state: RdtTabState): void;
45
+ focusForm(): void;
46
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdtTabComponent, never>;
47
+ static ɵcmp: i0.ɵɵComponentDeclaration<RdtTabComponent, "rdt-tab", never, { "stateId": { "alias": "stateId"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "visible": { "alias": "visible"; "required": false; }; "label": { "alias": "label"; "required": true; }; "formAutofocus": { "alias": "formAutofocus"; "required": false; }; "buttonClass": { "alias": "buttonClass"; "required": false; }; }, {}, ["explicitContent"], ["*"], false, [{ directive: typeof i1.RdtContainerDirective; inputs: {}; outputs: {}; }]>;
48
+ static ngAcceptInputType_disabled: unknown;
49
+ static ngAcceptInputType_visible: unknown;
50
+ static ngAcceptInputType_formAutofocus: unknown;
51
+ }
52
+
53
+ declare abstract class RdtTabsShortcutStrategy {
54
+ /**
55
+ * Gets called onInit and whenever tabs are added/removed from Controller.
56
+ * @param ctrl Controller using this strategy.
57
+ * @returns List of shortcuts to register.
58
+ */
59
+ abstract updateShortcuts(ctrl: RdtTabControllerDirective): RdtShortcut[];
60
+ /**
61
+ * Gets called whenever hotkeys detects one of the registered shortcuts.
62
+ * @param shortcut Registered shortcut.
63
+ * @param ctrl Controller using this strategy.
64
+ */
65
+ abstract onShortcut(shortcut: RdtShortcut, ctrl: RdtTabControllerDirective): void;
66
+ }
67
+
68
+ declare class RdtTabControllerDirective implements OnInit, AfterContentInit, OnDestroy {
69
+ private readonly destroyRef;
70
+ private readonly injector;
71
+ private readonly shortcutService;
72
+ private shortcutSub;
73
+ set rdtTabController(value: RdtTabsShortcutStrategy | string | null);
74
+ protected get tabContainers(): RdtTabContainerComponent[];
75
+ protected get tabs(): RdtTabComponent[];
76
+ protected childControllers: QueryList<RdtTabControllerDirective>;
77
+ get strategy(): RdtTabsShortcutStrategy;
78
+ private _strategy;
79
+ private _lastActiveTabContainer;
80
+ private _contentWasInit;
81
+ get disabled(): boolean;
82
+ private _disabled;
83
+ get shortcuts(): RdtShortcut[];
84
+ set shortcuts(value: RdtShortcut[]);
85
+ private _shortcuts;
86
+ get activeContainer(): RdtTabContainerComponent | undefined;
87
+ protected containerDirective: RdtContainerDirective;
88
+ ngOnInit(): void;
89
+ ngAfterContentInit(): void;
90
+ ngOnDestroy(): void;
91
+ getTabContainerIndex(cont: RdtTabContainerComponent): number;
92
+ /**
93
+ * Activates first parent container of current container
94
+ * that is not disabled and has any non disabled tabs.
95
+ */
96
+ goLevelUp(): boolean;
97
+ /**
98
+ * Activates first container under current tab which
99
+ * is not disabled and has any non disabled tabs.
100
+ */
101
+ goLevelDown(): boolean;
102
+ /**
103
+ * Activates next container on current level
104
+ * (under parent container of currently active container).
105
+ * Is cyclic.
106
+ */
107
+ goToNextContainer(): boolean;
108
+ /**
109
+ * Activates previous container on current level
110
+ * (under parent container of currently active container).
111
+ * Is cyclic.
112
+ */
113
+ goToPrevContainer(): boolean;
114
+ /**
115
+ * Activates tab within active container at the index of argument.
116
+ */
117
+ goToTabWithIndex(index: number): boolean;
118
+ /**
119
+ * Activates next tab within active container. Is cyclic.
120
+ */
121
+ goToNextTab(): boolean;
122
+ /**
123
+ * Activates previous tab within active container. Is cyclic.
124
+ */
125
+ goToPrevTab(): boolean;
126
+ private goToAdjacentContainer;
127
+ private goToAdjacentTab;
128
+ private getSameLevelContainers;
129
+ getTabByValue(value: string): RdtTabComponent | null;
130
+ activateTabContainer(tabs: RdtTabContainerComponent, scrollIntoView?: boolean): void;
131
+ activateTabContainerFromClick(tabs: RdtTabContainerComponent, timestamp: number): void;
132
+ activateTab(tab: RdtTabComponent): Promise<void>;
133
+ canActivateTab(tab: RdtTabComponent): boolean;
134
+ canActivateTabForms(tab: RdtTabComponent): Promise<boolean>;
135
+ onTabChanges(): void;
136
+ onTabContainerChanges(): void;
137
+ private disableSelfWhenChildCtrlExists;
138
+ private setDefaultActive;
139
+ private setDefaultActiveWhenAvailable;
140
+ private canContainerBeDefault;
141
+ private updateShortcuts;
142
+ private bindAll;
143
+ private unbindAll;
144
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdtTabControllerDirective, never>;
145
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdtTabControllerDirective, "[rdtTabController]", never, { "rdtTabController": { "alias": "rdtTabController"; "required": false; }; }, {}, ["childControllers"], never, false, [{ directive: typeof i1.RdtContainerDirective; inputs: {}; outputs: {}; }]>;
146
+ }
147
+
148
+ declare class RdtTabContainerComponent implements AfterContentInit {
149
+ readonly destroyRef: DestroyRef;
150
+ stateId: any;
151
+ set value(val: string);
152
+ get value(): string;
153
+ private _value;
154
+ disabled: boolean;
155
+ formAutofocus: boolean;
156
+ panelPosition: 'left' | 'right' | 'top' | 'bottom';
157
+ valueChange: EventEmitter<any>;
158
+ tabsList: QueryList<RdtTabComponent>;
159
+ tabHeaderButtons?: QueryList<ElementRef<HTMLElement>>;
160
+ tabContent: ElementRef<HTMLElement>;
161
+ private _active;
162
+ get active(): boolean;
163
+ set active(value: boolean);
164
+ get isTopLevel(): boolean;
165
+ readonly parentTab: RdtTabComponent | null;
166
+ readonly controller: RdtTabControllerDirective | null;
167
+ readonly cd: ChangeDetectorRef;
168
+ readonly elRef: ElementRef<any>;
169
+ protected readonly renderer: Renderer2;
170
+ protected currentTemplate: TemplateRef<any> | null;
171
+ protected currentTab: RdtTabComponent | null;
172
+ get classes(): string;
173
+ get isHorizontal(): boolean;
174
+ get isVertical(): boolean;
175
+ private attrRole;
176
+ get hasNonDisabledTabs(): boolean;
177
+ get activeTab(): RdtTabComponent | undefined;
178
+ getTabByValue(value: string): RdtTabComponent | undefined;
179
+ ngAfterContentInit(): void;
180
+ getState(): RdtTabContainerState;
181
+ applyState(state: RdtTabContainerState): void;
182
+ scrollIntoView(): void;
183
+ activateTab(value: string): Promise<void>;
184
+ scrollCurrentButtonIntoView(): void;
185
+ private onClick;
186
+ private setCurrent;
187
+ private setTab;
188
+ private solidifyTabContentSize;
189
+ private releaseTabContentSize;
190
+ private getFirstEnabledTab;
191
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdtTabContainerComponent, never>;
192
+ static ɵcmp: i0.ɵɵComponentDeclaration<RdtTabContainerComponent, "rdt-tab-container", never, { "stateId": { "alias": "stateId"; "required": false; }; "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "formAutofocus": { "alias": "formAutofocus"; "required": false; }; "panelPosition": { "alias": "panelPosition"; "required": false; }; }, { "valueChange": "valueChange"; }, ["tabsList"], never, false, [{ directive: typeof i1.RdtChildDirective; inputs: {}; outputs: {}; }]>;
193
+ }
194
+
195
+ declare class RdtDestroyInactiveDirective {
196
+ readonly template: TemplateRef<any>;
197
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdtDestroyInactiveDirective, never>;
198
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdtDestroyInactiveDirective, "[rdtDestroyInactive]", never, {}, {}, never, never, false, never>;
199
+ }
200
+
201
+ declare class RdtTabsModule {
202
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdtTabsModule, never>;
203
+ static ɵmod: i0.ɵɵNgModuleDeclaration<RdtTabsModule, [typeof RdtTabComponent, typeof RdtTabContainerComponent, typeof RdtTabControllerDirective, typeof RdtDestroyInactiveDirective], [typeof i5.CommonModule], [typeof RdtTabComponent, typeof RdtTabContainerComponent, typeof RdtTabControllerDirective, typeof RdtDestroyInactiveDirective]>;
204
+ static ɵinj: i0.ɵɵInjectorDeclaration<RdtTabsModule>;
205
+ }
206
+
207
+ interface StaticRdtTabsConfig {
208
+ shortcuts: Map<RdtShortcut, string>;
209
+ }
210
+ declare class StaticRdtTabsShortcutStrategy implements RdtTabsShortcutStrategy {
211
+ private config;
212
+ constructor(config: StaticRdtTabsConfig);
213
+ updateShortcuts(): RdtShortcut[];
214
+ onShortcut(shortcut: RdtShortcut, ctrl: RdtTabControllerDirective): void;
215
+ }
216
+
217
+ export { RdtDestroyInactiveDirective, RdtTabComponent, RdtTabContainerComponent, RdtTabControllerDirective, RdtTabMode, RdtTabsModule, RdtTabsShortcutStrategy, StaticRdtTabsShortcutStrategy };
218
+ export type { RdtTabContainerState, RdtTabState, StaticRdtTabsConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngrdt/tabs",
3
- "version": "0.0.3",
3
+ "version": "v0.0.18",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=18.2.0",
6
6
  "@angular/core": ">=18.2.0",
@@ -18,8 +18,6 @@
18
18
  },
19
19
  ".": {
20
20
  "types": "./index.d.ts",
21
- "esm2022": "./esm2022/ngrdt-tabs.mjs",
22
- "esm": "./esm2022/ngrdt-tabs.mjs",
23
21
  "default": "./fesm2022/ngrdt-tabs.mjs"
24
22
  }
25
23
  },
package/esm2022/index.mjs DELETED
@@ -1,9 +0,0 @@
1
- export * from './lib/components/tab-container/rdt-tab-container.component';
2
- export * from './lib/components/tab/rdt-tab.component';
3
- export * from './lib/directives/rdt-destroy-inactive.directive';
4
- export * from './lib/directives/rdt-tab-controller.directive';
5
- export * from './lib/rdt-tabs-models';
6
- export * from './lib/rdt-tabs.module';
7
- export * from './lib/strategies/rdt-tabs-shortcut-strategy';
8
- export * from './lib/strategies/static-rdt-tabs-shortcut-strategy';
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9AbmdyZHQvdGFicy9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyw0REFBNEQsQ0FBQztBQUMzRSxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsaURBQWlELENBQUM7QUFDaEUsY0FBYywrQ0FBK0MsQ0FBQztBQUM5RCxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyw2Q0FBNkMsQ0FBQztBQUM1RCxjQUFjLG9EQUFvRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy90YWItY29udGFpbmVyL3JkdC10YWItY29udGFpbmVyLmNvbXBvbmVudCc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL3RhYi9yZHQtdGFiLmNvbXBvbmVudCc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9kaXJlY3RpdmVzL3JkdC1kZXN0cm95LWluYWN0aXZlLmRpcmVjdGl2ZSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9kaXJlY3RpdmVzL3JkdC10YWItY29udHJvbGxlci5kaXJlY3RpdmUnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvcmR0LXRhYnMtbW9kZWxzJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3JkdC10YWJzLm1vZHVsZSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9zdHJhdGVnaWVzL3JkdC10YWJzLXNob3J0Y3V0LXN0cmF0ZWd5JztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3N0cmF0ZWdpZXMvc3RhdGljLXJkdC10YWJzLXNob3J0Y3V0LXN0cmF0ZWd5JztcbiJdfQ==
@@ -1,145 +0,0 @@
1
- import { booleanAttribute, ChangeDetectionStrategy, Component, ContentChild, DestroyRef, inject, Injector, Input, TemplateRef, ViewChild, } from '@angular/core';
2
- import { RDT_GUARDED_COMPONENT, RdtContainerDirective, } from '@ngrdt/core';
3
- import { RdtDestroyInactiveDirective } from '../../directives/rdt-destroy-inactive.directive';
4
- import { RdtTabContainerComponent } from '../tab-container/rdt-tab-container.component';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "@ngrdt/core";
7
- export class RdtTabComponent {
8
- injector = inject(Injector);
9
- destroyRef = inject(DestroyRef);
10
- _contDir;
11
- get contDir() {
12
- return this._contDir;
13
- }
14
- get stateId() {
15
- if (this._stateId === null) {
16
- if (this.label !== '') {
17
- this._stateId = this.label;
18
- }
19
- else {
20
- const index = this.tabContainer?.tabsList?.toArray().indexOf(this);
21
- this._stateId = `tab-${index}`;
22
- }
23
- }
24
- return this._stateId;
25
- }
26
- set stateId(value) {
27
- this._stateId = value;
28
- }
29
- _stateId = null;
30
- disabled = false;
31
- visible = true;
32
- label;
33
- formAutofocus = true;
34
- buttonClass = null;
35
- implicitContent;
36
- explicitContent;
37
- get templateRef() {
38
- return this.explicitContent ?? this.implicitContent;
39
- }
40
- tabContainer = inject(RdtTabContainerComponent);
41
- //get forms() {
42
- // return this.getChildrenByClass(RdtBaseFormComponent);
43
- //}
44
- get childContainers() {
45
- return this.contDir.getChildrenByClass(RdtTabContainerComponent);
46
- }
47
- rdtIsActive() {
48
- return (this.visible && !this.disabled && this.tabContainer.activeTab === this);
49
- }
50
- ngOnInit() {
51
- this._contDir = this.injector.get(RdtContainerDirective);
52
- }
53
- ngOnChanges(changes) {
54
- if ('label' in changes ||
55
- 'value' in changes ||
56
- 'visible' in changes ||
57
- 'stateId' in changes) {
58
- this.tabContainer.cd.markForCheck();
59
- }
60
- }
61
- get isTopLevel() {
62
- return this.tabContainer.isTopLevel;
63
- }
64
- getState() {
65
- return {
66
- id: this.stateId,
67
- containerStates: this.childContainers.map((cont) => cont.getState()),
68
- };
69
- }
70
- applyState(state) {
71
- const states = [...state.containerStates];
72
- const conts = this.childContainers;
73
- const minLen = Math.min(states.length, conts.length);
74
- for (let i = 0; i < minLen; i++) {
75
- if (conts[i].stateId === states[i].id) {
76
- conts[i].applyState(states[i]);
77
- conts[i] = states[i] = null;
78
- }
79
- }
80
- conts.forEach((cont, contI) => {
81
- if (!cont) {
82
- return;
83
- }
84
- for (let offset = 0; offset < states.length; offset++) {
85
- const prev = contI - offset;
86
- const next = contI + offset;
87
- if (prev > 0 && states[prev]?.id === cont.stateId) {
88
- cont.applyState(states[prev]);
89
- states[prev] = null;
90
- return;
91
- }
92
- else if (next < states.length && states[next]?.id === cont.stateId) {
93
- cont.applyState(states[next]);
94
- states[next] = null;
95
- return;
96
- }
97
- }
98
- });
99
- }
100
- focusForm() {
101
- //TODO: getRdtAutofocusable(this.forms)?.rdtFocus();
102
- }
103
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
104
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "18.2.7", type: RdtTabComponent, selector: "rdt-tab", inputs: { stateId: "stateId", disabled: ["disabled", "disabled", booleanAttribute], visible: ["visible", "visible", booleanAttribute], label: "label", formAutofocus: ["formAutofocus", "formAutofocus", booleanAttribute], buttonClass: "buttonClass" }, providers: [
105
- {
106
- provide: RDT_GUARDED_COMPONENT,
107
- useExisting: RdtTabComponent,
108
- },
109
- ], queries: [{ propertyName: "explicitContent", first: true, predicate: RdtDestroyInactiveDirective, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "implicitContent", first: true, predicate: TemplateRef, descendants: true, static: true }], usesOnChanges: true, hostDirectives: [{ directive: i1.RdtContainerDirective }], ngImport: i0, template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
110
- }
111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtTabComponent, decorators: [{
112
- type: Component,
113
- args: [{ selector: 'rdt-tab', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
114
- {
115
- provide: RDT_GUARDED_COMPONENT,
116
- useExisting: RdtTabComponent,
117
- },
118
- ], hostDirectives: [RdtContainerDirective], template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n" }]
119
- }], propDecorators: { stateId: [{
120
- type: Input
121
- }], disabled: [{
122
- type: Input,
123
- args: [{ transform: booleanAttribute }]
124
- }], visible: [{
125
- type: Input,
126
- args: [{ transform: booleanAttribute }]
127
- }], label: [{
128
- type: Input,
129
- args: [{ required: true }]
130
- }], formAutofocus: [{
131
- type: Input,
132
- args: [{ transform: booleanAttribute }]
133
- }], buttonClass: [{
134
- type: Input
135
- }], implicitContent: [{
136
- type: ViewChild,
137
- args: [TemplateRef, { static: true }]
138
- }], explicitContent: [{
139
- type: ContentChild,
140
- args: [RdtDestroyInactiveDirective, {
141
- read: TemplateRef,
142
- static: true,
143
- }]
144
- }] } });
145
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmR0LXRhYi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9AbmdyZHQvdGFicy9zcmMvbGliL2NvbXBvbmVudHMvdGFiL3JkdC10YWIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vQG5ncmR0L3RhYnMvc3JjL2xpYi9jb21wb25lbnRzL3RhYi9yZHQtdGFiLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUlMLFdBQVcsRUFDWCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixxQkFBcUIsR0FFdEIsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0saURBQWlELENBQUM7QUFFOUYsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sOENBQThDLENBQUM7OztBQWN4RixNQUFNLE9BQU8sZUFBZTtJQUNULFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUVqQyxRQUFRLENBQXlCO0lBQ3pDLElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFDSSxPQUFPO1FBQ1QsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzNCLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQzdCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFN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Z0IsNENBM0N6QjtZQUNUO2dCQUNFLE9BQU8sRUFBRSxxQkFBcUI7Z0JBQzlCLFdBQVcsRUFBRSxlQUFlO2FBQzdCO1NBQ0YsdUVBK0NhLDJCQUEyQiwyQkFDakMsV0FBVyw0RkFKUixXQUFXLDhJQzlFeEIsOERBR0E7OzJGRGtDYSxlQUFlO2tCQVozQixTQUFTOytCQUNFLFNBQVMsbUJBRUYsdUJBQXVCLENBQUMsTUFBTSxhQUNwQzt3QkFDVDs0QkFDRSxPQUFPLEVBQUUscUJBQXFCOzRCQUM5QixXQUFXLGlCQUFpQjt5QkFDN0I7cUJBQ0Ysa0JBQ2UsQ0FBQyxxQkFBcUIsQ0FBQzs4QkFZbkMsT0FBTztzQkFEVixLQUFLO2dCQWtCTixRQUFRO3NCQURQLEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBSXRDLE9BQU87c0JBRE4sS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFJdEMsS0FBSztzQkFESixLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFJekIsYUFBYTtzQkFEWixLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUl0QyxXQUFXO3NCQURWLEtBQUs7Z0JBSVcsZUFBZTtzQkFEL0IsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQU92QixlQUFlO3NCQUovQixZQUFZO3VCQUFDLDJCQUEyQixFQUFFO3dCQUN6QyxJQUFJLEVBQUUsV0FBVzt3QkFDakIsTUFBTSxFQUFFLElBQUk7cUJBQ2IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBib29sZWFuQXR0cmlidXRlLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGQsXG4gIERlc3Ryb3lSZWYsXG4gIGluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBSRFRfR1VBUkRFRF9DT01QT05FTlQsXG4gIFJkdENvbnRhaW5lckRpcmVjdGl2ZSxcbiAgUmR0SXNBY3RpdmUsXG59IGZyb20gJ0BuZ3JkdC9jb3JlJztcbmltcG9ydCB7IE51bGxhYmxlIH0gZnJvbSAnQG5ncmR0L3V0aWxzJztcbmltcG9ydCB7IFJkdERlc3Ryb3lJbmFjdGl2ZURpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvcmR0LWRlc3Ryb3ktaW5hY3RpdmUuZGlyZWN0aXZlJztcbmltcG9ydCB7IFJkdFRhYkNvbnRhaW5lclN0YXRlLCBSZHRUYWJTdGF0ZSB9IGZyb20gJy4uLy4uL3JkdC10YWJzLW1vZGVscyc7XG5pbXBvcnQgeyBSZHRUYWJDb250YWluZXJDb21wb25lbnQgfSBmcm9tICcuLi90YWItY29udGFpbmVyL3JkdC10YWItY29udGFpbmVyLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3JkdC10YWInLFxuICB0ZW1wbGF0ZVVybDogJy4vcmR0LXRhYi5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBSRFRfR1VBUkRFRF9DT01QT05FTlQsXG4gICAgICB1c2VFeGlzdGluZzogUmR0VGFiQ29tcG9uZW50LFxuICAgIH0sXG4gIF0sXG4gIGhvc3REaXJlY3RpdmVzOiBbUmR0Q29udGFpbmVyRGlyZWN0aXZlXSxcbn0pXG5leHBvcnQgY2xhc3MgUmR0VGFiQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIFJkdElzQWN0aXZlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmplY3RvciA9IGluamVjdChJbmplY3Rvcik7XG4gIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHJpdmF0ZSBfY29udERpciE6IFJkdENvbnRhaW5lckRpcmVjdGl2ZTtcbiAgZ2V0IGNvbnREaXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbnREaXI7XG4gIH1cblxuICBASW5wdXQoKVxuICBnZXQgc3RhdGVJZCgpIHtcbiAgICBpZiAodGhpcy5fc3RhdGVJZCA9PT0gbnVsbCkge1xuICAgICAgaWYgKHRoaXMubGFiZWwgIT09ICcnKSB7XG4gICAgICAgIHRoaXMuX3N0YXRlSWQgPSB0aGlzLmxhYmVsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnRhYkNvbnRhaW5lcj8udGFic0xpc3Q/LnRvQXJyYXkoKS5pbmRleE9mKHRoaXMpO1xuICAgICAgICB0aGlzLl9zdGF0ZUlkID0gYHRhYi0ke2luZGV4fWA7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9zdGF0ZUlkO1xuICB9XG4gIHNldCBzdGF0ZUlkKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9zdGF0ZUlkID0gdmFsdWU7XG4gIH1cbiAgcHJpdmF0ZSBfc3RhdGVJZDogc3RyaW5nID0gbnVsbCBhcyB1bmtub3duIGFzIHN0cmluZztcblxuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSlcbiAgZGlzYWJsZWQgPSBmYWxzZTtcblxuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSlcbiAgdmlzaWJsZSA9IHRydWU7XG5cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcbiAgbGFiZWwhOiBzdHJpbmc7XG5cbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pXG4gIGZvcm1BdXRvZm9jdXMgPSB0cnVlO1xuXG4gIEBJbnB1dCgpXG4gIGJ1dHRvbkNsYXNzOiBOdWxsYWJsZTxzdHJpbmc+ID0gbnVsbDtcblxuICBAVmlld0NoaWxkKFRlbXBsYXRlUmVmLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICBwcml2YXRlIHJlYWRvbmx5IGltcGxpY2l0Q29udGVudCE6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgQENvbnRlbnRDaGlsZChSZHREZXN0cm95SW5hY3RpdmVEaXJlY3RpdmUsIHtcbiAgICByZWFkOiBUZW1wbGF0ZVJlZixcbiAgICBzdGF0aWM6IHRydWUsXG4gIH0pXG4gIHByaXZhdGUgcmVhZG9ubHkgZXhwbGljaXRDb250ZW50ITogVGVtcGxhdGVSZWY8YW55PjtcblxuICBnZXQgdGVtcGxhdGVSZWYoKSB7XG4gICAgcmV0dXJuIHRoaXMuZXhwbGljaXRDb250ZW50ID8/IHRoaXMuaW1wbGljaXRDb250ZW50O1xuICB9XG5cbiAgcmVhZG9ubHkgdGFiQ29udGFpbmVyID0gaW5qZWN0KFJkdFRhYkNvbnRhaW5lckNvbXBvbmVudCk7XG5cbiAgLy9nZXQgZm9ybXMoKSB7XG4gIC8vICByZXR1cm4gdGhpcy5nZXRDaGlsZHJlbkJ5Q2xhc3MoUmR0QmFzZUZvcm1Db21wb25lbnQpO1xuICAvL31cblxuICBnZXQgY2hpbGRDb250YWluZXJzKCkge1xuICAgIHJldHVybiB0aGlzLmNvbnREaXIuZ2V0Q2hpbGRyZW5CeUNsYXNzKFJkdFRhYkNvbnRhaW5lckNvbXBvbmVudCk7XG4gIH1cblxuICByZHRJc0FjdGl2ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy52aXNpYmxlICYmICF0aGlzLmRpc2FibGVkICYmIHRoaXMudGFiQ29udGFpbmVyLmFjdGl2ZVRhYiA9PT0gdGhpc1xuICAgICk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLl9jb250RGlyID0gdGhpcy5pbmplY3Rvci5nZXQoUmR0Q29udGFpbmVyRGlyZWN0aXZlKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoXG4gICAgICAnbGFiZWwnIGluIGNoYW5nZXMgfHxcbiAgICAgICd2YWx1ZScgaW4gY2hhbmdlcyB8fFxuICAgICAgJ3Zpc2libGUnIGluIGNoYW5nZXMgfHxcbiAgICAgICdzdGF0ZUlkJyBpbiBjaGFuZ2VzXG4gICAgKSB7XG4gICAgICB0aGlzLnRhYkNvbnRhaW5lci5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaXNUb3BMZXZlbCgpIHtcbiAgICByZXR1cm4gdGhpcy50YWJDb250YWluZXIuaXNUb3BMZXZlbDtcbiAgfVxuXG4gIGdldFN0YXRlKCk6IFJkdFRhYlN0YXRlIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHRoaXMuc3RhdGVJZCxcbiAgICAgIGNvbnRhaW5lclN0YXRlczogdGhpcy5jaGlsZENvbnRhaW5lcnMubWFwKChjb250KSA9PiBjb250LmdldFN0YXRlKCkpLFxuICAgIH07XG4gIH1cblxuICBhcHBseVN0YXRlKHN0YXRlOiBSZHRUYWJTdGF0ZSkge1xuICAgIGNvbnN0IHN0YXRlczogKFJkdFRhYkNvbnRhaW5lclN0YXRlIHwgbnVsbClbXSA9IFsuLi5zdGF0ZS5jb250YWluZXJTdGF0ZXNdO1xuICAgIGNvbnN0IGNvbnRzOiAoUmR0VGFiQ29udGFpbmVyQ29tcG9uZW50IHwgbnVsbClbXSA9IHRoaXMuY2hpbGRDb250YWluZXJzO1xuICAgIGNvbnN0IG1pbkxlbiA9IE1hdGgubWluKHN0YXRlcy5sZW5ndGgsIGNvbnRzLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1pbkxlbjsgaSsrKSB7XG4gICAgICBpZiAoY29udHNbaV0hLnN0YXRlSWQgPT09IHN0YXRlc1tpXSEuaWQpIHtcbiAgICAgICAgY29udHNbaV0hLmFwcGx5U3RhdGUoc3RhdGVzW2ldISk7XG4gICAgICAgIGNvbnRzW2ldID0gc3RhdGVzW2ldID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29udHMuZm9yRWFjaCgoY29udCwgY29udEkpID0+IHtcbiAgICAgIGlmICghY29udCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBmb3IgKGxldCBvZmZzZXQgPSAwOyBvZmZzZXQgPCBzdGF0ZXMubGVuZ3RoOyBvZmZzZXQrKykge1xuICAgICAgICBjb25zdCBwcmV2ID0gY29udEkgLSBvZmZzZXQ7XG4gICAgICAgIGNvbnN0IG5leHQgPSBjb250SSArIG9mZnNldDtcbiAgICAgICAgaWYgKHByZXYgPiAwICYmIHN0YXRlc1twcmV2XT8uaWQgPT09IGNvbnQuc3RhdGVJZCkge1xuICAgICAgICAgIGNvbnQuYXBwbHlTdGF0ZShzdGF0ZXNbcHJldl0hKTtcbiAgICAgICAgICBzdGF0ZXNbcHJldl0gPSBudWxsO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChuZXh0IDwgc3RhdGVzLmxlbmd0aCAmJiBzdGF0ZXNbbmV4dF0/LmlkID09PSBjb250LnN0YXRlSWQpIHtcbiAgICAgICAgICBjb250LmFwcGx5U3RhdGUoc3RhdGVzW25leHRdISk7XG4gICAgICAgICAgc3RhdGVzW25leHRdID0gbnVsbDtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZvY3VzRm9ybSgpIHtcbiAgICAvL1RPRE86IGdldFJkdEF1dG9mb2N1c2FibGUodGhpcy5mb3Jtcyk/LnJkdEZvY3VzKCk7XG4gIH1cbn1cbiIsIjxuZy10ZW1wbGF0ZT5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==