Spaces:
Running
Running
/* eslint-disable @next/next/no-img-element */ | |
import { | |
Dialog, | |
DialogPanel, | |
DialogTitle, | |
Transition, | |
TransitionChild, | |
} from '@headlessui/react'; | |
import { Document } from '@langchain/core/documents'; | |
import { File } from 'lucide-react'; | |
import { Fragment, useState } from 'react'; | |
const MessageSources = ({ sources }: { sources: Document[] }) => { | |
const [isDialogOpen, setIsDialogOpen] = useState(false); | |
const closeModal = () => { | |
setIsDialogOpen(false); | |
document.body.classList.remove('overflow-hidden-scrollable'); | |
}; | |
const openModal = () => { | |
setIsDialogOpen(true); | |
document.body.classList.add('overflow-hidden-scrollable'); | |
}; | |
return ( | |
<div className="grid grid-cols-2 lg:grid-cols-4 gap-2"> | |
{sources.slice(0, 3).map((source, i) => ( | |
<a | |
className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium" | |
key={i} | |
href={source.metadata.url} | |
target="_blank" | |
> | |
<p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis"> | |
{source.metadata.title} | |
</p> | |
<div className="flex flex-row items-center justify-between"> | |
<div className="flex flex-row items-center space-x-1"> | |
{source.metadata.url === 'File' ? ( | |
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> | |
<File size={12} className="text-white/70" /> | |
</div> | |
) : ( | |
<img | |
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`} | |
width={16} | |
height={16} | |
alt="favicon" | |
className="rounded-lg h-4 w-4" | |
/> | |
)} | |
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis"> | |
{source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')} | |
</p> | |
</div> | |
<div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs"> | |
<div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" /> | |
<span>{i + 1}</span> | |
</div> | |
</div> | |
</a> | |
))} | |
{sources.length > 3 && ( | |
<button | |
onClick={openModal} | |
className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium" | |
> | |
<div className="flex flex-row items-center space-x-1"> | |
{sources.slice(3, 6).map((source, i) => { | |
return source.metadata.url === 'File' ? ( | |
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> | |
<File size={12} className="text-white/70" /> | |
</div> | |
) : ( | |
<img | |
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`} | |
width={16} | |
height={16} | |
alt="favicon" | |
className="rounded-lg h-4 w-4" | |
/> | |
); | |
})} | |
</div> | |
<p className="text-xs text-black/50 dark:text-white/50"> | |
View {sources.length - 3} more | |
</p> | |
</button> | |
)} | |
<Transition appear show={isDialogOpen} as={Fragment}> | |
<Dialog as="div" className="relative z-50" onClose={closeModal}> | |
<div className="fixed inset-0 overflow-y-auto"> | |
<div className="flex min-h-full items-center justify-center p-4 text-center"> | |
<TransitionChild | |
as={Fragment} | |
enter="ease-out duration-200" | |
enterFrom="opacity-0 scale-95" | |
enterTo="opacity-100 scale-100" | |
leave="ease-in duration-100" | |
leaveFrom="opacity-100 scale-200" | |
leaveTo="opacity-0 scale-95" | |
> | |
<DialogPanel className="w-full max-w-md transform rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-left align-middle shadow-xl transition-all"> | |
<DialogTitle className="text-lg font-medium leading-6 dark:text-white"> | |
Sources | |
</DialogTitle> | |
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[300px] mt-2 pr-2"> | |
{sources.map((source, i) => ( | |
<a | |
className="bg-light-secondary hover:bg-light-200 dark:bg-dark-secondary dark:hover:bg-dark-200 border border-light-200 dark:border-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium" | |
key={i} | |
href={source.metadata.url} | |
target="_blank" | |
> | |
<p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis"> | |
{source.metadata.title} | |
</p> | |
<div className="flex flex-row items-center justify-between"> | |
<div className="flex flex-row items-center space-x-1"> | |
{source.metadata.url === 'File' ? ( | |
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> | |
<File size={12} className="text-white/70" /> | |
</div> | |
) : ( | |
<img | |
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`} | |
width={16} | |
height={16} | |
alt="favicon" | |
className="rounded-lg h-4 w-4" | |
/> | |
)} | |
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis"> | |
{source.metadata.url.replace( | |
/.+\/\/|www.|\..+/g, | |
'', | |
)} | |
</p> | |
</div> | |
<div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs"> | |
<div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" /> | |
<span>{i + 1}</span> | |
</div> | |
</div> | |
</a> | |
))} | |
</div> | |
</DialogPanel> | |
</TransitionChild> | |
</div> | |
</div> | |
</Dialog> | |
</Transition> | |
</div> | |
); | |
}; | |
export default MessageSources; | |