@embedpdf/plugin-render 3.0.0-next.10 → 3.0.0-next.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,333 +1,4 @@
1
- import { EngineRenderPolicy, PageImageHandle, PageImageOptions, PageObjectNumber, PageRenderViewport } from "@embedpdf/core";
2
- import { Rect } from "@embedpdf/core-geometry";
3
- //#region src/paint-plan.d.ts
4
- /**
5
- * The demand a page HOST supplies through dependency inversion:
6
- * plugin-render defines the shape, producers fill it. The Stage's page
7
- * host knows the camera and supplies `visibleRect`/`velocity`; a
8
- * stage-less `<PageView>` supplies neither — absent `visibleRect` means
9
- * "assume the whole page is visible", which a thumbnail-sized demand
10
- * turns into "no tiles engage" by arithmetic, not configuration.
11
- */
12
- interface PageViewDemand {
13
- /** Desired device pixels across the page's unrotated content width. */
14
- desiredDeviceWidth: number;
15
- /** Visible page region — y-down page points. ABSENT = whole page. */
16
- visibleRect?: Rect;
17
- /** Scroll velocity in page points/s — prefetch direction bias only. */
18
- velocity?: {
19
- dx: number;
20
- dy: number;
21
- };
22
- }
23
- /**
24
- * One tile the layer should have in the DOM. `key` is the reconciliation
25
- * identity (stable across plan recomputes — keyed lists preserve the DOM
26
- * node, which IS the retention mechanism); `rect` is y-down page points
27
- * inside the unrotated content box; `z` stacks by resolution so arriving
28
- * sharper tiles occlude retained coarser ones per region.
29
- */
30
- interface TilePaintSource {
31
- key: string;
32
- scale: number;
33
- rect: Rect;
34
- z: number;
35
- handle: PageImageHandle;
36
- }
37
- /**
38
- * What a tile plane paints right now. `paint` draws ONLY from resolved
39
- * rasters — retained generations live here until the release rules fire;
40
- * "loading" never reaches the DOM. `fetching` is diagnostic (badge/tests).
41
- */
42
- interface TilePaintPlan {
43
- /** Tiles engaged at all? False = the base rung fully covers demand. */
44
- engaged: boolean;
45
- paint: TilePaintSource[];
46
- /** Keys currently in flight (want-set members not yet resolved). */
47
- fetching: string[];
48
- /** Memoization stamp — a new object appears only when this changes. */
49
- stamp: string;
50
- }
51
- /**
52
- * The base-plane strategy: the pixel BUDGET and the render points below it.
53
- * Device px throughout (CSS px × devicePixelRatio).
54
- */
55
- interface FullPageOptions {
56
- /**
57
- * The budget: no full-page raster ever renders wider. Small by design —
58
- * the base is the instant backdrop; sharpness past it is the tile plane's
59
- * job. Default 640.
60
- */
61
- maxWidth?: number;
62
- /**
63
- * Render points under a `continuous` policy. `'exact'` (default) renders
64
- * the settled demand precisely — resting pixels are never resampled, the
65
- * only way ~1px text stems stay crisp on dpr-1 screens. A width ladder
66
- * opts into rung caching instead (defensible on dpr≥2 embeds). An
67
- * advertised deployment lattice always wins over either.
68
- */
69
- quantize?: 'exact' | readonly number[];
70
- }
71
- /** The tile-plane strategy. Pass `tiles: false` to disable the plane. */
72
- interface TilesOptions {
73
- /** Tile edge in device px. Default 512 (policy `tileSizes` win when advertised). */
74
- size?: number;
75
- /**
76
- * Tile levels under a `continuous` policy: `'exact'` (default) renders the
77
- * settled scale precisely; a scale ladder opts into pyramid reuse. An
78
- * advertised `policy.tiles` block always wins.
79
- */
80
- quantize?: 'exact' | readonly number[];
81
- /**
82
- * Exact-mode safety clamp on the tile level (device px per point) — the
83
- * sharpness ceiling. Past `maxScale × pageWidth` device px of demand,
84
- * tiles CSS-stretch instead of re-rendering. Per-screen tile cost is
85
- * constant at any level, so this bounds nothing but numeric range.
86
- * Default 128 (≈ 6,400% zoom on a letter page at dpr 2).
87
- */
88
- maxScale?: number;
89
- /**
90
- * Overlap neighboring tiles by this many device pixels per shared edge
91
- * (each tile renders a slightly larger region and is placed to match).
92
- * Kills hairline seams whenever tiles display at anything other than 1:1 —
93
- * separate `<img>`s at fractional boundaries each get partial-coverage
94
- * edge anti-aliasing, and bilinear scaling smears their last row — by
95
- * making every edge land over the neighbor's identical content instead of
96
- * the backdrop. Default 1; 0 disables.
97
- */
98
- bleed?: number;
99
- /**
100
- * Sharpness deficit (desired ÷ supplied-by-base) above which tiles engage.
101
- * Resolved default: 1.0 when the base is exact (nothing may rest
102
- * stretched), 1.25 under a lattice.
103
- */
104
- engageAt?: number;
105
- /** Prefetch ring around the visible rect. */
106
- prefetch?: {
107
- /** Extra coverage per side, in fractions of the visible rect. Default 0.5. */
108
- margin?: number;
109
- /** Stretch the ring toward scroll direction. Default true. */
110
- velocityBias?: boolean;
111
- };
112
- /**
113
- * Settle gate for LEVEL changes (a zoom in motion): tile fetches for a new
114
- * level wait this long; pan-driven fetches at the current level fire
115
- * immediately. Default 150ms; 0 disables.
116
- */
117
- settleMs?: number;
118
- /** Optional arrival cross-fade for tiles, in ms. Default 0 (hard pop —
119
- * clean once painting is decode-gated). */
120
- fadeMs?: number;
121
- }
122
- //#endregion
123
- //#region src/types.d.ts
124
- /**
125
- * Options for `renderPlugin()` — the render STRATEGY: what the viewer
126
- * chooses to spend, and which render points it uses when the engine permits
127
- * anything. The shape mirrors the deployment policy (`policy.fullPage` /
128
- * `policy.tiles`), and the one composition rule is: a strategy value
129
- * applies as written under a `continuous` policy, and the advertised
130
- * lattice wins when there is one — so the same options run unchanged
131
- * against local and cloud.
132
- */
133
- interface RenderPluginOptions {
134
- /** Base plane: the pixel budget + render points. */
135
- fullPage?: FullPageOptions;
136
- /** Tile plane strategy; `false` disables the plane entirely. */
137
- tiles?: TilesOptions | false;
138
- /**
139
- * Encode format for BOTH planes. Unset → engine default (png local, the
140
- * deployment's format on cloud). `'bmp'` is the local fast path — no
141
- * compression, no encoder-worker round trip; under a lattice it conforms
142
- * to `policy.formats`.
143
- */
144
- format?: NonNullable<PageImageOptions['format']>;
145
- /** Encoder quality (webp/png); ignored for bmp. */
146
- quality?: number;
147
- /**
148
- * Diagnostic logging: tile scheduling, settle timing, fetch outcomes —
149
- * the counters that catch convergence issues in long sessions. Console
150
- * `debug` level; off by default.
151
- */
152
- debug?: boolean;
153
- }
154
- /** Layer-facing paint settings (resolved options the view layers need). */
155
- interface PaintSettings {
156
- /** Tile arrival cross-fade (ms); 0 = hard pop. */
157
- fadeMs: number;
158
- /** Whether the tile plane is enabled at all (`tiles: false` opts out). */
159
- tiles: boolean;
160
- }
161
- interface RenderPageOptions {
162
- /** Device px per PDF point (use the page transform's `renderScale`). */
163
- scale: number;
164
- /**
165
- * Bake annotations into the page bitmap. Default true. Pass false when an
166
- * <AnnotationLayer> owns annotation rendering, so they aren't painted twice
167
- * (once baked, once by the overlay).
168
- */
169
- includeAnnotations?: boolean;
170
- /** Abort the render (camera moved / layer unmounted). */
171
- signal?: AbortSignal;
172
- }
173
- /**
174
- * The two invalidation scopes — every pixel-changing fact is one of them:
175
- *
176
- * 'annotations' — only baked APPEARANCES changed (an annotation mutated, a
177
- * form widget re-baked). Base renders keep their pixels.
178
- * 'content' — the PAGE ITSELF changed (redaction applied, text edited).
179
- * Invalidates everything: no mutation can change base pixels
180
- * yet leave an annotated raster valid, so content strictly
181
- * contains annotations.
182
- */
183
- type InvalidateScope = 'content' | 'annotations';
184
- /**
185
- * Per-page versions of the two raster products a page has — base
186
- * (`includeAnnotations: false`) and annotated. Fed by the document event
187
- * stream (see effects.ts) and by the `invalidate` verb: a confirmed
188
- * pixel-changing fact — own or remote — bumps the touched pages, and anything
189
- * holding a rendered bitmap (a thumbnail rail) refetches.
190
- */
191
- interface RenderState {
192
- /** Base-raster versions — bumped by CONTENT facts (redaction, text edit). */
193
- readonly contentEpochs: Readonly<Record<PageObjectNumber, number>>;
194
- /** Appearance versions — bumped by ANNOTATION facts (annotations, form widgets). */
195
- readonly annotatedEpochs: Readonly<Record<PageObjectNumber, number>>;
196
- /**
197
- * Tile paint-plan wake-ups. The tile manager's state (fetch/painted/
198
- * retention) lives OUTSIDE the store — it holds live handles and abort
199
- * controllers — so resolutions bump this counter to make subscribed
200
- * layers recompute `tilePlan`. The value itself carries no meaning.
201
- */
202
- readonly paintVersions: Readonly<Record<PageObjectNumber, number>>;
203
- }
204
- type RenderAction = {
205
- type: 'INVALIDATE';
206
- scope: InvalidateScope;
207
- pons: readonly PageObjectNumber[];
208
- } | {
209
- type: 'PAINT_ADVANCED';
210
- pon: PageObjectNumber;
211
- };
212
- /**
213
- * One view's scoped tile surface (see {@link RenderCapability.tilesFor}).
214
- * Identity (the view) is bound at creation; every call addresses that view's
215
- * own state for the given page.
216
- */
217
- interface ViewTiles {
218
- /**
219
- * The tile paint plan for a page under this view's demand. Tiling is a
220
- * STRATEGY inside this plugin, not a sibling.
221
- * Memoized: the same object returns until the demand, an epoch, or a
222
- * tile resolution actually changes it, so layers can subscribe with
223
- * plain `Object.is`. Calling it schedules the want-set fetches (visible
224
- * first, center-out, prefetch ring after) — idempotent, store-deduped.
225
- * Engagement is pure arithmetic against what the base will ACTUALLY
226
- * supply (the same `baseAsk` the base layer sizes with): tiles fire when
227
- * demand exceeds the budget/ladder cap × engageAt — on every engine.
228
- * A thumbnail-sized demand never engages.
229
- */
230
- plan(pon: PageObjectNumber, demand: PageViewDemand, opts?: {
231
- includeAnnotations?: boolean;
232
- }): TilePaintPlan;
233
- /**
234
- * The painter's report: the image for this plan key had a presentation
235
- * opportunity. Retained coarser generations covered by painted want-set
236
- * tiles release on this signal — never on fetch completion or image load,
237
- * which could drop the backdrop before replacement pixels are presented.
238
- */
239
- painted(pon: PageObjectNumber, key: string): void;
240
- /**
241
- * The inverse report: this plan key's <img> left the DOM, so its pixels
242
- * are no longer compositable. Painted is a statement about the SCREEN and
243
- * must follow the DOM — a remounting tile re-decodes, and until it
244
- * reports painted again, retention may not count it as coverage.
245
- */
246
- unpainted(pon: PageObjectNumber, key: string): void;
247
- /** This view unmounted its tile plane for the page: abort in-flight tile
248
- * fetches, drop ITS bookkeeping (resolved bytes stay cached). */
249
- release(pon: PageObjectNumber): void;
250
- }
251
- interface RenderCapability {
252
- /**
253
- * The twin (permissions.md): would page rasters be served to this session?
254
- * Mirrors `doc.render`. When false, `renderPage` and the tile plane refuse
255
- * locally (no doomed engine round-trips — the gate case for a capability
256
- * whose denial would otherwise 403 on every viewport tile) and a host can
257
- * render its "no preview" state instead of error tiles.
258
- */
259
- canRender(): boolean;
260
- /**
261
- * Render a page (by its durable pon) to an ENCODED image. Abortable. Encoded
262
- * output is identical for local & cloud and cheap over the wire (vs. raw RGBA).
263
- *
264
- * This is the VIEWER door: the desired `scale` conforms through the
265
- * resolved render points (STRATEGY ∧ POLICY) — the exact demand capped at
266
- * the pixel budget under `continuous`, the advertised ladder under a
267
- * lattice — and same-key requests collapse in the plugin's raster store
268
- * (singleflight + LRU). Scale-precise offline output (export, print)
269
- * belongs on the engine door: `doc.page(pon).render.image(...)`.
270
- */
271
- renderPage(pon: PageObjectNumber, options: RenderPageOptions): Promise<PageImageHandle>;
272
- /**
273
- * The identity of the raster `renderPage` would produce for these options —
274
- * conformed width + annotations flag + epoch, as one stable string. Layers
275
- * key their fetch effect on THIS instead of the raw scale. Under a lattice
276
- * it moves only at rung crossings; under exact-mode `continuous` it tracks
277
- * the demand, is constant above the budget (always the budget width), and
278
- * the LAYER settle-gates adoption so it never refetches mid-gesture.
279
- * Always available: the kernel materializes the policy on `DocumentMeta`
280
- * before the document publishes.
281
- */
282
- renderSourceKey(pon: PageObjectNumber, options: {
283
- scale: number;
284
- includeAnnotations?: boolean;
285
- }): string;
286
- /**
287
- * The canonical viewport a desired scale conforms to for this page —
288
- * always width-kind: the exact demand capped at the budget (exact mode)
289
- * or the snapped rung (ladder/lattice mode).
290
- */
291
- conformViewport(pon: PageObjectNumber, scale: number): PageRenderViewport;
292
- /** Resolved layer-facing paint settings (settle, fade, tiles on/off). */
293
- paintSettings(): PaintSettings;
294
- /** The document's advertised policy (sugar over `DocumentMeta.renderPolicy`). */
295
- renderPolicy(): EngineRenderPolicy;
296
- /**
297
- * This view's tile surface — the ONE tile entry point. `view` is the
298
- * consuming view's identity (`PageContextValue.view`: a stage lens id, or
299
- * a PageView instance id). Tile state is kept PER VIEW × PAGE, so two
300
- * views showing the same page plan independently — a thumbnail rail's
301
- * never-engaging demand cannot disturb the main view's tiles. Binding the
302
- * identity ONCE makes it unforgettable and unmixable: the handle's four
303
- * calls can never disagree about whose state they address. Stable per
304
- * view — safe as a hook/effect dependency.
305
- */
306
- tilesFor(view: string): ViewTiles;
307
- /**
308
- * Version of the raster the given options would produce. Key a long-lived
309
- * render on it: when it bumps, refetch. Base renders version on content
310
- * facts; annotated renders on content AND annotation facts. Bumps only on
311
- * CONFIRMED mutations — never optimistically — so a drag invalidates once,
312
- * at commit.
313
- */
314
- renderEpoch(pon: PageObjectNumber, includeAnnotations?: boolean): number;
315
- /**
316
- * Declare that page pixels changed — the open door for facts the built-in
317
- * event map doesn't know (a plugin's own mutation vocabulary: redaction,
318
- * text edit, anything third-party). Call at CONFIRMATION (after the engine
319
- * write resolves), never for optimistic previews — those belong in overlay
320
- * layers. `pons` omitted = every page; `scope` defaults to 'content'
321
- * (repaint everything) because a caller who doesn't say is safest repainted
322
- * fully. Redundant with a mapped engine event? Harmless — one extra refetch.
323
- */
324
- invalidate(opts?: {
325
- pons?: readonly PageObjectNumber[];
326
- scope?: InvalidateScope;
327
- }): void;
328
- }
329
- declare const RenderToken: import("@embedpdf/core").CapabilityToken<RenderCapability>;
330
- //#endregion
1
+ import { a as RenderPluginOptions, c as FullPageOptions, d as TilePaintSource, f as TilesOptions, i as RenderCapability, l as PageViewDemand, n as PaintSettings, o as RenderState, r as RenderAction, s as RenderToken, t as InvalidateScope, u as TilePaintPlan } from "./contract-CWPMd1OW.cjs";
331
2
  //#region src/render.plugin.d.ts
