@tolle_/tolle-ui 18.2.29 → 18.2.30

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 (279) hide show
  1. package/esm2022/lib/accordion-item.component.mjs +5 -11
  2. package/esm2022/lib/accordion.component.mjs +4 -9
  3. package/esm2022/lib/alert-dialog-dynamic.component.mjs +5 -10
  4. package/esm2022/lib/alert-dialog.component.mjs +44 -59
  5. package/esm2022/lib/alert.component.mjs +5 -11
  6. package/esm2022/lib/aspect-ratio.component.mjs +119 -0
  7. package/esm2022/lib/attachment.component.mjs +334 -0
  8. package/esm2022/lib/avatar-fallback.component.mjs +3 -3
  9. package/esm2022/lib/avatar.component.mjs +4 -9
  10. package/esm2022/lib/badge.component.mjs +4 -9
  11. package/esm2022/lib/breadcrumb-item.component.mjs +3 -3
  12. package/esm2022/lib/breadcrumb-link.component.mjs +3 -3
  13. package/esm2022/lib/breadcrumb-separator.component.mjs +3 -3
  14. package/esm2022/lib/breadcrumb.component.mjs +3 -3
  15. package/esm2022/lib/bubble.component.mjs +301 -0
  16. package/esm2022/lib/button.component.mjs +5 -11
  17. package/esm2022/lib/calendar.component.mjs +5 -11
  18. package/esm2022/lib/card.component.mjs +14 -43
  19. package/esm2022/lib/carousel/carousel.component.mjs +5 -12
  20. package/esm2022/lib/chain-of-thought.component.mjs +380 -0
  21. package/esm2022/lib/chart-pie.component.mjs +386 -0
  22. package/esm2022/lib/chart.component.mjs +1146 -0
  23. package/esm2022/lib/chart.service.mjs +555 -0
  24. package/esm2022/lib/checkbox.component.mjs +5 -11
  25. package/esm2022/lib/checkpoint.component.mjs +134 -0
  26. package/esm2022/lib/collapsible.component.mjs +4 -11
  27. package/esm2022/lib/combobox.component.mjs +372 -0
  28. package/esm2022/lib/command-dialog.component.mjs +164 -0
  29. package/esm2022/lib/command.component.mjs +514 -0
  30. package/esm2022/lib/command.service.mjs +130 -0
  31. package/esm2022/lib/confirmation.component.mjs +219 -0
  32. package/esm2022/lib/context-menu-trigger.directive.mjs +36 -0
  33. package/esm2022/lib/context-menu.component.mjs +460 -0
  34. package/esm2022/lib/context-menu.service.mjs +121 -0
  35. package/esm2022/lib/context.component.mjs +377 -0
  36. package/esm2022/lib/conversation.component.mjs +442 -0
  37. package/esm2022/lib/country-selector.component.mjs +5 -11
  38. package/esm2022/lib/data-table.component.mjs +59 -12
  39. package/esm2022/lib/date-picker.component.mjs +251 -198
  40. package/esm2022/lib/date-range-picker.component.mjs +224 -116
  41. package/esm2022/lib/date-time-picker.component.mjs +506 -0
  42. package/esm2022/lib/direction.component.mjs +79 -0
  43. package/esm2022/lib/dropdown-item.component.mjs +3 -3
  44. package/esm2022/lib/dropdown-label.component.mjs +3 -3
  45. package/esm2022/lib/dropdown-menu.component.mjs +3 -3
  46. package/esm2022/lib/dropdown-separator.component.mjs +3 -3
  47. package/esm2022/lib/dropdown-trigger.directive.mjs +6 -4
  48. package/esm2022/lib/empty-state.component.mjs +4 -9
  49. package/esm2022/lib/field.component.mjs +394 -0
  50. package/esm2022/lib/hover-card.component.mjs +6 -16
  51. package/esm2022/lib/inline-citation.component.mjs +263 -0
  52. package/esm2022/lib/input-group.component.mjs +418 -0
  53. package/esm2022/lib/input.component.mjs +5 -11
  54. package/esm2022/lib/item.component.mjs +243 -0
  55. package/esm2022/lib/kbd.component.mjs +82 -0
  56. package/esm2022/lib/label.component.mjs +4 -9
  57. package/esm2022/lib/marker.component.mjs +135 -0
  58. package/esm2022/lib/masked-input.component.mjs +5 -11
  59. package/esm2022/lib/menubar.component.mjs +683 -0
  60. package/esm2022/lib/message-scroller.component.mjs +353 -0
  61. package/esm2022/lib/message-scroller.service.mjs +157 -0
  62. package/esm2022/lib/message.component.mjs +228 -0
  63. package/esm2022/lib/model-selector.component.mjs +310 -0
  64. package/esm2022/lib/multi-select.component.mjs +155 -72
  65. package/esm2022/lib/native-select.component.mjs +201 -0
  66. package/esm2022/lib/navigation-menu.component.mjs +642 -0
  67. package/esm2022/lib/otp-group.component.mjs +3 -3
  68. package/esm2022/lib/otp-slot.component.mjs +4 -9
  69. package/esm2022/lib/otp.component.mjs +5 -11
  70. package/esm2022/lib/pagination.component.mjs +7 -10
  71. package/esm2022/lib/plan.component.mjs +335 -0
  72. package/esm2022/lib/popover-content.component.mjs +4 -9
  73. package/esm2022/lib/popover.component.mjs +15 -13
  74. package/esm2022/lib/progress.component.mjs +4 -9
  75. package/esm2022/lib/prompt-input.component.mjs +526 -0
  76. package/esm2022/lib/queue.component.mjs +280 -0
  77. package/esm2022/lib/radio-group.component.mjs +6 -13
  78. package/esm2022/lib/radio-item.component.mjs +4 -9
  79. package/esm2022/lib/range-calendar.component.mjs +5 -11
  80. package/esm2022/lib/reasoning.component.mjs +335 -0
  81. package/esm2022/lib/resizable.component.mjs +219 -0
  82. package/esm2022/lib/segment.component.mjs +17 -7
  83. package/esm2022/lib/select-group.component.mjs +4 -8
  84. package/esm2022/lib/select-item.component.mjs +4 -9
  85. package/esm2022/lib/select-separator.component.mjs +4 -8
  86. package/esm2022/lib/select.component.mjs +133 -49
  87. package/esm2022/lib/separator.component.mjs +4 -9
  88. package/esm2022/lib/sheet.component.mjs +38 -56
  89. package/esm2022/lib/shimmer.component.mjs +84 -0
  90. package/esm2022/lib/sidebar.component.mjs +11 -1
  91. package/esm2022/lib/skeleton.component.mjs +4 -9
  92. package/esm2022/lib/sources.component.mjs +452 -0
  93. package/esm2022/lib/spinner.component.mjs +68 -0
  94. package/esm2022/lib/suggestion.component.mjs +207 -0
  95. package/esm2022/lib/switch.component.mjs +5 -11
  96. package/esm2022/lib/table.component.mjs +213 -0
  97. package/esm2022/lib/tabs.component.mjs +4 -11
  98. package/esm2022/lib/tag-input.component.mjs +5 -11
  99. package/esm2022/lib/task.component.mjs +359 -0
  100. package/esm2022/lib/textarea.component.mjs +5 -11
  101. package/esm2022/lib/theme.service.mjs +17 -6
  102. package/esm2022/lib/time-picker.component.mjs +923 -0
  103. package/esm2022/lib/toast.service.mjs +3 -2
  104. package/esm2022/lib/toaster.component.mjs +76 -39
  105. package/esm2022/lib/toggle-group.component.mjs +4 -9
  106. package/esm2022/lib/toggle.component.mjs +5 -11
  107. package/esm2022/lib/tool.component.mjs +462 -0
  108. package/esm2022/lib/typography.component.mjs +83 -0
  109. package/esm2022/lib/utils/color.mjs +140 -19
  110. package/esm2022/public-api.mjs +61 -1
  111. package/fesm2022/tolle-ui.mjs +16453 -1024
  112. package/fesm2022/tolle-ui.mjs.map +1 -1
  113. package/lib/alert-dialog.component.d.ts +10 -2
  114. package/lib/aspect-ratio.component.d.ts +20 -0
  115. package/lib/attachment.component.d.ts +101 -0
  116. package/lib/bubble.component.d.ts +112 -0
  117. package/lib/chain-of-thought.component.d.ts +166 -0
  118. package/lib/chart-pie.component.d.ts +108 -0
  119. package/lib/chart.component.d.ts +369 -0
  120. package/lib/chart.service.d.ts +222 -0
  121. package/lib/checkpoint.component.d.ts +51 -0
  122. package/lib/combobox.component.d.ts +90 -0
  123. package/lib/command-dialog.component.d.ts +53 -0
  124. package/lib/command.component.d.ts +189 -0
  125. package/lib/command.service.d.ts +67 -0
  126. package/lib/confirmation.component.d.ts +70 -0
  127. package/lib/context-menu-trigger.directive.d.ts +12 -0
  128. package/lib/context-menu.component.d.ts +41 -0
  129. package/lib/context-menu.service.d.ts +38 -0
  130. package/lib/context.component.d.ts +134 -0
  131. package/lib/conversation.component.d.ts +165 -0
  132. package/lib/data-table.component.d.ts +26 -1
  133. package/lib/date-picker.component.d.ts +72 -11
  134. package/lib/date-range-picker.component.d.ts +63 -6
  135. package/lib/date-time-picker.component.d.ts +119 -0
  136. package/lib/direction.component.d.ts +45 -0
  137. package/lib/field.component.d.ts +201 -0
  138. package/lib/inline-citation.component.d.ts +103 -0
  139. package/lib/input-group.component.d.ts +150 -0
  140. package/lib/item.component.d.ts +154 -0
  141. package/lib/kbd.component.d.ts +50 -0
  142. package/lib/marker.component.d.ts +58 -0
  143. package/lib/menubar.component.d.ts +247 -0
  144. package/lib/message-scroller.component.d.ts +159 -0
  145. package/lib/message-scroller.service.d.ts +73 -0
  146. package/lib/message.component.d.ts +128 -0
  147. package/lib/model-selector.component.d.ts +103 -0
  148. package/lib/multi-select.component.d.ts +66 -14
  149. package/lib/native-select.component.d.ts +57 -0
  150. package/lib/navigation-menu.component.d.ts +230 -0
  151. package/lib/plan.component.d.ts +120 -0
  152. package/lib/popover.component.d.ts +1 -0
  153. package/lib/prompt-input.component.d.ts +194 -0
  154. package/lib/queue.component.d.ts +106 -0
  155. package/lib/reasoning.component.d.ts +127 -0
  156. package/lib/resizable.component.d.ts +43 -0
  157. package/lib/segment.component.d.ts +13 -3
  158. package/lib/select.component.d.ts +37 -5
  159. package/lib/sheet.component.d.ts +3 -0
  160. package/lib/shimmer.component.d.ts +38 -0
  161. package/lib/sidebar.component.d.ts +2 -0
  162. package/lib/sources.component.d.ts +156 -0
  163. package/lib/spinner.component.d.ts +29 -0
  164. package/lib/suggestion.component.d.ts +96 -0
  165. package/lib/table.component.d.ts +106 -0
  166. package/lib/task.component.d.ts +151 -0
  167. package/lib/theme.service.d.ts +9 -0
  168. package/lib/time-picker.component.d.ts +243 -0
  169. package/lib/toast.service.d.ts +3 -1
  170. package/lib/toaster.component.d.ts +26 -9
  171. package/lib/tool.component.d.ts +158 -0
  172. package/lib/typography.component.d.ts +32 -0
  173. package/lib/utils/color.d.ts +19 -5
  174. package/package.json +1 -1
  175. package/public-api.d.ts +50 -0
  176. package/registry/docs-content.json +8480 -1542
  177. package/registry/llms-full.txt +2679 -319
  178. package/registry/llms.txt +43 -4
  179. package/registry/manifest.json +9090 -1742
  180. package/registry/r/accordion-item.json +1 -1
  181. package/registry/r/accordion.json +1 -1
  182. package/registry/r/alert-dialog-dynamic.json +1 -1
  183. package/registry/r/alert-dialog.json +1 -1
  184. package/registry/r/alert.json +1 -1
  185. package/registry/r/attachment.json +23 -0
  186. package/registry/r/avatar-fallback.json +1 -1
  187. package/registry/r/avatar.json +1 -1
  188. package/registry/r/badge.json +1 -1
  189. package/registry/r/breadcrumb-item.json +1 -1
  190. package/registry/r/breadcrumb-link.json +1 -1
  191. package/registry/r/breadcrumb-separator.json +1 -1
  192. package/registry/r/breadcrumb.json +1 -1
  193. package/registry/r/bubble.json +23 -0
  194. package/registry/r/button.json +1 -1
  195. package/registry/r/calendar.json +1 -1
  196. package/registry/r/card.json +1 -1
  197. package/registry/r/carousel.json +1 -1
  198. package/registry/r/chain-of-thought.json +23 -0
  199. package/registry/r/chart-pie.json +30 -0
  200. package/registry/r/chart.json +28 -0
  201. package/registry/r/checkbox.json +1 -1
  202. package/registry/r/checkpoint.json +23 -0
  203. package/registry/r/collapsible.json +1 -1
  204. package/registry/r/combobox.json +31 -0
  205. package/registry/r/command-dialog.json +21 -0
  206. package/registry/r/command.json +26 -0
  207. package/registry/r/confirmation.json +23 -0
  208. package/registry/r/context.json +26 -0
  209. package/registry/r/conversation.json +23 -0
  210. package/registry/r/country-selector.json +1 -1
  211. package/registry/r/data-table.json +1 -1
  212. package/registry/r/date-picker.json +4 -4
  213. package/registry/r/date-range-picker.json +3 -3
  214. package/registry/r/date-time-picker.json +28 -0
  215. package/registry/r/direction.json +16 -0
  216. package/registry/r/dropdown-item.json +1 -1
  217. package/registry/r/dropdown-label.json +1 -1
  218. package/registry/r/dropdown-menu.json +1 -1
  219. package/registry/r/dropdown-separator.json +1 -1
  220. package/registry/r/dropdown-trigger.json +1 -1
  221. package/registry/r/empty-state.json +1 -1
  222. package/registry/r/field.json +23 -0
  223. package/registry/r/hover-card.json +1 -1
  224. package/registry/r/inline-citation.json +26 -0
  225. package/registry/r/input-group.json +23 -0
  226. package/registry/r/input.json +1 -1
  227. package/registry/r/item.json +23 -0
  228. package/registry/r/kbd.json +23 -0
  229. package/registry/r/label.json +1 -1
  230. package/registry/r/marker.json +23 -0
  231. package/registry/r/masked-input.json +1 -1
  232. package/registry/r/menubar.json +24 -0
  233. package/registry/r/message-scroller.json +26 -0
  234. package/registry/r/message.json +23 -0
  235. package/registry/r/model-selector.json +32 -0
  236. package/registry/r/multi-select.json +2 -2
  237. package/registry/r/native-select.json +23 -0
  238. package/registry/r/navigation-menu.json +24 -0
  239. package/registry/r/otp-group.json +1 -1
  240. package/registry/r/otp-slot.json +1 -1
  241. package/registry/r/otp.json +1 -1
  242. package/registry/r/pagination.json +3 -2
  243. package/registry/r/plan.json +23 -0
  244. package/registry/r/popover-content.json +1 -1
  245. package/registry/r/popover.json +1 -1
  246. package/registry/r/progress.json +1 -1
  247. package/registry/r/prompt-input.json +23 -0
  248. package/registry/r/queue.json +23 -0
  249. package/registry/r/radio-group.json +1 -1
  250. package/registry/r/radio-item.json +1 -1
  251. package/registry/r/range-calendar.json +1 -1
  252. package/registry/r/reasoning.json +23 -0
  253. package/registry/r/segment.json +1 -1
  254. package/registry/r/select-group.json +1 -1
  255. package/registry/r/select-item.json +1 -1
  256. package/registry/r/select-separator.json +1 -1
  257. package/registry/r/select.json +4 -3
  258. package/registry/r/separator.json +1 -1
  259. package/registry/r/sheet.json +1 -1
  260. package/registry/r/shimmer.json +23 -0
  261. package/registry/r/sidebar.json +1 -1
  262. package/registry/r/skeleton.json +1 -1
  263. package/registry/r/sources.json +23 -0
  264. package/registry/r/spinner.json +23 -0
  265. package/registry/r/suggestion.json +23 -0
  266. package/registry/r/switch.json +1 -1
  267. package/registry/r/table.json +21 -0
  268. package/registry/r/tabs.json +1 -1
  269. package/registry/r/tag-input.json +1 -1
  270. package/registry/r/task.json +23 -0
  271. package/registry/r/textarea.json +1 -1
  272. package/registry/r/time-picker.json +24 -0
  273. package/registry/r/toaster.json +2 -2
  274. package/registry/r/toggle-group.json +1 -1
  275. package/registry/r/toggle.json +1 -1
  276. package/registry/r/tool.json +23 -0
  277. package/registry/r/typography.json +23 -0
  278. package/registry/registry.json +915 -22
  279. package/theme.css +109 -8
