VerifyKitv0.5.1

React Integration

@trexolab/verifykit-react provides a React PDF viewer with signature verification, a plugin architecture, and theme support. It uses @trexolab/verifykit-core for cryptographic verification, powered by a Rust/WASM engine.

Setup

Install

bash
npm install @trexolab/verifykit-react

pdfjs-dist is included as a direct dependency and installs automatically.

Requirements: React 19+, modern browser with WebAssembly support. The workerUrl option is required in VerifyKitProvider config.

Import CSS

Add the stylesheet import at the top of your entry file:

tsx
import '@trexolab/verifykit-react/styles.css'

Without this import, the viewer renders as a blank white area.

Copy CMap and Font Files

For non-Latin text support (CJK, Arabic, etc.), copy the CMap and font files to your public directory:

bash
cp -r node_modules/pdfjs-dist/cmaps public/cmaps
cp -r node_modules/pdfjs-dist/standard_fonts public/standard_fonts

Add CSS Reset

css
html, body, #root {
  height: 100%;
  margin: 0;
  padding: 0;
}

Wrap with VerifyKitProvider

tsx
import { VerifyKitProvider } from '@trexolab/verifykit-react'
 
function App() {
  return (
    <VerifyKitProvider config={{
      workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
      theme: { mode: 'system' },
    }}>
      <div style={{ height: '100vh' }}>
        <MyViewer />
      </div>
    </VerifyKitProvider>
  )
}

VerifyKitProvider

The provider wraps your app to supply configuration, verifier instance, theme, and i18n context. It handles WASM initialization internally -- no setup code needed.

tsx
<VerifyKitProvider config={config}>
  <App />
</VerifyKitProvider>

Configuration

ts
interface VerifyKitConfig extends VerifyKitCoreConfig {
  workerUrl: string            // REQUIRED. URL to the PDF.js worker script.
  cMapUrl?: string              // Default: '/cmaps/'
  standardFontDataUrl?: string  // Default: '/standard_fonts/'
  theme?: {
    mode?: 'light' | 'dark' | 'system'
    overrides?: Record<string, string>  // CSS variable overrides
  }
  embeddedFont?: boolean | string
  toolbar?: ToolbarConfig
  locale?: string           // Default: 'en'
  translations?: Partial<TranslationStrings>
}

Key options:

  • workerUrl -- Required. URL to the PDF.js worker script. Use 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs' for CDN, or self-host the file and pass a local path like '/pdf.worker.min.mjs'.
  • theme.mode -- Set the initial theme to 'light', 'dark', or 'system' (follows OS preference).
  • cMapUrl / standardFontDataUrl -- Paths to CMap and font files for non-Latin text.
  • toolbar -- Configure which toolbar features are enabled.

useVerification Hook

The useVerification() hook manages PDF loading, verification, and result state. It creates an async verifier backed by the Rust/WASM core.

ts
const verification = useVerification()
 
// Load a file (File, ArrayBuffer, Uint8Array, or URL)
await verification.load(file)
 
// Access results
verification.fileBuffer      // ArrayBuffer | null — the loaded PDF bytes
verification.originalFileBuffer // ArrayBuffer | null — original file bytes (before appearance swap)
verification.fileName        // string — display name of the loaded file
verification.signatures      // PdfSignature[] — all verified signatures
verification.status          // 'valid' | 'invalid' | 'warning' | 'unknown' | 'pending' | null
verification.unsignedFields  // UnsignedSigField[] — unsigned signature fields
verification.isLoading       // boolean — true while verification is in progress
verification.error           // LoadError | null — error object if verification failed
verification.result          // VerificationResult | null — full verification result object
verification.metadata        // DocumentMetadata | null — PDF document metadata
verification.permissions     // DocumentPermissions | null — PDF security permissions
 
// Re-verify all signatures on the current buffer
await verification.revalidate()
 
// Reset state
verification.reset()

Key concept: Verification vs Viewer

VerifyKit separates two concerns:

ConcernResponsibilityComponent
VerificationCryptographic signature validation via Rust/WASMuseVerification() hook
ViewerPDF rendering and UI features<Viewer> component with plugins

The <Viewer> does not perform verification -- it only displays pre-verified results. useVerification() loads the PDF, runs all cryptographic checks, and produces results that you pass to the viewer as props.

