UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

109 lines (108 loc) 8.37 kB
// @ts-nocheck "use client"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useCallback, useEffect, useRef, useState } from "react"; import { AnimatePresence, motion } from "framer-motion"; import { Globe, Paperclip, Plus, Send } from "lucide-react"; import { cn } from "../../lib/utils"; import { Textarea } from "./textarea"; function useAutoResizeTextarea({ minHeight, maxHeight, }) { const textareaRef = useRef(null); const adjustHeight = useCallback((reset) => { const textarea = textareaRef.current; if (!textarea) return; if (reset) { textarea.style.height = `${minHeight}px`; return; } textarea.style.height = `${minHeight}px`; const newHeight = Math.max(minHeight, Math.min(textarea.scrollHeight, maxHeight ?? Number.POSITIVE_INFINITY)); textarea.style.height = `${newHeight}px`; }, [minHeight, maxHeight]); useEffect(() => { const textarea = textareaRef.current; if (textarea) { textarea.style.height = `${minHeight}px`; } }, [minHeight]); useEffect(() => { const handleResize = () => adjustHeight(); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, [adjustHeight]); return { textareaRef, adjustHeight }; } const MIN_HEIGHT = 48; const MAX_HEIGHT = 164; const AnimatedPlaceholder = ({ showSearch }) => (_jsx(AnimatePresence, { mode: "wait", children: _jsx(motion.p, { initial: { opacity: 0, y: 5 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -5 }, transition: { duration: 0.1 }, className: "pointer-events-none w-[1500px] text-sm absolute \r\n text-black/70 dark:text-white/70", children: showSearch ? "Search the web..." : "Ask Skiper Ai..." }, showSearch ? "search" : "ask") })); export function AiInput() { const [value, setValue] = useState(""); const { textareaRef, adjustHeight } = useAutoResizeTextarea({ minHeight: MIN_HEIGHT, maxHeight: MAX_HEIGHT, }); const [showSearch, setShowSearch] = useState(true); const [imagePreview, setImagePreview] = useState(null); const fileInputRef = useRef(null); const handelClose = (e) => { e.preventDefault(); e.stopPropagation(); if (fileInputRef.current) { fileInputRef.current.value = ""; // Reset file input } setImagePreview(null); // Use null instead of empty string }; const handelChange = (e) => { const file = e.target.files ? e.target.files[0] : null; if (file) { setImagePreview(URL.createObjectURL(file)); } }; const handleSubmit = () => { setValue(""); adjustHeight(true); }; useEffect(() => { return () => { if (imagePreview) { URL.revokeObjectURL(imagePreview); } }; }, [imagePreview]); return (_jsx("div", { className: "mx-auto lg:min-w-[400px] w-full py-4", children: _jsx("div", { className: "relative max-w-xl border rounded-[22px] border-black/5 p-1 w-full mx-auto", children: _jsxs("div", { className: "relative rounded-2xl border border-black/5 bg-neutral-800/5 flex flex-col", children: [_jsx("div", { style: { maxHeight: `${MAX_HEIGHT}px` }, children: _jsxs("div", { className: "relative", children: [_jsx(Textarea, { id: "ai-input-04", value: value, placeholder: "", className: "w-full rounded-2xl rounded-b-none px-4 py-3 bg-black/5 dark:bg-white/5 border-none dark:text-white resize-none focus-visible:ring-0 leading-[1.2]", ref: textareaRef, onKeyDown: (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleSubmit(); } }, onChange: (e) => { setValue(e.target.value); adjustHeight(); } }), !value && (_jsx("div", { className: "absolute left-4 top-3", children: _jsx(AnimatedPlaceholder, { showSearch: showSearch }) }))] }) }), _jsxs("div", { className: "h-12 bg-black/5 dark:bg-white/5 rounded-b-xl", children: [_jsxs("div", { className: "absolute left-3 bottom-3 flex items-center gap-2", children: [_jsxs("label", { className: cn("cursor-pointer relative rounded-full p-2 bg-black/5 dark:bg-white/5", imagePreview ? "bg-[#ff3f17]/15 border border-[#ff3f17] text-[#ff3f17]" : "bg-black/5 dark:bg-white/5 text-black/40 dark:text-white/40 hover:text-black dark:hover:text-white"), children: [_jsx("input", { type: "file", ref: fileInputRef, onChange: handelChange, className: "hidden" }), _jsx(Paperclip, { className: cn("w-4 h-4 text-black/40 dark:text-white/40 hover:text-black dark:hover:text-white transition-colors", imagePreview && "text-[#ff3f17]") }), imagePreview && (_jsxs("div", { className: "absolute w-[100px] h-[100px] top-14 -left-4", children: [_jsx("img", { className: "object-cover rounded-2xl", src: imagePreview || "/picture1.jpeg", height: 500, width: 500, alt: "additional image" }), _jsx("button", { onClick: handelClose, className: "bg-[#e8e8e8] text-[#464646] absolute -top-1 -left-1 shadow-3xl rounded-full rotate-45", children: _jsx(Plus, { className: "w-4 h-4" }) })] }))] }), _jsxs("button", { type: "button", onClick: () => { setShowSearch(!showSearch); }, className: cn("rounded-full transition-all flex items-center gap-2 px-1.5 py-1 border h-8", showSearch ? "bg-[#ff3f17]/15 border-[#ff3f17] text-[#ff3f17]" : "bg-black/5 dark:bg-white/5 border-transparent text-black/40 dark:text-white/40 hover:text-black dark:hover:text-white"), children: [_jsx("div", { className: "w-4 h-4 flex items-center justify-center flex-shrink-0", children: _jsx(motion.div, { animate: { rotate: showSearch ? 180 : 0, scale: showSearch ? 1.1 : 1, }, whileHover: { rotate: showSearch ? 180 : 15, scale: 1.1, transition: { type: "spring", stiffness: 300, damping: 10, }, }, transition: { type: "spring", stiffness: 260, damping: 25, }, children: _jsx(Globe, { className: cn("w-4 h-4", showSearch ? "text-[#ff3f17]" : "text-inherit") }) }) }), _jsx(AnimatePresence, { children: showSearch && (_jsx(motion.span, { initial: { width: 0, opacity: 0 }, animate: { width: "auto", opacity: 1, }, exit: { width: 0, opacity: 0 }, transition: { duration: 0.2 }, className: "text-sm overflow-hidden whitespace-nowrap text-[#ff3f17] flex-shrink-0", children: "Search" })) })] })] }), _jsx("div", { className: "absolute right-3 bottom-3", children: _jsx("button", { type: "button", onClick: handleSubmit, className: cn("rounded-full p-2 transition-colors", value ? "bg-[#ff3f17]/15 text-[#ff3f17]" : "bg-black/5 dark:bg-white/5 text-black/40 dark:text-white/40 hover:text-black dark:hover:text-white"), children: _jsx(Send, { className: "w-4 h-4" }) }) })] })] }) }) })); }