@@ -0,0 +1,642 @@
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Injectable, Input, Output, ViewChild, inject } from '@angular/core';
2
+ import { BehaviorSubject, Subscription } from 'rxjs';
3
+ import { computePosition, flip, shift, offset, size, autoUpdate } from '@floating-ui/dom';
4
+ import { cva } from 'class-variance-authority';
5
+ import { cn } from './utils/cn';
6
+ import * as i0 from "@angular/core";
7
+ let navigationMenuItemCounter = 0;
8
+ /**
9
+ * Coordinates the items of a single `tolle-navigation-menu`. Provided by
10
+ * `NavigationMenuComponent`, injected by its descendants.
11
+ *
12
+ * Closing is deferred by `closeDelay` so a pointer travelling diagonally from a
13
+ * trigger into its panel does not dismiss the menu mid-flight; re-entering
14
+ * either surface calls `cancelClose()` and the pending close is dropped.
15
+ */
16
+ export class NavigationMenuService {
17
+ openIdSource = new BehaviorSubject(null);
18
+ /** Emits the id of the currently open item, or `null` when all are closed. */
19
+ openId$ = this.openIdSource.asObservable();
20
+ /** Milliseconds to wait before closing after the pointer leaves. */
21
+ closeDelay = 150;
22
+ closeTimer;
23
+ /** Id of the open item, or `null`. */
24
+ get openId() {
25
+ return this.openIdSource.value;
26
+ }
27
+ /** True while any panel is open. */
28
+ get isAnyOpen() {
29
+ return this.openIdSource.value !== null;
30
+ }
31
+ /** True while a deferred close is pending — exposed for tests/diagnostics. */
32
+ get isCloseScheduled() {
33
+ return this.closeTimer !== undefined;
34
+ }
35
+ isOpen(id) {
36
+ return this.openId === id;
37
+ }
38
+ /** Opens an item immediately and cancels any pending close. */
39
+ open(id) {
40
+ this.cancelClose();
41
+ if (this.openId !== id)
42
+ this.openIdSource.next(id);
43
+ }
44
+ /** Closes immediately, dropping any pending close. */
45
+ closeNow() {
46
+ this.cancelClose();
47
+ if (this.openId !== null)
48
+ this.openIdSource.next(null);
49
+ }
50
+ /** Queues a close in `closeDelay` ms; a later `open`/`cancelClose` wins. */
51
+ scheduleClose() {
52
+ this.cancelClose();
53
+ this.closeTimer = setTimeout(() => {
54
+ this.closeTimer = undefined;
55
+ this.closeNow();
56
+ }, this.closeDelay);
57
+ }
58
+ /** Drops a pending close (pointer came back). */
59
+ cancelClose() {
60
+ if (this.closeTimer !== undefined) {
61
+ clearTimeout(this.closeTimer);
62
+ this.closeTimer = undefined;
63
+ }
64
+ }
65
+ toggle(id) {
66
+ if (this.openId === id)
67
+ this.closeNow();
68
+ else
69
+ this.open(id);
70
+ }
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuService });
73
+ }
74
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuService, decorators: [{
75
+ type: Injectable
76
+ }] });
77
+ const navigationMenuVariants = cva('relative z-10 flex max-w-max flex-1 items-center justify-center', {
78
+ variants: {
79
+ align: {
80
+ start: 'justify-start',
81
+ center: 'justify-center',
82
+ end: 'justify-end',
83
+ },
84
+ },
85
+ defaultVariants: {
86
+ align: 'center',
87
+ },
88
+ });
89
+ const navigationMenuTriggerVariants = cva('group inline-flex w-max select-none items-center justify-center gap-1 rounded-md bg-background font-medium transition-colors ' +
90
+ 'hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none ' +
91
+ 'data-[state=open]:bg-accent/50 data-[state=open]:text-accent-foreground ' +
92
+ 'disabled:pointer-events-none disabled:opacity-50', {
93
+ variants: {
94
+ size: {
95
+ sm: 'h-8 px-3 text-xs',
96
+ default: 'h-9 px-4 py-2 text-sm',
97
+ lg: 'h-10 px-5 text-sm',
98
+ },
99
+ },
100
+ defaultVariants: {
101
+ size: 'default',
102
+ },
103
+ });
104
+ const navigationMenuLinkVariants = cva('flex select-none flex-col gap-1 rounded-md p-3 leading-none no-underline outline-none transition-colors ' +
105
+ 'hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground', {
106
+ variants: {
107
+ variant: {
108
+ default: 'text-foreground',
109
+ muted: 'text-muted-foreground hover:text-accent-foreground',
110
+ },
111
+ active: {
112
+ true: 'bg-accent text-accent-foreground',
113
+ false: '',
114
+ },
115
+ },
116
+ defaultVariants: {
117
+ variant: 'default',
118
+ active: false,
119
+ },
120
+ });
121
+ /**
122
+ * Site navigation menu: a row of links and triggers, where each trigger reveals
123
+ * a floating panel on hover, focus or click.
124
+ *
125
+ * ```html
126
+ * <tolle-navigation-menu>
127
+ * <tolle-navigation-menu-list>
128
+ * <tolle-navigation-menu-item>
129
+ * <tolle-navigation-menu-trigger>Products</tolle-navigation-menu-trigger>
130
+ * <tolle-navigation-menu-content class="w-[420px]">
131
+ * <tolle-navigation-menu-link href="/analytics">Analytics</tolle-navigation-menu-link>
132
+ * </tolle-navigation-menu-content>
133
+ * </tolle-navigation-menu-item>
134
+ * </tolle-navigation-menu-list>
135
+ * </tolle-navigation-menu>
136
+ * ```
137
+ * @new
138
+ */
139
+ export class NavigationMenuComponent {
140
+ cdr = inject(ChangeDetectorRef);
141
+ /**
142
+ * Angular writes a bound `class` input through its styling path, which does
143
+ * not mark an OnPush component dirty — without this hook the component keeps
144
+ * rendering the class it was born with.
145
+ */
146
+ ngOnChanges() {
147
+ this.cdr.markForCheck();
148
+ }
149
+ /** Horizontal alignment of the list within the nav. @default 'center' */
150
+ align = 'center';
151
+ /** Accessible name for the `<nav>` landmark. @default 'Main' */
152
+ ariaLabel = 'Main';
153
+ /**
154
+ * Milliseconds before a panel closes after the pointer leaves — the grace
155
+ * period that lets the pointer travel diagonally into the panel. @default 150
156
+ */
157
+ set closeDelay(value) {
158
+ this.service.closeDelay = value;
159
+ }
160
+ get closeDelay() {
161
+ return this.service.closeDelay;
162
+ }
163
+ /** Extra Tailwind classes merged onto the `<nav>` via `cn()` (last-wins). */
164
+ class = '';
165
+ /** Emitted with the id of the item that opened, or `null` when the menu closes. */
166
+ openChange = new EventEmitter();
167
+ service = inject(NavigationMenuService);
168
+ host = inject(ElementRef);
169
+ sub = new Subscription();
170
+ listening = false;
171
+ get computedClass() {
172
+ return cn(navigationMenuVariants({ align: this.align }), this.class);
173
+ }
174
+ ngOnInit() {
175
+ this.sub.add(this.service.openId$.subscribe(id => {
176
+ this.openChange.emit(id);
177
+ if (id !== null)
178
+ this.startListening();
179
+ else
180
+ this.stopListening();
181
+ }));
182
+ }
183
+ onKeydown(event) {
184
+ if (event.key === 'Escape' && this.service.isAnyOpen) {
185
+ event.preventDefault();
186
+ this.service.closeNow();
187
+ }
188
+ }
189
+ // Capture phase so containers that stopPropagation() on their root cannot
190
+ // prevent the outside click from reaching us.
191
+ outsideClick = (event) => {
192
+ if (!this.host.nativeElement.contains(event.target))
193
+ this.service.closeNow();
194
+ };
195
+ startListening() {
196
+ if (this.listening)
197
+ return;
198
+ this.listening = true;
199
+ document.addEventListener('pointerdown', this.outsideClick, true);
200
+ }
201
+ stopListening() {
202
+ if (!this.listening)
203
+ return;
204
+ this.listening = false;
205
+ document.removeEventListener('pointerdown', this.outsideClick, true);
206
+ }
207
+ ngOnDestroy() {
208
+ this.sub.unsubscribe();
209
+ this.stopListening();
210
+ this.service.cancelClose();
211
+ }
212
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
213
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NavigationMenuComponent, isStandalone: true, selector: "tolle-navigation-menu", inputs: { align: "align", ariaLabel: "ariaLabel", closeDelay: "closeDelay", class: "class" }, outputs: { openChange: "openChange" }, providers: [NavigationMenuService], usesOnChanges: true, ngImport: i0, template: `
214
+ <nav [attr.aria-label]="ariaLabel" [class]="computedClass" (keydown)="onKeydown($event)">
215
+ <ng-content></ng-content>
216
+ </nav>
217
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
218
+ }
219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuComponent, decorators: [{
220
+ type: Component,
221
+ args: [{ selector: 'tolle-navigation-menu', standalone: true, imports: [], providers: [NavigationMenuService], changeDetection: ChangeDetectionStrategy.OnPush, template: `
222
+ <nav [attr.aria-label]="ariaLabel" [class]="computedClass" (keydown)="onKeydown($event)">
223
+ <ng-content></ng-content>
224
+ </nav>
225
+ `, styles: [":host{display:block}\n"] }]
226
+ }], propDecorators: { align: [{
227
+ type: Input
228
+ }], ariaLabel: [{
229
+ type: Input
230
+ }], closeDelay: [{
231
+ type: Input
232
+ }], class: [{
233
+ type: Input
234
+ }], openChange: [{
235
+ type: Output
236
+ }] } });
237
+ /** The horizontal list that holds the navigation items. */
238
+ export class NavigationMenuListComponent {
239
+ cdr = inject(ChangeDetectorRef);
240
+ /**
241
+ * Angular writes a bound `class` input through its styling path, which does
242
+ * not mark an OnPush component dirty — without this hook the component keeps
243
+ * rendering the class it was born with.
244
+ */
245
+ ngOnChanges() {
246
+ this.cdr.markForCheck();
247
+ }
248
+ /** Extra Tailwind classes merged onto the `<ul>` via `cn()` (last-wins). */
249
+ class = '';
250
+ cn = cn;
251
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
252
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NavigationMenuListComponent, isStandalone: true, selector: "tolle-navigation-menu-list", inputs: { class: "class" }, usesOnChanges: true, ngImport: i0, template: `
253
+ <ul [class]="cn('group flex flex-1 list-none items-center justify-center gap-1', class)">
254
+ <ng-content></ng-content>
255
+ </ul>
256
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
257
+ }
258
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuListComponent, decorators: [{
259
+ type: Component,
260
+ args: [{ selector: 'tolle-navigation-menu-list', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: `
261
+ <ul [class]="cn('group flex flex-1 list-none items-center justify-center gap-1', class)">
262
+ <ng-content></ng-content>
263
+ </ul>
264
+ `, styles: [":host{display:block}\n"] }]
265
+ }], propDecorators: { class: [{
266
+ type: Input
267
+ }] } });
268
+ /** One entry in the list — a plain link, or a trigger plus its content panel. */
269
+ export class NavigationMenuItemComponent {
270
+ cdr = inject(ChangeDetectorRef);
271
+ /**
272
+ * Angular writes a bound `class` input through its styling path, which does
273
+ * not mark an OnPush component dirty — without this hook the component keeps
274
+ * rendering the class it was born with.
275
+ */
276
+ ngOnChanges() {
277
+ this.cdr.markForCheck();
278
+ }
279
+ /** Explicit id for the item; one is generated when omitted. */
280
+ id = `tolle-navigation-menu-item-${navigationMenuItemCounter++}`;
281
+ /** Extra Tailwind classes merged onto the `<li>` via `cn()` (last-wins). */
282
+ class = '';
283
+ service = inject(NavigationMenuService);
284
+ cn = cn;
285
+ triggerElement = null;
286
+ get triggerId() {
287
+ return `${this.id}-trigger`;
288
+ }
289
+ get contentId() {
290
+ return `${this.id}-content`;
291
+ }
292
+ get isOpen() {
293
+ return this.service.isOpen(this.id);
294
+ }
295
+ ngOnDestroy() {
296
+ if (this.isOpen)
297
+ this.service.closeNow();
298
+ }
299
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
300
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NavigationMenuItemComponent, isStandalone: true, selector: "tolle-navigation-menu-item", inputs: { id: "id", class: "class" }, host: { properties: { "class": "'contents'" } }, usesOnChanges: true, ngImport: i0, template: `
301
+ <li [class]="cn('relative', class)">
302
+ <ng-content></ng-content>
303
+ </li>
304
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
305
+ }
306
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuItemComponent, decorators: [{
307
+ type: Component,
308
+ args: [{
309
+ selector: 'tolle-navigation-menu-item',
310
+ standalone: true,
311
+ imports: [],
312
+ changeDetection: ChangeDetectionStrategy.OnPush,
313
+ host: { '[class]': "'contents'" },
314
+ template: `
315
+ <li [class]="cn('relative', class)">
316
+ <ng-content></ng-content>
317
+ </li>
318
+ `,
319
+ }]
320
+ }], propDecorators: { id: [{
321
+ type: Input
322
+ }], class: [{
323
+ type: Input
324
+ }] } });
325
+ /** Button that reveals its item's panel on hover, focus or click. */
326
+ export class NavigationMenuTriggerComponent {
327
+ /**
328
+ * Angular writes a bound `class` input through its styling path, which does
329
+ * not mark an OnPush component dirty — without this hook the component keeps
330
+ * rendering the class it was born with.
331
+ */
332
+ ngOnChanges() {
333
+ this.cdr.markForCheck();
334
+ }
335
+ /** Prevents the panel from opening. @default false */
336
+ disabled = false;
337
+ /** Height/padding scale of the trigger. @default 'default' */
338
+ size = 'default';
339
+ /** Extra Tailwind classes merged onto the trigger via `cn()` (last-wins). */
340
+ class = '';
341
+ item = inject(NavigationMenuItemComponent);
342
+ service = inject(NavigationMenuService);
343
+ cdr = inject(ChangeDetectorRef);
344
+ sub;
345
+ constructor() {
346
+ this.sub = this.service.openId$.subscribe(() => this.cdr.markForCheck());
347
+ }
348
+ set triggerRef(ref) {
349
+ this.item.triggerElement = ref?.nativeElement ?? null;
350
+ }
351
+ get isOpen() {
352
+ return this.item.isOpen;
353
+ }
354
+ get computedClass() {
355
+ return cn(navigationMenuTriggerVariants({ size: this.size }), this.class);
356
+ }
357
+ onClick() {
358
+ if (this.disabled)
359
+ return;
360
+ this.service.toggle(this.item.id);
361
+ }
362
+ onPointerEnter() {
363
+ if (this.disabled)
364
+ return;
365
+ this.service.open(this.item.id);
366
+ }
367
+ onPointerLeave() {
368
+ this.service.scheduleClose();
369
+ }
370
+ onKeydown(event) {
371
+ if (this.disabled)
372
+ return;
373
+ if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
374
+ event.preventDefault();
375
+ this.service.open(this.item.id);
376
+ }
377
+ }
378
+ ngOnDestroy() {
379
+ this.sub.unsubscribe();
380
+ }
381
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
382
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NavigationMenuTriggerComponent, isStandalone: true, selector: "tolle-navigation-menu-trigger", inputs: { disabled: "disabled", size: "size", class: "class" }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
383
+ <button
384
+ #trigger
385
+ type="button"
386
+ [id]="item.triggerId"
387
+ [disabled]="disabled"
388
+ aria-haspopup="true"
389
+ [attr.aria-expanded]="isOpen"
390
+ [attr.aria-controls]="isOpen ? item.contentId : null"
391
+ [attr.data-state]="isOpen ? 'open' : 'closed'"
392
+ [class]="computedClass"
393
+ (click)="onClick()"
394
+ (mouseenter)="onPointerEnter()"
395
+ (mouseleave)="onPointerLeave()"
396
+ (focus)="onPointerEnter()"
397
+ (keydown)="onKeydown($event)"
398
+ >
399
+ <ng-content></ng-content>
400
+ <i
401
+ class="ri-arrow-down-s-line text-[16px] transition-transform duration-200"
402
+ [class.rotate-180]="isOpen"
403
+ aria-hidden="true"
404
+ ></i>
405
+ </button>
406
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
407
+ }
408
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuTriggerComponent, decorators: [{
409
+ type: Component,
410
+ args: [{ selector: 'tolle-navigation-menu-trigger', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: `
411
+ <button
412
+ #trigger
413
+ type="button"
414
+ [id]="item.triggerId"
415
+ [disabled]="disabled"
416
+ aria-haspopup="true"
417
+ [attr.aria-expanded]="isOpen"
418
+ [attr.aria-controls]="isOpen ? item.contentId : null"
419
+ [attr.data-state]="isOpen ? 'open' : 'closed'"
420
+ [class]="computedClass"
421
+ (click)="onClick()"
422
+ (mouseenter)="onPointerEnter()"
423
+ (mouseleave)="onPointerLeave()"
424
+ (focus)="onPointerEnter()"
425
+ (keydown)="onKeydown($event)"
426
+ >
427
+ <ng-content></ng-content>
428
+ <i
429
+ class="ri-arrow-down-s-line text-[16px] transition-transform duration-200"
430
+ [class.rotate-180]="isOpen"
431
+ aria-hidden="true"
432
+ ></i>
433
+ </button>
434
+ `, styles: [":host{display:block}\n"] }]
435
+ }], ctorParameters: () => [], propDecorators: { disabled: [{
436
+ type: Input
437
+ }], size: [{
438
+ type: Input
439
+ }], class: [{
440
+ type: Input
441
+ }], triggerRef: [{
442
+ type: ViewChild,
443
+ args: ['trigger']
444
+ }] } });
445
+ /** The floating panel revealed by a trigger. Rendered only while open. */
446
+ export class NavigationMenuContentComponent {
447
+ /**
448
+ * Angular writes a bound `class` input through its styling path, which does
449
+ * not mark an OnPush component dirty — without this hook the component keeps
450
+ * rendering the class it was born with.
451
+ */
452
+ ngOnChanges() {
453
+ this.cdr.markForCheck();
454
+ }
455
+ /** Preferred side of the trigger to render on; flips when space is tight. @default 'bottom' */
456
+ placement = 'bottom';
457
+ /** Gap in pixels between the trigger and the panel. @default 8 */
458
+ sideOffset = 8;
459
+ /** Extra Tailwind classes merged onto the panel via `cn()` (last-wins). */
460
+ class = '';
461
+ item = inject(NavigationMenuItemComponent);
462
+ service = inject(NavigationMenuService);
463
+ cdr = inject(ChangeDetectorRef);
464
+ sub;
465
+ cleanup;
466
+ constructor() {
467
+ this.sub = this.service.openId$.subscribe(() => this.cdr.markForCheck());
468
+ }
469
+ set panelRef(ref) {
470
+ this.stopPositioning();
471
+ if (ref?.nativeElement)
472
+ this.startPositioning(ref.nativeElement);
473
+ }
474
+ get isOpen() {
475
+ return this.item.isOpen;
476
+ }
477
+ get computedClass() {
478
+ return cn('z-[1000] overflow-auto rounded-md border border-border bg-popover p-2 text-popover-foreground', 'shadow-lg animate-in fade-in zoom-in-95', this.class);
479
+ }
480
+ onPointerEnter() {
481
+ this.service.cancelClose();
482
+ }
483
+ onPointerLeave() {
484
+ this.service.scheduleClose();
485
+ }
486
+ startPositioning(panel) {
487
+ const trigger = this.item.triggerElement;
488
+ if (!trigger)
489
+ return;
490
+ this.cleanup = autoUpdate(trigger, panel, () => {
491
+ computePosition(trigger, panel, {
492
+ strategy: 'fixed',
493
+ placement: this.placement,
494
+ middleware: [
495
+ offset(this.sideOffset),
496
+ flip(),
497
+ shift({ padding: 8 }),
498
+ // Wide panels are common here — clamp to what the viewport can show
499
+ // instead of letting them overflow.
500
+ size({
501
+ padding: 8,
502
+ apply({ elements, availableWidth, availableHeight }) {
503
+ Object.assign(elements.floating.style, {
504
+ maxWidth: `${Math.max(0, availableWidth)}px`,
505
+ maxHeight: `${Math.max(0, availableHeight)}px`,
506
+ });
507
+ },
508
+ }),
509
+ ],
510
+ }).then(({ x, y }) => {
511
+ Object.assign(panel.style, { left: `${x}px`, top: `${y}px` });
512
+ });
513
+ });
514
+ }
515
+ stopPositioning() {
516
+ this.cleanup?.();
517
+ this.cleanup = undefined;
518
+ }
519
+ ngOnDestroy() {
520
+ this.sub.unsubscribe();
521
+ this.stopPositioning();
522
+ }
523
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
524
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: NavigationMenuContentComponent, isStandalone: true, selector: "tolle-navigation-menu-content", inputs: { placement: "placement", sideOffset: "sideOffset", class: "class" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
525
+ @if (isOpen) {
526
+ <div
527
+ #panel
528
+ [id]="item.contentId"
529
+ [attr.aria-labelledby]="item.triggerId"
530
+ data-state="open"
531
+ [class]="computedClass"
532
+ style="position: fixed; top: 0; left: 0;"
533
+ (mouseenter)="onPointerEnter()"
534
+ (mouseleave)="onPointerLeave()"
535
+ >
536
+ <ng-content></ng-content>
537
+ </div>
538
+ }
539
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
540
+ }
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuContentComponent, decorators: [{
542
+ type: Component,
543
+ args: [{ selector: 'tolle-navigation-menu-content', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: `
544
+ @if (isOpen) {
545
+ <div
546
+ #panel
547
+ [id]="item.contentId"
548
+ [attr.aria-labelledby]="item.triggerId"
549
+ data-state="open"
550
+ [class]="computedClass"
551
+ style="position: fixed; top: 0; left: 0;"
552
+ (mouseenter)="onPointerEnter()"
553
+ (mouseleave)="onPointerLeave()"
554
+ >
555
+ <ng-content></ng-content>
556
+ </div>
557
+ }
558
+ `, styles: [":host{display:block}\n"] }]
559
+ }], ctorParameters: () => [], propDecorators: { placement: [{
560
+ type: Input
561
+ }], sideOffset: [{
562
+ type: Input
563
+ }], class: [{
564
+ type: Input
565
+ }], panelRef: [{
566
+ type: ViewChild,
567
+ args: ['panel']
568
+ }] } });
569
+ /** A link inside a panel (or directly in the list, for flat entries). */
570
+ export class NavigationMenuLinkComponent {
571
+ cdr = inject(ChangeDetectorRef);
572
+ /**
573
+ * Angular writes a bound `class` input through its styling path, which does
574
+ * not mark an OnPush component dirty — without this hook the component keeps
575
+ * rendering the class it was born with.
576
+ */
577
+ ngOnChanges() {
578
+ this.cdr.markForCheck();
579
+ }
580
+ /** Destination URL. Omit to render a non-navigating item. */
581
+ href = '';
582
+ /** Anchor target; `_blank` also sets a safe `rel`. */
583
+ target = '';
584
+ /** Marks the link as the current page. @default false */
585
+ active = false;
586
+ /** Visual style of the link. @default 'default' */
587
+ variant = 'default';
588
+ /** Extra Tailwind classes merged onto the anchor via `cn()` (last-wins). */
589
+ class = '';
590
+ /** Emitted with the click event when the link is activated. */
591
+ navigate = new EventEmitter();
592
+ get computedClass() {
593
+ return cn(navigationMenuLinkVariants({ variant: this.variant, active: this.active }), this.class);
594
+ }
595
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
596
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NavigationMenuLinkComponent, isStandalone: true, selector: "tolle-navigation-menu-link", inputs: { href: "href", target: "target", active: "active", variant: "variant", class: "class" }, outputs: { navigate: "navigate" }, usesOnChanges: true, ngImport: i0, template: `
597
+ <a
598
+ [attr.href]="href || null"
599
+ [attr.target]="target || null"
600
+ [attr.rel]="target === '_blank' ? 'noreferrer noopener' : null"
601
+ [attr.aria-current]="active ? 'page' : null"
602
+ [attr.data-active]="active ? '' : null"
603
+ [class]="computedClass"
604
+ (click)="navigate.emit($event)"
605
+ >
606
+ <ng-content select="[label]"></ng-content>
607
+ <ng-content></ng-content>
608
+ <ng-content select="[description]"></ng-content>
609
+ </a>
610
+ `, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
611
+ }
612
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationMenuLinkComponent, decorators: [{
613
+ type: Component,
614
+ args: [{ selector: 'tolle-navigation-menu-link', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: `
615
+ <a
616
+ [attr.href]="href || null"
617
+ [attr.target]="target || null"
618
+ [attr.rel]="target === '_blank' ? 'noreferrer noopener' : null"
619
+ [attr.aria-current]="active ? 'page' : null"
620
+ [attr.data-active]="active ? '' : null"
621
+ [class]="computedClass"
622
+ (click)="navigate.emit($event)"
623
+ >
624
+ <ng-content select="[label]"></ng-content>
625
+ <ng-content></ng-content>
626
+ <ng-content select="[description]"></ng-content>
627
+ </a>
628
+ `, styles: [":host{display:block}\n"] }]
629
+ }], propDecorators: { href: [{
630
+ type: Input
631
+ }], target: [{
632
+ type: Input
633
+ }], active: [{
634
+ type: Input
635
+ }], variant: [{
636
+ type: Input
637
+ }], class: [{
638
+ type: Input
639
+ }], navigate: [{
640
+ type: Output
641
+ }] } });
642
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbi1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvbmF2aWdhdGlvbi1tZW51LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDNUwsT0FBTyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDMUYsT0FBTyxFQUFFLEdBQUcsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sWUFBWSxDQUFDOztBQUVoQyxJQUFJLHlCQUF5QixHQUFHLENBQUMsQ0FBQztBQUVsQzs7Ozs7OztHQU9HO0FBRUgsTUFBTSxPQUFPLHFCQUFxQjtJQUN4QixZQUFZLEdBQUcsSUFBSSxlQUFlLENBQWdCLElBQUksQ0FBQyxDQUFDO0lBQ2hFLDhFQUE4RTtJQUNyRSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUVwRCxvRUFBb0U7SUFDcEUsVUFBVSxHQUFHLEdBQUcsQ0FBQztJQUVULFVBQVUsQ0FBNEM7SUFFOUQsc0NBQXNDO0lBQ3RDLElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUM7SUFDakMsQ0FBQztJQUVELG9DQUFvQztJQUNwQyxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxZ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SUFBYyxhQUFhO1FBQ3pCLE9BQU8sRUFBRSxDQUNQLDBCQUEwQixDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUMxRSxJQUFJLENBQUMsS0FBSyxDQUNYLENBQUM7SUFDSixDQUFDO3dHQS9CVSwyQkFBMkI7NEZBQTNCLDJCQUEyQixnUEFoQjVCOzs7Ozs7Ozs7Ozs7OztHQWNUOzs0RkFFVSwyQkFBMkI7a0JBdEJ2QyxTQUFTOytCQUNFLDRCQUE0QixjQUUxQixJQUFJLFdBQ1AsRUFBRSxtQkFDTSx1QkFBdUIsQ0FBQyxNQUFNLFlBQ3JDOzs7Ozs7Ozs7Ozs7OztHQWNUOzhCQWVRLElBQUk7c0JBQVosS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0ksUUFBUTtzQkFBakIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEluamVjdGFibGUsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBWaWV3Q2hpbGQsIGluamVjdCwgT25DaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY29tcHV0ZVBvc2l0aW9uLCBmbGlwLCBzaGlmdCwgb2Zmc2V0LCBzaXplLCBhdXRvVXBkYXRlIH0gZnJvbSAnQGZsb2F0aW5nLXVpL2RvbSc7XG5pbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAnY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5JztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5cbmxldCBuYXZpZ2F0aW9uTWVudUl0ZW1Db3VudGVyID0gMDtcblxuLyoqXG4gKiBDb29yZGluYXRlcyB0aGUgaXRlbXMgb2YgYSBzaW5nbGUgYHRvbGxlLW5hdmlnYXRpb24tbWVudWAuIFByb3ZpZGVkIGJ5XG4gKiBgTmF2aWdhdGlvbk1lbnVDb21wb25lbnRgLCBpbmplY3RlZCBieSBpdHMgZGVzY2VuZGFudHMuXG4gKlxuICogQ2xvc2luZyBpcyBkZWZlcnJlZCBieSBgY2xvc2VEZWxheWAgc28gYSBwb2ludGVyIHRyYXZlbGxpbmcgZGlhZ29uYWxseSBmcm9tIGFcbiAqIHRyaWdnZXIgaW50byBpdHMgcGFuZWwgZG9lcyBub3QgZGlzbWlzcyB0aGUgbWVudSBtaWQtZmxpZ2h0OyByZS1lbnRlcmluZ1xuICogZWl0aGVyIHN1cmZhY2UgY2FsbHMgYGNhbmNlbENsb3NlKClgIGFuZCB0aGUgcGVuZGluZyBjbG9zZSBpcyBkcm9wcGVkLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvbk1lbnVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBvcGVuSWRTb3VyY2UgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IG51bGw+KG51bGwpO1xuICAvKiogRW1pdHMgdGhlIGlkIG9mIHRoZSBjdXJyZW50bHkgb3BlbiBpdGVtLCBvciBgbnVsbGAgd2hlbiBhbGwgYXJlIGNsb3NlZC4gKi9cbiAgcmVhZG9ubHkgb3BlbklkJCA9IHRoaXMub3BlbklkU291cmNlLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8qKiBNaWxsaXNlY29uZHMgdG8gd2FpdCBiZWZvcmUgY2xvc2luZyBhZnRlciB0aGUgcG9pbnRlciBsZWF2ZXMuICovXG4gIGNsb3NlRGVsYXkgPSAxNTA7XG5cbiAgcHJpdmF0ZSBjbG9zZVRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IHVuZGVmaW5lZDtcblxuICAvKiogSWQgb2YgdGhlIG9wZW4gaXRlbSwgb3IgYG51bGxgLiAqL1xuICBnZXQgb3BlbklkKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLm9wZW5JZFNvdXJjZS52YWx1ZTtcbiAgfVxuXG4gIC8qKiBUcnVlIHdoaWxlIGFueSBwYW5lbCBpcyBvcGVuLiAqL1xuICBnZXQgaXNBbnlPcGVuKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm9wZW5JZFNvdXJjZS52YWx1ZSAhPT0gbnVsbDtcbiAgfVxuXG4gIC8qKiBUcnVlIHdoaWxlIGEgZGVmZXJyZWQgY2xvc2UgaXMgcGVuZGluZyDigJQgZXhwb3NlZCBmb3IgdGVzdHMvZGlhZ25vc3RpY3MuICovXG4gIGdldCBpc0Nsb3NlU2NoZWR1bGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsb3NlVGltZXIgIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlzT3BlbihpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub3BlbklkID09PSBpZDtcbiAgfVxuXG4gIC8qKiBPcGVucyBhbiBpdGVtIGltbWVkaWF0ZWx5IGFuZCBjYW5jZWxzIGFueSBwZW5kaW5nIGNsb3NlLiAqL1xuICBvcGVuKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNhbmNlbENsb3NlKCk7XG4gICAgaWYgKHRoaXMub3BlbklkICE9PSBpZCkgdGhpcy5vcGVuSWRTb3VyY2UubmV4dChpZCk7XG4gIH1cblxuICAvKiogQ2xvc2VzIGltbWVkaWF0ZWx5LCBkcm9wcGluZyBhbnkgcGVuZGluZyBjbG9zZS4gKi9cbiAgY2xvc2VOb3coKTogdm9pZCB7XG4gICAgdGhpcy5jYW5jZWxDbG9zZSgpO1xuICAgIGlmICh0aGlzLm9wZW5JZCAhPT0gbnVsbCkgdGhpcy5vcGVuSWRTb3VyY2UubmV4dChudWxsKTtcbiAgfVxuXG4gIC8qKiBRdWV1ZXMgYSBjbG9zZSBpbiBgY2xvc2VEZWxheWAgbXM7IGEgbGF0ZXIgYG9wZW5gL2BjYW5jZWxDbG9zZWAgd2lucy4gKi9cbiAgc2NoZWR1bGVDbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhbmNlbENsb3NlKCk7XG4gICAgdGhpcy5jbG9zZVRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmNsb3NlVGltZXIgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLmNsb3NlTm93KCk7XG4gICAgfSwgdGhpcy5jbG9zZURlbGF5KTtcbiAgfVxuXG4gIC8qKiBEcm9wcyBhIHBlbmRpbmcgY2xvc2UgKHBvaW50ZXIgY2FtZSBiYWNrKS4gKi9cbiAgY2FuY2VsQ2xvc2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY2xvc2VUaW1lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5jbG9zZVRpbWVyKTtcbiAgICAgIHRoaXMuY2xvc2VUaW1lciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICB0b2dnbGUoaWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLm9wZW5JZCA9PT0gaWQpIHRoaXMuY2xvc2VOb3coKTtcbiAgICBlbHNlIHRoaXMub3BlbihpZCk7XG4gIH1cbn1cblxuY29uc3QgbmF2aWdhdGlvbk1lbnVWYXJpYW50cyA9IGN2YSgncmVsYXRpdmUgei0xMCBmbGV4IG1heC13LW1heCBmbGV4LTEgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyJywge1xuICB2YXJpYW50czoge1xuICAgIGFsaWduOiB7XG4gICAgICBzdGFydDogJ2p1c3RpZnktc3RhcnQnLFxuICAgICAgY2VudGVyOiAnanVzdGlmeS1jZW50ZXInLFxuICAgICAgZW5kOiAnanVzdGlmeS1lbmQnLFxuICAgIH0sXG4gIH0sXG4gIGRlZmF1bHRWYXJpYW50czoge1xuICAgIGFsaWduOiAnY2VudGVyJyxcbiAgfSxcbn0pO1xuXG5leHBvcnQgdHlwZSBOYXZpZ2F0aW9uTWVudVByb3BzID0gVmFyaWFudFByb3BzPHR5cGVvZiBuYXZpZ2F0aW9uTWVudVZhcmlhbnRzPjtcblxuY29uc3QgbmF2aWdhdGlvbk1lbnVUcmlnZ2VyVmFyaWFudHMgPSBjdmEoXG4gICdncm91cCBpbmxpbmUtZmxleCB3LW1heCBzZWxlY3Qtbm9uZSBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTEgcm91bmRlZC1tZCBiZy1iYWNrZ3JvdW5kIGZvbnQtbWVkaXVtIHRyYW5zaXRpb24tY29sb3JzICcgK1xuICAgICdob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBmb2N1czpiZy1hY2NlbnQgZm9jdXM6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBmb2N1czpvdXRsaW5lLW5vbmUgJyArXG4gICAgJ2RhdGEtW3N0YXRlPW9wZW5dOmJnLWFjY2VudC81MCBkYXRhLVtzdGF0ZT1vcGVuXTp0ZXh0LWFjY2VudC1mb3JlZ3JvdW5kICcgK1xuICAgICdkaXNhYmxlZDpwb2ludGVyLWV2ZW50cy1ub25lIGRpc2FibGVkOm9wYWNpdHktNTAnLFxuICB7XG4gICAgdmFyaWFudHM6IHtcbiAgICAgIHNpemU6IHtcbiAgICAgICAgc206ICdoLTggcHgtMyB0ZXh0LXhzJyxcbiAgICAgICAgZGVmYXVsdDogJ2gtOSBweC00IHB5LTIgdGV4dC1zbScsXG4gICAgICAgIGxnOiAnaC0xMCBweC01IHRleHQtc20nLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGRlZmF1bHRWYXJpYW50czoge1xuICAgICAgc2l6ZTogJ2RlZmF1bHQnLFxuICAgIH0sXG4gIH1cbik7XG5cbmV4cG9ydCB0eXBlIE5hdmlnYXRpb25NZW51VHJpZ2dlclByb3BzID0gVmFyaWFudFByb3BzPHR5cGVvZiBuYXZpZ2F0aW9uTWVudVRyaWdnZXJWYXJpYW50cz47XG5cbmNvbnN0IG5hdmlnYXRpb25NZW51TGlua1ZhcmlhbnRzID0gY3ZhKFxuICAnZmxleCBzZWxlY3Qtbm9uZSBmbGV4LWNvbCBnYXAtMSByb3VuZGVkLW1kIHAtMyBsZWFkaW5nLW5vbmUgbm8tdW5kZXJsaW5lIG91dGxpbmUtbm9uZSB0cmFuc2l0aW9uLWNvbG9ycyAnICtcbiAgICAnaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQgZm9jdXM6YmctYWNjZW50IGZvY3VzOnRleHQtYWNjZW50LWZvcmVncm91bmQnLFxuICB7XG4gICAgdmFyaWFudHM6IHtcbiAgICAgIHZhcmlhbnQ6IHtcbiAgICAgICAgZGVmYXVsdDogJ3RleHQtZm9yZWdyb3VuZCcsXG4gICAgICAgIG11dGVkOiAndGV4dC1tdXRlZC1mb3JlZ3JvdW5kIGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQnLFxuICAgICAgfSxcbiAgICAgIGFjdGl2ZToge1xuICAgICAgICB0cnVlOiAnYmctYWNjZW50IHRleHQtYWNjZW50LWZvcmVncm91bmQnLFxuICAgICAgICBmYWxzZTogJycsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGVmYXVsdFZhcmlhbnRzOiB7XG4gICAgICB2YXJpYW50OiAnZGVmYXVsdCcsXG4gICAgICBhY3RpdmU6IGZhbHNlLFxuICAgIH0sXG4gIH1cbik7XG5cbmV4cG9ydCB0eXBlIE5hdmlnYXRpb25NZW51TGlua1Byb3BzID0gVmFyaWFudFByb3BzPHR5cGVvZiBuYXZpZ2F0aW9uTWVudUxpbmtWYXJpYW50cz47XG5cbi8qKlxuICogU2l0ZSBuYXZpZ2F0aW9uIG1lbnU6IGEgcm93IG9mIGxpbmtzIGFuZCB0cmlnZ2Vycywgd2hlcmUgZWFjaCB0cmlnZ2VyIHJldmVhbHNcbiAqIGEgZmxvYXRpbmcgcGFuZWwgb24gaG92ZXIsIGZvY3VzIG9yIGNsaWNrLlxuICpcbiAqIGBgYGh0bWxcbiAqIDx0b2xsZS1uYXZpZ2F0aW9uLW1lbnU+XG4gKiAgIDx0b2xsZS1uYXZpZ2F0aW9uLW1lbnUtbGlzdD5cbiAqICAgICA8dG9sbGUtbmF2aWdhdGlvbi1tZW51LWl0ZW0+XG4gKiAgICAgICA8dG9sbGUtbmF2aWdhdGlvbi1tZW51LXRyaWdnZXI+UHJvZHVjdHM8L3RvbGxlLW5hdmlnYXRpb24tbWVudS10cmlnZ2VyPlxuICogICAgICAgPHRvbGxlLW5hdmlnYXRpb24tbWVudS1jb250ZW50IGNsYXNzPVwidy1bNDIwcHhdXCI+XG4gKiAgICAgICAgIDx0b2xsZS1uYXZpZ2F0aW9uLW1lbnUtbGluayBocmVmPVwiL2FuYWx5dGljc1wiPkFuYWx5dGljczwvdG9sbGUtbmF2aWdhdGlvbi1tZW51LWxpbms+XG4gKiAgICAgICA8L3RvbGxlLW5hdmlnYXRpb24tbWVudS1jb250ZW50PlxuICogICAgIDwvdG9sbGUtbmF2aWdhdGlvbi1tZW51LWl0ZW0+XG4gKiAgIDwvdG9sbGUtbmF2aWdhdGlvbi1tZW51LWxpc3Q+XG4gKiA8L3RvbGxlLW5hdmlnYXRpb24tbWVudT5cbiAqIGBgYFxuICogQG5ld1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1uYXZpZ2F0aW9uLW1lbnUnLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXSxcbiAgcHJvdmlkZXJzOiBbTmF2aWdhdGlvbk1lbnVTZXJ2aWNlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG5hdiBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCIgKGtleWRvd24pPVwib25LZXlkb3duKCRldmVudClcIj5cbiAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICA8L25hdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvbk1lbnVDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogSG9yaXpvbnRhbCBhbGlnbm1lbnQgb2YgdGhlIGxpc3Qgd2l0aGluIHRoZSBuYXYuIEBkZWZhdWx0ICdjZW50ZXInICovXG4gIEBJbnB1dCgpIGFsaWduOiBOYXZpZ2F0aW9uTWVudVByb3BzWydhbGlnbiddID0gJ2NlbnRlcic7XG4gIC8qKiBBY2Nlc3NpYmxlIG5hbWUgZm9yIHRoZSBgPG5hdj5gIGxhbmRtYXJrLiBAZGVmYXVsdCAnTWFpbicgKi9cbiAgQElucHV0KCkgYXJpYUxhYmVsID0gJ01haW4nO1xuICAvKipcbiAgICogTWlsbGlzZWNvbmRzIGJlZm9yZSBhIHBhbmVsIGNsb3NlcyBhZnRlciB0aGUgcG9pbnRlciBsZWF2ZXMg4oCUIHRoZSBncmFjZVxuICAgKiBwZXJpb2QgdGhhdCBsZXRzIHRoZSBwb2ludGVyIHRyYXZlbCBkaWFnb25hbGx5IGludG8gdGhlIHBhbmVsLiBAZGVmYXVsdCAxNTBcbiAgICovXG4gIEBJbnB1dCgpIHNldCBjbG9zZURlbGF5KHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLnNlcnZpY2UuY2xvc2VEZWxheSA9IHZhbHVlO1xuICB9XG4gIGdldCBjbG9zZURlbGF5KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmljZS5jbG9zZURlbGF5O1xuICB9XG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSBgPG5hdj5gIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgLyoqIEVtaXR0ZWQgd2l0aCB0aGUgaWQgb2YgdGhlIGl0ZW0gdGhhdCBvcGVuZWQsIG9yIGBudWxsYCB3aGVuIHRoZSBtZW51IGNsb3Nlcy4gKi9cbiAgQE91dHB1dCgpIG9wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bGw+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlID0gaW5qZWN0KE5hdmlnYXRpb25NZW51U2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaG9zdCA9IGluamVjdDxFbGVtZW50UmVmPEhUTUxFbGVtZW50Pj4oRWxlbWVudFJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3ViID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBwcml2YXRlIGxpc3RlbmluZyA9IGZhbHNlO1xuXG4gIHByb3RlY3RlZCBnZXQgY29tcHV0ZWRDbGFzcygpOiBzdHJpbmcge1xuICAgIHJldHVybiBjbihuYXZpZ2F0aW9uTWVudVZhcmlhbnRzKHsgYWxpZ246IHRoaXMuYWxpZ24gfSksIHRoaXMuY2xhc3MpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWIuYWRkKFxuICAgICAgdGhpcy5zZXJ2aWNlLm9wZW5JZCQuc3Vic2NyaWJlKGlkID0+IHtcbiAgICAgICAgdGhpcy5vcGVuQ2hhbmdlLmVtaXQoaWQpO1xuICAgICAgICBpZiAoaWQgIT09IG51bGwpIHRoaXMuc3RhcnRMaXN0ZW5pbmcoKTtcbiAgICAgICAgZWxzZSB0aGlzLnN0b3BMaXN0ZW5pbmcoKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbktleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnRXNjYXBlJyAmJiB0aGlzLnNlcnZpY2UuaXNBbnlPcGVuKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5zZXJ2aWNlLmNsb3NlTm93KCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ2FwdHVyZSBwaGFzZSBzbyBjb250YWluZXJzIHRoYXQgc3RvcFByb3BhZ2F0aW9uKCkgb24gdGhlaXIgcm9vdCBjYW5ub3RcbiAgLy8gcHJldmVudCB0aGUgb3V0c2lkZSBjbGljayBmcm9tIHJlYWNoaW5nIHVzLlxuICBwcml2YXRlIG91dHNpZGVDbGljayA9IChldmVudDogRXZlbnQpID0+IHtcbiAgICBpZiAoIXRoaXMuaG9zdC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnRhcmdldCBhcyBOb2RlKSkgdGhpcy5zZXJ2aWNlLmNsb3NlTm93KCk7XG4gIH07XG5cbiAgcHJpdmF0ZSBzdGFydExpc3RlbmluZygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5saXN0ZW5pbmcpIHJldHVybjtcbiAgICB0aGlzLmxpc3RlbmluZyA9IHRydWU7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLm91dHNpZGVDbGljaywgdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIHN0b3BMaXN0ZW5pbmcoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmxpc3RlbmluZykgcmV0dXJuO1xuICAgIHRoaXMubGlzdGVuaW5nID0gZmFsc2U7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLm91dHNpZGVDbGljaywgdHJ1ZSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuc3RvcExpc3RlbmluZygpO1xuICAgIHRoaXMuc2VydmljZS5jYW5jZWxDbG9zZSgpO1xuICB9XG59XG5cbi8qKiBUaGUgaG9yaXpvbnRhbCBsaXN0IHRoYXQgaG9sZHMgdGhlIG5hdmlnYXRpb24gaXRlbXMuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1uYXZpZ2F0aW9uLW1lbnUtbGlzdCcsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8dWwgW2NsYXNzXT1cImNuKCdncm91cCBmbGV4IGZsZXgtMSBsaXN0LW5vbmUgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIGdhcC0xJywgY2xhc3MpXCI+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC91bD5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvbk1lbnVMaXN0Q29tcG9uZW50ICBpbXBsZW1lbnRzIE9uQ2hhbmdlc3tcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgYDx1bD5gIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG4gIHByb3RlY3RlZCByZWFkb25seSBjbiA9IGNuO1xufVxuXG4vKiogT25lIGVudHJ5IGluIHRoZSBsaXN0IOKAlCBhIHBsYWluIGxpbmssIG9yIGEgdHJpZ2dlciBwbHVzIGl0cyBjb250ZW50IHBhbmVsLiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtbmF2aWdhdGlvbi1tZW51LWl0ZW0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHsgJ1tjbGFzc10nOiBcIidjb250ZW50cydcIiB9LFxuICB0ZW1wbGF0ZTogYFxuICAgIDxsaSBbY2xhc3NdPVwiY24oJ3JlbGF0aXZlJywgY2xhc3MpXCI+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9saT5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvbk1lbnVJdGVtQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBFeHBsaWNpdCBpZCBmb3IgdGhlIGl0ZW07IG9uZSBpcyBnZW5lcmF0ZWQgd2hlbiBvbWl0dGVkLiAqL1xuICBASW5wdXQoKSBpZCA9IGB0b2xsZS1uYXZpZ2F0aW9uLW1lbnUtaXRlbS0ke25hdmlnYXRpb25NZW51SXRlbUNvdW50ZXIrK31gO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgYDxsaT5gIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgcmVhZG9ubHkgc2VydmljZSA9IGluamVjdChOYXZpZ2F0aW9uTWVudVNlcnZpY2UpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY24gPSBjbjtcblxuICB0cmlnZ2VyRWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblxuICBnZXQgdHJpZ2dlcklkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuaWR9LXRyaWdnZXJgO1xuICB9XG5cbiAgZ2V0IGNvbnRlbnRJZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHt0aGlzLmlkfS1jb250ZW50YDtcbiAgfVxuXG4gIGdldCBpc09wZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmljZS5pc09wZW4odGhpcy5pZCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc09wZW4pIHRoaXMuc2VydmljZS5jbG9zZU5vdygpO1xuICB9XG59XG5cbi8qKiBCdXR0b24gdGhhdCByZXZlYWxzIGl0cyBpdGVtJ3MgcGFuZWwgb24gaG92ZXIsIGZvY3VzIG9yIGNsaWNrLiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtbmF2aWdhdGlvbi1tZW51LXRyaWdnZXInLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGJ1dHRvblxuICAgICAgI3RyaWdnZXJcbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2lkXT1cIml0ZW0udHJpZ2dlcklkXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBhcmlhLWhhc3BvcHVwPVwidHJ1ZVwiXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImlzT3BlblwiXG4gICAgICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImlzT3BlbiA/IGl0ZW0uY29udGVudElkIDogbnVsbFwiXG4gICAgICBbYXR0ci5kYXRhLXN0YXRlXT1cImlzT3BlbiA/ICdvcGVuJyA6ICdjbG9zZWQnXCJcbiAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCJcbiAgICAgIChjbGljayk9XCJvbkNsaWNrKClcIlxuICAgICAgKG1vdXNlZW50ZXIpPVwib25Qb2ludGVyRW50ZXIoKVwiXG4gICAgICAobW91c2VsZWF2ZSk9XCJvblBvaW50ZXJMZWF2ZSgpXCJcbiAgICAgIChmb2N1cyk9XCJvblBvaW50ZXJFbnRlcigpXCJcbiAgICAgIChrZXlkb3duKT1cIm9uS2V5ZG93bigkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICA8aVxuICAgICAgICBjbGFzcz1cInJpLWFycm93LWRvd24tcy1saW5lIHRleHQtWzE2cHhdIHRyYW5zaXRpb24tdHJhbnNmb3JtIGR1cmF0aW9uLTIwMFwiXG4gICAgICAgIFtjbGFzcy5yb3RhdGUtMTgwXT1cImlzT3BlblwiXG4gICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICA+PC9pPlxuICAgIDwvYnV0dG9uPlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBOYXZpZ2F0aW9uTWVudVRyaWdnZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBQcmV2ZW50cyB0aGUgcGFuZWwgZnJvbSBvcGVuaW5nLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuICAvKiogSGVpZ2h0L3BhZGRpbmcgc2NhbGUgb2YgdGhlIHRyaWdnZXIuIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSBzaXplOiBOYXZpZ2F0aW9uTWVudVRyaWdnZXJQcm9wc1snc2l6ZSddID0gJ2RlZmF1bHQnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgdHJpZ2dlciB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBpdGVtID0gaW5qZWN0KE5hdmlnYXRpb25NZW51SXRlbUNvbXBvbmVudCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2VydmljZSA9IGluamVjdChOYXZpZ2F0aW9uTWVudVNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3ViOiBTdWJzY3JpcHRpb247XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5zdWIgPSB0aGlzLnNlcnZpY2Uub3BlbklkJC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jZHIubWFya0ZvckNoZWNrKCkpO1xuICB9XG5cbiAgQFZpZXdDaGlsZCgndHJpZ2dlcicpIHNldCB0cmlnZ2VyUmVmKHJlZjogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD4gfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLml0ZW0udHJpZ2dlckVsZW1lbnQgPSByZWY/Lm5hdGl2ZUVsZW1lbnQgPz8gbnVsbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgaXNPcGVuKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLml0ZW0uaXNPcGVuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBjb21wdXRlZENsYXNzKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNuKG5hdmlnYXRpb25NZW51VHJpZ2dlclZhcmlhbnRzKHsgc2l6ZTogdGhpcy5zaXplIH0pLCB0aGlzLmNsYXNzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkNsaWNrKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSByZXR1cm47XG4gICAgdGhpcy5zZXJ2aWNlLnRvZ2dsZSh0aGlzLml0ZW0uaWQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uUG9pbnRlckVudGVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSByZXR1cm47XG4gICAgdGhpcy5zZXJ2aWNlLm9wZW4odGhpcy5pdGVtLmlkKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblBvaW50ZXJMZWF2ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNlcnZpY2Uuc2NoZWR1bGVDbG9zZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSByZXR1cm47XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0Fycm93RG93bicgfHwgZXZlbnQua2V5ID09PSAnRW50ZXInIHx8IGV2ZW50LmtleSA9PT0gJyAnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5zZXJ2aWNlLm9wZW4odGhpcy5pdGVtLmlkKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi51bnN1YnNjcmliZSgpO1xuICB9XG59XG5cbi8qKiBUaGUgZmxvYXRpbmcgcGFuZWwgcmV2ZWFsZWQgYnkgYSB0cmlnZ2VyLiBSZW5kZXJlZCBvbmx5IHdoaWxlIG9wZW4uICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1uYXZpZ2F0aW9uLW1lbnUtY29udGVudCcsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKGlzT3Blbikge1xuICAgICAgPGRpdlxuICAgICAgICAjcGFuZWxcbiAgICAgICAgW2lkXT1cIml0ZW0uY29udGVudElkXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cIml0ZW0udHJpZ2dlcklkXCJcbiAgICAgICAgZGF0YS1zdGF0ZT1cIm9wZW5cIlxuICAgICAgICBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiXG4gICAgICAgIHN0eWxlPVwicG9zaXRpb246IGZpeGVkOyB0b3A6IDA7IGxlZnQ6IDA7XCJcbiAgICAgICAgKG1vdXNlZW50ZXIpPVwib25Qb2ludGVyRW50ZXIoKVwiXG4gICAgICAgIChtb3VzZWxlYXZlKT1cIm9uUG9pbnRlckxlYXZlKClcIlxuICAgICAgPlxuICAgICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIE5hdmlnYXRpb25NZW51Q29udGVudENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblxuICAvKipcbiAgICogQW5ndWxhciB3cml0ZXMgYSBib3VuZCBgY2xhc3NgIGlucHV0IHRocm91Z2ggaXRzIHN0eWxpbmcgcGF0aCwgd2hpY2ggZG9lc1xuICAgKiBub3QgbWFyayBhbiBPblB1c2ggY29tcG9uZW50IGRpcnR5IOKAlCB3aXRob3V0IHRoaXMgaG9vayB0aGUgY29tcG9uZW50IGtlZXBzXG4gICAqIHJlbmRlcmluZyB0aGUgY2xhc3MgaXQgd2FzIGJvcm4gd2l0aC5cbiAgICovXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqIFByZWZlcnJlZCBzaWRlIG9mIHRoZSB0cmlnZ2VyIHRvIHJlbmRlciBvbjsgZmxpcHMgd2hlbiBzcGFjZSBpcyB0aWdodC4gQGRlZmF1bHQgJ2JvdHRvbScgKi9cbiAgQElucHV0KCkgcGxhY2VtZW50OiAnYm90dG9tJyB8ICdib3R0b20tc3RhcnQnIHwgJ2JvdHRvbS1lbmQnIHwgJ3RvcCcgfCAndG9wLXN0YXJ0JyB8ICd0b3AtZW5kJyA9XG4gICAgJ2JvdHRvbSc7XG4gIC8qKiBHYXAgaW4gcGl4ZWxzIGJldHdlZW4gdGhlIHRyaWdnZXIgYW5kIHRoZSBwYW5lbC4gQGRlZmF1bHQgOCAqL1xuICBASW5wdXQoKSBzaWRlT2Zmc2V0ID0gODtcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIHBhbmVsIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGl0ZW0gPSBpbmplY3QoTmF2aWdhdGlvbk1lbnVJdGVtQ29tcG9uZW50KTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlID0gaW5qZWN0KE5hdmlnYXRpb25NZW51U2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzdWI6IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBjbGVhbnVwPzogKCkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnN1YiA9IHRoaXMuc2VydmljZS5vcGVuSWQkLnN1YnNjcmliZSgoKSA9PiB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKSk7XG4gIH1cblxuICBAVmlld0NoaWxkKCdwYW5lbCcpIHNldCBwYW5lbFJlZihyZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5zdG9wUG9zaXRpb25pbmcoKTtcbiAgICBpZiAocmVmPy5uYXRpdmVFbGVtZW50KSB0aGlzLnN0YXJ0UG9zaXRpb25pbmcocmVmLm5hdGl2ZUVsZW1lbnQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBpc09wZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbS5pc09wZW47XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGNvbXB1dGVkQ2xhc3MoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY24oXG4gICAgICAnei1bMTAwMF0gb3ZlcmZsb3ctYXV0byByb3VuZGVkLW1kIGJvcmRlciBib3JkZXItYm9yZGVyIGJnLXBvcG92ZXIgcC0yIHRleHQtcG9wb3Zlci1mb3JlZ3JvdW5kJyxcbiAgICAgICdzaGFkb3ctbGcgYW5pbWF0ZS1pbiBmYWRlLWluIHpvb20taW4tOTUnLFxuICAgICAgdGhpcy5jbGFzc1xuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25Qb2ludGVyRW50ZXIoKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLmNhbmNlbENsb3NlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25Qb2ludGVyTGVhdmUoKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLnNjaGVkdWxlQ2xvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRQb3NpdGlvbmluZyhwYW5lbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICBjb25zdCB0cmlnZ2VyID0gdGhpcy5pdGVtLnRyaWdnZXJFbGVtZW50O1xuICAgIGlmICghdHJpZ2dlcikgcmV0dXJuO1xuICAgIHRoaXMuY2xlYW51cCA9IGF1dG9VcGRhdGUodHJpZ2dlciwgcGFuZWwsICgpID0+IHtcbiAgICAgIGNvbXB1dGVQb3NpdGlvbih0cmlnZ2VyLCBwYW5lbCwge1xuICAgICAgICBzdHJhdGVneTogJ2ZpeGVkJyxcbiAgICAgICAgcGxhY2VtZW50OiB0aGlzLnBsYWNlbWVudCxcbiAgICAgICAgbWlkZGxld2FyZTogW1xuICAgICAgICAgIG9mZnNldCh0aGlzLnNpZGVPZmZzZXQpLFxuICAgICAgICAgIGZsaXAoKSxcbiAgICAgICAgICBzaGlmdCh7IHBhZGRpbmc6IDggfSksXG4gICAgICAgICAgLy8gV2lkZSBwYW5lbHMgYXJlIGNvbW1vbiBoZXJlIOKAlCBjbGFtcCB0byB3aGF0IHRoZSB2aWV3cG9ydCBjYW4gc2hvd1xuICAgICAgICAgIC8vIGluc3RlYWQgb2YgbGV0dGluZyB0aGVtIG92ZXJmbG93LlxuICAgICAgICAgIHNpemUoe1xuICAgICAgICAgICAgcGFkZGluZzogOCxcbiAgICAgICAgICAgIGFwcGx5KHsgZWxlbWVudHMsIGF2YWlsYWJsZVdpZHRoLCBhdmFpbGFibGVIZWlnaHQgfSkge1xuICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKGVsZW1lbnRzLmZsb2F0aW5nLnN0eWxlLCB7XG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IGAke01hdGgubWF4KDAsIGF2YWlsYWJsZVdpZHRoKX1weGAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiBgJHtNYXRoLm1heCgwLCBhdmFpbGFibGVIZWlnaHQpfXB4YCxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICBdLFxuICAgICAgfSkudGhlbigoeyB4LCB5IH0pID0+IHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihwYW5lbC5zdHlsZSwgeyBsZWZ0OiBgJHt4fXB4YCwgdG9wOiBgJHt5fXB4YCB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzdG9wUG9zaXRpb25pbmcoKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhbnVwPy4oKTtcbiAgICB0aGlzLmNsZWFudXAgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuc3RvcFBvc2l0aW9uaW5nKCk7XG4gIH1cbn1cblxuLyoqIEEgbGluayBpbnNpZGUgYSBwYW5lbCAob3IgZGlyZWN0bHkgaW4gdGhlIGxpc3QsIGZvciBmbGF0IGVudHJpZXMpLiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtbmF2aWdhdGlvbi1tZW51LWxpbmsnLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGFcbiAgICAgIFthdHRyLmhyZWZdPVwiaHJlZiB8fCBudWxsXCJcbiAgICAgIFthdHRyLnRhcmdldF09XCJ0YXJnZXQgfHwgbnVsbFwiXG4gICAgICBbYXR0ci5yZWxdPVwidGFyZ2V0ID09PSAnX2JsYW5rJyA/ICdub3JlZmVycmVyIG5vb3BlbmVyJyA6IG51bGxcIlxuICAgICAgW2F0dHIuYXJpYS1jdXJyZW50XT1cImFjdGl2ZSA/ICdwYWdlJyA6IG51bGxcIlxuICAgICAgW2F0dHIuZGF0YS1hY3RpdmVdPVwiYWN0aXZlID8gJycgOiBudWxsXCJcbiAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCJcbiAgICAgIChjbGljayk9XCJuYXZpZ2F0ZS5lbWl0KCRldmVudClcIlxuICAgID5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltsYWJlbF1cIj48L25nLWNvbnRlbnQ+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbZGVzY3JpcHRpb25dXCI+PC9uZy1jb250ZW50PlxuICAgIDwvYT5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTmF2aWdhdGlvbk1lbnVMaW5rQ29tcG9uZW50ICBpbXBsZW1lbnRzIE9uQ2hhbmdlc3tcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogRGVzdGluYXRpb24gVVJMLiBPbWl0IHRvIHJlbmRlciBhIG5vbi1uYXZpZ2F0aW5nIGl0ZW0uICovXG4gIEBJbnB1dCgpIGhyZWYgPSAnJztcbiAgLyoqIEFuY2hvciB0YXJnZXQ7IGBfYmxhbmtgIGFsc28gc2V0cyBhIHNhZmUgYHJlbGAuICovXG4gIEBJbnB1dCgpIHRhcmdldCA9ICcnO1xuICAvKiogTWFya3MgdGhlIGxpbmsgYXMgdGhlIGN1cnJlbnQgcGFnZS4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgYWN0aXZlID0gZmFsc2U7XG4gIC8qKiBWaXN1YWwgc3R5bGUgb2YgdGhlIGxpbmsuIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSB2YXJpYW50OiBOYXZpZ2F0aW9uTWVudUxpbmtQcm9wc1sndmFyaWFudCddID0gJ2RlZmF1bHQnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgYW5jaG9yIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgLyoqIEVtaXR0ZWQgd2l0aCB0aGUgY2xpY2sgZXZlbnQgd2hlbiB0aGUgbGluayBpcyBhY3RpdmF0ZWQuICovXG4gIEBPdXRwdXQoKSBuYXZpZ2F0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8TW91c2VFdmVudD4oKTtcblxuICBwcm90ZWN0ZWQgZ2V0IGNvbXB1dGVkQ2xhc3MoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY24oXG4gICAgICBuYXZpZ2F0aW9uTWVudUxpbmtWYXJpYW50cyh7IHZhcmlhbnQ6IHRoaXMudmFyaWFudCwgYWN0aXZlOiB0aGlzLmFjdGl2ZSB9KSxcbiAgICAgIHRoaXMuY2xhc3NcbiAgICApO1xuICB9XG59XG4iXX0=