@copilotkitnext/angular 0.0.2 → 0.0.4

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 (168) 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/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  7. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  8. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  9. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  11. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  12. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  13. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  14. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  15. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  16. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  17. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  18. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  19. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  20. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  21. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  22. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  23. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  24. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  25. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  26. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  29. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  30. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  31. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  32. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  37. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  38. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  39. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  40. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  41. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  42. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  43. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  44. package/dist/esm2022/core/copilotkit.service.mjs +430 -0
  45. package/dist/esm2022/core/copilotkit.types.mjs +12 -0
  46. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  47. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  48. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  49. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  50. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +266 -0
  52. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  53. package/dist/esm2022/index.mjs +70 -0
  54. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  55. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  56. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  57. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  58. package/dist/esm2022/lib/utils.mjs +10 -0
  59. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  60. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  61. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  62. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  63. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  64. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  65. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  66. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  67. package/dist/esm2022/utils/frontend-tool.utils.mjs +228 -0
  68. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +296 -0
  69. package/dist/fesm2022/copilotkitnext-angular.mjs +163 -164
  70. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  71. package/package.json +21 -18
  72. package/vitest.config.mts +32 -21
  73. package/.turbo/turbo-build.log +0 -38
  74. package/.turbo/turbo-check-types.log +0 -0
  75. package/.turbo/turbo-test.log +0 -71
  76. package/ng-package.json +0 -19
  77. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  78. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  79. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  80. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  81. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  82. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  83. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  84. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  85. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  86. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  87. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  88. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  89. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  90. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  91. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  92. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  93. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  94. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  95. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  96. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  97. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  98. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  99. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  100. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  101. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  102. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  103. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  104. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  105. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  106. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  107. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  108. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  109. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  110. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  111. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  112. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  113. package/src/components/chat/copilot-chat.component.ts +0 -232
  114. package/src/components/copilotkit-tool-render.component.ts +0 -169
  115. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  116. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  117. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  118. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  119. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  120. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  121. package/src/core/copilotkit.providers.ts +0 -59
  122. package/src/core/copilotkit.service.ts +0 -542
  123. package/src/core/copilotkit.types.ts +0 -132
  124. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  125. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  126. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  127. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  128. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  129. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  130. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  131. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  132. package/src/directives/copilotkit-agent.directive.ts +0 -225
  133. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  134. package/src/directives/copilotkit-config.directive.ts +0 -81
  135. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  136. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  137. package/src/directives/stick-to-bottom.directive.ts +0 -204
  138. package/src/index.ts +0 -105
  139. package/src/lib/directives/tooltip.directive.ts +0 -292
  140. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  141. package/src/lib/slots/copilot-slot.component.ts +0 -135
  142. package/src/lib/slots/index.ts +0 -3
  143. package/src/lib/slots/slot.types.ts +0 -64
  144. package/src/lib/slots/slot.utils.ts +0 -289
  145. package/src/lib/utils.ts +0 -10
  146. package/src/public-api.ts +0 -1
  147. package/src/services/resize-observer.service.ts +0 -181
  148. package/src/services/scroll-position.service.ts +0 -169
  149. package/src/styles/globals.css +0 -266
  150. package/src/styles/index.css +0 -3
  151. package/src/test-setup.ts +0 -15
  152. package/src/testing/index.ts +0 -3
  153. package/src/testing/testing.utils.ts +0 -248
  154. package/src/types/frontend-tool.ts +0 -44
  155. package/src/types/human-in-the-loop.ts +0 -52
  156. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  157. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  158. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  159. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  160. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  161. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  162. package/src/utils/agent-context.utils.ts +0 -133
  163. package/src/utils/agent.utils.ts +0 -239
  164. package/src/utils/chat-config.utils.ts +0 -221
  165. package/src/utils/copilotkit.utils.ts +0 -20
  166. package/src/utils/frontend-tool.utils.ts +0 -266
  167. package/src/utils/human-in-the-loop.utils.ts +0 -359
  168. 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
- }