@copilotkitnext/angular 0.0.2 → 0.0.5

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 (173) hide show
  1. package/README.md +3 -3
  2. package/dist/README.md +3 -3
  3. package/dist/components/chat/copilot-chat-assistant-message.component.d.ts +10 -10
  4. package/dist/components/chat/copilot-chat-message-view.component.d.ts +42 -42
  5. package/dist/components/chat/copilot-chat-view.component.d.ts +14 -14
  6. package/dist/core/copilotkit.providers.d.ts +1 -1
  7. package/dist/core/copilotkit.service.d.ts +5 -5
  8. package/dist/core/copilotkit.types.d.ts +8 -10
  9. package/dist/directives/copilotkit-frontend-tool.directive.d.ts +1 -1
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  11. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  12. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  13. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  14. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  15. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  16. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  17. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  18. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  19. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  20. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  21. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  22. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  23. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  24. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  25. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  26. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  29. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  30. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  31. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  32. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  37. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  38. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  39. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  40. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  41. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  42. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  43. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  44. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  45. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  46. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  47. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  48. package/dist/esm2022/core/copilotkit.service.mjs +426 -0
  49. package/dist/esm2022/core/copilotkit.types.mjs +13 -0
  50. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  52. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  53. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  54. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +128 -0
  55. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +265 -0
  56. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  57. package/dist/esm2022/index.mjs +70 -0
  58. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  59. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  60. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  61. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  62. package/dist/esm2022/lib/utils.mjs +10 -0
  63. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  64. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  65. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  66. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  67. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  68. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  69. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  70. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  71. package/dist/esm2022/utils/frontend-tool.utils.mjs +224 -0
  72. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +293 -0
  73. package/dist/fesm2022/copilotkitnext-angular.mjs +174 -187
  74. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  75. package/dist/utils/frontend-tool.utils.d.ts +1 -1
  76. package/package.json +23 -20
  77. package/vitest.config.mts +32 -21
  78. package/.turbo/turbo-build.log +0 -38
  79. package/.turbo/turbo-check-types.log +0 -0
  80. package/.turbo/turbo-test.log +0 -71
  81. package/ng-package.json +0 -19
  82. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  83. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  84. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  85. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  86. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  87. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  88. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  89. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  90. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  91. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  92. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  93. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  94. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  95. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  96. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  97. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  98. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  99. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  100. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  101. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  102. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  103. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  104. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  105. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  106. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  107. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  108. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  109. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  110. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  111. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  112. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  113. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  114. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  115. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  116. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  117. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  118. package/src/components/chat/copilot-chat.component.ts +0 -232
  119. package/src/components/copilotkit-tool-render.component.ts +0 -169
  120. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  121. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  122. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  123. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  124. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  125. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  126. package/src/core/copilotkit.providers.ts +0 -59
  127. package/src/core/copilotkit.service.ts +0 -542
  128. package/src/core/copilotkit.types.ts +0 -132
  129. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  130. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  131. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  132. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  133. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  134. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  135. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  136. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  137. package/src/directives/copilotkit-agent.directive.ts +0 -225
  138. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  139. package/src/directives/copilotkit-config.directive.ts +0 -81
  140. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  141. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  142. package/src/directives/stick-to-bottom.directive.ts +0 -204
  143. package/src/index.ts +0 -105
  144. package/src/lib/directives/tooltip.directive.ts +0 -292
  145. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  146. package/src/lib/slots/copilot-slot.component.ts +0 -135
  147. package/src/lib/slots/index.ts +0 -3
  148. package/src/lib/slots/slot.types.ts +0 -64
  149. package/src/lib/slots/slot.utils.ts +0 -289
  150. package/src/lib/utils.ts +0 -10
  151. package/src/public-api.ts +0 -1
  152. package/src/services/resize-observer.service.ts +0 -181
  153. package/src/services/scroll-position.service.ts +0 -169
  154. package/src/styles/globals.css +0 -266
  155. package/src/styles/index.css +0 -3
  156. package/src/test-setup.ts +0 -15
  157. package/src/testing/index.ts +0 -3
  158. package/src/testing/testing.utils.ts +0 -248
  159. package/src/types/frontend-tool.ts +0 -44
  160. package/src/types/human-in-the-loop.ts +0 -52
  161. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  162. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  163. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  164. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  165. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  166. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  167. package/src/utils/agent-context.utils.ts +0 -133
  168. package/src/utils/agent.utils.ts +0 -239
  169. package/src/utils/chat-config.utils.ts +0 -221
  170. package/src/utils/copilotkit.utils.ts +0 -20
  171. package/src/utils/frontend-tool.utils.ts +0 -266
  172. package/src/utils/human-in-the-loop.utils.ts +0 -359
  173. package/tsconfig.spec.json +0 -12
