VerifyKitv0.13.3

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
onPasswordAccepted(pwd: string) => voidNoFired with the password PDF.js accepted for an encrypted document, after it loads. Optional — since v0.5.14 the password reaches useVerification() automatically via the provider. Not fired for unencrypted documents.
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')

<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

Messages. The bar derives its own wording from status and the signatures — there is no prop to override it:

ConditionMessage
pendingValidating signatures…
invalidAt least one signature is INVALID.
valid, a signature carries mdpPermissionCertified by … (see below)
validSigned and all signatures are valid.
warningAt least one signature has problems.
otherwiseSignature validity is UNKNOWN.

Certified documents get Adobe's sentence, built from the signer certificate, plus a second line describing the DocMDP permission level (for example "No changes to the document are permitted." for P=1).

The certification sentence adapts to the width of the bar (since 0.6.4). Rather than clipping mid-email, the bar measures three complete phrasings and renders the longest one that fits, dropping the permission line before the message loses characters:

Sentence
fullCertified by <CN> <email>, <OU>, certificate issued by <issuer CN>.
compactCertified by <CN>, <OU>.
minimalCertified by <CN>.

Which one appears depends on the certificate as much as the viewport — a long common name degrades sooner than a short one at the same width. The untrimmed text (message and permission line) is always on the element's title, so a test that needs a stable string should read that rather than the rendered text.


<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>
  applyPassword(pwd: string): Promise<void>
  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

applyPassword(pwd) — report the password that unlocked an encrypted PDF, so the on-page signature appearance can be swapped to its verified state. The original bytes are never modified.

You normally do not call this. Since v0.5.14 the viewer reports the accepted password to useVerification() automatically through VerifyKitProvider, as long as <Viewer> and useVerification() are under the same provider. It exists for hosts that unlock the document with their own PDF.js instance:

ts
// Only if your app unlocks the PDF outside VerifyKit's viewer.
await verification.applyPassword(userPassword)

'' is a meaningful value, not "no password": an owner-password-only PDF is encrypted but opens with an empty user password, and the swap needs it to derive the file key. Repeat calls with an already-applied password are ignored, so combining this with the onPasswordAccepted prop is harmless.


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)

Reports the size of the container element, plus a breakpoint derived from its width. It observes the element rather than the window, so it reacts when the signature panel opens or the sidebar toggles — a viewer embedded in a 380px column reports xs on a 1440px screen.

ts
type Breakpoint = 'xs' | 'sm' | 'md' | 'lg'
 
function useContainerSize(
  ref: React.RefObject<HTMLElement | null>
): { width: number; height: number; breakpoint: Breakpoint }
BreakpointContainer width
xs< 400px
sm400px – 559px
md560px – 839px
lg≥ 840px

Measurements are clientWidth/clientHeight, batched into an animation frame. The viewer publishes its own breakpoint as a data-breakpoint attribute on the root element, so you can style against it without calling the hook:

css
.verifykit-root[data-breakpoint="xs"] .my-panel { display: none; }

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
  /** Override zoom range and step. See {@link ZoomPluginOptions}. */
  zoom?: ZoomPluginOptions
  /** Page navigation. See {@link PageNavigationPluginOptions}. */
  pageNavigation?: PageNavigationPluginOptions
  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 ZoomPluginOptions {
  /** Minimum scale. Default `0.25` (25%). */
  minScale?: number
  /** Maximum scale. Default `10` (1000%). */
  maxScale?: number
  /** Scale delta per zoom-in / zoom-out click. Default `0.15`. */
  step?: number
}
 
