valtech-components 2.0.404 → 2.0.406

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 (280) hide show
  1. package/README.md +71 -0
  2. package/esm2022/lib/components/atoms/avatar/avatar.component.mjs +4 -4
  3. package/esm2022/lib/components/atoms/avatar/types.mjs +1 -1
  4. package/esm2022/lib/components/atoms/box/box.component.mjs +4 -4
  5. package/esm2022/lib/components/atoms/box/types.mjs +1 -1
  6. package/esm2022/lib/components/atoms/button/button.component.mjs +4 -4
  7. package/esm2022/lib/components/atoms/button/factory.mjs +1 -1
  8. package/esm2022/lib/components/atoms/countdown/countdown.component.mjs +343 -0
  9. package/esm2022/lib/components/atoms/countdown/types.mjs +27 -0
  10. package/esm2022/lib/components/atoms/display/display.component.mjs +4 -4
  11. package/esm2022/lib/components/atoms/display/types.mjs +1 -1
  12. package/esm2022/lib/components/atoms/divider/divider.component.mjs +4 -4
  13. package/esm2022/lib/components/atoms/divider/types.mjs +1 -1
  14. package/esm2022/lib/components/atoms/fab/fab.component.mjs +152 -0
  15. package/esm2022/lib/components/atoms/fab/types.mjs +2 -0
  16. package/esm2022/lib/components/atoms/href/href.component.mjs +4 -4
  17. package/esm2022/lib/components/atoms/href/types.mjs +1 -1
  18. package/esm2022/lib/components/atoms/icon/icon.component.mjs +4 -4
  19. package/esm2022/lib/components/atoms/icon/types.mjs +1 -1
  20. package/esm2022/lib/components/atoms/image/image.component.mjs +6 -6
  21. package/esm2022/lib/components/atoms/image/types.mjs +1 -1
  22. package/esm2022/lib/components/atoms/price-tag/price-tag.component.mjs +245 -0
  23. package/esm2022/lib/components/atoms/price-tag/types.mjs +15 -0
  24. package/esm2022/lib/components/atoms/progress-bar/progress-bar.component.mjs +4 -4
  25. package/esm2022/lib/components/atoms/progress-bar/types.mjs +1 -1
  26. package/esm2022/lib/components/atoms/progress-ring/progress-ring.component.mjs +149 -0
  27. package/esm2022/lib/components/atoms/progress-ring/types.mjs +2 -0
  28. package/esm2022/lib/components/atoms/qr-code/qr-code.component.mjs +417 -0
  29. package/esm2022/lib/components/atoms/qr-code/types.mjs +2 -0
  30. package/esm2022/lib/components/atoms/skeleton/skeleton.component.mjs +193 -0
  31. package/esm2022/lib/components/atoms/skeleton/types.mjs +13 -0
  32. package/esm2022/lib/components/atoms/text/text.component.mjs +4 -4
  33. package/esm2022/lib/components/atoms/text/types.mjs +1 -1
  34. package/esm2022/lib/components/atoms/title/title.component.mjs +4 -4
  35. package/esm2022/lib/components/atoms/title/types.mjs +1 -1
  36. package/esm2022/lib/components/molecules/accordion/accordion.component.mjs +139 -0
  37. package/esm2022/lib/components/molecules/accordion/types.mjs +2 -0
  38. package/esm2022/lib/components/molecules/action-header/action-header.component.mjs +4 -4
  39. package/esm2022/lib/components/molecules/action-header/types.mjs +1 -1
  40. package/esm2022/lib/components/molecules/alert-box/alert-box.component.mjs +4 -4
  41. package/esm2022/lib/components/molecules/alert-box/types.mjs +1 -1
  42. package/esm2022/lib/components/molecules/breadcrumb/breadcrumb.component.mjs +137 -0
  43. package/esm2022/lib/components/molecules/breadcrumb/types.mjs +2 -0
  44. package/esm2022/lib/components/molecules/button-group/button-group.component.mjs +4 -4
  45. package/esm2022/lib/components/molecules/button-group/types.mjs +1 -1
  46. package/esm2022/lib/components/molecules/card/card.component.mjs +5 -5
  47. package/esm2022/lib/components/molecules/card/types.mjs +1 -1
  48. package/esm2022/lib/components/molecules/check-input/check-input.component.mjs +4 -4
  49. package/esm2022/lib/components/molecules/chip-group/chip-group.component.mjs +174 -0
  50. package/esm2022/lib/components/molecules/chip-group/types.mjs +2 -0
  51. package/esm2022/lib/components/molecules/code-display/code-display.component.mjs +4 -4
  52. package/esm2022/lib/components/molecules/code-display/types.mjs +1 -1
  53. package/esm2022/lib/components/molecules/command-display/command-display.component.mjs +4 -4
  54. package/esm2022/lib/components/molecules/command-display/types.mjs +1 -1
  55. package/esm2022/lib/components/molecules/comment/comment.component.mjs +634 -0
  56. package/esm2022/lib/components/molecules/comment/types.mjs +2 -0
  57. package/esm2022/lib/components/molecules/comment-input/comment-input.component.mjs +4 -4
  58. package/esm2022/lib/components/molecules/content-loader/content-loader.component.mjs +4 -4
  59. package/esm2022/lib/components/molecules/content-loader/types.mjs +1 -1
  60. package/esm2022/lib/components/molecules/currency-input/currency-input.component.mjs +368 -0
  61. package/esm2022/lib/components/molecules/currency-input/types.mjs +18 -0
  62. package/esm2022/lib/components/molecules/date-input/date-input.component.mjs +5 -5
  63. package/esm2022/lib/components/molecules/date-range-input/date-range-input.component.mjs +418 -0
  64. package/esm2022/lib/components/molecules/date-range-input/types.mjs +2 -0
  65. package/esm2022/lib/components/molecules/email-input/email-input.component.mjs +4 -4
  66. package/esm2022/lib/components/molecules/expandable-text/expandable-text.component.mjs +4 -4
  67. package/esm2022/lib/components/molecules/expandable-text/types.mjs +1 -1
  68. package/esm2022/lib/components/molecules/file-input/file-input.component.mjs +4 -4
  69. package/esm2022/lib/components/molecules/glow-card/glow-card.component.mjs +279 -0
  70. package/esm2022/lib/components/molecules/glow-card/types.mjs +11 -0
  71. package/esm2022/lib/components/molecules/hint/hint.component.mjs +4 -4
  72. package/esm2022/lib/components/molecules/hour-input/hour-input.component.mjs +4 -4
  73. package/esm2022/lib/components/molecules/info/info.component.mjs +4 -4
  74. package/esm2022/lib/components/molecules/info/types.mjs +1 -1
  75. package/esm2022/lib/components/molecules/language-selector/language-selector.component.mjs +4 -4
  76. package/esm2022/lib/components/molecules/language-selector/types.mjs +1 -1
  77. package/esm2022/lib/components/molecules/layered-card/layered-card.component.mjs +4 -4
  78. package/esm2022/lib/components/molecules/layered-card/types.mjs +1 -1
  79. package/esm2022/lib/components/molecules/link/link.component.mjs +4 -4
  80. package/esm2022/lib/components/molecules/link/types.mjs +1 -1
  81. package/esm2022/lib/components/molecules/links-cake/links-cake.component.mjs +4 -4
  82. package/esm2022/lib/components/molecules/links-cake/types.mjs +1 -1
  83. package/esm2022/lib/components/molecules/multi-select-search/multi-select-search.component.mjs +5 -5
  84. package/esm2022/lib/components/molecules/notes-box/notes-box.component.mjs +4 -4
  85. package/esm2022/lib/components/molecules/notes-box/types.mjs +1 -1
  86. package/esm2022/lib/components/molecules/number-from-to/number-from-to.component.mjs +4 -4
  87. package/esm2022/lib/components/molecules/number-input/number-input.component.mjs +4 -4
  88. package/esm2022/lib/components/molecules/number-stepper/number-stepper.component.mjs +377 -0
  89. package/esm2022/lib/components/molecules/number-stepper/types.mjs +2 -0
  90. package/esm2022/lib/components/molecules/pagination/pagination.component.mjs +253 -0
  91. package/esm2022/lib/components/molecules/pagination/types.mjs +2 -0
  92. package/esm2022/lib/components/molecules/participant-card/participant-card.component.mjs +486 -0
  93. package/esm2022/lib/components/molecules/participant-card/types.mjs +21 -0
  94. package/esm2022/lib/components/molecules/password-input/password-input.component.mjs +4 -4
  95. package/esm2022/lib/components/molecules/phone-input/phone-input.component.mjs +336 -0
  96. package/esm2022/lib/components/molecules/phone-input/types.mjs +19 -0
  97. package/esm2022/lib/components/molecules/pill/pill.component.mjs +4 -4
  98. package/esm2022/lib/components/molecules/pill/types.mjs +1 -1
  99. package/esm2022/lib/components/molecules/pin-input/pin-input.component.mjs +4 -4
  100. package/esm2022/lib/components/molecules/plain-code-box/plain-code-box.component.mjs +4 -4
  101. package/esm2022/lib/components/molecules/plain-code-box/types.mjs +1 -1
  102. package/esm2022/lib/components/molecules/popover-selector/popover-selector.component.mjs +5 -5
  103. package/esm2022/lib/components/molecules/popover-selector/types.mjs +1 -1
  104. package/esm2022/lib/components/molecules/progress-status/progress-status.component.mjs +4 -4
  105. package/esm2022/lib/components/molecules/progress-status/types.mjs +1 -1
  106. package/esm2022/lib/components/molecules/prompter/prompter.component.mjs +4 -4
  107. package/esm2022/lib/components/molecules/prompter/types.mjs +1 -1
  108. package/esm2022/lib/components/molecules/quote-box/quote-box.component.mjs +155 -0
  109. package/esm2022/lib/components/molecules/radio-input/radio-input.component.mjs +5 -5
  110. package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +484 -0
  111. package/esm2022/lib/components/molecules/raffle-status-card/types.mjs +23 -0
  112. package/esm2022/lib/components/molecules/range-input/range-input.component.mjs +148 -0
  113. package/esm2022/lib/components/molecules/range-input/types.mjs +2 -0
  114. package/esm2022/lib/components/molecules/rating/rating.component.mjs +149 -0
  115. package/esm2022/lib/components/molecules/rating/types.mjs +2 -0
  116. package/esm2022/lib/components/molecules/searchbar/searchbar.component.mjs +4 -4
  117. package/esm2022/lib/components/molecules/segment-control/segment-control.component.mjs +145 -0
  118. package/esm2022/lib/components/molecules/segment-control/types.mjs +2 -0
  119. package/esm2022/lib/components/molecules/select-input/select-input.component.mjs +5 -5
  120. package/esm2022/lib/components/molecules/select-search/select-search.component.mjs +5 -5
  121. package/esm2022/lib/components/molecules/share-buttons/share-buttons.component.mjs +277 -0
  122. package/esm2022/lib/components/molecules/share-buttons/types.mjs +88 -0
  123. package/esm2022/lib/components/molecules/stats-card/stats-card.component.mjs +165 -0
  124. package/esm2022/lib/components/molecules/stats-card/types.mjs +2 -0
  125. package/esm2022/lib/components/molecules/stepper/stepper.component.mjs +239 -0
  126. package/esm2022/lib/components/molecules/stepper/types.mjs +2 -0
  127. package/esm2022/lib/components/molecules/tabs/tabs.component.mjs +135 -0
  128. package/esm2022/lib/components/molecules/tabs/types.mjs +2 -0
  129. package/esm2022/lib/components/molecules/text-input/text-input.component.mjs +4 -4
  130. package/esm2022/lib/components/molecules/textarea-input/textarea-input.component.mjs +204 -0
  131. package/esm2022/lib/components/molecules/textarea-input/types.mjs +2 -0
  132. package/esm2022/lib/components/molecules/ticket-grid/ticket-grid.component.mjs +497 -0
  133. package/esm2022/lib/components/molecules/ticket-grid/types.mjs +11 -0
  134. package/esm2022/lib/components/molecules/timeline/timeline.component.mjs +140 -0
  135. package/esm2022/lib/components/molecules/timeline/types.mjs +2 -0
  136. package/esm2022/lib/components/molecules/title-block/title-block.component.mjs +4 -4
  137. package/esm2022/lib/components/molecules/title-block/types.mjs +1 -1
  138. package/esm2022/lib/components/molecules/toggle-input/toggle-input.component.mjs +89 -0
  139. package/esm2022/lib/components/molecules/toggle-input/types.mjs +2 -0
  140. package/esm2022/lib/components/molecules/winner-display/types.mjs +9 -0
  141. package/esm2022/lib/components/molecules/winner-display/winner-display.component.mjs +370 -0
  142. package/esm2022/lib/components/organisms/article/article.component.mjs +4 -4
  143. package/esm2022/lib/components/organisms/article/types.mjs +1 -1
  144. package/esm2022/lib/components/organisms/banner/banner.component.mjs +4 -4
  145. package/esm2022/lib/components/organisms/banner/types.mjs +1 -1
  146. package/esm2022/lib/components/organisms/comment-section/comment-section.component.mjs +578 -0
  147. package/esm2022/lib/components/organisms/comment-section/types.mjs +2 -0
  148. package/esm2022/lib/components/organisms/data-table/data-table.component.mjs +853 -0
  149. package/esm2022/lib/components/organisms/data-table/types.mjs +13 -0
  150. package/esm2022/lib/components/organisms/footer/footer.component.mjs +4 -4
  151. package/esm2022/lib/components/organisms/footer/types.mjs +1 -1
  152. package/esm2022/lib/components/organisms/form/factory.mjs +1 -1
  153. package/esm2022/lib/components/organisms/form/form-footer/form-footer.component.mjs +4 -4
  154. package/esm2022/lib/components/organisms/form/form.component.mjs +4 -4
  155. package/esm2022/lib/components/organisms/header/header.component.mjs +4 -4
  156. package/esm2022/lib/components/organisms/header/types.mjs +1 -1
  157. package/esm2022/lib/components/organisms/item-list/item-list.component.mjs +4 -4
  158. package/esm2022/lib/components/organisms/item-list/types.mjs +1 -1
  159. package/esm2022/lib/components/organisms/no-content/no-content.component.mjs +4 -4
  160. package/esm2022/lib/components/organisms/no-content/types.mjs +1 -1
  161. package/esm2022/lib/components/organisms/toolbar/toolbar.component.mjs +4 -4
  162. package/esm2022/lib/components/organisms/toolbar/types.mjs +1 -1
  163. package/esm2022/lib/components/organisms/wizard/types.mjs +1 -1
  164. package/esm2022/lib/components/organisms/wizard/wizard-footer/wizard-footer.component.mjs +4 -4
  165. package/esm2022/lib/components/organisms/wizard/wizard.component.mjs +4 -4
  166. package/esm2022/lib/components/templates/layout/layout.component.mjs +4 -4
  167. package/esm2022/lib/components/templates/simple/simple.component.mjs +5 -5
  168. package/esm2022/lib/components/templates/simple/types.mjs +1 -1
  169. package/esm2022/lib/components/types.mjs +22 -16
  170. package/esm2022/lib/services/confirmation-dialog/confirmation-dialog.service.mjs +180 -0
  171. package/esm2022/lib/services/confirmation-dialog/types.mjs +14 -0
  172. package/esm2022/lib/services/download.service.mjs +4 -4
  173. package/esm2022/lib/services/icons.service.mjs +4 -4
  174. package/esm2022/lib/services/in-app-browser.service.mjs +4 -4
  175. package/esm2022/lib/services/lang-provider/components/lang-settings.mjs +1 -1
  176. package/esm2022/lib/services/lang-provider/content.mjs +1 -1
  177. package/esm2022/lib/services/lang-provider/lang-provider.service.mjs +4 -4
  178. package/esm2022/lib/services/lang-provider/types.mjs +1 -1
  179. package/esm2022/lib/services/link-processor.service.mjs +4 -4
  180. package/esm2022/lib/services/local-storage.service.mjs +1 -1
  181. package/esm2022/lib/services/modal/modal.service.mjs +213 -0
  182. package/esm2022/lib/services/modal/simple-modal-content.component.mjs +133 -0
  183. package/esm2022/lib/services/modal/types.mjs +26 -0
  184. package/esm2022/lib/services/navigation.service.mjs +4 -4
  185. package/esm2022/lib/services/qr-generator/qr-generator.service.mjs +341 -0
  186. package/esm2022/lib/services/qr-generator/types.mjs +46 -0
  187. package/esm2022/lib/services/theme.service.mjs +4 -4
  188. package/esm2022/lib/services/toast.service.mjs +4 -4
  189. package/esm2022/lib/services/types.mjs +1 -1
  190. package/esm2022/lib/shared/constants/storage.mjs +1 -1
  191. package/esm2022/lib/shared/pipes/process-links.pipe.mjs +4 -4
  192. package/esm2022/lib/shared/utils/content.mjs +1 -1
  193. package/esm2022/lib/shared/utils/dom.mjs +1 -1
  194. package/esm2022/lib/shared/utils/form-defaults.mjs +1 -1
  195. package/esm2022/lib/shared/utils/simple-content.mjs +1 -1
  196. package/esm2022/lib/shared/utils/styles.mjs +1 -1
  197. package/esm2022/lib/shared/utils/text.mjs +1 -1
  198. package/esm2022/public-api.mjs +73 -3
  199. package/esm2022/valtech-components.mjs +1 -1
  200. package/fesm2022/valtech-components-simple-modal-content.component-DQhEgUmS.mjs +136 -0
  201. package/fesm2022/valtech-components-simple-modal-content.component-DQhEgUmS.mjs.map +1 -0
  202. package/fesm2022/valtech-components.mjs +14847 -4292
  203. package/fesm2022/valtech-components.mjs.map +1 -1
  204. package/lib/components/atoms/countdown/countdown.component.d.ts +38 -0
  205. package/lib/components/atoms/countdown/types.d.ts +108 -0
  206. package/lib/components/atoms/fab/fab.component.d.ts +16 -0
  207. package/lib/components/atoms/fab/types.d.ts +45 -0
  208. package/lib/components/atoms/price-tag/price-tag.component.d.ts +16 -0
  209. package/lib/components/atoms/price-tag/types.d.ts +59 -0
  210. package/lib/components/atoms/progress-ring/progress-ring.component.d.ts +20 -0
  211. package/lib/components/atoms/progress-ring/types.d.ts +24 -0
  212. package/lib/components/atoms/qr-code/qr-code.component.d.ts +36 -0
  213. package/lib/components/atoms/qr-code/types.d.ts +124 -0
  214. package/lib/components/atoms/skeleton/skeleton.component.d.ts +12 -0
  215. package/lib/components/atoms/skeleton/types.d.ts +29 -0
  216. package/lib/components/molecules/accordion/accordion.component.d.ts +19 -0
  217. package/lib/components/molecules/accordion/types.d.ts +47 -0
  218. package/lib/components/molecules/breadcrumb/breadcrumb.component.d.ts +22 -0
  219. package/lib/components/molecules/breadcrumb/types.d.ts +45 -0
  220. package/lib/components/molecules/chip-group/chip-group.component.d.ts +22 -0
  221. package/lib/components/molecules/chip-group/types.d.ts +65 -0
  222. package/lib/components/molecules/comment/comment.component.d.ts +42 -0
  223. package/lib/components/molecules/comment/types.d.ts +171 -0
  224. package/lib/components/molecules/currency-input/currency-input.component.d.ts +43 -0
  225. package/lib/components/molecules/currency-input/types.d.ts +96 -0
  226. package/lib/components/molecules/date-range-input/date-range-input.component.d.ts +42 -0
  227. package/lib/components/molecules/date-range-input/types.d.ts +109 -0
  228. package/lib/components/molecules/glow-card/glow-card.component.d.ts +51 -0
  229. package/lib/components/molecules/glow-card/types.d.ts +92 -0
  230. package/lib/components/molecules/number-stepper/number-stepper.component.d.ts +34 -0
  231. package/lib/components/molecules/number-stepper/types.d.ts +88 -0
  232. package/lib/components/molecules/pagination/pagination.component.d.ts +15 -0
  233. package/lib/components/molecules/pagination/types.d.ts +41 -0
  234. package/lib/components/molecules/participant-card/participant-card.component.d.ts +26 -0
  235. package/lib/components/molecules/participant-card/types.d.ts +132 -0
  236. package/lib/components/molecules/phone-input/phone-input.component.d.ts +38 -0
  237. package/lib/components/molecules/phone-input/types.d.ts +98 -0
  238. package/lib/components/molecules/quote-box/quote-box.component.d.ts +26 -0
  239. package/lib/components/molecules/raffle-status-card/raffle-status-card.component.d.ts +22 -0
  240. package/lib/components/molecules/raffle-status-card/types.d.ts +108 -0
  241. package/lib/components/molecules/range-input/range-input.component.d.ts +30 -0
  242. package/lib/components/molecules/range-input/types.d.ts +59 -0
  243. package/lib/components/molecules/rating/rating.component.d.ts +17 -0
  244. package/lib/components/molecules/rating/types.d.ts +41 -0
  245. package/lib/components/molecules/segment-control/segment-control.component.d.ts +30 -0
  246. package/lib/components/molecules/segment-control/types.d.ts +46 -0
  247. package/lib/components/molecules/share-buttons/share-buttons.component.d.ts +22 -0
  248. package/lib/components/molecules/share-buttons/types.d.ts +108 -0
  249. package/lib/components/molecules/stats-card/stats-card.component.d.ts +14 -0
  250. package/lib/components/molecules/stats-card/types.d.ts +41 -0
  251. package/lib/components/molecules/stepper/stepper.component.d.ts +21 -0
  252. package/lib/components/molecules/stepper/types.d.ts +66 -0
  253. package/lib/components/molecules/tabs/tabs.component.d.ts +17 -0
  254. package/lib/components/molecules/tabs/types.d.ts +45 -0
  255. package/lib/components/molecules/textarea-input/textarea-input.component.d.ts +27 -0
  256. package/lib/components/molecules/textarea-input/types.d.ts +74 -0
  257. package/lib/components/molecules/ticket-grid/ticket-grid.component.d.ts +41 -0
  258. package/lib/components/molecules/ticket-grid/types.d.ts +122 -0
  259. package/lib/components/molecules/timeline/timeline.component.d.ts +14 -0
  260. package/lib/components/molecules/timeline/types.d.ts +39 -0
  261. package/lib/components/molecules/toggle-input/toggle-input.component.d.ts +24 -0
  262. package/lib/components/molecules/toggle-input/types.d.ts +30 -0
  263. package/lib/components/molecules/winner-display/types.d.ts +103 -0
  264. package/lib/components/molecules/winner-display/winner-display.component.d.ts +37 -0
  265. package/lib/components/organisms/article/article.component.d.ts +1 -1
  266. package/lib/components/organisms/comment-section/comment-section.component.d.ts +52 -0
  267. package/lib/components/organisms/comment-section/types.d.ts +144 -0
  268. package/lib/components/organisms/data-table/data-table.component.d.ts +46 -0
  269. package/lib/components/organisms/data-table/types.d.ts +205 -0
  270. package/lib/components/types.d.ts +21 -15
  271. package/lib/services/confirmation-dialog/confirmation-dialog.service.d.ts +71 -0
  272. package/lib/services/confirmation-dialog/types.d.ts +61 -0
  273. package/lib/services/modal/modal.service.d.ts +98 -0
  274. package/lib/services/modal/simple-modal-content.component.d.ts +19 -0
  275. package/lib/services/modal/types.d.ts +155 -0
  276. package/lib/services/qr-generator/qr-generator.service.d.ts +115 -0
  277. package/lib/services/qr-generator/types.d.ts +141 -0
  278. package/package.json +9 -2
  279. package/public-api.d.ts +72 -2
  280. package/LICENSE +0 -21