332
3
  /**
333
4
  * Document-scoped. The ONE policy consumer in the client stack: the doc-bind
package/dist/index.d.ts CHANGED
@@ -1,333 +1,4 @@
1
- import { EngineRenderPolicy, PageImageHandle, PageImageOptions, PageObjectNumber, PageRenderViewport } from "@embedpdf/core";
2
- import { Rect } from "@embedpdf/core-geometry";
3
- //#region src/paint-plan.d.ts
4
- /**
5
- * The demand a page HOST supplies through dependency inversion:
6
- * plugin-render defines the shape, producers fill it. The Stage's page
7
- * host knows the camera and supplies `visibleRect`/`velocity`; a
8
- * stage-less `<PageView>` supplies neither — absent `visibleRect` means
9
- * "assume the whole page is visible", which a thumbnail-sized demand
10
- * turns into "no tiles engage" by arithmetic, not configuration.
11
- */
12
- interface PageViewDemand {
13
- /** Desired device pixels across the page's unrotated content width. */
14
- desiredDeviceWidth: number;
15
- /** Visible page region — y-down page points. ABSENT = whole page. */
16
- visibleRect?: Rect;
17
- /** Scroll velocity in page points/s — prefetch direction bias only. */
18
- velocity?: {
19
- dx: number;
20
- dy: number;
21
- };
22
- }
23
- /**
24
- * One tile the layer should have in the DOM. `key` is the reconciliation
25
- * identity (stable across plan recomputes — keyed lists preserve the DOM
26
- * node, which IS the retention mechanism); `rect` is y-down page points
27
- * inside the unrotated content box; `z` stacks by resolution so arriving
28
- * sharper tiles occlude retained coarser ones per region.
29
- */
30
- interface TilePaintSource {
31
- key: string;
32
- scale: number;
33
- rect: Rect;
34
- z: number;
35
- handle: PageImageHandle;
36
- }
37
- /**
38
- * What a tile plane paints right now. `paint` draws ONLY from resolved
39
- * rasters — retained generations live here until the release rules fire;
40
- * "loading" never reaches the DOM. `fetching` is diagnostic (badge/tests).
41
- */
42
- interface TilePaintPlan {
43
- /** Tiles engaged at all? False = the base rung fully covers demand. */
44
- engaged: boolean;
45
- paint: TilePaintSource[];
46
- /** Keys currently in flight (want-set members not yet resolved). */
47
- fetching: string[];
48
- /** Memoization stamp — a new object appears only when this changes. */
49
- stamp: string;
50
- }
51
- /**
52
- * The base-plane strategy: the pixel BUDGET and the render points below it.
53
- * Device px throughout (CSS px × devicePixelRatio).
54
- */
55
- interface FullPageOptions {
56
- /**
57
- * The budget: no full-page raster ever renders wider. Small by design —
58
- * the base is the instant backdrop; sharpness past it is the tile plane's
59
- * job. Default 640.
60
- */
61
- maxWidth?: number;
62
- /**
63
- * Render points under a `continuous` policy. `'exact'` (default) renders
64
- * the settled demand precisely — resting pixels are never resampled, the
65
- * only way ~1px text stems stay crisp on dpr-1 screens. A width ladder
66
- * opts into rung caching instead (defensible on dpr≥2 embeds). An
67
- * advertised deployment lattice always wins over either.
68
- */
69
- quantize?: 'exact' | readonly number[];
70
- }
71
- /** The tile-plane strategy. Pass `tiles: false` to disable the plane. */
72
- interface TilesOptions {
73
- /** Tile edge in device px. Default 512 (policy `tileSizes` win when advertised). */
74
- size?: number;
75
- /**
76
- * Tile levels under a `continuous` policy: `'exact'` (default) renders the
77
- * settled scale precisely; a scale ladder opts into pyramid reuse. An
78
- * advertised `policy.tiles` block always wins.
79
- */
80
- quantize?: 'exact' | readonly number[];
81
- /**
82
- * Exact-mode safety clamp on the tile level (device px per point) — the
83
- * sharpness ceiling. Past `maxScale × pageWidth` device px of demand,
84
- * tiles CSS-stretch instead of re-rendering. Per-screen tile cost is
85
- * constant at any level, so this bounds nothing but numeric range.
86
- * Default 128 (≈ 6,400% zoom on a letter page at dpr 2).
87
- */
88
- maxScale?: number;
89
- /**
90
- * Overlap neighboring tiles by this many device pixels per shared edge
91
- * (each tile renders a slightly larger region and is placed to match).
92
- * Kills hairline seams whenever tiles display at anything other than 1:1 —
93
- * separate `<img>`s at fractional boundaries each get partial-coverage
94
- * edge anti-aliasing, and bilinear scaling smears their last row — by
95
- * making every edge land over the neighbor's identical content instead of
96
- * the backdrop. Default 1; 0 disables.
97
- */
98
- bleed?: number;
99
- /**
100
- * Sharpness deficit (desired ÷ supplied-by-base) above which tiles engage.
101
- * Resolved default: 1.0 when the base is exact (nothing may rest
102
- * stretched), 1.25 under a lattice.
103
- */
104
- engageAt?: number;
105
- /** Prefetch ring around the visible rect. */
106
- prefetch?: {
107
- /** Extra coverage per side, in fractions of the visible rect. Default 0.5. */
108
- margin?: number;
109
- /** Stretch the ring toward scroll direction. Default true. */
110
- velocityBias?: boolean;
111
- };
112
- /**
113
- * Settle gate for LEVEL changes (a zoom in motion): tile fetches for a new
114
- * level wait this long; pan-driven fetches at the current level fire
115
- * immediately. Default 150ms; 0 disables.
116
- */
117
- settleMs?: number;
118
- /** Optional arrival cross-fade for tiles, in ms. Default 0 (hard pop —
119
- * clean once painting is decode-gated). */
120
- fadeMs?: number;
121
- }
122
- //#endregion
123
- //#region src/types.d.ts
124
- /**
125
- * Options for `renderPlugin()` — the render STRATEGY: what the viewer
126
- * chooses to spend, and which render points it uses when the engine permits
127
- * anything. The shape mirrors the deployment policy (`policy.fullPage` /
128
- * `policy.tiles`), and the one composition rule is: a strategy value
129
- * applies as written under a `continuous` policy, and the advertised
130
- * lattice wins when there is one — so the same options run unchanged
131
- * against local and cloud.
132
- */
133
- interface RenderPluginOptions {
134
- /** Base plane: the pixel budget + render points. */
135
- fullPage?: FullPageOptions;
136
- /** Tile plane strategy; `false` disables the plane entirely. */
137
- tiles?: TilesOptions | false;
138
- /**
139
- * Encode format for BOTH planes. Unset → engine default (png local, the
140
- * deployment's format on cloud). `'bmp'` is the local fast path — no
141
- * compression, no encoder-worker round trip; under a lattice it conforms
142
- * to `policy.formats`.
143
- */
144
- format?: NonNullable<PageImageOptions['format']>;
145
- /** Encoder quality (webp/png); ignored for bmp. */
146
- quality?: number;
147
- /**
148
- * Diagnostic logging: tile scheduling, settle timing, fetch outcomes —
149
- * the counters that catch convergence issues in long sessions. Console
150
- * `debug` level; off by default.
151
- */
152
- debug?: boolean;
153
- }
154
- /** Layer-facing paint settings (resolved options the view layers need). */
155
- interface PaintSettings {
156
- /** Tile arrival cross-fade (ms); 0 = hard pop. */
157
- fadeMs: number;
158
- /** Whether the tile plane is enabled at all (`tiles: false` opts out). */
159
- tiles: boolean;
160
- }
161
- interface RenderPageOptions {
162
- /** Device px per PDF point (use the page transform's `renderScale`). */
163
- scale: number;
164
- /**
165
- * Bake annotations into the page bitmap. Default true. Pass false when an
166
- * <AnnotationLayer> owns annotation rendering, so they aren't painted twice
167
- * (once baked, once by the overlay).
168
- */
169
- includeAnnotations?: boolean;
170
- /** Abort the render (camera moved / layer unmounted). */
171
- signal?: AbortSignal;
172
- }
173
- /**
174
- * The two invalidation scopes — every pixel-changing fact is one of them:
175
- *
176
- * 'annotations' — only baked APPEARANCES changed (an annotation mutated, a
177
- * form widget re-baked). Base renders keep their pixels.
178
- * 'content' — the PAGE ITSELF changed (redaction applied, text edited).
179
- * Invalidates everything: no mutation can change base pixels
180
- * yet leave an annotated raster valid, so content strictly
181
- * contains annotations.
182
- */
183
- type InvalidateScope = 'content' | 'annotations';
184
- /**
185
- * Per-page versions of the two raster products a page has — base
186
- * (`includeAnnotations: false`) and annotated. Fed by the document event
187
- * stream (see effects.ts) and by the `invalidate` verb: a confirmed
188
- * pixel-changing fact — own or remote — bumps the touched pages, and anything
189
- * holding a rendered bitmap (a thumbnail rail) refetches.
190
- */
191
- interface RenderState {
192
- /** Base-raster versions — bumped by CONTENT facts (redaction, text edit). */
193
- readonly contentEpochs: Readonly<Record<PageObjectNumber, number>>;
194
- /** Appearance versions — bumped by ANNOTATION facts (annotations, form widgets). */
195
- readonly annotatedEpochs: Readonly<Record<PageObjectNumber, number>>;
196
- /**
197
- * Tile paint-plan wake-ups. The tile manager's state (fetch/painted/
198
- * retention) lives OUTSIDE the store — it holds live handles and abort
199
- * controllers — so resolutions bump this counter to make subscribed
200
- * layers recompute `tilePlan`. The value itself carries no meaning.
201
- */
202
- readonly paintVersions: Readonly<Record<PageObjectNumber, number>>;
203
- }
204
- type RenderAction = {
205
- type: 'INVALIDATE';
206
- scope: InvalidateScope;
207
- pons: readonly PageObjectNumber[];
208
- } | {
209
- type: 'PAINT_ADVANCED';
210
- pon: PageObjectNumber;
211
- };
212
- /**
213
- * One view's scoped tile surface (see {@link RenderCapability.tilesFor}).
214
- * Identity (the view) is bound at creation; every call addresses that view's
215
- * own state for the given page.
216
- */
217
- interface ViewTiles {
218
- /**
219
- * The tile paint plan for a page under this view's demand. Tiling is a
220
- * STRATEGY inside this plugin, not a sibling.
221
- * Memoized: the same object returns until the demand, an epoch, or a
222
- * tile resolution actually changes it, so layers can subscribe with
223
- * plain `Object.is`. Calling it schedules the want-set fetches (visible
224
- * first, center-out, prefetch ring after) — idempotent, store-deduped.
225
- * Engagement is pure arithmetic against what the base will ACTUALLY
226
- * supply (the same `baseAsk` the base layer sizes with): tiles fire when
227
- * demand exceeds the budget/ladder cap × engageAt — on every engine.
228
- * A thumbnail-sized demand never engages.
229
- */
230
- plan(pon: PageObjectNumber, demand: PageViewDemand, opts?: {
231
- includeAnnotations?: boolean;
232
- }): TilePaintPlan;
233
- /**
234
- * The painter's report: the image for this plan key had a presentation
235
- * opportunity. Retained coarser generations covered by painted want-set
236
- * tiles release on this signal — never on fetch completion or image load,
237
- * which could drop the backdrop before replacement pixels are presented.
238
- */
239
- painted(pon: PageObjectNumber, key: string): void;
240
- /**
241
- * The inverse report: this plan key's <img> left the DOM, so its pixels
242
- * are no longer compositable. Painted is a statement about the SCREEN and
243
- * must follow the DOM — a remounting tile re-decodes, and until it
244
- * reports painted again, retention may not count it as coverage.
245
- */
246
- unpainted(pon: PageObjectNumber, key: string): void;
247
- /** This view unmounted its tile plane for the page: abort in-flight tile
248
- * fetches, drop ITS bookkeeping (resolved bytes stay cached). */
249
- release(pon: PageObjectNumber): void;
250
- }
251
- interface RenderCapability {
252
- /**
253
- * The twin (permissions.md): would page rasters be served to this session?
254
- * Mirrors `doc.render`. When false, `renderPage` and the tile plane refuse
255
- * locally (no doomed engine round-trips — the gate case for a capability
256
- * whose denial would otherwise 403 on every viewport tile) and a host can
257
- * render its "no preview" state instead of error tiles.
258
- */
259
- canRender(): boolean;
260
- /**
261
- * Render a page (by its durable pon) to an ENCODED image. Abortable. Encoded
262
- * output is identical for local & cloud and cheap over the wire (vs. raw RGBA).
263
- *
264
- * This is the VIEWER door: the desired `scale` conforms through the
265
- * resolved render points (STRATEGY ∧ POLICY) — the exact demand capped at
266
- * the pixel budget under `continuous`, the advertised ladder under a
267
- * lattice — and same-key requests collapse in the plugin's raster store
268
- * (singleflight + LRU). Scale-precise offline output (export, print)
269
- * belongs on the engine door: `doc.page(pon).render.image(...)`.
270
- */
271
- renderPage(pon: PageObjectNumber, options: RenderPageOptions): Promise<PageImageHandle>;
272
- /**
273
- * The identity of the raster `renderPage` would produce for these options —
274
- * conformed width + annotations flag + epoch, as one stable string. Layers
275
- * key their fetch effect on THIS instead of the raw scale. Under a lattice
276
- * it moves only at rung crossings; under exact-mode `continuous` it tracks
277
- * the demand, is constant above the budget (always the budget width), and
278
- * the LAYER settle-gates adoption so it never refetches mid-gesture.
279
- * Always available: the kernel materializes the policy on `DocumentMeta`
280
- * before the document publishes.
281
- */
282
- renderSourceKey(pon: PageObjectNumber, options: {
283
- scale: number;
284
- includeAnnotations?: boolean;
285
- }): string;
286
- /**
287
- * The canonical viewport a desired scale conforms to for this page —
288
- * always width-kind: the exact demand capped at the budget (exact mode)
289
- * or the snapped rung (ladder/lattice mode).
290
- */
291
- conformViewport(pon: PageObjectNumber, scale: number): PageRenderViewport;
292
- /** Resolved layer-facing paint settings (settle, fade, tiles on/off). */
293
- paintSettings(): PaintSettings;
294
- /** The document's advertised policy (sugar over `DocumentMeta.renderPolicy`). */
295
- renderPolicy(): EngineRenderPolicy;
296
- /**
297
- * This view's tile surface — the ONE tile entry point. `view` is the
298
- * consuming view's identity (`PageContextValue.view`: a stage lens id, or
299
- * a PageView instance id). Tile state is kept PER VIEW × PAGE, so two
300
- * views showing the same page plan independently — a thumbnail rail's
301
- * never-engaging demand cannot disturb the main view's tiles. Binding the
302
- * identity ONCE makes it unforgettable and unmixable: the handle's four
303
- * calls can never disagree about whose state they address. Stable per
304
- * view — safe as a hook/effect dependency.
305
- */
306
- tilesFor(view: string): ViewTiles;
307
- /**
308
- * Version of the raster the given options would produce. Key a long-lived
309
- * render on it: when it bumps, refetch. Base renders version on content
310
- * facts; annotated renders on content AND annotation facts. Bumps only on
311
- * CONFIRMED mutations — never optimistically — so a drag invalidates once,
312
- * at commit.
313
- */
314
- renderEpoch(pon: PageObjectNumber, includeAnnotations?: boolean): number;
315
- /**
316
- * Declare that page pixels changed — the open door for facts the built-in
317
- * event map doesn't know (a plugin's own mutation vocabulary: redaction,
318
- * text edit, anything third-party). Call at CONFIRMATION (after the engine
319
- * write resolves), never for optimistic previews — those belong in overlay
320
- * layers. `pons` omitted = every page; `scope` defaults to 'content'
321
- * (repaint everything) because a caller who doesn't say is safest repainted
322
- * fully. Redundant with a mapped engine event? Harmless — one extra refetch.
323
- */
324
- invalidate(opts?: {
325
- pons?: readonly PageObjectNumber[];
326
- scope?: InvalidateScope;
327
- }): void;
328
- }
329
- declare const RenderToken: import("@embedpdf/core").CapabilityToken<RenderCapability>;
330
- //#endregion
1
+ import { a as RenderPluginOptions, c as FullPageOptions, d as TilePaintSource, f as TilesOptions, i as RenderCapability, l as PageViewDemand, n as PaintSettings, o as RenderState, r as RenderAction, s as RenderToken, t as InvalidateScope, u as TilePaintPlan } from "./contract-CWPMd1OW.js";
331
2
  //#region src/render.plugin.d.ts
332
3
  /**
333
4
  * Document-scoped. The ONE policy consumer in the client stack: the doc-bind
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import { CONTINUOUS_RENDER_POLICY, PermissionDenied, createCapabilityToken, definePlugin } from "@embedpdf/core";
1
+ import { t as RenderToken } from "./contract-BvwW7rrm.js";
2
+ import { CONTINUOUS_RENDER_POLICY, PermissionDenied, definePlugin } from "@embedpdf/core";
2
3
  import { intersectRects } from "@embedpdf/core-geometry";
3
4
  //#region src/paint-plan.ts
4
5
  const EMPTY_TILE_PLAN = {
@@ -1002,9 +1003,6 @@ const renderReducer = (state, a) => {
1002
1003
  };
1003
1004
  };
1004
1005
  //#endregion
1005
- //#region src/types.ts
1006
- const RenderToken = createCapabilityToken("render");
1007
- //#endregion
1008
1006
  //#region src/render.plugin.ts
1009
1007
  /**
1010
1008
  * Document-scoped. The ONE policy consumer in the client stack: the doc-bind