"use client"; import { RemoveScroll } from "react-remove-scroll"; import { type ComponentProps, createContext, SVGProps, type SyntheticEvent, use, useEffect, useMemo, useRef, useState, } from "react"; import { Loader2, SearchIcon, Send, Trash2, X } from "lucide-react"; import { cn } from "@/lib/utils"; import { buttonVariants } from "fumadocs-ui/components/ui/button"; import Link from "fumadocs-core/link"; import { type UIMessage, useChat, type UseChatHelpers } from "@ai-sdk/react"; import type { ProvideLinksToolSchema } from "@/lib/chat/inkeep-qa-schema"; import type { z } from "zod"; import { DefaultChatTransport } from "ai"; import { Markdown } from "./markdown"; import { Presence } from "@radix-ui/react-presence"; import { MessageFeedback } from "./message-feedback"; const Context = createContext<{ open: boolean; setOpen: (open: boolean) => void; chat: UseChatHelpers; } | null>(null); function useChatContext() { return use(Context)!.chat; } // function SearchAIActions() { // const { messages, status, setMessages, stop } = useChatContext(); // const isGenerating = status === "streaming" || status === "submitted"; // if (messages.length === 0) return null; // return ( // <> // // // ); // } const suggestions = [ "How to configure Sqlite database?", "How to require email verification?", "How to change session expiry?", "How to share cookies across subdomains?", ]; function SearchAIInput(props: ComponentProps<"form">) { const { status, sendMessage, stop, messages, setMessages } = useChatContext(); const [input, setInput] = useState(""); const isLoading = status === "streaming" || status === "submitted"; const showSuggestions = messages.length === 0 && !isLoading; const onStart = (e?: SyntheticEvent) => { e?.preventDefault(); void sendMessage({ text: input }); setInput(""); }; const handleSuggestionClick = (suggestion: string) => { void sendMessage({ text: suggestion }); }; const handleClear = () => { setMessages([]); setInput(""); }; useEffect(() => { if (isLoading) document.getElementById("nd-ai-input")?.focus(); }, [isLoading]); return (
{ setInput(e.target.value); }} onKeyDown={(event) => { if (!event.shiftKey && event.key === "Enter") { onStart(event); } }} /> {isLoading ? ( ) : ( )}
{showSuggestions && (

Try asking:

{suggestions.slice(0, 4).map((suggestion, i) => ( ))}
)} {showSuggestions && (
Powered by{" "} Inkeep. AI can be inaccurate, please verify the information.
)} {!showSuggestions && (
{ if (!isLoading) { handleClear(); } }} >

Clear

)}
); } function List( props: Omit, "dir"> & { messageCount: number }, ) { const containerRef = useRef(null); const isUserScrollingRef = useRef(false); const prevMessageCountRef = useRef(props.messageCount); // Scroll to bottom when new message is submitted useEffect(() => { if (props.messageCount > prevMessageCountRef.current) { // New message submitted, reset scroll lock and scroll to bottom isUserScrollingRef.current = false; if (containerRef.current) { containerRef.current.scrollTo({ top: containerRef.current.scrollHeight, behavior: "smooth", }); } } prevMessageCountRef.current = props.messageCount; }, [props.messageCount]); useEffect(() => { if (!containerRef.current) return; function callback() { const container = containerRef.current; if (!container) return; // Only auto-scroll if user hasn't manually scrolled up if (!isUserScrollingRef.current) { container.scrollTo({ top: container.scrollHeight, behavior: "instant", }); } } const observer = new ResizeObserver(callback); callback(); const element = containerRef.current?.firstElementChild; if (element) { observer.observe(element); } return () => { observer.disconnect(); }; }, []); // Track when user manually scrolls useEffect(() => { const container = containerRef.current; if (!container) return; const handleScroll = () => { const { scrollTop, scrollHeight, clientHeight } = container; const isNearBottom = scrollHeight - scrollTop - clientHeight < 50; // If user is near bottom, enable auto-scroll, otherwise disable it isUserScrollingRef.current = !isNearBottom; }; container.addEventListener("scroll", handleScroll); return () => container.removeEventListener("scroll", handleScroll); }, []); return (
{props.children}
); } function Input(props: ComponentProps<"textarea">) { const ref = useRef(null); const shared = cn("col-start-1 row-start-1", props.className); return (