@pepperi-addons/ngx-lib 0.4.1-beta.54 → 0.4.1-beta.56

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 (739) hide show
  1. package/address/address.component.d.ts +30 -30
  2. package/address/address.module.d.ts +15 -15
  3. package/address/index.d.ts +5 -5
  4. package/address/public-api.d.ts +2 -2
  5. package/attachment/attachment.component.d.ts +85 -85
  6. package/attachment/attachment.module.d.ts +14 -14
  7. package/attachment/index.d.ts +5 -5
  8. package/attachment/public-api.d.ts +2 -2
  9. package/bread-crumbs/bread-crumbs.component.d.ts +27 -27
  10. package/bread-crumbs/bread-crumbs.model.d.ts +11 -11
  11. package/bread-crumbs/bread-crumbs.module.d.ts +15 -15
  12. package/bread-crumbs/index.d.ts +5 -5
  13. package/bread-crumbs/public-api.d.ts +3 -3
  14. package/button/button.component.d.ts +102 -102
  15. package/button/button.model.d.ts +14 -14
  16. package/button/button.module.d.ts +13 -13
  17. package/button/index.d.ts +5 -5
  18. package/button/public-api.d.ts +3 -3
  19. package/carousel/carousel-item.directive.d.ts +12 -12
  20. package/carousel/carousel.component.d.ts +148 -148
  21. package/carousel/carousel.module.d.ts +8 -8
  22. package/carousel/index.d.ts +5 -5
  23. package/carousel/public-api.d.ts +3 -3
  24. package/checkbox/checkbox.component.d.ts +50 -50
  25. package/checkbox/checkbox.module.d.ts +19 -19
  26. package/checkbox/index.d.ts +5 -5
  27. package/checkbox/public-api.d.ts +2 -2
  28. package/chips/chips.component.d.ts +93 -93
  29. package/chips/chips.model.d.ts +14 -14
  30. package/chips/chips.module.d.ts +20 -20
  31. package/chips/chips.service.d.ts +15 -15
  32. package/chips/index.d.ts +5 -5
  33. package/chips/public-api.d.ts +3 -3
  34. package/color/color-picker.component.d.ts +57 -57
  35. package/color/color.component.d.ts +30 -30
  36. package/color/color.model.d.ts +1 -1
  37. package/color/color.module.d.ts +26 -26
  38. package/color/index.d.ts +5 -5
  39. package/color/public-api.d.ts +3 -3
  40. package/core/clipboard/clipboard.directive.d.ts +5 -5
  41. package/core/clipboard/clipboard.service.d.ts +5 -5
  42. package/core/clipboard/index.d.ts +1 -1
  43. package/core/clipboard/public-api.d.ts +2 -2
  44. package/core/common/directives/auto-width.directive.d.ts +19 -19
  45. package/core/common/directives/button-blur.directive.d.ts +9 -9
  46. package/core/common/directives/button-loader.directive.d.ts +26 -26
  47. package/core/common/directives/data-qa.directive.d.ts +11 -11
  48. package/core/common/directives/div-loader.directive.d.ts +21 -21
  49. package/core/common/directives/index.d.ts +1 -1
  50. package/core/common/directives/menu-blur.directive.d.ts +10 -10
  51. package/core/common/directives/prevent-multi-click.directive.d.ts +7 -7
  52. package/core/common/directives/print.directive.d.ts +75 -75
  53. package/core/common/directives/public-api.d.ts +8 -8
  54. package/core/common/index.d.ts +1 -1
  55. package/core/common/model/index.d.ts +1 -1
  56. package/core/common/model/papi.model.d.ts +2 -2
  57. package/core/common/model/public-api.d.ts +3 -3
  58. package/core/common/model/utilities.model.d.ts +5 -5
  59. package/core/common/model/wapi.model.d.ts +202 -202
  60. package/core/common/pipes/common-pipes.d.ts +57 -57
  61. package/core/common/pipes/date-ago.pipe.d.ts +11 -11
  62. package/core/common/pipes/index.d.ts +1 -1
  63. package/core/common/pipes/public-api.d.ts +2 -2
  64. package/core/common/public-api.d.ts +4 -4
  65. package/core/common/services/addon.service.d.ts +48 -48
  66. package/core/common/services/color.service.d.ts +51 -51
  67. package/core/common/services/cookie.service.d.ts +53 -53
  68. package/core/common/services/data-convertor.service.d.ts +45 -45
  69. package/core/common/services/file.service.d.ts +27 -27
  70. package/core/common/services/index.d.ts +1 -1
  71. package/core/common/services/jwt-helper.service.d.ts +13 -13
  72. package/core/common/services/public-api.d.ts +11 -11
  73. package/core/common/services/session.service.d.ts +18 -18
  74. package/core/common/services/translate.service.d.ts +12 -12
  75. package/core/common/services/utilities.service.d.ts +39 -39
  76. package/core/common/services/validator.service.d.ts +31 -31
  77. package/core/common/services/window-scrolling.service.d.ts +10 -10
  78. package/core/customization/customization.model.d.ts +277 -277
  79. package/core/customization/customization.service.d.ts +159 -159
  80. package/core/customization/index.d.ts +1 -1
  81. package/core/customization/public-api.d.ts +2 -2
  82. package/core/http/index.d.ts +1 -1
  83. package/core/http/interceptors/error.interceptor.d.ts +8 -8
  84. package/core/http/interceptors/index.d.ts +11 -11
  85. package/core/http/interceptors/loader.interceptor.d.ts +11 -11
  86. package/core/http/interceptors/profiler.interceptor.d.ts +8 -8
  87. package/core/http/public-api.d.ts +2 -2
  88. package/core/http/services/http.service.d.ts +28 -28
  89. package/core/http/services/loader.service.d.ts +13 -13
  90. package/core/index.d.ts +1 -1
  91. package/core/layout/index.d.ts +1 -1
  92. package/core/layout/layout.service.d.ts +36 -36
  93. package/core/layout/public-api.d.ts +2 -2
  94. package/core/layout/rtl.directive.d.ts +21 -21
  95. package/core/portal/attach.directive.d.ts +13 -13
  96. package/core/portal/index.d.ts +1 -1
  97. package/core/portal/portal.service.d.ts +12 -12
  98. package/core/portal/public-api.d.ts +3 -3
  99. package/core/portal/target.directive.d.ts +12 -12
  100. package/core/public-api.d.ts +7 -7
  101. package/core/scroll-to/index.d.ts +1 -1
  102. package/core/scroll-to/public-api.d.ts +1 -1
  103. package/core/scroll-to/scroll-to.service.d.ts +11 -11
  104. package/date/date.component.d.ts +69 -69
  105. package/date/date.model.d.ts +31 -31
  106. package/date/date.module.d.ts +23 -23
  107. package/date/index.d.ts +5 -5
  108. package/date/public-api.d.ts +2 -2
  109. package/dialog/default-dialog.component.d.ts +12 -12
  110. package/dialog/dialog.component.d.ts +13 -13
  111. package/dialog/dialog.model.d.ts +31 -31
  112. package/dialog/dialog.module.d.ts +18 -18
  113. package/dialog/dialog.service.d.ts +27 -27
  114. package/dialog/index.d.ts +5 -5
  115. package/dialog/public-api.d.ts +4 -4
  116. package/draggable-items/draggable-item/draggable-item.component.d.ts +11 -11
  117. package/draggable-items/draggable-items.component.d.ts +36 -36
  118. package/draggable-items/draggable-items.model.d.ts +11 -11
  119. package/draggable-items/draggable-items.module.d.ts +18 -18
  120. package/draggable-items/index.d.ts +5 -5
  121. package/draggable-items/public-api.d.ts +4 -4
  122. package/esm2020/address/address.component.mjs +108 -108
  123. package/esm2020/address/address.module.mjs +53 -53
  124. package/esm2020/address/pepperi-addons-ngx-lib-address.mjs +4 -4
  125. package/esm2020/address/public-api.mjs +5 -5
  126. package/esm2020/attachment/attachment.component.mjs +219 -219
  127. package/esm2020/attachment/attachment.module.mjs +49 -49
  128. package/esm2020/attachment/pepperi-addons-ngx-lib-attachment.mjs +4 -4
  129. package/esm2020/attachment/public-api.mjs +5 -5
  130. package/esm2020/bread-crumbs/bread-crumbs.component.mjs +84 -84
  131. package/esm2020/bread-crumbs/bread-crumbs.model.mjs +6 -6
  132. package/esm2020/bread-crumbs/bread-crumbs.module.mjs +49 -49
  133. package/esm2020/bread-crumbs/pepperi-addons-ngx-lib-bread-crumbs.mjs +4 -4
  134. package/esm2020/bread-crumbs/public-api.mjs +6 -6
  135. package/esm2020/button/button.component.mjs +137 -137
  136. package/esm2020/button/button.model.mjs +5 -5
  137. package/esm2020/button/button.module.mjs +45 -45
  138. package/esm2020/button/pepperi-addons-ngx-lib-button.mjs +4 -4
  139. package/esm2020/button/public-api.mjs +6 -6
  140. package/esm2020/carousel/carousel-item.directive.mjs +32 -32
  141. package/esm2020/carousel/carousel.component.mjs +736 -736
  142. package/esm2020/carousel/carousel.module.mjs +16 -16
  143. package/esm2020/carousel/pepperi-addons-ngx-lib-carousel.mjs +4 -4
  144. package/esm2020/carousel/public-api.mjs +7 -7
  145. package/esm2020/checkbox/checkbox.component.mjs +167 -167
  146. package/esm2020/checkbox/checkbox.module.mjs +62 -62
  147. package/esm2020/checkbox/pepperi-addons-ngx-lib-checkbox.mjs +4 -4
  148. package/esm2020/checkbox/public-api.mjs +5 -5
  149. package/esm2020/chips/chips.component.mjs +157 -157
  150. package/esm2020/chips/chips.model.mjs +1 -1
  151. package/esm2020/chips/chips.module.mjs +80 -80
  152. package/esm2020/chips/chips.service.mjs +44 -44
  153. package/esm2020/chips/pepperi-addons-ngx-lib-chips.mjs +4 -4
  154. package/esm2020/chips/public-api.mjs +6 -6
  155. package/esm2020/color/color-picker.component.mjs +197 -197
  156. package/esm2020/color/color.component.mjs +89 -89
  157. package/esm2020/color/color.model.mjs +1 -1
  158. package/esm2020/color/color.module.mjs +92 -92
  159. package/esm2020/color/pepperi-addons-ngx-lib-color.mjs +4 -4
  160. package/esm2020/color/public-api.mjs +6 -6
  161. package/esm2020/core/clipboard/clipboard.directive.mjs +23 -23
  162. package/esm2020/core/clipboard/clipboard.service.mjs +13 -13
  163. package/esm2020/core/clipboard/index.mjs +4 -4
  164. package/esm2020/core/clipboard/public-api.mjs +5 -5
  165. package/esm2020/core/common/directives/auto-width.directive.mjs +76 -76
  166. package/esm2020/core/common/directives/button-blur.directive.mjs +23 -23
  167. package/esm2020/core/common/directives/button-loader.directive.mjs +111 -111
  168. package/esm2020/core/common/directives/data-qa.directive.mjs +22 -22
  169. package/esm2020/core/common/directives/div-loader.directive.mjs +60 -60
  170. package/esm2020/core/common/directives/index.mjs +4 -4
  171. package/esm2020/core/common/directives/menu-blur.directive.mjs +31 -31
  172. package/esm2020/core/common/directives/prevent-multi-click.directive.mjs +26 -26
  173. package/esm2020/core/common/directives/print.directive.mjs +144 -144
  174. package/esm2020/core/common/directives/public-api.mjs +12 -12
  175. package/esm2020/core/common/index.mjs +4 -4
  176. package/esm2020/core/common/model/index.mjs +4 -4
  177. package/esm2020/core/common/model/papi.model.mjs +2 -2
  178. package/esm2020/core/common/model/public-api.mjs +6 -6
  179. package/esm2020/core/common/model/utilities.model.mjs +56 -56
  180. package/esm2020/core/common/model/wapi.model.mjs +156 -156
  181. package/esm2020/core/common/pipes/common-pipes.mjs +166 -166
  182. package/esm2020/core/common/pipes/date-ago.pipe.mjs +45 -45
  183. package/esm2020/core/common/pipes/index.mjs +4 -4
  184. package/esm2020/core/common/pipes/public-api.mjs +5 -5
  185. package/esm2020/core/common/public-api.mjs +7 -7
  186. package/esm2020/core/common/services/addon.service.mjs +188 -188
  187. package/esm2020/core/common/services/color.service.mjs +358 -358
  188. package/esm2020/core/common/services/cookie.service.mjs +152 -152
  189. package/esm2020/core/common/services/data-convertor.service.mjs +121 -121
  190. package/esm2020/core/common/services/file.service.mjs +212 -212
  191. package/esm2020/core/common/services/index.mjs +4 -4
  192. package/esm2020/core/common/services/jwt-helper.service.mjs +105 -105
  193. package/esm2020/core/common/services/public-api.mjs +14 -14
  194. package/esm2020/core/common/services/session.service.mjs +70 -70
  195. package/esm2020/core/common/services/translate.service.mjs +45 -45
  196. package/esm2020/core/common/services/utilities.service.mjs +299 -299
  197. package/esm2020/core/common/services/validator.service.mjs +271 -271
  198. package/esm2020/core/common/services/window-scrolling.service.mjs +31 -31
  199. package/esm2020/core/customization/customization.model.mjs +301 -301
  200. package/esm2020/core/customization/customization.service.mjs +770 -770
  201. package/esm2020/core/customization/index.mjs +4 -4
  202. package/esm2020/core/customization/public-api.mjs +5 -5
  203. package/esm2020/core/http/index.mjs +4 -4
  204. package/esm2020/core/http/interceptors/error.interceptor.mjs +26 -26
  205. package/esm2020/core/http/interceptors/index.mjs +23 -23
  206. package/esm2020/core/http/interceptors/loader.interceptor.mjs +31 -31
  207. package/esm2020/core/http/interceptors/profiler.interceptor.mjs +31 -31
  208. package/esm2020/core/http/public-api.mjs +5 -5
  209. package/esm2020/core/http/services/http.service.mjs +154 -154
  210. package/esm2020/core/http/services/loader.service.mjs +49 -49
  211. package/esm2020/core/index.mjs +4 -4
  212. package/esm2020/core/layout/index.mjs +4 -4
  213. package/esm2020/core/layout/layout.service.mjs +167 -167
  214. package/esm2020/core/layout/public-api.mjs +5 -5
  215. package/esm2020/core/layout/rtl.directive.mjs +43 -43
  216. package/esm2020/core/portal/attach.directive.mjs +26 -26
  217. package/esm2020/core/portal/index.mjs +4 -4
  218. package/esm2020/core/portal/portal.service.mjs +35 -35
  219. package/esm2020/core/portal/public-api.mjs +6 -6
  220. package/esm2020/core/portal/target.directive.mjs +23 -23
  221. package/esm2020/core/public-api.mjs +10 -10
  222. package/esm2020/core/scroll-to/index.mjs +4 -4
  223. package/esm2020/core/scroll-to/public-api.mjs +5 -5
  224. package/esm2020/core/scroll-to/scroll-to.service.mjs +83 -83
  225. package/esm2020/date/date.component.mjs +306 -306
  226. package/esm2020/date/date.model.mjs +53 -53
  227. package/esm2020/date/date.module.mjs +87 -87
  228. package/esm2020/date/pepperi-addons-ngx-lib-date.mjs +4 -4
  229. package/esm2020/date/public-api.mjs +5 -5
  230. package/esm2020/dialog/default-dialog.component.mjs +36 -36
  231. package/esm2020/dialog/dialog.component.mjs +35 -35
  232. package/esm2020/dialog/dialog.model.mjs +32 -32
  233. package/esm2020/dialog/dialog.module.mjs +58 -58
  234. package/esm2020/dialog/dialog.service.mjs +81 -81
  235. package/esm2020/dialog/pepperi-addons-ngx-lib-dialog.mjs +4 -4
  236. package/esm2020/dialog/public-api.mjs +7 -7
  237. package/esm2020/draggable-items/draggable-item/draggable-item.component.mjs +26 -26
  238. package/esm2020/draggable-items/draggable-items.component.mjs +101 -101
  239. package/esm2020/draggable-items/draggable-items.model.mjs +1 -1
  240. package/esm2020/draggable-items/draggable-items.module.mjs +59 -59
  241. package/esm2020/draggable-items/pepperi-addons-ngx-lib-draggable-items.mjs +4 -4
  242. package/esm2020/draggable-items/public-api.mjs +7 -7
  243. package/esm2020/field-title/field-title.component.mjs +44 -44
  244. package/esm2020/field-title/field-title.module.mjs +46 -46
  245. package/esm2020/field-title/pepperi-addons-ngx-lib-field-title.mjs +4 -4
  246. package/esm2020/field-title/public-api.mjs +5 -5
  247. package/esm2020/files-uploader/files-uploader.component.mjs +240 -240
  248. package/esm2020/files-uploader/files-uploader.module.mjs +78 -78
  249. package/esm2020/files-uploader/pepperi-addons-ngx-lib-files-uploader.mjs +4 -4
  250. package/esm2020/files-uploader/public-api.mjs +5 -5
  251. package/esm2020/form/field-generator.component.mjs +152 -152
  252. package/esm2020/form/form.component.mjs +1226 -1226
  253. package/esm2020/form/form.model.mjs +1 -1
  254. package/esm2020/form/form.module.mjs +178 -178
  255. package/esm2020/form/indicators.component.mjs +22 -22
  256. package/esm2020/form/internal-button.component.mjs +183 -183
  257. package/esm2020/form/internal-carusel.component.mjs +116 -116
  258. package/esm2020/form/internal-carusel.service.mjs +31 -31
  259. package/esm2020/form/internal-field-generator.component.mjs +146 -146
  260. package/esm2020/form/internal-form.component.mjs +1215 -1215
  261. package/esm2020/form/internal-list.component.mjs +512 -512
  262. package/esm2020/form/internal-menu.component.mjs +65 -65
  263. package/esm2020/form/internal-page.component.mjs +361 -361
  264. package/esm2020/form/internal-page.service.mjs +119 -119
  265. package/esm2020/form/pepperi-addons-ngx-lib-form.mjs +4 -4
  266. package/esm2020/form/public-api.mjs +6 -6
  267. package/esm2020/group-buttons/group-buttons.component.mjs +70 -70
  268. package/esm2020/group-buttons/group-buttons.module.mjs +58 -58
  269. package/esm2020/group-buttons/pepperi-addons-ngx-lib-group-buttons.mjs +4 -4
  270. package/esm2020/group-buttons/public-api.mjs +5 -5
  271. package/esm2020/icon/icon-generated-all.model.mjs +113 -113
  272. package/esm2020/icon/icon-generated.model.mjs +441 -441
  273. package/esm2020/icon/icon-registry.service.mjs +24 -24
  274. package/esm2020/icon/icon.component.mjs +90 -90
  275. package/esm2020/icon/icon.module.mjs +19 -19
  276. package/esm2020/icon/icon.service.mjs +30 -30
  277. package/esm2020/icon/pepperi-addons-ngx-lib-icon.mjs +4 -4
  278. package/esm2020/icon/public-api.mjs +10 -10
  279. package/esm2020/image/image.component.mjs +246 -246
  280. package/esm2020/image/image.module.mjs +73 -73
  281. package/esm2020/image/image.service.mjs +51 -51
  282. package/esm2020/image/pepperi-addons-ngx-lib-image.mjs +4 -4
  283. package/esm2020/image/public-api.mjs +6 -6
  284. package/esm2020/images-filmstrip/images-filmstrip.component.mjs +336 -336
  285. package/esm2020/images-filmstrip/images-filmstrip.module.mjs +82 -82
  286. package/esm2020/images-filmstrip/pepperi-addons-ngx-lib-images-filmstrip.mjs +4 -4
  287. package/esm2020/images-filmstrip/public-api.mjs +5 -5
  288. package/esm2020/link/link.component.mjs +325 -325
  289. package/esm2020/link/link.module.mjs +79 -79
  290. package/esm2020/link/link.pipes.mjs +17 -17
  291. package/esm2020/link/pepperi-addons-ngx-lib-link.mjs +4 -4
  292. package/esm2020/link/public-api.mjs +5 -5
  293. package/esm2020/list/list-actions.component.mjs +43 -43
  294. package/esm2020/list/list-carousel.component.mjs +106 -106
  295. package/esm2020/list/list-chooser.component.mjs +63 -63
  296. package/esm2020/list/list-pager.component.mjs +119 -119
  297. package/esm2020/list/list-sorting.component.mjs +60 -60
  298. package/esm2020/list/list-total.component.mjs +29 -29
  299. package/esm2020/list/list-views.component.mjs +84 -84
  300. package/esm2020/list/list.component.mjs +1162 -1162
  301. package/esm2020/list/list.model.mjs +3 -3
  302. package/esm2020/list/list.module.mjs +143 -143
  303. package/esm2020/list/list.pipes.mjs +46 -46
  304. package/esm2020/list/pepperi-addons-ngx-lib-list.mjs +4 -4
  305. package/esm2020/list/public-api.mjs +14 -14
  306. package/esm2020/list/virtual-scroller.mjs +1061 -1061
  307. package/esm2020/menu/menu-item.component.mjs +114 -114
  308. package/esm2020/menu/menu.component.mjs +212 -212
  309. package/esm2020/menu/menu.model.mjs +18 -18
  310. package/esm2020/menu/menu.module.mjs +58 -58
  311. package/esm2020/menu/pepperi-addons-ngx-lib-menu.mjs +4 -4
  312. package/esm2020/menu/public-api.mjs +6 -6
  313. package/esm2020/ngx-lib.module.mjs +161 -161
  314. package/esm2020/page-layout/page-layout.component.mjs +34 -34
  315. package/esm2020/page-layout/page-layout.module.mjs +33 -33
  316. package/esm2020/page-layout/pepperi-addons-ngx-lib-page-layout.mjs +4 -4
  317. package/esm2020/page-layout/public-api.mjs +5 -5
  318. package/esm2020/pepperi-addons-ngx-lib.mjs +4 -4
  319. package/esm2020/profile-data-views-list/pepperi-addons-ngx-lib-profile-data-views-list.mjs +4 -4
  320. package/esm2020/profile-data-views-list/profile-data-view/profile-data-view.component.mjs +44 -44
  321. package/esm2020/profile-data-views-list/profile-data-views-card/profile-data-views-card.component.mjs +64 -64
  322. package/esm2020/profile-data-views-list/profile-data-views-list.component.mjs +94 -94
  323. package/esm2020/profile-data-views-list/profile-data-views-list.model.mjs +1 -1
  324. package/esm2020/profile-data-views-list/profile-data-views-list.module.mjs +87 -87
  325. package/esm2020/profile-data-views-list/public-api.mjs +8 -8
  326. package/esm2020/public-api.mjs +5 -5
  327. package/esm2020/quantity-selector/pepperi-addons-ngx-lib-quantity-selector.mjs +4 -4
  328. package/esm2020/quantity-selector/public-api.mjs +5 -5
  329. package/esm2020/quantity-selector/quantity-selector-validation.directive.mjs +48 -48
  330. package/esm2020/quantity-selector/quantity-selector.component.mjs +577 -577
  331. package/esm2020/quantity-selector/quantity-selector.module.mjs +81 -81
  332. package/esm2020/quantity-selector/quantity-selector.pipes.mjs +22 -22
  333. package/esm2020/query-builder/common/model/field.mjs +1 -1
  334. package/esm2020/query-builder/common/model/filter.mjs +1 -1
  335. package/esm2020/query-builder/common/model/legacy.mjs +1 -1
  336. package/esm2020/query-builder/common/model/operator-unit.mjs +41 -41
  337. package/esm2020/query-builder/common/model/operator.mjs +265 -265
  338. package/esm2020/query-builder/common/model/structure.mjs +1 -1
  339. package/esm2020/query-builder/common/model/type-map.mjs +26 -26
  340. package/esm2020/query-builder/common/model/type.mjs +5 -5
  341. package/esm2020/query-builder/common/services/output-query.service.mjs +113 -113
  342. package/esm2020/query-builder/common/services/query-structure.service.mjs +225 -225
  343. package/esm2020/query-builder/common/services/type-convertor.service.mjs +41 -41
  344. package/esm2020/query-builder/pepperi-addons-ngx-lib-query-builder.mjs +4 -4
  345. package/esm2020/query-builder/public-api.mjs +8 -8
  346. package/esm2020/query-builder/query-builder-item/query-builder-item.component.mjs +124 -124
  347. package/esm2020/query-builder/query-builder-section/query-builder-section.component.mjs +70 -70
  348. package/esm2020/query-builder/query-builder.component.mjs +109 -109
  349. package/esm2020/query-builder/query-builder.module.mjs +58 -58
  350. package/esm2020/query-builder/query-builder.service.mjs +101 -101
  351. package/esm2020/remote-loader/addon-block-loader.component.mjs +101 -101
  352. package/esm2020/remote-loader/addon-block-loader.service.mjs +61 -61
  353. package/esm2020/remote-loader/pepperi-addons-ngx-lib-remote-loader.mjs +4 -4
  354. package/esm2020/remote-loader/public-api.mjs +10 -10
  355. package/esm2020/remote-loader/remote-loader-element.component.mjs +104 -104
  356. package/esm2020/remote-loader/remote-loader.component.mjs +108 -108
  357. package/esm2020/remote-loader/remote-loader.model.mjs +1 -1
  358. package/esm2020/remote-loader/remote-loader.module.mjs +68 -68
  359. package/esm2020/remote-loader/remote-loader.service.mjs +80 -80
  360. package/esm2020/rich-html-textarea/pepperi-addons-ngx-lib-rich-html-textarea.mjs +4 -4
  361. package/esm2020/rich-html-textarea/public-api.mjs +5 -5
  362. package/esm2020/rich-html-textarea/rich-html-textarea.component.mjs +247 -247
  363. package/esm2020/rich-html-textarea/rich-html-textarea.module.mjs +94 -94
  364. package/esm2020/search/pepperi-addons-ngx-lib-search.mjs +4 -4
  365. package/esm2020/search/public-api.mjs +6 -6
  366. package/esm2020/search/search.component.mjs +316 -316
  367. package/esm2020/search/search.model.mjs +1 -1
  368. package/esm2020/search/search.module.mjs +69 -69
  369. package/esm2020/select/pepperi-addons-ngx-lib-select.mjs +4 -4
  370. package/esm2020/select/public-api.mjs +5 -5
  371. package/esm2020/select/select.component.mjs +266 -266
  372. package/esm2020/select/select.module.mjs +69 -69
  373. package/esm2020/select-panel/pepperi-addons-ngx-lib-select-panel.mjs +4 -4
  374. package/esm2020/select-panel/public-api.mjs +6 -6
  375. package/esm2020/select-panel/select-panel.component.mjs +159 -158
  376. package/esm2020/select-panel/select-panel.model.mjs +1 -1
  377. package/esm2020/select-panel/select-panel.module.mjs +69 -69
  378. package/esm2020/separator/pepperi-addons-ngx-lib-separator.mjs +4 -4
  379. package/esm2020/separator/public-api.mjs +5 -5
  380. package/esm2020/separator/separator.component.mjs +62 -62
  381. package/esm2020/separator/separator.module.mjs +17 -17
  382. package/esm2020/side-bar/pepperi-addons-ngx-lib-side-bar.mjs +4 -4
  383. package/esm2020/side-bar/public-api.mjs +6 -6
  384. package/esm2020/side-bar/side-bar.component.mjs +121 -121
  385. package/esm2020/side-bar/side-bar.model.mjs +1 -1
  386. package/esm2020/side-bar/side-bar.module.mjs +54 -54
  387. package/esm2020/signature/pepperi-addons-ngx-lib-signature.mjs +4 -4
  388. package/esm2020/signature/public-api.mjs +5 -5
  389. package/esm2020/signature/signature.component.mjs +253 -253
  390. package/esm2020/signature/signature.module.mjs +89 -89
  391. package/esm2020/size-detector/pepperi-addons-ngx-lib-size-detector.mjs +4 -4
  392. package/esm2020/size-detector/public-api.mjs +5 -5
  393. package/esm2020/size-detector/size-detector.component.mjs +91 -91
  394. package/esm2020/size-detector/size-detector.module.mjs +34 -34
  395. package/esm2020/slider/pepperi-addons-ngx-lib-slider.mjs +4 -4
  396. package/esm2020/slider/public-api.mjs +5 -5
  397. package/esm2020/slider/slider.component.mjs +100 -100
  398. package/esm2020/slider/slider.module.mjs +41 -41
  399. package/esm2020/smart-filters/boolean-filter/boolean-filter.component.mjs +74 -74
  400. package/esm2020/smart-filters/common/filter-actions.component.mjs +28 -28
  401. package/esm2020/smart-filters/common/model/base-filter-component.mjs +295 -295
  402. package/esm2020/smart-filters/common/model/creator.mjs +75 -75
  403. package/esm2020/smart-filters/common/model/field.mjs +116 -116
  404. package/esm2020/smart-filters/common/model/filter.mjs +1 -1
  405. package/esm2020/smart-filters/common/model/operator.mjs +270 -270
  406. package/esm2020/smart-filters/common/model/type.mjs +1 -1
  407. package/esm2020/smart-filters/date-filter/date-filter.component.mjs +181 -181
  408. package/esm2020/smart-filters/multi-select-filter/multi-select-filter.component.mjs +199 -199
  409. package/esm2020/smart-filters/number-filter/number-filter.component.mjs +135 -135
  410. package/esm2020/smart-filters/pepperi-addons-ngx-lib-smart-filters.mjs +4 -4
  411. package/esm2020/smart-filters/public-api.mjs +18 -18
  412. package/esm2020/smart-filters/smart-filters.component.mjs +140 -140
  413. package/esm2020/smart-filters/smart-filters.module.mjs +157 -157
  414. package/esm2020/smart-filters/text-filter/text-filter.component.mjs +92 -92
  415. package/esm2020/snack-bar/default-snack-bar.component.mjs +28 -28
  416. package/esm2020/snack-bar/pepperi-addons-ngx-lib-snack-bar.mjs +4 -4
  417. package/esm2020/snack-bar/public-api.mjs +7 -7
  418. package/esm2020/snack-bar/snack-bar.component.mjs +25 -25
  419. package/esm2020/snack-bar/snack-bar.model.mjs +6 -6
  420. package/esm2020/snack-bar/snack-bar.module.mjs +62 -62
  421. package/esm2020/snack-bar/snack-bar.service.mjs +59 -59
  422. package/esm2020/textarea/pepperi-addons-ngx-lib-textarea.mjs +4 -4
  423. package/esm2020/textarea/public-api.mjs +5 -5
  424. package/esm2020/textarea/textarea.component.mjs +188 -182
  425. package/esm2020/textarea/textarea.module.mjs +81 -81
  426. package/esm2020/textbox/pepperi-addons-ngx-lib-textbox.mjs +4 -4
  427. package/esm2020/textbox/public-api.mjs +5 -5
  428. package/esm2020/textbox/textbox-validation.directive.mjs +92 -92
  429. package/esm2020/textbox/textbox.component.mjs +552 -546
  430. package/esm2020/textbox/textbox.module.mjs +71 -71
  431. package/esm2020/textbox-icon/pepperi-addons-ngx-lib-textbox-icon.mjs +4 -4
  432. package/esm2020/textbox-icon/public-api.mjs +5 -5
  433. package/esm2020/textbox-icon/textbox-icon.component.mjs +47 -47
  434. package/esm2020/textbox-icon/textbox-icon.module.mjs +63 -63
  435. package/esm2020/top-bar/pepperi-addons-ngx-lib-top-bar.mjs +4 -4
  436. package/esm2020/top-bar/public-api.mjs +6 -6
  437. package/esm2020/top-bar/top-bar.component.mjs +111 -111
  438. package/esm2020/top-bar/top-bar.model.mjs +1 -1
  439. package/esm2020/top-bar/top-bar.module.mjs +61 -61
  440. package/fesm2015/pepperi-addons-ngx-lib-address.mjs +143 -143
  441. package/fesm2015/pepperi-addons-ngx-lib-address.mjs.map +1 -1
  442. package/fesm2015/pepperi-addons-ngx-lib-attachment.mjs +253 -253
  443. package/fesm2015/pepperi-addons-ngx-lib-bread-crumbs.mjs +122 -122
  444. package/fesm2015/pepperi-addons-ngx-lib-button.mjs +171 -171
  445. package/fesm2015/pepperi-addons-ngx-lib-carousel.mjs +780 -780
  446. package/fesm2015/pepperi-addons-ngx-lib-checkbox.mjs +206 -206
  447. package/fesm2015/pepperi-addons-ngx-lib-chips.mjs +255 -255
  448. package/fesm2015/pepperi-addons-ngx-lib-color.mjs +336 -336
  449. package/fesm2015/pepperi-addons-ngx-lib-color.mjs.map +1 -1
  450. package/fesm2015/pepperi-addons-ngx-lib-date.mjs +409 -409
  451. package/fesm2015/pepperi-addons-ngx-lib-dialog.mjs +207 -207
  452. package/fesm2015/pepperi-addons-ngx-lib-draggable-items.mjs +163 -163
  453. package/fesm2015/pepperi-addons-ngx-lib-field-title.mjs +76 -76
  454. package/fesm2015/pepperi-addons-ngx-lib-files-uploader.mjs +291 -291
  455. package/fesm2015/pepperi-addons-ngx-lib-form.mjs +4121 -4121
  456. package/fesm2015/pepperi-addons-ngx-lib-form.mjs.map +1 -1
  457. package/fesm2015/pepperi-addons-ngx-lib-group-buttons.mjs +109 -109
  458. package/fesm2015/pepperi-addons-ngx-lib-icon.mjs +702 -702
  459. package/fesm2015/pepperi-addons-ngx-lib-image.mjs +340 -340
  460. package/fesm2015/pepperi-addons-ngx-lib-images-filmstrip.mjs +390 -390
  461. package/fesm2015/pepperi-addons-ngx-lib-link.mjs +388 -388
  462. package/fesm2015/pepperi-addons-ngx-lib-list.mjs +2826 -2826
  463. package/fesm2015/pepperi-addons-ngx-lib-list.mjs.map +1 -1
  464. package/fesm2015/pepperi-addons-ngx-lib-menu.mjs +368 -368
  465. package/fesm2015/pepperi-addons-ngx-lib-page-layout.mjs +59 -59
  466. package/fesm2015/pepperi-addons-ngx-lib-profile-data-views-list.mjs +254 -254
  467. package/fesm2015/pepperi-addons-ngx-lib-quantity-selector.mjs +689 -689
  468. package/fesm2015/pepperi-addons-ngx-lib-query-builder.mjs +1119 -1119
  469. package/fesm2015/pepperi-addons-ngx-lib-remote-loader.mjs +504 -504
  470. package/fesm2015/pepperi-addons-ngx-lib-rich-html-textarea.mjs +303 -303
  471. package/fesm2015/pepperi-addons-ngx-lib-search.mjs +356 -356
  472. package/fesm2015/pepperi-addons-ngx-lib-select-panel.mjs +207 -206
  473. package/fesm2015/pepperi-addons-ngx-lib-select-panel.mjs.map +1 -1
  474. package/fesm2015/pepperi-addons-ngx-lib-select.mjs +308 -308
  475. package/fesm2015/pepperi-addons-ngx-lib-separator.mjs +73 -73
  476. package/fesm2015/pepperi-addons-ngx-lib-side-bar.mjs +158 -158
  477. package/fesm2015/pepperi-addons-ngx-lib-signature.mjs +311 -311
  478. package/fesm2015/pepperi-addons-ngx-lib-size-detector.mjs +114 -114
  479. package/fesm2015/pepperi-addons-ngx-lib-slider.mjs +130 -130
  480. package/fesm2015/pepperi-addons-ngx-lib-smart-filters.mjs +1634 -1634
  481. package/fesm2015/pepperi-addons-ngx-lib-smart-filters.mjs.map +1 -1
  482. package/fesm2015/pepperi-addons-ngx-lib-snack-bar.mjs +152 -152
  483. package/fesm2015/pepperi-addons-ngx-lib-textarea.mjs +238 -232
  484. package/fesm2015/pepperi-addons-ngx-lib-textarea.mjs.map +1 -1
  485. package/fesm2015/pepperi-addons-ngx-lib-textbox-icon.mjs +95 -95
  486. package/fesm2015/pepperi-addons-ngx-lib-textbox.mjs +679 -673
  487. package/fesm2015/pepperi-addons-ngx-lib-textbox.mjs.map +1 -1
  488. package/fesm2015/pepperi-addons-ngx-lib-top-bar.mjs +155 -155
  489. package/fesm2015/pepperi-addons-ngx-lib.mjs +4615 -4615
  490. package/fesm2015/pepperi-addons-ngx-lib.mjs.map +1 -1
  491. package/fesm2020/pepperi-addons-ngx-lib-address.mjs +143 -143
  492. package/fesm2020/pepperi-addons-ngx-lib-address.mjs.map +1 -1
  493. package/fesm2020/pepperi-addons-ngx-lib-attachment.mjs +253 -253
  494. package/fesm2020/pepperi-addons-ngx-lib-bread-crumbs.mjs +122 -122
  495. package/fesm2020/pepperi-addons-ngx-lib-button.mjs +171 -171
  496. package/fesm2020/pepperi-addons-ngx-lib-carousel.mjs +776 -776
  497. package/fesm2020/pepperi-addons-ngx-lib-checkbox.mjs +206 -206
  498. package/fesm2020/pepperi-addons-ngx-lib-chips.mjs +254 -254
  499. package/fesm2020/pepperi-addons-ngx-lib-color.mjs +333 -333
  500. package/fesm2020/pepperi-addons-ngx-lib-color.mjs.map +1 -1
  501. package/fesm2020/pepperi-addons-ngx-lib-date.mjs +405 -405
  502. package/fesm2020/pepperi-addons-ngx-lib-dialog.mjs +203 -203
  503. package/fesm2020/pepperi-addons-ngx-lib-draggable-items.mjs +162 -162
  504. package/fesm2020/pepperi-addons-ngx-lib-field-title.mjs +76 -76
  505. package/fesm2020/pepperi-addons-ngx-lib-files-uploader.mjs +288 -288
  506. package/fesm2020/pepperi-addons-ngx-lib-form.mjs +4120 -4120
  507. package/fesm2020/pepperi-addons-ngx-lib-form.mjs.map +1 -1
  508. package/fesm2020/pepperi-addons-ngx-lib-group-buttons.mjs +109 -109
  509. package/fesm2020/pepperi-addons-ngx-lib-icon.mjs +700 -700
  510. package/fesm2020/pepperi-addons-ngx-lib-image.mjs +338 -338
  511. package/fesm2020/pepperi-addons-ngx-lib-images-filmstrip.mjs +387 -387
  512. package/fesm2020/pepperi-addons-ngx-lib-link.mjs +388 -388
  513. package/fesm2020/pepperi-addons-ngx-lib-list.mjs +2812 -2812
  514. package/fesm2020/pepperi-addons-ngx-lib-list.mjs.map +1 -1
  515. package/fesm2020/pepperi-addons-ngx-lib-menu.mjs +368 -368
  516. package/fesm2020/pepperi-addons-ngx-lib-page-layout.mjs +59 -59
  517. package/fesm2020/pepperi-addons-ngx-lib-profile-data-views-list.mjs +253 -253
  518. package/fesm2020/pepperi-addons-ngx-lib-quantity-selector.mjs +688 -688
  519. package/fesm2020/pepperi-addons-ngx-lib-query-builder.mjs +1108 -1108
  520. package/fesm2020/pepperi-addons-ngx-lib-remote-loader.mjs +482 -482
  521. package/fesm2020/pepperi-addons-ngx-lib-rich-html-textarea.mjs +303 -303
  522. package/fesm2020/pepperi-addons-ngx-lib-search.mjs +355 -355
  523. package/fesm2020/pepperi-addons-ngx-lib-select-panel.mjs +206 -205
  524. package/fesm2020/pepperi-addons-ngx-lib-select-panel.mjs.map +1 -1
  525. package/fesm2020/pepperi-addons-ngx-lib-select.mjs +308 -308
  526. package/fesm2020/pepperi-addons-ngx-lib-separator.mjs +73 -73
  527. package/fesm2020/pepperi-addons-ngx-lib-side-bar.mjs +158 -158
  528. package/fesm2020/pepperi-addons-ngx-lib-signature.mjs +311 -311
  529. package/fesm2020/pepperi-addons-ngx-lib-size-detector.mjs +114 -114
  530. package/fesm2020/pepperi-addons-ngx-lib-slider.mjs +129 -129
  531. package/fesm2020/pepperi-addons-ngx-lib-smart-filters.mjs +1627 -1627
  532. package/fesm2020/pepperi-addons-ngx-lib-smart-filters.mjs.map +1 -1
  533. package/fesm2020/pepperi-addons-ngx-lib-snack-bar.mjs +149 -149
  534. package/fesm2020/pepperi-addons-ngx-lib-textarea.mjs +237 -231
  535. package/fesm2020/pepperi-addons-ngx-lib-textarea.mjs.map +1 -1
  536. package/fesm2020/pepperi-addons-ngx-lib-textbox-icon.mjs +95 -95
  537. package/fesm2020/pepperi-addons-ngx-lib-textbox.mjs +679 -673
  538. package/fesm2020/pepperi-addons-ngx-lib-textbox.mjs.map +1 -1
  539. package/fesm2020/pepperi-addons-ngx-lib-top-bar.mjs +154 -154
  540. package/fesm2020/pepperi-addons-ngx-lib.mjs +4585 -4585
  541. package/fesm2020/pepperi-addons-ngx-lib.mjs.map +1 -1
  542. package/field-title/field-title.component.d.ts +15 -15
  543. package/field-title/field-title.module.d.ts +15 -15
  544. package/field-title/index.d.ts +5 -5
  545. package/field-title/public-api.d.ts +2 -2
  546. package/files-uploader/files-uploader.component.d.ts +57 -57
  547. package/files-uploader/files-uploader.module.d.ts +21 -21
  548. package/files-uploader/index.d.ts +5 -5
  549. package/files-uploader/public-api.d.ts +2 -2
  550. package/form/field-generator.component.d.ts +39 -39
  551. package/form/form.component.d.ts +93 -93
  552. package/form/form.model.d.ts +20 -20
  553. package/form/form.module.d.ts +50 -50
  554. package/form/index.d.ts +5 -5
  555. package/form/indicators.component.d.ts +10 -10
  556. package/form/internal-button.component.d.ts +42 -42
  557. package/form/internal-carusel.component.d.ts +39 -39
  558. package/form/internal-carusel.service.d.ts +10 -10
  559. package/form/internal-field-generator.component.d.ts +35 -35
  560. package/form/internal-form.component.d.ts +89 -89
  561. package/form/internal-list.component.d.ts +95 -95
  562. package/form/internal-menu.component.d.ts +19 -19
  563. package/form/internal-page.component.d.ts +73 -73
  564. package/form/internal-page.service.d.ts +22 -22
  565. package/form/public-api.d.ts +3 -3
  566. package/group-buttons/group-buttons.component.d.ts +24 -24
  567. package/group-buttons/group-buttons.module.d.ts +18 -18
  568. package/group-buttons/index.d.ts +5 -5
  569. package/group-buttons/public-api.d.ts +2 -2
  570. package/icon/icon-generated-all.model.d.ts +112 -112
  571. package/icon/icon-generated.model.d.ts +446 -446
  572. package/icon/icon-registry.service.d.ts +9 -9
  573. package/icon/icon.component.d.ts +49 -49
  574. package/icon/icon.module.d.ts +7 -7
  575. package/icon/icon.service.d.ts +13 -13
  576. package/icon/index.d.ts +5 -5
  577. package/icon/public-api.d.ts +6 -6
  578. package/image/image.component.d.ts +66 -66
  579. package/image/image.module.d.ts +20 -20
  580. package/image/image.service.d.ts +14 -14
  581. package/image/index.d.ts +5 -5
  582. package/image/public-api.d.ts +3 -3
  583. package/images-filmstrip/images-filmstrip.component.d.ts +87 -87
  584. package/images-filmstrip/images-filmstrip.module.d.ts +22 -22
  585. package/images-filmstrip/index.d.ts +5 -5
  586. package/images-filmstrip/public-api.d.ts +2 -2
  587. package/index.d.ts +5 -5
  588. package/link/index.d.ts +5 -5
  589. package/link/link.component.d.ts +126 -126
  590. package/link/link.module.d.ts +22 -22
  591. package/link/link.pipes.d.ts +7 -7
  592. package/link/public-api.d.ts +2 -2
  593. package/list/index.d.ts +5 -5
  594. package/list/list-actions.component.d.ts +18 -18
  595. package/list/list-carousel.component.d.ts +40 -40
  596. package/list/list-chooser.component.d.ts +29 -29
  597. package/list/list-pager.component.d.ts +39 -39
  598. package/list/list-sorting.component.d.ts +30 -30
  599. package/list/list-total.component.d.ts +11 -11
  600. package/list/list-views.component.d.ts +35 -35
  601. package/list/list.component.d.ts +164 -164
  602. package/list/list.model.d.ts +31 -31
  603. package/list/list.module.d.ts +34 -34
  604. package/list/list.pipes.d.ts +16 -16
  605. package/list/public-api.d.ts +10 -10
  606. package/list/virtual-scroller.d.ts +183 -183
  607. package/menu/index.d.ts +5 -5
  608. package/menu/menu-item.component.d.ts +28 -28
  609. package/menu/menu.component.d.ts +48 -48
  610. package/menu/menu.model.d.ts +25 -25
  611. package/menu/menu.module.d.ts +18 -18
  612. package/menu/public-api.d.ts +3 -3
  613. package/ngx-lib.module.d.ts +24 -24
  614. package/package.json +1 -1
  615. package/page-layout/index.d.ts +5 -5
  616. package/page-layout/page-layout.component.d.ts +19 -19
  617. package/page-layout/page-layout.module.d.ts +10 -10
  618. package/page-layout/public-api.d.ts +2 -2
  619. package/profile-data-views-list/index.d.ts +5 -5
  620. package/profile-data-views-list/profile-data-view/profile-data-view.component.d.ts +18 -18
  621. package/profile-data-views-list/profile-data-views-card/profile-data-views-card.component.d.ts +24 -24
  622. package/profile-data-views-list/profile-data-views-list.component.d.ts +35 -35
  623. package/profile-data-views-list/profile-data-views-list.model.d.ts +18 -18
  624. package/profile-data-views-list/profile-data-views-list.module.d.ts +23 -23
  625. package/profile-data-views-list/public-api.d.ts +5 -5
  626. package/public-api.d.ts +2 -2
  627. package/quantity-selector/index.d.ts +5 -5
  628. package/quantity-selector/public-api.d.ts +2 -2
  629. package/quantity-selector/quantity-selector-validation.directive.d.ts +17 -17
  630. package/quantity-selector/quantity-selector.component.d.ts +112 -112
  631. package/quantity-selector/quantity-selector.module.d.ts +23 -23
  632. package/quantity-selector/quantity-selector.pipes.d.ts +7 -7
  633. package/query-builder/common/model/field.d.ts +8 -8
  634. package/query-builder/common/model/filter.d.ts +6 -6
  635. package/query-builder/common/model/legacy.d.ts +29 -29
  636. package/query-builder/common/model/operator-unit.d.ts +13 -13
  637. package/query-builder/common/model/operator.d.ts +21 -21
  638. package/query-builder/common/model/structure.d.ts +4 -4
  639. package/query-builder/common/model/type-map.d.ts +12 -12
  640. package/query-builder/common/model/type.d.ts +4 -4
  641. package/query-builder/common/services/output-query.service.d.ts +47 -47
  642. package/query-builder/common/services/query-structure.service.d.ts +82 -82
  643. package/query-builder/common/services/type-convertor.service.d.ts +13 -13
  644. package/query-builder/index.d.ts +5 -5
  645. package/query-builder/public-api.d.ts +5 -5
  646. package/query-builder/query-builder-item/query-builder-item.component.d.ts +41 -41
  647. package/query-builder/query-builder-section/query-builder-section.component.d.ts +30 -30
  648. package/query-builder/query-builder.component.d.ts +39 -39
  649. package/query-builder/query-builder.module.d.ts +16 -16
  650. package/query-builder/query-builder.service.d.ts +30 -30
  651. package/remote-loader/addon-block-loader.component.d.ts +36 -36
  652. package/remote-loader/addon-block-loader.service.d.ts +15 -15
  653. package/remote-loader/index.d.ts +5 -5
  654. package/remote-loader/public-api.d.ts +7 -7
  655. package/remote-loader/remote-loader-element.component.d.ts +30 -30
  656. package/remote-loader/remote-loader.component.d.ts +25 -25
  657. package/remote-loader/remote-loader.model.d.ts +41 -41
  658. package/remote-loader/remote-loader.module.d.ts +15 -15
  659. package/remote-loader/remote-loader.service.d.ts +15 -15
  660. package/rich-html-textarea/index.d.ts +5 -5
  661. package/rich-html-textarea/public-api.d.ts +2 -2
  662. package/rich-html-textarea/rich-html-textarea.component.d.ts +79 -79
  663. package/rich-html-textarea/rich-html-textarea.module.d.ts +25 -25
  664. package/search/index.d.ts +5 -5
  665. package/search/public-api.d.ts +3 -3
  666. package/search/search.component.d.ts +65 -65
  667. package/search/search.model.d.ts +14 -14
  668. package/search/search.module.d.ts +20 -20
  669. package/select/index.d.ts +5 -5
  670. package/select/public-api.d.ts +2 -2
  671. package/select/select.component.d.ts +60 -60
  672. package/select/select.module.d.ts +20 -20
  673. package/select-panel/index.d.ts +5 -5
  674. package/select-panel/public-api.d.ts +3 -3
  675. package/select-panel/select-panel.component.d.ts +51 -50
  676. package/select-panel/select-panel.model.d.ts +5 -5
  677. package/select-panel/select-panel.module.d.ts +19 -19
  678. package/separator/index.d.ts +5 -5
  679. package/separator/public-api.d.ts +2 -2
  680. package/separator/separator.component.d.ts +22 -22
  681. package/separator/separator.module.d.ts +8 -8
  682. package/side-bar/index.d.ts +5 -5
  683. package/side-bar/public-api.d.ts +3 -3
  684. package/side-bar/side-bar.component.d.ts +42 -42
  685. package/side-bar/side-bar.model.d.ts +4 -4
  686. package/side-bar/side-bar.module.d.ts +16 -16
  687. package/signature/index.d.ts +5 -5
  688. package/signature/public-api.d.ts +2 -2
  689. package/signature/signature.component.d.ts +68 -68
  690. package/signature/signature.module.d.ts +24 -24
  691. package/size-detector/index.d.ts +5 -5
  692. package/size-detector/public-api.d.ts +2 -2
  693. package/size-detector/size-detector.component.d.ts +29 -29
  694. package/size-detector/size-detector.module.d.ts +11 -11
  695. package/slider/index.d.ts +5 -5
  696. package/slider/public-api.d.ts +2 -2
  697. package/slider/slider.component.d.ts +39 -39
  698. package/slider/slider.module.d.ts +12 -12
  699. package/smart-filters/boolean-filter/boolean-filter.component.d.ts +28 -28
  700. package/smart-filters/common/filter-actions.component.d.ts +12 -12
  701. package/smart-filters/common/model/base-filter-component.d.ts +74 -74
  702. package/smart-filters/common/model/creator.d.ts +6 -6
  703. package/smart-filters/common/model/field.d.ts +69 -69
  704. package/smart-filters/common/model/filter.d.ts +11 -11
  705. package/smart-filters/common/model/operator.d.ts +51 -51
  706. package/smart-filters/common/model/type.d.ts +4 -4
  707. package/smart-filters/date-filter/date-filter.component.d.ts +60 -60
  708. package/smart-filters/index.d.ts +5 -5
  709. package/smart-filters/multi-select-filter/multi-select-filter.component.d.ts +56 -56
  710. package/smart-filters/number-filter/number-filter.component.d.ts +52 -52
  711. package/smart-filters/public-api.d.ts +14 -14
  712. package/smart-filters/smart-filters.component.d.ts +35 -35
  713. package/smart-filters/smart-filters.module.d.ts +37 -37
  714. package/smart-filters/text-filter/text-filter.component.d.ts +28 -28
  715. package/snack-bar/default-snack-bar.component.d.ts +13 -13
  716. package/snack-bar/index.d.ts +5 -5
  717. package/snack-bar/public-api.d.ts +4 -4
  718. package/snack-bar/snack-bar.component.d.ts +12 -12
  719. package/snack-bar/snack-bar.model.d.ts +8 -8
  720. package/snack-bar/snack-bar.module.d.ts +19 -19
  721. package/snack-bar/snack-bar.service.d.ts +24 -24
  722. package/textarea/index.d.ts +5 -5
  723. package/textarea/public-api.d.ts +2 -2
  724. package/textarea/textarea.component.d.ts +56 -54
  725. package/textarea/textarea.module.d.ts +23 -23
  726. package/textbox/index.d.ts +5 -5
  727. package/textbox/public-api.d.ts +2 -2
  728. package/textbox/textbox-validation.directive.d.ts +22 -22
  729. package/textbox/textbox.component.d.ts +155 -153
  730. package/textbox/textbox.module.d.ts +22 -22
  731. package/textbox-icon/index.d.ts +5 -5
  732. package/textbox-icon/public-api.d.ts +2 -2
  733. package/textbox-icon/textbox-icon.component.d.ts +13 -13
  734. package/textbox-icon/textbox-icon.module.d.ts +16 -16
  735. package/top-bar/index.d.ts +5 -5
  736. package/top-bar/public-api.d.ts +3 -3
  737. package/top-bar/top-bar.component.d.ts +39 -39
  738. package/top-bar/top-bar.model.d.ts +4 -4
  739. package/top-bar/top-bar.module.d.ts +18 -18
