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.
<VerifyKitProvider config={config}>
<App />
</VerifyKitProvider>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
config | VerifyKitConfig | No | Provider configuration (see VerifyKitConfig type below) |
children | ReactNode | Yes | Child components |
<Viewer>
The recommended plugin-based PDF viewer component. Accepts plugins for composable features.
<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:
| Prop | Type | Required | Description |
|---|---|---|---|
fileBuffer | ArrayBuffer | null | No | PDF file bytes |
fileName | string | No | Display file name |
plugins | ViewerPlugin[] | No | Array of viewer plugins to install |
initialState | Partial<ViewerStoreState> | No | Initial store state overrides |
signatures | PdfSignature[] | No | Reactive signature data (synced to store) |
unsignedFields | UnsignedSigField[] | No | Reactive unsigned field data |
verificationStatus | VerificationStatus | No | Reactive overall verification status |
onDocumentLoaded | (doc: PDFDocumentProxy) => void | No | Called when the PDF document loads |
onPageCountChange | (n: number) => void | No | Called when page count is known |
onReady | () => void | No | Called when the viewer is ready |
onOpenFile | (file: File) => void | No | File open handler (enables drag-drop) |
onContextMenu | (e: React.MouseEvent) => void | No | Context menu handler |
onLoadError | (error: LoadError) => void | No | Called when the PDF fails to load |
onRevalidate | () => void | No | Called when user requests re-verification |
onPasswordAccepted | (pwd: string) => void | No | Fired 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. |
signaturePanelOpen | boolean | No | Auto-open the signature panel |
isActive | boolean | No | Tab isolation — disable global listeners when hidden (default: true) |
verifying | boolean | No | Show loading indicator while verification is in progress |
renderError | (error: LoadError) => ReactNode | No | Custom error UI renderer |
renderLayout | (slots) => ReactNode | No | Custom layout render function |
Ref handle (ViewerHandle):
interface ViewerHandle {
scrollToPage(n: number): void
getStore(): ViewerStore
}const viewerRef = useRef<ViewerHandle>(null)
viewerRef.current.scrollToPage(5)<WelcomeScreen>
A drop-target landing screen for when no file is loaded.
<WelcomeScreen
onOpenFile={(file: File) => verification.load(file)}
title="My PDF Viewer"
subtitle="Drag and drop a PDF here"
/>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
onOpenFile | (file: File) => void | Yes | Called when a file is dropped or selected |
title | string | No | Heading text |
subtitle | string | No | Subheading text |
accept | string | No | File type filter for file picker (default: '.pdf,application/pdf') |
<DocumentMessageBar>
Colored status bar displayed above the viewer showing the overall verification result.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
status | VerificationStatus | Yes | Overall document verification status |
signatures | PdfSignature[] | Yes | All document signatures |
onShowPanel | () => void | No | Called when user clicks to show signature panel |
panelVisible | boolean | No | Whether 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:
| Condition | Message |
|---|---|
pending | Validating signatures… |
invalid | At least one signature is INVALID. |
valid, a signature carries mdpPermission | Certified by … (see below) |
valid | Signed and all signatures are valid. |
warning | At least one signature has problems. |
| otherwise | Signature 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 | |
|---|---|
| full | Certified by <CN> <email>, <OU>, certificate issued by <issuer CN>. |
| compact | Certified by <CN>, <OU>. |
| minimal | Certified 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:
| Prop | Type | Required | Description |
|---|---|---|---|
signatures | PdfSignature[] | Yes | All document signatures |
unsignedFields | UnsignedSigField[] | No | Unsigned signature fields |
selectedIdx | number | Yes | Currently selected signature index |
onSelect | (i: number, tab?: string) => void | Yes | Selection handler |
onNavigate | (i: number) => void | No | Navigate to signature in PDF |
onClose | () => void | No | Close panel handler |
onRevalidate | () => void | No | Re-verify signatures |
isRevalidating | boolean | No | Show revalidation spinner |
<SignaturePropertiesModal>
Tabbed modal dialog showing detailed signature information, validity checks, certificate chain, and timestamp data.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
sig | PdfSignature | null | Yes | The signature to display |
fieldName | string | Yes | Form field name |
open | boolean | Yes | Whether the modal is open |
onClose | () => void | Yes | Close handler |
initialTab | 'details' | 'certificates' | 'tsa' | 'pades' | No | Initially active tab |
<CertificateViewer>
Interactive certificate chain tree viewer. Displays the full certificate chain from signer to root CA with expandable details.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
cert | CertificateInfo | Yes | Certificate to display |
isTsa | boolean | No | Whether this is a TSA certificate |
<PasswordDialog>
Password prompt dialog for encrypted/password-protected PDFs.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
error | boolean | Yes | Whether a previous password attempt failed |
onSubmit | (pwd: string) => void | Yes | Submit handler with entered password |
onCancel | () => void | Yes | Cancel handler |
<SignatureStatusIcon>
Status icon component showing valid/invalid/warning/unknown state.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
status | VerificationStatus | Yes | Verification status to display |
size | number | No | Icon size in pixels |
<ValidityChecklist>
Expandable list of all verification checks for a signature.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
sig | PdfSignature | Yes | Signature to show checks for |
<PdfViewerErrorBoundary>
Error boundary wrapper for the PDF viewer. Catches render errors and shows a fallback UI.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
children | ReactNode | Yes | Child components |
fallback | ReactNode | No | Custom fallback UI |
onReset | () => void | No | Called when the user resets the error boundary |
Hooks
useVerification()
Manages PDF loading, verification, and result state. Must be used inside a <VerifyKitProvider>.
function useVerification(): VerificationStateReturns:
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:
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 stateapplyPassword(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:
// 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>.
function useViewerStore<T>(selector: (state: ViewerStoreState) => T): TExample:
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.
function useViewerStoreKey<K extends keyof ViewerStoreState>(key: K): ViewerStoreState[K]Example:
const currentPage = useViewerStoreKey('currentPage')useViewerStoreUpdate()
Get the store's update function for dispatching partial state updates.
function useViewerStoreUpdate(): (partial: Partial<ViewerStoreState>) => voidExample:
const update = useViewerStoreUpdate()
update({ scale: 1.5, fitMode: 'none' })useStore()
Returns the raw ViewerStore instance for advanced use (batch updates, direct subscriptions).
function useStore(): ViewerStoreuseContainerSize(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.
type Breakpoint = 'xs' | 'sm' | 'md' | 'lg'
function useContainerSize(
ref: React.RefObject<HTMLElement | null>
): { width: number; height: number; breakpoint: Breakpoint }| Breakpoint | Container width |
|---|---|
xs | < 400px |
sm | 400px – 559px |
md | 560px – 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:
.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:
const [layout] = useState(() => defaultLayoutPlugin())Meta Plugin
defaultLayoutPlugin(options?)
Composes all 24 plugins into a batteries-included experience. The recommended starting point for most applications.
function defaultLayoutPlugin(options?: DefaultLayoutPluginOptions): DefaultLayoutPluginResultOptions:
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:
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:
// 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]} />Navigation Plugins
| Plugin | API Type | Description |
|---|---|---|
zoomPlugin(options?) | ZoomPluginApi | Zoom 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?) | PageNavigationPluginApi | Page 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() | RotationPluginApi | Document rotation: rotateCW(), rotateCCW() |
scrollModePlugin() | ScrollModePluginApi | Scroll 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() | SpreadModePluginApi | Spread/facing mode: setSpreadMode(mode) |
Content Plugins
| Plugin | API Type | Description |
|---|---|---|
searchPlugin() | SearchPluginApi | Text search: open(), close() |
highlightPlugin() | -- | Text highlighting and selection display |
selectionPlugin() | SelectionPluginApi | Cursor tool selection: setCursorTool(tool) |
Action Plugins
| Plugin | API Type | Description |
|---|---|---|
printPlugin() | PrintPluginApi | Print the document: print() |
downloadPlugin() | DownloadPluginApi | Download the document: download() |
openFilePlugin() | -- | File open and drag-drop handling |
UI Plugins
| Plugin | API Type | Description |
|---|---|---|
toolbarPlugin() | -- | Toolbar with slot system for positioning controls |
sidebarPlugin() | SidebarPluginApi | Sidebar panel: toggle(tab?), open(tab), close() |
themePlugin() | ThemePluginApi | Theme control: toggleTheme(), setTheme(mode), getTheme() |
fullscreenPlugin() | FullscreenPluginApi | Fullscreen: enterFullscreen(), exitFullscreen(), toggleFullscreen() |
accessibilityPlugin() | AccessibilityPluginApi | UI font scale: setFontScale(scale), getFontScale() |
Panel Plugins
| Plugin | API Type | Description |
|---|---|---|
signaturePlugin() | SignaturePluginApi | Signature panel: openPanel(), closePanel(), togglePanel() |
thumbnailPlugin() | -- | Thumbnail sidebar tab |
bookmarkPlugin() | -- | Bookmark/outline sidebar tab |
attachmentPlugin() | -- | Attachment sidebar tab |
propertiesPlugin() | -- | Document properties modal |
Help Plugins
| Plugin | API Type | Description |
|---|---|---|
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.
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.
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:
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.mjsViewerPlugin
Plugin interface for extending the viewer with features.
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, notPluginContext. The package also re-exports the core engine'sPluginContext(used byVerifyKitPlugin.setup), so the plain name resolves to that one.
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.
interface ViewerHandle {
scrollToPage(n: number): void
getStore(): ViewerStore
}ViewerStore
Lightweight pub-sub reactive store that drives the viewer state.
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:
| Category | Keys |
|---|---|
| Document | document, fileBuffer, originalFileBuffer, fileName, loadState, loadError |
| Navigation | currentPage, totalPages |
| Zoom | scale, fitMode |
| Rotation | rotation |
| Layout | scrollMode, spreadMode, cursorTool |
| Theme | themeMode |
| Fullscreen | isFullscreen |
| Verification | signatures, unsignedFields, verificationStatus, isRevalidating |
| UI panels | sidebarOpen, sidebarTab, sigPanelOpen, findOpen, propertiesModalOpen, shortcutHelpOpen, aboutModalOpen, contextMenuPos, sigModalIndex, sigModalFieldName, sigModalTab, highlightedSigIndex |
| Password | passwordNeeded, passwordError |
View Mode Types
The unions behind the layout state keys, each exported by name so you can annotate your own handlers.
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 ownFitMode 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, whilefitMode: 'page'is fit-whole-page zoom.
Event Types
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
interface KeyboardShortcut {
id: string
key: string
ctrl?: boolean
shift?: boolean
alt?: boolean
handler: (e: KeyboardEvent) => void
allowInInput?: boolean
description?: string
}SidebarTabDefinition
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
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[]
}MenuItemRenderProps
Passed to a plugin's renderMenuItems. Added in 0.7.0.
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.
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
PluginContexthere is the core engine's context, the oneVerifyKitPlugin.setup()receives. The viewer's context is a different type, exported asViewerPluginContext.
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.
interface LoadError {
/** Semantic error type for programmatic handling */
name: LoadErrorName
/** Human-readable error message */
message: string
}LoadErrorName
Union of all recognized error classification names.
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.
function classifyPdfError(error: unknown): LoadErrorcreateLoadError(name, message)
Create a LoadError with a specific name and message.
function createLoadError(name: LoadErrorName, message: string): LoadErrorStatus & 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
| Constant | Type | Description |
|---|---|---|
STATUS_LABEL | Record<VerificationStatus, string> | Human-readable label per status ('Valid', 'Invalid', etc.) |
STATUS_COLOR | Record<VerificationStatus, string> | Foreground text color CSS variable per status |
STATUS_BG | Record<VerificationStatus, string> | Background surface color CSS variable per status |
STATUS_STRIPE | Record<VerificationStatus, string> | Border/stripe color CSS variable per status |
STATUS_CFG | Record<VerificationStatus, StatusCfg> | Combined status banner config (color, bg, stripe, title) |
AVATAR_RING | Record<VerificationStatus, string> | Avatar ring color per status (signature modal header) |
PANEL_STRIPE | Record<VerificationStatus, string> | Left stripe color per status (signature list panel) |
StatusCfg
interface StatusCfg {
color: string
bg: string
stripe: string
title: string
}Functions
statusTextColor(status)
Returns the CSS color variable for status check rows and bullets.
function statusTextColor(status: VerificationStatus): stringgetStatusSentence(sig)
Returns an Adobe Reader DC-style status sentence for a signature. Handles deleted and not-yet-verified signatures.
function getStatusSentence(sig: PdfSignature): stringgetInvalidSub(sig)
Returns a detailed sub-message explaining why a signature is invalid (revoked, modified, expired, etc.).
function getInvalidSub(sig: PdfSignature): stringgetPillLabel(sig)
Returns the uppercase status label for the modal header badge (e.g. 'VALID', 'INVALID').
function getPillLabel(sig: PdfSignature): stringgetInitials(name)
Extracts initials from a signer name for avatar display. Returns first and last initials for multi-word names, or a single initial.
function getInitials(name: string): stringgetDisplayStatus(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."
function getDisplayStatus(sig: PdfSignature): VerificationStatusoverallStatus(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.
function overallStatus(result: VerificationResult): VerificationStatusCheck Builders
Functions that construct validation check items from PdfSignature data. Shared between the full validity checklist and the compact signature list panel.
CheckItem
interface CheckItem {
status: VerificationStatus
label: string
text: string
detail?: string
}MiniCheckItem
interface MiniCheckItem {
status: VerificationStatus
label: string
}SummaryLine
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.
function buildChecks(sig: PdfSignature): CheckItem[]buildMiniChecks(sig)
Builds compact check items for the signature list panel (integrity, cryptographic, identity, revocation, timestamp).
function buildMiniChecks(sig: PdfSignature): MiniCheckItem[]buildSummaryLines(sig)
Builds Adobe-style summary lines for the signature list panel expanded section (integrity, identity, timestamp, LTV status).
function buildSummaryLines(sig: PdfSignature): SummaryLine[]isLtvEnabled(sig)
Returns true if the signature is LTV-enabled (has a verified timestamp and valid revocation data).
function isLtvEnabled(sig: PdfSignature): booleanCertificate 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.
function getCN(s: string): stringgetO(s)
Extract the Organization (O) from a DN string. Returns empty string if not found.
function getO(s: string): stringgetField(s, key)
Extract any RDN field from a DN string by key (e.g. 'OU', 'C', 'L').
function getField(s: string, key: string): stringFormat 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.
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.
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.
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.
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).
function uint8ToBase64(bytes: Uint8Array): stringdownloadBlob(blob, name)
Trigger a browser file download for a Blob with the given filename.
function downloadBlob(blob: Blob, name: string): voidexportCertAsPem(cert, filename)
Export a certificate as a PEM file. Downloads a .pem file if the certificate has raw DER data.
function exportCertAsPem(cert: CertificateInfo, filename: string): voidexportCertAsDer(cert, filename)
Export a certificate as a DER file. Downloads a .cer file if the certificate has raw DER data.
function exportCertAsDer(cert: CertificateInfo, filename: string): voidsafeName(cert)
Generate a filesystem-safe filename from a certificate's Common Name. Replaces non-alphanumeric characters with underscores.
function safeName(cert: CertificateInfo): stringexportCertChainAsPem(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.
function exportCertChainAsPem(
certs: readonly CertificateInfo[],
filename: string,
): voidCommon 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.
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.
function exportCertChainAsZip(
certs: readonly CertificateInfo[],
filename: string,
): voidThese 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.
async function swapSignatureAppearances(
pdfBytes: Uint8Array,
signatures: PdfSignature[],
): Promise<Uint8Array>| Parameter | Type | Description |
|---|---|---|
pdfBytes | Uint8Array | Original PDF bytes (unmodified) |
signatures | PdfSignature[] | 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.
async function hasAcro6Appearances(pdfBytes: Uint8Array): Promise<boolean>Recent Files
Recent files persistence via localStorage. SSR-safe: all localStorage calls are guarded.
RecentFileEntry
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.
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.
function addRecentFile(entry: RecentFileEntry): RecentFileEntry[]clearRecentFiles()
Remove all recent files from localStorage.
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.
<CoreViewer
ref={viewerRef}
fileBuffer={buffer}
fileName="report.pdf"
plugins={[layout.plugin]}
onDocumentLoaded={(doc) => console.log(doc.numPages)}
renderError={(err) => <MyErrorUI error={err} />}
/>Props (CoreViewerProps):
| Prop | Type | Required | Description |
|---|---|---|---|
fileBuffer | ArrayBuffer | null | No | PDF file bytes |
fileName | string | No | File name for display |
plugins | ViewerPlugin[] | No | Plugins to install |
initialState | Partial<ViewerStoreState> | No | Initial viewer state overrides |
signatures | PdfSignature[] | No | Reactive signature data (synced to store) |
unsignedFields | UnsignedSigField[] | No | Reactive unsigned field data |
verificationStatus | VerificationStatus | No | Reactive overall verification status |
signaturePanelOpen | boolean | No | Whether the signature panel should initially be open |
onDocumentLoaded | (doc: PDFDocumentProxy) => void | No | Called when document is loaded |
onPageCountChange | (n: number) => void | No | Called when page count is known |
onReady | () => void | No | Called when viewer is ready |
renderError | (error: LoadError) => ReactNode | No | Custom error renderer |
onLoadError | (error: LoadError) => void | No | Called when a document load error occurs |
onRevalidate | () => void | No | Called when the user requests re-verification |
onPasswordAccepted | (pwd: string) => void | No | Fired 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) => ReactNode | No | Custom layout render function |
onContextMenu | (e: React.MouseEvent) => void | No | Right-click handler |
onOpenFile | (file: File) => void | No | File open handler (enables drag-drop) |
isActive | boolean | No | Tab isolation -- disable global listeners when hidden (default: true) |
verifying | boolean | No | True while verification is in progress (controls VerificationFloater) |
CoreViewerHandle
Ref handle exposed by the <CoreViewer> component.
interface CoreViewerHandle {
scrollToPage(n: number): void
getStore(): ViewerStore
}CoreViewerSlots
Layout slot objects passed to the renderLayout callback for full custom layout control.
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).
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.
function createViewerStore(overrides?: Partial<ViewerStoreState>): ViewerStoreExample:
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.
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.
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.
function downloadPdf(store: ViewerStore): voidrotateCW(store)
Rotate the document clockwise by 90 degrees.
function rotateCW(store: ViewerStore): voidrotateCCW(store)
Rotate the document counter-clockwise by 90 degrees.
function rotateCCW(store: ViewerStore): voidtoggleFullscreen(store, element?)
Toggle fullscreen on the given element (falls back to document root).
function toggleFullscreen(store: ViewerStore, element?: HTMLElement | null): voidPlugin 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.
function resolvePlugins(plugins: ViewerPlugin[]): ViewerPlugin[]collectToolbarSlots(plugins)
Merge toolbar slot contributions from all plugins, then apply any transformToolbarSlots transforms.
function collectToolbarSlots(plugins: ViewerPlugin[]): ToolbarSlotscollectSidebarTabs(plugins)
Collect sidebar tab definitions from all plugins, sorted by order.
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
interface ZoomPluginApi {
zoomIn(): void
zoomOut(): void
zoomTo(scale: number): void
setFitMode(mode: 'none' | 'width' | 'page'): void
}PageNavigationPluginApi
interface PageNavigationPluginApi {
goToPage(n: number): void
goToPreviousPage(): void
goToNextPage(): void
goToFirstPage(): void
goToLastPage(): void
}RotationPluginApi
interface RotationPluginApi {
rotateCW(): void
rotateCCW(): void
setRotation(r: 0 | 90 | 180 | 270): void
}SearchPluginApi
interface SearchPluginApi {
open(): void
close(): void
toggle(): void
}PrintPluginApi
interface PrintPluginApi {
print(): void
}DownloadPluginApi
interface DownloadPluginApi {
download(): void
}ThemePluginApi
interface ThemePluginApi {
toggleTheme(): void
setTheme(mode: 'light' | 'dark'): void
getTheme(): 'light' | 'dark'
}FullscreenPluginApi
interface FullscreenPluginApi {
enterFullscreen(): void
exitFullscreen(): void
toggleFullscreen(): void
}SelectionPluginApi
interface SelectionPluginApi {
setCursorTool(tool: 'select' | 'hand'): void
toggleHand(): void
}ScrollModePluginApi
interface ScrollModePluginApi {
setScrollMode(mode: 'vertical' | 'horizontal' | 'page'): void
}SpreadModePluginApi
interface SpreadModePluginApi {
setSpreadMode(mode: 'none' | 'odd' | 'even'): void
}SignaturePluginApi
interface SignaturePluginApi {
openPanel(): void
closePanel(): void
togglePanel(): void
}SidebarPluginApi
interface SidebarPluginApi {
open(tabId?: string): void
close(): void
toggle(tabId?: string): void
setTab(tabId: string): void
}AccessibilityPluginApi
interface AccessibilityPluginApi {
setFontScale(scale: 'compact' | 'default' | 'large' | 'extra-large'): void
getFontScale(): 'compact' | 'default' | 'large' | 'extra-large'
}DefaultLayoutPluginOptions
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
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.
// 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:
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.
// 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.ReactNodeToolbar Components
<Toolbar>
Three-section grid layout toolbar (LEFT | CENTER | RIGHT) that renders named slots contributed by plugins.
function Toolbar(props: { slots: ToolbarSlots; store: ViewerStore }): React.ReactNode<ToolbarButton>
Shared toolbar button primitive with tooltip, active state, and badge support.
| Prop | Type | Required | Description |
|---|---|---|---|
icon | React.ReactNode | Yes | Button icon |
onClick | () => void | Yes | Click handler |
disabled | boolean | No | Disabled state |
title | string | No | Tooltip text |
shortcut | string | No | Keyboard shortcut hint in tooltip |
active | boolean | No | Active/pressed state |
badge | number | No | Notification badge count |
ariaExpanded | boolean | No | ARIA expanded state |
ariaHasPopup | boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | No | ARIA popup indicator |
<ToolbarDivider>
Visual separator line between toolbar button groups.
function ToolbarDivider(): React.ReactNodeToolbarPluginOptions
Options for the toolbar plugin. Allows transforming toolbar slots to add, remove, or reorder controls.
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:
| Locale | Language |
|---|---|
'en' | English (default) |
Additional locales ('fr', 'de', 'es', 'ar', 'ja', 'zh') can be registered via registerLocale().
Locale
type Locale = 'en' | 'fr' | 'de' | 'es' | 'ar' | 'ja' | 'zh' | stringTranslationStrings
Interface defining all translatable string keys. Keys are organized by category:
| Category | Key prefix | Example keys |
|---|---|---|
| Toolbar | toolbar.* | toolbar.openFile, toolbar.zoomIn, toolbar.print |
| Status | status.* | status.valid, status.invalid, status.warning |
| Signature panel | panel.* | panel.signatures, panel.noSignatures |
| Document | document.* | document.properties, document.metadata |
| Find bar | find.* | find.placeholder, find.noResults |
| Welcome | welcome.* | welcome.title, welcome.subtitle |
| Password | password.* | password.title, password.submit |
| Verification | verification.* | verification.checking, verification.complete |
| PAdES | pades.* | pades.B-B, pades.B-T, pades.B-LT, pades.B-LTA |
| General | general.* | general.close, general.cancel, general.ok |
t(key, locale?)
Translate a key. Falls back to English, then to the key itself.
function t(key: string, locale?: string): stringsetLocale(locale) / getLocale()
Set or get the current active locale.
function setLocale(locale: string): void
function getLocale(): stringregisterLocale(locale, strings)
Register a custom locale or override strings for an existing locale.
function registerLocale(locale: string, strings: Partial<TranslationStrings>): voidExample:
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.
function getAvailableLocales(): string[]