@decaf-ts/for-angular 0.0.10 → 0.0.12

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.
Files changed (163) hide show
  1. package/dist/for-angular/cli/cli-module.d.ts +22 -0
  2. package/dist/for-angular/cli/cli-module.d.ts.map +1 -0
  3. package/dist/for-angular/cli/cli-module.js +131 -0
  4. package/dist/for-angular/cli/cli-module.js.map +1 -0
  5. package/dist/{components → lib/components}/component-renderer/component-renderer.component.d.ts +1 -0
  6. package/dist/lib/components/component-renderer/component-renderer.component.d.ts.map +1 -0
  7. package/dist/{components → lib/components}/crud-field/crud-field.component.d.ts +1 -0
  8. package/dist/lib/components/crud-field/crud-field.component.d.ts.map +1 -0
  9. package/dist/{components → lib/components}/crud-form/constants.d.ts +1 -0
  10. package/dist/lib/components/crud-form/constants.d.ts.map +1 -0
  11. package/dist/{components → lib/components}/crud-form/crud-form.component.d.ts +1 -0
  12. package/dist/lib/components/crud-form/crud-form.component.d.ts.map +1 -0
  13. package/dist/{components → lib/components}/crud-form/types.d.ts +1 -0
  14. package/dist/lib/components/crud-form/types.d.ts.map +1 -0
  15. package/dist/{components → lib/components}/empty-state/empty-state.component.d.ts +1 -0
  16. package/dist/lib/components/empty-state/empty-state.component.d.ts.map +1 -0
  17. package/dist/{components → lib/components}/fieldset/fieldset.component.d.ts +1 -0
  18. package/dist/lib/components/fieldset/fieldset.component.d.ts.map +1 -0
  19. package/dist/{components → lib/components}/filter/filter.component.d.ts +1 -0
  20. package/dist/lib/components/filter/filter.component.d.ts.map +1 -0
  21. package/dist/{components → lib/components}/for-angular-components.module.d.ts +1 -0
  22. package/dist/lib/components/for-angular-components.module.d.ts.map +1 -0
  23. package/dist/{components → lib/components}/index.d.ts +1 -0
  24. package/dist/lib/components/index.d.ts.map +1 -0
  25. package/dist/{components → lib/components}/layout/layout.component.d.ts +1 -0
  26. package/dist/lib/components/layout/layout.component.d.ts.map +1 -0
  27. package/dist/{components → lib/components}/list/constants.d.ts +1 -0
  28. package/dist/lib/components/list/constants.d.ts.map +1 -0
  29. package/dist/{components → lib/components}/list/list.component.d.ts +1 -0
  30. package/dist/lib/components/list/list.component.d.ts.map +1 -0
  31. package/dist/{components → lib/components}/list-item/list-item.component.d.ts +1 -0
  32. package/dist/lib/components/list-item/list-item.component.d.ts.map +1 -0
  33. package/dist/{components → lib/components}/model-renderer/model-renderer.component.d.ts +1 -0
  34. package/dist/lib/components/model-renderer/model-renderer.component.d.ts.map +1 -0
  35. package/dist/{components → lib/components}/pagination/constants.d.ts +1 -0
  36. package/dist/lib/components/pagination/constants.d.ts.map +1 -0
  37. package/dist/{components → lib/components}/pagination/pagination.component.d.ts +1 -0
  38. package/dist/lib/components/pagination/pagination.component.d.ts.map +1 -0
  39. package/dist/{components → lib/components}/searchbar/searchbar.component.d.ts +1 -0
  40. package/dist/lib/components/searchbar/searchbar.component.d.ts.map +1 -0
  41. package/dist/lib/decaf-ts-for-angular.d.ts.map +1 -0
  42. package/dist/{directives → lib/directives}/collapsable.directive.d.ts +1 -0
  43. package/dist/lib/directives/collapsable.directive.d.ts.map +1 -0
  44. package/dist/{directives → lib/directives}/index.d.ts +1 -0
  45. package/dist/lib/directives/index.d.ts.map +1 -0
  46. package/dist/{engine → lib/engine}/DynamicModule.d.ts +1 -0
  47. package/dist/lib/engine/DynamicModule.d.ts.map +1 -0
  48. package/dist/{engine → lib/engine}/NgxBaseComponent.d.ts +1 -0
  49. package/dist/lib/engine/NgxBaseComponent.d.ts.map +1 -0
  50. package/dist/{engine → lib/engine}/NgxCrudFormField.d.ts +1 -0
  51. package/dist/lib/engine/NgxCrudFormField.d.ts.map +1 -0
  52. package/dist/{engine → lib/engine}/NgxFormService.d.ts +1 -0
  53. package/dist/lib/engine/NgxFormService.d.ts.map +1 -0
  54. package/dist/{engine → lib/engine}/NgxRenderingEngine.d.ts +1 -0
  55. package/dist/lib/engine/NgxRenderingEngine.d.ts.map +1 -0
  56. package/dist/{engine → lib/engine}/NgxRenderingEngine2.d.ts +1 -0
  57. package/dist/lib/engine/NgxRenderingEngine2.d.ts.map +1 -0
  58. package/dist/{engine → lib/engine}/ValidatorFactory.d.ts +1 -0
  59. package/dist/lib/engine/ValidatorFactory.d.ts.map +1 -0
  60. package/dist/{engine → lib/engine}/constants.d.ts +1 -0
  61. package/dist/lib/engine/constants.d.ts.map +1 -0
  62. package/dist/{engine → lib/engine}/decorators.d.ts +1 -0
  63. package/dist/lib/engine/decorators.d.ts.map +1 -0
  64. package/dist/{engine → lib/engine}/index.d.ts +1 -0
  65. package/dist/lib/engine/index.d.ts.map +1 -0
  66. package/dist/{engine → lib/engine}/types.d.ts +1 -0
  67. package/dist/lib/engine/types.d.ts.map +1 -0
  68. package/dist/lib/esm2022/components/component-renderer/component-renderer.component.mjs +359 -0
  69. package/dist/lib/esm2022/components/crud-field/crud-field.component.mjs +456 -0
  70. package/dist/lib/esm2022/components/crud-form/constants.mjs +14 -0
  71. package/dist/lib/esm2022/components/crud-form/crud-form.component.mjs +272 -0
  72. package/dist/lib/esm2022/components/crud-form/types.mjs +2 -0
  73. package/dist/lib/esm2022/components/empty-state/empty-state.component.mjs +410 -0
  74. package/dist/lib/esm2022/components/fieldset/fieldset.component.mjs +250 -0
  75. package/dist/lib/esm2022/components/filter/filter.component.mjs +906 -0
  76. package/dist/lib/esm2022/components/for-angular-components.module.mjs +72 -0
  77. package/dist/lib/esm2022/components/index.mjs +20 -0
  78. package/dist/lib/esm2022/components/layout/layout.component.mjs +245 -0
  79. package/dist/lib/esm2022/components/list/constants.mjs +6 -0
  80. package/dist/lib/esm2022/components/list/list.component.mjs +1405 -0
  81. package/dist/lib/esm2022/components/list-item/list-item.component.mjs +612 -0
  82. package/dist/lib/esm2022/components/model-renderer/model-renderer.component.mjs +182 -0
  83. package/dist/lib/esm2022/components/pagination/constants.mjs +2 -0
  84. package/dist/lib/esm2022/components/pagination/pagination.component.mjs +364 -0
  85. package/dist/lib/esm2022/components/searchbar/searchbar.component.mjs +503 -0
  86. package/dist/lib/esm2022/decaf-ts-for-angular.mjs +5 -0
  87. package/dist/lib/esm2022/directives/collapsable.directive.mjs +28 -0
  88. package/dist/lib/esm2022/directives/index.mjs +2 -0
  89. package/dist/lib/esm2022/engine/DynamicModule.mjs +18 -0
  90. package/dist/lib/esm2022/engine/NgxBaseComponent.mjs +546 -0
  91. package/dist/lib/esm2022/engine/NgxCrudFormField.mjs +125 -0
  92. package/dist/lib/esm2022/engine/NgxFormService.mjs +315 -0
  93. package/dist/lib/esm2022/engine/NgxRenderingEngine.mjs +192 -0
  94. package/dist/lib/esm2022/engine/NgxRenderingEngine2.mjs +332 -0
  95. package/dist/lib/esm2022/engine/ValidatorFactory.mjs +102 -0
  96. package/dist/lib/esm2022/engine/constants.mjs +160 -0
  97. package/dist/lib/esm2022/engine/decorators.mjs +38 -0
  98. package/dist/lib/esm2022/engine/index.mjs +17 -0
  99. package/dist/lib/esm2022/engine/types.mjs +4 -0
  100. package/dist/lib/esm2022/for-angular.module.mjs +119 -0
  101. package/dist/lib/esm2022/helpers/index.mjs +13 -0
  102. package/dist/lib/esm2022/helpers/utils.mjs +415 -0
  103. package/dist/lib/esm2022/interfaces.mjs +2 -0
  104. package/dist/lib/esm2022/public-apis.mjs +14 -0
  105. package/dist/{fesm2022 → lib/fesm2022}/decaf-ts-for-angular.mjs +1805 -621
  106. package/dist/lib/fesm2022/decaf-ts-for-angular.mjs.map +1 -0
  107. package/dist/{for-angular.module.d.ts → lib/for-angular.module.d.ts} +1 -0
  108. package/dist/lib/for-angular.module.d.ts.map +1 -0
  109. package/dist/{helpers → lib/helpers}/index.d.ts +1 -0
  110. package/dist/lib/helpers/index.d.ts.map +1 -0
  111. package/dist/{helpers → lib/helpers}/utils.d.ts +1 -0
  112. package/dist/lib/helpers/utils.d.ts.map +1 -0
  113. package/dist/{index.d.ts → lib/index.d.ts} +1 -0
  114. package/dist/{interfaces.d.ts → lib/interfaces.d.ts} +1 -0
  115. package/dist/lib/interfaces.d.ts.map +1 -0
  116. package/dist/{public-apis.d.ts → lib/public-apis.d.ts} +1 -0
  117. package/dist/lib/public-apis.d.ts.map +1 -0
  118. package/package.json +3 -2
  119. package/dist/esm2022/components/component-renderer/component-renderer.component.mjs +0 -313
  120. package/dist/esm2022/components/crud-field/crud-field.component.mjs +0 -301
  121. package/dist/esm2022/components/crud-form/constants.mjs +0 -14
  122. package/dist/esm2022/components/crud-form/crud-form.component.mjs +0 -139
  123. package/dist/esm2022/components/crud-form/types.mjs +0 -2
  124. package/dist/esm2022/components/empty-state/empty-state.component.mjs +0 -348
  125. package/dist/esm2022/components/fieldset/fieldset.component.mjs +0 -225
  126. package/dist/esm2022/components/filter/filter.component.mjs +0 -689
  127. package/dist/esm2022/components/for-angular-components.module.mjs +0 -71
  128. package/dist/esm2022/components/index.mjs +0 -20
  129. package/dist/esm2022/components/layout/layout.component.mjs +0 -176
  130. package/dist/esm2022/components/list/constants.mjs +0 -6
  131. package/dist/esm2022/components/list/list.component.mjs +0 -1236
  132. package/dist/esm2022/components/list-item/list-item.component.mjs +0 -408
  133. package/dist/esm2022/components/model-renderer/model-renderer.component.mjs +0 -138
  134. package/dist/esm2022/components/pagination/constants.mjs +0 -2
  135. package/dist/esm2022/components/pagination/pagination.component.mjs +0 -323
  136. package/dist/esm2022/components/searchbar/searchbar.component.mjs +0 -493
  137. package/dist/esm2022/decaf-ts-for-angular.mjs +0 -5
  138. package/dist/esm2022/directives/collapsable.directive.mjs +0 -28
  139. package/dist/esm2022/directives/index.mjs +0 -2
  140. package/dist/esm2022/engine/DynamicModule.mjs +0 -18
  141. package/dist/esm2022/engine/NgxBaseComponent.mjs +0 -539
  142. package/dist/esm2022/engine/NgxCrudFormField.mjs +0 -125
  143. package/dist/esm2022/engine/NgxFormService.mjs +0 -315
  144. package/dist/esm2022/engine/NgxRenderingEngine.mjs +0 -192
  145. package/dist/esm2022/engine/NgxRenderingEngine2.mjs +0 -332
  146. package/dist/esm2022/engine/ValidatorFactory.mjs +0 -102
  147. package/dist/esm2022/engine/constants.mjs +0 -160
  148. package/dist/esm2022/engine/decorators.mjs +0 -38
  149. package/dist/esm2022/engine/index.mjs +0 -17
  150. package/dist/esm2022/engine/types.mjs +0 -4
  151. package/dist/esm2022/for-angular.module.mjs +0 -118
  152. package/dist/esm2022/helpers/index.mjs +0 -13
  153. package/dist/esm2022/helpers/utils.mjs +0 -415
  154. package/dist/esm2022/interfaces.mjs +0 -2
  155. package/dist/esm2022/public-apis.mjs +0 -14
  156. package/dist/fesm2022/decaf-ts-for-angular.mjs.map +0 -1
  157. /package/dist/{README.md → lib/README.md} +0 -0
  158. /package/dist/{assets → lib/assets}/i18n/en.json +0 -0
  159. /package/dist/{assets → lib/assets}/images/angular-logo.svg +0 -0
  160. /package/dist/{assets → lib/assets}/images/decaf-logo-black.svg +0 -0
  161. /package/dist/{assets → lib/assets}/images/decaf-logo-lw.svg +0 -0
  162. /package/dist/{assets → lib/assets}/images/decaf-logo-white.svg +0 -0
  163. /package/dist/{assets → lib/assets}/images/decaf-logo.svg +0 -0
