@embedpdf/angular 3.0.0-next.6 → 3.0.0-next.7

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.
@@ -1,10 +1,11 @@
1
- import { StageToken, wheelZoomFactor, settingsEqual } from '@embedpdf/plugin-stage';
1
+ import { StageToken, createScrollHandler, settingsEqual } from '@embedpdf/plugin-stage';
2
2
  export * from '@embedpdf/plugin-stage';
3
3
  import * as i0 from '@angular/core';
4
4
  import { inject, TemplateRef, Directive, input, computed, viewChild, Injector, ChangeDetectionStrategy, Component, contentChild, PLATFORM_ID, ElementRef, NgZone, effect } from '@angular/core';
5
5
  import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
6
6
  import { createPageContext, EPDF_PAGE, injectKernelHost, injectOptionalCapabilityFor, injectOptionalCapability, injectDocumentId, injectOptionalSelectorFor, injectCapability, injectSelector, shallowArray } from '@embedpdf/angular/runtime';
7
7
  import { InteractionToken } from '@embedpdf/plugin-interaction';
8
+ import { createStageSurface } from '@embedpdf/web';
8
9
 
9
10
  /**
10
11
  * The render-prop translation: React's `children: (page) => ReactNode` becomes
@@ -111,7 +112,7 @@ class EpdfPageSurface {
111
112
  transparent fill so it can never peek out behind the bitmap, and it
112
113
  stays put under rotation. -->
113
114
  <div
114
- style="position: absolute; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);"
115
+ style="position: absolute; box-shadow: var(--epdf-page-shadow, 0 6px 18px rgba(0, 0, 0, 0.18));"
115
116
  [style.left.px]="frame().left"
116
117
  [style.top.px]="frame().top"
117
118
  [style.width.px]="t().viewWidth"
@@ -165,7 +166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImpor
165
166
  transparent fill so it can never peek out behind the bitmap, and it
166
167
  stays put under rotation. -->
167
168
  <div
168
- style="position: absolute; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);"
169
+ style="position: absolute; box-shadow: var(--epdf-page-shadow, 0 6px 18px rgba(0, 0, 0, 0.18));"
169
170
  [style.left.px]="frame().left"
170
171
  [style.top.px]="frame().top"
171
172
  [style.width.px]="t().viewWidth"
@@ -202,29 +203,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImpor
202
203
  }]
203
204
  }] });
204
205
 
205
- /**
206
- * Robust multi-click counter. `pointerdown.detail` is 0/1 in several browsers,
207
- * so we count clicks ourselves from timing + proximity — the standard
208
- * double/triple detection. Input normalization belongs in the adapter; the
209
- * hub/handlers stay pure.
210
- *
211
- * INTERNAL for now — moves to the `/interaction` entry point (its React home)
212
- * when that vertical lands.
213
- */
214
- function createClickCounter(maxGapMs = 400, maxDistPx = 6) {
215
- let last = 0;
216
- let lastX = 0;
217
- let lastY = 0;
218
- let count = 0;
219
- return (now, x, y) => {
220
- count = now - last <= maxGapMs && Math.hypot(x - lastX, y - lastY) <= maxDistPx ? count + 1 : 1;
221
- last = now;
222
- lastX = x;
223
- lastY = y;
224
- return count;
225
- };
226
- }
227
-
228
206
  /**
229
207
  * `<epdf-stage>` — virtualizes and positions page surfaces by the camera, and
230
208
  * stamps each one with YOUR `<ng-template epdfPage>` — you bring the layers.
@@ -246,11 +224,24 @@ const frameEqual = (a, b) => a.top === b.top && a.right === b.right && a.bottom
246
224
  class EpdfStage {
247
225
  /**
248
226
  * Route this Stage's pointer events to the interaction hub (page-resolved via
249
- * `pageAt`) instead of the built-in drag-to-pan. Pan then becomes the `pan`
250
- * tool's job and dragging in `pointer` mode selects text (incl. across pages).
251
- * Pair with `stagePlugin({ interaction: true })`. Default false (built-in pan).
227
+ * `pageAt`) — AND register this lens's tool-gated pan-scroll handler with it
228
+ * (lens-scoped, so multiple stages on one document never pan each other).
229
+ * Pan is then the `pan` tool's job and dragging in `pointer` mode selects
230
+ * text (incl. across pages).
231
+ *
232
+ * Default TRUE: registering `interactionPlugin()` is the one opt-in — tools
233
+ * just work; without the hub this is inert and the stage falls back to
234
+ * built-in drag-to-pan, so a hub-less setup costs nothing. Set `false` on
235
+ * SECONDARY lenses (a thumbnail rail) that should stay click-to-navigate
236
+ * instead of feeding the document's tools.
237
+ */
238
+ interaction = input(true, ...(ngDevMode ? [{ debugName: "interaction" }] : []));
239
+ /**
240
+ * With `interaction`: let drags over page GAPS pan regardless of the active
241
+ * tool (and show a grab cursor there) — the gutter always pans; there is
242
+ * nothing to draw/select outside a page. Default true.
252
243
  */
