PDF Generation Template Editor
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
UI state is managed by Pinia, split across two stores. This guide describes the store architecture, the key state each holds, and how the apis/ layer interacts with them.
packages/webview/src/stores/index.js creates a single Pinia instance and exports setupStore(app) to install it. The stores follow a strict two-store separation (documented in stores/AGENTS.md):
Both stores are referenced by ~102 files across components/ and apis/.
modules/viewer.js (useViewerStore, ~1770 lines) Holds UI / view state. Highlights:
| Category | Fields |
|---|---|
| View / navigation | currentPage, scale, oldScale, newScale, zoomLevel (preset array), scrollMode, pageMode, pageLabels. |
| Theme / display | theme ('light'/'dark'), fullScreen, language, languages[]. |
| Tool mode | toolMode ('view' default), activeHand, activeStickNote, activeActiveMeasure. |
| Elements open/close | activeElements{} (boolean map keyed by DataElements.*), activeElementsTab{}, panelSpace{left,right}, openedPanelsNum{left,right}. |
| Disabled elements | disabledElements{} — { disabled, style } per element. |
| Toolbar definition | headers{} (per group), rightHeaders[], toolItems{}, documentEditorHeaders, toolbarGroup, activeHeaderGroup. |
| Signature config | signatureDialogTabs, signatureDialogProperties{}, enableSignatureTemplates, digitalSignature{}, selectedSignatureField, disableSignatureTool, electronicSignaturesList[], digitalSignaturesList[]. |
| Stamps | customStamps[], stampPanelTabs[], importStamps[]. |
| Compare | compareStatus, compareMode, showCompareTip. |
| Popups | textPopup[], cropPagePopup[], contentEditorPopup[], annotationPopup[], showAnnotationPopup, popoverChanged. |
| Form board | formBoardFold, formBoardPosition{}, enableFillForm, skipNoRequired, consecutiveType. |
| Misc flags | license, verified, readOnly, userAdmin, isDisabledHeader, downloading, upload, uploadLoading, customLoading, documentEditorSaveStatus, documentEditorSaveAsStatus, webviewerMode. |
| Fonts | customFonts[], fontSizes[]. |
| Panels config | genericPanels[], customModals[]. |
| Annotation flags | annotation{isAnnotationExport, isAnnotationImport}. |
openElement(dataElement, capability?) — sets activeElements[de]=true; closes sibling panels on the same side; on LEFT_PANEL toggles core.toggleSidebar(); on SEARCH_PANEL also opens LEFT_PANEL and switches its tab.closeElement / openElements / closeElements / toggleElement / resetPanels — variants. Closing LEFT_PANEL also calls core.webViewerPageMode('none') and closes SEARCH_PANEL.setActiveElementTab(dataElement, tab) — maps ThumbnailsButton → core.webViewerPageMode('thumbs'), OutlinesButton → 'outline'.setActiveToolMode(mode) — guards readOnly and mobile (blocks separation/measurement); closes context panels; calls core.setToolMode(mode).setToolbarGroup(value) — mobile guard for Separation/Measurement.disableElement / enableElement / disableElements / enableElements(de, key?) — toggle disabled flags.localStorage.dispatch(action) / getState(key) — explicitly the API-access channel; expose store actions/state to apis/.modules/document.js (useDocumentStore, ~600 lines) Holds document data + tool configuration. Highlights:
| Category | Fields |
|---|---|
| Document meta | totalPages, loadingProgress, annotationsCount, info, currentPdfData{}, fileHasPwd, pwd. |
| Annotations | annotations (shallowReactive), selected{}, selectedAnnotation, outlines[], activeOutlineId, searchResults[], activeSearchResult, layers[], selectedLayer. |
| Current tool | activeTool, markupTool (default HIGHLIGHT), shapeTool (default SQUARE). |
| Tool style presets | per-tool { color, opacity?, stroke? } (highlight, underline, squiggly, strikeout, square, arc, polygon, polyline, circle, arrow, line, ink, freetext, text, form fields, redaction, remove). |
| Property panel | propertyPanel{} — form-field/editor property model. |
| Compare | compareFiles{}, compareSettings{}, compareResult. |
| Signatures | signatures[], selectedSignature, trustedCertificateLists[], pkcs12, author, annotator, highlightLink, highlightForm, autoJumpNextSign, disableDigitalSignature, disableElectronicSignature. |
| Measure | measure{scale, precision}. |
| Document editor | documentEditor{operationList[], pageList[], selectedPageList[]}. |
| Undo/redo | canUndo{content, annotation}, canRedo{content, annotation}. |
setActiveToolColor(color) — writes this[activeTool].color and calls core.setTool(activeTool).setToolState(tool) — toggles off if same; otherwise looks up map[tool], calls core.setTool(mapTool.tool, mapTool.toolName), sets activeTool, and for form tools calls core.setInitProperty().setActiveToolColor / setPropertyPanel / setCurrentUser / setHighlightLink / setHighlightForm / setAutoJumpNextSign — push the value into core in addition to storing it.initAnnotations / setAnnotations(annotation, type) — manage the annotation array by page index.dispatch(action) / getState(key) — API access.apis/ interacts with the stores Each apis/*.js module is a factory (stores...) => (...args) => result. Two access patterns:
getActiveTool.js → store.getActiveTool.dispatch for actions: closeElement.js → store.dispatch('closeElement')(dataElement).Some APIs (openElement, closeElements, enableElements, disableElements, addPanel, getPanels, isElementOpen, getPassword) use dispatch/getState; others call getters directly. api_helpers/createEncapsulatedStore.js builds the encapsulated viewerStore / documentStore wrappers (exposing only dispatch/getState) used by the popup APIs, getPassword, and getPanels.
localStorage['language'] — selected language.localStorage['customStamps'], ['electronicSignatures'], ['digitalSignatures'] — stamp/signature lists.