@embedpdf/angular 3.0.0-next.14 → 3.0.0-next.16

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.
Files changed (87) hide show
  1. package/README.md +309 -0
  2. package/dist/README.md +309 -0
  3. package/dist/actions/index.d.ts +34 -16
  4. package/dist/anchored/index.d.ts +67 -0
  5. package/dist/annotation/index.d.ts +602 -0
  6. package/dist/attachment/index.d.ts +29 -0
  7. package/dist/commands/index.d.ts +109 -0
  8. package/dist/fesm2022/embedpdf-angular-actions.mjs +117 -36
  9. package/dist/fesm2022/embedpdf-angular-actions.mjs.map +1 -1
  10. package/dist/fesm2022/embedpdf-angular-anchored.mjs +148 -0
  11. package/dist/fesm2022/embedpdf-angular-anchored.mjs.map +1 -0
  12. package/dist/fesm2022/embedpdf-angular-annotation.mjs +1933 -0
  13. package/dist/fesm2022/embedpdf-angular-annotation.mjs.map +1 -0
  14. package/dist/fesm2022/embedpdf-angular-attachment.mjs +67 -0
  15. package/dist/fesm2022/embedpdf-angular-attachment.mjs.map +1 -0
  16. package/dist/fesm2022/embedpdf-angular-commands.mjs +235 -0
  17. package/dist/fesm2022/embedpdf-angular-commands.mjs.map +1 -0
  18. package/dist/fesm2022/embedpdf-angular-form.mjs +1074 -0
  19. package/dist/fesm2022/embedpdf-angular-form.mjs.map +1 -0
  20. package/dist/fesm2022/embedpdf-angular-history.mjs +54 -0
  21. package/dist/fesm2022/embedpdf-angular-history.mjs.map +1 -0
  22. package/dist/fesm2022/embedpdf-angular-i18n.mjs +100 -0
  23. package/dist/fesm2022/embedpdf-angular-i18n.mjs.map +1 -0
  24. package/dist/fesm2022/embedpdf-angular-interaction.mjs +157 -0
  25. package/dist/fesm2022/embedpdf-angular-interaction.mjs.map +1 -0
  26. package/dist/fesm2022/embedpdf-angular-link.mjs +306 -0
  27. package/dist/fesm2022/embedpdf-angular-link.mjs.map +1 -0
  28. package/dist/fesm2022/embedpdf-angular-measurement.mjs +106 -0
  29. package/dist/fesm2022/embedpdf-angular-measurement.mjs.map +1 -0
  30. package/dist/fesm2022/embedpdf-angular-metadata.mjs +77 -0
  31. package/dist/fesm2022/embedpdf-angular-metadata.mjs.map +1 -0
  32. package/dist/fesm2022/embedpdf-angular-outline.mjs +76 -0
  33. package/dist/fesm2022/embedpdf-angular-outline.mjs.map +1 -0
  34. package/dist/fesm2022/embedpdf-angular-page-edit.mjs +68 -0
  35. package/dist/fesm2022/embedpdf-angular-page-edit.mjs.map +1 -0
  36. package/dist/fesm2022/embedpdf-angular-page-view.mjs +297 -0
  37. package/dist/fesm2022/embedpdf-angular-page-view.mjs.map +1 -0
  38. package/dist/fesm2022/embedpdf-angular-redaction.mjs +93 -0
  39. package/dist/fesm2022/embedpdf-angular-redaction.mjs.map +1 -0
  40. package/dist/fesm2022/embedpdf-angular-render.mjs +331 -69
  41. package/dist/fesm2022/embedpdf-angular-render.mjs.map +1 -1
  42. package/dist/fesm2022/embedpdf-angular-runtime.mjs +1151 -390
  43. package/dist/fesm2022/embedpdf-angular-runtime.mjs.map +1 -1
  44. package/dist/fesm2022/embedpdf-angular-search.mjs +251 -0
  45. package/dist/fesm2022/embedpdf-angular-search.mjs.map +1 -0
  46. package/dist/fesm2022/embedpdf-angular-selection.mjs +477 -0
  47. package/dist/fesm2022/embedpdf-angular-selection.mjs.map +1 -0
  48. package/dist/fesm2022/embedpdf-angular-shell.mjs +177 -0
  49. package/dist/fesm2022/embedpdf-angular-shell.mjs.map +1 -0
  50. package/dist/fesm2022/embedpdf-angular-signature.mjs +120 -0
  51. package/dist/fesm2022/embedpdf-angular-signature.mjs.map +1 -0
  52. package/dist/fesm2022/embedpdf-angular-stage.mjs +688 -288
  53. package/dist/fesm2022/embedpdf-angular-stage.mjs.map +1 -1
  54. package/dist/fesm2022/embedpdf-angular-stamp.mjs +169 -0
  55. package/dist/fesm2022/embedpdf-angular-stamp.mjs.map +1 -0
  56. package/dist/fesm2022/embedpdf-angular-testing.mjs +89 -0
  57. package/dist/fesm2022/embedpdf-angular-testing.mjs.map +1 -0
  58. package/dist/fesm2022/embedpdf-angular-toolbar.mjs +1123 -0
  59. package/dist/fesm2022/embedpdf-angular-toolbar.mjs.map +1 -0
  60. package/dist/fesm2022/embedpdf-angular-view-manager.mjs +69 -0
  61. package/dist/fesm2022/embedpdf-angular-view-manager.mjs.map +1 -0
  62. package/dist/fesm2022/embedpdf-angular.mjs +25 -3
  63. package/dist/fesm2022/embedpdf-angular.mjs.map +1 -1
  64. package/dist/form/index.d.ts +79 -0
  65. package/dist/history/index.d.ts +28 -0
  66. package/dist/i18n/index.d.ts +52 -0
  67. package/dist/index.d.ts +22 -0
  68. package/dist/interaction/index.d.ts +58 -0
  69. package/dist/link/index.d.ts +77 -0
  70. package/dist/measurement/index.d.ts +46 -0
  71. package/dist/metadata/index.d.ts +51 -0
  72. package/dist/outline/index.d.ts +32 -0
  73. package/dist/page-edit/index.d.ts +27 -0
  74. package/dist/page-view/index.d.ts +94 -0
  75. package/dist/redaction/index.d.ts +38 -0
  76. package/dist/render/index.d.ts +45 -6
  77. package/dist/runtime/index.d.ts +579 -199
  78. package/dist/search/index.d.ts +71 -0
  79. package/dist/selection/index.d.ts +141 -0
  80. package/dist/shell/index.d.ts +88 -0
  81. package/dist/signature/index.d.ts +45 -0
  82. package/dist/stage/index.d.ts +242 -141
  83. package/dist/stamp/index.d.ts +58 -0
  84. package/dist/testing/index.d.ts +53 -0
  85. package/dist/toolbar/index.d.ts +257 -0
  86. package/dist/view-manager/index.d.ts +23 -0
  87. package/package.json +145 -14