interface PageNavigationPluginOptions {
  /**
   * Floating previous/next control over the bottom of the page in single-page
   * scroll mode, revealed while the pointer is over the document. Default `true`.
   *
   * Single-page is the one mode where scrolling cannot reach the next page, so
   * turning this off leaves the toolbar as the only way forward.
   */
  floatingNav?: boolean
}
 
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(options?)ZoomPluginApiZoom controls: zoomIn(), zoomOut(), zoomTo(scale), setFitMode(mode). Also installs Ctrl/Cmd+wheel and two-finger pinch zoom. Options: { minScale?: number; maxScale?: number; step?: number } (defaults 0.25 / 10 / 0.15)
pageNavigationPlugin(options?)PageNavigationPluginApiPage navigation: goToPage(n), goToNextPage(), goToPreviousPage(), goToFirstPage(), goToLastPage(). Also renders the floating previous/next control shown over the page in scrollMode: 'page'. Options: { floatingNav?: boolean } (default true)
rotationPlugin()RotationPluginApiDocument rotation: rotateCW(), rotateCCW()
scrollModePlugin()ScrollModePluginApiScroll mode: setScrollMode(mode) -- 'vertical', 'horizontal' or 'page'. In 'horizontal' the wheel drives the axis the pages flow along: plain wheel moves across, Shift+wheel moves down a page taller than the window
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: pdf.js is bundled into this package rather than installed into your project, so there is no node_modules/pdfjs-dist to copy from. Download the pinned worker into your public directory and pass the local path:

bash
npm pack pdfjs-dist@5.5.207 --pack-destination /tmp \
  && tar -xzOf /tmp/pdfjs-dist-5.5.207.tgz package/legacy/build/pdf.worker.min.mjs \
     > public/pdf.worker.min.mjs

ViewerPlugin

Plugin interface for extending the viewer with features.

ts
interface ViewerPlugin {
  name: string
  dependencies?: string[]
  composedPlugins?: ViewerPlugin[]
 
  // Lifecycle hooks
  install?(ctx: ViewerPluginContext): 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>
  renderMenuItems?: MenuItemsRender   // 0.7.0+
  renderContextMenuItems?: ContextMenuItemsRender  // unreleased
  menuOrder?: number                  // 0.7.0+ — lower renders earlier (default 50)
  menuGroup?: string                  // 0.7.0+ — section label for the divider
  sidebarTabs?: SidebarTabDefinition[]
  renderOverlay?: (props: OverlayRenderProps) => React.ReactNode
  renderRightPanel?: (props: OverlayRenderProps) => React.ReactNode
  renderPageOverlay?: (props: PageOverlayRenderProps) => React.ReactNode
  transformToolbarSlots?: (slots: ToolbarSlots) => ToolbarSlots
}

renderMenuItems, menuOrder and menuGroup were added in 0.7.0 — see MenuItemRenderProps and the overflow-menu guide. renderContextMenuItems is the same contribution model for the right-click menu and shares menuOrder / menuGroup with it — see ContextMenuItemRenderProps and the context-menu guide.


ViewerPluginContext

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

Exported as ViewerPluginContext, not PluginContext. The package also re-exports the core engine's PluginContext (used by VerifyKitPlugin.setup), so the plain name resolves to that one.

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

getPlugins() returns every plugin resolved into this viewer, composed sub-plugins included. It exists for a plugin that draws a surface assembled from what the others contribute — the built-in context menu — and everything else should stay ignorant of its neighbours.


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: (state: ViewerStoreState, prev: ViewerStoreState) => 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

View Mode Types

The unions behind the layout state keys, each exported by name so you can annotate your own handlers.

ts
type FitMode    = 'none' | 'width' | 'page'
type ScrollMode = 'vertical' | 'horizontal' | 'page'
type SpreadMode = 'none' | 'odd' | 'even'
type CursorTool = 'select' | 'hand'
type SidebarTab = string   // tab id; plugins register their own

FitMode is 'none' for a plain zoom level, 'width' when the page is fitted to the width of its column, and 'page' when the whole page is fitted. It is also the type of ZoomChangeEvent.fitMode.

Note the overlap: 'page' and 'none' appear in more than one union. They mean different things in each — scrollMode: 'page' is one-page-at-a-time scrolling, while fitMode: 'page' is fit-whole-page zoom.


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<SidebarTabProps>
  canRender?: (state: ViewerStoreState) => boolean
  order: number
}
 
interface SidebarTabProps {
  store: ViewerStore
}

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
  FontScale?: ToolbarSlotRender
  ThemeToggle?: ToolbarSlotRender
  Fullscreen?: ToolbarSlotRender
  MoreMenu?: ToolbarSlotRender
  [custom: string]: ToolbarSlotRender | undefined
}
 
type ToolbarSlotRender = (props: ToolbarSlotProps) => React.ReactNode
 
