@chatsdk-dev/elements 0.0.1
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/README.md +43 -0
- package/dist/chunk-2LHKM7RD.js +14 -0
- package/dist/chunk-5UMYP6MD.js +10 -0
- package/dist/chunk-AP4MG32M.js +36 -0
- package/dist/chunk-CFM57HOS.js +358 -0
- package/dist/chunk-EGIUE7H2.js +37 -0
- package/dist/chunk-M5OONVIO.js +90 -0
- package/dist/chunk-MXTBCHYC.js +31 -0
- package/dist/chunk-NIC3MOMY.js +55 -0
- package/dist/chunk-QTRMNIG3.js +83 -0
- package/dist/chunk-R7G3RQLU.js +36 -0
- package/dist/chunk-RJG5D2TM.js +113 -0
- package/dist/chunk-SLJNKQ2G.js +125 -0
- package/dist/chunk-TDEFIW2L.js +9 -0
- package/dist/chunk-TDP6D7U7.js +551 -0
- package/dist/chunk-V2ITXC65.js +24 -0
- package/dist/chunk-VS55HRUS.js +16 -0
- package/dist/chunk-VYDYCGJL.js +25 -0
- package/dist/chunk-X5YUF2YM.js +113 -0
- package/dist/chunk-YX46JVQN.js +78 -0
- package/dist/chunk-YXAMLTTT.js +16 -0
- package/dist/chunk-YXFVHSY4.js +51 -0
- package/dist/chunk-ZCSZX3OI.js +4 -0
- package/dist/common/use-copy-to-clipboard.d.ts +3 -0
- package/dist/common/use-copy-to-clipboard.js +33 -0
- package/dist/common/utilts.d.ts +8 -0
- package/dist/common/utilts.js +28 -0
- package/dist/components/ai-elements/actions.d.ts +13 -0
- package/dist/components/ai-elements/actions.js +42 -0
- package/dist/components/ai-elements/agent.d.ts +31 -0
- package/dist/components/ai-elements/agent.js +77 -0
- package/dist/components/ai-elements/artifact.d.ts +27 -0
- package/dist/components/ai-elements/artifact.js +108 -0
- package/dist/components/ai-elements/attachments.d.ts +57 -0
- package/dist/components/ai-elements/attachments.js +258 -0
- package/dist/components/ai-elements/audio-player.d.ts +33 -0
- package/dist/components/ai-elements/audio-player.js +199 -0
- package/dist/components/ai-elements/canvas.d.ts +10 -0
- package/dist/components/ai-elements/canvas.js +24 -0
- package/dist/components/ai-elements/chain-of-thought.d.ts +34 -0
- package/dist/components/ai-elements/chain-of-thought.js +159 -0
- package/dist/components/ai-elements/checkpoint.d.ts +16 -0
- package/dist/components/ai-elements/checkpoint.js +47 -0
- package/dist/components/ai-elements/code-block.d.ts +48 -0
- package/dist/components/ai-elements/code-block.js +1 -0
- package/dist/components/ai-elements/commit.d.ts +68 -0
- package/dist/components/ai-elements/commit.js +314 -0
- package/dist/components/ai-elements/confirmation.d.ts +52 -0
- package/dist/components/ai-elements/confirmation.js +76 -0
- package/dist/components/ai-elements/connection.d.ts +5 -0
- package/dist/components/ai-elements/connection.js +34 -0
- package/dist/components/ai-elements/context.d.ts +36 -0
- package/dist/components/ai-elements/context.js +320 -0
- package/dist/components/ai-elements/controls.d.ts +8 -0
- package/dist/components/ai-elements/controls.js +17 -0
- package/dist/components/ai-elements/conversation.d.ts +27 -0
- package/dist/components/ai-elements/conversation.js +119 -0
- package/dist/components/ai-elements/edge.d.ts +9 -0
- package/dist/components/ai-elements/edge.js +111 -0
- package/dist/components/ai-elements/environment-variables.d.ts +42 -0
- package/dist/components/ai-elements/environment-variables.js +208 -0
- package/dist/components/ai-elements/file-tree.d.ts +30 -0
- package/dist/components/ai-elements/file-tree.js +212 -0
- package/dist/components/ai-elements/image.d.ts +10 -0
- package/dist/components/ai-elements/image.js +23 -0
- package/dist/components/ai-elements/inline-citation.d.ts +42 -0
- package/dist/components/ai-elements/inline-citation.js +203 -0
- package/dist/components/ai-elements/jsx-preview.d.ts +33 -0
- package/dist/components/ai-elements/jsx-preview.js +206 -0
- package/dist/components/ai-elements/loader.d.ts +9 -0
- package/dist/components/ai-elements/loader.js +115 -0
- package/dist/components/ai-elements/message.d.ts +42 -0
- package/dist/components/ai-elements/message.js +259 -0
- package/dist/components/ai-elements/mic-selector.d.ts +49 -0
- package/dist/components/ai-elements/mic-selector.js +252 -0
- package/dist/components/ai-elements/model-selector.d.ts +39 -0
- package/dist/components/ai-elements/model-selector.js +73 -0
- package/dist/components/ai-elements/node.d.ts +25 -0
- package/dist/components/ai-elements/node.js +41 -0
- package/dist/components/ai-elements/open-in-chat.d.ts +32 -0
- package/dist/components/ai-elements/open-in-chat.js +366 -0
- package/dist/components/ai-elements/package-info.d.ts +32 -0
- package/dist/components/ai-elements/package-info.js +162 -0
- package/dist/components/ai-elements/panel.d.ts +8 -0
- package/dist/components/ai-elements/panel.js +17 -0
- package/dist/components/ai-elements/persona.d.ts +50 -0
- package/dist/components/ai-elements/persona.js +209 -0
- package/dist/components/ai-elements/plan.d.ts +29 -0
- package/dist/components/ai-elements/plan.js +95 -0
- package/dist/components/ai-elements/prompt-input.d.ts +153 -0
- package/dist/components/ai-elements/prompt-input.js +939 -0
- package/dist/components/ai-elements/queue.d.ts +65 -0
- package/dist/components/ai-elements/queue.js +179 -0
- package/dist/components/ai-elements/reasoning.d.ts +30 -0
- package/dist/components/ai-elements/reasoning.js +161 -0
- package/dist/components/ai-elements/response.d.ts +9 -0
- package/dist/components/ai-elements/response.js +33 -0
- package/dist/components/ai-elements/sandbox.d.ts +28 -0
- package/dist/components/ai-elements/sandbox.js +98 -0
- package/dist/components/ai-elements/schema-display.d.ts +58 -0
- package/dist/components/ai-elements/schema-display.js +313 -0
- package/dist/components/ai-elements/shimmer.d.ts +14 -0
- package/dist/components/ai-elements/shimmer.js +1 -0
- package/dist/components/ai-elements/snippet.d.ts +22 -0
- package/dist/components/ai-elements/snippet.js +90 -0
- package/dist/components/ai-elements/sources.d.ts +16 -0
- package/dist/components/ai-elements/sources.js +62 -0
- package/dist/components/ai-elements/speech-input.d.ts +57 -0
- package/dist/components/ai-elements/speech-input.js +206 -0
- package/dist/components/ai-elements/stack-trace.d.ts +42 -0
- package/dist/components/ai-elements/stack-trace.js +377 -0
- package/dist/components/ai-elements/suggestion.d.ts +14 -0
- package/dist/components/ai-elements/suggestion.js +41 -0
- package/dist/components/ai-elements/task.d.ts +18 -0
- package/dist/components/ai-elements/task.js +60 -0
- package/dist/components/ai-elements/terminal.d.ts +31 -0
- package/dist/components/ai-elements/terminal.js +203 -0
- package/dist/components/ai-elements/test-results.d.ts +61 -0
- package/dist/components/ai-elements/test-results.js +349 -0
- package/dist/components/ai-elements/tool.d.ts +35 -0
- package/dist/components/ai-elements/tool.js +2 -0
- package/dist/components/ai-elements/toolbar.d.ts +8 -0
- package/dist/components/ai-elements/toolbar.js +18 -0
- package/dist/components/ai-elements/transcription.d.ts +19 -0
- package/dist/components/ai-elements/transcription.js +90 -0
- package/dist/components/ai-elements/voice-selector.d.ts +66 -0
- package/dist/components/ai-elements/voice-selector.js +332 -0
- package/dist/components/ai-elements/web-preview.d.ts +38 -0
- package/dist/components/ai-elements/web-preview.js +214 -0
- package/dist/components/info-card.d.ts +14 -0
- package/dist/components/info-card.js +1 -0
- package/dist/components/responsive-alert-dialog.d.ts +19 -0
- package/dist/components/responsive-alert-dialog.js +1 -0
- package/dist/components/responsive-dialog.d.ts +14 -0
- package/dist/components/responsive-dialog.js +1 -0
- package/dist/config-IcWUmjwj.d.ts +239 -0
- package/dist/features/chat/chat-card.d.ts +5 -0
- package/dist/features/chat/chat-card.js +14 -0
- package/dist/features/chat/chat-element/chat-element.d.ts +8 -0
- package/dist/features/chat/chat-element/chat-element.js +14 -0
- package/dist/features/chat/chat-element/use-chat.d.ts +21 -0
- package/dist/features/chat/chat-element/use-chat.js +14 -0
- package/dist/features/chat/chat-element/use-initial-messages.d.ts +20 -0
- package/dist/features/chat/chat-element/use-initial-messages.js +14 -0
- package/dist/features/chat/chat-header/chat-header.d.ts +8 -0
- package/dist/features/chat/chat-header/chat-header.js +14 -0
- package/dist/features/chat/chat-header/chat-menu.d.ts +5 -0
- package/dist/features/chat/chat-header/chat-menu.js +2 -0
- package/dist/features/chat/chat-history/chat-history-empty.d.ts +5 -0
- package/dist/features/chat/chat-history/chat-history-empty.js +1 -0
- package/dist/features/chat/chat-history/chat-history.d.ts +5 -0
- package/dist/features/chat/chat-history/chat-history.js +14 -0
- package/dist/features/chat/chat-message.d.ts +10 -0
- package/dist/features/chat/chat-message.js +1 -0
- package/dist/features/chat/chat-molecule.d.ts +35 -0
- package/dist/features/chat/chat-molecule.js +14 -0
- package/dist/features/chat/chat-prompt-input.d.ts +16 -0
- package/dist/features/chat/chat-prompt-input.js +14 -0
- package/dist/features/chat/chat.context.d.ts +26 -0
- package/dist/features/chat/chat.context.js +13 -0
- package/dist/features/chat/index.d.ts +14 -0
- package/dist/features/chat/index.js +14 -0
- package/dist/features/chat/queries/query-keys.d.ts +8 -0
- package/dist/features/chat/queries/query-keys.js +1 -0
- package/dist/features/chat/queries/use-create-conversation-mutation.d.ts +29 -0
- package/dist/features/chat/queries/use-create-conversation-mutation.js +38 -0
- package/dist/features/chat/queries/use-get-chat-query.d.ts +9 -0
- package/dist/features/chat/queries/use-get-chat-query.js +14 -0
- package/dist/features/chat/queries/use-get-conversation-query.d.ts +62 -0
- package/dist/features/chat/queries/use-get-conversation-query.js +14 -0
- package/dist/features/chat/queries/use-list-conversations-query.d.ts +29 -0
- package/dist/features/chat/queries/use-list-conversations-query.js +14 -0
- package/dist/features/chat/store.d.ts +13 -0
- package/dist/features/chat/store.js +1 -0
- package/dist/features/chat/utils.d.ts +5 -0
- package/dist/features/chat/utils.js +1 -0
- package/dist/features/data-fetching/use-api-client.d.ts +5 -0
- package/dist/features/data-fetching/use-api-client.js +14 -0
- package/dist/features/logger/logger.d.ts +9 -0
- package/dist/features/logger/logger.js +1 -0
- package/dist/features/molecule/chatsdk-provider.d.ts +19 -0
- package/dist/features/molecule/chatsdk-provider.js +26 -0
- package/dist/features/molecule/constants.d.ts +3 -0
- package/dist/features/molecule/constants.js +1 -0
- package/dist/features/molecule/molecule-provider.d.ts +39 -0
- package/dist/features/molecule/molecule-provider.js +1 -0
- package/dist/features/molecule/store.d.ts +53 -0
- package/dist/features/molecule/store.js +3 -0
- package/dist/features/molecule/types/api.d.ts +8 -0
- package/dist/features/molecule/types/api.js +1 -0
- package/dist/features/molecule/types/callbacks.d.ts +22 -0
- package/dist/features/molecule/types/callbacks.js +1 -0
- package/dist/features/molecule/types/config.d.ts +10 -0
- package/dist/features/molecule/types/config.js +1 -0
- package/dist/features/molecule/types/context.d.ts +11 -0
- package/dist/features/molecule/types/context.js +1 -0
- package/dist/features/molecule/types/locale.d.ts +9 -0
- package/dist/features/molecule/types/locale.js +1 -0
- package/dist/features/molecule/types/theme.d.ts +38 -0
- package/dist/features/molecule/types/theme.js +1 -0
- package/dist/features/molecule/types/translations.d.ts +10 -0
- package/dist/features/molecule/types/translations.js +1 -0
- package/dist/features/molecule/use-merge-global-config.d.ts +22 -0
- package/dist/features/molecule/use-merge-global-config.js +5 -0
- package/dist/features/molecule/use-molecule-config.d.ts +41 -0
- package/dist/features/molecule/use-molecule-config.js +6 -0
- package/dist/features/molecule/utils.d.ts +10 -0
- package/dist/features/molecule/utils.js +1 -0
- package/dist/i18n/config.d.ts +61 -0
- package/dist/i18n/config.js +1 -0
- package/dist/i18n/i18next.d.ts +11 -0
- package/dist/i18n/i18next.js +2 -0
- package/dist/i18n/utils.d.ts +11 -0
- package/dist/i18n/utils.js +6 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +20 -0
- package/dist/styles.css +6811 -0
- package/package.json +123 -0
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '@chatsdk-dev/ui/components/command';
|
|
2
|
+
import { DropdownMenuItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent } from '@chatsdk-dev/ui/components/dropdown-menu';
|
|
3
|
+
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@chatsdk-dev/ui/components/hover-card';
|
|
4
|
+
import { InputGroup, InputGroupTextarea, InputGroupAddon, InputGroupButton } from '@chatsdk-dev/ui/components/input-group';
|
|
5
|
+
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@chatsdk-dev/ui/components/select';
|
|
6
|
+
import { Spinner } from '@chatsdk-dev/ui/components/spinner';
|
|
7
|
+
import { Tooltip, TooltipTrigger, TooltipContent } from '@chatsdk-dev/ui/components/tooltip';
|
|
8
|
+
import { cn } from '@chatsdk-dev/ui/lib/utils';
|
|
9
|
+
import { ImageIcon, Monitor, PlusIcon, CornerDownLeftIcon, SquareIcon, XIcon } from 'lucide-react';
|
|
10
|
+
import { nanoid } from 'nanoid';
|
|
11
|
+
import { createContext, useContext, useState, useCallback, useRef, useEffect, useMemo, Children } from 'react';
|
|
12
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
13
|
+
|
|
14
|
+
var convertBlobUrlToDataUrl = async (url) => {
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(url);
|
|
17
|
+
const blob = await response.blob();
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
const reader = new FileReader();
|
|
20
|
+
reader.onloadend = () => resolve(reader.result);
|
|
21
|
+
reader.onerror = () => resolve(null);
|
|
22
|
+
reader.readAsDataURL(blob);
|
|
23
|
+
});
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var captureScreenshot = async () => {
|
|
29
|
+
if (typeof navigator === "undefined" || !navigator.mediaDevices?.getDisplayMedia) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
let stream = null;
|
|
33
|
+
const video = document.createElement("video");
|
|
34
|
+
video.muted = true;
|
|
35
|
+
video.playsInline = true;
|
|
36
|
+
try {
|
|
37
|
+
stream = await navigator.mediaDevices.getDisplayMedia({
|
|
38
|
+
audio: false,
|
|
39
|
+
video: true
|
|
40
|
+
});
|
|
41
|
+
video.srcObject = stream;
|
|
42
|
+
await new Promise((resolve, reject) => {
|
|
43
|
+
video.onloadedmetadata = () => resolve();
|
|
44
|
+
video.onerror = () => reject(new Error("Failed to load screen stream"));
|
|
45
|
+
});
|
|
46
|
+
await video.play();
|
|
47
|
+
const width = video.videoWidth;
|
|
48
|
+
const height = video.videoHeight;
|
|
49
|
+
if (!width || !height) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const canvas = document.createElement("canvas");
|
|
53
|
+
canvas.width = width;
|
|
54
|
+
canvas.height = height;
|
|
55
|
+
const context = canvas.getContext("2d");
|
|
56
|
+
if (!context) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
context.drawImage(video, 0, 0, width, height);
|
|
60
|
+
const blob = await new Promise((resolve) => {
|
|
61
|
+
canvas.toBlob(resolve, "image/png");
|
|
62
|
+
});
|
|
63
|
+
if (!blob) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g, "-").replace("T", "_").replace("Z", "");
|
|
67
|
+
return new File([blob], `screenshot-${timestamp}.png`, {
|
|
68
|
+
lastModified: Date.now(),
|
|
69
|
+
type: "image/png"
|
|
70
|
+
});
|
|
71
|
+
} finally {
|
|
72
|
+
if (stream) {
|
|
73
|
+
for (const track of stream.getTracks()) {
|
|
74
|
+
track.stop();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
video.pause();
|
|
78
|
+
video.srcObject = null;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var PromptInputController = createContext(
|
|
82
|
+
null
|
|
83
|
+
);
|
|
84
|
+
var ProviderAttachmentsContext = createContext(
|
|
85
|
+
null
|
|
86
|
+
);
|
|
87
|
+
var usePromptInputController = () => {
|
|
88
|
+
const ctx = useContext(PromptInputController);
|
|
89
|
+
if (!ctx) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
"Wrap your component inside <PromptInputProvider> to use usePromptInputController()."
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return ctx;
|
|
95
|
+
};
|
|
96
|
+
var useOptionalPromptInputController = () => useContext(PromptInputController);
|
|
97
|
+
var useProviderAttachments = () => {
|
|
98
|
+
const ctx = useContext(ProviderAttachmentsContext);
|
|
99
|
+
if (!ctx) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"Wrap your component inside <PromptInputProvider> to use useProviderAttachments()."
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return ctx;
|
|
105
|
+
};
|
|
106
|
+
var useOptionalProviderAttachments = () => useContext(ProviderAttachmentsContext);
|
|
107
|
+
var PromptInputProvider = ({
|
|
108
|
+
initialInput: initialTextInput = "",
|
|
109
|
+
children
|
|
110
|
+
}) => {
|
|
111
|
+
const [textInput, setTextInput] = useState(initialTextInput);
|
|
112
|
+
const clearInput = useCallback(() => setTextInput(""), []);
|
|
113
|
+
const [attachmentFiles, setAttachmentFiles] = useState([]);
|
|
114
|
+
const fileInputRef = useRef(null);
|
|
115
|
+
const openRef = useRef(() => {
|
|
116
|
+
});
|
|
117
|
+
const add = useCallback((files) => {
|
|
118
|
+
const incoming = [...files];
|
|
119
|
+
if (incoming.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
setAttachmentFiles((prev) => [
|
|
123
|
+
...prev,
|
|
124
|
+
...incoming.map((file) => ({
|
|
125
|
+
filename: file.name,
|
|
126
|
+
id: nanoid(),
|
|
127
|
+
mediaType: file.type,
|
|
128
|
+
type: "file",
|
|
129
|
+
url: URL.createObjectURL(file)
|
|
130
|
+
}))
|
|
131
|
+
]);
|
|
132
|
+
}, []);
|
|
133
|
+
const remove = useCallback((id) => {
|
|
134
|
+
setAttachmentFiles((prev) => {
|
|
135
|
+
const found = prev.find((f) => f.id === id);
|
|
136
|
+
if (found?.url) {
|
|
137
|
+
URL.revokeObjectURL(found.url);
|
|
138
|
+
}
|
|
139
|
+
return prev.filter((f) => f.id !== id);
|
|
140
|
+
});
|
|
141
|
+
}, []);
|
|
142
|
+
const clear = useCallback(() => {
|
|
143
|
+
setAttachmentFiles((prev) => {
|
|
144
|
+
for (const f of prev) {
|
|
145
|
+
if (f.url) {
|
|
146
|
+
URL.revokeObjectURL(f.url);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return [];
|
|
150
|
+
});
|
|
151
|
+
}, []);
|
|
152
|
+
const attachmentsRef = useRef(attachmentFiles);
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
attachmentsRef.current = attachmentFiles;
|
|
155
|
+
}, [attachmentFiles]);
|
|
156
|
+
useEffect(
|
|
157
|
+
() => () => {
|
|
158
|
+
for (const f of attachmentsRef.current) {
|
|
159
|
+
if (f.url) {
|
|
160
|
+
URL.revokeObjectURL(f.url);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
[]
|
|
165
|
+
);
|
|
166
|
+
const openFileDialog = useCallback(() => {
|
|
167
|
+
openRef.current?.();
|
|
168
|
+
}, []);
|
|
169
|
+
const attachments = useMemo(
|
|
170
|
+
() => ({
|
|
171
|
+
add,
|
|
172
|
+
clear,
|
|
173
|
+
fileInputRef,
|
|
174
|
+
files: attachmentFiles,
|
|
175
|
+
openFileDialog,
|
|
176
|
+
remove
|
|
177
|
+
}),
|
|
178
|
+
[attachmentFiles, add, remove, clear, openFileDialog]
|
|
179
|
+
);
|
|
180
|
+
const __registerFileInput = useCallback(
|
|
181
|
+
(ref, open) => {
|
|
182
|
+
fileInputRef.current = ref.current;
|
|
183
|
+
openRef.current = open;
|
|
184
|
+
},
|
|
185
|
+
[]
|
|
186
|
+
);
|
|
187
|
+
const controller = useMemo(
|
|
188
|
+
() => ({
|
|
189
|
+
__registerFileInput,
|
|
190
|
+
attachments,
|
|
191
|
+
textInput: {
|
|
192
|
+
clear: clearInput,
|
|
193
|
+
setInput: setTextInput,
|
|
194
|
+
value: textInput
|
|
195
|
+
}
|
|
196
|
+
}),
|
|
197
|
+
[textInput, clearInput, attachments, __registerFileInput]
|
|
198
|
+
);
|
|
199
|
+
return /* @__PURE__ */ jsx(PromptInputController.Provider, { value: controller, children: /* @__PURE__ */ jsx(ProviderAttachmentsContext.Provider, { value: attachments, children }) });
|
|
200
|
+
};
|
|
201
|
+
var LocalAttachmentsContext = createContext(null);
|
|
202
|
+
var usePromptInputAttachments = () => {
|
|
203
|
+
const provider = useOptionalProviderAttachments();
|
|
204
|
+
const local = useContext(LocalAttachmentsContext);
|
|
205
|
+
const context = local ?? provider;
|
|
206
|
+
if (!context) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
"usePromptInputAttachments must be used within a PromptInput or PromptInputProvider"
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return context;
|
|
212
|
+
};
|
|
213
|
+
var LocalReferencedSourcesContext = createContext(null);
|
|
214
|
+
var usePromptInputReferencedSources = () => {
|
|
215
|
+
const ctx = useContext(LocalReferencedSourcesContext);
|
|
216
|
+
if (!ctx) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
"usePromptInputReferencedSources must be used within a LocalReferencedSourcesContext.Provider"
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return ctx;
|
|
222
|
+
};
|
|
223
|
+
var PromptInputActionAddAttachments = ({
|
|
224
|
+
label = "Add photos or files",
|
|
225
|
+
...props
|
|
226
|
+
}) => {
|
|
227
|
+
const attachments = usePromptInputAttachments();
|
|
228
|
+
const handleSelect = useCallback(
|
|
229
|
+
(e) => {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
attachments.openFileDialog();
|
|
232
|
+
},
|
|
233
|
+
[attachments]
|
|
234
|
+
);
|
|
235
|
+
return /* @__PURE__ */ jsxs(DropdownMenuItem, { ...props, onSelect: handleSelect, children: [
|
|
236
|
+
/* @__PURE__ */ jsx(ImageIcon, { className: "mr-2 size-4" }),
|
|
237
|
+
" ",
|
|
238
|
+
label
|
|
239
|
+
] });
|
|
240
|
+
};
|
|
241
|
+
var PromptInputActionAddScreenshot = ({
|
|
242
|
+
label = "Take screenshot",
|
|
243
|
+
onSelect,
|
|
244
|
+
...props
|
|
245
|
+
}) => {
|
|
246
|
+
const attachments = usePromptInputAttachments();
|
|
247
|
+
const handleSelect = useCallback(
|
|
248
|
+
async (event) => {
|
|
249
|
+
onSelect?.(event);
|
|
250
|
+
if (event.defaultPrevented) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const screenshot = await captureScreenshot();
|
|
255
|
+
if (screenshot) {
|
|
256
|
+
attachments.add([screenshot]);
|
|
257
|
+
}
|
|
258
|
+
} catch (error) {
|
|
259
|
+
if (error instanceof DOMException && (error.name === "NotAllowedError" || error.name === "AbortError")) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
[onSelect, attachments]
|
|
266
|
+
);
|
|
267
|
+
return /* @__PURE__ */ jsxs(DropdownMenuItem, { ...props, onSelect: handleSelect, children: [
|
|
268
|
+
/* @__PURE__ */ jsx(Monitor, { className: "mr-2 size-4" }),
|
|
269
|
+
label
|
|
270
|
+
] });
|
|
271
|
+
};
|
|
272
|
+
var PromptInput = ({
|
|
273
|
+
className,
|
|
274
|
+
accept,
|
|
275
|
+
multiple,
|
|
276
|
+
globalDrop,
|
|
277
|
+
syncHiddenInput,
|
|
278
|
+
maxFiles,
|
|
279
|
+
maxFileSize,
|
|
280
|
+
onError,
|
|
281
|
+
onSubmit,
|
|
282
|
+
children,
|
|
283
|
+
...props
|
|
284
|
+
}) => {
|
|
285
|
+
const controller = useOptionalPromptInputController();
|
|
286
|
+
const usingProvider = !!controller;
|
|
287
|
+
const inputRef = useRef(null);
|
|
288
|
+
const formRef = useRef(null);
|
|
289
|
+
const [items, setItems] = useState([]);
|
|
290
|
+
const files = usingProvider ? controller.attachments.files : items;
|
|
291
|
+
const [referencedSources, setReferencedSources] = useState([]);
|
|
292
|
+
const filesRef = useRef(files);
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
filesRef.current = files;
|
|
295
|
+
}, [files]);
|
|
296
|
+
const openFileDialogLocal = useCallback(() => {
|
|
297
|
+
inputRef.current?.click();
|
|
298
|
+
}, []);
|
|
299
|
+
const matchesAccept = useCallback(
|
|
300
|
+
(f) => {
|
|
301
|
+
if (!accept || accept.trim() === "") {
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
const patterns = accept.split(",").map((s) => s.trim()).filter(Boolean);
|
|
305
|
+
return patterns.some((pattern) => {
|
|
306
|
+
if (pattern.endsWith("/*")) {
|
|
307
|
+
const prefix = pattern.slice(0, -1);
|
|
308
|
+
return f.type.startsWith(prefix);
|
|
309
|
+
}
|
|
310
|
+
return f.type === pattern;
|
|
311
|
+
});
|
|
312
|
+
},
|
|
313
|
+
[accept]
|
|
314
|
+
);
|
|
315
|
+
const addLocal = useCallback(
|
|
316
|
+
(fileList) => {
|
|
317
|
+
const incoming = [...fileList];
|
|
318
|
+
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
319
|
+
if (incoming.length && accepted.length === 0) {
|
|
320
|
+
onError?.({
|
|
321
|
+
code: "accept",
|
|
322
|
+
message: "No files match the accepted types."
|
|
323
|
+
});
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const withinSize = (f) => maxFileSize ? f.size <= maxFileSize : true;
|
|
327
|
+
const sized = accepted.filter(withinSize);
|
|
328
|
+
if (accepted.length > 0 && sized.length === 0) {
|
|
329
|
+
onError?.({
|
|
330
|
+
code: "max_file_size",
|
|
331
|
+
message: "All files exceed the maximum size."
|
|
332
|
+
});
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
setItems((prev) => {
|
|
336
|
+
const capacity = typeof maxFiles === "number" ? Math.max(0, maxFiles - prev.length) : void 0;
|
|
337
|
+
const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
|
|
338
|
+
if (typeof capacity === "number" && sized.length > capacity) {
|
|
339
|
+
onError?.({
|
|
340
|
+
code: "max_files",
|
|
341
|
+
message: "Too many files. Some were not added."
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
const next = [];
|
|
345
|
+
for (const file of capped) {
|
|
346
|
+
next.push({
|
|
347
|
+
filename: file.name,
|
|
348
|
+
id: nanoid(),
|
|
349
|
+
mediaType: file.type,
|
|
350
|
+
type: "file",
|
|
351
|
+
url: URL.createObjectURL(file)
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return [...prev, ...next];
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
[matchesAccept, maxFiles, maxFileSize, onError]
|
|
358
|
+
);
|
|
359
|
+
const removeLocal = useCallback(
|
|
360
|
+
(id) => setItems((prev) => {
|
|
361
|
+
const found = prev.find((file) => file.id === id);
|
|
362
|
+
if (found?.url) {
|
|
363
|
+
URL.revokeObjectURL(found.url);
|
|
364
|
+
}
|
|
365
|
+
return prev.filter((file) => file.id !== id);
|
|
366
|
+
}),
|
|
367
|
+
[]
|
|
368
|
+
);
|
|
369
|
+
const addWithProviderValidation = useCallback(
|
|
370
|
+
(fileList) => {
|
|
371
|
+
const incoming = [...fileList];
|
|
372
|
+
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
373
|
+
if (incoming.length && accepted.length === 0) {
|
|
374
|
+
onError?.({
|
|
375
|
+
code: "accept",
|
|
376
|
+
message: "No files match the accepted types."
|
|
377
|
+
});
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const withinSize = (f) => maxFileSize ? f.size <= maxFileSize : true;
|
|
381
|
+
const sized = accepted.filter(withinSize);
|
|
382
|
+
if (accepted.length > 0 && sized.length === 0) {
|
|
383
|
+
onError?.({
|
|
384
|
+
code: "max_file_size",
|
|
385
|
+
message: "All files exceed the maximum size."
|
|
386
|
+
});
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const currentCount = files.length;
|
|
390
|
+
const capacity = typeof maxFiles === "number" ? Math.max(0, maxFiles - currentCount) : void 0;
|
|
391
|
+
const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
|
|
392
|
+
if (typeof capacity === "number" && sized.length > capacity) {
|
|
393
|
+
onError?.({
|
|
394
|
+
code: "max_files",
|
|
395
|
+
message: "Too many files. Some were not added."
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
if (capped.length > 0) {
|
|
399
|
+
controller?.attachments.add(capped);
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
[matchesAccept, maxFileSize, maxFiles, onError, files.length, controller]
|
|
403
|
+
);
|
|
404
|
+
const clearAttachments = useCallback(
|
|
405
|
+
() => usingProvider ? controller?.attachments.clear() : setItems((prev) => {
|
|
406
|
+
for (const file of prev) {
|
|
407
|
+
if (file.url) {
|
|
408
|
+
URL.revokeObjectURL(file.url);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return [];
|
|
412
|
+
}),
|
|
413
|
+
[usingProvider, controller]
|
|
414
|
+
);
|
|
415
|
+
const clearReferencedSources = useCallback(
|
|
416
|
+
() => setReferencedSources([]),
|
|
417
|
+
[]
|
|
418
|
+
);
|
|
419
|
+
const add = usingProvider ? addWithProviderValidation : addLocal;
|
|
420
|
+
const remove = usingProvider ? controller.attachments.remove : removeLocal;
|
|
421
|
+
const openFileDialog = usingProvider ? controller.attachments.openFileDialog : openFileDialogLocal;
|
|
422
|
+
const clear = useCallback(() => {
|
|
423
|
+
clearAttachments();
|
|
424
|
+
clearReferencedSources();
|
|
425
|
+
}, [clearAttachments, clearReferencedSources]);
|
|
426
|
+
useEffect(() => {
|
|
427
|
+
if (!usingProvider) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
controller.__registerFileInput(inputRef, () => inputRef.current?.click());
|
|
431
|
+
}, [usingProvider, controller]);
|
|
432
|
+
useEffect(() => {
|
|
433
|
+
if (syncHiddenInput && inputRef.current && files.length === 0) {
|
|
434
|
+
inputRef.current.value = "";
|
|
435
|
+
}
|
|
436
|
+
}, [files, syncHiddenInput]);
|
|
437
|
+
useEffect(() => {
|
|
438
|
+
const form = formRef.current;
|
|
439
|
+
if (!form) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
if (globalDrop) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const onDragOver = (e) => {
|
|
446
|
+
if (e.dataTransfer?.types?.includes("Files")) {
|
|
447
|
+
e.preventDefault();
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
const onDrop = (e) => {
|
|
451
|
+
if (e.dataTransfer?.types?.includes("Files")) {
|
|
452
|
+
e.preventDefault();
|
|
453
|
+
}
|
|
454
|
+
if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
|
|
455
|
+
add(e.dataTransfer.files);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
form.addEventListener("dragover", onDragOver);
|
|
459
|
+
form.addEventListener("drop", onDrop);
|
|
460
|
+
return () => {
|
|
461
|
+
form.removeEventListener("dragover", onDragOver);
|
|
462
|
+
form.removeEventListener("drop", onDrop);
|
|
463
|
+
};
|
|
464
|
+
}, [add, globalDrop]);
|
|
465
|
+
useEffect(() => {
|
|
466
|
+
if (!globalDrop) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const onDragOver = (e) => {
|
|
470
|
+
if (e.dataTransfer?.types?.includes("Files")) {
|
|
471
|
+
e.preventDefault();
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
const onDrop = (e) => {
|
|
475
|
+
if (e.dataTransfer?.types?.includes("Files")) {
|
|
476
|
+
e.preventDefault();
|
|
477
|
+
}
|
|
478
|
+
if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
|
|
479
|
+
add(e.dataTransfer.files);
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
document.addEventListener("dragover", onDragOver);
|
|
483
|
+
document.addEventListener("drop", onDrop);
|
|
484
|
+
return () => {
|
|
485
|
+
document.removeEventListener("dragover", onDragOver);
|
|
486
|
+
document.removeEventListener("drop", onDrop);
|
|
487
|
+
};
|
|
488
|
+
}, [add, globalDrop]);
|
|
489
|
+
useEffect(
|
|
490
|
+
() => () => {
|
|
491
|
+
if (!usingProvider) {
|
|
492
|
+
for (const f of filesRef.current) {
|
|
493
|
+
if (f.url) {
|
|
494
|
+
URL.revokeObjectURL(f.url);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
[usingProvider]
|
|
500
|
+
);
|
|
501
|
+
const handleChange = useCallback(
|
|
502
|
+
(event) => {
|
|
503
|
+
if (event.currentTarget.files) {
|
|
504
|
+
add(event.currentTarget.files);
|
|
505
|
+
}
|
|
506
|
+
event.currentTarget.value = "";
|
|
507
|
+
},
|
|
508
|
+
[add]
|
|
509
|
+
);
|
|
510
|
+
const attachmentsCtx = useMemo(
|
|
511
|
+
() => ({
|
|
512
|
+
add,
|
|
513
|
+
clear: clearAttachments,
|
|
514
|
+
fileInputRef: inputRef,
|
|
515
|
+
files: files.map((item) => ({ ...item, id: item.id })),
|
|
516
|
+
openFileDialog,
|
|
517
|
+
remove
|
|
518
|
+
}),
|
|
519
|
+
[files, add, remove, clearAttachments, openFileDialog]
|
|
520
|
+
);
|
|
521
|
+
const refsCtx = useMemo(
|
|
522
|
+
() => ({
|
|
523
|
+
add: (incoming) => {
|
|
524
|
+
const array = Array.isArray(incoming) ? incoming : [incoming];
|
|
525
|
+
setReferencedSources((prev) => [
|
|
526
|
+
...prev,
|
|
527
|
+
...array.map((s) => ({ ...s, id: nanoid() }))
|
|
528
|
+
]);
|
|
529
|
+
},
|
|
530
|
+
clear: clearReferencedSources,
|
|
531
|
+
remove: (id) => {
|
|
532
|
+
setReferencedSources((prev) => prev.filter((s) => s.id !== id));
|
|
533
|
+
},
|
|
534
|
+
sources: referencedSources
|
|
535
|
+
}),
|
|
536
|
+
[referencedSources, clearReferencedSources]
|
|
537
|
+
);
|
|
538
|
+
const handleSubmit = useCallback(
|
|
539
|
+
async (event) => {
|
|
540
|
+
event.preventDefault();
|
|
541
|
+
const form = event.currentTarget;
|
|
542
|
+
const text = usingProvider ? controller.textInput.value : (() => {
|
|
543
|
+
const formData = new FormData(form);
|
|
544
|
+
return formData.get("message") || "";
|
|
545
|
+
})();
|
|
546
|
+
if (!usingProvider) {
|
|
547
|
+
form.reset();
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
const convertedFiles = await Promise.all(
|
|
551
|
+
files.map(async ({ id: _id, ...item }) => {
|
|
552
|
+
if (item.url?.startsWith("blob:")) {
|
|
553
|
+
const dataUrl = await convertBlobUrlToDataUrl(item.url);
|
|
554
|
+
return {
|
|
555
|
+
...item,
|
|
556
|
+
url: dataUrl ?? item.url
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return item;
|
|
560
|
+
})
|
|
561
|
+
);
|
|
562
|
+
const result = onSubmit({ files: convertedFiles, text }, event);
|
|
563
|
+
if (result instanceof Promise) {
|
|
564
|
+
try {
|
|
565
|
+
await result;
|
|
566
|
+
clear();
|
|
567
|
+
if (usingProvider) {
|
|
568
|
+
controller.textInput.clear();
|
|
569
|
+
}
|
|
570
|
+
} catch {
|
|
571
|
+
}
|
|
572
|
+
} else {
|
|
573
|
+
clear();
|
|
574
|
+
if (usingProvider) {
|
|
575
|
+
controller.textInput.clear();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
} catch {
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
[usingProvider, controller, files, onSubmit, clear]
|
|
582
|
+
);
|
|
583
|
+
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
584
|
+
/* @__PURE__ */ jsx(
|
|
585
|
+
"input",
|
|
586
|
+
{
|
|
587
|
+
accept,
|
|
588
|
+
"aria-label": "Upload files",
|
|
589
|
+
className: "hidden",
|
|
590
|
+
multiple,
|
|
591
|
+
onChange: handleChange,
|
|
592
|
+
ref: inputRef,
|
|
593
|
+
title: "Upload files",
|
|
594
|
+
type: "file"
|
|
595
|
+
}
|
|
596
|
+
),
|
|
597
|
+
/* @__PURE__ */ jsx(
|
|
598
|
+
"form",
|
|
599
|
+
{
|
|
600
|
+
className: cn("w-full", className),
|
|
601
|
+
onSubmit: handleSubmit,
|
|
602
|
+
ref: formRef,
|
|
603
|
+
...props,
|
|
604
|
+
children: /* @__PURE__ */ jsx(InputGroup, { className: "overflow-hidden", children })
|
|
605
|
+
}
|
|
606
|
+
)
|
|
607
|
+
] });
|
|
608
|
+
const withReferencedSources = /* @__PURE__ */ jsx(LocalReferencedSourcesContext.Provider, { value: refsCtx, children: inner });
|
|
609
|
+
return /* @__PURE__ */ jsx(LocalAttachmentsContext.Provider, { value: attachmentsCtx, children: withReferencedSources });
|
|
610
|
+
};
|
|
611
|
+
var PromptInputBody = ({
|
|
612
|
+
className,
|
|
613
|
+
...props
|
|
614
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("contents", className), ...props });
|
|
615
|
+
var PromptInputTextarea = ({
|
|
616
|
+
onChange,
|
|
617
|
+
onKeyDown,
|
|
618
|
+
className,
|
|
619
|
+
placeholder = "What would you like to know?",
|
|
620
|
+
...props
|
|
621
|
+
}) => {
|
|
622
|
+
const controller = useOptionalPromptInputController();
|
|
623
|
+
const attachments = usePromptInputAttachments();
|
|
624
|
+
const [isComposing, setIsComposing] = useState(false);
|
|
625
|
+
const handleKeyDown = useCallback(
|
|
626
|
+
(e) => {
|
|
627
|
+
onKeyDown?.(e);
|
|
628
|
+
if (e.defaultPrevented) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
if (e.key === "Enter") {
|
|
632
|
+
if (isComposing || e.nativeEvent.isComposing) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
if (e.shiftKey) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
e.preventDefault();
|
|
639
|
+
const { form } = e.currentTarget;
|
|
640
|
+
const submitButton = form?.querySelector(
|
|
641
|
+
'button[type="submit"]'
|
|
642
|
+
);
|
|
643
|
+
if (submitButton?.disabled) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
form?.requestSubmit();
|
|
647
|
+
}
|
|
648
|
+
if (e.key === "Backspace" && e.currentTarget.value === "" && attachments.files.length > 0) {
|
|
649
|
+
e.preventDefault();
|
|
650
|
+
const lastAttachment = attachments.files.at(-1);
|
|
651
|
+
if (lastAttachment) {
|
|
652
|
+
attachments.remove(lastAttachment.id);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
[onKeyDown, isComposing, attachments]
|
|
657
|
+
);
|
|
658
|
+
const handlePaste = useCallback(
|
|
659
|
+
(event) => {
|
|
660
|
+
const items = event.clipboardData?.items;
|
|
661
|
+
if (!items) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const files = [];
|
|
665
|
+
for (const item of items) {
|
|
666
|
+
if (item.kind === "file") {
|
|
667
|
+
const file = item.getAsFile();
|
|
668
|
+
if (file) {
|
|
669
|
+
files.push(file);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (files.length > 0) {
|
|
674
|
+
event.preventDefault();
|
|
675
|
+
attachments.add(files);
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
[attachments]
|
|
679
|
+
);
|
|
680
|
+
const handleCompositionEnd = useCallback(() => setIsComposing(false), []);
|
|
681
|
+
const handleCompositionStart = useCallback(() => setIsComposing(true), []);
|
|
682
|
+
const controlledProps = controller ? {
|
|
683
|
+
onChange: (e) => {
|
|
684
|
+
controller.textInput.setInput(e.currentTarget.value);
|
|
685
|
+
onChange?.(e);
|
|
686
|
+
},
|
|
687
|
+
value: controller.textInput.value
|
|
688
|
+
} : {
|
|
689
|
+
onChange
|
|
690
|
+
};
|
|
691
|
+
return /* @__PURE__ */ jsx(
|
|
692
|
+
InputGroupTextarea,
|
|
693
|
+
{
|
|
694
|
+
className: cn("field-sizing-content max-h-48 min-h-16", className),
|
|
695
|
+
name: "message",
|
|
696
|
+
onCompositionEnd: handleCompositionEnd,
|
|
697
|
+
onCompositionStart: handleCompositionStart,
|
|
698
|
+
onKeyDown: handleKeyDown,
|
|
699
|
+
onPaste: handlePaste,
|
|
700
|
+
placeholder,
|
|
701
|
+
...props,
|
|
702
|
+
...controlledProps
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
};
|
|
706
|
+
var PromptInputHeader = ({
|
|
707
|
+
className,
|
|
708
|
+
...props
|
|
709
|
+
}) => /* @__PURE__ */ jsx(
|
|
710
|
+
InputGroupAddon,
|
|
711
|
+
{
|
|
712
|
+
align: "block-end",
|
|
713
|
+
className: cn("order-first flex-wrap gap-1", className),
|
|
714
|
+
...props
|
|
715
|
+
}
|
|
716
|
+
);
|
|
717
|
+
var PromptInputFooter = ({
|
|
718
|
+
className,
|
|
719
|
+
...props
|
|
720
|
+
}) => /* @__PURE__ */ jsx(
|
|
721
|
+
InputGroupAddon,
|
|
722
|
+
{
|
|
723
|
+
align: "block-end",
|
|
724
|
+
className: cn("justify-between gap-1", className),
|
|
725
|
+
...props
|
|
726
|
+
}
|
|
727
|
+
);
|
|
728
|
+
var PromptInputTools = ({
|
|
729
|
+
className,
|
|
730
|
+
...props
|
|
731
|
+
}) => /* @__PURE__ */ jsx(
|
|
732
|
+
"div",
|
|
733
|
+
{
|
|
734
|
+
className: cn("flex min-w-0 items-center gap-1", className),
|
|
735
|
+
...props
|
|
736
|
+
}
|
|
737
|
+
);
|
|
738
|
+
var PromptInputButton = ({
|
|
739
|
+
variant = "ghost",
|
|
740
|
+
className,
|
|
741
|
+
size,
|
|
742
|
+
tooltip,
|
|
743
|
+
...props
|
|
744
|
+
}) => {
|
|
745
|
+
const newSize = size ?? (Children.count(props.children) > 1 ? "sm" : "icon-sm");
|
|
746
|
+
const button = /* @__PURE__ */ jsx(
|
|
747
|
+
InputGroupButton,
|
|
748
|
+
{
|
|
749
|
+
className: cn(className),
|
|
750
|
+
size: newSize,
|
|
751
|
+
type: "button",
|
|
752
|
+
variant,
|
|
753
|
+
...props
|
|
754
|
+
}
|
|
755
|
+
);
|
|
756
|
+
if (!tooltip) {
|
|
757
|
+
return button;
|
|
758
|
+
}
|
|
759
|
+
const tooltipContent = typeof tooltip === "string" ? tooltip : tooltip.content;
|
|
760
|
+
const shortcut = typeof tooltip === "string" ? void 0 : tooltip.shortcut;
|
|
761
|
+
const side = typeof tooltip === "string" ? "top" : tooltip.side ?? "top";
|
|
762
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
763
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { render: () => button }),
|
|
764
|
+
/* @__PURE__ */ jsxs(TooltipContent, { side, children: [
|
|
765
|
+
tooltipContent,
|
|
766
|
+
shortcut && /* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground", children: shortcut })
|
|
767
|
+
] })
|
|
768
|
+
] });
|
|
769
|
+
};
|
|
770
|
+
var PromptInputActionMenu = (props) => /* @__PURE__ */ jsx(DropdownMenu, { ...props });
|
|
771
|
+
var PromptInputActionMenuTrigger = ({
|
|
772
|
+
className,
|
|
773
|
+
children,
|
|
774
|
+
...props
|
|
775
|
+
}) => /* @__PURE__ */ jsx(
|
|
776
|
+
DropdownMenuTrigger,
|
|
777
|
+
{
|
|
778
|
+
render: () => /* @__PURE__ */ jsx(PromptInputButton, { className, ...props, children: children ?? /* @__PURE__ */ jsx(PlusIcon, { className: "size-4" }) })
|
|
779
|
+
}
|
|
780
|
+
);
|
|
781
|
+
var PromptInputActionMenuContent = ({
|
|
782
|
+
className,
|
|
783
|
+
...props
|
|
784
|
+
}) => /* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: cn(className), ...props });
|
|
785
|
+
var PromptInputActionMenuItem = ({
|
|
786
|
+
className,
|
|
787
|
+
...props
|
|
788
|
+
}) => /* @__PURE__ */ jsx(DropdownMenuItem, { className: cn(className), ...props });
|
|
789
|
+
var PromptInputSubmit = ({
|
|
790
|
+
className,
|
|
791
|
+
variant = "primary",
|
|
792
|
+
size = "icon-sm",
|
|
793
|
+
status,
|
|
794
|
+
onStop,
|
|
795
|
+
onClick,
|
|
796
|
+
children,
|
|
797
|
+
...props
|
|
798
|
+
}) => {
|
|
799
|
+
const isGenerating = status === "submitted" || status === "streaming";
|
|
800
|
+
let Icon = /* @__PURE__ */ jsx(CornerDownLeftIcon, { className: "size-4" });
|
|
801
|
+
if (status === "submitted") {
|
|
802
|
+
Icon = /* @__PURE__ */ jsx(Spinner, {});
|
|
803
|
+
} else if (status === "streaming") {
|
|
804
|
+
Icon = /* @__PURE__ */ jsx(SquareIcon, { className: "size-4" });
|
|
805
|
+
} else if (status === "error") {
|
|
806
|
+
Icon = /* @__PURE__ */ jsx(XIcon, { className: "size-4" });
|
|
807
|
+
}
|
|
808
|
+
const handleClick = useCallback(
|
|
809
|
+
(e) => {
|
|
810
|
+
if (isGenerating && onStop) {
|
|
811
|
+
e.preventDefault();
|
|
812
|
+
onStop();
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
onClick?.(e);
|
|
816
|
+
},
|
|
817
|
+
[isGenerating, onStop, onClick]
|
|
818
|
+
);
|
|
819
|
+
return /* @__PURE__ */ jsx(
|
|
820
|
+
InputGroupButton,
|
|
821
|
+
{
|
|
822
|
+
"aria-label": isGenerating ? "Stop" : "Submit",
|
|
823
|
+
className: cn(className),
|
|
824
|
+
onClick: handleClick,
|
|
825
|
+
size,
|
|
826
|
+
type: isGenerating && onStop ? "button" : "submit",
|
|
827
|
+
variant,
|
|
828
|
+
...props,
|
|
829
|
+
children: children ?? Icon
|
|
830
|
+
}
|
|
831
|
+
);
|
|
832
|
+
};
|
|
833
|
+
var PromptInputSelect = (props) => /* @__PURE__ */ jsx(Select, { ...props });
|
|
834
|
+
var PromptInputSelectTrigger = ({
|
|
835
|
+
className,
|
|
836
|
+
...props
|
|
837
|
+
}) => /* @__PURE__ */ jsx(
|
|
838
|
+
SelectTrigger,
|
|
839
|
+
{
|
|
840
|
+
className: cn(
|
|
841
|
+
"border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors",
|
|
842
|
+
"hover:bg-accent hover:text-foreground aria-expanded:bg-accent aria-expanded:text-foreground",
|
|
843
|
+
className
|
|
844
|
+
),
|
|
845
|
+
...props
|
|
846
|
+
}
|
|
847
|
+
);
|
|
848
|
+
var PromptInputSelectContent = ({
|
|
849
|
+
className,
|
|
850
|
+
...props
|
|
851
|
+
}) => /* @__PURE__ */ jsx(SelectContent, { className: cn(className), ...props });
|
|
852
|
+
var PromptInputSelectItem = ({
|
|
853
|
+
className,
|
|
854
|
+
...props
|
|
855
|
+
}) => /* @__PURE__ */ jsx(SelectItem, { className: cn(className), ...props });
|
|
856
|
+
var PromptInputSelectValue = ({
|
|
857
|
+
className,
|
|
858
|
+
...props
|
|
859
|
+
}) => /* @__PURE__ */ jsx(SelectValue, { className: cn(className), ...props });
|
|
860
|
+
var PromptInputHoverCard = ({
|
|
861
|
+
...props
|
|
862
|
+
}) => /* @__PURE__ */ jsx(HoverCard, { ...props });
|
|
863
|
+
var PromptInputHoverCardTrigger = (props) => /* @__PURE__ */ jsx(HoverCardTrigger, { ...props });
|
|
864
|
+
var PromptInputHoverCardContent = ({
|
|
865
|
+
align = "start",
|
|
866
|
+
...props
|
|
867
|
+
}) => /* @__PURE__ */ jsx(HoverCardContent, { align, ...props });
|
|
868
|
+
var PromptInputTabsList = ({
|
|
869
|
+
className,
|
|
870
|
+
...props
|
|
871
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn(className), ...props });
|
|
872
|
+
var PromptInputTab = ({
|
|
873
|
+
className,
|
|
874
|
+
...props
|
|
875
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn(className), ...props });
|
|
876
|
+
var PromptInputTabLabel = ({
|
|
877
|
+
className,
|
|
878
|
+
...props
|
|
879
|
+
}) => (
|
|
880
|
+
// Content provided via children in props
|
|
881
|
+
// oxlint-disable-next-line eslint-plugin-jsx-a11y(heading-has-content)
|
|
882
|
+
/* @__PURE__ */ jsx(
|
|
883
|
+
"h3",
|
|
884
|
+
{
|
|
885
|
+
className: cn(
|
|
886
|
+
"mb-2 px-3 font-medium text-muted-foreground text-xs",
|
|
887
|
+
className
|
|
888
|
+
),
|
|
889
|
+
...props
|
|
890
|
+
}
|
|
891
|
+
)
|
|
892
|
+
);
|
|
893
|
+
var PromptInputTabBody = ({
|
|
894
|
+
className,
|
|
895
|
+
...props
|
|
896
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("space-y-1", className), ...props });
|
|
897
|
+
var PromptInputTabItem = ({
|
|
898
|
+
className,
|
|
899
|
+
...props
|
|
900
|
+
}) => /* @__PURE__ */ jsx(
|
|
901
|
+
"div",
|
|
902
|
+
{
|
|
903
|
+
className: cn(
|
|
904
|
+
"flex items-center gap-2 px-3 py-2 text-xs hover:bg-accent",
|
|
905
|
+
className
|
|
906
|
+
),
|
|
907
|
+
...props
|
|
908
|
+
}
|
|
909
|
+
);
|
|
910
|
+
var PromptInputCommand = ({
|
|
911
|
+
className,
|
|
912
|
+
...props
|
|
913
|
+
}) => /* @__PURE__ */ jsx(Command, { className: cn(className), ...props });
|
|
914
|
+
var PromptInputCommandInput = ({
|
|
915
|
+
className,
|
|
916
|
+
...props
|
|
917
|
+
}) => /* @__PURE__ */ jsx(CommandInput, { className: cn(className), ...props });
|
|
918
|
+
var PromptInputCommandList = ({
|
|
919
|
+
className,
|
|
920
|
+
...props
|
|
921
|
+
}) => /* @__PURE__ */ jsx(CommandList, { className: cn(className), ...props });
|
|
922
|
+
var PromptInputCommandEmpty = ({
|
|
923
|
+
className,
|
|
924
|
+
...props
|
|
925
|
+
}) => /* @__PURE__ */ jsx(CommandEmpty, { className: cn(className), ...props });
|
|
926
|
+
var PromptInputCommandGroup = ({
|
|
927
|
+
className,
|
|
928
|
+
...props
|
|
929
|
+
}) => /* @__PURE__ */ jsx(CommandGroup, { className: cn(className), ...props });
|
|
930
|
+
var PromptInputCommandItem = ({
|
|
931
|
+
className,
|
|
932
|
+
...props
|
|
933
|
+
}) => /* @__PURE__ */ jsx(CommandItem, { className: cn(className), ...props });
|
|
934
|
+
var PromptInputCommandSeparator = ({
|
|
935
|
+
className,
|
|
936
|
+
...props
|
|
937
|
+
}) => /* @__PURE__ */ jsx(CommandSeparator, { className: cn(className), ...props });
|
|
938
|
+
|
|
939
|
+
export { LocalReferencedSourcesContext, PromptInput, PromptInputActionAddAttachments, PromptInputActionAddScreenshot, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuItem, PromptInputActionMenuTrigger, PromptInputBody, PromptInputButton, PromptInputCommand, PromptInputCommandEmpty, PromptInputCommandGroup, PromptInputCommandInput, PromptInputCommandItem, PromptInputCommandList, PromptInputCommandSeparator, PromptInputFooter, PromptInputHeader, PromptInputHoverCard, PromptInputHoverCardContent, PromptInputHoverCardTrigger, PromptInputProvider, PromptInputSelect, PromptInputSelectContent, PromptInputSelectItem, PromptInputSelectTrigger, PromptInputSelectValue, PromptInputSubmit, PromptInputTab, PromptInputTabBody, PromptInputTabItem, PromptInputTabLabel, PromptInputTabsList, PromptInputTextarea, PromptInputTools, usePromptInputAttachments, usePromptInputController, usePromptInputReferencedSources, useProviderAttachments };
|