/* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck "use client" import Ansi from "ansi-to-react" import { CheckIcon, CopyIcon, TerminalIcon, Trash2Icon } from "lucide-react" import { type ComponentProps, createContext, type HTMLAttributes, useContext, useEffect, useRef, useState, } from "react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" import { Shimmer } from "./shimmer" interface TerminalContextType { output: string isStreaming: boolean autoScroll: boolean onClear?: () => void } const TerminalContext = createContext({ output: "", isStreaming: false, autoScroll: true, }) export type TerminalProps = HTMLAttributes & { output: string isStreaming?: boolean autoScroll?: boolean onClear?: () => void } export const Terminal = ({ output, isStreaming = false, autoScroll = true, onClear, className, children, ...props }: TerminalProps) => (
{children ?? ( <>
{onClear && }
)}
) export type TerminalHeaderProps = HTMLAttributes export const TerminalHeader = ({ className, children, ...props }: TerminalHeaderProps) => (
{children}
) export type TerminalTitleProps = HTMLAttributes export const TerminalTitle = ({ className, children, ...props }: TerminalTitleProps) => (
{children ?? "Terminal"}
) export type TerminalStatusProps = HTMLAttributes export const TerminalStatus = ({ className, children, ...props }: TerminalStatusProps) => { const { isStreaming } = useContext(TerminalContext) if (!isStreaming) { return null } return (
{children ?? }
) } export type TerminalActionsProps = HTMLAttributes export const TerminalActions = ({ className, children, ...props }: TerminalActionsProps) => (
{children}
) export type TerminalCopyButtonProps = ComponentProps & { onCopy?: () => void onError?: (error: Error) => void timeout?: number } export const TerminalCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }: TerminalCopyButtonProps) => { const [isCopied, setIsCopied] = useState(false) const { output } = useContext(TerminalContext) const copyToClipboard = async () => { if (typeof window === "undefined" || !navigator?.clipboard?.writeText) { onError?.(new Error("Clipboard API not available")) return } try { await navigator.clipboard.writeText(output) setIsCopied(true) onCopy?.() setTimeout(() => setIsCopied(false), timeout) } catch (error) { onError?.(error as Error) } } const Icon = isCopied ? CheckIcon : CopyIcon return ( ) } export type TerminalClearButtonProps = ComponentProps export const TerminalClearButton = ({ children, className, ...props }: TerminalClearButtonProps) => { const { onClear } = useContext(TerminalContext) if (!onClear) { return null } return ( ) } export type TerminalContentProps = HTMLAttributes export const TerminalContent = ({ className, children, ...props }: TerminalContentProps) => { const { output, isStreaming, autoScroll } = useContext(TerminalContext) const containerRef = useRef(null) useEffect(() => { if (autoScroll && containerRef.current) { containerRef.current.scrollTop = containerRef.current.scrollHeight } }, [output, autoScroll]) return (
{children ?? (
          {output}
          {isStreaming && (
            
          )}
        
)}
) } /** Demo component for preview */ export default function TerminalDemo() { const [output, setOutput] = useState( "\x1b[32m✓\x1b[0m Compiled successfully in 1.2s\n\x1b[34m→\x1b[0m Building pages...\n\x1b[33m⚠\x1b[0m Warning: Large bundle size detected\n\x1b[32m✓\x1b[0m Generated 24 static pages\n\x1b[32m✓\x1b[0m Build completed", ) return (
setOutput("")} />
) }