@tolle_/tolle-ui 18.2.28 → 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 +63 -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 +16457 -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 +27 -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 +8497 -1553
  177. package/registry/llms-full.txt +2679 -318
  178. package/registry/llms.txt +43 -4
  179. package/registry/manifest.json +9093 -1739
  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,526 @@
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Injectable, Input, Output, ViewChild, forwardRef, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import { BehaviorSubject, Subject, Subscription } from 'rxjs';
5
+ import { cva } from 'class-variance-authority';
6
+ import { cn } from './utils/cn';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ const promptInputVariants = cva('flex w-full flex-col gap-2 rounded-lg border bg-background p-2 shadow-sm transition-colors focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-background', {
10
+ variants: {
11
+ status: {
12
+ ready: 'border-input focus-within:ring-ring',
13
+ streaming: 'border-info focus-within:ring-info',
14
+ error: 'border-destructive focus-within:ring-destructive',
15
+ },
16
+ size: {
17
+ sm: 'p-1.5 text-xs',
18
+ default: 'p-2 text-sm',
19
+ lg: 'p-3 text-base',
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ status: 'ready',
24
+ size: 'default',
25
+ },
26
+ });
27
+ /**
28
+ * Coordinates a `tolle-prompt-input` with its projected toolbar controls.
29
+ *
30
+ * The submit button is an OnPush child that must flip to a stop button the
31
+ * moment the status changes, so the composer publishes its state here instead
32
+ * of the button reading the parent's fields.
33
+ *
34
+ * Provided on `PromptInputComponent`, so each composer gets its own instance.
35
+ */
36
+ export class PromptInputService {
37
+ statusSource = new BehaviorSubject('ready');
38
+ /** Emits the composer's current status. */
39
+ status$ = this.statusSource.asObservable();
40
+ canSubmitSource = new BehaviorSubject(false);
41
+ /** Emits whether there is submittable text and the composer is enabled. */
42
+ canSubmit$ = this.canSubmitSource.asObservable();
43
+ submitSource = new Subject();
44
+ /** Emits when a toolbar control asks the composer to submit. */
45
+ submit$ = this.submitSource.asObservable();
46
+ stopSource = new Subject();
47
+ /** Emits when a toolbar control asks the composer to stop streaming. */
48
+ stop$ = this.stopSource.asObservable();
49
+ /** The composer's current status. */
50
+ get status() {
51
+ return this.statusSource.value;
52
+ }
53
+ /** True when the composer has submittable text. */
54
+ get canSubmit() {
55
+ return this.canSubmitSource.value;
56
+ }
57
+ setStatus(status) {
58
+ if (this.statusSource.value !== status)
59
+ this.statusSource.next(status);
60
+ }
61
+ setCanSubmit(value) {
62
+ if (this.canSubmitSource.value !== value)
63
+ this.canSubmitSource.next(value);
64
+ }
65
+ requestSubmit() {
66
+ this.submitSource.next();
67
+ }
68
+ requestStop() {
69
+ this.stopSource.next();
70
+ }
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputService });
73
+ }
74
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputService, decorators: [{
75
+ type: Injectable
76
+ }] });
77
+ /**
78
+ * A message composer: an auto-growing textarea plus a toolbar, wired as a
79
+ * `ControlValueAccessor` so it drops into template- or reactive-driven forms.
80
+ *
81
+ * Enter submits and Shift+Enter inserts a newline (swap with `submitOnEnter`).
82
+ * While `status` is 'streaming' the projected `tolle-prompt-input-submit`
83
+ * becomes a stop button that emits `stopped`.
84
+ * @new
85
+ */
86
+ export class PromptInputComponent {
87
+ /** Placeholder shown while the composer is empty. @default 'Send a message…' */
88
+ placeholder = 'Send a message…';
89
+ /** Blocks typing and submission. @default false */
90
+ disabled = false;
91
+ /** Rows the textarea may grow to before it starts scrolling. @default 8 */
92
+ maxRows = 8;
93
+ /** Lifecycle of the response being composed. @default 'ready' */
94
+ status = 'ready';
95
+ /** Size scale of the composer. @default 'default' */
96
+ size = 'default';
97
+ /** Submit on Enter, keeping Shift+Enter for newlines. @default true */
98
+ submitOnEnter = true;
99
+ /** Clears the composer after a successful submit. @default true */
100
+ clearOnSubmit = true;
101
+ /** Accessible name for the textarea. @default '' */
102
+ ariaLabel = '';
103
+ /** Extra Tailwind classes merged onto the composer via `cn()` (last-wins). */
104
+ class = '';
105
+ /** Extra Tailwind classes merged onto the textarea via `cn()` (last-wins). */
106
+ textareaClass = '';
107
+ /** Emitted with the trimmed message text when the user submits. */
108
+ submitted = new EventEmitter();
109
+ /** Emitted when the user cancels an in-flight streaming response. */
110
+ stopped = new EventEmitter();
111
+ /** Emitted with the message text whenever it changes. */
112
+ valueChange = new EventEmitter();
113
+ textarea;
114
+ service = inject(PromptInputService);
115
+ cdr = inject(ChangeDetectorRef);
116
+ subscriptions = new Subscription();
117
+ value = '';
118
+ onChange = () => { };
119
+ onTouched = () => { };
120
+ ngOnInit() {
121
+ this.syncService();
122
+ this.subscriptions.add(this.service.submit$.subscribe(() => this.submit()));
123
+ this.subscriptions.add(this.service.stop$.subscribe(() => this.stop()));
124
+ }
125
+ ngOnChanges() {
126
+ this.syncService();
127
+ // A bound `class` input is written through Angular's styling path,
128
+ // which does not mark an OnPush view dirty on its own.
129
+ this.cdr.markForCheck();
130
+ }
131
+ ngAfterViewInit() {
132
+ this.resize();
133
+ }
134
+ ngOnDestroy() {
135
+ this.subscriptions.unsubscribe();
136
+ }
137
+ get computedClass() {
138
+ return cn(promptInputVariants({ status: this.status, size: this.size }), this.disabled && 'cursor-not-allowed opacity-60', this.class);
139
+ }
140
+ get textareaComputedClass() {
141
+ return cn('w-full resize-none bg-transparent px-2 py-1.5 text-sm text-foreground outline-none', 'placeholder:text-muted-foreground disabled:cursor-not-allowed', this.textareaClass);
142
+ }
143
+ onInput(event) {
144
+ const next = event.target.value;
145
+ this.setValue(next);
146
+ this.resize();
147
+ }
148
+ onKeyDown(event) {
149
+ if (event.key !== 'Enter' || !this.submitOnEnter)
150
+ return;
151
+ // Shift+Enter is the newline escape hatch; modifier chords and IME
152
+ // composition must never steal the keystroke.
153
+ if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)
154
+ return;
155
+ if (event.isComposing)
156
+ return;
157
+ event.preventDefault();
158
+ this.submit();
159
+ }
160
+ onBlur() {
161
+ this.onTouched();
162
+ }
163
+ /** Submits the current text, unless the composer is empty, disabled or busy. */
164
+ submit() {
165
+ if (this.disabled || this.status === 'streaming')
166
+ return;
167
+ const text = this.value.trim();
168
+ if (!text)
169
+ return;
170
+ this.submitted.emit(text);
171
+ if (this.clearOnSubmit) {
172
+ this.setValue('');
173
+ if (this.textarea)
174
+ this.textarea.nativeElement.value = '';
175
+ this.resize();
176
+ }
177
+ }
178
+ /** Cancels an in-flight streaming response. */
179
+ stop() {
180
+ this.stopped.emit();
181
+ }
182
+ /** Moves focus into the textarea. */
183
+ focus() {
184
+ this.textarea?.nativeElement.focus();
185
+ }
186
+ writeValue(value) {
187
+ this.value = value ?? '';
188
+ if (this.textarea)
189
+ this.textarea.nativeElement.value = this.value;
190
+ this.service.setCanSubmit(this.canSubmit);
191
+ this.cdr.markForCheck();
192
+ this.resize();
193
+ }
194
+ registerOnChange(fn) {
195
+ this.onChange = fn;
196
+ }
197
+ registerOnTouched(fn) {
198
+ this.onTouched = fn;
199
+ }
200
+ setDisabledState(isDisabled) {
201
+ this.disabled = isDisabled;
202
+ this.syncService();
203
+ this.cdr.markForCheck();
204
+ }
205
+ get canSubmit() {
206
+ return !this.disabled && this.value.trim().length > 0;
207
+ }
208
+ setValue(next) {
209
+ this.value = next;
210
+ this.onChange(next);
211
+ this.valueChange.emit(next);
212
+ this.service.setCanSubmit(this.canSubmit);
213
+ }
214
+ syncService() {
215
+ this.service.setStatus(this.status);
216
+ this.service.setCanSubmit(this.canSubmit);
217
+ }
218
+ /**
219
+ * Grows the textarea with its content up to `maxRows`, then lets it scroll.
220
+ * Measured from the computed line height so it tracks the inherited font.
221
+ */
222
+ resize() {
223
+ const el = this.textarea?.nativeElement;
224
+ if (!el)
225
+ return;
226
+ el.style.height = 'auto';
227
+ const styles = getComputedStyle(el);
228
+ const parsedLineHeight = parseFloat(styles.lineHeight);
229
+ const lineHeight = Number.isFinite(parsedLineHeight)
230
+ ? parsedLineHeight
231
+ : parseFloat(styles.fontSize) * 1.5 || 20;
232
+ const vertical = parseFloat(styles.paddingTop || '0') +
233
+ parseFloat(styles.paddingBottom || '0') +
234
+ parseFloat(styles.borderTopWidth || '0') +
235
+ parseFloat(styles.borderBottomWidth || '0');
236
+ const max = lineHeight * Math.max(1, this.maxRows) + vertical;
237
+ const next = Math.min(el.scrollHeight, max);
238
+ el.style.height = next + 'px';
239
+ el.style.overflowY = el.scrollHeight > max ? 'auto' : 'hidden';
240
+ }
241
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
242
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PromptInputComponent, isStandalone: true, selector: "tolle-prompt-input", inputs: { placeholder: "placeholder", disabled: "disabled", maxRows: "maxRows", status: "status", size: "size", submitOnEnter: "submitOnEnter", clearOnSubmit: "clearOnSubmit", ariaLabel: "ariaLabel", class: "class", textareaClass: "textareaClass" }, outputs: { submitted: "submitted", stopped: "stopped", valueChange: "valueChange" }, providers: [
243
+ PromptInputService,
244
+ {
245
+ provide: NG_VALUE_ACCESSOR,
246
+ useExisting: forwardRef(() => PromptInputComponent),
247
+ multi: true,
248
+ },
249
+ ], viewQueries: [{ propertyName: "textarea", first: true, predicate: ["textarea"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
250
+ <div [class]="computedClass">
251
+ <textarea
252
+ #textarea
253
+ data-prompt-input-textarea
254
+ rows="1"
255
+ [value]="value"
256
+ [attr.placeholder]="placeholder"
257
+ [disabled]="disabled"
258
+ [attr.aria-label]="ariaLabel || placeholder || 'Message'"
259
+ [attr.aria-invalid]="status === 'error' ? 'true' : null"
260
+ [class]="textareaComputedClass"
261
+ (input)="onInput($event)"
262
+ (keydown)="onKeyDown($event)"
263
+ (blur)="onBlur()"
264
+ ></textarea>
265
+
266
+ <ng-content></ng-content>
267
+ </div>
268
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
269
+ }
270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputComponent, decorators: [{
271
+ type: Component,
272
+ args: [{ selector: 'tolle-prompt-input', standalone: true, imports: [CommonModule], providers: [
273
+ PromptInputService,
274
+ {
275
+ provide: NG_VALUE_ACCESSOR,
276
+ useExisting: forwardRef(() => PromptInputComponent),
277
+ multi: true,
278
+ },
279
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: `
280
+ <div [class]="computedClass">
281
+ <textarea
282
+ #textarea
283
+ data-prompt-input-textarea
284
+ rows="1"
285
+ [value]="value"
286
+ [attr.placeholder]="placeholder"
287
+ [disabled]="disabled"
288
+ [attr.aria-label]="ariaLabel || placeholder || 'Message'"
289
+ [attr.aria-invalid]="status === 'error' ? 'true' : null"
290
+ [class]="textareaComputedClass"
291
+ (input)="onInput($event)"
292
+ (keydown)="onKeyDown($event)"
293
+ (blur)="onBlur()"
294
+ ></textarea>
295
+
296
+ <ng-content></ng-content>
297
+ </div>
298
+ `, styles: [":host{display:block}\n"] }]
299
+ }], propDecorators: { placeholder: [{
300
+ type: Input
301
+ }], disabled: [{
302
+ type: Input
303
+ }], maxRows: [{
304
+ type: Input
305
+ }], status: [{
306
+ type: Input
307
+ }], size: [{
308
+ type: Input
309
+ }], submitOnEnter: [{
310
+ type: Input
311
+ }], clearOnSubmit: [{
312
+ type: Input
313
+ }], ariaLabel: [{
314
+ type: Input
315
+ }], class: [{
316
+ type: Input
317
+ }], textareaClass: [{
318
+ type: Input
319
+ }], submitted: [{
320
+ type: Output
321
+ }], stopped: [{
322
+ type: Output
323
+ }], valueChange: [{
324
+ type: Output
325
+ }], textarea: [{
326
+ type: ViewChild,
327
+ args: ['textarea']
328
+ }] } });
329
+ /** Bottom bar of a `tolle-prompt-input`: tools on the left, submit on the right. */
330
+ export class PromptInputToolbarComponent {
331
+ cdr = inject(ChangeDetectorRef);
332
+ /**
333
+ * Angular writes a bound `class` input through its styling path, which does
334
+ * not mark an OnPush component dirty — without this hook the component keeps
335
+ * rendering the class it was born with.
336
+ */
337
+ ngOnChanges() {
338
+ this.cdr.markForCheck();
339
+ }
340
+ /** Extra Tailwind classes merged onto the toolbar via `cn()` (last-wins). */
341
+ class = '';
342
+ get computedClass() {
343
+ return cn('flex items-center justify-between gap-2 px-1', this.class);
344
+ }
345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
346
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PromptInputToolbarComponent, isStandalone: true, selector: "tolle-prompt-input-toolbar", inputs: { class: "class" }, usesOnChanges: true, ngImport: i0, template: `
347
+ <div [class]="computedClass">
348
+ <ng-content></ng-content>
349
+ </div>
350
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
351
+ }
352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputToolbarComponent, decorators: [{
353
+ type: Component,
354
+ args: [{ selector: 'tolle-prompt-input-toolbar', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
355
+ <div [class]="computedClass">
356
+ <ng-content></ng-content>
357
+ </div>
358
+ `, styles: [":host{display:block}\n"] }]
359
+ }], propDecorators: { class: [{
360
+ type: Input
361
+ }] } });
362
+ /** Left-aligned cluster of tool buttons inside a `tolle-prompt-input-toolbar`. */
363
+ export class PromptInputToolsComponent {
364
+ cdr = inject(ChangeDetectorRef);
365
+ /**
366
+ * Angular writes a bound `class` input through its styling path, which does
367
+ * not mark an OnPush component dirty — without this hook the component keeps
368
+ * rendering the class it was born with.
369
+ */
370
+ ngOnChanges() {
371
+ this.cdr.markForCheck();
372
+ }
373
+ /** Extra Tailwind classes merged onto the tool row via `cn()` (last-wins). */
374
+ class = '';
375
+ get computedClass() {
376
+ return cn('flex flex-1 items-center gap-1 text-muted-foreground', this.class);
377
+ }
378
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputToolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
379
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PromptInputToolsComponent, isStandalone: true, selector: "tolle-prompt-input-tools", inputs: { class: "class" }, usesOnChanges: true, ngImport: i0, template: `
380
+ <div [class]="computedClass">
381
+ <ng-content></ng-content>
382
+ </div>
383
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
384
+ }
385
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputToolsComponent, decorators: [{
386
+ type: Component,
387
+ args: [{ selector: 'tolle-prompt-input-tools', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
388
+ <div [class]="computedClass">
389
+ <ng-content></ng-content>
390
+ </div>
391
+ `, styles: [":host{display:block}\n"] }]
392
+ }], propDecorators: { class: [{
393
+ type: Input
394
+ }] } });
395
+ const promptInputSubmitVariants = cva('inline-flex shrink-0 items-center justify-center gap-1.5 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50', {
396
+ variants: {
397
+ variant: {
398
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
399
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
400
+ ghost: 'text-foreground hover:bg-accent hover:text-accent-foreground',
401
+ },
402
+ size: {
403
+ sm: 'h-7 px-2 text-xs',
404
+ default: 'size-8 text-sm',
405
+ lg: 'h-10 px-4 text-sm',
406
+ },
407
+ },
408
+ defaultVariants: {
409
+ variant: 'default',
410
+ size: 'default',
411
+ },
412
+ });
413
+ /**
414
+ * Send button for a `tolle-prompt-input`. Turns into a stop button while the
415
+ * composer's status is 'streaming', so one control covers both directions.
416
+ */
417
+ export class PromptInputSubmitComponent {
418
+ /**
419
+ * Angular writes a bound `class` input through its styling path, which does
420
+ * not mark an OnPush component dirty — without this hook the component keeps
421
+ * rendering the class it was born with.
422
+ */
423
+ ngOnChanges() {
424
+ this.cdr.markForCheck();
425
+ }
426
+ /** Visual style of the button. @default 'default' */
427
+ variant = 'default';
428
+ /** Size of the button. @default 'default' */
429
+ size = 'default';
430
+ /** Accessible name while the composer is idle. @default 'Send message' */
431
+ submitLabel = 'Send message';
432
+ /** Accessible name while the composer is streaming. @default 'Stop generating' */
433
+ stopLabel = 'Stop generating';
434
+ /** Renders the label next to the icon. @default false */
435
+ showLabel = false;
436
+ /** Extra Tailwind classes merged onto the button via `cn()` (last-wins). */
437
+ class = '';
438
+ service = inject(PromptInputService);
439
+ cdr = inject(ChangeDetectorRef);
440
+ subscriptions = new Subscription();
441
+ status = 'ready';
442
+ canSubmit = false;
443
+ ngOnInit() {
444
+ this.subscriptions.add(this.service.status$.subscribe((status) => {
445
+ this.status = status;
446
+ this.cdr.markForCheck();
447
+ }));
448
+ this.subscriptions.add(this.service.canSubmit$.subscribe((canSubmit) => {
449
+ this.canSubmit = canSubmit;
450
+ this.cdr.markForCheck();
451
+ }));
452
+ }
453
+ ngOnDestroy() {
454
+ this.subscriptions.unsubscribe();
455
+ }
456
+ /** True while the button is showing its stop affordance. */
457
+ get isStreaming() {
458
+ return this.status === 'streaming';
459
+ }
460
+ get currentIcon() {
461
+ return this.isStreaming ? 'ri-stop-circle-line' : 'ri-send-plane-2-fill';
462
+ }
463
+ get currentLabel() {
464
+ return this.isStreaming ? this.stopLabel : this.submitLabel;
465
+ }
466
+ /** Stopping stays available with an empty composer; sending does not. */
467
+ get isDisabled() {
468
+ return !this.isStreaming && !this.canSubmit;
469
+ }
470
+ get computedClass() {
471
+ return cn(promptInputSubmitVariants({ variant: this.variant, size: this.size }), this.isStreaming && 'bg-destructive text-destructive-foreground hover:bg-destructive/90', this.class);
472
+ }
473
+ onClick() {
474
+ if (this.isStreaming) {
475
+ this.service.requestStop();
476
+ }
477
+ else {
478
+ this.service.requestSubmit();
479
+ }
480
+ }
481
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputSubmitComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
482
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PromptInputSubmitComponent, isStandalone: true, selector: "tolle-prompt-input-submit", inputs: { variant: "variant", size: "size", submitLabel: "submitLabel", stopLabel: "stopLabel", showLabel: "showLabel", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
483
+ <button
484
+ type="button"
485
+ data-prompt-input-submit
486
+ [attr.data-state]="status"
487
+ [attr.aria-label]="currentLabel"
488
+ [disabled]="isDisabled"
489
+ [class]="computedClass"
490
+ (click)="onClick()"
491
+ >
492
+ <i [class]="currentIcon" aria-hidden="true"></i>
493
+ <span *ngIf="showLabel">{{ currentLabel }}</span>
494
+ </button>
495
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
496
+ }
497
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PromptInputSubmitComponent, decorators: [{
498
+ type: Component,
499
+ args: [{ selector: 'tolle-prompt-input-submit', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
500
+ <button
501
+ type="button"
502
+ data-prompt-input-submit
503
+ [attr.data-state]="status"
504
+ [attr.aria-label]="currentLabel"
505
+ [disabled]="isDisabled"
506
+ [class]="computedClass"
507
+ (click)="onClick()"
508
+ >
509
+ <i [class]="currentIcon" aria-hidden="true"></i>
510
+ <span *ngIf="showLabel">{{ currentLabel }}</span>
511
+ </button>
512
+ `, styles: [":host{display:block}\n"] }]
513
+ }], propDecorators: { variant: [{
514
+ type: Input
515
+ }], size: [{
516
+ type: Input
517
+ }], submitLabel: [{
518
+ type: Input
519
+ }], stopLabel: [{
520
+ type: Input
521
+ }], showLabel: [{
522
+ type: Input
523
+ }], class: [{
524
+ type: Input
525
+ }] } });
526
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbXB0LWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvcHJvbXB0LWlucHV0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWlCLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBYyxZQUFZLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBZ0MsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZOLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlELE9BQU8sRUFBRSxHQUFHLEVBQXFCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLFlBQVksQ0FBQzs7O0FBRWhDLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxDQUM3QiwrS0FBK0ssRUFDL0s7SUFDRSxRQUFRLEVBQUU7UUFDUixNQUFNLEVBQUU7WUFDTixLQUFLLEVBQUUscUNBQXFDO1lBQzVDLFNBQVMsRUFBRSxvQ0FBb0M7WUFDL0MsS0FBSyxFQUFFLGtEQUFrRDtTQUMxRDtRQUNELElBQUksRUFBRTtZQUNKLEVBQUUsRUFBRSxlQUFlO1lBQ25CLE9BQU8sRUFBRSxhQUFhO1lBQ3RCLEVBQUUsRUFBRSxlQUFlO1NBQ3BCO0tBQ0Y7SUFDRCxlQUFlLEVBQUU7UUFDZixNQUFNLEVBQUUsT0FBTztRQUNmLElBQUksRUFBRSxTQUFTO0tBQ2hCO0NBQ0YsQ0FDRixDQUFDO0FBT0Y7Ozs7Ozs7O0dBUUc7QUFFSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ1osWUFBWSxH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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbmplY3RhYmxlLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBWaWV3Q2hpbGQsIGZvcndhcmRSZWYsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAnY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5JztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5cbmNvbnN0IHByb21wdElucHV0VmFyaWFudHMgPSBjdmEoXG4gICdmbGV4IHctZnVsbCBmbGV4LWNvbCBnYXAtMiByb3VuZGVkLWxnIGJvcmRlciBiZy1iYWNrZ3JvdW5kIHAtMiBzaGFkb3ctc20gdHJhbnNpdGlvbi1jb2xvcnMgZm9jdXMtd2l0aGluOnJpbmctMiBmb2N1cy13aXRoaW46cmluZy1vZmZzZXQtMiBmb2N1cy13aXRoaW46cmluZy1vZmZzZXQtYmFja2dyb3VuZCcsXG4gIHtcbiAgICB2YXJpYW50czoge1xuICAgICAgc3RhdHVzOiB7XG4gICAgICAgIHJlYWR5OiAnYm9yZGVyLWlucHV0IGZvY3VzLXdpdGhpbjpyaW5nLXJpbmcnLFxuICAgICAgICBzdHJlYW1pbmc6ICdib3JkZXItaW5mbyBmb2N1cy13aXRoaW46cmluZy1pbmZvJyxcbiAgICAgICAgZXJyb3I6ICdib3JkZXItZGVzdHJ1Y3RpdmUgZm9jdXMtd2l0aGluOnJpbmctZGVzdHJ1Y3RpdmUnLFxuICAgICAgfSxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgc206ICdwLTEuNSB0ZXh0LXhzJyxcbiAgICAgICAgZGVmYXVsdDogJ3AtMiB0ZXh0LXNtJyxcbiAgICAgICAgbGc6ICdwLTMgdGV4dC1iYXNlJyxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBkZWZhdWx0VmFyaWFudHM6IHtcbiAgICAgIHN0YXR1czogJ3JlYWR5JyxcbiAgICAgIHNpemU6ICdkZWZhdWx0JyxcbiAgICB9LFxuICB9XG4pO1xuXG5leHBvcnQgdHlwZSBQcm9tcHRJbnB1dFByb3BzID0gVmFyaWFudFByb3BzPHR5cGVvZiBwcm9tcHRJbnB1dFZhcmlhbnRzPjtcblxuLyoqIExpZmVjeWNsZSBvZiB0aGUgcmVzcG9uc2UgdGhlIGNvbXBvc2VyIGlzIGRyaXZpbmcuICovXG5leHBvcnQgdHlwZSBQcm9tcHRJbnB1dFN0YXR1cyA9IE5vbk51bGxhYmxlPFByb21wdElucHV0UHJvcHNbJ3N0YXR1cyddPjtcblxuLyoqXG4gKiBDb29yZGluYXRlcyBhIGB0b2xsZS1wcm9tcHQtaW5wdXRgIHdpdGggaXRzIHByb2plY3RlZCB0b29sYmFyIGNvbnRyb2xzLlxuICpcbiAqIFRoZSBzdWJtaXQgYnV0dG9uIGlzIGFuIE9uUHVzaCBjaGlsZCB0aGF0IG11c3QgZmxpcCB0byBhIHN0b3AgYnV0dG9uIHRoZVxuICogbW9tZW50IHRoZSBzdGF0dXMgY2hhbmdlcywgc28gdGhlIGNvbXBvc2VyIHB1Ymxpc2hlcyBpdHMgc3RhdGUgaGVyZSBpbnN0ZWFkXG4gKiBvZiB0aGUgYnV0dG9uIHJlYWRpbmcgdGhlIHBhcmVudCdzIGZpZWxkcy5cbiAqXG4gKiBQcm92aWRlZCBvbiBgUHJvbXB0SW5wdXRDb21wb25lbnRgLCBzbyBlYWNoIGNvbXBvc2VyIGdldHMgaXRzIG93biBpbnN0YW5jZS5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFByb21wdElucHV0U2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RhdHVzU291cmNlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxQcm9tcHRJbnB1dFN0YXR1cz4oJ3JlYWR5Jyk7XG4gIC8qKiBFbWl0cyB0aGUgY29tcG9zZXIncyBjdXJyZW50IHN0YXR1cy4gKi9cbiAgcmVhZG9ubHkgc3RhdHVzJCA9IHRoaXMuc3RhdHVzU291cmNlLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2FuU3VibWl0U291cmNlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIC8qKiBFbWl0cyB3aGV0aGVyIHRoZXJlIGlzIHN1Ym1pdHRhYmxlIHRleHQgYW5kIHRoZSBjb21wb3NlciBpcyBlbmFibGVkLiAqL1xuICByZWFkb25seSBjYW5TdWJtaXQkID0gdGhpcy5jYW5TdWJtaXRTb3VyY2UuYXNPYnNlcnZhYmxlKCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzdWJtaXRTb3VyY2UgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAvKiogRW1pdHMgd2hlbiBhIHRvb2xiYXIgY29udHJvbCBhc2tzIHRoZSBjb21wb3NlciB0byBzdWJtaXQuICovXG4gIHJlYWRvbmx5IHN1Ym1pdCQgPSB0aGlzLnN1Ym1pdFNvdXJjZS5hc09ic2VydmFibGUoKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHN0b3BTb3VyY2UgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAvKiogRW1pdHMgd2hlbiBhIHRvb2xiYXIgY29udHJvbCBhc2tzIHRoZSBjb21wb3NlciB0byBzdG9wIHN0cmVhbWluZy4gKi9cbiAgcmVhZG9ubHkgc3RvcCQgPSB0aGlzLnN0b3BTb3VyY2UuYXNPYnNlcnZhYmxlKCk7XG5cbiAgLyoqIFRoZSBjb21wb3NlcidzIGN1cnJlbnQgc3RhdHVzLiAqL1xuICBnZXQgc3RhdHVzKCk6IFByb21wdElucHV0U3RhdHVzIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0dXNTb3VyY2UudmFsdWU7XG4gIH1cblxuICAvKiogVHJ1ZSB3aGVuIHRoZSBjb21wb3NlciBoYXMgc3VibWl0dGFibGUgdGV4dC4gKi9cbiAgZ2V0IGNhblN1Ym1pdCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jYW5TdWJtaXRTb3VyY2UudmFsdWU7XG4gIH1cblxuICBzZXRTdGF0dXMoc3RhdHVzOiBQcm9tcHRJbnB1dFN0YXR1cyk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0YXR1c1NvdXJjZS52YWx1ZSAhPT0gc3RhdHVzKSB0aGlzLnN0YXR1c1NvdXJjZS5uZXh0KHN0YXR1cyk7XG4gIH1cblxuICBzZXRDYW5TdWJtaXQodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jYW5TdWJtaXRTb3VyY2UudmFsdWUgIT09IHZhbHVlKSB0aGlzLmNhblN1Ym1pdFNvdXJjZS5uZXh0KHZhbHVlKTtcbiAgfVxuXG4gIHJlcXVlc3RTdWJtaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJtaXRTb3VyY2UubmV4dCgpO1xuICB9XG5cbiAgcmVxdWVzdFN0b3AoKTogdm9pZCB7XG4gICAgdGhpcy5zdG9wU291cmNlLm5leHQoKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgbWVzc2FnZSBjb21wb3NlcjogYW4gYXV0by1ncm93aW5nIHRleHRhcmVhIHBsdXMgYSB0b29sYmFyLCB3aXJlZCBhcyBhXG4gKiBgQ29udHJvbFZhbHVlQWNjZXNzb3JgIHNvIGl0IGRyb3BzIGludG8gdGVtcGxhdGUtIG9yIHJlYWN0aXZlLWRyaXZlbiBmb3Jtcy5cbiAqXG4gKiBFbnRlciBzdWJtaXRzIGFuZCBTaGlmdCtFbnRlciBpbnNlcnRzIGEgbmV3bGluZSAoc3dhcCB3aXRoIGBzdWJtaXRPbkVudGVyYCkuXG4gKiBXaGlsZSBgc3RhdHVzYCBpcyAnc3RyZWFtaW5nJyB0aGUgcHJvamVjdGVkIGB0b2xsZS1wcm9tcHQtaW5wdXQtc3VibWl0YFxuICogYmVjb21lcyBhIHN0b3AgYnV0dG9uIHRoYXQgZW1pdHMgYHN0b3BwZWRgLlxuICogQG5ld1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1wcm9tcHQtaW5wdXQnLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgUHJvbXB0SW5wdXRTZXJ2aWNlLFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gUHJvbXB0SW5wdXRDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgfSxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiPlxuICAgICAgPHRleHRhcmVhXG4gICAgICAgICN0ZXh0YXJlYVxuICAgICAgICBkYXRhLXByb21wdC1pbnB1dC10ZXh0YXJlYVxuICAgICAgICByb3dzPVwiMVwiXG4gICAgICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAgIFthdHRyLnBsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgcGxhY2Vob2xkZXIgfHwgJ01lc3NhZ2UnXCJcbiAgICAgICAgW2F0dHIuYXJpYS1pbnZhbGlkXT1cInN0YXR1cyA9PT0gJ2Vycm9yJyA/ICd0cnVlJyA6IG51bGxcIlxuICAgICAgICBbY2xhc3NdPVwidGV4dGFyZWFDb21wdXRlZENsYXNzXCJcbiAgICAgICAgKGlucHV0KT1cIm9uSW5wdXQoJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcbiAgICAgICAgKGJsdXIpPVwib25CbHVyKClcIlxuICAgICAgPjwvdGV4dGFyZWE+XG5cbiAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgUHJvbXB0SW5wdXRDb21wb25lbnRcbiAgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveVxue1xuICAvKiogUGxhY2Vob2xkZXIgc2hvd24gd2hpbGUgdGhlIGNvbXBvc2VyIGlzIGVtcHR5LiBAZGVmYXVsdCAnU2VuZCBhIG1lc3NhZ2XigKYnICovXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJ1NlbmQgYSBtZXNzYWdl4oCmJztcbiAgLyoqIEJsb2NrcyB0eXBpbmcgYW5kIHN1Ym1pc3Npb24uIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG4gIC8qKiBSb3dzIHRoZSB0ZXh0YXJlYSBtYXkgZ3JvdyB0byBiZWZvcmUgaXQgc3RhcnRzIHNjcm9sbGluZy4gQGRlZmF1bHQgOCAqL1xuICBASW5wdXQoKSBtYXhSb3dzID0gODtcbiAgLyoqIExpZmVjeWNsZSBvZiB0aGUgcmVzcG9uc2UgYmVpbmcgY29tcG9zZWQuIEBkZWZhdWx0ICdyZWFkeScgKi9cbiAgQElucHV0KCkgc3RhdHVzOiBQcm9tcHRJbnB1dFN0YXR1cyA9ICdyZWFkeSc7XG4gIC8qKiBTaXplIHNjYWxlIG9mIHRoZSBjb21wb3Nlci4gQGRlZmF1bHQgJ2RlZmF1bHQnICovXG4gIEBJbnB1dCgpIHNpemU6IFByb21wdElucHV0UHJvcHNbJ3NpemUnXSA9ICdkZWZhdWx0JztcbiAgLyoqIFN1Ym1pdCBvbiBFbnRlciwga2VlcGluZyBTaGlmdCtFbnRlciBmb3IgbmV3bGluZXMuIEBkZWZhdWx0IHRydWUgKi9cbiAgQElucHV0KCkgc3VibWl0T25FbnRlciA9IHRydWU7XG4gIC8qKiBDbGVhcnMgdGhlIGNvbXBvc2VyIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzdWJtaXQuIEBkZWZhdWx0IHRydWUgKi9cbiAgQElucHV0KCkgY2xlYXJPblN1Ym1pdCA9IHRydWU7XG4gIC8qKiBBY2Nlc3NpYmxlIG5hbWUgZm9yIHRoZSB0ZXh0YXJlYS4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgYXJpYUxhYmVsID0gJyc7XG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSBjb21wb3NlciB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgdGV4dGFyZWEgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgdGV4dGFyZWFDbGFzcyA9ICcnO1xuXG4gIC8qKiBFbWl0dGVkIHdpdGggdGhlIHRyaW1tZWQgbWVzc2FnZSB0ZXh0IHdoZW4gdGhlIHVzZXIgc3VibWl0cy4gKi9cbiAgQE91dHB1dCgpIHN1Ym1pdHRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICAvKiogRW1pdHRlZCB3aGVuIHRoZSB1c2VyIGNhbmNlbHMgYW4gaW4tZmxpZ2h0IHN0cmVhbWluZyByZXNwb25zZS4gKi9cbiAgQE91dHB1dCgpIHN0b3BwZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIC8qKiBFbWl0dGVkIHdpdGggdGhlIG1lc3NhZ2UgdGV4dCB3aGVuZXZlciBpdCBjaGFuZ2VzLiAqL1xuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBAVmlld0NoaWxkKCd0ZXh0YXJlYScpIHByaXZhdGUgdGV4dGFyZWE/OiBFbGVtZW50UmVmPEhUTUxUZXh0QXJlYUVsZW1lbnQ+O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VydmljZSA9IGluamVjdChQcm9tcHRJbnB1dFNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICB2YWx1ZSA9ICcnO1xuXG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHByaXZhdGUgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zeW5jU2VydmljZSgpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQodGhpcy5zZXJ2aWNlLnN1Ym1pdCQuc3Vic2NyaWJlKCgpID0+IHRoaXMuc3VibWl0KCkpKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuYWRkKHRoaXMuc2VydmljZS5zdG9wJC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zdG9wKCkpKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuc3luY1NlcnZpY2UoKTtcbiAgXG4gICAgLy8gQSBib3VuZCBgY2xhc3NgIGlucHV0IGlzIHdyaXR0ZW4gdGhyb3VnaCBBbmd1bGFyJ3Mgc3R5bGluZyBwYXRoLFxuICAgIC8vIHdoaWNoIGRvZXMgbm90IG1hcmsgYW4gT25QdXNoIHZpZXcgZGlydHkgb24gaXRzIG93bi5cbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2l6ZSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oXG4gICAgICBwcm9tcHRJbnB1dFZhcmlhbnRzKHsgc3RhdHVzOiB0aGlzLnN0YXR1cywgc2l6ZTogdGhpcy5zaXplIH0pLFxuICAgICAgdGhpcy5kaXNhYmxlZCAmJiAnY3Vyc29yLW5vdC1hbGxvd2VkIG9wYWNpdHktNjAnLFxuICAgICAgdGhpcy5jbGFzc1xuICAgICk7XG4gIH1cblxuICBnZXQgdGV4dGFyZWFDb21wdXRlZENsYXNzKCkge1xuICAgIHJldHVybiBjbihcbiAgICAgICd3LWZ1bGwgcmVzaXplLW5vbmUgYmctdHJhbnNwYXJlbnQgcHgtMiBweS0xLjUgdGV4dC1zbSB0ZXh0LWZvcmVncm91bmQgb3V0bGluZS1ub25lJyxcbiAgICAgICdwbGFjZWhvbGRlcjp0ZXh0LW11dGVkLWZvcmVncm91bmQgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkJyxcbiAgICAgIHRoaXMudGV4dGFyZWFDbGFzc1xuICAgICk7XG4gIH1cblxuICBvbklucHV0KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IG5leHQgPSAoZXZlbnQudGFyZ2V0IGFzIEhUTUxUZXh0QXJlYUVsZW1lbnQpLnZhbHVlO1xuICAgIHRoaXMuc2V0VmFsdWUobmV4dCk7XG4gICAgdGhpcy5yZXNpemUoKTtcbiAgfVxuXG4gIG9uS2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC5rZXkgIT09ICdFbnRlcicgfHwgIXRoaXMuc3VibWl0T25FbnRlcikgcmV0dXJuO1xuICAgIC8vIFNoaWZ0K0VudGVyIGlzIHRoZSBuZXdsaW5lIGVzY2FwZSBoYXRjaDsgbW9kaWZpZXIgY2hvcmRzIGFuZCBJTUVcbiAgICAvLyBjb21wb3NpdGlvbiBtdXN0IG5ldmVyIHN0ZWFsIHRoZSBrZXlzdHJva2UuXG4gICAgaWYgKGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50LmFsdEtleSB8fCBldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpIHJldHVybjtcbiAgICBpZiAoKGV2ZW50IGFzIEtleWJvYXJkRXZlbnQgJiB7IGlzQ29tcG9zaW5nPzogYm9vbGVhbiB9KS5pc0NvbXBvc2luZykgcmV0dXJuO1xuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLnN1Ym1pdCgpO1xuICB9XG5cbiAgb25CbHVyKCk6IHZvaWQge1xuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gIH1cblxuICAvKiogU3VibWl0cyB0aGUgY3VycmVudCB0ZXh0LCB1bmxlc3MgdGhlIGNvbXBvc2VyIGlzIGVtcHR5LCBkaXNhYmxlZCBvciBidXN5LiAqL1xuICBzdWJtaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5zdGF0dXMgPT09ICdzdHJlYW1pbmcnKSByZXR1cm47XG4gICAgY29uc3QgdGV4dCA9IHRoaXMudmFsdWUudHJpbSgpO1xuICAgIGlmICghdGV4dCkgcmV0dXJuO1xuXG4gICAgdGhpcy5zdWJtaXR0ZWQuZW1pdCh0ZXh0KTtcblxuICAgIGlmICh0aGlzLmNsZWFyT25TdWJtaXQpIHtcbiAgICAgIHRoaXMuc2V0VmFsdWUoJycpO1xuICAgICAgaWYgKHRoaXMudGV4dGFyZWEpIHRoaXMudGV4dGFyZWEubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2FuY2VscyBhbiBpbi1mbGlnaHQgc3RyZWFtaW5nIHJlc3BvbnNlLiAqL1xuICBzdG9wKCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcHBlZC5lbWl0KCk7XG4gIH1cblxuICAvKiogTW92ZXMgZm9jdXMgaW50byB0aGUgdGV4dGFyZWEuICovXG4gIGZvY3VzKCk6IHZvaWQge1xuICAgIHRoaXMudGV4dGFyZWE/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWUgPz8gJyc7XG4gICAgaWYgKHRoaXMudGV4dGFyZWEpIHRoaXMudGV4dGFyZWEubmF0aXZlRWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7XG4gICAgdGhpcy5zZXJ2aWNlLnNldENhblN1Ym1pdCh0aGlzLmNhblN1Ym1pdCk7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgdGhpcy5yZXNpemUoKTtcbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgdGhpcy5zeW5jU2VydmljZSgpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY2FuU3VibWl0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5kaXNhYmxlZCAmJiB0aGlzLnZhbHVlLnRyaW0oKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRWYWx1ZShuZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlID0gbmV4dDtcbiAgICB0aGlzLm9uQ2hhbmdlKG5leHQpO1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdChuZXh0KTtcbiAgICB0aGlzLnNlcnZpY2Uuc2V0Q2FuU3VibWl0KHRoaXMuY2FuU3VibWl0KTtcbiAgfVxuXG4gIHByaXZhdGUgc3luY1NlcnZpY2UoKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLnNldFN0YXR1cyh0aGlzLnN0YXR1cyk7XG4gICAgdGhpcy5zZXJ2aWNlLnNldENhblN1Ym1pdCh0aGlzLmNhblN1Ym1pdCk7XG4gIH1cblxuICAvKipcbiAgICogR3Jvd3MgdGhlIHRleHRhcmVhIHdpdGggaXRzIGNvbnRlbnQgdXAgdG8gYG1heFJvd3NgLCB0aGVuIGxldHMgaXQgc2Nyb2xsLlxuICAgKiBNZWFzdXJlZCBmcm9tIHRoZSBjb21wdXRlZCBsaW5lIGhlaWdodCBzbyBpdCB0cmFja3MgdGhlIGluaGVyaXRlZCBmb250LlxuICAgKi9cbiAgcHJpdmF0ZSByZXNpemUoKTogdm9pZCB7XG4gICAgY29uc3QgZWwgPSB0aGlzLnRleHRhcmVhPy5uYXRpdmVFbGVtZW50O1xuICAgIGlmICghZWwpIHJldHVybjtcblxuICAgIGVsLnN0eWxlLmhlaWdodCA9ICdhdXRvJztcblxuICAgIGNvbnN0IHN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIGNvbnN0IHBhcnNlZExpbmVIZWlnaHQgPSBwYXJzZUZsb2F0KHN0eWxlcy5saW5lSGVpZ2h0KTtcbiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gTnVtYmVyLmlzRmluaXRlKHBhcnNlZExpbmVIZWlnaHQpXG4gICAgICA/IHBhcnNlZExpbmVIZWlnaHRcbiAgICAgIDogcGFyc2VGbG9hdChzdHlsZXMuZm9udFNpemUpICogMS41IHx8IDIwO1xuICAgIGNvbnN0IHZlcnRpY2FsID1cbiAgICAgIHBhcnNlRmxvYXQoc3R5bGVzLnBhZGRpbmdUb3AgfHwgJzAnKSArXG4gICAgICBwYXJzZUZsb2F0KHN0eWxlcy5wYWRkaW5nQm90dG9tIHx8ICcwJykgK1xuICAgICAgcGFyc2VGbG9hdChzdHlsZXMuYm9yZGVyVG9wV2lkdGggfHwgJzAnKSArXG4gICAgICBwYXJzZUZsb2F0KHN0eWxlcy5ib3JkZXJCb3R0b21XaWR0aCB8fCAnMCcpO1xuICAgIGNvbnN0IG1heCA9IGxpbmVIZWlnaHQgKiBNYXRoLm1heCgxLCB0aGlzLm1heFJvd3MpICsgdmVydGljYWw7XG5cbiAgICBjb25zdCBuZXh0ID0gTWF0aC5taW4oZWwuc2Nyb2xsSGVpZ2h0LCBtYXgpO1xuICAgIGVsLnN0eWxlLmhlaWdodCA9IG5leHQgKyAncHgnO1xuICAgIGVsLnN0eWxlLm92ZXJmbG93WSA9IGVsLnNjcm9sbEhlaWdodCA+IG1heCA/ICdhdXRvJyA6ICdoaWRkZW4nO1xuICB9XG59XG5cbi8qKiBCb3R0b20gYmFyIG9mIGEgYHRvbGxlLXByb21wdC1pbnB1dGA6IHRvb2xzIG9uIHRoZSBsZWZ0LCBzdWJtaXQgb24gdGhlIHJpZ2h0LiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtcHJvbXB0LWlucHV0LXRvb2xiYXInLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiPlxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBQcm9tcHRJbnB1dFRvb2xiYXJDb21wb25lbnQgIGltcGxlbWVudHMgT25DaGFuZ2Vze1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSB0b29sYmFyIHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgZ2V0IGNvbXB1dGVkQ2xhc3MoKSB7XG4gICAgcmV0dXJuIGNuKCdmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gZ2FwLTIgcHgtMScsIHRoaXMuY2xhc3MpO1xuICB9XG59XG5cbi8qKiBMZWZ0LWFsaWduZWQgY2x1c3RlciBvZiB0b29sIGJ1dHRvbnMgaW5zaWRlIGEgYHRvbGxlLXByb21wdC1pbnB1dC10b29sYmFyYC4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLXByb21wdC1pbnB1dC10b29scycsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IFtjbGFzc109XCJjb21wdXRlZENsYXNzXCI+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFByb21wdElucHV0VG9vbHNDb21wb25lbnQgIGltcGxlbWVudHMgT25DaGFuZ2Vze1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSB0b29sIHJvdyB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuXG4gIGdldCBjb21wdXRlZENsYXNzKCkge1xuICAgIHJldHVybiBjbignZmxleCBmbGV4LTEgaXRlbXMtY2VudGVyIGdhcC0xIHRleHQtbXV0ZWQtZm9yZWdyb3VuZCcsIHRoaXMuY2xhc3MpO1xuICB9XG59XG5cbmNvbnN0IHByb21wdElucHV0U3VibWl0VmFyaWFudHMgPSBjdmEoXG4gICdpbmxpbmUtZmxleCBzaHJpbmstMCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTEuNSByb3VuZGVkLW1kIGZvbnQtbWVkaXVtIHRyYW5zaXRpb24tY29sb3JzIGZvY3VzLXZpc2libGU6b3V0bGluZS1ub25lIGZvY3VzLXZpc2libGU6cmluZy0yIGZvY3VzLXZpc2libGU6cmluZy1yaW5nIGZvY3VzLXZpc2libGU6cmluZy1vZmZzZXQtMiBmb2N1cy12aXNpYmxlOnJpbmctb2Zmc2V0LWJhY2tncm91bmQgZGlzYWJsZWQ6cG9pbnRlci1ldmVudHMtbm9uZSBkaXNhYmxlZDpvcGFjaXR5LTUwJyxcbiAge1xuICAgIHZhcmlhbnRzOiB7XG4gICAgICB2YXJpYW50OiB7XG4gICAgICAgIGRlZmF1bHQ6ICdiZy1wcmltYXJ5IHRleHQtcHJpbWFyeS1mb3JlZ3JvdW5kIGhvdmVyOmJnLXByaW1hcnkvOTAnLFxuICAgICAgICBzZWNvbmRhcnk6ICdiZy1zZWNvbmRhcnkgdGV4dC1zZWNvbmRhcnktZm9yZWdyb3VuZCBob3ZlcjpiZy1zZWNvbmRhcnkvODAnLFxuICAgICAgICBnaG9zdDogJ3RleHQtZm9yZWdyb3VuZCBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCcsXG4gICAgICB9LFxuICAgICAgc2l6ZToge1xuICAgICAgICBzbTogJ2gtNyBweC0yIHRleHQteHMnLFxuICAgICAgICBkZWZhdWx0OiAnc2l6ZS04IHRleHQtc20nLFxuICAgICAgICBsZzogJ2gtMTAgcHgtNCB0ZXh0LXNtJyxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBkZWZhdWx0VmFyaWFudHM6IHtcbiAgICAgIHZhcmlhbnQ6ICdkZWZhdWx0JyxcbiAgICAgIHNpemU6ICdkZWZhdWx0JyxcbiAgICB9LFxuICB9XG4pO1xuXG5leHBvcnQgdHlwZSBQcm9tcHRJbnB1dFN1Ym1pdFByb3BzID0gVmFyaWFudFByb3BzPHR5cGVvZiBwcm9tcHRJbnB1dFN1Ym1pdFZhcmlhbnRzPjtcblxuLyoqXG4gKiBTZW5kIGJ1dHRvbiBmb3IgYSBgdG9sbGUtcHJvbXB0LWlucHV0YC4gVHVybnMgaW50byBhIHN0b3AgYnV0dG9uIHdoaWxlIHRoZVxuICogY29tcG9zZXIncyBzdGF0dXMgaXMgJ3N0cmVhbWluZycsIHNvIG9uZSBjb250cm9sIGNvdmVycyBib3RoIGRpcmVjdGlvbnMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLXByb21wdC1pbnB1dC1zdWJtaXQnLFxuICBzdHlsZXM6IFsnOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfSddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGJ1dHRvblxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBkYXRhLXByb21wdC1pbnB1dC1zdWJtaXRcbiAgICAgIFthdHRyLmRhdGEtc3RhdGVdPVwic3RhdHVzXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiY3VycmVudExhYmVsXCJcbiAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcbiAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCJcbiAgICAgIChjbGljayk9XCJvbkNsaWNrKClcIlxuICAgID5cbiAgICAgIDxpIFtjbGFzc109XCJjdXJyZW50SWNvblwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuICpuZ0lmPVwic2hvd0xhYmVsXCI+e3sgY3VycmVudExhYmVsIH19PC9zcGFuPlxuICAgIDwvYnV0dG9uPlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBQcm9tcHRJbnB1dFN1Ym1pdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogVmlzdWFsIHN0eWxlIG9mIHRoZSBidXR0b24uIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSB2YXJpYW50OiBQcm9tcHRJbnB1dFN1Ym1pdFByb3BzWyd2YXJpYW50J10gPSAnZGVmYXVsdCc7XG4gIC8qKiBTaXplIG9mIHRoZSBidXR0b24uIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSBzaXplOiBQcm9tcHRJbnB1dFN1Ym1pdFByb3BzWydzaXplJ10gPSAnZGVmYXVsdCc7XG4gIC8qKiBBY2Nlc3NpYmxlIG5hbWUgd2hpbGUgdGhlIGNvbXBvc2VyIGlzIGlkbGUuIEBkZWZhdWx0ICdTZW5kIG1lc3NhZ2UnICovXG4gIEBJbnB1dCgpIHN1Ym1pdExhYmVsID0gJ1NlbmQgbWVzc2FnZSc7XG4gIC8qKiBBY2Nlc3NpYmxlIG5hbWUgd2hpbGUgdGhlIGNvbXBvc2VyIGlzIHN0cmVhbWluZy4gQGRlZmF1bHQgJ1N0b3AgZ2VuZXJhdGluZycgKi9cbiAgQElucHV0KCkgc3RvcExhYmVsID0gJ1N0b3AgZ2VuZXJhdGluZyc7XG4gIC8qKiBSZW5kZXJzIHRoZSBsYWJlbCBuZXh0IHRvIHRoZSBpY29uLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzaG93TGFiZWwgPSBmYWxzZTtcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIGJ1dHRvbiB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VydmljZSA9IGluamVjdChQcm9tcHRJbnB1dFNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBzdGF0dXM6IFByb21wdElucHV0U3RhdHVzID0gJ3JlYWR5JztcbiAgY2FuU3VibWl0ID0gZmFsc2U7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZChcbiAgICAgIHRoaXMuc2VydmljZS5zdGF0dXMkLnN1YnNjcmliZSgoc3RhdHVzKSA9PiB7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gc3RhdHVzO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuYWRkKFxuICAgICAgdGhpcy5zZXJ2aWNlLmNhblN1Ym1pdCQuc3Vic2NyaWJlKChjYW5TdWJtaXQpID0+IHtcbiAgICAgICAgdGhpcy5jYW5TdWJtaXQgPSBjYW5TdWJtaXQ7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKiogVHJ1ZSB3aGlsZSB0aGUgYnV0dG9uIGlzIHNob3dpbmcgaXRzIHN0b3AgYWZmb3JkYW5jZS4gKi9cbiAgZ2V0IGlzU3RyZWFtaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0YXR1cyA9PT0gJ3N0cmVhbWluZyc7XG4gIH1cblxuICBnZXQgY3VycmVudEljb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5pc1N0cmVhbWluZyA/ICdyaS1zdG9wLWNpcmNsZS1saW5lJyA6ICdyaS1zZW5kLXBsYW5lLTItZmlsbCc7XG4gIH1cblxuICBnZXQgY3VycmVudExhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaXNTdHJlYW1pbmcgPyB0aGlzLnN0b3BMYWJlbCA6IHRoaXMuc3VibWl0TGFiZWw7XG4gIH1cblxuICAvKiogU3RvcHBpbmcgc3RheXMgYXZhaWxhYmxlIHdpdGggYW4gZW1wdHkgY29tcG9zZXI7IHNlbmRpbmcgZG9lcyBub3QuICovXG4gIGdldCBpc0Rpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5pc1N0cmVhbWluZyAmJiAhdGhpcy5jYW5TdWJtaXQ7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oXG4gICAgICBwcm9tcHRJbnB1dFN1Ym1pdFZhcmlhbnRzKHsgdmFyaWFudDogdGhpcy52YXJpYW50LCBzaXplOiB0aGlzLnNpemUgfSksXG4gICAgICB0aGlzLmlzU3RyZWFtaW5nICYmICdiZy1kZXN0cnVjdGl2ZSB0ZXh0LWRlc3RydWN0aXZlLWZvcmVncm91bmQgaG92ZXI6YmctZGVzdHJ1Y3RpdmUvOTAnLFxuICAgICAgdGhpcy5jbGFzc1xuICAgICk7XG4gIH1cblxuICBvbkNsaWNrKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzU3RyZWFtaW5nKSB7XG4gICAgICB0aGlzLnNlcnZpY2UucmVxdWVzdFN0b3AoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZXJ2aWNlLnJlcXVlc3RTdWJtaXQoKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==