PDF Viewer
Inline PDF document viewer powered by Mozilla pdf.js. Renders multi-page documents on a canvas with page navigation, zoom controls, optional text search, and a one-click download shortcut. No npm build step or API key required.
Installation
dotnet add package Lumeo.PdfViewer
One-time app setup (AddLumeo(), CSS & JS) is covered in the
installation guide.
Usage
@using Lumeo <PdfViewer />
Lumeo.PdfViewer — install it alongside the core Lumeo
package. pdf.js is loaded on demand from jsDelivr the first time a PdfViewer
mounts; no npm build step is required for consumers.
When to Use
- Embedding contracts, invoices, or reports inline in a Blazor page without leaving the app
- Document preview surfaces where the browser's built-in viewer behaves inconsistently across platforms
- Read-only flows that benefit from page navigation, zoom, and full-text search (e.g. audit trails, e-signatures)
- Dashboards that surface generated PDF reports alongside live data
- Admin panels that need to display uploaded user documents with a controlled, branded UI
Self-hosting pdf.js
By default the viewer lazy-loads pdf.js + its worker from jsDelivr the
first time a PdfViewer mounts. That's the right tradeoff for low-traffic
apps and demos, but it doesn't work behind a strict CSP, on an air-gapped intranet,
or in compliance scenarios where every third-party script call is a no-go.
The Lumeo CLI ships a one-shot installer that vendors pdf.js into
wwwroot/lib/lumeo-vendor/ and wires up
window.lumeoCdn so the runtime loads from your own origin instead of
the CDN:
# 1. Install the Lumeo CLI as a global dotnet tool $ dotnet tool install -g Lumeo.Cli # 2. Vendor pdf.js into wwwroot/lib/lumeo-vendor/ and write the bootstrap $ lumeo deps install --lib pdfjs --write-bootstrap # 3. Include the bootstrap before _content/Lumeo.PdfViewer/js/* in index.html # <script src="js/lumeo-cdn-init.js"></script>
See CDN dependencies for the full list
of self-hostable libraries and the window.lumeoCdn override surface.
For more granular control (custom URL, integrity hash, alternative CDN) you can
set window.lumeoCdn = { pdfJs: "/my/cdn/pdf.min.mjs", pdfJsWorker: "/my/cdn/pdf.worker.min.mjs" };
before the first PdfViewer mounts.
API Reference
PdfViewer
| Prop | Type | Default | Description |
|---|---|---|---|
| Src | string? | null | PDF URL or data: URI. Marked [EditorRequired] — must be provided. Changing this value reloads the document. |
| Page | int | 1 | 1-based current page index. Two-way bindable via @bind-Page. |
| PageChanged | EventCallback<int> | — | Fires with the new page number whenever the user navigates (toolbar buttons, keyboard, or direct input). |
| Zoom | double | 1.0 | Render scale clamped to [0.5, 4.0]. Two-way bindable via @bind-Zoom. Steps of 0.25 per toolbar click. |
| ZoomChanged | EventCallback<double> | — | Fires with the new scale factor whenever the user changes zoom. |
| ShowToolbar | bool | true | Show the entire toolbar row. Set false for a chromeless embed driven by parent state. |
| ShowPageNav | bool | true | Show the prev / next buttons and editable page number input in the toolbar. |
| ShowZoomControls | bool | true | Show the ± zoom buttons and percentage label in the toolbar. |
| ShowDownload | bool | true | Show the download anchor linking to Src. Hide when the document should not be extractable. |
| ShowSearch | bool | false | Show the full-text search input. Returns the total match count across all pages. |
| HighlightColor | string | "yellow" | CSS color string for search match highlights. Accepts any valid CSS color: named (yellow), hex (#facc15), rgb/hsl. Active matches render at 70% opacity; inactive at 45%, mixed against transparent via color-mix. |
| OnLoaded | EventCallback<int> | — | Fires once with the total page count after the PDF finishes loading. Use to initialise parent state. |
| OnPageChanged | EventCallback<int> | — | Non-binding alternative to PageChanged. Useful when you only need a side-effect callback without two-way binding. |
| OnError | EventCallback<string> | — | Fires when the PDF fails to load or render (CDN unreachable, malformed PDF, worker init failure). Receives the exception message. The built-in EmptyState fallback still renders inside the viewer. |
| Class | string? | null | Extra CSS classes applied to the root container. Use to set a fixed height (e.g. h-[600px]) or override border radius. |
Keyboard shortcuts
Focus the canvas area (click once or Tab to it) then use:
| Key | Action |
|---|---|
| PageDown / ArrowRight | Next page |
| PageUp / ArrowLeft | Previous page |
| + / = | Zoom in (+25%) |
| - / _ | Zoom out (−25%) |
role="document"
with aria-label="PDF document" and tabindex="0" so it
receives keyboard focus. The loading overlay uses role="status" with
aria-live="polite". Search match counts are announced via aria-live.