"use client" import * as React from "react" import { cn } from "@/lib/utils" /* ═══════════════════════════════════════════════════════════════════════════ TERMINAL WINDOW ═══════════════════════════════════════════════════════════════════════════ */ interface TerminalProps extends React.HTMLAttributes { title?: string } const Terminal = React.forwardRef( ({ className, title = "terminal", children, ...props }, ref) => { return (
{/* Header */}
{title}
{/* Body */}
{children}
) } ) Terminal.displayName = "Terminal" /* ═══════════════════════════════════════════════════════════════════════════ TERMINAL LINE ═══════════════════════════════════════════════════════════════════════════ */ interface TerminalLineProps extends React.HTMLAttributes { prompt?: string command?: string output?: string isTyping?: boolean } const TerminalLine = React.forwardRef( ({ className, prompt = "$", command, output, isTyping = false, ...props }, ref) => { return (
{command && (
{prompt} {command} {isTyping && ( )}
)} {output && (
{output}
)}
) } ) TerminalLine.displayName = "TerminalLine" /* ═══════════════════════════════════════════════════════════════════════════ CODE BLOCK ═══════════════════════════════════════════════════════════════════════════ */ interface CodeBlockProps extends React.HTMLAttributes { language?: string filename?: string showLineNumbers?: boolean } const CodeBlock = React.forwardRef( ({ className, language, filename, showLineNumbers = false, children, ...props }, ref) => { const lines = typeof children === 'string' ? children.split('\n') : [] return (
{(language || filename) && (
{filename && ( {filename} )} {language && ( {language} )}
)}
          {showLineNumbers && typeof children === 'string' ? (
            
              {lines.map((line, i) => (
                
{i + 1} {line}
))}
) : ( {children} )}
) } ) CodeBlock.displayName = "CodeBlock" /* ═══════════════════════════════════════════════════════════════════════════ COMMAND PROMPT INPUT ═══════════════════════════════════════════════════════════════════════════ */ interface CommandInputProps extends React.InputHTMLAttributes { prompt?: string onCommand?: (command: string) => void } const CommandInput = React.forwardRef( ({ className, prompt = ">", onCommand, ...props }, ref) => { const [value, setValue] = React.useState("") const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && value.trim()) { onCommand?.(value.trim()) setValue("") } } return (
{prompt} setValue(e.target.value)} onKeyDown={handleKeyDown} className="flex-1 bg-transparent outline-none placeholder:text-[var(--terminal-green)]/40" style={{ textShadow: "0 0 10px rgba(0,255,0,0.3)" }} {...props} />
) } ) CommandInput.displayName = "CommandInput" /* ═══════════════════════════════════════════════════════════════════════════ MATRIX RAIN (Decorative) ═══════════════════════════════════════════════════════════════════════════ */ interface MatrixRainProps extends React.HTMLAttributes { density?: number } const MatrixRain = React.forwardRef( ({ className, density = 20, ...props }, ref) => { const characters = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン0123456789" return (
{Array.from({ length: density }).map((_, i) => (
{Array.from({ length: 20 }).map((_, j) => (
{characters[Math.floor(Math.random() * characters.length)]}
))}
))}
) } ) MatrixRain.displayName = "MatrixRain" /* ═══════════════════════════════════════════════════════════════════════════ ASCII ART BOX ═══════════════════════════════════════════════════════════════════════════ */ interface AsciiBoxProps extends React.HTMLAttributes { title?: string variant?: "single" | "double" | "rounded" } const AsciiBox = React.forwardRef( ({ className, title, variant = "single", children, ...props }, ref) => { const chars = { single: { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" }, double: { tl: "╔", tr: "╗", bl: "╚", br: "╝", h: "═", v: "║" }, rounded: { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│" }, } const c = chars[variant] return (
{c.tl}{c.h.repeat(title ? title.length + 2 : 30)}{c.tr}
{title && (
{c.v} {title} {c.v}
)}
{children}
{c.bl}{c.h.repeat(title ? title.length + 2 : 30)}{c.br}
) } ) AsciiBox.displayName = "AsciiBox" export { Terminal, TerminalLine, CodeBlock, CommandInput, MatrixRain, AsciiBox, }