Skip to content

Commit 4ac0eab

Browse files
arthrodclaudeweb-flow
committed
docs(pagination): first-class JSDoc on remaining exported APIs (CR PR #433 backlog)
Plate's markdown/TS guideline: "JSDoc must be first-class for agents in all API surfaces". This sweep upgrades the five remaining exports that either lacked JSDoc or carried a one-line summary insufficient for agent + human discoverability: - mapping.buildMappingIndex — new JSDoc; documents the positional pageIndex invariant (PR #438) as the reason it's the only safe projection - projection.fragmentRects — multi-line; documents fragment-by- fragment iteration semantics, the mapping dependency, and the empty- result conditions - projection.blockLinePosition — multi-line; documents line-within- fragment math and the null contract - alignContent.computePageStart — new JSDoc; documents the simplified Spacers formula (Gemini PR #442) and what keys appear in the returned map - geometry.getPageGeometry — upgraded from one-liner; documents placement shape, gap semantics, and the total-{width,height} convention No behavior change. Suite: 85/85 ✓. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: CodeRabbitAI <noreply@github.com>
1 parent f49ab4d commit 4ac0eab

4 files changed

Lines changed: 77 additions & 3 deletions

File tree

packages/pagination/src/layout/mapping.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ export type MappingIndex = {
3131
isSplit: (blockIndex: number) => boolean;
3232
};
3333

34+
/**
35+
* Build a {@link MappingIndex} over a composed page list — a once-per-layout
36+
* scan that lets consumers ask "which page is block N on?" and "which fragment
37+
* holds line L of block N?" in O(refs-of-block) without re-scanning every page.
38+
*
39+
* The returned index is the only safe way to project block + line locations
40+
* onto pages, because it stores the POSITIONAL index of each page in the
41+
* `pages` array (see CodeRabbit PR #438). Consumers downstream dereference
42+
* `layout.pages[ref.pageIndex]` and `geometry.placements[ref.pageIndex]` as
43+
* array offsets, so deriving the index from `page.index` (which the composer
44+
* is free to renumber for skipped covers etc.) would silently drop projections
45+
* the moment those two diverge.
46+
*
47+
* @param pages the ordered page list from `composeLayout`
48+
* @returns lookup interface; see {@link MappingIndex}
49+
*/
3450
export function buildMappingIndex(pages: PageLayout[]): MappingIndex {
3551
const byBlock = new Map<number, FragmentRef[]>();
3652

packages/pagination/src/layout/projection.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,20 @@ export type LinePosition = {
2626
top: number;
2727
};
2828

29-
/** Absolute stack rects for every fragment of a (possibly split) block. */
29+
/**
30+
* Absolute stack rects for every fragment of a (possibly split) block.
31+
*
32+
* Reads `layout.mapping` (the prebuilt {@link MappingIndex}) for the block's
33+
* fragments and projects each one onto its page's placement frame. Returns
34+
* one rect per fragment in document order; an unsplit block yields exactly
35+
* one rect. Empty array when the block is missing from the layout or sits on
36+
* a page that geometry hasn't placed.
37+
*
38+
* @param layout output of `composeLayout` (carries the mapping index)
39+
* @param geometry output of `getPageGeometry` (carries page placements)
40+
* @param blockIndex top-level block index (`path[0]`)
41+
* @returns one absolute stack-coordinate rect per fragment
42+
*/
3043
export function fragmentRects(
3144
layout: LayoutOutput,
3245
geometry: PageGeometry,
@@ -54,7 +67,22 @@ export function fragmentRects(
5467
return rects;
5568
}
5669

57-
/** Absolute stack position of a given (0-based) line within a block. */
70+
/**
71+
* Absolute stack position of a given (0-based) visual line within a block.
72+
*
73+
* Finds which fragment holds the requested `lineIndex` (a block may span
74+
* multiple page fragments), projects that fragment's origin into stack
75+
* coordinates, then advances by `(lineIndex - fragment.lineStart) *
76+
* lineHeightPx` to land on the line itself. Useful for caret + selection
77+
* placement across page boundaries.
78+
*
79+
* @param layout output of `composeLayout`
80+
* @param geometry output of `getPageGeometry`
81+
* @param blockIndex top-level block index (`path[0]`)
82+
* @param line `{ lineIndex, lineHeightPx }` for the target line
83+
* @returns `{ pageIndex, left, top }` in stack coords, or `null`
84+
* if the line falls outside the laid-out range
85+
*/
5886
export function blockLinePosition(
5987
layout: LayoutOutput,
6088
geometry: PageGeometry,

packages/pagination/src/react/alignContent.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@ import type { LayoutInput, LayoutOutput } from '../layout/types';
1515
import { topLevelBlockElements } from './domMeasure';
1616
import { PAGE_STACK_GAP_PX } from './geometry';
1717

18+
/**
19+
* Compute the page-start spacer map — for each block that begins a NEW page
20+
* (page index > 0), how much CSS `margin-top` is needed so the block snaps
21+
* to that page's content-frame top in continuous view.
22+
*
23+
* Pure: returns the map without touching the DOM. {@link alignContentToLayout}
24+
* is the side-effecting wrapper.
25+
*
26+
* Formula: `page.heightPx - prevBottom + gapPx`, clamped non-negative.
27+
* (See the inline note for the derivation; margins/chrome cancel exactly out
28+
* of the original four-term expression — Gemini PR #442.)
29+
*
30+
* @param layout output of `composeLayout`
31+
* @param input the same `LayoutInput` used to compose (for `page.heightPx`)
32+
* @param gapPx inter-page visual gap (defaults to {@link PAGE_STACK_GAP_PX})
33+
* @returns `Map<blockIndex, spacerPx>` — only contains entries for
34+
* blocks that start a non-first page
35+
*/
1836
export function computePageStartSpacers(
1937
layout: LayoutOutput,
2038
input: LayoutInput,

packages/pagination/src/react/geometry.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,19 @@ export type PageGeometry = {
2626
height: number;
2727
};
2828

29-
/** Vertically stack pages with a fixed gap (single-column mode). */
29+
/**
30+
* Vertically stack pages with a fixed inter-page gap (single-column mode) —
31+
* the geometry projection used by the continuous-view overlay to position
32+
* each page's chrome (header / footer) and break-line in stack coordinates.
33+
*
34+
* Each placement is `{ left: 0, top, width: spec.widthPx, height: spec.heightPx }`
35+
* where `top` advances by `spec.heightPx + gapPx` per page. The container's
36+
* total width is the max page width; total height excludes the trailing gap.
37+
*
38+
* @param layout output of `composeLayout`
39+
* @param gapPx inter-page visual gap (defaults to {@link PAGE_STACK_GAP_PX})
40+
* @returns `{ placements, width, height }` in stack coordinates
41+
*/
3042
export function getPageGeometry(
3143
layout: LayoutOutput,
3244
gapPx: number = PAGE_STACK_GAP_PX

0 commit comments

Comments
 (0)