@@ -1,1072 +1,1072 @@
1
- import { Component, ContentChild, ElementRef, EventEmitter, Inject, Input, NgModule, Optional, Output, ViewChild, } from '@angular/core';
2
- import { PLATFORM_ID } from '@angular/core';
3
- import { isPlatformServer } from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import * as tween from '@tweenjs/tween.js';
6
- import * as i0 from "@angular/core";
7
- export function VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY() {
8
- return {
9
- checkResizeInterval: 1000,
10
- modifyOverflowStyleOfParentScroll: true,
11
- resizeBypassRefreshThreshold: 5,
12
- scrollAnimationTime: 750,
13
- scrollDebounceTime: 0,
14
- scrollThrottlingTime: 0,
15
- stripedTable: false
16
- };
17
- }
18
- export class VirtualScrollerComponent {
19
- constructor(element, renderer, zone, changeDetectorRef, platformId, options) {
20
- this.element = element;
21
- this.renderer = renderer;
22
- this.zone = zone;
23
- this.changeDetectorRef = changeDetectorRef;
24
- this.window = window;
25
- this._disable = false;
26
- this.executeRefreshOutsideAngularZone = false;
27
- this._enableUnequalChildrenSizes = false;
28
- this.RTL = false;
29
- this.useMarginInsteadOfTranslate = false;
30
- this.ssrViewportWidth = 1920;
31
- this.ssrViewportHeight = 1080;
32
- this._items = [];
33
- this.compareItems = (item1, item2) => item1 === item2;
34
- this.vsChildRectChange = new EventEmitter();
35
- this.vsUpdate = new EventEmitter();
36
- this.vsChange = new EventEmitter();
37
- this.vsStart = new EventEmitter();
38
- this.vsEnd = new EventEmitter();
39
- this.calculatedScrollbarWidth = 0;
40
- this.calculatedScrollbarHeight = 0;
41
- this.padding = 0;
42
- this.previousViewPort = {};
43
- this.cachedPageSize = 0;
44
- this.previousScrollNumberElements = 0;
45
- this.isAngularUniversalSSR = isPlatformServer(platformId);
46
- const defaultOptions = VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY();
47
- this.checkResizeInterval = options?.checkResizeInterval || defaultOptions.checkResizeInterval;
48
- this.modifyOverflowStyleOfParentScroll = options?.modifyOverflowStyleOfParentScroll || defaultOptions.modifyOverflowStyleOfParentScroll;
49
- this.resizeBypassRefreshThreshold = options?.resizeBypassRefreshThreshold || defaultOptions.resizeBypassRefreshThreshold;
50
- this.scrollAnimationTime = options?.scrollAnimationTime || defaultOptions.scrollAnimationTime;
51
- this.scrollDebounceTime = options?.scrollDebounceTime || defaultOptions.scrollDebounceTime;
52
- this.scrollThrottlingTime = options?.scrollThrottlingTime || defaultOptions.scrollThrottlingTime;
53
- this.scrollbarHeight = options?.scrollbarHeight || defaultOptions.scrollbarHeight;
54
- this.scrollbarWidth = options?.scrollbarWidth || defaultOptions.scrollbarWidth;
55
- this.stripedTable = options?.stripedTable || defaultOptions.stripedTable;
56
- this.horizontal = false;
57
- this.resetWrapGroupDimensions();
58
- }
59
- get viewPortInfo() {
60
- const pageInfo = this.previousViewPort || {};
61
- return {
62
- startIndex: pageInfo.startIndex || 0,
63
- endIndex: pageInfo.endIndex || 0,
64
- scrollStartPosition: pageInfo.scrollStartPosition || 0,
65
- scrollEndPosition: pageInfo.scrollEndPosition || 0,
66
- scrollDirection: pageInfo.scrollDirection || 'forward',
67
- maxScrollPosition: pageInfo.maxScrollPosition || 0,
68
- startIndexWithBuffer: pageInfo.startIndexWithBuffer || 0,
69
- endIndexWithBuffer: pageInfo.endIndexWithBuffer || 0,
70
- };
71
- }
72
- get disable() {
73
- return this._disable;
74
- }
75
- set disable(value) {
76
- if (this._disable === value) {
77
- return;
78
- }
79
- this._disable = value;
80
- if (this._disable) {
81
- this.removeScrollEventHandlers();
82
- }
83
- else {
84
- this.addScrollEventHandlers();
85
- }
86
- }
87
- get enableUnequalChildrenSizes() {
88
- return this._enableUnequalChildrenSizes;
89
- }
90
- set enableUnequalChildrenSizes(value) {
91
- if (this._enableUnequalChildrenSizes === value) {
92
- return;
93
- }
94
- this._enableUnequalChildrenSizes = value;
95
- this.minMeasuredChildWidth = undefined;
96
- this.minMeasuredChildHeight = undefined;
97
- }
98
- get bufferAmount() {
99
- if (typeof (this._bufferAmount) === 'number' && this._bufferAmount > 0) {
100
- return this._bufferAmount;
101
- }
102
- else {
103
- return this.enableUnequalChildrenSizes ? 5 : 1;
104
- }
105
- }
106
- set bufferAmount(value) {
107
- this._bufferAmount = value;
108
- }
109
- get scrollThrottlingTime() {
110
- return this._scrollThrottlingTime;
111
- }
112
- set scrollThrottlingTime(value) {
113
- this._scrollThrottlingTime = value;
114
- this.updateOnScrollFunction();
115
- }
116
- get scrollDebounceTime() {
117
- return this._scrollDebounceTime;
118
- }
119
- set scrollDebounceTime(value) {
120
- this._scrollDebounceTime = value;
121
- this.updateOnScrollFunction();
122
- }
123
- updateOnScrollFunction() {
124
- if (this.scrollDebounceTime) {
125
- this.onScroll = this.debounce(() => {
126
- this.refresh_internal(false);
127
- }, this.scrollDebounceTime);
128
- }
129
- else if (this.scrollThrottlingTime) {
130
- this.onScroll = this.throttleTrailing(() => {
131
- this.refresh_internal(false);
132
- }, this.scrollThrottlingTime);
133
- }
134
- else {
135
- this.onScroll = () => {
136
- this.refresh_internal(false);
137
- };
138
- }
139
- }
140
- get checkResizeInterval() {
141
- return this._checkResizeInterval;
142
- }
143
- set checkResizeInterval(value) {
144
- if (this._checkResizeInterval === value) {
145
- return;
146
- }
147
- this._checkResizeInterval = value;
148
- this.addScrollEventHandlers();
149
- }
150
- get items() {
151
- return this._items;
152
- }
153
- set items(value) {
154
- if (value === this._items) {
155
- return;
156
- }
157
- this._items = value || [];
158
- this.refresh_internal(true);
159
- }
160
- get horizontal() {
161
- return this._horizontal;
162
- }
163
- set horizontal(value) {
164
- this._horizontal = value;
165
- this.updateDirection();
166
- }
167
- revertParentOverscroll() {
168
- const scrollElement = this.getScrollElement();
169
- if (scrollElement && this.oldParentScrollOverflow) {
170
- scrollElement.style['overflow-y'] = this.oldParentScrollOverflow.y;
171
- scrollElement.style['overflow-x'] = this.oldParentScrollOverflow.x;
172
- }
173
- this.oldParentScrollOverflow = undefined;
174
- }
175
- get parentScroll() {
176
- return this._parentScroll;
177
- }
178
- set parentScroll(value) {
179
- if (this._parentScroll === value) {
180
- return;
181
- }
182
- this.revertParentOverscroll();
183
- this._parentScroll = value;
184
- this.addScrollEventHandlers();
185
- const scrollElement = this.getScrollElement();
186
- if (this.modifyOverflowStyleOfParentScroll && scrollElement !== this.element.nativeElement) {
187
- this.oldParentScrollOverflow = { x: scrollElement.style['overflow-x'], y: scrollElement.style['overflow-y'] };
188
- scrollElement.style['overflow-y'] = this.horizontal ? 'visible' : 'auto';
189
- scrollElement.style['overflow-x'] = this.horizontal ? 'auto' : 'visible';
190
- }
191
- }
192
- ngOnInit() {
193
- this.addScrollEventHandlers();
194
- }
195
- ngOnDestroy() {
196
- this.removeScrollEventHandlers();
197
- this.revertParentOverscroll();
198
- }
199
- ngOnChanges(changes) {
200
- const indexLengthChanged = this.cachedItemsLength !== this.items.length;
201
- this.cachedItemsLength = this.items.length;
202
- const firstRun = !changes.items || !changes.items.previousValue || changes.items.previousValue.length === 0;
203
- this.refresh_internal(indexLengthChanged || firstRun);
204
- }
205
- ngDoCheck() {
206
- if (this.cachedItemsLength !== this.items.length) {
207
- this.cachedItemsLength = this.items.length;
208
- this.refresh_internal(true);
209
- return;
210
- }
211
- if (this.previousViewPort && this.viewPortItems && this.viewPortItems.length > 0) {
212
- let itemsArrayChanged = false;
213
- for (let i = 0; i < this.viewPortItems.length; ++i) {
214
- if (!this.compareItems(this.items[this.previousViewPort.startIndexWithBuffer + i], this.viewPortItems[i])) {
215
- itemsArrayChanged = true;
216
- break;
217
- }
218
- }
219
- if (itemsArrayChanged) {
220
- this.refresh_internal(true);
221
- }
222
- }
223
- }
224
- refresh() {
225
- this.refresh_internal(true);
226
- }
227
- invalidateAllCachedMeasurements() {
228
- this.wrapGroupDimensions = {
229
- maxChildSizePerWrapGroup: [],
230
- numberOfKnownWrapGroupChildSizes: 0,
231
- sumOfKnownWrapGroupChildWidths: 0,
232
- sumOfKnownWrapGroupChildHeights: 0
233
- };
234
- this.minMeasuredChildWidth = undefined;
235
- this.minMeasuredChildHeight = undefined;
236
- this.refresh_internal(false);
237
- }
238
- invalidateCachedMeasurementForItem(item) {
239
- if (this.enableUnequalChildrenSizes) {
240
- const index = this.items && this.items.indexOf(item);
241
- if (index >= 0) {
242
- this.invalidateCachedMeasurementAtIndex(index);
243
- }
244
- }
245
- else {
246
- this.minMeasuredChildWidth = undefined;
247
- this.minMeasuredChildHeight = undefined;
248
- }
249
- this.refresh_internal(false);
250
- }
251
- invalidateCachedMeasurementAtIndex(index) {
252
- if (this.enableUnequalChildrenSizes) {
253
- const cachedMeasurement = this.wrapGroupDimensions.maxChildSizePerWrapGroup[index];
254
- if (cachedMeasurement) {
255
- this.wrapGroupDimensions.maxChildSizePerWrapGroup[index] = undefined;
256
- --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
257
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -= cachedMeasurement.childWidth || 0;
258
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -= cachedMeasurement.childHeight || 0;
259
- }
260
- }
261
- else {
262
- this.minMeasuredChildWidth = undefined;
263
- this.minMeasuredChildHeight = undefined;
264
- }
265
- this.refresh_internal(false);
266
- }
267
- scrollInto(item, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
268
- const index = this.items.indexOf(item);
269
- if (index === -1) {
270
- return;
271
- }
272
- this.scrollToIndex(index, alignToBeginning, additionalOffset, animationMilliseconds, animationCompletedCallback);
273
- }
274
- scrollToIndex(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
275
- let maxRetries = 5;
276
- const retryIfNeeded = () => {
277
- --maxRetries;
278
- if (maxRetries <= 0) {
279
- if (animationCompletedCallback) {
280
- animationCompletedCallback();
281
- }
282
- return;
283
- }
284
- const dimensions = this.calculateDimensions();
285
- const desiredStartIndex = Math.min(Math.max(index, 0), dimensions.itemCount - 1);
286
- if (this.previousViewPort.startIndex === desiredStartIndex) {
287
- if (animationCompletedCallback) {
288
- animationCompletedCallback();
289
- }
290
- return;
291
- }
292
- this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, 0, retryIfNeeded);
293
- };
294
- this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, animationMilliseconds, retryIfNeeded);
295
- }
296
- scrollToIndex_internal(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
297
- animationMilliseconds = animationMilliseconds === undefined ? this.scrollAnimationTime : animationMilliseconds;
298
- const dimensions = this.calculateDimensions();
299
- let scroll = this.calculatePadding(index, dimensions) + additionalOffset;
300
- if (!alignToBeginning) {
301
- scroll -= dimensions.wrapGroupsPerPage * dimensions[this._childScrollDim];
302
- }
303
- this.scrollToPosition(scroll, animationMilliseconds, animationCompletedCallback);
304
- }
305
- scrollToPosition(scrollPosition, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
306
- scrollPosition += this.getElementsOffset();
307
- animationMilliseconds = animationMilliseconds === undefined ? this.scrollAnimationTime : animationMilliseconds;
308
- const scrollElement = this.getScrollElement();
309
- let animationRequest;
310
- if (this.currentTween) {
311
- this.currentTween.stop();
312
- this.currentTween = undefined;
313
- }
314
- if (!animationMilliseconds) {
315
- this.renderer.setProperty(scrollElement, this._scrollType, scrollPosition);
316
- this.refresh_internal(false, animationCompletedCallback);
317
- return;
318
- }
319
- const tweenConfigObj = { scrollPosition: scrollElement[this._scrollType] };
320
- const newTween = new tween.Tween(tweenConfigObj)
321
- .to({ scrollPosition }, animationMilliseconds)
322
- .easing(tween.Easing.Quadratic.Out)
323
- .onUpdate((data) => {
324
- if (isNaN(data.scrollPosition)) {
325
- return;
326
- }
327
- this.renderer.setProperty(scrollElement, this._scrollType, data.scrollPosition);
328
- this.refresh_internal(false);
329
- })
330
- .onStop(() => {
331
- cancelAnimationFrame(animationRequest);
332
- })
333
- .start();
334
- const animate = (time) => {
335
- if (!newTween["isPlaying"]()) {
336
- return;
337
- }
338
- newTween.update(time);
339
- if (tweenConfigObj.scrollPosition === scrollPosition) {
340
- this.refresh_internal(false, animationCompletedCallback);
341
- return;
342
- }
343
- this.zone.runOutsideAngular(() => {
344
- animationRequest = requestAnimationFrame(animate);
345
- });
346
- };
347
- animate();
348
- this.currentTween = newTween;
349
- }
350
- getElementSize(element) {
351
- const result = element.getBoundingClientRect();
352
- const styles = getComputedStyle(element);
353
- const marginTop = parseInt(styles['margin-top'], 10) || 0;
354
- const marginBottom = parseInt(styles['margin-bottom'], 10) || 0;
355
- const marginLeft = parseInt(styles['margin-left'], 10) || 0;
356
- const marginRight = parseInt(styles['margin-right'], 10) || 0;
357
- return {
358
- top: result.top + marginTop,
359
- bottom: result.bottom + marginBottom,
360
- left: result.left + marginLeft,
361
- right: result.right + marginRight,
362
- width: result.width + marginLeft + marginRight,
363
- height: result.height + marginTop + marginBottom
364
- };
365
- }
366
- checkScrollElementResized() {
367
- const boundingRect = this.getElementSize(this.getScrollElement());
368
- let sizeChanged;
369
- if (!this.previousScrollBoundingRect) {
370
- sizeChanged = true;
371
- }
372
- else {
373
- const widthChange = Math.abs(boundingRect.width - this.previousScrollBoundingRect.width);
374
- const heightChange = Math.abs(boundingRect.height - this.previousScrollBoundingRect.height);
375
- sizeChanged = widthChange > this.resizeBypassRefreshThreshold || heightChange > this.resizeBypassRefreshThreshold;
376
- }
377
- if (sizeChanged) {
378
- this.previousScrollBoundingRect = boundingRect;
379
- if (boundingRect.width > 0 && boundingRect.height > 0) {
380
- this.refresh_internal(false);
381
- }
382
- }
383
- }
384
- updateDirection() {
385
- if (this.horizontal) {
386
- this._childScrollDim = 'childWidth';
387
- this._invisiblePaddingProperty = 'scaleX';
388
- this._marginDir = 'margin-left';
389
- this._offsetType = 'offsetLeft';
390
- this._pageOffsetType = 'pageXOffset';
391
- this._scrollType = 'scrollLeft';
392
- this._translateDir = 'translateX';
393
- }
394
- else {
395
- this._childScrollDim = 'childHeight';
396
- this._invisiblePaddingProperty = 'scaleY';
397
- this._marginDir = 'margin-top';
398
- this._offsetType = 'offsetTop';
399
- this._pageOffsetType = 'pageYOffset';
400
- this._scrollType = 'scrollTop';
401
- this._translateDir = 'translateY';
402
- }
403
- }
404
- debounce(func, wait, ...args) {
405
- const throttled = this.throttleTrailing(func, wait);
406
- const result = function () {
407
- throttled['cancel']();
408
- throttled.apply(this, args);
409
- };
410
- result['cancel'] = function () {
411
- throttled['cancel']();
412
- };
413
- return result;
414
- }
415
- throttleTrailing(func, wait, ...args) {
416
- let timeout = undefined;
417
- let _arguments = args;
418
- const result = function () {
419
- const _this = this;
420
- _arguments = args;
421
- if (timeout) {
422
- return;
423
- }
424
- if (wait <= 0) {
425
- func.apply(_this, _arguments);
426
- }
427
- else {
428
- timeout = setTimeout(function () {
429
- timeout = undefined;
430
- func.apply(_this, _arguments);
431
- }, wait);
432
- }
433
- };
434
- result['cancel'] = function () {
435
- if (timeout) {
436
- clearTimeout(timeout);
437
- timeout = undefined;
438
- }
439
- };
440
- return result;
441
- }
442
- refresh_internal(itemsArrayModified, refreshCompletedCallback = undefined, maxRunTimes = 2) {
443
- //note: maxRunTimes is to force it to keep recalculating if the previous iteration caused a re-render (different sliced items in viewport or scrollPosition changed).
444
- //The default of 2x max will probably be accurate enough without causing too large a performance bottleneck
445
- //The code would typically quit out on the 2nd iteration anyways. The main time it'd think more than 2 runs would be necessary would be for vastly different sized child items or if this is the 1st time the items array was initialized.
446
- //Without maxRunTimes, If the user is actively scrolling this code would become an infinite loop until they stopped scrolling. This would be okay, except each scroll event would start an additional infinte loop. We want to short-circuit it to prevent this.
447
- if (itemsArrayModified && this.previousViewPort && this.previousViewPort.scrollStartPosition > 0) {
448
- //if items were prepended, scroll forward to keep same items visible
449
- const oldViewPort = this.previousViewPort;
450
- const oldViewPortItems = this.viewPortItems;
451
- const oldRefreshCompletedCallback = refreshCompletedCallback;
452
- refreshCompletedCallback = () => {
453
- const scrollLengthDelta = this.previousViewPort.scrollLength - oldViewPort.scrollLength;
454
- if (scrollLengthDelta > 0 && this.viewPortItems) {
455
- const oldStartItem = oldViewPortItems[0];
456
- const oldStartItemIndex = this.items.findIndex(x => this.compareItems(oldStartItem, x));
457
- if (oldStartItemIndex > this.previousViewPort.startIndexWithBuffer) {
458
- let itemOrderChanged = false;
459
- for (let i = 1; i < this.viewPortItems.length; ++i) {
460
- if (!this.compareItems(this.items[oldStartItemIndex + i], oldViewPortItems[i])) {
461
- itemOrderChanged = true;
462
- break;
463
- }
464
- }
465
- if (!itemOrderChanged) {
466
- this.scrollToPosition(this.previousViewPort.scrollStartPosition + scrollLengthDelta, 0, oldRefreshCompletedCallback);
467
- return;
468
- }
469
- }
470
- }
471
- if (oldRefreshCompletedCallback) {
472
- oldRefreshCompletedCallback();
473
- }
474
- };
475
- }
476
- this.zone.runOutsideAngular(() => {
477
- requestAnimationFrame(() => {
478
- if (itemsArrayModified) {
479
- this.resetWrapGroupDimensions();
480
- }
481
- const viewport = this.calculateViewport();
482
- const startChanged = itemsArrayModified || viewport.startIndex !== this.previousViewPort.startIndex;
483
- const endChanged = itemsArrayModified || viewport.endIndex !== this.previousViewPort.endIndex;
484
- const scrollLengthChanged = viewport.scrollLength !== this.previousViewPort.scrollLength;
485
- const paddingChanged = viewport.padding !== this.previousViewPort.padding;
486
- const scrollPositionChanged = viewport.scrollStartPosition !== this.previousViewPort.scrollStartPosition || viewport.scrollEndPosition !== this.previousViewPort.scrollEndPosition || viewport.maxScrollPosition !== this.previousViewPort.maxScrollPosition;
487
- const scrollDirection = this.previousViewPort.endIndex <= viewport.endIndex ? 'forward' : 'backward';
488
- this.previousViewPort = viewport;
489
- if (scrollLengthChanged) {
490
- this.renderer.setStyle(this.invisiblePaddingElementRef.nativeElement, 'transform', `${this._invisiblePaddingProperty}(${viewport.scrollLength})`);
491
- this.renderer.setStyle(this.invisiblePaddingElementRef.nativeElement, 'webkitTransform', `${this._invisiblePaddingProperty}(${viewport.scrollLength})`);
492
- }
493
- if (paddingChanged) {
494
- if (this.useMarginInsteadOfTranslate) {
495
- this.renderer.setStyle(this.contentElementRef.nativeElement, this._marginDir, `${viewport.padding}px`);
496
- }
497
- else {
498
- this.renderer.setStyle(this.contentElementRef.nativeElement, 'transform', `${this._translateDir}(${viewport.padding}px)`);
499
- this.renderer.setStyle(this.contentElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${viewport.padding}px)`);
500
- }
501
- }
502
- if (this.headerElementRef) {
503
- const scrollPosition = this.getScrollElement()[this._scrollType];
504
- const containerOffset = this.getElementsOffset();
505
- const offset = Math.max(scrollPosition - viewport.padding - containerOffset + this.headerElementRef.nativeElement.clientHeight, 0);
506
- this.renderer.setStyle(this.headerElementRef.nativeElement, 'transform', `${this._translateDir}(${offset}px)`);
507
- this.renderer.setStyle(this.headerElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${offset}px)`);
508
- }
509
- const changeEventArg = (startChanged || endChanged) ? {
510
- startIndex: viewport.startIndex,
511
- endIndex: viewport.endIndex,
512
- scrollStartPosition: viewport.scrollStartPosition,
513
- scrollEndPosition: viewport.scrollEndPosition,
514
- scrollDirection: scrollDirection,
515
- startIndexWithBuffer: viewport.startIndexWithBuffer,
516
- endIndexWithBuffer: viewport.endIndexWithBuffer,
517
- maxScrollPosition: viewport.maxScrollPosition,
518
- } : undefined;
519
- if (startChanged || endChanged || scrollPositionChanged) {
520
- const handleChanged = () => {
521
- // update the scroll list to trigger re-render of components in viewport
522
- this.viewPortItems = viewport.startIndexWithBuffer >= 0 && viewport.endIndexWithBuffer >= 0 ? this.items.slice(viewport.startIndexWithBuffer, viewport.endIndexWithBuffer + 1) : [];
523
- this.vsUpdate.emit(this.viewPortItems);
524
- if (startChanged) {
525
- this.vsStart.emit(changeEventArg);
526
- }
527
- if (endChanged) {
528
- this.vsEnd.emit(changeEventArg);
529
- }
530
- if (startChanged || endChanged) {
531
- this.changeDetectorRef.markForCheck();
532
- this.vsChange.emit(changeEventArg);
533
- }
534
- if (maxRunTimes > 0) {
535
- this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
536
- return;
537
- }
538
- if (refreshCompletedCallback) {
539
- refreshCompletedCallback();
540
- }
541
- };
542
- if (this.executeRefreshOutsideAngularZone) {
543
- handleChanged();
544
- }
545
- else {
546
- this.zone.run(handleChanged);
547
- }
548
- }
549
- else {
550
- if (maxRunTimes > 0 && (scrollLengthChanged || paddingChanged)) {
551
- this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
552
- return;
553
- }
554
- if (refreshCompletedCallback) {
555
- refreshCompletedCallback();
556
- }
557
- }
558
- });
559
- });
560
- }
561
- getScrollElement() {
562
- return this.parentScroll instanceof Window ? document.scrollingElement || document.documentElement || document.body : this.parentScroll || this.element.nativeElement;
563
- }
564
- addScrollEventHandlers() {
565
- if (this.isAngularUniversalSSR) {
566
- return;
567
- }
568
- const scrollElement = this.getScrollElement();
569
- this.removeScrollEventHandlers();
570
- this.zone.runOutsideAngular(() => {
571
- if (this.parentScroll instanceof Window) {
572
- this.disposeScrollHandler = this.renderer.listen('window', 'scroll', this.onScroll);
573
- this.disposeResizeHandler = this.renderer.listen('window', 'resize', this.onScroll);
574
- }
575
- else {
576
- this.disposeScrollHandler = this.renderer.listen(scrollElement, 'scroll', this.onScroll);
577
- if (this._checkResizeInterval > 0) {
578
- this.checkScrollElementResizedTimer = setInterval(() => { this.checkScrollElementResized(); }, this._checkResizeInterval);
579
- }
580
- }
581
- });
582
- }
583
- removeScrollEventHandlers() {
584
- if (this.checkScrollElementResizedTimer) {
585
- clearInterval(this.checkScrollElementResizedTimer);
586
- }
587
- if (this.disposeScrollHandler) {
588
- this.disposeScrollHandler();
589
- this.disposeScrollHandler = undefined;
590
- }
591
- if (this.disposeResizeHandler) {
592
- this.disposeResizeHandler();
593
- this.disposeResizeHandler = undefined;
594
- }
595
- }
596
- getElementsOffset() {
597
- if (this.isAngularUniversalSSR) {
598
- return 0;
599
- }
600
- let offset = 0;
601
- if (this.containerElementRef && this.containerElementRef.nativeElement) {
602
- offset += this.containerElementRef.nativeElement[this._offsetType];
603
- }
604
- if (this.parentScroll) {
605
- const scrollElement = this.getScrollElement();
606
- const elementClientRect = this.getElementSize(this.element.nativeElement);
607
- const scrollClientRect = this.getElementSize(scrollElement);
608
- if (this.horizontal) {
609
- offset += elementClientRect.left - scrollClientRect.left;
610
- }
611
- else {
612
- offset += elementClientRect.top - scrollClientRect.top;
613
- }
614
- if (!(this.parentScroll instanceof Window)) {
615
- offset += scrollElement[this._scrollType];
616
- }
617
- }
618
- return offset;
619
- }
620
- countItemsPerWrapGroup() {
621
- if (this.isAngularUniversalSSR) {
622
- return Math.round(this.horizontal ? this.ssrViewportHeight / this.ssrChildHeight : this.ssrViewportWidth / this.ssrChildWidth);
623
- }
624
- const propertyName = this.horizontal ? 'offsetLeft' : 'offsetTop';
625
- const children = ((this.containerElementRef && this.containerElementRef.nativeElement) || this.contentElementRef.nativeElement).children;
626
- const childrenLength = children ? children.length : 0;
627
- if (childrenLength === 0) {
628
- return 1;
629
- }
630
- const firstOffset = children[0][propertyName];
631
- let result = 1;
632
- while (result < childrenLength && firstOffset === children[result][propertyName]) {
633
- ++result;
634
- }
635
- return result;
636
- }
637
- getScrollStartPosition() {
638
- let windowScrollValue = undefined;
639
- if (this.parentScroll instanceof Window) {
640
- windowScrollValue = window[this._pageOffsetType];
641
- }
642
- return windowScrollValue || this.getScrollElement()[this._scrollType] || 0;
643
- }
644
- resetWrapGroupDimensions() {
645
- const oldWrapGroupDimensions = this.wrapGroupDimensions;
646
- this.invalidateAllCachedMeasurements();
647
- if (!this.enableUnequalChildrenSizes || !oldWrapGroupDimensions || oldWrapGroupDimensions.numberOfKnownWrapGroupChildSizes === 0) {
648
- return;
649
- }
650
- const itemsPerWrapGroup = this.countItemsPerWrapGroup();
651
- for (let wrapGroupIndex = 0; wrapGroupIndex < oldWrapGroupDimensions.maxChildSizePerWrapGroup.length; ++wrapGroupIndex) {
652
- const oldWrapGroupDimension = oldWrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
653
- if (!oldWrapGroupDimension || !oldWrapGroupDimension.items || !oldWrapGroupDimension.items.length) {
654
- continue;
655
- }
656
- if (oldWrapGroupDimension.items.length !== itemsPerWrapGroup) {
657
- return;
658
- }
659
- let itemsChanged = false;
660
- const arrayStartIndex = itemsPerWrapGroup * wrapGroupIndex;
661
- for (let i = 0; i < itemsPerWrapGroup; ++i) {
662
- if (!this.compareItems(oldWrapGroupDimension.items[i], this.items[arrayStartIndex + i])) {
663
- itemsChanged = true;
664
- break;
665
- }
666
- }
667
- if (!itemsChanged) {
668
- ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
669
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths += oldWrapGroupDimension.childWidth || 0;
670
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights += oldWrapGroupDimension.childHeight || 0;
671
- this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] = oldWrapGroupDimension;
672
- }
673
- }
674
- }
675
- calculateDimensions() {
676
- const scrollElement = this.getScrollElement();
677
- const maxCalculatedScrollBarSize = 25; // Note: Formula to auto-calculate doesn't work for ParentScroll, so we default to this if not set by consuming application
678
- this.calculatedScrollbarHeight = Math.max(Math.min(scrollElement.offsetHeight - scrollElement.clientHeight, maxCalculatedScrollBarSize), this.calculatedScrollbarHeight);
679
- this.calculatedScrollbarWidth = Math.max(Math.min(scrollElement.offsetWidth - scrollElement.clientWidth, maxCalculatedScrollBarSize), this.calculatedScrollbarWidth);
680
- let viewportWidth = scrollElement.offsetWidth - (this.scrollbarWidth || this.calculatedScrollbarWidth || (this.horizontal ? 0 : maxCalculatedScrollBarSize));
681
- let viewportHeight = scrollElement.offsetHeight - (this.scrollbarHeight || this.calculatedScrollbarHeight || (this.horizontal ? maxCalculatedScrollBarSize : 0));
682
- const content = (this.containerElementRef && this.containerElementRef.nativeElement) || this.contentElementRef.nativeElement;
683
- const itemsPerWrapGroup = this.countItemsPerWrapGroup();
684
- let wrapGroupsPerPage;
685
- let defaultChildWidth;
686
- let defaultChildHeight;
687
- if (this.isAngularUniversalSSR) {
688
- viewportWidth = this.ssrViewportWidth;
689
- viewportHeight = this.ssrViewportHeight;
690
- defaultChildWidth = this.ssrChildWidth;
691
- defaultChildHeight = this.ssrChildHeight;
692
- const itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
693
- const itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
694
- wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
695
- }
696
- else if (!this.enableUnequalChildrenSizes) {
697
- if (content.children.length > 0) {
698
- if (!this.childWidth || !this.childHeight) {
699
- if (!this.minMeasuredChildWidth && viewportWidth > 0) {
700
- this.minMeasuredChildWidth = viewportWidth;
701
- }
702
- if (!this.minMeasuredChildHeight && viewportHeight > 0) {
703
- this.minMeasuredChildHeight = viewportHeight;
704
- }
705
- }
706
- const child = content.children[0];
707
- const clientRect = this.getElementSize(child);
708
- this.minMeasuredChildWidth = Math.min(this.minMeasuredChildWidth, clientRect.width);
709
- this.minMeasuredChildHeight = Math.min(this.minMeasuredChildHeight, clientRect.height);
710
- // Added for getting the child height (for card view, return all the clientRect object).
711
- if (this._lastChildRect?.height !== clientRect?.height ||
712
- this._lastChildRect?.width !== clientRect?.width) {
713
- this._lastChildRect = clientRect;
714
- this.vsChildRectChange.emit(clientRect);
715
- }
716
- }
717
- defaultChildWidth = this.childWidth || this.minMeasuredChildWidth || viewportWidth;
718
- defaultChildHeight = this.childHeight || this.minMeasuredChildHeight || viewportHeight;
719
- const itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
720
- const itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
721
- wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
722
- }
723
- else {
724
- let scrollOffset = scrollElement[this._scrollType] - (this.previousViewPort ? this.previousViewPort.padding : 0);
725
- let arrayStartIndex = this.previousViewPort.startIndexWithBuffer || 0;
726
- let wrapGroupIndex = Math.ceil(arrayStartIndex / itemsPerWrapGroup);
727
- let maxWidthForWrapGroup = 0;
728
- let maxHeightForWrapGroup = 0;
729
- let sumOfVisibleMaxWidths = 0;
730
- let sumOfVisibleMaxHeights = 0;
731
- wrapGroupsPerPage = 0;
732
- for (let i = 0; i < content.children.length; ++i) {
733
- ++arrayStartIndex;
734
- const child = content.children[i];
735
- const clientRect = this.getElementSize(child);
736
- maxWidthForWrapGroup = Math.max(maxWidthForWrapGroup, clientRect.width);
737
- maxHeightForWrapGroup = Math.max(maxHeightForWrapGroup, clientRect.height);
738
- if (arrayStartIndex % itemsPerWrapGroup === 0) {
739
- const oldValue = this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
740
- if (oldValue) {
741
- --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
742
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -= oldValue.childWidth || 0;
743
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -= oldValue.childHeight || 0;
744
- }
745
- ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
746
- const items = this.items.slice(arrayStartIndex - itemsPerWrapGroup, arrayStartIndex);
747
- this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] = {
748
- childWidth: maxWidthForWrapGroup,
749
- childHeight: maxHeightForWrapGroup,
750
- items: items
751
- };
752
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths += maxWidthForWrapGroup;
753
- this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights += maxHeightForWrapGroup;
754
- if (this.horizontal) {
755
- let maxVisibleWidthForWrapGroup = Math.min(maxWidthForWrapGroup, Math.max(viewportWidth - sumOfVisibleMaxWidths, 0));
756
- if (scrollOffset > 0) {
757
- const scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleWidthForWrapGroup);
758
- maxVisibleWidthForWrapGroup -= scrollOffsetToRemove;
759
- scrollOffset -= scrollOffsetToRemove;
760
- }
761
- sumOfVisibleMaxWidths += maxVisibleWidthForWrapGroup;
762
- if (maxVisibleWidthForWrapGroup > 0 && viewportWidth >= sumOfVisibleMaxWidths) {
763
- ++wrapGroupsPerPage;
764
- }
765
- }
766
- else {
767
- let maxVisibleHeightForWrapGroup = Math.min(maxHeightForWrapGroup, Math.max(viewportHeight - sumOfVisibleMaxHeights, 0));
768
- if (scrollOffset > 0) {
769
- const scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleHeightForWrapGroup);
770
- maxVisibleHeightForWrapGroup -= scrollOffsetToRemove;
771
- scrollOffset -= scrollOffsetToRemove;
772
- }
773
- sumOfVisibleMaxHeights += maxVisibleHeightForWrapGroup;
774
- if (maxVisibleHeightForWrapGroup > 0 && viewportHeight >= sumOfVisibleMaxHeights) {
775
- ++wrapGroupsPerPage;
776
- }
777
- }
778
- ++wrapGroupIndex;
779
- maxWidthForWrapGroup = 0;
780
- maxHeightForWrapGroup = 0;
781
- }
782
- }
783
- const averageChildWidth = this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths / this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
784
- const averageChildHeight = this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights / this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
785
- defaultChildWidth = this.childWidth || averageChildWidth || viewportWidth;
786
- defaultChildHeight = this.childHeight || averageChildHeight || viewportHeight;
787
- if (this.horizontal) {
788
- if (viewportWidth > sumOfVisibleMaxWidths) {
789
- wrapGroupsPerPage += Math.ceil((viewportWidth - sumOfVisibleMaxWidths) / defaultChildWidth);
790
- }
791
- }
792
- else {
793
- if (viewportHeight > sumOfVisibleMaxHeights) {
794
- wrapGroupsPerPage += Math.ceil((viewportHeight - sumOfVisibleMaxHeights) / defaultChildHeight);
795
- }
796
- }
797
- }
798
- const itemCount = this.items.length;
799
- const itemsPerPage = itemsPerWrapGroup * wrapGroupsPerPage;
800
- const pageCount_fractional = itemCount / itemsPerPage;
801
- const numberOfWrapGroups = Math.ceil(itemCount / itemsPerWrapGroup);
802
- let scrollLength = 0;
803
- const defaultScrollLengthPerWrapGroup = this.horizontal ? defaultChildWidth : defaultChildHeight;
804
- if (this.enableUnequalChildrenSizes) {
805
- let numUnknownChildSizes = 0;
806
- for (let i = 0; i < numberOfWrapGroups; ++i) {
807
- const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
808
- if (childSize) {
809
- scrollLength += childSize;
810
- }
811
- else {
812
- ++numUnknownChildSizes;
813
- }
814
- }
815
- scrollLength += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
816
- }
817
- else {
818
- scrollLength = numberOfWrapGroups * defaultScrollLengthPerWrapGroup;
819
- }
820
- if (this.headerElementRef) {
821
- scrollLength += this.headerElementRef.nativeElement.clientHeight;
822
- }
823
- const viewportLength = this.horizontal ? viewportWidth : viewportHeight;
824
- const maxScrollPosition = Math.max(scrollLength - viewportLength, 0);
825
- return {
826
- childHeight: defaultChildHeight,
827
- childWidth: defaultChildWidth,
828
- itemCount: itemCount,
829
- itemsPerPage: itemsPerPage,
830
- itemsPerWrapGroup: itemsPerWrapGroup,
831
- maxScrollPosition: maxScrollPosition,
832
- pageCount_fractional: pageCount_fractional,
833
- scrollLength: scrollLength,
834
- viewportLength: viewportLength,
835
- wrapGroupsPerPage: wrapGroupsPerPage,
836
- };
837
- }
838
- calculatePadding(arrayStartIndexWithBuffer, dimensions) {
839
- if (dimensions.itemCount === 0) {
840
- return 0;
841
- }
842
- const defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
843
- const startingWrapGroupIndex = Math.floor(arrayStartIndexWithBuffer / dimensions.itemsPerWrapGroup) || 0;
844
- if (!this.enableUnequalChildrenSizes) {
845
- return defaultScrollLengthPerWrapGroup * startingWrapGroupIndex;
846
- }
847
- let numUnknownChildSizes = 0;
848
- let result = 0;
849
- for (let i = 0; i < startingWrapGroupIndex; ++i) {
850
- const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
851
- if (childSize) {
852
- result += childSize;
853
- }
854
- else {
855
- ++numUnknownChildSizes;
856
- }
857
- }
858
- result += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
859
- return result;
860
- }
861
- calculatePageInfo(scrollPosition, dimensions) {
862
- let scrollPercentage = 0;
863
- if (this.enableUnequalChildrenSizes) {
864
- const numberOfWrapGroups = Math.ceil(dimensions.itemCount / dimensions.itemsPerWrapGroup);
865
- let totalScrolledLength = 0;
866
- const defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
867
- for (let i = 0; i < numberOfWrapGroups; ++i) {
868
- const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
869
- if (childSize) {
870
- totalScrolledLength += childSize;
871
- }
872
- else {
873
- totalScrolledLength += defaultScrollLengthPerWrapGroup;
874
- }
875
- if (scrollPosition < totalScrolledLength) {
876
- scrollPercentage = i / numberOfWrapGroups;
877
- break;
878
- }
879
- }
880
- }
881
- else {
882
- scrollPercentage = scrollPosition / dimensions.scrollLength;
883
- }
884
- const startingArrayIndex_fractional = Math.min(Math.max(scrollPercentage * dimensions.pageCount_fractional, 0), dimensions.pageCount_fractional) * dimensions.itemsPerPage;
885
- const maxStart = dimensions.itemCount - dimensions.itemsPerPage - 1;
886
- let arrayStartIndex = Math.min(Math.floor(startingArrayIndex_fractional), maxStart);
887
- arrayStartIndex -= arrayStartIndex % dimensions.itemsPerWrapGroup; // round down to start of wrapGroup
888
- if (this.stripedTable) {
889
- const bufferBoundary = 2 * dimensions.itemsPerWrapGroup;
890
- if (arrayStartIndex % bufferBoundary !== 0) {
891
- arrayStartIndex = Math.max(arrayStartIndex - arrayStartIndex % bufferBoundary, 0);
892
- }
893
- }
894
- let arrayEndIndex = Math.ceil(startingArrayIndex_fractional) + dimensions.itemsPerPage - 1;
895
- const endIndexWithinWrapGroup = (arrayEndIndex + 1) % dimensions.itemsPerWrapGroup;
896
- if (endIndexWithinWrapGroup > 0) {
897
- arrayEndIndex += dimensions.itemsPerWrapGroup - endIndexWithinWrapGroup; // round up to end of wrapGroup
898
- }
899
- if (isNaN(arrayStartIndex)) {
900
- arrayStartIndex = 0;
901
- }
902
- if (isNaN(arrayEndIndex)) {
903
- arrayEndIndex = 0;
904
- }
905
- arrayStartIndex = Math.min(Math.max(arrayStartIndex, 0), dimensions.itemCount - 1);
906
- arrayEndIndex = Math.min(Math.max(arrayEndIndex, 0), dimensions.itemCount - 1);
907
- const bufferSize = this.bufferAmount * dimensions.itemsPerWrapGroup;
908
- const startIndexWithBuffer = Math.min(Math.max(arrayStartIndex - bufferSize, 0), dimensions.itemCount - 1);
909
- const endIndexWithBuffer = Math.min(Math.max(arrayEndIndex + bufferSize, 0), dimensions.itemCount - 1);
910
- return {
911
- startIndex: arrayStartIndex,
912
- endIndex: arrayEndIndex,
913
- startIndexWithBuffer: startIndexWithBuffer,
914
- endIndexWithBuffer: endIndexWithBuffer,
915
- scrollStartPosition: scrollPosition,
916
- scrollEndPosition: scrollPosition + dimensions.viewportLength,
917
- maxScrollPosition: dimensions.maxScrollPosition
918
- };
919
- }
920
- calculateViewport() {
921
- const dimensions = this.calculateDimensions();
922
- const offset = this.getElementsOffset();
923
- let scrollStartPosition = this.getScrollStartPosition();
924
- if (scrollStartPosition > (dimensions.scrollLength + offset) && !(this.parentScroll instanceof Window)) {
925
- scrollStartPosition = dimensions.scrollLength;
926
- }
927
- else {
928
- scrollStartPosition -= offset;
929
- }
930
- scrollStartPosition = Math.max(0, scrollStartPosition);
931
- const pageInfo = this.calculatePageInfo(scrollStartPosition, dimensions);
932
- const newPadding = this.calculatePadding(pageInfo.startIndexWithBuffer, dimensions);
933
- const newScrollLength = dimensions.scrollLength;
934
- return {
935
- startIndex: pageInfo.startIndex,
936
- endIndex: pageInfo.endIndex,
937
- startIndexWithBuffer: pageInfo.startIndexWithBuffer,
938
- endIndexWithBuffer: pageInfo.endIndexWithBuffer,
939
- padding: Math.round(newPadding),
940
- scrollLength: Math.round(newScrollLength),
941
- scrollStartPosition: pageInfo.scrollStartPosition,
942
- scrollEndPosition: pageInfo.scrollEndPosition,
943
- maxScrollPosition: pageInfo.maxScrollPosition
944
- };
945
- }
946
- }
947
- VirtualScrollerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }, { token: 'virtual-scroller-default-options', optional: true }], target: i0.ɵɵFactoryTarget.Component });
1
+ import { Component, ContentChild, ElementRef, EventEmitter, Inject, Input, NgModule, Optional, Output, ViewChild, } from '@angular/core';
2
+ import { PLATFORM_ID } from '@angular/core';
3
+ import { isPlatformServer } from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as tween from '@tweenjs/tween.js';
6
+ import * as i0 from "@angular/core";
7
+ export function VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY() {
8
+ return {
9
+ checkResizeInterval: 1000,
10
+ modifyOverflowStyleOfParentScroll: true,
11
+ resizeBypassRefreshThreshold: 5,
12
+ scrollAnimationTime: 750,
13
+ scrollDebounceTime: 0,
14
+ scrollThrottlingTime: 0,
15
+ stripedTable: false
16
+ };
17
+ }
18
+ export class VirtualScrollerComponent {
19
+ constructor(element, renderer, zone, changeDetectorRef, platformId, options) {
20
+ this.element = element;
21
+ this.renderer = renderer;
22
+ this.zone = zone;
23
+ this.changeDetectorRef = changeDetectorRef;
24
+ this.window = window;
25
+ this._disable = false;
26
+ this.executeRefreshOutsideAngularZone = false;
27
+ this._enableUnequalChildrenSizes = false;
28
+ this.RTL = false;
29
+ this.useMarginInsteadOfTranslate = false;
30
+ this.ssrViewportWidth = 1920;
31
+ this.ssrViewportHeight = 1080;
32
+ this._items = [];
33
+ this.compareItems = (item1, item2) => item1 === item2;
34
+ this.vsChildRectChange = new EventEmitter();
35
+ this.vsUpdate = new EventEmitter();
36
+ this.vsChange = new EventEmitter();
37
+ this.vsStart = new EventEmitter();
38
+ this.vsEnd = new EventEmitter();
39
+ this.calculatedScrollbarWidth = 0;
40
+ this.calculatedScrollbarHeight = 0;
41
+ this.padding = 0;
42
+ this.previousViewPort = {};
43
+ this.cachedPageSize = 0;
44
+ this.previousScrollNumberElements = 0;
45
+ this.isAngularUniversalSSR = isPlatformServer(platformId);
46
+ const defaultOptions = VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY();
47
+ this.checkResizeInterval = options?.checkResizeInterval || defaultOptions.checkResizeInterval;
48
+ this.modifyOverflowStyleOfParentScroll = options?.modifyOverflowStyleOfParentScroll || defaultOptions.modifyOverflowStyleOfParentScroll;
49
+ this.resizeBypassRefreshThreshold = options?.resizeBypassRefreshThreshold || defaultOptions.resizeBypassRefreshThreshold;
50
+ this.scrollAnimationTime = options?.scrollAnimationTime || defaultOptions.scrollAnimationTime;
51
+ this.scrollDebounceTime = options?.scrollDebounceTime || defaultOptions.scrollDebounceTime;
52
+ this.scrollThrottlingTime = options?.scrollThrottlingTime || defaultOptions.scrollThrottlingTime;
53
+ this.scrollbarHeight = options?.scrollbarHeight || defaultOptions.scrollbarHeight;
54
+ this.scrollbarWidth = options?.scrollbarWidth || defaultOptions.scrollbarWidth;
55
+ this.stripedTable = options?.stripedTable || defaultOptions.stripedTable;
56
+ this.horizontal = false;
57
+ this.resetWrapGroupDimensions();
58
+ }
59
+ get viewPortInfo() {
60
+ const pageInfo = this.previousViewPort || {};
61
+ return {
62
+ startIndex: pageInfo.startIndex || 0,
63
+ endIndex: pageInfo.endIndex || 0,
64
+ scrollStartPosition: pageInfo.scrollStartPosition || 0,
65
+ scrollEndPosition: pageInfo.scrollEndPosition || 0,
66
+ scrollDirection: pageInfo.scrollDirection || 'forward',
67
+ maxScrollPosition: pageInfo.maxScrollPosition || 0,
68
+ startIndexWithBuffer: pageInfo.startIndexWithBuffer || 0,
69
+ endIndexWithBuffer: pageInfo.endIndexWithBuffer || 0,
70
+ };
71
+ }
72
+ get disable() {
73
+ return this._disable;
74
+ }
75
+ set disable(value) {
76
+ if (this._disable === value) {
77
+ return;
78
+ }
79
+ this._disable = value;
80
+ if (this._disable) {
81
+ this.removeScrollEventHandlers();
82
+ }
83
+ else {
84
+ this.addScrollEventHandlers();
85
+ }
86
+ }
87
+ get enableUnequalChildrenSizes() {
88
+ return this._enableUnequalChildrenSizes;
89
+ }
90
+ set enableUnequalChildrenSizes(value) {
91
+ if (this._enableUnequalChildrenSizes === value) {
92
+ return;
93
+ }
94
+ this._enableUnequalChildrenSizes = value;
95
+ this.minMeasuredChildWidth = undefined;
96
+ this.minMeasuredChildHeight = undefined;
97
+ }
98
+ get bufferAmount() {
99
+ if (typeof (this._bufferAmount) === 'number' && this._bufferAmount > 0) {
100
+ return this._bufferAmount;
101
+ }
102
+ else {
103
+ return this.enableUnequalChildrenSizes ? 5 : 1;
104
+ }
105
+ }
106
+ set bufferAmount(value) {
107
+ this._bufferAmount = value;
108
+ }
109
+ get scrollThrottlingTime() {
110
+ return this._scrollThrottlingTime;
111
+ }
112
+ set scrollThrottlingTime(value) {
113
+ this._scrollThrottlingTime = value;
114
+ this.updateOnScrollFunction();
115
+ }
116
+ get scrollDebounceTime() {
117
+ return this._scrollDebounceTime;
118
+ }
119
+ set scrollDebounceTime(value) {
120
+ this._scrollDebounceTime = value;
121
+ this.updateOnScrollFunction();
122
+ }
123
+ updateOnScrollFunction() {
124
+ if (this.scrollDebounceTime) {
125
+ this.onScroll = this.debounce(() => {
126
+ this.refresh_internal(false);
127
+ }, this.scrollDebounceTime);
128
+ }
129
+ else if (this.scrollThrottlingTime) {
130
+ this.onScroll = this.throttleTrailing(() => {
131
+ this.refresh_internal(false);
132
+ }, this.scrollThrottlingTime);
133
+ }
134
+ else {
135
+ this.onScroll = () => {
136
+ this.refresh_internal(false);
137
+ };
138
+ }
139
+ }
140
+ get checkResizeInterval() {
141
+ return this._checkResizeInterval;
142
+ }
143
+ set checkResizeInterval(value) {
144
+ if (this._checkResizeInterval === value) {
145
+ return;
146
+ }
147
+ this._checkResizeInterval = value;
148
+ this.addScrollEventHandlers();
149
+ }
150
+ get items() {
151
+ return this._items;
152
+ }
153
+ set items(value) {
154
+ if (value === this._items) {
155
+ return;
156
+ }
157
+ this._items = value || [];
158
+ this.refresh_internal(true);
159
+ }
160
+ get horizontal() {
161
+ return this._horizontal;
162
+ }
163
+ set horizontal(value) {
164
+ this._horizontal = value;
165
+ this.updateDirection();
166
+ }
167
+ revertParentOverscroll() {
168
+ const scrollElement = this.getScrollElement();
169
+ if (scrollElement && this.oldParentScrollOverflow) {
170
+ scrollElement.style['overflow-y'] = this.oldParentScrollOverflow.y;
171
+ scrollElement.style['overflow-x'] = this.oldParentScrollOverflow.x;
172
+ }
173
+ this.oldParentScrollOverflow = undefined;
174
+ }
175
+ get parentScroll() {
176
+ return this._parentScroll;
177
+ }
178
+ set parentScroll(value) {
179
+ if (this._parentScroll === value) {
180
+ return;
181
+ }
182
+ this.revertParentOverscroll();
183
+ this._parentScroll = value;
184
+ this.addScrollEventHandlers();
185
+ const scrollElement = this.getScrollElement();
186
+ if (this.modifyOverflowStyleOfParentScroll && scrollElement !== this.element.nativeElement) {
187
+ this.oldParentScrollOverflow = { x: scrollElement.style['overflow-x'], y: scrollElement.style['overflow-y'] };
188
+ scrollElement.style['overflow-y'] = this.horizontal ? 'visible' : 'auto';
189
+ scrollElement.style['overflow-x'] = this.horizontal ? 'auto' : 'visible';
190
+ }
191
+ }
192
+ ngOnInit() {
193
+ this.addScrollEventHandlers();
194
+ }
195
+ ngOnDestroy() {
196
+ this.removeScrollEventHandlers();
197
+ this.revertParentOverscroll();
198
+ }
199
+ ngOnChanges(changes) {
200
+ const indexLengthChanged = this.cachedItemsLength !== this.items.length;
201
+ this.cachedItemsLength = this.items.length;
202
+ const firstRun = !changes.items || !changes.items.previousValue || changes.items.previousValue.length === 0;
203
+ this.refresh_internal(indexLengthChanged || firstRun);
204
+ }
205
+ ngDoCheck() {
206
+ if (this.cachedItemsLength !== this.items.length) {
207
+ this.cachedItemsLength = this.items.length;
208
+ this.refresh_internal(true);
209
+ return;
210
+ }
211
+ if (this.previousViewPort && this.viewPortItems && this.viewPortItems.length > 0) {
212
+ let itemsArrayChanged = false;
213
+ for (let i = 0; i < this.viewPortItems.length; ++i) {
214
+ if (!this.compareItems(this.items[this.previousViewPort.startIndexWithBuffer + i], this.viewPortItems[i])) {
215
+ itemsArrayChanged = true;
216
+ break;
217
+ }
218
+ }
219
+ if (itemsArrayChanged) {
220
+ this.refresh_internal(true);
221
+ }
222
+ }
223
+ }
224
+ refresh() {
225
+ this.refresh_internal(true);
226
+ }
227
+ invalidateAllCachedMeasurements() {
228
+ this.wrapGroupDimensions = {
229
+ maxChildSizePerWrapGroup: [],
230
+ numberOfKnownWrapGroupChildSizes: 0,
231
+ sumOfKnownWrapGroupChildWidths: 0,
232
+ sumOfKnownWrapGroupChildHeights: 0
233
+ };
234
+ this.minMeasuredChildWidth = undefined;
235
+ this.minMeasuredChildHeight = undefined;
236
+ this.refresh_internal(false);
237
+ }
238
+ invalidateCachedMeasurementForItem(item) {
239
+ if (this.enableUnequalChildrenSizes) {
240
+ const index = this.items && this.items.indexOf(item);
241
+ if (index >= 0) {
242
+ this.invalidateCachedMeasurementAtIndex(index);
243
+ }
244
+ }
245
+ else {
246
+ this.minMeasuredChildWidth = undefined;
247
+ this.minMeasuredChildHeight = undefined;
248
+ }
249
+ this.refresh_internal(false);
250
+ }
251
+ invalidateCachedMeasurementAtIndex(index) {
252
+ if (this.enableUnequalChildrenSizes) {
253
+ const cachedMeasurement = this.wrapGroupDimensions.maxChildSizePerWrapGroup[index];
254
+ if (cachedMeasurement) {
255
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[index] = undefined;
256
+ --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
257
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -= cachedMeasurement.childWidth || 0;
258
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -= cachedMeasurement.childHeight || 0;
259
+ }
260
+ }
261
+ else {
262
+ this.minMeasuredChildWidth = undefined;
263
+ this.minMeasuredChildHeight = undefined;
264
+ }
265
+ this.refresh_internal(false);
266
+ }
267
+ scrollInto(item, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
268
+ const index = this.items.indexOf(item);
269
+ if (index === -1) {
270
+ return;
271
+ }
272
+ this.scrollToIndex(index, alignToBeginning, additionalOffset, animationMilliseconds, animationCompletedCallback);
273
+ }
274
+ scrollToIndex(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
275
+ let maxRetries = 5;
276
+ const retryIfNeeded = () => {
277
+ --maxRetries;
278
+ if (maxRetries <= 0) {
279
+ if (animationCompletedCallback) {
280
+ animationCompletedCallback();
281
+ }
282
+ return;
283
+ }
284
+ const dimensions = this.calculateDimensions();
285
+ const desiredStartIndex = Math.min(Math.max(index, 0), dimensions.itemCount - 1);
286
+ if (this.previousViewPort.startIndex === desiredStartIndex) {
287
+ if (animationCompletedCallback) {
288
+ animationCompletedCallback();
289
+ }
290
+ return;
291
+ }
292
+ this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, 0, retryIfNeeded);
293
+ };
294
+ this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, animationMilliseconds, retryIfNeeded);
295
+ }
296
+ scrollToIndex_internal(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
297
+ animationMilliseconds = animationMilliseconds === undefined ? this.scrollAnimationTime : animationMilliseconds;
298
+ const dimensions = this.calculateDimensions();
299
+ let scroll = this.calculatePadding(index, dimensions) + additionalOffset;
300
+ if (!alignToBeginning) {
301
+ scroll -= dimensions.wrapGroupsPerPage * dimensions[this._childScrollDim];
302
+ }
303
+ this.scrollToPosition(scroll, animationMilliseconds, animationCompletedCallback);
304
+ }
305
+ scrollToPosition(scrollPosition, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
306
+ scrollPosition += this.getElementsOffset();
307
+ animationMilliseconds = animationMilliseconds === undefined ? this.scrollAnimationTime : animationMilliseconds;
308
+ const scrollElement = this.getScrollElement();
309
+ let animationRequest;
310
+ if (this.currentTween) {
311
+ this.currentTween.stop();
312
+ this.currentTween = undefined;
313
+ }
314
+ if (!animationMilliseconds) {
315
+ this.renderer.setProperty(scrollElement, this._scrollType, scrollPosition);
316
+ this.refresh_internal(false, animationCompletedCallback);
317
+ return;
318
+ }
319
+ const tweenConfigObj = { scrollPosition: scrollElement[this._scrollType] };
320
+ const newTween = new tween.Tween(tweenConfigObj)
321
+ .to({ scrollPosition }, animationMilliseconds)
322
+ .easing(tween.Easing.Quadratic.Out)
323
+ .onUpdate((data) => {
324
+ if (isNaN(data.scrollPosition)) {
325
+ return;
326
+ }
327
+ this.renderer.setProperty(scrollElement, this._scrollType, data.scrollPosition);
328
+ this.refresh_internal(false);
329
+ })
330
+ .onStop(() => {
331
+ cancelAnimationFrame(animationRequest);
332
+ })
333
+ .start();
334
+ const animate = (time) => {
335
+ if (!newTween["isPlaying"]()) {
336
+ return;
337
+ }
338
+ newTween.update(time);
339
+ if (tweenConfigObj.scrollPosition === scrollPosition) {
340
+ this.refresh_internal(false, animationCompletedCallback);
341
+ return;
342
+ }
343
+ this.zone.runOutsideAngular(() => {
344
+ animationRequest = requestAnimationFrame(animate);
345
+ });
346
+ };
347
+ animate();
348
+ this.currentTween = newTween;
349
+ }
350
+ getElementSize(element) {
351
+ const result = element.getBoundingClientRect();
352
+ const styles = getComputedStyle(element);
353
+ const marginTop = parseInt(styles['margin-top'], 10) || 0;
354
+ const marginBottom = parseInt(styles['margin-bottom'], 10) || 0;
355
+ const marginLeft = parseInt(styles['margin-left'], 10) || 0;
356
+ const marginRight = parseInt(styles['margin-right'], 10) || 0;
357
+ return {
358
+ top: result.top + marginTop,
359
+ bottom: result.bottom + marginBottom,
360
+ left: result.left + marginLeft,
361
+ right: result.right + marginRight,
362
+ width: result.width + marginLeft + marginRight,
363
+ height: result.height + marginTop + marginBottom
364
+ };
365
+ }
366
+ checkScrollElementResized() {
367
+ const boundingRect = this.getElementSize(this.getScrollElement());
368
+ let sizeChanged;
369
+ if (!this.previousScrollBoundingRect) {
370
+ sizeChanged = true;
371
+ }
372
+ else {
373
+ const widthChange = Math.abs(boundingRect.width - this.previousScrollBoundingRect.width);
374
+ const heightChange = Math.abs(boundingRect.height - this.previousScrollBoundingRect.height);
375
+ sizeChanged = widthChange > this.resizeBypassRefreshThreshold || heightChange > this.resizeBypassRefreshThreshold;
376
+ }
377
+ if (sizeChanged) {
378
+ this.previousScrollBoundingRect = boundingRect;
379
+ if (boundingRect.width > 0 && boundingRect.height > 0) {
380
+ this.refresh_internal(false);
381
+ }
382
+ }
383
+ }
384
+ updateDirection() {
385
+ if (this.horizontal) {
386
+ this._childScrollDim = 'childWidth';
387
+ this._invisiblePaddingProperty = 'scaleX';
388
+ this._marginDir = 'margin-left';
389
+ this._offsetType = 'offsetLeft';
390
+ this._pageOffsetType = 'pageXOffset';
391
+ this._scrollType = 'scrollLeft';
392
+ this._translateDir = 'translateX';
393
+ }
394
+ else {
395
+ this._childScrollDim = 'childHeight';
396
+ this._invisiblePaddingProperty = 'scaleY';
397
+ this._marginDir = 'margin-top';
398
+ this._offsetType = 'offsetTop';
399
+ this._pageOffsetType = 'pageYOffset';
400
+ this._scrollType = 'scrollTop';
401
+ this._translateDir = 'translateY';
402
+ }
403
+ }
404
+ debounce(func, wait, ...args) {
405
+ const throttled = this.throttleTrailing(func, wait);
406
+ const result = function () {
407
+ throttled['cancel']();
408
+ throttled.apply(this, args);
409
+ };
410
+ result['cancel'] = function () {
411
+ throttled['cancel']();
412
+ };
413
+ return result;
414
+ }
415
+ throttleTrailing(func, wait, ...args) {
416
+ let timeout = undefined;
417
+ let _arguments = args;
418
+ const result = function () {
419
+ const _this = this;
420
+ _arguments = args;
421
+ if (timeout) {
422
+ return;
423
+ }
424
+ if (wait <= 0) {
425
+ func.apply(_this, _arguments);
426
+ }
427
+ else {
428
+ timeout = setTimeout(function () {
429
+ timeout = undefined;
430
+ func.apply(_this, _arguments);
431
+ }, wait);
432
+ }
433
+ };
434
+ result['cancel'] = function () {
435
+ if (timeout) {
436
+ clearTimeout(timeout);
437
+ timeout = undefined;
438
+ }
439
+ };
440
+ return result;
441
+ }
442
+ refresh_internal(itemsArrayModified, refreshCompletedCallback = undefined, maxRunTimes = 2) {
443
+ //note: maxRunTimes is to force it to keep recalculating if the previous iteration caused a re-render (different sliced items in viewport or scrollPosition changed).
444
+ //The default of 2x max will probably be accurate enough without causing too large a performance bottleneck
445
+ //The code would typically quit out on the 2nd iteration anyways. The main time it'd think more than 2 runs would be necessary would be for vastly different sized child items or if this is the 1st time the items array was initialized.
446
+ //Without maxRunTimes, If the user is actively scrolling this code would become an infinite loop until they stopped scrolling. This would be okay, except each scroll event would start an additional infinte loop. We want to short-circuit it to prevent this.
447
+ if (itemsArrayModified && this.previousViewPort && this.previousViewPort.scrollStartPosition > 0) {
448
+ //if items were prepended, scroll forward to keep same items visible
449
+ const oldViewPort = this.previousViewPort;
450
+ const oldViewPortItems = this.viewPortItems;
451
+ const oldRefreshCompletedCallback = refreshCompletedCallback;
452
+ refreshCompletedCallback = () => {
453
+ const scrollLengthDelta = this.previousViewPort.scrollLength - oldViewPort.scrollLength;
454
+ if (scrollLengthDelta > 0 && this.viewPortItems) {
455
+ const oldStartItem = oldViewPortItems[0];
456
+ const oldStartItemIndex = this.items.findIndex(x => this.compareItems(oldStartItem, x));
457
+ if (oldStartItemIndex > this.previousViewPort.startIndexWithBuffer) {
458
+ let itemOrderChanged = false;
459
+ for (let i = 1; i < this.viewPortItems.length; ++i) {
460
+ if (!this.compareItems(this.items[oldStartItemIndex + i], oldViewPortItems[i])) {
461
+ itemOrderChanged = true;
462
+ break;
463
+ }
464
+ }
465
+ if (!itemOrderChanged) {
466
+ this.scrollToPosition(this.previousViewPort.scrollStartPosition + scrollLengthDelta, 0, oldRefreshCompletedCallback);
467
+ return;
468
+ }
469
+ }
470
+ }
471
+ if (oldRefreshCompletedCallback) {
472
+ oldRefreshCompletedCallback();
473
+ }
474
+ };
475
+ }
476
+ this.zone.runOutsideAngular(() => {
477
+ requestAnimationFrame(() => {
478
+ if (itemsArrayModified) {
479
+ this.resetWrapGroupDimensions();
480
+ }
481
+ const viewport = this.calculateViewport();
482
+ const startChanged = itemsArrayModified || viewport.startIndex !== this.previousViewPort.startIndex;
483
+ const endChanged = itemsArrayModified || viewport.endIndex !== this.previousViewPort.endIndex;
484
+ const scrollLengthChanged = viewport.scrollLength !== this.previousViewPort.scrollLength;
485
+ const paddingChanged = viewport.padding !== this.previousViewPort.padding;
486
+ const scrollPositionChanged = viewport.scrollStartPosition !== this.previousViewPort.scrollStartPosition || viewport.scrollEndPosition !== this.previousViewPort.scrollEndPosition || viewport.maxScrollPosition !== this.previousViewPort.maxScrollPosition;
487
+ const scrollDirection = this.previousViewPort.endIndex <= viewport.endIndex ? 'forward' : 'backward';
488
+ this.previousViewPort = viewport;
489
+ if (scrollLengthChanged) {
490
+ this.renderer.setStyle(this.invisiblePaddingElementRef.nativeElement, 'transform', `${this._invisiblePaddingProperty}(${viewport.scrollLength})`);
491
+ this.renderer.setStyle(this.invisiblePaddingElementRef.nativeElement, 'webkitTransform', `${this._invisiblePaddingProperty}(${viewport.scrollLength})`);
492
+ }
493
+ if (paddingChanged) {
494
+ if (this.useMarginInsteadOfTranslate) {
495
+ this.renderer.setStyle(this.contentElementRef.nativeElement, this._marginDir, `${viewport.padding}px`);
496
+ }
497
+ else {
498
+ this.renderer.setStyle(this.contentElementRef.nativeElement, 'transform', `${this._translateDir}(${viewport.padding}px)`);
499
+ this.renderer.setStyle(this.contentElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${viewport.padding}px)`);
500
+ }
501
+ }
502
+ if (this.headerElementRef) {
503
+ const scrollPosition = this.getScrollElement()[this._scrollType];
504
+ const containerOffset = this.getElementsOffset();
505
+ const offset = Math.max(scrollPosition - viewport.padding - containerOffset + this.headerElementRef.nativeElement.clientHeight, 0);
506
+ this.renderer.setStyle(this.headerElementRef.nativeElement, 'transform', `${this._translateDir}(${offset}px)`);
507
+ this.renderer.setStyle(this.headerElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${offset}px)`);
508
+ }
509
+ const changeEventArg = (startChanged || endChanged) ? {
510
+ startIndex: viewport.startIndex,
511
+ endIndex: viewport.endIndex,
512
+ scrollStartPosition: viewport.scrollStartPosition,
513
+ scrollEndPosition: viewport.scrollEndPosition,
514
+ scrollDirection: scrollDirection,
515
+ startIndexWithBuffer: viewport.startIndexWithBuffer,
516
+ endIndexWithBuffer: viewport.endIndexWithBuffer,
517
+ maxScrollPosition: viewport.maxScrollPosition,
518
+ } : undefined;
519
+ if (startChanged || endChanged || scrollPositionChanged) {
520
+ const handleChanged = () => {
521
+ // update the scroll list to trigger re-render of components in viewport
522
+ this.viewPortItems = viewport.startIndexWithBuffer >= 0 && viewport.endIndexWithBuffer >= 0 ? this.items.slice(viewport.startIndexWithBuffer, viewport.endIndexWithBuffer + 1) : [];
523
+ this.vsUpdate.emit(this.viewPortItems);
524
+ if (startChanged) {
525
+ this.vsStart.emit(changeEventArg);
526
+ }
527
+ if (endChanged) {
528
+ this.vsEnd.emit(changeEventArg);
529
+ }
530
+ if (startChanged || endChanged) {
531
+ this.changeDetectorRef.markForCheck();
532
+ this.vsChange.emit(changeEventArg);
533
+ }
534
+ if (maxRunTimes > 0) {
535
+ this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
536
+ return;
537
+ }
538
+ if (refreshCompletedCallback) {
539
+ refreshCompletedCallback();
540
+ }
541
+ };
542
+ if (this.executeRefreshOutsideAngularZone) {
543
+ handleChanged();
544
+ }
545
+ else {
546
+ this.zone.run(handleChanged);
547
+ }
548
+ }
549
+ else {
550
+ if (maxRunTimes > 0 && (scrollLengthChanged || paddingChanged)) {
551
+ this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
552
+ return;
553
+ }
554
+ if (refreshCompletedCallback) {
555
+ refreshCompletedCallback();
556
+ }
557
+ }
558
+ });
559
+ });
560
+ }
561
+ getScrollElement() {
562
+ return this.parentScroll instanceof Window ? document.scrollingElement || document.documentElement || document.body : this.parentScroll || this.element.nativeElement;
563
+ }
564
+ addScrollEventHandlers() {
565
+ if (this.isAngularUniversalSSR) {
566
+ return;
567
+ }
568
+ const scrollElement = this.getScrollElement();
569
+ this.removeScrollEventHandlers();
570
+ this.zone.runOutsideAngular(() => {
571
+ if (this.parentScroll instanceof Window) {
572
+ this.disposeScrollHandler = this.renderer.listen('window', 'scroll', this.onScroll);
573
+ this.disposeResizeHandler = this.renderer.listen('window', 'resize', this.onScroll);
574
+ }
575
+ else {
576
+ this.disposeScrollHandler = this.renderer.listen(scrollElement, 'scroll', this.onScroll);
577
+ if (this._checkResizeInterval > 0) {
578
+ this.checkScrollElementResizedTimer = setInterval(() => { this.checkScrollElementResized(); }, this._checkResizeInterval);
579
+ }
580
+ }
581
+ });
582
+ }
583
+ removeScrollEventHandlers() {
584
+ if (this.checkScrollElementResizedTimer) {
585
+ clearInterval(this.checkScrollElementResizedTimer);
586
+ }
587
+ if (this.disposeScrollHandler) {
588
+ this.disposeScrollHandler();
589
+ this.disposeScrollHandler = undefined;
590
+ }
591
+ if (this.disposeResizeHandler) {
592
+ this.disposeResizeHandler();
593
+ this.disposeResizeHandler = undefined;
594
+ }
595
+ }
596
+ getElementsOffset() {
597
+ if (this.isAngularUniversalSSR) {
598
+ return 0;
599
+ }
600
+ let offset = 0;
601
+ if (this.containerElementRef && this.containerElementRef.nativeElement) {
602
+ offset += this.containerElementRef.nativeElement[this._offsetType];
603
+ }
604
+ if (this.parentScroll) {
605
+ const scrollElement = this.getScrollElement();
606
+ const elementClientRect = this.getElementSize(this.element.nativeElement);
607
+ const scrollClientRect = this.getElementSize(scrollElement);
608
+ if (this.horizontal) {
609
+ offset += elementClientRect.left - scrollClientRect.left;
610
+ }
611
+ else {
612
+ offset += elementClientRect.top - scrollClientRect.top;
613
+ }
614
+ if (!(this.parentScroll instanceof Window)) {
615
+ offset += scrollElement[this._scrollType];
616
+ }
617
+ }
618
+ return offset;
619
+ }
620
+ countItemsPerWrapGroup() {
621
+ if (this.isAngularUniversalSSR) {
622
+ return Math.round(this.horizontal ? this.ssrViewportHeight / this.ssrChildHeight : this.ssrViewportWidth / this.ssrChildWidth);
623
+ }
624
+ const propertyName = this.horizontal ? 'offsetLeft' : 'offsetTop';
625
+ const children = ((this.containerElementRef && this.containerElementRef.nativeElement) || this.contentElementRef.nativeElement).children;
626
+ const childrenLength = children ? children.length : 0;
627
+ if (childrenLength === 0) {
628
+ return 1;
629
+ }
630
+ const firstOffset = children[0][propertyName];
631
+ let result = 1;
632
+ while (result < childrenLength && firstOffset === children[result][propertyName]) {
633
+ ++result;
634
+ }
635
+ return result;
636
+ }
637
+ getScrollStartPosition() {
638
+ let windowScrollValue = undefined;
639
+ if (this.parentScroll instanceof Window) {
640
+ windowScrollValue = window[this._pageOffsetType];
641
+ }
642
+ return windowScrollValue || this.getScrollElement()[this._scrollType] || 0;
643
+ }
644
+ resetWrapGroupDimensions() {
645
+ const oldWrapGroupDimensions = this.wrapGroupDimensions;
646
+ this.invalidateAllCachedMeasurements();
647
+ if (!this.enableUnequalChildrenSizes || !oldWrapGroupDimensions || oldWrapGroupDimensions.numberOfKnownWrapGroupChildSizes === 0) {
648
+ return;
649
+ }
650
+ const itemsPerWrapGroup = this.countItemsPerWrapGroup();
651
+ for (let wrapGroupIndex = 0; wrapGroupIndex < oldWrapGroupDimensions.maxChildSizePerWrapGroup.length; ++wrapGroupIndex) {
652
+ const oldWrapGroupDimension = oldWrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
653
+ if (!oldWrapGroupDimension || !oldWrapGroupDimension.items || !oldWrapGroupDimension.items.length) {
654
+ continue;
655
+ }
656
+ if (oldWrapGroupDimension.items.length !== itemsPerWrapGroup) {
657
+ return;
658
+ }
659
+ let itemsChanged = false;
660
+ const arrayStartIndex = itemsPerWrapGroup * wrapGroupIndex;
661
+ for (let i = 0; i < itemsPerWrapGroup; ++i) {
662
+ if (!this.compareItems(oldWrapGroupDimension.items[i], this.items[arrayStartIndex + i])) {
663
+ itemsChanged = true;
664
+ break;
665
+ }
666
+ }
667
+ if (!itemsChanged) {
668
+ ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
669
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths += oldWrapGroupDimension.childWidth || 0;
670
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights += oldWrapGroupDimension.childHeight || 0;
671
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] = oldWrapGroupDimension;
672
+ }
673
+ }
674
+ }
675
+ calculateDimensions() {
676
+ const scrollElement = this.getScrollElement();
677
+ const maxCalculatedScrollBarSize = 25; // Note: Formula to auto-calculate doesn't work for ParentScroll, so we default to this if not set by consuming application
678
+ this.calculatedScrollbarHeight = Math.max(Math.min(scrollElement.offsetHeight - scrollElement.clientHeight, maxCalculatedScrollBarSize), this.calculatedScrollbarHeight);
679
+ this.calculatedScrollbarWidth = Math.max(Math.min(scrollElement.offsetWidth - scrollElement.clientWidth, maxCalculatedScrollBarSize), this.calculatedScrollbarWidth);
680
+ let viewportWidth = scrollElement.offsetWidth - (this.scrollbarWidth || this.calculatedScrollbarWidth || (this.horizontal ? 0 : maxCalculatedScrollBarSize));
681
+ let viewportHeight = scrollElement.offsetHeight - (this.scrollbarHeight || this.calculatedScrollbarHeight || (this.horizontal ? maxCalculatedScrollBarSize : 0));
682
+ const content = (this.containerElementRef && this.containerElementRef.nativeElement) || this.contentElementRef.nativeElement;
683
+ const itemsPerWrapGroup = this.countItemsPerWrapGroup();
684
+ let wrapGroupsPerPage;
685
+ let defaultChildWidth;
686
+ let defaultChildHeight;
687
+ if (this.isAngularUniversalSSR) {
688
+ viewportWidth = this.ssrViewportWidth;
689
+ viewportHeight = this.ssrViewportHeight;
690
+ defaultChildWidth = this.ssrChildWidth;
691
+ defaultChildHeight = this.ssrChildHeight;
692
+ const itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
693
+ const itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
694
+ wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
695
+ }
696
+ else if (!this.enableUnequalChildrenSizes) {
697
+ if (content.children.length > 0) {
698
+ if (!this.childWidth || !this.childHeight) {
699
+ if (!this.minMeasuredChildWidth && viewportWidth > 0) {
700
+ this.minMeasuredChildWidth = viewportWidth;
701
+ }
702
+ if (!this.minMeasuredChildHeight && viewportHeight > 0) {
703
+ this.minMeasuredChildHeight = viewportHeight;
704
+ }
705
+ }
706
+ const child = content.children[0];
707
+ const clientRect = this.getElementSize(child);
708
+ this.minMeasuredChildWidth = Math.min(this.minMeasuredChildWidth, clientRect.width);
709
+ this.minMeasuredChildHeight = Math.min(this.minMeasuredChildHeight, clientRect.height);
710
+ // Added for getting the child height (for card view, return all the clientRect object).
711
+ if (this._lastChildRect?.height !== clientRect?.height ||
712
+ this._lastChildRect?.width !== clientRect?.width) {
713
+ this._lastChildRect = clientRect;
714
+ this.vsChildRectChange.emit(clientRect);
715
+ }
716
+ }
717
+ defaultChildWidth = this.childWidth || this.minMeasuredChildWidth || viewportWidth;
718
+ defaultChildHeight = this.childHeight || this.minMeasuredChildHeight || viewportHeight;
719
+ const itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
720
+ const itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
721
+ wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
722
+ }
723
+ else {
724
+ let scrollOffset = scrollElement[this._scrollType] - (this.previousViewPort ? this.previousViewPort.padding : 0);
725
+ let arrayStartIndex = this.previousViewPort.startIndexWithBuffer || 0;
726
+ let wrapGroupIndex = Math.ceil(arrayStartIndex / itemsPerWrapGroup);
727
+ let maxWidthForWrapGroup = 0;
728
+ let maxHeightForWrapGroup = 0;
729
+ let sumOfVisibleMaxWidths = 0;
730
+ let sumOfVisibleMaxHeights = 0;
731
+ wrapGroupsPerPage = 0;
732
+ for (let i = 0; i < content.children.length; ++i) {
733
+ ++arrayStartIndex;
734
+ const child = content.children[i];
735
+ const clientRect = this.getElementSize(child);
736
+ maxWidthForWrapGroup = Math.max(maxWidthForWrapGroup, clientRect.width);
737
+ maxHeightForWrapGroup = Math.max(maxHeightForWrapGroup, clientRect.height);
738
+ if (arrayStartIndex % itemsPerWrapGroup === 0) {
739
+ const oldValue = this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
740
+ if (oldValue) {
741
+ --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
742
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -= oldValue.childWidth || 0;
743
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -= oldValue.childHeight || 0;
744
+ }
745
+ ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
746
+ const items = this.items.slice(arrayStartIndex - itemsPerWrapGroup, arrayStartIndex);
747
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] = {
748
+ childWidth: maxWidthForWrapGroup,
749
+ childHeight: maxHeightForWrapGroup,
750
+ items: items
751
+ };
752
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths += maxWidthForWrapGroup;
753
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights += maxHeightForWrapGroup;
754
+ if (this.horizontal) {
755
+ let maxVisibleWidthForWrapGroup = Math.min(maxWidthForWrapGroup, Math.max(viewportWidth - sumOfVisibleMaxWidths, 0));
756
+ if (scrollOffset > 0) {
757
+ const scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleWidthForWrapGroup);
758
+ maxVisibleWidthForWrapGroup -= scrollOffsetToRemove;
759
+ scrollOffset -= scrollOffsetToRemove;
760
+ }
761
+ sumOfVisibleMaxWidths += maxVisibleWidthForWrapGroup;
762
+ if (maxVisibleWidthForWrapGroup > 0 && viewportWidth >= sumOfVisibleMaxWidths) {
763
+ ++wrapGroupsPerPage;
764
+ }
765
+ }
766
+ else {
767
+ let maxVisibleHeightForWrapGroup = Math.min(maxHeightForWrapGroup, Math.max(viewportHeight - sumOfVisibleMaxHeights, 0));
768
+ if (scrollOffset > 0) {
769
+ const scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleHeightForWrapGroup);
770
+ maxVisibleHeightForWrapGroup -= scrollOffsetToRemove;
771
+ scrollOffset -= scrollOffsetToRemove;
772
+ }
773
+ sumOfVisibleMaxHeights += maxVisibleHeightForWrapGroup;
774
+ if (maxVisibleHeightForWrapGroup > 0 && viewportHeight >= sumOfVisibleMaxHeights) {
775
+ ++wrapGroupsPerPage;
776
+ }
777
+ }
778
+ ++wrapGroupIndex;
779
+ maxWidthForWrapGroup = 0;
780
+ maxHeightForWrapGroup = 0;
781
+ }
782
+ }
783
+ const averageChildWidth = this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths / this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
784
+ const averageChildHeight = this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights / this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
785
+ defaultChildWidth = this.childWidth || averageChildWidth || viewportWidth;
786
+ defaultChildHeight = this.childHeight || averageChildHeight || viewportHeight;
787
+ if (this.horizontal) {
788
+ if (viewportWidth > sumOfVisibleMaxWidths) {
789
+ wrapGroupsPerPage += Math.ceil((viewportWidth - sumOfVisibleMaxWidths) / defaultChildWidth);
790
+ }
791
+ }
792
+ else {
793
+ if (viewportHeight > sumOfVisibleMaxHeights) {
794
+ wrapGroupsPerPage += Math.ceil((viewportHeight - sumOfVisibleMaxHeights) / defaultChildHeight);
795
+ }
796
+ }
797
+ }
798
+ const itemCount = this.items.length;
799
+ const itemsPerPage = itemsPerWrapGroup * wrapGroupsPerPage;
800
+ const pageCount_fractional = itemCount / itemsPerPage;
801
+ const numberOfWrapGroups = Math.ceil(itemCount / itemsPerWrapGroup);
802
+ let scrollLength = 0;
803
+ const defaultScrollLengthPerWrapGroup = this.horizontal ? defaultChildWidth : defaultChildHeight;
804
+ if (this.enableUnequalChildrenSizes) {
805
+ let numUnknownChildSizes = 0;
806
+ for (let i = 0; i < numberOfWrapGroups; ++i) {
807
+ const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
808
+ if (childSize) {
809
+ scrollLength += childSize;
810
+ }
811
+ else {
812
+ ++numUnknownChildSizes;
813
+ }
814
+ }
815
+ scrollLength += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
816
+ }
817
+ else {
818
+ scrollLength = numberOfWrapGroups * defaultScrollLengthPerWrapGroup;
819
+ }
820
+ if (this.headerElementRef) {
821
+ scrollLength += this.headerElementRef.nativeElement.clientHeight;
822
+ }
823
+ const viewportLength = this.horizontal ? viewportWidth : viewportHeight;
824
+ const maxScrollPosition = Math.max(scrollLength - viewportLength, 0);
825
+ return {
826
+ childHeight: defaultChildHeight,
827
+ childWidth: defaultChildWidth,
828
+ itemCount: itemCount,
829
+ itemsPerPage: itemsPerPage,
830
+ itemsPerWrapGroup: itemsPerWrapGroup,
831
+ maxScrollPosition: maxScrollPosition,
832
+ pageCount_fractional: pageCount_fractional,
833
+ scrollLength: scrollLength,
834
+ viewportLength: viewportLength,
835
+ wrapGroupsPerPage: wrapGroupsPerPage,
836
+ };
837
+ }
838
+ calculatePadding(arrayStartIndexWithBuffer, dimensions) {
839
+ if (dimensions.itemCount === 0) {
840
+ return 0;
841
+ }
842
+ const defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
843
+ const startingWrapGroupIndex = Math.floor(arrayStartIndexWithBuffer / dimensions.itemsPerWrapGroup) || 0;
844
+ if (!this.enableUnequalChildrenSizes) {
845
+ return defaultScrollLengthPerWrapGroup * startingWrapGroupIndex;
846
+ }
847
+ let numUnknownChildSizes = 0;
848
+ let result = 0;
849
+ for (let i = 0; i < startingWrapGroupIndex; ++i) {
850
+ const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
851
+ if (childSize) {
852
+ result += childSize;
853
+ }
854
+ else {
855
+ ++numUnknownChildSizes;
856
+ }
857
+ }
858
+ result += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
859
+ return result;
860
+ }
861
+ calculatePageInfo(scrollPosition, dimensions) {
862
+ let scrollPercentage = 0;
863
+ if (this.enableUnequalChildrenSizes) {
864
+ const numberOfWrapGroups = Math.ceil(dimensions.itemCount / dimensions.itemsPerWrapGroup);
865
+ let totalScrolledLength = 0;
866
+ const defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
867
+ for (let i = 0; i < numberOfWrapGroups; ++i) {
868
+ const childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] && this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
869
+ if (childSize) {
870
+ totalScrolledLength += childSize;
871
+ }
872
+ else {
873
+ totalScrolledLength += defaultScrollLengthPerWrapGroup;
874
+ }
875
+ if (scrollPosition < totalScrolledLength) {
876
+ scrollPercentage = i / numberOfWrapGroups;
877
+ break;
878
+ }
879
+ }
880
+ }
881
+ else {
882
+ scrollPercentage = scrollPosition / dimensions.scrollLength;
883
+ }
884
+ const startingArrayIndex_fractional = Math.min(Math.max(scrollPercentage * dimensions.pageCount_fractional, 0), dimensions.pageCount_fractional) * dimensions.itemsPerPage;
885
+ const maxStart = dimensions.itemCount - dimensions.itemsPerPage - 1;
886
+ let arrayStartIndex = Math.min(Math.floor(startingArrayIndex_fractional), maxStart);
887
+ arrayStartIndex -= arrayStartIndex % dimensions.itemsPerWrapGroup; // round down to start of wrapGroup
888
+ if (this.stripedTable) {
889
+ const bufferBoundary = 2 * dimensions.itemsPerWrapGroup;
890
+ if (arrayStartIndex % bufferBoundary !== 0) {
891
+ arrayStartIndex = Math.max(arrayStartIndex - arrayStartIndex % bufferBoundary, 0);
892
+ }
893
+ }
894
+ let arrayEndIndex = Math.ceil(startingArrayIndex_fractional) + dimensions.itemsPerPage - 1;
895
+ const endIndexWithinWrapGroup = (arrayEndIndex + 1) % dimensions.itemsPerWrapGroup;
896
+ if (endIndexWithinWrapGroup > 0) {
897
+ arrayEndIndex += dimensions.itemsPerWrapGroup - endIndexWithinWrapGroup; // round up to end of wrapGroup
898
+ }
899
+ if (isNaN(arrayStartIndex)) {
900
+ arrayStartIndex = 0;
901
+ }
902
+ if (isNaN(arrayEndIndex)) {
903
+ arrayEndIndex = 0;
904
+ }
905
+ arrayStartIndex = Math.min(Math.max(arrayStartIndex, 0), dimensions.itemCount - 1);
906
+ arrayEndIndex = Math.min(Math.max(arrayEndIndex, 0), dimensions.itemCount - 1);
907
+ const bufferSize = this.bufferAmount * dimensions.itemsPerWrapGroup;
908
+ const startIndexWithBuffer = Math.min(Math.max(arrayStartIndex - bufferSize, 0), dimensions.itemCount - 1);
909
+ const endIndexWithBuffer = Math.min(Math.max(arrayEndIndex + bufferSize, 0), dimensions.itemCount - 1);
910
+ return {
911
+ startIndex: arrayStartIndex,
912
+ endIndex: arrayEndIndex,
913
+ startIndexWithBuffer: startIndexWithBuffer,
914
+ endIndexWithBuffer: endIndexWithBuffer,
915
+ scrollStartPosition: scrollPosition,
916
+ scrollEndPosition: scrollPosition + dimensions.viewportLength,
917
+ maxScrollPosition: dimensions.maxScrollPosition
918
+ };
919
+ }
920
+ calculateViewport() {
921
+ const dimensions = this.calculateDimensions();
922
+ const offset = this.getElementsOffset();
923
+ let scrollStartPosition = this.getScrollStartPosition();
924
+ if (scrollStartPosition > (dimensions.scrollLength + offset) && !(this.parentScroll instanceof Window)) {
925
+ scrollStartPosition = dimensions.scrollLength;
926
+ }
927
+ else {
928
+ scrollStartPosition -= offset;
929
+ }
930
+ scrollStartPosition = Math.max(0, scrollStartPosition);
931
+ const pageInfo = this.calculatePageInfo(scrollStartPosition, dimensions);
932
+ const newPadding = this.calculatePadding(pageInfo.startIndexWithBuffer, dimensions);
933
+ const newScrollLength = dimensions.scrollLength;
934
+ return {
935
+ startIndex: pageInfo.startIndex,
936
+ endIndex: pageInfo.endIndex,
937
+ startIndexWithBuffer: pageInfo.startIndexWithBuffer,
938
+ endIndexWithBuffer: pageInfo.endIndexWithBuffer,
939
+ padding: Math.round(newPadding),
940
+ scrollLength: Math.round(newScrollLength),
941
+ scrollStartPosition: pageInfo.scrollStartPosition,
942
+ scrollEndPosition: pageInfo.scrollEndPosition,
943
+ maxScrollPosition: pageInfo.maxScrollPosition
944
+ };
945
+ }
946
+ }
947
+ VirtualScrollerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }, { token: 'virtual-scroller-default-options', optional: true }], target: i0.ɵɵFactoryTarget.Component });
948
948
  VirtualScrollerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.2", type: VirtualScrollerComponent, selector: "virtual-scroller,[virtualScroller]", inputs: { disable: "disable", executeRefreshOutsideAngularZone: "executeRefreshOutsideAngularZone", enableUnequalChildrenSizes: "enableUnequalChildrenSizes", RTL: "RTL", useMarginInsteadOfTranslate: "useMarginInsteadOfTranslate", modifyOverflowStyleOfParentScroll: "modifyOverflowStyleOfParentScroll", stripedTable: "stripedTable", scrollbarWidth: "scrollbarWidth", scrollbarHeight: "scrollbarHeight", childWidth: "childWidth", childHeight: "childHeight", ssrChildWidth: "ssrChildWidth", ssrChildHeight: "ssrChildHeight", ssrViewportWidth: "ssrViewportWidth", ssrViewportHeight: "ssrViewportHeight", bufferAmount: "bufferAmount", scrollAnimationTime: "scrollAnimationTime", resizeBypassRefreshThreshold: "resizeBypassRefreshThreshold", scrollThrottlingTime: "scrollThrottlingTime", scrollDebounceTime: "scrollDebounceTime", checkResizeInterval: "checkResizeInterval", items: "items", compareItems: "compareItems", horizontal: "horizontal", parentScroll: "parentScroll" }, outputs: { vsChildRectChange: "vsChildRectChange", vsUpdate: "vsUpdate", vsChange: "vsChange", vsStart: "vsStart", vsEnd: "vsEnd" }, host: { properties: { "class.horizontal": "horizontal", "class.vertical": "!horizontal", "class.selfScroll": "!parentScroll", "class.rtl": "RTL" } }, queries: [{ propertyName: "headerElementRef", first: true, predicate: ["header"], descendants: true, read: ElementRef }, { propertyName: "containerElementRef", first: true, predicate: ["container"], descendants: true, read: ElementRef }], viewQueries: [{ propertyName: "contentElementRef", first: true, predicate: ["content"], descendants: true, read: ElementRef, static: true }, { propertyName: "invisiblePaddingElementRef", first: true, predicate: ["invisiblePadding"], descendants: true, read: ElementRef, static: true }], exportAs: ["virtualScroller"], usesOnChanges: true, ngImport: i0, template: `
