'use client'
import { memo, useState } from 'react'
import Link from 'next/link'
import type { SearchResultItem } from '@/lib/types'
import { cn } from '@/lib/utils'
import { isCitationLabel } from '@/lib/utils/citation'
import { faviconUrl } from '@/lib/utils/favicon'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
Popover,
PopoverContent,
PopoverTrigger
} from '@/components/ui/popover'
interface CitationLinkProps {
href: string
children: React.ReactNode
className?: string
citationData?: SearchResultItem
}
// Helper function to safely extract hostname from URL
const getHostname = (url: string): string => {
try {
return new URL(url).hostname
} catch {
return 'unknown'
}
}
export const CitationLink = memo(function CitationLink({
href,
children,
className,
citationData
}: CitationLinkProps) {
const [open, setOpen] = useState(false)
const childrenText = children?.toString() || ''
const isCitation = isCitationLabel(childrenText)
const linkClasses = cn(
isCitation
? 'text-[10px] bg-muted/50 text-muted-foreground/60 rounded-full h-4 px-1.5 inline-flex items-center justify-center hover:bg-primary hover:text-primary-foreground duration-200 no-underline -translate-y-0.5 whitespace-nowrap'
: 'hover:underline inline-flex items-center gap-1.5',
className
)
// If no citation data, render as simple link
if (!citationData) {
return (
{children}
)
}
// For citations with data, show popover on hover
if (isCitation && citationData) {
return (
setOpen(true)}
onMouseLeave={() => setOpen(false)}
>
{children}
e.preventDefault()}
>
{citationData ? (
{getHostname(citationData.url)[0]?.toUpperCase() || '?'}
{getHostname(citationData.url)}
{citationData.title}
{citationData.content}
) : null}
)
}
// For non-numbered citations, render as regular link
return (
{children}
)
})