Lector

API reference

Component contracts, defaults, hook scope, and public exports in the current source.

Import public APIs from @anaralabs/lector. This reference follows packages/lector/src/index.ts and the implementation on main; compare your installed version with the releases if a symbol is missing. Do not import from src/internal or a package-internal path.

Root

Loads one document and supplies its context. Accepts HTML div props in addition to the document options below. Its onError is a Lector callback, not a DOM error handler.

PropDefaultContract
sourceRequiredURL string, URL, typed array, ArrayBuffer, or PDF.js loading-parameters object
loader"Loading..."Content shown until the document and viewports are ready
onDocumentLoadReceives { proxy, source } after PDF.js loads the document, before viewport generation
onErrorReceives { error, phase, source } for initialization failures
documentOptionsLector defaultsPDF.js loading-parameter overrides; applied on the next load
zoom1Initial zoom multiplier
isZoomFitWidthfalseInitial fit-width mode
zoomOptions{ minZoom: 0.5, maxZoom: 10 }Initial limits for zoom updates
colorScheme"light""light" or "dark"; changes synchronize with the store
darkModeColorsSee dark modeOptional background and foreground; changes synchronize with the store

source changes trigger loading. Keep object and binary sources stable. The zoom props initialize state; use store actions for subsequent changes. Changing documentOptions alone does not reload the document. See loading documents for source handling, retries, and asset paths.

The current type also contains initialRotation, but Root does not forward it into document initialization. Do not rely on it for rotation controls.

Pages and Page

Component / propDefaultContract
Pages.childrenRequiredOne React element, normally a Page template
Pages.gap10Gap between virtualized pages
Pages.virtualizerOptions{ overscan: 1 }Extra pages mounted outside the visible range
Pages.initialOffsetInitial vertical scroll offset in pixels
Pages.onOffsetChangeReports nonzero scroll offsets; zero is currently omitted
Page.pageNumber1One-based page number; supplied automatically by Pages

Both accept HTML div props. Pages supplies its own scrolling and a default height of 100%; its parent needs a definite height. Page establishes page-number context and owns viewport dimensions. See layout.

Page layers

All page layers belong under Page.

ComponentPurpose and special props
CanvasLayerVisible content; accepts canvas props and optional background
TextLayerSelectable text; accepts div props and adds PDF.js's textLayer class
AnnotationLayerExisting PDF links and fields; renderForms=true, externalLinksEnabled=true, jumpOptions={ behavior: "smooth", align: "start" }
HighlightLayerDraws current highlights; div props and asChild apply to each rectangle
ColoredHighlightLayerColor-selection tools and stored colored overlays; onHighlight(highlight) reports a new record
CustomLayerRender prop: children(pageNumber) returns JSX; position your own overlay
AnnotationHighlightLayerDraws application annotation records; used with AnnotationsStoreProvider

CanvasLayer does not provide searchable DOM text. HighlightLayer needs a visible color or border from your styles. Links and fields need the PDF.js stylesheet.

Controls and thumbnails

Mount document controls under Root.

ExportContract
CurrentPageLabeled number input; commits on blur or Enter
TotalPagesA div containing the page count
CurrentZoomLabeled input displaying zoom as a percentage
ZoomIn, ZoomOutButtons that change zoom by 0.1; supply text, labels, and type="button"
ThumbnailsClones one thumbnail template per page
ThumbnailCanvas preview with a one-based pageNumber; click or Enter navigates
NextPage, PreviousPageExported placeholders; use custom navigation buttons

Outline, OutlineItem, and OutlineChildItems compose a document outline. Their current destination handling has page-index limitations, so verify navigation against your PDFs before using them. For a custom outline, the PDF.js document proxy exposes getOutline() and getDestination(). Convert PDF.js's zero-based getPageIndex() result to a one-based page number before calling jumpToPage.

usePdf