@@ -1,512 +0,0 @@
1
- import {
2
- Component,
3
- Input,
4
- Output,
5
- EventEmitter,
6
- ViewChild,
7
- TemplateRef,
8
- signal,
9
- computed,
10
- effect,
11
- inject,
12
- ChangeDetectionStrategy,
13
- AfterViewInit,
14
- OnDestroy,
15
- Type,
16
- ViewEncapsulation,
17
- ContentChild
18
- } from '@angular/core';
19
- import { CommonModule } from '@angular/common';
20
- import { CopilotSlotComponent } from '../../lib/slots/copilot-slot.component';
21
- import { CopilotChatConfigurationService } from '../../core/chat-configuration/chat-configuration.service';
22
- import { LucideAngularModule, ArrowUp } from 'lucide-angular';
23
- import { CopilotChatTextareaComponent } from './copilot-chat-textarea.component';
24
- import { CopilotChatAudioRecorderComponent } from './copilot-chat-audio-recorder.component';
25
- import {
26
- CopilotChatSendButtonComponent,
27
- CopilotChatStartTranscribeButtonComponent,
28
- CopilotChatCancelTranscribeButtonComponent,
29
- CopilotChatFinishTranscribeButtonComponent,
30
- CopilotChatAddFileButtonComponent
31
- } from './copilot-chat-buttons.component';
32
- import { CopilotChatToolbarComponent } from './copilot-chat-toolbar.component';
33
- import { CopilotChatToolsMenuComponent } from './copilot-chat-tools-menu.component';
34
- import type {
35
- CopilotChatInputMode,
36
- ToolsMenuItem
37
- } from './copilot-chat-input.types';
38
- import { cn } from '../../lib/utils';
39
-
40
- /**
41
- * Context provided to slot templates
42
- */
43
- export interface SendButtonContext {
44
- send: () => void;
45
- disabled: boolean;
46
- value: string;
47
- }
48
-
49
- export interface ToolbarContext {
50
- mode: CopilotChatInputMode;
51
- value: string;
52
- }
53
-
54
- @Component({
55
- selector: 'copilot-chat-input',
56
- standalone: true,
57
- imports: [
58
- CommonModule,
59
- CopilotSlotComponent,
60
- LucideAngularModule,
61
- CopilotChatTextareaComponent,
62
- CopilotChatAudioRecorderComponent,
63
- CopilotChatSendButtonComponent,
64
- CopilotChatStartTranscribeButtonComponent,
65
- CopilotChatCancelTranscribeButtonComponent,
66
- CopilotChatFinishTranscribeButtonComponent,
67
- CopilotChatAddFileButtonComponent,
68
- CopilotChatToolbarComponent,
69
- CopilotChatToolsMenuComponent
70
- ],
71
- changeDetection: ChangeDetectionStrategy.OnPush,
72
- encapsulation: ViewEncapsulation.None,
73
- template: `
74
- <div [class]="computedClass()">
75
- <!-- Main input area: either textarea or audio recorder -->
76
- @if (computedMode() === 'transcribe') {
77
- @if (audioRecorderTemplate || audioRecorderComponent) {
78
- <copilot-slot
79
- [slot]="audioRecorderTemplate || audioRecorderComponent"
80
- [context]="audioRecorderContext()"
81
- [defaultComponent]="defaultAudioRecorder"
82
- >
83
- </copilot-slot>
84
- } @else {
85
- <copilot-chat-audio-recorder
86
- [inputShowControls]="true">
87
- </copilot-chat-audio-recorder>
88
- }
89
- } @else {
90
- @if (textAreaTemplate || textAreaComponent) {
91
- <copilot-slot
92
- [slot]="textAreaTemplate || textAreaComponent"
93
- [context]="textAreaContext()"
94
- >
95
- </copilot-slot>
96
- } @else {
97
- <textarea copilotChatTextarea
98
- [inputValue]="computedValue()"
99
- [inputAutoFocus]="computedAutoFocus()"
100
- [inputDisabled]="computedMode() === 'processing'"
101
- [inputClass]="textAreaClass"
102
- [inputMaxRows]="textAreaMaxRows"
103
- [inputPlaceholder]="textAreaPlaceholder"
104
- (keyDown)="handleKeyDown($event)"
105
- (valueChange)="handleValueChange($event)"></textarea>
106
- }
107
- }
108
-
109
- <!-- Toolbar -->
110
- @if (toolbarTemplate || toolbarComponent) {
111
- <copilot-slot
112
- [slot]="toolbarTemplate || toolbarComponent"
113
- [context]="toolbarContext()"
114
- [defaultComponent]="CopilotChatToolbarComponent"
115
- >
116
- </copilot-slot>
117
- } @else {
118
- <div copilotChatToolbar>
119
- <div class="flex items-center">
120
- @if (addFile.observed) {
121
- @if (addFileButtonTemplate || addFileButtonComponent) {
122
- <copilot-slot
123
- [slot]="addFileButtonTemplate || addFileButtonComponent"
124
- [context]="{ inputDisabled: computedMode() === 'transcribe' }"
125
- [outputs]="addFileButtonOutputs"
126
- [defaultComponent]="CopilotChatAddFileButtonComponent"
127
- >
128
- </copilot-slot>
129
- } @else {
130
- <copilot-chat-add-file-button
131
- [disabled]="computedMode() === 'transcribe'"
132
- (clicked)="handleAddFile()">
133
- </copilot-chat-add-file-button>
134
- }
135
- }
136
- @if (computedToolsMenu().length > 0) {
137
- @if (toolsButtonTemplate || toolsButtonComponent) {
138
- <copilot-slot
139
- [slot]="toolsButtonTemplate || toolsButtonComponent"
140
- [context]="toolsContext()"
141
- [defaultComponent]="CopilotChatToolsMenuComponent"
142
- >
143
- </copilot-slot>
144
- } @else {
145
- <copilot-chat-tools-menu
146
- [inputToolsMenu]="computedToolsMenu()"
147
- [inputDisabled]="computedMode() === 'transcribe'">
148
- </copilot-chat-tools-menu>
149
- }
150
- }
151
- @if (additionalToolbarItems) {
152
- <ng-container *ngTemplateOutlet="additionalToolbarItems"></ng-container>
153
- }
154
- </div>
155
- <div class="flex items-center">
156
- @if (computedMode() === 'transcribe') {
157
- @if (cancelTranscribe.observed) {
158
- @if (cancelTranscribeButtonTemplate || cancelTranscribeButtonComponent) {
159
- <copilot-slot
160
- [slot]="cancelTranscribeButtonTemplate || cancelTranscribeButtonComponent"
161
- [context]="{}"
162
- [outputs]="cancelTranscribeButtonOutputs"
163
- [defaultComponent]="CopilotChatCancelTranscribeButtonComponent"
164
- >
165
- </copilot-slot>
166
- } @else {
167
- <copilot-chat-cancel-transcribe-button
168
- (clicked)="handleCancelTranscribe()">
169
- </copilot-chat-cancel-transcribe-button>
170
- }
171
- }
172
- @if (finishTranscribe.observed) {
173
- @if (finishTranscribeButtonTemplate || finishTranscribeButtonComponent) {
174
- <copilot-slot
175
- [slot]="finishTranscribeButtonTemplate || finishTranscribeButtonComponent"
176
- [context]="{}"
177
- [outputs]="finishTranscribeButtonOutputs"
178
- [defaultComponent]="CopilotChatFinishTranscribeButtonComponent"
179
- >
180
- </copilot-slot>
181
- } @else {
182
- <copilot-chat-finish-transcribe-button
183
- (clicked)="handleFinishTranscribe()">
184
- </copilot-chat-finish-transcribe-button>
185
- }
186
- }
187
- } @else {
188
- @if (startTranscribe.observed) {
189
- @if (startTranscribeButtonTemplate || startTranscribeButtonComponent) {
190
- <copilot-slot
191
- [slot]="startTranscribeButtonTemplate || startTranscribeButtonComponent"
192
- [context]="{}"
193
- [outputs]="startTranscribeButtonOutputs"
194
- [defaultComponent]="CopilotChatStartTranscribeButtonComponent"
195
- >
196
- </copilot-slot>
197
- } @else {
198
- <copilot-chat-start-transcribe-button
199
- (clicked)="handleStartTranscribe()">
200
- </copilot-chat-start-transcribe-button>
201
- }
202
- }
203
- <!-- Send button with slot -->
204
- @if (sendButtonTemplate || sendButtonComponent) {
205
- <copilot-slot
206
- [slot]="sendButtonTemplate || sendButtonComponent"
207
- [context]="sendButtonContext()"
208
- [outputs]="sendButtonOutputs"
209
- >
210
- </copilot-slot>
211
- } @else {
212
- <div class="mr-[10px]">
213
- <button
214
- type="button"
215
- [class]="sendButtonClass || defaultButtonClass"
216
- [disabled]="!computedValue().trim() || computedMode() === 'processing'"
217
- (click)="send()">
218
- <lucide-angular [img]="ArrowUpIcon" [size]="18"></lucide-angular>
219
- </button>
220
- </div>
221
- }
222
- }
223
- </div>
224
- </div>
225
- }
226
- </div>
227
- `,
228
- styles: [`
229
- :host {
230
- display: block;
231
- width: 100%;
232
- }
233
- .shadow-\\[0_4px_4px_0_\\#0000000a\\2c_0_0_1px_0_\\#0000009e\\] {
234
- box-shadow: 0 4px 4px 0 #0000000a, 0 0 1px 0 #0000009e !important;
235
- }
236
- `]
237
- })
238
- export class CopilotChatInputComponent implements AfterViewInit, OnDestroy {
239
- @ViewChild(CopilotChatTextareaComponent, { read: CopilotChatTextareaComponent })
240
- textAreaRef?: CopilotChatTextareaComponent;
241
-
242
- @ViewChild(CopilotChatAudioRecorderComponent)
243
- audioRecorderRef?: CopilotChatAudioRecorderComponent;
244
-
245
- // Capture templates from content projection
246
- @ContentChild('sendButton', { read: TemplateRef }) sendButtonTemplate?: TemplateRef<SendButtonContext>;
247
- @ContentChild('toolbar', { read: TemplateRef }) toolbarTemplate?: TemplateRef<ToolbarContext>;
248
- @ContentChild('textArea', { read: TemplateRef }) textAreaTemplate?: TemplateRef<any>;
249
- @ContentChild('audioRecorder', { read: TemplateRef }) audioRecorderTemplate?: TemplateRef<any>;
250
- @ContentChild('startTranscribeButton', { read: TemplateRef }) startTranscribeButtonTemplate?: TemplateRef<any>;
251
- @ContentChild('cancelTranscribeButton', { read: TemplateRef }) cancelTranscribeButtonTemplate?: TemplateRef<any>;
252
- @ContentChild('finishTranscribeButton', { read: TemplateRef }) finishTranscribeButtonTemplate?: TemplateRef<any>;
253
- @ContentChild('addFileButton', { read: TemplateRef }) addFileButtonTemplate?: TemplateRef<any>;
254
- @ContentChild('toolsButton', { read: TemplateRef }) toolsButtonTemplate?: TemplateRef<any>;
255
-
256
- // Class inputs for styling default components
257
- @Input() sendButtonClass?: string;
258
- @Input() toolbarClass?: string;
259
- @Input() textAreaClass?: string;
260
- @Input() textAreaMaxRows?: number;
261
- @Input() textAreaPlaceholder?: string;
262
- @Input() audioRecorderClass?: string;
263
- @Input() startTranscribeButtonClass?: string;
264
- @Input() cancelTranscribeButtonClass?: string;
265
- @Input() finishTranscribeButtonClass?: string;
266
- @Input() addFileButtonClass?: string;
267
- @Input() toolsButtonClass?: string;
268
-
269
- // Component inputs for overrides
270
- @Input() sendButtonComponent?: Type<any>;
271
- @Input() toolbarComponent?: Type<any>;
272
- @Input() textAreaComponent?: Type<any>;
273
- @Input() audioRecorderComponent?: Type<any>;
274
- @Input() startTranscribeButtonComponent?: Type<any>;
275
- @Input() cancelTranscribeButtonComponent?: Type<any>;
276
- @Input() finishTranscribeButtonComponent?: Type<any>;
277
- @Input() addFileButtonComponent?: Type<any>;
278
- @Input() toolsButtonComponent?: Type<any>;
279
-
280
- // Regular inputs
281
- @Input() set mode(val: CopilotChatInputMode | undefined) {
282
- this.modeSignal.set(val || 'input');
283
- }
284
- @Input() set toolsMenu(val: (ToolsMenuItem | '-')[] | undefined) {
285
- this.toolsMenuSignal.set(val || []);
286
- }
287
- @Input() set autoFocus(val: boolean | undefined) {
288
- this.autoFocusSignal.set(val ?? true);
289
- }
290
- @Input() set value(val: string | undefined) {
291
- this.valueSignal.set(val || '');
292
- }
293
- @Input() set inputClass(val: string | undefined) {
294
- this.customClass.set(val);
295
- }
296
- // Note: Prefer host `class` for styling this component;
297
- // keep only `inputClass` to style the internal wrapper if needed.
298
- @Input() additionalToolbarItems?: TemplateRef<any>;
299
-
300
- // Output events
301
- @Output() submitMessage = new EventEmitter<string>();
302
- @Output() startTranscribe = new EventEmitter<void>();
303
- @Output() cancelTranscribe = new EventEmitter<void>();
304
- @Output() finishTranscribe = new EventEmitter<void>();
305
- @Output() addFile = new EventEmitter<void>();
306
- @Output() valueChange = new EventEmitter<string>();
307
-
308
- // Icons and default classes
309
- readonly ArrowUpIcon = ArrowUp;
310
- readonly defaultButtonClass = cn(
311
- // Base button styles
312
- 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium',
313
- 'transition-all disabled:pointer-events-none disabled:opacity-50',
314
- 'shrink-0 outline-none',
315
- 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
316
- // chatInputToolbarPrimary variant
317
- 'cursor-pointer',
318
- 'bg-black text-white',
319
- 'dark:bg-white dark:text-black dark:focus-visible:outline-white',
320
- 'rounded-full h-9 w-9',
321
- 'transition-colors',
322
- 'focus:outline-none',
323
- 'hover:opacity-70 disabled:hover:opacity-100',
324
- 'disabled:cursor-not-allowed disabled:bg-[#00000014] disabled:text-[rgb(13,13,13)]',
325
- 'dark:disabled:bg-[#454545] dark:disabled:text-white'
326
- );
327
-
328
- // Services
329
- private chatConfig = inject(CopilotChatConfigurationService, { optional: true });
330
-
331
- // Signals
332
- modeSignal = signal<CopilotChatInputMode>('input');
333
- toolsMenuSignal = signal<(ToolsMenuItem | '-')[]>([]);
334
- autoFocusSignal = signal<boolean>(true);
335
- valueSignal = signal<string>('');
336
- customClass = signal<string | undefined>(undefined);
337
-
338
- // Default components
339
- // Note: CopilotChatTextareaComponent uses attribute selector but is a component
340
- defaultAudioRecorder = CopilotChatAudioRecorderComponent;
341
- defaultSendButton: any = null; // Will be set to avoid circular dependency
342
- CopilotChatToolbarComponent = CopilotChatToolbarComponent;
343
- CopilotChatAddFileButtonComponent = CopilotChatAddFileButtonComponent;
344
- CopilotChatToolsMenuComponent = CopilotChatToolsMenuComponent;
345
- CopilotChatCancelTranscribeButtonComponent = CopilotChatCancelTranscribeButtonComponent;
346
- CopilotChatFinishTranscribeButtonComponent = CopilotChatFinishTranscribeButtonComponent;
347
- CopilotChatStartTranscribeButtonComponent = CopilotChatStartTranscribeButtonComponent;
348
-
349
- // Computed values
350
- computedMode = computed(() => this.modeSignal());
351
- computedToolsMenu = computed(() => this.toolsMenuSignal());
352
- computedAutoFocus = computed(() => this.autoFocusSignal());
353
- computedValue = computed(() => {
354
- const customValue = this.valueSignal();
355
- const configValue = this.chatConfig?.inputValue();
356
- return customValue || configValue || '';
357
- });
358
-
359
- computedClass = computed(() => {
360
- const baseClasses = cn(
361
- // Layout
362
- 'flex w-full flex-col items-center justify-center',
363
- // Interaction
364
- 'cursor-text',
365
- // Overflow and clipping
366
- 'overflow-visible bg-clip-padding contain-inline-size',
367
- // Background
368
- 'bg-white dark:bg-[#303030]',
369
- // Visual effects
370
- 'shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] rounded-[28px]'
371
- );
372
- return cn(baseClasses, this.customClass());
373
- });
374
-
375
- // Context for slots (reactive via signals)
376
- sendButtonContext = computed<SendButtonContext>(() => ({
377
- send: () => this.send(),
378
- disabled: !this.computedValue().trim() || this.computedMode() === 'processing',
379
- value: this.computedValue()
380
- }));
381
-
382
- toolbarContext = computed<ToolbarContext>(() => ({
383
- mode: this.computedMode(),
384
- value: this.computedValue()
385
- }));
386
-
387
- textAreaContext = computed(() => ({
388
- value: this.computedValue(),
389
- autoFocus: this.computedAutoFocus(),
390
- disabled: this.computedMode() === 'processing',
391
- maxRows: this.textAreaMaxRows,
392
- placeholder: this.textAreaPlaceholder,
393
- inputClass: this.textAreaClass,
394
- onKeyDown: (event: KeyboardEvent) => this.handleKeyDown(event),
395
- onChange: (value: string) => this.handleValueChange(value)
396
- }));
397
-
398
- audioRecorderContext = computed(() => ({
399
- inputShowControls: true
400
- }));
401
-
402
- // Button contexts removed - now using outputs map for click handlers
403
-
404
- toolsContext = computed(() => ({
405
- inputToolsMenu: this.computedToolsMenu(),
406
- inputDisabled: this.computedMode() === 'transcribe'
407
- }));
408
-
409
- constructor() {
410
- // Effect to handle mode changes
411
- effect(() => {
412
- const currentMode = this.computedMode();
413
- if (currentMode === 'transcribe' && this.audioRecorderRef) {
414
- this.audioRecorderRef.start().catch(console.error);
415
- } else if (this.audioRecorderRef?.getState() === 'recording') {
416
- this.audioRecorderRef.stop().catch(console.error);
417
- }
418
- });
419
-
420
- // Sync with chat configuration
421
- effect(() => {
422
- const configValue = this.chatConfig?.inputValue();
423
- if (configValue !== undefined && !this.valueSignal()) {
424
- this.valueSignal.set(configValue);
425
- }
426
- });
427
- }
428
-
429
- // Output maps for slots
430
- addFileButtonOutputs = { clicked: () => this.handleAddFile() };
431
- cancelTranscribeButtonOutputs = { clicked: () => this.handleCancelTranscribe() };
432
- finishTranscribeButtonOutputs = { clicked: () => this.handleFinishTranscribe() };
433
- startTranscribeButtonOutputs = { clicked: () => this.handleStartTranscribe() };
434
- // Support both `clicked` (idiomatic in our slots) and `click` (legacy)
435
- sendButtonOutputs = { clicked: () => this.send(), click: () => this.send() };
436
-
437
- ngAfterViewInit(): void {
438
- // Auto-focus if needed
439
- if (this.computedAutoFocus() && this.textAreaRef) {
440
- setTimeout(() => {
441
- this.textAreaRef?.focus();
442
- });
443
- }
444
- }
445
-
446
- ngOnDestroy(): void {
447
- // Clean up any resources
448
- if (this.audioRecorderRef?.getState() === 'recording') {
449
- this.audioRecorderRef.stop().catch(console.error);
450
- }
451
- }
452
-
453
- handleKeyDown(event: KeyboardEvent): void {
454
- if (event.key === 'Enter' && !event.shiftKey) {
455
- event.preventDefault();
456
- this.send();
457
- }
458
- }
459
-
460
- handleValueChange(value: string): void {
461
- this.valueSignal.set(value);
462
- this.valueChange.emit(value);
463
-
464
- if (this.chatConfig) {
465
- this.chatConfig.setInputValue(value);
466
- }
467
- }
468
-
469
- send(): void {
470
- const trimmed = this.computedValue().trim();
471
- if (trimmed) {
472
- this.submitMessage.emit(trimmed);
473
-
474
- // Use chat config handler if available
475
- if (this.chatConfig) {
476
- this.chatConfig.submitInput(trimmed);
477
- }
478
-
479
- // Clear input
480
- this.valueSignal.set('');
481
- if (this.textAreaRef) {
482
- this.textAreaRef.setValue('');
483
- }
484
-
485
- // Refocus input
486
- if (this.textAreaRef) {
487
- setTimeout(() => {
488
- this.textAreaRef?.focus();
489
- });
490
- }
491
- }
492
- }
493
-
494
- handleStartTranscribe(): void {
495
- this.startTranscribe.emit();
496
- this.modeSignal.set('transcribe');
497
- }
498
-
499
- handleCancelTranscribe(): void {
500
- this.cancelTranscribe.emit();
501
- this.modeSignal.set('input');
502
- }
503
-
504
- handleFinishTranscribe(): void {
505
- this.finishTranscribe.emit();
506
- this.modeSignal.set('input');
507
- }
508
-
509
- handleAddFile(): void {
510
- this.addFile.emit();
511
- }
512
- }
@@ -1,148 +0,0 @@
1
- import type { Type, TemplateRef } from '@angular/core';
2
-
3
- /**
4
- * Mode of the chat input component
5
- */
6
- export type CopilotChatInputMode = 'input' | 'transcribe' | 'processing';
7
-
8
- /**
9
- * Represents a menu item in the tools menu
10
- */
11
- export type ToolsMenuItem = {
12
- label: string;
13
- } & (
14
- | {
15
- action: () => void;
16
- items?: never;
17
- }
18
- | {
19
- action?: never;
20
- items: (ToolsMenuItem | '-')[];
21
- }
22
- );
23
-
24
- /**
25
- * Audio recorder state
26
- */
27
- export type AudioRecorderState = 'idle' | 'recording' | 'processing';
28
-
29
- /**
30
- * Error class for audio recorder failures
31
- */
32
- export class AudioRecorderError extends Error {
33
- constructor(message: string) {
34
- super(message);
35
- this.name = 'AudioRecorderError';
36
- }
37
- }
38
-
39
- /**
40
- * Props for textarea component
41
- */
42
- export interface CopilotChatTextareaProps {
43
- value?: string;
44
- placeholder?: string;
45
- maxRows?: number;
46
- autoFocus?: boolean;
47
- disabled?: boolean;
48
- onChange?: (value: string) => void;
49
- onKeyDown?: (event: KeyboardEvent) => void;
50
- inputClass?: string;
51
- style?: any;
52
- rows?: number;
53
- cols?: number;
54
- readonly?: boolean;
55
- spellcheck?: boolean;
56
- wrap?: 'hard' | 'soft' | 'off';
57
- }
58
-
59
- /**
60
- * Props for button components
61
- */
62
- export interface CopilotChatButtonProps {
63
- disabled?: boolean;
64
- onClick?: () => void;
65
- inputClass?: string;
66
- style?: any;
67
- type?: 'button' | 'submit' | 'reset';
68
- ariaLabel?: string;
69
- ariaPressed?: boolean;
70
- ariaExpanded?: boolean;
71
- title?: string;
72
- }
73
-
74
- /**
75
- * Props for toolbar button with tooltip
76
- */
77
- export interface CopilotChatToolbarButtonProps extends CopilotChatButtonProps {
78
- icon?: TemplateRef<any>;
79
- tooltip?: string;
80
- variant?: 'primary' | 'secondary';
81
- }
82
-
83
- /**
84
- * Props for tools menu button
85
- */
86
- export interface CopilotChatToolsButtonProps extends CopilotChatButtonProps {
87
- toolsMenu?: (ToolsMenuItem | '-')[];
88
- }
89
-
90
- /**
91
- * Props for audio recorder
92
- */
93
- export interface CopilotChatAudioRecorderProps {
94
- inputClass?: string;
95
- style?: any;
96
- onStateChange?: (state: AudioRecorderState) => void;
97
- showControls?: boolean;
98
- maxDuration?: number;
99
- }
100
-
101
- /**
102
- * Props for toolbar
103
- */
104
- export interface CopilotChatToolbarProps {
105
- inputClass?: string;
106
- style?: any;
107
- position?: 'top' | 'bottom';
108
- alignment?: 'left' | 'center' | 'right' | 'space-between';
109
- }
110
-
111
- /**
112
- * Slot configuration for chat input
113
- */
114
- export interface CopilotChatInputSlots {
115
- textArea?: Type<any> | TemplateRef<any>;
116
- sendButton?: Type<any> | TemplateRef<any>;
117
- startTranscribeButton?: Type<any> | TemplateRef<any>;
118
- cancelTranscribeButton?: Type<any> | TemplateRef<any>;
119
- finishTranscribeButton?: Type<any> | TemplateRef<any>;
120
- addFileButton?: Type<any> | TemplateRef<any>;
121
- toolsButton?: Type<any> | TemplateRef<any>;
122
- toolbar?: Type<any> | TemplateRef<any>;
123
- audioRecorder?: Type<any> | TemplateRef<any>;
124
- }
125
-
126
- /**
127
- * Input configuration for the chat input component
128
- */
129
- export interface CopilotChatInputConfig {
130
- mode?: CopilotChatInputMode;
131
- toolsMenu?: (ToolsMenuItem | '-')[];
132
- autoFocus?: boolean;
133
- additionalToolbarItems?: TemplateRef<any>;
134
- value?: string;
135
- class?: string;
136
- }
137
-
138
- /**
139
- * Output events for the chat input component
140
- */
141
- export interface CopilotChatInputOutputs {
142
- submitMessage: (value: string) => void;
143
- startTranscribe: () => void;
144
- cancelTranscribe: () => void;
145
- finishTranscribe: () => void;
146
- addFile: () => void;
147
- changeValue: (value: string) => void;
148
- }