VerifyKitv0.5.1

React API Reference

@trexolab/verifykit-react

React PDF viewer with signature verification, plugin architecture, and theme support. Render PDFs, verify digital signatures, and compose viewer features using 24 independent plugins.


Components

<VerifyKitProvider>

Context provider that initializes the WASM engine, configures the verifier, sets the theme, and provides i18n. Must wrap all VerifyKit components.

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

Props:

PropTypeRequiredDescription
configVerifyKitConfigNoProvider configuration (see VerifyKitConfig type below)
childrenReactNodeYesChild components

<Viewer>

The recommended plugin-based PDF viewer component. Accepts plugins for composable features.

tsx
<Viewer
  ref={viewerRef}
  fileBuffer={arrayBuffer}
  fileName="report.pdf"
  plugins={[layout.plugin]}
  onDocumentLoaded={(doc) => console.log('Pages:', doc.numPages)}
  onOpenFile={(file) => verification.load(file)}
  signatures={verification.signatures}
  unsignedFields={verification.unsignedFields}
  verificationStatus={verification.status}
/>

Props:

PropTypeRequiredDescription
fileBufferArrayBuffer | nullNoPDF file bytes
fileNamestringNoDisplay file name
pluginsViewerPlugin[]NoArray of viewer plugins to install
initialStatePartial<ViewerStoreState>NoInitial store state overrides
signaturesPdfSignature[]NoReactive signature data (synced to store)
unsignedFieldsUnsignedSigField[]NoReactive unsigned field data
verificationStatusVerificationStatusNoReactive overall verification status
onDocumentLoaded(doc: PDFDocumentProxy) => voidNoCalled when the PDF document loads
onPageCountChange(n: number) => voidNoCalled when page count is known
onReady() => voidNoCalled when the viewer is ready
onOpenFile(file: File) => voidNoFile open handler (enables drag-drop)
onContextMenu(e: React.MouseEvent) => voidNoContext menu handler
onLoadError(error: LoadError) => voidNoCalled when the PDF fails to load
onRevalidate() => voidNoCalled when user requests re-verification
signaturePanelOpenbooleanNoAuto-open the signature panel
isActivebooleanNoTab isolation — disable global listeners when hidden (default: true)
verifyingbooleanNoShow loading indicator while verification is in progress
renderError(error: LoadError) => ReactNodeNoCustom error UI renderer
renderLayout(slots) => ReactNodeNoCustom layout render function

Ref handle (ViewerHandle):

ts
interface ViewerHandle {
  scrollToPage(n: number): void
  getStore(): ViewerStore
}
ts
const viewerRef = useRef<ViewerHandle>(null)
viewerRef.current.scrollToPage(5)

<WelcomeScreen>

A drop-target landing screen for when no file is loaded.

tsx
<WelcomeScreen
  onOpenFile={(file: File) => verification.load(file)}
  title="My PDF Viewer"
  subtitle="Drag and drop a PDF here"
/>

Props:

PropTypeRequiredDescription
onOpenFile(file: File) => voidYesCalled when a file is dropped or selected
titlestringNoHeading text
subtitlestringNoSubheading text
acceptstringNoFile type filter for file picker (default: '.pdf,application/pdf')

<PdfViewer> (Legacy)

The original monolithic viewer component. Still fully supported for backward compatibility but not extensible via plugins. Use <Viewer> with the plugin system for new projects.

tsx
<PdfViewer
  ref={viewerRef}
  fileBuffer={arrayBuffer}
  signatures={signatures}
  onWidgetClick={(sig, fieldName) => {}}
/>

<DocumentMessageBar>

Colored status bar displayed above the viewer showing the overall verification result.

Props:

PropTypeRequiredDescription
statusVerificationStatusYesOverall document verification status
signaturesPdfSignature[]YesAll document signatures
onShowPanel() => voidNoCalled when user clicks to show signature panel
panelVisiblebooleanNoWhether the signature panel is currently visible

<SignatureListPanel>

Side panel listing all signatures with status icons. Click a signature to view its details.

Props:

PropTypeRequiredDescription
signaturesPdfSignature[]YesAll document signatures
unsignedFieldsUnsignedSigField[]NoUnsigned signature fields
selectedIdxnumberYesCurrently selected signature index
onSelect(i: number, tab?: string) => voidYesSelection handler
onNavigate(i: number) => voidNoNavigate to signature in PDF
onClose() => voidNoClose panel handler
onRevalidate() => voidNoRe-verify signatures
isRevalidatingbooleanNoShow revalidation spinner

<SignaturePropertiesModal>

Tabbed modal dialog showing detailed signature information, validity checks, certificate chain, and timestamp data.

Props:

PropTypeRequiredDescription
sigPdfSignature | nullYesThe signature to display
fieldNamestringYesForm field name
openbooleanYesWhether the modal is open
onClose() => voidYesClose handler
initialTab'details' | 'certificates' | 'tsa' | 'pades'NoInitially active tab

<CertificateViewer>

Interactive certificate chain tree viewer. Displays the full certificate chain from signer to root CA with expandable details.

Props:

PropTypeRequiredDescription
certCertificateInfoYesCertificate to display
isTsabooleanNoWhether this is a TSA certificate

<PasswordDialog>

Password prompt dialog for encrypted/password-protected PDFs.

Props:

PropTypeRequiredDescription
errorbooleanYesWhether a previous password attempt failed
onSubmit(pwd: string) => voidYesSubmit handler with entered password
onCancel() => voidYesCancel handler

<SignatureStatusIcon>

Status icon component showing valid/invalid/warning/unknown state.

Props:

PropTypeRequiredDescription
statusVerificationStatusYesVerification status to display
sizenumberNoIcon size in pixels

