'use client'; import { memo, MouseEvent, useCallback, useEffect, useMemo, useRef, } from 'react'; import { UIBlock } from './block'; import { FileIcon, FullscreenIcon, LoaderIcon } from './icons'; import { cn, fetcher } from '@/lib/utils'; import { Document } from '@/lib/db/schema'; import { InlineDocumentSkeleton } from './document-skeleton'; import useSWR from 'swr'; import { Editor } from './editor'; import { DocumentToolCall, DocumentToolResult } from './document'; import { CodeEditor } from './code-editor'; import { useBlock } from '@/hooks/use-block'; import equal from 'fast-deep-equal'; interface DocumentPreviewProps { isReadonly: boolean; result?: any; args?: any; } export function DocumentPreview({ isReadonly, result, args, }: DocumentPreviewProps) { const { block, setBlock } = useBlock(); const { data: documents, isLoading: isDocumentsFetching } = useSWR< Array >(result ? `/api/document?id=${result.id}` : null, fetcher); const previewDocument = useMemo(() => documents?.[0], [documents]); const hitboxRef = useRef(null); useEffect(() => { const boundingBox = hitboxRef.current?.getBoundingClientRect(); if (block.documentId && boundingBox) { setBlock((block) => ({ ...block, boundingBox: { left: boundingBox.x, top: boundingBox.y, width: boundingBox.width, height: boundingBox.height, }, })); } }, [block.documentId, setBlock]); if (block.isVisible) { if (result) { return ( ); } if (args) { return ( ); } } if (isDocumentsFetching) { return ; } const document: Document | null = previewDocument ? previewDocument : block.status === 'streaming' ? { title: block.title, kind: block.kind, content: block.content, id: block.documentId, createdAt: new Date(), userId: 'noop', } : null; if (!document) return ; return (
); } const LoadingSkeleton = () => (
); const PureHitboxLayer = ({ hitboxRef, result, setBlock, }: { hitboxRef: React.RefObject; result: any; setBlock: (updaterFn: UIBlock | ((currentBlock: UIBlock) => UIBlock)) => void; }) => { const handleClick = useCallback( (event: MouseEvent) => { const boundingBox = event.currentTarget.getBoundingClientRect(); setBlock((block) => block.status === 'streaming' ? { ...block, isVisible: true } : { ...block, documentId: result.id, kind: result.kind, isVisible: true, boundingBox: { left: boundingBox.x, top: boundingBox.y, width: boundingBox.width, height: boundingBox.height, }, }, ); }, [setBlock, result], ); return (