@copilotkit/vue 2.0.0-rc.20 → 2.0.0-rc.22
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.
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +13 -13
- package/dist/use-render-activity-message-CyrhHFhA.js +16200 -0
- package/dist/use-render-activity-message-CyrhHFhA.js.map +1 -0
- package/dist/use-render-activity-message-EwHHrwQB.cjs +114 -0
- package/dist/use-render-activity-message-EwHHrwQB.cjs.map +1 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
- package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +7 -21
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +0 -5
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -138
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
- package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
- package/dist/v2/components/a2ui/utils.d.ts +3 -15
- package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
- package/dist/v2/components/a2ui.d.ts +6 -1
- package/dist/v2/components/a2ui.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
- package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +3 -2
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
- package/dist/v2/components/chat/index.d.ts +6 -6
- package/dist/v2/components/chat/tool-call-display-context.d.ts +3 -1
- package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
- package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
- package/dist/v2/components/chat/types.d.ts +1 -1
- package/dist/v2/components/chat/types.d.ts.map +1 -1
- package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent-context.d.ts +2 -3
- package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent.d.ts +4 -1
- package/dist/v2/hooks/use-agent.d.ts.map +1 -1
- package/dist/v2/hooks/use-attachments.d.ts +7 -0
- package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
- package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
- package/dist/v2/hooks/use-component.d.ts +1 -0
- package/dist/v2/hooks/use-component.d.ts.map +1 -1
- package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
- package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
- package/dist/v2/hooks/use-interrupt.d.ts +0 -1
- package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
- package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-threads.d.ts +0 -8
- package/dist/v2/hooks/use-threads.d.ts.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/lib/vue-core.d.ts +12 -11
- package/dist/v2/lib/vue-core.d.ts.map +1 -1
- package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -124
- package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
- package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
- package/dist/v2/providers/markdown-renderer.d.ts +3 -1
- package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
- package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
- package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/v2/__tests__/exports.test.ts +10 -0
- package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
- package/src/v2/__tests__/utils/test-helpers.ts +34 -4
- package/src/v2/components/A2UIMessageRenderer.ts +98 -68
- package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
- package/src/v2/components/CopilotKitInspector.vue +104 -51
- package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
- package/src/v2/components/OpenGenerativeUIRenderer.ts +78 -80
- package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
- package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +9 -2
- package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
- package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +1 -6
- package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -93
- package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
- package/src/v2/components/a2ui/catalog.ts +2 -3
- package/src/v2/components/a2ui/utils.ts +13 -67
- package/src/v2/components/a2ui.ts +14 -21
- package/src/v2/components/chat/CopilotChat.vue +136 -324
- package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +22 -45
- package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
- package/src/v2/components/chat/CopilotChatInput.vue +69 -407
- package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
- package/src/v2/components/chat/CopilotChatMessageView.vue +52 -112
- package/src/v2/components/chat/CopilotChatToolCallGroup.vue +14 -45
- package/src/v2/components/chat/CopilotChatToolCallItem.vue +6 -4
- package/src/v2/components/chat/CopilotChatToolCallsView.vue +16 -19
- package/src/v2/components/chat/CopilotChatView.vue +28 -23
- package/src/v2/components/chat/CopilotPopupViewInternal.vue +21 -97
- package/src/v2/components/chat/CopilotSidebarViewInternal.vue +24 -25
- package/src/v2/components/chat/CopilotThreadsDrawer.vue +37 -102
- package/src/v2/components/chat/StreamingMarkdownDefault.vue +13 -26
- package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
- package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +56 -0
- package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
- package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
- package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
- package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
- package/src/v2/components/chat/audioRecorder.ts +4 -7
- package/src/v2/components/chat/copilotChatToolCallItemRender.ts +22 -71
- package/src/v2/components/chat/tool-call-display-context.ts +6 -1
- package/src/v2/components/chat/tool-call-group-parts.ts +13 -33
- package/src/v2/components/chat/types.ts +1 -1
- package/src/v2/components/chat/use-lightbox.ts +15 -33
- package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
- package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
- package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
- package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
- package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
- package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
- package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +4 -0
- package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
- package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
- package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
- package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +2 -1
- package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
- package/src/v2/hooks/use-agent-context.ts +4 -10
- package/src/v2/hooks/use-agent.ts +86 -290
- package/src/v2/hooks/use-attachments.ts +42 -166
- package/src/v2/hooks/use-capabilities.ts +2 -7
- package/src/v2/hooks/use-component.ts +7 -4
- package/src/v2/hooks/use-configure-suggestions.ts +28 -218
- package/src/v2/hooks/use-default-render-tool.ts +34 -94
- package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
- package/src/v2/hooks/use-interrupt.ts +29 -308
- package/src/v2/hooks/use-render-activity-message.ts +17 -20
- package/src/v2/hooks/use-render-custom-messages.ts +20 -63
- package/src/v2/hooks/use-suggestions.ts +9 -33
- package/src/v2/hooks/use-threads.ts +43 -273
- package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
- package/src/v2/lib/vue-core.ts +67 -72
- package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
- package/src/v2/providers/CopilotKitProvider.types.ts +12 -127
- package/src/v2/providers/CopilotKitProvider.vue +188 -402
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +19 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +45 -2
- package/src/v2/providers/chat-configuration-store-key.ts +9 -0
- package/src/v2/providers/markdown-renderer.ts +7 -1
- package/src/v2/providers/use-inspector-thread-override.ts +22 -80
- package/vite.config.ts +5 -1
- package/vitest.config.ts +12 -7
- package/dist/use-render-activity-message-CsWYyd6r.cjs +0 -91
- package/dist/use-render-activity-message-CsWYyd6r.cjs.map +0 -1
- package/dist/use-render-activity-message-DntKKNdd.js +0 -17418
- package/dist/use-render-activity-message-DntKKNdd.js.map +0 -1
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
- package/dist/v2/lib/is-mobile-viewport.d.ts +0 -2
- package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
- package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
- package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
- package/src/v2/components/chat/normalize-auto-scroll.ts +0 -3
- package/src/v2/lib/is-mobile-viewport.ts +0 -5
|
@@ -5,10 +5,20 @@ import {
|
|
|
5
5
|
onBeforeUnmount,
|
|
6
6
|
onMounted,
|
|
7
7
|
ref,
|
|
8
|
+
shallowRef,
|
|
8
9
|
useAttrs,
|
|
9
10
|
watch,
|
|
10
11
|
} from "vue";
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
ɵclampSlashIndex,
|
|
14
|
+
ɵcomposerButtonState,
|
|
15
|
+
ɵcreateComposerAutosize,
|
|
16
|
+
ɵfilterCommands,
|
|
17
|
+
ɵflattenCommandItems,
|
|
18
|
+
ɵparseSlashQuery,
|
|
19
|
+
ɵresolveComposerKey,
|
|
20
|
+
ɵresolveSlashKey,
|
|
21
|
+
} from "@copilotkit/core";
|
|
12
22
|
import {
|
|
13
23
|
IconArrowUp,
|
|
14
24
|
IconCheck,
|
|
@@ -116,7 +126,20 @@ const slashMenuRef = ref<HTMLElement | null>(null);
|
|
|
116
126
|
const audioRecorderRef = ref<CopilotChatAudioRecorderRef | null>(null);
|
|
117
127
|
const localValue = ref(props.modelValue ?? "");
|
|
118
128
|
const isComposing = ref(false);
|
|
119
|
-
|
|
129
|
+
// Sizes the text box and picks the compact or expanded layout.
|
|
130
|
+
const autosize = ɵcreateComposerAutosize({
|
|
131
|
+
getElements: () => ({
|
|
132
|
+
textarea: textareaRef.value,
|
|
133
|
+
grid: gridRef.value,
|
|
134
|
+
start: addButtonContainerRef.value,
|
|
135
|
+
actions: actionsContainerRef.value,
|
|
136
|
+
}),
|
|
137
|
+
maxRows: props.maxRows,
|
|
138
|
+
});
|
|
139
|
+
const layout = shallowRef(autosize.getSnapshot());
|
|
140
|
+
autosize.subscribe(() => {
|
|
141
|
+
layout.value = autosize.getSnapshot();
|
|
142
|
+
});
|
|
120
143
|
const commandQuery = ref<string | null>(null);
|
|
121
144
|
const slashHighlightIndex = ref(0);
|
|
122
145
|
const previousCommandQuery = ref<string | null>(null);
|
|
@@ -127,21 +150,6 @@ const addMenuInitialFocus = ref<"first" | "last" | "content">("content");
|
|
|
127
150
|
const addMenuAnchor = ref<HTMLElement | null>(null);
|
|
128
151
|
const addMenuId = useCopilotId("cpk-add-menu");
|
|
129
152
|
const addMenuTriggerId = `${addMenuId}-trigger`;
|
|
130
|
-
const measurements = ref({
|
|
131
|
-
singleLineHeight: 0,
|
|
132
|
-
maxHeight: 0,
|
|
133
|
-
paddingLeft: 0,
|
|
134
|
-
paddingRight: 0,
|
|
135
|
-
});
|
|
136
|
-
const resizeEvaluationRafRef = ref<number | null>(null);
|
|
137
|
-
const ignoreResizeRef = ref(false);
|
|
138
|
-
const measurementCanvasRef = ref<HTMLCanvasElement | null>(null);
|
|
139
|
-
const containerCacheRef = ref<{
|
|
140
|
-
compactWidth: number;
|
|
141
|
-
} | null>(null);
|
|
142
|
-
const didWarnMissingFontRef = ref(false);
|
|
143
|
-
const didWarnMissingCanvasContextRef = ref(false);
|
|
144
|
-
let resizeObserver: ResizeObserver | null = null;
|
|
145
153
|
|
|
146
154
|
const isControlled = computed(() => props.modelValue !== undefined);
|
|
147
155
|
const inputValue = computed(() =>
|
|
@@ -251,35 +259,7 @@ function normalizeMenuItems() {
|
|
|
251
259
|
const menuItems = computed(() => normalizeMenuItems());
|
|
252
260
|
const hasMenuItems = computed(() => menuItems.value.length > 0);
|
|
253
261
|
|
|
254
|
-
|
|
255
|
-
const seen = new Set<string>();
|
|
256
|
-
const commands: ToolsMenuItem[] = [];
|
|
257
|
-
|
|
258
|
-
const walk = (entryList: MenuEntry[]) => {
|
|
259
|
-
for (const entry of entryList) {
|
|
260
|
-
if (entry === "-") {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (isMenuGroup(entry) && entry.items.length > 0) {
|
|
265
|
-
walk(entry.items);
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (!entry.action || seen.has(entry.label)) {
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
seen.add(entry.label);
|
|
274
|
-
commands.push(entry);
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
walk(items);
|
|
279
|
-
return commands;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const commandItems = computed(() => flattenMenuForCommands(menuItems.value));
|
|
262
|
+
const commandItems = computed(() => ɵflattenCommandItems(menuItems.value));
|
|
283
263
|
|
|
284
264
|
function flattenMenuDisplay(items: MenuEntry[], depth = 0, prefix = "root") {
|
|
285
265
|
const entries: MenuDisplayEntry[] = [];
|
|
@@ -314,32 +294,9 @@ function flattenMenuDisplay(items: MenuEntry[], depth = 0, prefix = "root") {
|
|
|
314
294
|
|
|
315
295
|
const menuDisplayItems = computed(() => flattenMenuDisplay(menuItems.value));
|
|
316
296
|
|
|
317
|
-
const filteredCommands = computed(() =>
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const normalized = commandQuery.value.trim().toLowerCase();
|
|
323
|
-
if (normalized.length === 0) {
|
|
324
|
-
return commandItems.value;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const startsWith: ToolsMenuItem[] = [];
|
|
328
|
-
const contains: ToolsMenuItem[] = [];
|
|
329
|
-
|
|
330
|
-
for (const command of commandItems.value) {
|
|
331
|
-
const label = command.label.toLowerCase();
|
|
332
|
-
if (label.startsWith(normalized)) {
|
|
333
|
-
startsWith.push(command);
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
if (label.includes(normalized)) {
|
|
337
|
-
contains.push(command);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return [...startsWith, ...contains];
|
|
342
|
-
});
|
|
297
|
+
const filteredCommands = computed(() =>
|
|
298
|
+
ɵfilterCommands(commandItems.value, commandQuery.value),
|
|
299
|
+
);
|
|
343
300
|
|
|
344
301
|
const slashMenuVisible = computed(
|
|
345
302
|
() => commandQuery.value !== null && commandItems.value.length > 0,
|
|
@@ -357,18 +314,7 @@ function clearInputValue() {
|
|
|
357
314
|
}
|
|
358
315
|
|
|
359
316
|
function updateSlashState(value: string) {
|
|
360
|
-
|
|
361
|
-
commandQuery.value = null;
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (value.startsWith("/")) {
|
|
366
|
-
const firstLine = value.split(/\r?\n/, 1)[0] ?? "";
|
|
367
|
-
commandQuery.value = firstLine.slice(1);
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
commandQuery.value = null;
|
|
317
|
+
commandQuery.value = ɵparseSlashQuery(value, commandItems.value.length > 0);
|
|
372
318
|
}
|
|
373
319
|
|
|
374
320
|
function runCommand(command: ToolsMenuItem) {
|
|
@@ -429,50 +375,24 @@ function handleKeydown(event: KeyboardEvent) {
|
|
|
429
375
|
return;
|
|
430
376
|
}
|
|
431
377
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
378
|
+
const slash = ɵresolveSlashKey(event, {
|
|
379
|
+
query: props.mode === "input" ? commandQuery.value : null,
|
|
380
|
+
commands: filteredCommands.value,
|
|
381
|
+
highlightIndex: slashHighlightIndex.value,
|
|
382
|
+
});
|
|
383
|
+
if (slash.type !== "none") event.preventDefault();
|
|
384
|
+
switch (slash.type) {
|
|
385
|
+
case "highlight":
|
|
386
|
+
slashHighlightIndex.value = slash.index;
|
|
441
387
|
return;
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
if (event.key === "ArrowUp") {
|
|
445
|
-
if (filteredCommands.value.length > 0) {
|
|
446
|
-
event.preventDefault();
|
|
447
|
-
if (slashHighlightIndex.value < 0) {
|
|
448
|
-
slashHighlightIndex.value = filteredCommands.value.length - 1;
|
|
449
|
-
} else {
|
|
450
|
-
slashHighlightIndex.value =
|
|
451
|
-
slashHighlightIndex.value <= 0
|
|
452
|
-
? filteredCommands.value.length - 1
|
|
453
|
-
: slashHighlightIndex.value - 1;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
388
|
+
case "run":
|
|
389
|
+
runCommand(slash.command);
|
|
456
390
|
return;
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
if (event.key === "Enter") {
|
|
460
|
-
const selected =
|
|
461
|
-
slashHighlightIndex.value >= 0
|
|
462
|
-
? filteredCommands.value[slashHighlightIndex.value]
|
|
463
|
-
: undefined;
|
|
464
|
-
if (selected) {
|
|
465
|
-
event.preventDefault();
|
|
466
|
-
runCommand(selected);
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (event.key === "Escape") {
|
|
472
|
-
event.preventDefault();
|
|
391
|
+
case "close":
|
|
473
392
|
commandQuery.value = null;
|
|
474
393
|
return;
|
|
475
|
-
|
|
394
|
+
case "none":
|
|
395
|
+
break;
|
|
476
396
|
}
|
|
477
397
|
|
|
478
398
|
if (props.mode !== "input") {
|
|
@@ -603,240 +523,6 @@ function handleContainerClick(event: MouseEvent) {
|
|
|
603
523
|
textareaRef.value?.focus();
|
|
604
524
|
}
|
|
605
525
|
|
|
606
|
-
function ensureMeasurements() {
|
|
607
|
-
const textarea = textareaRef.value;
|
|
608
|
-
if (!textarea || isComposing.value) {
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
const previousValue = textarea.value;
|
|
613
|
-
const previousHeight = textarea.style.height;
|
|
614
|
-
textarea.style.height = "auto";
|
|
615
|
-
|
|
616
|
-
const computedStyle = window.getComputedStyle(textarea);
|
|
617
|
-
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
|
|
618
|
-
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
|
|
619
|
-
const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
|
|
620
|
-
const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;
|
|
621
|
-
|
|
622
|
-
textarea.value = "";
|
|
623
|
-
const singleLineHeight = textarea.scrollHeight;
|
|
624
|
-
textarea.value = previousValue;
|
|
625
|
-
|
|
626
|
-
const contentHeight = singleLineHeight - paddingTop - paddingBottom;
|
|
627
|
-
const maxHeight = contentHeight * props.maxRows + paddingTop + paddingBottom;
|
|
628
|
-
|
|
629
|
-
measurements.value = {
|
|
630
|
-
singleLineHeight,
|
|
631
|
-
maxHeight,
|
|
632
|
-
paddingLeft,
|
|
633
|
-
paddingRight,
|
|
634
|
-
};
|
|
635
|
-
|
|
636
|
-
textarea.style.height = previousHeight;
|
|
637
|
-
textarea.style.maxHeight = `${maxHeight}px`;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
function adjustTextareaHeight() {
|
|
641
|
-
const textarea = textareaRef.value;
|
|
642
|
-
if (!textarea) {
|
|
643
|
-
return 0;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (measurements.value.singleLineHeight === 0) {
|
|
647
|
-
ensureMeasurements();
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
const { maxHeight } = measurements.value;
|
|
651
|
-
if (maxHeight) {
|
|
652
|
-
textarea.style.maxHeight = `${maxHeight}px`;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
textarea.style.height = "auto";
|
|
656
|
-
const scrollHeight = textarea.scrollHeight;
|
|
657
|
-
textarea.style.height = `${maxHeight ? Math.min(scrollHeight, maxHeight) : scrollHeight}px`;
|
|
658
|
-
return scrollHeight;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
function updateLayout(nextLayout: "compact" | "expanded") {
|
|
662
|
-
if (layout.value === nextLayout) {
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
665
|
-
ignoreResizeRef.value = true;
|
|
666
|
-
layout.value = nextLayout;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
function resolveTextareaFont(textarea: HTMLTextAreaElement): string | null {
|
|
670
|
-
const textareaStyles = window.getComputedStyle(textarea);
|
|
671
|
-
if (textareaStyles.font?.trim()) {
|
|
672
|
-
return textareaStyles.font;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (textareaStyles.fontSize && textareaStyles.fontFamily) {
|
|
676
|
-
const fallbackFont =
|
|
677
|
-
`${textareaStyles.fontStyle} ${textareaStyles.fontVariant} ` +
|
|
678
|
-
`${textareaStyles.fontWeight} ${textareaStyles.fontSize}/${textareaStyles.lineHeight} ` +
|
|
679
|
-
`${textareaStyles.fontFamily}`;
|
|
680
|
-
if (fallbackFont.trim()) {
|
|
681
|
-
return fallbackFont;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
if (process.env.NODE_ENV !== "production" && !didWarnMissingFontRef.value) {
|
|
686
|
-
didWarnMissingFontRef.value = true;
|
|
687
|
-
console.warn(
|
|
688
|
-
"[CopilotChatInput] Could not resolve textarea font for layout measurement. " +
|
|
689
|
-
"Text-width-based expansion will be skipped until the next container resize.",
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
return null;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function updateContainerCache() {
|
|
696
|
-
const grid = gridRef.value;
|
|
697
|
-
const addContainer = addButtonContainerRef.value;
|
|
698
|
-
const actionsContainer = actionsContainerRef.value;
|
|
699
|
-
if (!grid || !addContainer || !actionsContainer) {
|
|
700
|
-
containerCacheRef.value = null;
|
|
701
|
-
return null;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
const gridStyles = window.getComputedStyle(grid);
|
|
705
|
-
const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0;
|
|
706
|
-
const paddingRight = parseFloat(gridStyles.paddingRight) || 0;
|
|
707
|
-
const columnGap = parseFloat(gridStyles.columnGap) || 0;
|
|
708
|
-
const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight;
|
|
709
|
-
if (gridAvailableWidth <= 0) {
|
|
710
|
-
containerCacheRef.value = null;
|
|
711
|
-
return null;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
const addWidth = addContainer.getBoundingClientRect().width;
|
|
715
|
-
const actionsWidth = actionsContainer.getBoundingClientRect().width;
|
|
716
|
-
const compactWidth = Math.max(
|
|
717
|
-
gridAvailableWidth - addWidth - actionsWidth - columnGap * 2,
|
|
718
|
-
0,
|
|
719
|
-
);
|
|
720
|
-
if (compactWidth <= 0) {
|
|
721
|
-
containerCacheRef.value = null;
|
|
722
|
-
return null;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
const cache = { compactWidth };
|
|
726
|
-
containerCacheRef.value = cache;
|
|
727
|
-
return cache;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
function evaluateLayout() {
|
|
731
|
-
if (props.mode !== "input") {
|
|
732
|
-
updateLayout("compact");
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
if (
|
|
737
|
-
typeof window.matchMedia === "function" &&
|
|
738
|
-
window.matchMedia("(max-width: 767px)").matches
|
|
739
|
-
) {
|
|
740
|
-
ensureMeasurements();
|
|
741
|
-
adjustTextareaHeight();
|
|
742
|
-
updateLayout("expanded");
|
|
743
|
-
return;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const textarea = textareaRef.value;
|
|
747
|
-
if (
|
|
748
|
-
!textarea ||
|
|
749
|
-
!gridRef.value ||
|
|
750
|
-
!addButtonContainerRef.value ||
|
|
751
|
-
!actionsContainerRef.value
|
|
752
|
-
) {
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
if (measurements.value.singleLineHeight === 0) {
|
|
757
|
-
ensureMeasurements();
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const scrollHeight = adjustTextareaHeight();
|
|
761
|
-
const baseline = measurements.value.singleLineHeight;
|
|
762
|
-
const hasExplicitBreak = inputValue.value.includes("\n");
|
|
763
|
-
const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false;
|
|
764
|
-
let shouldExpand = hasExplicitBreak || renderedMultiline;
|
|
765
|
-
|
|
766
|
-
if (!shouldExpand) {
|
|
767
|
-
const cache = containerCacheRef.value ?? updateContainerCache();
|
|
768
|
-
if (cache && cache.compactWidth > 0) {
|
|
769
|
-
const compactInnerWidth = Math.max(
|
|
770
|
-
cache.compactWidth -
|
|
771
|
-
measurements.value.paddingLeft -
|
|
772
|
-
measurements.value.paddingRight,
|
|
773
|
-
0,
|
|
774
|
-
);
|
|
775
|
-
|
|
776
|
-
if (compactInnerWidth > 0) {
|
|
777
|
-
const canvas =
|
|
778
|
-
measurementCanvasRef.value ?? document.createElement("canvas");
|
|
779
|
-
if (!measurementCanvasRef.value) {
|
|
780
|
-
measurementCanvasRef.value = canvas;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
const context = canvas.getContext("2d");
|
|
784
|
-
if (context) {
|
|
785
|
-
const resolvedFont = resolveTextareaFont(textarea);
|
|
786
|
-
if (resolvedFont) {
|
|
787
|
-
context.font = resolvedFont;
|
|
788
|
-
const lines =
|
|
789
|
-
inputValue.value.length > 0 ? inputValue.value.split("\n") : [""];
|
|
790
|
-
let longestLine = 0;
|
|
791
|
-
for (const line of lines) {
|
|
792
|
-
const width = context.measureText(line || " ").width;
|
|
793
|
-
if (width > longestLine) {
|
|
794
|
-
longestLine = width;
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
if (longestLine > compactInnerWidth) {
|
|
798
|
-
shouldExpand = true;
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
} else if (
|
|
802
|
-
process.env.NODE_ENV !== "production" &&
|
|
803
|
-
!didWarnMissingCanvasContextRef.value
|
|
804
|
-
) {
|
|
805
|
-
didWarnMissingCanvasContextRef.value = true;
|
|
806
|
-
console.warn(
|
|
807
|
-
"[CopilotChatInput] canvas.getContext('2d') returned null. " +
|
|
808
|
-
"Text-width-based expansion will be skipped.",
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
updateLayout(shouldExpand ? "expanded" : "compact");
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
function scheduleLayoutEvaluation(invalidateCache: boolean) {
|
|
819
|
-
if (ignoreResizeRef.value) {
|
|
820
|
-
ignoreResizeRef.value = false;
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
if (invalidateCache) {
|
|
825
|
-
containerCacheRef.value = null;
|
|
826
|
-
didWarnMissingFontRef.value = false;
|
|
827
|
-
didWarnMissingCanvasContextRef.value = false;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if (resizeEvaluationRafRef.value !== null) {
|
|
831
|
-
cancelAnimationFrame(resizeEvaluationRafRef.value);
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
resizeEvaluationRafRef.value = requestAnimationFrame(() => {
|
|
835
|
-
resizeEvaluationRafRef.value = null;
|
|
836
|
-
evaluateLayout();
|
|
837
|
-
});
|
|
838
|
-
}
|
|
839
|
-
|
|
840
526
|
watch(
|
|
841
527
|
() => props.modelValue,
|
|
842
528
|
(next) => {
|
|
@@ -848,13 +534,25 @@ watch(
|
|
|
848
534
|
|
|
849
535
|
watch(inputValue, (value) => {
|
|
850
536
|
updateSlashState(value);
|
|
851
|
-
evaluateLayout();
|
|
852
537
|
});
|
|
853
538
|
|
|
539
|
+
watch(
|
|
540
|
+
[inputValue, () => props.mode],
|
|
541
|
+
([value, mode]) => {
|
|
542
|
+
autosize.evaluate(value, mode);
|
|
543
|
+
},
|
|
544
|
+
{ flush: "post" },
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
watch(
|
|
548
|
+
() => props.maxRows,
|
|
549
|
+
(maxRows) => {
|
|
550
|
+
autosize.setMaxRows(maxRows);
|
|
551
|
+
},
|
|
552
|
+
);
|
|
553
|
+
|
|
854
554
|
watch(commandItems, () => {
|
|
855
|
-
|
|
856
|
-
commandQuery.value = null;
|
|
857
|
-
}
|
|
555
|
+
updateSlashState(inputValue.value);
|
|
858
556
|
});
|
|
859
557
|
|
|
860
558
|
watch(
|
|
@@ -876,20 +574,13 @@ watch(
|
|
|
876
574
|
watch(
|
|
877
575
|
[commandQuery, filteredCommands],
|
|
878
576
|
() => {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}
|
|
887
|
-
if (
|
|
888
|
-
slashHighlightIndex.value < 0 ||
|
|
889
|
-
slashHighlightIndex.value >= filteredCommands.value.length
|
|
890
|
-
) {
|
|
891
|
-
slashHighlightIndex.value = 0;
|
|
892
|
-
}
|
|
577
|
+
slashHighlightIndex.value =
|
|
578
|
+
commandQuery.value === null
|
|
579
|
+
? 0
|
|
580
|
+
: ɵclampSlashIndex(
|
|
581
|
+
slashHighlightIndex.value,
|
|
582
|
+
filteredCommands.value.length,
|
|
583
|
+
);
|
|
893
584
|
},
|
|
894
585
|
{ immediate: true },
|
|
895
586
|
);
|
|
@@ -898,7 +589,6 @@ watch(
|
|
|
898
589
|
() => props.mode,
|
|
899
590
|
async (mode) => {
|
|
900
591
|
if (mode !== "input") {
|
|
901
|
-
layout.value = "compact";
|
|
902
592
|
commandQuery.value = null;
|
|
903
593
|
closeAddMenu();
|
|
904
594
|
}
|
|
@@ -970,39 +660,11 @@ onMounted(() => {
|
|
|
970
660
|
textareaRef.value?.focus();
|
|
971
661
|
}
|
|
972
662
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
976
|
-
const containerTargets = new Set<HTMLElement>();
|
|
977
|
-
if (gridRef.value) containerTargets.add(gridRef.value);
|
|
978
|
-
if (addButtonContainerRef.value)
|
|
979
|
-
containerTargets.add(addButtonContainerRef.value);
|
|
980
|
-
if (actionsContainerRef.value)
|
|
981
|
-
containerTargets.add(actionsContainerRef.value);
|
|
982
|
-
|
|
983
|
-
resizeObserver = new ResizeObserver((entries) => {
|
|
984
|
-
const shouldInvalidate = entries.some((entry) =>
|
|
985
|
-
containerTargets.has(entry.target as HTMLElement),
|
|
986
|
-
);
|
|
987
|
-
scheduleLayoutEvaluation(shouldInvalidate);
|
|
988
|
-
});
|
|
989
|
-
|
|
990
|
-
if (gridRef.value) resizeObserver.observe(gridRef.value);
|
|
991
|
-
if (addButtonContainerRef.value)
|
|
992
|
-
resizeObserver.observe(addButtonContainerRef.value);
|
|
993
|
-
if (actionsContainerRef.value)
|
|
994
|
-
resizeObserver.observe(actionsContainerRef.value);
|
|
995
|
-
if (textareaRef.value) resizeObserver.observe(textareaRef.value);
|
|
996
|
-
}
|
|
663
|
+
autosize.evaluate(inputValue.value, props.mode);
|
|
997
664
|
});
|
|
998
665
|
|
|
999
666
|
onBeforeUnmount(() => {
|
|
1000
|
-
|
|
1001
|
-
resizeObserver = null;
|
|
1002
|
-
if (resizeEvaluationRafRef.value !== null) {
|
|
1003
|
-
cancelAnimationFrame(resizeEvaluationRafRef.value);
|
|
1004
|
-
resizeEvaluationRafRef.value = null;
|
|
1005
|
-
}
|
|
667
|
+
autosize.dispose();
|
|
1006
668
|
});
|
|
1007
669
|
</script>
|
|
1008
670
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* the element that opened it (or `returnFocusTo`) when it closes.
|
|
10
10
|
*/
|
|
11
11
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
|
|
12
|
+
import { ɵbindDialogFocus } from "@copilotkit/core";
|
|
12
13
|
import { IconX } from "../icons";
|
|
13
14
|
import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
|
|
14
15
|
import { CopilotChatDefaultLabels } from "../../providers/types";
|
|
@@ -29,49 +30,28 @@ const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
|
|
|
29
30
|
|
|
30
31
|
const root = ref<HTMLElement | null>(null);
|
|
31
32
|
const closeButton = ref<HTMLButtonElement | null>(null);
|
|
32
|
-
let
|
|
33
|
-
|
|
34
|
-
const FOCUSABLE =
|
|
35
|
-
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), audio[controls], video[controls], iframe, [tabindex]:not([tabindex="-1"])';
|
|
33
|
+
let releaseFocus: (() => void) | undefined;
|
|
36
34
|
|
|
37
35
|
function handleKeydown(event: KeyboardEvent) {
|
|
38
36
|
if (event.key === "Escape") emit("close");
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
/** Keeps Tab inside the lightbox while it is open. */
|
|
42
|
-
function handleTab(event: KeyboardEvent) {
|
|
43
|
-
if (event.key !== "Tab" || !root.value) return;
|
|
44
|
-
const focusables = Array.from(
|
|
45
|
-
root.value.querySelectorAll<HTMLElement>(FOCUSABLE),
|
|
46
|
-
);
|
|
47
|
-
const first = focusables[0];
|
|
48
|
-
const last = focusables[focusables.length - 1];
|
|
49
|
-
if (!first || !last) return;
|
|
50
|
-
const active = document.activeElement;
|
|
51
|
-
if (event.shiftKey && (active === first || !root.value.contains(active))) {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
last.focus();
|
|
54
|
-
} else if (!event.shiftKey && active === last) {
|
|
55
|
-
event.preventDefault();
|
|
56
|
-
first.focus();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
39
|
onMounted(() => {
|
|
61
40
|
if (typeof document === "undefined") return;
|
|
62
|
-
previouslyFocused =
|
|
63
|
-
document.activeElement instanceof HTMLElement
|
|
64
|
-
? document.activeElement
|
|
65
|
-
: null;
|
|
66
41
|
document.addEventListener("keydown", handleKeydown);
|
|
67
|
-
void nextTick(() =>
|
|
42
|
+
void nextTick(() => {
|
|
43
|
+
if (!root.value) return;
|
|
44
|
+
releaseFocus = ɵbindDialogFocus(root.value, {
|
|
45
|
+
initialFocus: closeButton.value,
|
|
46
|
+
returnFocusTo: props.returnFocusTo,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
68
49
|
});
|
|
69
50
|
|
|
70
51
|
onBeforeUnmount(() => {
|
|
71
52
|
if (typeof document === "undefined") return;
|
|
72
53
|
document.removeEventListener("keydown", handleKeydown);
|
|
73
|
-
|
|
74
|
-
if (target?.isConnected) target.focus();
|
|
54
|
+
releaseFocus?.();
|
|
75
55
|
});
|
|
76
56
|
</script>
|
|
77
57
|
|
|
@@ -85,7 +65,6 @@ onBeforeUnmount(() => {
|
|
|
85
65
|
:aria-label="label"
|
|
86
66
|
data-testid="copilot-chat-attachment-lightbox"
|
|
87
67
|
@click="emit('close')"
|
|
88
|
-
@keydown="handleTab"
|
|
89
68
|
>
|
|
90
69
|
<button
|
|
91
70
|
ref="closeButton"
|