'use client'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; const PDF_PREVIEW_WIDTH = 200; /** * Превью первой страницы PDF для карточки файла задания. * Рендерит только на клиенте (react-pdf использует pdf.js). */ export function PdfFirstPagePreview({ url, alt }: { url: string; alt?: string }) { const [PdfComponents, setPdfComponents] = useState<{ Document: React.ComponentType; Page: React.ComponentType; pdfjs: { GlobalWorkerOptions: { workerSrc: string }; version: string }; } | null>(null); const [error, setError] = useState(false); useEffect(() => { import('react-pdf').then((mod) => { const { Document, Page, pdfjs } = mod; if (pdfjs?.GlobalWorkerOptions) { pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version || '4.0.379'}/build/pdf.worker.min.mjs`; } setPdfComponents({ Document, Page, pdfjs }); }).catch(() => setError(true)); }, []); const fileOptionsRef = useRef<{ url: string; withCredentials: true } | null>(null); if (fileOptionsRef.current === null || fileOptionsRef.current.url !== url) { fileOptionsRef.current = { url, withCredentials: true as const }; } const fileOptions = fileOptionsRef.current; const onLoadError = useCallback(() => setError(true), []); const loadingElement = useMemo( () => (
hourglass_empty
), [] ); const wrapperStyle = useMemo( () => ({ width: PDF_PREVIEW_WIDTH, minHeight: 120, background: '#f5f5f5', borderRadius: 10, overflow: 'hidden' as const, display: 'flex', alignItems: 'center', justifyContent: 'center', }), [] ); if (error || !PdfComponents) { return (
picture_as_pdf
); } const { Document, Page } = PdfComponents; return (
); }