interface ToolbarSlotProps {
  store: ViewerStore
  /** Slots the toolbar could not fit at the current width (0.7.0+). */
  overflowSlots?: string[]
  /** Collect every plugin's menu contributions — passed to the `MoreMenu` slot (0.7.0+). */
  renderMenuItems?: (onClose: () => void) => CollectedMenuItems[]
}

Passed to a plugin's renderMenuItems. Added in 0.7.0.

ts
type MenuItemsRender = (props: MenuItemRenderProps) => React.ReactNode
 
interface MenuItemRenderProps {
  store: ViewerStore
  /** Registered slots the toolbar could not fit, in the order they were dropped. */
  overflowSlots: string[]
  /** True when `slot` is registered in the toolbar but not currently visible. */
  isOverflowed(slot: string): boolean
  /** Close the menu. Call after running an action. */
  onClose(): void
}
 
/** One plugin's contribution, as gathered by `collectMenuItems`. */
interface CollectedMenuItems {
  name: string    // contributing plugin name — used as the React key
  group: string   // section label; a divider is drawn where this changes
  node: React.ReactNode
}

isOverflowed(slot) returns false for a slot that was never registered. A consumer who removed Download via toolbarPlugin({ transform }) has said they do not want that action, so the menu must not offer it either. A plugin with no toolbar slot of its own (document properties, shortcut help) should not consult it and simply always contributes.

See the overflow-menu guide for a worked example.


ContextMenuItemRenderProps

Passed to a plugin's renderContextMenuItems. Unreleased.

ts
type ContextMenuItemsRender = (props: ContextMenuItemRenderProps) => React.ReactNode
 
interface ContextMenuItemRenderProps {
  store: ViewerStore
  /** Close the menu. Call after running an action. */
  onClose(): void
}

Smaller than MenuItemRenderProps on purpose: the context menu sits over the page rather than in the toolbar, so nothing can overflow into it and there is no isOverflowed to ask — a plugin contributes whenever it is installed, and contributes nothing when it is not. Contributions are gathered by collectContextMenuItems into the same CollectedMenuItems shape, ordered and grouped by the plugin's menuOrder / menuGroup.

See the context-menu guide for a worked example.


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

PluginContext here is the core engine's context, the one VerifyKitPlugin.setup() receives. The viewer's context is a different type, exported as ViewerPluginContext.

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

exportCertChainAsPem(certs, filename)

Concatenate every certificate with a rawDer into a single .pem file (PEM blocks back-to-back) and trigger a browser download. Certs missing rawDer are skipped silently.

ts
function exportCertChainAsPem(
  certs: readonly CertificateInfo[],
  filename: string,
): void

Common use: exporting the full signer-to-root trust chain from the Signature Properties dialog for a Unix / Java / server trust store.

exportCertChainAsPkcs7(certs, filename)

Build a certs-only PKCS#7 (.p7b) bundle via buildCertChainPkcs7 and trigger a download. Windows and Adobe Reader import this format natively.

ts
async function exportCertChainAsPkcs7(
  certs: readonly CertificateInfo[],
  filename: string,
): Promise<void>

exportCertChainAsZip(certs, filename)

Package every certificate as both PEM and DER files inside a .zip. Filenames inside the archive follow NN-<safeName>.{pem,cer}, sorted from signer (01) to root. Uses a pure-JS stored-ZIP writer — no runtime dependency.

ts
function exportCertChainAsZip(
  certs: readonly CertificateInfo[],
  filename: string,
): void

These three helpers are what power the Export Chain ▾ dropdown in the Signature Properties dialog's Certificates tab. Use them directly in your own UI if you build a custom viewer.


Appearance Swapper

Functions for updating signature appearances 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)

Draw the verification status icon (checkmark, cross, question mark) on each signature field, inside the PDF canvas. Works with the signature appearance styles produced by Acrobat and the common signing tools, including password-protected documents. Fields that cannot carry a status icon are left as the signer authored them.

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 signature fields whose appearance can carry a status icon? Use it to decide whether calling swapSignatureAppearances() is worthwhile; it does not modify the document.

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
onRevalidate() => voidNoCalled when the user requests re-verification
onPasswordAccepted(pwd: string) => voidNoFired with the password PDF.js accepted for an encrypted document. Optional — the password also reaches useVerification() automatically via the provider. Not fired for unencrypted documents.
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' | '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[]