949
949
  <div class="total-padding" #invisiblePadding></div>
950
950
  <div class="scrollable-content" #content>
951
951
  <ng-content></ng-content>
952
952
  </div>
953
- `, isInline: true, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.horizontal.selfScroll.rtl{transform:scaleX(-1)}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}:host.horizontal.rtl .scrollable-content ::ng-deep>*{transform:scaleX(-1)}.total-padding{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0;opacity:0}:host.horizontal .total-padding{height:100%}\n"] });
954
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerComponent, decorators: [{
955
- type: Component,
953
+ `, isInline: true, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.horizontal.selfScroll.rtl{transform:scaleX(-1)}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}:host.horizontal.rtl .scrollable-content ::ng-deep>*{transform:scaleX(-1)}.total-padding{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0;opacity:0}:host.horizontal .total-padding{height:100%}\n"] });
954
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerComponent, decorators: [{
955
+ type: Component,
956
956
  args: [{ selector: 'virtual-scroller,[virtualScroller]', exportAs: 'virtualScroller', template: `
957
957
  <div class="total-padding" #invisiblePadding></div>
958
958
  <div class="scrollable-content" #content>
959
959
  <ng-content></ng-content>
960
960
  </div>
961
- `, host: {
962
- '[class.horizontal]': "horizontal",
963
- '[class.vertical]': "!horizontal",
964
- '[class.selfScroll]': "!parentScroll",
965
- '[class.rtl]': "RTL"
966
- }, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.horizontal.selfScroll.rtl{transform:scaleX(-1)}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}:host.horizontal.rtl .scrollable-content ::ng-deep>*{transform:scaleX(-1)}.total-padding{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0;opacity:0}:host.horizontal .total-padding{height:100%}\n"] }]
967
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
968
- type: Inject,
969
- args: [PLATFORM_ID]
970
- }] }, { type: undefined, decorators: [{
971
- type: Optional
972
- }, {
973
- type: Inject,
974
- args: ['virtual-scroller-default-options']
975
- }] }]; }, propDecorators: { disable: [{
976
- type: Input
977
- }], executeRefreshOutsideAngularZone: [{
978
- type: Input
979
- }], enableUnequalChildrenSizes: [{
980
- type: Input
981
- }], RTL: [{
982
- type: Input
983
- }], useMarginInsteadOfTranslate: [{
984
- type: Input
985
- }], modifyOverflowStyleOfParentScroll: [{
986
- type: Input
987
- }], stripedTable: [{
988
- type: Input
989
- }], scrollbarWidth: [{
990
- type: Input
991
- }], scrollbarHeight: [{
992
- type: Input
993
- }], childWidth: [{
994
- type: Input
995
- }], childHeight: [{
996
- type: Input
997
- }], ssrChildWidth: [{
998
- type: Input
999
- }], ssrChildHeight: [{
1000
- type: Input
1001
- }], ssrViewportWidth: [{
1002
- type: Input
1003
- }], ssrViewportHeight: [{
1004
- type: Input
1005
- }], bufferAmount: [{
1006
- type: Input
1007
- }], scrollAnimationTime: [{
1008
- type: Input
1009
- }], resizeBypassRefreshThreshold: [{
1010
- type: Input
1011
- }], scrollThrottlingTime: [{
1012
- type: Input
1013
- }], scrollDebounceTime: [{
1014
- type: Input
1015
- }], checkResizeInterval: [{
1016
- type: Input
1017
- }], items: [{
1018
- type: Input
1019
- }], compareItems: [{
1020
- type: Input
1021
- }], horizontal: [{
1022
- type: Input
1023
- }], parentScroll: [{
1024
- type: Input
1025
- }], vsChildRectChange: [{
1026
- type: Output
1027
- }], vsUpdate: [{
1028
- type: Output
1029
- }], vsChange: [{
1030
- type: Output
1031
- }], vsStart: [{
1032
- type: Output
1033
- }], vsEnd: [{
1034
- type: Output
1035
- }], contentElementRef: [{
1036
- type: ViewChild,
1037
- args: ['content', { read: ElementRef, static: true }]
1038
- }], invisiblePaddingElementRef: [{
1039
- type: ViewChild,
1040
- args: ['invisiblePadding', { read: ElementRef, static: true }]
1041
- }], headerElementRef: [{
1042
- type: ContentChild,
1043
- args: ['header', { read: ElementRef, static: false }]
1044
- }], containerElementRef: [{
1045
- type: ContentChild,
1046
- args: ['container', { read: ElementRef, static: false }]
1047
- }] } });
1048
- export class VirtualScrollerModule {
1049
- }
1050
- VirtualScrollerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1051
- VirtualScrollerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, declarations: [VirtualScrollerComponent], imports: [CommonModule], exports: [VirtualScrollerComponent] });
1052
- VirtualScrollerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, providers: [
1053
- {
1054
- provide: 'virtual-scroller-default-options',
1055
- useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY
1056
- }
1057
- ], imports: [CommonModule] });
1058
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, decorators: [{
1059
- type: NgModule,
1060
- args: [{
1061
- exports: [VirtualScrollerComponent],
1062
- declarations: [VirtualScrollerComponent],
1063
- imports: [CommonModule],
1064
- providers: [
1065
- {
1066
- provide: 'virtual-scroller-default-options',
1067
- useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY
1068
- }
1069
- ]
1070
- }]
1071
- }] });
961
+ `, host: {
962
+ '[class.horizontal]': "horizontal",
963
+ '[class.vertical]': "!horizontal",
964
+ '[class.selfScroll]': "!parentScroll",
965
+ '[class.rtl]': "RTL"
966
+ }, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.horizontal.selfScroll.rtl{transform:scaleX(-1)}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}:host.horizontal.rtl .scrollable-content ::ng-deep>*{transform:scaleX(-1)}.total-padding{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0;opacity:0}:host.horizontal .total-padding{height:100%}\n"] }]
967
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
968
+ type: Inject,
969
+ args: [PLATFORM_ID]
970
+ }] }, { type: undefined, decorators: [{
971
+ type: Optional
972
+ }, {
973
+ type: Inject,
974
+ args: ['virtual-scroller-default-options']
975
+ }] }]; }, propDecorators: { disable: [{
976
+ type: Input
977
+ }], executeRefreshOutsideAngularZone: [{
978
+ type: Input
979
+ }], enableUnequalChildrenSizes: [{
980
+ type: Input
981
+ }], RTL: [{
982
+ type: Input
983
+ }], useMarginInsteadOfTranslate: [{
984
+ type: Input
985
+ }], modifyOverflowStyleOfParentScroll: [{
986
+ type: Input
987
+ }], stripedTable: [{
988
+ type: Input
989
+ }], scrollbarWidth: [{
990
+ type: Input
991
+ }], scrollbarHeight: [{
992
+ type: Input
993
+ }], childWidth: [{
994
+ type: Input
995
+ }], childHeight: [{
996
+ type: Input
997
+ }], ssrChildWidth: [{
998
+ type: Input
999
+ }], ssrChildHeight: [{
1000
+ type: Input
1001
+ }], ssrViewportWidth: [{
1002
+ type: Input
1003
+ }], ssrViewportHeight: [{
1004
+ type: Input
1005
+ }], bufferAmount: [{
1006
+ type: Input
1007
+ }], scrollAnimationTime: [{
1008
+ type: Input
1009
+ }], resizeBypassRefreshThreshold: [{
1010
+ type: Input
1011
+ }], scrollThrottlingTime: [{
1012
+ type: Input
1013
+ }], scrollDebounceTime: [{
1014
+ type: Input
1015
+ }], checkResizeInterval: [{
1016
+ type: Input
1017
+ }], items: [{
1018
+ type: Input
1019
+ }], compareItems: [{
1020
+ type: Input
1021
+ }], horizontal: [{
1022
+ type: Input
1023
+ }], parentScroll: [{
1024
+ type: Input
1025
+ }], vsChildRectChange: [{
1026
+ type: Output
1027
+ }], vsUpdate: [{
1028
+ type: Output
1029
+ }], vsChange: [{
1030
+ type: Output
1031
+ }], vsStart: [{
1032
+ type: Output
1033
+ }], vsEnd: [{
1034
+ type: Output
1035
+ }], contentElementRef: [{
1036
+ type: ViewChild,
1037
+ args: ['content', { read: ElementRef, static: true }]
1038
+ }], invisiblePaddingElementRef: [{
1039
+ type: ViewChild,
1040
+ args: ['invisiblePadding', { read: ElementRef, static: true }]
1041
+ }], headerElementRef: [{
1042
+ type: ContentChild,
1043
+ args: ['header', { read: ElementRef, static: false }]
1044
+ }], containerElementRef: [{
1045
+ type: ContentChild,
1046
+ args: ['container', { read: ElementRef, static: false }]
1047
+ }] } });
1048
+ export class VirtualScrollerModule {
1049
+ }
1050
+ VirtualScrollerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1051
+ VirtualScrollerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, declarations: [VirtualScrollerComponent], imports: [CommonModule], exports: [VirtualScrollerComponent] });
1052
+ VirtualScrollerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, providers: [
1053
+ {
1054
+ provide: 'virtual-scroller-default-options',
1055
+ useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY
1056
+ }
1057
+ ], imports: [CommonModule] });
1058
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.2", ngImport: i0, type: VirtualScrollerModule, decorators: [{
1059
+ type: NgModule,
1060
+ args: [{
1061
+ exports: [VirtualScrollerComponent],
1062
+ declarations: [VirtualScrollerComponent],
1063
+ imports: [CommonModule],
1064
+ providers: [
1065
+ {
1066
+ provide: 'virtual-scroller-default-options',
1067
+ useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY
1068
+ }
1069
+ ]
1070
+ }]
1071
+ }] });
1072
1072
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1zY3JvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1saWIvbGlzdC92aXJ0dWFsLXNjcm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTixTQUFTLEVBQ1QsWUFBWSxFQUNaLFVBQVUsRUFDVixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxRQUFRLEVBS1IsUUFBUSxFQUNSLE1BQU0sRUFFTixTQUFTLEdBQ1QsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM1QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUVuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFL0MsT0FBTyxLQUFLLEtBQUssTUFBTSxtQkFBbUIsQ0FBQTs7QUFjMUMsTUFBTSxVQUFVLHdDQUF3QztJQUN2RCxPQUFPO1FBQ04sbUJBQW1CLEVBQUUsSUFBSTtRQUN6QixpQ0FBaUMsRUFBRSxJQUFJO1FBQ3ZDLDRCQUE0QixFQUFFLENBQUM7UUFDL0IsbUJBQW1CLEVBQUUsR0FBRztRQUN4QixrQkFBa0IsRUFBRSxDQUFDO1FBQ3JCLG9CQUFvQixFQUFFLENBQUM7UUFDdkIsWUFBWSxFQUFFLEtBQUs7S0FDbkIsQ0FBQztBQUNILENBQUM7QUFzSEQsTUFBTSxPQUFPLHdCQUF3QjtJQThicEMsWUFDb0IsT0FBbUIsRUFDbkIsUUFBbUIsRUFDbkIsSUFBWSxFQUNyQixpQkFBb0MsRUFDekIsVUFBZSxFQUVwQyxPQUFzQztRQU5uQixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUNyQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBaGN4QyxXQUFNLEdBQUcsTUFBTSxDQUFDO1FB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TSxFQUFFLEtBQUssRUFBRTtnQkFJakQsbUJBQW1CO3NCQUQ1QixZQUFZO3VCQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTs7QUErN0IvRCxNQUFNLE9BQU8scUJBQXFCOztrSEFBckIscUJBQXFCO21IQUFyQixxQkFBcUIsaUJBeHJDckIsd0JBQXdCLGFBZ3JDMUIsWUFBWSxhQWhyQ1Ysd0JBQXdCO21IQXdyQ3hCLHFCQUFxQixhQVB0QjtRQUNWO1lBQ0MsT0FBTyxFQUFFLGtDQUFrQztZQUMzQyxVQUFVLEVBQUUsd0NBQXdDO1NBQ3BEO0tBQ0QsWUFOUyxZQUFZOzJGQVFWLHFCQUFxQjtrQkFYakMsUUFBUTttQkFBQztvQkFDVCxPQUFPLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQztvQkFDbkMsWUFBWSxFQUFFLENBQUMsd0JBQXdCLENBQUM7b0JBQ3hDLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQztvQkFDdkIsU0FBUyxFQUFFO3dCQUNWOzRCQUNDLE9BQU8sRUFBRSxrQ0FBa0M7NEJBQzNDLFVBQVUsRUFBRSx3Q0FBd0M7eUJBQ3BEO3FCQUNEO2lCQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuXHRDaGFuZ2VEZXRlY3RvclJlZixcclxuXHRDb21wb25lbnQsXHJcblx0Q29udGVudENoaWxkLFxyXG5cdEVsZW1lbnRSZWYsXHJcblx0RXZlbnRFbWl0dGVyLFxyXG5cdEluamVjdCxcclxuXHRJbnB1dCxcclxuXHROZ01vZHVsZSxcclxuXHROZ1pvbmUsXHJcblx0T25DaGFuZ2VzLFxyXG5cdE9uRGVzdHJveSxcclxuXHRPbkluaXQsXHJcblx0T3B0aW9uYWwsXHJcblx0T3V0cHV0LFxyXG5cdFJlbmRlcmVyMixcclxuXHRWaWV3Q2hpbGQsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbXBvcnQgeyBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBpc1BsYXRmb3JtU2VydmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuXHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcblxyXG5pbXBvcnQgKiBhcyB0d2VlbiBmcm9tICdAdHdlZW5qcy90d2Vlbi5qcydcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVmlydHVhbFNjcm9sbGVyRGVmYXVsdE9wdGlvbnMge1xyXG5cdGNoZWNrUmVzaXplSW50ZXJ2YWw6IG51bWJlclxyXG5cdG1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbDogYm9vbGVhbixcclxuXHRyZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkOiBudW1iZXIsXHJcblx0c2Nyb2xsQW5pbWF0aW9uVGltZTogbnVtYmVyO1xyXG5cdHNjcm9sbERlYm91bmNlVGltZTogbnVtYmVyO1xyXG5cdHNjcm9sbFRocm90dGxpbmdUaW1lOiBudW1iZXI7XHJcblx0c2Nyb2xsYmFySGVpZ2h0PzogbnVtYmVyO1xyXG5cdHNjcm9sbGJhcldpZHRoPzogbnVtYmVyO1xyXG5cdHN0cmlwZWRUYWJsZTogYm9vbGVhblxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gVklSVFVBTF9TQ1JPTExFUl9ERUZBVUxUX09QVElPTlNfRkFDVE9SWSgpOiBWaXJ0dWFsU2Nyb2xsZXJEZWZhdWx0T3B0aW9ucyB7XHJcblx0cmV0dXJuIHtcclxuXHRcdGNoZWNrUmVzaXplSW50ZXJ2YWw6IDEwMDAsXHJcblx0XHRtb2RpZnlPdmVyZmxvd1N0eWxlT2ZQYXJlbnRTY3JvbGw6IHRydWUsXHJcblx0XHRyZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkOiA1LFxyXG5cdFx0c2Nyb2xsQW5pbWF0aW9uVGltZTogNzUwLFxyXG5cdFx0c2Nyb2xsRGVib3VuY2VUaW1lOiAwLFxyXG5cdFx0c2Nyb2xsVGhyb3R0bGluZ1RpbWU6IDAsXHJcblx0XHRzdHJpcGVkVGFibGU6IGZhbHNlXHJcblx0fTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBXcmFwR3JvdXBEaW1lbnNpb25zIHtcclxuXHRtYXhDaGlsZFNpemVQZXJXcmFwR3JvdXA6IFdyYXBHcm91cERpbWVuc2lvbltdO1xyXG5cdG51bWJlck9mS25vd25XcmFwR3JvdXBDaGlsZFNpemVzOiBudW1iZXI7XHJcblx0c3VtT2ZLbm93bldyYXBHcm91cENoaWxkSGVpZ2h0czogbnVtYmVyO1xyXG5cdHN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRoczogbnVtYmVyO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFdyYXBHcm91cERpbWVuc2lvbiB7XHJcblx0Y2hpbGRIZWlnaHQ6IG51bWJlcjtcclxuXHRjaGlsZFdpZHRoOiBudW1iZXI7XHJcblx0aXRlbXM6IGFueVtdO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIElEaW1lbnNpb25zIHtcclxuXHRjaGlsZEhlaWdodDogbnVtYmVyO1xyXG5cdGNoaWxkV2lkdGg6IG51bWJlcjtcclxuXHRpdGVtQ291bnQ6IG51bWJlcjtcclxuXHRpdGVtc1BlclBhZ2U6IG51bWJlcjtcclxuXHRpdGVtc1BlcldyYXBHcm91cDogbnVtYmVyO1xyXG5cdG1heFNjcm9sbFBvc2l0aW9uOiBudW1iZXI7XHJcblx0cGFnZUNvdW50X2ZyYWN0aW9uYWw6IG51bWJlcjtcclxuXHRzY3JvbGxMZW5ndGg6IG51bWJlcjtcclxuXHR2aWV3cG9ydExlbmd0aDogbnVtYmVyO1xyXG5cdHdyYXBHcm91cHNQZXJQYWdlOiBudW1iZXI7XHJcbn1cclxuXHJcbmV4cG9ydCB0eXBlIFNjcm9sbERpcmVjdGlvblR5cGUgPSAnYmFja3dhcmQnIHwgJ2ZvcndhcmQnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJUGFnZUluZm8ge1xyXG5cdGVuZEluZGV4OiBudW1iZXI7XHJcblx0ZW5kSW5kZXhXaXRoQnVmZmVyOiBudW1iZXI7XHJcblx0bWF4U2Nyb2xsUG9zaXRpb246IG51bWJlcjtcclxuXHRzY3JvbGxFbmRQb3NpdGlvbjogbnVtYmVyO1xyXG5cdHNjcm9sbFN0YXJ0UG9zaXRpb246IG51bWJlcjtcclxuXHRzY3JvbGxEaXJlY3Rpb24/OiBTY3JvbGxEaXJlY3Rpb25UeXBlO1xyXG5cdHN0YXJ0SW5kZXg6IG51bWJlcjtcclxuXHRzdGFydEluZGV4V2l0aEJ1ZmZlcjogbnVtYmVyO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIElWaWV3cG9ydCBleHRlbmRzIElQYWdlSW5mbyB7XHJcblx0cGFkZGluZzogbnVtYmVyO1xyXG5cdHNjcm9sbExlbmd0aDogbnVtYmVyO1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuXHRzZWxlY3RvcjogJ3ZpcnR1YWwtc2Nyb2xsZXIsW3ZpcnR1YWxTY3JvbGxlcl0nLFxyXG5cdGV4cG9ydEFzOiAndmlydHVhbFNjcm9sbGVyJyxcclxuXHR0ZW1wbGF0ZTogYFxyXG4gICAgPGRpdiBjbGFzcz1cInRvdGFsLXBhZGRpbmdcIiAjaW52aXNpYmxlUGFkZGluZz48L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJzY3JvbGxhYmxlLWNvbnRlbnRcIiAjY29udGVudD5cclxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG4gICAgPC9kaXY+XHJcbiAgYCxcclxuXHRob3N0OiB7XHJcblx0XHQnW2NsYXNzLmhvcml6b250YWxdJzogXCJob3Jpem9udGFsXCIsXHJcblx0XHQnW2NsYXNzLnZlcnRpY2FsXSc6IFwiIWhvcml6b250YWxcIixcclxuXHRcdCdbY2xhc3Muc2VsZlNjcm9sbF0nOiBcIiFwYXJlbnRTY3JvbGxcIixcclxuXHRcdCdbY2xhc3MucnRsXSc6IFwiUlRMXCJcclxuXHR9LFxyXG5cdHN0eWxlczogW2BcclxuICAgIDpob3N0IHtcclxuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG5cdCAgXHRkaXNwbGF5OiBibG9jaztcclxuICAgICAgLXdlYmtpdC1vdmVyZmxvdy1zY3JvbGxpbmc6IHRvdWNoO1xyXG4gICAgfVxyXG5cdFx0Omhvc3QuaG9yaXpvbnRhbC5zZWxmU2Nyb2xsIHtcclxuICAgICAgb3ZlcmZsb3cteTogdmlzaWJsZTtcclxuICAgICAgb3ZlcmZsb3cteDogYXV0bztcclxuXHRcdH1cclxuXHRcdDpob3N0Lmhvcml6b250YWwuc2VsZlNjcm9sbC5ydGwge1xyXG5cdFx0XHR0cmFuc2Zvcm06IHNjYWxlWCgtMSk7XHJcblx0XHR9XHJcblx0XHQ6aG9zdC52ZXJ0aWNhbC5zZWxmU2Nyb2xsIHtcclxuICAgICAgb3ZlcmZsb3cteTogYXV0bztcclxuICAgICAgb3ZlcmZsb3cteDogdmlzaWJsZTtcclxuXHRcdH1cclxuICAgIC5zY3JvbGxhYmxlLWNvbnRlbnQge1xyXG4gICAgICB0b3A6IDA7XHJcbiAgICAgIGxlZnQ6IDA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgIG1heC13aWR0aDogMTAwdnc7XHJcbiAgICAgIG1heC1oZWlnaHQ6IDEwMHZoO1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB9XHJcblx0XHQuc2Nyb2xsYWJsZS1jb250ZW50IDo6bmctZGVlcCA+ICoge1xyXG5cdFx0XHRib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG5cdFx0fVxyXG5cdFx0Omhvc3QuaG9yaXpvbnRhbCB7XHJcblx0XHRcdHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcblx0XHR9XHJcblx0XHQ6aG9zdC5ob3Jpem9udGFsIC5zY3JvbGxhYmxlLWNvbnRlbnQge1xyXG5cdFx0XHRkaXNwbGF5OiBmbGV4O1xyXG5cdFx0fVxyXG5cdFx0Omhvc3QuaG9yaXpvbnRhbCAuc2Nyb2xsYWJsZS1jb250ZW50IDo6bmctZGVlcCA+ICoge1xyXG5cdFx0XHRmbGV4LXNocmluazogMDtcclxuXHRcdFx0ZmxleC1ncm93OiAwO1xyXG5cdFx0XHR3aGl0ZS1zcGFjZTogaW5pdGlhbDtcclxuXHRcdH1cclxuXHRcdDpob3N0Lmhvcml6b250YWwucnRsIC5zY3JvbGxhYmxlLWNvbnRlbnQgOjpuZy1kZWVwID4gKiB7XHJcblx0XHRcdHRyYW5zZm9ybTpzY2FsZVgoLTEpO1xyXG5cdFx0fVxyXG4gICAgLnRvdGFsLXBhZGRpbmcge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgICAgaGVpZ2h0OiAxcHg7XHJcbiAgICAgIHdpZHRoOiAxcHg7XHJcbiAgICAgIHRyYW5zZm9ybS1vcmlnaW46IDAgMDtcclxuICAgICAgb3BhY2l0eTogMDtcclxuICAgIH1cclxuICAgIDpob3N0Lmhvcml6b250YWwgLnRvdGFsLXBhZGRpbmcge1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcbiAgYF1cclxufSlcclxuZXhwb3J0IGNsYXNzIFZpcnR1YWxTY3JvbGxlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xyXG5cdHB1YmxpYyB2aWV3UG9ydEl0ZW1zOiBhbnlbXTtcclxuXHRwdWJsaWMgd2luZG93ID0gd2luZG93O1xyXG5cclxuXHRwdWJsaWMgZ2V0IHZpZXdQb3J0SW5mbygpOiBJUGFnZUluZm8ge1xyXG5cdFx0Y29uc3QgcGFnZUluZm86IElWaWV3cG9ydCA9IHRoaXMucHJldmlvdXNWaWV3UG9ydCB8fCA8YW55Pnt9O1xyXG5cdFx0cmV0dXJuIHtcclxuXHRcdFx0c3RhcnRJbmRleDogcGFnZUluZm8uc3RhcnRJbmRleCB8fCAwLFxyXG5cdFx0XHRlbmRJbmRleDogcGFnZUluZm8uZW5kSW5kZXggfHwgMCxcclxuXHRcdFx0c2Nyb2xsU3RhcnRQb3NpdGlvbjogcGFnZUluZm8uc2Nyb2xsU3RhcnRQb3NpdGlvbiB8fCAwLFxyXG5cdFx0XHRzY3JvbGxFbmRQb3NpdGlvbjogcGFnZUluZm8uc2Nyb2xsRW5kUG9zaXRpb24gfHwgMCxcclxuXHRcdFx0c2Nyb2xsRGlyZWN0aW9uOiBwYWdlSW5mby5zY3JvbGxEaXJlY3Rpb24gfHwgJ2ZvcndhcmQnLFxyXG5cdFx0XHRtYXhTY3JvbGxQb3NpdGlvbjogcGFnZUluZm8ubWF4U2Nyb2xsUG9zaXRpb24gfHwgMCxcclxuXHRcdFx0c3RhcnRJbmRleFdpdGhCdWZmZXI6IHBhZ2VJbmZvLnN0YXJ0SW5kZXhXaXRoQnVmZmVyIHx8IDAsXHJcblx0XHRcdGVuZEluZGV4V2l0aEJ1ZmZlcjogcGFnZUluZm8uZW5kSW5kZXhXaXRoQnVmZmVyIHx8IDAsXHJcblx0XHR9O1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIF9kaXNhYmxlID0gZmFsc2U7XHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgZ2V0IGRpc2FibGUoKTogYm9vbGVhbiB7XHJcblx0XHRyZXR1cm4gdGhpcy5fZGlzYWJsZTtcclxuXHR9XHJcblx0cHVibGljIHNldCBkaXNhYmxlKHZhbHVlOiBib29sZWFuKSB7XHJcblx0XHRpZiAodGhpcy5fZGlzYWJsZSA9PT0gdmFsdWUpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2Rpc2FibGUgPSB2YWx1ZTtcclxuXHRcdGlmICh0aGlzLl9kaXNhYmxlKSB7XHJcblx0XHRcdHRoaXMucmVtb3ZlU2Nyb2xsRXZlbnRIYW5kbGVycygpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0dGhpcy5hZGRTY3JvbGxFdmVudEhhbmRsZXJzKCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBleGVjdXRlUmVmcmVzaE91dHNpZGVBbmd1bGFyWm9uZSA9IGZhbHNlO1xyXG5cclxuXHRwcm90ZWN0ZWQgX2VuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzID0gZmFsc2U7XHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgZ2V0IGVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzKCk6IGJvb2xlYW4ge1xyXG5cdFx0cmV0dXJuIHRoaXMuX2VuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzO1xyXG5cdH1cclxuXHRwdWJsaWMgc2V0IGVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzKHZhbHVlOiBib29sZWFuKSB7XHJcblx0XHRpZiAodGhpcy5fZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgPT09IHZhbHVlKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcyA9IHZhbHVlO1xyXG5cdFx0dGhpcy5taW5NZWFzdXJlZENoaWxkV2lkdGggPSB1bmRlZmluZWQ7XHJcblx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSB1bmRlZmluZWQ7XHJcblx0fVxyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBSVEwgPSBmYWxzZTtcclxuXHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgdXNlTWFyZ2luSW5zdGVhZE9mVHJhbnNsYXRlID0gZmFsc2U7XHJcblxyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIG1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbDogYm9vbGVhbjtcclxuXHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgc3RyaXBlZFRhYmxlOiBib29sZWFuO1xyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBzY3JvbGxiYXJXaWR0aDogbnVtYmVyO1xyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBzY3JvbGxiYXJIZWlnaHQ6IG51bWJlcjtcclxuXHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgY2hpbGRXaWR0aDogbnVtYmVyO1xyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBjaGlsZEhlaWdodDogbnVtYmVyO1xyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBzc3JDaGlsZFdpZHRoOiBudW1iZXI7XHJcblxyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIHNzckNoaWxkSGVpZ2h0OiBudW1iZXI7XHJcblxyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIHNzclZpZXdwb3J0V2lkdGggPSAxOTIwO1xyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBzc3JWaWV3cG9ydEhlaWdodCA9IDEwODA7XHJcblxyXG5cdHByb3RlY3RlZCBfYnVmZmVyQW1vdW50OiBudW1iZXI7XHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgZ2V0IGJ1ZmZlckFtb3VudCgpOiBudW1iZXIge1xyXG5cdFx0aWYgKHR5cGVvZiAodGhpcy5fYnVmZmVyQW1vdW50KSA9PT0gJ251bWJlcicgJiYgdGhpcy5fYnVmZmVyQW1vdW50ID4gMCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5fYnVmZmVyQW1vdW50O1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgPyA1IDogMTtcclxuXHRcdH1cclxuXHR9XHJcblx0cHVibGljIHNldCBidWZmZXJBbW91bnQodmFsdWU6IG51bWJlcikge1xyXG5cdFx0dGhpcy5fYnVmZmVyQW1vdW50ID0gdmFsdWU7XHJcblx0fVxyXG5cclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBzY3JvbGxBbmltYXRpb25UaW1lOiBudW1iZXI7XHJcblxyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIHJlc2l6ZUJ5cGFzc1JlZnJlc2hUaHJlc2hvbGQ6IG51bWJlcjtcclxuXHJcblx0cHJvdGVjdGVkIF9zY3JvbGxUaHJvdHRsaW5nVGltZTogbnVtYmVyO1xyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIGdldCBzY3JvbGxUaHJvdHRsaW5nVGltZSgpOiBudW1iZXIge1xyXG5cdFx0cmV0dXJuIHRoaXMuX3Njcm9sbFRocm90dGxpbmdUaW1lO1xyXG5cdH1cclxuXHRwdWJsaWMgc2V0IHNjcm9sbFRocm90dGxpbmdUaW1lKHZhbHVlOiBudW1iZXIpIHtcclxuXHRcdHRoaXMuX3Njcm9sbFRocm90dGxpbmdUaW1lID0gdmFsdWU7XHJcblx0XHR0aGlzLnVwZGF0ZU9uU2Nyb2xsRnVuY3Rpb24oKTtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBfc2Nyb2xsRGVib3VuY2VUaW1lOiBudW1iZXI7XHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgZ2V0IHNjcm9sbERlYm91bmNlVGltZSgpOiBudW1iZXIge1xyXG5cdFx0cmV0dXJuIHRoaXMuX3Njcm9sbERlYm91bmNlVGltZTtcclxuXHR9XHJcblx0cHVibGljIHNldCBzY3JvbGxEZWJvdW5jZVRpbWUodmFsdWU6IG51bWJlcikge1xyXG5cdFx0dGhpcy5fc2Nyb2xsRGVib3VuY2VUaW1lID0gdmFsdWU7XHJcblx0XHR0aGlzLnVwZGF0ZU9uU2Nyb2xsRnVuY3Rpb24oKTtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBvblNjcm9sbDogKCkgPT4gdm9pZDtcclxuXHRwcm90ZWN0ZWQgdXBkYXRlT25TY3JvbGxGdW5jdGlvbigpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLnNjcm9sbERlYm91bmNlVGltZSkge1xyXG5cdFx0XHR0aGlzLm9uU2Nyb2xsID0gPGFueT50aGlzLmRlYm91bmNlKCgpID0+IHtcclxuXHRcdFx0XHR0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xyXG5cdFx0XHR9LCB0aGlzLnNjcm9sbERlYm91bmNlVGltZSk7XHJcblx0XHR9XHJcblx0XHRlbHNlIGlmICh0aGlzLnNjcm9sbFRocm90dGxpbmdUaW1lKSB7XHJcblx0XHRcdHRoaXMub25TY3JvbGwgPSA8YW55PnRoaXMudGhyb3R0bGVUcmFpbGluZygoKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcclxuXHRcdFx0fSwgdGhpcy5zY3JvbGxUaHJvdHRsaW5nVGltZSk7XHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0dGhpcy5vblNjcm9sbCA9ICgpID0+IHtcclxuXHRcdFx0XHR0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xyXG5cdFx0XHR9O1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIGNoZWNrU2Nyb2xsRWxlbWVudFJlc2l6ZWRUaW1lcjogbnVtYmVyO1xyXG5cdHByb3RlY3RlZCBfY2hlY2tSZXNpemVJbnRlcnZhbDogbnVtYmVyO1xyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIGdldCBjaGVja1Jlc2l6ZUludGVydmFsKCk6IG51bWJlciB7XHJcblx0XHRyZXR1cm4gdGhpcy5fY2hlY2tSZXNpemVJbnRlcnZhbDtcclxuXHR9XHJcblx0cHVibGljIHNldCBjaGVja1Jlc2l6ZUludGVydmFsKHZhbHVlOiBudW1iZXIpIHtcclxuXHRcdGlmICh0aGlzLl9jaGVja1Jlc2l6ZUludGVydmFsID09PSB2YWx1ZSkge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fY2hlY2tSZXNpemVJbnRlcnZhbCA9IHZhbHVlO1xyXG5cdFx0dGhpcy5hZGRTY3JvbGxFdmVudEhhbmRsZXJzKCk7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgX2l0ZW1zOiBhbnlbXSA9IFtdO1xyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIGdldCBpdGVtcygpOiBhbnlbXSB7XHJcblx0XHRyZXR1cm4gdGhpcy5faXRlbXM7XHJcblx0fVxyXG5cdHB1YmxpYyBzZXQgaXRlbXModmFsdWU6IGFueVtdKSB7XHJcblx0XHRpZiAodmFsdWUgPT09IHRoaXMuX2l0ZW1zKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pdGVtcyA9IHZhbHVlIHx8IFtdO1xyXG5cdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKHRydWUpO1xyXG5cdH1cclxuXHJcblx0QElucHV0KClcclxuXHRwdWJsaWMgY29tcGFyZUl0ZW1zOiAoaXRlbTE6IGFueSwgaXRlbTI6IGFueSkgPT4gYm9vbGVhbiA9IChpdGVtMTogYW55LCBpdGVtMjogYW55KSA9PiBpdGVtMSA9PT0gaXRlbTI7XHJcblxyXG5cdHByb3RlY3RlZCBfaG9yaXpvbnRhbDogYm9vbGVhbjtcclxuXHRASW5wdXQoKVxyXG5cdHB1YmxpYyBnZXQgaG9yaXpvbnRhbCgpOiBib29sZWFuIHtcclxuXHRcdHJldHVybiB0aGlzLl9ob3Jpem9udGFsO1xyXG5cdH1cclxuXHRwdWJsaWMgc2V0IGhvcml6b250YWwodmFsdWU6IGJvb2xlYW4pIHtcclxuXHRcdHRoaXMuX2hvcml6b250YWwgPSB2YWx1ZTtcclxuXHRcdHRoaXMudXBkYXRlRGlyZWN0aW9uKCk7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgcmV2ZXJ0UGFyZW50T3ZlcnNjcm9sbCgpOiB2b2lkIHtcclxuXHRcdGNvbnN0IHNjcm9sbEVsZW1lbnQgPSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKTtcclxuXHRcdGlmIChzY3JvbGxFbGVtZW50ICYmIHRoaXMub2xkUGFyZW50U2Nyb2xsT3ZlcmZsb3cpIHtcclxuXHRcdFx0c2Nyb2xsRWxlbWVudC5zdHlsZVsnb3ZlcmZsb3cteSddID0gdGhpcy5vbGRQYXJlbnRTY3JvbGxPdmVyZmxvdy55O1xyXG5cdFx0XHRzY3JvbGxFbGVtZW50LnN0eWxlWydvdmVyZmxvdy14J10gPSB0aGlzLm9sZFBhcmVudFNjcm9sbE92ZXJmbG93Lng7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5vbGRQYXJlbnRTY3JvbGxPdmVyZmxvdyA9IHVuZGVmaW5lZDtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBvbGRQYXJlbnRTY3JvbGxPdmVyZmxvdzogeyB4OiBzdHJpbmcsIHk6IHN0cmluZyB9O1xyXG5cdHByb3RlY3RlZCBfcGFyZW50U2Nyb2xsOiBFbGVtZW50IHwgV2luZG93O1xyXG5cdEBJbnB1dCgpXHJcblx0cHVibGljIGdldCBwYXJlbnRTY3JvbGwoKTogRWxlbWVudCB8IFdpbmRvdyB7XHJcblx0XHRyZXR1cm4gdGhpcy5fcGFyZW50U2Nyb2xsO1xyXG5cdH1cclxuXHRwdWJsaWMgc2V0IHBhcmVudFNjcm9sbCh2YWx1ZTogRWxlbWVudCB8IFdpbmRvdykge1xyXG5cdFx0aWYgKHRoaXMuX3BhcmVudFNjcm9sbCA9PT0gdmFsdWUpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMucmV2ZXJ0UGFyZW50T3ZlcnNjcm9sbCgpO1xyXG5cdFx0dGhpcy5fcGFyZW50U2Nyb2xsID0gdmFsdWU7XHJcblx0XHR0aGlzLmFkZFNjcm9sbEV2ZW50SGFuZGxlcnMoKTtcclxuXHJcblx0XHRjb25zdCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XHJcblx0XHRpZiAodGhpcy5tb2RpZnlPdmVyZmxvd1N0eWxlT2ZQYXJlbnRTY3JvbGwgJiYgc2Nyb2xsRWxlbWVudCAhPT0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcclxuXHRcdFx0dGhpcy5vbGRQYXJlbnRTY3JvbGxPdmVyZmxvdyA9IHsgeDogc2Nyb2xsRWxlbWVudC5zdHlsZVsnb3ZlcmZsb3cteCddLCB5OiBzY3JvbGxFbGVtZW50LnN0eWxlWydvdmVyZmxvdy15J10gfTtcclxuXHRcdFx0c2Nyb2xsRWxlbWVudC5zdHlsZVsnb3ZlcmZsb3cteSddID0gdGhpcy5ob3Jpem9udGFsID8gJ3Zpc2libGUnIDogJ2F1dG8nO1xyXG5cdFx0XHRzY3JvbGxFbGVtZW50LnN0eWxlWydvdmVyZmxvdy14J10gPSB0aGlzLmhvcml6b250YWwgPyAnYXV0bycgOiAndmlzaWJsZSc7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIF9sYXN0Q2hpbGRSZWN0OiBDbGllbnRSZWN0O1xyXG5cclxuXHRAT3V0cHV0KClcclxuXHRwdWJsaWMgdnNDaGlsZFJlY3RDaGFuZ2U6IEV2ZW50RW1pdHRlcjxDbGllbnRSZWN0PiA9IG5ldyBFdmVudEVtaXR0ZXI8Q2xpZW50UmVjdD4oKTtcclxuXHJcblx0QE91dHB1dCgpXHJcblx0cHVibGljIHZzVXBkYXRlOiBFdmVudEVtaXR0ZXI8YW55W10+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnlbXT4oKTtcclxuXHJcblx0QE91dHB1dCgpXHJcblx0cHVibGljIHZzQ2hhbmdlOiBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPiA9IG5ldyBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPigpO1xyXG5cclxuXHRAT3V0cHV0KClcclxuXHRwdWJsaWMgdnNTdGFydDogRXZlbnRFbWl0dGVyPElQYWdlSW5mbz4gPSBuZXcgRXZlbnRFbWl0dGVyPElQYWdlSW5mbz4oKTtcclxuXHJcblx0QE91dHB1dCgpXHJcblx0cHVibGljIHZzRW5kOiBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPiA9IG5ldyBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPigpO1xyXG5cclxuXHRAVmlld0NoaWxkKCdjb250ZW50JywgeyByZWFkOiBFbGVtZW50UmVmLCBzdGF0aWM6IHRydWUgfSlcclxuXHRwdWJsaWMgY29udGVudEVsZW1lbnRSZWY6IEVsZW1lbnRSZWY7XHJcblxyXG5cdEBWaWV3Q2hpbGQoJ2ludmlzaWJsZVBhZGRpbmcnLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogdHJ1ZSB9KVxyXG5cdHByb3RlY3RlZCBpbnZpc2libGVQYWRkaW5nRWxlbWVudFJlZjogRWxlbWVudFJlZjtcclxuXHJcblx0QENvbnRlbnRDaGlsZCgnaGVhZGVyJywgeyByZWFkOiBFbGVtZW50UmVmLCBzdGF0aWM6IGZhbHNlIH0pXHJcblx0cHJvdGVjdGVkIGhlYWRlckVsZW1lbnRSZWY6IEVsZW1lbnRSZWY7XHJcblxyXG5cdEBDb250ZW50Q2hpbGQoJ2NvbnRhaW5lcicsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZSB9KVxyXG5cdHByb3RlY3RlZCBjb250YWluZXJFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xyXG5cclxuXHRwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcblx0XHR0aGlzLmFkZFNjcm9sbEV2ZW50SGFuZGxlcnMoKTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuXHRcdHRoaXMucmVtb3ZlU2Nyb2xsRXZlbnRIYW5kbGVycygpO1xyXG5cdFx0dGhpcy5yZXZlcnRQYXJlbnRPdmVyc2Nyb2xsKCk7XHJcblx0fVxyXG5cclxuXHRwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogYW55KTogdm9pZCB7XHJcblx0XHRjb25zdCBpbmRleExlbmd0aENoYW5nZWQgPSB0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoICE9PSB0aGlzLml0ZW1zLmxlbmd0aDtcclxuXHRcdHRoaXMuY2FjaGVkSXRlbXNMZW5ndGggPSB0aGlzLml0ZW1zLmxlbmd0aDtcclxuXHJcblx0XHRjb25zdCBmaXJzdFJ1bjogYm9vbGVhbiA9ICFjaGFuZ2VzLml0ZW1zIHx8ICFjaGFuZ2VzLml0ZW1zLnByZXZpb3VzVmFsdWUgfHwgY2hhbmdlcy5pdGVtcy5wcmV2aW91c1ZhbHVlLmxlbmd0aCA9PT0gMDtcclxuXHRcdHRoaXMucmVmcmVzaF9pbnRlcm5hbChpbmRleExlbmd0aENoYW5nZWQgfHwgZmlyc3RSdW4pO1xyXG5cdH1cclxuXHJcblx0cHVibGljIG5nRG9DaGVjaygpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoICE9PSB0aGlzLml0ZW1zLmxlbmd0aCkge1xyXG5cdFx0XHR0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoID0gdGhpcy5pdGVtcy5sZW5ndGg7XHJcblx0XHRcdHRoaXMucmVmcmVzaF9pbnRlcm5hbCh0cnVlKTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLnByZXZpb3VzVmlld1BvcnQgJiYgdGhpcy52aWV3UG9ydEl0ZW1zICYmIHRoaXMudmlld1BvcnRJdGVtcy5sZW5ndGggPiAwKSB7XHJcblx0XHRcdGxldCBpdGVtc0FycmF5Q2hhbmdlZCA9IGZhbHNlO1xyXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudmlld1BvcnRJdGVtcy5sZW5ndGg7ICsraSkge1xyXG5cdFx0XHRcdGlmICghdGhpcy5jb21wYXJlSXRlbXModGhpcy5pdGVtc1t0aGlzLnByZXZpb3VzVmlld1BvcnQuc3RhcnRJbmRleFdpdGhCdWZmZXIgKyBpXSwgdGhpcy52aWV3UG9ydEl0ZW1zW2ldKSkge1xyXG5cdFx0XHRcdFx0aXRlbXNBcnJheUNoYW5nZWQgPSB0cnVlO1xyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChpdGVtc0FycmF5Q2hhbmdlZCkge1xyXG5cdFx0XHRcdHRoaXMucmVmcmVzaF9pbnRlcm5hbCh0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHVibGljIHJlZnJlc2goKTogdm9pZCB7XHJcblx0XHR0aGlzLnJlZnJlc2hfaW50ZXJuYWwodHJ1ZSk7XHJcblx0fVxyXG5cclxuXHRwdWJsaWMgaW52YWxpZGF0ZUFsbENhY2hlZE1lYXN1cmVtZW50cygpOiB2b2lkIHtcclxuXHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucyA9IHtcclxuXHRcdFx0bWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwOiBbXSxcclxuXHRcdFx0bnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXM6IDAsXHJcblx0XHRcdHN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRoczogMCxcclxuXHRcdFx0c3VtT2ZLbm93bldyYXBHcm91cENoaWxkSGVpZ2h0czogMFxyXG5cdFx0fTtcclxuXHJcblx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCA9IHVuZGVmaW5lZDtcclxuXHRcdHRoaXMubWluTWVhc3VyZWRDaGlsZEhlaWdodCA9IHVuZGVmaW5lZDtcclxuXHJcblx0XHR0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xyXG5cdH1cclxuXHJcblx0cHVibGljIGludmFsaWRhdGVDYWNoZWRNZWFzdXJlbWVudEZvckl0ZW0oaXRlbTogYW55KTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcykge1xyXG5cdFx0XHRjb25zdCBpbmRleCA9IHRoaXMuaXRlbXMgJiYgdGhpcy5pdGVtcy5pbmRleE9mKGl0ZW0pO1xyXG5cdFx0XHRpZiAoaW5kZXggPj0gMCkge1xyXG5cdFx0XHRcdHRoaXMuaW52YWxpZGF0ZUNhY2hlZE1lYXN1cmVtZW50QXRJbmRleChpbmRleCk7XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoID0gdW5kZWZpbmVkO1xyXG5cdFx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSB1bmRlZmluZWQ7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBpbnZhbGlkYXRlQ2FjaGVkTWVhc3VyZW1lbnRBdEluZGV4KGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLmVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzKSB7XHJcblx0XHRcdGNvbnN0IGNhY2hlZE1lYXN1cmVtZW50ID0gdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpbmRleF07XHJcblx0XHRcdGlmIChjYWNoZWRNZWFzdXJlbWVudCkge1xyXG5cdFx0XHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbaW5kZXhdID0gdW5kZWZpbmVkO1xyXG5cdFx0XHRcdC0tdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm51bWJlck9mS25vd25XcmFwR3JvdXBDaGlsZFNpemVzO1xyXG5cdFx0XHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRXaWR0aHMgLT0gY2FjaGVkTWVhc3VyZW1lbnQuY2hpbGRXaWR0aCB8fCAwO1xyXG5cdFx0XHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRIZWlnaHRzIC09IGNhY2hlZE1lYXN1cmVtZW50LmNoaWxkSGVpZ2h0IHx8IDA7XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoID0gdW5kZWZpbmVkO1xyXG5cdFx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSB1bmRlZmluZWQ7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyBzY3JvbGxJbnRvKGl0ZW06IGFueSwgYWxpZ25Ub0JlZ2lubmluZyA9IHRydWUsIGFkZGl0aW9uYWxPZmZzZXQgPSAwLCBhbmltYXRpb25NaWxsaXNlY29uZHM6IG51bWJlciA9IHVuZGVmaW5lZCwgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSB1bmRlZmluZWQpOiB2b2lkIHtcclxuXHRcdGNvbnN0IGluZGV4OiBudW1iZXIgPSB0aGlzLml0ZW1zLmluZGV4T2YoaXRlbSk7XHJcblx0XHRpZiAoaW5kZXggPT09IC0xKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLnNjcm9sbFRvSW5kZXgoaW5kZXgsIGFsaWduVG9CZWdpbm5pbmcsIGFkZGl0aW9uYWxPZmZzZXQsIGFuaW1hdGlvbk1pbGxpc2Vjb25kcywgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2spO1xyXG5cdH1cclxuXHJcblx0cHVibGljIHNjcm9sbFRvSW5kZXgoaW5kZXg6IG51bWJlciwgYWxpZ25Ub0JlZ2lubmluZyA9IHRydWUsIGFkZGl0aW9uYWxPZmZzZXQgPSAwLCBhbmltYXRpb25NaWxsaXNlY29uZHM6IG51bWJlciA9IHVuZGVmaW5lZCwgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSB1bmRlZmluZWQpOiB2b2lkIHtcclxuXHRcdGxldCBtYXhSZXRyaWVzID0gNTtcclxuXHJcblx0XHRjb25zdCByZXRyeUlmTmVlZGVkID0gKCkgPT4ge1xyXG5cdFx0XHQtLW1heFJldHJpZXM7XHJcblx0XHRcdGlmIChtYXhSZXRyaWVzIDw9IDApIHtcclxuXHRcdFx0XHRpZiAoYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2spIHtcclxuXHRcdFx0XHRcdGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3QgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlRGltZW5zaW9ucygpO1xyXG5cdFx0XHRjb25zdCBkZXNpcmVkU3RhcnRJbmRleCA9IE1hdGgubWluKE1hdGgubWF4KGluZGV4LCAwKSwgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxKTtcclxuXHRcdFx0aWYgKHRoaXMucHJldmlvdXNWaWV3UG9ydC5zdGFydEluZGV4ID09PSBkZXNpcmVkU3RhcnRJbmRleCkge1xyXG5cdFx0XHRcdGlmIChhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0YW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2soKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLnNjcm9sbFRvSW5kZXhfaW50ZXJuYWwoaW5kZXgsIGFsaWduVG9CZWdpbm5pbmcsIGFkZGl0aW9uYWxPZmZzZXQsIDAsIHJldHJ5SWZOZWVkZWQpO1xyXG5cdFx0fTtcclxuXHJcblx0XHR0aGlzLnNjcm9sbFRvSW5kZXhfaW50ZXJuYWwoaW5kZXgsIGFsaWduVG9CZWdpbm5pbmcsIGFkZGl0aW9uYWxPZmZzZXQsIGFuaW1hdGlvbk1pbGxpc2Vjb25kcywgcmV0cnlJZk5lZWRlZCk7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgc2Nyb2xsVG9JbmRleF9pbnRlcm5hbChpbmRleDogbnVtYmVyLCBhbGlnblRvQmVnaW5uaW5nID0gdHJ1ZSwgYWRkaXRpb25hbE9mZnNldCA9IDAsIGFuaW1hdGlvbk1pbGxpc2Vjb25kczogbnVtYmVyID0gdW5kZWZpbmVkLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjazogKCkgPT4gdm9pZCA9IHVuZGVmaW5lZCk6IHZvaWQge1xyXG5cdFx0YW5pbWF0aW9uTWlsbGlzZWNvbmRzID0gYW5pbWF0aW9uTWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWQgPyB0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWUgOiBhbmltYXRpb25NaWxsaXNlY29uZHM7XHJcblxyXG5cdFx0Y29uc3QgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlRGltZW5zaW9ucygpO1xyXG5cdFx0bGV0IHNjcm9sbCA9IHRoaXMuY2FsY3VsYXRlUGFkZGluZyhpbmRleCwgZGltZW5zaW9ucykgKyBhZGRpdGlvbmFsT2Zmc2V0O1xyXG5cdFx0aWYgKCFhbGlnblRvQmVnaW5uaW5nKSB7XHJcblx0XHRcdHNjcm9sbCAtPSBkaW1lbnNpb25zLndyYXBHcm91cHNQZXJQYWdlICogZGltZW5zaW9uc1t0aGlzLl9jaGlsZFNjcm9sbERpbV07XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5zY3JvbGxUb1Bvc2l0aW9uKHNjcm9sbCwgYW5pbWF0aW9uTWlsbGlzZWNvbmRzLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjayk7XHJcblx0fVxyXG5cclxuXHRwdWJsaWMgc2Nyb2xsVG9Qb3NpdGlvbihzY3JvbGxQb3NpdGlvbjogbnVtYmVyLCBhbmltYXRpb25NaWxsaXNlY29uZHM6IG51bWJlciA9IHVuZGVmaW5lZCwgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSB1bmRlZmluZWQpOiB2b2lkIHtcclxuXHRcdHNjcm9sbFBvc2l0aW9uICs9IHRoaXMuZ2V0RWxlbWVudHNPZmZzZXQoKTtcclxuXHJcblx0XHRhbmltYXRpb25NaWxsaXNlY29uZHMgPSBhbmltYXRpb25NaWxsaXNlY29uZHMgPT09IHVuZGVmaW5lZCA/IHRoaXMuc2Nyb2xsQW5pbWF0aW9uVGltZSA6IGFuaW1hdGlvbk1pbGxpc2Vjb25kcztcclxuXHJcblx0XHRjb25zdCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XHJcblxyXG5cdFx0bGV0IGFuaW1hdGlvblJlcXVlc3Q6IG51bWJlcjtcclxuXHJcblx0XHRpZiAodGhpcy5jdXJyZW50VHdlZW4pIHtcclxuXHRcdFx0dGhpcy5jdXJyZW50VHdlZW4uc3RvcCgpO1xyXG5cdFx0XHR0aGlzLmN1cnJlbnRUd2VlbiA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWFuaW1hdGlvbk1pbGxpc2Vjb25kcykge1xyXG5cdFx0XHR0aGlzLnJlbmRlcmVyLnNldFByb3BlcnR5KHNjcm9sbEVsZW1lbnQsIHRoaXMuX3Njcm9sbFR5cGUsIHNjcm9sbFBvc2l0aW9uKTtcclxuXHRcdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjayk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCB0d2VlbkNvbmZpZ09iaiA9IHsgc2Nyb2xsUG9zaXRpb246IHNjcm9sbEVsZW1lbnRbdGhpcy5fc2Nyb2xsVHlwZV0gfTtcclxuXHJcblx0XHRjb25zdCBuZXdUd2VlbiA9IG5ldyB0d2Vlbi5Ud2Vlbih0d2VlbkNvbmZpZ09iailcclxuXHRcdFx0LnRvKHsgc2Nyb2xsUG9zaXRpb24gfSwgYW5pbWF0aW9uTWlsbGlzZWNvbmRzKVxyXG5cdFx0XHQuZWFzaW5nKHR3ZWVuLkVhc2luZy5RdWFkcmF0aWMuT3V0KVxyXG5cdFx0XHQub25VcGRhdGUoKGRhdGEpID0+IHtcclxuXHRcdFx0XHRpZiAoaXNOYU4oZGF0YS5zY3JvbGxQb3NpdGlvbikpIHtcclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0dGhpcy5yZW5kZXJlci5zZXRQcm9wZXJ0eShzY3JvbGxFbGVtZW50LCB0aGlzLl9zY3JvbGxUeXBlLCBkYXRhLnNjcm9sbFBvc2l0aW9uKTtcclxuXHRcdFx0XHR0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xyXG5cdFx0XHR9KVxyXG5cdFx0XHQub25TdG9wKCgpID0+IHtcclxuXHRcdFx0XHRjYW5jZWxBbmltYXRpb25GcmFtZShhbmltYXRpb25SZXF1ZXN0KTtcclxuXHRcdFx0fSlcclxuXHRcdFx0LnN0YXJ0KCk7XHJcblxyXG5cdFx0Y29uc3QgYW5pbWF0ZSA9ICh0aW1lPzogbnVtYmVyKSA9PiB7XHJcblx0XHRcdGlmICghbmV3VHdlZW5bXCJpc1BsYXlpbmdcIl0oKSkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0bmV3VHdlZW4udXBkYXRlKHRpbWUpO1xyXG5cdFx0XHRpZiAodHdlZW5Db25maWdPYmouc2Nyb2xsUG9zaXRpb24gPT09IHNjcm9sbFBvc2l0aW9uKSB7XHJcblx0XHRcdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjayk7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG5cdFx0XHRcdGFuaW1hdGlvblJlcXVlc3QgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYW5pbWF0ZSk7XHJcblx0XHRcdH0pO1xyXG5cdFx0fTtcclxuXHJcblx0XHRhbmltYXRlKCk7XHJcblx0XHR0aGlzLmN1cnJlbnRUd2VlbiA9IG5ld1R3ZWVuO1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIGlzQW5ndWxhclVuaXZlcnNhbFNTUjogYm9vbGVhbjtcclxuXHJcblx0Y29uc3RydWN0b3IoXHJcblx0XHRwcm90ZWN0ZWQgcmVhZG9ubHkgZWxlbWVudDogRWxlbWVudFJlZixcclxuXHRcdHByb3RlY3RlZCByZWFkb25seSByZW5kZXJlcjogUmVuZGVyZXIyLFxyXG5cdFx0cHJvdGVjdGVkIHJlYWRvbmx5IHpvbmU6IE5nWm9uZSxcclxuXHRcdHByb3RlY3RlZCBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcblx0XHRASW5qZWN0KFBMQVRGT1JNX0lEKSBwbGF0Zm9ybUlkOiBhbnksXHJcblx0XHRAT3B0aW9uYWwoKSBASW5qZWN0KCd2aXJ0dWFsLXNjcm9sbGVyLWRlZmF1bHQtb3B0aW9ucycpXHJcblx0XHRvcHRpb25zOiBWaXJ0dWFsU2Nyb2xsZXJEZWZhdWx0T3B0aW9uc1xyXG5cdCkge1xyXG5cclxuXHRcdHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSID0gaXNQbGF0Zm9ybVNlcnZlcihwbGF0Zm9ybUlkKTtcclxuXHJcblx0XHRjb25zdCBkZWZhdWx0T3B0aW9ucyA9IFZJUlRVQUxfU0NST0xMRVJfREVGQVVMVF9PUFRJT05TX0ZBQ1RPUlkoKTtcclxuXHJcblx0XHR0aGlzLmNoZWNrUmVzaXplSW50ZXJ2YWwgPSBvcHRpb25zPy5jaGVja1Jlc2l6ZUludGVydmFsIHx8IGRlZmF1bHRPcHRpb25zLmNoZWNrUmVzaXplSW50ZXJ2YWw7XHJcblx0XHR0aGlzLm1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbCA9IG9wdGlvbnM/Lm1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbCB8fCBkZWZhdWx0T3B0aW9ucy5tb2RpZnlPdmVyZmxvd1N0eWxlT2ZQYXJlbnRTY3JvbGw7XHJcblx0XHR0aGlzLnJlc2l6ZUJ5cGFzc1JlZnJlc2hUaHJlc2hvbGQgPSBvcHRpb25zPy5yZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkIHx8IGRlZmF1bHRPcHRpb25zLnJlc2l6ZUJ5cGFzc1JlZnJlc2hUaHJlc2hvbGQ7XHJcblx0XHR0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWUgPSBvcHRpb25zPy5zY3JvbGxBbmltYXRpb25UaW1lIHx8IGRlZmF1bHRPcHRpb25zLnNjcm9sbEFuaW1hdGlvblRpbWU7XHJcblx0XHR0aGlzLnNjcm9sbERlYm91bmNlVGltZSA9IG9wdGlvbnM/LnNjcm9sbERlYm91bmNlVGltZSB8fCBkZWZhdWx0T3B0aW9ucy5zY3JvbGxEZWJvdW5jZVRpbWU7XHJcblx0XHR0aGlzLnNjcm9sbFRocm90dGxpbmdUaW1lID0gb3B0aW9ucz8uc2Nyb2xsVGhyb3R0bGluZ1RpbWUgfHwgZGVmYXVsdE9wdGlvbnMuc2Nyb2xsVGhyb3R0bGluZ1RpbWU7XHJcblx0XHR0aGlzLnNjcm9sbGJhckhlaWdodCA9IG9wdGlvbnM/LnNjcm9sbGJhckhlaWdodCB8fCBkZWZhdWx0T3B0aW9ucy5zY3JvbGxiYXJIZWlnaHQ7XHJcblx0XHR0aGlzLnNjcm9sbGJhcldpZHRoID0gb3B0aW9ucz8uc2Nyb2xsYmFyV2lkdGggfHwgZGVmYXVsdE9wdGlvbnMuc2Nyb2xsYmFyV2lkdGg7XHJcblx0XHR0aGlzLnN0cmlwZWRUYWJsZSA9IG9wdGlvbnM/LnN0cmlwZWRUYWJsZSB8fCBkZWZhdWx0T3B0aW9ucy5zdHJpcGVkVGFibGU7XHJcblxyXG5cdFx0dGhpcy5ob3Jpem9udGFsID0gZmFsc2U7XHJcblx0XHR0aGlzLnJlc2V0V3JhcEdyb3VwRGltZW5zaW9ucygpO1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIGdldEVsZW1lbnRTaXplKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYW55IHtcclxuXHRcdGNvbnN0IHJlc3VsdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcblx0XHRjb25zdCBzdHlsZXMgPSBnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xyXG5cdFx0Y29uc3QgbWFyZ2luVG9wID0gcGFyc2VJbnQoc3R5bGVzWydtYXJnaW4tdG9wJ10sIDEwKSB8fCAwO1xyXG5cdFx0Y29uc3QgbWFyZ2luQm90dG9tID0gcGFyc2VJbnQoc3R5bGVzWydtYXJnaW4tYm90dG9tJ10sIDEwKSB8fCAwO1xyXG5cdFx0Y29uc3QgbWFyZ2luTGVmdCA9IHBhcnNlSW50KHN0eWxlc1snbWFyZ2luLWxlZnQnXSwgMTApIHx8IDA7XHJcblx0XHRjb25zdCBtYXJnaW5SaWdodCA9IHBhcnNlSW50KHN0eWxlc1snbWFyZ2luLXJpZ2h0J10sIDEwKSB8fCAwO1xyXG5cclxuXHRcdHJldHVybiB7XHJcblx0XHRcdHRvcDogcmVzdWx0LnRvcCArIG1hcmdpblRvcCxcclxuXHRcdFx0Ym90dG9tOiByZXN1bHQuYm90dG9tICsgbWFyZ2luQm90dG9tLFxyXG5cdFx0XHRsZWZ0OiByZXN1bHQubGVmdCArIG1hcmdpbkxlZnQsXHJcblx0XHRcdHJpZ2h0OiByZXN1bHQucmlnaHQgKyBtYXJnaW5SaWdodCxcclxuXHRcdFx0d2lkdGg6IHJlc3VsdC53aWR0aCArIG1hcmdpbkxlZnQgKyBtYXJnaW5SaWdodCxcclxuXHRcdFx0aGVpZ2h0OiByZXN1bHQuaGVpZ2h0ICsgbWFyZ2luVG9wICsgbWFyZ2luQm90dG9tXHJcblx0XHR9O1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIHByZXZpb3VzU2Nyb2xsQm91bmRpbmdSZWN0OiBDbGllbnRSZWN0O1xyXG5cdHByb3RlY3RlZCBjaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgYm91bmRpbmdSZWN0ID0gdGhpcy5nZXRFbGVtZW50U2l6ZSh0aGlzLmdldFNjcm9sbEVsZW1lbnQoKSk7XHJcblxyXG5cdFx0bGV0IHNpemVDaGFuZ2VkOiBib29sZWFuO1xyXG5cdFx0aWYgKCF0aGlzLnByZXZpb3VzU2Nyb2xsQm91bmRpbmdSZWN0KSB7XHJcblx0XHRcdHNpemVDaGFuZ2VkID0gdHJ1ZTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGNvbnN0IHdpZHRoQ2hhbmdlID0gTWF0aC5hYnMoYm91bmRpbmdSZWN0LndpZHRoIC0gdGhpcy5wcmV2aW91c1Njcm9sbEJvdW5kaW5nUmVjdC53aWR0aCk7XHJcblx0XHRcdGNvbnN0IGhlaWdodENoYW5nZSA9IE1hdGguYWJzKGJvdW5kaW5nUmVjdC5oZWlnaHQgLSB0aGlzLnByZXZpb3VzU2Nyb2xsQm91bmRpbmdSZWN0LmhlaWdodCk7XHJcblx0XHRcdHNpemVDaGFuZ2VkID0gd2lkdGhDaGFuZ2UgPiB0aGlzLnJlc2l6ZUJ5cGFzc1JlZnJlc2hUaHJlc2hvbGQgfHwgaGVpZ2h0Q2hhbmdlID4gdGhpcy5yZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChzaXplQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLnByZXZpb3VzU2Nyb2xsQm91bmRpbmdSZWN0ID0gYm91bmRpbmdSZWN0O1xyXG5cdFx0XHRpZiAoYm91bmRpbmdSZWN0LndpZHRoID4gMCAmJiBib3VuZGluZ1JlY3QuaGVpZ2h0ID4gMCkge1xyXG5cdFx0XHRcdHRoaXMucmVmcmVzaF9pbnRlcm5hbChmYWxzZSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBfaW52aXNpYmxlUGFkZGluZ1Byb3BlcnR5O1xyXG5cdHByb3RlY3RlZCBfb2Zmc2V0VHlwZTtcclxuXHRwcm90ZWN0ZWQgX3Njcm9sbFR5cGU7XHJcblx0cHJvdGVjdGVkIF9wYWdlT2Zmc2V0VHlwZTtcclxuXHRwcm90ZWN0ZWQgX2NoaWxkU2Nyb2xsRGltO1xyXG5cdHByb3RlY3RlZCBfdHJhbnNsYXRlRGlyO1xyXG5cdHByb3RlY3RlZCBfbWFyZ2luRGlyO1xyXG5cdHByb3RlY3RlZCB1cGRhdGVEaXJlY3Rpb24oKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5ob3Jpem9udGFsKSB7XHJcblx0XHRcdHRoaXMuX2NoaWxkU2Nyb2xsRGltID0gJ2NoaWxkV2lkdGgnO1xyXG5cdFx0XHR0aGlzLl9pbnZpc2libGVQYWRkaW5nUHJvcGVydHkgPSAnc2NhbGVYJztcclxuXHRcdFx0dGhpcy5fbWFyZ2luRGlyID0gJ21hcmdpbi1sZWZ0JztcclxuXHRcdFx0dGhpcy5fb2Zmc2V0VHlwZSA9ICdvZmZzZXRMZWZ0JztcclxuXHRcdFx0dGhpcy5fcGFnZU9mZnNldFR5cGUgPSAncGFnZVhPZmZzZXQnO1xyXG5cdFx0XHR0aGlzLl9zY3JvbGxUeXBlID0gJ3Njcm9sbExlZnQnO1xyXG5cdFx0XHR0aGlzLl90cmFuc2xhdGVEaXIgPSAndHJhbnNsYXRlWCc7XHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0dGhpcy5fY2hpbGRTY3JvbGxEaW0gPSAnY2hpbGRIZWlnaHQnO1xyXG5cdFx0XHR0aGlzLl9pbnZpc2libGVQYWRkaW5nUHJvcGVydHkgPSAnc2NhbGVZJztcclxuXHRcdFx0dGhpcy5fbWFyZ2luRGlyID0gJ21hcmdpbi10b3AnO1xyXG5cdFx0XHR0aGlzLl9vZmZzZXRUeXBlID0gJ29mZnNldFRvcCc7XHJcblx0XHRcdHRoaXMuX3BhZ2VPZmZzZXRUeXBlID0gJ3BhZ2VZT2Zmc2V0JztcclxuXHRcdFx0dGhpcy5fc2Nyb2xsVHlwZSA9ICdzY3JvbGxUb3AnO1xyXG5cdFx0XHR0aGlzLl90cmFuc2xhdGVEaXIgPSAndHJhbnNsYXRlWSc7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgZGVib3VuY2UoZnVuYzogKCkgPT4gdm9pZCwgd2FpdDogbnVtYmVyLCAuLi5hcmdzKTogKCkgPT4gdm9pZCB7XHJcblx0XHRjb25zdCB0aHJvdHRsZWQgPSB0aGlzLnRocm90dGxlVHJhaWxpbmcoZnVuYywgd2FpdCk7XHJcblx0XHRjb25zdCByZXN1bHQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRocm90dGxlZFsnY2FuY2VsJ10oKTtcclxuXHRcdFx0dGhyb3R0bGVkLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG5cdFx0fTtcclxuXHRcdHJlc3VsdFsnY2FuY2VsJ10gPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRocm90dGxlZFsnY2FuY2VsJ10oKTtcclxuXHRcdH07XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCB0aHJvdHRsZVRyYWlsaW5nKGZ1bmM6ICgpID0+IHZvaWQsIHdhaXQ6IG51bWJlciwgLi4uYXJncyk6ICgpID0+IHZvaWQge1xyXG5cdFx0bGV0IHRpbWVvdXQgPSB1bmRlZmluZWQ7XHJcblx0XHRsZXQgX2FyZ3VtZW50cyA9IGFyZ3M7XHJcblx0XHRjb25zdCByZXN1bHQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdGNvbnN0IF90aGlzID0gdGhpcztcclxuXHRcdFx0X2FyZ3VtZW50cyA9IGFyZ3NcclxuXHJcblx0XHRcdGlmICh0aW1lb3V0KSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAod2FpdCA8PSAwKSB7XHJcblx0XHRcdFx0ZnVuYy5hcHBseShfdGhpcywgX2FyZ3VtZW50cyk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0dGltZW91dCA9IHVuZGVmaW5lZDtcclxuXHRcdFx0XHRcdGZ1bmMuYXBwbHkoX3RoaXMsIF9hcmd1bWVudHMpO1xyXG5cdFx0XHRcdH0sIHdhaXQpO1xyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdFx0cmVzdWx0WydjYW5jZWwnXSA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0aWYgKHRpbWVvdXQpIHtcclxuXHRcdFx0XHRjbGVhclRpbWVvdXQodGltZW91dCk7XHJcblx0XHRcdFx0dGltZW91dCA9IHVuZGVmaW5lZDtcclxuXHRcdFx0fVxyXG5cdFx0fTtcclxuXHJcblx0XHRyZXR1cm4gcmVzdWx0O1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIGNhbGN1bGF0ZWRTY3JvbGxiYXJXaWR0aCA9IDA7XHJcblx0cHJvdGVjdGVkIGNhbGN1bGF0ZWRTY3JvbGxiYXJIZWlnaHQgPSAwO1xyXG5cclxuXHRwcm90ZWN0ZWQgcGFkZGluZyA9IDA7XHJcblx0cHJvdGVjdGVkIHByZXZpb3VzVmlld1BvcnQ6IElWaWV3cG9ydCA9IDxhbnk+e307XHJcblx0cHJvdGVjdGVkIGN1cnJlbnRUd2VlbjogdHdlZW4uVHdlZW47XHJcblx0cHJvdGVjdGVkIGNhY2hlZEl0ZW1zTGVuZ3RoOiBudW1iZXI7XHJcblxyXG5cdHByb3RlY3RlZCBkaXNwb3NlU2Nyb2xsSGFuZGxlcjogKCkgPT4gdm9pZCB8IHVuZGVmaW5lZDtcclxuXHRwcm90ZWN0ZWQgZGlzcG9zZVJlc2l6ZUhhbmRsZXI6ICgpID0+IHZvaWQgfCB1bmRlZmluZWQ7XHJcblxyXG5cdHByb3RlY3RlZCByZWZyZXNoX2ludGVybmFsKGl0ZW1zQXJyYXlNb2RpZmllZDogYm9vbGVhbiwgcmVmcmVzaENvbXBsZXRlZENhbGxiYWNrOiAoKSA9PiB2b2lkID0gdW5kZWZpbmVkLCBtYXhSdW5UaW1lcyA9IDIpOiB2b2lkIHtcclxuXHRcdC8vbm90ZTogbWF4UnVuVGltZXMgaXMgdG8gZm9yY2UgaXQgdG8ga2VlcCByZWNhbGN1bGF0aW5nIGlmIHRoZSBwcmV2aW91cyBpdGVyYXRpb24gY2F1c2VkIGEgcmUtcmVuZGVyIChkaWZmZXJlbnQgc2xpY2VkIGl0ZW1zIGluIHZpZXdwb3J0IG9yIHNjcm9sbFBvc2l0aW9uIGNoYW5nZWQpLlxyXG5cdFx0Ly9UaGUgZGVmYXVsdCBvZiAyeCBtYXggd2lsbCBwcm9iYWJseSBiZSBhY2N1cmF0ZSBlbm91Z2ggd2l0aG91dCBjYXVzaW5nIHRvbyBsYXJnZSBhIHBlcmZvcm1hbmNlIGJvdHRsZW5lY2tcclxuXHRcdC8vVGhlIGNvZGUgd291bGQgdHlwaWNhbGx5IHF1aXQgb3V0IG9uIHRoZSAybmQgaXRlcmF0aW9uIGFueXdheXMuIFRoZSBtYWluIHRpbWUgaXQnZCB0aGluayBtb3JlIHRoYW4gMiBydW5zIHdvdWxkIGJlIG5lY2Vzc2FyeSB3b3VsZCBiZSBmb3IgdmFzdGx5IGRpZmZlcmVudCBzaXplZCBjaGlsZCBpdGVtcyBvciBpZiB0aGlzIGlzIHRoZSAxc3QgdGltZSB0aGUgaXRlbXMgYXJyYXkgd2FzIGluaXRpYWxpemVkLlxyXG5cdFx0Ly9XaXRob3V0IG1heFJ1blRpbWVzLCBJZiB0aGUgdXNlciBpcyBhY3RpdmVseSBzY3JvbGxpbmcgdGhpcyBjb2RlIHdvdWxkIGJlY29tZSBhbiBpbmZpbml0ZSBsb29wIHVudGlsIHRoZXkgc3RvcHBlZCBzY3JvbGxpbmcuIFRoaXMgd291bGQgYmUgb2theSwgZXhjZXB0IGVhY2ggc2Nyb2xsIGV2ZW50IHdvdWxkIHN0YXJ0IGFuIGFkZGl0aW9uYWwgaW5maW50ZSBsb29wLiBXZSB3YW50IHRvIHNob3J0LWNpcmN1aXQgaXQgdG8gcHJldmVudCB0aGlzLlxyXG5cclxuXHRcdGlmIChpdGVtc0FycmF5TW9kaWZpZWQgJiYgdGhpcy5wcmV2aW91c1ZpZXdQb3J0ICYmIHRoaXMucHJldmlvdXNWaWV3UG9ydC5zY3JvbGxTdGFydFBvc2l0aW9uID4gMCkge1xyXG5cdFx0XHQvL2lmIGl0ZW1zIHdlcmUgcHJlcGVuZGVkLCBzY3JvbGwgZm9yd2FyZCB0byBrZWVwIHNhbWUgaXRlbXMgdmlzaWJsZVxyXG5cdFx0XHRjb25zdCBvbGRWaWV3UG9ydCA9IHRoaXMucHJldmlvdXNWaWV3UG9ydDtcclxuXHRcdFx0Y29uc3Qgb2xkVmlld1BvcnRJdGVtcyA9IHRoaXMudmlld1BvcnRJdGVtcztcclxuXHJcblx0XHRcdGNvbnN0IG9sZFJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjayA9IHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaztcclxuXHRcdFx0cmVmcmVzaENvbXBsZXRlZENhbGxiYWNrID0gKCkgPT4ge1xyXG5cdFx0XHRcdGNvbnN0IHNjcm9sbExlbmd0aERlbHRhID0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbExlbmd0aCAtIG9sZFZpZXdQb3J0LnNjcm9sbExlbmd0aDtcclxuXHRcdFx0XHRpZiAoc2Nyb2xsTGVuZ3RoRGVsdGEgPiAwICYmIHRoaXMudmlld1BvcnRJdGVtcykge1xyXG5cdFx0XHRcdFx0Y29uc3Qgb2xkU3RhcnRJdGVtID0gb2xkVmlld1BvcnRJdGVtc1swXTtcclxuXHRcdFx0XHRcdGNvbnN0IG9sZFN0YXJ0SXRlbUluZGV4ID0gdGhpcy5pdGVtcy5maW5kSW5kZXgoeCA9PiB0aGlzLmNvbXBhcmVJdGVtcyhvbGRTdGFydEl0ZW0sIHgpKTtcclxuXHRcdFx0XHRcdGlmIChvbGRTdGFydEl0ZW1JbmRleCA+IHRoaXMucHJldmlvdXNWaWV3UG9ydC5zdGFydEluZGV4V2l0aEJ1ZmZlcikge1xyXG5cdFx0XHRcdFx0XHRsZXQgaXRlbU9yZGVyQ2hhbmdlZCA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0XHRmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMudmlld1BvcnRJdGVtcy5sZW5ndGg7ICsraSkge1xyXG5cdFx0XHRcdFx0XHRcdGlmICghdGhpcy5jb21wYXJlSXRlbXModGhpcy5pdGVtc1tvbGRTdGFydEl0ZW1JbmRleCArIGldLCBvbGRWaWV3UG9ydEl0ZW1zW2ldKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0aXRlbU9yZGVyQ2hhbmdlZCA9IHRydWU7XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRcdGlmICghaXRlbU9yZGVyQ2hhbmdlZCkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMuc2Nyb2xsVG9Qb3NpdGlvbih0aGlzLnByZXZpb3VzVmlld1BvcnQuc2Nyb2xsU3RhcnRQb3NpdGlvbiArIHNjcm9sbExlbmd0aERlbHRhLCAwLCBvbGRSZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2spO1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKG9sZFJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0b2xkUmVmcmVzaENvbXBsZXRlZENhbGxiYWNrKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9O1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcblx0XHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XHJcblxyXG5cdFx0XHRcdGlmIChpdGVtc0FycmF5TW9kaWZpZWQpIHtcclxuXHRcdFx0XHRcdHRoaXMucmVzZXRXcmFwR3JvdXBEaW1lbnNpb25zKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5jYWxjdWxhdGVWaWV3cG9ydCgpO1xyXG5cclxuXHRcdFx0XHRjb25zdCBzdGFydENoYW5nZWQgPSBpdGVtc0FycmF5TW9kaWZpZWQgfHwgdmlld3BvcnQuc3RhcnRJbmRleCAhPT0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnN0YXJ0SW5kZXg7XHJcblx0XHRcdFx0Y29uc3QgZW5kQ2hhbmdlZCA9IGl0ZW1zQXJyYXlNb2RpZmllZCB8fCB2aWV3cG9ydC5lbmRJbmRleCAhPT0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LmVuZEluZGV4O1xyXG5cdFx0XHRcdGNvbnN0IHNjcm9sbExlbmd0aENoYW5nZWQgPSB2aWV3cG9ydC5zY3JvbGxMZW5ndGggIT09IHRoaXMucHJldmlvdXNWaWV3UG9ydC5zY3JvbGxMZW5ndGg7XHJcblx0XHRcdFx0Y29uc3QgcGFkZGluZ0NoYW5nZWQgPSB2aWV3cG9ydC5wYWRkaW5nICE9PSB0aGlzLnByZXZpb3VzVmlld1BvcnQucGFkZGluZztcclxuXHRcdFx0XHRjb25zdCBzY3JvbGxQb3NpdGlvbkNoYW5nZWQgPSB2aWV3cG9ydC5zY3JvbGxTdGFydFBvc2l0aW9uICE9PSB0aGlzLnByZXZpb3VzVmlld1BvcnQuc2Nyb2xsU3RhcnRQb3NpdGlvbiB8fCB2aWV3cG9ydC5zY3JvbGxFbmRQb3NpdGlvbiAhPT0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbEVuZFBvc2l0aW9uIHx8IHZpZXdwb3J0Lm1heFNjcm9sbFBvc2l0aW9uICE9PSB0aGlzLnByZXZpb3VzVmlld1BvcnQubWF4U2Nyb2xsUG9zaXRpb247XHJcblxyXG5cdFx0XHRcdGNvbnN0IHNjcm9sbERpcmVjdGlvbjogU2Nyb2xsRGlyZWN0aW9uVHlwZSA9IHRoaXMucHJldmlvdXNWaWV3UG9ydC5lbmRJbmRleCA8PSB2aWV3cG9ydC5lbmRJbmRleCA/ICdmb3J3YXJkJyA6ICdiYWNrd2FyZCc7XHJcblx0XHRcdFx0dGhpcy5wcmV2aW91c1ZpZXdQb3J0ID0gdmlld3BvcnQ7XHJcblxyXG5cdFx0XHRcdGlmIChzY3JvbGxMZW5ndGhDaGFuZ2VkKSB7XHJcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuaW52aXNpYmxlUGFkZGluZ0VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3RyYW5zZm9ybScsIGAke3RoaXMuX2ludmlzaWJsZVBhZGRpbmdQcm9wZXJ0eX0oJHt2aWV3cG9ydC5zY3JvbGxMZW5ndGh9KWApO1xyXG5cdFx0XHRcdFx0dGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmludmlzaWJsZVBhZGRpbmdFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICd3ZWJraXRUcmFuc2Zvcm0nLCBgJHt0aGlzLl9pbnZpc2libGVQYWRkaW5nUHJvcGVydHl9KCR7dmlld3BvcnQuc2Nyb2xsTGVuZ3RofSlgKTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGlmIChwYWRkaW5nQ2hhbmdlZCkge1xyXG5cdFx0XHRcdFx0aWYgKHRoaXMudXNlTWFyZ2luSW5zdGVhZE9mVHJhbnNsYXRlKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jb250ZW50RWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCB0aGlzLl9tYXJnaW5EaXIsIGAke3ZpZXdwb3J0LnBhZGRpbmd9cHhgKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3RyYW5zZm9ybScsIGAke3RoaXMuX3RyYW5zbGF0ZURpcn0oJHt2aWV3cG9ydC5wYWRkaW5nfXB4KWApO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3dlYmtpdFRyYW5zZm9ybScsIGAke3RoaXMuX3RyYW5zbGF0ZURpcn0oJHt2aWV3cG9ydC5wYWRkaW5nfXB4KWApO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKHRoaXMuaGVhZGVyRWxlbWVudFJlZikge1xyXG5cdFx0XHRcdFx0Y29uc3Qgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKVt0aGlzLl9zY3JvbGxUeXBlXTtcclxuXHRcdFx0XHRcdGNvbnN0IGNvbnRhaW5lck9mZnNldCA9IHRoaXMuZ2V0RWxlbWVudHNPZmZzZXQoKTtcclxuXHRcdFx0XHRcdGNvbnN0IG9mZnNldCA9IE1hdGgubWF4KHNjcm9sbFBvc2l0aW9uIC0gdmlld3BvcnQucGFkZGluZyAtIGNvbnRhaW5lck9mZnNldCArIHRoaXMuaGVhZGVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodCwgMCk7XHJcblx0XHRcdFx0XHR0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuaGVhZGVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndHJhbnNmb3JtJywgYCR7dGhpcy5fdHJhbnNsYXRlRGlyfSgke29mZnNldH1weClgKTtcclxuXHRcdFx0XHRcdHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5oZWFkZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICd3ZWJraXRUcmFuc2Zvcm0nLCBgJHt0aGlzLl90cmFuc2xhdGVEaXJ9KCR7b2Zmc2V0fXB4KWApO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Y29uc3QgY2hhbmdlRXZlbnRBcmc6IElQYWdlSW5mbyA9IChzdGFydENoYW5nZWQgfHwgZW5kQ2hhbmdlZCkgPyB7XHJcblx0XHRcdFx0XHRzdGFydEluZGV4OiB2aWV3cG9ydC5zdGFydEluZGV4LFxyXG5cdFx0XHRcdFx0ZW5kSW5kZXg6IHZpZXdwb3J0LmVuZEluZGV4LFxyXG5cdFx0XHRcdFx0c2Nyb2xsU3RhcnRQb3NpdGlvbjogdmlld3BvcnQuc2Nyb2xsU3RhcnRQb3NpdGlvbixcclxuXHRcdFx0XHRcdHNjcm9sbEVuZFBvc2l0aW9uOiB2aWV3cG9ydC5zY3JvbGxFbmRQb3NpdGlvbixcclxuXHRcdFx0XHRcdHNjcm9sbERpcmVjdGlvbjogc2Nyb2xsRGlyZWN0aW9uLFxyXG5cdFx0XHRcdFx0c3RhcnRJbmRleFdpdGhCdWZmZXI6IHZpZXdwb3J0LnN0YXJ0SW5kZXhXaXRoQnVmZmVyLFxyXG5cdFx0XHRcdFx0ZW5kSW5kZXhXaXRoQnVmZmVyOiB2aWV3cG9ydC5lbmRJbmRleFdpdGhCdWZmZXIsXHJcblx0XHRcdFx0XHRtYXhTY3JvbGxQb3NpdGlvbjogdmlld3BvcnQubWF4U2Nyb2xsUG9zaXRpb24sXHJcblx0XHRcdFx0fSA6IHVuZGVmaW5lZDtcclxuXHJcblxyXG5cdFx0XHRcdGlmIChzdGFydENoYW5nZWQgfHwgZW5kQ2hhbmdlZCB8fCBzY3JvbGxQb3NpdGlvbkNoYW5nZWQpIHtcclxuXHRcdFx0XHRcdGNvbnN0IGhhbmRsZUNoYW5nZWQgPSAoKSA9PiB7XHJcblx0XHRcdFx0XHRcdC8vIHVwZGF0ZSB0aGUgc2Nyb2xsIGxpc3QgdG8gdHJpZ2dlciByZS1yZW5kZXIgb2YgY29tcG9uZW50cyBpbiB2aWV3cG9ydFxyXG5cdFx0XHRcdFx0XHR0aGlzLnZpZXdQb3J0SXRlbXMgPSB2aWV3cG9ydC5zdGFydEluZGV4V2l0aEJ1ZmZlciA+PSAwICYmIHZpZXdwb3J0LmVuZEluZGV4V2l0aEJ1ZmZlciA+PSAwID8gdGhpcy5pdGVtcy5zbGljZSh2aWV3cG9ydC5zdGFydEluZGV4V2l0aEJ1ZmZlciwgdmlld3BvcnQuZW5kSW5kZXhXaXRoQnVmZmVyICsgMSkgOiBbXTtcclxuXHRcdFx0XHRcdFx0dGhpcy52c1VwZGF0ZS5lbWl0KHRoaXMudmlld1BvcnRJdGVtcyk7XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoc3RhcnRDaGFuZ2VkKSB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy52c1N0YXJ0LmVtaXQoY2hhbmdlRXZlbnRBcmcpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoZW5kQ2hhbmdlZCkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMudnNFbmQuZW1pdChjaGFuZ2VFdmVudEFyZyk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRcdGlmIChzdGFydENoYW5nZWQgfHwgZW5kQ2hhbmdlZCkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy52c0NoYW5nZS5lbWl0KGNoYW5nZUV2ZW50QXJnKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0aWYgKG1heFJ1blRpbWVzID4gMCkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucmVmcmVzaF9pbnRlcm5hbChmYWxzZSwgcmVmcmVzaENvbXBsZXRlZENhbGxiYWNrLCBtYXhSdW5UaW1lcyAtIDEpO1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0aWYgKHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0XHRcdHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaygpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9O1xyXG5cclxuXHJcblx0XHRcdFx0XHRpZiAodGhpcy5leGVjdXRlUmVmcmVzaE91dHNpZGVBbmd1bGFyWm9uZSkge1xyXG5cdFx0XHRcdFx0XHRoYW5kbGVDaGFuZ2VkKCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0dGhpcy56b25lLnJ1bihoYW5kbGVDaGFuZ2VkKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0aWYgKG1heFJ1blRpbWVzID4gMCAmJiAoc2Nyb2xsTGVuZ3RoQ2hhbmdlZCB8fCBwYWRkaW5nQ2hhbmdlZCkpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlLCByZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2ssIG1heFJ1blRpbWVzIC0gMSk7XHJcblx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRpZiAocmVmcmVzaENvbXBsZXRlZENhbGxiYWNrKSB7XHJcblx0XHRcdFx0XHRcdHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaygpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBnZXRTY3JvbGxFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcclxuXHRcdHJldHVybiB0aGlzLnBhcmVudFNjcm9sbCBpbnN0YW5jZW9mIFdpbmRvdyA/IGRvY3VtZW50LnNjcm9sbGluZ0VsZW1lbnQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IHx8IGRvY3VtZW50LmJvZHkgOiB0aGlzLnBhcmVudFNjcm9sbCB8fCB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBhZGRTY3JvbGxFdmVudEhhbmRsZXJzKCk6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XHJcblxyXG5cdFx0dGhpcy5yZW1vdmVTY3JvbGxFdmVudEhhbmRsZXJzKCk7XHJcblxyXG5cdFx0dGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuXHRcdFx0aWYgKHRoaXMucGFyZW50U2Nyb2xsIGluc3RhbmNlb2YgV2luZG93KSB7XHJcblx0XHRcdFx0dGhpcy5kaXNwb3NlU2Nyb2xsSGFuZGxlciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKCd3aW5kb3cnLCAnc2Nyb2xsJywgdGhpcy5vblNjcm9sbCk7XHJcblx0XHRcdFx0dGhpcy5kaXNwb3NlUmVzaXplSGFuZGxlciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKCd3aW5kb3cnLCAncmVzaXplJywgdGhpcy5vblNjcm9sbCk7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0dGhpcy5kaXNwb3NlU2Nyb2xsSGFuZGxlciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKHNjcm9sbEVsZW1lbnQsICdzY3JvbGwnLCB0aGlzLm9uU2Nyb2xsKTtcclxuXHRcdFx0XHRpZiAodGhpcy5fY2hlY2tSZXNpemVJbnRlcnZhbCA+IDApIHtcclxuXHRcdFx0XHRcdHRoaXMuY2hlY2tTY3JvbGxFbGVtZW50UmVzaXplZFRpbWVyID0gPGFueT5zZXRJbnRlcnZhbCgoKSA9PiB7IHRoaXMuY2hlY2tTY3JvbGxFbGVtZW50UmVzaXplZCgpOyB9LCB0aGlzLl9jaGVja1Jlc2l6ZUludGVydmFsKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIHJlbW92ZVNjcm9sbEV2ZW50SGFuZGxlcnMoKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5jaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkVGltZXIpIHtcclxuXHRcdFx0Y2xlYXJJbnRlcnZhbCh0aGlzLmNoZWNrU2Nyb2xsRWxlbWVudFJlc2l6ZWRUaW1lcik7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMuZGlzcG9zZVNjcm9sbEhhbmRsZXIpIHtcclxuXHRcdFx0dGhpcy5kaXNwb3NlU2Nyb2xsSGFuZGxlcigpO1xyXG5cdFx0XHR0aGlzLmRpc3Bvc2VTY3JvbGxIYW5kbGVyID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLmRpc3Bvc2VSZXNpemVIYW5kbGVyKSB7XHJcblx0XHRcdHRoaXMuZGlzcG9zZVJlc2l6ZUhhbmRsZXIoKTtcclxuXHRcdFx0dGhpcy5kaXNwb3NlUmVzaXplSGFuZGxlciA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBnZXRFbGVtZW50c09mZnNldCgpOiBudW1iZXIge1xyXG5cdFx0aWYgKHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSKSB7XHJcblx0XHRcdHJldHVybiAwO1xyXG5cdFx0fVxyXG5cclxuXHRcdGxldCBvZmZzZXQgPSAwO1xyXG5cclxuXHRcdGlmICh0aGlzLmNvbnRhaW5lckVsZW1lbnRSZWYgJiYgdGhpcy5jb250YWluZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpIHtcclxuXHRcdFx0b2Zmc2V0ICs9IHRoaXMuY29udGFpbmVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50W3RoaXMuX29mZnNldFR5cGVdO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLnBhcmVudFNjcm9sbCkge1xyXG5cdFx0XHRjb25zdCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XHJcblx0XHRcdGNvbnN0IGVsZW1lbnRDbGllbnRSZWN0ID0gdGhpcy5nZXRFbGVtZW50U2l6ZSh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XHJcblx0XHRcdGNvbnN0IHNjcm9sbENsaWVudFJlY3QgPSB0aGlzLmdldEVsZW1lbnRTaXplKHNjcm9sbEVsZW1lbnQpO1xyXG5cdFx0XHRpZiAodGhpcy5ob3Jpem9udGFsKSB7XHJcblx0XHRcdFx0b2Zmc2V0ICs9IGVsZW1lbnRDbGllbnRSZWN0LmxlZnQgLSBzY3JvbGxDbGllbnRSZWN0LmxlZnQ7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0b2Zmc2V0ICs9IGVsZW1lbnRDbGllbnRSZWN0LnRvcCAtIHNjcm9sbENsaWVudFJlY3QudG9wO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAoISh0aGlzLnBhcmVudFNjcm9sbCBpbnN0YW5jZW9mIFdpbmRvdykpIHtcclxuXHRcdFx0XHRvZmZzZXQgKz0gc2Nyb2xsRWxlbWVudFt0aGlzLl9zY3JvbGxUeXBlXTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBvZmZzZXQ7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgY291bnRJdGVtc1BlcldyYXBHcm91cCgpOiBudW1iZXIge1xyXG5cdFx0aWYgKHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSKSB7XHJcblx0XHRcdHJldHVybiBNYXRoLnJvdW5kKHRoaXMuaG9yaXpvbnRhbCA/IHRoaXMuc3NyVmlld3BvcnRIZWlnaHQgLyB0aGlzLnNzckNoaWxkSGVpZ2h0IDogdGhpcy5zc3JWaWV3cG9ydFdpZHRoIC8gdGhpcy5zc3JDaGlsZFdpZHRoKTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBwcm9wZXJ0eU5hbWUgPSB0aGlzLmhvcml6b250YWwgPyAnb2Zmc2V0TGVmdCcgOiAnb2Zmc2V0VG9wJztcclxuXHRcdGNvbnN0IGNoaWxkcmVuID0gKCh0aGlzLmNvbnRhaW5lckVsZW1lbnRSZWYgJiYgdGhpcy5jb250YWluZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpIHx8IHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkuY2hpbGRyZW47XHJcblxyXG5cdFx0Y29uc3QgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbiA/IGNoaWxkcmVuLmxlbmd0aCA6IDA7XHJcblx0XHRpZiAoY2hpbGRyZW5MZW5ndGggPT09IDApIHtcclxuXHRcdFx0cmV0dXJuIDE7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgZmlyc3RPZmZzZXQgPSBjaGlsZHJlblswXVtwcm9wZXJ0eU5hbWVdO1xyXG5cdFx0bGV0IHJlc3VsdCA9IDE7XHJcblx0XHR3aGlsZSAocmVzdWx0IDwgY2hpbGRyZW5MZW5ndGggJiYgZmlyc3RPZmZzZXQgPT09IGNoaWxkcmVuW3Jlc3VsdF1bcHJvcGVydHlOYW1lXSkge1xyXG5cdFx0XHQrK3Jlc3VsdDtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcmVzdWx0O1xyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIGdldFNjcm9sbFN0YXJ0UG9zaXRpb24oKTogbnVtYmVyIHtcclxuXHRcdGxldCB3aW5kb3dTY3JvbGxWYWx1ZSA9IHVuZGVmaW5lZDtcclxuXHRcdGlmICh0aGlzLnBhcmVudFNjcm9sbCBpbnN0YW5jZW9mIFdpbmRvdykge1xyXG5cdFx0XHR3aW5kb3dTY3JvbGxWYWx1ZSA9IHdpbmRvd1t0aGlzLl9wYWdlT2Zmc2V0VHlwZV07XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHdpbmRvd1Njcm9sbFZhbHVlIHx8IHRoaXMuZ2V0U2Nyb2xsRWxlbWVudCgpW3RoaXMuX3Njcm9sbFR5cGVdIHx8IDA7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgbWluTWVhc3VyZWRDaGlsZFdpZHRoOiBudW1iZXI7XHJcblx0cHJvdGVjdGVkIG1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQ6IG51bWJlcjtcclxuXHJcblx0cHJvdGVjdGVkIHdyYXBHcm91cERpbWVuc2lvbnM6IFdyYXBHcm91cERpbWVuc2lvbnM7XHJcblxyXG5cdHByb3RlY3RlZCByZXNldFdyYXBHcm91cERpbWVuc2lvbnMoKTogdm9pZCB7XHJcblx0XHRjb25zdCBvbGRXcmFwR3JvdXBEaW1lbnNpb25zID0gdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zO1xyXG5cdFx0dGhpcy5pbnZhbGlkYXRlQWxsQ2FjaGVkTWVhc3VyZW1lbnRzKCk7XHJcblxyXG5cdFx0aWYgKCF0aGlzLmVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzIHx8ICFvbGRXcmFwR3JvdXBEaW1lbnNpb25zIHx8IG9sZFdyYXBHcm91cERpbWVuc2lvbnMubnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXMgPT09IDApIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGl0ZW1zUGVyV3JhcEdyb3VwOiBudW1iZXIgPSB0aGlzLmNvdW50SXRlbXNQZXJXcmFwR3JvdXAoKTtcclxuXHRcdGZvciAobGV0IHdyYXBHcm91cEluZGV4ID0gMDsgd3JhcEdyb3VwSW5kZXggPCBvbGRXcmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cC5sZW5ndGg7ICsrd3JhcEdyb3VwSW5kZXgpIHtcclxuXHRcdFx0Y29uc3Qgb2xkV3JhcEdyb3VwRGltZW5zaW9uOiBXcmFwR3JvdXBEaW1lbnNpb24gPSBvbGRXcmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFt3cmFwR3JvdXBJbmRleF07XHJcblx0XHRcdGlmICghb2xkV3JhcEdyb3VwRGltZW5zaW9uIHx8ICFvbGRXcmFwR3JvdXBEaW1lbnNpb24uaXRlbXMgfHwgIW9sZFdyYXBHcm91cERpbWVuc2lvbi5pdGVtcy5sZW5ndGgpIHtcclxuXHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKG9sZFdyYXBHcm91cERpbWVuc2lvbi5pdGVtcy5sZW5ndGggIT09IGl0ZW1zUGVyV3JhcEdyb3VwKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRsZXQgaXRlbXNDaGFuZ2VkID0gZmFsc2U7XHJcblx0XHRcdGNvbnN0IGFycmF5U3RhcnRJbmRleCA9IGl0ZW1zUGVyV3JhcEdyb3VwICogd3JhcEdyb3VwSW5kZXg7XHJcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXNQZXJXcmFwR3JvdXA7ICsraSkge1xyXG5cdFx0XHRcdGlmICghdGhpcy5jb21wYXJlSXRlbXMob2xkV3JhcEdyb3VwRGltZW5zaW9uLml0ZW1zW2ldLCB0aGlzLml0ZW1zW2FycmF5U3RhcnRJbmRleCArIGldKSkge1xyXG5cdFx0XHRcdFx0aXRlbXNDaGFuZ2VkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKCFpdGVtc0NoYW5nZWQpIHtcclxuXHRcdFx0XHQrK3RoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5udW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplcztcclxuXHRcdFx0XHR0aGlzLndyYXBHcm91cERpbWVuc2lvbnMuc3VtT2ZLbm93bldyYXBHcm91cENoaWxkV2lkdGhzICs9IG9sZFdyYXBHcm91cERpbWVuc2lvbi5jaGlsZFdpZHRoIHx8IDA7XHJcblx0XHRcdFx0dGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHMgKz0gb2xkV3JhcEdyb3VwRGltZW5zaW9uLmNoaWxkSGVpZ2h0IHx8IDA7XHJcblx0XHRcdFx0dGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFt3cmFwR3JvdXBJbmRleF0gPSBvbGRXcmFwR3JvdXBEaW1lbnNpb247XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByb3RlY3RlZCBjYWxjdWxhdGVEaW1lbnNpb25zKCk6IElEaW1lbnNpb25zIHtcclxuXHRcdGNvbnN0IHNjcm9sbEVsZW1lbnQgPSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKTtcclxuXHJcblx0XHRjb25zdCBtYXhDYWxjdWxhdGVkU2Nyb2xsQmFyU2l6ZSA9IDI1OyAvLyBOb3RlOiBGb3JtdWxhIHRvIGF1dG8tY2FsY3VsYXRlIGRvZXNuJ3Qgd29yayBmb3IgUGFyZW50U2Nyb2xsLCBzbyB3ZSBkZWZhdWx0IHRvIHRoaXMgaWYgbm90IHNldCBieSBjb25zdW1pbmcgYXBwbGljYXRpb25cclxuXHRcdHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodCA9IE1hdGgubWF4KE1hdGgubWluKHNjcm9sbEVsZW1lbnQub2Zmc2V0SGVpZ2h0IC0gc2Nyb2xsRWxlbWVudC5jbGllbnRIZWlnaHQsIG1heENhbGN1bGF0ZWRTY3JvbGxCYXJTaXplKSwgdGhpcy5jYWxjdWxhdGVkU2Nyb2xsYmFySGVpZ2h0KTtcclxuXHRcdHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoID0gTWF0aC5tYXgoTWF0aC5taW4oc2Nyb2xsRWxlbWVudC5vZmZzZXRXaWR0aCAtIHNjcm9sbEVsZW1lbnQuY2xpZW50V2lkdGgsIG1heENhbGN1bGF0ZWRTY3JvbGxCYXJTaXplKSwgdGhpcy5jYWxjdWxhdGVkU2Nyb2xsYmFyV2lkdGgpO1xyXG5cclxuXHRcdGxldCB2aWV3cG9ydFdpZHRoID0gc2Nyb2xsRWxlbWVudC5vZmZzZXRXaWR0aCAtICh0aGlzLnNjcm9sbGJhcldpZHRoIHx8IHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoIHx8ICh0aGlzLmhvcml6b250YWwgPyAwIDogbWF4Q2FsY3VsYXRlZFNjcm9sbEJhclNpemUpKTtcclxuXHRcdGxldCB2aWV3cG9ydEhlaWdodCA9IHNjcm9sbEVsZW1lbnQub2Zmc2V0SGVpZ2h0IC0gKHRoaXMuc2Nyb2xsYmFySGVpZ2h0IHx8IHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodCB8fCAodGhpcy5ob3Jpem9udGFsID8gbWF4Q2FsY3VsYXRlZFNjcm9sbEJhclNpemUgOiAwKSk7XHJcblxyXG5cdFx0Y29uc3QgY29udGVudCA9ICh0aGlzLmNvbnRhaW5lckVsZW1lbnRSZWYgJiYgdGhpcy5jb250YWluZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpIHx8IHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcclxuXHJcblx0XHRjb25zdCBpdGVtc1BlcldyYXBHcm91cCA9IHRoaXMuY291bnRJdGVtc1BlcldyYXBHcm91cCgpO1xyXG5cdFx0bGV0IHdyYXBHcm91cHNQZXJQYWdlO1xyXG5cclxuXHRcdGxldCBkZWZhdWx0Q2hpbGRXaWR0aDtcclxuXHRcdGxldCBkZWZhdWx0Q2hpbGRIZWlnaHQ7XHJcblxyXG5cdFx0aWYgKHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSKSB7XHJcblx0XHRcdHZpZXdwb3J0V2lkdGggPSB0aGlzLnNzclZpZXdwb3J0V2lkdGg7XHJcblx0XHRcdHZpZXdwb3J0SGVpZ2h0ID0gdGhpcy5zc3JWaWV3cG9ydEhlaWdodDtcclxuXHRcdFx0ZGVmYXVsdENoaWxkV2lkdGggPSB0aGlzLnNzckNoaWxkV2lkdGg7XHJcblx0XHRcdGRlZmF1bHRDaGlsZEhlaWdodCA9IHRoaXMuc3NyQ2hpbGRIZWlnaHQ7XHJcblx0XHRcdGNvbnN0IGl0ZW1zUGVyUm93ID0gTWF0aC5tYXgoTWF0aC5jZWlsKHZpZXdwb3J0V2lkdGggLyBkZWZhdWx0Q2hpbGRXaWR0aCksIDEpO1xyXG5cdFx0XHRjb25zdCBpdGVtc1BlckNvbCA9IE1hdGgubWF4KE1hdGguY2VpbCh2aWV3cG9ydEhlaWdodCAvIGRlZmF1bHRDaGlsZEhlaWdodCksIDEpO1xyXG5cdFx0XHR3cmFwR3JvdXBzUGVyUGFnZSA9IHRoaXMuaG9yaXpvbnRhbCA/IGl0ZW1zUGVyUm93IDogaXRlbXNQZXJDb2w7XHJcblx0XHR9XHJcblx0XHRlbHNlIGlmICghdGhpcy5lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcykge1xyXG5cdFx0XHRpZiAoY29udGVudC5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0aWYgKCF0aGlzLmNoaWxkV2lkdGggfHwgIXRoaXMuY2hpbGRIZWlnaHQpIHtcclxuXHRcdFx0XHRcdGlmICghdGhpcy5taW5NZWFzdXJlZENoaWxkV2lkdGggJiYgdmlld3BvcnRXaWR0aCA+IDApIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5taW5NZWFzdXJlZENoaWxkV2lkdGggPSB2aWV3cG9ydFdpZHRoO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aWYgKCF0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgJiYgdmlld3BvcnRIZWlnaHQgPiAwKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMubWluTWVhc3VyZWRDaGlsZEhlaWdodCA9IHZpZXdwb3J0SGVpZ2h0O1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Y29uc3QgY2hpbGQgPSBjb250ZW50LmNoaWxkcmVuWzBdO1xyXG5cdFx0XHRcdGNvbnN0IGNsaWVudFJlY3QgPSB0aGlzLmdldEVsZW1lbnRTaXplKGNoaWxkKTtcclxuXHRcdFx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCA9IE1hdGgubWluKHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoLCBjbGllbnRSZWN0LndpZHRoKTtcclxuXHRcdFx0XHR0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSBNYXRoLm1pbih0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQsIGNsaWVudFJlY3QuaGVpZ2h0KTtcclxuXHJcblx0XHRcdFx0Ly8gQWRkZWQgZm9yIGdldHRpbmcgdGhlIGNoaWxkIGhlaWdodCAoZm9yIGNhcmQgdmlldywgcmV0dXJuIGFsbCB0aGUgY2xpZW50UmVjdCBvYmplY3QpLlxyXG5cdFx0XHRcdGlmICh0aGlzLl9sYXN0Q2hpbGRSZWN0Py5oZWlnaHQgIT09IGNsaWVudFJlY3Q/LmhlaWdodCB8fFxyXG5cdFx0XHRcdFx0dGhpcy5fbGFzdENoaWxkUmVjdD8ud2lkdGggIT09IGNsaWVudFJlY3Q/LndpZHRoKSB7XHJcblx0XHRcdFx0XHR0aGlzLl9sYXN0Q2hpbGRSZWN0ID0gY2xpZW50UmVjdDtcclxuXHRcdFx0XHRcdHRoaXMudnNDaGlsZFJlY3RDaGFuZ2UuZW1pdChjbGllbnRSZWN0KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGRlZmF1bHRDaGlsZFdpZHRoID0gdGhpcy5jaGlsZFdpZHRoIHx8IHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoIHx8IHZpZXdwb3J0V2lkdGg7XHJcblx0XHRcdGRlZmF1bHRDaGlsZEhlaWdodCA9IHRoaXMuY2hpbGRIZWlnaHQgfHwgdGhpcy5taW5NZWFzdXJlZENoaWxkSGVpZ2h0IHx8IHZpZXdwb3J0SGVpZ2h0O1xyXG5cdFx0XHRjb25zdCBpdGVtc1BlclJvdyA9IE1hdGgubWF4KE1hdGguY2VpbCh2aWV3cG9ydFdpZHRoIC8gZGVmYXVsdENoaWxkV2lkdGgpLCAxKTtcclxuXHRcdFx0Y29uc3QgaXRlbXNQZXJDb2wgPSBNYXRoLm1heChNYXRoLmNlaWwodmlld3BvcnRIZWlnaHQgLyBkZWZhdWx0Q2hpbGRIZWlnaHQpLCAxKTtcclxuXHRcdFx0d3JhcEdyb3Vwc1BlclBhZ2UgPSB0aGlzLmhvcml6b250YWwgPyBpdGVtc1BlclJvdyA6IGl0ZW1zUGVyQ29sO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0bGV0IHNjcm9sbE9mZnNldCA9IHNjcm9sbEVsZW1lbnRbdGhpcy5fc2Nyb2xsVHlwZV0gLSAodGhpcy5wcmV2aW91c1ZpZXdQb3J0ID8gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnBhZGRpbmcgOiAwKTtcclxuXHJcblx0XHRcdGxldCBhcnJheVN0YXJ0SW5kZXggPSB0aGlzLnByZXZpb3VzVmlld1BvcnQuc3RhcnRJbmRleFdpdGhCdWZmZXIgfHwgMDtcclxuXHRcdFx0bGV0IHdyYXBHcm91cEluZGV4ID0gTWF0aC5jZWlsKGFycmF5U3RhcnRJbmRleCAvIGl0ZW1zUGVyV3JhcEdyb3VwKTtcclxuXHJcblx0XHRcdGxldCBtYXhXaWR0aEZvcldyYXBHcm91cCA9IDA7XHJcblx0XHRcdGxldCBtYXhIZWlnaHRGb3JXcmFwR3JvdXAgPSAwO1xyXG5cdFx0XHRsZXQgc3VtT2ZWaXNpYmxlTWF4V2lkdGhzID0gMDtcclxuXHRcdFx0bGV0IHN1bU9mVmlzaWJsZU1heEhlaWdodHMgPSAwO1xyXG5cdFx0XHR3cmFwR3JvdXBzUGVyUGFnZSA9IDA7XHJcblxyXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNvbnRlbnQuY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcclxuXHRcdFx0XHQrK2FycmF5U3RhcnRJbmRleDtcclxuXHRcdFx0XHRjb25zdCBjaGlsZCA9IGNvbnRlbnQuY2hpbGRyZW5baV07XHJcblx0XHRcdFx0Y29uc3QgY2xpZW50UmVjdCA9IHRoaXMuZ2V0RWxlbWVudFNpemUoY2hpbGQpO1xyXG5cclxuXHRcdFx0XHRtYXhXaWR0aEZvcldyYXBHcm91cCA9IE1hdGgubWF4KG1heFdpZHRoRm9yV3JhcEdyb3VwLCBjbGllbnRSZWN0LndpZHRoKTtcclxuXHRcdFx0XHRtYXhIZWlnaHRGb3JXcmFwR3JvdXAgPSBNYXRoLm1heChtYXhIZWlnaHRGb3JXcmFwR3JvdXAsIGNsaWVudFJlY3QuaGVpZ2h0KTtcclxuXHJcblx0XHRcdFx0aWYgKGFycmF5U3RhcnRJbmRleCAlIGl0ZW1zUGVyV3JhcEdyb3VwID09PSAwKSB7XHJcblx0XHRcdFx0XHRjb25zdCBvbGRWYWx1ZSA9IHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbd3JhcEdyb3VwSW5kZXhdO1xyXG5cdFx0XHRcdFx0aWYgKG9sZFZhbHVlKSB7XHJcblx0XHRcdFx0XHRcdC0tdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm51bWJlck9mS25vd25XcmFwR3JvdXBDaGlsZFNpemVzO1xyXG5cdFx0XHRcdFx0XHR0aGlzLndyYXBHcm91cERpbWVuc2lvbnMuc3VtT2ZLbm93bldyYXBHcm91cENoaWxkV2lkdGhzIC09IG9sZFZhbHVlLmNoaWxkV2lkdGggfHwgMDtcclxuXHRcdFx0XHRcdFx0dGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHMgLT0gb2xkVmFsdWUuY2hpbGRIZWlnaHQgfHwgMDtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHQrK3RoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5udW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplcztcclxuXHRcdFx0XHRcdGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtcy5zbGljZShhcnJheVN0YXJ0SW5kZXggLSBpdGVtc1BlcldyYXBHcm91cCwgYXJyYXlTdGFydEluZGV4KTtcclxuXHRcdFx0XHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbd3JhcEdyb3VwSW5kZXhdID0ge1xyXG5cdFx0XHRcdFx0XHRjaGlsZFdpZHRoOiBtYXhXaWR0aEZvcldyYXBHcm91cCxcclxuXHRcdFx0XHRcdFx0Y2hpbGRIZWlnaHQ6IG1heEhlaWdodEZvcldyYXBHcm91cCxcclxuXHRcdFx0XHRcdFx0aXRlbXM6IGl0ZW1zXHJcblx0XHRcdFx0XHR9O1xyXG5cdFx0XHRcdFx0dGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRocyArPSBtYXhXaWR0aEZvcldyYXBHcm91cDtcclxuXHRcdFx0XHRcdHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRIZWlnaHRzICs9IG1heEhlaWdodEZvcldyYXBHcm91cDtcclxuXHJcblx0XHRcdFx0XHRpZiAodGhpcy5ob3Jpem9udGFsKSB7XHJcblx0XHRcdFx0XHRcdGxldCBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXAgPSBNYXRoLm1pbihtYXhXaWR0aEZvcldyYXBHcm91cCwgTWF0aC5tYXgodmlld3BvcnRXaWR0aCAtIHN1bU9mVmlzaWJsZU1heFdpZHRocywgMCkpO1xyXG5cdFx0XHRcdFx0XHRpZiAoc2Nyb2xsT2Zmc2V0ID4gMCkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHNjcm9sbE9mZnNldFRvUmVtb3ZlID0gTWF0aC5taW4oc2Nyb2xsT2Zmc2V0LCBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXApO1xyXG5cdFx0XHRcdFx0XHRcdG1heFZpc2libGVXaWR0aEZvcldyYXBHcm91cCAtPSBzY3JvbGxPZmZzZXRUb1JlbW92ZTtcclxuXHRcdFx0XHRcdFx0XHRzY3JvbGxPZmZzZXQgLT0gc2Nyb2xsT2Zmc2V0VG9SZW1vdmU7XHJcblx0XHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRcdHN1bU9mVmlzaWJsZU1heFdpZHRocyArPSBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXA7XHJcblx0XHRcdFx0XHRcdGlmIChtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXAgPiAwICYmIHZpZXdwb3J0V2lkdGggPj0gc3VtT2ZWaXNpYmxlTWF4V2lkdGhzKSB7XHJcblx0XHRcdFx0XHRcdFx0Kyt3cmFwR3JvdXBzUGVyUGFnZTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0bGV0IG1heFZpc2libGVIZWlnaHRGb3JXcmFwR3JvdXAgPSBNYXRoLm1pbihtYXhIZWlnaHRGb3JXcmFwR3JvdXAsIE1hdGgubWF4KHZpZXdwb3J0SGVpZ2h0IC0gc3VtT2ZWaXNpYmxlTWF4SGVpZ2h0cywgMCkpO1xyXG5cdFx0XHRcdFx0XHRpZiAoc2Nyb2xsT2Zmc2V0ID4gMCkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHNjcm9sbE9mZnNldFRvUmVtb3ZlID0gTWF0aC5taW4oc2Nyb2xsT2Zmc2V0LCBtYXhWaXNpYmxlSGVpZ2h0Rm9yV3JhcEdyb3VwKTtcclxuXHRcdFx0XHRcdFx0XHRtYXhWaXNpYmxlSGVpZ2h0Rm9yV3JhcEdyb3VwIC09IHNjcm9sbE9mZnNldFRvUmVtb3ZlO1xyXG5cdFx0XHRcdFx0XHRcdHNjcm9sbE9mZnNldCAtPSBzY3JvbGxPZmZzZXRUb1JlbW92ZTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0c3VtT2ZWaXNpYmxlTWF4SGVpZ2h0cyArPSBtYXhWaXNpYmxlSGVpZ2h0Rm9yV3JhcEdyb3VwO1xyXG5cdFx0XHRcdFx0XHRpZiAobWF4VmlzaWJsZUhlaWdodEZvcldyYXBHcm91cCA+IDAgJiYgdmlld3BvcnRIZWlnaHQgPj0gc3VtT2ZWaXNpYmxlTWF4SGVpZ2h0cykge1xyXG5cdFx0XHRcdFx0XHRcdCsrd3JhcEdyb3Vwc1BlclBhZ2U7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHQrK3dyYXBHcm91cEluZGV4O1xyXG5cclxuXHRcdFx0XHRcdG1heFdpZHRoRm9yV3JhcEdyb3VwID0gMDtcclxuXHRcdFx0XHRcdG1heEhlaWdodEZvcldyYXBHcm91cCA9IDA7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRjb25zdCBhdmVyYWdlQ2hpbGRXaWR0aCA9IHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRXaWR0aHMgLyB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXM7XHJcblx0XHRcdGNvbnN0IGF2ZXJhZ2VDaGlsZEhlaWdodCA9IHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRIZWlnaHRzIC8gdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm51bWJlck9mS25vd25XcmFwR3JvdXBDaGlsZFNpemVzO1xyXG5cdFx0XHRkZWZhdWx0Q2hpbGRXaWR0aCA9IHRoaXMuY2hpbGRXaWR0aCB8fCBhdmVyYWdlQ2hpbGRXaWR0aCB8fCB2aWV3cG9ydFdpZHRoO1xyXG5cdFx0XHRkZWZhdWx0Q2hpbGRIZWlnaHQgPSB0aGlzLmNoaWxkSGVpZ2h0IHx8IGF2ZXJhZ2VDaGlsZEhlaWdodCB8fCB2aWV3cG9ydEhlaWdodDtcclxuXHJcblx0XHRcdGlmICh0aGlzLmhvcml6b250YWwpIHtcclxuXHRcdFx0XHRpZiAodmlld3BvcnRXaWR0aCA+IHN1bU9mVmlzaWJsZU1heFdpZHRocykge1xyXG5cdFx0XHRcdFx0d3JhcEdyb3Vwc1BlclBhZ2UgKz0gTWF0aC5jZWlsKCh2aWV3cG9ydFdpZHRoIC0gc3VtT2ZWaXNpYmxlTWF4V2lkdGhzKSAvIGRlZmF1bHRDaGlsZFdpZHRoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0aWYgKHZpZXdwb3J0SGVpZ2h0ID4gc3VtT2ZWaXNpYmxlTWF4SGVpZ2h0cykge1xyXG5cdFx0XHRcdFx0d3JhcEdyb3Vwc1BlclBhZ2UgKz0gTWF0aC5jZWlsKCh2aWV3cG9ydEhlaWdodCAtIHN1bU9mVmlzaWJsZU1heEhlaWdodHMpIC8gZGVmYXVsdENoaWxkSGVpZ2h0KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBpdGVtQ291bnQgPSB0aGlzLml0ZW1zLmxlbmd0aDtcclxuXHRcdGNvbnN0IGl0ZW1zUGVyUGFnZSA9IGl0ZW1zUGVyV3JhcEdyb3VwICogd3JhcEdyb3Vwc1BlclBhZ2U7XHJcblx0XHRjb25zdCBwYWdlQ291bnRfZnJhY3Rpb25hbCA9IGl0ZW1Db3VudCAvIGl0ZW1zUGVyUGFnZTtcclxuXHRcdGNvbnN0IG51bWJlck9mV3JhcEdyb3VwcyA9IE1hdGguY2VpbChpdGVtQ291bnQgLyBpdGVtc1BlcldyYXBHcm91cCk7XHJcblxyXG5cdFx0bGV0IHNjcm9sbExlbmd0aCA9IDA7XHJcblxyXG5cdFx0Y29uc3QgZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCA9IHRoaXMuaG9yaXpvbnRhbCA/IGRlZmF1bHRDaGlsZFdpZHRoIDogZGVmYXVsdENoaWxkSGVpZ2h0O1xyXG5cdFx0aWYgKHRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMpIHtcclxuXHRcdFx0bGV0IG51bVVua25vd25DaGlsZFNpemVzID0gMDtcclxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZldyYXBHcm91cHM7ICsraSkge1xyXG5cdFx0XHRcdGNvbnN0IGNoaWxkU2l6ZSA9IHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbaV0gJiYgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpXVt0aGlzLl9jaGlsZFNjcm9sbERpbV07XHJcblx0XHRcdFx0aWYgKGNoaWxkU2l6ZSkge1xyXG5cdFx0XHRcdFx0c2Nyb2xsTGVuZ3RoICs9IGNoaWxkU2l6ZTtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0KytudW1Vbmtub3duQ2hpbGRTaXplcztcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHNjcm9sbExlbmd0aCArPSBNYXRoLnJvdW5kKG51bVVua25vd25DaGlsZFNpemVzICogZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRzY3JvbGxMZW5ndGggPSBudW1iZXJPZldyYXBHcm91cHMgKiBkZWZhdWx0U2Nyb2xsTGVuZ3RoUGVyV3JhcEdyb3VwO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLmhlYWRlckVsZW1lbnRSZWYpIHtcclxuXHRcdFx0c2Nyb2xsTGVuZ3RoICs9IHRoaXMuaGVhZGVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCB2aWV3cG9ydExlbmd0aCA9IHRoaXMuaG9yaXpvbnRhbCA/IHZpZXdwb3J0V2lkdGggOiB2aWV3cG9ydEhlaWdodDtcclxuXHRcdGNvbnN0IG1heFNjcm9sbFBvc2l0aW9uID0gTWF0aC5tYXgoc2Nyb2xsTGVuZ3RoIC0gdmlld3BvcnRMZW5ndGgsIDApO1xyXG5cclxuXHRcdHJldHVybiB7XHJcblx0XHRcdGNoaWxkSGVpZ2h0OiBkZWZhdWx0Q2hpbGRIZWlnaHQsXHJcblx0XHRcdGNoaWxkV2lkdGg6IGRlZmF1bHRDaGlsZFdpZHRoLFxyXG5cdFx0XHRpdGVtQ291bnQ6IGl0ZW1Db3VudCxcclxuXHRcdFx0aXRlbXNQZXJQYWdlOiBpdGVtc1BlclBhZ2UsXHJcblx0XHRcdGl0ZW1zUGVyV3JhcEdyb3VwOiBpdGVtc1BlcldyYXBHcm91cCxcclxuXHRcdFx0bWF4U2Nyb2xsUG9zaXRpb246IG1heFNjcm9sbFBvc2l0aW9uLFxyXG5cdFx0XHRwYWdlQ291bnRfZnJhY3Rpb25hbDogcGFnZUNvdW50X2ZyYWN0aW9uYWwsXHJcblx0XHRcdHNjcm9sbExlbmd0aDogc2Nyb2xsTGVuZ3RoLFxyXG5cdFx0XHR2aWV3cG9ydExlbmd0aDogdmlld3BvcnRMZW5ndGgsXHJcblx0XHRcdHdyYXBHcm91cHNQZXJQYWdlOiB3cmFwR3JvdXBzUGVyUGFnZSxcclxuXHRcdH07XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgY2FjaGVkUGFnZVNpemUgPSAwO1xyXG5cdHByb3RlY3RlZCBwcmV2aW91c1Njcm9sbE51bWJlckVsZW1lbnRzID0gMDtcclxuXHJcblx0cHJvdGVjdGVkIGNhbGN1bGF0ZVBhZGRpbmcoYXJyYXlTdGFydEluZGV4V2l0aEJ1ZmZlcjogbnVtYmVyLCBkaW1lbnNpb25zOiBJRGltZW5zaW9ucyk6IG51bWJlciB7XHJcblx0XHRpZiAoZGltZW5zaW9ucy5pdGVtQ291bnQgPT09IDApIHtcclxuXHRcdFx0cmV0dXJuIDA7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCA9IGRpbWVuc2lvbnNbdGhpcy5fY2hpbGRTY3JvbGxEaW1dO1xyXG5cdFx0Y29uc3Qgc3RhcnRpbmdXcmFwR3JvdXBJbmRleCA9IE1hdGguZmxvb3IoYXJyYXlTdGFydEluZGV4V2l0aEJ1ZmZlciAvIGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXApIHx8IDA7XHJcblxyXG5cdFx0aWYgKCF0aGlzLmVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzKSB7XHJcblx0XHRcdHJldHVybiBkZWZhdWx0U2Nyb2xsTGVuZ3RoUGVyV3JhcEdyb3VwICogc3RhcnRpbmdXcmFwR3JvdXBJbmRleDtcclxuXHRcdH1cclxuXHJcblx0XHRsZXQgbnVtVW5rbm93bkNoaWxkU2l6ZXMgPSAwO1xyXG5cdFx0bGV0IHJlc3VsdCA9IDA7XHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHN0YXJ0aW5nV3JhcEdyb3VwSW5kZXg7ICsraSkge1xyXG5cdFx0XHRjb25zdCBjaGlsZFNpemUgPSB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW2ldICYmIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbaV1bdGhpcy5fY2hpbGRTY3JvbGxEaW1dO1xyXG5cdFx0XHRpZiAoY2hpbGRTaXplKSB7XHJcblx0XHRcdFx0cmVzdWx0ICs9IGNoaWxkU2l6ZTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHQrK251bVVua25vd25DaGlsZFNpemVzO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXN1bHQgKz0gTWF0aC5yb3VuZChudW1Vbmtub3duQ2hpbGRTaXplcyAqIGRlZmF1bHRTY3JvbGxMZW5ndGhQZXJXcmFwR3JvdXApO1xyXG5cclxuXHRcdHJldHVybiByZXN1bHQ7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgY2FsY3VsYXRlUGFnZUluZm8oc2Nyb2xsUG9zaXRpb246IG51bWJlciwgZGltZW5zaW9uczogSURpbWVuc2lvbnMpOiBJUGFnZUluZm8ge1xyXG5cdFx0bGV0IHNjcm9sbFBlcmNlbnRhZ2UgPSAwO1xyXG5cdFx0aWYgKHRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMpIHtcclxuXHRcdFx0Y29uc3QgbnVtYmVyT2ZXcmFwR3JvdXBzID0gTWF0aC5jZWlsKGRpbWVuc2lvbnMuaXRlbUNvdW50IC8gZGltZW5zaW9ucy5pdGVtc1BlcldyYXBHcm91cCk7XHJcblx0XHRcdGxldCB0b3RhbFNjcm9sbGVkTGVuZ3RoID0gMDtcclxuXHRcdFx0Y29uc3QgZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCA9IGRpbWVuc2lvbnNbdGhpcy5fY2hpbGRTY3JvbGxEaW1dO1xyXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mV3JhcEdyb3VwczsgKytpKSB7XHJcblx0XHRcdFx0Y29uc3QgY2hpbGRTaXplID0gdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpXSAmJiB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW2ldW3RoaXMuX2NoaWxkU2Nyb2xsRGltXTtcclxuXHRcdFx0XHRpZiAoY2hpbGRTaXplKSB7XHJcblx0XHRcdFx0XHR0b3RhbFNjcm9sbGVkTGVuZ3RoICs9IGNoaWxkU2l6ZTtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0dG90YWxTY3JvbGxlZExlbmd0aCArPSBkZWZhdWx0U2Nyb2xsTGVuZ3RoUGVyV3JhcEdyb3VwO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKHNjcm9sbFBvc2l0aW9uIDwgdG90YWxTY3JvbGxlZExlbmd0aCkge1xyXG5cdFx0XHRcdFx0c2Nyb2xsUGVyY2VudGFnZSA9IGkgLyBudW1iZXJPZldyYXBHcm91cHM7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHNjcm9sbFBlcmNlbnRhZ2UgPSBzY3JvbGxQb3NpdGlvbiAvIGRpbWVuc2lvbnMuc2Nyb2xsTGVuZ3RoO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IHN0YXJ0aW5nQXJyYXlJbmRleF9mcmFjdGlvbmFsID0gTWF0aC5taW4oTWF0aC5tYXgoc2Nyb2xsUGVyY2VudGFnZSAqIGRpbWVuc2lvbnMucGFnZUNvdW50X2ZyYWN0aW9uYWwsIDApLCBkaW1lbnNpb25zLnBhZ2VDb3VudF9mcmFjdGlvbmFsKSAqIGRpbWVuc2lvbnMuaXRlbXNQZXJQYWdlO1xyXG5cclxuXHRcdGNvbnN0IG1heFN0YXJ0ID0gZGltZW5zaW9ucy5pdGVtQ291bnQgLSBkaW1lbnNpb25zLml0ZW1zUGVyUGFnZSAtIDE7XHJcblx0XHRsZXQgYXJyYXlTdGFydEluZGV4ID0gTWF0aC5taW4oTWF0aC5mbG9vcihzdGFydGluZ0FycmF5SW5kZXhfZnJhY3Rpb25hbCksIG1heFN0YXJ0KTtcclxuXHRcdGFycmF5U3RhcnRJbmRleCAtPSBhcnJheVN0YXJ0SW5kZXggJSBkaW1lbnNpb25zLml0ZW1zUGVyV3JhcEdyb3VwOyAvLyByb3VuZCBkb3duIHRvIHN0YXJ0IG9mIHdyYXBHcm91cFxyXG5cclxuXHRcdGlmICh0aGlzLnN0cmlwZWRUYWJsZSkge1xyXG5cdFx0XHRjb25zdCBidWZmZXJCb3VuZGFyeSA9IDIgKiBkaW1lbnNpb25zLml0ZW1zUGVyV3JhcEdyb3VwO1xyXG5cdFx0XHRpZiAoYXJyYXlTdGFydEluZGV4ICUgYnVmZmVyQm91bmRhcnkgIT09IDApIHtcclxuXHRcdFx0XHRhcnJheVN0YXJ0SW5kZXggPSBNYXRoLm1heChhcnJheVN0YXJ0SW5kZXggLSBhcnJheVN0YXJ0SW5kZXggJSBidWZmZXJCb3VuZGFyeSwgMCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRsZXQgYXJyYXlFbmRJbmRleCA9IE1hdGguY2VpbChzdGFydGluZ0FycmF5SW5kZXhfZnJhY3Rpb25hbCkgKyBkaW1lbnNpb25zLml0ZW1zUGVyUGFnZSAtIDE7XHJcblx0XHRjb25zdCBlbmRJbmRleFdpdGhpbldyYXBHcm91cCA9IChhcnJheUVuZEluZGV4ICsgMSkgJSBkaW1lbnNpb25zLml0ZW1zUGVyV3JhcEdyb3VwO1xyXG5cdFx0aWYgKGVuZEluZGV4V2l0aGluV3JhcEdyb3VwID4gMCkge1xyXG5cdFx0XHRhcnJheUVuZEluZGV4ICs9IGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXAgLSBlbmRJbmRleFdpdGhpbldyYXBHcm91cDsgLy8gcm91bmQgdXAgdG8gZW5kIG9mIHdyYXBHcm91cFxyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChpc05hTihhcnJheVN0YXJ0SW5kZXgpKSB7XHJcblx0XHRcdGFycmF5U3RhcnRJbmRleCA9IDA7XHJcblx0XHR9XHJcblx0XHRpZiAoaXNOYU4oYXJyYXlFbmRJbmRleCkpIHtcclxuXHRcdFx0YXJyYXlFbmRJbmRleCA9IDA7XHJcblx0XHR9XHJcblxyXG5cdFx0YXJyYXlTdGFydEluZGV4ID0gTWF0aC5taW4oTWF0aC5tYXgoYXJyYXlTdGFydEluZGV4LCAwKSwgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxKTtcclxuXHRcdGFycmF5RW5kSW5kZXggPSBNYXRoLm1pbihNYXRoLm1heChhcnJheUVuZEluZGV4LCAwKSwgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxKTtcclxuXHJcblx0XHRjb25zdCBidWZmZXJTaXplID0gdGhpcy5idWZmZXJBbW91bnQgKiBkaW1lbnNpb25zLml0ZW1zUGVyV3JhcEdyb3VwO1xyXG5cdFx0Y29uc3Qgc3RhcnRJbmRleFdpdGhCdWZmZXIgPSBNYXRoLm1pbihNYXRoLm1heChhcnJheVN0YXJ0SW5kZXggLSBidWZmZXJTaXplLCAwKSwgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxKTtcclxuXHRcdGNvbnN0IGVuZEluZGV4V2l0aEJ1ZmZlciA9IE1hdGgubWluKE1hdGgubWF4KGFycmF5RW5kSW5kZXggKyBidWZmZXJTaXplLCAwKSwgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxKTtcclxuXHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHRzdGFydEluZGV4OiBhcnJheVN0YXJ0SW5kZXgsXHJcblx0XHRcdGVuZEluZGV4OiBhcnJheUVuZEluZGV4LFxyXG5cdFx0XHRzdGFydEluZGV4V2l0aEJ1ZmZlcjogc3RhcnRJbmRleFdpdGhCdWZmZXIsXHJcblx0XHRcdGVuZEluZGV4V2l0aEJ1ZmZlcjogZW5kSW5kZXhXaXRoQnVmZmVyLFxyXG5cdFx0XHRzY3JvbGxTdGFydFBvc2l0aW9uOiBzY3JvbGxQb3NpdGlvbixcclxuXHRcdFx0c2Nyb2xsRW5kUG9zaXRpb246IHNjcm9sbFBvc2l0aW9uICsgZGltZW5zaW9ucy52aWV3cG9ydExlbmd0aCxcclxuXHRcdFx0bWF4U2Nyb2xsUG9zaXRpb246IGRpbWVuc2lvbnMubWF4U2Nyb2xsUG9zaXRpb25cclxuXHRcdH07XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgY2FsY3VsYXRlVmlld3BvcnQoKTogSVZpZXdwb3J0IHtcclxuXHRcdGNvbnN0IGRpbWVuc2lvbnMgPSB0aGlzLmNhbGN1bGF0ZURpbWVuc2lvbnMoKTtcclxuXHRcdGNvbnN0IG9mZnNldCA9IHRoaXMuZ2V0RWxlbWVudHNPZmZzZXQoKTtcclxuXHJcblx0XHRsZXQgc2Nyb2xsU3RhcnRQb3NpdGlvbiA9IHRoaXMuZ2V0U2Nyb2xsU3RhcnRQb3NpdGlvbigpO1xyXG5cdFx0aWYgKHNjcm9sbFN0YXJ0UG9zaXRpb24gPiAoZGltZW5zaW9ucy5zY3JvbGxMZW5ndGggKyBvZmZzZXQpICYmICEodGhpcy5wYXJlbnRTY3JvbGwgaW5zdGFuY2VvZiBXaW5kb3cpKSB7XHJcblx0XHRcdHNjcm9sbFN0YXJ0UG9zaXRpb24gPSBkaW1lbnNpb25zLnNjcm9sbExlbmd0aDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHNjcm9sbFN0YXJ0UG9zaXRpb24gLT0gb2Zmc2V0O1xyXG5cdFx0fVxyXG5cdFx0c2Nyb2xsU3RhcnRQb3NpdGlvbiA9IE1hdGgubWF4KDAsIHNjcm9sbFN0YXJ0UG9zaXRpb24pO1xyXG5cclxuXHRcdGNvbnN0IHBhZ2VJbmZvID0gdGhpcy5jYWxjdWxhdGVQYWdlSW5mbyhzY3JvbGxTdGFydFBvc2l0aW9uLCBkaW1lbnNpb25zKTtcclxuXHRcdGNvbnN0IG5ld1BhZGRpbmcgPSB0aGlzLmNhbGN1bGF0ZVBhZGRpbmcocGFnZUluZm8uc3RhcnRJbmRleFdpdGhCdWZmZXIsIGRpbWVuc2lvbnMpO1xyXG5cdFx0Y29uc3QgbmV3U2Nyb2xsTGVuZ3RoID0gZGltZW5zaW9ucy5zY3JvbGxMZW5ndGg7XHJcblxyXG5cdFx0cmV0dXJuIHtcclxuXHRcdFx0c3RhcnRJbmRleDogcGFnZUluZm8uc3RhcnRJbmRleCxcclxuXHRcdFx0ZW5kSW5kZXg6IHBhZ2VJbmZvLmVuZEluZGV4LFxyXG5cdFx0XHRzdGFydEluZGV4V2l0aEJ1ZmZlcjogcGFnZUluZm8uc3RhcnRJbmRleFdpdGhCdWZmZXIsXHJcblx0XHRcdGVuZEluZGV4V2l0aEJ1ZmZlcjogcGFnZUluZm8uZW5kSW5kZXhXaXRoQnVmZmVyLFxyXG5cdFx0XHRwYWRkaW5nOiBNYXRoLnJvdW5kKG5ld1BhZGRpbmcpLFxyXG5cdFx0XHRzY3JvbGxMZW5ndGg6IE1hdGgucm91bmQobmV3U2Nyb2xsTGVuZ3RoKSxcclxuXHRcdFx0c2Nyb2xsU3RhcnRQb3NpdGlvbjogcGFnZUluZm8uc2Nyb2xsU3RhcnRQb3NpdGlvbixcclxuXHRcdFx0c2Nyb2xsRW5kUG9zaXRpb246IHBhZ2VJbmZvLnNjcm9sbEVuZFBvc2l0aW9uLFxyXG5cdFx0XHRtYXhTY3JvbGxQb3NpdGlvbjogcGFnZUluZm8ubWF4U2Nyb2xsUG9zaXRpb25cclxuXHRcdH07XHJcblx0fVxyXG59XHJcblxyXG5ATmdNb2R1bGUoe1xyXG5cdGV4cG9ydHM6IFtWaXJ0dWFsU2Nyb2xsZXJDb21wb25lbnRdLFxyXG5cdGRlY2xhcmF0aW9uczogW1ZpcnR1YWxTY3JvbGxlckNvbXBvbmVudF0sXHJcblx0aW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXHJcblx0cHJvdmlkZXJzOiBbXHJcblx0XHR7XHJcblx0XHRcdHByb3ZpZGU6ICd2aXJ0dWFsLXNjcm9sbGVyLWRlZmF1bHQtb3B0aW9ucycsXHJcblx0XHRcdHVzZUZhY3Rvcnk6IFZJUlRVQUxfU0NST0xMRVJfREVGQVVMVF9PUFRJT05TX0ZBQ1RPUllcclxuXHRcdH1cclxuXHRdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBWaXJ0dWFsU2Nyb2xsZXJNb2R1bGUgeyB9Il19