@copilotkitnext/angular 0.0.9-alpha.2 → 0.0.10

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 (210) hide show
  1. package/dist/esm2022/index.mjs +2 -70
  2. package/dist/esm2022/lib/agent.mjs +73 -0
  3. package/dist/esm2022/lib/chat-config.mjs +35 -0
  4. package/dist/esm2022/lib/chat-state.mjs +18 -0
  5. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-buttons.mjs +344 -0
  6. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-renderer.mjs +260 -0
  7. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message-toolbar.mjs +22 -0
  8. package/dist/esm2022/{components/chat/copilot-chat-assistant-message.component.mjs → lib/components/chat/copilot-chat-assistant-message.mjs} +216 -240
  9. package/dist/esm2022/lib/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  10. package/dist/esm2022/lib/components/chat/copilot-chat-audio-recorder.mjs +196 -0
  11. package/dist/esm2022/lib/components/chat/copilot-chat-buttons.mjs +299 -0
  12. package/dist/esm2022/lib/components/chat/copilot-chat-input-defaults.mjs +39 -0
  13. package/dist/esm2022/lib/components/chat/copilot-chat-input.mjs +634 -0
  14. package/dist/esm2022/lib/components/chat/copilot-chat-input.types.mjs +10 -0
  15. package/dist/esm2022/lib/components/chat/copilot-chat-message-view-cursor.mjs +27 -0
  16. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.mjs +268 -0
  17. package/dist/esm2022/lib/components/chat/copilot-chat-message-view.types.mjs +2 -0
  18. package/dist/esm2022/lib/components/chat/copilot-chat-textarea.mjs +139 -0
  19. package/dist/esm2022/lib/components/chat/copilot-chat-tool-calls-view.mjs +36 -0
  20. package/dist/esm2022/lib/components/chat/copilot-chat-toolbar.mjs +20 -0
  21. package/dist/esm2022/lib/components/chat/copilot-chat-tools-menu.mjs +203 -0
  22. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-branch-navigation.mjs +118 -0
  23. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-buttons.mjs +182 -0
  24. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-renderer.mjs +28 -0
  25. package/dist/esm2022/lib/components/chat/copilot-chat-user-message-toolbar.mjs +25 -0
  26. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.mjs +306 -0
  27. package/dist/esm2022/lib/components/chat/copilot-chat-user-message.types.mjs +2 -0
  28. package/dist/esm2022/lib/components/chat/copilot-chat-view-disclaimer.mjs +48 -0
  29. package/dist/esm2022/lib/components/chat/copilot-chat-view-feather.mjs +41 -0
  30. package/dist/esm2022/lib/components/chat/copilot-chat-view-handlers.mjs +19 -0
  31. package/dist/esm2022/lib/components/chat/copilot-chat-view-input-container.mjs +96 -0
  32. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-to-bottom-button.mjs +89 -0
  33. package/dist/esm2022/lib/components/chat/copilot-chat-view-scroll-view.mjs +456 -0
  34. package/dist/esm2022/lib/components/chat/copilot-chat-view.mjs +404 -0
  35. package/dist/esm2022/lib/components/chat/copilot-chat-view.types.mjs +2 -0
  36. package/dist/esm2022/lib/components/chat/copilot-chat.mjs +167 -0
  37. package/dist/esm2022/lib/config.mjs +9 -0
  38. package/dist/esm2022/lib/copilotkit.mjs +124 -0
  39. package/dist/esm2022/lib/directives/copilotkit-agent-context.mjs +130 -0
  40. package/dist/esm2022/lib/directives/stick-to-bottom.mjs +170 -0
  41. package/dist/esm2022/lib/directives/tooltip.mjs +217 -0
  42. package/dist/esm2022/lib/human-in-the-loop.mjs +19 -0
  43. package/dist/esm2022/lib/render-tool-calls.mjs +131 -0
  44. package/dist/esm2022/lib/resize-observer.mjs +152 -0
  45. package/dist/esm2022/lib/scroll-position.mjs +124 -0
  46. package/dist/esm2022/lib/slots/copilot-slot.mjs +156 -0
  47. package/dist/esm2022/lib/slots/index.mjs +4 -0
  48. package/dist/esm2022/lib/slots/slot.types.mjs +3 -3
  49. package/dist/esm2022/lib/slots/slot.utils.mjs +19 -15
  50. package/dist/esm2022/lib/tools.mjs +31 -0
  51. package/dist/esm2022/lib/utils.mjs +3 -3
  52. package/dist/esm2022/public-api.mjs +47 -0
  53. package/dist/fesm2022/copilotkitnext-angular.mjs +5249 -8271
  54. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  55. package/dist/index.d.ts +1 -55
  56. package/dist/lib/agent.d.ts +53 -0
  57. package/dist/{core/chat-configuration/chat-configuration.types.d.ts → lib/chat-config.d.ts} +4 -8
  58. package/dist/lib/chat-state.d.ts +10 -0
  59. package/dist/lib/components/chat/copilot-chat-assistant-message-buttons.d.ts +68 -0
  60. package/dist/lib/components/chat/copilot-chat-assistant-message-renderer.d.ts +26 -0
  61. package/dist/lib/components/chat/copilot-chat-assistant-message-toolbar.d.ts +7 -0
  62. package/dist/lib/components/chat/copilot-chat-assistant-message.d.ts +178 -0
  63. package/dist/{components → lib/components}/chat/copilot-chat-assistant-message.types.d.ts +1 -1
  64. package/dist/{components/chat/copilot-chat-audio-recorder.component.d.ts → lib/components/chat/copilot-chat-audio-recorder.d.ts} +10 -10
  65. package/dist/lib/components/chat/copilot-chat-buttons.d.ts +65 -0
  66. package/dist/lib/components/chat/copilot-chat-input-defaults.d.ts +38 -0
  67. package/dist/lib/components/chat/copilot-chat-input.d.ts +133 -0
  68. package/dist/{components → lib/components}/chat/copilot-chat-input.types.d.ts +11 -11
  69. package/dist/lib/components/chat/copilot-chat-message-view-cursor.d.ts +11 -0
  70. package/dist/{components/chat/copilot-chat-message-view.component.d.ts → lib/components/chat/copilot-chat-message-view.d.ts} +68 -36
  71. package/dist/{components → lib/components}/chat/copilot-chat-message-view.types.d.ts +2 -2
  72. package/dist/lib/components/chat/copilot-chat-textarea.d.ts +41 -0
  73. package/dist/lib/components/chat/copilot-chat-tool-calls-view.d.ts +55 -0
  74. package/dist/lib/components/chat/copilot-chat-toolbar.d.ts +7 -0
  75. package/dist/lib/components/chat/copilot-chat-tools-menu.d.ts +20 -0
  76. package/dist/lib/components/chat/copilot-chat-user-message-branch-navigation.d.ts +20 -0
  77. package/dist/lib/components/chat/copilot-chat-user-message-buttons.d.ts +35 -0
  78. package/dist/lib/components/chat/copilot-chat-user-message-renderer.d.ts +8 -0
  79. package/dist/lib/components/chat/copilot-chat-user-message-toolbar.d.ts +7 -0
  80. package/dist/lib/components/chat/copilot-chat-user-message.d.ts +55 -0
  81. package/dist/{components → lib/components}/chat/copilot-chat-user-message.types.d.ts +2 -2
  82. package/dist/lib/components/chat/copilot-chat-view-disclaimer.d.ts +15 -0
  83. package/dist/{components/chat/copilot-chat-view-feather.component.d.ts → lib/components/chat/copilot-chat-view-feather.d.ts} +6 -6
  84. package/dist/{components/chat/copilot-chat-view-handlers.service.d.ts → lib/components/chat/copilot-chat-view-handlers.d.ts} +3 -3
  85. package/dist/lib/components/chat/copilot-chat-view-input-container.d.ts +23 -0
  86. package/dist/lib/components/chat/copilot-chat-view-scroll-to-bottom-button.d.ts +16 -0
  87. package/dist/lib/components/chat/copilot-chat-view-scroll-view.d.ts +114 -0
  88. package/dist/lib/components/chat/copilot-chat-view.d.ts +239 -0
  89. package/dist/{components → lib/components}/chat/copilot-chat-view.types.d.ts +2 -2
  90. package/dist/lib/components/chat/copilot-chat.d.ts +67 -0
  91. package/dist/lib/config.d.ts +16 -0
  92. package/dist/lib/copilotkit.d.ts +29 -0
  93. package/dist/{directives/copilotkit-agent-context.directive.d.ts → lib/directives/copilotkit-agent-context.d.ts} +5 -5
  94. package/dist/lib/directives/stick-to-bottom.d.ts +62 -0
  95. package/dist/lib/directives/tooltip.d.ts +33 -0
  96. package/dist/lib/human-in-the-loop.d.ts +13 -0
  97. package/dist/lib/render-tool-calls.d.ts +75 -0
  98. package/dist/{services/resize-observer.service.d.ts → lib/resize-observer.d.ts} +2 -2
  99. package/dist/{services/scroll-position.service.d.ts → lib/scroll-position.d.ts} +6 -6
  100. package/dist/lib/slots/copilot-slot.d.ts +34 -0
  101. package/dist/lib/slots/index.d.ts +3 -0
  102. package/dist/lib/slots/slot.types.d.ts +1 -1
  103. package/dist/lib/slots/slot.utils.d.ts +6 -4
  104. package/dist/lib/tools.d.ts +63 -0
  105. package/dist/lib/utils.d.ts +1 -1
  106. package/dist/public-api.d.ts +46 -0
  107. package/dist/styles.css +0 -69
  108. package/package.json +3 -3
  109. package/dist/components/chat/copilot-chat-assistant-message-buttons.component.d.ts +0 -75
  110. package/dist/components/chat/copilot-chat-assistant-message-renderer.component.d.ts +0 -31
  111. package/dist/components/chat/copilot-chat-assistant-message-toolbar.component.d.ts +0 -8
  112. package/dist/components/chat/copilot-chat-assistant-message.component.d.ts +0 -132
  113. package/dist/components/chat/copilot-chat-buttons.component.d.ts +0 -66
  114. package/dist/components/chat/copilot-chat-input-defaults.d.ts +0 -37
  115. package/dist/components/chat/copilot-chat-input.component.d.ts +0 -133
  116. package/dist/components/chat/copilot-chat-message-view-cursor.component.d.ts +0 -15
  117. package/dist/components/chat/copilot-chat-textarea.component.d.ts +0 -45
  118. package/dist/components/chat/copilot-chat-tool-calls-view.component.d.ts +0 -35
  119. package/dist/components/chat/copilot-chat-toolbar.component.d.ts +0 -8
  120. package/dist/components/chat/copilot-chat-tools-menu.component.d.ts +0 -20
  121. package/dist/components/chat/copilot-chat-user-message-branch-navigation.component.d.ts +0 -23
  122. package/dist/components/chat/copilot-chat-user-message-buttons.component.d.ts +0 -39
  123. package/dist/components/chat/copilot-chat-user-message-renderer.component.d.ts +0 -9
  124. package/dist/components/chat/copilot-chat-user-message-toolbar.component.d.ts +0 -8
  125. package/dist/components/chat/copilot-chat-user-message.component.d.ts +0 -55
  126. package/dist/components/chat/copilot-chat-view-disclaimer.component.d.ts +0 -15
  127. package/dist/components/chat/copilot-chat-view-input-container.component.d.ts +0 -23
  128. package/dist/components/chat/copilot-chat-view-scroll-to-bottom-button.component.d.ts +0 -17
  129. package/dist/components/chat/copilot-chat-view-scroll-view.component.d.ts +0 -84
  130. package/dist/components/chat/copilot-chat-view.component.d.ts +0 -205
  131. package/dist/components/chat/copilot-chat.component.d.ts +0 -36
  132. package/dist/components/copilotkit-tool-render.component.d.ts +0 -25
  133. package/dist/core/chat-configuration/chat-configuration.providers.d.ts +0 -54
  134. package/dist/core/chat-configuration/chat-configuration.service.d.ts +0 -75
  135. package/dist/core/copilotkit.providers.d.ts +0 -13
  136. package/dist/core/copilotkit.service.d.ts +0 -119
  137. package/dist/core/copilotkit.types.d.ts +0 -81
  138. package/dist/directives/copilotkit-agent.directive.d.ts +0 -106
  139. package/dist/directives/copilotkit-chat-config.directive.d.ts +0 -84
  140. package/dist/directives/copilotkit-config.directive.d.ts +0 -44
  141. package/dist/directives/copilotkit-frontend-tool.directive.d.ts +0 -25
  142. package/dist/directives/copilotkit-human-in-the-loop.directive.d.ts +0 -124
  143. package/dist/directives/stick-to-bottom.directive.d.ts +0 -62
  144. package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +0 -384
  145. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +0 -286
  146. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +0 -27
  147. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +0 -2
  148. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +0 -202
  149. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +0 -321
  150. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +0 -38
  151. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +0 -666
  152. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +0 -10
  153. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +0 -45
  154. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +0 -296
  155. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +0 -2
  156. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +0 -188
  157. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +0 -222
  158. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +0 -25
  159. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +0 -199
  160. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +0 -137
  161. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +0 -207
  162. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +0 -35
  163. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +0 -34
  164. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +0 -341
  165. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +0 -2
  166. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +0 -52
  167. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +0 -55
  168. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +0 -19
  169. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +0 -110
  170. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +0 -93
  171. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +0 -443
  172. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +0 -479
  173. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +0 -2
  174. package/dist/esm2022/components/chat/copilot-chat.component.mjs +0 -220
  175. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +0 -150
  176. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +0 -65
  177. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +0 -145
  178. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +0 -26
  179. package/dist/esm2022/core/copilotkit.providers.mjs +0 -34
  180. package/dist/esm2022/core/copilotkit.service.mjs +0 -411
  181. package/dist/esm2022/core/copilotkit.types.mjs +0 -13
  182. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +0 -130
  183. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +0 -221
  184. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +0 -218
  185. package/dist/esm2022/directives/copilotkit-config.directive.mjs +0 -94
  186. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +0 -128
  187. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +0 -265
  188. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +0 -181
  189. package/dist/esm2022/lib/directives/tooltip.directive.mjs +0 -211
  190. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +0 -154
  191. package/dist/esm2022/services/resize-observer.service.mjs +0 -152
  192. package/dist/esm2022/services/scroll-position.service.mjs +0 -124
  193. package/dist/esm2022/types/frontend-tool.mjs +0 -2
  194. package/dist/esm2022/types/human-in-the-loop.mjs +0 -2
  195. package/dist/esm2022/utils/agent-context.utils.mjs +0 -114
  196. package/dist/esm2022/utils/agent.utils.mjs +0 -212
  197. package/dist/esm2022/utils/chat-config.utils.mjs +0 -186
  198. package/dist/esm2022/utils/copilotkit.utils.mjs +0 -20
  199. package/dist/esm2022/utils/frontend-tool.utils.mjs +0 -224
  200. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +0 -293
  201. package/dist/lib/directives/tooltip.directive.d.ts +0 -33
  202. package/dist/lib/slots/copilot-slot.component.d.ts +0 -34
  203. package/dist/types/frontend-tool.d.ts +0 -37
  204. package/dist/types/human-in-the-loop.d.ts +0 -44
  205. package/dist/utils/agent-context.utils.d.ts +0 -75
  206. package/dist/utils/agent.utils.d.ts +0 -108
  207. package/dist/utils/chat-config.utils.d.ts +0 -166
  208. package/dist/utils/copilotkit.utils.d.ts +0 -16
  209. package/dist/utils/frontend-tool.utils.d.ts +0 -119
  210. package/dist/utils/human-in-the-loop.utils.d.ts +0 -92