Viewer Component

The <Viewer> is the recommended component for displaying PDFs. It accepts plugins for composable features.

tsx
<Viewer
  ref={viewerRef}
  fileBuffer={verification.fileBuffer}
  fileName={verification.fileName}
  plugins={[layout.plugin]}
  onOpenFile={handleFile}
  signatures={verification.signatures}
  unsignedFields={verification.unsignedFields}
  verificationStatus={verification.status ?? undefined}
/>

Props

PropTypeDescription
fileBufferArrayBuffer | nullPDF file bytes
fileNamestringDisplay name
pluginsViewerPlugin[]Plugins to install
signaturesPdfSignature[]Reactive signature data (synced to store)
unsignedFieldsUnsignedSigField[]Reactive unsigned field data
verificationStatusVerificationStatusReactive overall verification status
verifyingbooleanShow a loading indicator while verification is in progress
initialStatePartial<ViewerStoreState>Initial store overrides (for advanced use)
onDocumentLoaded(doc) => voidCalled when PDF.js document is ready
onOpenFile(file) => voidFile open handler (enables drag-and-drop)
onLoadError(error: LoadError) => voidCalled when the PDF fails to load
onRevalidate() => voidCalled when user requests re-verification
signaturePanelOpenbooleanAuto-open the signature panel
isActivebooleanTab isolation — set to false to freeze state updates
renderError(error: LoadError) => ReactNodeCustom error UI renderer
renderLayout(slots) => ReactNodeCustom layout render function

Ref Handle

ts
const viewerRef = useRef<ViewerHandle>(null)
viewerRef.current.scrollToPage(5)

Plugins

Viewer features are provided by plugins. You compose only the plugins you need.

Batteries-Included (defaultLayoutPlugin)

The simplest approach -- all features with zero configuration:

tsx
import { defaultLayoutPlugin } from '@trexolab/verifykit-react'
 
function MyViewer() {
  const [layout] = useState(() => defaultLayoutPlugin())
 
  return <Viewer fileBuffer={buffer} plugins={[layout.plugin]} />
}

Always wrap plugin creation in useState to avoid infinite re-renders. Creating a plugin inside the render body without useState produces a new instance every render.

Selective Features

Disable specific features you do not need:

tsx
const [layout] = useState(() =>
  defaultLayoutPlugin({
    disable: { print: true, download: true, contextMenu: true },
  })
)

Individual Plugins

For maximum control, import and compose individual plugins:

tsx
import { zoomPlugin, pageNavigationPlugin, toolbarPlugin } from '@trexolab/verifykit-react'
 
const [zoom] = useState(() => zoomPlugin())
const [nav] = useState(() => pageNavigationPlugin())
const [toolbar] = useState(() => toolbarPlugin())
 
<Viewer fileBuffer={buffer} plugins={[zoom, nav, toolbar]} />

See the Plugins guide for a complete list of all 24 plugins with their APIs and options.

WelcomeScreen

A file open/drop landing screen shown before a PDF is loaded:

tsx
import { WelcomeScreen } from '@trexolab/verifykit-react'
 
if (!verification.fileBuffer) {
  return <WelcomeScreen onOpenFile={handleFile} />
}

The WelcomeScreen displays a drop zone where users can drag and drop PDF files or click to browse. Pass onOpenFile to receive the selected File object. The accept prop controls which file types are shown in the file picker (default: '.pdf,application/pdf').

Theme Configuration

Theme Modes

Set the theme via the provider config:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  theme: { mode: 'system' },
}}>

Available modes:

  • 'light' -- Light theme
  • 'dark' -- Dark theme
  • 'system' -- Follows the operating system preference

CSS Variable Overrides

Override CSS variables through the provider config:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  theme: {
    mode: 'dark',
    overrides: {
      '--primary': '#6366f1',
      '--primary-hover': '#4f46e5',
    },
  },
}}>

Runtime Theme Toggle

When using defaultLayoutPlugin, you can toggle the theme programmatically:

tsx
const [layout] = useState(() => defaultLayoutPlugin())
 
// Toggle between light and dark
layout.theme.toggleTheme()
 
// Set explicitly
layout.theme.setTheme('dark')

Common Patterns

