"use client" import { useState, useCallback, useRef, useEffect, useLayoutEffect, } from "react" import { cn } from "@lib/utils" import { dmSansClassName } from "@/lib/fonts" import { ChevronLeft, ChevronRight, Info, MessageSquare, Link2, ArrowUp, X, } from "lucide-react" import { Logo } from "@ui/assets/Logo" import { Popover, PopoverContent, PopoverTrigger } from "@ui/components/popover" import { analytics } from "@/lib/analytics" export type HighlightFormat = "paragraph" | "bullets" | "quote" | "one_liner" export interface HighlightItem { id: string title: string content: string format: HighlightFormat query: string sourceDocumentIds: string[] } interface HighlightsCardProps { items: HighlightItem[] onChat: (highlightContent: string, userReply: string) => void onShowRelated: (query: string) => void isLoading?: boolean onAddMemory?: () => void } function renderContent(content: string, format: HighlightFormat) { switch (format) { case "bullets": { const lines = content .split("\n") .map((line) => line.replace(/^[-•*]\s*/, "").trim()) .filter(Boolean) return ( ) } case "quote": return (

"{content}"

) case "one_liner": return

{content}

default: return

{content}

} } export function HighlightsCard({ items, onChat, onShowRelated, isLoading = false, onAddMemory, }: HighlightsCardProps) { const [activeIndex, setActiveIndex] = useState(0) const [isReplyOpen, setIsReplyOpen] = useState(false) const [replyText, setReplyText] = useState("") const [isExpanded, setIsExpanded] = useState(false) const [isClamped, setIsClamped] = useState(false) const contentRef = useRef(null) const replyInputRef = useRef(null) const currentItem = items[activeIndex] useEffect(() => { if (isReplyOpen) replyInputRef.current?.focus() }, [isReplyOpen]) // biome-ignore lint/correctness/useExhaustiveDependencies: intentionally re-run when items changes useEffect(() => { setIsReplyOpen(false) setReplyText("") setIsExpanded(false) }, [items]) // biome-ignore lint/correctness/useExhaustiveDependencies: re-run when item or expansion changes to detect clamping useLayoutEffect(() => { const el = contentRef.current if (!el) return setIsClamped(el.scrollHeight > el.clientHeight) }, [currentItem, isExpanded]) const handlePrev = useCallback(() => { setActiveIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1)) setIsReplyOpen(false) setReplyText("") setIsExpanded(false) }, [items.length]) const handleNext = useCallback(() => { setActiveIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0)) setIsReplyOpen(false) setReplyText("") setIsExpanded(false) }, [items.length]) const handleChatClick = useCallback(() => { if (!currentItem) return analytics.highlightClicked({ highlight_id: currentItem.id, action: "chat", }) setIsReplyOpen(true) }, [currentItem]) const handleReplySubmit = useCallback(() => { if (!currentItem || !replyText.trim()) return const highlightContent = `${currentItem.title}\n\n${currentItem.content}` onChat(highlightContent, replyText.trim()) setIsReplyOpen(false) setReplyText("") }, [currentItem, replyText, onChat]) const handleReplyKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault() handleReplySubmit() } if (e.key === "Escape") { setIsReplyOpen(false) setReplyText("") } }, [handleReplySubmit], ) const handleShowRelated = useCallback(() => { if (!currentItem) return analytics.highlightClicked({ highlight_id: currentItem.id, action: "related", }) onShowRelated(currentItem.query || currentItem.title) }, [currentItem, onShowRelated]) if (isLoading) { return (
) } if (!currentItem || items.length === 0) { return (
powered by supermemory

Add some documents to see highlights here

{onAddMemory ? ( ) : null}
) } return (
powered by supermemory

Daily Brief

AI-generated highlights and questions drawn from your memories. It refreshes automatically every few hours — tap the refresh icon to update it now.

{currentItem.title}

{renderContent(currentItem.content, currentItem.format)}
{(isClamped || isExpanded) && ( )}
{isReplyOpen && (
setReplyText(e.target.value)} onKeyDown={handleReplyKeyDown} placeholder={`Ask Nova about "${currentItem.title.length > 36 ? `${currentItem.title.slice(0, 36)}…` : currentItem.title}"`} className="flex-1 bg-transparent text-[11px] text-fg-primary placeholder:text-fg-subtle outline-none min-w-0" />
)}
{items.length > 1 && (
{items.map((_, idx) => (
)}
) }