<ValidityChecklist>

Expandable list of all verification checks for a signature.

Props:

PropTypeRequiredDescription
sigPdfSignatureYesSignature to show checks for

<PdfViewerErrorBoundary>

Error boundary wrapper for the PDF viewer. Catches render errors and shows a fallback UI.

Props:

PropTypeRequiredDescription
childrenReactNodeYesChild components
fallbackReactNodeNoCustom fallback UI
onReset() => voidNoCalled when the user resets the error boundary

Hooks

useVerification()

Manages PDF loading, verification, and result state. Must be used inside a <VerifyKitProvider>.

ts
function useVerification(): VerificationState

Returns:

ts
interface VerificationState {
  load(input: PdfInput, fileName?: string): Promise<VerificationResult>
  revalidate(): Promise<VerificationResult | null>
  reset(): void
  fileBuffer: ArrayBuffer | null
  originalFileBuffer: ArrayBuffer | null
  fileName: string
  result: VerificationResult | null
  metadata: DocumentMetadata | null
  permissions: DocumentPermissions | null
  signatures: PdfSignature[]
  unsignedFields: UnsignedSigField[]
  status: VerificationStatus | null
  isLoading: boolean
  error: LoadError | null
}

Example:

ts
const verification = useVerification()
 
await verification.load(file)        // File, ArrayBuffer, Uint8Array, or URL
verification.signatures              // PdfSignature[]
verification.status                  // 'valid' | 'invalid' | 'warning' | ...
verification.isLoading               // boolean
verification.error                   // LoadError | null (object with name and message)
await verification.revalidate()      // Re-verify signatures on current buffer
verification.reset()                 // Clear state

useViewerStore(selector)

Subscribe to a slice of the viewer store. Re-renders only when the selected value changes. Must be used inside <Viewer>.

ts
function useViewerStore<T>(selector: (state: ViewerStoreState) => T): T

Example:

ts
const scale = useViewerStore(s => s.scale)
const [page, total] = useViewerStore(s => [s.currentPage, s.totalPages])

useViewerStoreKey(key)

Subscribe to a single key in the viewer store.

ts
function useViewerStoreKey<K extends keyof ViewerStoreState>(key: K): ViewerStoreState[K]

Example:

ts
const currentPage = useViewerStoreKey('currentPage')

useViewerStoreUpdate()

Get the store's update function for dispatching partial state updates.

ts
function useViewerStoreUpdate(): (partial: Partial<ViewerStoreState>) => void

Example:

ts
const update = useViewerStoreUpdate()
update({ scale: 1.5, fitMode: 'none' })

useStore()

Returns the raw ViewerStore instance for advanced use (batch updates, direct subscriptions).

ts
function useStore(): ViewerStore

useContainerSize(ref)

Responsive breakpoint hook that reports the container dimensions.

ts
function useContainerSize(ref: React.RefObject<HTMLElement>): { width: number; height: number }

usePinchZoom(ref, onZoom)

Touch pinch-zoom gesture handler for mobile support.

ts
function usePinchZoom(
  ref: React.RefObject<HTMLElement>,
  onZoom: (scaleDelta: number) => void,
): void

Plugin Functions

All plugins are factory functions that return a ViewerPlugin. Always wrap plugin creation in useState to ensure a stable instance across renders:

tsx
const [layout] = useState(() => defaultLayoutPlugin())

Meta Plugin

defaultLayoutPlugin(options?)

Composes all 24 plugins into a batteries-included experience. The recommended starting point for most applications.

ts
function defaultLayoutPlugin(options?: DefaultLayoutPluginOptions): DefaultLayoutPluginResult

Options:

ts
interface DefaultLayoutPluginOptions {
  accessibility?: AccessibilityPluginOptions
  disable?: {
    search?: boolean
    print?: boolean
    download?: boolean
    fullscreen?: boolean
    theme?: boolean
    rotation?: boolean
    selection?: boolean
    sidebar?: boolean
    signatures?: boolean
    highlights?: boolean
    openFile?: boolean
    properties?: boolean
    shortcuts?: boolean
    contextMenu?: boolean
    accessibility?: boolean
  }
  toolbar?: ToolbarPluginOptions
}
 
interface AccessibilityPluginOptions {
  initialScale?: 'compact' | 'default' | 'large' | 'extra-large'
  persist?: boolean  // default: true — save preference to localStorage
}

Result:

ts
interface DefaultLayoutPluginResult {
  plugin: ViewerPlugin
  zoom: ZoomPluginApi
  navigation: PageNavigationPluginApi
  rotation: RotationPluginApi
  search: SearchPluginApi
  print: PrintPluginApi
  download: DownloadPluginApi
  theme: ThemePluginApi
  fullscreen: FullscreenPluginApi
  selection: SelectionPluginApi
  scrollMode: ScrollModePluginApi
  spreadMode: SpreadModePluginApi
  signature: SignaturePluginApi
  sidebar: SidebarPluginApi
  accessibility: AccessibilityPluginApi
}

Example:

tsx
// All features
const [layout] = useState(() => defaultLayoutPlugin())
 
// Selective features
const [layout] = useState(() =>
  defaultLayoutPlugin({
    disable: { print: true, download: true, contextMenu: true },
  })
)
 
<Viewer fileBuffer={buffer} plugins={[layout.plugin]} />

PluginAPI TypeDescription
zoomPlugin()ZoomPluginApiZoom controls: zoomIn(), zoomOut(), zoomTo(scale), setFitMode(mode)
pageNavigationPlugin()PageNavigationPluginApiPage navigation: goToPage(n), goToNextPage(), goToPreviousPage(), goToFirstPage(), goToLastPage()
rotationPlugin()RotationPluginApiDocument rotation: rotateCW(), rotateCCW()
scrollModePlugin()ScrollModePluginApiScroll mode: setScrollMode(mode)
spreadModePlugin()SpreadModePluginApiSpread/facing mode: setSpreadMode(mode)

