"use client" import { Textarea } from "@/components/ui/textarea" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { cn } from "@/lib/utils" import React, { createContext, useContext, useLayoutEffect, useRef, useState, } from "react" type PromptInputContextType = { isLoading: boolean value: string setValue: (value: string) => void maxHeight: number | string onSubmit?: () => void disabled?: boolean textareaRef: React.RefObject } const PromptInputContext = createContext({ isLoading: false, value: "", setValue: () => {}, maxHeight: 240, onSubmit: undefined, disabled: false, textareaRef: React.createRef(), }) function usePromptInput() { return useContext(PromptInputContext) } export type PromptInputProps = { isLoading?: boolean value?: string onValueChange?: (value: string) => void maxHeight?: number | string onSubmit?: () => void children: React.ReactNode className?: string disabled?: boolean } & React.ComponentProps<"div"> function PromptInput({ className, isLoading = false, maxHeight = 240, value, onValueChange, onSubmit, children, disabled = false, onClick, ...props }: PromptInputProps) { const [internalValue, setInternalValue] = useState(value || "") const textareaRef = useRef(null) const handleChange = (newValue: string) => { setInternalValue(newValue) onValueChange?.(newValue) } const handleClick: React.MouseEventHandler = (e) => { if (!disabled) textareaRef.current?.focus() onClick?.(e) } return (
{children}
) } export type PromptInputTextareaProps = { disableAutosize?: boolean } & React.ComponentProps function PromptInputTextarea({ className, onKeyDown, disableAutosize = false, ...props }: PromptInputTextareaProps) { const { value, setValue, maxHeight, onSubmit, disabled, textareaRef } = usePromptInput() const adjustHeight = (el: HTMLTextAreaElement | null) => { if (!el || disableAutosize) return el.style.height = "auto" if (typeof maxHeight === "number") { el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px` } else { el.style.height = `min(${el.scrollHeight}px, ${maxHeight})` } } const handleRef = (el: HTMLTextAreaElement | null) => { textareaRef.current = el adjustHeight(el) } useLayoutEffect(() => { if (!textareaRef.current || disableAutosize) return const el = textareaRef.current el.style.height = "auto" if (typeof maxHeight === "number") { el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px` } else { el.style.height = `min(${el.scrollHeight}px, ${maxHeight})` } // eslint-disable-next-line react-hooks/exhaustive-deps }, [value, maxHeight, disableAutosize]) const handleChange = (e: React.ChangeEvent) => { adjustHeight(e.target) setValue(e.target.value) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault() onSubmit?.() } onKeyDown?.(e) } return (