Editor
Editor
Section titled “Editor”Scope: React viewer toolkit — editor layer (@scaryterry/pdfium/react/editor).
The editor is still additive, but the flagship path is no longer a hand-assembled stack. Start with PDFEditor, then drop to lower-level editor pieces only when you need to replace part of the shipped shell.
The flagship Vite /editor route now uses this contract directly:
PDFEditorkeepsPDFVieweras the document frame.- The shipped document/view top bar, left editing tool rail, editor overlay, editor-aware annotations panel, and dedicated redactions panel are wired for you.
- Lower-level editor exports remain public for partial replacement, not mandatory setup.
Canonical Path
Section titled “Canonical Path”import { PDFEditor } from '@scaryterry/pdfium/react/editor';
export function EditorScreen() { return <PDFEditor />;}PDFEditor defaults to the flagship editor posture:
- panels:
thumbnails,annotations, andredactions - initial panel:
annotations - initial panel visibility:
'desktop-only'so narrow viewports start with the document primary showAnnotations={false}so the passive annotation layer does not compete with interactive editingbufferPages={2}for steadier editing interactions
The shipped shell also reuses the same toolbar, panel, and dialog theme tokens as PDFViewer, so editor chrome themes through the standard --pdfium-toolbar-*, --pdfium-panel-*, and --pdfium-dialog-* variables instead of a separate editor-only skin.
The default shell is intentionally split by task:
- top bar: page navigation, zoom, search, undo/redo, save, and secondary view actions under
More - left tool rail: selection, text, draw, shapes, stamp, and redact
- active-tool action bar: on-canvas defaults for the current creation tool, plus a quick return to select mode. It docks automatically on coarse-pointer layouts instead of covering the page.
- free-text editing: free-text annotations can be re-edited inline after creation from the selected-object bar, and the inline editor keeps typing isolated from viewer/editor shortcuts so text entry does not leak into document commands.
- free-text typography: the shipped text defaults and selected-text style surfaces expose a constrained standard-font set (
Helvetica,Times, andCourierfamilies with bold/italic variants), plus size and colour, so free-text stays portable through save/reload instead of relying on arbitrary local fonts. - text selection bubble: highlight, underline, and strikeout actions appear when the user selects real page text
- selected-annotation action bar: on-canvas style, duplicate, overlap picking, arrange, and delete actions stay attached to the current object instead of a hidden inspector section. It docks automatically on coarse-pointer layouts and for genuinely small selected objects so overlap-heavy editing stays readable.
- left panels: thumbnails, a page-local annotations workspace for selection-aware editing, and a dedicated redactions workspace for review/apply
What PDFEditor Wires
Section titled “What PDFEditor Wires”EditorProviderfor tool state, selection, dirty tracking, and history- a shipped document/view command bar that keeps navigation and save visible without mixing in every editing mode
- a shipped left tool rail so editing tools no longer compete with document navigation in the top bar
- a shipped on-canvas active-tool surface so creation defaults stay near the document instead of buried in side chrome
renderDefaultEditorPageOverlayas the interactive page-overlay pathDefaultEditorAnnotationsPanelinside the leftannotationspanel so selection-aware editing stays in the main viewer shellDefaultEditorRedactionsPanelinside a dedicatedredactionspanel so document-scope redaction review does not pollute page-local annotation inspection
That means the canonical editor route no longer needs local provider plumbing, a local overlay bridge, or a second inspector column.
How To Extend It
Section titled “How To Extend It”Use PDFEditor first, then customise one seam at a time:
childrenappends extra content after the shipped top-bar document commands.toolbarPropscustomises the shipped top-bar shell.toolbarControlsPropscustomises save behaviour for the shipped top-bar save path.classNamesextends the viewer shell contract withtoolRailandpageChrome, so you can style the shipped editor-only chrome without replacing it.toolRailPropsandpageChromePropsforward lightweightclassName/stylehooks to the shipped tool rail and active-tool bar.renderToolbar,renderSearch,renderToolRail,renderPageChrome, andrenderPanelSidebarlet you replace the shipped editor shell surfaces one seam at a time while keepingPDFEditoras the surrounding frame.panelsreplaces or extends the left-panel set. If you keep the built-in'annotations'entry,PDFEditorswaps in the shipped editor-aware annotations panel automatically. AddcreateDefaultEditorRedactionsPanelEntry()when you want the shipped redactions workflow in a manual composition.sidebar={<MySidebar />}adds an explicit secondary sidebar only when you intentionally want one.sidebarPropsopts intoDefaultEditorSidebarfor advanced split-shell layouts. It is not part of the default editor shell.renderPageOverlayadds extra overlay content beneath the shipped editor overlay.editorProviderPropscustomisesEditorProviderwithout rebuilding the shell.
If you need to replace the overlay stack, own the layout outright, or split the sidebar across multiple regions, drop to the lower-level composition. That lower-level path stays public, but it is intentionally more manual than the shipped PDFEditor shell:
If you only want to replace one shell region, prefer the render slots first. They keep the default frame, provider, and viewer/editor synchronisation intact:
<PDFEditor classNames={{ toolRail: 'my-editor-tool-rail', pageChrome: 'my-editor-page-chrome' }} toolRailProps={{ style: { backdropFilter: 'blur(24px)' } }} renderPageChrome={() => <MyCanvasChrome />}/>import { DefaultToolbar, DefaultToolbarDownloadButton, PDFViewer } from '@scaryterry/pdfium/react';import { DefaultEditorAnnotationsPanel, DefaultEditorRedactionsPanel, DefaultEditorToolbarControls, EditorProvider, createDefaultEditorAnnotationsPanelEntry, createDefaultEditorRedactionsPanelEntry, renderDefaultEditorPageOverlay,} from '@scaryterry/pdfium/react/editor';
export function CustomEditorScreen() { return ( <EditorProvider> <PDFViewer panels={['thumbnails', createDefaultEditorAnnotationsPanelEntry(), createDefaultEditorRedactionsPanelEntry()]} initialPanel="annotations" showAnnotations={false} bufferPages={2} renderPageOverlay={renderDefaultEditorPageOverlay} > <DefaultToolbar leadingChildren={<DefaultEditorToolbarControls />}> <DefaultToolbarDownloadButton /> </DefaultToolbar> </PDFViewer> </EditorProvider> );}Common Building Blocks
Section titled “Common Building Blocks”| Need | API | Notes |
|---|---|---|
| Canonical shipped editor route | PDFEditor | Fastest path to the flagship editor shell. |
| Live tool state and history | useEditor() | Reads the active tool, selection, dirty state, and undo/redo actions. |
| Viewer/editor mode sync | useEditorInteractionBridge() | Keeps pointer mode, text selection, and editor tools in sync. |
Viewer navigation outside PDFViewer | useEditorViewerNavigation() | Reads current page and page count from direct viewer context or the shipped editor bridge. |
| Shipped page-overlay renderer | renderDefaultEditorPageOverlay | Canonical renderPageOverlay helper for manual PDFViewer composition. |
| Shipped page-overlay component | DefaultEditorPageOverlay | Lower-level overlay component when you want to wrap or style the shipped renderer yourself. |
| Shipped editor annotations panel | DefaultEditorAnnotationsPanel | Left-panel annotations view that upgrades selection detail into mutable editor controls. |
| Shipped annotations panel entry | createDefaultEditorAnnotationsPanelEntry() | Drops the shipped editor-aware annotations panel into manual PDFViewer compositions. |
| Shipped redactions panel | DefaultEditorRedactionsPanel | Dedicated review/apply workspace for marked redactions with current-page actions and document-wide context. |
| Shipped redactions panel entry | createDefaultEditorRedactionsPanelEntry() | Drops the shipped redactions workflow into manual PDFViewer compositions. |
| Lower-level toolbar extension | DefaultEditorToolbarControls | Manual composition helper for custom PDFViewer + DefaultToolbar shells. Useful when you are intentionally not using PDFEditor. |
| Page overlay editing | EditorOverlay | Mount through renderPageOverlay; pass page geometry and current annotations. |
| Save workflow | useEditorSave(document) | Flushes pending commits, saves the document, and marks the session clean. |
| Optional split-shell sidebar | DefaultEditorSidebar | Advanced-only sidebar helper when you intentionally want a second column for custom layouts. |
| Selection-driven property editing | AnnotationPropertyPanel | Low-level selection editor when you want to own the annotation-resolution flow yourself. |
| Page insertion, movement, deletion | usePageManagement() + PageManagementPanel | Low-level page controls when you are prepared to design the surrounding UX yourself. |
| Cross-page redaction totals | useRedactionSummary(document) | Recomputes only pages whose revision changed, which is useful for custom editor status UI. |
Workflow Rules Worth Preserving
Section titled “Workflow Rules Worth Preserving”- Markup tools should stay text-selection-first. Let users select real text, then trigger highlight/underline/strikeout.
- Stack-order, overlap picking, and duplicate/delete actions should stay attached to the selected annotation itself, not buried inside the annotations workspace.
- Common colour and border changes should be reachable from quick presets before falling back to raw inputs.
- Free-text should stay truly editable after creation. Keep inline editing on the page surface and make sure keyboard input remains local to the text editor instead of triggering global document actions.
- Destructive redaction apply should be explicit and confirmed in UI. Marking happens from the tool/rail flow; review and apply should live in the dedicated redactions workspace, not the page-local annotations workspace.
- Save should stay disabled until the editor is dirty.
- Undo and redo should remain available on the main path, not hidden in a secondary panel.
- Editing tools should stay off the main document bar. Keep navigation/view commands in the top bar, editing modes in the left rail, and routine creation defaults near the canvas unless you have a very strong reason to collapse them together.
Keyboard UX Defaults
Section titled “Keyboard UX Defaults”The shipped editor path is designed to stay usable without a mouse:
Escapereturns active editor tools to the neutral pointer/select posture instead of leaving drawing tools sticky.Vreturns the editor to the neutral posture and synchronises the viewer’s built-in text-selection control.Ctrl/Cmd + ZandCtrl + Y/Ctrl/Cmd + Shift + Zdrive the shipped editor undo/redo history without requiring extra document listeners in user code.Ctrl/Cmd + Striggers the shipped save path inPDFEditor/DefaultEditorToolbarControls, so the public editor shell owns save instead of deferring to the browser.- Undo/redo shortcuts defer to native text editing when focus is inside inputs or contenteditable regions, so property editing and free-text editing keep their local editing affordances.
- The shipped toolbar, left annotations workspace, and viewer shell all use the shared PDFium focus-ring tokens, so replacing one surface should preserve the same visible focus language.
If you replace PDFEditor with manual composition, preserve those same rules unless you have a strong reason to change them.