@@ -0,0 +1,89 @@
1
+ import { Component, input, output, ChangeDetectionStrategy, ViewEncapsulation, } from "@angular/core";
2
+ import { CommonModule } from "@angular/common";
3
+ import { LucideAngularModule, ChevronDown } from "lucide-angular";
4
+ import { cn } from "../../utils";
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "lucide-angular";
7
+ /**
8
+ * ScrollToBottomButton component for CopilotChatView
9
+ * Matches React implementation exactly with same Tailwind classes
10
+ */
11
+ export class CopilotChatViewScrollToBottomButton {
12
+ inputClass = input();
13
+ disabled = input(false);
14
+ // Support function-style click handler via slot context
15
+ onClick = input();
16
+ // Simple, idiomatic Angular output
17
+ clicked = output();
18
+ // Icon reference
19
+ ChevronDown = ChevronDown;
20
+ // Computed class matching React exactly
21
+ get computedClass() {
22
+ return cn(
23
+ // Base button styles
24
+ "rounded-full w-10 h-10 p-0",
25
+ // Background colors
26
+ "bg-white dark:bg-gray-900",
27
+ // Border and shadow
28
+ "shadow-lg border border-gray-200 dark:border-gray-700",
29
+ // Hover states
30
+ "hover:bg-gray-50 dark:hover:bg-gray-800",
31
+ // Layout
32
+ "flex items-center justify-center cursor-pointer",
33
+ // Transition
34
+ "transition-colors",
35
+ // Focus states
36
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
37
+ // Custom classes
38
+ this.inputClass());
39
+ }
40
+ handleClick() {
41
+ if (!this.disabled()) {
42
+ // Call input handler if provided (slot-style)
43
+ if (this.onClick()) {
44
+ this.onClick()();
45
+ }
46
+ this.clicked.emit();
47
+ }
48
+ }
49
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatViewScrollToBottomButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
50
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: CopilotChatViewScrollToBottomButton, isStandalone: true, selector: "copilot-chat-view-scroll-to-bottom-button", inputs: { inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, onClick: { classPropertyName: "onClick", publicName: "onClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: `
51
+ <button
52
+ type="button"
53
+ [class]="computedClass"
54
+ [disabled]="disabled()"
55
+ (click)="handleClick()"
56
+ >
57
+ <lucide-angular
58
+ [img]="ChevronDown"
59
+ class="w-4 h-4 text-gray-600 dark:text-white"
60
+ >
61
+ </lucide-angular>
62
+ </button>
63
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatViewScrollToBottomButton, decorators: [{
66
+ type: Component,
67
+ args: [{
68
+ standalone: true,
69
+ selector: "copilot-chat-view-scroll-to-bottom-button",
70
+ imports: [CommonModule, LucideAngularModule],
71
+ changeDetection: ChangeDetectionStrategy.OnPush,
72
+ encapsulation: ViewEncapsulation.None,
73
+ template: `
74
+ <button
75
+ type="button"
76
+ [class]="computedClass"
77
+ [disabled]="disabled()"
78
+ (click)="handleClick()"
79
+ >
80
+ <lucide-angular
81
+ [img]="ChevronDown"
82
+ class="w-4 h-4 text-gray-600 dark:text-white"
83
+ >
84
+ </lucide-angular>
85
+ </button>
86
+ `,
87
+ }]
88
+ }] });
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LXZpZXctc2Nyb2xsLXRvLWJvdHRvbS1idXR0b24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvY2hhdC9jb3BpbG90LWNoYXQtdmlldy1zY3JvbGwtdG8tYm90dG9tLWJ1dHRvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sdUJBQXVCLEVBQ3ZCLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxhQUFhLENBQUM7OztBQUVqQzs7O0dBR0c7QUFzQkgsTUFBTSxPQUFPLG1DQUFtQztJQUM5QyxVQUFVLEdBQUcsS0FBSyxFQUFzQixDQUFDO0lBQ3pDLFFBQVEsR0FBRyxLQUFLLENBQVUsS0FBSyxDQUFDLENBQUM7SUFDakMsd0RBQXdEO0lBQ3hELE9BQU8sR0FBRyxLQUFLLEVBQTRCLENBQUM7SUFFNUMsbUNBQW1DO0lBQ25DLE9BQU8sR0FBRyxNQUFNLEVBQVEsQ0FBQztJQUV6QixpQkFBaUI7SUFDRSxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBRTdDLHdDQUF3QztJQUN4QyxJQUFJLGFBQWE7UUFDZixPQUFPLEVBQUU7UUFDUCxxQkFBcUI7UUFDckIsNEJBQTRCO1FBQzVCLG9CQUFvQjtRQUNwQiwyQkFBMkI7UUFDM0Isb0JBQW9CO1FBQ3BCLHVEQUF1RDtRQUN2RCxlQUFlO1FBQ2YseUNBQXlDO1FBQ3pDLFNBQVM7UUFDVCxpREFBaUQ7UUFDakQsYUFBYTtRQUNiLG1CQUFtQjtRQUNuQixlQUFlO1FBQ2YscUVBQXFFO1FBQ3JFLGlCQUFpQjtRQUNqQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQ2xCLENBQUM7SUFDSixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNyQiw4Q0FBOEM7WUFDOUMsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE9BQU8sRUFBRyxFQUFFLENBQUM7WUFDcEIsQ0FBQztZQUNELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsQ0FBQztJQUNILENBQUM7d0dBMUNVLG1DQUFtQzs0RkFBbkMsbUNBQW1DLHdoQkFmcEM7Ozs7Ozs7Ozs7Ozs7R0FhVCwyREFoQlMsWUFBWSw4QkFBRSxtQkFBbUI7OzRGQWtCaEMsbUNBQW1DO2tCQXJCL0MsU0FBUzttQkFBQztvQkFDVCxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsUUFBUSxFQUFFLDJDQUEyQztvQkFDckQsT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLG1CQUFtQixDQUFDO29CQUM1QyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7b0JBQ3JDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7OztHQWFUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBpbnB1dCxcbiAgb3V0cHV0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBMdWNpZGVBbmd1bGFyTW9kdWxlLCBDaGV2cm9uRG93biB9IGZyb20gXCJsdWNpZGUtYW5ndWxhclwiO1xuaW1wb3J0IHsgY24gfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcblxuLyoqXG4gKiBTY3JvbGxUb0JvdHRvbUJ1dHRvbiBjb21wb25lbnQgZm9yIENvcGlsb3RDaGF0Vmlld1xuICogTWF0Y2hlcyBSZWFjdCBpbXBsZW1lbnRhdGlvbiBleGFjdGx5IHdpdGggc2FtZSBUYWlsd2luZCBjbGFzc2VzXG4gKi9cbkBDb21wb25lbnQoe1xuICBzdGFuZGFsb25lOiB0cnVlLFxuICBzZWxlY3RvcjogXCJjb3BpbG90LWNoYXQtdmlldy1zY3JvbGwtdG8tYm90dG9tLWJ1dHRvblwiLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBMdWNpZGVBbmd1bGFyTW9kdWxlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGJ1dHRvblxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQoKVwiXG4gICAgICAoY2xpY2spPVwiaGFuZGxlQ2xpY2soKVwiXG4gICAgPlxuICAgICAgPGx1Y2lkZS1hbmd1bGFyXG4gICAgICAgIFtpbWddPVwiQ2hldnJvbkRvd25cIlxuICAgICAgICBjbGFzcz1cInctNCBoLTQgdGV4dC1ncmF5LTYwMCBkYXJrOnRleHQtd2hpdGVcIlxuICAgICAgPlxuICAgICAgPC9sdWNpZGUtYW5ndWxhcj5cbiAgICA8L2J1dHRvbj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgQ29waWxvdENoYXRWaWV3U2Nyb2xsVG9Cb3R0b21CdXR0b24ge1xuICBpbnB1dENsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICBkaXNhYmxlZCA9IGlucHV0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLy8gU3VwcG9ydCBmdW5jdGlvbi1zdHlsZSBjbGljayBoYW5kbGVyIHZpYSBzbG90IGNvbnRleHRcbiAgb25DbGljayA9IGlucHV0PCgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZD4oKTtcblxuICAvLyBTaW1wbGUsIGlkaW9tYXRpYyBBbmd1bGFyIG91dHB1dFxuICBjbGlja2VkID0gb3V0cHV0PHZvaWQ+KCk7XG5cbiAgLy8gSWNvbiByZWZlcmVuY2VcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IENoZXZyb25Eb3duID0gQ2hldnJvbkRvd247XG5cbiAgLy8gQ29tcHV0ZWQgY2xhc3MgbWF0Y2hpbmcgUmVhY3QgZXhhY3RseVxuICBnZXQgY29tcHV0ZWRDbGFzcygpOiBzdHJpbmcge1xuICAgIHJldHVybiBjbihcbiAgICAgIC8vIEJhc2UgYnV0dG9uIHN0eWxlc1xuICAgICAgXCJyb3VuZGVkLWZ1bGwgdy0xMCBoLTEwIHAtMFwiLFxuICAgICAgLy8gQmFja2dyb3VuZCBjb2xvcnNcbiAgICAgIFwiYmctd2hpdGUgZGFyazpiZy1ncmF5LTkwMFwiLFxuICAgICAgLy8gQm9yZGVyIGFuZCBzaGFkb3dcbiAgICAgIFwic2hhZG93LWxnIGJvcmRlciBib3JkZXItZ3JheS0yMDAgZGFyazpib3JkZXItZ3JheS03MDBcIixcbiAgICAgIC8vIEhvdmVyIHN0YXRlc1xuICAgICAgXCJob3ZlcjpiZy1ncmF5LTUwIGRhcms6aG92ZXI6YmctZ3JheS04MDBcIixcbiAgICAgIC8vIExheW91dFxuICAgICAgXCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBjdXJzb3ItcG9pbnRlclwiLFxuICAgICAgLy8gVHJhbnNpdGlvblxuICAgICAgXCJ0cmFuc2l0aW9uLWNvbG9yc1wiLFxuICAgICAgLy8gRm9jdXMgc3RhdGVzXG4gICAgICBcImZvY3VzOm91dGxpbmUtbm9uZSBmb2N1cy12aXNpYmxlOnJpbmctMiBmb2N1cy12aXNpYmxlOnJpbmctb2Zmc2V0LTJcIixcbiAgICAgIC8vIEN1c3RvbSBjbGFzc2VzXG4gICAgICB0aGlzLmlucHV0Q2xhc3MoKVxuICAgICk7XG4gIH1cblxuICBoYW5kbGVDbGljaygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQoKSkge1xuICAgICAgLy8gQ2FsbCBpbnB1dCBoYW5kbGVyIGlmIHByb3ZpZGVkIChzbG90LXN0eWxlKVxuICAgICAgaWYgKHRoaXMub25DbGljaygpKSB7XG4gICAgICAgIHRoaXMub25DbGljaygpISgpO1xuICAgICAgfVxuICAgICAgdGhpcy5jbGlja2VkLmVtaXQoKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,456 @@
1
+ import { Component, input, output, ViewChild, ElementRef, ChangeDetectionStrategy, ViewEncapsulation, signal, computed, inject, PLATFORM_ID, ChangeDetectorRef, } from "@angular/core";
2
+ import { CommonModule, isPlatformBrowser } from "@angular/common";
3
+ import { ScrollingModule } from "@angular/cdk/scrolling";
4
+ import { CopilotSlot } from "../../slots/copilot-slot";
5
+ import { CopilotChatMessageView } from "./copilot-chat-message-view";
6
+ import { CopilotChatViewScrollToBottomButton } from "./copilot-chat-view-scroll-to-bottom-button";
7
+ import { StickToBottom } from "../../directives/stick-to-bottom";
8
+ import { ScrollPosition } from "../../scroll-position";
9
+ import { cn } from "../../utils";
10
+ import { Subject } from "rxjs";
11
+ import { takeUntil } from "rxjs/operators";
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "@angular/cdk/scrolling";
14
+ /**
15
+ * ScrollView component for CopilotChatView
16
+ * Handles auto-scrolling and scroll position management
17
+ */
18
+ export class CopilotChatViewScrollView {
19
+ cdr = inject(ChangeDetectorRef);
20
+ autoScroll = input(true);
21
+ inputContainerHeight = input(0);
22
+ isResizing = input(false);
23
+ inputClass = input();
24
+ messages = input([]);
25
+ messageView = input();
26
+ messageViewClass = input();
27
+ showCursor = input(false);
28
+ // Handler availability flags removed in favor of DI service
29
+ // Slot inputs
30
+ scrollToBottomButton = input();
31
+ scrollToBottomButtonClass = input();
32
+ // Output events (bubbled from message view)
33
+ assistantMessageThumbsUp = output();
34
+ assistantMessageThumbsDown = output();
35
+ assistantMessageReadAloud = output();
36
+ assistantMessageRegenerate = output();
37
+ userMessageCopy = output();
38
+ userMessageEdit = output();
39
+ // ViewChild references
40
+ scrollContainer;
41
+ contentContainer;
42
+ stickToBottomDirective;
43
+ // Default components
44
+ defaultMessageViewComponent = CopilotChatMessageView;
45
+ defaultScrollToBottomButtonComponent = CopilotChatViewScrollToBottomButton;
46
+ // Signals
47
+ hasMounted = signal(false);
48
+ showScrollButton = signal(false);
49
+ isAtBottom = signal(true);
50
+ paddingBottom = computed(() => this.inputContainerHeight() + 32);
51
+ // Computed class
52
+ computedClass = computed(() => cn(this.inputClass()));
53
+ destroy$ = new Subject();
54
+ platformId = inject(PLATFORM_ID);
55
+ scrollPositionService = inject(ScrollPosition);
56
+ // No mirroring of inputs; derive directly via computed()
57
+ ngOnInit() {
58
+ // Check if we're in the browser
59
+ if (isPlatformBrowser(this.platformId)) {
60
+ // Set mounted after a tick to allow for hydration
61
+ setTimeout(() => {
62
+ this.hasMounted.set(true);
63
+ }, 0);
64
+ }
65
+ }
66
+ ngAfterViewInit() {
67
+ if (!this.autoScroll()) {
68
+ // Wait for the view to be fully rendered after hasMounted is set
69
+ setTimeout(() => {
70
+ if (this.scrollContainer) {
71
+ // Check initial scroll position
72
+ const initialState = this.scrollPositionService.getScrollState(this.scrollContainer.nativeElement, 10);
73
+ this.showScrollButton.set(!initialState.isAtBottom);
74
+ // Monitor scroll position for manual mode
75
+ this.scrollPositionService
76
+ .monitorScrollPosition(this.scrollContainer, 10)
77
+ .pipe(takeUntil(this.destroy$))
78
+ .subscribe((state) => {
79
+ this.showScrollButton.set(!state.isAtBottom);
80
+ });
81
+ }
82
+ }, 100);
83
+ }
84
+ }
85
+ /**
86
+ * Handle isAtBottom change from StickToBottom directive
87
+ */
88
+ onIsAtBottomChange(isAtBottom) {
89
+ this.isAtBottom.set(isAtBottom);
90
+ }
91
+ /**
92
+ * Scroll to bottom for manual mode
93
+ */
94
+ scrollToBottom() {
95
+ if (this.scrollContainer) {
96
+ this.scrollPositionService.scrollToBottom(this.scrollContainer, true);
97
+ }
98
+ }
99
+ /**
100
+ * Scroll to bottom for stick-to-bottom mode
101
+ */
102
+ scrollToBottomFromStick() {
103
+ if (this.stickToBottomDirective) {
104
+ this.stickToBottomDirective.scrollToBottom("smooth");
105
+ }
106
+ }
107
+ ngOnDestroy() {
108
+ this.destroy$.next();
109
+ this.destroy$.complete();
110
+ }
111
+ // Output maps for slots
112
+ scrollToBottomOutputs = { clicked: () => this.scrollToBottom() };
113
+ scrollToBottomFromStickOutputs = {
114
+ clicked: () => this.scrollToBottomFromStick(),
115
+ };
116
+ // Context methods for templates
117
+ messageViewContext() {
118
+ return {
119
+ messages: this.messages(),
120
+ inputClass: this.messageViewClass(),
121
+ showCursor: this.showCursor(),
122
+ };
123
+ }
124
+ scrollToBottomContext() {
125
+ return {
126
+ inputClass: this.scrollToBottomButtonClass(),
127
+ onClick: () => this.scrollToBottom(),
128
+ };
129
+ }
130
+ scrollToBottomFromStickContext() {
131
+ return {
132
+ inputClass: this.scrollToBottomButtonClass(),
133
+ onClick: () => this.scrollToBottomFromStick(),
134
+ };
135
+ }
136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatViewScrollView, deps: [], target: i0.ɵɵFactoryTarget.Component });
137
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CopilotChatViewScrollView, isStandalone: true, selector: "copilot-chat-view-scroll-view", inputs: { autoScroll: { classPropertyName: "autoScroll", publicName: "autoScroll", isSignal: true, isRequired: false, transformFunction: null }, inputContainerHeight: { classPropertyName: "inputContainerHeight", publicName: "inputContainerHeight", isSignal: true, isRequired: false, transformFunction: null }, isResizing: { classPropertyName: "isResizing", publicName: "isResizing", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null }, messageView: { classPropertyName: "messageView", publicName: "messageView", isSignal: true, isRequired: false, transformFunction: null }, messageViewClass: { classPropertyName: "messageViewClass", publicName: "messageViewClass", isSignal: true, isRequired: false, transformFunction: null }, showCursor: { classPropertyName: "showCursor", publicName: "showCursor", isSignal: true, isRequired: false, transformFunction: null }, scrollToBottomButton: { classPropertyName: "scrollToBottomButton", publicName: "scrollToBottomButton", isSignal: true, isRequired: false, transformFunction: null }, scrollToBottomButtonClass: { classPropertyName: "scrollToBottomButtonClass", publicName: "scrollToBottomButtonClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { assistantMessageThumbsUp: "assistantMessageThumbsUp", assistantMessageThumbsDown: "assistantMessageThumbsDown", assistantMessageReadAloud: "assistantMessageReadAloud", assistantMessageRegenerate: "assistantMessageRegenerate", userMessageCopy: "userMessageCopy", userMessageEdit: "userMessageEdit" }, providers: [ScrollPosition], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, read: ElementRef }, { propertyName: "contentContainer", first: true, predicate: ["contentContainer"], descendants: true, read: ElementRef }, { propertyName: "stickToBottomDirective", first: true, predicate: StickToBottom, descendants: true }], ngImport: i0, template: `
138
+ @if (!hasMounted()) {
139
+ <!-- SSR/Initial render without stick-to-bottom -->
140
+ <div
141
+ class="h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden"
142
+ >
143
+ <div class="px-4 sm:px-0">
144
+ <ng-content></ng-content>
145
+ </div>
146
+ </div>
147
+ } @else if (!autoScroll()) {
148
+ <!-- Manual scroll mode -->
149
+ <div class="h-full max-h-full flex flex-col min-h-0 relative">
150
+ <div
151
+ #scrollContainer
152
+ cdkScrollable
153
+ [class]="computedClass()"
154
+ class="overflow-y-scroll overflow-x-hidden"
155
+ >
156
+ <div #contentContainer class="px-4 sm:px-0">
157
+ <!-- Content with padding-bottom matching React -->
158
+ <div [style.padding-bottom.px]="paddingBottom()">
159
+ <div class="max-w-3xl mx-auto">
160
+ @if (messageView()) {
161
+ <copilot-slot
162
+ [slot]="messageView()"
163
+ [context]="messageViewContext()"
164
+ [defaultComponent]="defaultMessageViewComponent"
165
+ >
166
+ </copilot-slot>
167
+ } @else {
168
+ <copilot-chat-message-view
169
+ [messages]="messages()"
170
+ [inputClass]="messageViewClass()"
171
+ [showCursor]="showCursor()"
172
+ (assistantMessageThumbsUp)="
173
+ assistantMessageThumbsUp.emit($event)
174
+ "
175
+ (assistantMessageThumbsDown)="
176
+ assistantMessageThumbsDown.emit($event)
177
+ "
178
+ (assistantMessageReadAloud)="
179
+ assistantMessageReadAloud.emit($event)
180
+ "
181
+ (assistantMessageRegenerate)="
182
+ assistantMessageRegenerate.emit($event)
183
+ "
184
+ (userMessageCopy)="userMessageCopy.emit($event)"
185
+ (userMessageEdit)="userMessageEdit.emit($event)"
186
+ >
187
+ </copilot-chat-message-view>
188
+ }
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- Scroll to bottom button for manual mode, OUTSIDE scrollable content -->
195
+ @if (showScrollButton() && !isResizing()) {
196
+ <div
197
+ class="absolute inset-x-0 flex justify-center z-30"
198
+ [style.bottom.px]="inputContainerHeight() + 16"
199
+ >
200
+ <copilot-slot
201
+ [slot]="scrollToBottomButton()"
202
+ [context]="scrollToBottomContext()"
203
+ [defaultComponent]="defaultScrollToBottomButtonComponent"
204
+ [outputs]="scrollToBottomOutputs"
205
+ >
206
+ </copilot-slot>
207
+ </div>
208
+ }
209
+ </div>
210
+ } @else {
211
+ <!-- Auto-scroll mode with StickToBottom directive -->
212
+ <div class="h-full max-h-full flex flex-col min-h-0 relative">
213
+ <div
214
+ #scrollContainer
215
+ cdkScrollable
216
+ copilotStickToBottom
217
+ [enabled]="autoScroll()"
218
+ [threshold]="10"
219
+ [debounceMs]="0"
220
+ [initialBehavior]="'smooth'"
221
+ [resizeBehavior]="'smooth'"
222
+ (isAtBottomChange)="onIsAtBottomChange($event)"
223
+ [class]="computedClass()"
224
+ class="overflow-y-scroll overflow-x-hidden"
225
+ >
226
+ <!-- Scrollable content wrapper -->
227
+ <div class="px-4 sm:px-0">
228
+ <!-- Content with padding-bottom matching React -->
229
+ <div [style.padding-bottom.px]="paddingBottom()">
230
+ <div class="max-w-3xl mx-auto">
231
+ @if (messageView()) {
232
+ <copilot-slot
233
+ [slot]="messageView()"
234
+ [context]="messageViewContext()"
235
+ [defaultComponent]="defaultMessageViewComponent"
236
+ >
237
+ </copilot-slot>
238
+ } @else {
239
+ <copilot-chat-message-view
240
+ [messages]="messages()"
241
+ [inputClass]="messageViewClass()"
242
+ [showCursor]="showCursor()"
243
+ (assistantMessageThumbsUp)="
244
+ assistantMessageThumbsUp.emit($event)
245
+ "
246
+ (assistantMessageThumbsDown)="
247
+ assistantMessageThumbsDown.emit($event)
248
+ "
249
+ (assistantMessageReadAloud)="
250
+ assistantMessageReadAloud.emit($event)
251
+ "
252
+ (assistantMessageRegenerate)="
253
+ assistantMessageRegenerate.emit($event)
254
+ "
255
+ (userMessageCopy)="userMessageCopy.emit($event)"
256
+ (userMessageEdit)="userMessageEdit.emit($event)"
257
+ >
258
+ </copilot-chat-message-view>
259
+ }
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+
265
+ <!-- Scroll to bottom button - hidden during resize, OUTSIDE scrollable content -->
266
+ @if (!isAtBottom() && !isResizing()) {
267
+ <div
268
+ class="absolute inset-x-0 flex justify-center z-30"
269
+ [style.bottom.px]="inputContainerHeight() + 16"
270
+ >
271
+ <copilot-slot
272
+ [slot]="scrollToBottomButton()"
273
+ [context]="scrollToBottomFromStickContext()"
274
+ [defaultComponent]="defaultScrollToBottomButtonComponent"
275
+ [outputs]="scrollToBottomFromStickOutputs"
276
+ >
277
+ </copilot-slot>
278
+ </div>
279
+ }
280
+ </div>
281
+ }
282
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: CopilotSlot, selector: "copilot-slot", inputs: ["slot", "context", "defaultComponent", "outputs"] }, { kind: "component", type: CopilotChatMessageView, selector: "copilot-chat-message-view", inputs: ["messages", "showCursor", "isLoading", "inputClass", "assistantMessageComponent", "assistantMessageTemplate", "assistantMessageClass", "userMessageComponent", "userMessageTemplate", "userMessageClass", "cursorComponent", "cursorTemplate", "cursorClass"], outputs: ["assistantMessageThumbsUp", "assistantMessageThumbsDown", "assistantMessageReadAloud", "assistantMessageRegenerate", "userMessageCopy", "userMessageEdit"] }, { kind: "directive", type: StickToBottom, selector: "[copilotStickToBottom]", inputs: ["enabled", "threshold", "initialBehavior", "resizeBehavior", "debounceMs"], outputs: ["isAtBottomChange", "scrollToBottomRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
283
+ }
284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CopilotChatViewScrollView, decorators: [{
285
+ type: Component,
286
+ args: [{
287
+ standalone: true,
288
+ selector: "copilot-chat-view-scroll-view",
289
+ imports: [
290
+ CommonModule,
291
+ ScrollingModule,
292
+ CopilotSlot,
293
+ CopilotChatMessageView,
294
+ StickToBottom,
295
+ ],
296
+ changeDetection: ChangeDetectionStrategy.OnPush,
297
+ encapsulation: ViewEncapsulation.None,
298
+ providers: [ScrollPosition],
299
+ template: `
300
+ @if (!hasMounted()) {
301
+ <!-- SSR/Initial render without stick-to-bottom -->
302
+ <div
303
+ class="h-full max-h-full flex flex-col min-h-0 overflow-y-scroll overflow-x-hidden"
304
+ >
305
+ <div class="px-4 sm:px-0">
306
+ <ng-content></ng-content>
307
+ </div>
308
+ </div>
309
+ } @else if (!autoScroll()) {
310
+ <!-- Manual scroll mode -->
311
+ <div class="h-full max-h-full flex flex-col min-h-0 relative">
312
+ <div
313
+ #scrollContainer
314
+ cdkScrollable
315
+ [class]="computedClass()"
316
+ class="overflow-y-scroll overflow-x-hidden"
317
+ >
318
+ <div #contentContainer class="px-4 sm:px-0">
319
+ <!-- Content with padding-bottom matching React -->
320
+ <div [style.padding-bottom.px]="paddingBottom()">
321
+ <div class="max-w-3xl mx-auto">
322
+ @if (messageView()) {
323
+ <copilot-slot
324
+ [slot]="messageView()"
325
+ [context]="messageViewContext()"
326
+ [defaultComponent]="defaultMessageViewComponent"
327
+ >
328
+ </copilot-slot>
329
+ } @else {
330
+ <copilot-chat-message-view
331
+ [messages]="messages()"
332
+ [inputClass]="messageViewClass()"
333
+ [showCursor]="showCursor()"
334
+ (assistantMessageThumbsUp)="
335
+ assistantMessageThumbsUp.emit($event)
336
+ "
337
+ (assistantMessageThumbsDown)="
338
+ assistantMessageThumbsDown.emit($event)
339
+ "
340
+ (assistantMessageReadAloud)="
341
+ assistantMessageReadAloud.emit($event)
342
+ "
343
+ (assistantMessageRegenerate)="
344
+ assistantMessageRegenerate.emit($event)
345
+ "
346
+ (userMessageCopy)="userMessageCopy.emit($event)"
347
+ (userMessageEdit)="userMessageEdit.emit($event)"
348
+ >
349
+ </copilot-chat-message-view>
350
+ }
351
+ </div>
352
+ </div>
353
+ </div>
354
+ </div>
355
+
356
+ <!-- Scroll to bottom button for manual mode, OUTSIDE scrollable content -->
357
+ @if (showScrollButton() && !isResizing()) {
358
+ <div
359
+ class="absolute inset-x-0 flex justify-center z-30"
360
+ [style.bottom.px]="inputContainerHeight() + 16"
361
+ >
362
+ <copilot-slot
363
+ [slot]="scrollToBottomButton()"
364
+ [context]="scrollToBottomContext()"
365
+ [defaultComponent]="defaultScrollToBottomButtonComponent"
366
+ [outputs]="scrollToBottomOutputs"
367
+ >
368
+ </copilot-slot>
369
+ </div>
370
+ }
371
+ </div>
372
+ } @else {
373
+ <!-- Auto-scroll mode with StickToBottom directive -->
374
+ <div class="h-full max-h-full flex flex-col min-h-0 relative">
375
+ <div
376
+ #scrollContainer
377
+ cdkScrollable
378
+ copilotStickToBottom
379
+ [enabled]="autoScroll()"
380
+ [threshold]="10"
381
+ [debounceMs]="0"
382
+ [initialBehavior]="'smooth'"
383
+ [resizeBehavior]="'smooth'"
384
+ (isAtBottomChange)="onIsAtBottomChange($event)"
385
+ [class]="computedClass()"
386
+ class="overflow-y-scroll overflow-x-hidden"
387
+ >
388
+ <!-- Scrollable content wrapper -->
389
+ <div class="px-4 sm:px-0">
390
+ <!-- Content with padding-bottom matching React -->
391
+ <div [style.padding-bottom.px]="paddingBottom()">
392
+ <div class="max-w-3xl mx-auto">
393
+ @if (messageView()) {
394
+ <copilot-slot
395
+ [slot]="messageView()"
396
+ [context]="messageViewContext()"
397
+ [defaultComponent]="defaultMessageViewComponent"
398
+ >
399
+ </copilot-slot>
400
+ } @else {
401
+ <copilot-chat-message-view
402
+ [messages]="messages()"
403
+ [inputClass]="messageViewClass()"
404
+ [showCursor]="showCursor()"
405
+ (assistantMessageThumbsUp)="
406
+ assistantMessageThumbsUp.emit($event)
407
+ "
408
+ (assistantMessageThumbsDown)="
409
+ assistantMessageThumbsDown.emit($event)
410
+ "
411
+ (assistantMessageReadAloud)="
412
+ assistantMessageReadAloud.emit($event)
413
+ "
414
+ (assistantMessageRegenerate)="
415
+ assistantMessageRegenerate.emit($event)
416
+ "
417
+ (userMessageCopy)="userMessageCopy.emit($event)"
418
+ (userMessageEdit)="userMessageEdit.emit($event)"
419
+ >
420
+ </copilot-chat-message-view>
421
+ }
422
+ </div>
423
+ </div>
424
+ </div>
425
+ </div>
426
+
427
+ <!-- Scroll to bottom button - hidden during resize, OUTSIDE scrollable content -->
428
+ @if (!isAtBottom() && !isResizing()) {
429
+ <div
430
+ class="absolute inset-x-0 flex justify-center z-30"
431
+ [style.bottom.px]="inputContainerHeight() + 16"
432
+ >
433
+ <copilot-slot
434
+ [slot]="scrollToBottomButton()"
435
+ [context]="scrollToBottomFromStickContext()"
436
+ [defaultComponent]="defaultScrollToBottomButtonComponent"
437
+ [outputs]="scrollToBottomFromStickOutputs"
438
+ >
439
+ </copilot-slot>
440
+ </div>
441
+ }
442
+ </div>
443
+ }
444
+ `,
445
+ }]
446
+ }], propDecorators: { scrollContainer: [{
447
+ type: ViewChild,
448
+ args: ["scrollContainer", { read: ElementRef }]
449
+ }], contentContainer: [{
450
+ type: ViewChild,
451
+ args: ["contentContainer", { read: ElementRef }]
452
+ }], stickToBottomDirective: [{
453
+ type: ViewChild,
454
+ args: [StickToBottom]
455
+ }] } });
456
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29waWxvdC1jaGF0LXZpZXctc2Nyb2xsLXZpZXcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvY2hhdC9jb3BpbG90LWNoYXQtdmlldy1zY3JvbGwtdmlldy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULFVBQVUsRUFDVix1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLE1BQU0sRUFDTixRQUFRLEVBSVIsTUFBTSxFQUNOLFdBQVcsRUFDWCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDckUsT0FBTyxFQUFFLG1DQUFtQyxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDbEcsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFFM0M7OztHQUdHO0FBaUtILE1BQU0sT0FBTyx5QkFBeUI7SUFHNUIsR0FBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRXhDLFVBQVUsR0FBRyxLQUFLLENBQVUsSUFBSSxDQUFDLENB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TTtvQkFDL0MsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7b0JBQ3JDLFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztvQkFDM0IsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUpUO2lCQUNGOzhCQWlDQyxlQUFlO3NCQURkLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO2dCQUdsRCxnQkFBZ0I7c0JBRGYsU0FBUzt1QkFBQyxrQkFBa0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBRXpCLHNCQUFzQjtzQkFBL0MsU0FBUzt1QkFBQyxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBpbnB1dCxcbiAgb3V0cHV0LFxuICBWaWV3Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgc2lnbmFsLFxuICBjb21wdXRlZCxcbiAgT25Jbml0LFxuICBBZnRlclZpZXdJbml0LFxuICBPbkRlc3Ryb3ksXG4gIGluamVjdCxcbiAgUExBVEZPUk1fSUQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7IFNjcm9sbGluZ01vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9jZGsvc2Nyb2xsaW5nXCI7XG5pbXBvcnQgeyBDb3BpbG90U2xvdCB9IGZyb20gXCIuLi8uLi9zbG90cy9jb3BpbG90LXNsb3RcIjtcbmltcG9ydCB7IENvcGlsb3RDaGF0TWVzc2FnZVZpZXcgfSBmcm9tIFwiLi9jb3BpbG90LWNoYXQtbWVzc2FnZS12aWV3XCI7XG5pbXBvcnQgeyBDb3BpbG90Q2hhdFZpZXdTY3JvbGxUb0JvdHRvbUJ1dHRvbiB9IGZyb20gXCIuL2NvcGlsb3QtY2hhdC12aWV3LXNjcm9sbC10by1ib3R0b20tYnV0dG9uXCI7XG5pbXBvcnQgeyBTdGlja1RvQm90dG9tIH0gZnJvbSBcIi4uLy4uL2RpcmVjdGl2ZXMvc3RpY2stdG8tYm90dG9tXCI7XG5pbXBvcnQgeyBTY3JvbGxQb3NpdGlvbiB9IGZyb20gXCIuLi8uLi9zY3JvbGwtcG9zaXRpb25cIjtcbmltcG9ydCB7IE1lc3NhZ2UgfSBmcm9tIFwiQGFnLXVpL2NsaWVudFwiO1xuaW1wb3J0IHsgY24gfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5cbi8qKlxuICogU2Nyb2xsVmlldyBjb21wb25lbnQgZm9yIENvcGlsb3RDaGF0Vmlld1xuICogSGFuZGxlcyBhdXRvLXNjcm9sbGluZyBhbmQgc2Nyb2xsIHBvc2l0aW9uIG1hbmFnZW1lbnRcbiAqL1xuQENvbXBvbmVudCh7XG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHNlbGVjdG9yOiBcImNvcGlsb3QtY2hhdC12aWV3LXNjcm9sbC12aWV3XCIsXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgU2Nyb2xsaW5nTW9kdWxlLFxuICAgIENvcGlsb3RTbG90LFxuICAgIENvcGlsb3RDaGF0TWVzc2FnZVZpZXcsXG4gICAgU3RpY2tUb0JvdHRvbSxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHByb3ZpZGVyczogW1Njcm9sbFBvc2l0aW9uXSxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKCFoYXNNb3VudGVkKCkpIHtcbiAgICAgIDwhLS0gU1NSL0luaXRpYWwgcmVuZGVyIHdpdGhvdXQgc3RpY2stdG8tYm90dG9tIC0tPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImgtZnVsbCBtYXgtaC1mdWxsIGZsZXggZmxleC1jb2wgbWluLWgtMCBvdmVyZmxvdy15LXNjcm9sbCBvdmVyZmxvdy14LWhpZGRlblwiXG4gICAgICA+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJweC00IHNtOnB4LTBcIj5cbiAgICAgICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgfSBAZWxzZSBpZiAoIWF1dG9TY3JvbGwoKSkge1xuICAgICAgPCEtLSBNYW51YWwgc2Nyb2xsIG1vZGUgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwiaC1mdWxsIG1heC1oLWZ1bGwgZmxleCBmbGV4LWNvbCBtaW4taC0wIHJlbGF0aXZlXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAjc2Nyb2xsQ29udGFpbmVyXG4gICAgICAgICAgY2RrU2Nyb2xsYWJsZVxuICAgICAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzKClcIlxuICAgICAgICAgIGNsYXNzPVwib3ZlcmZsb3cteS1zY3JvbGwgb3ZlcmZsb3cteC1oaWRkZW5cIlxuICAgICAgICA+XG4gICAgICAgICAgPGRpdiAjY29udGVudENvbnRhaW5lciBjbGFzcz1cInB4LTQgc206cHgtMFwiPlxuICAgICAgICAgICAgPCEtLSBDb250ZW50IHdpdGggcGFkZGluZy1ib3R0b20gbWF0Y2hpbmcgUmVhY3QgLS0+XG4gICAgICAgICAgICA8ZGl2IFtzdHlsZS5wYWRkaW5nLWJvdHRvbS5weF09XCJwYWRkaW5nQm90dG9tKClcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1heC13LTN4bCBteC1hdXRvXCI+XG4gICAgICAgICAgICAgICAgQGlmIChtZXNzYWdlVmlldygpKSB7XG4gICAgICAgICAgICAgICAgICA8Y29waWxvdC1zbG90XG4gICAgICAgICAgICAgICAgICAgIFtzbG90XT1cIm1lc3NhZ2VWaWV3KClcIlxuICAgICAgICAgICAgICAgICAgICBbY29udGV4dF09XCJtZXNzYWdlVmlld0NvbnRleHQoKVwiXG4gICAgICAgICAgICAgICAgICAgIFtkZWZhdWx0Q29tcG9uZW50XT1cImRlZmF1bHRNZXNzYWdlVmlld0NvbXBvbmVudFwiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8L2NvcGlsb3Qtc2xvdD5cbiAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIDxjb3BpbG90LWNoYXQtbWVzc2FnZS12aWV3XG4gICAgICAgICAgICAgICAgICAgIFttZXNzYWdlc109XCJtZXNzYWdlcygpXCJcbiAgICAgICAgICAgICAgICAgICAgW2lucHV0Q2xhc3NdPVwibWVzc2FnZVZpZXdDbGFzcygpXCJcbiAgICAgICAgICAgICAgICAgICAgW3Nob3dDdXJzb3JdPVwic2hvd0N1cnNvcigpXCJcbiAgICAgICAgICAgICAgICAgICAgKGFzc2lzdGFudE1lc3NhZ2VUaHVtYnNVcCk9XCJcbiAgICAgICAgICAgICAgICAgICAgICBhc3Npc3RhbnRNZXNzYWdlVGh1bWJzVXAuZW1pdCgkZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgIChhc3Npc3RhbnRNZXNzYWdlVGh1bWJzRG93bik9XCJcbiAgICAgICAgICAgICAgICAgICAgICBhc3Npc3RhbnRNZXNzYWdlVGh1bWJzRG93bi5lbWl0KCRldmVudClcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgKGFzc2lzdGFudE1lc3NhZ2VSZWFkQWxvdWQpPVwiXG4gICAgICAgICAgICAgICAgICAgICAgYXNzaXN0YW50TWVzc2FnZVJlYWRBbG91ZC5lbWl0KCRldmVudClcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgKGFzc2lzdGFudE1lc3NhZ2VSZWdlbmVyYXRlKT1cIlxuICAgICAgICAgICAgICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2VSZWdlbmVyYXRlLmVtaXQoJGV2ZW50KVxuICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAodXNlck1lc3NhZ2VDb3B5KT1cInVzZXJNZXNzYWdlQ29weS5lbWl0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAodXNlck1lc3NhZ2VFZGl0KT1cInVzZXJNZXNzYWdlRWRpdC5lbWl0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPC9jb3BpbG90LWNoYXQtbWVzc2FnZS12aWV3PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBTY3JvbGwgdG8gYm90dG9tIGJ1dHRvbiBmb3IgbWFudWFsIG1vZGUsIE9VVFNJREUgc2Nyb2xsYWJsZSBjb250ZW50IC0tPlxuICAgICAgICBAaWYgKHNob3dTY3JvbGxCdXR0b24oKSAmJiAhaXNSZXNpemluZygpKSB7XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJhYnNvbHV0ZSBpbnNldC14LTAgZmxleCBqdXN0aWZ5LWNlbnRlciB6LTMwXCJcbiAgICAgICAgICAgIFtzdHlsZS5ib3R0b20ucHhdPVwiaW5wdXRDb250YWluZXJIZWlnaHQoKSArIDE2XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8Y29waWxvdC1zbG90XG4gICAgICAgICAgICAgIFtzbG90XT1cInNjcm9sbFRvQm90dG9tQnV0dG9uKClcIlxuICAgICAgICAgICAgICBbY29udGV4dF09XCJzY3JvbGxUb0JvdHRvbUNvbnRleHQoKVwiXG4gICAgICAgICAgICAgIFtkZWZhdWx0Q29tcG9uZW50XT1cImRlZmF1bHRTY3JvbGxUb0JvdHRvbUJ1dHRvbkNvbXBvbmVudFwiXG4gICAgICAgICAgICAgIFtvdXRwdXRzXT1cInNjcm9sbFRvQm90dG9tT3V0cHV0c1wiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8L2NvcGlsb3Qtc2xvdD5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfSBAZWxzZSB7XG4gICAgICA8IS0tIEF1dG8tc2Nyb2xsIG1vZGUgd2l0aCBTdGlja1RvQm90dG9tIGRpcmVjdGl2ZSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJoLWZ1bGwgbWF4LWgtZnVsbCBmbGV4IGZsZXgtY29sIG1pbi1oLTAgcmVsYXRpdmVcIj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICNzY3JvbGxDb250YWluZXJcbiAgICAgICAgICBjZGtTY3JvbGxhYmxlXG4gICAgICAgICAgY29waWxvdFN0aWNrVG9Cb3R0b21cbiAgICAgICAgICBbZW5hYmxlZF09XCJhdXRvU2Nyb2xsKClcIlxuICAgICAgICAgIFt0aHJlc2hvbGRdPVwiMTBcIlxuICAgICAgICAgIFtkZWJvdW5jZU1zXT1cIjBcIlxuICAgICAgICAgIFtpbml0aWFsQmVoYXZpb3JdPVwiJ3Ntb290aCdcIlxuICAgICAgICAgIFtyZXNpemVCZWhhdmlvcl09XCInc21vb3RoJ1wiXG4gICAgICAgICAgKGlzQXRCb3R0b21DaGFuZ2UpPVwib25Jc0F0Qm90dG9tQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzKClcIlxuICAgICAgICAgIGNsYXNzPVwib3ZlcmZsb3cteS1zY3JvbGwgb3ZlcmZsb3cteC1oaWRkZW5cIlxuICAgICAgICA+XG4gICAgICAgICAgPCEtLSBTY3JvbGxhYmxlIGNvbnRlbnQgd3JhcHBlciAtLT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicHgtNCBzbTpweC0wXCI+XG4gICAgICAgICAgICA8IS0tIENvbnRlbnQgd2l0aCBwYWRkaW5nLWJvdHRvbSBtYXRjaGluZyBSZWFjdCAtLT5cbiAgICAgICAgICAgIDxkaXYgW3N0eWxlLnBhZGRpbmctYm90dG9tLnB4XT1cInBhZGRpbmdCb3R0b20oKVwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWF4LXctM3hsIG14LWF1dG9cIj5cbiAgICAgICAgICAgICAgICBAaWYgKG1lc3NhZ2VWaWV3KCkpIHtcbiAgICAgICAgICAgICAgICAgIDxjb3BpbG90LXNsb3RcbiAgICAgICAgICAgICAgICAgICAgW3Nsb3RdPVwibWVzc2FnZVZpZXcoKVwiXG4gICAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cIm1lc3NhZ2VWaWV3Q29udGV4dCgpXCJcbiAgICAgICAgICAgICAgICAgICAgW2RlZmF1bHRDb21wb25lbnRdPVwiZGVmYXVsdE1lc3NhZ2VWaWV3Q29tcG9uZW50XCJcbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDwvY29waWxvdC1zbG90PlxuICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgPGNvcGlsb3QtY2hhdC1tZXNzYWdlLXZpZXdcbiAgICAgICAgICAgICAgICAgICAgW21lc3NhZ2VzXT1cIm1lc3NhZ2VzKClcIlxuICAgICAgICAgICAgICAgICAgICBbaW5wdXRDbGFzc109XCJtZXNzYWdlVmlld0NsYXNzKClcIlxuICAgICAgICAgICAgICAgICAgICBbc2hvd0N1cnNvcl09XCJzaG93Q3Vyc29yKClcIlxuICAgICAgICAgICAgICAgICAgICAoYXNzaXN0YW50TWVzc2FnZVRodW1ic1VwKT1cIlxuICAgICAgICAgICAgICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2VUaHVtYnNVcC5lbWl0KCRldmVudClcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgKGFzc2lzdGFudE1lc3NhZ2VUaHVtYnNEb3duKT1cIlxuICAgICAgICAgICAgICAgICAgICAgIGFzc2lzdGFudE1lc3NhZ2VUaHVtYnNEb3duLmVtaXQoJGV2ZW50KVxuICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAoYXNzaXN0YW50TWVzc2FnZVJlYWRBbG91ZCk9XCJcbiAgICAgICAgICAgICAgICAgICAgICBhc3Npc3RhbnRNZXNzYWdlUmVhZEFsb3VkLmVtaXQoJGV2ZW50KVxuICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAoYXNzaXN0YW50TWVzc2FnZVJlZ2VuZXJhdGUpPVwiXG4gICAgICAgICAgICAgICAgICAgICAgYXNzaXN0YW50TWVzc2FnZVJlZ2VuZXJhdGUuZW1pdCgkZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICh1c2VyTWVzc2FnZUNvcHkpPVwidXNlck1lc3NhZ2VDb3B5LmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICh1c2VyTWVzc2FnZUVkaXQpPVwidXNlck1lc3NhZ2VFZGl0LmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8L2NvcGlsb3QtY2hhdC1tZXNzYWdlLXZpZXc+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIFNjcm9sbCB0byBib3R0b20gYnV0dG9uIC0gaGlkZGVuIGR1cmluZyByZXNpemUsIE9VVFNJREUgc2Nyb2xsYWJsZSBjb250ZW50IC0tPlxuICAgICAgICBAaWYgKCFpc0F0Qm90dG9tKCkgJiYgIWlzUmVzaXppbmcoKSkge1xuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwiYWJzb2x1dGUgaW5zZXQteC0wIGZsZXgganVzdGlmeS1jZW50ZXIgei0zMFwiXG4gICAgICAgICAgICBbc3R5bGUuYm90dG9tLnB4XT1cImlucHV0Q29udGFpbmVySGVpZ2h0KCkgKyAxNlwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGNvcGlsb3Qtc2xvdFxuICAgICAgICAgICAgICBbc2xvdF09XCJzY3JvbGxUb0JvdHRvbUJ1dHRvbigpXCJcbiAgICAgICAgICAgICAgW2NvbnRleHRdPVwic2Nyb2xsVG9Cb3R0b21Gcm9tU3RpY2tDb250ZXh0KClcIlxuICAgICAgICAgICAgICBbZGVmYXVsdENvbXBvbmVudF09XCJkZWZhdWx0U2Nyb2xsVG9Cb3R0b21CdXR0b25Db21wb25lbnRcIlxuICAgICAgICAgICAgICBbb3V0cHV0c109XCJzY3JvbGxUb0JvdHRvbUZyb21TdGlja091dHB1dHNcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPC9jb3BpbG90LXNsb3Q+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgQ29waWxvdENoYXRWaWV3U2Nyb2xsVmlld1xuICBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95XG57XG4gIHByaXZhdGUgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICBhdXRvU2Nyb2xsID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgaW5wdXRDb250YWluZXJIZWlnaHQgPSBpbnB1dDxudW1iZXI+KDApO1xuXG4gIGlzUmVzaXppbmcgPSBpbnB1dDxib29sZWFuPihmYWxzZSk7XG4gIGlucHV0Q2xhc3MgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KCk7XG4gIG1lc3NhZ2VzID0gaW5wdXQ8TWVzc2FnZVtdPihbXSk7XG4gIG1lc3NhZ2VWaWV3ID0gaW5wdXQ8YW55IHwgdW5kZWZpbmVkPigpO1xuICBtZXNzYWdlVmlld0NsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICBzaG93Q3Vyc29yID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIC8vIEhhbmRsZXIgYXZhaWxhYmlsaXR5IGZsYWdzIHJlbW92ZWQgaW4gZmF2b3Igb2YgREkgc2VydmljZVxuXG4gIC8vIFNsb3QgaW5wdXRzXG4gIHNjcm9sbFRvQm90dG9tQnV0dG9uID0gaW5wdXQ8YW55IHwgdW5kZWZpbmVkPigpO1xuICBzY3JvbGxUb0JvdHRvbUJ1dHRvbkNsYXNzID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuXG4gIC8vIE91dHB1dCBldmVudHMgKGJ1YmJsZWQgZnJvbSBtZXNzYWdlIHZpZXcpXG4gIGFzc2lzdGFudE1lc3NhZ2VUaHVtYnNVcCA9IG91dHB1dDx7IG1lc3NhZ2U6IE1lc3NhZ2UgfT4oKTtcbiAgYXNzaXN0YW50TWVzc2FnZVRodW1ic0Rvd24gPSBvdXRwdXQ8eyBtZXNzYWdlOiBNZXNzYWdlIH0+KCk7XG4gIGFzc2lzdGFudE1lc3NhZ2VSZWFkQWxvdWQgPSBvdXRwdXQ8eyBtZXNzYWdlOiBNZXNzYWdlIH0+KCk7XG4gIGFzc2lzdGFudE1lc3NhZ2VSZWdlbmVyYXRlID0gb3V0cHV0PHsgbWVzc2FnZTogTWVzc2FnZSB9PigpO1xuICB1c2VyTWVzc2FnZUNvcHkgPSBvdXRwdXQ8eyBtZXNzYWdlOiBNZXNzYWdlIH0+KCk7XG4gIHVzZXJNZXNzYWdlRWRpdCA9IG91dHB1dDx7IG1lc3NhZ2U6IE1lc3NhZ2UgfT4oKTtcblxuICAvLyBWaWV3Q2hpbGQgcmVmZXJlbmNlc1xuICBAVmlld0NoaWxkKFwic2Nyb2xsQ29udGFpbmVyXCIsIHsgcmVhZDogRWxlbWVudFJlZiB9KVxuICBzY3JvbGxDb250YWluZXI/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgQFZpZXdDaGlsZChcImNvbnRlbnRDb250YWluZXJcIiwgeyByZWFkOiBFbGVtZW50UmVmIH0pXG4gIGNvbnRlbnRDb250YWluZXI/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgQFZpZXdDaGlsZChTdGlja1RvQm90dG9tKSBzdGlja1RvQm90dG9tRGlyZWN0aXZlPzogU3RpY2tUb0JvdHRvbTtcblxuICAvLyBEZWZhdWx0IGNvbXBvbmVudHNcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGRlZmF1bHRNZXNzYWdlVmlld0NvbXBvbmVudCA9IENvcGlsb3RDaGF0TWVzc2FnZVZpZXc7XG4gIHByb3RlY3RlZCByZWFkb25seSBkZWZhdWx0U2Nyb2xsVG9Cb3R0b21CdXR0b25Db21wb25lbnQgPVxuICAgIENvcGlsb3RDaGF0Vmlld1Njcm9sbFRvQm90dG9tQnV0dG9uO1xuXG4gIC8vIFNpZ25hbHNcbiAgcHJvdGVjdGVkIGhhc01vdW50ZWQgPSBzaWduYWwoZmFsc2UpO1xuICBwcm90ZWN0ZWQgc2hvd1Njcm9sbEJ1dHRvbiA9IHNpZ25hbChmYWxzZSk7XG4gIHByb3RlY3RlZCBpc0F0Qm90dG9tID0gc2lnbmFsKHRydWUpO1xuICBwcm90ZWN0ZWQgcGFkZGluZ0JvdHRvbSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuaW5wdXRDb250YWluZXJIZWlnaHQoKSArIDMyKTtcblxuICAvLyBDb21wdXRlZCBjbGFzc1xuICBwcm90ZWN0ZWQgY29tcHV0ZWRDbGFzcyA9IGNvbXB1dGVkKCgpID0+IGNuKHRoaXMuaW5wdXRDbGFzcygpKSk7XG5cbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgcGxhdGZvcm1JZCA9IGluamVjdChQTEFURk9STV9JRCk7XG4gIHByaXZhdGUgc2Nyb2xsUG9zaXRpb25TZXJ2aWNlID0gaW5qZWN0KFNjcm9sbFBvc2l0aW9uKTtcblxuICAvLyBObyBtaXJyb3Jpbmcgb2YgaW5wdXRzOyBkZXJpdmUgZGlyZWN0bHkgdmlhIGNvbXB1dGVkKClcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBDaGVjayBpZiB3ZSdyZSBpbiB0aGUgYnJvd3NlclxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICAvLyBTZXQgbW91bnRlZCBhZnRlciBhIHRpY2sgdG8gYWxsb3cgZm9yIGh5ZHJhdGlvblxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuaGFzTW91bnRlZC5zZXQodHJ1ZSk7XG4gICAgICB9LCAwKTtcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmF1dG9TY3JvbGwoKSkge1xuICAgICAgLy8gV2FpdCBmb3IgdGhlIHZpZXcgdG8gYmUgZnVsbHkgcmVuZGVyZWQgYWZ0ZXIgaGFzTW91bnRlZCBpcyBzZXRcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxDb250YWluZXIpIHtcbiAgICAgICAgICAvLyBDaGVjayBpbml0aWFsIHNjcm9sbCBwb3NpdGlvblxuICAgICAgICAgIGNvbnN0IGluaXRpYWxTdGF0ZSA9IHRoaXMuc2Nyb2xsUG9zaXRpb25TZXJ2aWNlLmdldFNjcm9sbFN0YXRlKFxuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb250YWluZXIubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgIDEwXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLnNob3dTY3JvbGxCdXR0b24uc2V0KCFpbml0aWFsU3RhdGUuaXNBdEJvdHRvbSk7XG5cbiAgICAgICAgICAvLyBNb25pdG9yIHNjcm9sbCBwb3NpdGlvbiBmb3IgbWFudWFsIG1vZGVcbiAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uU2VydmljZVxuICAgICAgICAgICAgLm1vbml0b3JTY3JvbGxQb3NpdGlvbih0aGlzLnNjcm9sbENvbnRhaW5lciwgMTApXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChzdGF0ZSkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnNob3dTY3JvbGxCdXR0b24uc2V0KCFzdGF0ZS5pc0F0Qm90dG9tKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9LCAxMDApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgaXNBdEJvdHRvbSBjaGFuZ2UgZnJvbSBTdGlja1RvQm90dG9tIGRpcmVjdGl2ZVxuICAgKi9cbiAgb25Jc0F0Qm90dG9tQ2hhbmdlKGlzQXRCb3R0b206IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmlzQXRCb3R0b20uc2V0KGlzQXRCb3R0b20pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNjcm9sbCB0byBib3R0b20gZm9yIG1hbnVhbCBtb2RlXG4gICAqL1xuICBzY3JvbGxUb0JvdHRvbSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zY3JvbGxDb250YWluZXIpIHtcbiAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb25TZXJ2aWNlLnNjcm9sbFRvQm90dG9tKHRoaXMuc2Nyb2xsQ29udGFpbmVyLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xsIHRvIGJvdHRvbSBmb3Igc3RpY2stdG8tYm90dG9tIG1vZGVcbiAgICovXG4gIHNjcm9sbFRvQm90dG9tRnJvbVN0aWNrKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0aWNrVG9Cb3R0b21EaXJlY3RpdmUpIHtcbiAgICAgIHRoaXMuc3RpY2tUb0JvdHRvbURpcmVjdGl2ZS5zY3JvbGxUb0JvdHRvbShcInNtb290aFwiKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcbiAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvLyBPdXRwdXQgbWFwcyBmb3Igc2xvdHNcbiAgc2Nyb2xsVG9Cb3R0b21PdXRwdXRzID0geyBjbGlja2VkOiAoKSA9PiB0aGlzLnNjcm9sbFRvQm90dG9tKCkgfTtcbiAgc2Nyb2xsVG9Cb3R0b21Gcm9tU3RpY2tPdXRwdXRzID0ge1xuICAgIGNsaWNrZWQ6ICgpID0+IHRoaXMuc2Nyb2xsVG9Cb3R0b21Gcm9tU3RpY2soKSxcbiAgfTtcblxuICAvLyBDb250ZXh0IG1ldGhvZHMgZm9yIHRlbXBsYXRlc1xuICBtZXNzYWdlVmlld0NvbnRleHQoKTogYW55IHtcbiAgICByZXR1cm4ge1xuICAgICAgbWVzc2FnZXM6IHRoaXMubWVzc2FnZXMoKSxcbiAgICAgIGlucHV0Q2xhc3M6IHRoaXMubWVzc2FnZVZpZXdDbGFzcygpLFxuICAgICAgc2hvd0N1cnNvcjogdGhpcy5zaG93Q3Vyc29yKCksXG4gICAgfTtcbiAgfVxuXG4gIHNjcm9sbFRvQm90dG9tQ29udGV4dCgpOiBhbnkge1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dENsYXNzOiB0aGlzLnNjcm9sbFRvQm90dG9tQnV0dG9uQ2xhc3MoKSxcbiAgICAgIG9uQ2xpY2s6ICgpID0+IHRoaXMuc2Nyb2xsVG9Cb3R0b20oKSxcbiAgICB9O1xuICB9XG5cbiAgc2Nyb2xsVG9Cb3R0b21Gcm9tU3RpY2tDb250ZXh0KCk6IGFueSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlucHV0Q2xhc3M6IHRoaXMuc2Nyb2xsVG9Cb3R0b21CdXR0b25DbGFzcygpLFxuICAgICAgb25DbGljazogKCkgPT4gdGhpcy5zY3JvbGxUb0JvdHRvbUZyb21TdGljaygpLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==