Content Plugins

PluginAPI TypeDescription
searchPlugin()SearchPluginApiText search: open(), close()
highlightPlugin()--Text highlighting and selection display
selectionPlugin()SelectionPluginApiCursor tool selection: setCursorTool(tool)

Action Plugins

PluginAPI TypeDescription
printPlugin()PrintPluginApiPrint the document: print()
downloadPlugin()DownloadPluginApiDownload the document: download()
openFilePlugin()--File open and drag-drop handling

UI Plugins

PluginAPI TypeDescription
toolbarPlugin()--Toolbar with slot system for positioning controls
sidebarPlugin()SidebarPluginApiSidebar panel: toggle(tab?), open(tab), close()
themePlugin()ThemePluginApiTheme control: toggleTheme(), setTheme(mode), getTheme()
fullscreenPlugin()FullscreenPluginApiFullscreen: enterFullscreen(), exitFullscreen(), toggleFullscreen()
accessibilityPlugin()AccessibilityPluginApiUI font scale: setFontScale(scale), getFontScale()

Panel Plugins

PluginAPI TypeDescription
signaturePlugin()SignaturePluginApiSignature panel: openPanel(), closePanel(), togglePanel()
thumbnailPlugin()--Thumbnail sidebar tab
bookmarkPlugin()--Bookmark/outline sidebar tab
attachmentPlugin()--Attachment sidebar tab
propertiesPlugin()--Document properties modal

Help Plugins

PluginAPI TypeDescription
shortcutHelpPlugin()--Keyboard shortcuts help panel
contextMenuPlugin()--Right-click context menu
moreMenuPlugin()--Overflow menu for toolbar items

Types

VerifyKitConfig

Provider configuration, extending VerifyKitCoreConfig with viewer-specific options.

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?: ThemeConfig
  embeddedFont?: boolean | string
  toolbar?: ToolbarConfig
  locale?: string               // Default: 'en'
  translations?: Partial<TranslationStrings>
}
 
interface ThemeConfig {
  mode?: 'light' | 'dark' | 'system'
  overrides?: Record<string, string>  // CSS variable overrides
}

ToolbarConfig

Controls which toolbar features are visible in the viewer. All fields default to true unless noted.

ts
interface ToolbarConfig {
  openFile?: boolean          // default: false
  pageNavigation?: boolean    // default: true
  zoom?: boolean              // default: true
  fitMode?: boolean           // default: true
  rotation?: boolean          // default: true
  scrollMode?: boolean        // default: true
  search?: boolean            // default: true
  print?: boolean             // default: true
  download?: boolean          // default: false
  themeToggle?: boolean       // default: true
  fullscreen?: boolean        // default: true
  signaturePanel?: boolean    // default: true
  cursorTool?: boolean        // default: true
  moreMenu?: boolean          // default: true
  documentProperties?: boolean // default: true
}

Recommended CDN URL:

https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs

Self-hosted: Copy node_modules/pdfjs-dist/legacy/build/pdf.worker.min.mjs to your public directory and pass the local path.


ViewerPlugin

Plugin interface for extending the viewer with features.

ts
interface ViewerPlugin {
  name: string
  dependencies?: string[]
  composedPlugins?: ViewerPlugin[]
 
  // Lifecycle hooks
  install?(ctx: PluginContext): void
  onDocumentLoad?(e: DocumentLoadEvent): void
  onDocumentUnload?(): void
  onPageChange?(e: PageChangeEvent): void
  onZoomChange?(e: ZoomChangeEvent): void
  onRotationChange?(e: RotationChangeEvent): void
  destroy?(): void
 
  // UI contributions
  renderToolbarSlot?: Partial<ToolbarSlots>
  sidebarTabs?: SidebarTabDefinition[]
  renderOverlay?: (props: OverlayRenderProps) => React.ReactNode
  renderRightPanel?: (props: OverlayRenderProps) => React.ReactNode
  renderPageOverlay?: (props: PageOverlayRenderProps) => React.ReactNode
  transformToolbarSlots?: (slots: ToolbarSlots) => ToolbarSlots
}

PluginContext (Viewer)

Context passed to a plugin's install() method.

ts
interface PluginContext {
  store: ViewerStore
  getDocument(): PDFDocumentProxy | null
  scrollToPage(pageNum: number): void
  getScrollContainer(): HTMLElement | null
  getViewerContainer(): HTMLElement | null
  registerShortcut(shortcut: KeyboardShortcut): () => void
  onOpenFile?: (file: File) => void
  onRevalidate?: () => void
  t(key: string): string
}

ViewerHandle

Ref handle exposed by the <Viewer> component.

ts
interface ViewerHandle {
  scrollToPage(n: number): void
  getStore(): ViewerStore
}

ViewerStore

Lightweight pub-sub reactive store that drives the viewer state.

ts
interface ViewerStore {
  get<K extends keyof ViewerStoreState>(key: K): ViewerStoreState[K]
  getState(): ViewerStoreState
  update(partial: Partial<ViewerStoreState>): void
  subscribe<K extends keyof ViewerStoreState>(
    key: K,
    listener: (newVal: ViewerStoreState[K], oldVal: ViewerStoreState[K]) => void,
  ): () => void
  subscribeAll(listener: (key: string, newVal: unknown, oldVal: unknown) => void): () => void
  batch(fn: () => void): void
  reset(): void
  destroy(): void
}

State shape:

