Skip to content

feat(paginate): repeat flag and stepwise createPaginator API - #3497

Merged
diegomura merged 17 commits into
masterfrom
dm/paginate-repeat-engine
Aug 17, 2026
Merged

feat(paginate): repeat flag and stepwise createPaginator API#3497
diegomura merged 17 commits into
masterfrom
dm/paginate-repeat-engine

Conversation

@diegomura

Copy link
Copy Markdown
Owner

Summary

Engine-only changes to @react-pdf/paginate, split out of the pagination-rewrite branch so they can merge independently (the package has no released consumer yet).

repeat flag

Items flagged repeat: true (leaf, column, row, lazy — not spacer/penalty) re-emit as fresh fragments at the head of every continuation of their parent column — thead-style repeating table headers.

  • Placed-once rule: an item only re-emits on continuations created after it fully placed; mid-split items continue their remainder instead, and a split consumes the item's identity.
  • Scoped lifetime: repetition is per-container and ends with it.
  • Progress guard: a page that places nothing but repeats stops the repetition, so content always advances (no wedge; MAX_PAGES stays as backstop).
  • Lazy composition: a repeat lazy re-materializes on every page it lands on with that page's number, via an origin tag on materialized fragments.
  • Wired at both continuation-building sites (fit/column and fit/row's column children).

createPaginator

Sealed stepwise pagination: next(height) fills exactly one page (a different height per call — the hook for page templates whose chrome varies per page), done signals exhaustion. paginate(root, height) is now the constant-height loop over it, keeping its MAX_PAGES cap. Internal state is deliberately unreachable from callers.

Tests

19 new tests, every one ending in a visual snapshot per repo convention; the snapshot renderer now accepts per-page regions so varying-height pages render at their true sizes. 90/90 total, typecheck clean.

🤖 Generated with Claude Code

diegomura and others added 17 commits August 18, 2026 00:55
…eights

paginate(root, height) becomes the constant-height loop over the sealed
iterator, keeping its MAX_PAGES backstop. Iterator callers pass a height
per next() call, own their termination, and cannot mutate in-flight state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Names what comes back — fresh Fragments of the completed repeat items —
instead of where the caller happens to put them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…how real page sizes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
index.ts becomes pure re-exports, matching the one-unit-per-file layout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3a91e3a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@react-pdf/paginate Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@diegomura
diegomura merged commit 482d7cd into master Aug 17, 2026
14 checks passed
@diegomura
diegomura deleted the dm/paginate-repeat-engine branch August 17, 2026 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant