'use client' import { useEffect, useState } from "react"; import { ArrowRight, File } from "@phosphor-icons/react"; import markdownIt from "markdown-it"; const md = new markdownIt({ html: true, linkify: true, typographer: true }); import { Context, WebPage, OnlineContextData } from "../chatMessage/chatMessage"; import { Card } from "@/components/ui/card"; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import * as DomPurify from 'dompurify'; interface NotesContextReferenceData { title: string; content: string; } interface NotesContextReferenceCardProps extends NotesContextReferenceData { showFullContent: boolean; } function NotesContextReferenceCard(props: NotesContextReferenceCardProps) { const snippet = props.showFullContent ? DomPurify.sanitize(md.render(props.content)) : DomPurify.sanitize(props.content); const [isHovering, setIsHovering] = useState(false); return ( <> setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} className={`${props.showFullContent ? 'w-auto' : 'w-[200px]'} overflow-hidden break-words text-balance rounded-lg p-2 bg-muted border-none`} >

{props.title}

{props.title}

) } export interface ReferencePanelData { notesReferenceCardData: NotesContextReferenceData[]; onlineReferenceCardData: OnlineReferenceData[]; } interface OnlineReferenceData { title: string; description: string; link: string; } interface OnlineReferenceCardProps extends OnlineReferenceData { showFullContent: boolean; } function GenericOnlineReferenceCard(props: OnlineReferenceCardProps) { const [isHovering, setIsHovering] = useState(false); if (!props.link || props.link.split(' ').length > 1) { return null; } let favicon = `https://www.google.com/s2/favicons?domain=globe`; let domain = "unknown"; try { domain = new URL(props.link).hostname; favicon = `https://www.google.com/s2/favicons?domain=${domain}`; } catch (error) { console.warn(`Error parsing domain from link: ${props.link}`); return null; } const handleMouseEnter = () => { setIsHovering(true); } const handleMouseLeave = () => { setIsHovering(false); } return ( <>

{domain}

{props.title}

{props.description}

{domain}

{props.title}

{props.description}

) } export function constructAllReferences(contextData: Context[], onlineData: { [key: string]: OnlineContextData }) { const onlineReferences: OnlineReferenceData[] = []; const contextReferences: NotesContextReferenceData[] = []; if (onlineData) { let localOnlineReferences = []; for (const [key, value] of Object.entries(onlineData)) { if (value.answerBox) { localOnlineReferences.push({ title: value.answerBox.title, description: value.answerBox.answer, link: value.answerBox.source }); } if (value.knowledgeGraph) { localOnlineReferences.push({ title: value.knowledgeGraph.title, description: value.knowledgeGraph.description, link: value.knowledgeGraph.descriptionLink }); } if (value.webpages) { // If webpages is of type Array, iterate through it and add each webpage to the localOnlineReferences array if (value.webpages instanceof Array) { let webPageResults = value.webpages.map((webPage) => { return { title: webPage.query, description: webPage.snippet, link: webPage.link } }); localOnlineReferences.push(...webPageResults); } else { let singleWebpage = value.webpages as WebPage; // If webpages is an object, add the object to the localOnlineReferences array localOnlineReferences.push({ title: singleWebpage.query, description: singleWebpage.snippet, link: singleWebpage.link }); } } if (value.organic) { let organicResults = value.organic.map((organicContext) => { return { title: organicContext.title, description: organicContext.snippet, link: organicContext.link } }); localOnlineReferences.push(...organicResults); } } onlineReferences.push(...localOnlineReferences); } if (contextData) { let localContextReferences = contextData.map((context) => { if (!context.compiled) { const fileContent = context as unknown as string; const title = fileContent.split('\n')[0]; const content = fileContent.split('\n').slice(1).join('\n'); return { title: title, content: content }; } return { title: context.file, content: context.compiled } }); contextReferences.push(...localContextReferences); } return { notesReferenceCardData: contextReferences, onlineReferenceCardData: onlineReferences } } export interface TeaserReferenceSectionProps { notesReferenceCardData: NotesContextReferenceData[]; onlineReferenceCardData: OnlineReferenceData[]; isMobileWidth: boolean; } export function TeaserReferencesSection(props: TeaserReferenceSectionProps) { const [numTeaserSlots, setNumTeaserSlots] = useState(3); useEffect(() => { setNumTeaserSlots(props.isMobileWidth ? 1 : 3); }, [props.isMobileWidth]); const notesDataToShow = props.notesReferenceCardData.slice(0, numTeaserSlots); const onlineDataToShow = notesDataToShow.length < numTeaserSlots ? props.onlineReferenceCardData.slice(0, numTeaserSlots - notesDataToShow.length) : []; const shouldShowShowMoreButton = props.notesReferenceCardData.length > 0 || props.onlineReferenceCardData.length > 0; const numReferences = props.notesReferenceCardData.length + props.onlineReferenceCardData.length; if (numReferences === 0) { return null; } return (

References

{numReferences} sources

{ notesDataToShow.map((note, index) => { return }) } { onlineDataToShow.map((online, index) => { return }) } { shouldShowShowMoreButton && }
) } interface ReferencePanelDataProps { notesReferenceCardData: NotesContextReferenceData[]; onlineReferenceCardData: OnlineReferenceData[]; } export default function ReferencePanel(props: ReferencePanelDataProps) { if (!props.notesReferenceCardData && !props.onlineReferenceCardData) { return null; } return ( View references References View all references for this response
{ props.notesReferenceCardData.map((note, index) => { return }) } { props.onlineReferenceCardData.map((online, index) => { return }) }
); }