@@ -0,0 +1,906 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
3
+ import { ForAngularModule } from '../../for-angular.module';
4
+ import { NgxBaseComponent } from '../../engine/NgxBaseComponent';
5
+ import { IonChip, IonIcon, IonItem, IonLabel, IonSelect } from '@ionic/angular/standalone';
6
+ import { Dynamic } from '../../engine';
7
+ import { getWindowWidth } from '../../helpers/utils';
8
+ import { debounceTime, fromEvent } from 'rxjs';
9
+ import { OrderDirection, Repository } from '@decaf-ts/core';
10
+ import { SearchbarComponent } from '../searchbar/searchbar.component';
11
+ import { addIcons } from 'ionicons';
12
+ import { chevronDownOutline, chevronUpOutline } from 'ionicons/icons';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@ionic/angular/standalone";
15
+ import * as i2 from "@angular/common";
16
+ import * as i3 from "@angular/forms";
17
+ import * as i4 from "@ngx-translate/core";
18
+ const _c0 = ["optionsFilterElement"];
19
+ function _forTrack0($index, $item) { return this.trackItemFn($index, $item == null ? null : $item["index"]); }
20
+ const _c1 = a0 => ({ "dcf-hidden": a0 });
21
+ function FilterComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
22
+ const _r2 = i0.ɵɵgetCurrentView();
23
+ i0.ɵɵelementStart(0, "ngx-decaf-searchbar", 15);
24
+ i0.ɵɵlistener("searchEvent", function FilterComponent_Conditional_0_Template_ngx_decaf_searchbar_searchEvent_0_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.handleSearch($event)); });
25
+ i0.ɵɵelementEnd();
26
+ } if (rf & 2) {
27
+ i0.ɵɵproperty("emitEventToWindow", false)("debounce", 500);
28
+ } }
29
+ function FilterComponent_For_6_Conditional_0_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelementStart(0, "ion-chip", 16);
31
+ i0.ɵɵtext(1);
32
+ i0.ɵɵelementEnd();
33
+ } if (rf & 2) {
34
+ const filter_r4 = i0.ɵɵnextContext().$implicit;
35
+ i0.ɵɵproperty("outline", true);
36
+ i0.ɵɵadvance();
37
+ i0.ɵɵtextInterpolate(filter_r4 == null ? null : filter_r4["index"]);
38
+ } }
39
+ function FilterComponent_For_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
40
+ i0.ɵɵelementStart(0, "ion-chip", 16);
41
+ i0.ɵɵtext(1);
42
+ i0.ɵɵelementEnd();
43
+ } if (rf & 2) {
44
+ const filter_r4 = i0.ɵɵnextContext().$implicit;
45
+ i0.ɵɵproperty("outline", true);
46
+ i0.ɵɵadvance();
47
+ i0.ɵɵtextInterpolate(filter_r4 == null ? null : filter_r4["condition"]);
48
+ } }
49
+ function FilterComponent_For_6_Conditional_2_Template(rf, ctx) { if (rf & 1) {
50
+ const _r5 = i0.ɵɵgetCurrentView();
51
+ i0.ɵɵelementStart(0, "ion-chip", 17);
52
+ i0.ɵɵtext(1);
53
+ i0.ɵɵelementStart(2, "ion-icon", 18);
54
+ i0.ɵɵlistener("click", function FilterComponent_For_6_Conditional_2_Template_ion_icon_click_2_listener() { i0.ɵɵrestoreView(_r5); const filter_r4 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.removeFilter(filter_r4 == null ? null : filter_r4["value"])); });
55
+ i0.ɵɵelementEnd()();
56
+ } if (rf & 2) {
57
+ const filter_r4 = i0.ɵɵnextContext().$implicit;
58
+ i0.ɵɵproperty("outline", true);
59
+ i0.ɵɵadvance();
60
+ i0.ɵɵtextInterpolate1(" ", filter_r4 == null ? null : filter_r4["value"], " ");
61
+ } }
62
+ function FilterComponent_For_6_Template(rf, ctx) { if (rf & 1) {
63
+ i0.ɵɵtemplate(0, FilterComponent_For_6_Conditional_0_Template, 2, 2, "ion-chip", 16)(1, FilterComponent_For_6_Conditional_1_Template, 2, 2, "ion-chip", 16)(2, FilterComponent_For_6_Conditional_2_Template, 3, 2, "ion-chip", 17);
64
+ } if (rf & 2) {
65
+ const filter_r4 = ctx.$implicit;
66
+ i0.ɵɵconditional((filter_r4 == null ? null : filter_r4["index"]) ? 0 : -1);
67
+ i0.ɵɵadvance();
68
+ i0.ɵɵconditional((filter_r4 == null ? null : filter_r4["condition"]) ? 1 : -1);
69
+ i0.ɵɵadvance();
70
+ i0.ɵɵconditional((filter_r4 == null ? null : filter_r4["value"]) ? 2 : -1);
71
+ } }
72
+ function FilterComponent_Conditional_11_Conditional_3_For_1_Template(rf, ctx) { if (rf & 1) {
73
+ const _r6 = i0.ɵɵgetCurrentView();
74
+ i0.ɵɵelementStart(0, "div", 21);
75
+ i0.ɵɵlistener("keydown.enter", function FilterComponent_Conditional_11_Conditional_3_For_1_Template_div_keydown_enter_0_listener() { const key_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectOption(key_r7)); })("click", function FilterComponent_Conditional_11_Conditional_3_For_1_Template_div_click_0_listener() { const key_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectOption(key_r7)); });
76
+ i0.ɵɵtext(1);
77
+ i0.ɵɵelementEnd();
78
+ } if (rf & 2) {
79
+ const key_r7 = ctx.$implicit;
80
+ i0.ɵɵadvance();
81
+ i0.ɵɵtextInterpolate1(" ", key_r7, " ");
82
+ } }
83
+ function FilterComponent_Conditional_11_Conditional_3_Template(rf, ctx) { if (rf & 1) {
84
+ i0.ɵɵrepeaterCreate(0, FilterComponent_Conditional_11_Conditional_3_For_1_Template, 2, 1, "div", 20, i0.ɵɵrepeaterTrackByIdentity);
85
+ } if (rf & 2) {
86
+ const ctx_r2 = i0.ɵɵnextContext(2);
87
+ i0.ɵɵrepeater(ctx_r2.filteredOptions);
88
+ } }
89
+ function FilterComponent_Conditional_11_Conditional_4_Template(rf, ctx) { if (rf & 1) {
90
+ const _r8 = i0.ɵɵgetCurrentView();
91
+ i0.ɵɵelementStart(0, "div", 22);
92
+ i0.ɵɵlistener("click", function FilterComponent_Conditional_11_Conditional_4_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.filteredOptions = ctx_r2.options; return i0.ɵɵresetView(ctx_r2.value = ""); })("keydown.enter", function FilterComponent_Conditional_11_Conditional_4_Template_div_keydown_enter_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.filteredOptions = ctx_r2.options; return i0.ɵɵresetView(ctx_r2.value = ""); });
93
+ i0.ɵɵtext(1);
94
+ i0.ɵɵpipe(2, "translate");
95
+ i0.ɵɵelementEnd();
96
+ } if (rf & 2) {
97
+ i0.ɵɵadvance();
98
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(2, 1, "no_suggestions"), " ");
99
+ } }
100
+ function FilterComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
101
+ i0.ɵɵelementStart(0, "div", null, 1)(2, "div");
102
+ i0.ɵɵtemplate(3, FilterComponent_Conditional_11_Conditional_3_Template, 2, 0)(4, FilterComponent_Conditional_11_Conditional_4_Template, 3, 3, "div", 19);
103
+ i0.ɵɵelementEnd()();
104
+ } if (rf & 2) {
105
+ const ctx_r2 = i0.ɵɵnextContext();
106
+ i0.ɵɵclassMap("dcf-dropdown " + (ctx_r2.options.length > 0 ? " dcf-active" : ""));
107
+ i0.ɵɵadvance(3);
108
+ i0.ɵɵconditional(ctx_r2.filteredOptions.length > 0 ? 3 : 4);
109
+ } }
110
+ function FilterComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
111
+ const _r9 = i0.ɵɵgetCurrentView();
112
+ i0.ɵɵelementStart(0, "div", 10)(1, "ion-button", 12);
113
+ i0.ɵɵlistener("click", function FilterComponent_Conditional_12_Template_ion_button_click_1_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.clear()); });
114
+ i0.ɵɵelement(2, "ion-icon", 23);
115
+ i0.ɵɵelementEnd()();
116
+ } }
117
+ function FilterComponent_Conditional_16_Conditional_3_For_1_Template(rf, ctx) { if (rf & 1) {
118
+ const _r10 = i0.ɵɵgetCurrentView();
119
+ i0.ɵɵelementStart(0, "div", 21);
120
+ i0.ɵɵlistener("keydown.enter", function FilterComponent_Conditional_16_Conditional_3_For_1_Template_div_keydown_enter_0_listener() { const key_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectOption(key_r11)); })("click", function FilterComponent_Conditional_16_Conditional_3_For_1_Template_div_click_0_listener() { const key_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectOption(key_r11)); });
121
+ i0.ɵɵtext(1);
122
+ i0.ɵɵelementEnd();
123
+ } if (rf & 2) {
124
+ const key_r11 = ctx.$implicit;
125
+ i0.ɵɵadvance();
126
+ i0.ɵɵtextInterpolate1(" ", key_r11, " ");
127
+ } }
128
+ function FilterComponent_Conditional_16_Conditional_3_Template(rf, ctx) { if (rf & 1) {
129
+ i0.ɵɵrepeaterCreate(0, FilterComponent_Conditional_16_Conditional_3_For_1_Template, 2, 1, "div", 20, i0.ɵɵrepeaterTrackByIdentity);
130
+ } if (rf & 2) {
131
+ const ctx_r2 = i0.ɵɵnextContext(2);
132
+ i0.ɵɵrepeater(ctx_r2.filteredOptions);
133
+ } }
134
+ function FilterComponent_Conditional_16_Conditional_4_Template(rf, ctx) { if (rf & 1) {
135
+ const _r12 = i0.ɵɵgetCurrentView();
136
+ i0.ɵɵelementStart(0, "div", 22);
137
+ i0.ɵɵlistener("click", function FilterComponent_Conditional_16_Conditional_4_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.filteredOptions = ctx_r2.options; return i0.ɵɵresetView(ctx_r2.value = ""); })("keydown.enter", function FilterComponent_Conditional_16_Conditional_4_Template_div_keydown_enter_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.filteredOptions = ctx_r2.options; return i0.ɵɵresetView(ctx_r2.value = ""); });
138
+ i0.ɵɵtext(1);
139
+ i0.ɵɵpipe(2, "translate");
140
+ i0.ɵɵelementEnd();
141
+ } if (rf & 2) {
142
+ i0.ɵɵadvance();
143
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(2, 1, "no_suggestions"), " ");
144
+ } }
145
+ function FilterComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵelementStart(0, "div", null, 1)(2, "div");
147
+ i0.ɵɵtemplate(3, FilterComponent_Conditional_16_Conditional_3_Template, 2, 0)(4, FilterComponent_Conditional_16_Conditional_4_Template, 3, 3, "div", 19);
148
+ i0.ɵɵelementEnd()();
149
+ } if (rf & 2) {
150
+ const ctx_r2 = i0.ɵɵnextContext();
151
+ i0.ɵɵclassMap("dcf-dropdown " + (ctx_r2.options.length > 0 ? " dcf-active" : ""));
152
+ i0.ɵɵadvance(3);
153
+ i0.ɵɵconditional(ctx_r2.filteredOptions.length > 0 ? 3 : 4);
154
+ } }
155
+ function FilterComponent_Conditional_17_For_5_Template(rf, ctx) { if (rf & 1) {
156
+ i0.ɵɵtext(0, " aa ");
157
+ i0.ɵɵelementStart(1, "ion-select-option", 26);
158
+ i0.ɵɵtext(2);
159
+ i0.ɵɵpipe(3, "translate");
160
+ i0.ɵɵelementEnd();
161
+ } if (rf & 2) {
162
+ const sort_r14 = ctx.$implicit;
163
+ i0.ɵɵadvance();
164
+ i0.ɵɵproperty("value", sort_r14);
165
+ i0.ɵɵadvance();
166
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 2, sort_r14));
167
+ } }
168
+ function FilterComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
169
+ const _r13 = i0.ɵɵgetCurrentView();
170
+ i0.ɵɵelementStart(0, "div", 14)(1, "div", 24)(2, "div", 4)(3, "ion-select", 25);
171
+ i0.ɵɵlistener("ionChange", function FilterComponent_Conditional_17_Template_ion_select_ionChange_3_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.handleSortChange($event)); });
172
+ i0.ɵɵrepeaterCreate(4, FilterComponent_Conditional_17_For_5_Template, 4, 4, "ion-select-option", 26, i0.ɵɵrepeaterTrackByIdentity);
173
+ i0.ɵɵelementEnd()();
174
+ i0.ɵɵelementStart(6, "div", 27)(7, "ion-button", 28);
175
+ i0.ɵɵlistener("click", function FilterComponent_Conditional_17_Template_ion_button_click_7_listener() { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.handleSortDirectionChange()); });
176
+ i0.ɵɵelement(8, "ion-icon", 29);
177
+ i0.ɵɵelementEnd()()()();
178
+ } if (rf & 2) {
179
+ const ctx_r2 = i0.ɵɵnextContext();
180
+ i0.ɵɵadvance(3);
181
+ i0.ɵɵproperty("value", ctx_r2.sortValue);
182
+ i0.ɵɵadvance();
183
+ i0.ɵɵrepeater(ctx_r2.sortBy);
184
+ i0.ɵɵadvance(4);
185
+ i0.ɵɵproperty("name", ctx_r2.sortDirection === "desc" ? "arrow-down-outline" : "arrow-up-outline");
186
+ } }
187
+ /**
188
+ * @description Advanced filter component for creating dynamic search filters with step-by-step construction.
189
+ * @summary This component provides a comprehensive filtering interface that allows users to build
190
+ * complex search criteria using a three-step approach: select index → select condition → enter value.
191
+ * It supports filtering by multiple field indexes, comparison conditions, and values, displaying
192
+ * selected filters as removable chips. The component is responsive and includes auto-suggestions
193
+ * with keyboard navigation support.
194
+ *
195
+ * @example
196
+ * ```html
197
+ * <ngx-decaf-filter
198
+ * [indexes]="['name', 'email', 'department', 'status']"
199
+ * [conditions]="['Equal', 'Contains', 'Greater Than', 'Less Than']"
200
+ * [sort]="['createdAt', 'updatedAt']"
201
+ * [disableSort]="false"
202
+ * (filterEvent)="onFiltersChanged($event)">
203
+ * </ngx-decaf-filter>
204
+ * ```
205
+ *
206
+ * @mermaid
207
+ * sequenceDiagram
208
+ * participant U as User
209
+ * participant F as FilterComponent
210
+ * participant P as Parent Component
211
+ *
212
+ * U->>F: Focus input field
213
+ * F->>F: handleFocus() - Show available indexes
214
+ * U->>F: Select index (e.g., "name")
215
+ * F->>F: addFilter() - Step 1 completed
216
+ * F->>F: Show available conditions
217
+ * U->>F: Select condition (e.g., "Contains")
218
+ * F->>F: addFilter() - Step 2 completed
219
+ * F->>F: Show value input prompt
220
+ * U->>F: Enter value and press Enter
221
+ * F->>F: addFilter() - Step 3 completed
222
+ * F->>F: Create complete filter object
223
+ * F->>P: Emit filterEvent with new filter array
224
+ * F->>F: Reset to step 1 for next filter
225
+ *
226
+ * @memberOf ForAngularModule
227
+ */
228
+ let FilterComponent = class FilterComponent extends NgxBaseComponent {
229
+ /**
230
+ * @description Constructor for FilterComponent.
231
+ * @summary Initializes a new instance of the FilterComponent.
232
+ * Calls the parent constructor with the component name to establish base locale string generation
233
+ * and internationalization support.
234
+ *
235
+ * @memberOf FilterComponent
236
+ */
237
+ constructor() {
238
+ super("FilterComponent");
239
+ /**
240
+ * @description Available field indexes for filtering operations.
241
+ * @summary Defines the list of field names that users can filter by. These represent
242
+ * the data properties available for filtering operations. Each index corresponds to
243
+ * a field in the data model that supports comparison operations.
244
+ *
245
+ * @type {string[]}
246
+ * @default []
247
+ * @memberOf FilterComponent
248
+ */
249
+ this.indexes = [];
250
+ /**
251
+ * @description Available comparison conditions for filters.
252
+ * @summary Defines the list of comparison operators that can be used when creating filters.
253
+ * These conditions determine how the filter value is compared against the field value.
254
+ * Common conditions include equality, containment, and numerical comparison operations.
255
+ *
256
+ * @type {string[]}
257
+ * @default []
258
+ * @memberOf FilterComponent
259
+ */
260
+ this.conditions = ['Equal', 'Contains', 'Not Contains', 'Greater Than', 'Less Than', 'Not Equal'];
261
+ /**
262
+ * @description Available sorting options for the filtered data.
263
+ * @summary Defines the list of field names that can be used for sorting the filtered results.
264
+ * When disableSort is false, this array is automatically merged with the indexes array
265
+ * to provide comprehensive sorting capabilities.
266
+ *
267
+ * @type {string[]}
268
+ * @default []
269
+ * @memberOf FilterComponent
270
+ */
271
+ this.sortBy = [];
272
+ /**
273
+ * @description Controls whether sorting functionality is disabled.
274
+ * @summary When set to true, prevents the automatic merging of sort and indexes arrays,
275
+ * effectively disabling sorting capabilities. This is useful when you want to provide
276
+ * filtering without sorting options.
277
+ *
278
+ * @type {boolean}
279
+ * @default false
280
+ * @memberOf FilterComponent
281
+ */
282
+ this.disableSort = false;
283
+ /**
284
+ * @description Available options for the current filter step.
285
+ * @summary Contains the list of options available for selection in the current step.
286
+ * This array changes dynamically based on the current step: indexes → conditions → empty for value input.
287
+ *
288
+ * @type {string[]}
289
+ * @default []
290
+ * @memberOf FilterComponent
291
+ */
292
+ this.options = [];
293
+ /**
294
+ * @description Filtered options based on user input.
295
+ * @summary Contains the subset of options that match the current user input for real-time
296
+ * filtering. This array is updated as the user types to show only relevant suggestions
297
+ * in the dropdown menu.
298
+ *
299
+ * @type {string[]}
300
+ * @default []
301
+ * @memberOf FilterComponent
302
+ */
303
+ this.filteredOptions = [];
304
+ /**
305
+ * @description Complete filter objects created by the user.
306
+ * @summary Array of complete filter objects, each containing index, condition, and value properties.
307
+ * These represent the active filters that can be applied to data operations.
308
+ *
309
+ * @type {KeyValue[]}
310
+ * @default []
311
+ * @memberOf FilterComponent
312
+ */
313
+ this.filterValue = [];
314
+ /**
315
+ * @description Current filter being constructed.
316
+ * @summary Temporary object that accumulates filter properties (index, condition, value)
317
+ * during the three-step filter creation process. Gets added to filterValue when complete.
318
+ *
319
+ * @type {KeyValue}
320
+ * @default {}
321
+ * @memberOf FilterComponent
322
+ */
323
+ this.lastFilter = {};
324
+ /**
325
+ * @description Current step in the filter creation process.
326
+ * @summary Tracks the current step of filter creation: 1 = index selection, 2 = condition selection,
327
+ * 3 = value input. Automatically resets to 1 after completing a filter.
328
+ *
329
+ * @type {number}
330
+ * @default 1
331
+ * @memberOf FilterComponent
332
+ */
333
+ this.step = 1;
334
+ /**
335
+ * @description Controls dropdown visibility state.
336
+ * @summary Boolean flag that determines whether the options dropdown is currently visible.
337
+ * Used to manage the dropdown's open/close state and coordinate with focus/blur events.
338
+ *
339
+ * @type {boolean}
340
+ * @default false
341
+ * @memberOf FilterComponent
342
+ */
343
+ this.dropdownOpen = false;
344
+ /**
345
+ * @description Current input field value.
346
+ * @summary Stores the current text input value that the user is typing. This value is
347
+ * bound to the input field and is cleared after each successful filter step completion.
348
+ *
349
+ * @type {string}
350
+ * @default ''
351
+ * @memberOf FilterComponent
352
+ */
353
+ this.value = '';
354
+ /**
355
+ * @description Current sorting field value.
356
+ * @summary Stores the field name currently selected for sorting operations.
357
+ * This value determines which field is used to order the filtered results.
358
+ * Defaults to 'id' and can be changed through the sort dropdown selection.
359
+ *
360
+ * @type {string}
361
+ * @default 'id'
362
+ * @memberOf FilterComponent
363
+ */
364
+ this.sortValue = 'id';
365
+ /**
366
+ * @description Current sorting direction.
367
+ * @summary Defines the direction of the sort operation - ascending or descending.
368
+ * This value works in conjunction with sortValue to determine the complete
369
+ * sorting configuration for filtered results.
370
+ *
371
+ * @type {OrderDirection}
372
+ * @default OrderDirection.DSC
373
+ * @memberOf FilterComponent
374
+ */
375
+ this.sortDirection = OrderDirection.DSC;
376
+ /**
377
+ * @description Event emitter for filter changes.
378
+ * @summary Emits filter events when the user creates, modifies, or clears filters.
379
+ * The emitted value contains an array of complete filter objects or undefined when
380
+ * filters are cleared. Parent components listen to this event to update their data display.
381
+ *
382
+ * @type {EventEmitter<KeyValue[] | undefined>}
383
+ * @memberOf FilterComponent
384
+ */
385
+ this.filterEvent = new EventEmitter();
386
+ /**
387
+ * @description Event emitter for search events.
388
+ * @summary Emits search events when the user interacts with the searchbar.
389
+ * @type {EventEmitter<string>}
390
+ * @memberOf FilterComponent
391
+ */
392
+ this.searchEvent = new EventEmitter();
393
+ addIcons({ chevronDownOutline, chevronUpOutline });
394
+ }
395
+ /**
396
+ * @description Initializes the component after Angular first displays the data-bound properties.
397
+ * @summary Sets up the component by initializing window width tracking, setting up resize event
398
+ * subscriptions with debouncing, configuring sorting options, and calling the base initialization.
399
+ * This method prepares the component for user interaction and responsive behavior.
400
+ *
401
+ * @mermaid
402
+ * sequenceDiagram
403
+ * participant A as Angular Lifecycle
404
+ * participant F as FilterComponent
405
+ * participant W as Window
406
+ * participant R as RxJS
407
+ *
408
+ * A->>F: ngOnInit()
409
+ * F->>W: getWindowWidth()
410
+ * W-->>F: Return current width
411
+ * F->>R: Setup resize subscription with debounce
412
+ * R-->>F: Subscription created
413
+ * alt disableSort is false
414
+ * F->>F: Merge sort and indexes arrays
415
+ * end
416
+ * F->>F: Call initialize()
417
+ *
418
+ * @returns {void}
419
+ * @memberOf FilterComponent
420
+ */
421
+ ngOnInit() {
422
+ this.windowWidth = getWindowWidth();
423
+ this.windowResizeSubscription = fromEvent(window, 'resize')
424
+ .pipe(debounceTime(300))
425
+ .subscribe(() => {
426
+ this.windowWidth = getWindowWidth();
427
+ });
428
+ this.getIndexes();
429
+ this.initialize();
430
+ }
431
+ /**
432
+ * @description Retrieves and configures available indexes for filtering and sorting.
433
+ * @summary Extracts field indexes from the model if available and merges them with
434
+ * sorting options when sorting is enabled. This method sets up the available field
435
+ * options for both filtering and sorting operations based on the model structure.
436
+ *
437
+ * @returns {void}
438
+ * @memberOf FilterComponent
439
+ */
440
+ getIndexes() {
441
+ if (this.model)
442
+ this.indexes = Object.keys(Repository.indexes(this.model) || {});
443
+ if (!this.disableSort)
444
+ this.sortBy = [...this.sortBy, ...this.indexes];
445
+ }
446
+ /**
447
+ * @description Cleanup method called when the component is destroyed.
448
+ * @summary Unsubscribes from window resize events to prevent memory leaks.
449
+ * This is essential for proper cleanup of RxJS subscriptions when the component
450
+ * is removed from the DOM.
451
+ *
452
+ * @returns {void}
453
+ * @memberOf FilterComponent
454
+ */
455
+ ngOnDestroy() {
456
+ this.windowResizeSubscription.unsubscribe();
457
+ this.clear();
458
+ }
459
+ /**
460
+ * @description Handles input events from the text field.
461
+ * @summary Processes user input and filters the available options based on the typed value.
462
+ * This method provides real-time filtering of suggestions as the user types in the input field.
463
+ *
464
+ * @param {InputEvent} event - The input event containing the new value
465
+ * @returns {void}
466
+ * @memberOf FilterComponent
467
+ */
468
+ handleInput(event) {
469
+ const { value } = event.target;
470
+ this.filteredOptions = this.filterOptions(value);
471
+ }
472
+ /**
473
+ * @description Handles focus events on the input field.
474
+ * @summary Sets up the available options when the input field receives focus and opens the dropdown.
475
+ * If no options are provided, automatically determines the appropriate options based on current step.
476
+ * This method initializes the dropdown with contextually relevant suggestions.
477
+ *
478
+ * @param {string[]} options - Optional array of options to display
479
+ * @returns {void}
480
+ * @memberOf FilterComponent
481
+ */
482
+ handleFocus(options = []) {
483
+ if (!options.length)
484
+ options = this.getOptions();
485
+ this.filteredOptions = this.options = options;
486
+ this.dropdownOpen = true;
487
+ }
488
+ /**
489
+ * @description Handles blur events on the input field with delayed closing.
490
+ * @summary Manages the dropdown closing behavior with a delay to allow for option selection.
491
+ * Uses a two-phase approach to prevent premature closing when users click on dropdown options.
492
+ *
493
+ * @param {boolean} close - Internal flag to control the closing phase
494
+ * @returns {void}
495
+ * @memberOf FilterComponent
496
+ */
497
+ handleBlur(close = false) {
498
+ if (!close) {
499
+ this.dropdownOpen = false;
500
+ setTimeout(() => {
501
+ this.handleBlur(true);
502
+ }, 100);
503
+ }
504
+ else {
505
+ if (!this.dropdownOpen && this.options.length) {
506
+ setTimeout(() => {
507
+ this.options = [];
508
+ this.dropdownOpen = false;
509
+ }, 50);
510
+ }
511
+ }
512
+ }
513
+ /**
514
+ * @description Determines the appropriate options based on the current filter step.
515
+ * @summary Returns the contextually relevant options for the current step in the filter creation process.
516
+ * Step 1 shows indexes, Step 2 shows conditions, Step 3 shows no options (value input).
517
+ *
518
+ * @returns {string[]} Array of options appropriate for the current step
519
+ * @memberOf FilterComponent
520
+ */
521
+ getOptions() {
522
+ switch (this.step) {
523
+ case 1:
524
+ this.options = this.indexes;
525
+ break;
526
+ case 2:
527
+ this.options = this.conditions;
528
+ break;
529
+ case 3:
530
+ this.options = [];
531
+ break;
532
+ }
533
+ return this.options;
534
+ }
535
+ /**
536
+ * @description Adds a filter step or completes filter creation through a three-step process.
537
+ * @summary Core method for building filters step by step: Step 1 (Index) → Step 2 (Condition) → Step 3 (Value).
538
+ * When all steps are complete, creates a complete filter object and adds it to the filter collection.
539
+ * Handles both keyboard events (Enter to submit) and programmatic calls.
540
+ *
541
+ * @param {string} value - The value to add for the current step
542
+ * @param {CustomEvent} event - Optional event (KeyboardEvent triggers submission when value is empty)
543
+ * @returns {void}
544
+ *
545
+ * @mermaid
546
+ * sequenceDiagram
547
+ * participant U as User
548
+ * participant F as FilterComponent
549
+ *
550
+ * U->>F: addFilter(value, event)
551
+ * F->>F: Trim and validate value
552
+ * alt KeyboardEvent && empty value
553
+ * F->>F: submit() - Send current filters
554
+ * else Valid value or step 3
555
+ * alt Step 1 (Index)
556
+ * F->>F: lastFilter.index = value
557
+ * F->>F: options = conditions
558
+ * else Step 2 (Condition)
559
+ * F->>F: lastFilter.condition = value
560
+ * F->>F: options = []
561
+ * else Step 3 (Value)
562
+ * F->>F: lastFilter.value = value
563
+ * F->>F: Add complete filter to filterValue
564
+ * F->>F: Reset step to 1
565
+ * end
566
+ * F->>F: Increment step
567
+ * F->>F: Clear input & focus
568
+ * F->>F: Show next options
569
+ * end
570
+ *
571
+ * @memberOf FilterComponent
572
+ */
573
+ addFilter(value, event) {
574
+ value = value.trim();
575
+ if (event instanceof KeyboardEvent && !value) {
576
+ this.submit();
577
+ }
578
+ else {
579
+ if ((value && (!(event instanceof KeyboardEvent)) || this.step === 3)) {
580
+ const filter = this.lastFilter;
581
+ switch (this.step) {
582
+ case 1:
583
+ filter['index'] = value;
584
+ this.options = this.conditions;
585
+ break;
586
+ case 2:
587
+ filter['condition'] = value;
588
+ this.options = [];
589
+ break;
590
+ case 3:
591
+ filter['value'] = value;
592
+ this.options = this.indexes;
593
+ break;
594
+ }
595
+ if (!this.filterValue.length) {
596
+ this.filterValue.push(filter);
597
+ }
598
+ else {
599
+ if (this.step === 1)
600
+ this.filterValue.push(filter);
601
+ }
602
+ if (this.step === 3) {
603
+ this.step = 0;
604
+ this.filterValue[this.filterValue.length - 1] = filter;
605
+ this.lastFilter = {};
606
+ }
607
+ this.step++;
608
+ this.value = '';
609
+ if (this.options.length)
610
+ this.handleFocus(this.options);
611
+ this.component.nativeElement.focus();
612
+ }
613
+ }
614
+ }
615
+ /**
616
+ * @description Selects an option from the dropdown suggestions.
617
+ * @summary Handles option selection when a user clicks on a suggestion in the dropdown.
618
+ * This method acts as a bridge between dropdown clicks and the main addFilter logic.
619
+ *
620
+ * @param {CustomEvent} event - The click event from the dropdown option
621
+ * @param {string} value - The selected option value
622
+ * @returns {void}
623
+ * @memberOf FilterComponent
624
+ */
625
+ selectOption(value) {
626
+ this.addFilter(value);
627
+ }
628
+ /**
629
+ * @description Determines if a filter option can be individually removed.
630
+ * @summary Checks whether a filter component should display a close icon for removal.
631
+ * Only value options can be removed individually; index and condition options are part
632
+ * of the complete filter structure and cannot be removed separately.
633
+ *
634
+ * @param {string} option - The filter option text to check
635
+ * @returns {boolean} True if the option can be cleared individually, false otherwise
636
+ * @memberOf FilterComponent
637
+ */
638
+ allowClear(option) {
639
+ return this.indexes.indexOf(option) === -1 && this.conditions.indexOf(option) === -1;
640
+ }
641
+ /**
642
+ * @description Removes a complete filter from the collection based on filter value.
643
+ * @summary Removes a complete filter by matching the provided value against filter values
644
+ * in the collection. Uses string normalization to handle accents and case differences.
645
+ * After removal, resets the interface to show available indexes for new filter creation.
646
+ *
647
+ * @param {string} filter - The filter value to remove (matches against filter.value property)
648
+ * @returns {void}
649
+ *
650
+ * @mermaid
651
+ * sequenceDiagram
652
+ * participant U as User
653
+ * participant F as FilterComponent
654
+ *
655
+ * U->>F: removeFilter(filterValue)
656
+ * F->>F: cleanString(filterValue)
657
+ * F->>F: Filter out matching filter objects
658
+ * F->>F: Clear input value
659
+ * F->>F: handleFocus(indexes) - Reset to index selection
660
+ * Note over F: Filter removed and UI reset
661
+ *
662
+ * @memberOf FilterComponent
663
+ */
664
+ removeFilter(filter) {
665
+ function cleanString(filter) {
666
+ return filter
667
+ .toLowerCase() // convert all characters to lowercase
668
+ .normalize("NFD") // separate accent marks from characters
669
+ .replace(/[\u0300-\u036f]/g, "") // remove accent marks
670
+ .replace(/\s+/g, ""); // remove all whitespace
671
+ }
672
+ this.value = "";
673
+ this.filterValue = this.filterValue.filter((item) => item?.['value'] && cleanString(item?.['value']) !== cleanString(filter));
674
+ if (this.filterValue.length === 0) {
675
+ this.step = 1;
676
+ this.lastFilter = {};
677
+ }
678
+ this.handleFocus(this.indexes);
679
+ }
680
+ /**
681
+ * @description Resets the component to its initial state.
682
+ * @summary Clears all filter data, options, and resets the step counter to 1.
683
+ * This method provides a clean slate for new filter creation without emitting events.
684
+ *
685
+ * @returns {void}
686
+ * @memberOf FilterComponent
687
+ */
688
+ reset() {
689
+ this.options = this.filteredOptions = this.filterValue = [];
690
+ this.step = 1;
691
+ this.lastFilter = {};
692
+ this.value = '';
693
+ setTimeout(() => {
694
+ this.submit();
695
+ }, 100);
696
+ }
697
+ /**
698
+ * @description Clears all filters and notifies parent components.
699
+ * @summary Resets the component state and emits undefined to notify parent components
700
+ * that all filters have been cleared. This triggers any connected data refresh logic.
701
+ *
702
+ * @param {string} value - Optional parameter (currently unused)
703
+ * @returns {void}
704
+ * @memberOf FilterComponent
705
+ */
706
+ clear(value) {
707
+ if (!value)
708
+ this.reset();
709
+ }
710
+ /**
711
+ * @description Submits the current filter collection to parent components.
712
+ * @summary Emits the current filter array to parent components when filters are ready
713
+ * to be applied. Only emits if there are active filters. Clears options after submission.
714
+ *
715
+ * @returns {void}
716
+ * @memberOf FilterComponent
717
+ */
718
+ submit() {
719
+ this.filterEvent.emit({
720
+ query: this.filterValue.length > 0 ? this.filterValue : undefined,
721
+ sort: {
722
+ value: this.sortValue,
723
+ direction: this.sortDirection
724
+ }
725
+ });
726
+ if (this.filterValue.length === 0)
727
+ this.options = [];
728
+ }
729
+ /**
730
+ * @description Toggles the sort direction between ascending and descending.
731
+ * @summary Handles sort direction changes by toggling between ASC and DSC values.
732
+ * When the direction changes, automatically triggers a submit to apply the new
733
+ * sorting configuration to the filtered results.
734
+ *
735
+ * @returns {void}
736
+ * @memberOf FilterComponent
737
+ */
738
+ handleSortDirectionChange() {
739
+ const direction = this.sortDirection === OrderDirection.ASC ? OrderDirection.DSC : OrderDirection.ASC;
740
+ if (direction !== this.sortDirection) {
741
+ this.sortDirection = direction;
742
+ this.submit();
743
+ }
744
+ }
745
+ /**
746
+ * @description Handles sort field selection changes from the dropdown.
747
+ * @summary Processes sort field changes when users select a different field
748
+ * from the sort dropdown. Updates the sortValue property and triggers
749
+ * a submit to apply the new sorting configuration if the value has changed.
750
+ *
751
+ * @param {CustomEvent} event - The select change event containing the new sort field value
752
+ * @returns {void}
753
+ * @memberOf FilterComponent
754
+ */
755
+ handleSortChange(event) {
756
+ const target = event.target;
757
+ const value = target.value;
758
+ if (value !== this.sortValue) {
759
+ this.sortValue = value;
760
+ this.submit();
761
+ }
762
+ }
763
+ /**
764
+ * @description Filters available options based on user input with visual highlighting.
765
+ * @summary Performs real-time filtering of available options based on user input.
766
+ * Also handles visual highlighting of matching options in the dropdown. Returns all
767
+ * options if input is less than 2 characters for performance optimization.
768
+ *
769
+ * @param {string | null | undefined} value - The search value to filter by
770
+ * @returns {string[]} Array of filtered options that match the input
771
+ *
772
+ * @mermaid
773
+ * sequenceDiagram
774
+ * participant U as User
775
+ * participant F as FilterComponent
776
+ * participant D as DOM
777
+ *
778
+ * U->>F: filterOptions(inputValue)
779
+ * alt inputValue < 2 characters
780
+ * F->>D: Remove existing highlights
781
+ * F-->>U: Return all options
782
+ * else inputValue >= 2 characters
783
+ * F->>D: Query all option elements
784
+ * F->>D: Add highlight to first matching option
785
+ * F->>F: Filter options by substring match
786
+ * F-->>U: Return filtered options
787
+ * end
788
+ *
789
+ * @memberOf FilterComponent
790
+ */
791
+ filterOptions(value) {
792
+ const optionsElement = this.optionsFilterElement.nativeElement;
793
+ if (!value?.length || !value || value.length < 2) {
794
+ const filteredOption = optionsElement.querySelector('.dcf-filtering-item');
795
+ if (filteredOption)
796
+ filteredOption.classList.remove('dcf-filtering-item');
797
+ return this.options;
798
+ }
799
+ const options = optionsElement.querySelectorAll('.dcf-item');
800
+ for (const option of options) {
801
+ const isActive = option.textContent?.toLowerCase().includes(value.toLowerCase());
802
+ if (isActive) {
803
+ option.classList.add('dcf-filtering-item');
804
+ break;
805
+ }
806
+ }
807
+ return this.options.filter((option) => option.toLowerCase().includes(value.toLowerCase()));
808
+ }
809
+ /**
810
+ * @description Handles search events from the integrated searchbar component.
811
+ * @summary Processes search input from the searchbar and emits search events
812
+ * to parent components. This method acts as a bridge between the internal
813
+ * searchbar component and external search event listeners.
814
+ *
815
+ * @param {string | undefined} value - The search value entered by the user
816
+ * @returns {void}
817
+ * @memberOf FilterComponent
818
+ */
819
+ handleSearch(value) {
820
+ this.searchEvent.emit(value);
821
+ }
822
+ static { this.ɵfac = function FilterComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FilterComponent)(); }; }
823
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FilterComponent, selectors: [["ngx-decaf-filter"]], viewQuery: function FilterComponent_Query(rf, ctx) { if (rf & 1) {
824
+ i0.ɵɵviewQuery(_c0, 5, ElementRef);
825
+ } if (rf & 2) {
826
+ let _t;
827
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.optionsFilterElement = _t.first);
828
+ } }, inputs: { indexes: "indexes", conditions: "conditions", sortBy: "sortBy", disableSort: "disableSort" }, outputs: { filterEvent: "filterEvent", searchEvent: "searchEvent" }, standalone: true, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵStandaloneFeature], decls: 18, vars: 13, consts: [["component", ""], ["optionsFilterElement", ""], [3, "emitEventToWindow", "debounce"], [1, "dcf-grid", "dcf-grid-small", "dcf-grid-match", "dcf-filter-grid", 3, "ngClass"], [1, "dcf-width-expand"], [1, "dcf-filter"], [1, "dcf-input"], [1, "dcf-width-1-1"], ["fill", "none", "type", "text", 3, "ngModelChange", "keydown.enter", "keydown.backspace", "input", "click", "blur", "ngModel", "readonly", "placeholder"], [3, "class"], [1, "dcf-icon-clear"], [1, "dcf-icon-search"], ["fill", "clear", "size", "small", 3, "click"], ["name", "search-outline", "color", "dark", "slot", "icon-only"], [1, "dcf-width-1-5@m", "dcf-width-1-1", "dcf-sort-container"], [3, "searchEvent", "emitEventToWindow", "debounce"], [3, "outline"], [1, "dcf-filter-value", 3, "outline"], ["name", "close", "size", "small", 3, "click"], ["tabindex", "0", 1, "dcf-empty"], ["tabindex", "0", 1, "dcf-item"], ["tabindex", "0", 1, "dcf-item", 3, "keydown.enter", "click"], ["tabindex", "0", 1, "dcf-empty", 3, "click", "keydown.enter"], ["name", "trash-outline", "color", "dark", "slot", "icon-only"], [1, "dcf-grid", "dcf-grid-collapse", "dcf-flex", "dcf-flex-middle", "dcf-grid-match"], ["toggleIcon", "chevron-down-outline", "expandedIcon", "chevron-up-outline", "interface", "popover", "label-placement", "floating", "fill", "outline", 1, "dcf-sort-select", 3, "ionChange", "value"], [3, "value"], [1, "dcf-width-auto"], ["fill", "clear", 3, "click"], ["slot", "icon-only", 3, "name"]], template: function FilterComponent_Template(rf, ctx) { if (rf & 1) {
829
+ const _r1 = i0.ɵɵgetCurrentView();
830
+ i0.ɵɵtemplate(0, FilterComponent_Conditional_0_Template, 1, 2, "ngx-decaf-searchbar", 2);
831
+ i0.ɵɵelementStart(1, "div", 3)(2, "div", 4)(3, "div", 5)(4, "div", 6);
832
+ i0.ɵɵrepeaterCreate(5, FilterComponent_For_6_Template, 3, 3, null, null, _forTrack0, true);
833
+ i0.ɵɵelementStart(7, "div", 7)(8, "input", 8, 0);
834
+ i0.ɵɵpipe(10, "translate");
835
+ i0.ɵɵtwoWayListener("ngModelChange", function FilterComponent_Template_input_ngModelChange_8_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.value, $event) || (ctx.value = $event); return i0.ɵɵresetView($event); });
836
+ i0.ɵɵlistener("keydown.enter", function FilterComponent_Template_input_keydown_enter_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.addFilter(ctx.value, $event)); })("keydown.backspace", function FilterComponent_Template_input_keydown_backspace_8_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.clear(ctx.value)); })("input", function FilterComponent_Template_input_input_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleInput($event)); })("click", function FilterComponent_Template_input_click_8_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleFocus()); })("blur", function FilterComponent_Template_input_blur_8_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleBlur()); });
837
+ i0.ɵɵelementEnd();
838
+ i0.ɵɵtemplate(11, FilterComponent_Conditional_11_Template, 5, 3, "div", 9);
839
+ i0.ɵɵelementEnd()();
840
+ i0.ɵɵtemplate(12, FilterComponent_Conditional_12_Template, 3, 0, "div", 10);
841
+ i0.ɵɵelementStart(13, "div", 11)(14, "ion-button", 12);
842
+ i0.ɵɵlistener("click", function FilterComponent_Template_ion_button_click_14_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.submit()); });
843
+ i0.ɵɵelement(15, "ion-icon", 13);
844
+ i0.ɵɵelementEnd()()();
845
+ i0.ɵɵtemplate(16, FilterComponent_Conditional_16_Template, 5, 3, "div", 9);
846
+ i0.ɵɵelementEnd();
847
+ i0.ɵɵtemplate(17, FilterComponent_Conditional_17_Template, 9, 2, "div", 14);
848
+ i0.ɵɵelementEnd();
849
+ } if (rf & 2) {
850
+ i0.ɵɵconditional(!ctx.indexes.length ? 0 : -1);
851
+ i0.ɵɵadvance();
852
+ i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(11, _c1, !ctx.indexes.length));
853
+ i0.ɵɵadvance(4);
854
+ i0.ɵɵrepeater(ctx.filterValue);
855
+ i0.ɵɵadvance(3);
856
+ i0.ɵɵpropertyInterpolate("placeholder", i0.ɵɵpipeBind1(10, 9, ctx.locale + (ctx.step === 3 ? ".type" : ".select")));
857
+ i0.ɵɵtwoWayProperty("ngModel", ctx.value);
858
+ i0.ɵɵproperty("readonly", ctx.step !== 3);
859
+ i0.ɵɵadvance(3);
860
+ i0.ɵɵconditional(ctx.windowWidth >= 768 ? 11 : -1);
861
+ i0.ɵɵadvance();
862
+ i0.ɵɵconditional(ctx.filterValue.length > 0 ? 12 : -1);
863
+ i0.ɵɵadvance(4);
864
+ i0.ɵɵconditional(ctx.windowWidth < 768 ? 16 : -1);
865
+ i0.ɵɵadvance();
866
+ i0.ɵɵconditional(!ctx.disableSort ? 17 : -1);
867
+ } }, dependencies: [ForAngularModule, i1.IonButton, i2.NgClass, i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.TranslatePipe, IonChip,
868
+ IonIcon,
869
+ IonSelect,
870
+ SearchbarComponent], styles: [".dcf-filter-grid[_ngcontent-%COMP%]{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select[_ngcontent-%COMP%]{min-height:44px!important}.dcf-hidden[_ngcontent-%COMP%]{display:none!important}.dcf-filter[_ngcontent-%COMP%]{display:flex;width:100%;min-height:40px;border:1px solid var(--ion-color-gray-3);box-shadow:0 1px 2px #0a0d120d;background-color:#fff;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter[_ngcontent-%COMP%]:focus-within{border-color:var(--ion-color-primary);background-color:#fff}.dcf-filter[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%]{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;border:1px solid var(--ion-color-gray-3);color:var(--ion-color-gray-7);font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter[_ngcontent-%COMP%] ion-chip.dcf-filter-value[_ngcontent-%COMP%]{background:var(--ion-color-gray-2);border-color:var(--ion-color-gray-4)!important;color:var(--ion-color-gray-8)!important}.dcf-filter[_ngcontent-%COMP%] ion-chip.sc-ion-chip-md-h[_ngcontent-%COMP%], .dcf-filter[_ngcontent-%COMP%] ion-chip.sc-ion-chip-ios-h[_ngcontent-%COMP%]{height:24px;min-height:24px}.dcf-filter[_ngcontent-%COMP%] ion-chip.sc-ion-chip-md-h[_ngcontent-%COMP%] .chip-native[_ngcontent-%COMP%], .dcf-filter[_ngcontent-%COMP%] ion-chip.sc-ion-chip-ios-h[_ngcontent-%COMP%] .chip-native[_ngcontent-%COMP%]{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%] ion-label[_ngcontent-%COMP%]{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%] ion-icon[_ngcontent-%COMP%]{margin:0 2px;font-size:.75rem}.dcf-filter[_ngcontent-%COMP%] .dcf-input[_ngcontent-%COMP%]{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter[_ngcontent-%COMP%] .dcf-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{min-height:40px;color:var(--ion-color-gray-7);min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter[_ngcontent-%COMP%] .dcf-input[_ngcontent-%COMP%] input[_ngcontent-%COMP%]:focus{border:0px!important;outline:none!important}.dcf-filter[_ngcontent-%COMP%] .dcf-icon-clear[_ngcontent-%COMP%], .dcf-filter[_ngcontent-%COMP%] .dcf-icon-search[_ngcontent-%COMP%]{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter[_ngcontent-%COMP%] .dcf-icon-search[_ngcontent-%COMP%] ion-icon[_ngcontent-%COMP%]{font-size:1.25rem}.dcf-sort-container[_ngcontent-%COMP%]{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container[_ngcontent-%COMP%]{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container[_ngcontent-%COMP%]{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown[_ngcontent-%COMP%]{position:absolute;max-height:200px;overflow-y:auto;background-color:#fff;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active[_ngcontent-%COMP%]{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border:1px solid var(--ion-color-gray-2);border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active[_ngcontent-%COMP%]{margin-top:55px}}.dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;color:var(--ion-color-gray-8);border-radius:6px}.dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div.dcf-filtering-item[_ngcontent-%COMP%], .dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]:only-child{border-color:var(--ion-color-primary)}.dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div.dcf-filtering-item.dcf-empty[_ngcontent-%COMP%], .dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]:only-child.dcf-empty{border-color:var(--ion-color-gray-7)!important}.dcf-dropdown.dcf-active[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]:hover{background-color:var(--ion-color-gray-1)}"] }); }
871
+ };
872
+ FilterComponent = __decorate([
873
+ Dynamic(),
874
+ __metadata("design:paramtypes", [])
875
+ ], FilterComponent);
876
+ export { FilterComponent };
877
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FilterComponent, [{
878
+ type: Component,
879
+ args: [{ selector: 'ngx-decaf-filter', imports: [
880
+ ForAngularModule,
881
+ IonLabel,
882
+ IonItem,
883
+ IonChip,
884
+ IonIcon,
885
+ IonSelect,
886
+ IonIcon,
887
+ SearchbarComponent
888
+ ], standalone: true, template: "\n@if(!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-grid\" [ngClass]=\"{'dcf-hidden': !indexes.length}\">\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if(filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if(filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if(filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon name=\"close\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n [readonly]=\"step !== 3\"\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n #component\n />\n @if(windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ 'no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if(filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon name=\"search-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if(windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ 'no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if(!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n >\n @for(sort of sortBy; track sort) {\n aa\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: [".dcf-filter-grid{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;border:1px solid var(--ion-color-gray-3);box-shadow:0 1px 2px #0a0d120d;background-color:#fff;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter:focus-within{border-color:var(--ion-color-primary);background-color:#fff}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;border:1px solid var(--ion-color-gray-3);color:var(--ion-color-gray-7);font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter ion-chip.dcf-filter-value{background:var(--ion-color-gray-2);border-color:var(--ion-color-gray-4)!important;color:var(--ion-color-gray-8)!important}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;color:var(--ion-color-gray-7);min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;background-color:#fff;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border:1px solid var(--ion-color-gray-2);border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;color:var(--ion-color-gray-8);border-radius:6px}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--ion-color-primary)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{border-color:var(--ion-color-gray-7)!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--ion-color-gray-1)}\n"] }]
889
+ }], () => [], { optionsFilterElement: [{
890
+ type: ViewChild,
891
+ args: ['optionsFilterElement', { read: ElementRef, static: false }]
892
+ }], indexes: [{
893
+ type: Input
894
+ }], conditions: [{
895
+ type: Input
896
+ }], sortBy: [{
897
+ type: Input
898
+ }], disableSort: [{
899
+ type: Input
900
+ }], filterEvent: [{
901
+ type: Output
902
+ }], searchEvent: [{
903
+ type: Output
904
+ }] }); })();
905
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FilterComponent, { className: "FilterComponent", filePath: "components/filter/filter.component.ts", lineNumber: 72 }); })();
906
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9maWx0ZXIvZmlsdGVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9maWx0ZXIvZmlsdGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQUUsU0FBUyxFQUFHLE1BQU0sZUFBZSxDQUFDO0FBQ2xILE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzVELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDMUYsT0FBTyxFQUFFLE9BQU8sRUFBa0MsTUFBTSxjQUFjLENBQUM7QUFDdkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUM3RCxPQUFPLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7NENDRjlELHNEQUE2QixPQUFPLEVBQUU7Ozs7SUFQNUMsK0NBQXlHO0lBQXZDLGtOQUFlLDJCQUFvQixLQUFDO0lBQXRHLGlCQUF5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b0JBQ2hCLFFBQVE7b0JBQ1IsT0FBTztvQkFDUCxPQUFPO29CQUNQLE9BQU87b0JBQ1AsU0FBUztvQkFDVCxPQUFPO29CQUNQLGtCQUFrQjtpQkFDbkIsY0FDVyxJQUFJO29CQWNoQixvQkFBb0I7a0JBRG5CLFNBQVM7bUJBQUMsc0JBQXNCLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7WUFjdEUsT0FBTztrQkFETixLQUFLO1lBY04sVUFBVTtrQkFEVCxLQUFLO1lBY04sTUFBTTtrQkFETCxLQUFLO1lBY04sV0FBVztrQkFEVixLQUFLO1lBeUlOLFdBQVc7a0JBRFYsTUFBTTtZQVVQLFdBQVc7a0JBRFYsTUFBTTs7a0ZBaE5JLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFZpZXdDaGlsZCAgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvckFuZ3VsYXJNb2R1bGUgfSBmcm9tICcuLi8uLi9mb3ItYW5ndWxhci5tb2R1bGUnO1xuaW1wb3J0IHsgTmd4QmFzZUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2VuZ2luZS9OZ3hCYXNlQ29tcG9uZW50JztcbmltcG9ydCB7IElvbkNoaXAsIElvbkljb24sIElvbkl0ZW0sIElvbkxhYmVsLCBJb25TZWxlY3R9IGZyb20gJ0Bpb25pYy9hbmd1bGFyL3N0YW5kYWxvbmUnO1xuaW1wb3J0IHsgRHluYW1pYywgSUZpbHRlclF1ZXJ5LCBJRmlsdGVyUXVlcnlJdGVtIH0gZnJvbSAnLi4vLi4vZW5naW5lJztcbmltcG9ydCB7IGdldFdpbmRvd1dpZHRoIH0gZnJvbSAnLi4vLi4vaGVscGVycy91dGlscyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIGZyb21FdmVudCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBPcmRlckRpcmVjdGlvbiwgUmVwb3NpdG9yeSB9IGZyb20gJ0BkZWNhZi10cy9jb3JlJztcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSAnQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uJztcbmltcG9ydCB7IFNlYXJjaGJhckNvbXBvbmVudCB9IGZyb20gJy4uL3NlYXJjaGJhci9zZWFyY2hiYXIuY29tcG9uZW50JztcbmltcG9ydCB7IGFkZEljb25zIH0gZnJvbSAnaW9uaWNvbnMnO1xuaW1wb3J0IHsgY2hldnJvbkRvd25PdXRsaW5lLCBjaGV2cm9uVXBPdXRsaW5lIH0gZnJvbSAnaW9uaWNvbnMvaWNvbnMnO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBZHZhbmNlZCBmaWx0ZXIgY29tcG9uZW50IGZvciBjcmVhdGluZyBkeW5hbWljIHNlYXJjaCBmaWx0ZXJzIHdpdGggc3RlcC1ieS1zdGVwIGNvbnN0cnVjdGlvbi5cbiAqIEBzdW1tYXJ5IFRoaXMgY29tcG9uZW50IHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBmaWx0ZXJpbmcgaW50ZXJmYWNlIHRoYXQgYWxsb3dzIHVzZXJzIHRvIGJ1aWxkXG4gKiBjb21wbGV4IHNlYXJjaCBjcml0ZXJpYSB1c2luZyBhIHRocmVlLXN0ZXAgYXBwcm9hY2g6IHNlbGVjdCBpbmRleCDihpIgc2VsZWN0IGNvbmRpdGlvbiDihpIgZW50ZXIgdmFsdWUuXG4gKiBJdCBzdXBwb3J0cyBmaWx0ZXJpbmcgYnkgbXVsdGlwbGUgZmllbGQgaW5kZXhlcywgY29tcGFyaXNvbiBjb25kaXRpb25zLCBhbmQgdmFsdWVzLCBkaXNwbGF5aW5nXG4gKiBzZWxlY3RlZCBmaWx0ZXJzIGFzIHJlbW92YWJsZSBjaGlwcy4gVGhlIGNvbXBvbmVudCBpcyByZXNwb25zaXZlIGFuZCBpbmNsdWRlcyBhdXRvLXN1Z2dlc3Rpb25zXG4gKiB3aXRoIGtleWJvYXJkIG5hdmlnYXRpb24gc3VwcG9ydC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgaHRtbFxuICogPG5neC1kZWNhZi1maWx0ZXJcbiAqICAgW2luZGV4ZXNdPVwiWyduYW1lJywgJ2VtYWlsJywgJ2RlcGFydG1lbnQnLCAnc3RhdHVzJ11cIlxuICogICBbY29uZGl0aW9uc109XCJbJ0VxdWFsJywgJ0NvbnRhaW5zJywgJ0dyZWF0ZXIgVGhhbicsICdMZXNzIFRoYW4nXVwiXG4gKiAgIFtzb3J0XT1cIlsnY3JlYXRlZEF0JywgJ3VwZGF0ZWRBdCddXCJcbiAqICAgW2Rpc2FibGVTb3J0XT1cImZhbHNlXCJcbiAqICAgKGZpbHRlckV2ZW50KT1cIm9uRmlsdGVyc0NoYW5nZWQoJGV2ZW50KVwiPlxuICogPC9uZ3gtZGVjYWYtZmlsdGVyPlxuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAqICAgcGFydGljaXBhbnQgRiBhcyBGaWx0ZXJDb21wb25lbnRcbiAqICAgcGFydGljaXBhbnQgUCBhcyBQYXJlbnQgQ29tcG9uZW50XG4gKlxuICogICBVLT4+RjogRm9jdXMgaW5wdXQgZmllbGRcbiAqICAgRi0+PkY6IGhhbmRsZUZvY3VzKCkgLSBTaG93IGF2YWlsYWJsZSBpbmRleGVzXG4gKiAgIFUtPj5GOiBTZWxlY3QgaW5kZXggKGUuZy4sIFwibmFtZVwiKVxuICogICBGLT4+RjogYWRkRmlsdGVyKCkgLSBTdGVwIDEgY29tcGxldGVkXG4gKiAgIEYtPj5GOiBTaG93IGF2YWlsYWJsZSBjb25kaXRpb25zXG4gKiAgIFUtPj5GOiBTZWxlY3QgY29uZGl0aW9uIChlLmcuLCBcIkNvbnRhaW5zXCIpXG4gKiAgIEYtPj5GOiBhZGRGaWx0ZXIoKSAtIFN0ZXAgMiBjb21wbGV0ZWRcbiAqICAgRi0+PkY6IFNob3cgdmFsdWUgaW5wdXQgcHJvbXB0XG4gKiAgIFUtPj5GOiBFbnRlciB2YWx1ZSBhbmQgcHJlc3MgRW50ZXJcbiAqICAgRi0+PkY6IGFkZEZpbHRlcigpIC0gU3RlcCAzIGNvbXBsZXRlZFxuICogICBGLT4+RjogQ3JlYXRlIGNvbXBsZXRlIGZpbHRlciBvYmplY3RcbiAqICAgRi0+PlA6IEVtaXQgZmlsdGVyRXZlbnQgd2l0aCBuZXcgZmlsdGVyIGFycmF5XG4gKiAgIEYtPj5GOiBSZXNldCB0byBzdGVwIDEgZm9yIG5leHQgZmlsdGVyXG4gKlxuICogQG1lbWJlck9mIEZvckFuZ3VsYXJNb2R1bGVcbiAqL1xuQER5bmFtaWMoKVxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWRlY2FmLWZpbHRlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9maWx0ZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9maWx0ZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgaW1wb3J0czogW1xuICAgIEZvckFuZ3VsYXJNb2R1bGUsXG4gICAgSW9uTGFiZWwsXG4gICAgSW9uSXRlbSxcbiAgICBJb25DaGlwLFxuICAgIElvbkljb24sXG4gICAgSW9uU2VsZWN0LFxuICAgIElvbkljb24sXG4gICAgU2VhcmNoYmFyQ29tcG9uZW50XG4gIF0sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIEZpbHRlckNvbXBvbmVudCBleHRlbmRzIE5neEJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWZlcmVuY2UgdG8gdGhlIGRyb3Bkb3duIG9wdGlvbnMgY29udGFpbmVyIGVsZW1lbnQuXG4gICAqIEBzdW1tYXJ5IFZpZXdDaGlsZCByZWZlcmVuY2UgdXNlZCB0byBhY2Nlc3MgYW5kIG1hbmlwdWxhdGUgdGhlIGRyb3Bkb3duIG9wdGlvbnMgZWxlbWVudFxuICAgKiBmb3IgaGlnaGxpZ2h0aW5nIGZpbHRlcmVkIGl0ZW1zIGFuZCBtYW5hZ2luZyB2aXN1YWwgZmVlZGJhY2sgZHVyaW5nIG9wdGlvbiBzZWxlY3Rpb24uXG4gICAqIFRoaXMgZWxlbWVudCBjb250YWlucyB0aGUgZmlsdGVyYWJsZSBzdWdnZXN0aW9ucyB0aGF0IHVzZXJzIGNhbiBpbnRlcmFjdCB3aXRoLlxuICAgKlxuICAgKiBAdHlwZSB7RWxlbWVudFJlZn1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgQFZpZXdDaGlsZCgnb3B0aW9uc0ZpbHRlckVsZW1lbnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSlcbiAgb3B0aW9uc0ZpbHRlckVsZW1lbnQhOiBFbGVtZW50UmVmO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXZhaWxhYmxlIGZpZWxkIGluZGV4ZXMgZm9yIGZpbHRlcmluZyBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBsaXN0IG9mIGZpZWxkIG5hbWVzIHRoYXQgdXNlcnMgY2FuIGZpbHRlciBieS4gVGhlc2UgcmVwcmVzZW50XG4gICAqIHRoZSBkYXRhIHByb3BlcnRpZXMgYXZhaWxhYmxlIGZvciBmaWx0ZXJpbmcgb3BlcmF0aW9ucy4gRWFjaCBpbmRleCBjb3JyZXNwb25kcyB0b1xuICAgKiBhIGZpZWxkIGluIHRoZSBkYXRhIG1vZGVsIHRoYXQgc3VwcG9ydHMgY29tcGFyaXNvbiBvcGVyYXRpb25zLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nW119XG4gICAqIEBkZWZhdWx0IFtdXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGluZGV4ZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBdmFpbGFibGUgY29tcGFyaXNvbiBjb25kaXRpb25zIGZvciBmaWx0ZXJzLlxuICAgKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBsaXN0IG9mIGNvbXBhcmlzb24gb3BlcmF0b3JzIHRoYXQgY2FuIGJlIHVzZWQgd2hlbiBjcmVhdGluZyBmaWx0ZXJzLlxuICAgKiBUaGVzZSBjb25kaXRpb25zIGRldGVybWluZSBob3cgdGhlIGZpbHRlciB2YWx1ZSBpcyBjb21wYXJlZCBhZ2FpbnN0IHRoZSBmaWVsZCB2YWx1ZS5cbiAgICogQ29tbW9uIGNvbmRpdGlvbnMgaW5jbHVkZSBlcXVhbGl0eSwgY29udGFpbm1lbnQsIGFuZCBudW1lcmljYWwgY29tcGFyaXNvbiBvcGVyYXRpb25zLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nW119XG4gICAqIEBkZWZhdWx0IFtdXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGNvbmRpdGlvbnM6IHN0cmluZ1tdID0gWydFcXVhbCcsICdDb250YWlucycsICdOb3QgQ29udGFpbnMnLCAnR3JlYXRlciBUaGFuJywgJ0xlc3MgVGhhbicsICdOb3QgRXF1YWwnXTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF2YWlsYWJsZSBzb3J0aW5nIG9wdGlvbnMgZm9yIHRoZSBmaWx0ZXJlZCBkYXRhLlxuICAgKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBsaXN0IG9mIGZpZWxkIG5hbWVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIHNvcnRpbmcgdGhlIGZpbHRlcmVkIHJlc3VsdHMuXG4gICAqIFdoZW4gZGlzYWJsZVNvcnQgaXMgZmFsc2UsIHRoaXMgYXJyYXkgaXMgYXV0b21hdGljYWxseSBtZXJnZWQgd2l0aCB0aGUgaW5kZXhlcyBhcnJheVxuICAgKiB0byBwcm92aWRlIGNvbXByZWhlbnNpdmUgc29ydGluZyBjYXBhYmlsaXRpZXMuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmdbXX1cbiAgICogQGRlZmF1bHQgW11cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgc29ydEJ5OiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udHJvbHMgd2hldGhlciBzb3J0aW5nIGZ1bmN0aW9uYWxpdHkgaXMgZGlzYWJsZWQuXG4gICAqIEBzdW1tYXJ5IFdoZW4gc2V0IHRvIHRydWUsIHByZXZlbnRzIHRoZSBhdXRvbWF0aWMgbWVyZ2luZyBvZiBzb3J0IGFuZCBpbmRleGVzIGFycmF5cyxcbiAgICogZWZmZWN0aXZlbHkgZGlzYWJsaW5nIHNvcnRpbmcgY2FwYWJpbGl0aWVzLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIHByb3ZpZGVcbiAgICogZmlsdGVyaW5nIHdpdGhvdXQgc29ydGluZyBvcHRpb25zLlxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgZGlzYWJsZVNvcnQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgd2luZG93IHdpZHRoIGZvciByZXNwb25zaXZlIGJlaGF2aW9yLlxuICAgKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGN1cnJlbnQgYnJvd3NlciB3aW5kb3cgd2lkdGggaW4gcGl4ZWxzLiBUaGlzIHZhbHVlIGlzIHVwZGF0ZWRcbiAgICogb24gd2luZG93IHJlc2l6ZSBldmVudHMgdG8gZW5hYmxlIHJlc3BvbnNpdmUgZmlsdGVyaW5nIGJlaGF2aW9yIGFuZCBsYXlvdXQgYWRqdXN0bWVudHNcbiAgICogYmFzZWQgb24gYXZhaWxhYmxlIHNjcmVlbiBzcGFjZS5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgd2luZG93V2lkdGghOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhlIGN1cnJlbnQgZmlsdGVyIHN0ZXAuXG4gICAqIEBzdW1tYXJ5IENvbnRhaW5zIHRoZSBsaXN0IG9mIG9wdGlvbnMgYXZhaWxhYmxlIGZvciBzZWxlY3Rpb24gaW4gdGhlIGN1cnJlbnQgc3RlcC5cbiAgICogVGhpcyBhcnJheSBjaGFuZ2VzIGR5bmFtaWNhbGx5IGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0ZXA6IGluZGV4ZXMg4oaSIGNvbmRpdGlvbnMg4oaSIGVtcHR5IGZvciB2YWx1ZSBpbnB1dC5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZ1tdfVxuICAgKiBAZGVmYXVsdCBbXVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBvcHRpb25zOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmlsdGVyZWQgb3B0aW9ucyBiYXNlZCBvbiB1c2VyIGlucHV0LlxuICAgKiBAc3VtbWFyeSBDb250YWlucyB0aGUgc3Vic2V0IG9mIG9wdGlvbnMgdGhhdCBtYXRjaCB0aGUgY3VycmVudCB1c2VyIGlucHV0IGZvciByZWFsLXRpbWVcbiAgICogZmlsdGVyaW5nLiBUaGlzIGFycmF5IGlzIHVwZGF0ZWQgYXMgdGhlIHVzZXIgdHlwZXMgdG8gc2hvdyBvbmx5IHJlbGV2YW50IHN1Z2dlc3Rpb25zXG4gICAqIGluIHRoZSBkcm9wZG93biBtZW51LlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nW119XG4gICAqIEBkZWZhdWx0IFtdXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIGZpbHRlcmVkT3B0aW9uczogc3RyaW5nW10gPSBbXTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbXBsZXRlIGZpbHRlciBvYmplY3RzIGNyZWF0ZWQgYnkgdGhlIHVzZXIuXG4gICAqIEBzdW1tYXJ5IEFycmF5IG9mIGNvbXBsZXRlIGZpbHRlciBvYmplY3RzLCBlYWNoIGNvbnRhaW5pbmcgaW5kZXgsIGNvbmRpdGlvbiwgYW5kIHZhbHVlIHByb3BlcnRpZXMuXG4gICAqIFRoZXNlIHJlcHJlc2VudCB0aGUgYWN0aXZlIGZpbHRlcnMgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBkYXRhIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEB0eXBlIHtLZXlWYWx1ZVtdfVxuICAgKiBAZGVmYXVsdCBbXVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBmaWx0ZXJWYWx1ZTogSUZpbHRlclF1ZXJ5SXRlbVtdID0gW107XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IGZpbHRlciBiZWluZyBjb25zdHJ1Y3RlZC5cbiAgICogQHN1bW1hcnkgVGVtcG9yYXJ5IG9iamVjdCB0aGF0IGFjY3VtdWxhdGVzIGZpbHRlciBwcm9wZXJ0aWVzIChpbmRleCwgY29uZGl0aW9uLCB2YWx1ZSlcbiAgICogZHVyaW5nIHRoZSB0aHJlZS1zdGVwIGZpbHRlciBjcmVhdGlvbiBwcm9jZXNzLiBHZXRzIGFkZGVkIHRvIGZpbHRlclZhbHVlIHdoZW4gY29tcGxldGUuXG4gICAqXG4gICAqIEB0eXBlIHtLZXlWYWx1ZX1cbiAgICogQGRlZmF1bHQge31cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgbGFzdEZpbHRlcjogSUZpbHRlclF1ZXJ5SXRlbSA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBzdGVwIGluIHRoZSBmaWx0ZXIgY3JlYXRpb24gcHJvY2Vzcy5cbiAgICogQHN1bW1hcnkgVHJhY2tzIHRoZSBjdXJyZW50IHN0ZXAgb2YgZmlsdGVyIGNyZWF0aW9uOiAxID0gaW5kZXggc2VsZWN0aW9uLCAyID0gY29uZGl0aW9uIHNlbGVjdGlvbixcbiAgICogMyA9IHZhbHVlIGlucHV0LiBBdXRvbWF0aWNhbGx5IHJlc2V0cyB0byAxIGFmdGVyIGNvbXBsZXRpbmcgYSBmaWx0ZXIuXG4gICAqXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqIEBkZWZhdWx0IDFcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgc3RlcDogbnVtYmVyID0gMTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnRyb2xzIGRyb3Bkb3duIHZpc2liaWxpdHkgc3RhdGUuXG4gICAqIEBzdW1tYXJ5IEJvb2xlYW4gZmxhZyB0aGF0IGRldGVybWluZXMgd2hldGhlciB0aGUgb3B0aW9ucyBkcm9wZG93biBpcyBjdXJyZW50bHkgdmlzaWJsZS5cbiAgICogVXNlZCB0byBtYW5hZ2UgdGhlIGRyb3Bkb3duJ3Mgb3Blbi9jbG9zZSBzdGF0ZSBhbmQgY29vcmRpbmF0ZSB3aXRoIGZvY3VzL2JsdXIgZXZlbnRzLlxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgZHJvcGRvd25PcGVuOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IGlucHV0IGZpZWxkIHZhbHVlLlxuICAgKiBAc3VtbWFyeSBTdG9yZXMgdGhlIGN1cnJlbnQgdGV4dCBpbnB1dCB2YWx1ZSB0aGF0IHRoZSB1c2VyIGlzIHR5cGluZy4gVGhpcyB2YWx1ZSBpc1xuICAgKiBib3VuZCB0byB0aGUgaW5wdXQgZmllbGQgYW5kIGlzIGNsZWFyZWQgYWZ0ZXIgZWFjaCBzdWNjZXNzZnVsIGZpbHRlciBzdGVwIGNvbXBsZXRpb24uXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZWZhdWx0ICcnXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIHZhbHVlOiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgc29ydGluZyBmaWVsZCB2YWx1ZS5cbiAgICogQHN1bW1hcnkgU3RvcmVzIHRoZSBmaWVsZCBuYW1lIGN1cnJlbnRseSBzZWxlY3RlZCBmb3Igc29ydGluZyBvcGVyYXRpb25zLlxuICAgKiBUaGlzIHZhbHVlIGRldGVybWluZXMgd2hpY2ggZmllbGQgaXMgdXNlZCB0byBvcmRlciB0aGUgZmlsdGVyZWQgcmVzdWx0cy5cbiAgICogRGVmYXVsdHMgdG8gJ2lkJyBhbmQgY2FuIGJlIGNoYW5nZWQgdGhyb3VnaCB0aGUgc29ydCBkcm9wZG93biBzZWxlY3Rpb24uXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZWZhdWx0ICdpZCdcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgc29ydFZhbHVlOiBzdHJpbmcgPSAnaWQnO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBzb3J0aW5nIGRpcmVjdGlvbi5cbiAgICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzb3J0IG9wZXJhdGlvbiAtIGFzY2VuZGluZyBvciBkZXNjZW5kaW5nLlxuICAgKiBUaGlzIHZhbHVlIHdvcmtzIGluIGNvbmp1bmN0aW9uIHdpdGggc29ydFZhbHVlIHRvIGRldGVybWluZSB0aGUgY29tcGxldGVcbiAgICogc29ydGluZyBjb25maWd1cmF0aW9uIGZvciBmaWx0ZXJlZCByZXN1bHRzLlxuICAgKlxuICAgKiBAdHlwZSB7T3JkZXJEaXJlY3Rpb259XG4gICAqIEBkZWZhdWx0IE9yZGVyRGlyZWN0aW9uLkRTQ1xuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBzb3J0RGlyZWN0aW9uOiBPcmRlckRpcmVjdGlvbiA9IE9yZGVyRGlyZWN0aW9uLkRTQztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN1YnNjcmlwdGlvbiBmb3Igd2luZG93IHJlc2l6ZSBldmVudHMuXG4gICAqIEBzdW1tYXJ5IFJ4SlMgc3Vic2NyaXB0aW9uIHRoYXQgbGlzdGVucyBmb3Igd2luZG93IHJlc2l6ZSBldmVudHMgd2l0aCBkZWJvdW5jaW5nXG4gICAqIHRvIHVwZGF0ZSB0aGUgd2luZG93V2lkdGggcHJvcGVydHkuIFRoaXMgZW5hYmxlcyByZXNwb25zaXZlIGJlaGF2aW9yIGFuZCBwcmV2ZW50c1xuICAgKiBleGNlc3NpdmUgdXBkYXRlcyBkdXJpbmcgcmVzaXplIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEB0eXBlIHtTdWJzY3JpcHRpb259XG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIHdpbmRvd1Jlc2l6ZVN1YnNjcmlwdGlvbiE6IFN1YnNjcmlwdGlvbjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV2ZW50IGVtaXR0ZXIgZm9yIGZpbHRlciBjaGFuZ2VzLlxuICAgKiBAc3VtbWFyeSBFbWl0cyBmaWx0ZXIgZXZlbnRzIHdoZW4gdGhlIHVzZXIgY3JlYXRlcywgbW9kaWZpZXMsIG9yIGNsZWFycyBmaWx0ZXJzLlxuICAgKiBUaGUgZW1pdHRlZCB2YWx1ZSBjb250YWlucyBhbiBhcnJheSBvZiBjb21wbGV0ZSBmaWx0ZXIgb2JqZWN0cyBvciB1bmRlZmluZWQgd2hlblxuICAgKiBmaWx0ZXJzIGFyZSBjbGVhcmVkLiBQYXJlbnQgY29tcG9uZW50cyBsaXN0ZW4gdG8gdGhpcyBldmVudCB0byB1cGRhdGUgdGhlaXIgZGF0YSBkaXNwbGF5LlxuICAgKlxuICAgKiBAdHlwZSB7RXZlbnRFbWl0dGVyPEtleVZhbHVlW10gfCB1bmRlZmluZWQ+fVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBAT3V0cHV0KClcbiAgZmlsdGVyRXZlbnQ6IEV2ZW50RW1pdHRlcjxJRmlsdGVyUXVlcnkgfCB1bmRlZmluZWQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJRmlsdGVyUXVlcnkgfCB1bmRlZmluZWQ+KCk7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFdmVudCBlbWl0dGVyIGZvciBzZWFyY2ggZXZlbnRzLlxuICAgKiBAc3VtbWFyeSBFbWl0cyBzZWFyY2ggZXZlbnRzIHdoZW4gdGhlIHVzZXIgaW50ZXJhY3RzIHdpdGggdGhlIHNlYXJjaGJhci5cbiAgICogQHR5cGUge0V2ZW50RW1pdHRlcjxzdHJpbmc+fVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBAT3V0cHV0KClcbiAgc2VhcmNoRXZlbnQ6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnN0cnVjdG9yIGZvciBGaWx0ZXJDb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBGaWx0ZXJDb21wb25lbnQuXG4gICAqIENhbGxzIHRoZSBwYXJlbnQgY29uc3RydWN0b3Igd2l0aCB0aGUgY29tcG9uZW50IG5hbWUgdG8gZXN0YWJsaXNoIGJhc2UgbG9jYWxlIHN0cmluZyBnZW5lcmF0aW9uXG4gICAqIGFuZCBpbnRlcm5hdGlvbmFsaXphdGlvbiBzdXBwb3J0LlxuICAgKlxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcIkZpbHRlckNvbXBvbmVudFwiKTtcbiAgICBhZGRJY29ucyh7Y2hldnJvbkRvd25PdXRsaW5lLCBjaGV2cm9uVXBPdXRsaW5lfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluaXRpYWxpemVzIHRoZSBjb21wb25lbnQgYWZ0ZXIgQW5ndWxhciBmaXJzdCBkaXNwbGF5cyB0aGUgZGF0YS1ib3VuZCBwcm9wZXJ0aWVzLlxuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBjb21wb25lbnQgYnkgaW5pdGlhbGl6aW5nIHdpbmRvdyB3aWR0aCB0cmFja2luZywgc2V0dGluZyB1cCByZXNpemUgZXZlbnRcbiAgICogc3Vic2NyaXB0aW9ucyB3aXRoIGRlYm91bmNpbmcsIGNvbmZpZ3VyaW5nIHNvcnRpbmcgb3B0aW9ucywgYW5kIGNhbGxpbmcgdGhlIGJhc2UgaW5pdGlhbGl6YXRpb24uXG4gICAqIFRoaXMgbWV0aG9kIHByZXBhcmVzIHRoZSBjb21wb25lbnQgZm9yIHVzZXIgaW50ZXJhY3Rpb24gYW5kIHJlc3BvbnNpdmUgYmVoYXZpb3IuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgQW5ndWxhciBMaWZlY3ljbGVcbiAgICogICBwYXJ0aWNpcGFudCBGIGFzIEZpbHRlckNvbXBvbmVudFxuICAgKiAgIHBhcnRpY2lwYW50IFcgYXMgV2luZG93XG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBSeEpTXG4gICAqXG4gICAqICAgQS0+PkY6IG5nT25Jbml0KClcbiAgICogICBGLT4+VzogZ2V0V2luZG93V2lkdGgoKVxuICAgKiAgIFctLT4+RjogUmV0dXJuIGN1cnJlbnQgd2lkdGhcbiAgICogICBGLT4+UjogU2V0dXAgcmVzaXplIHN1YnNjcmlwdGlvbiB3aXRoIGRlYm91bmNlXG4gICAqICAgUi0tPj5GOiBTdWJzY3JpcHRpb24gY3JlYXRlZFxuICAgKiAgIGFsdCBkaXNhYmxlU29ydCBpcyBmYWxzZVxuICAgKiAgICAgRi0+PkY6IE1lcmdlIHNvcnQgYW5kIGluZGV4ZXMgYXJyYXlzXG4gICAqICAgZW5kXG4gICAqICAgRi0+PkY6IENhbGwgaW5pdGlhbGl6ZSgpXG4gICAqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLndpbmRvd1dpZHRoID0gZ2V0V2luZG93V2lkdGgoKSBhcyBudW1iZXI7XG4gICAgdGhpcy53aW5kb3dSZXNpemVTdWJzY3JpcHRpb24gPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJylcbiAgICAucGlwZShkZWJvdW5jZVRpbWUoMzAwKSlcbiAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgdGhpcy53aW5kb3dXaWR0aCA9IGdldFdpbmRvd1dpZHRoKCkgYXMgbnVtYmVyO1xuICAgIH0pO1xuXG4gICAgdGhpcy5nZXRJbmRleGVzKCk7XG4gICAgdGhpcy5pbml0aWFsaXplKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbmQgY29uZmlndXJlcyBhdmFpbGFibGUgaW5kZXhlcyBmb3IgZmlsdGVyaW5nIGFuZCBzb3J0aW5nLlxuICAgKiBAc3VtbWFyeSBFeHRyYWN0cyBmaWVsZCBpbmRleGVzIGZyb20gdGhlIG1vZGVsIGlmIGF2YWlsYWJsZSBhbmQgbWVyZ2VzIHRoZW0gd2l0aFxuICAgKiBzb3J0aW5nIG9wdGlvbnMgd2hlbiBzb3J0aW5nIGlzIGVuYWJsZWQuIFRoaXMgbWV0aG9kIHNldHMgdXAgdGhlIGF2YWlsYWJsZSBmaWVsZFxuICAgKiBvcHRpb25zIGZvciBib3RoIGZpbHRlcmluZyBhbmQgc29ydGluZyBvcGVyYXRpb25zIGJhc2VkIG9uIHRoZSBtb2RlbCBzdHJ1Y3R1cmUuXG4gICAqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBnZXRJbmRleGVzKCk6IHZvaWQge1xuICAgIGlmKHRoaXMubW9kZWwpXG4gICAgICB0aGlzLmluZGV4ZXMgPSBPYmplY3Qua2V5cyhSZXBvc2l0b3J5LmluZGV4ZXModGhpcy5tb2RlbCBhcyBNb2RlbCkgfHwge30pO1xuICAgIGlmKCF0aGlzLmRpc2FibGVTb3J0KVxuICAgICAgdGhpcy5zb3J0QnkgPSBbLi4uIHRoaXMuc29ydEJ5LCAuLi50aGlzLmluZGV4ZXNdO1xuICB9XG5cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENsZWFudXAgbWV0aG9kIGNhbGxlZCB3aGVuIHRoZSBjb21wb25lbnQgaXMgZGVzdHJveWVkLlxuICAgKiBAc3VtbWFyeSBVbnN1YnNjcmliZXMgZnJvbSB3aW5kb3cgcmVzaXplIGV2ZW50cyB0byBwcmV2ZW50IG1lbW9yeSBsZWFrcy5cbiAgICogVGhpcyBpcyBlc3NlbnRpYWwgZm9yIHByb3BlciBjbGVhbnVwIG9mIFJ4SlMgc3Vic2NyaXB0aW9ucyB3aGVuIHRoZSBjb21wb25lbnRcbiAgICogaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00uXG4gICAqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLndpbmRvd1Jlc2l6ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuY2xlYXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBpbnB1dCBldmVudHMgZnJvbSB0aGUgdGV4dCBmaWVsZC5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIHVzZXIgaW5wdXQgYW5kIGZpbHRlcnMgdGhlIGF2YWlsYWJsZSBvcHRpb25zIGJhc2VkIG9uIHRoZSB0eXBlZCB2YWx1ZS5cbiAgICogVGhpcyBtZXRob2QgcHJvdmlkZXMgcmVhbC10aW1lIGZpbHRlcmluZyBvZiBzdWdnZXN0aW9ucyBhcyB0aGUgdXNlciB0eXBlcyBpbiB0aGUgaW5wdXQgZmllbGQuXG4gICAqXG4gICAqIEBwYXJhbSB7SW5wdXRFdmVudH0gZXZlbnQgLSBUaGUgaW5wdXQgZXZlbnQgY29udGFpbmluZyB0aGUgbmV3IHZhbHVlXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBoYW5kbGVJbnB1dChldmVudDogSW5wdXRFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHt2YWx1ZX0gPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIHRoaXMuZmlsdGVyZWRPcHRpb25zID0gdGhpcy5maWx0ZXJPcHRpb25zKHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBmb2N1cyBldmVudHMgb24gdGhlIGlucHV0IGZpZWxkLlxuICAgKiBAc3VtbWFyeSBTZXRzIHVwIHRoZSBhdmFpbGFibGUgb3B0aW9ucyB3aGVuIHRoZSBpbnB1dCBmaWVsZCByZWNlaXZlcyBmb2N1cyBhbmQgb3BlbnMgdGhlIGRyb3Bkb3duLlxuICAgKiBJZiBubyBvcHRpb25zIGFyZSBwcm92aWRlZCwgYXV0b21hdGljYWxseSBkZXRlcm1pbmVzIHRoZSBhcHByb3ByaWF0ZSBvcHRpb25zIGJhc2VkIG9uIGN1cnJlbnQgc3RlcC5cbiAgICogVGhpcyBtZXRob2QgaW5pdGlhbGl6ZXMgdGhlIGRyb3Bkb3duIHdpdGggY29udGV4dHVhbGx5IHJlbGV2YW50IHN1Z2dlc3Rpb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBvcHRpb25zIC0gT3B0aW9uYWwgYXJyYXkgb2Ygb3B0aW9ucyB0byBkaXNwbGF5XG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBoYW5kbGVGb2N1cyhvcHRpb25zOiBzdHJpbmdbXSAgPSBbXSk6IHZvaWQge1xuICAgIGlmKCFvcHRpb25zLmxlbmd0aClcbiAgICAgb3B0aW9ucyA9IHRoaXMuZ2V0T3B0aW9ucygpO1xuICAgIHRoaXMuZmlsdGVyZWRPcHRpb25zID0gdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLmRyb3Bkb3duT3BlbiA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgYmx1ciBldmVudHMgb24gdGhlIGlucHV0IGZpZWxkIHdpdGggZGVsYXllZCBjbG9zaW5nLlxuICAgKiBAc3VtbWFyeSBNYW5hZ2VzIHRoZSBkcm9wZG93biBjbG9zaW5nIGJlaGF2aW9yIHdpdGggYSBkZWxheSB0byBhbGxvdyBmb3Igb3B0aW9uIHNlbGVjdGlvbi5cbiAgICogVXNlcyBhIHR3by1waGFzZSBhcHByb2FjaCB0byBwcmV2ZW50IHByZW1hdHVyZSBjbG9zaW5nIHdoZW4gdXNlcnMgY2xpY2sgb24gZHJvcGRvd24gb3B0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHtib29sZWFufSBjbG9zZSAtIEludGVybmFsIGZsYWcgdG8gY29udHJvbCB0aGUgY2xvc2luZyBwaGFzZVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgaGFuZGxlQmx1cihjbG9zZTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYoIWNsb3NlKSB7XG4gICAgICB0aGlzLmRyb3Bkb3duT3BlbiA9IGZhbHNlO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuaGFuZGxlQmx1cih0cnVlKTtcbiAgICAgIH0sIDEwMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmKCF0aGlzLmRyb3Bkb3duT3BlbiAmJiB0aGlzLm9wdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMub3B0aW9ucyA9IFtdO1xuICAgICAgICAgIHRoaXMuZHJvcGRvd25PcGVuID0gZmFsc2U7XG4gICAgICAgIH0sIDUwKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERldGVybWluZXMgdGhlIGFwcHJvcHJpYXRlIG9wdGlvbnMgYmFzZWQgb24gdGhlIGN1cnJlbnQgZmlsdGVyIHN0ZXAuXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGNvbnRleHR1YWxseSByZWxldmFudCBvcHRpb25zIGZvciB0aGUgY3VycmVudCBzdGVwIGluIHRoZSBmaWx0ZXIgY3JlYXRpb24gcHJvY2Vzcy5cbiAgICogU3RlcCAxIHNob3dzIGluZGV4ZXMsIFN0ZXAgMiBzaG93cyBjb25kaXRpb25zLCBTdGVwIDMgc2hvd3Mgbm8gb3B0aW9ucyAodmFsdWUgaW5wdXQpLlxuICAgKlxuICAgKiBAcmV0dXJucyB7c3RyaW5nW119IEFycmF5IG9mIG9wdGlvbnMgYXBwcm9wcmlhdGUgZm9yIHRoZSBjdXJyZW50IHN0ZXBcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgZ2V0T3B0aW9ucygpOiBzdHJpbmdbXSB7XG4gICBzd2l0Y2ggKHRoaXMuc3RlcCkge1xuICAgICAgY2FzZSAxOlxuICAgICAgICB0aGlzLm9wdGlvbnMgPSB0aGlzLmluZGV4ZXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICB0aGlzLm9wdGlvbnMgPSB0aGlzLmNvbmRpdGlvbnM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzOlxuICAgICAgICB0aGlzLm9wdGlvbnMgPSBbXTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm9wdGlvbnNcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkcyBhIGZpbHRlciBzdGVwIG9yIGNvbXBsZXRlcyBmaWx0ZXIgY3JlYXRpb24gdGhyb3VnaCBhIHRocmVlLXN0ZXAgcHJvY2Vzcy5cbiAgICogQHN1bW1hcnkgQ29yZSBtZXRob2QgZm9yIGJ1aWxkaW5nIGZpbHRlcnMgc3RlcCBieSBzdGVwOiBTdGVwIDEgKEluZGV4KSDihpIgU3RlcCAyIChDb25kaXRpb24pIOKGkiBTdGVwIDMgKFZhbHVlKS5cbiAgICogV2hlbiBhbGwgc3RlcHMgYXJlIGNvbXBsZXRlLCBjcmVhdGVzIGEgY29tcGxldGUgZmlsdGVyIG9iamVjdCBhbmQgYWRkcyBpdCB0byB0aGUgZmlsdGVyIGNvbGxlY3Rpb24uXG4gICAqIEhhbmRsZXMgYm90aCBrZXlib2FyZCBldmVudHMgKEVudGVyIHRvIHN1Ym1pdCkgYW5kIHByb2dyYW1tYXRpYyBjYWxscy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gVGhlIHZhbHVlIHRvIGFkZCBmb3IgdGhlIGN1cnJlbnQgc3RlcFxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50fSBldmVudCAtIE9wdGlvbmFsIGV2ZW50IChLZXlib2FyZEV2ZW50IHRyaWdnZXJzIHN1Ym1pc3Npb24gd2hlbiB2YWx1ZSBpcyBlbXB0eSlcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlclxuICAgKiAgIHBhcnRpY2lwYW50IEYgYXMgRmlsdGVyQ29tcG9uZW50XG4gICAqXG4gICAqICAgVS0+PkY6IGFkZEZpbHRlcih2YWx1ZSwgZXZlbnQpXG4gICAqICAgRi0+PkY6IFRyaW0gYW5kIHZhbGlkYXRlIHZhbHVlXG4gICAqICAgYWx0IEtleWJvYXJkRXZlbnQgJiYgZW1wdHkgdmFsdWVcbiAgICogICAgIEYtPj5GOiBzdWJtaXQoKSAtIFNlbmQgY3VycmVudCBmaWx0ZXJzXG4gICAqICAgZWxzZSBWYWxpZCB2YWx1ZSBvciBzdGVwIDNcbiAgICogICAgIGFsdCBTdGVwIDEgKEluZGV4KVxuICAgKiAgICAgICBGLT4+RjogbGFzdEZpbHRlci5pbmRleCA9IHZhbHVlXG4gICAqICAgICAgIEYtPj5GOiBvcHRpb25zID0gY29uZGl0aW9uc1xuICAgKiAgICAgZWxzZSBTdGVwIDIgKENvbmRpdGlvbilcbiAgICogICAgICAgRi0+PkY6IGxhc3RGaWx0ZXIuY29uZGl0aW9uID0gdmFsdWVcbiAgICogICAgICAgRi0+PkY6IG9wdGlvbnMgPSBbXVxuICAgKiAgICAgZWxzZSBTdGVwIDMgKFZhbHVlKVxuICAgKiAgICAgICBGLT4+RjogbGFzdEZpbHRlci52YWx1ZSA9IHZhbHVlXG4gICAqICAgICAgIEYtPj5GOiBBZGQgY29tcGxldGUgZmlsdGVyIHRvIGZpbHRlclZhbHVlXG4gICAqICAgICAgIEYtPj5GOiBSZXNldCBzdGVwIHRvIDFcbiAgICogICAgIGVuZFxuICAgKiAgICAgRi0+PkY6IEluY3JlbWVudCBzdGVwXG4gICAqICAgICBGLT4+RjogQ2xlYXIgaW5wdXQgJiBmb2N1c1xuICAgKiAgICAgRi0+PkY6IFNob3cgbmV4dCBvcHRpb25zXG4gICAqICAgZW5kXG4gICAqXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIGFkZEZpbHRlcih2YWx1ZTogc3RyaW5nLCBldmVudD86IEN1c3RvbUV2ZW50KTogdm9pZCB7XG4gICAgdmFsdWUgPSB2YWx1ZS50cmltKCk7XG4gICAgaWYoZXZlbnQgaW5zdGFuY2VvZiBLZXlib2FyZEV2ZW50ICYmICF2YWx1ZSkge1xuICAgICAgdGhpcy5zdWJtaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgIGlmKCh2YWx1ZSAmJiAoIShldmVudCBpbnN0YW5jZW9mIEtleWJvYXJkRXZlbnQpKSB8fCB0aGlzLnN0ZXAgPT09IDMpKSB7XG4gICAgICAgIGNvbnN0IGZpbHRlciA9IHRoaXMubGFzdEZpbHRlcjtcbiAgICAgICAgc3dpdGNoICh0aGlzLnN0ZXApIHtcbiAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICBmaWx0ZXJbJ2luZGV4J10gPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHRoaXMuY29uZGl0aW9ucztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIGZpbHRlclsnY29uZGl0aW9uJ10gPSB2YWx1ZTtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IFtdO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgZmlsdGVyWyd2YWx1ZSddID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB0aGlzLmluZGV4ZXM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZighdGhpcy5maWx0ZXJWYWx1ZS5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLmZpbHRlclZhbHVlLnB1c2goZmlsdGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZih0aGlzLnN0ZXAgPT09IDEpXG4gICAgICAgICAgICB0aGlzLmZpbHRlclZhbHVlLnB1c2goZmlsdGVyKTtcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLnN0ZXAgPT09IDMpIHtcbiAgICAgICAgICB0aGlzLnN0ZXAgPSAwO1xuICAgICAgICAgIHRoaXMuZmlsdGVyVmFsdWVbdGhpcy5maWx0ZXJWYWx1ZS5sZW5ndGggLSAxXSA9IGZpbHRlcjtcbiAgICAgICAgICB0aGlzLmxhc3RGaWx0ZXIgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0ZXArKztcbiAgICAgICAgdGhpcy52YWx1ZSA9ICcnO1xuICAgICAgICBpZih0aGlzLm9wdGlvbnMubGVuZ3RoKVxuICAgICAgICAgIHRoaXMuaGFuZGxlRm9jdXModGhpcy5vcHRpb25zKTtcbiAgICAgICAgdGhpcy5jb21wb25lbnQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2VsZWN0cyBhbiBvcHRpb24gZnJvbSB0aGUgZHJvcGRvd24gc3VnZ2VzdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEhhbmRsZXMgb3B0aW9uIHNlbGVjdGlvbiB3aGVuIGEgdXNlciBjbGlja3Mgb24gYSBzdWdnZXN0aW9uIGluIHRoZSBkcm9wZG93bi5cbiAgICogVGhpcyBtZXRob2QgYWN0cyBhcyBhIGJyaWRnZSBiZXR3ZWVuIGRyb3Bkb3duIGNsaWNrcyBhbmQgdGhlIG1haW4gYWRkRmlsdGVyIGxvZ2ljLlxuICAgKlxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50fSBldmVudCAtIFRoZSBjbGljayBldmVudCBmcm9tIHRoZSBkcm9wZG93biBvcHRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gVGhlIHNlbGVjdGVkIG9wdGlvbiB2YWx1ZVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgc2VsZWN0T3B0aW9uKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmFkZEZpbHRlcih2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERldGVybWluZXMgaWYgYSBmaWx0ZXIgb3B0aW9uIGNhbiBiZSBpbmRpdmlkdWFsbHkgcmVtb3ZlZC5cbiAgICogQHN1bW1hcnkgQ2hlY2tzIHdoZXRoZXIgYSBmaWx0ZXIgY29tcG9uZW50IHNob3VsZCBkaXNwbGF5IGEgY2xvc2UgaWNvbiBmb3IgcmVtb3ZhbC5cbiAgICogT25seSB2YWx1ZSBvcHRpb25zIGNhbiBiZSByZW1vdmVkIGluZGl2aWR1YWxseTsgaW5kZXggYW5kIGNvbmRpdGlvbiBvcHRpb25zIGFyZSBwYXJ0XG4gICAqIG9mIHRoZSBjb21wbGV0ZSBmaWx0ZXIgc3RydWN0dXJlIGFuZCBjYW5ub3QgYmUgcmVtb3ZlZCBzZXBhcmF0ZWx5LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9uIC0gVGhlIGZpbHRlciBvcHRpb24gdGV4dCB0byBjaGVja1xuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgb3B0aW9uIGNhbiBiZSBjbGVhcmVkIGluZGl2aWR1YWxseSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqIEBtZW1iZXJPZiBGaWx0ZXJDb21wb25lbnRcbiAgICovXG4gIGFsbG93Q2xlYXIob3B0aW9uOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbmRleGVzLmluZGV4T2Yob3B0aW9uKSA9PT0gLTEgJiYgdGhpcy5jb25kaXRpb25zLmluZGV4T2Yob3B0aW9uKSA9PT0gLTE7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlbW92ZXMgYSBjb21wbGV0ZSBmaWx0ZXIgZnJvbSB0aGUgY29sbGVjdGlvbiBiYXNlZCBvbiBmaWx0ZXIgdmFsdWUuXG4gICAqIEBzdW1tYXJ5IFJlbW92ZXMgYSBjb21wbGV0ZSBmaWx0ZXIgYnkgbWF0Y2hpbmcgdGhlIHByb3ZpZGVkIHZhbHVlIGFnYWluc3QgZmlsdGVyIHZhbHVlc1xuICAgKiBpbiB0aGUgY29sbGVjdGlvbi4gVXNlcyBzdHJpbmcgbm9ybWFsaXphdGlvbiB0byBoYW5kbGUgYWNjZW50cyBhbmQgY2FzZSBkaWZmZXJlbmNlcy5cbiAgICogQWZ0ZXIgcmVtb3ZhbCwgcmVzZXRzIHRoZSBpbnRlcmZhY2UgdG8gc2hvdyBhdmFpbGFibGUgaW5kZXhlcyBmb3IgbmV3IGZpbHRlciBjcmVhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbHRlciAtIFRoZSBmaWx0ZXIgdmFsdWUgdG8gcmVtb3ZlIChtYXRjaGVzIGFnYWluc3QgZmlsdGVyLnZhbHVlIHByb3BlcnR5KVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VyXG4gICAqICAgcGFydGljaXBhbnQgRiBhcyBGaWx0ZXJDb21wb25lbnRcbiAgICpcbiAgICogICBVLT4+RjogcmVtb3ZlRmlsdGVyKGZpbHRlclZhbHVlKVxuICAgKiAgIEYtPj5GOiBjbGVhblN0cmluZyhmaWx0ZXJWYWx1ZSlcbiAgICogICBGLT4+RjogRmlsdGVyIG91dCBtYXRjaGluZyBmaWx0ZXIgb2JqZWN0c1xuICAgKiAgIEYtPj5GOiBDbGVhciBpbnB1dCB2YWx1ZVxuICAgKiAgIEYtPj5GOiBoYW5kbGVGb2N1cyhpbmRleGVzKSAtIFJlc2V0IHRvIGluZGV4IHNlbGVjdGlvblxuICAgKiAgIE5vdGUgb3ZlciBGOiBGaWx0ZXIgcmVtb3ZlZCBhbmQgVUkgcmVzZXRcbiAgICpcbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgcmVtb3ZlRmlsdGVyKGZpbHRlcjogc3RyaW5nKTogdm9pZCB7XG4gICAgZnVuY3Rpb24gY2xlYW5TdHJpbmcoZmlsdGVyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIGZpbHRlclxuICAgICAgICAudG9Mb3dlckNhc2UoKSAgICAgICAgICAgICAgICAgLy8gY29udmVydCBhbGwgY2hhcmFjdGVycyB0byBsb3dlcmNhc2VcbiAgICAgICAgLm5vcm1hbGl6ZShcIk5GRFwiKSAgICAgICAgICAgICAgLy8gc2VwYXJhdGUgYWNjZW50IG1hcmtzIGZyb20gY2hhcmFjdGVyc1xuICAgICAgICAucmVwbGFjZSgvW1xcdTAzMDAtXFx1MDM2Zl0vZywgXCJcIikgLy8gcmVtb3ZlIGFjY2VudCBtYXJrc1xuICAgICAgICAucmVwbGFjZSgvXFxzKy9nLCBcIlwiKTsgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB3aGl0ZXNwYWNlXG4gICAgfVxuICAgIHRoaXMudmFsdWUgPSBcIlwiO1xuICAgIHRoaXMuZmlsdGVyVmFsdWUgPSB0aGlzLmZpbHRlclZhbHVlLmZpbHRlcigoaXRlbSkgPT4gaXRlbT8uWyd2YWx1ZSddICYmIGNsZWFuU3RyaW5nKGl0ZW0/LlsndmFsdWUnXSkgIT09IGNsZWFuU3RyaW5nKGZpbHRlcikpO1xuICAgIGlmKHRoaXMuZmlsdGVyVmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnN0ZXAgPSAxO1xuICAgICAgdGhpcy5sYXN0RmlsdGVyID0ge307XG4gICAgfVxuICAgIHRoaXMuaGFuZGxlRm9jdXModGhpcy5pbmRleGVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVzZXRzIHRoZSBjb21wb25lbnQgdG8gaXRzIGluaXRpYWwgc3RhdGUuXG4gICAqIEBzdW1tYXJ5IENsZWFycyBhbGwgZmlsdGVyIGRhdGEsIG9wdGlvbnMsIGFuZCByZXNldHMgdGhlIHN0ZXAgY291bnRlciB0byAxLlxuICAgKiBUaGlzIG1ldGhvZCBwcm92aWRlcyBhIGNsZWFuIHNsYXRlIGZvciBuZXcgZmlsdGVyIGNyZWF0aW9uIHdpdGhvdXQgZW1pdHRpbmcgZXZlbnRzLlxuICAgKlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zID0gdGhpcy5maWx0ZXJlZE9wdGlvbnMgPSB0aGlzLmZpbHRlclZhbHVlID0gW107XG4gICAgdGhpcy5zdGVwID0gMTtcbiAgICB0aGlzLmxhc3RGaWx0ZXIgPSB7fTtcbiAgICB0aGlzLnZhbHVlID0gJyc7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgdGhpcy5zdWJtaXQoKTtcbiAgICB9LCAxMDApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDbGVhcnMgYWxsIGZpbHRlcnMgYW5kIG5vdGlmaWVzIHBhcmVudCBjb21wb25lbnRzLlxuICAgKiBAc3VtbWFyeSBSZXNldHMgdGhlIGNvbXBvbmVudCBzdGF0ZSBhbmQgZW1pdHMgdW5kZWZpbmVkIHRvIG5vdGlmeSBwYXJlbnQgY29tcG9uZW50c1xuICAgKiB0aGF0IGFsbCBmaWx0ZXJzIGhhdmUgYmVlbiBjbGVhcmVkLiBUaGlzIHRyaWdnZXJzIGFueSBjb25uZWN0ZWQgZGF0YSByZWZyZXNoIGxvZ2ljLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBPcHRpb25hbCBwYXJhbWV0ZXIgKGN1cnJlbnRseSB1bnVzZWQpXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBjbGVhcih2YWx1ZT86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmKCF2YWx1ZSlcbiAgICAgIHRoaXMucmVzZXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3VibWl0cyB0aGUgY3VycmVudCBmaWx0ZXIgY29sbGVjdGlvbiB0byBwYXJlbnQgY29tcG9uZW50cy5cbiAgICogQHN1bW1hcnkgRW1pdHMgdGhlIGN1cnJlbnQgZmlsdGVyIGFycmF5IHRvIHBhcmVudCBjb21wb25lbnRzIHdoZW4gZmlsdGVycyBhcmUgcmVhZHlcbiAgICogdG8gYmUgYXBwbGllZC4gT25seSBlbWl0cyBpZiB0aGVyZSBhcmUgYWN0aXZlIGZpbHRlcnMuIENsZWFycyBvcHRpb25zIGFmdGVyIHN1Ym1pc3Npb24uXG4gICAqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBzdWJtaXQoKTogdm9pZCB7XG4gICAgdGhpcy5maWx0ZXJFdmVudC5lbWl0KHtcbiAgICAgIHF1ZXJ5OiB0aGlzLmZpbHRlclZhbHVlLmxlbmd0aCA+IDAgPyB0aGlzLmZpbHRlclZhbHVlIDogdW5kZWZpbmVkLFxuICAgICAgc29ydDoge1xuICAgICAgICB2YWx1ZTogdGhpcy5zb3J0VmFsdWUsXG4gICAgICAgIGRpcmVjdGlvbjogdGhpcy5zb3J0RGlyZWN0aW9uXG4gICAgICB9XG4gICAgfSBhcyBJRmlsdGVyUXVlcnkpO1xuICAgIGlmKHRoaXMuZmlsdGVyVmFsdWUubGVuZ3RoID09PSAwKVxuICAgICAgdGhpcy5vcHRpb25zID0gW107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRvZ2dsZXMgdGhlIHNvcnQgZGlyZWN0aW9uIGJldHdlZW4gYXNjZW5kaW5nIGFuZCBkZXNjZW5kaW5nLlxuICAgKiBAc3VtbWFyeSBIYW5kbGVzIHNvcnQgZGlyZWN0aW9uIGNoYW5nZXMgYnkgdG9nZ2xpbmcgYmV0d2VlbiBBU0MgYW5kIERTQyB2YWx1ZXMuXG4gICAqIFdoZW4gdGhlIGRpcmVjdGlvbiBjaGFuZ2VzLCBhdXRvbWF0aWNhbGx5IHRyaWdnZXJzIGEgc3VibWl0IHRvIGFwcGx5IHRoZSBuZXdcbiAgICogc29ydGluZyBjb25maWd1cmF0aW9uIHRvIHRoZSBmaWx0ZXJlZCByZXN1bHRzLlxuICAgKlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgIGhhbmRsZVNvcnREaXJlY3Rpb25DaGFuZ2UoKTogdm9pZCB7XG4gICAgY29uc3QgZGlyZWN0aW9uID0gdGhpcy5zb3J0RGlyZWN0aW9uID09PSAgT3JkZXJEaXJlY3Rpb24uQVNDID8gT3JkZXJEaXJlY3Rpb24uRFNDIDogT3JkZXJEaXJlY3Rpb24uQVNDO1xuICAgIGlmKGRpcmVjdGlvbiAhPT0gdGhpcy5zb3J0RGlyZWN0aW9uKSB7XG4gICAgICB0aGlzLnNvcnREaXJlY3Rpb24gPSBkaXJlY3Rpb247XG4gICAgICB0aGlzLnN1Ym1pdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBzb3J0IGZpZWxkIHNlbGVjdGlvbiBjaGFuZ2VzIGZyb20gdGhlIGRyb3Bkb3duLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgc29ydCBmaWVsZCBjaGFuZ2VzIHdoZW4gdXNlcnMgc2VsZWN0IGEgZGlmZmVyZW50IGZpZWxkXG4gICAqIGZyb20gdGhlIHNvcnQgZHJvcGRvd24uIFVwZGF0ZXMgdGhlIHNvcnRWYWx1ZSBwcm9wZXJ0eSBhbmQgdHJpZ2dlcnNcbiAgICogYSBzdWJtaXQgdG8gYXBwbHkgdGhlIG5ldyBzb3J0aW5nIGNvbmZpZ3VyYXRpb24gaWYgdGhlIHZhbHVlIGhhcyBjaGFuZ2VkLlxuICAgKlxuICAgKiBAcGFyYW0ge0N1c3RvbUV2ZW50fSBldmVudCAtIFRoZSBzZWxlY3QgY2hhbmdlIGV2ZW50IGNvbnRhaW5pbmcgdGhlIG5ldyBzb3J0IGZpZWxkIHZhbHVlXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBoYW5kbGVTb3J0Q2hhbmdlKGV2ZW50OiBDdXN0b21FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW9uU2VsZWN0RWxlbWVudDtcbiAgICBjb25zdCB2YWx1ZSA9IHRhcmdldC52YWx1ZTtcbiAgICBpZih2YWx1ZSAhPT0gdGhpcy5zb3J0VmFsdWUpIHtcbiAgICAgIHRoaXMuc29ydFZhbHVlID0gdmFsdWUgYXMgc3RyaW5nO1xuICAgICAgdGhpcy5zdWJtaXQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZpbHRlcnMgYXZhaWxhYmxlIG9wdGlvbnMgYmFzZWQgb24gdXNlciBpbnB1dCB3aXRoIHZpc3VhbCBoaWdobGlnaHRpbmcuXG4gICAqIEBzdW1tYXJ5IFBlcmZvcm1zIHJlYWwtdGltZSBmaWx0ZXJpbmcgb2YgYXZhaWxhYmxlIG9wdGlvbnMgYmFzZWQgb24gdXNlciBpbnB1dC5cbiAgICogQWxzbyBoYW5kbGVzIHZpc3VhbCBoaWdobGlnaHRpbmcgb2YgbWF0Y2hpbmcgb3B0aW9ucyBpbiB0aGUgZHJvcGRvd24uIFJldHVybnMgYWxsXG4gICAqIG9wdGlvbnMgaWYgaW5wdXQgaXMgbGVzcyB0aGFuIDIgY2hhcmFjdGVycyBmb3IgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bGwgfCB1bmRlZmluZWR9IHZhbHVlIC0gVGhlIHNlYXJjaCB2YWx1ZSB0byBmaWx0ZXIgYnlcbiAgICogQHJldHVybnMge3N0cmluZ1tdfSBBcnJheSBvZiBmaWx0ZXJlZCBvcHRpb25zIHRoYXQgbWF0Y2ggdGhlIGlucHV0XG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlclxuICAgKiAgIHBhcnRpY2lwYW50IEYgYXMgRmlsdGVyQ29tcG9uZW50XG4gICAqICAgcGFydGljaXBhbnQgRCBhcyBET01cbiAgICpcbiAgICogICBVLT4+RjogZmlsdGVyT3B0aW9ucyhpbnB1dFZhbHVlKVxuICAgKiAgIGFsdCBpbnB1dFZhbHVlIDwgMiBjaGFyYWN0ZXJzXG4gICAqICAgICBGLT4+RDogUmVtb3ZlIGV4aXN0aW5nIGhpZ2hsaWdodHNcbiAgICogICAgIEYtLT4+VTogUmV0dXJuIGFsbCBvcHRpb25zXG4gICAqICAgZWxzZSBpbnB1dFZhbHVlID49IDIgY2hhcmFjdGVyc1xuICAgKiAgICAgRi0+PkQ6IFF1ZXJ5IGFsbCBvcHRpb24gZWxlbWVudHNcbiAgICogICAgIEYtPj5EOiBBZGQgaGlnaGxpZ2h0IHRvIGZpcnN0IG1hdGNoaW5nIG9wdGlvblxuICAgKiAgICAgRi0+PkY6IEZpbHRlciBvcHRpb25zIGJ5IHN1YnN0cmluZyBtYXRjaFxuICAgKiAgICAgRi0tPj5VOiBSZXR1cm4gZmlsdGVyZWQgb3B0aW9uc1xuICAgKiAgIGVuZFxuICAgKlxuICAgKiBAbWVtYmVyT2YgRmlsdGVyQ29tcG9uZW50XG4gICAqL1xuICBmaWx0ZXJPcHRpb25zKHZhbHVlOiBzdHJpbmcgfCBudWxsIHwgIHVuZGVmaW5lZCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBvcHRpb25zRWxlbWVudCA9IHRoaXMub3B0aW9uc0ZpbHRlckVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICBpZighdmFsdWU/Lmxlbmd0aCB8fCAhdmFsdWUgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgY29uc3QgZmlsdGVyZWRPcHRpb24gPSBvcHRpb25zRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuZGNmLWZpbHRlcmluZy1pdGVtJyk7XG4gICAgICBpZihmaWx0ZXJlZE9wdGlvbilcbiAgICAgICAgZmlsdGVyZWRPcHRpb24uY2xhc3NMaXN0LnJlbW92ZSgnZGNmLWZpbHRlcmluZy1pdGVtJyk7XG4gICAgICByZXR1cm4gdGhpcy5vcHRpb25zO1xuICAgIH1cbiAgICBjb25zdCBvcHRpb25zID0gb3B0aW9uc0VsZW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmRjZi1pdGVtJyk7XG4gICAgZm9yIChjb25zdCBvcHRpb24gb2Ygb3B0aW9ucykge1xuICAgICAgY29uc3QgaXNBY3RpdmUgPSBvcHRpb24udGV4dENvbnRlbnQ/LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModmFsdWUudG9Mb3dlckNhc2UoKSk7XG4gICAgICBpZihpc0FjdGl2ZSkge1xuICAgICAgICBvcHRpb24uY2xhc3NMaXN0LmFkZCgnZGNmLWZpbHRlcmluZy1pdGVtJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmZpbHRlcigob3B0aW9uOiBzdHJpbmcpID0+IG9wdGlvbi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHZhbHVlLnRvTG93ZXJDYXNlKCkgYXMgc3RyaW5nKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgc2VhcmNoIGV2ZW50cyBmcm9tIHRoZSBpbnRlZ3JhdGVkIHNlYXJjaGJhciBjb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBzZWFyY2ggaW5wdXQgZnJvbSB0aGUgc2VhcmNoYmFyIGFuZCBlbWl0cyBzZWFyY2ggZXZlbnRzXG4gICAqIHRvIHBhcmVudCBjb21wb25lbnRzLiBUaGlzIG1ldGhvZCBhY3RzIGFzIGEgYnJpZGdlIGJldHdlZW4gdGhlIGludGVybmFsXG4gICAqIHNlYXJjaGJhciBjb21wb25lbnQgYW5kIGV4dGVybmFsIHNlYXJjaCBldmVudCBsaXN0ZW5lcnMuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkfSB2YWx1ZSAtIFRoZSBzZWFyY2ggdmFsdWUgZW50ZXJlZCBieSB0aGUgdXNlclxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICogQG1lbWJlck9mIEZpbHRlckNvbXBvbmVudFxuICAgKi9cbiAgaGFuZGxlU2VhcmNoKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICB0aGlzLnNlYXJjaEV2ZW50LmVtaXQodmFsdWUpO1xuICB9XG5cbn1cbiIsIlxuQGlmKCFpbmRleGVzLmxlbmd0aCkge1xuICA8bmd4LWRlY2FmLXNlYXJjaGJhciBbZW1pdEV2ZW50VG9XaW5kb3ddPVwiZmFsc2VcIiBbZGVib3VuY2VdPVwiNTAwXCIgKHNlYXJjaEV2ZW50KT1cImhhbmRsZVNlYXJjaCgkZXZlbnQpXCIgLz5cbn1cblxuPGRpdiBjbGFzcz1cImRjZi1ncmlkIGRjZi1ncmlkLXNtYWxsIGRjZi1ncmlkLW1hdGNoIGRjZi1maWx0ZXItZ3JpZFwiIFtuZ0NsYXNzXT1cInsnZGNmLWhpZGRlbic6ICFpbmRleGVzLmxlbmd0aH1cIj5cbiAgPGRpdiBjbGFzcz1cImRjZi13aWR0aC1leHBhbmRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZGNmLWZpbHRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImRjZi1pbnB1dFwiPlxuICAgICAgICBAZm9yKGZpbHRlciBvZiBmaWx0ZXJWYWx1ZTsgdHJhY2sgdHJhY2tJdGVtRm4oJGluZGV4LCBmaWx0ZXI/LlsnaW5kZXgnXSkpIHtcbiAgICAgICAgICBAaWYoZmlsdGVyPy5bJ2luZGV4J10pIHtcbiAgICAgICAgICAgIDxpb24tY2hpcCBbb3V0bGluZV09XCJ0cnVlXCI+e3sgZmlsdGVyPy5bJ2luZGV4J10gfX08L2lvbi1jaGlwPlxuICAgICAgICAgIH1cbiAgICAgICAgICBAaWYoZmlsdGVyPy5bJ2NvbmRpdGlvbiddKSB7XG4gICAgICAgICAgICA8aW9uLWNoaXAgW291dGxpbmVdPVwidHJ1ZVwiPnt7IGZpbHRlcj8uWydjb25kaXRpb24nXSB9fTwvaW9uLWNoaXA+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBpZihmaWx0ZXI/LlsndmFsdWUnXSkge1xuICAgICAgICAgICAgPGlvbi1jaGlwIFtvdXRsaW5lXT1cInRydWVcIiBjbGFzcz1cImRjZi1maWx0ZXItdmFsdWVcIj5cbiAgICAgICAgICAgICAge3sgZmlsdGVyPy5bJ3ZhbHVlJ10gfX1cbiAgICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJjbG9zZVwiIChjbGljayk9XCJyZW1vdmVGaWx0ZXIoZmlsdGVyPy5bJ3ZhbHVlJ10pXCIgc2l6ZT1cInNtYWxsXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgIDwvaW9uLWNoaXA+XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkY2Ytd2lkdGgtMS0xXCI+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcbiAgICAgICAgICAgIChrZXlkb3duLmVudGVyKT1cImFkZEZpbHRlcih2YWx1ZSwgJGV2ZW50KVwiXG4gICAgICAgICAgICAoa2V5ZG93bi5iYWNrc3BhY2UpPVwiY2xlYXIodmFsdWUpXCJcbiAgICAgICAgICAgIChpbnB1dCk9XCJoYW5kbGVJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChjbGljayk9XCJoYW5kbGVGb2N1cygpXCJcbiAgICAgICAgICAgIChibHVyKT1cImhhbmRsZUJsdXIoKVwiXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBbcmVhZG9ubHldPVwic3RlcCAhPT0gM1wiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7IGxvY2FsZSArIChzdGVwID09PSAzID8gJy50eXBlJyA6ICcuc2VsZWN0JykgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgI2NvbXBvbmVudFxuICAgICAgICAgIC8+XG4gICAgICAgICAgQGlmKHdpbmRvd1dpZHRoID49IDc2OCkge1xuICAgICAgICAgICAgPGRpdiBbY2xhc3NdPVwiJ2RjZi1kcm9wZG93biAnICsgKG9wdGlvbnMubGVuZ3RoID4gMCA/ICcgZGNmLWFjdGl2ZScgOiAnJylcIiAjb3B0aW9uc0ZpbHRlckVsZW1lbnQ+XG4gICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgQGlmKGZpbHRlcmVkT3B0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICBAZm9yKGtleSBvZiBmaWx0ZXJlZE9wdGlvbnM7IHRyYWNrIGtleSkge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkY2YtaXRlbVwiXG4gICAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg9XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJzZWxlY3RPcHRpb24oa2V5KVwiXG4gICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdE9wdGlvbihrZXkpXCI+XG4gICAgICAgICAgICAgICAgICAgICAge3sga2V5IH19XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRjZi1lbXB0eVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJmaWx0ZXJlZE9wdGlvbnMgPSBvcHRpb25zOyB2YWx1ZSA9ICcnXCJcbiAgICAgICAgICAgICAgICAgICAgdGFiaW5kZXg9XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiZmlsdGVyZWRPcHRpb25zID0gb3B0aW9uczsgdmFsdWUgPSAnJ1wiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHt7ICdub19zdWdnZXN0aW9ucycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICBAaWYoZmlsdGVyVmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwiZGNmLWljb24tY2xlYXJcIj5cbiAgICAgICAgICA8aW9uLWJ1dHRvbiBmaWxsPVwiY2xlYXJcIiBzaXplPVwic21hbGxcIiAoY2xpY2spPVwiY2xlYXIoKVwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJ0cmFzaC1vdXRsaW5lXCIgY29sb3I9XCJkYXJrXCIgc2xvdD1cImljb24tb25seVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICAgIDxkaXYgY2xhc3M9XCJkY2YtaWNvbi1zZWFyY2hcIj5cbiAgICAgICAgPGlvbi1idXR0b24gZmlsbD1cImNsZWFyXCIgc2l6ZT1cInNtYWxsXCIgKGNsaWNrKT1cInN1Ym1pdCgpXCI+XG4gICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzZWFyY2gtb3V0bGluZVwiIGNvbG9yPVwiZGFya1wiIHNsb3Q9XCJpY29uLW9ubHlcIj48L2lvbi1pY29uPlxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICBAaWYod2luZG93V2lkdGggPCA3NjgpIHtcbiAgICAgIDxkaXYgW2NsYXNzXT1cIidkY2YtZHJvcGRvd24gJyArIChvcHRpb25zLmxlbmd0aCA+IDAgPyAnIGRjZi1hY3RpdmUnIDogJycpXCIgI29wdGlvbnNGaWx0ZXJFbGVtZW50PlxuICAgICAgICA8ZGl2PlxuICAgICAgICAgIEBpZihmaWx0ZXJlZE9wdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgQGZvcihrZXkgb2YgZmlsdGVyZWRPcHRpb25zOyB0cmFjayBrZXkpIHtcbiAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZGNmLWl0ZW1cIlxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwic2VsZWN0T3B0aW9uKGtleSlcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RPcHRpb24oa2V5KVwiPlxuICAgICAgICAgICAgICAgIHt7IGtleSB9fVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkY2YtZW1wdHlcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImZpbHRlcmVkT3B0aW9ucyA9IG9wdGlvbnM7IHZhbHVlID0gJydcIlxuICAgICAgICAgICAgdGFiaW5kZXg9XCIwXCJcbiAgICAgICAgICAgIChrZXlkb3duLmVudGVyKT1cImZpbHRlcmVkT3B0aW9ucyA9IG9wdGlvbnM7IHZhbHVlID0gJydcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyAnbm9fc3VnZ2VzdGlvbnMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbiAgQGlmKCFkaXNhYmxlU29ydCkge1xuICAgIDxkaXYgY2xhc3M9XCJkY2Ytd2lkdGgtMS01QG0gZGNmLXdpZHRoLTEtMSBkY2Ytc29ydC1jb250YWluZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkY2YtZ3JpZCBkY2YtZ3JpZC1jb2xsYXBzZSBkY2YtZmxleCBkY2YtZmxleC1taWRkbGUgZGNmLWdyaWQtbWF0Y2hcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRjZi13aWR0aC1leHBhbmRcIj5cbiAgICAgICAgICA8aW9uLXNlbGVjdFxuICAgICAgICAgICAgICB0b2dnbGVJY29uPVwiY2hldnJvbi1kb3duLW91dGxpbmVcIlxuICAgICAgICAgICAgICBleHBhbmRlZEljb249XCJjaGV2cm9uLXVwLW91dGxpbmVcIlxuICAgICAgICAgICAgICBjbGFzcz1cImRjZi1zb3J0LXNlbGVjdFwiXG4gICAgICAgICAgICAgIChpb25DaGFuZ2UpPVwiaGFuZGxlU29ydENoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgaW50ZXJmYWNlPVwicG9wb3ZlclwiXG4gICAgICAgICAgICAgIFt2YWx1ZV09XCJzb3J0VmFsdWVcIlxuICAgICAgICAgICAgICBsYWJlbC1wbGFjZW1lbnQ9XCJmbG9hdGluZ1wiXG4gICAgICAgICAgICAgIGZpbGw9XCJvdXRsaW5lXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgIEBmb3Ioc29ydCBvZiBzb3J0Qnk7IHRyYWNrIHNvcnQpIHtcbiAgICAgICAgICAgICAgYWFcbiAgICAgICAgICAgICAgPGlvbi1zZWxlY3Qtb3B0aW9uIFt2YWx1ZV09XCJzb3J0XCI+e3sgc29ydCB8IHRyYW5zbGF0ZSB9fTwvaW9uLXNlbGVjdC1vcHRpb24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9pb24tc2VsZWN0PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRjZi13aWR0aC1hdXRvXCI+XG4gICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImhhbmRsZVNvcnREaXJlY3Rpb25DaGFuZ2UoKVwiIGZpbGw9XCJjbGVhclwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJpY29uLW9ubHlcIiBbbmFtZV09XCJzb3J0RGlyZWN0aW9uID09PSAnZGVzYycgPyAnYXJyb3ctZG93bi1vdXRsaW5lJyA6ICdhcnJvdy11cC1vdXRsaW5lJ1wiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICB9XG48L2Rpdj5cblxuXG4iXX0=