# PdfViewer
**Also known as:** PdfReader, Pdf
## Description
BitPdfViewer is a native pure-C# pdf viewer for Blazor: it parses pdf files and paints their pages as plain HTML/CSS (or onto a canvas), with no browser plugin and no js library. It ships a full reading toolbar - navigation, zoom and fit modes, page layouts, rotation, find, thumbnails, bookmarks, attachments and layers, printing, download, presentation and fullscreen - and everything the toolbar does is on the public API too.
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| AllowDropFile | `bool` | false | Whether a pdf dropped onto the viewer opens in it. The dropped file goes through the same path as the toolbar's open-file button, so OnFileOpened and MaxOpenFileSize apply to it too. |
| BackgroundRendering | `bool` | false | Offloads document parsing and page rendering to a background thread so scrolling and navigation stay responsive while a complex page renders. Only has an effect when the runtime provides a spare thread (Blazor Server, or a Blazor WebAssembly app built with WasmEnableThreads); on the default single-threaded WebAssembly runtime it is a safe no-op. |
| Classes | `BitPdfViewerClassStyles?` | null | Custom CSS classes for the different parts of the viewer. |
| CursorTool | `BitPdfCursorTool` | BitPdfCursorTool.Select | What dragging on the document surface does: select text (the default) or pan the document, as the hand tool of a desktop viewer does. |
| CurrentPage | `int` | 1 | The focused page (1-based), two-way bindable. Reading it gives the page the reader is on; assigning it navigates there. Bound one way (without CurrentPageChanged) the page becomes the host's to control: the viewer then reports navigation through OnPageChanged but does not move the value itself. |
| DefaultSidebar | `BitPdfSidebar` | BitPdfSidebar.None | The side panel open when a document first loads. The panel can be changed afterwards from the toolbar or through the ShowSidebar method. |
| EmptyTemplate | `RenderFragment?` | null | Custom content shown in place of the pages while no document is loaded. Defaults to the NoDocument text. |
| EnableKeyboardShortcuts | `bool` | true | Whether the viewer handles keyboard shortcuts while it has focus: page navigation (n/j, p/k, PageUp/PageDown, Home/End, plus the arrow keys and Space while one page is shown at a time), zoom (Ctrl +, Ctrl -, Ctrl 0), rotation (r, Shift+r), find (Ctrl+F, Ctrl+G, Shift+Ctrl+G), print (Ctrl+P), download (Ctrl+S), presentation mode (Ctrl+Alt+P) and the sidebar (F4). Find, print and download follow ToolbarItems: leaving their control out of the toolbar leaves their shortcut out too. |
| ErrorTemplate | `RenderFragment<string>?` | null | Custom content shown in place of the pages when a document fails to load, with the message OnError receives. Announced as an alert, as the default message is. |
| Height | `string?` | null | The CSS height of the viewer (sets --bit-PdfViewer-height on the instance). When not set, the viewer height is responsive: capped at 780px and shrinking to fit the viewport on small screens. |
| InitialZoomMode | `BitPdfZoomMode` | BitPdfZoomMode.FitWidth | The initial zoom behavior. |
| LoadingTemplate | `RenderFragment?` | null | Custom content shown in place of the pages while a document is fetched and parsed. Defaults to a page-shaped placeholder; the loading bar shows either way. |
| MaxOpenFileSize | `long` | 67108864 | The largest file the toolbar's open-file button - and a drop, when AllowDropFile allows one - accepts, in bytes (64 MB by default). The whole file is read into memory, and on Blazor Server it also travels the circuit. |
| MaxZoom | `double` | 8 | The largest zoom factor the viewer allows (1 means 100%). |
| MaxRenderedPageCount | `int` | 24 | How many pages stay materialized in the DOM at once. Pages outside the window centered on the current one revert to placeholders and are re-rendered when scrolled back to, which is what keeps a long document from growing the DOM (and a Blazor Server circuit's memory) without bound. |
| MaxRenderedThumbnailCount | `int` | 40 | How many thumbnails stay materialized in the sidebar at once. A thumbnail fragment is as heavy as a full page, so this bounds the sidebar the way MaxRenderedPageCount bounds the document surface. |
| MinZoom | `double` | 0.1 | The smallest zoom factor the viewer allows (1 means 100%). |
| OnDocumentLoaded | `EventCallback` | | The callback for when a document has finished loading. |
| OnDownloading | `EventCallback<BitPdfDownloadArgs>` | | The callback raised before the document is downloaded - from the toolbar, Ctrl+S or the Download method - to rename the file or cancel the download. |
| OnError | `EventCallback<string>` | | The callback for when loading or rendering fails, with the error message. |
| OnPageChanged | `EventCallback<int>` | | The callback for when the focused page changes (with the 1-based page number). |
| OnFileOpened | `EventCallback<BitPdfSource>` | | The callback for when the reader picks a file with the toolbar's open-file button, with the source built from it. Handle it to drive Source yourself; when unset the viewer opens the file on its own. |
| OnPageRendered | `EventCallback<int>` | | The callback for when a page has been rendered into the document surface, with its 1-based page number. Lazy rendering means this is raised as the reader reaches a page, not once per page up front. |
| OnPasswordRequested | `Func<Task<string?>>?` | null | Invoked when an encrypted document needs a password. Return the password to retry, or null/empty to cancel. When unset, the viewer's own password dialog asks instead (see ShowPasswordPrompt). |
| OnPrinting | `EventCallback<BitPdfPrintArgs>` | | The callback raised before the document is printed - from the toolbar, Ctrl+P or a Print method - with the page range, to cancel the print. |
| OnProgress | `EventCallback<double>` | | The callback for the download progress of a URL source, as a fraction from 0 to 1. Only raised when the server declares a content length (which is also when the loading bar shows the progress); a chunked response has no total to report against. |
| OnRotationChanged | `EventCallback<int>` | | The callback for when the page rotation changes, with the new angle in degrees (0, 90, 180 or 270). |
| OnSidebarChanged | `EventCallback<BitPdfSidebar>` | | The callback for when the open side panel changes. |
| OnWarnings | `EventCallback<IReadOnlyList<string>>` | | The callback raised after a document loads with any non-fatal diagnostics (e.g. a damaged file whose cross-reference table had to be rebuilt). |
| OnZoomChanged | `EventCallback<double>` | | The callback for when the zoom factor changes (1 means 100%), whatever caused it: the toolbar, a fit mode, Ctrl+wheel or the public API. |
| RespectPermissions | `bool` | false | Whether the document's own user access permissions are enforced. With it set, a document that forbids printing or copying has the corresponding toolbar control disabled, Print and Download refuse, and its text cannot be selected. Off by default, as in every browser pdf viewer: the flags are advisory, not a security boundary. |
| RenderMode | `BitPdfRenderMode` | BitPdfRenderMode.Html | How page content is painted. Canvas replays a display list onto a per-page canvas, while Html (the default) renders prerenderable positioned DOM. |
| ScrollMode | `BitPdfScrollMode` | BitPdfScrollMode.Vertical | How the pages are laid out on the scrollable surface: stacked vertically (the default), side by side on one horizontally scrolling row, wrapped into rows that fill the width, or one page (or spread) at a time. |
| ShowPasswordPrompt | `bool` | true | Whether the viewer asks for the password of an encrypted document with a dialog of its own. Ignored when OnPasswordRequested is set, which takes over the asking. Set to false to let a password failure surface through OnError instead. |
| ShowToolbar | `bool` | true | Whether the toolbar is shown. |
| Source | `BitPdfSource?` | null | The document to display. |
| SpreadMode | `BitPdfSpreadMode` | BitPdfSpreadMode.None | How pages are paired into spreads, the way a printed book falls open. |
| Width | `string?` | null | The CSS width of the viewer (sets --bit-PdfViewer-width on the instance). When not set, the viewer fills the width its host gives it. |
| ZoomPresets | `IEnumerable<double>?` | null | The explicit zoom factors the toolbar's zoom dropdown offers (1 means 100%). Values outside MinZoom..MaxZoom are dropped. Defaults to 50%, 75%, 100%, 125%, 150%, 200%, 300% and 400%. |
| Styles | `BitPdfViewerClassStyles?` | null | Custom CSS styles for the different parts of the viewer. |
| TextCoalescing | `BitPdfTextCoalescing` | BitPdfTextCoalescing.Exact | How painted text is emitted. Compact merges same-line, same-style runs into one span per visual line (far fewer DOM nodes on per-glyph pdfs). |
| Texts | `BitPdfViewerTexts?` | null | The texts of the viewer UI. Defaults to English; assign an instance with the properties you want to override to localize the toolbar, the sidebars and the status messages. |
| ToolbarItems | `BitPdfToolbarItems` | BitPdfToolbarItems.All | Which controls the toolbar offers. Combine the flags to build a reduced toolbar (e.g. navigation and zoom only). |
| ToolbarStartTemplate | `RenderFragment<BitPdfViewer>?` | null | Custom content rendered at the start of the toolbar, before the built-in controls. The context is the viewer itself, so the content can drive it through its public API. |
| ToolbarEndTemplate | `RenderFragment<BitPdfViewer>?` | null | Custom content rendered at the end of the toolbar, after the built-in controls. The context is the viewer itself. |
| Rotation | `int` | 0 | The rotation applied to every page, in degrees, two-way bindable. Assigned values are normalized to the nearest quarter turn (0, 90, 180 or 270). |
| Zoom | `double` | 1 | The zoom factor (1 means 100%), two-way bindable. Assigning it switches the viewer to Custom zoom mode and clamps the value to MinZoom..MaxZoom. |
| ZoomStep | `double` | 1.2 | The multiplier applied by ZoomIn and ZoomOut (and by the toolbar's zoom buttons), i.e. 20% a step by default. |
| AriaLabel | `string?` | null | Gets or sets the accessible label for the component, used by assistive technologies. |
| Class | `string?` | null | Gets or sets the CSS class name(s) to apply to the rendered element. |
| Dir | `BitDir?` | null | Gets or sets the text directionality for the component's content. |
| Disabled | `bool` | false | Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction. |
| ForceAnimation | `bool` | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. |
| HtmlAttributes | `Dictionary<string, object>` | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. |
| Id | `string?` | null | Gets or sets the unique identifier for the component's root element. |
| Style | `string?` | null | Gets or sets the CSS style string to apply to the rendered element. |
| TabIndex | `string?` | null | Gets or sets the tab order index for the component when navigating with the keyboard. |
| Visibility | `BitVisibility` | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. |
## Public Members
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Attachments | `IReadOnlyList<BitPdfAttachment>` | | The files embedded in the document (the /EmbeddedFiles name tree plus any /FileAttachment annotation), empty when it carries none. |
| CurrentCursorTool | `BitPdfCursorTool` | | What dragging on the document surface currently does. |
| CurrentScrollMode | `BitPdfScrollMode` | | The current page layout on the scrollable surface. |
| CurrentSpreadMode | `BitPdfSpreadMode` | | The current spread pairing. |
| Document | `BitPdfDocument?` | | The parsed document model, or null when nothing is loaded. Exposes the full engine surface (catalog, pages, cross-reference table) for callers that need more than the viewer's own API. |
| FailedPages | `IReadOnlyList<int>` | | The 1-based numbers of the pages whose rendering failed, in ascending order. Such a page shows an error note in place of its content and is not retried; a reload, rotation or render-mode change gives every page a fresh attempt. |
| FileSize | `long` | | The size in bytes of the loaded document, or 0 when nothing is loaded. |
| FormFields | `IReadOnlyList<BitPdfFormField>` | | The interactive form fields (/AcroForm) of the loaded document as a flat list of name/type/value, or an empty list when there is no form. |
| HasAttachments | `bool` | | Whether the document carries any embedded file. |
| HasLayers | `bool` | | Whether the document declares any optional-content group (layer). |
| HasOutline | `bool` | | Whether the document exposes any bookmarks. |
| IsEncrypted | `bool` | | Whether the loaded document declares an encryption dictionary. |
| IsFullscreen | `bool` | | Whether the viewer currently fills the screen. |
| IsPresenting | `bool` | | Whether the viewer is in presentation mode: fullscreen, one page at a time, scaled to fit, with the chrome out of the way. |
| IsSearchOpen | `bool` | | Whether the find box is open. |
| Layers | `IReadOnlyList<BitPdfLayer>` | | The optional-content groups (layers) the document declares, empty when it declares none. |
| Metadata | `BitPdfMetadata?` | | The document metadata (/Info fields plus the raw XMP packet), or null when nothing is loaded. |
| Outline | `IReadOnlyList<BitPdfOutlineItem>` | | The document outline (bookmarks) as a tree, empty when the document has none. |
| PageCount | `int` | | The number of pages of the current document. |
| PageLabels | `IReadOnlyList<string>` | | The document-defined page labels (e.g. "i", "ii", "1", "A-1"), one per page in document order, or an empty list when nothing is loaded. |
| PdfVersion | `string?` | | The pdf version the loaded document declares (e.g. "1.7"), or null. |
| Permissions | `BitPdfPermissions` | | The user access permissions of the loaded document. Every permission is granted for an unencrypted document, and for no document at all. |
| SearchHighlightAll | `bool` | | Whether the find box paints every match, not just the current one. |
| SearchMatchCase | `bool` | | Whether the find box compares case-sensitively. |
| SearchMatchDiacritics | `bool` | | Whether the find box tells an accented letter apart from its bare form. |
| SearchMatchIndex | `int` | | The 1-based ordinal of the find match the reader is on, or 0 when there is no match. |
| SearchQuery | `string` | | The current find query, or an empty string when nothing is being searched for. |
| SearchWholeWord | `bool` | | Whether the find box matches whole words only. |
| SearchMatchCount | `int` | | The number of matches of the current find query, counted over the whole document (0 when there is no query or no match). |
| Sidebar | `BitPdfSidebar` | | Which side panel is currently open. |
| StructureTree | `IReadOnlyList<BitPdfStructElement>` | | The tagged-pdf logical structure tree of the loaded document, or an empty list when the document is untagged. |
| Warnings | `IReadOnlyList<string>` | | The non-fatal diagnostics collected while the current document was parsed (e.g. a damaged cross-reference table that had to be rebuilt), empty when there were none or nothing is loaded. |
| ZoomMode | `BitPdfZoomMode` | | The current zoom behavior (fit-width, fit-page, actual size or custom). |
| ClearSearch | `Task ClearSearch()` | | Clears the current find query and its highlights. |
| DownloadAttachment | `Task DownloadAttachment(BitPdfAttachment attachment)` | | Saves an embedded file to the reader's machine. |
| Download | `Task Download()` | | Downloads the original document bytes. Works for URL sources too: the bytes fetched for the current document are reused, so nothing is downloaded twice. OnDownloading runs first and may rename or cancel it. |
| ClearSelection | `Task ClearSelection()` | | Drops the reader's selection inside the document. A selection made elsewhere on the hosting page is left alone. |
| GetSelectedText | `Task<string> GetSelectedText()` | | The text the reader currently has selected in the document, or an empty string when nothing inside the viewer is selected. Reads the live DOM selection over the page's text layer, so it is the words the reader sees, in reading order. |
| ExtractPageText | `string ExtractPageText(int pageNumber)` | | Extracts the visible text of a single page (1-based) for search or copy, or an empty string when unavailable. |
| ExtractText | `string ExtractText(string pageSeparator = "\n\n")` | | Extracts the visible text of the whole document, one page per entry joined by the separator. Reuses the index the find box builds. |
| IsLayerVisible | `bool IsLayerVisible(BitPdfLayer layer)` | | Whether the layer is currently painted. |
| SetLayerVisible | `Task SetLayerVisible(BitPdfLayer layer, bool visible)` | | Shows or hides an optional-content group and re-renders the pages, the way a desktop viewer's layers panel does. |
| FindNext | `Task FindNext()` | | Moves to the next find match, wrapping around at the end. |
| FindPrevious | `Task FindPrevious()` | | Moves to the previous find match, wrapping around at the start. |
| FirstPage | `Task FirstPage()` | | Navigates to the first page. |
| GetBytes | `byte[]? GetBytes()` | | The raw bytes of the loaded document (fetched ones included), or null when nothing is loaded. |
| GoToDestination | `Task GoToDestination(BitPdfDestination? destination)` | | Navigates to a destination: its page, and - when the destination names a vertical position - that position within the page, whatever the rotation. A destination that names a zoom applies it too. |
| GoToNamedDestination | `Task GoToNamedDestination(string name)` | | Navigates to a named destination (the /Dests entry a link or an external anchor refers to). Does nothing when the document does not declare it. |
| GoToPage | `Task GoToPage(int pageNumber)` | | Navigates to the provided page number (1-based). |
| LastPage | `Task LastPage()` | | Navigates to the last page. |
| NextPage | `Task NextPage()` | | Navigates to the next page. |
| PrevPage | `Task PrevPage()` | | Navigates to the previous page. |
| OpenAsync | `Task OpenAsync(BitPdfSource? source)` | | Loads a document without going through the Source parameter. Passing null closes the current one. The Source parameter still wins: a later host render that changes it replaces whatever was opened this way. |
| PrintCurrentPage | `Task PrintCurrentPage()` | | Opens the browser print dialog with just the page the reader is on. |
| Print | `Task Print()` | | Opens the browser print dialog with all pages of the document. An overload takes a page range: Print(int from, int to). OnPrinting runs first and may cancel it. |
| RenderPageHtml | `string RenderPageHtml(int pageNumber)` | | Renders a single page (1-based) to self-contained HTML, or an empty string when no document is loaded or the number is out of range. |
| RotateClockwise | `Task RotateClockwise()` | | Rotates all pages 90 degrees clockwise. |
| RotateCounterClockwise | `Task RotateCounterClockwise()` | | Rotates all pages 90 degrees counter-clockwise. |
| Search | `Task Search(string? query)` | | Opens the find box (when it is closed) and searches the document for the query. An empty query just clears the current matches. |
| SetSearchOptions | `Task SetSearchOptions(bool? matchCase, bool? wholeWord, bool? matchDiacritics, bool? highlightAll)` | | Sets the find options and re-runs the current query against them. A null leaves that option as it is. |
| SetRotation | `Task SetRotation(int degrees)` | | Rotates all pages to the given absolute angle in degrees, normalized to the nearest quarter turn. |
| SetCursorTool | `void SetCursorTool(BitPdfCursorTool tool)` | | Changes what dragging on the document surface does. |
| SetScrollMode | `Task SetScrollMode(BitPdfScrollMode mode)` | | Changes how the pages are laid out on the scrollable surface. |
| SetSpreadMode | `Task SetSpreadMode(BitPdfSpreadMode mode)` | | Changes how pages are paired into spreads. |
| SetZoom | `Task SetZoom(double zoom)` | | Sets an explicit zoom factor (1 means 100%), switching the viewer to Custom zoom mode. The value is clamped to MinZoom..MaxZoom. |
| SetZoomMode | `Task SetZoomMode(BitPdfZoomMode mode)` | | Sets the zoom mode (fit-width, fit-page, actual size or custom). |
| ShowSidebar | `Task ShowSidebar(BitPdfSidebar sidebar)` | | Opens the given side panel, or closes the open one when None is passed. |
| EnterPresentationMode | `Task EnterPresentationMode()` | | Shows the document fullscreen, one page at a time, scaled to fit the screen. |
| ExitPresentationMode | `Task ExitPresentationMode()` | | Leaves presentation mode and restores the layout it replaced. |
| TogglePresentationMode | `Task TogglePresentationMode()` | | Enters or leaves presentation mode. Entering remembers the layout the reader had, so leaving - however it happens, including the browser's own Escape - puts it back. |
| ToggleFullscreen | `Task ToggleFullscreen()` | | Toggles the fullscreen mode of the viewer. |
| ToggleProperties | `void ToggleProperties()` | | Opens or closes the document-properties dialog. |
| ZoomIn | `Task ZoomIn()` | | Zooms in by one ZoomStep (20% by default). |
| ZoomOut | `Task ZoomOut()` | | Zooms out by one ZoomStep (20% by default). |
| UniqueId | `Guid` | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. |
| RootElement | `ElementReference` | | Gets the reference to the root HTML element associated with this component. |
## Enums
### BitPdfZoomMode Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Custom | 0 | An explicit zoom factor is applied (the user picked a percentage). |
| FitWidth | 1 | Each page is scaled so its width fills the viewport. |
| FitPage | 2 | Each page is scaled so the whole page fits in the viewport. |
| ActualSize | 3 | Pages are shown at their natural size (one CSS pixel per point). |
| FitHeight | 4 | Each page is scaled so its height fills the viewport, letting a wide page overflow horizontally rather than shrinking it to fit. |
| Automatic | 5 | Fit-width, but never magnified past 125% - the behavior a desktop viewer calls "automatic zoom", which keeps a narrow page readable without blowing it up to fill a wide screen. |
### BitPdfRenderMode Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Html | 0 | Pages render to positioned HTML/CSS DOM (the default). Fully prerenderable and crisp at any zoom. |
| Canvas | 1 | Page content is painted onto a per-page canvas by replaying a display list produced by the C# engine. Far fewer DOM nodes; selection, search and links still work through the DOM text layer, and zoom changes re-rasterize the canvases so text stays crisp. Requires JavaScript, so no prerender. |
### BitPdfTextCoalescing Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Exact | 0 | Every show-text run keeps its own positioned span, so each glyph run lands at its exact pdf-computed position. Highest fidelity, but per-glyph pdfs emit one span per character. |
| Compact | 1 | Adjacent runs on the same baseline with identical style are merged into one span per visual line. Dramatically fewer DOM nodes on per-glyph pdfs, at the cost of small intra-line position drift. Rotated text is never coalesced and stays exact. |
### BitPdfSidebar Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | No side panel is open; the document surface fills the viewer. |
| Thumbnails | 1 | The page-thumbnails panel is open. |
| Bookmarks | 2 | The bookmarks (document outline) panel is open. |
| Attachments | 3 | The embedded-files (attachments) panel is open. |
| Layers | 4 | The optional-content (layers) panel is open. |
### BitPdfScrollMode Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Vertical | 0 | Pages are stacked top to bottom and the surface scrolls vertically (the default). |
| Horizontal | 1 | Pages are placed side by side on one row and the surface scrolls horizontally. |
| Wrapped | 2 | Pages flow left to right and wrap onto the next row, filling the width of the surface. |
| Page | 3 | Only the current page (or spread) is shown; navigation replaces it rather than scrolling to it, and on a touch screen a horizontal swipe turns it. |
### BitPdfSpreadMode Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | No pairing: one page per row (the default). |
| Odd | 1 | Odd-numbered pages start a spread, pairing 1-2, 3-4 and so on. |
| Even | 2 | Even-numbered pages start a spread, so page 1 stands alone and 2-3, 4-5 and so on are paired. |
### BitPdfCursorTool Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Select | 0 | Dragging selects text (the default). |
| Pan | 1 | Dragging pans the document, as the hand tool of a desktop viewer does. |
### BitPdfToolbarItems Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | No toolbar control at all (the toolbar bar itself still renders). |
| Thumbnails | 1 | The page-thumbnails sidebar toggle. |
| Bookmarks | 2 | The bookmarks (document outline) sidebar toggle. |
| Navigation | 4 | The previous/next page buttons and the page-number box. |
| FirstLastPage | 8 | The first/last page buttons. |
| Zoom | 16 | The zoom in/out buttons and the zoom-level dropdown. |
| Title | 32 | The document title. |
| Search | 64 | The find-in-document control. |
| Rotate | 128 | The rotate clockwise/counter-clockwise buttons. |
| Download | 256 | The download button. |
| Print | 512 | The print button. |
| Fullscreen | 1024 | The fullscreen toggle. |
| Properties | 2048 | The document-properties button and its dialog. |
| Layout | 4096 | The scroll-mode and spread-mode dropdowns. |
| CursorTool | 8192 | The pan (hand) tool toggle. |
| Attachments | 16384 | The embedded-files (attachments) sidebar toggle. |
| Presentation | 32768 | The presentation-mode toggle. |
| Layers | 65536 | The optional-content (layers) sidebar toggle. |
| OpenFile | 131072 | The button that opens a pdf file from the reader's own machine. |
| All | 131071 | Every toolbar control (the default). |
### BitVisibility Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Visible | 0 | The content of the component is visible. |
| Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). |
| Collapsed | 2 | The component is hidden (display:none). |
### BitDir Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). |
| Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). |
| Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. |
## Sub Classes
### BitPdfSource Properties
Identifies where a pdf document is loaded from. A source is either a byte buffer already in memory (BitPdfSource.FromBytes), or a URL the document can be fetched from (BitPdfSource.FromUrl).
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Bytes | `byte[]?` | null | Raw document bytes, when the source is an in-memory buffer. |
| Url | `string?` | null | The URL to fetch the document from, when the source is remote. |
| FileName | `string?` | null | An optional display name (e.g. the original file name). |
| Password | `string?` | null | The password to open an encrypted document, if known up front (also see the WithPassword method). |
| Headers | `IReadOnlyDictionary<string, string>?` | null | Extra HTTP request headers sent when the document is fetched from Url - an Authorization header, for instance. Ignored for an in-memory source (also see the WithHeaders method). |
| IsBytes | `bool` | false | True when this source carries an in-memory byte buffer. |
| FromStreamAsync | `static Task<BitPdfSource> FromStreamAsync(Stream stream, string? fileName = null, CancellationToken cancellationToken = default)` | | Reads the stream to the end and creates an in-memory source from it - the shape an upload, a database blob or an embedded resource arrives in. The stream is read, not owned: the caller still disposes it. |
| FromBase64 | `static BitPdfSource FromBase64(string base64, string? fileName = null)` | | Creates an in-memory source from a base64-encoded document - the shape a document arrives in from a JSON API, a data URI or a database text column. A data:application/pdf;base64, prefix is accepted and stripped. |
### BitPdfAttachment Properties
A file embedded in the document, either document-wide through the catalog's /Names /EmbeddedFiles name tree or pinned to a page through a /FileAttachment annotation.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Name | `string` | | The file name the document gives the attachment. |
| Description | `string?` | null | The description (/Desc) the document gives it, when present. |
| MimeType | `string?` | null | The declared MIME type of the embedded stream, when present. |
| PageNumber | `int?` | null | The page the attachment is pinned to (1-based), or null for a document-wide attachment. |
| Content | `byte[]` | | The decoded bytes of the attachment. Empty when the embedded stream could not be decoded. |
| Size | `long` | 0 | The size in bytes of Content. |
### BitPdfDownloadArgs Properties
Arguments for the OnDownloading callback, raised before the document is saved.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| FileName | `string` | | The name the file is offered under: the source's own name, then the document title, then "document.pdf". Change it to rename the download; a blank value keeps the default. |
| Cancel | `bool` | false | Set to true to cancel the download. |
### BitPdfPrintArgs Properties
Arguments for the OnPrinting callback, raised before the pages are prepared for the print dialog.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| FromPage | `int` | | The first page about to be printed (1-based). |
| ToPage | `int` | | The last page about to be printed (1-based, inclusive). |
| Cancel | `bool` | false | Set to true to cancel the print. |
### BitPdfViewerClassStyles Properties
Custom CSS classes/styles for the different parts of the BitPdfViewer.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Root | `string?` | null | Custom CSS classes/styles for the root element of the BitPdfViewer. |
| ProgressBar | `string?` | null | Custom CSS classes/styles for the indeterminate loading bar of the BitPdfViewer. |
| Toolbar | `string?` | null | Custom CSS classes/styles for the toolbar of the BitPdfViewer. |
| ToolbarButton | `string?` | null | Custom CSS classes/styles for the toolbar buttons of the BitPdfViewer. |
| Title | `string?` | null | Custom CSS classes/styles for the document title shown in the toolbar of the BitPdfViewer. |
| SearchBox | `string?` | null | Custom CSS classes/styles for the find box of the BitPdfViewer. |
| Body | `string?` | null | Custom CSS classes/styles for the body (sidebar plus surface) of the BitPdfViewer. |
| Thumbnails | `string?` | null | Custom CSS classes/styles for the thumbnails sidebar of the BitPdfViewer. |
| Thumbnail | `string?` | null | Custom CSS classes/styles for each thumbnail of the BitPdfViewer. |
| Outline | `string?` | null | Custom CSS classes/styles for the bookmarks sidebar of the BitPdfViewer. |
| OutlineItem | `string?` | null | Custom CSS classes/styles for each bookmark of the BitPdfViewer. |
| Layers | `string?` | null | Custom CSS classes/styles for the layers sidebar of the BitPdfViewer. |
| Layer | `string?` | null | Custom CSS classes/styles for each layer row of the BitPdfViewer. |
| Surface | `string?` | null | Custom CSS classes/styles for the scrollable document surface of the BitPdfViewer. |
| Page | `string?` | null | Custom CSS classes/styles for each rendered page of the BitPdfViewer. |
| PropertiesDialog | `string?` | null | Custom CSS classes/styles for the document properties dialog of the BitPdfViewer. |
| PasswordDialog | `string?` | null | Custom CSS classes/styles for the password dialog of the BitPdfViewer. |
### BitPdfLayer Properties
An optional-content group (a layer) declared by the document - the switchable content a CAD drawing, a map overlay, multilingual artwork or a watermark ships as.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Id | `string` | | The identity of the group: a stable key derived from the indirect reference that names it. Content marked with this group is what the layer switches. |
| Name | `string` | | The group's display name (/Name). |
| VisibleByDefault | `bool` | false | Whether the document's default configuration shows the layer. The viewer starts from this and the reader takes it from there. |
### BitPdfViewerTexts Properties
The texts of the BitPdfViewer UI. All strings default to English; override individual properties to localize the viewer. The table lists the groups; every property is a plain settable string.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| ToolbarAriaLabel, LoadingAriaLabel, DocumentAriaLabel, ThumbnailAriaLabelFormat, PageAriaLabelFormat, LinkAriaLabelFormat, PageAnnouncementFormat | `string` | "PDF viewer toolbar", "Loading document", "Document", "Page {0}", "Page {0}", "Go to page {0}", "Page {0} of {1}" | The accessible names of the toolbar, the loading bar, the document surface (when no file name is known), each thumbnail, each page and each link to another page, and the announcement of a page move. |
| Thumbnails, Bookmarks, Attachments, Layers | `string` | "Page thumbnails", "Bookmarks", "Attachments", "Layers" | The labels of the side panel toggles. |
| FirstPage, PreviousPage, NextPage, LastPage, PageNumber, PageLabel | `string` | "First page", "Previous page", ... | The labels of the page navigation group. |
| ZoomIn, ZoomOut, ZoomLevel, Automatic, FitWidth, FitPage, FitHeight, ActualSize | `string` | "Zoom in", "Zoom out", ... | The labels of the zoom group and of the zoom dropdown options. |
| Find, FindPlaceholder, PreviousMatch, NextMatch, MatchCase, WholeWord, MatchDiacritics, HighlightAll, PhraseNotFound, MatchCountFormat | `string` | "Find in document", ..., "{0}/{1}" | The labels of the find box. MatchCountFormat receives the current match and the total. |
| ScrollMode, ScrollVertical, ScrollHorizontal, ScrollWrapped, ScrollPage, SpreadMode, SpreadNone, SpreadOdd, SpreadEven, PanTool | `string` | "Scroll mode", "Vertical scrolling", ... | The labels of the page-layout dropdowns and of the pan (hand) tool toggle. |
| RotateClockwise, RotateCounterClockwise, Download, Print, Fullscreen, ExitFullscreen, Presentation, Properties, OpenFile, Close | `string` | "Rotate clockwise", ... | The labels of the remaining toolbar actions. |
| NoDocument, PageRenderFailed, PreparingPrint, PrintAborted, HttpClientRequired, FetchFailedFormat, ErrorFormat, PageCountFormat | `string` | "No document loaded.", ... | The status messages shown on the surface (PreparingPrint and PrintAborted are announced). The *Format strings receive the underlying error or the page count. |
| PasswordTitle, PasswordPrompt, PasswordRejected, PasswordSubmit, Cancel | `string` | "Password required", "This document is protected...", ... | The texts of the built-in password dialog. |
| PropertyFileName, PropertyFileSize, PropertyTitle, PropertyAuthor, PropertySubject, PropertyKeywords, PropertyCreationDate, PropertyModificationDate, PropertyCreator, PropertyProducer, PropertyVersion, PropertyPageCount, PropertyPageSize, PropertyUnknown | `string` | "File name", "File size", ... | The row labels of the document properties dialog, and the placeholder shown for a property the document does not declare. |
## CSS Variables
Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance.
| Name | Default Value | Description |
| :--- | :------------ | :---------- |
| `--bit-PdfViewer-color` | var(--bit-clr-fg-pri) | Text and glyphs of the chrome. |
| `--bit-PdfViewer-background` | var(--bit-clr-bg-sec-dark) | Backdrop behind the pages. |
| `--bit-PdfViewer-border-color` | var(--bit-clr-brd-sec) | Color of the outer border. |
| `--bit-PdfViewer-border-width` | var(--bit-shp-brd-width) | Width of the outer border. |
| `--bit-PdfViewer-border-radius` | var(--bit-shp-radius-surface) | Corner radius of the viewer. |
| `--bit-PdfViewer-divider-color` | var(--bit-clr-brd-sec) | Lines between the toolbar, the sidebars and the pages. |
| `--bit-PdfViewer-focus-color` | var(--bit-clr-pri-focus) | Every focus indicator of the viewer, and the drop-target frame. While it is unset, every focus ring held off its element is the library's own --bit-shd-focus-ring; the ones drawn flush against a cell or a field keep this color. |
| `--bit-PdfViewer-font-family` | var(--bit-tpg-font-family) | Font of the chrome (page text keeps the document's own fonts). |
| `--bit-PdfViewer-height` | min(780px, 85dvh) | Height of the viewer (the Height parameter sets it on the instance). |
| `--bit-PdfViewer-width` | auto | Width of the viewer (the Width parameter sets it on the instance). |
| `--bit-PdfViewer-toolbar-background` | var(--bit-clr-bg-sec) | Background of the toolbar. |
| `--bit-PdfViewer-button-size` | spacing(3.75) | Width and height of a toolbar button. |
| `--bit-PdfViewer-button-radius` | var(--bit-shp-radius-button) | Corner radius of a toolbar button and a find option. |
| `--bit-PdfViewer-button-hover-background` | var(--bit-clr-bg-sec-hover) | Background of a toolbar button under the pointer. |
| `--bit-PdfViewer-button-active-color` | var(--bit-clr-pri-text) | Glyph of a toggle that is on (an open sidebar, the find box, a find option). |
| `--bit-PdfViewer-button-active-background` | var(--bit-clr-pri) | Background of a toggle that is on. |
| `--bit-PdfViewer-button-active-hover-background` | var(--bit-clr-pri-hover) | Background of a toggle that is on, under the pointer. |
| `--bit-PdfViewer-field-background` | var(--bit-clr-bg-pri) | Background of the page box, the find box and the dropdowns. |
| `--bit-PdfViewer-field-border-color` | var(--bit-clr-brd-pri) | Border of the page box, the find box, the dropdowns and the find options. |
| `--bit-PdfViewer-sidebar-background` | var(--bit-clr-bg-sec) | Background of the side panels. |
| `--bit-PdfViewer-sidebar-width` | spacing(29) | Width of the bookmarks, attachments and layers panels (at most half the viewer). |
| `--bit-PdfViewer-item-hover-background` | var(--bit-clr-bg-sec-hover) | A bookmark, attachment or layer row under the pointer. |
| `--bit-PdfViewer-selection-color` | var(--bit-clr-pri) | The current thumbnail's frame, the current bookmark and a checked layer. |
| `--bit-PdfViewer-surface-padding` | spacing(2) | Space around the pages. |
| `--bit-PdfViewer-page-gap` | spacing(2) | Space between the pages. |
| `--bit-PdfViewer-page-background` | #fff | Paper of a page and a thumbnail. |
| `--bit-PdfViewer-page-shadow` | var(--bit-shd-card) | Elevation of a page. |
| `--bit-PdfViewer-page-filter` | none | A CSS filter over every page and thumbnail - invert(1) hue-rotate(180deg) is a dark reading mode. |
| `--bit-PdfViewer-placeholder-background` | #f0f0f0 | A page that has not painted yet (its shimmer is derived from it). |
| `--bit-PdfViewer-progress-color` | var(--bit-clr-pri) | The loading bar. |
| `--bit-PdfViewer-progress-track-color` | var(--bit-clr-pri-light) | The track under the loading bar. |
| `--bit-PdfViewer-progress-height` | var(--bit-siz-track-sm) | Thickness of the loading bar. |
| `--bit-PdfViewer-text-selection-background` | color-mix(in srgb, var(--bit-clr-pri) 35%, transparent) | Selected document text. |
| `--bit-PdfViewer-search-match-background` | var(--bit-clr-wrn) | A find match. |
| `--bit-PdfViewer-search-match-color` | var(--bit-clr-wrn-text) | Text of a find match. |
| `--bit-PdfViewer-search-current-background` | var(--bit-clr-swr) | The find match being walked to. |
| `--bit-PdfViewer-search-current-color` | var(--bit-clr-swr-text) | Text of the find match being walked to. |
| `--bit-PdfViewer-presentation-background` | #000 | Backdrop of presentation mode. |
## Examples
\n**Basic**:
```razor
```
```csharp
private BitPdfSource basicSource = BitPdfSource.FromUrl("url-to-the-pdf-file.pdf", "file-name.pdf");
// or from what you already have in memory:
// BitPdfSource.FromBytes(pdfBytes, "file-name.pdf");
// BitPdfSource.FromBase64(base64OrDataUri, "file-name.pdf");
// await BitPdfSource.FromStreamAsync(stream, "file-name.pdf");
// A url source can carry request headers and a known password too:
// BitPdfSource.FromUrl(url).WithHeaders(headers).WithPassword("secret");
private async Task OnBasicFileChange(InputFileChangeEventArgs e)
{
if (e.FileCount == 0) return;
const long maxSize = 512 * 1024 * 1024;
if (e.File.Size <= 0 || e.File.Size > maxSize) return;
using var stream = e.File.OpenReadStream(maxAllowedSize: maxSize);
var bytes = new byte[(int)e.File.Size];
await stream.ReadExactlyAsync(bytes);
basicSource = BitPdfSource.FromBytes(bytes, e.File.Name);
}
```
\n**Dimensions**:
```razor
Load document
```
```csharp
private BitPdfSource? heightSource;
```
\n**Toolbar**:
```razor
Load document
@* The context is the viewer itself. *@
Share
@if (toolbarMessage is not null)
{
*@
```
```csharp
private BitPdfSource? toolbarSource;
private string? toolbarMessage;
private void Share(BitPdfViewer viewer)
{
toolbarMessage = viewer.PageCount == 0 ? null : $"Share requested for page {viewer.CurrentPage} of {viewer.PageCount}";
}
```
\n**Sidebars**:
```razor
Load document
```
```csharp
private BitPdfSource? sidebarSource;
```
\n**Zoom**:
```razor
Load document
```
```csharp
private BitPdfSource? zoomSource;
// The percentages the zoom dropdown offers, replacing the built-in ones.
private readonly double[] zoomPresets = [0.5, 1, 1.5, 2];
```
\n**Page layout**:
```razor
Load document
```
```csharp
private BitPdfSource? layoutSource;
private bool panTool;
private BitPdfScrollMode scrollMode = BitPdfScrollMode.Vertical;
private BitPdfSpreadMode spreadMode = BitPdfSpreadMode.None;
```
\n**Find in document**:
```razor
Load document
Search from code
Case + whole word
```
```csharp
private BitPdfSource? searchSource;
private string searchTerm = "the";
private BitPdfViewer searchViewerRef = default!;
// await searchViewerRef.FindNext();
// await searchViewerRef.FindPrevious();
// await searchViewerRef.ClearSearch();
// int count = searchViewerRef.SearchMatchCount;
```
\n**Rendering**:
```razor
Load document
@* BackgroundRendering is a safe no-op on single-threaded WebAssembly. *@
```
```csharp
private BitPdfSource? renderingSource;
private BitPdfRenderMode renderMode = BitPdfRenderMode.Html;
private BitPdfTextCoalescing textCoalescing = BitPdfTextCoalescing.Exact;
```
\n**Document info**:
```razor
Load document
@if (infoViewerRef?.Document is not null)
{
@* A known password travels on the source: Source='passwordSource.WithPassword("secret")'
and your own UI can do the asking: OnPasswordRequested="AskForPassword" *@
```
```csharp
private BitPdfSource? passwordSource;
private async Task OnPasswordFileChange(InputFileChangeEventArgs e)
{
if (e.FileCount == 0) return;
const long maxSize = 512 * 1024 * 1024;
if (e.File.Size <= 0 || e.File.Size > maxSize) return;
using var stream = e.File.OpenReadStream(maxAllowedSize: maxSize);
var bytes = new byte[(int)e.File.Size];
await stream.ReadExactlyAsync(bytes);
passwordSource = BitPdfSource.FromBytes(bytes, e.File.Name);
}
// private Task AskForPassword() => myOwnDialog.ShowAsync();
```
\n**Loading, empty & error states**:
```razor
Load a document
Load a broken file
Clear
Drop a pdf file here.
This file could not be opened: @context
```
```csharp
private BitPdfSource? statesSource;
// A file that only claims to be a pdf.
private void LoadBrokenFile()
=> statesSource = BitPdfSource.FromBytes("%PDF-1.7 this is not a pdf"u8.ToArray(), "broken.pdf");
```
\n**Events**:
```razor
Load document
eventsLog = [];
private void HandleDownloading(BitPdfDownloadArgs args)
{
args.FileName = $"report-{DateTime.Now:yyyy-MM-dd}.pdf";
eventsLog.Add($"Saving as {args.FileName}");
}
private void HandlePrinting(BitPdfPrintArgs args)
{
args.Cancel = blockPrinting;
eventsLog.Add($"Printing pages {args.FromPage}-{args.ToPage}{(args.Cancel ? " (blocked)" : "")}");
}
```
\n**Binding**:
```razor
Load document
```
```csharp
private BitPdfSource? bindingSource;
private int boundPage = 1;
private double boundZoom = 1;
private int boundRotation;
```
\n**Public API**:
```razor
Load document
First
Prev
Next
Last
Zoom -
100%
Zoom +
Fit page
Rotate
Thumbnails
First bookmark
Selected text
Download
Print all
Print page
Print 1-2
Present
@if (selectedText is not null)
{
Load document
```
```csharp
private BitPdfSource? localizedSource;
// Only the properties you assign are replaced; the rest keep their English defaults.
private readonly BitPdfViewerTexts germanTexts = new()
{
ToolbarAriaLabel = "PDF-Werkzeugleiste",
DocumentAriaLabel = "Dokument",
Thumbnails = "Seitenminiaturen",
Bookmarks = "Lesezeichen",
Attachments = "Anhänge",
Layers = "Ebenen",
FirstPage = "Erste Seite",
PreviousPage = "Vorherige Seite",
NextPage = "Nächste Seite",
LastPage = "Letzte Seite",
PageNumber = "Seitenzahl",
ThumbnailAriaLabelFormat = "Seite {0}",
PageAriaLabelFormat = "Seite {0}",
LinkAriaLabelFormat = "Gehe zu Seite {0}",
PageAnnouncementFormat = "Seite {0} von {1}",
ZoomIn = "Vergrößern",
ZoomOut = "Verkleinern",
ZoomLevel = "Zoomstufe",
Automatic = "Automatischer Zoom",
FitWidth = "Seitenbreite",
FitPage = "Ganze Seite",
FitHeight = "Seitenhöhe",
ActualSize = "Originalgröße",
Find = "Im Dokument suchen",
FindPlaceholder = "Im Dokument suchen",
PreviousMatch = "Vorheriger Treffer",
NextMatch = "Nächster Treffer",
MatchCase = "Groß-/Kleinschreibung",
WholeWord = "Ganze Wörter",
MatchDiacritics = "Akzente beachten",
HighlightAll = "Alle hervorheben",
PhraseNotFound = "Nicht gefunden",
MatchCountFormat = "{0} von {1}",
RotateClockwise = "Im Uhrzeigersinn drehen",
RotateCounterClockwise = "Gegen den Uhrzeigersinn drehen",
Download = "Herunterladen",
Print = "Drucken",
Fullscreen = "Vollbild",
ExitFullscreen = "Vollbild beenden",
Presentation = "Präsentationsmodus",
Properties = "Dokumenteigenschaften",
OpenFile = "Datei öffnen",
Close = "Schließen",
NoDocument = "Kein Dokument geladen.",
PageCountFormat = "{0} Seite(n).",
};
```
\n**Keyboard & accessibility**:
```razor
Load document
@* EnableKeyboardShortcuts="false" hands every key back to the page. *@
```
```csharp
private BitPdfSource? a11ySource;
private bool a11yDisabled;
```
\n**Cascading parameters**:
```razor
Load document
```
```csharp
private BitPdfSource? cascadeSource;
private readonly BitPdfViewerParams[] pdfViewerParams =
[
new()
{
Height = "300px",
InitialZoomMode = BitPdfZoomMode.FitPage,
ToolbarItems = BitPdfToolbarItems.Navigation | BitPdfToolbarItems.Zoom | BitPdfToolbarItems.Search,
Texts = new() { NoDocument = "Both viewers share their defaults - load a document." },
}
];
```
\n**Style & Class**:
```razor
Load document
```
```csharp
private BitPdfSource? styleSource;
// The same variables set on :root restyle every viewer of the app.
private const string cssVariablesStyle = "--bit-PdfViewer-border-radius:1rem;" +
"--bit-PdfViewer-border-color:var(--bit-clr-pri);" +
"--bit-PdfViewer-background:var(--bit-clr-bg-pri);" +
"--bit-PdfViewer-toolbar-background:var(--bit-clr-pri-light);" +
"--bit-PdfViewer-button-radius:999px;" +
"--bit-PdfViewer-page-shadow:none;" +
"--bit-PdfViewer-page-gap:0.5rem;" +
"--bit-PdfViewer-page-filter:invert(1) hue-rotate(180deg);" +
"--bit-PdfViewer-search-match-background:gold;";
```
\n**RTL**:
```razor
Load document
```
```csharp
private BitPdfSource? rtlSource;
```
@toolbarMessage
}
@* ShowToolbar="false" hides the bar; OnFileOpened takes the file the OpenFile picker read:
Title: @(infoViewerRef.Metadata?.Title ?? "-")
Producer: @(infoViewerRef.Metadata?.Producer ?? "-")
Pdf version: @(infoViewerRef.PdfVersion ?? "-")
Encrypted: @infoViewerRef.IsEncrypted
Can print: @infoViewerRef.Permissions.CanPrint, can copy: @infoViewerRef.Permissions.CanCopy
Form fields: @infoViewerRef.FormFields.Count
File size: @infoViewerRef.FileSize bytes
}
```
```csharp
private BitPdfSource? infoSource;
private BitPdfViewer? infoViewerRef;
// var labels = infoViewerRef.PageLabels;
// var structure = infoViewerRef.StructureTree;
```
\n**Encrypted documents**:
```razor
Events:
@foreach (var log in Enumerable.Reverse(eventsLog).Take(8))
{
```
```csharp
private BitPdfSource? eventsSource;
private bool blockPrinting;
private readonly List@log
}
Selected: @(selectedText.Length == 0 ? "(nothing)" : selectedText)
}
```
```csharp
private BitPdfSource? publicApiSource;
private BitPdfViewer pdfViewerRef = default!;
private string? selectedText;
// The reference is only set once the viewer has rendered.
private string PublicApiPosition => $"{pdfViewerRef?.CurrentPage}/{pdfViewerRef?.PageCount}";
// A destination lands on the exact spot a bookmark points at, not just its page.
private BitPdfDestination? FirstBookmarkDestination()
=> pdfViewerRef?.Outline.FirstOrDefault()?.Destination;
private async Task ShowSelectedText()
{
selectedText = await pdfViewerRef.GetSelectedText();
}
// await pdfViewerRef.OpenAsync(BitPdfSource.FromBytes(bytes, "other.pdf"));
// await pdfViewerRef.GoToNamedDestination("chapter-2");
// string text = pdfViewerRef.ExtractText();
// string html = pdfViewerRef.RenderPageHtml(1);
```
\n**Localization**:
```razor