CategoryKeys
Documentdocument, fileBuffer, originalFileBuffer, fileName, loadState, loadError
NavigationcurrentPage, totalPages
Zoomscale, fitMode
Rotationrotation
LayoutscrollMode, spreadMode, cursorTool
ThemethemeMode
FullscreenisFullscreen
Verificationsignatures, unsignedFields, verificationStatus, isRevalidating
UI panelssidebarOpen, sidebarTab, sigPanelOpen, findOpen, propertiesModalOpen, shortcutHelpOpen, aboutModalOpen, contextMenuPos, sigModalIndex, sigModalFieldName, sigModalTab, highlightedSigIndex
PasswordpasswordNeeded, passwordError

Event Types

ts
interface DocumentLoadEvent {
  document: PDFDocumentProxy
  numPages: number
}
 
interface PageChangeEvent {
  currentPage: number
  previousPage: number
}
 
interface ZoomChangeEvent {
  scale: number
  previousScale: number
  fitMode: ViewerStoreState['fitMode']
}
 
interface RotationChangeEvent {
  rotation: ViewerStoreState['rotation']
  previousRotation: ViewerStoreState['rotation']
}

KeyboardShortcut

ts
interface KeyboardShortcut {
  id: string
  key: string
  ctrl?: boolean
  shift?: boolean
  alt?: boolean
  handler: (e: KeyboardEvent) => void
  allowInInput?: boolean
  description?: string
}

SidebarTabDefinition

ts
interface SidebarTabDefinition {
  id: string
  label: string
  icon: React.ReactNode
  component: React.ComponentType<{ store: ViewerStore }>
  canRender?: (state: ViewerStoreState) => boolean
  order: number
}

Toolbar Slots

ts
interface ToolbarSlots {
  SearchPopover?: ToolbarSlotRender
  GoToPreviousPage?: ToolbarSlotRender
  CurrentPageInput?: ToolbarSlotRender
  NumberOfPages?: ToolbarSlotRender
  GoToNextPage?: ToolbarSlotRender
  ZoomOut?: ToolbarSlotRender
  Zoom?: ToolbarSlotRender
  ZoomIn?: ToolbarSlotRender
  Rotate?: ToolbarSlotRender
  CursorTool?: ToolbarSlotRender
  OpenFile?: ToolbarSlotRender
  Download?: ToolbarSlotRender
  Print?: ToolbarSlotRender
  ThemeToggle?: ToolbarSlotRender
  Fullscreen?: ToolbarSlotRender
  MoreMenu?: ToolbarSlotRender
  [custom: string]: ToolbarSlotRender | undefined
}
 
type ToolbarSlotRender = (props: { store: ViewerStore }) => React.ReactNode

Re-exported from Core

The React package re-exports all core types and functions for convenience:

Functions: createVerifier, verifyPdf, extractPdfMetadata, extractSignaturesFromPdf, getTrustStore, setTrustStoreConfig, resetTrustStore, ensureCryptoEngine, buf2hex, sha256hex, decompressFlate, computeUnsignedFields, oidToName, parseDn, isNode

Types: VerificationStatus, PdfSignature, VerificationResult, CertificateInfo, TimestampInfo, SignatureCheckResult, DocumentMetadata, DocumentPermissions, UnsignedSigField, VerifyKitCoreConfig, VerifyKitVerifier, VerifyKitPlugin, PluginContext (core), PdfInput, TrustStoreConfig, RevocationCheckResult, TrustStore

See the Core API Reference for documentation on these.


Error Handling

LoadError

Typed PDF loading/verification error. The name property classifies the error for programmatic handling and matches pdf.js exception names where applicable.

ts
interface LoadError {
  /** Semantic error type for programmatic handling */
  name: LoadErrorName
  /** Human-readable error message */
  message: string
}

LoadErrorName

Union of all recognized error classification names.

ts
type LoadErrorName =
  | 'InvalidPDFException'
  | 'MissingPDFException'
  | 'UnexpectedResponseException'
  | 'PasswordException'
  | 'AbortException'
  | 'FormatError'
  | 'NetworkError'
  | 'UnsupportedInputError'
  | 'VerificationError'
  | 'UnknownErrorException'

classifyPdfError(error)

Classify an unknown error into a typed LoadError. Preserves pdf.js exception names; everything else becomes UnknownErrorException.

ts
function classifyPdfError(error: unknown): LoadError

createLoadError(name, message)

Create a LoadError with a specific name and message.

ts
function createLoadError(name: LoadErrorName, message: string): LoadError

Status & Styling Helpers

Status configuration constants and helper functions for mapping VerificationStatus to labels, colors, and display text. All color values reference CSS custom properties from the VerifyKit theme.

Constants

ConstantTypeDescription
STATUS_LABELRecord<VerificationStatus, string>Human-readable label per status ('Valid', 'Invalid', etc.)
STATUS_COLORRecord<VerificationStatus, string>Foreground text color CSS variable per status
STATUS_BGRecord<VerificationStatus, string>Background surface color CSS variable per status
STATUS_STRIPERecord<VerificationStatus, string>Border/stripe color CSS variable per status
STATUS_CFGRecord<VerificationStatus, StatusCfg>Combined status banner config (color, bg, stripe, title)
AVATAR_RINGRecord<VerificationStatus, string>Avatar ring color per status (signature modal header)
PANEL_STRIPERecord<VerificationStatus, string>Left stripe color per status (signature list panel)

StatusCfg

ts
interface StatusCfg {
  color: string
  bg: string
  stripe: string
  title: string
}

Functions

statusTextColor(status)

Returns the CSS color variable for status check rows and bullets.

ts
function statusTextColor(status: VerificationStatus): string

getStatusSentence(sig)

Returns an Adobe Reader DC-style status sentence for a signature. Handles deleted and not-yet-verified signatures.

