import { useEffect, useMemo, useState } from 'react'; import { createPluginRegistration } from '@embedpdf/core'; import { EmbedPDF } from '@embedpdf/core/react'; import { usePdfiumEngine } from '@embedpdf/engines/react'; // Import the essential plugins import { Viewport, ViewportPluginPackage } from '@embedpdf/plugin-viewport/react'; import { Scroller, ScrollPluginPackage, ScrollStrategy } from '@embedpdf/plugin-scroll/react'; import { LoaderPluginPackage } from '@embedpdf/plugin-loader/react'; import { RenderPluginPackage } from '@embedpdf/plugin-render/react'; import { ZoomPluginPackage } from '@embedpdf/plugin-zoom/react'; import { InteractionManagerPluginPackage, PagePointerProvider, GlobalPointerProvider } from '@embedpdf/plugin-interaction-manager/react'; import { SelectionLayer, SelectionPluginPackage } from '@embedpdf/plugin-selection/react'; import { TilingLayer, TilingPluginPackage } from '@embedpdf/plugin-tiling/react'; import { PanPluginPackage } from '@embedpdf/plugin-pan/react'; import { SpreadPluginPackage, SpreadMode } from '@embedpdf/plugin-spread/react'; import { SearchPluginPackage } from '@embedpdf/plugin-search/react'; import { ThumbnailPluginPackage } from '@embedpdf/plugin-thumbnail/react'; import { RotatePluginPackage, Rotate } from '@embedpdf/plugin-rotate/react'; import { Rotation } from '@embedpdf/models'; // Import annotation plugins import { HistoryPluginPackage } from '@embedpdf/plugin-history/react'; import { AnnotationLayer, AnnotationPluginPackage } from '@embedpdf/plugin-annotation/react'; import { PdfAnnotationSubtype } from '@embedpdf/models'; import { CustomSearchLayer } from './CustomSearchLayer'; import { ZoomAPIBridge } from './ZoomAPIBridge'; import ToolLoadingFallback from '../tools/ToolLoadingFallback'; import { Center, Stack, Text } from '@mantine/core'; import { ScrollAPIBridge } from './ScrollAPIBridge'; import { SelectionAPIBridge } from './SelectionAPIBridge'; import { PanAPIBridge } from './PanAPIBridge'; import { SpreadAPIBridge } from './SpreadAPIBridge'; import { SearchAPIBridge } from './SearchAPIBridge'; import { ThumbnailAPIBridge } from './ThumbnailAPIBridge'; import { RotateAPIBridge } from './RotateAPIBridge'; interface LocalEmbedPDFWithAnnotationsProps { file?: File | Blob; url?: string | null; onAnnotationChange?: (annotations: any[]) => void; } export function LocalEmbedPDFWithAnnotations({ file, url, onAnnotationChange }: LocalEmbedPDFWithAnnotationsProps) { const [pdfUrl, setPdfUrl] = useState(null); // Convert File to URL if needed useEffect(() => { if (file) { const objectUrl = URL.createObjectURL(file); setPdfUrl(objectUrl); return () => URL.revokeObjectURL(objectUrl); } else if (url) { setPdfUrl(url); } }, [file, url]); // Create plugins configuration with annotation support const plugins = useMemo(() => { if (!pdfUrl) return []; return [ createPluginRegistration(LoaderPluginPackage, { loadingOptions: { type: 'url', pdfFile: { id: 'stirling-pdf-signing-viewer', url: pdfUrl, }, }, }), createPluginRegistration(ViewportPluginPackage, { viewportGap: 10, }), createPluginRegistration(ScrollPluginPackage, { strategy: ScrollStrategy.Vertical, initialPage: 0, }), createPluginRegistration(RenderPluginPackage), // Register interaction manager (required for annotations) createPluginRegistration(InteractionManagerPluginPackage), // Register selection plugin (depends on InteractionManager) createPluginRegistration(SelectionPluginPackage), // Register history plugin for undo/redo (recommended for annotations) createPluginRegistration(HistoryPluginPackage), // Register annotation plugin (depends on InteractionManager, Selection, History) createPluginRegistration(AnnotationPluginPackage, { annotationAuthor: 'Digital Signature', autoCommit: true, deactivateToolAfterCreate: false, selectAfterCreate: true, }), // Register pan plugin createPluginRegistration(PanPluginPackage, { defaultMode: 'mobile', }), // Register zoom plugin createPluginRegistration(ZoomPluginPackage, { defaultZoomLevel: 1.4, minZoom: 0.2, maxZoom: 3.0, }), // Register tiling plugin createPluginRegistration(TilingPluginPackage, { tileSize: 768, overlapPx: 5, extraRings: 1, }), // Register spread plugin createPluginRegistration(SpreadPluginPackage, { defaultSpreadMode: SpreadMode.None, }), // Register search plugin createPluginRegistration(SearchPluginPackage), // Register thumbnail plugin createPluginRegistration(ThumbnailPluginPackage), // Register rotate plugin createPluginRegistration(RotatePluginPackage, { defaultRotation: Rotation.Degree0, }), ]; }, [pdfUrl]); // Initialize the engine const { engine, isLoading, error } = usePdfiumEngine(); // Early return if no file or URL provided if (!file && !url) { return (
📄
No PDF provided
); } if (isLoading || !engine || !pdfUrl) { return ; } if (error) { return (
Error loading PDF engine: {error.message}
); } return (
{ const annotationPlugin = registry.getPlugin('annotation'); if (!annotationPlugin || !annotationPlugin.provides) return; const annotationApi = annotationPlugin.provides(); if (!annotationApi) return; // Add custom signature stamp tool annotationApi.addTool({ id: 'signatureStamp', name: 'Digital Signature', interaction: { exclusive: false, cursor: 'copy' }, matchScore: () => 0, defaults: { type: PdfAnnotationSubtype.STAMP, // Will be set dynamically when user creates signature }, }); // Add custom ink signature tool annotationApi.addTool({ id: 'signatureInk', name: 'Signature Draw', interaction: { exclusive: true, cursor: 'crosshair' }, matchScore: () => 0, defaults: { type: PdfAnnotationSubtype.INK, color: '#000000', opacity: 1.0, borderWidth: 2, }, }); // Listen for annotation events to notify parent if (onAnnotationChange) { annotationApi.onAnnotationEvent((event: any) => { if (event.committed) { // Get all annotations and notify parent // This is a simplified approach - in reality you'd need to get all annotations onAnnotationChange([event.annotation]); } }); } }} > (
e.preventDefault()} onDrop={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()} > {/* High-resolution tile layer */} {/* Search highlight layer */} {/* Selection layer for text interaction */} {/* Annotation layer for signatures */}
)} />
); }