API

KViewer

API reference for the KViewer component

KViewer is the main component for rendering a single PDF document with annotation editing, form fields, and search.

Props

PropTypeDefaultDescription
sourcestring | Uint8Array | objectrequiredPDF source: URL string, raw bytes, or pdfjs-dist document init params
textLayerbooleanfalseEnable text selection overlay and text-based annotation tools
userNamestringundefinedAuthor name attached to new annotations
stampsStampDefinition[]undefinedCustom stamp definitions for the stamp tool
signatureHandlersSignatureHandlersundefinedCallbacks for loading, saving, and deleting signatures
viewModeViewMode'fit-width'Initial fit mode: 'fit-width', 'fit-page', or 'fit-height'
zoomnumber1Initial zoom multiplier (0.25 to 2)
readonlybooleanfalseDisable all annotation and form editing
shapeDetectionbooleanfalseAuto-detect checkbox shapes and create interactive form fields
activebooleantrueWhether this viewer captures global keyboard shortcuts (used internally by KViewerTabs)
formEditModebooleanundefinedForm-edit mode toggle. Supports v-model:form-edit-mode. See Form-Edit Mode.
roleColorsRecord<string, string>undefinedMap from roleId → CSS color used to color-code form fields in form-edit mode. The host owns the role list; the viewer just consumes a flat lookup table.
activeRoleIdstring | nullundefinedRole id new field placements are auto-tagged with. Supports v-model:active-role-id.
scriptingbooleanfalseExecute embedded PDF JavaScript (field AA, calculate/format/validate, document/page Open). See Embedded JavaScript.
menuItemsViewerMenuItem[]undefinedExtra items appended to the default burger menu (after Download and the form-field-detection toggle). Ignored when the host supplies a custom #header slot. See Customization → Custom menu items.

Slots

SlotDefaultDescription
headerBuilt-in ViewerBar toolbarReplace the entire top toolbar
footerEmptyAdd content below the viewer

Default Header (ViewerBar)

The default header includes: menu (download), page settings (rotation, layout, fullscreen), zoom controls, hand tool, marquee tool, page info, search, tool properties (color, stroke), drawing tools, and action tools (undo/redo/eraser).

Methods

Access these through a template ref:

<template>
  <KViewer ref="viewer" :source="pdfUrl" />
</template>

<script setup lang="ts">
const viewer = ref()
</script>

getAnnotations()

Returns all current annotations as a serializable array.

const annotations: IAnnotationStore[] = viewer.value?.getAnnotations()

importAnnotations(annotations, options?)

Restores previously saved annotations.

const result = await viewer.value?.importAnnotations(annotations, {
  mode: 'replace', // 'replace' | 'merge'
})
// result: { loaded: number, skipped: number }
OptionTypeDefaultDescription
mode'replace' | 'merge''replace'replace clears existing annotations first. merge adds alongside existing, skipping collisions.

exportPdf(options?)

Exports the PDF with annotations as a Uint8Array.

const bytes = await viewer.value?.exportPdf({
  flatten: true,
  download: false,
  preserveOriginalAnnotations: false,
})

See ExportPdfOptions for all options.

getFormFieldValues()

Returns all form field values.

const fields: FormFieldValue[] = viewer.value?.getFormFieldValues()

setFormFieldValue(fieldName, value)

Sets a form field value by field name.

viewer.value?.setFormFieldValue('email', 'user@example.com')
viewer.value?.setFormFieldValue('agree_terms', true)

addFormField(payload)

Adds a new form field programmatically. Returns the created FormFieldDefinition. The new field is exported into the PDF on exportPdf() like any field placed via the placement tool.

const def = viewer.value?.addFormField({
  pageNumber: 1,
  fieldType: 'text',
  rect: [50, 700, 250, 720],
  fieldName: 'firstName',
  required: true,
})

The rect is in PDF user-space coordinates with a bottom-left origin: [x1, y1, x2, y2]. fieldName is auto-generated when omitted; multiple widgets that share a fieldName (and fieldType) act as one PDF field — values mirror across them on edit, and radios with the same fieldName form one option group.

See AddFormFieldPayload for all properties.

updateFormField(id, patch)

Patches a form field by id. Accepts a partial FormFieldDefinition — typically rect, fieldName, readOnly, required, or any type-specific prop.

viewer.value?.updateFormField(def.id, { rect: [60, 700, 260, 720] })
viewer.value?.updateFormField(def.id, { readOnly: true })

removeFormField(id)

Removes a form field by id and drops its value.

viewer.value?.removeFormField(def.id)

getFormFields()

Returns all form-field definitions across the document (parsed from the source PDF, auto-detected, and programmatically/UI placed), flattened across pages.

const defs: FormFieldDefinition[] = viewer.value?.getFormFields()

formEditMode

Reactive Ref<boolean> for the current form-edit-mode state. Read with .value. See Form-Edit Mode.

const isEditing = viewer.value?.formEditMode.value

setFormEditMode(enabled)

Programmatically enter or leave form-edit mode.

viewer.value?.setFormEditMode(true)

toggleFormEditMode()

Flips form-edit mode. Returns the new state.

const next = viewer.value?.toggleFormEditMode()

getKonvaCanvasState()

Returns the raw Konva canvas state for each page (page number to serialized Konva JSON).

const state: Record<number, string> = viewer.value?.getKonvaCanvasState()

Usage Example

pages/editor.vue
<template>
  <div class="h-screen">
    <KViewer
      ref="viewer"
      :source="pdfUrl"
      text-layer
      user-name="Jane Doe"
      :stamps="stamps"
      :signature-handlers="signatureHandlers"
    />
  </div>
</template>

<script setup lang="ts">
const viewer = ref()
const pdfUrl = '/documents/contract.pdf'

const stamps = [
  { id: 'approved', name: 'Approved', imageUrl: '/stamps/approved.svg', width: 48, height: 48 },
]

const signatureHandlers = {
  onLoad: () => fetch('/api/signatures').then(r => r.json()),
  onSave: (imageUrl: string) => fetch('/api/signatures', {
    method: 'POST',
    body: JSON.stringify({ imageUrl }),
    headers: { 'Content-Type': 'application/json' },
  }).then(r => r.json()),
  onDelete: (id: string) => fetch(`/api/signatures/${id}`, { method: 'DELETE' }).then(() => {}),
}
</script>
Copyright © 2026