ts
function getStatusSentence(sig: PdfSignature): string

getInvalidSub(sig)

Returns a detailed sub-message explaining why a signature is invalid (revoked, modified, expired, etc.).

ts
function getInvalidSub(sig: PdfSignature): string

getPillLabel(sig)

Returns the uppercase status label for the modal header badge (e.g. 'VALID', 'INVALID').

ts
function getPillLabel(sig: PdfSignature): string

getInitials(name)

Extracts initials from a signer name for avatar display. Returns first and last initials for multi-word names, or a single initial.

ts
function getInitials(name: string): string

getDisplayStatus(sig)

Returns the Adobe Reader DC-aligned display status for a signature. Accounts for the attempted field on revocation checks to differentiate "not checked" from "checked but unknown."

ts
function getDisplayStatus(sig: PdfSignature): VerificationStatus

overallStatus(result)

Derives the document-level overall verification status from a VerificationResult. Returns 'invalid' if any active signature is invalid, 'valid' if all are valid, 'warning' otherwise.

ts
function overallStatus(result: VerificationResult): VerificationStatus

Check Builders

Functions that construct validation check items from PdfSignature data. Shared between the full validity checklist and the compact signature list panel.

CheckItem

ts
interface CheckItem {
  status: VerificationStatus
  label: string
  text: string
  detail?: string
}

MiniCheckItem

ts
interface MiniCheckItem {
  status: VerificationStatus
  label: string
}

SummaryLine

ts
interface SummaryLine {
  status: VerificationStatus
  text: string
}

buildChecks(sig)

Builds the full list of validation check items for a signature (integrity, cryptographic, identity, revocation, timestamp, algorithm, chain, EKU). Used by the ValidityChecklist component.

ts
function buildChecks(sig: PdfSignature): CheckItem[]

buildMiniChecks(sig)

Builds compact check items for the signature list panel (integrity, cryptographic, identity, revocation, timestamp).

ts
function buildMiniChecks(sig: PdfSignature): MiniCheckItem[]

buildSummaryLines(sig)

Builds Adobe-style summary lines for the signature list panel expanded section (integrity, identity, timestamp, LTV status).

ts
function buildSummaryLines(sig: PdfSignature): SummaryLine[]

isLtvEnabled(sig)

Returns true if the signature is LTV-enabled (has a verified timestamp and valid revocation data).

ts
function isLtvEnabled(sig: PdfSignature): boolean

Certificate Utilities

DN (Distinguished Name) parsing utilities shared across signature, certificate, and panel components.

getCN(s)

Extract the Common Name (CN) from a DN string. Falls back to the full string if CN is not found.

ts
function getCN(s: string): string

getO(s)

Extract the Organization (O) from a DN string. Returns empty string if not found.

ts
function getO(s: string): string

getField(s, key)

Extract any RDN field from a DN string by key (e.g. 'OU', 'C', 'L').

ts
function getField(s: string, key: string): string

Format Utilities

Date formatting utilities for UI display. All functions accept Date | string defensively, handling ISO strings from rehydration.

fmtDateLong(d)

Full datetime with weekday. Used in signature detail views.

ts
function fmtDateLong(d: Date | string): string
// Example: "Saturday, March 15, 2025, 02:30:45 PM UTC"

fmtDateShort(d)

Short datetime. Used in certificate viewer tables and timestamp details.

ts
function fmtDateShort(d: Date | string): string
// Example: "Mar 15, 2025, 02:30:45 PM UTC"

fmtDateCompact(d)

Compact datetime without seconds. Used in the signature list panel. Returns empty string for null/undefined.

ts
function fmtDateCompact(d: Date | string | null | undefined): string
// Example: "Mar 15, 2025, 14:30"

fmtDatePanel(d)

Panel datetime with seconds in 24h format. Used in Adobe-style signature list panel. Returns empty string for null/undefined.

ts
function fmtDatePanel(d: Date | string | null | undefined): string
// Example: "Mar 15, 2025, 14:30:45 UTC"

Download & Export Utilities

Certificate export and file download utilities. SSR-safe: browser-only APIs are guarded. These functions are only called from click handlers, never during render.

uint8ToBase64(bytes)

Convert a Uint8Array to a base64 string. Works in both browser (via btoa) and Node.js (via Buffer).

ts
function uint8ToBase64(bytes: Uint8Array): string

downloadBlob(blob, name)

Trigger a browser file download for a Blob with the given filename.

ts
function downloadBlob(blob: Blob, name: string): void

exportCertAsPem(cert, filename)

Export a certificate as a PEM file. Downloads a .pem file if the certificate has raw DER data.

ts
function exportCertAsPem(cert: CertificateInfo, filename: string): void

exportCertAsDer(cert, filename)

Export a certificate as a DER file. Downloads a .cer file if the certificate has raw DER data.

ts
function exportCertAsDer(cert: CertificateInfo, filename: string): void

safeName(cert)

Generate a filesystem-safe filename from a certificate's Common Name. Replaces non-alphanumeric characters with underscores.

ts
function safeName(cert: CertificateInfo): string

Appearance Swapper

Functions for modifying signature appearance XObject layers in-memory to reflect verification results. Called after verifyPdf() on the original bytes -- the returned bytes are used only for PDF.js display.

swapSignatureAppearances(pdfBytes, signatures)

Swap signature appearance XObject layers to show verification status icons (checkmark, cross, question mark). Supports both legacy (n1 layer) and Acro6 (FRM/n0 layer) signature structures.

ts
async function swapSignatureAppearances(
  pdfBytes: Uint8Array,
  signatures: PdfSignature[],
): Promise<Uint8Array>
ParameterTypeDescription
pdfBytesUint8ArrayOriginal PDF bytes (unmodified)
signaturesPdfSignature[]Verified signatures with overallStatus populated

Returns: Modified PDF bytes for display, or the original bytes if swapping is not possible.

hasAcro6Appearances(pdfBytes)

Lightweight read-only check: does this PDF have any signature widgets with Acro6 layer structure (no /n1, has /FRM or /n0)?

ts
async function hasAcro6Appearances(pdfBytes: Uint8Array): Promise<boolean>

Recent Files

Recent files persistence via localStorage. SSR-safe: all localStorage calls are guarded.

RecentFileEntry

ts
interface RecentFileEntry {
  fileName: string
  fileSize: number
  lastOpened: string          // ISO date string
  signatureCount?: number
  overallStatus?: string
}

loadRecentFiles()

Load the list of recent files from localStorage. Returns an empty array on the server or if no data exists.

ts
function loadRecentFiles(): RecentFileEntry[]

addRecentFile(entry)

Add a file to the recent files list. Deduplicates by filename, prepends the new entry, and trims to 8 entries max.

ts
function addRecentFile(entry: RecentFileEntry): RecentFileEntry[]

clearRecentFiles()

Remove all recent files from localStorage.

ts
function clearRecentFiles(): RecentFileEntry[]

CoreViewer & Viewer Components

<CoreViewer>

The minimal PDF viewer engine. Manages PDF.js document loading, page rendering, store creation, plugin lifecycle, and layout composition. <Viewer> is a thin wrapper around this component.

tsx
<CoreViewer
  ref={viewerRef}
  fileBuffer={buffer}
  fileName="report.pdf"
  plugins={[layout.plugin]}
  onDocumentLoaded={(doc) => console.log(doc.numPages)}
  renderError={(err) => <MyErrorUI error={err} />}
/>

Props (CoreViewerProps):

PropTypeRequiredDescription
fileBufferArrayBuffer | nullNoPDF file bytes
fileNamestringNoFile name for display
pluginsViewerPlugin[]NoPlugins to install
initialStatePartial<ViewerStoreState>NoInitial viewer state overrides
signaturesPdfSignature[]NoReactive signature data (synced to store)
unsignedFieldsUnsignedSigField[]NoReactive unsigned field data
verificationStatusVerificationStatusNoReactive overall verification status
signaturePanelOpenbooleanNoWhether the signature panel should initially be open
onDocumentLoaded(doc: PDFDocumentProxy) => voidNoCalled when document is loaded
onPageCountChange(n: number) => voidNoCalled when page count is known
onReady() => voidNoCalled when viewer is ready
renderError(error: LoadError) => ReactNodeNoCustom error renderer
onLoadError(error: LoadError) => voidNoCalled when a document load error occurs
renderLayout(slots: CoreViewerSlots) => ReactNodeNoCustom layout render function
onContextMenu(e: React.MouseEvent) => voidNoRight-click handler
onOpenFile(file: File) => voidNoFile open handler (enables drag-drop)
isActivebooleanNoTab isolation -- disable global listeners when hidden (default: true)
verifyingbooleanNoTrue while verification is in progress (controls VerificationFloater)

CoreViewerHandle

Ref handle exposed by the <CoreViewer> component.

ts
interface CoreViewerHandle {
  scrollToPage(n: number): void
  getStore(): ViewerStore
}

CoreViewerSlots

Layout slot objects passed to the renderLayout callback for full custom layout control.

ts
interface CoreViewerSlots {
  /** Toolbar area content from plugins */
  toolbar: React.ReactNode
  /** Sidebar area content from plugins */
  sidebar: React.ReactNode
  /** The scrollable page area */
  pages: React.ReactNode
  /** Overlays (findbar, message bar, etc.) */
  overlays: React.ReactNode[]
  /** All resolved toolbar slots */
  toolbarSlots: ToolbarSlots
  /** All resolved sidebar tabs */
  sidebarTabs: SidebarTabDefinition[]
}

<PageRenderer>

Renders a single PDF page with canvas, text layer, and annotation layer. Lazy-rendered via IntersectionObserver. HiDPI-aware canvas rendering (capped at 3x device pixel ratio).

ts
interface PageRendererProps {
  page: PDFPageProxy
  scale: number
  rotation: 0 | 90 | 180 | 270
  pageNum: number
  totalPages: number
  linkService: any
  /** Additional overlays (signature widgets, highlights, etc.) */
  children?: React.ReactNode
}

Store Infrastructure

createViewerStore(overrides?)

Factory function that creates a new ViewerStore instance. The store is a lightweight pub-sub reactive state container that drives the viewer.

ts
function createViewerStore(overrides?: Partial<ViewerStoreState>): ViewerStore

Example:

ts
const store = createViewerStore({ scale: 1.5, themeMode: 'dark' })
store.get('scale')       // 1.5
store.update({ scale: 2 })
store.subscribe('scale', (newVal, oldVal) => console.log(newVal))

INITIAL_STATE

The default initial state for a ViewerStore. Can be used as a reference or for resetting state.

ts
const INITIAL_STATE: ViewerStoreState = {
  document: null,
  fileBuffer: null,
  originalFileBuffer: null,
  fileName: '',
  loadState: 'idle',
  loadError: null,
  currentPage: 1,
  totalPages: 0,
  scale: 1.2,
  fitMode: 'none',
  rotation: 0,
  scrollMode: 'vertical',
  spreadMode: 'none',
  cursorTool: 'select',
  themeMode: 'light',
  uiFontScale: 'default',
  isFullscreen: false,
  signatures: [],
  unsignedFields: [],
  verificationStatus: null,
  sidebarOpen: false,
  sidebarTab: 'thumbnails',
  sigPanelOpen: false,
  findOpen: false,
  propertiesModalOpen: false,
  shortcutHelpOpen: false,
  contextMenuPos: null,
  sigModalIndex: null,
  sigModalFieldName: '',
  sigModalTab: 'details',
  passwordNeeded: false,
  passwordError: false,
}

