feat(deps): pdfjs-dist + react-pdf for consistent in-app PDF preview
Replaces the `<iframe src={presignedUrl}>` preview path which
delegated rendering to the browser's built-in PDF viewer. The iframe
worked on desktop but failed on mobile (older Android Chrome
refuses inline PDFs; iOS Safari opens a new tab).
`<PdfViewer>` renders via pdfjs-dist + react-pdf so the experience
is identical across all browsers + form factors. Adds page nav,
zoom controls, and per-page accessibility labels.
Lazy-loaded via next/dynamic with ssr:false — pdfjs is ~150kb gzip,
no route ships it unless a PDF is actually previewed.
pdfjs worker + CMaps + fonts loaded from unpkg CDN pinned to the
matched pdfjs-dist version (first-load cost paid once per user, no
bundle-size impact on routes that never preview a PDF).
Verified: tsc clean, vitest 1315/1315, next build green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,23 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ExternalLink } from 'lucide-react';
|
||||
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { apiFetch } from '@/lib/api/client';
|
||||
|
||||
// pdfjs-dist is ~150kb gzip — lazy-load so routes that never preview
|
||||
// PDFs don't ship it. ssr:false because the worker setup needs window.
|
||||
const PdfViewer = dynamic(() => import('./pdf-viewer').then((m) => ({ default: m.PdfViewer })), {
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
||||
Loading PDF viewer…
|
||||
</div>
|
||||
),
|
||||
});
|
||||
|
||||
interface FilePreviewDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
@@ -94,7 +106,7 @@ export function FilePreviewDialog({
|
||||
)}
|
||||
|
||||
{!loading && !error && previewUrl && isPdf && (
|
||||
<iframe src={previewUrl} title={fileName ?? 'PDF Preview'} className="h-full w-full" />
|
||||
<PdfViewer url={previewUrl} fileName={fileName} />
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
||||
Reference in New Issue
Block a user