@stesura/pdf-export-client
Browser side of PDF export: the toolbar button, and the shell for the export
page the server loads. The server side is
@stesura/pdf-export-server; the
PDF export guide covers setup.
Toolbar
pdfUiExtension adds the PDF export group to the toolbar’s Export tab:
import { pdfUiExtension } from '@stesura/pdf-export-client'
<StesuraEditor uiExtensions={[pdfUiExtension]} />For a custom endpoint, file name or request headers, build the extension with
createPdfUiExtension(props) (once, at module scope), or mount PdfExportGroup
(the button in a labelled toolbar group, which is what the extension mounts) or
the bare PdfExportButton yourself. The button posts { doc, fileName, experimental, layout?, docId? } to
the endpoint (experimental is the editor’s experimental features, which the
export page must lay out with) and downloads the PDF; failures, including a non-PDF response, show a toast
unless you pass onError. Both take the same props:
PdfExportButtonProps
Standalone export service
When rendering runs on its own host, the browser posts the document there
directly and your app only vouches for the request with a one-use ticket.
exportTicketHeaders(tokenEndpoint) is a ready-made getRequestHeaders: before
each export it POSTs to your token route (which answers { token }, minted with
mintExportToken from
@stesura/pdf-export-server/token)
and sends the ticket as Authorization: Bearer ….
import { createPdfUiExtension, exportTicketHeaders } from '@stesura/pdf-export-client'
export const pdfExport = createPdfUiExtension({
endpoint: 'https://pdf.example.com/render',
getRequestHeaders: exportTicketHeaders('/api/export/token'),
})Export page (/shell)
ExportEditorShell ({ children: ReactNode; isSettled?: () => boolean; layoutManifest?: () => ExportLayoutManifest | null })
wraps the read-only editor on the export route. It provides the clipping viewport, publishes
window.__stesuraPdfExport (ExportApi) and flags <body> with
data-export-ready or data-export-error once the layout has settled. The
editor stays in your app, so it keeps your plugins and extensions.
import { ExportEditorShell } from '@stesura/pdf-export-client/shell'
<ExportEditorShell>
<StesuraEditor printMode editable={false} toolbar={false} … />
</ExportEditorShell>Pass isSettled to settle on the pagination engine’s own signal: with it the
export is ready within a few animation frames of the last layout pass, instead
of after ~400ms of unchanged geometry.
import { getPaginationActivity, isPaginationIdle } from '@stesura/pagination'
const isSettled = () =>
isPaginationIdle(editorState) && getPaginationActivity(editorState).engineRuns > 0It is on its own subpath because it loads the print stylesheet, whose @page
rule can’t be scoped and must only load on the export route. Don’t import
@stesura/pdf-export-client/print.css yourself.
The server injects the document as window.__STESURA_EXPORT_DOC__ (an
ExportPayload) before any page script runs; importing the shell types that
global. If the payload is missing, set document.body.dataset.exportError
rather than rendering nothing, or the server waits until its timeout. The
guide lists the rest of the export
page’s requirements.
Protocol types
The contract between the export page and the server, from @stesura/core/types
so the server can import it without depending on this package.
ExportApi
Window-level API the server drives (window.__stesuraPdfExport). Optional
members may be missing from older client bundles.
ExportPayload
Payload the server injects via page.addInitScript, before any page script runs.
| Name | Type | Default |
|---|---|---|
doc | JSONContent | |
fileName | string | |
experimental | ExportExperimental |
ExportPageInfo
One printable page, in global page order (sections in DOM order, pages by index).
ExportLink
One clickable region on a page. A link that wraps across lines produces one entry per client rect (internal ones share the same target).
| Name | Type | Default |
|---|---|---|
kind | "url" | "internal" | |
rect | ExportLinkRect |
ExportLinkRect
Axis-aligned box in page-local CSS px (origin: the page’s top-left corner).
| Name | Type | Default |
|---|---|---|
x | number | |
y | number | |
width | number | |
height | number |
ExportOutlineNode
One bookmark in the PDF outline (heading), with its GoTo destination.
| Name | Type | Default |
|---|---|---|
title | string | |
pageIndex | numberManifest / merged-PDF page index of the heading. | |
y | numberHeading top in page-local CSS px from the page top. | |
children | ExportOutlineNode[] |