ViewerStoreContext

React context that provides the ViewerStore instance. Created by <CoreViewer> / <Viewer> and consumed by useViewerStore() and related hooks.

ts
const ViewerStoreContext: React.Context<ViewerStore | null>

Store Actions

Shared viewer store action functions that eliminate duplicate logic across plugins and menu components. SSR-safe: all browser API calls are guarded.

downloadPdf(store)

Download the PDF. Prefers the original unmodified bytes over appearance-swapped bytes.

ts
function downloadPdf(store: ViewerStore): void

rotateCW(store)

Rotate the document clockwise by 90 degrees.

ts
function rotateCW(store: ViewerStore): void

rotateCCW(store)

Rotate the document counter-clockwise by 90 degrees.

ts
function rotateCCW(store: ViewerStore): void

toggleFullscreen(store, element?)

Toggle fullscreen on the given element (falls back to document root).

ts
function toggleFullscreen(store: ViewerStore, element?: HTMLElement | null): void

Plugin Host Functions

Internal infrastructure for managing plugin lifecycle and collecting UI contributions. Useful for advanced custom viewer implementations.

resolvePlugins(plugins)

Flatten composedPlugins and deduplicate by name. Validates that all declared dependencies are present.

ts
function resolvePlugins(plugins: ViewerPlugin[]): ViewerPlugin[]

collectToolbarSlots(plugins)

Merge toolbar slot contributions from all plugins, then apply any transformToolbarSlots transforms.

ts
function collectToolbarSlots(plugins: ViewerPlugin[]): ToolbarSlots

collectSidebarTabs(plugins)

Collect sidebar tab definitions from all plugins, sorted by order.

ts
function collectSidebarTabs(plugins: ViewerPlugin[]): SidebarTabDefinition[]

Individual Plugin APIs

Each plugin factory function returns a ViewerPlugin & { api: <ApiType> }. Access the API via the .api property. When using defaultLayoutPlugin(), sub-plugin APIs are available directly on the result object.

ZoomPluginApi

ts
interface ZoomPluginApi {
  zoomIn(): void
  zoomOut(): void
  zoomTo(scale: number): void
  setFitMode(mode: 'none' | 'width' | 'page'): void
}
ts
interface PageNavigationPluginApi {
  goToPage(n: number): void
  goToPreviousPage(): void
  goToNextPage(): void
  goToFirstPage(): void
  goToLastPage(): void
}

RotationPluginApi

ts
interface RotationPluginApi {
  rotateCW(): void
  rotateCCW(): void
  setRotation(r: 0 | 90 | 180 | 270): void
}

SearchPluginApi

ts
interface SearchPluginApi {
  open(): void
  close(): void
  toggle(): void
}

PrintPluginApi

ts
interface PrintPluginApi {
  print(): void
}

DownloadPluginApi

ts
interface DownloadPluginApi {
  download(): void
}

ThemePluginApi

ts
interface ThemePluginApi {
  toggleTheme(): void
  setTheme(mode: 'light' | 'dark'): void
  getTheme(): 'light' | 'dark'
}

FullscreenPluginApi

ts
interface FullscreenPluginApi {
  enterFullscreen(): void
  exitFullscreen(): void
  toggleFullscreen(): void
}

SelectionPluginApi

ts
interface SelectionPluginApi {
  setCursorTool(tool: 'select' | 'hand'): void
  toggleHand(): void
}

ScrollModePluginApi

ts
interface ScrollModePluginApi {
  setScrollMode(mode: 'vertical' | 'horizontal' | 'wrapped' | 'page'): void
}

SpreadModePluginApi

ts
interface SpreadModePluginApi {
  setSpreadMode(mode: 'none' | 'odd' | 'even'): void
}

SignaturePluginApi

ts
interface SignaturePluginApi {
  openPanel(): void
  closePanel(): void
  togglePanel(): void
}

SidebarPluginApi

ts
interface SidebarPluginApi {
  open(tabId?: string): void
  close(): void
  toggle(tabId?: string): void
  setTab(tabId: string): void
}

AccessibilityPluginApi

ts
interface AccessibilityPluginApi {
  setFontScale(scale: 'compact' | 'default' | 'large' | 'extra-large'): void
  getFontScale(): 'compact' | 'default' | 'large' | 'extra-large'
}

DefaultLayoutPluginOptions

ts
interface DefaultLayoutPluginOptions {
  accessibility?: AccessibilityPluginOptions
  toolbar?: ToolbarPluginOptions
  disable?: {
    search?: boolean
    print?: boolean
    download?: boolean
    fullscreen?: boolean
    theme?: boolean
    rotation?: boolean
    selection?: boolean
    sidebar?: boolean
    signatures?: boolean
    highlights?: boolean
    openFile?: boolean
    properties?: boolean
    shortcuts?: boolean
    contextMenu?: boolean
    accessibility?: boolean
  }
}
 
interface AccessibilityPluginOptions {
  initialScale?: 'compact' | 'default' | 'large' | 'extra-large'
  persist?: boolean  // default: true — save preference to localStorage
}

DefaultLayoutPluginResult

ts
interface DefaultLayoutPluginResult {
  plugin: ViewerPlugin
  zoom: ZoomPluginApi
  navigation: PageNavigationPluginApi
  rotation: RotationPluginApi
  search: SearchPluginApi
  print: PrintPluginApi
  download: DownloadPluginApi
  theme: ThemePluginApi
  fullscreen: FullscreenPluginApi
  selection: SelectionPluginApi
  scrollMode: ScrollModePluginApi
  spreadMode: SpreadModePluginApi
  signature: SignaturePluginApi
  sidebar: SidebarPluginApi
  accessibility: AccessibilityPluginApi
}

