"use client"; import { useControllableState } from "@radix-ui/react-use-controllable-state"; import { Badge } from "@/components/ui/badge"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { cn } from "@/lib/utils"; import { BrainIcon, ChevronDownIcon, DotIcon, type LucideIcon, } from "lucide-react"; import type { ComponentProps, ReactNode } from "react"; import { createContext, memo, useContext, useMemo } from "react"; type ChainOfThoughtContextValue = { isOpen: boolean; setIsOpen: (open: boolean) => void; }; const ChainOfThoughtContext = createContext( null, ); const useChainOfThought = () => { const context = useContext(ChainOfThoughtContext); if (!context) { throw new Error( "ChainOfThought components must be used within ChainOfThought", ); } return context; }; export type ChainOfThoughtProps = ComponentProps<"div"> & { open?: boolean; defaultOpen?: boolean; onOpenChange?: (open: boolean) => void; }; export const ChainOfThought = memo( ({ className, open, defaultOpen = false, onOpenChange, children, ...props }: ChainOfThoughtProps) => { const [isOpen, setIsOpen] = useControllableState({ prop: open, defaultProp: defaultOpen, onChange: onOpenChange, }); const chainOfThoughtContext = useMemo( () => ({ isOpen, setIsOpen }), [isOpen, setIsOpen], ); return (
{children}
); }, ); export type ChainOfThoughtHeaderProps = ComponentProps< typeof CollapsibleTrigger > & { icon?: React.ReactElement; }; export const ChainOfThoughtHeader = memo( ({ className, children, icon, ...props }: ChainOfThoughtHeaderProps) => { const { isOpen, setIsOpen } = useChainOfThought(); return ( {icon ?? } {children ?? "Chain of Thought"} ); }, ); export type ChainOfThoughtStepProps = ComponentProps<"div"> & { icon?: LucideIcon; label: ReactNode; description?: ReactNode; status?: "complete" | "active" | "pending"; }; export const ChainOfThoughtStep = memo( ({ className, icon: Icon = DotIcon, label, description, status = "complete", children, ...props }: ChainOfThoughtStepProps) => { const statusStyles = { complete: "text-muted-foreground", active: "text-foreground", pending: "text-muted-foreground/50", }; return (
{label}
{description && (
{description}
)} {children}
); }, ); export type ChainOfThoughtSearchResultsProps = ComponentProps<"div">; export const ChainOfThoughtSearchResults = memo( ({ className, ...props }: ChainOfThoughtSearchResultsProps) => (
), ); export type ChainOfThoughtSearchResultProps = ComponentProps; export const ChainOfThoughtSearchResult = memo( ({ className, children, ...props }: ChainOfThoughtSearchResultProps) => ( {children} ), ); export type ChainOfThoughtContentProps = ComponentProps< typeof CollapsibleContent >; export const ChainOfThoughtContent = memo( ({ className, children, ...props }: ChainOfThoughtContentProps) => { const { isOpen } = useChainOfThought(); return ( {children} ); }, ); export type ChainOfThoughtImageProps = ComponentProps<"div"> & { caption?: string; }; export const ChainOfThoughtImage = memo( ({ className, children, caption, ...props }: ChainOfThoughtImageProps) => (
{children}
{caption &&

{caption}

}
), ); ChainOfThought.displayName = "ChainOfThought"; ChainOfThoughtHeader.displayName = "ChainOfThoughtHeader"; ChainOfThoughtStep.displayName = "ChainOfThoughtStep"; ChainOfThoughtSearchResults.displayName = "ChainOfThoughtSearchResults"; ChainOfThoughtSearchResult.displayName = "ChainOfThoughtSearchResult"; ChainOfThoughtContent.displayName = "ChainOfThoughtContent"; ChainOfThoughtImage.displayName = "ChainOfThoughtImage";