green-screen-react 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/GreenScreenTerminal.tsx","../src/hooks/useTN5250.ts","../src/hooks/useTypingAnimation.ts","../src/utils/grid.ts","../src/protocols/tn5250.ts","../src/protocols/tn3270.ts","../src/protocols/vt.ts","../src/protocols/hp6530.ts","../src/protocols/registry.ts","../src/components/TerminalBootLoader.tsx","../src/adapters/RestAdapter.ts","../src/utils/rendering.ts"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';\nimport type { TerminalAdapter, ScreenData, ConnectionStatus, Field, TerminalProtocol, ProtocolProfile, ConnectConfig } from '../adapters/types';\nimport { useTerminalScreen, useTerminalInput, useTerminalConnection } from '../hooks/useTN5250';\nimport { useTypingAnimation } from '../hooks/useTypingAnimation';\nimport { getProtocolProfile } from '../protocols/registry';\nimport { TerminalBootLoader as DefaultBootLoader } from './TerminalBootLoader';\n\n/* ── Inline SVG Icons (no external dependency) ────────────────────── */\n\nconst TerminalIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 17 10 11 4 5\" /><line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\" />\n </svg>\n);\n\nconst WifiIcon = ({ size = 12, className, style: s }: { size?: number; className?: string; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className} style={s}>\n <path d=\"M5 12.55a11 11 0 0 1 14.08 0\" /><path d=\"M1.42 9a16 16 0 0 1 21.16 0\" /><path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" /><line x1=\"12\" y1=\"20\" x2=\"12.01\" y2=\"20\" />\n </svg>\n);\n\nconst WifiOffIcon = ({ size = 12, className, style: s }: { size?: number; className?: string; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className} style={s}>\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" /><path d=\"M16.72 11.06A10.94 10.94 0 0 1 19 12.55\" /><path d=\"M5 12.55a10.94 10.94 0 0 1 5.17-2.39\" /><path d=\"M10.71 5.05A16 16 0 0 1 22.56 9\" /><path d=\"M1.42 9a15.91 15.91 0 0 1 4.7-2.88\" /><path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" /><line x1=\"12\" y1=\"20\" x2=\"12.01\" y2=\"20\" />\n </svg>\n);\n\nconst AlertTriangleIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" /><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" /><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n);\n\nconst RefreshIcon = ({ size = 12, className }: { size?: number; className?: string }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"23 4 23 10 17 10\" /><polyline points=\"1 20 1 14 7 14\" /><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\" />\n </svg>\n);\n\nconst KeyIcon = ({ size = 12, style: s }: { size?: number; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={s}>\n <path d=\"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4\" />\n </svg>\n);\n\nconst MinimizeIcon = () => (\n <svg width={14} height={14} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 14h6v6M3 21l7-7M20 10h-6V4M21 3l-7 7\" />\n </svg>\n);\n\n/* ── Inline Sign-In Form ─────────────────────────────────────────── */\n\nconst PROTOCOL_OPTIONS: { value: TerminalProtocol; label: string }[] = [\n { value: 'tn5250', label: 'TN5250 (IBM i)' },\n { value: 'tn3270', label: 'TN3270 (Mainframe)' },\n { value: 'vt', label: 'VT220' },\n { value: 'hp6530', label: 'HP 6530 (NonStop)' },\n];\n\ninterface InlineSignInProps {\n defaultProtocol: TerminalProtocol;\n loading: boolean;\n error: string | null;\n onConnect: (config: ConnectConfig) => void;\n}\n\nfunction InlineSignIn({ defaultProtocol, loading, error, onConnect }: InlineSignInProps) {\n const [host, setHost] = useState('');\n const [port, setPort] = useState('');\n const [selectedProtocol, setSelectedProtocol] = useState<TerminalProtocol>(defaultProtocol);\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onConnect({\n host,\n port: port ? parseInt(port, 10) : undefined,\n protocol: selectedProtocol,\n username,\n password,\n });\n };\n\n const inputStyle: React.CSSProperties = {\n width: '100%',\n padding: '6px 8px',\n backgroundColor: 'rgba(16, 185, 129, 0.05)',\n border: '1px solid var(--gs-card-border, #1e293b)',\n color: 'var(--gs-green, #10b981)',\n fontFamily: 'var(--gs-font)',\n fontSize: '13px',\n outline: 'none',\n boxSizing: 'border-box',\n };\n\n const labelStyle: React.CSSProperties = {\n display: 'block',\n marginBottom: '4px',\n fontSize: '10px',\n letterSpacing: '0.1em',\n textTransform: 'uppercase',\n color: 'var(--gs-muted, #94a3b8)',\n fontFamily: 'var(--gs-font)',\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"gs-signin\">\n <div style={{ textAlign: 'center', marginBottom: '16px' }}>\n <TerminalIcon size={28} />\n <div style={{ fontSize: '11px', letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--gs-muted)', marginTop: '8px' }}>Connect to Host</div>\n </div>\n\n <div className=\"gs-signin-row\">\n <div style={{ flex: 1 }}>\n <label style={labelStyle}>Host</label>\n <input style={inputStyle} value={host} onChange={e => setHost(e.target.value)} placeholder=\"192.168.1.100\" required autoFocus />\n </div>\n <div style={{ width: '72px' }}>\n <label style={labelStyle}>Port</label>\n <input style={inputStyle} value={port} onChange={e => setPort(e.target.value)} placeholder=\"23\" type=\"number\" min=\"1\" max=\"65535\" />\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Protocol</label>\n <select style={{ ...inputStyle, appearance: 'none' }} value={selectedProtocol} onChange={e => setSelectedProtocol(e.target.value as TerminalProtocol)}>\n {PROTOCOL_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}\n </select>\n </div>\n\n <div>\n <label style={labelStyle}>Username</label>\n <input style={inputStyle} value={username} onChange={e => setUsername(e.target.value)} required autoComplete=\"username\" />\n </div>\n\n <div>\n <label style={labelStyle}>Password</label>\n <input style={inputStyle} type=\"password\" value={password} onChange={e => setPassword(e.target.value)} required autoComplete=\"current-password\" />\n </div>\n\n {error && (\n <div style={{ color: '#FF6B00', fontSize: '11px', fontFamily: 'var(--gs-font)', display: 'flex', alignItems: 'center', gap: '6px' }}>\n <AlertTriangleIcon size={12} />\n <span>{error}</span>\n </div>\n )}\n\n <button type=\"submit\" disabled={loading || !host || !username || !password} className=\"gs-signin-btn\">\n {loading ? 'Connecting...' : 'Connect'}\n </button>\n </form>\n );\n}\n\n/* ── Component Props ──────────────────────────────────────────────── */\n\nexport interface GreenScreenTerminalProps {\n /** Adapter for communicating with the terminal backend */\n adapter: TerminalAdapter;\n /** Terminal protocol (determines color conventions, header label, etc.) */\n protocol?: TerminalProtocol;\n /** Custom protocol profile (overrides protocol param) */\n protocolProfile?: ProtocolProfile;\n /** Direct screen data injection (bypasses polling) */\n screenData?: ScreenData | null;\n /** Direct connection status injection */\n connectionStatus?: ConnectionStatus | null;\n\n /** Whether the terminal is read-only (no keyboard input) */\n readOnly?: boolean;\n /** Polling interval in ms (0 to disable polling; default 2000) */\n pollInterval?: number;\n /** Whether to auto-reconnect on disconnect (default true) */\n autoReconnect?: boolean;\n /** Max auto-reconnect attempts (default 5) */\n maxReconnectAttempts?: number;\n\n /** Compact embedded mode */\n embedded?: boolean;\n /** Show the header bar (default true) */\n showHeader?: boolean;\n /** Enable typing animation (default true) */\n typingAnimation?: boolean;\n /** Typing animation budget in ms (default 60) */\n typingBudgetMs?: number;\n\n /** Show inline sign-in form when disconnected (default false) */\n inlineSignIn?: boolean;\n /** Default protocol for the sign-in form dropdown (default 'tn5250') */\n defaultProtocol?: TerminalProtocol;\n /** Callback when sign-in form is submitted */\n onSignIn?: (config: ConnectConfig) => void;\n\n /** Custom boot loader element, or false to disable */\n bootLoader?: React.ReactNode | false;\n /** Content for the right side of the header */\n headerRight?: React.ReactNode;\n /** Overlay content (e.g. \"Extracting...\" state) */\n overlay?: React.ReactNode;\n /** Callback for notifications (replaces toast) */\n onNotification?: (message: string, type: 'info' | 'error') => void;\n /** Callback when screen content changes */\n onScreenChange?: (screen: ScreenData) => void;\n /** Callback for minimize action (embedded mode) */\n onMinimize?: () => void;\n\n /** Additional CSS class name */\n className?: string;\n /** Inline styles */\n style?: React.CSSProperties;\n}\n\n/** @deprecated Use GreenScreenTerminalProps instead */\nexport type TN5250TerminalProps = GreenScreenTerminalProps;\n\n/**\n * GreenScreenTerminal — Multi-protocol legacy terminal emulator component.\n *\n * Renders a terminal screen with:\n * - Green-on-black terminal aesthetic with protocol-specific color conventions\n * - Connection status indicator\n * - Keyboard input support (text, function keys, tab)\n * - Auto-reconnect with exponential backoff\n * - Typing animation for field entries\n * - Focus lock mode for keyboard capture\n *\n * Supports: TN5250 (IBM i), TN3270 (z/OS), VT (OpenVMS/Pick), HP 6530 (NonStop)\n */\nexport function GreenScreenTerminal({\n adapter,\n protocol,\n protocolProfile: customProfile,\n screenData: externalScreenData,\n connectionStatus: externalStatus,\n readOnly = false,\n pollInterval = 2000,\n autoReconnect: autoReconnectEnabled = true,\n maxReconnectAttempts: maxAttempts = 5,\n embedded = false,\n showHeader = true,\n typingAnimation = true,\n typingBudgetMs = 60,\n inlineSignIn = false,\n defaultProtocol: signInDefaultProtocol,\n onSignIn,\n bootLoader,\n headerRight,\n overlay,\n onNotification,\n onScreenChange,\n onMinimize,\n className,\n style,\n}: GreenScreenTerminalProps) {\n const profile = customProfile ?? getProtocolProfile(protocol);\n\n // --- Data sources ---\n const shouldPoll = pollInterval > 0 && !externalScreenData;\n const { data: polledScreenData, error: screenError } = useTerminalScreen(adapter, pollInterval, shouldPoll);\n const { sendText: _sendText, sendKey: _sendKey } = useTerminalInput(adapter);\n const { connect, reconnect, loading: reconnecting, error: connectError } = useTerminalConnection(adapter);\n\n const rawScreenData = externalScreenData ?? polledScreenData;\n\n const connStatus = externalStatus ?? (rawScreenData ? { connected: true, status: 'authenticated' as const } : { connected: false, status: 'disconnected' as const });\n\n // Typing animation\n const { displayedContent, animatedCursorPos } = useTypingAnimation(\n rawScreenData?.content,\n typingAnimation,\n typingBudgetMs,\n );\n\n const screenData = useMemo(() => {\n if (!rawScreenData) return null;\n return { ...rawScreenData, content: displayedContent };\n }, [rawScreenData, displayedContent]);\n\n // Notify parent on screen changes\n const prevScreenSigRef = useRef<string | undefined>(undefined);\n useEffect(() => {\n if (screenData && onScreenChange && screenData.screen_signature !== prevScreenSigRef.current) {\n prevScreenSigRef.current = screenData.screen_signature;\n onScreenChange(screenData);\n }\n }, [screenData, onScreenChange]);\n\n const sendText = useCallback(async (text: string) => _sendText(text), [_sendText]);\n const sendKey = useCallback(async (key: string) => _sendKey(key), [_sendKey]);\n\n // --- UI State ---\n const [inputText, setInputText] = useState('');\n const [isFocused, setIsFocused] = useState(false);\n const terminalRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const [syncedCursor, setSyncedCursor] = useState<{ row: number; col: number } | null>(null);\n const prevRawContentRef = useRef('');\n\n useEffect(() => {\n const newContent = rawScreenData?.content || '';\n if (prevRawContentRef.current && newContent && newContent !== prevRawContentRef.current) {\n setSyncedCursor(null);\n setInputText('');\n }\n prevRawContentRef.current = newContent;\n }, [rawScreenData?.content]);\n\n // --- Auto-reconnect ---\n const [autoReconnectAttempt, setAutoReconnectAttempt] = useState(0);\n const [isAutoReconnecting, setIsAutoReconnecting] = useState(false);\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wasConnectedRef = useRef(false);\n const isConnectedRef = useRef(false);\n\n useEffect(() => { isConnectedRef.current = connStatus?.connected ?? false; }, [connStatus?.connected]);\n\n useEffect(() => {\n if (!autoReconnectEnabled) return;\n const isConnected = connStatus?.connected;\n\n if (isConnected) {\n wasConnectedRef.current = true;\n if (reconnectTimeoutRef.current) { clearTimeout(reconnectTimeoutRef.current); reconnectTimeoutRef.current = null; }\n setAutoReconnectAttempt(0);\n setIsAutoReconnecting(false);\n } else if (wasConnectedRef.current && !isConnected && !isAutoReconnecting && !reconnecting) {\n if (autoReconnectAttempt < maxAttempts) {\n setIsAutoReconnecting(true);\n const delay = Math.pow(2, autoReconnectAttempt) * 1000;\n reconnectTimeoutRef.current = setTimeout(async () => {\n if (isConnectedRef.current) { setIsAutoReconnecting(false); return; }\n onNotification?.(`Auto-reconnect attempt ${autoReconnectAttempt + 1}/${maxAttempts}`, 'info');\n try {\n const result = await reconnect();\n if (!result?.success) setAutoReconnectAttempt(prev => prev + 1);\n } catch {\n onNotification?.('Auto-reconnect failed', 'error');\n setAutoReconnectAttempt(prev => prev + 1);\n }\n setIsAutoReconnecting(false);\n }, delay);\n }\n }\n return () => { if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current); };\n }, [connStatus?.connected, autoReconnectAttempt, isAutoReconnecting, reconnecting, reconnect, autoReconnectEnabled, maxAttempts, onNotification]);\n\n // --- Inline sign-in ---\n const handleSignIn = useCallback(async (config: ConnectConfig) => {\n onSignIn?.(config);\n await connect(config);\n }, [connect, onSignIn]);\n\n // --- Boot loader ---\n const [showBootLoader, setShowBootLoader] = useState(bootLoader !== false);\n const [bootFadingOut, setBootFadingOut] = useState(false);\n\n useEffect(() => {\n if (screenData?.content && showBootLoader) {\n setBootFadingOut(true);\n setShowBootLoader(false);\n const timer = setTimeout(() => setBootFadingOut(false), 400);\n return () => clearTimeout(timer);\n }\n }, [screenData?.content, showBootLoader]);\n\n // --- Focus management ---\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (terminalRef.current && !terminalRef.current.contains(event.target as Node)) setIsFocused(false);\n };\n if (isFocused) document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isFocused]);\n\n useEffect(() => {\n if (readOnly && isFocused) { setIsFocused(false); inputRef.current?.blur(); }\n }, [readOnly, isFocused]);\n\n const handleTerminalClick = useCallback(() => {\n if (readOnly) return;\n setIsFocused(true);\n inputRef.current?.focus();\n }, [readOnly]);\n\n // --- Field helpers ---\n const getCurrentField = useCallback(() => {\n const fields = screenData?.fields || [];\n const cursorRow = syncedCursor?.row ?? screenData?.cursor_row ?? 0;\n const cursorCol = syncedCursor?.col ?? screenData?.cursor_col ?? 0;\n for (const field of fields) {\n if (field.is_input && field.row === cursorRow && cursorCol >= field.col && cursorCol < field.col + field.length) return field;\n }\n return null;\n }, [screenData, syncedCursor]);\n\n const canTypeMore = useCallback((additionalChars: number = 1) => {\n const currentField = getCurrentField();\n if (!currentField) return true;\n const cursorCol = (syncedCursor?.col ?? screenData?.cursor_col ?? 0) + inputText.length;\n return cursorCol + additionalChars <= currentField.col + currentField.length;\n }, [getCurrentField, syncedCursor, screenData, inputText]);\n\n // --- Keyboard handling ---\n const handleKeyDown = async (e: React.KeyboardEvent) => {\n if (readOnly) { e.preventDefault(); return; }\n\n if (e.key === 'Escape') { e.preventDefault(); setIsFocused(false); inputRef.current?.blur(); return; }\n\n if (e.key === 'Backspace') {\n e.preventDefault();\n if (inputText.length > 0) { setInputText(prev => prev.slice(0, -1)); }\n else {\n const keyResult = await sendKey('BACKSPACE');\n if (keyResult.cursor_row !== undefined) setSyncedCursor({ row: keyResult.cursor_row, col: keyResult.cursor_col! });\n }\n return;\n }\n\n const keyMap: Record<string, string> = {\n Enter: 'ENTER', Tab: 'TAB', Delete: 'DELETE',\n ArrowUp: 'UP', ArrowDown: 'DOWN', ArrowLeft: 'LEFT', ArrowRight: 'RIGHT',\n PageUp: 'PAGEUP', PageDown: 'PAGEDOWN', Home: 'HOME', End: 'END', Insert: 'INSERT',\n };\n\n if (e.key.startsWith('F') && e.key.length <= 3) {\n e.preventDefault();\n const fKey = e.key.toUpperCase();\n if (/^F([1-9]|1[0-9]|2[0-4])$/.test(fKey)) {\n if (inputText) {\n const r = await sendText(inputText); setInputText('');\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey(fKey);\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n return;\n }\n }\n\n if (keyMap[e.key]) {\n e.preventDefault();\n if (inputText) {\n const r = await sendText(inputText); setInputText('');\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey(keyMap[e.key]);\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n }\n };\n\n const handleInput = async (e: React.ChangeEvent<HTMLInputElement>) => {\n if (readOnly) { e.target.value = ''; return; }\n const newText = e.target.value;\n if (newText.includes('\\n')) {\n const textToSend = newText.replace('\\n', '');\n if (textToSend) {\n const r = await sendText(textToSend);\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey('ENTER');\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n setInputText(''); e.target.value = '';\n } else {\n const charsToAdd = newText.length - inputText.length;\n if (charsToAdd > 0 && !canTypeMore(charsToAdd)) { e.target.value = inputText; return; }\n setInputText(newText);\n }\n };\n\n // --- Cursor ---\n const termCols = screenData?.cols || profile.defaultCols;\n const getCursorPos = () => {\n if (animatedCursorPos) return animatedCursorPos;\n let cursorRow = syncedCursor?.row ?? screenData?.cursor_row ?? 0;\n let cursorCol = (syncedCursor?.col ?? screenData?.cursor_col ?? 0) + inputText.length;\n while (cursorCol >= termCols) { cursorCol -= termCols; cursorRow += 1; }\n return { row: cursorRow, col: cursorCol };\n };\n\n // --- Rendering helpers ---\n const renderTextWithUnderlines = useCallback((text: string, keyPrefix: string): React.ReactNode => {\n const underscoreRegex = /_{2,}/g;\n const segments: React.ReactNode[] = [];\n let lastIndex = 0;\n let match;\n let segmentIndex = 0;\n while ((match = underscoreRegex.exec(text)) !== null) {\n if (match.index > lastIndex) segments.push(<span key={`${keyPrefix}-t-${segmentIndex}`}>{text.substring(lastIndex, match.index)}</span>);\n const count = match[0].length;\n segments.push(<span key={`${keyPrefix}-u-${segmentIndex}`} style={{ borderBottom: '1px solid var(--gs-green, #10b981)', display: 'inline-block', width: `${count}ch` }}>{' '.repeat(count)}</span>);\n lastIndex = match.index + match[0].length;\n segmentIndex++;\n }\n if (lastIndex < text.length) segments.push(<span key={`${keyPrefix}-e`}>{text.substring(lastIndex)}</span>);\n return segments.length > 0 ? <>{segments}</> : <>{text}</>;\n }, []);\n\n const renderRowWithFields = useCallback((line: string, rowIndex: number, fields: Field[]): React.ReactNode => {\n const inputFields = fields.filter(f => f.row === rowIndex && f.is_input);\n const highlightedFields = fields.filter(f => f.row === rowIndex && f.is_protected && f.is_highlighted);\n const reverseFields = fields.filter(f => f.row === rowIndex && f.is_protected && f.is_reverse);\n const allRowFields = [...inputFields, ...highlightedFields, ...reverseFields];\n\n if (allRowFields.length === 0) return <span>{renderTextWithUnderlines(line, `r${rowIndex}`)}</span>;\n\n const sorted = [...allRowFields].sort((a, b) => a.col - b.col);\n const segs: React.ReactNode[] = [];\n let lastEnd = 0;\n const cols = screenData?.cols || profile.defaultCols;\n\n sorted.forEach((field, idx) => {\n const fs = field.col;\n const fe = Math.min(field.col + field.length, cols);\n if (fs > lastEnd) segs.push(<span key={`t${idx}`}>{renderTextWithUnderlines(line.substring(lastEnd, fs), `r${rowIndex}p${idx}`)}</span>);\n const fc = line.substring(fs, fe);\n if (field.is_input) {\n const w = field.length >= 30 ? Math.max(field.length, 40) : field.length;\n segs.push(<span key={`f${idx}`} className=\"gs-input-field\" style={{ borderBottom: '2px solid var(--gs-green, #10b981)', display: 'inline-block', minWidth: `${w}ch` }}>{fc}</span>);\n } else if (field.is_reverse) {\n segs.push(<span key={`v${idx}`} style={{ color: '#ef4444', fontWeight: 'bold' }}>{fc}</span>);\n } else {\n segs.push(<span key={`h${idx}`} style={{ color: 'var(--gs-white, #FFFFFF)' }}>{fc}</span>);\n }\n lastEnd = fe;\n });\n if (lastEnd < line.length) segs.push(<span key=\"te\">{renderTextWithUnderlines(line.substring(lastEnd), `r${rowIndex}e`)}</span>);\n return <>{segs}</>;\n }, [renderTextWithUnderlines, screenData?.cols, profile.defaultCols]);\n\n // --- Screen rendering ---\n const renderScreen = () => {\n if (showBootLoader && !screenData?.content) {\n if (bootLoader === false) return null;\n if (bootLoader) return <>{bootLoader}</>;\n return <DefaultBootLoader brandText={profile.bootText} />;\n }\n if (bootFadingOut && screenData?.content) return <div className=\"gs-fade-in\">{renderScreenContent()}</div>;\n if (!screenData?.content) {\n if (inlineSignIn && !connStatus?.connected) {\n return (\n <div style={{ width: `${screenData?.cols || profile.defaultCols}ch`, height: `${(screenData?.rows || profile.defaultRows) * 21}px`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <InlineSignIn defaultProtocol={signInDefaultProtocol || protocol || 'tn5250'} loading={reconnecting} error={connectError} onConnect={handleSignIn} />\n </div>\n );\n }\n return (\n <div style={{ width: `${screenData?.cols || profile.defaultCols}ch`, height: `${(screenData?.rows || profile.defaultRows) * 21}px`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <div style={{ textAlign: 'center' }}>\n <div style={{ color: '#808080', marginBottom: '12px' }}><TerminalIcon size={40} /></div>\n <p style={{ fontFamily: 'var(--gs-font)', fontSize: '12px', color: '#808080' }}>\n {connStatus?.connected ? 'Waiting for screen data...' : 'Not connected'}\n </p>\n </div>\n </div>\n );\n }\n return renderScreenContent();\n };\n\n const renderScreenContent = () => {\n if (!screenData?.content) return null;\n const termRows = screenData.rows || profile.defaultRows;\n const cols = screenData.cols || profile.defaultCols;\n const lines = screenData.content.split('\\n');\n const rows: string[] = [];\n for (let i = 0; i < termRows; i++) rows.push((lines[i] || '').padEnd(cols, ' '));\n\n const fields = screenData.fields || [];\n const ROW_HEIGHT = 21;\n const cursor = getCursorPos();\n const hasInputFields = fields.some(f => f.is_input);\n const hasCursor = screenData.cursor_row !== undefined && screenData.cursor_col !== undefined\n && (hasInputFields || screenData.cursor_row !== 0 || screenData.cursor_col !== 0);\n\n return (\n <div style={{ fontFamily: 'var(--gs-font)', fontSize: '13px', position: 'relative', width: `${cols}ch` }}>\n {rows.map((line, index) => {\n let displayLine = line;\n if (hasCursor && index === cursor.row && inputText && !animatedCursorPos) {\n const baseCol = syncedCursor?.col ?? screenData.cursor_col ?? 0;\n displayLine = (line.substring(0, baseCol) + inputText + line.substring(baseCol + inputText.length)).substring(0, cols).padEnd(cols, ' ');\n }\n const headerSegments = index === 0 ? profile.colors.parseHeaderRow(displayLine) : null;\n return (\n <div key={index} className={headerSegments ? '' : profile.colors.getRowColorClass(index, displayLine, termRows)} style={{ height: `${ROW_HEIGHT}px`, lineHeight: `${ROW_HEIGHT}px`, whiteSpace: 'pre', position: 'relative' }}>\n {headerSegments\n ? headerSegments.map((seg, i) => <span key={i} className={seg.colorClass}>{seg.text}</span>)\n : renderRowWithFields(displayLine, index, fields)}\n {hasCursor && index === cursor.row && (\n <span className=\"gs-cursor\" style={{ position: 'absolute', left: `${cursor.col}ch`, width: '1ch', height: `${ROW_HEIGHT}px`, top: 0, pointerEvents: 'none' }} />\n )}\n </div>\n );\n })}\n {screenData.cursor_row !== undefined && screenData.cursor_col !== undefined && (\n <span style={{ position: 'absolute', bottom: 0, right: 0, fontFamily: 'var(--gs-font)', fontSize: '10px', color: 'var(--gs-green, #10b981)', pointerEvents: 'none', opacity: 0.6 }}>\n {String(screenData.cursor_row + 1).padStart(2, '0')}/{String(screenData.cursor_col + 1).padStart(3, '0')}\n </span>\n )}\n </div>\n );\n };\n\n const handleReconnect = async () => {\n setAutoReconnectAttempt(0);\n setIsAutoReconnecting(false);\n if (reconnectTimeoutRef.current) { clearTimeout(reconnectTimeoutRef.current); reconnectTimeoutRef.current = null; }\n await reconnect();\n };\n\n const getStatusColor = (status?: string) => {\n switch (status) {\n case 'authenticated': return 'var(--gs-green, #10b981)';\n case 'connected': return '#F59E0B';\n case 'connecting': return '#64748b';\n case 'error': return '#EF4444';\n default: return '#64748b';\n }\n };\n\n return (\n <div className={`gs-terminal ${isFocused ? 'gs-terminal-focused' : ''} ${className || ''}`} style={style}>\n {showHeader && (\n <div className=\"gs-header\">\n {embedded ? (\n <>\n <span className=\"gs-header-left\">\n <TerminalIcon size={14} />\n <span>TERMINAL</span>\n {isFocused && <span className=\"gs-badge-focused\">FOCUSED</span>}\n {screenData?.timestamp && <span className=\"gs-timestamp\">{new Date(screenData.timestamp).toLocaleTimeString()}</span>}\n <span className=\"gs-hint\">{readOnly ? 'Read-only' : isFocused ? 'ESC to exit focus' : 'Click to control'}</span>\n </span>\n <div className=\"gs-header-right\">\n {connStatus?.status && <KeyIcon size={12} style={{ color: getStatusColor(connStatus.status) }} />}\n {connStatus && (connStatus.connected\n ? <WifiIcon size={12} style={{ color: 'var(--gs-green, #10b981)' }} />\n : <WifiOffIcon size={12} style={{ color: '#FF6B00' }} />)}\n {onMinimize && <button onClick={(e) => { e.stopPropagation(); onMinimize(); }} className=\"gs-btn-icon\" title=\"Minimize terminal\"><MinimizeIcon /></button>}\n {headerRight}\n </div>\n </>\n ) : (\n <>\n <span className=\"gs-header-left\">\n <TerminalIcon size={14} />\n <span>{profile.headerLabel}</span>\n {isFocused && <span className=\"gs-badge-focused\">FOCUSED</span>}\n {screenData?.timestamp && <span className=\"gs-timestamp\">{new Date(screenData.timestamp).toLocaleTimeString()}</span>}\n <span className=\"gs-hint\">{readOnly ? 'Read-only mode' : isFocused ? 'ESC to exit focus' : 'Click terminal to control'}</span>\n </span>\n <div className=\"gs-header-right\">\n {connStatus && (\n <div className=\"gs-status-group\">\n {connStatus.connected ? (\n <>\n <WifiIcon size={12} style={{ color: 'var(--gs-green, #10b981)' }} />\n <span className=\"gs-host\">{connStatus.host}</span>\n </>\n ) : (\n <>\n <WifiOffIcon size={12} style={{ color: '#FF6B00' }} />\n <span className=\"gs-disconnected-text\">\n {isAutoReconnecting || reconnecting\n ? `RECONNECTING${autoReconnectAttempt > 0 ? ` (${autoReconnectAttempt}/${maxAttempts})` : '...'}`\n : autoReconnectAttempt >= maxAttempts ? 'DISCONNECTED (auto-retry exhausted)' : 'DISCONNECTED'}\n </span>\n <button onClick={handleReconnect} disabled={reconnecting || isAutoReconnecting} className=\"gs-btn-icon\" title=\"Reconnect\">\n <RefreshIcon size={12} className={reconnecting || isAutoReconnecting ? 'gs-spin' : ''} />\n </button>\n </>\n )}\n </div>\n )}\n {connStatus?.status && (\n <div className=\"gs-status-group\">\n <KeyIcon size={12} style={{ color: getStatusColor(connStatus.status) }} />\n {connStatus.username && <span className=\"gs-host\">{connStatus.username}</span>}\n </div>\n )}\n {headerRight}\n </div>\n </>\n )}\n </div>\n )}\n\n <div className=\"gs-body\">\n <div ref={terminalRef} onClick={handleTerminalClick} className={`gs-screen ${embedded ? 'gs-screen-embedded' : ''}`}\n style={!embedded ? { width: `calc(${screenData?.cols || profile.defaultCols}ch + 24px)`, fontSize: (screenData?.cols ?? profile.defaultCols) > 80 ? '11px' : '13px', fontFamily: 'var(--gs-font)' } : undefined}>\n {screenError != null && (\n <div className=\"gs-error-banner\">\n <AlertTriangleIcon size={14} />\n <span>{String(screenError)}</span>\n </div>\n )}\n <div className=\"gs-screen-content\">{renderScreen()}</div>\n {overlay}\n {connStatus && !connStatus.connected && screenData && (\n <div className=\"gs-overlay\">\n <WifiOffIcon size={28} />\n <span>{isAutoReconnecting || reconnecting ? 'Reconnecting...' : 'Disconnected'}</span>\n </div>\n )}\n <input ref={inputRef} type=\"text\" value={inputText} onChange={handleInput} onKeyDown={handleKeyDown}\n style={{ position: 'absolute', opacity: 0, pointerEvents: 'none' }}\n autoComplete=\"off\" autoCorrect=\"off\" autoCapitalize=\"off\" spellCheck={false} />\n </div>\n </div>\n </div>\n );\n}\n\n/** @deprecated Use GreenScreenTerminal instead */\nexport const TN5250Terminal = GreenScreenTerminal;\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport type { TerminalAdapter, ScreenData, ConnectionStatus, SendResult, ConnectConfig } from '../adapters/types';\n\n/**\n * Hook for terminal connection management via adapter.\n */\nexport function useTerminalConnection(adapter: TerminalAdapter) {\n const [status, setStatus] = useState<ConnectionStatus | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchStatus = useCallback(async () => {\n try {\n const result = await adapter.getStatus();\n setStatus(result);\n return result;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return null;\n }\n }, [adapter]);\n\n const connect = useCallback(async (config?: ConnectConfig) => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.connect(config);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const disconnect = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n await adapter.disconnect();\n setStatus(prev => prev ? { ...prev, connected: false, status: 'disconnected' } : null);\n return { success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const reconnect = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.reconnect();\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n return { status, loading, error, fetchStatus, connect, disconnect, reconnect };\n}\n\n/**\n * Hook for terminal screen content with polling.\n */\nexport function useTerminalScreen(\n adapter: TerminalAdapter,\n interval: number = 2000,\n enabled: boolean = true,\n) {\n const [data, setData] = useState<ScreenData | null>(null);\n const [error, setError] = useState<unknown>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return;\n }\n\n const poll = async () => {\n try {\n const screen = await adapter.getScreen();\n if (screen) setData(screen);\n setError(null);\n } catch (err) {\n setError(err);\n }\n };\n\n poll(); // Initial fetch\n intervalRef.current = setInterval(poll, interval);\n\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [adapter, interval, enabled]);\n\n return { data, error };\n}\n\n/**\n * Hook for terminal operations (sendText, sendKey).\n */\nexport function useTerminalInput(adapter: TerminalAdapter) {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const sendText = useCallback(async (text: string): Promise<SendResult> => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.sendText(text);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const sendKey = useCallback(async (key: string): Promise<SendResult> => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.sendKey(key);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n return { loading, error, sendText, sendKey };\n}\n\n/** @deprecated Use `useTerminalConnection` instead */\nexport const useTN5250Connection = useTerminalConnection;\n/** @deprecated Use `useTerminalScreen` instead */\nexport const useTN5250Screen = useTerminalScreen;\n/** @deprecated Use `useTerminalInput` instead */\nexport const useTN5250Terminal = useTerminalInput;\n","import { useState, useEffect, useRef, useCallback, useMemo } from 'react';\nimport { positionToRowCol, isFieldEntry } from '../utils/grid';\n\n/**\n * Hook for typing animation effect on terminal screen content.\n * Reveals characters progressively when screen content changes.\n * Also provides animated cursor position that follows the typing.\n *\n * Uses a queue-based model: incoming content updates are queued when an\n * animation is in progress, then played sequentially. This prevents\n * blinks (no mid-animation cancellation) and skips (every field entry\n * gets its own animation). Queue depth is capped to avoid falling\n * behind real-time.\n *\n * Screen transitions (large changes) always display SYNCHRONOUSLY.\n */\nexport function useTypingAnimation(\n content: string | null | undefined,\n enabled: boolean = true,\n typingBudgetMs: number = 100,\n) {\n const FRAME_DELAY = 16; // ~60fps\n\n const previousContentRef = useRef('');\n const targetContentRef = useRef('');\n const contentQueueRef = useRef<string[]>([]);\n const isAnimatingRef = useRef(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const rafRef = useRef<number | null>(null);\n\n const [animatedContent, setAnimatedContent] = useState('');\n const [isAnimating, setIsAnimating] = useState(false);\n const [animatedCursorPos, setAnimatedCursorPos] = useState<{ row: number; col: number } | null>(null);\n\n const cancelAnimation = () => {\n if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; }\n if (rafRef.current) { cancelAnimationFrame(rafRef.current); rafRef.current = null; }\n };\n\n const showInstant = useCallback((c: string) => {\n cancelAnimation();\n setAnimatedContent(c);\n setAnimatedCursorPos(null);\n setIsAnimating(false);\n isAnimatingRef.current = false;\n previousContentRef.current = c;\n targetContentRef.current = '';\n }, []);\n\n const processNextRef = useRef<(() => void) | null>(null);\n\n const startFieldAnimation = useCallback((fromContent: string, toContent: string) => {\n let diffStart = -1;\n let diffEnd = 0;\n const maxLen = Math.max(fromContent.length, toContent.length);\n for (let i = 0; i < maxLen; i++) {\n if ((fromContent[i] || ' ') !== (toContent[i] || ' ')) {\n if (diffStart === -1) diffStart = i;\n diffEnd = i;\n }\n }\n if (diffStart === -1) { showInstant(toContent); return; }\n\n setIsAnimating(true);\n isAnimatingRef.current = true;\n targetContentRef.current = toContent;\n\n const diffLength = diffEnd - diffStart + 1;\n\n const oldRegion = fromContent.substring(diffStart, diffEnd + 1);\n const isCorrection = oldRegion.replace(/[_\\s\\n]/g, '').length > 0;\n\n const finishAnimation = () => {\n setAnimatedContent(toContent);\n setIsAnimating(false);\n isAnimatingRef.current = false;\n setAnimatedCursorPos(null);\n previousContentRef.current = toContent;\n targetContentRef.current = '';\n timeoutRef.current = null;\n rafRef.current = null;\n if (processNextRef.current) processNextRef.current();\n };\n\n if (isCorrection) {\n const CORRECTION_BUDGET = 400;\n const removalBudget = Math.floor(CORRECTION_BUDGET * 0.4);\n const typingBudget = CORRECTION_BUDGET - removalBudget;\n const removalFrames = Math.max(2, Math.floor(removalBudget / FRAME_DELAY));\n const typingFrames = Math.max(2, Math.floor(typingBudget / FRAME_DELAY));\n const removalCPF = Math.max(1, Math.ceil(diffLength / removalFrames));\n const typingCPF = Math.max(1, Math.ceil(diffLength / typingFrames));\n\n let removePos = diffEnd + 1;\n let typePos = diffStart;\n\n const buildRemovalContent = (erasedFrom: number) => {\n const before = fromContent.substring(0, diffStart);\n const remaining = fromContent.substring(diffStart, erasedFrom);\n const erased = ' '.repeat(Math.max(0, diffEnd + 1 - erasedFrom));\n const after = toContent.substring(diffEnd + 1);\n return before + remaining + erased + after;\n };\n\n const buildTypingContent = (revealedUpTo: number) => {\n const before = toContent.substring(0, diffStart);\n const revealed = toContent.substring(diffStart, revealedUpTo);\n const hidden = toContent.substring(revealedUpTo, diffEnd + 1).replace(/[^\\n]/g, ' ');\n const after = toContent.substring(diffEnd + 1);\n return before + revealed + hidden + after;\n };\n\n const animateTyping = () => {\n typePos += typingCPF;\n if (typePos >= diffEnd + 1) {\n finishAnimation();\n } else {\n setAnimatedContent(buildTypingContent(typePos));\n setAnimatedCursorPos(positionToRowCol(toContent, typePos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateTyping);\n }, FRAME_DELAY);\n }\n };\n\n const animateRemoval = () => {\n removePos -= removalCPF;\n if (removePos <= diffStart) {\n setAnimatedContent(buildTypingContent(diffStart));\n setAnimatedCursorPos(positionToRowCol(toContent, diffStart));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateTyping);\n }, FRAME_DELAY);\n } else {\n setAnimatedContent(buildRemovalContent(removePos));\n setAnimatedCursorPos(positionToRowCol(fromContent, removePos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateRemoval);\n }, FRAME_DELAY);\n }\n };\n\n setAnimatedCursorPos(positionToRowCol(fromContent, diffEnd));\n setAnimatedContent(buildRemovalContent(diffEnd + 1));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateRemoval);\n }, FRAME_DELAY);\n } else {\n let currentPos = diffStart;\n const totalFrames = Math.max(1, Math.floor(typingBudgetMs / FRAME_DELAY));\n const charsPerFrame = Math.max(1, Math.ceil(diffLength / totalFrames));\n\n setAnimatedCursorPos(positionToRowCol(toContent, diffStart));\n\n const buildDisplayContent = (revealedUpTo: number) => {\n const before = toContent.substring(0, diffStart);\n const revealed = toContent.substring(diffStart, revealedUpTo);\n const hidden = toContent.substring(revealedUpTo, diffEnd + 1).replace(/[^\\n]/g, ' ');\n const after = toContent.substring(diffEnd + 1);\n return before + revealed + hidden + after;\n };\n\n const animate = () => {\n currentPos += charsPerFrame;\n if (currentPos >= diffEnd + 1) {\n finishAnimation();\n } else {\n setAnimatedContent(buildDisplayContent(currentPos));\n setAnimatedCursorPos(positionToRowCol(toContent, currentPos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animate);\n }, FRAME_DELAY);\n }\n };\n\n setAnimatedContent(buildDisplayContent(diffStart));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animate);\n }, FRAME_DELAY);\n }\n }, [showInstant, typingBudgetMs]);\n\n processNextRef.current = () => {\n const queue = contentQueueRef.current;\n if (queue.length === 0) return;\n\n while (queue.length > 2) queue.shift();\n\n const next = queue.shift()!;\n const base = previousContentRef.current;\n\n if (isFieldEntry(base, next)) {\n startFieldAnimation(base, next);\n } else {\n showInstant(next);\n if (queue.length > 0 && processNextRef.current) processNextRef.current();\n }\n };\n\n const shouldAnimate = enabled && content && isFieldEntry(previousContentRef.current, content);\n if (!shouldAnimate && !isAnimatingRef.current && content !== previousContentRef.current) {\n previousContentRef.current = content || '';\n }\n\n useEffect(() => {\n if (!enabled || !content) {\n cancelAnimation();\n contentQueueRef.current = [];\n showInstant(content || '');\n previousContentRef.current = content || '';\n return;\n }\n\n const currentTarget = targetContentRef.current || previousContentRef.current;\n if (content === currentTarget) return;\n\n if (isAnimatingRef.current) {\n if (!isFieldEntry(currentTarget, content)) {\n contentQueueRef.current = [];\n showInstant(content);\n } else {\n contentQueueRef.current.push(content);\n if (contentQueueRef.current.length > 3) {\n contentQueueRef.current = contentQueueRef.current.slice(-2);\n }\n }\n return;\n }\n\n const prev = previousContentRef.current;\n if (!isFieldEntry(prev, content)) {\n showInstant(content);\n return;\n }\n startFieldAnimation(prev, content);\n\n return cancelAnimation;\n }, [content, enabled, showInstant, startFieldAnimation]);\n\n const animationActive = isAnimatingRef.current;\n\n const displayedContent = useMemo(() => {\n if (!enabled || !content) return content || '';\n if (animationActive) return animatedContent;\n return content;\n }, [enabled, content, animationActive, animatedContent]);\n\n const effectiveCursorPos = animationActive ? animatedCursorPos : null;\n\n return { displayedContent, isAnimating, animatedCursorPos: effectiveCursorPos };\n}\n","/**\n * Convert a linear position in screen content to row/col coordinates.\n * Content is lines of characters separated by newlines.\n */\nexport function positionToRowCol(content: string, position: number): { row: number; col: number } {\n let row = 0;\n let col = 0;\n for (let i = 0; i < position && i < content.length; i++) {\n if (content[i] === '\\n') {\n row++;\n col = 0;\n } else {\n col++;\n }\n }\n return { row, col };\n}\n\n/**\n * Detect if a content change is a field entry (small, localized change)\n * vs a screen transition (large, distributed change).\n *\n * Field entries: < 50 changed characters within a span of < 100 positions.\n * Screen transitions: everything else.\n */\nexport function isFieldEntry(previousContent: string | null | undefined, content: string | null | undefined): boolean {\n if (!previousContent || !content) return false;\n\n let diffCount = 0;\n let diffStart = -1;\n let diffEnd = 0;\n const maxLen = Math.max(previousContent.length, content.length);\n\n for (let i = 0; i < maxLen; i++) {\n const oldChar = previousContent[i] || ' ';\n const newChar = content[i] || ' ';\n if (oldChar !== newChar) {\n diffCount++;\n if (diffStart === -1) diffStart = i;\n diffEnd = i;\n }\n }\n\n const diffSpan = diffEnd - diffStart + 1;\n // Field entry: small number of changes (< 50 chars), localized (span < 100)\n return diffCount > 2 && diffCount < 50 && diffSpan < 100;\n}\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const tn5250Profile: ProtocolProfile = {\n protocol: 'tn5250',\n displayName: 'IBM TN5250',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'TN5250 TERMINAL',\n bootText: 'TN5250',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 2) return 'gs-row-fkey';\n if (/F\\d{1,2}=/.test(rowContent)) return 'gs-row-fkey';\n if (/Select one of the following/i.test(rowContent)) return 'gs-row-subtitle';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n const trimmed = line.trimStart();\n const leftMatch = trimmed.match(/^(\\S+)/);\n if (leftMatch) {\n const leftId = leftMatch[1];\n const leftEnd = line.indexOf(leftId) + leftId.length;\n const rightMatch = line.trimEnd().match(/(\\S+)$/);\n if (rightMatch && rightMatch[1] !== leftId) {\n const rightStart = line.lastIndexOf(rightMatch[1]);\n return [\n { text: line.substring(0, leftEnd), colorClass: 'gs-row-fkey' },\n { text: line.substring(leftEnd, rightStart), colorClass: 'gs-row-title' },\n { text: line.substring(rightStart), colorClass: 'gs-row-content' },\n ];\n }\n }\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const tn3270Profile: ProtocolProfile = {\n protocol: 'tn3270',\n displayName: 'IBM TN3270',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'TN3270 TERMINAL',\n bootText: 'TN3270',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n // z/OS ISPF conventions: row 0 = title, last 2 rows = PF keys/command\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 2) return 'gs-row-fkey';\n if (/PF\\d{1,2}[=/]/.test(rowContent) || /F\\d{1,2}=/.test(rowContent)) return 'gs-row-fkey';\n if (/COMMAND\\s*===>/i.test(rowContent) || /===>/.test(rowContent)) return 'gs-row-subtitle';\n if (/OPTION\\s*===>/i.test(rowContent)) return 'gs-row-subtitle';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n // ISPF: typically \"Menu Utilities Compilers ...\" action bar or panel title\n const trimmed = line.trimStart();\n const leftMatch = trimmed.match(/^(\\S+)/);\n if (leftMatch) {\n const leftId = leftMatch[1];\n const leftEnd = line.indexOf(leftId) + leftId.length;\n const rightMatch = line.trimEnd().match(/(\\S+)$/);\n if (rightMatch && rightMatch[1] !== leftId) {\n const rightStart = line.lastIndexOf(rightMatch[1]);\n return [\n { text: line.substring(0, leftEnd), colorClass: 'gs-row-fkey' },\n { text: line.substring(leftEnd, rightStart), colorClass: 'gs-row-title' },\n { text: line.substring(rightStart), colorClass: 'gs-row-content' },\n ];\n }\n }\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const vtProfile: ProtocolProfile = {\n protocol: 'vt',\n displayName: 'VT Terminal',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'VT TERMINAL',\n bootText: 'VT220',\n colors: {\n getRowColorClass(_rowIndex: number, _rowContent: string, _totalRows: number): string {\n // VT terminals use inline escape-sequence-driven colors, not row-based conventions.\n // All rows default to green; actual colors come from ANSI attributes in the data stream.\n return 'gs-row-content';\n },\n parseHeaderRow(_line: string): { text: string; colorClass: string }[] | null {\n // VT has no header row convention\n return null;\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const hp6530Profile: ProtocolProfile = {\n protocol: 'hp6530',\n displayName: 'HP 6530',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: '6530 TERMINAL',\n bootText: 'HP6530',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n // HP NonStop 6530: row 0 = status/title, last row = function key labels\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 1) return 'gs-row-fkey';\n if (/F\\d{1,2}[=\\-]/.test(rowContent) || /SF\\d{1,2}/.test(rowContent)) return 'gs-row-fkey';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { TerminalProtocol, ProtocolProfile } from '../adapters/types';\nimport { tn5250Profile } from './tn5250';\nimport { tn3270Profile } from './tn3270';\nimport { vtProfile } from './vt';\nimport { hp6530Profile } from './hp6530';\n\nconst profiles: Record<TerminalProtocol, ProtocolProfile> = {\n tn5250: tn5250Profile,\n tn3270: tn3270Profile,\n vt: vtProfile,\n hp6530: hp6530Profile,\n};\n\n/**\n * Get a protocol profile by type. Defaults to TN5250 for backward compatibility.\n */\nexport function getProtocolProfile(protocol?: TerminalProtocol): ProtocolProfile {\n return profiles[protocol || 'tn5250'];\n}\n","import React, { useState, useEffect, useRef } from 'react';\n\nexport interface TerminalBootLoaderProps {\n /** Text to display during boot animation */\n brandText?: string;\n /** Speed in ms per character */\n charSpeed?: number;\n /** Optional logo element to render alongside the text */\n logo?: React.ReactNode;\n /** Height of the boot loader container */\n height?: number | string;\n}\n\n/**\n * Animated boot loader for the terminal.\n * Shows a typewriter-style text reveal animation.\n */\nexport function TerminalBootLoader({\n brandText = 'TERMINAL',\n charSpeed = 80,\n logo,\n height = 504,\n}: TerminalBootLoaderProps) {\n const [charCount, setCharCount] = useState(0);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n intervalRef.current = setInterval(() => {\n setCharCount(prev => {\n if (prev >= brandText.length) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return prev;\n }\n return prev + 1;\n });\n }, charSpeed);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [brandText, charSpeed]);\n\n const displayed = brandText.substring(0, charCount);\n\n return (\n <div\n className=\"gs-boot-loader\"\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n backgroundColor: 'var(--gs-bg, #000)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'var(--gs-font)',\n fontSize: '13px',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n {logo}\n <h1\n style={{\n fontFamily: 'var(--gs-font)',\n fontSize: '1.5rem',\n letterSpacing: '0.1em',\n color: 'var(--gs-green, #10b981)',\n textShadow: '0 0 12px rgba(16, 185, 129, 0.4)',\n margin: 0,\n }}\n >\n {displayed}\n <span\n className=\"tn5250-cursor\"\n style={{\n display: 'inline-block',\n width: '0.6ch',\n height: '1.2em',\n verticalAlign: 'middle',\n marginLeft: '2px',\n }}\n />\n </h1>\n </div>\n </div>\n );\n}\n","import type { TerminalAdapter, ScreenData, ConnectionStatus, SendResult, ConnectConfig } from './types';\n\nexport interface RestAdapterOptions {\n /** Base URL for the terminal API (e.g. \"https://myhost.com/api/terminal\") */\n baseUrl: string;\n /** Optional headers to include with every request (e.g. Authorization) */\n headers?: Record<string, string>;\n /** Optional function that returns headers (called per-request, useful for dynamic tokens) */\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * REST API adapter for terminal communication.\n *\n * Expects a backend that exposes these endpoints relative to `baseUrl`:\n * - GET /screen → ScreenData\n * - GET /status → ConnectionStatus\n * - POST /send-text → SendResult (body: { text })\n * - POST /send-key → SendResult (body: { key })\n * - POST /connect → SendResult\n * - POST /disconnect → SendResult\n * - POST /reconnect → SendResult\n */\nexport class RestAdapter implements TerminalAdapter {\n private baseUrl: string;\n private staticHeaders: Record<string, string>;\n private getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n\n constructor(options: RestAdapterOptions) {\n // Remove trailing slash\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.staticHeaders = options.headers || {};\n this.getHeaders = options.getHeaders;\n }\n\n private async buildHeaders(): Promise<Record<string, string>> {\n const dynamic = this.getHeaders ? await this.getHeaders() : {};\n return {\n 'Content-Type': 'application/json',\n ...this.staticHeaders,\n ...dynamic,\n };\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const headers = await this.buildHeaders();\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const detail = await response.json().catch(() => ({}));\n throw new Error(detail?.detail || `HTTP ${response.status}`);\n }\n\n return response.json();\n }\n\n async getScreen(): Promise<ScreenData | null> {\n try {\n return await this.request<ScreenData>('GET', '/screen');\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n // 503/404 expected when no active connection\n if (message.includes('503') || message.includes('404')) {\n return null;\n }\n throw e;\n }\n }\n\n async getStatus(): Promise<ConnectionStatus> {\n return this.request<ConnectionStatus>('GET', '/status');\n }\n\n async sendText(text: string): Promise<SendResult> {\n return this.request<SendResult>('POST', '/send-text', { text });\n }\n\n async sendKey(key: string): Promise<SendResult> {\n return this.request<SendResult>('POST', '/send-key', { key });\n }\n\n async connect(config?: ConnectConfig): Promise<SendResult> {\n return this.request<SendResult>('POST', '/connect', config);\n }\n\n async disconnect(): Promise<SendResult> {\n return this.request<SendResult>('POST', '/disconnect');\n }\n\n async reconnect(): Promise<SendResult> {\n return this.request<SendResult>('POST', '/reconnect');\n }\n}\n","import { getProtocolProfile } from '../protocols/registry';\n\n/**\n * Get the appropriate CSS class name for a row.\n * Delegates to the TN5250 protocol profile for backward compatibility.\n *\n * For protocol-aware rendering, use `getProtocolProfile(protocol).colors.getRowColorClass()`.\n */\nexport function getRowColorClass(rowIndex: number, rowContent: string): string {\n return getProtocolProfile('tn5250').colors.getRowColorClass(rowIndex, rowContent, 24);\n}\n\n/**\n * Parse the header row into colored segments.\n * Delegates to the TN5250 protocol profile for backward compatibility.\n *\n * For protocol-aware rendering, use `getProtocolProfile(protocol).colors.parseHeaderRow()`.\n */\nexport function parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n return getProtocolProfile('tn5250').colors.parseHeaderRow(line);\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","useCallback","useMemo","useState","useEffect","useRef","useCallback","useRef","useState","useCallback","useEffect","useState","useEffect","useRef","jsx","jsxs","useState","useMemo","useRef","useEffect","useCallback"]}
1
+ {"version":3,"sources":["../src/components/GreenScreenTerminal.tsx","../src/adapters/RestAdapter.ts","../src/adapters/WebSocketAdapter.ts","../src/hooks/useTerminal.ts","../src/hooks/useTypingAnimation.ts","../src/utils/grid.ts","../src/protocols/tn5250.ts","../src/protocols/tn3270.ts","../src/protocols/vt.ts","../src/protocols/hp6530.ts","../src/protocols/registry.ts","../src/components/TerminalBootLoader.tsx","../src/components/Icons.tsx","../src/components/InlineSignIn.tsx","../src/utils/rendering.ts"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';\nimport type { TerminalAdapter, ScreenData, ConnectionStatus, Field, TerminalProtocol, ProtocolProfile, ConnectConfig } from '../adapters/types';\nimport { RestAdapter } from '../adapters/RestAdapter';\nimport { WebSocketAdapter } from '../adapters/WebSocketAdapter';\nimport { useTerminalScreen, useTerminalInput, useTerminalConnection } from '../hooks/useTerminal';\nimport { useTypingAnimation } from '../hooks/useTypingAnimation';\nimport { getProtocolProfile } from '../protocols/registry';\nimport { TerminalBootLoader as DefaultBootLoader } from './TerminalBootLoader';\nimport { TerminalIcon, WifiIcon, WifiOffIcon, AlertTriangleIcon, RefreshIcon, KeyIcon, MinimizeIcon } from './Icons';\nimport { InlineSignIn } from './InlineSignIn';\n\n/* ── No-op adapter (placeholder before connection) ───────────────── */\n\nconst noopResult = { success: false, error: 'No adapter configured' };\nconst noopAdapter: TerminalAdapter = {\n getScreen: async () => null,\n getStatus: async () => ({ connected: false, status: 'disconnected' }),\n sendText: async () => noopResult,\n sendKey: async () => noopResult,\n connect: async () => noopResult,\n disconnect: async () => noopResult,\n reconnect: async () => noopResult,\n};\n\n/* ── Component Props ──────────────────────────────────────────────── */\n\nexport interface GreenScreenTerminalProps {\n /** Adapter for communicating with the terminal backend (optional — auto-created from sign-in form or baseUrl) */\n adapter?: TerminalAdapter;\n /** Base URL for the terminal API — convenience shorthand that auto-creates a RestAdapter */\n baseUrl?: string;\n /** Worker/proxy WebSocket URL — convenience shorthand that auto-creates a WebSocketAdapter */\n workerUrl?: string;\n /** Terminal protocol (determines color conventions, header label, etc.) */\n protocol?: TerminalProtocol;\n /** Custom protocol profile (overrides protocol param) */\n protocolProfile?: ProtocolProfile;\n /** Direct screen data injection (bypasses polling) */\n screenData?: ScreenData | null;\n /** Direct connection status injection */\n connectionStatus?: ConnectionStatus | null;\n\n /** Whether the terminal is read-only (no keyboard input) */\n readOnly?: boolean;\n /** Polling interval in ms (0 to disable polling; default 2000) */\n pollInterval?: number;\n /** Whether to auto-reconnect on disconnect (default true) */\n autoReconnect?: boolean;\n /** Max auto-reconnect attempts (default 5) */\n maxReconnectAttempts?: number;\n\n /** Compact embedded mode */\n embedded?: boolean;\n /** Show the header bar (default true) */\n showHeader?: boolean;\n /** Enable typing animation (default true) */\n typingAnimation?: boolean;\n /** Typing animation budget in ms (default 60) */\n typingBudgetMs?: number;\n\n /** Show inline sign-in form when disconnected (default true) */\n inlineSignIn?: boolean;\n /** Default protocol for the sign-in form dropdown (default 'tn5250') */\n defaultProtocol?: TerminalProtocol;\n /** Callback when sign-in form is submitted */\n onSignIn?: (config: ConnectConfig) => void;\n /** Show \"press Enter to continue\" hint after auto sign-in (for external adapter flows) */\n autoSignedIn?: boolean;\n /** Disable auto-focus on the terminal after connecting (default false) */\n autoFocusDisabled?: boolean;\n\n /** Custom boot loader element, or false to disable */\n bootLoader?: React.ReactNode | false;\n /** Content for the right side of the header */\n headerRight?: React.ReactNode;\n /** Overlay content (e.g. \"Extracting...\" state) */\n overlay?: React.ReactNode;\n /** Callback for notifications (replaces toast) */\n onNotification?: (message: string, type: 'info' | 'error') => void;\n /** Callback when screen content changes */\n onScreenChange?: (screen: ScreenData) => void;\n /** Callback for minimize action (embedded mode) */\n onMinimize?: () => void;\n\n /** Additional CSS class name */\n className?: string;\n /** Inline styles */\n style?: React.CSSProperties;\n}\n\n/**\n * GreenScreenTerminal — Multi-protocol legacy terminal emulator component.\n *\n * Renders a terminal screen with:\n * - Green-on-black terminal aesthetic with protocol-specific color conventions\n * - Connection status indicator\n * - Keyboard input support (text, function keys, tab)\n * - Auto-reconnect with exponential backoff\n * - Typing animation for field entries\n * - Focus lock mode for keyboard capture\n *\n * Supports: TN5250 (IBM i), TN3270 (z/OS), VT (OpenVMS/Pick), HP 6530 (NonStop)\n */\nexport function GreenScreenTerminal({\n adapter: externalAdapter,\n baseUrl,\n workerUrl,\n protocol,\n protocolProfile: customProfile,\n screenData: externalScreenData,\n connectionStatus: externalStatus,\n readOnly = false,\n pollInterval = 2000,\n autoReconnect: autoReconnectEnabled = true,\n maxReconnectAttempts: maxAttempts = 5,\n embedded = false,\n showHeader = true,\n typingAnimation = true,\n typingBudgetMs = 60,\n inlineSignIn = true,\n defaultProtocol: signInDefaultProtocol,\n onSignIn,\n autoSignedIn,\n autoFocusDisabled = false,\n bootLoader,\n headerRight,\n overlay,\n onNotification,\n onScreenChange,\n onMinimize,\n className,\n style,\n}: GreenScreenTerminalProps) {\n const profile = customProfile ?? getProtocolProfile(protocol);\n\n // --- Resolve adapter: explicit > baseUrl > workerUrl > internal (from sign-in) > default WebSocket > noop ---\n const [internalAdapter, setInternalAdapter] = useState<TerminalAdapter | null>(null);\n const baseUrlAdapter = useMemo(\n () => baseUrl ? new RestAdapter({ baseUrl }) : null,\n [baseUrl],\n );\n const workerUrlAdapter = useMemo(\n () => workerUrl ? new WebSocketAdapter({ workerUrl }) : null,\n [workerUrl],\n );\n // Default WebSocketAdapter (auto-detects env vars, falls back to localhost:3001) when no adapter is configured\n const defaultWsAdapter = useMemo(\n () => (!externalAdapter && !baseUrl && !workerUrl) ? new WebSocketAdapter() : null,\n [externalAdapter, baseUrl, workerUrl],\n );\n const adapter = externalAdapter ?? baseUrlAdapter ?? workerUrlAdapter ?? internalAdapter ?? defaultWsAdapter ?? noopAdapter;\n const isUsingDefaultAdapter = adapter === defaultWsAdapter;\n\n // --- Data sources ---\n const shouldPoll = pollInterval > 0 && !externalScreenData;\n const { data: polledScreenData, error: screenError } = useTerminalScreen(adapter, pollInterval, shouldPoll);\n const { sendText: _sendText, sendKey: _sendKey } = useTerminalInput(adapter);\n const { connect, reconnect, loading: reconnecting, error: connectError } = useTerminalConnection(adapter);\n\n const rawScreenData = externalScreenData ?? polledScreenData;\n\n const connStatus = externalStatus ?? (rawScreenData ? { connected: true, status: 'authenticated' as const } : { connected: false, status: 'disconnected' as const });\n\n // Typing animation\n const { displayedContent, animatedCursorPos } = useTypingAnimation(\n rawScreenData?.content,\n typingAnimation,\n typingBudgetMs,\n );\n\n const screenData = useMemo(() => {\n if (!rawScreenData) return null;\n return { ...rawScreenData, content: displayedContent };\n }, [rawScreenData, displayedContent]);\n\n // Notify parent on screen changes\n const prevScreenSigRef = useRef<string | undefined>(undefined);\n useEffect(() => {\n if (screenData && onScreenChange && screenData.screen_signature !== prevScreenSigRef.current) {\n prevScreenSigRef.current = screenData.screen_signature;\n onScreenChange(screenData);\n }\n }, [screenData, onScreenChange]);\n\n const sendText = useCallback(async (text: string) => _sendText(text), [_sendText]);\n const sendKey = useCallback(async (key: string) => _sendKey(key), [_sendKey]);\n\n // --- UI State ---\n const [inputText, setInputText] = useState('');\n const [isFocused, setIsFocused] = useState(false);\n const [showSignInHint, setShowSignInHint] = useState(false);\n const prevAutoSignedIn = useRef(false);\n useEffect(() => {\n if (autoSignedIn && !prevAutoSignedIn.current) setShowSignInHint(true);\n prevAutoSignedIn.current = !!autoSignedIn;\n }, [autoSignedIn]);\n const terminalRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const [syncedCursor, setSyncedCursor] = useState<{ row: number; col: number } | null>(null);\n const prevRawContentRef = useRef('');\n\n useEffect(() => {\n const newContent = rawScreenData?.content || '';\n if (prevRawContentRef.current && newContent && newContent !== prevRawContentRef.current) {\n setSyncedCursor(null);\n setInputText('');\n if (showSignInHint) setShowSignInHint(false);\n }\n prevRawContentRef.current = newContent;\n }, [rawScreenData?.content]);\n\n // --- Auto-reconnect ---\n const [autoReconnectAttempt, setAutoReconnectAttempt] = useState(0);\n const [isAutoReconnecting, setIsAutoReconnecting] = useState(false);\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wasConnectedRef = useRef(false);\n const isConnectedRef = useRef(false);\n\n useEffect(() => { isConnectedRef.current = connStatus?.connected ?? false; }, [connStatus?.connected]);\n\n useEffect(() => {\n if (!autoReconnectEnabled) return;\n const isConnected = connStatus?.connected;\n\n if (isConnected) {\n wasConnectedRef.current = true;\n if (reconnectTimeoutRef.current) { clearTimeout(reconnectTimeoutRef.current); reconnectTimeoutRef.current = null; }\n setAutoReconnectAttempt(0);\n setIsAutoReconnecting(false);\n } else if (wasConnectedRef.current && !isConnected && !isAutoReconnecting && !reconnecting) {\n if (autoReconnectAttempt < maxAttempts) {\n setIsAutoReconnecting(true);\n const delay = Math.pow(2, autoReconnectAttempt) * 1000;\n reconnectTimeoutRef.current = setTimeout(async () => {\n if (isConnectedRef.current) { setIsAutoReconnecting(false); return; }\n onNotification?.(`Auto-reconnect attempt ${autoReconnectAttempt + 1}/${maxAttempts}`, 'info');\n try {\n const result = await reconnect();\n if (!result?.success) setAutoReconnectAttempt(prev => prev + 1);\n } catch {\n onNotification?.('Auto-reconnect failed', 'error');\n setAutoReconnectAttempt(prev => prev + 1);\n }\n setIsAutoReconnecting(false);\n }, delay);\n }\n }\n return () => { if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current); };\n }, [connStatus?.connected, autoReconnectAttempt, isAutoReconnecting, reconnecting, reconnect, autoReconnectEnabled, maxAttempts, onNotification]);\n\n // --- Inline sign-in ---\n const [connecting, setConnecting] = useState(false);\n const [signInError, setSignInError] = useState<string | null>(null);\n const handleSignIn = useCallback(async (config: ConnectConfig) => {\n // If the caller provided onSignIn, let them handle connection setup\n if (onSignIn) {\n onSignIn(config);\n return;\n }\n setConnecting(true);\n setSignInError(null);\n try {\n // Auto-create adapter from sign-in config when no external adapter is provided\n if (!externalAdapter && !baseUrlAdapter) {\n const port = config.port ? `:${config.port}` : '';\n const newAdapter = new RestAdapter({ baseUrl: `http://${config.host}${port}` });\n setInternalAdapter(newAdapter);\n await newAdapter.connect(config);\n if (config.username && config.password) setShowSignInHint(true);\n return;\n }\n await connect(config);\n if (config.username && config.password) setShowSignInHint(true);\n } catch (err) {\n setSignInError(err instanceof Error ? err.message : String(err));\n setConnecting(false);\n }\n // Note: connecting is cleared by the screenData effect below, not here —\n // the connect() promise may resolve before the screen is actually ready.\n }, [connect, onSignIn, externalAdapter, baseUrlAdapter]);\n\n // Clear connecting state when screen data arrives or connection is confirmed\n useEffect(() => {\n if (connecting && screenData?.content) setConnecting(false);\n }, [connecting, screenData?.content]);\n\n // --- Boot loader ---\n const [showBootLoader, setShowBootLoader] = useState(bootLoader !== false);\n const [bootFadingOut, setBootFadingOut] = useState(false);\n\n useEffect(() => {\n if (screenData?.content && showBootLoader) {\n setBootFadingOut(true);\n setShowBootLoader(false);\n const timer = setTimeout(() => setBootFadingOut(false), 400);\n return () => clearTimeout(timer);\n }\n }, [screenData?.content, showBootLoader]);\n\n // --- Focus management ---\n const FOCUS_STORAGE_KEY = 'gs-terminal-focused';\n\n // Restore focus from localStorage on mount (if auto-focus enabled)\n useEffect(() => {\n if (!autoFocusDisabled && !readOnly) {\n try {\n if (localStorage.getItem(FOCUS_STORAGE_KEY) === 'true') {\n setIsFocused(true);\n }\n } catch { /* localStorage unavailable */ }\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Persist focus state to localStorage\n useEffect(() => {\n if (autoFocusDisabled) return;\n try { localStorage.setItem(FOCUS_STORAGE_KEY, String(isFocused)); } catch { /* noop */ }\n }, [isFocused, autoFocusDisabled]);\n\n // Sync DOM focus with isFocused state\n useEffect(() => {\n if (isFocused) inputRef.current?.focus();\n }, [isFocused]);\n\n // Auto-focus terminal when screen data arrives (i.e. connected)\n const hadScreenData = useRef(false);\n useEffect(() => {\n if (screenData?.content && !hadScreenData.current && !autoFocusDisabled && !readOnly) {\n hadScreenData.current = true;\n setIsFocused(true);\n }\n if (!screenData?.content) hadScreenData.current = false;\n }, [screenData?.content, autoFocusDisabled, readOnly]);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (terminalRef.current && !terminalRef.current.contains(event.target as Node)) setIsFocused(false);\n };\n if (isFocused) document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isFocused]);\n\n useEffect(() => {\n if (readOnly && isFocused) { setIsFocused(false); inputRef.current?.blur(); }\n }, [readOnly, isFocused]);\n\n const handleTerminalClick = useCallback(() => {\n if (readOnly) return;\n setIsFocused(true);\n inputRef.current?.focus();\n }, [readOnly]);\n\n // --- Field helpers ---\n const getCurrentField = useCallback(() => {\n const fields = screenData?.fields || [];\n const cursorRow = syncedCursor?.row ?? screenData?.cursor_row ?? 0;\n const cursorCol = syncedCursor?.col ?? screenData?.cursor_col ?? 0;\n for (const field of fields) {\n if (field.is_input && field.row === cursorRow && cursorCol >= field.col && cursorCol < field.col + field.length) return field;\n }\n return null;\n }, [screenData, syncedCursor]);\n\n const canTypeMore = useCallback((additionalChars: number = 1) => {\n const currentField = getCurrentField();\n if (!currentField) return true;\n const cursorCol = (syncedCursor?.col ?? screenData?.cursor_col ?? 0) + inputText.length;\n return cursorCol + additionalChars <= currentField.col + currentField.length;\n }, [getCurrentField, syncedCursor, screenData, inputText]);\n\n // --- Keyboard handling ---\n const handleKeyDown = async (e: React.KeyboardEvent) => {\n if (readOnly) { e.preventDefault(); return; }\n\n if (e.key === 'Escape') { e.preventDefault(); setIsFocused(false); inputRef.current?.blur(); return; }\n\n if (e.key === 'Backspace') {\n e.preventDefault();\n if (inputText.length > 0) { setInputText(prev => prev.slice(0, -1)); }\n else {\n const keyResult = await sendKey('BACKSPACE');\n if (keyResult.cursor_row !== undefined) setSyncedCursor({ row: keyResult.cursor_row, col: keyResult.cursor_col! });\n }\n return;\n }\n\n const keyMap: Record<string, string> = {\n Enter: 'ENTER', Tab: 'TAB', Delete: 'DELETE',\n ArrowUp: 'UP', ArrowDown: 'DOWN', ArrowLeft: 'LEFT', ArrowRight: 'RIGHT',\n PageUp: 'PAGEUP', PageDown: 'PAGEDOWN', Home: 'HOME', End: 'END', Insert: 'INSERT',\n };\n\n if (e.key.startsWith('F') && e.key.length <= 3) {\n e.preventDefault();\n const fKey = e.key.toUpperCase();\n if (/^F([1-9]|1[0-9]|2[0-4])$/.test(fKey)) {\n if (inputText) {\n const r = await sendText(inputText); setInputText('');\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey(fKey);\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n return;\n }\n }\n\n if (keyMap[e.key]) {\n e.preventDefault();\n if (inputText) {\n const r = await sendText(inputText); setInputText('');\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey(keyMap[e.key]);\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n }\n };\n\n const handleInput = async (e: React.ChangeEvent<HTMLInputElement>) => {\n if (readOnly) { e.target.value = ''; return; }\n const newText = e.target.value;\n if (newText.includes('\\n')) {\n const textToSend = newText.replace('\\n', '');\n if (textToSend) {\n const r = await sendText(textToSend);\n if (r.cursor_row !== undefined) setSyncedCursor({ row: r.cursor_row, col: r.cursor_col! });\n }\n const kr = await sendKey('ENTER');\n if (kr.cursor_row !== undefined) setSyncedCursor({ row: kr.cursor_row, col: kr.cursor_col! });\n setInputText(''); e.target.value = '';\n } else {\n const charsToAdd = newText.length - inputText.length;\n if (charsToAdd > 0 && !canTypeMore(charsToAdd)) { e.target.value = inputText; return; }\n setInputText(newText);\n }\n };\n\n // --- Cursor ---\n const termCols = screenData?.cols || profile.defaultCols;\n const getCursorPos = () => {\n if (animatedCursorPos) return animatedCursorPos;\n let cursorRow = syncedCursor?.row ?? screenData?.cursor_row ?? 0;\n let cursorCol = (syncedCursor?.col ?? screenData?.cursor_col ?? 0) + inputText.length;\n while (cursorCol >= termCols) { cursorCol -= termCols; cursorRow += 1; }\n return { row: cursorRow, col: cursorCol };\n };\n\n // --- Rendering helpers ---\n const renderTextWithUnderlines = useCallback((text: string, keyPrefix: string): React.ReactNode => {\n const underscoreRegex = /_{2,}/g;\n const segments: React.ReactNode[] = [];\n let lastIndex = 0;\n let match;\n let segmentIndex = 0;\n while ((match = underscoreRegex.exec(text)) !== null) {\n if (match.index > lastIndex) segments.push(<span key={`${keyPrefix}-t-${segmentIndex}`}>{text.substring(lastIndex, match.index)}</span>);\n const count = match[0].length;\n segments.push(<span key={`${keyPrefix}-u-${segmentIndex}`} style={{ borderBottom: '1px solid var(--gs-green, #10b981)', display: 'inline-block', width: `${count}ch` }}>{' '.repeat(count)}</span>);\n lastIndex = match.index + match[0].length;\n segmentIndex++;\n }\n if (lastIndex < text.length) segments.push(<span key={`${keyPrefix}-e`}>{text.substring(lastIndex)}</span>);\n return segments.length > 0 ? <>{segments}</> : <>{text}</>;\n }, []);\n\n const renderRowWithFields = useCallback((line: string, rowIndex: number, fields: Field[]): React.ReactNode => {\n const inputFields = fields.filter(f => f.row === rowIndex && f.is_input);\n const highlightedFields = fields.filter(f => f.row === rowIndex && f.is_protected && f.is_highlighted);\n const reverseFields = fields.filter(f => f.row === rowIndex && f.is_protected && f.is_reverse);\n const allRowFields = [...inputFields, ...highlightedFields, ...reverseFields];\n\n if (allRowFields.length === 0) return <span>{line}</span>;\n\n const sorted = [...allRowFields].sort((a, b) => a.col - b.col);\n const segs: React.ReactNode[] = [];\n let lastEnd = 0;\n const cols = screenData?.cols || profile.defaultCols;\n\n sorted.forEach((field, idx) => {\n const fs = field.col;\n const fe = Math.min(field.col + field.length, cols);\n if (fs > lastEnd) segs.push(<span key={`t${idx}`}>{line.substring(lastEnd, fs)}</span>);\n const fc = line.substring(fs, fe);\n if (field.is_input) {\n const fieldWidth = Math.min(field.length, cols - fs);\n const fieldClass = showSignInHint ? 'gs-confirmed-field' : (field.is_underscored ? 'gs-input-field' : undefined);\n segs.push(<span key={`f${idx}`} className={fieldClass || undefined} style={{ display: 'inline-block', width: `${fieldWidth}ch`, overflow: 'hidden' }}>{fc}</span>);\n } else if (field.is_reverse) {\n segs.push(<span key={`v${idx}`} style={{ color: '#ef4444', fontWeight: 'bold' }}>{fc}</span>);\n } else if (field.is_highlighted) {\n segs.push(<span key={`h${idx}`} style={{ color: 'var(--gs-white, #FFFFFF)' }}>{fc}</span>);\n } else {\n segs.push(<span key={`h${idx}`}>{fc}</span>);\n }\n lastEnd = fe;\n });\n if (lastEnd < line.length) segs.push(<span key=\"te\">{line.substring(lastEnd)}</span>);\n return <>{segs}</>;\n }, [renderTextWithUnderlines, screenData?.cols, profile.defaultCols, showSignInHint]);\n\n // --- Screen rendering ---\n const renderScreen = () => {\n if (showBootLoader && !screenData?.content) {\n if (bootLoader === false) return null;\n if (bootLoader) return <>{bootLoader}</>;\n return <DefaultBootLoader brandText={profile.bootText} />;\n }\n if (bootFadingOut && screenData?.content) return <div className=\"gs-fade-in\">{renderScreenContent()}</div>;\n if (!screenData?.content) {\n if (inlineSignIn && !connStatus?.connected) {\n return (\n <div style={{ width: '100%', height: `${(screenData?.rows || profile.defaultRows) * 21}px`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <InlineSignIn defaultProtocol={signInDefaultProtocol || protocol || 'tn5250'} loading={connecting || reconnecting} error={signInError || connectError} onConnect={handleSignIn} />\n </div>\n );\n }\n return (\n <div style={{ width: `${screenData?.cols || profile.defaultCols}ch`, height: `${(screenData?.rows || profile.defaultRows) * 21}px`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <div style={{ textAlign: 'center' }}>\n <div style={{ color: '#808080', marginBottom: '12px' }}><TerminalIcon size={40} /></div>\n <p style={{ fontFamily: 'var(--gs-font)', fontSize: '12px', color: '#808080' }}>\n {connStatus?.connected ? 'Waiting for screen data...' : 'Not connected'}\n </p>\n {!connStatus?.connected && isUsingDefaultAdapter && (\n <p style={{ fontFamily: 'var(--gs-font)', fontSize: '11px', color: '#606060', marginTop: '8px' }}>\n Start the proxy: <code style={{ color: '#10b981' }}>npx green-screen-proxy --mock</code>\n </p>\n )}\n </div>\n </div>\n );\n }\n return renderScreenContent();\n };\n\n const renderScreenContent = () => {\n if (!screenData?.content) return null;\n const termRows = screenData.rows || profile.defaultRows;\n const cols = screenData.cols || profile.defaultCols;\n const lines = screenData.content.split('\\n');\n const rows: string[] = [];\n for (let i = 0; i < termRows; i++) rows.push((lines[i] || '').padEnd(cols, ' '));\n\n const fields = screenData.fields || [];\n const ROW_HEIGHT = 21;\n const cursor = getCursorPos();\n const hasCursor = screenData.cursor_row !== undefined && screenData.cursor_col !== undefined;\n\n return (\n <div style={{ fontFamily: 'var(--gs-font)', fontSize: '13px', position: 'relative', width: `${cols}ch` }}>\n {rows.map((line, index) => {\n let displayLine = line;\n if (hasCursor && index === cursor.row && inputText && !animatedCursorPos) {\n const baseCol = syncedCursor?.col ?? screenData.cursor_col ?? 0;\n displayLine = (line.substring(0, baseCol) + inputText + line.substring(baseCol + inputText.length)).substring(0, cols).padEnd(cols, ' ');\n }\n const headerSegments = index === 0 ? profile.colors.parseHeaderRow(displayLine) : null;\n return (\n <div key={index} className={headerSegments ? '' : profile.colors.getRowColorClass(index, displayLine, termRows)} style={{ height: `${ROW_HEIGHT}px`, lineHeight: `${ROW_HEIGHT}px`, whiteSpace: 'pre', position: 'relative' }}>\n {headerSegments\n ? headerSegments.map((seg, i) => <span key={i} className={seg.colorClass}>{seg.text}</span>)\n : renderRowWithFields(displayLine, index, fields)}\n {hasCursor && !showSignInHint && index === cursor.row && (\n <span className=\"gs-cursor\" style={{ position: 'absolute', left: `${cursor.col}ch`, width: '1ch', height: `${ROW_HEIGHT}px`, top: 0, pointerEvents: 'none' }} />\n )}\n </div>\n );\n })}\n {showSignInHint && (\n <div className=\"gs-signin-hint\">\n Signed in — press Enter to continue\n </div>\n )}\n {screenData.cursor_row !== undefined && screenData.cursor_col !== undefined && (\n <span style={{ position: 'absolute', bottom: 0, right: 0, fontFamily: 'var(--gs-font)', fontSize: '10px', color: 'var(--gs-green, #10b981)', pointerEvents: 'none', opacity: 0.6 }}>\n {String(screenData.cursor_row + 1).padStart(2, '0')}/{String(screenData.cursor_col + 1).padStart(3, '0')}\n </span>\n )}\n </div>\n );\n };\n\n const handleReconnect = async () => {\n setAutoReconnectAttempt(0);\n setIsAutoReconnecting(false);\n if (reconnectTimeoutRef.current) { clearTimeout(reconnectTimeoutRef.current); reconnectTimeoutRef.current = null; }\n await reconnect();\n };\n\n const getStatusColor = (status?: string) => {\n switch (status) {\n case 'authenticated': return 'var(--gs-green, #10b981)';\n case 'connected': return '#F59E0B';\n case 'connecting': return '#64748b';\n case 'error': return '#EF4444';\n default: return '#64748b';\n }\n };\n\n return (\n <div className={`gs-terminal ${isFocused ? 'gs-terminal-focused' : ''} ${className || ''}`} style={style}>\n {showHeader && (\n <div className=\"gs-header\">\n {embedded ? (\n <>\n <span className=\"gs-header-left\">\n <TerminalIcon size={14} />\n <span>TERMINAL</span>\n {isFocused && <span className=\"gs-badge-focused\">FOCUSED</span>}\n {screenData?.timestamp && <span className=\"gs-timestamp\">{new Date(screenData.timestamp).toLocaleTimeString()}</span>}\n <span className=\"gs-hint\">{readOnly ? 'Read-only' : isFocused ? 'ESC to exit focus' : 'Click to control'}</span>\n </span>\n <div className=\"gs-header-right\">\n {connStatus?.status && <KeyIcon size={12} style={{ color: getStatusColor(connStatus.status) }} />}\n {connStatus && (connStatus.connected\n ? <WifiIcon size={12} style={{ color: 'var(--gs-green, #10b981)' }} />\n : <WifiOffIcon size={12} style={{ color: '#FF6B00' }} />)}\n {onMinimize && <button onClick={(e) => { e.stopPropagation(); onMinimize(); }} className=\"gs-btn-icon\" title=\"Minimize terminal\"><MinimizeIcon /></button>}\n {headerRight}\n </div>\n </>\n ) : (\n <>\n <span className=\"gs-header-left\">\n <TerminalIcon size={14} />\n <span>{profile.headerLabel}</span>\n {isFocused && <span className=\"gs-badge-focused\">FOCUSED</span>}\n {screenData?.timestamp && <span className=\"gs-timestamp\">{new Date(screenData.timestamp).toLocaleTimeString()}</span>}\n <span className=\"gs-hint\">{readOnly ? 'Read-only mode' : isFocused ? 'ESC to exit focus' : 'Click terminal to control'}</span>\n </span>\n <div className=\"gs-header-right\">\n {connStatus && (\n <div className=\"gs-status-group\">\n {connStatus.connected ? (\n <>\n <WifiIcon size={12} style={{ color: 'var(--gs-green, #10b981)' }} />\n <span className=\"gs-host\">{connStatus.host}</span>\n </>\n ) : (\n <>\n <WifiOffIcon size={12} style={{ color: '#FF6B00' }} />\n <span className=\"gs-disconnected-text\">\n {isAutoReconnecting || reconnecting\n ? `RECONNECTING${autoReconnectAttempt > 0 ? ` (${autoReconnectAttempt}/${maxAttempts})` : '...'}`\n : autoReconnectAttempt >= maxAttempts ? 'DISCONNECTED (auto-retry exhausted)' : 'DISCONNECTED'}\n </span>\n <button onClick={handleReconnect} disabled={reconnecting || isAutoReconnecting} className=\"gs-btn-icon\" title=\"Reconnect\">\n <RefreshIcon size={12} className={reconnecting || isAutoReconnecting ? 'gs-spin' : ''} />\n </button>\n </>\n )}\n </div>\n )}\n {connStatus?.status && (\n <div className=\"gs-status-group\">\n <KeyIcon size={12} style={{ color: getStatusColor(connStatus.status) }} />\n {connStatus.username && <span className=\"gs-host\">{connStatus.username}</span>}\n </div>\n )}\n {headerRight}\n </div>\n </>\n )}\n </div>\n )}\n\n <div className=\"gs-body\">\n <div ref={terminalRef} onClick={handleTerminalClick} className={`gs-screen ${embedded ? 'gs-screen-embedded' : ''}`}\n style={!embedded ? { width: `calc(${screenData?.cols || profile.defaultCols}ch + 24px)`, fontSize: (screenData?.cols ?? profile.defaultCols) > 80 ? '11px' : '13px', fontFamily: 'var(--gs-font)' } : undefined}>\n {screenError != null && (\n <div className=\"gs-error-banner\">\n <AlertTriangleIcon size={14} />\n <span>{String(screenError)}</span>\n </div>\n )}\n <div className=\"gs-screen-content\">{renderScreen()}</div>\n {overlay}\n {connStatus && !connStatus.connected && screenData && (\n <div className=\"gs-overlay\">\n <WifiOffIcon size={28} />\n <span>{isAutoReconnecting || reconnecting ? 'Reconnecting...' : 'Disconnected'}</span>\n </div>\n )}\n <input ref={inputRef} type=\"text\" value={inputText} onChange={handleInput} onKeyDown={handleKeyDown}\n style={{ position: 'absolute', opacity: 0, pointerEvents: 'none' }}\n autoComplete=\"off\" autoCorrect=\"off\" autoCapitalize=\"off\" spellCheck={false} />\n </div>\n </div>\n </div>\n );\n}\n","import type { TerminalAdapter, ScreenData, ConnectionStatus, SendResult, ConnectConfig } from './types';\n\nexport interface RestAdapterOptions {\n /** Base URL for the terminal API (e.g. \"https://myhost.com/api/terminal\") */\n baseUrl: string;\n /** Optional headers to include with every request (e.g. Authorization) */\n headers?: Record<string, string>;\n /** Optional function that returns headers (called per-request, useful for dynamic tokens) */\n getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * REST API adapter for terminal communication.\n *\n * Expects a backend that exposes these endpoints relative to `baseUrl`:\n * - GET /screen → ScreenData\n * - GET /status → ConnectionStatus\n * - POST /send-text → SendResult (body: { text })\n * - POST /send-key → SendResult (body: { key })\n * - POST /connect → SendResult\n * - POST /disconnect → SendResult\n * - POST /reconnect → SendResult\n */\nexport class RestAdapter implements TerminalAdapter {\n private baseUrl: string;\n private staticHeaders: Record<string, string>;\n private getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;\n\n constructor(options: RestAdapterOptions) {\n // Remove trailing slash\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.staticHeaders = options.headers || {};\n this.getHeaders = options.getHeaders;\n }\n\n private async buildHeaders(): Promise<Record<string, string>> {\n const dynamic = this.getHeaders ? await this.getHeaders() : {};\n return {\n 'Content-Type': 'application/json',\n ...this.staticHeaders,\n ...dynamic,\n };\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const headers = await this.buildHeaders();\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const detail = await response.json().catch(() => ({}));\n throw new Error(detail?.detail || `HTTP ${response.status}`);\n }\n\n return response.json();\n }\n\n async getScreen(): Promise<ScreenData | null> {\n try {\n return await this.request<ScreenData>('GET', '/screen');\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n // 503/404 expected when no active connection\n if (message.includes('503') || message.includes('404')) {\n return null;\n }\n throw e;\n }\n }\n\n async getStatus(): Promise<ConnectionStatus> {\n return this.request<ConnectionStatus>('GET', '/status');\n }\n\n async sendText(text: string): Promise<SendResult> {\n return this.request<SendResult>('POST', '/send-text', { text });\n }\n\n async sendKey(key: string): Promise<SendResult> {\n return this.request<SendResult>('POST', '/send-key', { key });\n }\n\n async connect(config?: ConnectConfig): Promise<SendResult> {\n return this.request<SendResult>('POST', '/connect', config);\n }\n\n async disconnect(): Promise<SendResult> {\n return this.request<SendResult>('POST', '/disconnect');\n }\n\n async reconnect(): Promise<SendResult> {\n return this.request<SendResult>('POST', '/reconnect');\n }\n}\n","import type { TerminalAdapter, ScreenData, ConnectionStatus, SendResult, ConnectConfig } from './types';\n\nexport interface WebSocketAdapterOptions {\n /** URL of the green-screen proxy or worker. Auto-detected from env vars, defaults to http://localhost:3001 */\n workerUrl?: string;\n}\n\n/**\n * WebSocket adapter that connects to a green-screen proxy or Cloudflare Worker.\n * The backend holds the TCP connection to the legacy host and relays protocol data.\n *\n * Unlike RestAdapter (which polls over HTTP), this adapter receives real-time\n * screen updates via WebSocket push.\n *\n * workerUrl resolution order:\n * 1. Explicit `workerUrl` option\n * 2. VITE_GREEN_SCREEN_URL / VITE_WORKER_URL (Vite)\n * 3. NEXT_PUBLIC_GREEN_SCREEN_URL (Next.js)\n * 4. REACT_APP_GREEN_SCREEN_URL (CRA)\n * 5. http://localhost:3001\n */\nexport class WebSocketAdapter implements TerminalAdapter {\n private workerUrl: string;\n private ws: WebSocket | null = null;\n private screen: ScreenData | null = null;\n private status: ConnectionStatus = { connected: false, status: 'disconnected' };\n private pendingScreenResolver: ((value: ScreenData | null) => void) | null = null;\n private pendingConnectResolver: ((result: SendResult) => void) | null = null;\n private connectingPromise: Promise<void> | null = null;\n private screenListeners: Set<(screen: ScreenData) => void> = new Set();\n private statusListeners: Set<(status: ConnectionStatus) => void> = new Set();\n private _sessionId: string | null = null;\n\n constructor(options: WebSocketAdapterOptions = {}) {\n this.workerUrl = (\n options.workerUrl\n || WebSocketAdapter.detectEnvUrl()\n || 'http://localhost:3001'\n ).replace(/\\/+$/, '');\n }\n\n private static detectEnvUrl(): string | undefined {\n try {\n if (typeof import.meta !== 'undefined' && (import.meta as any).env) {\n const env = (import.meta as any).env;\n return env.VITE_GREEN_SCREEN_URL || env.VITE_WORKER_URL || undefined;\n }\n } catch { /* import.meta not available */ }\n try {\n // Use indirect eval to avoid static analysis picking up 'process' as a Node global\n const p = typeof globalThis !== 'undefined' && (globalThis as any).process;\n if (p && p.env) {\n return p.env.NEXT_PUBLIC_GREEN_SCREEN_URL\n || p.env.REACT_APP_GREEN_SCREEN_URL\n || undefined;\n }\n } catch { /* process not available */ }\n return undefined;\n }\n\n /** The proxy-side session ID (available after connect or reattach) */\n get sessionId(): string | null {\n return this._sessionId;\n }\n\n /** Subscribe to real-time screen updates */\n onScreen(listener: (screen: ScreenData) => void): () => void {\n this.screenListeners.add(listener);\n return () => this.screenListeners.delete(listener);\n }\n\n /** Subscribe to status changes */\n onStatus(listener: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => this.statusListeners.delete(listener);\n }\n\n async getScreen(): Promise<ScreenData | null> {\n return this.screen;\n }\n\n async getStatus(): Promise<ConnectionStatus> {\n return this.status;\n }\n\n async sendText(text: string): Promise<SendResult> {\n return this.sendAndWaitForScreen({ type: 'text', text });\n }\n\n async sendKey(key: string): Promise<SendResult> {\n return this.sendAndWaitForScreen({ type: 'key', key });\n }\n\n async connect(config?: ConnectConfig): Promise<SendResult> {\n await this.ensureWebSocket();\n\n if (!config) {\n return { success: false, error: 'ConnectConfig required' };\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n this.pendingConnectResolver = null;\n resolve({ success: false, error: 'Connection timeout' });\n }, 30000);\n\n this.pendingConnectResolver = (result: SendResult) => {\n clearTimeout(timeout);\n resolve(result);\n };\n\n this.wsSend({\n type: 'connect',\n host: config.host,\n port: config.port,\n protocol: config.protocol,\n username: config.username,\n password: config.password,\n });\n });\n }\n\n /**\n * Reattach to an existing proxy session (e.g. after page reload).\n * The proxy keeps the TCP connection alive; this just reconnects the\n * WebSocket and receives the current screen.\n */\n async reattach(sessionId: string): Promise<SendResult> {\n await this.ensureWebSocket();\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n this.pendingConnectResolver = null;\n resolve({ success: false, error: 'Reattach timeout' });\n }, 10000);\n\n this.pendingConnectResolver = (result: SendResult) => {\n clearTimeout(timeout);\n resolve(result);\n };\n\n this.wsSend({ type: 'reattach', sessionId });\n });\n }\n\n async disconnect(): Promise<SendResult> {\n this.wsSend({ type: 'disconnect' });\n this.status = { connected: false, status: 'disconnected' };\n this._sessionId = null;\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n return { success: true };\n }\n\n async reconnect(): Promise<SendResult> {\n return { success: false, error: 'Use disconnect() then connect() instead' };\n }\n\n /** Close the WebSocket without sending disconnect (session stays alive on proxy) */\n dispose(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n private async ensureWebSocket(): Promise<void> {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) return;\n if (this.connectingPromise) return this.connectingPromise;\n\n this.connectingPromise = new Promise<void>((resolve, reject) => {\n const wsUrl = this.workerUrl.replace(/^http/, 'ws') + '/ws';\n this.ws = new WebSocket(wsUrl);\n\n this.ws.onopen = () => resolve();\n this.ws.onerror = () => reject(new Error('WebSocket connection failed'));\n\n this.ws.onmessage = (event) => {\n try {\n const msg = JSON.parse(event.data);\n this.handleMessage(msg);\n } catch { /* ignore non-JSON messages */ }\n };\n\n this.ws.onclose = () => {\n this.status = { connected: false, status: 'disconnected' };\n for (const listener of this.statusListeners) listener(this.status);\n };\n }).finally(() => {\n this.connectingPromise = null;\n });\n\n return this.connectingPromise;\n }\n\n private handleMessage(msg: any): void {\n switch (msg.type) {\n case 'screen': {\n this.screen = msg.data;\n for (const listener of this.screenListeners) listener(msg.data);\n if (this.pendingScreenResolver) {\n const resolver = this.pendingScreenResolver;\n this.pendingScreenResolver = null;\n resolver(msg.data);\n }\n break;\n }\n\n case 'status':\n this.status = msg.data;\n for (const listener of this.statusListeners) listener(msg.data);\n break;\n\n case 'connected':\n this._sessionId = msg.sessionId ?? null;\n if (this.pendingConnectResolver) {\n const resolver = this.pendingConnectResolver;\n this.pendingConnectResolver = null;\n resolver({ success: true });\n }\n break;\n\n case 'error': {\n if (this.pendingConnectResolver) {\n const resolver = this.pendingConnectResolver;\n this.pendingConnectResolver = null;\n resolver({ success: false, error: msg.message });\n } else if (this.pendingScreenResolver) {\n const resolver = this.pendingScreenResolver;\n this.pendingScreenResolver = null;\n resolver(null);\n }\n break;\n }\n }\n }\n\n private sendAndWaitForScreen(msg: object): Promise<SendResult> {\n return new Promise((resolve) => {\n // Flush any existing pending resolver with current screen data\n if (this.pendingScreenResolver) {\n const old = this.pendingScreenResolver;\n this.pendingScreenResolver = null;\n old(this.screen);\n }\n\n const timeout = setTimeout(() => {\n this.pendingScreenResolver = null;\n resolve({ success: true, ...this.screenToResult() });\n }, 5000);\n\n this.pendingScreenResolver = (screen: ScreenData | null) => {\n clearTimeout(timeout);\n if (screen) {\n resolve({\n success: true,\n cursor_row: screen.cursor_row,\n cursor_col: screen.cursor_col,\n content: screen.content,\n screen_signature: screen.screen_signature,\n });\n } else {\n resolve({ success: false, error: 'No screen data received' });\n }\n };\n\n this.wsSend(msg);\n });\n }\n\n private screenToResult(): Partial<SendResult> {\n if (!this.screen) return {};\n return {\n cursor_row: this.screen.cursor_row,\n cursor_col: this.screen.cursor_col,\n content: this.screen.content,\n screen_signature: this.screen.screen_signature,\n };\n }\n\n private wsSend(data: object): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(data));\n }\n }\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport type { TerminalAdapter, ScreenData, ConnectionStatus, SendResult, ConnectConfig } from '../adapters/types';\n\n/**\n * Hook for terminal connection management via adapter.\n */\nexport function useTerminalConnection(adapter: TerminalAdapter) {\n const [status, setStatus] = useState<ConnectionStatus | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchStatus = useCallback(async () => {\n try {\n const result = await adapter.getStatus();\n setStatus(result);\n return result;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return null;\n }\n }, [adapter]);\n\n const connect = useCallback(async (config?: ConnectConfig) => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.connect(config);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const disconnect = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n await adapter.disconnect();\n setStatus(prev => prev ? { ...prev, connected: false, status: 'disconnected' } : null);\n return { success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const reconnect = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.reconnect();\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n return { status, loading, error, fetchStatus, connect, disconnect, reconnect };\n}\n\n/**\n * Hook for terminal screen content with polling.\n */\nexport function useTerminalScreen(\n adapter: TerminalAdapter,\n interval: number = 2000,\n enabled: boolean = true,\n) {\n const [data, setData] = useState<ScreenData | null>(null);\n const [error, setError] = useState<unknown>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return;\n }\n\n const poll = async () => {\n try {\n const screen = await adapter.getScreen();\n if (screen) setData(screen);\n setError(null);\n } catch (err) {\n setError(err);\n }\n };\n\n poll(); // Initial fetch\n intervalRef.current = setInterval(poll, interval);\n\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [adapter, interval, enabled]);\n\n return { data, error };\n}\n\n/**\n * Hook for terminal operations (sendText, sendKey).\n */\nexport function useTerminalInput(adapter: TerminalAdapter) {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const sendText = useCallback(async (text: string): Promise<SendResult> => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.sendText(text);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n const sendKey = useCallback(async (key: string): Promise<SendResult> => {\n setLoading(true);\n setError(null);\n try {\n const result = await adapter.sendKey(key);\n return { ...result, success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n return { success: false, error: message };\n } finally {\n setLoading(false);\n }\n }, [adapter]);\n\n return { loading, error, sendText, sendKey };\n}\n","import { useState, useEffect, useRef, useCallback, useMemo } from 'react';\nimport { positionToRowCol, isFieldEntry } from '../utils/grid';\n\n/**\n * Hook for typing animation effect on terminal screen content.\n * Reveals characters progressively when screen content changes.\n * Also provides animated cursor position that follows the typing.\n *\n * Uses a queue-based model: incoming content updates are queued when an\n * animation is in progress, then played sequentially. This prevents\n * blinks (no mid-animation cancellation) and skips (every field entry\n * gets its own animation). Queue depth is capped to avoid falling\n * behind real-time.\n *\n * Screen transitions (large changes) always display SYNCHRONOUSLY.\n */\nexport function useTypingAnimation(\n content: string | null | undefined,\n enabled: boolean = true,\n typingBudgetMs: number = 100,\n) {\n const FRAME_DELAY = 16; // ~60fps\n\n const previousContentRef = useRef('');\n const targetContentRef = useRef('');\n const contentQueueRef = useRef<string[]>([]);\n const isAnimatingRef = useRef(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const rafRef = useRef<number | null>(null);\n\n const [animatedContent, setAnimatedContent] = useState('');\n const [isAnimating, setIsAnimating] = useState(false);\n const [animatedCursorPos, setAnimatedCursorPos] = useState<{ row: number; col: number } | null>(null);\n\n const cancelAnimation = () => {\n if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; }\n if (rafRef.current) { cancelAnimationFrame(rafRef.current); rafRef.current = null; }\n };\n\n const showInstant = useCallback((c: string) => {\n cancelAnimation();\n setAnimatedContent(c);\n setAnimatedCursorPos(null);\n setIsAnimating(false);\n isAnimatingRef.current = false;\n previousContentRef.current = c;\n targetContentRef.current = '';\n }, []);\n\n const processNextRef = useRef<(() => void) | null>(null);\n\n const startFieldAnimation = useCallback((fromContent: string, toContent: string) => {\n let diffStart = -1;\n let diffEnd = 0;\n const maxLen = Math.max(fromContent.length, toContent.length);\n for (let i = 0; i < maxLen; i++) {\n if ((fromContent[i] || ' ') !== (toContent[i] || ' ')) {\n if (diffStart === -1) diffStart = i;\n diffEnd = i;\n }\n }\n if (diffStart === -1) { showInstant(toContent); return; }\n\n setIsAnimating(true);\n isAnimatingRef.current = true;\n targetContentRef.current = toContent;\n\n const diffLength = diffEnd - diffStart + 1;\n\n const oldRegion = fromContent.substring(diffStart, diffEnd + 1);\n const isCorrection = oldRegion.replace(/[_\\s\\n]/g, '').length > 0;\n\n const finishAnimation = () => {\n setAnimatedContent(toContent);\n setIsAnimating(false);\n isAnimatingRef.current = false;\n setAnimatedCursorPos(null);\n previousContentRef.current = toContent;\n targetContentRef.current = '';\n timeoutRef.current = null;\n rafRef.current = null;\n if (processNextRef.current) processNextRef.current();\n };\n\n if (isCorrection) {\n const CORRECTION_BUDGET = 400;\n const removalBudget = Math.floor(CORRECTION_BUDGET * 0.4);\n const typingBudget = CORRECTION_BUDGET - removalBudget;\n const removalFrames = Math.max(2, Math.floor(removalBudget / FRAME_DELAY));\n const typingFrames = Math.max(2, Math.floor(typingBudget / FRAME_DELAY));\n const removalCPF = Math.max(1, Math.ceil(diffLength / removalFrames));\n const typingCPF = Math.max(1, Math.ceil(diffLength / typingFrames));\n\n let removePos = diffEnd + 1;\n let typePos = diffStart;\n\n const buildRemovalContent = (erasedFrom: number) => {\n const before = fromContent.substring(0, diffStart);\n const remaining = fromContent.substring(diffStart, erasedFrom);\n const erased = ' '.repeat(Math.max(0, diffEnd + 1 - erasedFrom));\n const after = toContent.substring(diffEnd + 1);\n return before + remaining + erased + after;\n };\n\n const buildTypingContent = (revealedUpTo: number) => {\n const before = toContent.substring(0, diffStart);\n const revealed = toContent.substring(diffStart, revealedUpTo);\n const hidden = toContent.substring(revealedUpTo, diffEnd + 1).replace(/[^\\n]/g, ' ');\n const after = toContent.substring(diffEnd + 1);\n return before + revealed + hidden + after;\n };\n\n const animateTyping = () => {\n typePos += typingCPF;\n if (typePos >= diffEnd + 1) {\n finishAnimation();\n } else {\n setAnimatedContent(buildTypingContent(typePos));\n setAnimatedCursorPos(positionToRowCol(toContent, typePos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateTyping);\n }, FRAME_DELAY);\n }\n };\n\n const animateRemoval = () => {\n removePos -= removalCPF;\n if (removePos <= diffStart) {\n setAnimatedContent(buildTypingContent(diffStart));\n setAnimatedCursorPos(positionToRowCol(toContent, diffStart));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateTyping);\n }, FRAME_DELAY);\n } else {\n setAnimatedContent(buildRemovalContent(removePos));\n setAnimatedCursorPos(positionToRowCol(fromContent, removePos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateRemoval);\n }, FRAME_DELAY);\n }\n };\n\n setAnimatedCursorPos(positionToRowCol(fromContent, diffEnd));\n setAnimatedContent(buildRemovalContent(diffEnd + 1));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animateRemoval);\n }, FRAME_DELAY);\n } else {\n let currentPos = diffStart;\n const totalFrames = Math.max(1, Math.floor(typingBudgetMs / FRAME_DELAY));\n const charsPerFrame = Math.max(1, Math.ceil(diffLength / totalFrames));\n\n setAnimatedCursorPos(positionToRowCol(toContent, diffStart));\n\n const buildDisplayContent = (revealedUpTo: number) => {\n const before = toContent.substring(0, diffStart);\n const revealed = toContent.substring(diffStart, revealedUpTo);\n const hidden = toContent.substring(revealedUpTo, diffEnd + 1).replace(/[^\\n]/g, ' ');\n const after = toContent.substring(diffEnd + 1);\n return before + revealed + hidden + after;\n };\n\n const animate = () => {\n currentPos += charsPerFrame;\n if (currentPos >= diffEnd + 1) {\n finishAnimation();\n } else {\n setAnimatedContent(buildDisplayContent(currentPos));\n setAnimatedCursorPos(positionToRowCol(toContent, currentPos));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animate);\n }, FRAME_DELAY);\n }\n };\n\n setAnimatedContent(buildDisplayContent(diffStart));\n timeoutRef.current = setTimeout(() => {\n rafRef.current = requestAnimationFrame(animate);\n }, FRAME_DELAY);\n }\n }, [showInstant, typingBudgetMs]);\n\n processNextRef.current = () => {\n const queue = contentQueueRef.current;\n if (queue.length === 0) return;\n\n while (queue.length > 2) queue.shift();\n\n const next = queue.shift()!;\n const base = previousContentRef.current;\n\n if (isFieldEntry(base, next)) {\n startFieldAnimation(base, next);\n } else {\n showInstant(next);\n if (queue.length > 0 && processNextRef.current) processNextRef.current();\n }\n };\n\n const shouldAnimate = enabled && content && isFieldEntry(previousContentRef.current, content);\n if (!shouldAnimate && !isAnimatingRef.current && content !== previousContentRef.current) {\n previousContentRef.current = content || '';\n }\n\n useEffect(() => {\n if (!enabled || !content) {\n cancelAnimation();\n contentQueueRef.current = [];\n showInstant(content || '');\n previousContentRef.current = content || '';\n return;\n }\n\n const currentTarget = targetContentRef.current || previousContentRef.current;\n if (content === currentTarget) return;\n\n if (isAnimatingRef.current) {\n if (!isFieldEntry(currentTarget, content)) {\n contentQueueRef.current = [];\n showInstant(content);\n } else {\n contentQueueRef.current.push(content);\n if (contentQueueRef.current.length > 3) {\n contentQueueRef.current = contentQueueRef.current.slice(-2);\n }\n }\n return;\n }\n\n const prev = previousContentRef.current;\n if (!isFieldEntry(prev, content)) {\n showInstant(content);\n return;\n }\n startFieldAnimation(prev, content);\n\n return cancelAnimation;\n }, [content, enabled, showInstant, startFieldAnimation]);\n\n const animationActive = isAnimatingRef.current;\n\n const displayedContent = useMemo(() => {\n if (!enabled || !content) return content || '';\n if (animationActive) return animatedContent;\n return content;\n }, [enabled, content, animationActive, animatedContent]);\n\n const effectiveCursorPos = animationActive ? animatedCursorPos : null;\n\n return { displayedContent, isAnimating, animatedCursorPos: effectiveCursorPos };\n}\n","/**\n * Convert a linear position in screen content to row/col coordinates.\n * Content is lines of characters separated by newlines.\n */\nexport function positionToRowCol(content: string, position: number): { row: number; col: number } {\n let row = 0;\n let col = 0;\n for (let i = 0; i < position && i < content.length; i++) {\n if (content[i] === '\\n') {\n row++;\n col = 0;\n } else {\n col++;\n }\n }\n return { row, col };\n}\n\n/**\n * Detect if a content change is a field entry (small, localized change)\n * vs a screen transition (large, distributed change).\n *\n * Field entries: < 50 changed characters within a span of < 100 positions.\n * Screen transitions: everything else.\n */\nexport function isFieldEntry(previousContent: string | null | undefined, content: string | null | undefined): boolean {\n if (!previousContent || !content) return false;\n\n let diffCount = 0;\n let diffStart = -1;\n let diffEnd = 0;\n const maxLen = Math.max(previousContent.length, content.length);\n\n for (let i = 0; i < maxLen; i++) {\n const oldChar = previousContent[i] || ' ';\n const newChar = content[i] || ' ';\n if (oldChar !== newChar) {\n diffCount++;\n if (diffStart === -1) diffStart = i;\n diffEnd = i;\n }\n }\n\n const diffSpan = diffEnd - diffStart + 1;\n // Field entry: small number of changes (< 50 chars), localized (span < 100)\n return diffCount > 2 && diffCount < 50 && diffSpan < 100;\n}\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const tn5250Profile: ProtocolProfile = {\n protocol: 'tn5250',\n displayName: 'IBM TN5250',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'TN5250 TERMINAL',\n bootText: 'TN5250',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 2) return 'gs-row-fkey';\n if (/F\\d{1,2}=/.test(rowContent)) return 'gs-row-fkey';\n if (/Select one of the following/i.test(rowContent)) return 'gs-row-subtitle';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n const trimmed = line.trimStart();\n const leftMatch = trimmed.match(/^(\\S+)/);\n if (leftMatch) {\n const leftId = leftMatch[1];\n const leftEnd = line.indexOf(leftId) + leftId.length;\n const rightMatch = line.trimEnd().match(/(\\S+)$/);\n if (rightMatch && rightMatch[1] !== leftId) {\n const rightStart = line.lastIndexOf(rightMatch[1]);\n return [\n { text: line.substring(0, leftEnd), colorClass: 'gs-row-fkey' },\n { text: line.substring(leftEnd, rightStart), colorClass: 'gs-row-title' },\n { text: line.substring(rightStart), colorClass: 'gs-row-content' },\n ];\n }\n }\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const tn3270Profile: ProtocolProfile = {\n protocol: 'tn3270',\n displayName: 'IBM TN3270',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'TN3270 TERMINAL',\n bootText: 'TN3270',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n // z/OS ISPF conventions: row 0 = title, last 2 rows = PF keys/command\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 2) return 'gs-row-fkey';\n if (/PF\\d{1,2}[=/]/.test(rowContent) || /F\\d{1,2}=/.test(rowContent)) return 'gs-row-fkey';\n if (/COMMAND\\s*===>/i.test(rowContent) || /===>/.test(rowContent)) return 'gs-row-subtitle';\n if (/OPTION\\s*===>/i.test(rowContent)) return 'gs-row-subtitle';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n // ISPF: typically \"Menu Utilities Compilers ...\" action bar or panel title\n const trimmed = line.trimStart();\n const leftMatch = trimmed.match(/^(\\S+)/);\n if (leftMatch) {\n const leftId = leftMatch[1];\n const leftEnd = line.indexOf(leftId) + leftId.length;\n const rightMatch = line.trimEnd().match(/(\\S+)$/);\n if (rightMatch && rightMatch[1] !== leftId) {\n const rightStart = line.lastIndexOf(rightMatch[1]);\n return [\n { text: line.substring(0, leftEnd), colorClass: 'gs-row-fkey' },\n { text: line.substring(leftEnd, rightStart), colorClass: 'gs-row-title' },\n { text: line.substring(rightStart), colorClass: 'gs-row-content' },\n ];\n }\n }\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const vtProfile: ProtocolProfile = {\n protocol: 'vt',\n displayName: 'VT Terminal',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: 'VT TERMINAL',\n bootText: 'VT220',\n colors: {\n getRowColorClass(_rowIndex: number, _rowContent: string, _totalRows: number): string {\n // VT terminals use inline escape-sequence-driven colors, not row-based conventions.\n // All rows default to green; actual colors come from ANSI attributes in the data stream.\n return 'gs-row-content';\n },\n parseHeaderRow(_line: string): { text: string; colorClass: string }[] | null {\n // VT has no header row convention\n return null;\n },\n },\n};\n","import type { ProtocolProfile } from '../adapters/types';\n\nexport const hp6530Profile: ProtocolProfile = {\n protocol: 'hp6530',\n displayName: 'HP 6530',\n defaultRows: 24,\n defaultCols: 80,\n headerLabel: '6530 TERMINAL',\n bootText: 'HP6530',\n colors: {\n getRowColorClass(rowIndex: number, rowContent: string, totalRows: number): string {\n // HP NonStop 6530: row 0 = status/title, last row = function key labels\n if (rowIndex === 0 && rowContent.trim().length > 0) return 'gs-row-title';\n if (rowIndex >= totalRows - 1) return 'gs-row-fkey';\n if (/F\\d{1,2}[=\\-]/.test(rowContent) || /SF\\d{1,2}/.test(rowContent)) return 'gs-row-fkey';\n return 'gs-row-content';\n },\n parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n if (line.trim().length === 0) return null;\n return [{ text: line, colorClass: 'gs-row-title' }];\n },\n },\n};\n","import type { TerminalProtocol, ProtocolProfile } from '../adapters/types';\nimport { tn5250Profile } from './tn5250';\nimport { tn3270Profile } from './tn3270';\nimport { vtProfile } from './vt';\nimport { hp6530Profile } from './hp6530';\n\nconst profiles: Record<TerminalProtocol, ProtocolProfile> = {\n tn5250: tn5250Profile,\n tn3270: tn3270Profile,\n vt: vtProfile,\n hp6530: hp6530Profile,\n};\n\n/**\n * Get a protocol profile by type. Defaults to TN5250 for backward compatibility.\n */\nexport function getProtocolProfile(protocol?: TerminalProtocol): ProtocolProfile {\n return profiles[protocol || 'tn5250'];\n}\n","import React, { useState, useEffect, useRef } from 'react';\n\nexport interface TerminalBootLoaderProps {\n /** Text to display during boot animation */\n brandText?: string;\n /** Speed in ms per character */\n charSpeed?: number;\n /** Optional logo element to render alongside the text */\n logo?: React.ReactNode;\n /** Height of the boot loader container */\n height?: number | string;\n}\n\n/**\n * Animated boot loader for the terminal.\n * Shows a typewriter-style text reveal animation.\n */\nexport function TerminalBootLoader({\n brandText = 'TERMINAL',\n charSpeed = 80,\n logo,\n height = 504,\n}: TerminalBootLoaderProps) {\n const [charCount, setCharCount] = useState(0);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n intervalRef.current = setInterval(() => {\n setCharCount(prev => {\n if (prev >= brandText.length) {\n if (intervalRef.current) clearInterval(intervalRef.current);\n return prev;\n }\n return prev + 1;\n });\n }, charSpeed);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [brandText, charSpeed]);\n\n const displayed = brandText.substring(0, charCount);\n\n return (\n <div\n className=\"gs-boot-loader\"\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n backgroundColor: 'var(--gs-bg, #000)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'var(--gs-font)',\n fontSize: '13px',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>\n {logo}\n <h1\n style={{\n fontFamily: 'var(--gs-font)',\n fontSize: '1.5rem',\n letterSpacing: '0.1em',\n color: 'var(--gs-green, #10b981)',\n textShadow: '0 0 12px rgba(16, 185, 129, 0.4)',\n margin: 0,\n }}\n >\n {displayed}\n <span\n className=\"tn5250-cursor\"\n style={{\n display: 'inline-block',\n width: '0.6ch',\n height: '1.2em',\n verticalAlign: 'middle',\n marginLeft: '2px',\n }}\n />\n </h1>\n </div>\n </div>\n );\n}\n","import React from 'react';\n\nexport const TerminalIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 17 10 11 4 5\" /><line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\" />\n </svg>\n);\n\nexport const WifiIcon = ({ size = 12, className, style: s }: { size?: number; className?: string; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className} style={s}>\n <path d=\"M5 12.55a11 11 0 0 1 14.08 0\" /><path d=\"M1.42 9a16 16 0 0 1 21.16 0\" /><path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" /><line x1=\"12\" y1=\"20\" x2=\"12.01\" y2=\"20\" />\n </svg>\n);\n\nexport const WifiOffIcon = ({ size = 12, className, style: s }: { size?: number; className?: string; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className} style={s}>\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" /><path d=\"M16.72 11.06A10.94 10.94 0 0 1 19 12.55\" /><path d=\"M5 12.55a10.94 10.94 0 0 1 5.17-2.39\" /><path d=\"M10.71 5.05A16 16 0 0 1 22.56 9\" /><path d=\"M1.42 9a15.91 15.91 0 0 1 4.7-2.88\" /><path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" /><line x1=\"12\" y1=\"20\" x2=\"12.01\" y2=\"20\" />\n </svg>\n);\n\nexport const AlertTriangleIcon = ({ size = 14 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" /><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" /><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n);\n\nexport const RefreshIcon = ({ size = 12, className }: { size?: number; className?: string }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <polyline points=\"23 4 23 10 17 10\" /><polyline points=\"1 20 1 14 7 14\" /><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\" />\n </svg>\n);\n\nexport const KeyIcon = ({ size = 12, style: s }: { size?: number; style?: React.CSSProperties }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={s}>\n <path d=\"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4\" />\n </svg>\n);\n\nexport const MinimizeIcon = () => (\n <svg width={14} height={14} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M4 14h6v6M3 21l7-7M20 10h-6V4M21 3l-7 7\" />\n </svg>\n);\n","import React, { useState } from 'react';\nimport type { TerminalProtocol, ConnectConfig } from '../adapters/types';\nimport { TerminalIcon, AlertTriangleIcon, RefreshIcon } from './Icons';\n\nconst PROTOCOL_OPTIONS: { value: TerminalProtocol; label: string }[] = [\n { value: 'tn5250', label: 'TN5250 (IBM i)' },\n { value: 'tn3270', label: 'TN3270 (Mainframe)' },\n { value: 'vt', label: 'VT220' },\n { value: 'hp6530', label: 'HP 6530 (NonStop)' },\n];\n\nexport interface InlineSignInProps {\n defaultProtocol: TerminalProtocol;\n loading: boolean;\n error: string | null;\n onConnect: (config: ConnectConfig) => void;\n}\n\nexport function InlineSignIn({ defaultProtocol, loading: externalLoading, error, onConnect }: InlineSignInProps) {\n const [host, setHost] = useState('');\n const [port, setPort] = useState('');\n const [selectedProtocol, setSelectedProtocol] = useState<TerminalProtocol>(defaultProtocol);\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [submitted, setSubmitted] = useState(false);\n\n const loading = externalLoading || submitted;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setSubmitted(true);\n onConnect({\n host,\n port: port ? parseInt(port, 10) : 23,\n protocol: selectedProtocol,\n ...(username.trim() ? { username: username.trim() } : {}),\n ...(password ? { password } : {}),\n });\n };\n\n const inputStyle: React.CSSProperties = {\n width: '100%',\n padding: '6px 8px',\n backgroundColor: 'rgba(16, 185, 129, 0.05)',\n border: '1px solid var(--gs-card-border, #1e293b)',\n color: 'var(--gs-green, #10b981)',\n fontFamily: 'var(--gs-font)',\n fontSize: '13px',\n outline: 'none',\n boxSizing: 'border-box',\n };\n\n const labelStyle: React.CSSProperties = {\n display: 'block',\n marginBottom: '4px',\n fontSize: '10px',\n letterSpacing: '0.1em',\n textTransform: 'uppercase',\n color: 'var(--gs-muted, #94a3b8)',\n fontFamily: 'var(--gs-font)',\n };\n\n if (loading) {\n return (\n <div className=\"gs-signin\" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '12px' }}>\n <RefreshIcon size={28} className=\"gs-spin\" />\n <div style={{ fontSize: '11px', letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--gs-muted)', fontFamily: 'var(--gs-font)' }}>\n Connecting to {host || 'host'}...\n </div>\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"gs-signin\">\n <div style={{ textAlign: 'center', marginBottom: '16px' }}>\n <TerminalIcon size={28} />\n <div style={{ fontSize: '11px', letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--gs-muted)', marginTop: '8px' }}>Connect to Host</div>\n </div>\n\n <div className=\"gs-signin-row\">\n <div style={{ flex: 1 }}>\n <label style={labelStyle}>Host <span style={{ color: '#ef4444' }}>*</span></label>\n <input style={inputStyle} value={host} onChange={e => setHost(e.target.value)} placeholder=\"192.168.1.100\" required autoFocus />\n </div>\n <div style={{ width: '72px' }}>\n <label style={labelStyle}>Port</label>\n <input style={inputStyle} value={port} onChange={e => setPort(e.target.value)} placeholder=\"23\" type=\"number\" min=\"1\" max=\"65535\" />\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Protocol <span style={{ color: '#ef4444' }}>*</span></label>\n <select style={{ ...inputStyle, appearance: 'none' }} value={selectedProtocol} onChange={e => setSelectedProtocol(e.target.value as TerminalProtocol)}>\n {PROTOCOL_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}\n </select>\n </div>\n\n <div>\n <label style={labelStyle}>Username</label>\n <input style={inputStyle} value={username} onChange={e => setUsername(e.target.value)} autoComplete=\"username\" />\n </div>\n\n <div>\n <label style={labelStyle}>Password</label>\n <input style={inputStyle} type=\"password\" value={password} onChange={e => setPassword(e.target.value)} autoComplete=\"current-password\" />\n </div>\n\n {error && (\n <div style={{ color: '#FF6B00', fontSize: '11px', fontFamily: 'var(--gs-font)', display: 'flex', alignItems: 'center', gap: '6px' }}>\n <AlertTriangleIcon size={12} />\n <span>{error}</span>\n </div>\n )}\n\n <button type=\"submit\" disabled={!host} className=\"gs-signin-btn\">\n Connect\n </button>\n </form>\n );\n}\n","import { getProtocolProfile } from '../protocols/registry';\n\n/**\n * Get the appropriate CSS class name for a row.\n * Delegates to the TN5250 protocol profile for backward compatibility.\n *\n * For protocol-aware rendering, use `getProtocolProfile(protocol).colors.getRowColorClass()`.\n */\nexport function getRowColorClass(rowIndex: number, rowContent: string): string {\n return getProtocolProfile('tn5250').colors.getRowColorClass(rowIndex, rowContent, 24);\n}\n\n/**\n * Parse the header row into colored segments.\n * Delegates to the TN5250 protocol profile for backward compatibility.\n *\n * For protocol-aware rendering, use `getProtocolProfile(protocol).colors.parseHeaderRow()`.\n */\nexport function parseHeaderRow(line: string): { text: string; colorClass: string }[] | null {\n return getProtocolProfile('tn5250').colors.parseHeaderRow(line);\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","useCallback","useMemo","useState","useEffect","useRef","useCallback","useRef","useState","useCallback","useEffect","useState","useEffect","useRef","jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","useState","useMemo","useRef","useEffect","useCallback"]}
package/dist/styles.css CHANGED
@@ -133,6 +133,7 @@
133
133
  background-color: var(--gs-bg);
134
134
  flex: 1;
135
135
  display: flex;
136
+ justify-content: center;
136
137
  padding: 0;
137
138
  overflow: hidden;
138
139
  }
@@ -191,7 +192,13 @@
191
192
  .gs-input-field {
192
193
  display: inline-block;
193
194
  position: relative;
194
- border-bottom: 2px solid var(--gs-green);
195
+ border-bottom: 1px solid rgba(16, 185, 129, 0.45);
196
+ }
197
+
198
+ .gs-confirmed-field {
199
+ display: inline-block;
200
+ position: relative;
201
+ color: var(--gs-cyan);
195
202
  }
196
203
 
197
204
  /* ── Overlays ─────────────────────────────────────────────────────── */
@@ -230,6 +237,26 @@
230
237
  color: #FF6B00;
231
238
  }
232
239
 
240
+ /* ── Sign-in Hint ────────────────────────────────────────────────── */
241
+
242
+ .gs-signin-hint {
243
+ position: absolute;
244
+ bottom: 0;
245
+ left: 0;
246
+ right: 0;
247
+ padding: 6px 12px;
248
+ background-color: rgba(16, 185, 129, 0.12);
249
+ border-top: 1px solid rgba(16, 185, 129, 0.3);
250
+ color: var(--gs-green);
251
+ font-family: var(--gs-font);
252
+ font-size: 12px;
253
+ text-align: center;
254
+ letter-spacing: 0.05em;
255
+ z-index: 5;
256
+ animation: gs-fade-in 400ms ease-out;
257
+ pointer-events: none;
258
+ }
259
+
233
260
  /* ── Inline Sign-In ──────────────────────────────────────────────── */
234
261
 
235
262
  .gs-signin {