import { useI18n, useSite } from '@rspress/core/runtime'; import { IconExternalLink, SvgWrapper } from '@rspress/core/theme'; import { useEffect, useMemo, useRef, useState } from 'react'; import './LlmsOpenRow.scss'; import './LlmsViewOptions.scss'; import { useMdUrl } from './useMdUrl'; export function LlmsOpenRow() { const t = useI18n(); const { pathname } = useMdUrl(); const { site } = useSite(); const llmsUI = site?.themeConfig?.llmsUI; const [isOpen, setIsOpen] = useState(false); const containerRef = useRef(null); const options = typeof llmsUI === 'object' && llmsUI?.viewOptions ? llmsUI.viewOptions : (['chatgpt', 'claude'] as const); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( containerRef.current && event.target && !containerRef.current.contains(event.target as Node) ) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); const fullMarkdownUrl = useMemo( () => typeof window !== 'undefined' ? new URL(pathname, window.location.origin).toString() : '', [pathname], ); const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`; const builtinItems: Record< string, { title: string; href: string; icon: React.ReactNode } > = useMemo( () => ({ chatgpt: { title: t('openInText', { name: 'ChatGPT' }), href: `https://chatgpt.com/?${new URLSearchParams({ hints: 'search', q })}`, icon: ( ), }, claude: { title: t('openInText', { name: 'Claude' }), href: `https://claude.ai/new?${new URLSearchParams({ q })}`, icon: ( ), }, }), [t, q], ); if (!pathname) { return null; } return (
{isOpen && (
{options.map(option => { let item: { title: string; href?: string; icon?: React.ReactNode; onClick?: () => void; }; if (typeof option === 'string' && builtinItems[option]) { item = builtinItems[option]; } else if (typeof option === 'object' && 'title' in option) { item = option; } else { return null; } if (item.href) { return ( setIsOpen(false)} > {item.icon} {item.title} ); } return (
{ item.onClick?.(); setIsOpen(false); }} > {item.icon} {item.title}
); })}
)}
); }