Tools
Which tools the viewer offers. Set a tool to false and it is gone: not on the toolbar, not in the selection bar, and viewer.activateTool() refuses it with INVALID_ARGUMENT. Absent means on — within the mode: true cannot add a tool the mode does not offer (see SDKMode). Select, Pan and Search are there in every mode unless set to false. Five tools — sign, editText, stamp, image and erase — also take an object for their own settings; true is the same as {}.
Each tool also needs its license feature: the drawing, mark-up, Sign, Image, Stamp, Link, Note, Text box and Erase tools need annotations, Edit Text needs edit-text, Add Text needs add-text, Manage Pages needs edit-pages and Security needs export. Select, Pan and Search need no feature. Without any feature a valid license still opens and renders documents, navigates, zooms, searches from the toolbar and undoes; nothing that changes the document is in that list.
Example
new PDFViewer(container, doc, { tools: { stamp: { builtIn: true, custom: [{ label: 'Logo', url: '/stamps/logo.png' }] }, sign: { draw: true, type: false, upload: false }, image: { maxBytes: 2 * 1024 * 1024, types: ['image/png', 'image/jpeg'] }, erase: { minSize: 4, maxSize: 32, defaultSize: 12 }, link: false, security: false, }, });
Options 45
false. Needs no license feature. It is the resting tool by default (see defaultTool); selectText: false with a Select rest leaves no tool active.tools: { selectText: false }
false. Needs no license feature.false. Needs no license feature from the toolbar; the selection bar's Search for this also needs a license that lets the words leave the viewer (the extract feature, or a production license's clean output).annotations license feature.annotations license feature. The selection bar's Highlight, Comment, Underline, Squiggly underline, Strikethrough and Black out follow it (Comment also needs the Comments panel, editable).annotations license feature. The selection bar's Add a note follows it.annotations license feature (new text written into the page as page content is addText, which is add-text).annotations license feature.annotations license feature.annotations license feature.annotations license feature.annotations license feature.annotations license feature.annotations license feature.annotations license feature. check, cross and dot are tools of their own, so a host offers the three, two or none; the Marks menu goes with its last member.annotations license feature.annotations license feature.annotations license feature. Takes an EraseConfig object (or true, the same as {}) for the brush sizes, in points. A minSize, maxSize or defaultSize that is not a positive number keeps its default. A maxSize below minSize is raised to it, and a defaultSize outside them is brought inside; each correction is reported with a console warning.tools: { erase: { minSize: 4, maxSize: 32, defaultSize: 12 } }
minSize is raised to it.minSize–maxSize is brought inside.edit-text license feature (opening or retyping a block from code, through viewer.tools.editText, also needs extract). Takes an EditTextConfig object; passing true is the same as {}. See EditTextToolApi for the programmatic side.// One block per paragraph is the default and the recommended grouping: nothing to set. tools: { editText: true }
How text is grouped into editable blocks. Keep the default, 'paragraphs': it is what Edit Text is built around. It makes one block per paragraph: the consecutive lines of one column that share leading and face are selected, moved and edited together, while columns, bullets, headings, table rows and lone numbers stay apart; a tagged document's own paragraph elements settle the grouping where it has them. Typing inside a paragraph reflows it within its box: words flow onto the next line and back, Enter starts a new line, every word keeps its own font, size and color, and a changed line keeps the paragraph's alignment, justified spacing included.
'rows' is an alternative, not an improvement: it makes one block per visual row, split where a gap reads as a column boundary, so each line of a paragraph is its own block and is selected, moved and edited on its own.
'paragraphs'Default, and recommended. One block per paragraph; typing reflows the paragraph within its box.'rows'One block per visual row, split where a gap reads as a column boundary; a paragraph's lines are edited one at a time.
add-text license feature (the Text box tool, a comment on top of the page, is freeText under annotations).Signature tool. Needs the annotations license feature (signing a form's signature field needs forms). Sign is also offered in 'form-fill' mode, for your own button. The same dialog opens from the Sign tool and from a form's signature fields, so tools.sign shapes both. true is the same as {}: every tab, the built-in faces. With one tab left the dialog shows no tab strip. With every tab off there is no way to make a signature: the Sign tool is hidden and signature fields are read-only. tools.sign: false only hides the tool — form signature fields still open the full dialog.
A signature made in a form's signature field is saved as that field's appearance, cropped to its ink so it fills the field: every reader shows it in the field and prints it, the export's flatten locks it into the page with the other fields, and the field stays a signature field. It is an electronic signature, not a digital one — nothing is written as the field's signature value, so the file claims no digital signature, and a digital ID applied later in another application replaces the picture. The SDK never draws over a field that holds a digital signature, nor into a read-only or hidden one. A field that already shows a signature (saved by the SDK or another application) shows it as the page draws it, without the "Sign here" prompt, and can be signed again; one that holds a digital signature cannot (FormFieldInfo.signature). To replace the dialog entirely, see callbacks.onSignatureRequest.
import { SIGNATURE_FONTS } from '@kernstra/pdf-web-sdk'; tools: { sign: { upload: false, fonts: [...SIGNATURE_FONTS, { family: "'Acme Script', cursive", label: 'Acme' }], }, }
SignatureFont is { family, label }: family a CSS font-family value — load the face yourself (@font-face) — and label the name shown beside the preview. fonts replaces the Type tab's faces, in order; an empty list keeps the default. The built-in faces' names ("Standard", "Script", …) follow the viewer's language when you pass the SIGNATURE_FONTS objects themselves — spread the constant; a face you describe yourself shows the label you gave it.ColorList is a list of hex strings or { color, label } color options (see Annotations).savedSignaturesChanged event gives you and pass it back here. The list is shared by every viewer on the page. See What you can replace.Fetch the Type tab's script faces from Google Fonts. Beside its plain Standard face, the Type tab offers four script faces (Dancing Script, Great Vibes, Pacifico, Sacramento). By default they are not fetched: each renders in a handwriting face the operating system ships (Snell Roundhand, Apple Chancery, Marker Felt and Savoye on a Mac; Segoe Script, Lucida Handwriting, Segoe Print and Lucida Calligraphy on Windows, or Office's Edwardian Script and Monotype Corsiva where they are installed), and the dialog makes no network request, which keeps the SDK's no-Google-Fonts guarantee intact. Set it where a request to Google is acceptable to you and your users, and add https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src. Either way the dialog never waits on the font host; faces that have not arrived by the time a signature is placed fall back to the system face for that signature.
It is read from tools.sign as an object: with tools.sign: false the faces stay off for a form's signature fields too. To hide the tool and keep them, leave tools.sign on and drop the tool from toolbar.groups.
tools: { sign: { webFonts: true } }
annotations license feature. Takes an ImageConfig object (or true, the same as {}). types narrows what the Image tool accepts — the picker's file filter, its fine print ("PNG or JPEG · up to 2 MB") and the check on a chosen or supplied file all follow it.tools: { image: { maxBytes: 2 * 1024 * 1024, types: ['image/png', 'image/jpeg'] } }
Stamp tool. Needs the annotations license feature. Takes a StampConfig object (or true, the same as {}). With builtIn and builder off and neither custom nor a valid preset there is nothing to place, and the Stamp tool is hidden.
A picture stamp is kept as a PNG data: URL, and one lifted from a page is part of that document — so whatever stores the list holds a copy of it. A region is lifted with at most two megapixels (a seal-sized one at 432 dpi): a lift of a whole scanned page can take a few megabytes, past what localStorage holds in some browsers. Size the store for it, and keep the list for the session only where documents are confidential. A kept stamp larger than a PDF page (14,400 points a side) or a wording longer than 32 characters is skipped when restored.
// Your own wording stamps instead of the English set tools: { stamp: { builtIn: false, presets: [ { label: 'GENEHMIGT', color: '#2E7D32' }, { label: 'EINGANG', color: '#C62828', dated: true, border: 'ribbon' }, ], }, }
builtIn: false, presets are listed alone.builder: false takes "New stamp" and the stamps made with it off the picker.data: URL whose header claims a raster too large to decode (over 64 million pixels, or a side over 16384 px) is left out with a console warning. A stamp image url on another origin needs that origin in connect-src or img-src.tools: { stamp: { builtIn: true, custom: [{ label: 'Logo', url: '/stamps/logo.png' }] } }
dated one under "With today's date"), or alone with builtIn: false. They cannot be removed from the picker. A StampPreset is { label, color?, dated?, border? }: label the wording (e.g. 'PAID', 'BEZAHLT'), color a hex ink (default: the first of inks), dated adds the placing date under the wording (default false), border is 'boxed' (default), 'ribbon' or 'plain'. A label is trimmed; one left empty is skipped with a console warning, as is one whose color is not a hex color (only a preset with no color at all takes the first ink). #rgb is expanded to #RRGGBB.ColorList is a list of hex strings or color options (see Annotations).userStampsChanged event gives you and pass it back here. At most eight are kept, shared by every viewer on the page. See What you can replace.annotations license feature. The links already written into the document are configured under Links.edit-pages feature. It opens only when the document can be saved for its Cancel to go back to; otherwise the viewer reports INVALID_STATE and it stays closed. Page editing from the thumbnails (rotate, move, duplicate, delete) follows managePages the same way, so it too needs edit-pages. Extract pages inside Manage Pages also needs export.export feature: protection is part of the saved file. Without export there is no owner-password prompt: unlock a restricted document with doc.security.unlockOwnerPermissions(), which needs no feature.Notes
The selection bar that appears over selected text follows the same map: Highlight, Comment, Underline, Squiggly underline, Strikethrough and Black out need textHighlight (Comment also needs the Comments panel, editable), Add a note needs note, Search for this needs search; Copy and Search for this also need a license that lets the words leave the viewer (see the resting tool). In 'view-only' and 'form-fill', which offer no authoring tools, it offers Copy and Search for this.
A group whose every tool is disabled through tools renders no tab and no cluster on the toolbar — tools: { sign: false, image: false, stamp: false, link: false } makes the Insert tab disappear entirely. Use toolbar.groups to drop a group from the toolbar while leaving its tools available to viewer.activateTool().
Image, Sign and Black out write into the page itself; Erase can remove the page's own content.