import React, { useState } from 'react'; import { ExternalLink } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { getConnectorIcon } from './ConnectorComponents'; import { Source } from './types'; type CitationProps = { citationId: number; citationText: string; position: number; source: Source | null; }; /** * Citation component to handle individual citations */ export const Citation = React.memo(({ citationId, citationText, position, source }: CitationProps) => { const [open, setOpen] = useState(false); const citationKey = `citation-${citationId}-${position}`; if (!source) return <>{citationText}; return ( {citationId} {open && (
{getConnectorIcon(source.connectorType || '')}

{source.title}

{source.description}

{source.url}
)}
); }); Citation.displayName = 'Citation'; /** * Function to render text with citations */ export const renderTextWithCitations = (text: string, getCitationSource: (id: number) => Source | null) => { // Regular expression to find citation patterns like [1], [2], etc. const citationRegex = /\[(\d+)\]/g; const parts = []; let lastIndex = 0; let match; let position = 0; while ((match = citationRegex.exec(text)) !== null) { // Add text before the citation if (match.index > lastIndex) { parts.push(text.substring(lastIndex, match.index)); } // Add the citation component const citationId = parseInt(match[1], 10); parts.push( ); lastIndex = match.index + match[0].length; position++; } // Add any remaining text after the last citation if (lastIndex < text.length) { parts.push(text.substring(lastIndex)); } return parts; };