/* ============================================================ chat_ui.jsx — общие детали чата: аватар специалиста, пузыри, «печатает», карточка загрузки файла и разбор документа. Используется экраном резюме; вынесено отдельно, чтобы любой будущий чат брал те же элементы, а не копировал их. ============================================================ */ function AdvisorDot({ size = 30, avatar }) { if (avatar) return ( ); return (
); } function Typing({ avatar }) { return (
{[0, 1, 2].map(i => ( ))}
); } function AiBubble({ children, avatar }) { return (
{children}
); } function UserBubble({ children, file }) { return (
{file && } {children}
); } /* Карточка «прикрепить файл»: заголовок и подпись задаёт экран. */ function AttachCard({ title, sub, icon = 'clip', onPick, onSkip, skipLabel }) { return (
{onSkip && ( )}
); } /* «Читаю документ»: скелет строк, пока идёт разбор. */ function ParsingCard({ label }) { return (
{label}…
{[88, 64, 76].map((w, i) => (
))}
); } /* Живой ввод: человек печатает сам. Есть подсказки-чипы для тех, кому тяжело набирать текст — тап подставляет готовый вариант. */ function ChatInput({ ph, value, onChange, onSend, numeric, chips, lang, disabled }) { const ok = value && value.trim().length > 0; return (
{chips && chips.length > 0 && (
{chips.map((c, i) => ( ))}
)}
onChange(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && ok) onSend(); }} inputMode={numeric ? 'numeric' : 'text'} placeholder={ph} style={{ flex: 1, height: 46, borderRadius: 'var(--r-full)', background: 'var(--surface)', border: '1px solid var(--border)', padding: '0 18px', fontSize: 14.5, fontWeight: 500, color: 'var(--text)', boxShadow: 'var(--shadow-1)', outline: 'none', minWidth: 0, fontFamily: 'inherit', }} />
); } Object.assign(window, { AdvisorDot, Typing, AiBubble, UserBubble, AttachCard, ParsingCard, ChatInput });