import { LitElement, html, css } from './plugins.js'; import type { CSSResult, TemplateResult } from './plugins.js'; export class SmartchatMessage extends LitElement { declare role: 'user' | 'assistant' | 'tool'; declare content: string; declare toolName: string; declare timestamp: number; static properties = { role: { type: String }, content: { type: String }, toolName: { type: String }, timestamp: { type: Number }, }; static styles: CSSResult = css` :host { display: block; animation: msg-in 0.3s ease-out both; } @keyframes msg-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } /* ── Message Row ── */ .row { display: flex; gap: 10px; align-items: flex-end; margin-bottom: 4px; } .row.user { justify-content: flex-end; } .row.assistant { justify-content: flex-start; } /* ── Avatar ── */ .avatar { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0; line-height: 1; } .avatar.user { background: linear-gradient(135deg, #3b82f6, #2563eb); color: #fff; order: 2; } .avatar.assistant { background: linear-gradient(135deg, #6366f1, #7c3aed); color: #fff; } /* ── Bubble ── */ .bubble { padding: 10px 14px; border-radius: 18px; word-break: break-word; white-space: pre-wrap; font-size: 14px; line-height: 1.55; max-width: min(75%, 480px); } .bubble.user { background: linear-gradient(135deg, #3b82f6, #2563eb); color: #fff; border-bottom-right-radius: 6px; } .bubble.assistant { background: var(--smartchat-assistant-bg, #1e1e2e); border: 1px solid var(--smartchat-assistant-border, rgba(255, 255, 255, 0.08)); color: var(--smartchat-assistant-text, #d1d5db); border-bottom-left-radius: 6px; } /* ── Tool ── */ .tool-row { display: flex; justify-content: flex-start; padding: 2px 0 2px 38px; } .tool-pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; background: rgba(99, 102, 241, 0.1); border: 1px solid rgba(99, 102, 241, 0.15); border-radius: 20px; font-size: 11px; font-family: 'SF Mono', 'Fira Code', ui-monospace, monospace; color: #a5b4fc; } .tool-icon { font-size: 10px; } .tool-name { font-weight: 600; } /* ── Timestamp ── */ .time-row { padding: 1px 38px 6px; font-size: 10px; color: rgba(255, 255, 255, 0.2); font-variant-numeric: tabular-nums; } .time-row.user { text-align: right; } .time-row.assistant { text-align: left; } `; constructor() { super(); this.role = 'user'; this.content = ''; this.toolName = ''; this.timestamp = 0; } private formatTime(ts: number): string { if (!ts) return ''; const d = new Date(ts); return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } render(): TemplateResult { if (this.role === 'tool') { return html`
${this.toolName || 'tool'}
`; } return html`
${this.role === 'user' ? '⬆' : '✦'}
${this.content}
${this.timestamp ? html`
${this.formatTime(this.timestamp)}
` : ''} `; } } customElements.define('smartchat-message', SmartchatMessage);