chordia-ui 3.9.2 → 3.9.4
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.
- package/dist/ChatMessage.cjs.js +5 -5
- package/dist/ChatMessage.cjs.js.map +1 -1
- package/dist/ChatMessage.es.js +583 -353
- package/dist/ChatMessage.es.js.map +1 -1
- package/dist/MessageThread.cjs.js +15 -0
- package/dist/MessageThread.cjs.js.map +1 -0
- package/dist/MessageThread.es.js +1868 -0
- package/dist/MessageThread.es.js.map +1 -0
- package/dist/PerformancePanel.cjs.js +1 -1
- package/dist/PerformancePanel.cjs.js.map +1 -1
- package/dist/PerformancePanel.es.js +587 -749
- package/dist/PerformancePanel.es.js.map +1 -1
- package/dist/components/chat.cjs.js +1 -27
- package/dist/components/chat.cjs.js.map +1 -1
- package/dist/components/chat.es.js +276 -1617
- package/dist/components/chat.es.js.map +1 -1
- package/dist/components/layout.cjs.js +2 -2
- package/dist/components/layout.cjs.js.map +1 -1
- package/dist/components/layout.es.js +289 -272
- package/dist/components/layout.es.js.map +1 -1
- package/dist/components/media.cjs.js +1 -1
- package/dist/components/media.cjs.js.map +1 -1
- package/dist/components/media.es.js +4 -4
- package/dist/components/media.es.js.map +1 -1
- package/dist/components/reports.cjs.js +2 -2
- package/dist/components/reports.cjs.js.map +1 -1
- package/dist/components/reports.es.js +18 -18
- package/dist/components/reports.es.js.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +8 -8
- package/package.json +1 -1
- package/src/components/chat/ChatHistoryPanel.jsx +740 -388
- package/src/components/chat/ChatInterface.jsx +3 -3
- package/src/components/chat/ChatMessage.jsx +338 -48
- package/src/components/chat/ChatWelcome.jsx +386 -0
- package/src/components/chat/ThinkingIndicator.jsx +121 -275
- package/src/components/chat/index.js +1 -0
- package/src/components/layout/SplitPane.jsx +21 -13
- package/src/components/media/InteractionSummaryCard.jsx +1 -1
- package/src/components/performance/PerformanceDetailsPage.jsx +51 -52
- package/src/components/performance/performanceRangeFormat.js +3 -2
- package/src/components/reports/ReportsDetails.jsx +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageThread.cjs.js","sources":["../src/components/chat/ThinkingIndicator.jsx","../src/components/chat/ChatInterface.jsx","../src/components/chat/ChatHistoryPanel.jsx","../src/components/chat/MessageThread.jsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\n\n/**\n * ThinkingIndicator\n * Status bubble shown while the assistant is working: a Chordia brand symbol\n * followed by a rounded pill that sizes to its text. The pill grows / shrinks\n * (and wraps) with whatever status message is passed.\n *\n * Props:\n * phase - \"thinking\" | \"tool\" | \"responding\" | \"generating\"\n * label - explicit status text (e.g. a notice or tool label); overrides\n * the phase default\n * toolSteps - (kept for API compatibility; not rendered in this design)\n * compact - slightly smaller symbol / paddings\n */\n\nconst SYMBOL_BG = \"#2e3236\"; // grey/strong\nconst BUBBLE_BG = \"#e3e1d7\"; // rail/surface-2\nconst TEXT_COLOR = \"#2e3236\"; // grey/strong\n\n// Chordia brand symbol (concentric green rings on a dark disc).\nfunction BrandSymbol({ size = 32 }) {\n const inner = Math.round(size * 0.75);\n return (\n <div\n style={{\n width: size,\n height: size,\n borderRadius: \"9999px\",\n background: SYMBOL_BG,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n overflow: \"hidden\",\n flexShrink: 0,\n }}\n >\n <svg\n width={inner}\n height={inner}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ display: \"block\" }}\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 24C18.6274 24 24 18.6274 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24Z\"\n fill={SYMBOL_BG}\n />\n <path\n d=\"M12.0281 1.54883C15.1413 1.54883 17.9364 2.90958 19.8514 5.06845C21.4881 6.9137 22.4824 9.34236 22.4824 12.0032C22.4824 15.0939 21.1413 17.8711 19.0094 19.7849C17.1586 21.4463 14.7113 22.4575 12.0281 22.4575C9.34478 22.4575 6.74638 21.3828 4.8764 19.6286C2.84343 17.7216 1.57373 15.0107 1.57373 12.0032C1.57373 9.28897 2.60792 6.81646 4.30366 4.95829C6.21523 2.86349 8.9682 1.54883 12.0281 1.54883Z\"\n stroke=\"#E8D4A3\"\n strokeWidth=\"1.6\"\n strokeMiterlimit=\"10\"\n />\n <path\n d=\"M12.0281 4.27832C14.237 4.27832 16.2239 5.21303 17.6307 6.69799C18.9409 8.08066 19.7525 9.94558 19.7525 12.0027C19.7525 14.2369 18.8032 16.2491 17.2862 17.6582C15.9086 18.9419 14.06 19.7271 12.0281 19.7271C9.99626 19.7271 8.46689 18.4265 7.08366 17.1225C5.58971 15.714 4.30371 14.2184 4.30371 12.0027C4.30371 10.0097 5.05856 8.19307 6.2979 6.82333C7.71148 5.26024 9.75514 4.27832 12.0281 4.27832Z\"\n stroke=\"#9BDB9C\"\n strokeWidth=\"1.2\"\n strokeMiterlimit=\"10\"\n />\n <path\n d=\"M12.0282 7.00837C13.3327 7.00837 14.5209 7.50861 15.4101 8.32753C16.4016 9.24032 17.0226 10.5488 17.0226 12.0028C17.0226 13.3805 16.4651 14.6282 15.563 15.5315C14.6592 16.4369 13.4091 16.9973 12.0282 16.9973C10.6472 16.9973 10.1869 15.4702 9.29093 14.6164C8.33599 13.7065 7.03369 13.426 7.03369 12.0023C7.03369 10.7303 7.50919 9.56969 8.29158 8.68781C9.20662 7.65699 10.5415 7.00781 12.0282 7.00781V7.00837Z\"\n stroke=\"#4DE294\"\n strokeWidth=\"0.8\"\n strokeMiterlimit=\"10\"\n />\n </svg>\n </div>\n );\n}\n\nexport default function ThinkingIndicator({\n phase = \"thinking\",\n label,\n // eslint-disable-next-line no-unused-vars\n toolSteps = [],\n // eslint-disable-next-line no-unused-vars\n elapsedMs,\n compact = false,\n}) {\n const text =\n label ||\n (phase === \"responding\" || phase === \"generating\"\n ? \"Compass is generating response...\"\n : \"Thinking...\");\n\n const symbolSize = compact ? 28 : 32;\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n animation: \"cuiThinkingPulse 1.6s ease-in-out infinite\",\n }}\n >\n <style>{`\n @keyframes cuiThinkingPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }\n `}</style>\n\n <BrandSymbol size={symbolSize} />\n\n <div\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n background: BUBBLE_BG,\n padding: compact ? \"8px 12px\" : \"12px 16px\",\n borderRadius: \"20px\",\n maxWidth: \"100%\",\n minWidth: 0,\n }}\n >\n <p\n style={{\n margin: 0,\n fontSize: \"14px\",\n fontWeight: 400,\n lineHeight: \"normal\",\n color: TEXT_COLOR,\n fontFamily: \"inherit\",\n // Grow / shrink (and wrap) with the message text.\n overflowWrap: \"anywhere\",\n wordBreak: \"break-word\",\n }}\n >\n {text}\n </p>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from \"react\";\nimport { Send } from \"lucide-react\";\nimport ChatMessage from \"./ChatMessage\";\nimport ThinkingIndicator from \"./ThinkingIndicator\";\n// TODO: replace with framework-agnostic toast\nconst toast = { error: (...args) => console.warn(\"toast.error:\", ...args) };\n\n/**\n * ChatInterface Component\n * Interactive chat interface with streaming SSE support, thinking phases, and tool visibility.\n */\nexport default function ChatInterface({\n initialMessages = [],\n onSendMessage,\n onStreamMessage, // NEW: streaming version of onSendMessage\n onMessagesChange, // NEW: callback when messages array changes\n onCodeBlockClick, // callback when \"Canvas\" button clicked on a code block: ({ code, language }) => void\n placeholder = \"Ask a question about this interaction...\",\n title = \"Chat with Chordia\",\n}) {\n const [messages, setMessages] = useState(initialMessages || []);\n const [inputValue, setInputValue] = useState(\"\");\n const [isProcessing, setIsProcessing] = useState(false);\n const [isSending, setIsSending] = useState(false);\n const [currentAssistantMessage, setCurrentAssistantMessage] = useState(null);\n const [thinkingPhase, setThinkingPhase] = useState(\"thinking\");\n const [thinkingStartTime, setThinkingStartTime] = useState(null);\n const [elapsedMs, setElapsedMs] = useState(0);\n const messagesEndRef = useRef(null);\n const inputRef = useRef(null);\n const streamAbortController = useRef(null);\n const currentAssistantRef = useRef(null);\n const lastChunkTimeRef = useRef(null);\n const [streamSilent, setStreamSilent] = useState(false);\n const [silenceSeconds, setSilenceSeconds] = useState(0);\n\n // Auto-scroll to bottom when messages change\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages, isProcessing]);\n\n // Auto-resize textarea\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.style.height = \"auto\";\n inputRef.current.style.height = `${Math.min(\n inputRef.current.scrollHeight,\n 120\n )}px`;\n }\n }, [inputValue]);\n\n // Update messages and notify parent\n useEffect(() => {\n if (onMessagesChange) {\n const allMessages = [...messages];\n if (currentAssistantMessage) {\n allMessages.push(currentAssistantMessage);\n }\n onMessagesChange(allMessages);\n }\n }, [messages, currentAssistantMessage, onMessagesChange]);\n\n // Elapsed time tracker + silence detector\n useEffect(() => {\n let interval;\n if (isProcessing && thinkingStartTime) {\n interval = setInterval(() => {\n setElapsedMs(Date.now() - thinkingStartTime);\n // Detect stream silence (no chunks for 3s+)\n if (lastChunkTimeRef.current) {\n const gap = (Date.now() - lastChunkTimeRef.current) / 1000;\n if (gap >= 3) {\n setStreamSilent(true);\n setSilenceSeconds(Math.floor(gap));\n } else {\n setStreamSilent(false);\n }\n }\n }, 500);\n }\n return () => interval && clearInterval(interval);\n }, [isProcessing, thinkingStartTime]);\n\n const resetProcessingState = () => {\n setIsProcessing(false);\n setIsSending(false);\n setCurrentAssistantMessage(null);\n currentAssistantRef.current = null;\n setThinkingPhase(\"thinking\");\n setStreamSilent(false);\n setSilenceSeconds(0);\n lastChunkTimeRef.current = null;\n setThinkingStartTime(null);\n setElapsedMs(0);\n if (streamAbortController.current) {\n streamAbortController.current.abort();\n streamAbortController.current = null;\n }\n };\n\n const parseSSELine = (line) => {\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n if (data === \"[DONE]\") {\n return { type: \"done\" };\n }\n try {\n const parsed = JSON.parse(data);\n return { type: \"data\", data: parsed };\n } catch (e) {\n return null;\n }\n }\n return null;\n };\n\n const handleStreamChunk = (chunk) => {\n if (!chunk.choices?.[0]?.delta) return;\n\n lastChunkTimeRef.current = Date.now();\n setStreamSilent(false);\n\n const delta = chunk.choices[0].delta;\n \n // Check for tool use/result indicators\n if (delta.tool_calls || delta.tool_results) {\n setThinkingPhase(\"tool\");\n return;\n }\n\n // If we get content, switch to responding phase\n if (delta.content !== undefined) {\n setThinkingPhase(\"responding\");\n \n // Initialize or update current assistant message\n setCurrentAssistantMessage(prev => {\n const baseMessage = prev || {\n id: Date.now().toString(),\n role: \"assistant\",\n content: \"\",\n timestamp: new Date().toLocaleTimeString(undefined, {\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n isStreaming: true,\n };\n \n const updated = {\n ...baseMessage,\n content: (baseMessage.content || \"\") + (delta.content || \"\"),\n };\n currentAssistantRef.current = updated;\n return updated;\n });\n }\n };\n\n const processStream = async (stream) => {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\"; // Keep incomplete line in buffer\n\n for (const line of lines) {\n if (line.trim()) {\n const parsed = parseSSELine(line);\n if (parsed) {\n if (parsed.type === \"done\") {\n return; // Stream complete\n } else if (parsed.type === \"data\") {\n handleStreamChunk(parsed.data);\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n };\n\n const handleSend = async () => {\n if (!inputValue.trim() || isSending) return;\n\n const userContent = inputValue.trim();\n const userMessage = {\n id: Date.now().toString(),\n role: \"user\",\n content: userContent,\n timestamp: new Date().toLocaleTimeString(undefined, {\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n };\n\n // Add user message and start processing\n const newMessages = [...messages, userMessage];\n setMessages(newMessages);\n setInputValue(\"\");\n setIsProcessing(true);\n setIsSending(true);\n setThinkingPhase(\"thinking\");\n setThinkingStartTime(Date.now());\n lastChunkTimeRef.current = Date.now();\n\n // Create abort controller for this stream\n streamAbortController.current = new AbortController();\n\n try {\n let result;\n \n // Use streaming version if provided, otherwise fall back to regular\n if (onStreamMessage) {\n result = await onStreamMessage(userContent, newMessages);\n } else if (onSendMessage) {\n result = await onSendMessage(userContent, newMessages);\n } else {\n // Fallback to dummy response\n setTimeout(() => {\n const assistantMessage = {\n id: (Date.now() + 1).toString(),\n role: \"assistant\",\n content: \"This is a demonstration response. In a real implementation, this would connect to your LLM backend.\",\n timestamp: new Date().toLocaleTimeString(undefined, {\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n };\n setMessages(prev => [...prev, assistantMessage]);\n resetProcessingState();\n }, 1000);\n return;\n }\n\n // Handle ReadableStream response\n if (result instanceof ReadableStream) {\n await processStream(result);\n } \n // Handle Response with SSE body\n else if (result instanceof Response && result.body) {\n await processStream(result.body);\n }\n // Handle Promise that resolves to a stream\n else if (result && typeof result.then === \"function\") {\n const resolved = await result;\n if (resolved instanceof ReadableStream) {\n await processStream(resolved);\n } else if (resolved instanceof Response && resolved.body) {\n await processStream(resolved.body);\n }\n }\n\n // Finalize the assistant message using ref (state is stale in this closure)\n if (currentAssistantRef.current) {\n setMessages(prev => [...prev, { \n ...currentAssistantRef.current, \n isStreaming: false \n }]);\n }\n\n } catch (error) {\n if (error.name !== \"AbortError\") {\n toast.error(\"Failed to send message\");\n console.error(\"Stream error:\", error);\n }\n } finally {\n resetProcessingState();\n }\n };\n\n const handleKeyDown = (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n borderRadius: \"var(--radius-lg, 12px)\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n overflow: \"hidden\",\n }}\n >\n {/* Header — hidden when title is empty */}\n {title ? <div\n style={{\n padding: \"16px 20px\",\n borderBottom: \"1px solid var(--border-subtle, rgba(52,58,64,0.08))\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n }}\n >\n <div\n style={{\n fontSize: \"var(--text-lg, 16px)\",\n fontWeight: 720,\n letterSpacing: \"-0.01em\",\n color: \"var(--text-strong, rgba(30,33,37,0.92))\",\n }}\n >\n {title}\n </div>\n <div\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n marginTop: \"2px\",\n }}\n >\n Ask questions, get insights from analyzed interactions\n </div>\n </div> : null}\n\n {/* Messages area */}\n <div\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n padding: \"20px\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {messages.length === 0 ? (\n <div\n style={{\n flex: 1,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontSize: \"var(--text-md, 13px)\",\n textAlign: \"center\",\n padding: \"40px\",\n }}\n >\n No messages yet. Start a conversation by asking a question below.\n </div>\n ) : (\n <>\n {messages.map((message) => (\n <ChatMessage\n key={message.id}\n role={message.role}\n content={message.content}\n html={message.html}\n timestamp={message.timestamp}\n toolBadges={message.toolBadges}\n isStreaming={message.isStreaming}\n onCodeBlockClick={onCodeBlockClick}\n />\n ))}\n \n {/* Current streaming message */}\n {currentAssistantMessage && (\n <ChatMessage\n key={currentAssistantMessage.id}\n role={currentAssistantMessage.role}\n content={currentAssistantMessage.content}\n timestamp={currentAssistantMessage.timestamp}\n isStreaming={true}\n onCodeBlockClick={onCodeBlockClick}\n />\n )}\n \n {/* Thinking indicator — shows during initial thinking or stream silence */}\n {isProcessing && (!currentAssistantMessage || streamSilent) && (\n <div style={{ marginBottom: \"16px\" }}>\n <ThinkingIndicator \n phase={streamSilent ? \"tool\" : thinkingPhase}\n elapsedMs={elapsedMs}\n label={\n streamSilent && silenceSeconds >= 30\n ? \"Compacting conversation — trimming context to stay sharp...\"\n : streamSilent && silenceSeconds >= 10\n ? \"Running background tasks...\"\n : streamSilent\n ? \"Still working...\"\n : undefined\n }\n />\n </div>\n )}\n \n <div ref={messagesEndRef} />\n </>\n )}\n </div>\n\n {/* Input area */}\n <div\n style={{\n borderTop: \"1px solid var(--border-subtle, rgba(52,58,64,0.08))\",\n padding: \"16px 20px\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n gap: \"12px\",\n alignItems: \"flex-end\",\n }}\n >\n <textarea\n ref={inputRef}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n disabled={isSending}\n style={{\n flex: 1,\n padding: \"10px 14px\",\n fontSize: \"var(--text-base, 14px)\",\n lineHeight: 1.5,\n color: \"var(--text-strong, rgba(30,33,37,0.92))\",\n background: \"rgba(255, 255, 255, 0.95)\",\n border: \"1px solid rgba(52, 58, 64, 0.18)\",\n borderRadius: \"var(--radius-md, 8px)\",\n resize: \"none\",\n outline: \"none\",\n transition: \"border-color 0.15s ease\",\n fontFamily: \"inherit\",\n minHeight: \"42px\",\n maxHeight: \"120px\",\n opacity: isSending ? 0.6 : 1,\n cursor: isSending ? \"not-allowed\" : \"text\",\n }}\n onFocus={(e) => {\n if (!isSending) {\n e.target.style.borderColor = \"rgba(94, 136, 176, 0.35)\";\n }\n }}\n onBlur={(e) => {\n e.target.style.borderColor = \"rgba(52, 58, 64, 0.18)\";\n }}\n />\n <button\n onClick={handleSend}\n disabled={!inputValue.trim() || isSending}\n style={{\n padding: \"10px 16px\",\n background:\n inputValue.trim() && !isSending\n ? \"var(--Base-Strong, #0B0B0B)\"\n : \"#ECEEF2\",\n color:\n inputValue.trim() && !isSending\n ? \"white\"\n : \"var(--text-base)\",\n border: \"none\",\n borderRadius: \"var(--radius-md, 8px)\",\n cursor:\n inputValue.trim() && !isSending ? \"pointer\" : \"not-allowed\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n fontSize: \"var(--text-md, 13px)\",\n fontWeight: 650,\n transition: \"all 0.15s ease\",\n height: \"42px\",\n }}\n // onMouseEnter={(e) => {\n // if (inputValue.trim() && !isSending) {\n // e.currentTarget.style.background = \"var(--Base-Strong, #0B0B0B)\";\n // }\n // }}\n // onMouseLeave={(e) => {\n // if (inputValue.trim() && !isSending) {\n // e.currentTarget.style.background = \"#ECEEF2\";\n // }\n // }}\n >\n {isSending ? (\n <>\n <style>\n {`\n @keyframes buttonSpin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n `}\n </style>\n <div\n style={{\n width: \"14px\",\n height: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.3)\",\n borderTopColor: \"white\",\n borderRadius: \"50%\",\n animation: \"buttonSpin 0.6s linear infinite\",\n }}\n />\n Sending...\n </>\n ) : (\n <>\n <Send size={16} />\n Send\n </>\n )}\n </button>\n </div>\n <div\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n marginTop: \"8px\",\n }}\n >\n Press Enter to send, Shift+Enter for new line\n </div>\n </div>\n </div>\n );\n}","\"use client\";\n\nimport React, { useState, useRef, useEffect, useMemo } from \"react\";\nimport {\n MessageSquare,\n Search,\n Pin,\n Check,\n X,\n PanelLeftClose,\n MoreVertical,\n ChevronLeft,\n ChevronRight,\n} from \"lucide-react\";\n\n/**\n * ChatHistoryPanel Component\n * Panel showing chat thread history with search, All/Pinned filtering,\n * date-grouped sections and per-thread pin / rename / delete actions.\n *\n * Props:\n * threads - Array of thread objects: { id, title, created_at, updated_at, message_count, last_message_preview, pinned, archived, tags }\n * activeThreadId - Currently selected thread id\n * onSelectThread - (threadId) => void\n * onNewChat - () => void // optional: renders the \"new chat\" header action\n * onCollapse - () => void // optional: renders the collapse header action\n * onRenameThread - (threadId, newTitle) => void // optional: when provided, inline edit is enabled\n * onDeleteThread - (threadId) => void // optional: when provided, inline delete is enabled\n * onPinThread - (threadId, nextPinned) => void // optional: when provided, the pin toggle is enabled\n * loading - boolean\n */\n\n// Design tokens (from Figma \"Insights\" / thread history side section)\nconst COLORS = {\n title: \"#2e3236\", // grey/strong\n muted: \"#808183\", // grey/muted\n faint: \"#989898\", // neutral/400\n hoverBg: \"#f3f7f7\", // grey/hover\n selectedBg: \"#FAF5E9\", // selected thread background\n border: \"#d9d9d9\", // grey/absent\n borderSubtle: \"#e6e6e6\",\n pillDarkBg: \"#272727\", // neutral/850\n pillDarkText: \"#f2f2f0\", // neutral/50\n searchTrack: \"#d8d8d8\", // neutral/150\n};\n\n// Which date bucket a thread falls into.\nfunction dateBucket(dateStr) {\n const d = dateStr ? new Date(dateStr) : null;\n if (!d || Number.isNaN(d.getTime())) return \"Older\";\n const now = new Date();\n const startToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const startYesterday = new Date(startToday);\n startYesterday.setDate(startToday.getDate() - 1);\n if (d >= startToday) return \"Today\";\n if (d >= startYesterday) return \"Yesterday\";\n return \"Older\";\n}\n\nconst BUCKET_ORDER = [\"Today\", \"Yesterday\", \"Older\"];\n\n// Compact relative time, e.g. \"just now\", \"5m ago\", \"2h ago\", \"3d ago\",\n// falling back to a localized short date for anything older than a week.\nfunction formatRelative(dateStr) {\n const d = dateStr ? new Date(dateStr) : null;\n if (!d || Number.isNaN(d.getTime())) return \"\";\n const diff = Date.now() - d.getTime();\n const min = Math.floor(diff / 60000);\n if (min < 1) return \"just now\";\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const day = Math.floor(hr / 24);\n if (day < 7) return `${day}d ago`;\n return d.toLocaleDateString(undefined, { month: \"short\", day: \"numeric\" });\n}\n\nexport default function ChatHistoryPanel({\n threads = [],\n activeThreadId,\n onSelectThread,\n onNewChat,\n onCollapse,\n onRenameThread,\n onDeleteThread,\n onPinThread,\n loading = false,\n pageSize = 10,\n // Server-side pagination (controlled). When `onPageChange` is provided the\n // panel renders whatever `threads` it's given as the current page, drives the\n // controls from `page` / `pageCount`, and asks the parent to fetch new pages.\n page,\n pageCount,\n onPageChange,\n // Called when the All/Pinned filter changes. When provided, the parent is\n // expected to (re)fetch — e.g. hit the API with `&pinned=true`.\n onFilterChange,\n}) {\n const serverPaginated = typeof onPageChange === \"function\";\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [filter, setFilter] = useState(\"all\"); // \"all\" | \"pinned\"\n const changeFilter = (f) => {\n setFilter(f);\n onFilterChange?.(f);\n };\n const [currentPage, setCurrentPage] = useState(1);\n const [hoveredId, setHoveredId] = useState(null);\n const [editingId, setEditingId] = useState(null);\n const [editValue, setEditValue] = useState(\"\");\n const [deletingId, setDeletingId] = useState(null);\n const [menuOpenId, setMenuOpenId] = useState(null); // thread id whose ⋮ dropdown is open\n const editInputRef = useRef(null);\n\n useEffect(() => {\n if (editingId && editInputRef.current) {\n editInputRef.current.focus();\n editInputRef.current.select();\n }\n }, [editingId]);\n\n // Close the ⋮ dropdown on any outside click or Escape. The kebab toggle\n // stops propagation, so the click that opens the menu never reaches here.\n useEffect(() => {\n if (!menuOpenId) return;\n const close = () => setMenuOpenId(null);\n const onKey = (e) => {\n if (e.key === \"Escape\") setMenuOpenId(null);\n };\n document.addEventListener(\"click\", close);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"click\", close);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [menuOpenId]);\n\n const canEdit = typeof onRenameThread === \"function\";\n const canDelete = typeof onDeleteThread === \"function\";\n const canPin = typeof onPinThread === \"function\";\n\n // Filter -> search -> sort (pinned first, then most-recent) -> paginate ->\n // group the current page's slice by date.\n const { groups, totalPages } = useMemo(() => {\n const q = searchQuery.trim().toLowerCase();\n const filtered = threads.filter((t) => {\n if (filter === \"pinned\" && !t.pinned) return false;\n if (!q) return true;\n return (\n (t.title || \"\").toLowerCase().includes(q) ||\n (t.last_message_preview || \"\").toLowerCase().includes(q)\n );\n });\n\n const sorted = [...filtered].sort((a, b) => {\n if (a.pinned && !b.pinned) return -1;\n if (!a.pinned && b.pinned) return 1;\n const aTime = new Date(a.updated_at || a.created_at || 0).getTime();\n const bTime = new Date(b.updated_at || b.created_at || 0).getTime();\n return bTime - aTime;\n });\n\n // Server mode: `threads` is already the current page — render it all and\n // take the page count from the parent. Client mode: slice locally.\n const pages = serverPaginated\n ? Math.max(1, pageCount || 1)\n : Math.max(1, Math.ceil(sorted.length / pageSize));\n let pageItems;\n if (serverPaginated) {\n pageItems = sorted;\n } else {\n const safePage = Math.min(currentPage, pages);\n const start = (safePage - 1) * pageSize;\n pageItems = sorted.slice(start, start + pageSize);\n }\n\n const byBucket = {};\n for (const t of pageItems) {\n const bucket = dateBucket(t.updated_at || t.created_at);\n (byBucket[bucket] ||= []).push(t);\n }\n const grouped = BUCKET_ORDER.map((label) => ({\n label,\n items: byBucket[label] || [],\n })).filter((g) => g.items.length > 0);\n\n return { groups: grouped, totalPages: pages };\n }, [threads, searchQuery, filter, currentPage, pageSize, serverPaginated, pageCount]);\n\n const totalVisible = groups.reduce((n, g) => n + g.items.length, 0);\n\n // Effective page / navigation — controlled by the parent in server mode.\n const effectivePage = serverPaginated ? Math.max(1, page || 1) : currentPage;\n const goToPage = serverPaginated ? onPageChange : setCurrentPage;\n\n // Reset to the first page whenever the search / filter changes (client mode).\n useEffect(() => {\n if (!serverPaginated) setCurrentPage(1);\n }, [searchQuery, filter, serverPaginated]);\n\n // Clamp the current page when the page count shrinks (client mode).\n useEffect(() => {\n if (!serverPaginated) setCurrentPage((p) => Math.min(p, totalPages));\n }, [totalPages, serverPaginated]);\n\n // Window of up to 5 page numbers centered on the current page.\n const pageWindow = useMemo(() => {\n const max = 5;\n if (totalPages <= max) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n let start = Math.max(1, effectivePage - 2);\n const end = Math.min(totalPages, start + max - 1);\n start = Math.max(1, end - max + 1);\n return Array.from({ length: end - start + 1 }, (_, i) => start + i);\n }, [totalPages, effectivePage]);\n\n const startEdit = (e, thread) => {\n e.stopPropagation();\n setMenuOpenId(null);\n setDeletingId(null);\n setEditingId(thread.id);\n // Pre-fill the editor with the thread's current title so the user edits\n // the existing text rather than starting from a blank field. Fall back to\n // `name` in case the title is carried under that key.\n setEditValue(thread.title || thread.name || \"\");\n };\n\n const saveEdit = (e) => {\n if (e) e.stopPropagation();\n const trimmed = (editValue || \"\").trim();\n if (editingId && trimmed) onRenameThread?.(editingId, trimmed);\n setEditingId(null);\n setEditValue(\"\");\n };\n\n const cancelEdit = (e) => {\n if (e) e.stopPropagation();\n setEditingId(null);\n setEditValue(\"\");\n };\n\n const startDelete = (e, thread) => {\n e.stopPropagation();\n setMenuOpenId(null);\n setEditingId(null);\n setDeletingId(thread.id);\n };\n\n const confirmDelete = (e) => {\n if (e) e.stopPropagation();\n if (deletingId) onDeleteThread?.(deletingId);\n setDeletingId(null);\n };\n\n const cancelDelete = (e) => {\n if (e) e.stopPropagation();\n setDeletingId(null);\n };\n\n const togglePin = (e, thread) => {\n e.stopPropagation();\n onPinThread?.(thread.id, !thread.pinned);\n };\n\n const iconBtnStyle = {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"24px\",\n height: \"24px\",\n padding: 0,\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n cursor: \"pointer\",\n color: COLORS.muted,\n transition: \"all 0.12s ease\",\n flexShrink: 0,\n };\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n background: \"#FFFFFF\",\n overflow: \"hidden\",\n }}\n >\n {/* Header */}\n <div style={{ padding: \"16px 16px 0 16px\", flexShrink: 0 }}>\n {/* Section title */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n height: \"32px\",\n }}\n >\n <div style={{ fontSize: \"14px\", fontWeight: 400, color: COLORS.title }}>\n Threads\n </div>\n {onCollapse && (\n <button\n type=\"button\"\n title=\"Collapse\"\n onClick={onCollapse}\n style={{\n ...iconBtnStyle,\n width: \"20px\",\n height: \"20px\",\n color: COLORS.muted,\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = COLORS.hoverBg)}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"transparent\")}\n >\n <PanelLeftClose size={20} strokeWidth={1.5} />\n </button>\n )}\n </div>\n\n {/* Search */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n height: \"32px\",\n background: COLORS.searchTrack,\n borderRadius: \"11px\",\n padding: \"1px\",\n marginTop: \"12px\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n flex: 1,\n alignItems: \"center\",\n gap: \"8px\",\n height: \"30px\",\n background: \"#FFFFFF\",\n borderRadius: \"10px\",\n padding: \"4px 8px\",\n }}\n >\n <Search size={18} style={{ color: COLORS.faint, flexShrink: 0 }} />\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search\"\n style={{\n flex: 1,\n minWidth: 0,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n fontSize: \"14px\",\n fontWeight: 500,\n color: COLORS.title,\n }}\n />\n </div>\n </div>\n\n {/* Filter pills */}\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"16px\", marginTop: \"12px\" }}>\n <button\n type=\"button\"\n onClick={() => changeFilter(\"all\")}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"28px\",\n padding: \"0 12px\",\n borderRadius: \"8px\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 400,\n lineHeight: \"24px\",\n transition: \"all 0.12s ease\",\n background: filter === \"all\" ? COLORS.pillDarkBg : COLORS.hoverBg,\n color: filter === \"all\" ? COLORS.pillDarkText : COLORS.title,\n }}\n >\n All\n </button>\n <button\n type=\"button\"\n onClick={() => changeFilter(\"pinned\")}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"8px\",\n height: \"28px\",\n padding: \"0 16px\",\n borderRadius: \"10px\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n fontWeight: 400,\n lineHeight: \"24px\",\n transition: \"all 0.12s ease\",\n background: filter === \"pinned\" ? COLORS.pillDarkBg : COLORS.hoverBg,\n color: filter === \"pinned\" ? COLORS.pillDarkText : COLORS.title,\n }}\n >\n <Pin size={16} style={{ flexShrink: 0 }} />\n Pinned\n </button>\n </div>\n </div>\n\n {/* Thread List */}\n <div style={{ flex: 1, overflowY: \"auto\", padding: \"16px 16px 8px 16px\" }}>\n {loading ? (\n <div style={{ padding: \"30px 16px\", textAlign: \"center\", color: COLORS.faint, fontSize: \"13px\" }}>\n Loading threads...\n </div>\n ) : totalVisible === 0 ? (\n <div style={{ padding: \"30px 16px\", textAlign: \"center\", color: COLORS.faint, fontSize: \"13px\" }}>\n {searchQuery\n ? \"No threads found\"\n : filter === \"pinned\"\n ? \"No pinned threads\"\n : \"No threads yet\"}\n </div>\n ) : (\n groups.map((group) => (\n <div key={group.label} style={{ marginBottom: \"8px\" }}>\n {/* Section header */}\n <div\n style={{\n fontSize: \"13px\",\n fontWeight: 500,\n color: COLORS.title,\n padding: \"8px 0 4px 0\",\n }}\n >\n {group.label}\n </div>\n\n {group.items.map((thread) => {\n const isActive = thread.id === activeThreadId;\n const isHovered = hoveredId === thread.id;\n const isEditing = editingId === thread.id;\n const isDeleting = deletingId === thread.id;\n const isMenuOpen = menuOpenId === thread.id;\n const hasMenu = canEdit || canDelete;\n const showActions =\n (canPin || hasMenu) &&\n (isHovered || isActive || isMenuOpen) &&\n !isEditing &&\n !isDeleting;\n\n const isOpen = isMenuOpen || isDeleting || isEditing;\n const rowBg = isActive\n ? COLORS.selectedBg\n : isHovered || isOpen\n ? COLORS.hoverBg\n : \"transparent\";\n const rowBorder =\n isActive || isHovered || isOpen\n ? `1px solid ${COLORS.border}`\n : \"1px solid transparent\";\n\n return (\n <div\n key={thread.id}\n onClick={() => {\n if (isEditing || isDeleting) return;\n onSelectThread?.(thread.id);\n }}\n onMouseEnter={() => setHoveredId(thread.id)}\n onMouseLeave={() =>\n setHoveredId((prev) => (prev === thread.id ? null : prev))\n }\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"4px\",\n padding: \"8px 4px\",\n marginBottom: \"2px\",\n borderRadius: \"8px\",\n background: rowBg,\n border: rowBorder,\n cursor: isEditing || isDeleting ? \"default\" : \"pointer\",\n transition: \"background 0.12s ease, border-color 0.12s ease\",\n boxSizing: \"border-box\",\n position: \"relative\",\n }}\n >\n {/* Leading icon */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"40px\",\n height: \"40px\",\n flexShrink: 0,\n color: COLORS.muted,\n }}\n >\n <MessageSquare size={20} />\n </div>\n\n {/* Title + subtitle (or inline editor) */}\n {isEditing ? (\n <input\n ref={editInputRef}\n type=\"text\"\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") saveEdit(e);\n else if (e.key === \"Escape\") cancelEdit(e);\n }}\n style={{\n flex: 1,\n minWidth: 0,\n fontSize: \"14px\",\n fontWeight: 600,\n color: COLORS.title,\n background: \"#fff\",\n border: `1px solid ${COLORS.border}`,\n borderRadius: \"6px\",\n padding: \"4px 8px\",\n outline: \"none\",\n boxSizing: \"border-box\",\n }}\n />\n ) : (\n <div\n style={{\n flex: 1,\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n textAlign: \"left\",\n }}\n >\n <div\n title={thread.title || thread.name || \"Untitled thread\"}\n style={{\n display: \"block\",\n minWidth: 0,\n maxWidth: \"100%\",\n fontSize: \"14px\",\n fontWeight: isActive ? 550 : 500,\n color: COLORS.title,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n lineHeight: 1.2,\n }}\n >\n {thread.title || thread.name || \"Untitled thread\"}\n </div>\n {isDeleting ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n gap: \"8px\",\n }}\n >\n <span\n style={{\n fontSize: \"12px\",\n fontWeight: 500,\n color: COLORS.title,\n }}\n >\n Confirm: delete this thread?\n </span>\n <button\n type=\"button\"\n onClick={confirmDelete}\n style={{\n padding: \"3px 12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n color: COLORS.title,\n background: \"#ECEEF2\",\n border: `1px solid ${COLORS.borderSubtle}`,\n borderRadius: \"6px\",\n cursor: \"pointer\",\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = \"#E2E5EA\")}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"#ECEEF2\")}\n >\n Yes\n </button>\n <button\n type=\"button\"\n onClick={cancelDelete}\n style={{\n padding: \"3px 6px\",\n fontSize: \"12px\",\n fontWeight: 500,\n color: COLORS.muted,\n background: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n onMouseEnter={(e) => (e.currentTarget.style.color = COLORS.title)}\n onMouseLeave={(e) => (e.currentTarget.style.color = COLORS.muted)}\n >\n No\n </button>\n </div>\n ) : (\n <div\n style={{\n fontSize: \"12px\",\n color: COLORS.muted,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n lineHeight: 1.5,\n }}\n >\n {thread.message_count != null && (\n <>\n {thread.message_count} msg{thread.message_count !== 1 ? \"s\" : \"\"}\n {\" · \"}\n </>\n )}\n {formatRelative(thread.updated_at || thread.created_at)}\n </div>\n )}\n </div>\n )}\n\n {/* Inline edit actions */}\n {isEditing && (\n <div style={{ display: \"inline-flex\", alignItems: \"center\", gap: \"2px\", flexShrink: 0 }}>\n <button\n type=\"button\"\n title=\"Save\"\n onClick={saveEdit}\n style={{ ...iconBtnStyle, color: \"#1f9d57\" }}\n onMouseEnter={(e) => (e.currentTarget.style.background = \"rgba(31,157,87,0.12)\")}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"transparent\")}\n >\n <Check size={15} />\n </button>\n <button\n type=\"button\"\n title=\"Cancel\"\n onClick={cancelEdit}\n style={iconBtnStyle}\n onMouseEnter={(e) => (e.currentTarget.style.background = \"rgba(0,0,0,0.06)\")}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"transparent\")}\n >\n <X size={15} />\n </button>\n </div>\n )}\n\n {/* A pinned thread keeps its pin indicator visible even when\n the row isn't hovered/active and the action cluster is hidden. */}\n {!isEditing && !isDeleting && !showActions && thread.pinned && (\n <Pin\n size={14}\n style={{ color: COLORS.title, flexShrink: 0 }}\n fill=\"currentColor\"\n />\n )}\n\n {/* Hover / selected action cluster: pin + kebab menu */}\n {showActions && (\n <div style={{ display: \"inline-flex\", alignItems: \"center\", gap: \"2px\", flexShrink: 0 }}>\n {canPin && (\n <button\n type=\"button\"\n title={thread.pinned ? \"Unpin\" : \"Pin\"}\n onClick={(e) => togglePin(e, thread)}\n style={{\n ...iconBtnStyle,\n color: thread.pinned ? COLORS.title : COLORS.muted,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(0,0,0,0.06)\";\n e.currentTarget.style.color = COLORS.title;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n e.currentTarget.style.color = thread.pinned ? COLORS.title : COLORS.muted;\n }}\n >\n <Pin size={14} fill={thread.pinned ? \"currentColor\" : \"none\"} />\n </button>\n )}\n {hasMenu && (\n <button\n type=\"button\"\n title=\"More\"\n onClick={(e) => {\n e.stopPropagation();\n setMenuOpenId((prev) => (prev === thread.id ? null : thread.id));\n }}\n style={{\n ...iconBtnStyle,\n color: isMenuOpen ? COLORS.title : COLORS.muted,\n background: isMenuOpen ? \"rgba(0,0,0,0.06)\" : \"transparent\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(0,0,0,0.06)\";\n e.currentTarget.style.color = COLORS.title;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = isMenuOpen\n ? \"rgba(0,0,0,0.06)\"\n : \"transparent\";\n e.currentTarget.style.color = isMenuOpen ? COLORS.title : COLORS.muted;\n }}\n >\n <MoreVertical size={14} />\n </button>\n )}\n </div>\n )}\n\n {/* ⋮ dropdown: Rename / Delete */}\n {isMenuOpen && hasMenu && (\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"absolute\",\n top: \"calc(100% - 2px)\",\n right: \"8px\",\n zIndex: 20,\n width: \"144px\",\n background: \"#FFFFFF\",\n border: `1px solid ${COLORS.border}`,\n borderRadius: \"4px\",\n boxShadow: \"-2px 2px 4px rgba(0,0,0,0.1)\",\n overflow: \"hidden\",\n }}\n >\n {canEdit && (\n <button\n type=\"button\"\n onClick={(e) => startEdit(e, thread)}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n padding: \"12px\",\n fontSize: \"13px\",\n color: COLORS.title,\n background: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = COLORS.hoverBg)}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"transparent\")}\n >\n Rename\n </button>\n )}\n {canDelete && (\n <button\n type=\"button\"\n onClick={(e) => startDelete(e, thread)}\n style={{\n display: \"block\",\n width: \"100%\",\n textAlign: \"left\",\n padding: \"12px\",\n fontSize: \"13px\",\n color: COLORS.title,\n background: \"transparent\",\n border: \"none\",\n borderTop: canEdit ? `1px solid ${COLORS.border}` : \"none\",\n cursor: \"pointer\",\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = COLORS.hoverBg)}\n onMouseLeave={(e) => (e.currentTarget.style.background = \"transparent\")}\n >\n Delete\n </button>\n )}\n </div>\n )}\n\n </div>\n );\n })}\n </div>\n ))\n )}\n </div>\n\n {/* Pagination */}\n {!loading && totalPages > 1 && (\n <div\n style={{\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"6px\",\n height: \"64px\",\n padding: \"0 16px\",\n boxSizing: \"border-box\",\n borderTop: `1px solid ${COLORS.border}`,\n }}\n >\n {/* Back */}\n <button\n type=\"button\"\n disabled={effectivePage <= 1}\n onClick={() => goToPage(Math.max(1, effectivePage - 1))}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"4px\",\n height: \"24px\",\n padding: \"4px 8px\",\n borderRadius: \"10px\",\n background: \"#FFFFFF\",\n border: `1px solid ${COLORS.borderSubtle}`,\n fontSize: \"12px\",\n lineHeight: \"16px\",\n color: \"#0b0b0b\",\n cursor: effectivePage <= 1 ? \"default\" : \"pointer\",\n opacity: effectivePage <= 1 ? 0.5 : 1,\n }}\n >\n <ChevronLeft size={12} />\n Back\n </button>\n\n {/* Page numbers */}\n {pageWindow.map((n) => {\n const isActivePage = n === effectivePage;\n return (\n <button\n key={n}\n type=\"button\"\n onClick={() => goToPage(n)}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"24px\",\n minWidth: \"22px\",\n padding: \"4px 8px\",\n borderRadius: \"10px\",\n fontSize: \"12px\",\n lineHeight: \"16px\",\n cursor: \"pointer\",\n background: isActivePage ? \"#0b0b0b\" : \"#FFFFFF\",\n color: isActivePage ? \"#FFFFFF\" : \"#0b0b0b\",\n border: isActivePage ? \"1px solid #0b0b0b\" : `1px solid ${COLORS.borderSubtle}`,\n fontWeight: isActivePage ? 600 : 400,\n }}\n >\n {n}\n </button>\n );\n })}\n\n {/* Next */}\n <button\n type=\"button\"\n disabled={effectivePage >= totalPages}\n onClick={() => goToPage(Math.min(totalPages, effectivePage + 1))}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"4px\",\n height: \"24px\",\n padding: \"4px 8px\",\n borderRadius: \"10px\",\n background: \"#FFFFFF\",\n border: `1px solid ${COLORS.borderSubtle}`,\n fontSize: \"12px\",\n lineHeight: \"16px\",\n color: \"#0b0b0b\",\n cursor: effectivePage >= totalPages ? \"default\" : \"pointer\",\n opacity: effectivePage >= totalPages ? 0.5 : 1,\n }}\n >\n Next\n <ChevronRight size={12} />\n </button>\n </div>\n )}\n </div>\n );\n}\n","/**\n * NOTE: Deprecated component.\n *\n * This chat-scoped `MessageThread` was an early demo implementation and\n * is tightly coupled to app-specific context (`useUserContext`, `toast`, etc.).\n *\n * For new work and for consumers of the `chordia-ui` library, prefer the\n * framework-agnostic, reusable version exported from:\n *\n * `src/components/common/MessageThread.jsx`\n *\n * which is re-exported via the main package entry:\n *\n * import { MessageThread } from \"chordia-ui\";\n *\n * This file is kept only for backwards compatibility within the app.\n */\n\"use client\";\n\nimport React, { useState, useEffect, useRef } from \"react\";\nimport { Send, Paperclip, AtSign, Hash, Clock } from \"lucide-react\";\n// TODO: replace with framework-agnostic toast\nconst toast = { error: (...args) => console.warn(\"toast.error:\", ...args) };\n// TODO: replace with framework-agnostic context\nconst useUserContext = () => ({ userData: { name: \"User\", email: \"\" } });\n\n/**\n * MessageThread Component\n * Threaded messaging interface for team collaboration around sessions.\n * Supports mentions, condition references, and timestamp links.\n * Uses dummy data for demonstration purposes.\n */\nexport default function MessageThread({\n sessionTitle,\n messages: initialMessages,\n onSendMessage,\n currentUser,\n}) {\n const [messageInput, setMessageInput] = useState(\"\");\n const [isFocused, setIsFocused] = useState(false);\n const [messages, setMessages] = useState(initialMessages || []);\n const [isLoading, setIsLoading] = useState(false);\n const [isSending, setIsSending] = useState(false);\n const { userData } = useUserContext();\n const messagesEndRef = useRef(null);\n\n // Get current user from context if not provided\n const displayCurrentUser = currentUser || {\n name: userData?.name || \"You\",\n initials: userData?.name\n ?.split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .toUpperCase() || \"YO\",\n color: \"#6B7C93\",\n };\n\n // Use initialMessages if provided, otherwise use empty array (no API fetching)\n useEffect(() => {\n if (initialMessages) {\n setMessages(initialMessages);\n } else {\n setMessages([]);\n }\n }, [initialMessages]);\n\n // Scroll to bottom when new messages arrive\n useEffect(() => {\n if (messagesEndRef.current) {\n messagesEndRef.current.scrollIntoView({ behavior: \"smooth\" });\n }\n }, [messages]);\n\n const handleSend = async () => {\n if (!messageInput.trim()) return;\n\n const content = messageInput.trim();\n setMessageInput(\"\");\n setIsSending(true);\n\n // Create optimistic message\n const optimisticMessage = {\n id: `temp-${Date.now()}`,\n author: {\n name: displayCurrentUser.name,\n role: userData?.role || \"\",\n initials: displayCurrentUser.initials,\n color: displayCurrentUser.color,\n },\n content: content,\n timestamp: \"Just now\",\n type: \"comment\",\n isOptimistic: true,\n };\n\n // Optimistically add message\n setMessages((prev) => [...prev, optimisticMessage]);\n\n // If onSendMessage callback is provided, use it\n if (onSendMessage) {\n try {\n await onSendMessage(content);\n // Remove optimistic flag after callback succeeds\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === optimisticMessage.id\n ? { ...msg, isOptimistic: false }\n : msg\n )\n );\n } catch (error) {\n // Remove optimistic message on error\n setMessages((prev) => prev.filter((msg) => msg.id !== optimisticMessage.id));\n toast.error(\"Failed to send message\");\n } finally {\n setIsSending(false);\n }\n return;\n }\n\n // No API - just confirm the optimistic message\n setTimeout(() => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === optimisticMessage.id\n ? { ...msg, isOptimistic: false }\n : msg\n )\n );\n setIsSending(false);\n }, 500);\n };\n\n const handleKeyPress = (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n border: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n borderRadius: \"var(--radius-lg, 12px)\",\n overflow: \"hidden\",\n }}\n >\n {/* Header */}\n {sessionTitle && (\n <div\n style={{\n padding: \"14px 16px\",\n borderBottom: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n }}\n >\n <div\n style={{\n fontSize: \"var(--text-md, 13px)\",\n fontWeight: 680,\n color: \"var(--text-strong, rgba(30,33,37,0.92))\",\n marginBottom: \"3px\",\n }}\n >\n Session Discussion\n </div>\n {sessionTitle && (\n <div\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n }}\n >\n <span>{sessionTitle}</span>\n </div>\n )}\n </div>\n )}\n\n {/* Messages */}\n <div\n style={{\n flex: 1,\n overflowY: \"auto\",\n padding: \"16px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"16px\",\n }}\n >\n {isLoading ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"40px\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n }}\n >\n Loading messages...\n </div>\n ) : messages.length === 0 ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"40px\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n }}\n >\n No messages yet. Start the conversation!\n </div>\n ) : (\n messages.map((message) => (\n <div\n key={message.id}\n style={{\n display: \"flex\",\n gap: \"12px\",\n opacity: message.type === \"system\" ? 0.75 : 1,\n }}\n >\n {/* Avatar */}\n {message.type !== \"system\" && (\n <div\n style={{\n width: \"32px\",\n height: \"32px\",\n borderRadius: \"8px\",\n background: message.author.color,\n color: \"white\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"11px\",\n fontWeight: 650,\n flexShrink: 0,\n opacity: 0.9,\n }}\n >\n {message.author.initials}\n </div>\n )}\n {message.type === \"system\" && (\n <div\n style={{\n width: \"32px\",\n height: \"32px\",\n borderRadius: \"8px\",\n background: \"rgba(30, 33, 37, 0.08)\",\n color: \"rgba(30, 33, 37, 0.52)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"11px\",\n fontWeight: 650,\n flexShrink: 0,\n }}\n >\n <Clock size={14} />\n </div>\n )}\n\n {/* Message content */}\n <div style={{ flex: 1, minWidth: 0 }}>\n {/* Author and timestamp */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"baseline\",\n gap: \"8px\",\n marginBottom: \"4px\",\n }}\n >\n <span\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n fontWeight: 650,\n color: \"var(--text-base, rgba(30,33,37,0.78))\",\n }}\n >\n {message.author.name}\n </span>\n <span\n style={{\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontFamily: \"var(--font-mono, monospace)\",\n }}\n >\n {message.timestamp}\n </span>\n {message.author.role && (\n <span\n style={{\n fontSize: \"var(--text-xs, 10px)\",\n color: \"var(--text-muted, rgba(30,33,37,0.56))\",\n background: \"rgba(30, 33, 37, 0.06)\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n fontWeight: 600,\n }}\n >\n {message.author.role}\n </span>\n )}\n {message.isEdited && (\n <span\n style={{\n fontSize: \"var(--text-xs, 10px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontStyle: \"italic\",\n }}\n >\n (edited)\n </span>\n )}\n </div>\n\n {/* Message text */}\n <div\n style={{\n fontSize: \"var(--text-md, 13px)\",\n color: \"var(--text-base, rgba(30,33,37,0.78))\",\n lineHeight: 1.5,\n marginBottom: message.references ? \"8px\" : 0,\n }}\n >\n {message.content}\n </div>\n\n {/* References */}\n {message.references && message.references.length > 0 && (\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"6px\",\n marginTop: \"8px\",\n }}\n >\n {message.references.map((ref, idx) => (\n <button\n key={idx}\n type=\"button\"\n style={{\n fontSize: \"11px\",\n padding: \"4px 8px\",\n borderRadius: \"6px\",\n border: \"1px solid rgba(52, 58, 64, 0.16)\",\n background: \"rgba(255, 255, 255, 0.7)\",\n color:\n ref.type === \"condition\"\n ? \"rgba(94, 136, 176, 0.85)\"\n : ref.type === \"observation\"\n ? \"rgba(107, 123, 147, 0.85)\"\n : ref.type === \"timestamp\"\n ? \"rgba(184, 156, 106, 0.85)\"\n : \"rgba(30, 33, 37, 0.65)\",\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n transition: \"all 0.15s ease\",\n fontWeight: 550,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background =\n \"rgba(255, 255, 255, 0.95)\";\n e.currentTarget.style.borderColor =\n \"rgba(52, 58, 64, 0.24)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background =\n \"rgba(255, 255, 255, 0.7)\";\n e.currentTarget.style.borderColor =\n \"rgba(52, 58, 64, 0.16)\";\n }}\n >\n {ref.type === \"timestamp\" && <Clock size={12} />}\n {(ref.type === \"condition\" ||\n ref.type === \"observation\") && <Hash size={12} />}\n {ref.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n ))\n )}\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input area */}\n <div\n style={{\n padding: \"12px\",\n borderTop: \"1px solid var(--border, rgba(52,58,64,0.12))\",\n background: \"var(--paper-elevated, rgba(255,255,255,0.82))\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n gap: \"8px\",\n alignItems: \"flex-end\",\n }}\n >\n {/* Current user avatar */}\n <div\n style={{\n width: \"32px\",\n height: \"32px\",\n borderRadius: \"var(--radius-md, 8px)\",\n background: displayCurrentUser.color,\n color: \"white\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"var(--text-sm, 11px)\",\n fontWeight: 650,\n flexShrink: 0,\n opacity: 0.9,\n }}\n >\n {displayCurrentUser.initials}\n </div>\n\n {/* Input field */}\n <div\n style={{\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"8px\",\n }}\n >\n <textarea\n value={messageInput}\n onChange={(e) => setMessageInput(e.target.value)}\n onKeyDown={handleKeyPress}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n placeholder=\"Add a comment...\"\n style={{\n width: \"100%\",\n minHeight: \"38px\",\n maxHeight: \"120px\",\n padding: \"8px 12px\",\n fontSize: \"var(--text-md, 13px)\",\n color: \"var(--text-base, rgba(30,33,37,0.78))\",\n background: \"white\",\n border: `1px solid ${\n isFocused\n ? \"rgba(94, 136, 176, 0.35)\"\n : \"rgba(52, 58, 64, 0.16)\"\n }`,\n borderRadius: \"var(--radius-md, 8px)\",\n resize: \"vertical\",\n outline: \"none\",\n transition: \"border-color 0.15s ease\",\n fontFamily: \"inherit\",\n lineHeight: 1.5,\n }}\n />\n\n {/* Toolbar */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <div style={{ display: \"flex\", gap: \"4px\" }}>\n <button\n type=\"button\"\n style={{\n padding: \"6px\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n color: \"rgba(30, 33, 37, 0.52)\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background =\n \"rgba(30, 33, 37, 0.06)\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.75)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.52)\";\n }}\n title=\"Mention user\"\n >\n <AtSign size={16} />\n </button>\n <button\n type=\"button\"\n style={{\n padding: \"6px\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n color: \"rgba(30, 33, 37, 0.52)\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background =\n \"rgba(30, 33, 37, 0.06)\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.75)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.52)\";\n }}\n title=\"Reference condition\"\n >\n <Hash size={16} />\n </button>\n <button\n type=\"button\"\n style={{\n padding: \"6px\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: \"6px\",\n color: \"rgba(30, 33, 37, 0.52)\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background =\n \"rgba(30, 33, 37, 0.06)\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.75)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n e.currentTarget.style.color = \"rgba(30, 33, 37, 0.52)\";\n }}\n title=\"Attach file\"\n >\n <Paperclip size={16} />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!messageInput.trim() || isSending}\n style={{\n padding: \"6px 12px\",\n background:\n messageInput.trim() && !isSending\n ? \"rgba(94, 136, 176, 0.85)\"\n : \"var(--border-subtle, rgba(52,58,64,0.08))\",\n border: \"none\",\n borderRadius: \"6px\",\n color:\n messageInput.trim() && !isSending\n ? \"white\"\n : \"var(--text-faint, rgba(30,33,37,0.36))\",\n fontSize: \"var(--text-sm, 11px)\",\n fontWeight: 600,\n cursor:\n messageInput.trim() && !isSending\n ? \"pointer\"\n : \"not-allowed\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n transition: \"all 0.15s ease\",\n }}\n onMouseEnter={(e) => {\n if (messageInput.trim() && !isSending) {\n e.currentTarget.style.background = \"rgba(94, 136, 176, 1)\";\n }\n }}\n onMouseLeave={(e) => {\n if (messageInput.trim() && !isSending) {\n e.currentTarget.style.background =\n \"rgba(94, 136, 176, 0.85)\";\n }\n }}\n >\n {isSending ? (\n <>\n <style>\n {`\n @keyframes messageSpin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n `}\n </style>\n <div\n style={{\n width: \"14px\",\n height: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.3)\",\n borderTopColor: \"white\",\n borderRadius: \"50%\",\n animation: \"messageSpin 0.6s linear infinite\",\n }}\n />\n Sending...\n </>\n ) : (\n <>\n <Send size={14} />\n Send\n </>\n )}\n </button>\n </div>\n </div>\n </div>\n <div\n style={{\n marginTop: \"8px\",\n fontSize: \"var(--text-sm, 11px)\",\n color: \"var(--text-faint, rgba(30,33,37,0.36))\",\n lineHeight: 1.4,\n }}\n >\n <strong>Tip:</strong> Use{\" \"}\n <code\n style={{\n background: \"rgba(30, 33, 37, 0.06)\",\n padding: \"2px 4px\",\n borderRadius: \"3px\",\n fontFamily: \"var(--font-mono, monospace)\",\n fontSize: \"var(--text-xs, 10px)\",\n }}\n >\n @\n </code>{\" \"}\n to mention teammates,{\" \"}\n <code\n style={{\n background: \"rgba(30, 33, 37, 0.06)\",\n padding: \"2px 4px\",\n borderRadius: \"3px\",\n fontFamily: \"var(--font-mono, monospace)\",\n fontSize: \"var(--text-xs, 10px)\",\n }}\n >\n #\n </code>{\" \"}\n to reference conditions\n </div>\n </div>\n </div>\n );\n}\n\n"],"names":["SYMBOL_BG","BUBBLE_BG","TEXT_COLOR","BrandSymbol","size","inner","jsx","jsxs","ThinkingIndicator","phase","label","toolSteps","elapsedMs","compact","text","symbolSize","toast","args","ChatInterface","initialMessages","onSendMessage","onStreamMessage","onMessagesChange","onCodeBlockClick","placeholder","title","messages","setMessages","useState","inputValue","setInputValue","isProcessing","setIsProcessing","isSending","setIsSending","currentAssistantMessage","setCurrentAssistantMessage","thinkingPhase","setThinkingPhase","thinkingStartTime","setThinkingStartTime","setElapsedMs","messagesEndRef","useRef","inputRef","streamAbortController","currentAssistantRef","lastChunkTimeRef","streamSilent","setStreamSilent","silenceSeconds","setSilenceSeconds","useEffect","_a","allMessages","interval","gap","resetProcessingState","parseSSELine","line","data","handleStreamChunk","chunk","_b","delta","prev","baseMessage","updated","processStream","stream","reader","decoder","buffer","done","value","lines","parsed","handleSend","userContent","userMessage","newMessages","result","assistantMessage","resolved","error","handleKeyDown","e","Fragment","message","ChatMessage","Send","COLORS","dateBucket","dateStr","d","now","startToday","startYesterday","BUCKET_ORDER","formatRelative","diff","min","hr","day","ChatHistoryPanel","threads","activeThreadId","onSelectThread","onNewChat","onCollapse","onRenameThread","onDeleteThread","onPinThread","loading","pageSize","page","pageCount","onPageChange","onFilterChange","serverPaginated","searchQuery","setSearchQuery","filter","setFilter","changeFilter","f","currentPage","setCurrentPage","hoveredId","setHoveredId","editingId","setEditingId","editValue","setEditValue","deletingId","setDeletingId","menuOpenId","setMenuOpenId","editInputRef","close","onKey","canEdit","canDelete","canPin","groups","totalPages","useMemo","q","sorted","t","a","b","aTime","pages","pageItems","start","byBucket","bucket","totalVisible","n","g","effectivePage","goToPage","p","pageWindow","_","i","end","startEdit","thread","saveEdit","trimmed","cancelEdit","startDelete","confirmDelete","cancelDelete","togglePin","iconBtnStyle","PanelLeftClose","Search","Pin","group","isActive","isHovered","isEditing","isDeleting","isMenuOpen","hasMenu","showActions","isOpen","rowBg","rowBorder","MessageSquare","Check","X","MoreVertical","ChevronLeft","isActivePage","ChevronRight","useUserContext","MessageThread","sessionTitle","currentUser","messageInput","setMessageInput","isFocused","setIsFocused","isLoading","setIsLoading","userData","displayCurrentUser","content","optimisticMessage","msg","handleKeyPress","Clock","ref","idx","Hash","AtSign","Paperclip"],"mappings":"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"}
|