UI Primitives

Dialog Components

Portal-based modal dialog built on Radix UI Dialog. Renders at the document root with position: fixed.

ts
// Root dialog container (controls open/close state)
const Dialog: React.FC<RadixDialogProps>
 
// Semi-transparent backdrop overlay
const DialogOverlay: React.ForwardRefComponent<HTMLDivElement>
 
// Centered dialog content panel (includes overlay automatically)
const DialogContent: React.ForwardRefComponent<HTMLDivElement>
 
// Dialog title heading
const DialogTitle: React.ForwardRefComponent<HTMLHeadingElement>
 
// Flexbox column container for dialog header area
const DialogHeader: React.FC<React.HTMLAttributes<HTMLDivElement>>
 
// Close button (triggers onOpenChange(false))
const DialogClose: React.FC<RadixDialogCloseProps>

Example:

tsx
import { Dialog, DialogContent, DialogTitle, DialogHeader, DialogClose } from '@trexolab/verifykit-react'
 
<Dialog open={isOpen} onOpenChange={setIsOpen}>
  <DialogContent style={{ maxWidth: 480 }}>
    <DialogHeader>
      <DialogTitle>Certificate Details</DialogTitle>
    </DialogHeader>
    <p>Dialog body content</p>
    <DialogClose>Close</DialogClose>
  </DialogContent>
</Dialog>

ViewerDialog Components

Inline modal that renders inside the viewer container with position: absolute. Unlike the portal-based Dialog, these stay within the viewer bounds and work correctly when the viewer is embedded. Features backdrop blur, escape-to-close, and focus management.

ts
// Root dialog wrapper (absolute positioned within viewer)
function ViewerDialog(props: {
  open: boolean
  onOpenChange?: (open: boolean) => void
  children: React.ReactNode
}): React.ReactNode
 
// Blurred backdrop overlay (covers only the viewer area)
function ViewerDialogOverlay(props: {
  onClick?: () => void
}): React.ReactNode
 
// Centered content panel with border, shadow, and entrance animation
function ViewerDialogContent(props: {
  children: React.ReactNode
  style?: React.CSSProperties
  onClose?: () => void
}): React.ReactNode
 
// Dialog title heading (h2 element)
function ViewerDialogTitle(props: {
  children: React.ReactNode
  style?: React.CSSProperties
}): React.ReactNode

Toolbar Components

<Toolbar>

Three-section grid layout toolbar (LEFT | CENTER | RIGHT) that renders named slots contributed by plugins.

ts
function Toolbar(props: { slots: ToolbarSlots; store: ViewerStore }): React.ReactNode

<ToolbarButton>

Shared toolbar button primitive with tooltip, active state, and badge support.

PropTypeRequiredDescription
iconReact.ReactNodeYesButton icon
onClick() => voidYesClick handler
disabledbooleanNoDisabled state
titlestringNoTooltip text
shortcutstringNoKeyboard shortcut hint in tooltip
activebooleanNoActive/pressed state
badgenumberNoNotification badge count
ariaExpandedbooleanNoARIA expanded state
ariaHasPopupboolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog'NoARIA popup indicator

<ToolbarDivider>

Visual separator line between toolbar button groups.

ts
function ToolbarDivider(): React.ReactNode

ToolbarPluginOptions

Options for the toolbar plugin. Allows transforming toolbar slots to add, remove, or reorder controls.

ts
interface ToolbarPluginOptions {
  /** Transform toolbar slots -- add, remove, or reorder */
  transform?: (slots: ToolbarSlots) => ToolbarSlots
}

i18n (Internationalization)

Built-in Locales

The following locale is built-in with full translations:

LocaleLanguage
'en'English (default)

Additional locales ('fr', 'de', 'es', 'ar', 'ja', 'zh') can be registered via registerLocale().

Locale

ts
type Locale = 'en' | 'fr' | 'de' | 'es' | 'ar' | 'ja' | 'zh' | string

TranslationStrings

Interface defining all translatable string keys. Keys are organized by category:

CategoryKey prefixExample keys
Toolbartoolbar.*toolbar.openFile, toolbar.zoomIn, toolbar.print
Statusstatus.*status.valid, status.invalid, status.warning
Signature panelpanel.*panel.signatures, panel.noSignatures
Documentdocument.*document.properties, document.metadata
Find barfind.*find.placeholder, find.noResults
Welcomewelcome.*welcome.title, welcome.subtitle
Passwordpassword.*password.title, password.submit
Verificationverification.*verification.checking, verification.complete
PAdESpades.*pades.B-B, pades.B-T, pades.B-LT, pades.B-LTA
Generalgeneral.*general.close, general.cancel, general.ok

t(key, locale?)

Translate a key. Falls back to English, then to the key itself.

ts
function t(key: string, locale?: string): string

setLocale(locale) / getLocale()

Set or get the current active locale.

ts
function setLocale(locale: string): void
function getLocale(): string

registerLocale(locale, strings)

Register a custom locale or override strings for an existing locale.

ts
function registerLocale(locale: string, strings: Partial<TranslationStrings>): void

Example:

ts
import { registerLocale, setLocale } from '@trexolab/verifykit-react'
 
registerLocale('fr', {
  'toolbar.print': 'Imprimer',
  'toolbar.download': 'Telecharger',
  'status.valid': 'Valide',
  'status.invalid': 'Invalide',
})
setLocale('fr')

getAvailableLocales()

Get all registered locale codes.

ts
function getAvailableLocales(): string[]