feat: add pdf image renderer (#2554)

## Description

Replace the PDF renderer with an custom image renderer.

This allows us to remove the "react-pdf" dependency and allows us to use
a virtual list to improve performance.
This commit is contained in:
David Nguyen
2026-03-06 12:39:03 +11:00
committed by GitHub
parent 0ce909a298
commit 6faa01d384
82 changed files with 2581 additions and 1365 deletions
@@ -0,0 +1,63 @@
import React, { useRef } from 'react';
import type { MessageDescriptor } from '@lingui/core';
import { Trans, useLingui } from '@lingui/react/macro';
import { useCurrentEnvelopeRender } from '@documenso/lib/client-only/providers/envelope-render-provider';
import { PDF_VIEWER_ERROR_MESSAGES } from '@documenso/lib/constants/pdf-viewer-i18n';
import { cn } from '@documenso/ui/lib/utils';
import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert';
import { PDFViewer, type PDFViewerProps } from './pdf-viewer';
export type EnvelopePdfViewerProps = {
/**
* The error message to render when there is an error.
*/
errorMessage: { title: MessageDescriptor; description: MessageDescriptor } | null;
} & Omit<PDFViewerProps, 'data'>;
export const EnvelopePdfViewer = ({
errorMessage,
className,
...props
}: EnvelopePdfViewerProps) => {
const { t } = useLingui();
const $el = useRef<HTMLDivElement>(null);
const { currentEnvelopeItem, renderError } = useCurrentEnvelopeRender();
if (renderError || !currentEnvelopeItem) {
return (
<div ref={$el} className={cn('h-full w-full max-w-[800px]', className)} {...props}>
{renderError ? (
<Alert variant="destructive" className="mb-4 max-w-[800px]">
<AlertTitle>
{t(errorMessage?.title || PDF_VIEWER_ERROR_MESSAGES.default.title)}
</AlertTitle>
<AlertDescription>
{t(errorMessage?.description || PDF_VIEWER_ERROR_MESSAGES.default.description)}
</AlertDescription>
</Alert>
) : (
<div className="flex h-[80vh] max-h-[60rem] w-full flex-col items-center justify-center overflow-hidden rounded">
<p className="text-sm text-muted-foreground">
<Trans>No document selected</Trans>
</p>
</div>
)}
</div>
);
}
return (
<PDFViewer
{...props}
className={cn('h-full w-full max-w-[800px]', className)}
data={currentEnvelopeItem.data}
/>
);
};
export default EnvelopePdfViewer;