253
- interaction = input(false, ...(ngDevMode ? [{ debugName: "interaction" }] : []));
244
+ panFallback = input(true, ...(ngDevMode ? [{ debugName: "panFallback" }] : []));
254
245
  /**
255
246
  * Ambient ZOOM gestures on this stage: ctrl/cmd+wheel and trackpad pinch
256
247
  * (Safari gesture events included). Default true. Turn OFF for follower
@@ -292,164 +283,35 @@ class EpdfStage {
292
283
  const stage = this.stage();
293
284
  const ix = this.ix();
294
285
  const useHub = this.interaction() && !!ix;
286
+ const panFallback = this.panFallback();
295
287
  const zoomGestures = this.zoomGestures();
296
288
  if (!stage)
297
289
  return; // no document yet — nothing to drive
298
290
  const cleanups = [];
299
291
  zone.runOutsideAngular(() => {
300
- // Only report the viewport size. Initial placement (home) is the Stage
301
- // plugin's job — the shell stays dumb.
302
- const setViewport = () => stage.setViewport({ width: el.clientWidth, height: el.clientHeight });
303
- const resizeObserver = new ResizeObserver(setViewport);
304
- resizeObserver.observe(el);
305
- setViewport();
306
- cleanups.push(() => resizeObserver.disconnect());
307
- // Report the device pixel ratio so page transforms render crisp. dppx
308
- // changes (zoom, dragging between monitors) fire the media query;
309
- // re-subscribe each time since the query value itself moves.
310
- let mq = null;
311
- const reportDpr = () => {
312
- stage.setDevicePixelRatio(window.devicePixelRatio || 1);
313
- mq?.removeEventListener('change', reportDpr);
314
- mq = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
315
- mq.addEventListener('change', reportDpr);
316
- };
317
- reportDpr();
318
- cleanups.push(() => mq?.removeEventListener('change', reportDpr));
319
- // Wheel is ambient navigation in BOTH modes: ctrl/meta zooms (classified
320
- // per input by wheelZoomFactor), else scrolls. With zoom gestures off, a
321
- // zoom-wheel falls through to ordinary pan.
322
- const onWheel = (e) => {
323
- e.preventDefault();
324
- const r = el.getBoundingClientRect();
325
- if (zoomGestures && (e.ctrlKey || e.metaKey)) {
326
- stage.zoomAround({ x: e.clientX - r.left, y: e.clientY - r.top }, wheelZoomFactor(e));
327
- }
328
- else {
329
- const dx = e.shiftKey ? e.deltaY : e.deltaX;
330
- const dy = e.shiftKey ? e.deltaX : e.deltaY;
331
- stage.panBy(-dx, -dy);
332
- }
333
- };
334
- el.addEventListener('wheel', onWheel, { passive: false });
335
- cleanups.push(() => el.removeEventListener('wheel', onWheel));
336
- // Safari never synthesizes ctrl+wheel for trackpad pinch — it fires
337
- // proprietary gesture events carrying an ABSOLUTE scale; convert to the
338
- // per-event ratio the camera physics wants. Feature-detected, so Chrome
339
- // and Firefox pay nothing. preventDefault runs even with zoom gestures
340
- // off — a pinch over the stage must never zoom the page itself.
341
- let lastScale = 1;
342
- const onGestureStart = (e) => {
343
- e.preventDefault();
344
- lastScale = e.scale ?? 1;
345
- };
346
- const onGestureChange = (e) => {
347
- e.preventDefault();
348
- const g = e;
349
- const scale = g.scale ?? 1;
350
- if (zoomGestures && scale > 0) {
351
- const r = el.getBoundingClientRect();
352
- stage.zoomAround({ x: g.clientX - r.left, y: g.clientY - r.top }, scale / lastScale);
353
- }
354
- lastScale = scale;
355
- };
356
- if ('GestureEvent' in window) {
357
- el.addEventListener('gesturestart', onGestureStart);
358
- el.addEventListener('gesturechange', onGestureChange);
359
- el.addEventListener('gestureend', onGestureStart); // reset the base
360
- cleanups.push(() => {
361
- el.removeEventListener('gesturestart', onGestureStart);
362
- el.removeEventListener('gesturechange', onGestureChange);
363
- el.removeEventListener('gestureend', onGestureStart);
364
- });
365
- }
292
+ // The WHOLE browser binding — viewport/DPR reporting, sample
293
+ // normalization, gesture controller — is the shared @embedpdf/web
294
+ // surface, so every framework adapter has one feel. This component
295
+ // keeps only Angular glue.
296
+ cleanups.push(createStageSurface(el, stage, {
297
+ hub: useHub ? ix : null,
298
+ source: stage.lensId(),
299
+ zoomGestures,
300
+ }));
301
+ // Interaction opt-in lives WITH the sample source: the same knob that
302
+ // forwards this lens's samples also registers its pan-scroll handler,
303
+ // lens-scoped — two stages on one document can never pan each other.
366
304
  if (useHub && ix) {
367
- // Forward to the hub: pan/select/etc. become tool-gated handlers.
368
- // `pageAt` resolves the page per event, so a drag can cross pages.
369
- const clicks = createClickCounter();
370
- const forward = (phase, e, clickCount = 1) => {
371
- const r = el.getBoundingClientRect();
372
- const viewport = { x: e.clientX - r.left, y: e.clientY - r.top };
373
- ix.dispatch({
374
- phase,
375
- viewport,
376
- page: stage.pageAt(viewport) ?? undefined,
377
- // Page-anchored gestures (annotation move/resize) track the origin
378
- // page's frame through this even when the cursor is off that page.
379
- project: (pon) => stage.pointOnPage(pon, viewport),
380
- modifiers: { shift: e.shiftKey, alt: e.altKey, ctrl: e.ctrlKey, meta: e.metaKey },
381
- clickCount,
382
- });
383
- };
384
- let dragging = false;
385
- const down = (e) => {
386
- if (e.button !== 0)
387
- return;
388
- dragging = true;
389
- forward('down', e, clicks(Date.now(), e.clientX, e.clientY));
390
- };
391
- const hover = (e) => {
392
- if (!dragging)
393
- forward('move', e); // cursor feedback, no gesture
394
- };
395
- const windowMove = (e) => {
396
- if (dragging)
397
- forward('move', e);
398
- };
399
- const up = (e) => {
400
- if (!dragging)
401
- return;
402
- dragging = false;
403
- forward('up', e);
404
- };
405
- el.addEventListener('pointerdown', down);
406
- el.addEventListener('pointermove', hover);
407
- window.addEventListener('pointermove', windowMove);
408
- window.addEventListener('pointerup', up);
409
- cleanups.push(() => {
410
- el.removeEventListener('pointerdown', down);
411
- el.removeEventListener('pointermove', hover);
412
- window.removeEventListener('pointermove', windowMove);
413
- window.removeEventListener('pointerup', up);
414
- });
415
- }
416
- else {
417
- // Built-in drag-to-pan (no interaction hub).
418
- let dragging = false;
419
- let lastX = 0;
420
- let lastY = 0;
421
- const down = (e) => {
422
- if (e.button !== 0)
423
- return;
424
- dragging = true;
425
- lastX = e.clientX;
426
- lastY = e.clientY;
427
- };
428
- const move = (e) => {
429
- if (!dragging)
430
- return;
431
- stage.panBy(e.clientX - lastX, e.clientY - lastY);
432
- lastX = e.clientX;
433
- lastY = e.clientY;
434
- };
435
- const up = () => {
436
- dragging = false;
437
- };
438
- el.addEventListener('pointerdown', down);
439
- window.addEventListener('pointermove', move);
440
- window.addEventListener('pointerup', up);
441
- cleanups.push(() => {
442
- el.removeEventListener('pointerdown', down);
443
- window.removeEventListener('pointermove', move);
444
- window.removeEventListener('pointerup', up);
445
- });
305
+ cleanups.push(ix.registerHandler(createScrollHandler(stage, ix, { panFallback }), {
306
+ source: stage.lensId(),
307
+ }));
446
308
  }
447
309
  });
448
310
  onCleanup(() => cleanups.forEach((fn) => fn()));
449
311
  });
450
312
  }
451
313
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: EpdfStage, deps: [], target: i0.ɵɵFactoryTarget.Component });
452
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: EpdfStage, isStandalone: true, selector: "epdf-stage", inputs: { interaction: { classPropertyName: "interaction", publicName: "interaction", isSignal: true, isRequired: false, transformFunction: null }, zoomGestures: { classPropertyName: "zoomGestures", publicName: "zoomGestures", isSignal: true, isRequired: false, transformFunction: null }, token: { classPropertyName: "token", publicName: "token", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.cursor": "cursor()" }, styleAttribute: "position: relative; overflow: hidden; touch-action: none; display: block;" }, queries: [{ propertyName: "pageTemplateDir", first: true, predicate: EpdfPageTemplate, descendants: true, isSignal: true }, { propertyName: "chromeTemplateDir", first: true, predicate: EpdfPageChrome, descendants: true, isSignal: true }], ngImport: i0, template: `
314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: EpdfStage, isStandalone: true, selector: "epdf-stage", inputs: { interaction: { classPropertyName: "interaction", publicName: "interaction", isSignal: true, isRequired: false, transformFunction: null }, panFallback: { classPropertyName: "panFallback", publicName: "panFallback", isSignal: true, isRequired: false, transformFunction: null }, zoomGestures: { classPropertyName: "zoomGestures", publicName: "zoomGestures", isSignal: true, isRequired: false, transformFunction: null }, token: { classPropertyName: "token", publicName: "token", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.cursor": "cursor()" }, styleAttribute: "position: relative; overflow: hidden; touch-action: none; display: block;" }, queries: [{ propertyName: "pageTemplateDir", first: true, predicate: EpdfPageTemplate, descendants: true, isSignal: true }, { propertyName: "chromeTemplateDir", first: true, predicate: EpdfPageChrome, descendants: true, isSignal: true }], ngImport: i0, template: `
453
315
  @if (pageTemplate(); as tpl) {
454
316
  @for (p of pages(); track p.pon) {
455
317
  <epdf-page-surface
@@ -1 +1 @@
1
- {"version":3,"file":"embedpdf-angular-stage.mjs","sources":["../../stage/src/templates.ts","../../stage/src/page-surface.ts","../../stage/src/click-counter.ts","../../stage/src/stage.ts","../../stage/src/facades.ts","../../stage/src/public_api.ts","../../stage/src/embedpdf-angular-stage.ts"],"sourcesContent":["/**\n * The render-prop translation: React's `children: (page) => ReactNode` becomes\n * marker directives on `<ng-template>`, typed so `let-page` infers\n * `EpdfPageContext` in the template.\n *\n * <epdf-stage>\n * <ng-template epdfPage> page-space content (rotates)\n * <ng-template epdfPageChrome> box-space chrome (never rotates)\n *\n * The `$implicit` context is the SAME stable object the per-page injector\n * provides as `EPDF_PAGE` — `let-page` is sugar for inline chrome; components\n * inside the template just call `injectPage()`.\n */\nimport { Directive, inject, TemplateRef } from '@angular/core';\nimport type { EpdfPageContext } from '@embedpdf/angular/runtime';\n\nexport interface EpdfPageTemplateContext {\n $implicit: EpdfPageContext;\n}\n\n/** PAGE-SPACE content for each visible page (RenderLayer, annotations,\n * markers). Rendered inside the page's content frame, so it ROTATES with the\n * page's display rotation — coordinates are plain PDF points. */\n@Directive({ selector: 'ng-template[epdfPage]', standalone: true })\nexport class EpdfPageTemplate {\n readonly template = inject<TemplateRef<EpdfPageTemplateContext>>(TemplateRef);\n static ngTemplateContextGuard(\n _dir: EpdfPageTemplate,\n ctx: unknown,\n ): ctx is EpdfPageTemplateContext {\n return true;\n }\n}\n\n/** BOX-SPACE chrome for each visible page (page-number label, selection\n * border, per-page buttons). Rendered into the OUTER box (content + reserved\n * `pageFrame`), so it does NOT rotate and the reserved bands are plain\n * regions (`bottom: 0; height: page.frame().bottom`). */\n@Directive({ selector: 'ng-template[epdfPageChrome]', standalone: true })\nexport class EpdfPageChrome {\n readonly template = inject<TemplateRef<EpdfPageTemplateContext>>(TemplateRef);\n static ngTemplateContextGuard(\n _dir: EpdfPageChrome,\n ctx: unknown,\n ): ctx is EpdfPageTemplateContext {\n return true;\n }\n}\n","/**\n * INTERNAL page shell — one per visible page, tracked by `pon` so the instance\n * (and everything below) survives camera motion and page reorders.\n *\n * THE STABILITY INVARIANT (see page-context.ts): `page` (the context) and\n * `pageInjector` are created ONCE per surface. Camera frames arrive as new\n * `vp` input values; only the signals inside the context change. Changing the\n * injector or context object identity would make `NgTemplateOutlet` recreate\n * the embedded views — destroying layers at 120Hz. Don't.\n *\n * Geometry mirrors React's PageSurface: the outer box = content footprint +\n * reserved chrome bands; the shadow is axis-aligned and stays put under\n * rotation; the content wrapper is the ONLY thing rotation turns, and carries\n * no transform at rotation 0 so it pixel-snaps like the shadow behind it.\n * All numbers come from the transform — never re-derive `* zoom` / `* dpr`.\n */\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n Injector,\n input,\n viewChild,\n type TemplateRef,\n} from '@angular/core';\nimport type { PageFrame, VisiblePage } from '@embedpdf/plugin-stage';\nimport { createPageContext, EPDF_PAGE, type EpdfPageContext } from '@embedpdf/angular/runtime';\nimport type { EpdfPageTemplateContext } from './templates';\n\n@Component({\n selector: 'epdf-page-surface',\n standalone: true,\n imports: [NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n style: 'position: absolute; display: block;',\n '[style.left.px]': 'left()',\n '[style.top.px]': 'top()',\n '[style.width.px]': 'outerWidth()',\n '[style.height.px]': 'outerHeight()',\n },\n template: `\n <!-- drop shadow ONLY — axis-aligned at the content box (inset by the frame),\n transparent fill so it can never peek out behind the bitmap, and it\n stays put under rotation. -->\n <div\n style=\"position: absolute; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);\"\n [style.left.px]=\"frame().left\"\n [style.top.px]=\"frame().top\"\n [style.width.px]=\"t().viewWidth\"\n [style.height.px]=\"t().viewHeight\"\n ></div>\n <!-- the page: white backing + content as ONE box — the only thing rotation\n turns. We render our own selection highlights, so native selection is\n suppressed on the whole page subtree. -->\n <div\n #content\n style=\"position: absolute; background: #fff; user-select: none; -webkit-user-select: none;\"\n [style.left.px]=\"contentLeft()\"\n [style.top.px]=\"contentTop()\"\n [style.width.px]=\"t().contentWidth\"\n [style.height.px]=\"t().contentHeight\"\n [style.transform]=\"rotate()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"pageTpl()\"\n [ngTemplateOutletContext]=\"templateContext\"\n [ngTemplateOutletInjector]=\"pageInjector\"\n />\n </div>\n <!-- box-space chrome — fills the outer box, NEVER rotates. Bands are plain\n regions: a label is bottom: 0; height: frame().bottom. -->\n @if (chromeTpl(); as chrome) {\n <ng-container\n [ngTemplateOutlet]=\"chrome\"\n [ngTemplateOutletContext]=\"templateContext\"\n [ngTemplateOutletInjector]=\"pageInjector\"\n />\n }\n `,\n})\nexport class EpdfPageSurface {\n readonly vp = input.required<VisiblePage>();\n readonly frame = input.required<PageFrame>();\n readonly documentId = input.required<string>();\n readonly pageTpl = input.required<TemplateRef<EpdfPageTemplateContext>>();\n readonly chromeTpl = input<TemplateRef<EpdfPageTemplateContext> | null>(null);\n\n protected readonly t = computed(() => this.vp().transform);\n\n // Outer box = display footprint + reserved chrome bands; screenX/screenY are\n // the device-snapped footprint top-left, so the box sits one frame further out.\n protected readonly left = computed(() => this.vp().screenX - this.frame().left);\n protected readonly top = computed(() => this.vp().screenY - this.frame().top);\n protected readonly outerWidth = computed(\n () => this.t().viewWidth + this.frame().left + this.frame().right,\n );\n protected readonly outerHeight = computed(\n () => this.t().viewHeight + this.frame().top + this.frame().bottom,\n );\n // Center the (possibly rotated) content box on the display box and rotate\n // about its center — NO translate(), so rotation 0 carries no transform.\n protected readonly contentLeft = computed(\n () => this.frame().left + (this.t().viewWidth - this.t().contentWidth) / 2,\n );\n protected readonly contentTop = computed(\n () => this.frame().top + (this.t().viewHeight - this.t().contentHeight) / 2,\n );\n protected readonly rotate = computed(() => {\n const rotation = this.vp().rotation;\n return rotation ? `rotate(${rotation}deg)` : null;\n });\n\n private readonly contentEl = viewChild.required<ElementRef<HTMLDivElement>>('content');\n\n /** ONE stable context per surface — volatile parts are signals inside it. */\n readonly page: EpdfPageContext = createPageContext({\n documentId: () => this.documentId(),\n pon: () => this.vp().pon,\n pageIndex: computed(() => this.vp().pageIndex),\n frame: this.frame,\n transform: this.t,\n getRect: () => this.contentEl().nativeElement.getBoundingClientRect(),\n });\n\n /** ONE stable injector per surface (see the invariant above), parented to\n * this surface's node injector so layers also reach the kernel host. */\n protected readonly pageInjector = Injector.create({\n providers: [{ provide: EPDF_PAGE, useValue: this.page }],\n parent: inject(Injector),\n });\n\n protected readonly templateContext: EpdfPageTemplateContext = { $implicit: this.page };\n}\n","/**\n * Robust multi-click counter. `pointerdown.detail` is 0/1 in several browsers,\n * so we count clicks ourselves from timing + proximity — the standard\n * double/triple detection. Input normalization belongs in the adapter; the\n * hub/handlers stay pure.\n *\n * INTERNAL for now — moves to the `/interaction` entry point (its React home)\n * when that vertical lands.\n */\nexport function createClickCounter(maxGapMs = 400, maxDistPx = 6) {\n let last = 0;\n let lastX = 0;\n let lastY = 0;\n let count = 0;\n return (now: number, x: number, y: number): number => {\n count = now - last <= maxGapMs && Math.hypot(x - lastX, y - lastY) <= maxDistPx ? count + 1 : 1;\n last = now;\n lastX = x;\n lastY = y;\n return count;\n };\n}\n","/**\n * `<epdf-stage>` — virtualizes and positions page surfaces by the camera, and\n * stamps each one with YOUR `<ng-template epdfPage>` — you bring the layers.\n *\n * NULL-SAFE BY DESIGN (a deliberate deviation from React's strict Stage):\n * Angular instantiates projected content eagerly, so a stage constructed\n * before any document exists must not crash — it renders zero pages and its\n * listeners no-op until the document arrives. Teach the document gate anyway:\n * document CHROME (toolbars, panels) still belongs behind `*epdfDocumentGate`.\n *\n * ZONE RULE: every DOM listener here attaches OUTSIDE Angular's zone — a\n * 120Hz pointermove stream must never trigger app-wide change detection.\n * State flows kernel → tick signal → computeds → bindings, so the adapter is\n * zone-agnostic (zoneless recommended, zone.js tolerated).\n */\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n effect,\n ElementRef,\n inject,\n input,\n NgZone,\n PLATFORM_ID,\n} from '@angular/core';\nimport { StageToken, wheelZoomFactor } from '@embedpdf/plugin-stage';\nimport type { StageCapability, VisiblePage } from '@embedpdf/plugin-stage';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport type { PointerSample } from '@embedpdf/plugin-interaction';\nimport {\n injectDocumentId,\n injectKernelHost,\n injectOptionalCapability,\n injectOptionalCapabilityFor,\n injectOptionalSelectorFor,\n type CapabilityToken,\n} from '@embedpdf/angular/runtime';\nimport type { PageFrame } from '@embedpdf/plugin-stage';\nimport { createClickCounter } from './click-counter';\nimport { EpdfPageChrome, EpdfPageTemplate } from './templates';\nimport { EpdfPageSurface } from './page-surface';\n\n/** Which stage lens to bind to. Defaults to the main StageToken — pass a custom\n * token to drive an additional lens (e.g. a wrapped thumbnail sidebar). */\nexport type StageTokenProp = CapabilityToken<StageCapability>;\n\nconst EMPTY_PAGES: VisiblePage[] = [];\nconst NO_FRAME: PageFrame = { top: 0, right: 0, bottom: 0, left: 0 };\nconst frameEqual = (a: PageFrame, b: PageFrame) =>\n a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;\n\n@Component({\n selector: 'epdf-stage',\n standalone: true,\n imports: [EpdfPageSurface],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n style: 'position: relative; overflow: hidden; touch-action: none; display: block;',\n '[style.cursor]': 'cursor()',\n },\n template: `\n @if (pageTemplate(); as tpl) {\n @for (p of pages(); track p.pon) {\n <epdf-page-surface\n [vp]=\"p\"\n [frame]=\"frame()\"\n [documentId]=\"documentId() ?? ''\"\n [pageTpl]=\"tpl\"\n [chromeTpl]=\"chromeTemplate()\"\n />\n }\n }\n <!-- viewport-space overlay UI: anything projected into <epdf-stage>\n renders above the pages (menus, controls, scrollbars). -->\n <ng-content />\n `,\n})\nexport class EpdfStage {\n /**\n * Route this Stage's pointer events to the interaction hub (page-resolved via\n * `pageAt`) instead of the built-in drag-to-pan. Pan then becomes the `pan`\n * tool's job and dragging in `pointer` mode selects text (incl. across pages).\n * Pair with `stagePlugin({ interaction: true })`. Default false (built-in pan).\n */\n readonly interaction = input(false);\n /**\n * Ambient ZOOM gestures on this stage: ctrl/cmd+wheel and trackpad pinch\n * (Safari gesture events included). Default true. Turn OFF for follower\n * lenses with a fixed magnification (a thumbnail rail should scroll under\n * cmd+wheel, not zoom); pinches are still swallowed either way.\n */\n readonly zoomGestures = input(true);\n /** The stage lens to drive (default: the main StageToken). */\n readonly token = input<StageTokenProp>(StageToken);\n\n private readonly host = injectKernelHost();\n private readonly stage = injectOptionalCapabilityFor(() => this.token());\n private readonly ix = injectOptionalCapability(InteractionToken);\n private readonly useHub = computed(() => this.interaction() && this.ix() !== null);\n // The hub's resolved cursor (text/grab/…), applied to the viewport when driving.\n private readonly hubCursor = this.host.value(() => this.ix()?.cursor() ?? 'default');\n protected readonly cursor = computed(() => (this.useHub() ? this.hubCursor() : null));\n\n protected readonly documentId = injectDocumentId();\n // visiblePages already folds in the camera (each page carries its\n // device-snapped screenX/screenY + transform), so panning re-emits the list —\n // no separate camera subscription needed for positioning. The capability\n // memoizes, so Object.is equality suffices.\n protected readonly pages = injectOptionalSelectorFor(\n () => this.token(),\n (c) => c.visiblePages(),\n EMPTY_PAGES,\n );\n // Reserved chrome bands (screen px), uniform across pages — the frame the\n // outer box reserves and the chrome template paints into.\n protected readonly frame = injectOptionalSelectorFor(\n () => this.token(),\n (c) => c.pageFrame(),\n NO_FRAME,\n frameEqual,\n );\n\n private readonly pageTemplateDir = contentChild(EpdfPageTemplate);\n private readonly chromeTemplateDir = contentChild(EpdfPageChrome);\n protected readonly pageTemplate = computed(() => this.pageTemplateDir()?.template ?? null);\n protected readonly chromeTemplate = computed(() => this.chromeTemplateDir()?.template ?? null);\n\n constructor() {\n if (!isPlatformBrowser(inject(PLATFORM_ID))) return;\n const el = inject(ElementRef).nativeElement as HTMLElement;\n const zone = inject(NgZone);\n\n // Rebinds when the stage capability (document open/close/switch, token\n // change), hub, or gesture flags change — the Angular spelling of the React\n // Stage effect and its dependency array.\n effect((onCleanup) => {\n const stage = this.stage();\n const ix = this.ix();\n const useHub = this.interaction() && !!ix;\n const zoomGestures = this.zoomGestures();\n if (!stage) return; // no document yet — nothing to drive\n\n const cleanups: Array<() => void> = [];\n zone.runOutsideAngular(() => {\n // Only report the viewport size. Initial placement (home) is the Stage\n // plugin's job — the shell stays dumb.\n const setViewport = () =>\n stage.setViewport({ width: el.clientWidth, height: el.clientHeight });\n const resizeObserver = new ResizeObserver(setViewport);\n resizeObserver.observe(el);\n setViewport();\n cleanups.push(() => resizeObserver.disconnect());\n\n // Report the device pixel ratio so page transforms render crisp. dppx\n // changes (zoom, dragging between monitors) fire the media query;\n // re-subscribe each time since the query value itself moves.\n let mq: MediaQueryList | null = null;\n const reportDpr = () => {\n stage.setDevicePixelRatio(window.devicePixelRatio || 1);\n mq?.removeEventListener('change', reportDpr);\n mq = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);\n mq.addEventListener('change', reportDpr);\n };\n reportDpr();\n cleanups.push(() => mq?.removeEventListener('change', reportDpr));\n\n // Wheel is ambient navigation in BOTH modes: ctrl/meta zooms (classified\n // per input by wheelZoomFactor), else scrolls. With zoom gestures off, a\n // zoom-wheel falls through to ordinary pan.\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const r = el.getBoundingClientRect();\n if (zoomGestures && (e.ctrlKey || e.metaKey)) {\n stage.zoomAround({ x: e.clientX - r.left, y: e.clientY - r.top }, wheelZoomFactor(e));\n } else {\n const dx = e.shiftKey ? e.deltaY : e.deltaX;\n const dy = e.shiftKey ? e.deltaX : e.deltaY;\n stage.panBy(-dx, -dy);\n }\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n cleanups.push(() => el.removeEventListener('wheel', onWheel));\n\n // Safari never synthesizes ctrl+wheel for trackpad pinch — it fires\n // proprietary gesture events carrying an ABSOLUTE scale; convert to the\n // per-event ratio the camera physics wants. Feature-detected, so Chrome\n // and Firefox pay nothing. preventDefault runs even with zoom gestures\n // off — a pinch over the stage must never zoom the page itself.\n let lastScale = 1;\n const onGestureStart = (e: Event) => {\n e.preventDefault();\n lastScale = (e as unknown as { scale?: number }).scale ?? 1;\n };\n const onGestureChange = (e: Event) => {\n e.preventDefault();\n const g = e as unknown as { scale?: number; clientX: number; clientY: number };\n const scale = g.scale ?? 1;\n if (zoomGestures && scale > 0) {\n const r = el.getBoundingClientRect();\n stage.zoomAround({ x: g.clientX - r.left, y: g.clientY - r.top }, scale / lastScale);\n }\n lastScale = scale;\n };\n if ('GestureEvent' in window) {\n el.addEventListener('gesturestart', onGestureStart);\n el.addEventListener('gesturechange', onGestureChange);\n el.addEventListener('gestureend', onGestureStart); // reset the base\n cleanups.push(() => {\n el.removeEventListener('gesturestart', onGestureStart);\n el.removeEventListener('gesturechange', onGestureChange);\n el.removeEventListener('gestureend', onGestureStart);\n });\n }\n\n if (useHub && ix) {\n // Forward to the hub: pan/select/etc. become tool-gated handlers.\n // `pageAt` resolves the page per event, so a drag can cross pages.\n const clicks = createClickCounter();\n const forward = (phase: PointerSample['phase'], e: PointerEvent, clickCount = 1) => {\n const r = el.getBoundingClientRect();\n const viewport = { x: e.clientX - r.left, y: e.clientY - r.top };\n ix.dispatch({\n phase,\n viewport,\n page: stage.pageAt(viewport) ?? undefined,\n // Page-anchored gestures (annotation move/resize) track the origin\n // page's frame through this even when the cursor is off that page.\n project: (pon) => stage.pointOnPage(pon, viewport),\n modifiers: { shift: e.shiftKey, alt: e.altKey, ctrl: e.ctrlKey, meta: e.metaKey },\n clickCount,\n });\n };\n let dragging = false;\n const down = (e: PointerEvent) => {\n if (e.button !== 0) return;\n dragging = true;\n forward('down', e, clicks(Date.now(), e.clientX, e.clientY));\n };\n const hover = (e: PointerEvent) => {\n if (!dragging) forward('move', e); // cursor feedback, no gesture\n };\n const windowMove = (e: PointerEvent) => {\n if (dragging) forward('move', e);\n };\n const up = (e: PointerEvent) => {\n if (!dragging) return;\n dragging = false;\n forward('up', e);\n };\n el.addEventListener('pointerdown', down);\n el.addEventListener('pointermove', hover);\n window.addEventListener('pointermove', windowMove);\n window.addEventListener('pointerup', up);\n cleanups.push(() => {\n el.removeEventListener('pointerdown', down);\n el.removeEventListener('pointermove', hover);\n window.removeEventListener('pointermove', windowMove);\n window.removeEventListener('pointerup', up);\n });\n } else {\n // Built-in drag-to-pan (no interaction hub).\n let dragging = false;\n let lastX = 0;\n let lastY = 0;\n const down = (e: PointerEvent) => {\n if (e.button !== 0) return;\n dragging = true;\n lastX = e.clientX;\n lastY = e.clientY;\n };\n const move = (e: PointerEvent) => {\n if (!dragging) return;\n stage.panBy(e.clientX - lastX, e.clientY - lastY);\n lastX = e.clientX;\n lastY = e.clientY;\n };\n const up = () => {\n dragging = false;\n };\n el.addEventListener('pointerdown', down);\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n cleanups.push(() => {\n el.removeEventListener('pointerdown', down);\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n });\n }\n });\n onCleanup(() => cleanups.forEach((fn) => fn()));\n });\n }\n}\n","/**\n * Facade inject functions — thin sugar over the capability + generic binding,\n * name-for-name with the React hooks (`useZoom` → `injectZoom`), values\n * replaced by signals.\n *\n * STRICT like their React counterparts: they resolve a document-scoped\n * capability, so call them in document UI (behind `*epdfDocumentGate` /\n * `@if (documentId())`). For always-mounted chrome, read through\n * `injectOptionalSelector` with a fallback instead.\n *\n * Methods LATE-BIND the current capability (`() => cap().zoomIn()`), so a\n * facade captured before a document switch drives the document that is active\n * at CALL time, never a stale one.\n */\nimport type { Signal } from '@angular/core';\nimport { StageToken, settingsEqual } from '@embedpdf/plugin-stage';\nimport type { StageCapability } from '@embedpdf/plugin-stage';\nimport { injectCapability, injectSelector, shallowArray } from '@embedpdf/angular/runtime';\nimport type { StageTokenProp } from './stage';\n\ntype AnyFn = (...args: never[]) => unknown;\n/** Late-binding method passthrough: exact capability signature, current doc. */\nconst lazy = <K extends keyof StageCapability>(\n cap: Signal<StageCapability>,\n key: K,\n): StageCapability[K] =>\n ((...args: unknown[]) =>\n (cap()[key] as unknown as (...a: unknown[]) => unknown)(...args)) as StageCapability[K] &\n AnyFn as StageCapability[K];\n\nexport function injectStage(token: StageTokenProp = StageToken): Signal<StageCapability> {\n return injectCapability(token);\n}\n\nexport function injectZoom(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n zoom: injectSelector(token, (c) => c.zoomLevel()),\n /** Active zoom intent: 'automatic' | 'fit-page' | 'fit-width' | 'fit-all' | 'custom'. */\n mode: injectSelector(token, (c) => c.zoomMode()),\n zoomIn: lazy(s, 'zoomIn'),\n zoomOut: lazy(s, 'zoomOut'),\n fitWidth: lazy(s, 'fitWidth'),\n fitPage: lazy(s, 'fitPage'),\n fitAll: lazy(s, 'fitAll'),\n automatic: lazy(s, 'automatic'),\n zoomTo: lazy(s, 'zoomTo'),\n };\n}\n\nexport function injectPages(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n currentPage: injectSelector(token, (c) => c.currentPage()),\n pageCount: injectSelector(token, (c) => c.pageCount()),\n goToPage: lazy(s, 'goToPage'),\n next: lazy(s, 'next'),\n prev: lazy(s, 'prev'),\n reveal: lazy(s, 'reveal'),\n };\n}\n\nexport function injectLayout(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n flow: injectSelector(token, (c) => c.flow()),\n layout: injectSelector(token, (c) => c.layout()),\n spread: injectSelector(token, (c) => c.spread()),\n sizing: injectSelector(token, (c) => c.sizing()),\n bounded: injectSelector(token, (c) => c.bounded()),\n setFlow: lazy(s, 'setFlow'),\n setLayout: lazy(s, 'setLayout'),\n setSpread: lazy(s, 'setSpread'),\n setSizing: lazy(s, 'setSizing'),\n setBounded: lazy(s, 'setBounded'),\n };\n}\n\n/** The document's page list (with PDF labels) + the current item's pages — the\n * data for page thumbnails / worksheet-style page tabs. */\nexport function injectPageList(token: StageTokenProp = StageToken) {\n return {\n pages: injectSelector(\n token,\n (c) => c.pages(),\n (a, b) =>\n a.length === b.length && a.every((p, i) => p.pon === b[i].pon && p.label === b[i].label),\n ),\n currentItemPages: injectSelector(token, (c) => c.currentItemPages(), shallowArray),\n };\n}\n\n/**\n * All Stage settings + the batch `update`. The seam for \"presets are a customer\n * concern\": keep your own `Partial<StageSettings>` objects and apply them with\n * `update(preset)` (one anchor-preserving change).\n */\nexport function injectStageSettings(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n // settingsEqual derives from the plugin's settings registry — a new setting\n // is covered automatically, without this package spelling out the shape.\n settings: injectSelector(token, (c) => c.settings(), settingsEqual),\n update: lazy(s, 'update'),\n reset: lazy(s, 'resetView'),\n };\n}\n","/**\n * @embedpdf/angular/stage — the viewport trunk: `<epdf-stage>` + page\n * templates + the stage facade inject functions.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stage';\nexport * from './templates';\nexport * from './page-surface';\nexport * from './stage';\nexport * from './facades';\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-stage.mjs","sources":["../../stage/src/templates.ts","../../stage/src/page-surface.ts","../../stage/src/stage.ts","../../stage/src/facades.ts","../../stage/src/public_api.ts","../../stage/src/embedpdf-angular-stage.ts"],"sourcesContent":["/**\n * The render-prop translation: React's `children: (page) => ReactNode` becomes\n * marker directives on `<ng-template>`, typed so `let-page` infers\n * `EpdfPageContext` in the template.\n *\n * <epdf-stage>\n * <ng-template epdfPage> page-space content (rotates)\n * <ng-template epdfPageChrome> box-space chrome (never rotates)\n *\n * The `$implicit` context is the SAME stable object the per-page injector\n * provides as `EPDF_PAGE` — `let-page` is sugar for inline chrome; components\n * inside the template just call `injectPage()`.\n */\nimport { Directive, inject, TemplateRef } from '@angular/core';\nimport type { EpdfPageContext } from '@embedpdf/angular/runtime';\n\nexport interface EpdfPageTemplateContext {\n $implicit: EpdfPageContext;\n}\n\n/** PAGE-SPACE content for each visible page (RenderLayer, annotations,\n * markers). Rendered inside the page's content frame, so it ROTATES with the\n * page's display rotation — coordinates are plain PDF points. */\n@Directive({ selector: 'ng-template[epdfPage]', standalone: true })\nexport class EpdfPageTemplate {\n readonly template = inject<TemplateRef<EpdfPageTemplateContext>>(TemplateRef);\n static ngTemplateContextGuard(\n _dir: EpdfPageTemplate,\n ctx: unknown,\n ): ctx is EpdfPageTemplateContext {\n return true;\n }\n}\n\n/** BOX-SPACE chrome for each visible page (page-number label, selection\n * border, per-page buttons). Rendered into the OUTER box (content + reserved\n * `pageFrame`), so it does NOT rotate and the reserved bands are plain\n * regions (`bottom: 0; height: page.frame().bottom`). */\n@Directive({ selector: 'ng-template[epdfPageChrome]', standalone: true })\nexport class EpdfPageChrome {\n readonly template = inject<TemplateRef<EpdfPageTemplateContext>>(TemplateRef);\n static ngTemplateContextGuard(\n _dir: EpdfPageChrome,\n ctx: unknown,\n ): ctx is EpdfPageTemplateContext {\n return true;\n }\n}\n","/**\n * INTERNAL page shell — one per visible page, tracked by `pon` so the instance\n * (and everything below) survives camera motion and page reorders.\n *\n * THE STABILITY INVARIANT (see page-context.ts): `page` (the context) and\n * `pageInjector` are created ONCE per surface. Camera frames arrive as new\n * `vp` input values; only the signals inside the context change. Changing the\n * injector or context object identity would make `NgTemplateOutlet` recreate\n * the embedded views — destroying layers at 120Hz. Don't.\n *\n * Geometry mirrors React's PageSurface: the outer box = content footprint +\n * reserved chrome bands; the shadow is axis-aligned and stays put under\n * rotation; the content wrapper is the ONLY thing rotation turns, and carries\n * no transform at rotation 0 so it pixel-snaps like the shadow behind it.\n * All numbers come from the transform — never re-derive `* zoom` / `* dpr`.\n */\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n Injector,\n input,\n viewChild,\n type TemplateRef,\n} from '@angular/core';\nimport type { PageFrame, VisiblePage } from '@embedpdf/plugin-stage';\nimport { createPageContext, EPDF_PAGE, type EpdfPageContext } from '@embedpdf/angular/runtime';\nimport type { EpdfPageTemplateContext } from './templates';\n\n@Component({\n selector: 'epdf-page-surface',\n standalone: true,\n imports: [NgTemplateOutlet],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n style: 'position: absolute; display: block;',\n '[style.left.px]': 'left()',\n '[style.top.px]': 'top()',\n '[style.width.px]': 'outerWidth()',\n '[style.height.px]': 'outerHeight()',\n },\n template: `\n <!-- drop shadow ONLY — axis-aligned at the content box (inset by the frame),\n transparent fill so it can never peek out behind the bitmap, and it\n stays put under rotation. -->\n <div\n style=\"position: absolute; box-shadow: var(--epdf-page-shadow, 0 6px 18px rgba(0, 0, 0, 0.18));\"\n [style.left.px]=\"frame().left\"\n [style.top.px]=\"frame().top\"\n [style.width.px]=\"t().viewWidth\"\n [style.height.px]=\"t().viewHeight\"\n ></div>\n <!-- the page: white backing + content as ONE box — the only thing rotation\n turns. We render our own selection highlights, so native selection is\n suppressed on the whole page subtree. -->\n <div\n #content\n style=\"position: absolute; background: #fff; user-select: none; -webkit-user-select: none;\"\n [style.left.px]=\"contentLeft()\"\n [style.top.px]=\"contentTop()\"\n [style.width.px]=\"t().contentWidth\"\n [style.height.px]=\"t().contentHeight\"\n [style.transform]=\"rotate()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"pageTpl()\"\n [ngTemplateOutletContext]=\"templateContext\"\n [ngTemplateOutletInjector]=\"pageInjector\"\n />\n </div>\n <!-- box-space chrome — fills the outer box, NEVER rotates. Bands are plain\n regions: a label is bottom: 0; height: frame().bottom. -->\n @if (chromeTpl(); as chrome) {\n <ng-container\n [ngTemplateOutlet]=\"chrome\"\n [ngTemplateOutletContext]=\"templateContext\"\n [ngTemplateOutletInjector]=\"pageInjector\"\n />\n }\n `,\n})\nexport class EpdfPageSurface {\n readonly vp = input.required<VisiblePage>();\n readonly frame = input.required<PageFrame>();\n readonly documentId = input.required<string>();\n readonly pageTpl = input.required<TemplateRef<EpdfPageTemplateContext>>();\n readonly chromeTpl = input<TemplateRef<EpdfPageTemplateContext> | null>(null);\n\n protected readonly t = computed(() => this.vp().transform);\n\n // Outer box = display footprint + reserved chrome bands; screenX/screenY are\n // the device-snapped footprint top-left, so the box sits one frame further out.\n protected readonly left = computed(() => this.vp().screenX - this.frame().left);\n protected readonly top = computed(() => this.vp().screenY - this.frame().top);\n protected readonly outerWidth = computed(\n () => this.t().viewWidth + this.frame().left + this.frame().right,\n );\n protected readonly outerHeight = computed(\n () => this.t().viewHeight + this.frame().top + this.frame().bottom,\n );\n // Center the (possibly rotated) content box on the display box and rotate\n // about its center — NO translate(), so rotation 0 carries no transform.\n protected readonly contentLeft = computed(\n () => this.frame().left + (this.t().viewWidth - this.t().contentWidth) / 2,\n );\n protected readonly contentTop = computed(\n () => this.frame().top + (this.t().viewHeight - this.t().contentHeight) / 2,\n );\n protected readonly rotate = computed(() => {\n const rotation = this.vp().rotation;\n return rotation ? `rotate(${rotation}deg)` : null;\n });\n\n private readonly contentEl = viewChild.required<ElementRef<HTMLDivElement>>('content');\n\n /** ONE stable context per surface — volatile parts are signals inside it. */\n readonly page: EpdfPageContext = createPageContext({\n documentId: () => this.documentId(),\n pon: () => this.vp().pon,\n pageIndex: computed(() => this.vp().pageIndex),\n frame: this.frame,\n transform: this.t,\n getRect: () => this.contentEl().nativeElement.getBoundingClientRect(),\n });\n\n /** ONE stable injector per surface (see the invariant above), parented to\n * this surface's node injector so layers also reach the kernel host. */\n protected readonly pageInjector = Injector.create({\n providers: [{ provide: EPDF_PAGE, useValue: this.page }],\n parent: inject(Injector),\n });\n\n protected readonly templateContext: EpdfPageTemplateContext = { $implicit: this.page };\n}\n","/**\n * `<epdf-stage>` — virtualizes and positions page surfaces by the camera, and\n * stamps each one with YOUR `<ng-template epdfPage>` — you bring the layers.\n *\n * NULL-SAFE BY DESIGN (a deliberate deviation from React's strict Stage):\n * Angular instantiates projected content eagerly, so a stage constructed\n * before any document exists must not crash — it renders zero pages and its\n * listeners no-op until the document arrives. Teach the document gate anyway:\n * document CHROME (toolbars, panels) still belongs behind `*epdfDocumentGate`.\n *\n * ZONE RULE: every DOM listener here attaches OUTSIDE Angular's zone — a\n * 120Hz pointermove stream must never trigger app-wide change detection.\n * State flows kernel → tick signal → computeds → bindings, so the adapter is\n * zone-agnostic (zoneless recommended, zone.js tolerated).\n */\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n effect,\n ElementRef,\n inject,\n input,\n NgZone,\n PLATFORM_ID,\n} from '@angular/core';\nimport { StageToken, createScrollHandler } from '@embedpdf/plugin-stage';\nimport type { StageCapability, VisiblePage } from '@embedpdf/plugin-stage';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport {\n injectDocumentId,\n injectKernelHost,\n injectOptionalCapability,\n injectOptionalCapabilityFor,\n injectOptionalSelectorFor,\n type CapabilityToken,\n} from '@embedpdf/angular/runtime';\nimport type { PageFrame } from '@embedpdf/plugin-stage';\nimport { createStageSurface } from '@embedpdf/web';\nimport { EpdfPageChrome, EpdfPageTemplate } from './templates';\nimport { EpdfPageSurface } from './page-surface';\n\n/** Which stage lens to bind to. Defaults to the main StageToken — pass a custom\n * token to drive an additional lens (e.g. a wrapped thumbnail sidebar). */\nexport type StageTokenProp = CapabilityToken<StageCapability>;\n\nconst EMPTY_PAGES: VisiblePage[] = [];\nconst NO_FRAME: PageFrame = { top: 0, right: 0, bottom: 0, left: 0 };\nconst frameEqual = (a: PageFrame, b: PageFrame) =>\n a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;\n\n@Component({\n selector: 'epdf-stage',\n standalone: true,\n imports: [EpdfPageSurface],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n style: 'position: relative; overflow: hidden; touch-action: none; display: block;',\n '[style.cursor]': 'cursor()',\n },\n template: `\n @if (pageTemplate(); as tpl) {\n @for (p of pages(); track p.pon) {\n <epdf-page-surface\n [vp]=\"p\"\n [frame]=\"frame()\"\n [documentId]=\"documentId() ?? ''\"\n [pageTpl]=\"tpl\"\n [chromeTpl]=\"chromeTemplate()\"\n />\n }\n }\n <!-- viewport-space overlay UI: anything projected into <epdf-stage>\n renders above the pages (menus, controls, scrollbars). -->\n <ng-content />\n `,\n})\nexport class EpdfStage {\n /**\n * Route this Stage's pointer events to the interaction hub (page-resolved via\n * `pageAt`) — AND register this lens's tool-gated pan-scroll handler with it\n * (lens-scoped, so multiple stages on one document never pan each other).\n * Pan is then the `pan` tool's job and dragging in `pointer` mode selects\n * text (incl. across pages).\n *\n * Default TRUE: registering `interactionPlugin()` is the one opt-in — tools\n * just work; without the hub this is inert and the stage falls back to\n * built-in drag-to-pan, so a hub-less setup costs nothing. Set `false` on\n * SECONDARY lenses (a thumbnail rail) that should stay click-to-navigate\n * instead of feeding the document's tools.\n */\n readonly interaction = input(true);\n /**\n * With `interaction`: let drags over page GAPS pan regardless of the active\n * tool (and show a grab cursor there) — the gutter always pans; there is\n * nothing to draw/select outside a page. Default true.\n */\n readonly panFallback = input(true);\n /**\n * Ambient ZOOM gestures on this stage: ctrl/cmd+wheel and trackpad pinch\n * (Safari gesture events included). Default true. Turn OFF for follower\n * lenses with a fixed magnification (a thumbnail rail should scroll under\n * cmd+wheel, not zoom); pinches are still swallowed either way.\n */\n readonly zoomGestures = input(true);\n /** The stage lens to drive (default: the main StageToken). */\n readonly token = input<StageTokenProp>(StageToken);\n\n private readonly host = injectKernelHost();\n private readonly stage = injectOptionalCapabilityFor(() => this.token());\n private readonly ix = injectOptionalCapability(InteractionToken);\n private readonly useHub = computed(() => this.interaction() && this.ix() !== null);\n // The hub's resolved cursor (text/grab/…), applied to the viewport when driving.\n private readonly hubCursor = this.host.value(() => this.ix()?.cursor() ?? 'default');\n protected readonly cursor = computed(() => (this.useHub() ? this.hubCursor() : null));\n\n protected readonly documentId = injectDocumentId();\n // visiblePages already folds in the camera (each page carries its\n // device-snapped screenX/screenY + transform), so panning re-emits the list —\n // no separate camera subscription needed for positioning. The capability\n // memoizes, so Object.is equality suffices.\n protected readonly pages = injectOptionalSelectorFor(\n () => this.token(),\n (c) => c.visiblePages(),\n EMPTY_PAGES,\n );\n // Reserved chrome bands (screen px), uniform across pages — the frame the\n // outer box reserves and the chrome template paints into.\n protected readonly frame = injectOptionalSelectorFor(\n () => this.token(),\n (c) => c.pageFrame(),\n NO_FRAME,\n frameEqual,\n );\n\n private readonly pageTemplateDir = contentChild(EpdfPageTemplate);\n private readonly chromeTemplateDir = contentChild(EpdfPageChrome);\n protected readonly pageTemplate = computed(() => this.pageTemplateDir()?.template ?? null);\n protected readonly chromeTemplate = computed(() => this.chromeTemplateDir()?.template ?? null);\n\n constructor() {\n if (!isPlatformBrowser(inject(PLATFORM_ID))) return;\n const el = inject(ElementRef).nativeElement as HTMLElement;\n const zone = inject(NgZone);\n\n // Rebinds when the stage capability (document open/close/switch, token\n // change), hub, or gesture flags change — the Angular spelling of the React\n // Stage effect and its dependency array.\n effect((onCleanup) => {\n const stage = this.stage();\n const ix = this.ix();\n const useHub = this.interaction() && !!ix;\n const panFallback = this.panFallback();\n const zoomGestures = this.zoomGestures();\n if (!stage) return; // no document yet — nothing to drive\n\n const cleanups: Array<() => void> = [];\n zone.runOutsideAngular(() => {\n // The WHOLE browser binding — viewport/DPR reporting, sample\n // normalization, gesture controller — is the shared @embedpdf/web\n // surface, so every framework adapter has one feel. This component\n // keeps only Angular glue.\n cleanups.push(\n createStageSurface(el, stage, {\n hub: useHub ? ix : null,\n source: stage.lensId(),\n zoomGestures,\n }),\n );\n // Interaction opt-in lives WITH the sample source: the same knob that\n // forwards this lens's samples also registers its pan-scroll handler,\n // lens-scoped — two stages on one document can never pan each other.\n if (useHub && ix) {\n cleanups.push(\n ix.registerHandler(createScrollHandler(stage, ix, { panFallback }), {\n source: stage.lensId(),\n }),\n );\n }\n });\n onCleanup(() => cleanups.forEach((fn) => fn()));\n });\n }\n}\n","/**\n * Facade inject functions — thin sugar over the capability + generic binding,\n * name-for-name with the React hooks (`useZoom` → `injectZoom`), values\n * replaced by signals.\n *\n * STRICT like their React counterparts: they resolve a document-scoped\n * capability, so call them in document UI (behind `*epdfDocumentGate` /\n * `@if (documentId())`). For always-mounted chrome, read through\n * `injectOptionalSelector` with a fallback instead.\n *\n * Methods LATE-BIND the current capability (`() => cap().zoomIn()`), so a\n * facade captured before a document switch drives the document that is active\n * at CALL time, never a stale one.\n */\nimport type { Signal } from '@angular/core';\nimport { StageToken, settingsEqual } from '@embedpdf/plugin-stage';\nimport type { StageCapability } from '@embedpdf/plugin-stage';\nimport { injectCapability, injectSelector, shallowArray } from '@embedpdf/angular/runtime';\nimport type { StageTokenProp } from './stage';\n\ntype AnyFn = (...args: never[]) => unknown;\n/** Late-binding method passthrough: exact capability signature, current doc. */\nconst lazy = <K extends keyof StageCapability>(\n cap: Signal<StageCapability>,\n key: K,\n): StageCapability[K] =>\n ((...args: unknown[]) =>\n (cap()[key] as unknown as (...a: unknown[]) => unknown)(...args)) as StageCapability[K] &\n AnyFn as StageCapability[K];\n\nexport function injectStage(token: StageTokenProp = StageToken): Signal<StageCapability> {\n return injectCapability(token);\n}\n\nexport function injectZoom(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n zoom: injectSelector(token, (c) => c.zoomLevel()),\n /** Active zoom intent: 'automatic' | 'fit-page' | 'fit-width' | 'fit-all' | 'custom'. */\n mode: injectSelector(token, (c) => c.zoomMode()),\n zoomIn: lazy(s, 'zoomIn'),\n zoomOut: lazy(s, 'zoomOut'),\n fitWidth: lazy(s, 'fitWidth'),\n fitPage: lazy(s, 'fitPage'),\n fitAll: lazy(s, 'fitAll'),\n automatic: lazy(s, 'automatic'),\n zoomTo: lazy(s, 'zoomTo'),\n };\n}\n\nexport function injectPages(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n currentPage: injectSelector(token, (c) => c.currentPage()),\n pageCount: injectSelector(token, (c) => c.pageCount()),\n goToPage: lazy(s, 'goToPage'),\n next: lazy(s, 'next'),\n prev: lazy(s, 'prev'),\n reveal: lazy(s, 'reveal'),\n };\n}\n\nexport function injectLayout(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n flow: injectSelector(token, (c) => c.flow()),\n layout: injectSelector(token, (c) => c.layout()),\n spread: injectSelector(token, (c) => c.spread()),\n sizing: injectSelector(token, (c) => c.sizing()),\n bounded: injectSelector(token, (c) => c.bounded()),\n setFlow: lazy(s, 'setFlow'),\n setLayout: lazy(s, 'setLayout'),\n setSpread: lazy(s, 'setSpread'),\n setSizing: lazy(s, 'setSizing'),\n setBounded: lazy(s, 'setBounded'),\n };\n}\n\n/** The document's page list (with PDF labels) + the current item's pages — the\n * data for page thumbnails / worksheet-style page tabs. */\nexport function injectPageList(token: StageTokenProp = StageToken) {\n return {\n pages: injectSelector(\n token,\n (c) => c.pages(),\n (a, b) =>\n a.length === b.length && a.every((p, i) => p.pon === b[i].pon && p.label === b[i].label),\n ),\n currentItemPages: injectSelector(token, (c) => c.currentItemPages(), shallowArray),\n };\n}\n\n/**\n * All Stage settings + the batch `update`. The seam for \"presets are a customer\n * concern\": keep your own `Partial<StageSettings>` objects and apply them with\n * `update(preset)` (one anchor-preserving change).\n */\nexport function injectStageSettings(token: StageTokenProp = StageToken) {\n const s = injectCapability(token);\n return {\n // settingsEqual derives from the plugin's settings registry — a new setting\n // is covered automatically, without this package spelling out the shape.\n settings: injectSelector(token, (c) => c.settings(), settingsEqual),\n update: lazy(s, 'update'),\n reset: lazy(s, 'resetView'),\n };\n}\n","/**\n * @embedpdf/angular/stage — the viewport trunk: `<epdf-stage>` + page\n * templates + the stage facade inject functions.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stage';\nexport * from './templates';\nexport * from './page-surface';\nexport * from './stage';\nexport * from './facades';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
@@ -77,11 +77,24 @@ type StageTokenProp = CapabilityToken<StageCapability>;
77
77
  declare class EpdfStage {
78
78
  /**
79
79
  * Route this Stage's pointer events to the interaction hub (page-resolved via
80
- * `pageAt`) instead of the built-in drag-to-pan. Pan then becomes the `pan`
81
- * tool's job and dragging in `pointer` mode selects text (incl. across pages).
82
- * Pair with `stagePlugin({ interaction: true })`. Default false (built-in pan).
80
+ * `pageAt`) — AND register this lens's tool-gated pan-scroll handler with it
81
+ * (lens-scoped, so multiple stages on one document never pan each other).
82
+ * Pan is then the `pan` tool's job and dragging in `pointer` mode selects
83
+ * text (incl. across pages).
84
+ *
85
+ * Default TRUE: registering `interactionPlugin()` is the one opt-in — tools
86
+ * just work; without the hub this is inert and the stage falls back to
87
+ * built-in drag-to-pan, so a hub-less setup costs nothing. Set `false` on
88
+ * SECONDARY lenses (a thumbnail rail) that should stay click-to-navigate
89
+ * instead of feeding the document's tools.
83
90
  */
84
91
  readonly interaction: _angular_core.InputSignal<boolean>;
92
+ /**
93
+ * With `interaction`: let drags over page GAPS pan regardless of the active
94
+ * tool (and show a grab cursor there) — the gutter always pans; there is
95
+ * nothing to draw/select outside a page. Default true.
96
+ */
97
+ readonly panFallback: _angular_core.InputSignal<boolean>;
85
98
  /**
86
99
  * Ambient ZOOM gestures on this stage: ctrl/cmd+wheel and trackpad pinch
87
100
  * (Safari gesture events included). Default true. Turn OFF for follower
@@ -106,7 +119,7 @@ declare class EpdfStage {
106
119
  protected readonly chromeTemplate: _angular_core.Signal<_angular_core.TemplateRef<_embedpdf_angular_stage.EpdfPageTemplateContext> | null>;
107
120
  constructor();
108
121
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EpdfStage, never>;
109
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EpdfStage, "epdf-stage", never, { "interaction": { "alias": "interaction"; "required": false; "isSignal": true; }; "zoomGestures": { "alias": "zoomGestures"; "required": false; "isSignal": true; }; "token": { "alias": "token"; "required": false; "isSignal": true; }; }, {}, ["pageTemplateDir", "chromeTemplateDir"], ["*"], true, never>;
122
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EpdfStage, "epdf-stage", never, { "interaction": { "alias": "interaction"; "required": false; "isSignal": true; }; "panFallback": { "alias": "panFallback"; "required": false; "isSignal": true; }; "zoomGestures": { "alias": "zoomGestures"; "required": false; "isSignal": true; }; "token": { "alias": "token"; "required": false; "isSignal": true; }; }, {}, ["pageTemplateDir", "chromeTemplateDir"], ["*"], true, never>;
110
123
  }
111
124
 
112
125
  declare function injectStage(token?: StageTokenProp): Signal<StageCapability>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/angular",
3
- "version": "3.0.0-next.6",
3
+ "version": "3.0.0-next.7",
4
4
  "private": false,
5
5
  "description": "Angular adapter for EmbedPDF v3: one generic signal binding + structural components (EpdfViewer, EpdfStage) + headless layers & inject functions. The whole framework surface, one secondary entry point per feature.",
6
6
  "sideEffects": false,
@@ -29,12 +29,13 @@
29
29
  ],
30
30
  "dependencies": {
31
31
  "tslib": "^2.6.0",
32
- "@embedpdf/core-stage": "3.0.0-next.6",
33
- "@embedpdf/core": "3.0.0-next.6",
34
- "@embedpdf/core-geometry": "3.0.0-next.6",
35
- "@embedpdf/plugin-stage": "3.0.0-next.6",
36
- "@embedpdf/plugin-render": "3.0.0-next.6",
37
- "@embedpdf/plugin-interaction": "3.0.0-next.6"
32
+ "@embedpdf/core-geometry": "3.0.0-next.7",
33
+ "@embedpdf/plugin-stage": "3.0.0-next.7",
34
+ "@embedpdf/plugin-render": "3.0.0-next.7",
35
+ "@embedpdf/core": "3.0.0-next.7",
36
+ "@embedpdf/core-stage": "3.0.0-next.7",
37
+ "@embedpdf/web": "3.0.0-next.7",
38
+ "@embedpdf/plugin-interaction": "3.0.0-next.7"
38
39
  },
39
40
  "peerDependencies": {
40
41
  "@angular/common": ">=20.2.0 <23.0.0",