@@ -1,119 +1,381 @@
1
- import { RenderToken } from '@embedpdf/plugin-render';
1
+ import { RenderToken, renderPlugin } from '@embedpdf/plugin-render';
2
2
  export * from '@embedpdf/plugin-render';
3
- import { isPlatformBrowser } from '@angular/common';
4
3
  import * as i0 from '@angular/core';
5
- import { input, signal, inject, PLATFORM_ID, effect, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
6
- import { injectPage, injectCapability, injectSelector } from '@embedpdf/angular/runtime';
4
+ import { Injectable, input, inject, ElementRef, computed, effect, untracked, Directive, signal, ChangeDetectionStrategy, Component, viewChild, PLATFORM_ID } from '@angular/core';
5
+ import { pluginService, CapabilityBinding, injectKernelHost, injectPage, devWarn, injectPaintedParts } from '@embedpdf/angular/runtime';
6
+ import { isPlatformBrowser } from '@angular/common';
7
+ import { RenderToken as RenderToken$1 } from '@embedpdf/plugin-render/contract/host';
8
+ import { bindPaintedImage, pictureLayerOptionsOf, partsDrawnTwice } from '@embedpdf/web';
7
9
 
8
10
  /**
9
- * `<epdf-render-layer>` — the Angular view of @embedpdf/plugin-render.
11
+ * The render plugin's service and feature:
10
12
  *
11
- * Paints a page to an `<img>` from the engine's ENCODED image() (identical for
12
- * local & cloud). Abortable (cancels when the camera moves / the layer is
13
- * destroyed) and leak-free (revokes the object URL). React's useEffect deps
14
- * become `effect()` auto-tracking: scale, the annotations input, and the
15
- * render epoch are the tracked reads; everything else is untracked.
13
+ * withRender(options) the plugin, for provideEmbedPdf()
14
+ * inject(EpdfRender) pictures of pages on demand (`renderPage`, `renderPages`), redraws
15
+ * (`invalidate`, `invalidated$`), and the settings (`settings()`)
16
+ */
17
+ /**
18
+ * Pictures of pages, apart from the Stage: a thumbnail, a page at an exact width, every page in
19
+ * batches. `invalidate()` redraws pages, `invalidated$` tells you when they were, and
20
+ * `settings()` / `updateSettings()` are the picture budget and tiles.
16
21
  */
22
+ class EpdfRender extends pluginService({
23
+ name: 'EpdfRender',
24
+ feature: 'withRender()',
25
+ token: RenderToken,
26
+ methods: [
27
+ 'canRender',
28
+ 'renderPage',
29
+ 'renderThumbnail',
30
+ 'renderPages',
31
+ 'getRenderPolicy',
32
+ 'getRenderEpoch',
33
+ 'invalidate',
34
+ ],
35
+ events: ['onInvalidated'],
36
+ }) {
37
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfRender, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
38
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfRender, providedIn: 'root' });
39
+ }
40
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfRender, decorators: [{
41
+ type: Injectable,
42
+ args: [{ providedIn: 'root' }]
43
+ }] });
44
+ /** The render plugin, with its settings: `withRender({ fullPage: { maxWidth: 1280 } })`. */
45
+ function withRender(options) {
46
+ return { plugins: [renderPlugin(options)], services: [EpdfRender] };
47
+ }
48
+
49
+ /**
50
+ * `<epdf-render-layer>`: the page's picture, in two planes.
51
+ *
52
+ * - The base: one picture of the whole page, at the size the render plugin resolves (the
53
+ * settled demand within the pixel budget on a local engine, the advertised ladder on a
54
+ * cloud one). Always there; the instant backdrop.
55
+ * - The tiles: sharper pieces above it, when the view wants more pixels than the base may
56
+ * spend. A thumbnail-sized demand engages none: the arithmetic is the configuration.
57
+ *
58
+ * The layer only paints: plain images, bound with `@embedpdf/web`'s painted-image helper, which
59
+ * reports each tile painted after the browser could show it. What to fetch, when to settle,
60
+ * what to keep and when to let go are all the render plugin's; mid-gesture the pictures are
61
+ * simply scaled with the page until the plugin hands down new ones.
62
+ */
63
+ const NO_PAINT_SETTINGS = Object.freeze({ tiles: false });
64
+ const NO_PLAN = Object.freeze({
65
+ engaged: false,
66
+ paint: [],
67
+ fetching: [],
68
+ stamp: '',
69
+ });
70
+ /** The render plugin's host side, for the document the page belongs to. */
71
+ const renderOf = (page, what) => new CapabilityBinding(injectKernelHost(what), () => RenderToken$1, () => page.documentId);
72
+ /**
73
+ * One tile: binds the painted-image helper to the element for the tile's picture. The helper
74
+ * hides the image until it's loaded, tells the tile's view it's painted after the browser could
75
+ * show it, and unpainted when the element goes.
76
+ */
77
+ class EpdfTileImage {
78
+ tile = input.required(...(ngDevMode ? [{ debugName: "tile", alias: 'epdfTile' }] : [{ alias: 'epdfTile' }]));
79
+ /** The view the tile is painted for; it hears when the picture is painted and when it goes. */
80
+ view = input.required(...(ngDevMode ? [{ debugName: "view", alias: 'epdfTileView' }] : [{ alias: 'epdfTileView' }]));
81
+ constructor() {
82
+ const element = inject(ElementRef).nativeElement;
83
+ const page = injectPage('<epdf-render-layer>');
84
+ // Bound again only for a new picture, not for every new plan that holds the same one.
85
+ const handle = computed(() => this.tile().handle, ...(ngDevMode ? [{ debugName: "handle" }] : []));
86
+ // The view is told directly, not through outputs: the picture goes when the element does,
87
+ // and an output emitted while its directive is destroyed is dropped.
88
+ effect((onCleanup) => {
89
+ const picture = handle();
90
+ const view = this.view();
91
+ const key = untracked(this.tile).key;
92
+ onCleanup(bindPaintedImage(element, picture, {
93
+ onPainted: () => view?.markPainted(page.ref, key),
94
+ onUnpainted: () => view?.markUnpainted(page.ref, key),
95
+ }));
96
+ });
97
+ }
98
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfTileImage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
99
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.4", type: EpdfTileImage, isStandalone: true, selector: "img[epdfTile]", inputs: { tile: { classPropertyName: "tile", publicName: "epdfTile", isSignal: true, isRequired: true, transformFunction: null }, view: { classPropertyName: "view", publicName: "epdfTileView", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
100
+ }
101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfTileImage, decorators: [{
102
+ type: Directive,
103
+ args: [{ selector: 'img[epdfTile]' }]
104
+ }], ctorParameters: () => [] });
105
+ /**
106
+ * The tiles: the render plugin's paint plan for this page in this view, as images keyed by
107
+ * tile. They're placed in view pixels, not in page points under a scaled box: browsers round
108
+ * lengths to 1/64 pixel before transforms apply, and under a 25× zoom that rounding would move
109
+ * each tile by up to half a pixel, showing seams that shift with every zoom step.
110
+ */
111
+ class EpdfTilePlane {
112
+ layers = input.required(...(ngDevMode ? [{ debugName: "layers" }] : []));
113
+ page = injectPage('<epdf-render-layer>');
114
+ render = renderOf(this.page, '<epdf-render-layer>');
115
+ /**
116
+ * This view's tile surface. Tile state is kept per view and page, so a thumbnail strip's
117
+ * small demand never disturbs the main view's tiles.
118
+ */
119
+ view = signal(null, ...(ngDevMode ? [{ debugName: "view" }] : []));
120
+ /**
121
+ * Which page this plane plans for: a new value only when the page changes (a page view can be
122
+ * given another page), never with the camera.
123
+ */
124
+ pageRef = computed(() => this.page.ref, ...(ngDevMode ? [{ debugName: "pageRef" }] : []));
125
+ plan = this.render.host.read(() => this.view()?.getPlan(this.pageRef()) ?? NO_PLAN, () => NO_PLAN);
126
+ constructor() {
127
+ // The page's claim on the view, let go of when the page changes or the plane goes: that
128
+ // stops what's still being fetched for it, and what arrived stays cached. Before the view's
129
+ // own effect, so as the plane goes the page is released before the view is disposed.
130
+ effect((onCleanup) => {
131
+ const view = this.view();
132
+ const page = this.pageRef();
133
+ if (view)
134
+ onCleanup(() => view.release(page));
135
+ });
136
+ effect((onCleanup) => {
137
+ const render = this.render.capability();
138
+ if (!render)
139
+ return;
140
+ const view = untracked(() => render.createViewDemand(this.page.view));
141
+ this.view.set(view);
142
+ onCleanup(() => {
143
+ view.dispose();
144
+ this.view.set(null);
145
+ });
146
+ });
147
+ // What the view wants, on every camera frame: setting it is the one call that plans and
148
+ // fetches; reading the paint plan above is pure.
149
+ effect(() => {
150
+ const view = this.view();
151
+ const page = this.pageRef();
152
+ const transform = this.page.transform();
153
+ const layers = this.layers();
154
+ if (!view)
155
+ return;
156
+ untracked(() => {
157
+ const demand = this.page.getViewDemand?.() ?? {
158
+ desiredDeviceWidth: transform.deviceWidth,
159
+ };
160
+ view.setDemand(page, demand, layers);
161
+ });
162
+ });
163
+ }
164
+ /** A picture whose size doesn't match its box would be stretched into place: a stale tile. */
165
+ checkSize(event, tile) {
166
+ const naturalWidth = event.target.naturalWidth;
167
+ const expected = Math.round(tile.rect.width * tile.scale);
168
+ if (naturalWidth > 0 && Math.abs(naturalWidth - expected) > 1) {
169
+ devWarn('tile-size', `[render] tile picture ${naturalWidth}px wide does not match its box (expected ` +
170
+ `~${expected}px): a stale picture? key=${tile.key}`);
171
+ }
172
+ }
173
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfTilePlane, deps: [], target: i0.ɵɵFactoryTarget.Component });
174
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: EpdfTilePlane, isStandalone: true, selector: "epdf-tile-plane", inputs: { layers: { classPropertyName: "layers", publicName: "layers", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
175
+ @if (plan().paint.length > 0) {
176
+ <!-- Its own stacking context: the tiles' z-index ranks stay inside it, below the
177
+ annotations and the page chrome, even mid-zoom while coarse and sharp tiles mix. -->
178
+ <div
179
+ style="position: absolute; left: 0; top: 0; pointer-events: none; isolation: isolate"
180
+ [style.width.px]="page.transform().contentWidth"
181
+ [style.height.px]="page.transform().contentHeight"
182
+ >
183
+ @for (tile of plan().paint; track tile.key) {
184
+ <img
185
+ alt=""
186
+ draggable="false"
187
+ style="position: absolute"
188
+ [epdfTile]="tile"
189
+ [epdfTileView]="view()"
190
+ [style.left.px]="tile.rect.x * page.transform().viewScale"
191
+ [style.top.px]="tile.rect.y * page.transform().viewScale"
192
+ [style.width.px]="tile.rect.width * page.transform().viewScale"
193
+ [style.height.px]="tile.rect.height * page.transform().viewScale"
194
+ [style.z-index]="tile.z"
195
+ (load)="checkSize($event, tile)"
196
+ />
197
+ }
198
+ </div>
199
+ }
200
+ `, isInline: true, dependencies: [{ kind: "directive", type: EpdfTileImage, selector: "img[epdfTile]", inputs: ["epdfTile", "epdfTileView"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
201
+ }
202
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfTilePlane, decorators: [{
203
+ type: Component,
204
+ args: [{
205
+ selector: 'epdf-tile-plane',
206
+ imports: [EpdfTileImage],
207
+ changeDetection: ChangeDetectionStrategy.OnPush,
208
+ template: `
209
+ @if (plan().paint.length > 0) {
210
+ <!-- Its own stacking context: the tiles' z-index ranks stay inside it, below the
211
+ annotations and the page chrome, even mid-zoom while coarse and sharp tiles mix. -->
212
+ <div
213
+ style="position: absolute; left: 0; top: 0; pointer-events: none; isolation: isolate"
214
+ [style.width.px]="page.transform().contentWidth"
215
+ [style.height.px]="page.transform().contentHeight"
216
+ >
217
+ @for (tile of plan().paint; track tile.key) {
218
+ <img
219
+ alt=""
220
+ draggable="false"
221
+ style="position: absolute"
222
+ [epdfTile]="tile"
223
+ [epdfTileView]="view()"
224
+ [style.left.px]="tile.rect.x * page.transform().viewScale"
225
+ [style.top.px]="tile.rect.y * page.transform().viewScale"
226
+ [style.width.px]="tile.rect.width * page.transform().viewScale"
227
+ [style.height.px]="tile.rect.height * page.transform().viewScale"
228
+ [style.z-index]="tile.z"
229
+ (load)="checkSize($event, tile)"
230
+ />
231
+ }
232
+ </div>
233
+ }
234
+ `,
235
+ }]
236
+ }], ctorParameters: () => [] });
17
237
  class EpdfRenderLayer {
18
238
  /**
19
- * Bake annotations into the page bitmap (default true). Pass false when an
20
- * annotation layer owns annotation rendering, so they aren't drawn twice.
239
+ * Draw the annotations into the page's picture (`true`) or leave them out (`false`). Left
240
+ * unset, the picture leaves them to an `<epdf-annotation-layer>` on the page, and otherwise
241
+ * draws them when the user may read them.
242
+ */
243
+ annotations = input(undefined, ...(ngDevMode ? [{ debugName: "annotations" }] : []));
244
+ /** The same for the form fields, which an `<epdf-form-layer>` paints. */
245
+ formFields = input(undefined, ...(ngDevMode ? [{ debugName: "formFields" }] : []));
246
+ /**
247
+ * The sharp tiles over the picture when zoomed in (default true). Whether they cost anything
248
+ * is decided by what the view wants; set it to false only for a view that must never tile.
249
+ */
250
+ tiles = input(true, ...(ngDevMode ? [{ debugName: "tiles" }] : []));
251
+ page = injectPage('<epdf-render-layer>');
252
+ render = renderOf(this.page, '<epdf-render-layer>');
253
+ /** The same object until a setting it reads changes. */
254
+ paintSettings = this.render.select((render) => render.getPaintSettings(), NO_PAINT_SETTINGS, Object.is);
255
+ parts = computed(() => ({
256
+ annotations: this.annotations(),
257
+ formFields: this.formFields(),
258
+ }), ...(ngDevMode ? [{ debugName: "parts" }] : []));
259
+ painted = injectPaintedParts(() => this.page.ref);
260
+ may = this.render.select((render) => render.getLayerRights(), null, Object.is);
261
+ /** The parts the picture draws; `null` until the page's layers have said what they paint. */
262
+ layers = computed(() => {
263
+ const painted = this.painted();
264
+ const may = this.may();
265
+ return painted && may ? pictureLayerOptionsOf(painted, this.parts(), may) : null;
266
+ }, ...(ngDevMode ? [{ debugName: "layers" }] : []));
267
+ /**
268
+ * The picture's identity: its size, the parts it draws and the page's version. Within a
269
+ * size step it doesn't move as you zoom (the page's transform scales the picture), so
270
+ * nothing is fetched again; it moves at a step and when the page changes.
21
271
  */
22
- annotations = input(true, ...(ngDevMode ? [{ debugName: "annotations" }] : []));
23
- page = injectPage();
24
- render = injectCapability(RenderToken);
25
- // ONE tracked dependency: the raster's canonical identity — conformed
26
- // viewport + annotations flag + epoch.
27
- // Inside a lattice rung, zoom changes don't move it: no refetch, no DOM
28
- // churn — the stage's CSS transform does the scaling. It changes exactly at
29
- // rung crossings and on CONFIRMED mutations (epoch bumps at commit, never
30
- // mid-gesture). Under `continuous` it embeds the exact scale — v2 behavior
31
- // byte-for-byte. The policy behind it is a document fact the kernel
32
- // materialized before publish, so the key is always computable.
33
- sourceKey = injectSelector(RenderToken, (c) => c.renderSourceKey(this.page.pon, {
34
- scale: this.page.transform().renderScale,
35
- includeAnnotations: this.annotations(),
36
- }));
37
- src = signal(null, ...(ngDevMode ? [{ debugName: "src" }] : []));
272
+ sourceKey = this.render.select((render) => {
273
+ const layers = this.layers();
274
+ return layers
275
+ ? render.getSourceKey(this.page.ref, {
276
+ scale: this.page.transform().renderScale,
277
+ ...layers,
278
+ })
279
+ : null;
280
+ }, null, Object.is);
281
+ picture = viewChild.required('picture');
38
282
  constructor() {
283
+ effect(() => {
284
+ const painted = this.painted();
285
+ if (painted && partsDrawnTwice(painted, this.parts()).length > 0) {
286
+ devWarn('render-layer-draws-what-a-layer-paints', '<epdf-render-layer [annotations]> or [formFields] draws what an ' +
287
+ '<epdf-annotation-layer> or an <epdf-form-layer> on the page paints too, so it shows ' +
288
+ 'twice. Leave the input out: the picture leaves out what a layer paints.');
289
+ }
290
+ });
39
291
  if (!isPlatformBrowser(inject(PLATFORM_ID)))
40
292
  return;
41
293
  effect((onCleanup) => {
42
- // Tracked reads — the effect's dependency set. `sourceKey` folds scale,
43
- // annotations, and the epoch into one identity; a stale scale read
44
- // inside the untracked body is harmless by construction (any scale in
45
- // this rung produces this key's canonical request).
46
- const render = this.render();
47
- this.sourceKey();
48
- const includeAnnotations = this.annotations();
294
+ const render = this.render.capability();
295
+ const key = this.sourceKey();
296
+ const layers = this.layers();
297
+ if (!render || key === null || !layers)
298
+ return;
49
299
  const controller = new AbortController();
50
300
  let revoke;
51
301
  onCleanup(() => {
52
302
  controller.abort();
53
303
  revoke?.();
54
304
  });
55
- untracked(() => {
56
- const scale = this.page.transform().renderScale;
57
- void (async () => {
58
- try {
59
- // The capability conforms this to the policy (lattice → ladder
60
- // width, continuous → this exact scale) and collapses same-key
61
- // asks in its raster store.
62
- const image = await render.renderPage(this.page.pon, {
63
- scale,
64
- includeAnnotations,
65
- signal: controller.signal,
66
- });
67
- const objectUrl = await image.objectUrl(controller.signal);
68
- if (controller.signal.aborted) {
69
- objectUrl.revoke();
70
- return;
71
- }
72
- revoke = objectUrl.revoke;
73
- this.src.set(objectUrl.url);
305
+ // Any scale inside this key's step asks for this key's picture, so reading it now is safe.
306
+ const scale = untracked(() => this.page.transform().renderScale);
307
+ void (async () => {
308
+ try {
309
+ const image = await render.renderSource(this.page.ref, {
310
+ scale,
311
+ ...layers,
312
+ view: this.page.view,
313
+ signal: controller.signal,
314
+ });
315
+ const objectUrl = await image.objectUrl().abortWith(controller.signal);
316
+ if (controller.signal.aborted) {
317
+ objectUrl.revoke();
318
+ return;
74
319
  }
75
- catch {
76
- /* aborted (camera moved / destroyed) or render failed */
77
- }
78
- })();
79
- });
320
+ revoke = objectUrl.revoke;
321
+ // Set on the element now, not through a binding. A binding applies at the next change
322
+ // detection, and the key can move on before that, revoking this URL: the image would
323
+ // then be handed a revoked URL and lose its picture. Set at once, the browser keeps
324
+ // showing the old picture until the new one is decoded and never asks for the old URL
325
+ // again, so revoking it when the next one comes is safe.
326
+ this.picture().nativeElement.src = objectUrl.url;
327
+ }
328
+ catch {
329
+ // Cancelled (the camera moved on, the layer went away) or the render failed.
330
+ }
331
+ })();
80
332
  });
81
333
  }
82
334
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfRenderLayer, deps: [], target: i0.ɵɵFactoryTarget.Component });
83
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.4", type: EpdfRenderLayer, isStandalone: true, selector: "epdf-render-layer", inputs: { annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
335
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: EpdfRenderLayer, isStandalone: true, selector: "epdf-render-layer", inputs: { annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, formFields: { classPropertyName: "formFields", publicName: "formFields", isSignal: true, isRequired: false, transformFunction: null }, tiles: { classPropertyName: "tiles", publicName: "tiles", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "picture", first: true, predicate: ["picture"], descendants: true, isSignal: true }], ngImport: i0, template: `
84
336
  <img
337
+ #picture
85
338
  alt=""
86
339
  draggable="false"
87
- [attr.src]="src()"
88
- style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;"
340
+ style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none"
89
341
  />
90
- `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
342
+ @if (tiles() && paintSettings().tiles && layers(); as drawn) {
343
+ <epdf-tile-plane [layers]="drawn" />
344
+ }
345
+ `, isInline: true, dependencies: [{ kind: "component", type: EpdfTilePlane, selector: "epdf-tile-plane", inputs: ["layers"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
91
346
  }
92
347
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfRenderLayer, decorators: [{
93
348
  type: Component,
94
349
  args: [{
95
350
  selector: 'epdf-render-layer',
96
- standalone: true,
351
+ imports: [EpdfTilePlane],
97
352
  changeDetection: ChangeDetectionStrategy.OnPush,
98
353
  template: `
99
354
  <img
355
+ #picture
100
356
  alt=""
101
357
  draggable="false"
102
- [attr.src]="src()"
103
- style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;"
358
+ style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none"
104
359
  />
360
+ @if (tiles() && paintSettings().tiles && layers(); as drawn) {
361
+ <epdf-tile-plane [layers]="drawn" />
362
+ }
105
363
  `,
106
364
  }]
107
365
  }], ctorParameters: () => [] });
108
366
 
109
367
  /**
110
- * @embedpdf/angular/render — `<epdf-render-layer>`.
368
+ * @embedpdf/angular/render: the page pictures.
369
+ *
370
+ * withRender(options) the plugin, for provideEmbedPdf()
371
+ * inject(EpdfRender) pictures on demand, redraws, the settings
372
+ * <epdf-render-layer> the picture of each page on a Stage
111
373
  */
112
- // One-line-per-feature: registration travels with the UI.
374
+ // The plugin's types and helpers, so app code has one import for the feature.
113
375
 
114
376
  /**
115
377
  * Generated bundle index. Do not edit.
116
378
  */
117
379
 
118
- export { EpdfRenderLayer };
380
+ export { EpdfRender, EpdfRenderLayer, withRender };
119
381
  //# sourceMappingURL=embedpdf-angular-render.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"embedpdf-angular-render.mjs","sources":["../../render/src/render-layer.ts","../../render/src/public_api.ts","../../render/src/embedpdf-angular-render.ts"],"sourcesContent":["/**\n * `<epdf-render-layer>` — the Angular view of @embedpdf/plugin-render.\n *\n * Paints a page to an `<img>` from the engine's ENCODED image() (identical for\n * local & cloud). Abortable (cancels when the camera moves / the layer is\n * destroyed) and leak-free (revokes the object URL). React's useEffect deps\n * become `effect()` auto-tracking: scale, the annotations input, and the\n * render epoch are the tracked reads; everything else is untracked.\n */\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n effect,\n inject,\n input,\n PLATFORM_ID,\n signal,\n untracked,\n} from '@angular/core';\nimport { RenderToken } from '@embedpdf/plugin-render';\nimport { injectCapability, injectPage, injectSelector } from '@embedpdf/angular/runtime';\n\n@Component({\n selector: 'epdf-render-layer',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <img\n alt=\"\"\n draggable=\"false\"\n [attr.src]=\"src()\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n />\n `,\n})\nexport class EpdfRenderLayer {\n /**\n * Bake annotations into the page bitmap (default true). Pass false when an\n * annotation layer owns annotation rendering, so they aren't drawn twice.\n */\n readonly annotations = input(true);\n\n private readonly page = injectPage();\n private readonly render = injectCapability(RenderToken);\n // ONE tracked dependency: the raster's canonical identity — conformed\n // viewport + annotations flag + epoch.\n // Inside a lattice rung, zoom changes don't move it: no refetch, no DOM\n // churn — the stage's CSS transform does the scaling. It changes exactly at\n // rung crossings and on CONFIRMED mutations (epoch bumps at commit, never\n // mid-gesture). Under `continuous` it embeds the exact scale — v2 behavior\n // byte-for-byte. The policy behind it is a document fact the kernel\n // materialized before publish, so the key is always computable.\n private readonly sourceKey = injectSelector(RenderToken, (c) =>\n c.renderSourceKey(this.page.pon, {\n scale: this.page.transform().renderScale,\n includeAnnotations: this.annotations(),\n }),\n );\n protected readonly src = signal<string | null>(null);\n\n constructor() {\n if (!isPlatformBrowser(inject(PLATFORM_ID))) return;\n effect((onCleanup) => {\n // Tracked reads — the effect's dependency set. `sourceKey` folds scale,\n // annotations, and the epoch into one identity; a stale scale read\n // inside the untracked body is harmless by construction (any scale in\n // this rung produces this key's canonical request).\n const render = this.render();\n this.sourceKey();\n const includeAnnotations = this.annotations();\n\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n onCleanup(() => {\n controller.abort();\n revoke?.();\n });\n\n untracked(() => {\n const scale = this.page.transform().renderScale;\n void (async () => {\n try {\n // The capability conforms this to the policy (lattice → ladder\n // width, continuous → this exact scale) and collapses same-key\n // asks in its raster store.\n const image = await render.renderPage(this.page.pon, {\n scale,\n includeAnnotations,\n signal: controller.signal,\n });\n const objectUrl = await image.objectUrl(controller.signal);\n if (controller.signal.aborted) {\n objectUrl.revoke();\n return;\n }\n revoke = objectUrl.revoke;\n this.src.set(objectUrl.url);\n } catch {\n /* aborted (camera moved / destroyed) or render failed */\n }\n })();\n });\n });\n }\n}\n","/**\n * @embedpdf/angular/render — `<epdf-render-layer>`.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-render';\nexport * from './render-layer';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"embedpdf-angular-render.mjs","sources":["../../render/src/render.ts","../../render/src/render-layer.ts","../../render/src/public_api.ts","../../render/src/embedpdf-angular-render.ts"],"sourcesContent":["/**\n * The render plugin's service and feature:\n *\n * withRender(options) the plugin, for provideEmbedPdf()\n * inject(EpdfRender) pictures of pages on demand (`renderPage`, `renderPages`), redraws\n * (`invalidate`, `invalidated$`), and the settings (`settings()`)\n */\nimport { Injectable } from '@angular/core';\nimport { pluginService, type EmbedPdfFeature } from '@embedpdf/angular/runtime';\nimport { renderPlugin, RenderToken, type RenderConfig } from '@embedpdf/plugin-render';\n\n/**\n * Pictures of pages, apart from the Stage: a thumbnail, a page at an exact width, every page in\n * batches. `invalidate()` redraws pages, `invalidated$` tells you when they were, and\n * `settings()` / `updateSettings()` are the picture budget and tiles.\n */\n@Injectable({ providedIn: 'root' })\nexport class EpdfRender extends pluginService({\n name: 'EpdfRender',\n feature: 'withRender()',\n token: RenderToken,\n methods: [\n 'canRender',\n 'renderPage',\n 'renderThumbnail',\n 'renderPages',\n 'getRenderPolicy',\n 'getRenderEpoch',\n 'invalidate',\n ],\n events: ['onInvalidated'],\n}) {}\n\n/** The render plugin, with its settings: `withRender({ fullPage: { maxWidth: 1280 } })`. */\nexport function withRender(options?: RenderConfig): EmbedPdfFeature {\n return { plugins: [renderPlugin(options)], services: [EpdfRender] };\n}\n","/**\n * `<epdf-render-layer>`: the page's picture, in two planes.\n *\n * - The base: one picture of the whole page, at the size the render plugin resolves (the\n * settled demand within the pixel budget on a local engine, the advertised ladder on a\n * cloud one). Always there; the instant backdrop.\n * - The tiles: sharper pieces above it, when the view wants more pixels than the base may\n * spend. A thumbnail-sized demand engages none: the arithmetic is the configuration.\n *\n * The layer only paints: plain images, bound with `@embedpdf/web`'s painted-image helper, which\n * reports each tile painted after the browser could show it. What to fetch, when to settle,\n * what to keep and when to let go are all the render plugin's; mid-gesture the pictures are\n * simply scaled with the page until the plugin hands down new ones.\n */\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n PLATFORM_ID,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport {\n RenderToken,\n type PageLayerOptions,\n type PaintSettings,\n type RenderHostCapability,\n type TilePaintPlan,\n type TilePaintSource,\n type ViewDemand,\n} from '@embedpdf/plugin-render/contract/host';\nimport { bindPaintedImage, partsDrawnTwice, pictureLayerOptionsOf } from '@embedpdf/web';\nimport {\n CapabilityBinding,\n devWarn,\n injectKernelHost,\n injectPage,\n injectPaintedParts,\n type EpdfPageContext,\n} from '@embedpdf/angular/runtime';\n\nconst NO_PAINT_SETTINGS: PaintSettings = Object.freeze({ tiles: false });\nconst NO_PLAN: TilePaintPlan = Object.freeze({\n engaged: false,\n paint: [],\n fetching: [],\n stamp: '',\n});\n\n/** The render plugin's host side, for the document the page belongs to. */\nconst renderOf = (page: EpdfPageContext, what: string) =>\n new CapabilityBinding<RenderHostCapability>(\n injectKernelHost(what),\n () => RenderToken,\n () => page.documentId,\n );\n\n/**\n * One tile: binds the painted-image helper to the element for the tile's picture. The helper\n * hides the image until it's loaded, tells the tile's view it's painted after the browser could\n * show it, and unpainted when the element goes.\n */\n@Directive({ selector: 'img[epdfTile]' })\nexport class EpdfTileImage {\n readonly tile = input.required<TilePaintSource>({ alias: 'epdfTile' });\n /** The view the tile is painted for; it hears when the picture is painted and when it goes. */\n readonly view = input.required<ViewDemand | null>({ alias: 'epdfTileView' });\n\n constructor() {\n const element = inject<ElementRef<HTMLImageElement>>(ElementRef).nativeElement;\n const page = injectPage('<epdf-render-layer>');\n // Bound again only for a new picture, not for every new plan that holds the same one.\n const handle = computed(() => this.tile().handle);\n // The view is told directly, not through outputs: the picture goes when the element does,\n // and an output emitted while its directive is destroyed is dropped.\n effect((onCleanup) => {\n const picture = handle();\n const view = this.view();\n const key = untracked(this.tile).key;\n onCleanup(\n bindPaintedImage(element, picture, {\n onPainted: () => view?.markPainted(page.ref, key),\n onUnpainted: () => view?.markUnpainted(page.ref, key),\n }),\n );\n });\n }\n}\n\n/**\n * The tiles: the render plugin's paint plan for this page in this view, as images keyed by\n * tile. They're placed in view pixels, not in page points under a scaled box: browsers round\n * lengths to 1/64 pixel before transforms apply, and under a 25× zoom that rounding would move\n * each tile by up to half a pixel, showing seams that shift with every zoom step.\n */\n@Component({\n selector: 'epdf-tile-plane',\n imports: [EpdfTileImage],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (plan().paint.length > 0) {\n <!-- Its own stacking context: the tiles' z-index ranks stay inside it, below the\n annotations and the page chrome, even mid-zoom while coarse and sharp tiles mix. -->\n <div\n style=\"position: absolute; left: 0; top: 0; pointer-events: none; isolation: isolate\"\n [style.width.px]=\"page.transform().contentWidth\"\n [style.height.px]=\"page.transform().contentHeight\"\n >\n @for (tile of plan().paint; track tile.key) {\n <img\n alt=\"\"\n draggable=\"false\"\n style=\"position: absolute\"\n [epdfTile]=\"tile\"\n [epdfTileView]=\"view()\"\n [style.left.px]=\"tile.rect.x * page.transform().viewScale\"\n [style.top.px]=\"tile.rect.y * page.transform().viewScale\"\n [style.width.px]=\"tile.rect.width * page.transform().viewScale\"\n [style.height.px]=\"tile.rect.height * page.transform().viewScale\"\n [style.z-index]=\"tile.z\"\n (load)=\"checkSize($event, tile)\"\n />\n }\n </div>\n }\n `,\n})\nexport class EpdfTilePlane {\n readonly layers = input.required<PageLayerOptions>();\n\n protected readonly page = injectPage('<epdf-render-layer>');\n private readonly render = renderOf(this.page, '<epdf-render-layer>');\n /**\n * This view's tile surface. Tile state is kept per view and page, so a thumbnail strip's\n * small demand never disturbs the main view's tiles.\n */\n protected readonly view = signal<ViewDemand | null>(null);\n /**\n * Which page this plane plans for: a new value only when the page changes (a page view can be\n * given another page), never with the camera.\n */\n private readonly pageRef = computed(() => this.page.ref);\n protected readonly plan = this.render.host.read(\n () => this.view()?.getPlan(this.pageRef()) ?? NO_PLAN,\n () => NO_PLAN,\n );\n\n constructor() {\n // The page's claim on the view, let go of when the page changes or the plane goes: that\n // stops what's still being fetched for it, and what arrived stays cached. Before the view's\n // own effect, so as the plane goes the page is released before the view is disposed.\n effect((onCleanup) => {\n const view = this.view();\n const page = this.pageRef();\n if (view) onCleanup(() => view.release(page));\n });\n effect((onCleanup) => {\n const render = this.render.capability();\n if (!render) return;\n const view = untracked(() => render.createViewDemand(this.page.view));\n this.view.set(view);\n onCleanup(() => {\n view.dispose();\n this.view.set(null);\n });\n });\n // What the view wants, on every camera frame: setting it is the one call that plans and\n // fetches; reading the paint plan above is pure.\n effect(() => {\n const view = this.view();\n const page = this.pageRef();\n const transform = this.page.transform();\n const layers = this.layers();\n if (!view) return;\n untracked(() => {\n const demand = this.page.getViewDemand?.() ?? {\n desiredDeviceWidth: transform.deviceWidth,\n };\n view.setDemand(page, demand, layers);\n });\n });\n }\n\n /** A picture whose size doesn't match its box would be stretched into place: a stale tile. */\n protected checkSize(event: Event, tile: TilePaintSource): void {\n const naturalWidth = (event.target as HTMLImageElement).naturalWidth;\n const expected = Math.round(tile.rect.width * tile.scale);\n if (naturalWidth > 0 && Math.abs(naturalWidth - expected) > 1) {\n devWarn(\n 'tile-size',\n `[render] tile picture ${naturalWidth}px wide does not match its box (expected ` +\n `~${expected}px): a stale picture? key=${tile.key}`,\n );\n }\n }\n}\n\n@Component({\n selector: 'epdf-render-layer',\n imports: [EpdfTilePlane],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <img\n #picture\n alt=\"\"\n draggable=\"false\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none\"\n />\n @if (tiles() && paintSettings().tiles && layers(); as drawn) {\n <epdf-tile-plane [layers]=\"drawn\" />\n }\n `,\n})\nexport class EpdfRenderLayer {\n /**\n * Draw the annotations into the page's picture (`true`) or leave them out (`false`). Left\n * unset, the picture leaves them to an `<epdf-annotation-layer>` on the page, and otherwise\n * draws them when the user may read them.\n */\n readonly annotations = input<boolean | undefined>(undefined);\n /** The same for the form fields, which an `<epdf-form-layer>` paints. */\n readonly formFields = input<boolean | undefined>(undefined);\n /**\n * The sharp tiles over the picture when zoomed in (default true). Whether they cost anything\n * is decided by what the view wants; set it to false only for a view that must never tile.\n */\n readonly tiles = input(true);\n\n private readonly page = injectPage('<epdf-render-layer>');\n private readonly render = renderOf(this.page, '<epdf-render-layer>');\n /** The same object until a setting it reads changes. */\n protected readonly paintSettings = this.render.select(\n (render) => render.getPaintSettings(),\n NO_PAINT_SETTINGS,\n Object.is,\n );\n private readonly parts = computed(() => ({\n annotations: this.annotations(),\n formFields: this.formFields(),\n }));\n private readonly painted = injectPaintedParts(() => this.page.ref);\n private readonly may = this.render.select((render) => render.getLayerRights(), null, Object.is);\n /** The parts the picture draws; `null` until the page's layers have said what they paint. */\n protected readonly layers = computed(() => {\n const painted = this.painted();\n const may = this.may();\n return painted && may ? pictureLayerOptionsOf(painted, this.parts(), may) : null;\n });\n /**\n * The picture's identity: its size, the parts it draws and the page's version. Within a\n * size step it doesn't move as you zoom (the page's transform scales the picture), so\n * nothing is fetched again; it moves at a step and when the page changes.\n */\n private readonly sourceKey = this.render.select(\n (render) => {\n const layers = this.layers();\n return layers\n ? render.getSourceKey(this.page.ref, {\n scale: this.page.transform().renderScale,\n ...layers,\n })\n : null;\n },\n null,\n Object.is,\n );\n private readonly picture = viewChild.required<ElementRef<HTMLImageElement>>('picture');\n\n constructor() {\n effect(() => {\n const painted = this.painted();\n if (painted && partsDrawnTwice(painted, this.parts()).length > 0) {\n devWarn(\n 'render-layer-draws-what-a-layer-paints',\n '<epdf-render-layer [annotations]> or [formFields] draws what an ' +\n '<epdf-annotation-layer> or an <epdf-form-layer> on the page paints too, so it shows ' +\n 'twice. Leave the input out: the picture leaves out what a layer paints.',\n );\n }\n });\n if (!isPlatformBrowser(inject(PLATFORM_ID))) return;\n effect((onCleanup) => {\n const render = this.render.capability();\n const key = this.sourceKey();\n const layers = this.layers();\n if (!render || key === null || !layers) return;\n const controller = new AbortController();\n let revoke: (() => void) | undefined;\n onCleanup(() => {\n controller.abort();\n revoke?.();\n });\n // Any scale inside this key's step asks for this key's picture, so reading it now is safe.\n const scale = untracked(() => this.page.transform().renderScale);\n void (async () => {\n try {\n const image = await render.renderSource(this.page.ref, {\n scale,\n ...layers,\n view: this.page.view,\n signal: controller.signal,\n });\n const objectUrl = await image.objectUrl().abortWith(controller.signal);\n if (controller.signal.aborted) {\n objectUrl.revoke();\n return;\n }\n revoke = objectUrl.revoke;\n // Set on the element now, not through a binding. A binding applies at the next change\n // detection, and the key can move on before that, revoking this URL: the image would\n // then be handed a revoked URL and lose its picture. Set at once, the browser keeps\n // showing the old picture until the new one is decoded and never asks for the old URL\n // again, so revoking it when the next one comes is safe.\n this.picture().nativeElement.src = objectUrl.url;\n } catch {\n // Cancelled (the camera moved on, the layer went away) or the render failed.\n }\n })();\n });\n }\n}\n","/**\n * @embedpdf/angular/render: the page pictures.\n *\n * withRender(options) the plugin, for provideEmbedPdf()\n * inject(EpdfRender) pictures on demand, redraws, the settings\n * <epdf-render-layer> the picture of each page on a Stage\n */\n\n// The plugin's types and helpers, so app code has one import for the feature.\nexport * from '@embedpdf/plugin-render';\nexport * from './render';\nexport { EpdfRenderLayer } from './render-layer';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["RenderToken"],"mappings":"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"}