usePdf(selector) subscribes to the store belonging to the nearest Root. Select only the values your component needs. The provider is unavailable in Root's loader and outside its children.

fit-width-button.tsx
"use client";
 
import { usePdf } from "@anaralabs/lector";
 
export default function FitWidthButton() {
  const fitWidth = usePdf((state) => state.zoomFitWidth);
  return <button type="button" onClick={fitWidth}>Fit width</button>;
}

These are the store fields most useful to application code:

ReadUpdate / action
pdfDocumentProxyPDF.js document methods such as saveDocument()
currentPageUse usePdfJump().jumpToPage() to navigate; setCurrentPage() alone does not scroll
zoom, isZoomFitWidth, zoomOptionsupdateZoom(numberOrUpdater, isZoomFitWidth?), zoomFitWidth()
colorScheme, darkModeColorssetColorScheme(scheme, colors?)
highlightssetHighlight(rectangles) replaces the array
coloredHighlightsaddColoredHighlight(record), deleteColoredHighlight(uuid)
viewportsScale-1 PDF.js page viewports, indexed from 0
pageProxiesgetPdfPageProxy(pageNumber) takes a one-based page number
textContentPopulated by Search

The store also exposes rendering and virtualizer internals. Prefer the components and hooks above over mutating those fields.

usePdfJump

Requires Root and a mounted Pages virtualizer.

MethodContract
jumpToPage(page, options?)One-based page; align defaults to "start", behavior to "smooth"
jumpToOffset(offset)Scroll pixels; smooth scrolling
jumpToHighlightRects(rects, type, align?, additionalOffset?)Replaces highlights and scrolls; type is "pixels" or "percent"
scrollToHighlightRects(rects, type, align?, additionalOffset?, behavior?)Scrolls without replacing highlights; returns whether an offset could be resolved

For rectangle navigation, align is "start" or "center" (default "start"), additionalOffset defaults to 0, and scroll behavior defaults to "smooth". Use the coordinate contract when supplying your own rectangles.

Search and selection

ExportScope and result
SearchUnder Root; indexes every page's text; accepts children, loading, and errorFallback({ error, retry })
useSearch()Under Root; returns search, searchAsync, cancelSearch, isSearching, searchResults, textContent, and keywords (currently an empty array)
calculateHighlightRects(pageProxy, textPosition)Async utility returning HighlightRect[] for a text match
SelectionTooltipUnder Root; displays children for a selection; mount once per viewer
useSelectionDimensions()Under Root; getDimension() reads text and rectangles, getAnnotationDimension() also computes underlines
usePDFPageNumber()Under Page; current one-based page number
usePageRendered(pageNumber)Under Root; reads whether that page is marked rendered

Use getDimension() with an undefined check. The getSelection() alias has a stronger return type than its runtime guarantee, so it does not remove that need. See search for options, result allocation, and indexing cost, and selection for a complete action.

The package also exports AnnotationsStoreProvider, useAnnotations, AnnotationTooltip, and the Annotation and AnnotationTooltipContentProps types for application-owned annotations. These use a separate annotation store; Root does not install that provider for you. Wrap each independent annotation session in AnnotationsStoreProvider; without it, useAnnotations uses a shared fallback store. The docs site's annotation demo source shows their composition.

LinkService, PDFLinkServiceContext, useCreatePDFLinkService, and usePDFLinkService expose the PDF link integration. Root installs the service; AnnotationLayer connects destination changes to scrolling. Use PDF links for the normal integration.

Public types and color utilities

HighlightRect, ColoredHighlight, SearchResult, and SearchResults describe overlay and search data. ColorScheme, DarkModeColors, and RenderColorMap describe color configuration. DEFAULT_DARK_MODE_COLORS and createDarkModeColorMap let your overlays use the same palette as the page. See dark mode.

Component props are inferred from the components rather than all being exported as named interfaces. For a wrapper, derive them with React.ComponentProps<typeof Root> (or the component you wrap).

On this page