CloudPDF
DocsPricing
Start building

Plugins

The viewer is the headless plugins with an interface built on top. Every feature is a plugin: search is the search plugin, the comments panel uses the annotation plugin’s comments. So everything the headless docs say about a plugin is true inside the viewer, with the same names:

  • its settings go in plugins, under its name;
  • its API is viewer.get(name);
  • its hooks work in your own components inside the viewer.

Every plugin#

NameWhat it doesHeadless page
stageScrolling, zoom, page layout and navigationScroll, zoom & layout
thumbnailsThe thumbnails panel: a second stage over the same documentTwo views of one document
renderSharp pages at every zoomRendering
linkLinks to pages and websitesLinks
selectionSelecting and copying textSelecting & copying
searchFinding textSearch
annotationAnnotations, their tools, and commentsAnnotations
stampStamp librariesStamps
measurementMeasuring at a drawing’s scaleMeasurements
redactionRemoving content for goodRedaction
formFilling and building formsFilling forms
signatureSigning and checking signaturesSignatures
pageEditRotating, moving, inserting and deleting pagesOrganizing pages
metadataA document’s title, author and your own fieldsMetadata
fontsThe fonts a document can be written in, and drawing its text in a browserFonts
outlineThe outline (bookmarks): following, adding, renaming, moving and deleting itemsOutline
attachmentThe files inside the PDF: listing, saving, attaching and removing themAttachments
actionsWhat a PDF does by itself: buttons, scripts, printingActions & scripts
documentsOpening, closing, tabs and savingOpening documents
interactionThe active tool, cursors and touchTools, cursors & touch
commandsEvery button’s action, and shortcutsCommands & shortcuts
shellWhich panels and menus are openPanels & dialogs
i18nThe languageTranslations

Settings#

plugins takes each plugin’s settings by its name, exactly as its page lists them under Settings:

{
  plugins: {
    stage: { spread: 'odd', zoom: { mode: 'fit-width' } },
    selection: { color: 'rgb(124 58 237 / 0.3)' },
    actions: { javascript: { enabled: false } },
  },
}

Loading live preview…

settings.vue
<script setup lang="ts">
import { PDFViewer, type ViewerConfig } from '@cloudpdf/viewer-vue';

const links = { grant: 'shr_xs-9Y5qwuYrJ2BKtWzuo_2xy' };

const config: ViewerConfig = {
  plugins: {
    stage: { spread: 'odd', zoom: { mode: 'fit-width' } },
    selection: { color: 'rgb(124 58 237 / 0.3)' },
  },
};
</script>

<template>
  <PDFViewer :src="links" v-bind="config" style="height: 100%" />
</template>

Try it: the brand guidelines open two pages at a time, at the width of the frame. Select some text: the selection is purple.

Change them while the viewer runs, and go back to what you set:

viewer.get('stage').updateSettings({ layout: 'horizontal' });
viewer.get('stage').resetSettings();

A change reaches every document, open or opened later, except for stage and thumbnails: their settings are each document’s own view of it. Changed from code, they change the active document, or the one you name with viewer.forDocument(id), and a document that opens later starts from what plugins says.

A few plugins take settings that only the viewer has, such as the standard stamps of plugins.stamp. The feature pages list them: Annotations, Forms & signatures.

In your components#

Your own components inside the viewer can use every headless hook. Install the headless adapter for your framework next to the viewer (@embedpdf/react, @embedpdf/vue, @embedpdf/svelte or @embedpdf/angular, the same version), and use its hooks as the headless docs show them:

hooks.vue
<script setup lang="ts">
import { useSearch, useSearchState } from '@embedpdf/vue/search';

// A search box of your own, in the viewer's header. The composables are the headless ones.
const search = useSearch();
const { hitCount, activeHitIndex } = useSearchState();
</script>

<template>
  <form @submit.prevent>
    <input type="search" placeholder="Search" @input="search.search({ text: ($event.target as HTMLInputElement).value })" />
    <span v-if="hitCount > 0">{{ activeHitIndex + 1 }} of {{ hitCount }}</span>
    <button type="button" @click="search.nextHit()">Next</button>
  </form>
</template>

Put HeaderSearch in the viewer’s header region, and it searches the open document. The hooks find the viewer they’re in, and the document that’s active, by themselves.

A plugin of your own#

A plugin you wrote for headless works in the viewer too. Give it a name in plugins:

import { analyticsPlugin } from './analytics-plugin';
 
export const config = {
  plugins: {
    analytics: analyticsPlugin({ endpoint: '/api/events' }),
  },
};

viewer.get('analytics') is then its API, its commands can go in the layout, and your components can use its hooks. See How it works in the headless docs for writing one.

When to build your own interface#

The viewer lets you move, add and replace everything around the pages. Go headless when you need to change what it doesn’t open up:

  • the look of its own buttons, menus and panels beyond theming;
  • an arrangement that isn’t bars, panels and regions;
  • what’s drawn on the pages themselves, such as annotations drawn your own way.

Everything on this page carries over: the same plugins, settings, names and hooks.