Full Example: File Loading and Verification

tsx
import { useState, useCallback, useRef } from 'react'
import {
  VerifyKitProvider,
  Viewer,
  WelcomeScreen,
  useVerification,
  defaultLayoutPlugin,
} from '@trexolab/verifykit-react'
import '@trexolab/verifykit-react/styles.css'
 
function App() {
  return (
    <VerifyKitProvider config={{
      workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
      theme: { mode: 'system' },
    }}>
      <div style={{ height: '100vh' }}>
        <MyViewer />
      </div>
    </VerifyKitProvider>
  )
}
 
function MyViewer() {
  const verification = useVerification()
  const viewerRef = useRef(null)
  const [layout] = useState(() => defaultLayoutPlugin())
 
  const handleFile = useCallback(
    (file) => { verification.load(file) },
    [verification],
  )
 
  if (!verification.fileBuffer) {
    return <WelcomeScreen onOpenFile={handleFile} />
  }
 
  return (
    <Viewer
      ref={viewerRef}
      fileBuffer={verification.fileBuffer}
      fileName={verification.fileName}
      plugins={[layout.plugin]}
      onOpenFile={handleFile}
      signatures={verification.signatures}
      unsignedFields={verification.unsignedFields}
      verificationStatus={verification.status ?? undefined}
    />
  )
}

Subscribing to Viewer State

Use useViewerStore inside a component rendered within <Viewer> to subscribe to reactive state:

tsx
import { useViewerStore, useViewerStoreKey } from '@trexolab/verifykit-react'
 
// Select multiple values
const [page, total] = useViewerStore(s => [s.currentPage, s.totalPages])
 
// Select a single key
const scale = useViewerStoreKey('scale')

Next.js Setup

VerifyKit works with Next.js 14+ but requires client-side rendering. All components use browser APIs (canvas, DOM, Web Workers, WebAssembly) and cannot run as Server Components.

tsx
// components/PdfViewer.tsx
'use client'
 
import { useState, useCallback, useRef } from 'react'
import { VerifyKitProvider, Viewer, WelcomeScreen, useVerification, defaultLayoutPlugin } from '@trexolab/verifykit-react'
import '@trexolab/verifykit-react/styles.css'
 
// ... viewer component

If you encounter SSR errors, wrap with next/dynamic:

tsx
import dynamic from 'next/dynamic'
const PdfViewer = dynamic(() => import('@/components/PdfViewer'), { ssr: false })

If you see a canvas module error, add to next.config.js:

js
const nextConfig = {
  webpack: (config) => { config.resolve.alias.canvas = false; return config },
}

Keyboard Shortcuts

The following shortcuts are available when using defaultLayoutPlugin:

ShortcutActionPlugin
Ctrl+= / Ctrl++Zoom inzoomPlugin
Ctrl+-Zoom outzoomPlugin
Ctrl+0Fit pagezoomPlugin
PageDown / N / JNext pagepageNavigationPlugin
PageUp / P / KPrevious pagepageNavigationPlugin
R / Shift+RRotate CW / CCWrotationPlugin
Ctrl+FOpen searchsearchPlugin
Ctrl+PPrintprintPlugin
Ctrl+SDownloaddownloadPlugin
F5FullscreenfullscreenPlugin
H / SHand / Select toolselectionPlugin
?Keyboard shortcuts helpshortcutHelpPlugin

Other Components

ComponentDescription
<PdfViewer>Legacy full-featured viewer with all features built-in. Still fully supported but not extensible via plugins.
<PasswordDialog>Password prompt for encrypted PDFs
<DocumentMessageBar>Top status bar showing verification result
<SignatureListPanel>Side panel listing all signatures
<SignaturePropertiesModal>Tabbed signature details modal (includes a PAdES tab for ETSI signatures)
<CertificateViewer>Certificate chain tree viewer

i18n

The React package exports translation utilities for internationalization:

ts
import { t, setLocale, registerLocale } from '@trexolab/verifykit-react'
 
// Get a translated string
const label = t('signature.valid')
 
// Switch locale at runtime
setLocale('fr')
 
// Register a custom locale
registerLocale('fr', { 'signature.valid': 'Signature valide', /* ... */ })

You can also pass locale and translations via the VerifyKitProvider config for initial setup.