({
initialInput: initialTextInput = "",
children,
}: PromptInputProviderProps)
| 169 | * If you don't use it, PromptInput stays fully self-managed. |
| 170 | */ |
| 171 | export const PromptInputProvider = ({ |
| 172 | initialInput: initialTextInput = "", |
| 173 | children, |
| 174 | }: PromptInputProviderProps) => { |
| 175 | // ----- textInput state |
| 176 | const [textInput, setTextInput] = useState(initialTextInput); |
| 177 | const clearInput = useCallback(() => setTextInput(""), []); |
| 178 | |
| 179 | // ----- attachments state (global when wrapped) |
| 180 | const [attachmentFiles, setAttachmentFiles] = useState< |
| 181 | (FileUIPart & { id: string })[] |
| 182 | >([]); |
| 183 | const fileInputRef = useRef<HTMLInputElement | null>(null); |
| 184 | // oxlint-disable-next-line eslint(no-empty-function) |
| 185 | const openRef = useRef<() => void>(() => {}); |
| 186 | |
| 187 | const add = useCallback((files: File[] | FileList) => { |
| 188 | const incoming = [...files]; |
| 189 | if (incoming.length === 0) { |
| 190 | return; |
| 191 | } |
| 192 | |
| 193 | setAttachmentFiles((prev) => [ |
| 194 | ...prev, |
| 195 | ...incoming.map((file) => ({ |
| 196 | filename: file.name, |
| 197 | id: nanoid(), |
| 198 | mediaType: file.type, |
| 199 | type: "file" as const, |
| 200 | url: URL.createObjectURL(file), |
| 201 | })), |
| 202 | ]); |
| 203 | }, []); |
| 204 | |
| 205 | const remove = useCallback((id: string) => { |
| 206 | setAttachmentFiles((prev) => { |
| 207 | const found = prev.find((f) => f.id === id); |
| 208 | if (found?.url) { |
| 209 | URL.revokeObjectURL(found.url); |
| 210 | } |
| 211 | return prev.filter((f) => f.id !== id); |
| 212 | }); |
| 213 | }, []); |
| 214 | |
| 215 | const clear = useCallback(() => { |
| 216 | setAttachmentFiles((prev) => { |
| 217 | for (const f of prev) { |
| 218 | if (f.url) { |
| 219 | URL.revokeObjectURL(f.url); |
| 220 | } |
| 221 | } |
| 222 | return []; |
| 223 | }); |
| 224 | }, []); |
| 225 | |
| 226 | // Keep a ref to attachments for cleanup on unmount (avoids stale closure) |
| 227 | const attachmentsRef = useRef(attachmentFiles); |
| 228 |
nothing calls this directly
no outgoing calls
no test coverage detected