Part

Last updated on

One document of a packet, numbering its own pages and saying where it sits in the packet.

A bundle on screen is a sequence of documents in one scroll, not one long document, and Part is the boundary between them: everything inside one numbers its pages from one, because that is what a reader of that document expects to see. The packet's own numbering — where each part's pages land in the whole — comes from the seal, not from the screen, so Part shows a page range only while it has one to show.

Preview

Rendering live preview requires JavaScript.

Installation

npx shadcn@4 add @paradoc/part

Or, with the Paradoc CLI, which writes the namespace into components.json for you:

npx paradoc-cli add part

Installs to components/paradoc/part.tsx.

Usage

import { Part } from "@/components/paradoc/part";<Part id="part-variant-unplaced" kind="composition" label="Cover note · composed live">  <Document artifact={proposalForm} data={shortProposalData}>    <Field path="customer" />  </Document></Part>
PropTypeDefaultDescription
idstring—The bundle content key.
kindPartKind—What the part is: a composition rendered live, a filled PDF form, or an annex.
label?ReactNode—Shown above the document. Nothing is shown when it is omitted.
firstPage?number—1-based packet page this part's first page is, when the caller has sealed the packet.
pageCount?number—Pages this part contributes, when the caller has sealed the packet.
attached?boolean—True when the part is carried beside the packet rather than merged into it.
placedFor?string—The packetHash the placement above was computed for.
packetHash?string—The packetHash of the packet on screen now. Page numbers show only while it matches.
className?string—Application-owned classes on the part's own wrapping element.
childrenReactNode—The part's document: a composition, painted PDF pages, or an attachment.

Composition

Part always sits inside a Bundle, which groups the packet's documents in one scroll and supplies the branding tokens every part reads. A part's own children are whatever the part is: a composition rendered live (usually a Document, often wrapped in its own pagination), a filled PDF form, or an annex — both of the latter two painted by PDF Pages.

The firstPage and pageCount a part shows come from core's sealBundle, which answers with exactly those two numbers per part once the packet is sealed. A part carries the packetHash that placement was computed for alongside the packetHash of the packet on screen now, and shows a page range only while the two match. A session that changes a field repaginates the composition, which moves every part after it; until the packet is resealed, the part it moved says its pages are pending rather than naming a page the packet no longer has.

An attached part is carried beside the packet rather than merged into its page count — a certificate or receipt a reader downloads alongside the packet rather than reads as one of its numbered pages.

The header's size follows the rhythm of the document it frames: the Bundle's token when there is one, otherwise the Document below, read through useDocumentTokensAround. See Typography.

Variants

Part's page range comes entirely from firstPage, pageCount, placedFor, and packetHash — the sealed placement, not a prop a caller chooses directly.

Unplaced

No firstPage or pageCount: the state before the packet has ever been sealed.

Rendering live preview requires JavaScript.

Placed

firstPage and pageCount match the packet on screen, so the header names the packet pages this part occupies.

Rendering live preview requires JavaScript.

Pending

placedFor no longer matches packetHash: a session's edit repaginated the composition and the packet has not been resealed yet, so the stale page numbers are suppressed.

Rendering live preview requires JavaScript.

On this page