@@ -0,0 +1,578 @@
1
+ import { Component, Input, Output, EventEmitter, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { IonIcon, IonButton, IonBadge, IonTextarea, IonItem, IonSelect, IonSelectOption, IonSpinner, IonInfiniteScroll, IonInfiniteScrollContent, } from '@ionic/angular/standalone';
5
+ import { addIcons } from 'ionicons';
6
+ import { chatbubblesOutline, filterOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, } from 'ionicons/icons';
7
+ import { CommentComponent } from '../../molecules/comment/comment.component';
8
+ import { AvatarComponent } from '../../atoms/avatar/avatar.component';
9
+ import { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';
10
+ import { LangService } from '../../../services/lang-provider/lang-provider.service';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
13
+ addIcons({
14
+ chatbubblesOutline,
15
+ filterOutline,
16
+ sendOutline,
17
+ chatbubbleEllipsesOutline,
18
+ swapVerticalOutline,
19
+ });
20
+ /**
21
+ * val-comment-section
22
+ *
23
+ * An organism component that provides a complete comment section with:
24
+ * - Header with title and count
25
+ * - Sort/filter options
26
+ * - New comment input
27
+ * - Comments list with val-comment
28
+ * - Load more pagination
29
+ * - Empty state
30
+ *
31
+ * @example Basic usage
32
+ * <val-comment-section [props]="{
33
+ * title: 'Comments',
34
+ * count: 42,
35
+ * comments: commentsArray,
36
+ * showInput: true
37
+ * }"></val-comment-section>
38
+ *
39
+ * @example With sorting
40
+ * <val-comment-section [props]="{
41
+ * title: 'Reviews',
42
+ * count: 128,
43
+ * comments: reviews,
44
+ * sortOptions: [
45
+ * { token: 'newest', label: 'Newest first' },
46
+ * { token: 'oldest', label: 'Oldest first' },
47
+ * { token: 'popular', label: 'Most popular' }
48
+ * ],
49
+ * selectedSort: 'newest'
50
+ * }" (sortChange)="onSort($event)"></val-comment-section>
51
+ *
52
+ * @input props: CommentSectionMetadata - Configuration for the section
53
+ * @output sortChange - Sort option changed
54
+ * @output commentSubmit - New comment submitted
55
+ * @output loadMore - Load more clicked
56
+ * @output authorClick - Comment author clicked (bubbled from val-comment)
57
+ * @output reactionClick - Reaction clicked (bubbled)
58
+ * @output actionClick - Action clicked (bubbled)
59
+ * @output menuItemClick - Menu item clicked (bubbled)
60
+ * @output commentLoadMore - Load more replies clicked (bubbled)
61
+ * @output collapseToggle - Comment collapse toggled (bubbled)
62
+ */
63
+ export class CommentSectionComponent {
64
+ constructor() {
65
+ // Section events
66
+ this.sortChange = new EventEmitter();
67
+ this.commentSubmit = new EventEmitter();
68
+ this.loadMore = new EventEmitter();
69
+ // Bubbled events from val-comment
70
+ this.authorClick = new EventEmitter();
71
+ this.reactionClick = new EventEmitter();
72
+ this.actionClick = new EventEmitter();
73
+ this.menuItemClick = new EventEmitter();
74
+ this.commentLoadMore = new EventEmitter();
75
+ this.collapseToggle = new EventEmitter();
76
+ // Reply state
77
+ this.replyStart = new EventEmitter();
78
+ this.newCommentText = '';
79
+ this.replyingTo = null;
80
+ this.displayTitle = '';
81
+ this.displayLoadMoreLabel = '';
82
+ this.langSubscription = null;
83
+ this.langService = inject(LangService);
84
+ this.infiniteScrollEvent = null;
85
+ }
86
+ ngOnInit() {
87
+ this.updateDisplayTexts();
88
+ if (this.hasReactiveContent()) {
89
+ this.langSubscription = this.langService.currentLang$.subscribe(() => {
90
+ this.updateDisplayTexts();
91
+ });
92
+ }
93
+ }
94
+ ngOnDestroy() {
95
+ this.langSubscription?.unsubscribe();
96
+ }
97
+ hasReactiveContent() {
98
+ return !!((this.props.titleContentKey && this.props.contentClass) ||
99
+ (this.props.loadMoreContentKey && this.props.contentClass));
100
+ }
101
+ updateDisplayTexts() {
102
+ // Title
103
+ if (this.props.titleContentKey && this.props.contentClass) {
104
+ this.displayTitle = this.langService.getText(this.props.contentClass, this.props.titleContentKey, this.props.titleContentFallback || this.props.title || 'Comments');
105
+ }
106
+ else {
107
+ this.displayTitle = this.props.title || 'Comments';
108
+ }
109
+ // Load more label
110
+ if (this.props.loadMoreContentKey && this.props.contentClass) {
111
+ this.displayLoadMoreLabel = this.langService.getText(this.props.contentClass, this.props.loadMoreContentKey, this.props.loadMoreLabel || 'Load more comments');
112
+ }
113
+ else {
114
+ this.displayLoadMoreLabel = this.props.loadMoreLabel || 'Load more comments';
115
+ }
116
+ }
117
+ formatCount(count) {
118
+ if (count >= 1000000) {
119
+ return (count / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
120
+ }
121
+ if (count >= 1000) {
122
+ return (count / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
123
+ }
124
+ return count.toString();
125
+ }
126
+ getSortOptionLabel(option) {
127
+ if (option.contentKey && option.contentClass) {
128
+ return this.langService.getText(option.contentClass, option.contentKey, option.contentFallback || option.label);
129
+ }
130
+ return option.label;
131
+ }
132
+ getInputPlaceholder() {
133
+ const config = this.props.inputConfig;
134
+ if (config?.placeholderContentKey && config?.contentClass) {
135
+ return this.langService.getText(config.contentClass, config.placeholderContentKey, config.placeholder || 'Write a comment...');
136
+ }
137
+ return config?.placeholder || 'Write a comment...';
138
+ }
139
+ getSubmitLabel() {
140
+ const config = this.props.inputConfig;
141
+ if (config?.submitLabelContentKey && config?.contentClass) {
142
+ return this.langService.getText(config.contentClass, config.submitLabelContentKey, config.submitLabel || 'Post');
143
+ }
144
+ return config?.submitLabel || 'Post';
145
+ }
146
+ getEmptyTitle() {
147
+ const empty = this.props.emptyState;
148
+ if (empty?.titleContentKey && empty?.contentClass) {
149
+ return this.langService.getText(empty.contentClass, empty.titleContentKey, empty.title || 'No comments yet');
150
+ }
151
+ return empty?.title || 'No comments yet';
152
+ }
153
+ getEmptyMessage() {
154
+ const empty = this.props.emptyState;
155
+ if (empty?.messageContentKey && empty?.contentClass) {
156
+ return this.langService.getText(empty.contentClass, empty.messageContentKey, empty.message || 'Be the first to share your thoughts!');
157
+ }
158
+ return empty?.message || 'Be the first to share your thoughts!';
159
+ }
160
+ getSkeletonArray() {
161
+ const count = this.props.skeletonCount || 3;
162
+ return Array(count).fill(0).map((_, i) => i);
163
+ }
164
+ canSubmit() {
165
+ const minLength = this.props.inputConfig?.minLength || 1;
166
+ return (this.newCommentText.trim().length >= minLength &&
167
+ !this.props.loading &&
168
+ !this.props.inputConfig?.disabled);
169
+ }
170
+ isNearLimit() {
171
+ const maxLength = this.props.inputConfig?.maxLength || 2000;
172
+ return this.newCommentText.length > maxLength * 0.9;
173
+ }
174
+ onSortChange(event) {
175
+ const selectedToken = event.detail.value;
176
+ const option = this.props.sortOptions?.find((o) => o.token === selectedToken);
177
+ if (option) {
178
+ this.sortChange.emit({
179
+ option,
180
+ previousSort: this.props.selectedSort,
181
+ });
182
+ }
183
+ }
184
+ onSubmitComment() {
185
+ if (!this.canSubmit())
186
+ return;
187
+ this.commentSubmit.emit({
188
+ content: this.newCommentText.trim(),
189
+ parentToken: this.replyingTo || undefined,
190
+ sectionToken: this.props.token,
191
+ });
192
+ this.newCommentText = '';
193
+ this.replyingTo = null;
194
+ }
195
+ onCommentAction(event) {
196
+ // Check if it's a reply action
197
+ if (event.action.token === 'reply') {
198
+ this.replyingTo = event.commentToken;
199
+ this.replyStart.emit({ commentToken: event.commentToken });
200
+ }
201
+ this.actionClick.emit(event);
202
+ }
203
+ onLoadMore() {
204
+ this.loadMore.emit({
205
+ sectionToken: this.props.token,
206
+ currentCount: this.props.comments?.length || 0,
207
+ });
208
+ }
209
+ onInfiniteScroll(event) {
210
+ this.loadMore.emit({
211
+ sectionToken: this.props.token,
212
+ currentCount: this.props.comments?.length || 0,
213
+ });
214
+ // The parent component should call completeInfiniteScroll() when done loading
215
+ // Store reference to complete the infinite scroll
216
+ this.infiniteScrollEvent = event;
217
+ }
218
+ // Call this method from parent after loading more comments
219
+ completeInfiniteScroll() {
220
+ if (this.infiniteScrollEvent) {
221
+ this.infiniteScrollEvent.target.complete();
222
+ this.infiniteScrollEvent = null;
223
+ }
224
+ }
225
+ // Method to programmatically start a reply
226
+ startReply(commentToken) {
227
+ this.replyingTo = commentToken;
228
+ }
229
+ // Method to cancel reply
230
+ cancelReply() {
231
+ this.replyingTo = null;
232
+ }
233
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
234
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CommentSectionComponent, isStandalone: true, selector: "val-comment-section", inputs: { props: "props" }, outputs: { sortChange: "sortChange", commentSubmit: "commentSubmit", loadMore: "loadMore", authorClick: "authorClick", reactionClick: "reactionClick", actionClick: "actionClick", menuItemClick: "menuItemClick", commentLoadMore: "commentLoadMore", collapseToggle: "collapseToggle", replyStart: "replyStart" }, ngImport: i0, template: `
235
+ <div class="comment-section" [class.loading]="props.loading">
236
+ <!-- Header -->
237
+ <div class="section-header">
238
+ <div class="header-title">
239
+ <ion-icon name="chatbubbles-outline" class="title-icon"></ion-icon>
240
+ <h3 class="title">{{ displayTitle }}</h3>
241
+ @if (props.showCount !== false && props.count !== undefined) {
242
+ <ion-badge color="medium" class="count-badge">
243
+ {{ formatCount(props.count) }}
244
+ </ion-badge>
245
+ }
246
+ </div>
247
+
248
+ @if (props.sortOptions && props.sortOptions.length > 0) {
249
+ <div class="header-actions">
250
+ <ion-item lines="none" class="sort-select-item">
251
+ <ion-icon name="swap-vertical-outline" slot="start" class="sort-icon"></ion-icon>
252
+ <ion-select
253
+ [value]="props.selectedSort"
254
+ [placeholder]="props.sortLabel || 'Sort by'"
255
+ interface="popover"
256
+ (ionChange)="onSortChange($event)"
257
+ >
258
+ @for (option of props.sortOptions; track option.token) {
259
+ <ion-select-option [value]="option.token">
260
+ {{ getSortOptionLabel(option) }}
261
+ </ion-select-option>
262
+ }
263
+ </ion-select>
264
+ </ion-item>
265
+ </div>
266
+ }
267
+ </div>
268
+
269
+ <!-- New Comment Input -->
270
+ @if (props.showInput !== false) {
271
+ <div class="new-comment-section">
272
+ <div class="input-wrapper">
273
+ @if (props.inputConfig?.currentUser?.avatar) {
274
+ <div class="input-avatar">
275
+ <val-avatar [props]="props.inputConfig.currentUser.avatar"></val-avatar>
276
+ </div>
277
+ }
278
+
279
+ <div class="input-container">
280
+ <ion-textarea
281
+ [(ngModel)]="newCommentText"
282
+ [placeholder]="getInputPlaceholder()"
283
+ [maxlength]="props.inputConfig?.maxLength || 2000"
284
+ [disabled]="props.inputConfig?.disabled || props.loading"
285
+ [autoGrow]="true"
286
+ rows="2"
287
+ class="comment-textarea"
288
+ ></ion-textarea>
289
+
290
+ <div class="input-actions">
291
+ @if (props.inputConfig?.showCounter && props.inputConfig?.maxLength) {
292
+ <span class="char-counter" [class.warning]="isNearLimit()">
293
+ {{ newCommentText.length }} / {{ props.inputConfig.maxLength }}
294
+ </span>
295
+ }
296
+
297
+ <ion-button
298
+ [color]="props.inputConfig?.submitColor || props.color || 'primary'"
299
+ [disabled]="!canSubmit()"
300
+ size="small"
301
+ (click)="onSubmitComment()"
302
+ >
303
+ <ion-icon name="send-outline" slot="start"></ion-icon>
304
+ {{ getSubmitLabel() }}
305
+ </ion-button>
306
+ </div>
307
+ </div>
308
+ </div>
309
+ </div>
310
+ }
311
+
312
+ @if (props.loading) {
313
+ <div class="loading-state">
314
+ @for (i of getSkeletonArray(); track i) {
315
+ <div class="skeleton-comment">
316
+ <val-skeleton [props]="{ type: 'avatar', width: '36px', height: '36px' }"></val-skeleton>
317
+ <div class="skeleton-content">
318
+ <val-skeleton [props]="{ type: 'text', width: '120px', height: '14px' }"></val-skeleton>
319
+ <val-skeleton [props]="{ type: 'paragraph', lines: 2 }"></val-skeleton>
320
+ </div>
321
+ </div>
322
+ }
323
+ </div>
324
+ } @else if (props.comments && props.comments.length > 0) {
325
+ <div class="comments-list" [class.with-dividers]="props.showDividers">
326
+ @for (comment of props.comments; track comment.token) {
327
+ <val-comment
328
+ [props]="comment"
329
+ (authorClick)="authorClick.emit($event)"
330
+ (reactionClick)="reactionClick.emit($event)"
331
+ (actionClick)="onCommentAction($event)"
332
+ (menuItemClick)="menuItemClick.emit($event)"
333
+ (loadMoreClick)="commentLoadMore.emit($event)"
334
+ (collapseToggle)="collapseToggle.emit($event)"
335
+ ></val-comment>
336
+
337
+ @if (props.showDividers && !$last) {
338
+ <div class="comment-divider"></div>
339
+ }
340
+ }
341
+
342
+ @if (props.hasMore && props.paginationMode !== 'infinite') {
343
+ <div class="load-more-section">
344
+ @if (props.loadingMore) {
345
+ <ion-spinner name="crescent" [color]="props.color || 'primary'"></ion-spinner>
346
+ } @else {
347
+ <ion-button
348
+ fill="outline"
349
+ [color]="props.color || 'primary'"
350
+ expand="block"
351
+ (click)="onLoadMore()"
352
+ >
353
+ {{ displayLoadMoreLabel }}
354
+ </ion-button>
355
+ }
356
+ </div>
357
+ }
358
+ </div>
359
+
360
+ @if (props.paginationMode === 'infinite') {
361
+ <ion-infinite-scroll
362
+ [threshold]="props.infiniteScrollThreshold || '100px'"
363
+ [position]="props.infiniteScrollPosition || 'bottom'"
364
+ [disabled]="!props.hasMore"
365
+ (ionInfinite)="onInfiniteScroll($event)"
366
+ >
367
+ <ion-infinite-scroll-content
368
+ [loadingSpinner]="'crescent'"
369
+ [loadingText]="displayLoadMoreLabel"
370
+ ></ion-infinite-scroll-content>
371
+ </ion-infinite-scroll>
372
+ }
373
+ } @else {
374
+ <div class="empty-state">
375
+ <ion-icon
376
+ [name]="props.emptyState?.icon || 'chatbubble-ellipses-outline'"
377
+ class="empty-icon"
378
+ ></ion-icon>
379
+ <h4 class="empty-title">{{ getEmptyTitle() }}</h4>
380
+ <p class="empty-message">{{ getEmptyMessage() }}</p>
381
+ </div>
382
+ }
383
+ </div>
384
+ `, isInline: true, styles: [":host{display:block}.comment-section.loading{pointer-events:none}.section-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--ion-color-light-shade)}.header-title{display:flex;align-items:center;gap:8px}.title-icon{font-size:24px;color:var(--ion-color-primary)}.title{margin:0;font-size:18px;font-weight:600;color:var(--ion-text-color)}.count-badge{font-size:12px;font-weight:600;--padding-start: 8px;--padding-end: 8px}.header-actions{display:flex;align-items:center;gap:8px}.sort-select-item{--padding-start: 0;--padding-end: 0;--inner-padding-end: 0;--background: transparent;--min-height: 36px}.sort-select-item ion-select{--padding-start: 8px;--padding-end: 8px;min-width:140px;font-size:14px}.sort-icon{font-size:18px;color:var(--ion-color-medium);margin-right:4px}.new-comment-section{margin-bottom:24px;padding:16px;background-color:var(--ion-color-light);border-radius:12px}.input-wrapper{display:flex;gap:12px}.input-avatar{flex-shrink:0}.input-avatar val-avatar{--size: 40px}.input-container{flex:1;min-width:0}.comment-textarea{--background: var(--ion-background-color);--padding-start: 12px;--padding-end: 12px;--padding-top: 10px;--padding-bottom: 10px;border-radius:8px;font-size:14px;min-height:60px;border:1px solid var(--ion-color-light-shade);transition:border-color .2s}.comment-textarea:focus-within{border-color:var(--ion-color-primary)}.input-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:10px}.char-counter{font-size:12px;color:var(--ion-color-medium)}.char-counter.warning{color:var(--ion-color-warning);font-weight:500}.loading-state{display:flex;flex-direction:column;gap:20px}.skeleton-comment{display:flex;gap:12px;padding:12px 0}.skeleton-comment .skeleton-content{flex:1;display:flex;flex-direction:column;gap:8px}.comments-list.with-dividers val-comment{padding:16px 0}.comments-list.with-dividers val-comment:first-child{padding-top:0}.comment-divider{height:1px;background-color:var(--ion-color-light-shade);margin:0}.load-more-section{display:flex;justify-content:center;padding:20px 0}.load-more-section ion-button{min-width:200px}.load-more-section ion-spinner{width:28px;height:28px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center}.empty-icon{font-size:64px;color:var(--ion-color-medium);opacity:.5;margin-bottom:16px}.empty-title{margin:0 0 8px;font-size:18px;font-weight:600;color:var(--ion-text-color)}.empty-message{margin:0;font-size:14px;color:var(--ion-color-medium);max-width:300px}@media (max-width: 576px){.section-header{flex-direction:column;align-items:flex-start}.header-actions,.sort-select-item{width:100%}.sort-select-item ion-select{width:100%}.input-wrapper{flex-direction:column}.input-avatar{display:none}.input-actions{flex-direction:column;align-items:stretch}.input-actions ion-button{width:100%}}@media (prefers-color-scheme: dark){.new-comment-section{background-color:var(--ion-color-step-100, #1a1a1a)}.comment-textarea{--background: var(--ion-color-step-50, #121212);border-color:var(--ion-color-step-200, #2a2a2a)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: CommentComponent, selector: "val-comment", inputs: ["props"], outputs: ["authorClick", "reactionClick", "actionClick", "menuItemClick", "loadMoreClick", "collapseToggle"] }, { kind: "component", type: AvatarComponent, selector: "val-avatar", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: SkeletonComponent, selector: "val-skeleton", inputs: ["props"] }] }); }
385
+ }
386
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CommentSectionComponent, decorators: [{
387
+ type: Component,
388
+ args: [{ selector: 'val-comment-section', standalone: true, imports: [
389
+ CommonModule,
390
+ FormsModule,
391
+ IonIcon,
392
+ IonButton,
393
+ IonBadge,
394
+ IonTextarea,
395
+ IonItem,
396
+ IonSelect,
397
+ IonSelectOption,
398
+ IonSpinner,
399
+ IonInfiniteScroll,
400
+ IonInfiniteScrollContent,
401
+ CommentComponent,
402
+ AvatarComponent,
403
+ SkeletonComponent,
404
+ ], template: `
405
+ <div class="comment-section" [class.loading]="props.loading">
406
+ <!-- Header -->
407
+ <div class="section-header">
408
+ <div class="header-title">
409
+ <ion-icon name="chatbubbles-outline" class="title-icon"></ion-icon>
410
+ <h3 class="title">{{ displayTitle }}</h3>
411
+ @if (props.showCount !== false && props.count !== undefined) {
412
+ <ion-badge color="medium" class="count-badge">
413
+ {{ formatCount(props.count) }}
414
+ </ion-badge>
415
+ }
416
+ </div>
417
+
418
+ @if (props.sortOptions && props.sortOptions.length > 0) {
419
+ <div class="header-actions">
420
+ <ion-item lines="none" class="sort-select-item">
421
+ <ion-icon name="swap-vertical-outline" slot="start" class="sort-icon"></ion-icon>
422
+ <ion-select
423
+ [value]="props.selectedSort"
424
+ [placeholder]="props.sortLabel || 'Sort by'"
425
+ interface="popover"
426
+ (ionChange)="onSortChange($event)"
427
+ >
428
+ @for (option of props.sortOptions; track option.token) {
429
+ <ion-select-option [value]="option.token">
430
+ {{ getSortOptionLabel(option) }}
431
+ </ion-select-option>
432
+ }
433
+ </ion-select>
434
+ </ion-item>
435
+ </div>
436
+ }
437
+ </div>
438
+
439
+ <!-- New Comment Input -->
440
+ @if (props.showInput !== false) {
441
+ <div class="new-comment-section">
442
+ <div class="input-wrapper">
443
+ @if (props.inputConfig?.currentUser?.avatar) {
444
+ <div class="input-avatar">
445
+ <val-avatar [props]="props.inputConfig.currentUser.avatar"></val-avatar>
446
+ </div>
447
+ }
448
+
449
+ <div class="input-container">
450
+ <ion-textarea
451
+ [(ngModel)]="newCommentText"
452
+ [placeholder]="getInputPlaceholder()"
453
+ [maxlength]="props.inputConfig?.maxLength || 2000"
454
+ [disabled]="props.inputConfig?.disabled || props.loading"
455
+ [autoGrow]="true"
456
+ rows="2"
457
+ class="comment-textarea"
458
+ ></ion-textarea>
459
+
460
+ <div class="input-actions">
461
+ @if (props.inputConfig?.showCounter && props.inputConfig?.maxLength) {
462
+ <span class="char-counter" [class.warning]="isNearLimit()">
463
+ {{ newCommentText.length }} / {{ props.inputConfig.maxLength }}
464
+ </span>
465
+ }
466
+
467
+ <ion-button
468
+ [color]="props.inputConfig?.submitColor || props.color || 'primary'"
469
+ [disabled]="!canSubmit()"
470
+ size="small"
471
+ (click)="onSubmitComment()"
472
+ >
473
+ <ion-icon name="send-outline" slot="start"></ion-icon>
474
+ {{ getSubmitLabel() }}
475
+ </ion-button>
476
+ </div>
477
+ </div>
478
+ </div>
479
+ </div>
480
+ }
481
+
482
+ @if (props.loading) {
483
+ <div class="loading-state">
484
+ @for (i of getSkeletonArray(); track i) {
485
+ <div class="skeleton-comment">
486
+ <val-skeleton [props]="{ type: 'avatar', width: '36px', height: '36px' }"></val-skeleton>
487
+ <div class="skeleton-content">
488
+ <val-skeleton [props]="{ type: 'text', width: '120px', height: '14px' }"></val-skeleton>
489
+ <val-skeleton [props]="{ type: 'paragraph', lines: 2 }"></val-skeleton>
490
+ </div>
491
+ </div>
492
+ }
493
+ </div>
494
+ } @else if (props.comments && props.comments.length > 0) {
495
+ <div class="comments-list" [class.with-dividers]="props.showDividers">
496
+ @for (comment of props.comments; track comment.token) {
497
+ <val-comment
498
+ [props]="comment"
499
+ (authorClick)="authorClick.emit($event)"
500
+ (reactionClick)="reactionClick.emit($event)"
501
+ (actionClick)="onCommentAction($event)"
502
+ (menuItemClick)="menuItemClick.emit($event)"
503
+ (loadMoreClick)="commentLoadMore.emit($event)"
504
+ (collapseToggle)="collapseToggle.emit($event)"
505
+ ></val-comment>
506
+
507
+ @if (props.showDividers && !$last) {
508
+ <div class="comment-divider"></div>
509
+ }
510
+ }
511
+
512
+ @if (props.hasMore && props.paginationMode !== 'infinite') {
513
+ <div class="load-more-section">
514
+ @if (props.loadingMore) {
515
+ <ion-spinner name="crescent" [color]="props.color || 'primary'"></ion-spinner>
516
+ } @else {
517
+ <ion-button
518
+ fill="outline"
519
+ [color]="props.color || 'primary'"
520
+ expand="block"
521
+ (click)="onLoadMore()"
522
+ >
523
+ {{ displayLoadMoreLabel }}
524
+ </ion-button>
525
+ }
526
+ </div>
527
+ }
528
+ </div>
529
+
530
+ @if (props.paginationMode === 'infinite') {
531
+ <ion-infinite-scroll
532
+ [threshold]="props.infiniteScrollThreshold || '100px'"
533
+ [position]="props.infiniteScrollPosition || 'bottom'"
534
+ [disabled]="!props.hasMore"
535
+ (ionInfinite)="onInfiniteScroll($event)"
536
+ >
537
+ <ion-infinite-scroll-content
538
+ [loadingSpinner]="'crescent'"
539
+ [loadingText]="displayLoadMoreLabel"
540
+ ></ion-infinite-scroll-content>
541
+ </ion-infinite-scroll>
542
+ }
543
+ } @else {
544
+ <div class="empty-state">
545
+ <ion-icon
546
+ [name]="props.emptyState?.icon || 'chatbubble-ellipses-outline'"
547
+ class="empty-icon"
548
+ ></ion-icon>
549
+ <h4 class="empty-title">{{ getEmptyTitle() }}</h4>
550
+ <p class="empty-message">{{ getEmptyMessage() }}</p>
551
+ </div>
552
+ }
553
+ </div>
554
+ `, styles: [":host{display:block}.comment-section.loading{pointer-events:none}.section-header{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--ion-color-light-shade)}.header-title{display:flex;align-items:center;gap:8px}.title-icon{font-size:24px;color:var(--ion-color-primary)}.title{margin:0;font-size:18px;font-weight:600;color:var(--ion-text-color)}.count-badge{font-size:12px;font-weight:600;--padding-start: 8px;--padding-end: 8px}.header-actions{display:flex;align-items:center;gap:8px}.sort-select-item{--padding-start: 0;--padding-end: 0;--inner-padding-end: 0;--background: transparent;--min-height: 36px}.sort-select-item ion-select{--padding-start: 8px;--padding-end: 8px;min-width:140px;font-size:14px}.sort-icon{font-size:18px;color:var(--ion-color-medium);margin-right:4px}.new-comment-section{margin-bottom:24px;padding:16px;background-color:var(--ion-color-light);border-radius:12px}.input-wrapper{display:flex;gap:12px}.input-avatar{flex-shrink:0}.input-avatar val-avatar{--size: 40px}.input-container{flex:1;min-width:0}.comment-textarea{--background: var(--ion-background-color);--padding-start: 12px;--padding-end: 12px;--padding-top: 10px;--padding-bottom: 10px;border-radius:8px;font-size:14px;min-height:60px;border:1px solid var(--ion-color-light-shade);transition:border-color .2s}.comment-textarea:focus-within{border-color:var(--ion-color-primary)}.input-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:10px}.char-counter{font-size:12px;color:var(--ion-color-medium)}.char-counter.warning{color:var(--ion-color-warning);font-weight:500}.loading-state{display:flex;flex-direction:column;gap:20px}.skeleton-comment{display:flex;gap:12px;padding:12px 0}.skeleton-comment .skeleton-content{flex:1;display:flex;flex-direction:column;gap:8px}.comments-list.with-dividers val-comment{padding:16px 0}.comments-list.with-dividers val-comment:first-child{padding-top:0}.comment-divider{height:1px;background-color:var(--ion-color-light-shade);margin:0}.load-more-section{display:flex;justify-content:center;padding:20px 0}.load-more-section ion-button{min-width:200px}.load-more-section ion-spinner{width:28px;height:28px}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px 24px;text-align:center}.empty-icon{font-size:64px;color:var(--ion-color-medium);opacity:.5;margin-bottom:16px}.empty-title{margin:0 0 8px;font-size:18px;font-weight:600;color:var(--ion-text-color)}.empty-message{margin:0;font-size:14px;color:var(--ion-color-medium);max-width:300px}@media (max-width: 576px){.section-header{flex-direction:column;align-items:flex-start}.header-actions,.sort-select-item{width:100%}.sort-select-item ion-select{width:100%}.input-wrapper{flex-direction:column}.input-avatar{display:none}.input-actions{flex-direction:column;align-items:stretch}.input-actions ion-button{width:100%}}@media (prefers-color-scheme: dark){.new-comment-section{background-color:var(--ion-color-step-100, #1a1a1a)}.comment-textarea{--background: var(--ion-color-step-50, #121212);border-color:var(--ion-color-step-200, #2a2a2a)}}\n"] }]
555
+ }], propDecorators: { props: [{
556
+ type: Input
557
+ }], sortChange: [{
558
+ type: Output
559
+ }], commentSubmit: [{
560
+ type: Output
561
+ }], loadMore: [{
562
+ type: Output
563
+ }], authorClick: [{
564
+ type: Output
565
+ }], reactionClick: [{
566
+ type: Output
567
+ }], actionClick: [{
568
+ type: Output
569
+ }], menuItemClick: [{
570
+ type: Output
571
+ }], commentLoadMore: [{
572
+ type: Output
573
+ }], collapseToggle: [{
574
+ type: Output
575
+ }], replyStart: [{
576
+ type: Output
577
+ }] } });
578
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWVudC1zZWN0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbmlzbXMvY29tbWVudC1zZWN0aW9uL2NvbW1lbnQtc2VjdGlvbi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBcUIsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUNMLE9BQU8sRUFDUCxTQUFTLEVBQ1QsUUFBUSxFQUNSLFdBQVcsRUFDWCxPQUFPLEVBQ1AsU0FBUyxFQUNULGVBQWUsRUFDZixVQUFVLEVBQ1YsaUJBQWlCLEVBQ2pCLHdCQUF3QixHQUN6QixNQUFNLDJCQUEyQixDQUFDO0FBRW5DLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsV0FBVyxFQUNYLHlCQUF5QixFQUN6QixtQkFBbUIsR0FDcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM3RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDNUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVEQUF1RCxDQUFDOzs7QUFnQnBGLFFBQVEsQ0FBQztJQUNQLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsV0FBVztJQUNYLHlCQUF5QjtJQUN6QixtQkFBbUI7Q0FDcEIsQ0FB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IElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPbkRlc3Ryb3ksIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgSW9uSWNvbixcbiAgSW9uQnV0dG9uLFxuICBJb25CYWRnZSxcbiAgSW9uVGV4dGFyZWEsXG4gIElvbkl0ZW0sXG4gIElvblNlbGVjdCxcbiAgSW9uU2VsZWN0T3B0aW9uLFxuICBJb25TcGlubmVyLFxuICBJb25JbmZpbml0ZVNjcm9sbCxcbiAgSW9uSW5maW5pdGVTY3JvbGxDb250ZW50LFxufSBmcm9tICdAaW9uaWMvYW5ndWxhci9zdGFuZGFsb25lJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgYWRkSWNvbnMgfSBmcm9tICdpb25pY29ucyc7XG5pbXBvcnQge1xuICBjaGF0YnViYmxlc091dGxpbmUsXG4gIGZpbHRlck91dGxpbmUsXG4gIHNlbmRPdXRsaW5lLFxuICBjaGF0YnViYmxlRWxsaXBzZXNPdXRsaW5lLFxuICBzd2FwVmVydGljYWxPdXRsaW5lLFxufSBmcm9tICdpb25pY29ucy9pY29ucyc7XG5cbmltcG9ydCB7IENvbW1lbnRDb21wb25lbnQgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvY29tbWVudC9jb21tZW50LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBBdmF0YXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9hdmF0YXIvYXZhdGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTa2VsZXRvbkNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL3NrZWxldG9uL3NrZWxldG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBMYW5nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2xhbmctcHJvdmlkZXIvbGFuZy1wcm92aWRlci5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIENvbW1lbnRTZWN0aW9uTWV0YWRhdGEsXG4gIENvbW1lbnRTb3J0T3B0aW9uLFxuICBDb21tZW50U29ydENoYW5nZUV2ZW50LFxuICBDb21tZW50U3VibWl0RXZlbnQsXG4gIENvbW1lbnRTZWN0aW9uTG9hZE1vcmVFdmVudCxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBDb21tZW50QXV0aG9yQ2xpY2tFdmVudCxcbiAgQ29tbWVudFJlYWN0aW9uQ2xpY2tFdmVudCxcbiAgQ29tbWVudEFjdGlvbkNsaWNrRXZlbnQsXG4gIENvbW1lbnRNZW51SXRlbUNsaWNrRXZlbnQsXG4gIENvbW1lbnRMb2FkTW9yZUV2ZW50LFxufSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvY29tbWVudC90eXBlcyc7XG5cbmFkZEljb25zKHtcbiAgY2hhdGJ1YmJsZXNPdXRsaW5lLFxuICBmaWx0ZXJPdXRsaW5lLFxuICBzZW5kT3V0bGluZSxcbiAgY2hhdGJ1YmJsZUVsbGlwc2VzT3V0bGluZSxcbiAgc3dhcFZlcnRpY2FsT3V0bGluZSxcbn0pO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtY29tbWVudC1zZWN0aW9uJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBJb25JY29uLFxuICAgIElvbkJ1dHRvbixcbiAgICBJb25CYWRnZSxcbiAgICBJb25UZXh0YXJlYSxcbiAgICBJb25JdGVtLFxuICAgIElvblNlbGVjdCxcbiAgICBJb25TZWxlY3RPcHRpb24sXG4gICAgSW9uU3Bpbm5lcixcbiAgICBJb25JbmZpbml0ZVNjcm9sbCxcbiAgICBJb25JbmZpbml0ZVNjcm9sbENvbnRlbnQsXG4gICAgQ29tbWVudENvbXBvbmVudCxcbiAgICBBdmF0YXJDb21wb25lbnQsXG4gICAgU2tlbGV0b25Db21wb25lbnQsXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImNvbW1lbnQtc2VjdGlvblwiIFtjbGFzcy5sb2FkaW5nXT1cInByb3BzLmxvYWRpbmdcIj5cbiAgICAgIDwhLS0gSGVhZGVyIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItdGl0bGVcIj5cbiAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImNoYXRidWJibGVzLW91dGxpbmVcIiBjbGFzcz1cInRpdGxlLWljb25cIj48L2lvbi1pY29uPlxuICAgICAgICAgIDxoMyBjbGFzcz1cInRpdGxlXCI+e3sgZGlzcGxheVRpdGxlIH19PC9oMz5cbiAgICAgICAgICBAaWYgKHByb3BzLnNob3dDb3VudCAhPT0gZmFsc2UgJiYgcHJvcHMuY291bnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgPGlvbi1iYWRnZSBjb2xvcj1cIm1lZGl1bVwiIGNsYXNzPVwiY291bnQtYmFkZ2VcIj5cbiAgICAgICAgICAgICAge3sgZm9ybWF0Q291bnQocHJvcHMuY291bnQpIH19XG4gICAgICAgICAgICA8L2lvbi1iYWRnZT5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIEBpZiAocHJvcHMuc29ydE9wdGlvbnMgJiYgcHJvcHMuc29ydE9wdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItYWN0aW9uc1wiPlxuICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiIGNsYXNzPVwic29ydC1zZWxlY3QtaXRlbVwiPlxuICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cInN3YXAtdmVydGljYWwtb3V0bGluZVwiIHNsb3Q9XCJzdGFydFwiIGNsYXNzPVwic29ydC1pY29uXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgPGlvbi1zZWxlY3RcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwicHJvcHMuc2VsZWN0ZWRTb3J0XCJcbiAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicHJvcHMuc29ydExhYmVsIHx8ICdTb3J0IGJ5J1wiXG4gICAgICAgICAgICAgICAgaW50ZXJmYWNlPVwicG9wb3ZlclwiXG4gICAgICAgICAgICAgICAgKGlvbkNoYW5nZSk9XCJvblNvcnRDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgcHJvcHMuc29ydE9wdGlvbnM7IHRyYWNrIG9wdGlvbi50b2tlbikge1xuICAgICAgICAgICAgICAgICAgPGlvbi1zZWxlY3Qtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udG9rZW5cIj5cbiAgICAgICAgICAgICAgICAgICAge3sgZ2V0U29ydE9wdGlvbkxhYmVsKG9wdGlvbikgfX1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLXNlbGVjdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2lvbi1zZWxlY3Q+XG4gICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBOZXcgQ29tbWVudCBJbnB1dCAtLT5cbiAgICAgIEBpZiAocHJvcHMuc2hvd0lucHV0ICE9PSBmYWxzZSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibmV3LWNvbW1lbnQtc2VjdGlvblwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC13cmFwcGVyXCI+XG4gICAgICAgICAgICBAaWYgKHByb3BzLmlucHV0Q29uZmlnPy5jdXJyZW50VXNlcj8uYXZhdGFyKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1hdmF0YXJcIj5cbiAgICAgICAgICAgICAgICA8dmFsLWF2YXRhciBbcHJvcHNdPVwicHJvcHMuaW5wdXRDb25maWcuY3VycmVudFVzZXIuYXZhdGFyXCI+PC92YWwtYXZhdGFyPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICA8aW9uLXRleHRhcmVhXG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJuZXdDb21tZW50VGV4dFwiXG4gICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImdldElucHV0UGxhY2Vob2xkZXIoKVwiXG4gICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJwcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoIHx8IDIwMDBcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJwcm9wcy5pbnB1dENvbmZpZz8uZGlzYWJsZWQgfHwgcHJvcHMubG9hZGluZ1wiXG4gICAgICAgICAgICAgICAgW2F1dG9Hcm93XT1cInRydWVcIlxuICAgICAgICAgICAgICAgIHJvd3M9XCIyXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImNvbW1lbnQtdGV4dGFyZWFcIlxuICAgICAgICAgICAgICA+PC9pb24tdGV4dGFyZWE+XG5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWFjdGlvbnNcIj5cbiAgICAgICAgICAgICAgICBAaWYgKHByb3BzLmlucHV0Q29uZmlnPy5zaG93Q291bnRlciAmJiBwcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNoYXItY291bnRlclwiIFtjbGFzcy53YXJuaW5nXT1cImlzTmVhckxpbWl0KClcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgbmV3Q29tbWVudFRleHQubGVuZ3RoIH19IC8ge3sgcHJvcHMuaW5wdXRDb25maWcubWF4TGVuZ3RoIH19XG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIFtjb2xvcl09XCJwcm9wcy5pbnB1dENvbmZpZz8uc3VibWl0Q29sb3IgfHwgcHJvcHMuY29sb3IgfHwgJ3ByaW1hcnknXCJcbiAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuU3VibWl0KClcIlxuICAgICAgICAgICAgICAgICAgc2l6ZT1cInNtYWxsXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvblN1Ym1pdENvbW1lbnQoKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzZW5kLW91dGxpbmVcIiBzbG90PVwic3RhcnRcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgICAgICAge3sgZ2V0U3VibWl0TGFiZWwoKSB9fVxuICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG5cbiAgICAgIEBpZiAocHJvcHMubG9hZGluZykge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1zdGF0ZVwiPlxuICAgICAgICAgIEBmb3IgKGkgb2YgZ2V0U2tlbGV0b25BcnJheSgpOyB0cmFjayBpKSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2tlbGV0b24tY29tbWVudFwiPlxuICAgICAgICAgICAgICA8dmFsLXNrZWxldG9uIFtwcm9wc109XCJ7IHR5cGU6ICdhdmF0YXInLCB3aWR0aDogJzM2cHgnLCBoZWlnaHQ6ICczNnB4JyB9XCI+PC92YWwtc2tlbGV0b24+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJza2VsZXRvbi1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgPHZhbC1za2VsZXRvbiBbcHJvcHNdPVwieyB0eXBlOiAndGV4dCcsIHdpZHRoOiAnMTIwcHgnLCBoZWlnaHQ6ICcxNHB4JyB9XCI+PC92YWwtc2tlbGV0b24+XG4gICAgICAgICAgICAgICAgPHZhbC1za2VsZXRvbiBbcHJvcHNdPVwieyB0eXBlOiAncGFyYWdyYXBoJywgbGluZXM6IDIgfVwiPjwvdmFsLXNrZWxldG9uPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9IEBlbHNlIGlmIChwcm9wcy5jb21tZW50cyAmJiBwcm9wcy5jb21tZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb21tZW50cy1saXN0XCIgW2NsYXNzLndpdGgtZGl2aWRlcnNdPVwicHJvcHMuc2hvd0RpdmlkZXJzXCI+XG4gICAgICAgICAgQGZvciAoY29tbWVudCBvZiBwcm9wcy5jb21tZW50czsgdHJhY2sgY29tbWVudC50b2tlbikge1xuICAgICAgICAgICAgPHZhbC1jb21tZW50XG4gICAgICAgICAgICAgIFtwcm9wc109XCJjb21tZW50XCJcbiAgICAgICAgICAgICAgKGF1dGhvckNsaWNrKT1cImF1dGhvckNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgIChyZWFjdGlvbkNsaWNrKT1cInJlYWN0aW9uQ2xpY2suZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGFjdGlvbkNsaWNrKT1cIm9uQ29tbWVudEFjdGlvbigkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKG1lbnVJdGVtQ2xpY2spPVwibWVudUl0ZW1DbGljay5lbWl0KCRldmVudClcIlxuICAgICAgICAgICAgICAobG9hZE1vcmVDbGljayk9XCJjb21tZW50TG9hZE1vcmUuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGNvbGxhcHNlVG9nZ2xlKT1cImNvbGxhcHNlVG9nZ2xlLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICA+PC92YWwtY29tbWVudD5cblxuICAgICAgICAgICAgQGlmIChwcm9wcy5zaG93RGl2aWRlcnMgJiYgISRsYXN0KSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb21tZW50LWRpdmlkZXJcIj48L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBAaWYgKHByb3BzLmhhc01vcmUgJiYgcHJvcHMucGFnaW5hdGlvbk1vZGUgIT09ICdpbmZpbml0ZScpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkLW1vcmUtc2VjdGlvblwiPlxuICAgICAgICAgICAgICBAaWYgKHByb3BzLmxvYWRpbmdNb3JlKSB7XG4gICAgICAgICAgICAgICAgPGlvbi1zcGlubmVyIG5hbWU9XCJjcmVzY2VudFwiIFtjb2xvcl09XCJwcm9wcy5jb2xvciB8fCAncHJpbWFyeSdcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8aW9uLWJ1dHRvblxuICAgICAgICAgICAgICAgICAgZmlsbD1cIm91dGxpbmVcIlxuICAgICAgICAgICAgICAgICAgW2NvbG9yXT1cInByb3BzLmNvbG9yIHx8ICdwcmltYXJ5J1wiXG4gICAgICAgICAgICAgICAgICBleHBhbmQ9XCJibG9ja1wiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25Mb2FkTW9yZSgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7eyBkaXNwbGF5TG9hZE1vcmVMYWJlbCB9fVxuICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICBAaWYgKHByb3BzLnBhZ2luYXRpb25Nb2RlID09PSAnaW5maW5pdGUnKSB7XG4gICAgICAgICAgPGlvbi1pbmZpbml0ZS1zY3JvbGxcbiAgICAgICAgICAgIFt0aHJlc2hvbGRdPVwicHJvcHMuaW5maW5pdGVTY3JvbGxUaHJlc2hvbGQgfHwgJzEwMHB4J1wiXG4gICAgICAgICAgICBbcG9zaXRpb25dPVwicHJvcHMuaW5maW5pdGVTY3JvbGxQb3NpdGlvbiB8fCAnYm90dG9tJ1wiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByb3BzLmhhc01vcmVcIlxuICAgICAgICAgICAgKGlvbkluZmluaXRlKT1cIm9uSW5maW5pdGVTY3JvbGwoJGV2ZW50KVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGlvbi1pbmZpbml0ZS1zY3JvbGwtY29udGVudFxuICAgICAgICAgICAgICBbbG9hZGluZ1NwaW5uZXJdPVwiJ2NyZXNjZW50J1wiXG4gICAgICAgICAgICAgIFtsb2FkaW5nVGV4dF09XCJkaXNwbGF5TG9hZE1vcmVMYWJlbFwiXG4gICAgICAgICAgICA+PC9pb24taW5maW5pdGUtc2Nyb2xsLWNvbnRlbnQ+XG4gICAgICAgICAgPC9pb24taW5maW5pdGUtc2Nyb2xsPlxuICAgICAgICB9XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCI+XG4gICAgICAgICAgPGlvbi1pY29uXG4gICAgICAgICAgICBbbmFtZV09XCJwcm9wcy5lbXB0eVN0YXRlPy5pY29uIHx8ICdjaGF0YnViYmxlLWVsbGlwc2VzLW91dGxpbmUnXCJcbiAgICAgICAgICAgIGNsYXNzPVwiZW1wdHktaWNvblwiXG4gICAgICAgICAgPjwvaW9uLWljb24+XG4gICAgICAgICAgPGg0IGNsYXNzPVwiZW1wdHktdGl0bGVcIj57eyBnZXRFbXB0eVRpdGxlKCkgfX08L2g0PlxuICAgICAgICAgIDxwIGNsYXNzPVwiZW1wdHktbWVzc2FnZVwiPnt7IGdldEVtcHR5TWVzc2FnZSgpIH19PC9wPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vY29tbWVudC1zZWN0aW9uLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuLyoqXG4gKiB2YWwtY29tbWVudC1zZWN0aW9uXG4gKlxuICogQW4gb3JnYW5pc20gY29tcG9uZW50IHRoYXQgcHJvdmlkZXMgYSBjb21wbGV0ZSBjb21tZW50IHNlY3Rpb24gd2l0aDpcbiAqIC0gSGVhZGVyIHdpdGggdGl0bGUgYW5kIGNvdW50XG4gKiAtIFNvcnQvZmlsdGVyIG9wdGlvbnNcbiAqIC0gTmV3IGNvbW1lbnQgaW5wdXRcbiAqIC0gQ29tbWVudHMgbGlzdCB3aXRoIHZhbC1jb21tZW50XG4gKiAtIExvYWQgbW9yZSBwYWdpbmF0aW9uXG4gKiAtIEVtcHR5IHN0YXRlXG4gKlxuICogQGV4YW1wbGUgQmFzaWMgdXNhZ2VcbiAqIDx2YWwtY29tbWVudC1zZWN0aW9uIFtwcm9wc109XCJ7XG4gKiAgIHRpdGxlOiAnQ29tbWVudHMnLFxuICogICBjb3VudDogNDIsXG4gKiAgIGNvbW1lbnRzOiBjb21tZW50c0FycmF5LFxuICogICBzaG93SW5wdXQ6IHRydWVcbiAqIH1cIj48L3ZhbC1jb21tZW50LXNlY3Rpb24+XG4gKlxuICogQGV4YW1wbGUgV2l0aCBzb3J0aW5nXG4gKiA8dmFsLWNvbW1lbnQtc2VjdGlvbiBbcHJvcHNdPVwie1xuICogICB0aXRsZTogJ1Jldmlld3MnLFxuICogICBjb3VudDogMTI4LFxuICogICBjb21tZW50czogcmV2aWV3cyxcbiAqICAgc29ydE9wdGlvbnM6IFtcbiAqICAgICB7IHRva2VuOiAnbmV3ZXN0JywgbGFiZWw6ICdOZXdlc3QgZmlyc3QnIH0sXG4gKiAgICAgeyB0b2tlbjogJ29sZGVzdCcsIGxhYmVsOiAnT2xkZXN0IGZpcnN0JyB9LFxuICogICAgIHsgdG9rZW46ICdwb3B1bGFyJywgbGFiZWw6ICdNb3N0IHBvcHVsYXInIH1cbiAqICAgXSxcbiAqICAgc2VsZWN0ZWRTb3J0OiAnbmV3ZXN0J1xuICogfVwiIChzb3J0Q2hhbmdlKT1cIm9uU29ydCgkZXZlbnQpXCI+PC92YWwtY29tbWVudC1zZWN0aW9uPlxuICpcbiAqIEBpbnB1dCBwcm9wczogQ29tbWVudFNlY3Rpb25NZXRhZGF0YSAtIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBzZWN0aW9uXG4gKiBAb3V0cHV0IHNvcnRDaGFuZ2UgLSBTb3J0IG9wdGlvbiBjaGFuZ2VkXG4gKiBAb3V0cHV0IGNvbW1lbnRTdWJtaXQgLSBOZXcgY29tbWVudCBzdWJtaXR0ZWRcbiAqIEBvdXRwdXQgbG9hZE1vcmUgLSBMb2FkIG1vcmUgY2xpY2tlZFxuICogQG91dHB1dCBhdXRob3JDbGljayAtIENvbW1lbnQgYXV0aG9yIGNsaWNrZWQgKGJ1YmJsZWQgZnJvbSB2YWwtY29tbWVudClcbiAqIEBvdXRwdXQgcmVhY3Rpb25DbGljayAtIFJlYWN0aW9uIGNsaWNrZWQgKGJ1YmJsZWQpXG4gKiBAb3V0cHV0IGFjdGlvbkNsaWNrIC0gQWN0aW9uIGNsaWNrZWQgKGJ1YmJsZWQpXG4gKiBAb3V0cHV0IG1lbnVJdGVtQ2xpY2sgLSBNZW51IGl0ZW0gY2xpY2tlZCAoYnViYmxlZClcbiAqIEBvdXRwdXQgY29tbWVudExvYWRNb3JlIC0gTG9hZCBtb3JlIHJlcGxpZXMgY2xpY2tlZCAoYnViYmxlZClcbiAqIEBvdXRwdXQgY29sbGFwc2VUb2dnbGUgLSBDb21tZW50IGNvbGxhcHNlIHRvZ2dsZWQgKGJ1YmJsZWQpXG4gKi9cbmV4cG9ydCBjbGFzcyBDb21tZW50U2VjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KCkgcHJvcHM6IENvbW1lbnRTZWN0aW9uTWV0YWRhdGE7XG5cbiAgLy8gU2VjdGlvbiBldmVudHNcbiAgQE91dHB1dCgpIHNvcnRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENvbW1lbnRTb3J0Q2hhbmdlRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBjb21tZW50U3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50U3VibWl0RXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBsb2FkTW9yZSA9IG5ldyBFdmVudEVtaXR0ZXI8Q29tbWVudFNlY3Rpb25Mb2FkTW9yZUV2ZW50PigpO1xuXG4gIC8vIEJ1YmJsZWQgZXZlbnRzIGZyb20gdmFsLWNvbW1lbnRcbiAgQE91dHB1dCgpIGF1dGhvckNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50QXV0aG9yQ2xpY2tFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWN0aW9uQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPENvbW1lbnRSZWFjdGlvbkNsaWNrRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBhY3Rpb25DbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8Q29tbWVudEFjdGlvbkNsaWNrRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBtZW51SXRlbUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50TWVudUl0ZW1DbGlja0V2ZW50PigpO1xuICBAT3V0cHV0KCkgY29tbWVudExvYWRNb3JlID0gbmV3IEV2ZW50RW1pdHRlcjxDb21tZW50TG9hZE1vcmVFdmVudD4oKTtcbiAgQE91dHB1dCgpIGNvbGxhcHNlVG9nZ2xlID0gbmV3IEV2ZW50RW1pdHRlcjx7IHRva2VuOiBzdHJpbmc7IGNvbGxhcHNlZDogYm9vbGVhbiB9PigpO1xuXG4gIC8vIFJlcGx5IHN0YXRlXG4gIEBPdXRwdXQoKSByZXBseVN0YXJ0ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGNvbW1lbnRUb2tlbjogc3RyaW5nIH0+KCk7XG5cbiAgbmV3Q29tbWVudFRleHQgPSAnJztcbiAgcmVwbHlpbmdUbzogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgZGlzcGxheVRpdGxlID0gJyc7XG4gIGRpc3BsYXlMb2FkTW9yZUxhYmVsID0gJyc7XG5cbiAgcHJpdmF0ZSBsYW5nU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsYW5nU2VydmljZSA9IGluamVjdChMYW5nU2VydmljZSk7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVEaXNwbGF5VGV4dHMoKTtcblxuICAgIGlmICh0aGlzLmhhc1JlYWN0aXZlQ29udGVudCgpKSB7XG4gICAgICB0aGlzLmxhbmdTdWJzY3JpcHRpb24gPSB0aGlzLmxhbmdTZXJ2aWNlLmN1cnJlbnRMYW5nJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXlUZXh0cygpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5sYW5nU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNSZWFjdGl2ZUNvbnRlbnQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKFxuICAgICAgKHRoaXMucHJvcHMudGl0bGVDb250ZW50S2V5ICYmIHRoaXMucHJvcHMuY29udGVudENsYXNzKSB8fFxuICAgICAgKHRoaXMucHJvcHMubG9hZE1vcmVDb250ZW50S2V5ICYmIHRoaXMucHJvcHMuY29udGVudENsYXNzKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZURpc3BsYXlUZXh0cygpOiB2b2lkIHtcbiAgICAvLyBUaXRsZVxuICAgIGlmICh0aGlzLnByb3BzLnRpdGxlQ29udGVudEtleSAmJiB0aGlzLnByb3BzLmNvbnRlbnRDbGFzcykge1xuICAgICAgdGhpcy5kaXNwbGF5VGl0bGUgPSB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoXG4gICAgICAgIHRoaXMucHJvcHMuY29udGVudENsYXNzLFxuICAgICAgICB0aGlzLnByb3BzLnRpdGxlQ29udGVudEtleSxcbiAgICAgICAgdGhpcy5wcm9wcy50aXRsZUNvbnRlbnRGYWxsYmFjayB8fCB0aGlzLnByb3BzLnRpdGxlIHx8ICdDb21tZW50cydcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzcGxheVRpdGxlID0gdGhpcy5wcm9wcy50aXRsZSB8fCAnQ29tbWVudHMnO1xuICAgIH1cblxuICAgIC8vIExvYWQgbW9yZSBsYWJlbFxuICAgIGlmICh0aGlzLnByb3BzLmxvYWRNb3JlQ29udGVudEtleSAmJiB0aGlzLnByb3BzLmNvbnRlbnRDbGFzcykge1xuICAgICAgdGhpcy5kaXNwbGF5TG9hZE1vcmVMYWJlbCA9IHRoaXMubGFuZ1NlcnZpY2UuZ2V0VGV4dChcbiAgICAgICAgdGhpcy5wcm9wcy5jb250ZW50Q2xhc3MsXG4gICAgICAgIHRoaXMucHJvcHMubG9hZE1vcmVDb250ZW50S2V5LFxuICAgICAgICB0aGlzLnByb3BzLmxvYWRNb3JlTGFiZWwgfHwgJ0xvYWQgbW9yZSBjb21tZW50cydcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzcGxheUxvYWRNb3JlTGFiZWwgPSB0aGlzLnByb3BzLmxvYWRNb3JlTGFiZWwgfHwgJ0xvYWQgbW9yZSBjb21tZW50cyc7XG4gICAgfVxuICB9XG5cbiAgZm9ybWF0Q291bnQoY291bnQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKGNvdW50ID49IDEwMDAwMDApIHtcbiAgICAgIHJldHVybiAoY291bnQgLyAxMDAwMDAwKS50b0ZpeGVkKDEpLnJlcGxhY2UoL1xcLjAkLywgJycpICsgJ00nO1xuICAgIH1cbiAgICBpZiAoY291bnQgPj0gMTAwMCkge1xuICAgICAgcmV0dXJuIChjb3VudCAvIDEwMDApLnRvRml4ZWQoMSkucmVwbGFjZSgvXFwuMCQvLCAnJykgKyAnSyc7XG4gICAgfVxuICAgIHJldHVybiBjb3VudC50b1N0cmluZygpO1xuICB9XG5cbiAgZ2V0U29ydE9wdGlvbkxhYmVsKG9wdGlvbjogQ29tbWVudFNvcnRPcHRpb24pOiBzdHJpbmcge1xuICAgIGlmIChvcHRpb24uY29udGVudEtleSAmJiBvcHRpb24uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBvcHRpb24uY29udGVudENsYXNzLFxuICAgICAgICBvcHRpb24uY29udGVudEtleSxcbiAgICAgICAgb3B0aW9uLmNvbnRlbnRGYWxsYmFjayB8fCBvcHRpb24ubGFiZWxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBvcHRpb24ubGFiZWw7XG4gIH1cblxuICBnZXRJbnB1dFBsYWNlaG9sZGVyKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5wcm9wcy5pbnB1dENvbmZpZztcbiAgICBpZiAoY29uZmlnPy5wbGFjZWhvbGRlckNvbnRlbnRLZXkgJiYgY29uZmlnPy5jb250ZW50Q2xhc3MpIHtcbiAgICAgIHJldHVybiB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoXG4gICAgICAgIGNvbmZpZy5jb250ZW50Q2xhc3MsXG4gICAgICAgIGNvbmZpZy5wbGFjZWhvbGRlckNvbnRlbnRLZXksXG4gICAgICAgIGNvbmZpZy5wbGFjZWhvbGRlciB8fCAnV3JpdGUgYSBjb21tZW50Li4uJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbmZpZz8ucGxhY2Vob2xkZXIgfHwgJ1dyaXRlIGEgY29tbWVudC4uLic7XG4gIH1cblxuICBnZXRTdWJtaXRMYWJlbCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMucHJvcHMuaW5wdXRDb25maWc7XG4gICAgaWYgKGNvbmZpZz8uc3VibWl0TGFiZWxDb250ZW50S2V5ICYmIGNvbmZpZz8uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBjb25maWcuY29udGVudENsYXNzLFxuICAgICAgICBjb25maWcuc3VibWl0TGFiZWxDb250ZW50S2V5LFxuICAgICAgICBjb25maWcuc3VibWl0TGFiZWwgfHwgJ1Bvc3QnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY29uZmlnPy5zdWJtaXRMYWJlbCB8fCAnUG9zdCc7XG4gIH1cblxuICBnZXRFbXB0eVRpdGxlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZW1wdHkgPSB0aGlzLnByb3BzLmVtcHR5U3RhdGU7XG4gICAgaWYgKGVtcHR5Py50aXRsZUNvbnRlbnRLZXkgJiYgZW1wdHk/LmNvbnRlbnRDbGFzcykge1xuICAgICAgcmV0dXJuIHRoaXMubGFuZ1NlcnZpY2UuZ2V0VGV4dChcbiAgICAgICAgZW1wdHkuY29udGVudENsYXNzLFxuICAgICAgICBlbXB0eS50aXRsZUNvbnRlbnRLZXksXG4gICAgICAgIGVtcHR5LnRpdGxlIHx8ICdObyBjb21tZW50cyB5ZXQnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZW1wdHk/LnRpdGxlIHx8ICdObyBjb21tZW50cyB5ZXQnO1xuICB9XG5cbiAgZ2V0RW1wdHlNZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZW1wdHkgPSB0aGlzLnByb3BzLmVtcHR5U3RhdGU7XG4gICAgaWYgKGVtcHR5Py5tZXNzYWdlQ29udGVudEtleSAmJiBlbXB0eT8uY29udGVudENsYXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYW5nU2VydmljZS5nZXRUZXh0KFxuICAgICAgICBlbXB0eS5jb250ZW50Q2xhc3MsXG4gICAgICAgIGVtcHR5Lm1lc3NhZ2VDb250ZW50S2V5LFxuICAgICAgICBlbXB0eS5tZXNzYWdlIHx8ICdCZSB0aGUgZmlyc3QgdG8gc2hhcmUgeW91ciB0aG91Z2h0cyEnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZW1wdHk/Lm1lc3NhZ2UgfHwgJ0JlIHRoZSBmaXJzdCB0byBzaGFyZSB5b3VyIHRob3VnaHRzISc7XG4gIH1cblxuICBnZXRTa2VsZXRvbkFycmF5KCk6IG51bWJlcltdIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMucHJvcHMuc2tlbGV0b25Db3VudCB8fCAzO1xuICAgIHJldHVybiBBcnJheShjb3VudCkuZmlsbCgwKS5tYXAoKF8sIGkpID0+IGkpO1xuICB9XG5cbiAgY2FuU3VibWl0KCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1pbkxlbmd0aCA9IHRoaXMucHJvcHMuaW5wdXRDb25maWc/Lm1pbkxlbmd0aCB8fCAxO1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLm5ld0NvbW1lbnRUZXh0LnRyaW0oKS5sZW5ndGggPj0gbWluTGVuZ3RoICYmXG4gICAgICAhdGhpcy5wcm9wcy5sb2FkaW5nICYmXG4gICAgICAhdGhpcy5wcm9wcy5pbnB1dENvbmZpZz8uZGlzYWJsZWRcbiAgICApO1xuICB9XG5cbiAgaXNOZWFyTGltaXQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWF4TGVuZ3RoID0gdGhpcy5wcm9wcy5pbnB1dENvbmZpZz8ubWF4TGVuZ3RoIHx8IDIwMDA7XG4gICAgcmV0dXJuIHRoaXMubmV3Q29tbWVudFRleHQubGVuZ3RoID4gbWF4TGVuZ3RoICogMC45O1xuICB9XG5cbiAgb25Tb3J0Q2hhbmdlKGV2ZW50OiBDdXN0b21FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbGVjdGVkVG9rZW4gPSBldmVudC5kZXRhaWwudmFsdWU7XG4gICAgY29uc3Qgb3B0aW9uID0gdGhpcy5wcm9wcy5zb3J0T3B0aW9ucz8uZmluZCgobykgPT4gby50b2tlbiA9PT0gc2VsZWN0ZWRUb2tlbik7XG5cbiAgICBpZiAob3B0aW9uKSB7XG4gICAgICB0aGlzLnNvcnRDaGFuZ2UuZW1pdCh7XG4gICAgICAgIG9wdGlvbixcbiAgICAgICAgcHJldmlvdXNTb3J0OiB0aGlzLnByb3BzLnNlbGVjdGVkU29ydCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uU3VibWl0Q29tbWVudCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FuU3VibWl0KCkpIHJldHVybjtcblxuICAgIHRoaXMuY29tbWVudFN1Ym1pdC5lbWl0KHtcbiAgICAgIGNvbnRlbnQ6IHRoaXMubmV3Q29tbWVudFRleHQudHJpbSgpLFxuICAgICAgcGFyZW50VG9rZW46IHRoaXMucmVwbHlpbmdUbyB8fCB1bmRlZmluZWQsXG4gICAgICBzZWN0aW9uVG9rZW46IHRoaXMucHJvcHMudG9rZW4sXG4gICAgfSk7XG5cbiAgICB0aGlzLm5ld0NvbW1lbnRUZXh0ID0gJyc7XG4gICAgdGhpcy5yZXBseWluZ1RvID0gbnVsbDtcbiAgfVxuXG4gIG9uQ29tbWVudEFjdGlvbihldmVudDogQ29tbWVudEFjdGlvbkNsaWNrRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBDaGVjayBpZiBpdCdzIGEgcmVwbHkgYWN0aW9uXG4gICAgaWYgKGV2ZW50LmFjdGlvbi50b2tlbiA9PT0gJ3JlcGx5Jykge1xuICAgICAgdGhpcy5yZXBseWluZ1RvID0gZXZlbnQuY29tbWVudFRva2VuO1xuICAgICAgdGhpcy5yZXBseVN0YXJ0LmVtaXQoeyBjb21tZW50VG9rZW46IGV2ZW50LmNvbW1lbnRUb2tlbiB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmFjdGlvbkNsaWNrLmVtaXQoZXZlbnQpO1xuICB9XG5cbiAgb25Mb2FkTW9yZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxvYWRNb3JlLmVtaXQoe1xuICAgICAgc2VjdGlvblRva2VuOiB0aGlzLnByb3BzLnRva2VuLFxuICAgICAgY3VycmVudENvdW50OiB0aGlzLnByb3BzLmNvbW1lbnRzPy5sZW5ndGggfHwgMCxcbiAgICB9KTtcbiAgfVxuXG4gIG9uSW5maW5pdGVTY3JvbGwoZXZlbnQ6IEN1c3RvbUV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5sb2FkTW9yZS5lbWl0KHtcbiAgICAgIHNlY3Rpb25Ub2tlbjogdGhpcy5wcm9wcy50b2tlbixcbiAgICAgIGN1cnJlbnRDb3VudDogdGhpcy5wcm9wcy5jb21tZW50cz8ubGVuZ3RoIHx8IDAsXG4gICAgfSk7XG5cbiAgICAvLyBUaGUgcGFyZW50IGNvbXBvbmVudCBzaG91bGQgY2FsbCBjb21wbGV0ZUluZmluaXRlU2Nyb2xsKCkgd2hlbiBkb25lIGxvYWRpbmdcbiAgICAvLyBTdG9yZSByZWZlcmVuY2UgdG8gY29tcGxldGUgdGhlIGluZmluaXRlIHNjcm9sbFxuICAgIHRoaXMuaW5maW5pdGVTY3JvbGxFdmVudCA9IGV2ZW50O1xuICB9XG5cbiAgLy8gQ2FsbCB0aGlzIG1ldGhvZCBmcm9tIHBhcmVudCBhZnRlciBsb2FkaW5nIG1vcmUgY29tbWVudHNcbiAgY29tcGxldGVJbmZpbml0ZVNjcm9sbCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50KSB7XG4gICAgICAodGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50LnRhcmdldCBhcyBIVE1MSW9uSW5maW5pdGVTY3JvbGxFbGVtZW50KS5jb21wbGV0ZSgpO1xuICAgICAgdGhpcy5pbmZpbml0ZVNjcm9sbEV2ZW50ID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluZmluaXRlU2Nyb2xsRXZlbnQ6IEN1c3RvbUV2ZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gTWV0aG9kIHRvIHByb2dyYW1tYXRpY2FsbHkgc3RhcnQgYSByZXBseVxuICBzdGFydFJlcGx5KGNvbW1lbnRUb2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5yZXBseWluZ1RvID0gY29tbWVudFRva2VuO1xuICB9XG5cbiAgLy8gTWV0aG9kIHRvIGNhbmNlbCByZXBseVxuICBjYW5jZWxSZXBseSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlcGx5aW5nVG8gPSBudWxsO1xuICB9XG59XG4iXX0=