@embedpdf/plugin-stage 3.0.0-next.15 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ActionsToken","NO_FRAME","ZoomMode","ZoomMode","ZOOM_MAX","ZoomMode","StageToken","ActionsToken","StageToken","ZoomMode"],"sources":["../src/working-set.ts","../src/connect.ts","../src/motion.ts","../src/camera/animation.ts","../src/responsive.ts","../src/settings.ts","../src/model.ts","../src/camera/gestures.ts","../src/camera/write.ts","../src/services/placement-latch.ts","../src/navigation/arrive.ts","../src/destination.ts","../src/navigation/reveal.ts","../src/navigation/zoom.ts","../src/read/pages.ts","../src/services/events.ts","../src/services/scene.ts","../src/services/index.ts","../src/settings/settings.ts","../src/view/lifecycle.ts","../src/controller.ts","../src/stage.plugin.ts","../src/state.ts","../src/scroll-handler.ts"],"sourcesContent":["/**\n * What this lens shows, told to the engine as the lens's working set\n * (`doc.setWorkingSet`): the engine ranks the jobs for those pages by it, and\n * keeps those pages parsed longest. Every lens tells its own, so a thumbnail\n * rail's small pages rank after the main view's.\n *\n * It comes from the pages the lens lays out (`listVisiblePages`):\n * - `visible`: a page with some of it on screen, with that part and its device\n * pixels, which rank visible pages among themselves: the page the user looks\n * at has the most;\n * - `near`: a page laid out just off screen (the scene's overscan), where the\n * view goes next.\n */\nimport type { PluginContext, WorkingSetPage } from '@embedpdf/core';\n\nimport type { VisiblePage } from './contract';\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\n\n/** A lens's working set, from the pages it lays out. */\nexport function workingSetOf(pages: readonly VisiblePage[]): WorkingSetPage[] {\n return pages.map(({ ref, visibleRect, transform }) => {\n if (visibleRect.width <= 0 || visibleRect.height <= 0) {\n return { page: ref, role: 'near', pixels: 0 };\n }\n const pixels = visibleRect.width * visibleRect.height * transform.renderScale ** 2;\n return { page: ref, role: 'visible', visible: visibleRect, pixels: Math.round(pixels) };\n });\n}\n\n/**\n * Tells the engine what the lens shows, now and whenever it changes: once per\n * camera move, so at most once per input event while the camera moves.\n */\nexport function connectWorkingSet(\n ctx: PluginContext<StageState>,\n stage: Pick<StageHostCapability, 'listVisiblePages'>,\n): void {\n let told = '';\n const tell = (shown: readonly VisiblePage[]) => {\n const pages = workingSetOf(shown);\n const key = keyOf(pages);\n if (key === told) return;\n told = key;\n ctx.doc.setWorkingSet(ctx.id, pages);\n };\n ctx.watch(() => stage.listVisiblePages(), tell);\n tell(stage.listVisiblePages());\n}\n\n/** A working set as one comparable string. */\nfunction keyOf(pages: readonly WorkingSetPage[]): string {\n return pages\n .map(({ page, role, visible, pixels }) => {\n const part = visible\n ? `${Math.round(visible.x)},${Math.round(visible.y)},${Math.round(visible.width)},${Math.round(visible.height)}`\n : '';\n return `${page.objectNumber}:${role}:${pixels}:${part}`;\n })\n .join('|');\n}\n","/**\n * The stage's wiring to its surroundings, run once every dependency exists:\n * the refit on page-registry changes and the working set told to the engine\n * (every lens) and, for the default lens only, the page-state feed and the navigation executors of the actions\n * plugin. A thumbnail lens must never report page state or win the\n * last-wins executor registry and start navigating the sidebar.\n */\nimport type { PluginContext } from '@embedpdf/core';\nimport { ActionsToken, type ActionsHostCapability } from '@embedpdf/plugin-actions/contract/host';\n\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\nimport { connectWorkingSet } from './working-set';\n\n/** The id of the main lens; additional lenses register under their own id. */\nexport const DEFAULT_LENS_ID = 'stage';\n\nexport function connectStage(ctx: PluginContext<StageState>, stage: StageHostCapability): void {\n // Rotate, move and delete change the registry revision, so the page geometry\n // under this lens changed: re-resolve the zoom intent and re-place. It\n // reacts to changes only, never to the initial value, so it cannot race the\n // level-triggered initial placement.\n ctx.watch(\n () => ctx.document()?.revision ?? 0,\n () => stage.refit(),\n );\n connectWorkingSet(ctx, stage);\n\n if (ctx.id !== DEFAULT_LENS_ID) return;\n const actions = ctx.tryGet(ActionsToken);\n if (!actions) return;\n feedPageState(ctx, stage, actions);\n registerNavigationExecutors(ctx, stage, actions);\n}\n\n/**\n * The page-state feed. The stage is authoritative for what page the viewer is\n * on; the actions plugin's lifecycle coordinator owns when page-lifecycle\n * triggers fire. The feed reports `{ currentPage, visiblePages, placed, cause }`\n * (page refs, not indexes, so reordering is safe) on placement and on every\n * change; the coordinator buffers reports until the document has opened and\n * diffs them against what it last emitted, so this side only reports.\n */\nfunction feedPageState(\n ctx: PluginContext<StageState>,\n stage: StageHostCapability,\n actions: ActionsHostCapability,\n): void {\n const snapshot = () => {\n const state = ctx.state.get();\n if (!state.placed) return null;\n return {\n currentPage: stage.getCurrentPage(),\n visiblePages: stage.listVisiblePages().map((page) => page.ref),\n cause: state.motionCause,\n };\n };\n ctx.watch(\n // The signature covers what is reported: the current page and the visible\n // page set. `cause` is left out on purpose: a cause flip alone is not a\n // page-state change and must not produce a report.\n () => {\n const current = snapshot();\n return current === null\n ? 'unplaced'\n : `${current.currentPage?.objectNumber ?? -1}|${current.visiblePages\n .map((page) => page.objectNumber)\n .sort((left, right) => left - right)\n .join(',')}`;\n },\n () => {\n const current = snapshot();\n if (current === null) return;\n actions.reportPageState({\n currentPage: current.currentPage,\n visiblePages: current.visiblePages,\n placed: true,\n cause: current.cause,\n });\n },\n );\n}\n\n/**\n * The GoTo and Named page verbs for the action engine. The dispatcher runs\n * them as deferred navigation effects, after every document node of a tree\n * succeeded, never in the middle of a walk. They move the view by its own\n * `scrollBehavior` setting, as a link does. /N Print is not handled here: the\n * dispatcher owns it (policy and the UI adapter).\n */\nfunction registerNavigationExecutors(\n ctx: PluginContext<StageState>,\n stage: StageHostCapability,\n actions: ActionsHostCapability,\n): void {\n ctx.cleanup(\n actions.registerExecutor('goto', (node) => {\n if (node.type !== 'goto') return { status: 'inert', reason: 'not a goto node' };\n if (!ctx.getPage(node.destination.page))\n return { status: 'failed', error: 'the destination page is not in this document' };\n stage.goToDestination(node.destination);\n return { status: 'executed' };\n }),\n );\n ctx.cleanup(\n actions.registerExecutor('named', (node) => {\n if (node.type !== 'named') return { status: 'inert', reason: 'not a named node' };\n switch (node.name) {\n case 'NextPage':\n stage.nextPage();\n return { status: 'executed' };\n case 'PrevPage':\n stage.previousPage();\n return { status: 'executed' };\n case 'FirstPage':\n stage.goToFirstPage();\n return { status: 'executed' };\n case 'LastPage':\n stage.goToLastPage();\n return { status: 'executed' };\n default:\n return { status: 'inert', reason: `unknown named action '${node.name}'` };\n }\n }),\n );\n}\n","/**\n * The camera's motion vocabulary, every formula pure.\n *\n * The capability owns the impure drivers (the clock's frames, state writes,\n * gesture state); the laws those drivers integrate live here, parameterized\n * by elapsed time with no state and no clock, so they are unit-testable in\n * isolation and have no plugin dependencies.\n *\n * Two families:\n * • ballistic — one per-axis law for every free motion: `glideStep` (the\n * touch fling, decaying on UIScrollView's curve) and `springStep` (a\n * critically-damped return to the clamp). A glide that reaches a content\n * edge converts to a spring with its velocity carried in, so the bounce\n * grows out of physics rather than a scripted overshoot.\n * • resistance — the iOS rubber-band curve `rubberOut` and its exact inverse\n * `rubberIn`: dragging past an edge displays an asymptotically bounded\n * stretch, and re-entering a gesture over a stretched camera (catching it\n * mid-bounce) reconstructs the finger-integrated position the curve came\n * from.\n * Plus the tween interpolators: `easeOutCubic` for coordinate tweens and\n * `zoomLerp`, a geometric zoom interpolation (zoom is multiplicative: equal\n * ratios per unit time, not equal deltas).\n */\n\n// ── constants ──\n/** Resistance coefficient of the rubber-band curve (the iOS feel). */\nexport const RUBBER = 0.55;\n/** Glide decay per ms: UIScrollView's normal deceleration rate. */\nexport const FLING_DECAY = 0.998;\n/** px/ms; below about 20 px/s the eye reads \"stopped\". */\nexport const FLING_STOP = 0.02;\n/** rad/ms; critically damped, settling in about 400 ms. */\nexport const SPRING_OMEGA = 0.015;\n\n// ── resistance (rubber-band) ──\n/**\n * Overshoot distance → displayed stretch, asymptotic to the viewport\n * dimension, so the content never leaves the screen however far the finger\n * travels. `rubberOut(0) === 0`: inside the bounds the curve is invisible.\n */\nexport const rubberOut = (distance: number, dimension: number): number =>\n (1 - 1 / ((distance * RUBBER) / dimension + 1)) * dimension;\n/** The exact inverse of `rubberOut` (defined for `stretch < dimension`). */\nexport const rubberIn = (stretch: number, dimension: number): number =>\n (stretch * dimension) / (RUBBER * (dimension - stretch));\n\n// ── ballistic (one axis, one frame) ──\n/** The state one integration step hands back; `done` means \"at rest\". */\nexport interface MotionStep {\n position: number;\n velocity: number;\n done: boolean;\n}\n/**\n * One frame of free glide: exponential velocity decay, the position advanced\n * by the midpoint integral of the decay over `elapsedMs` (exact for the\n * exponential, so frame-rate independent).\n */\nexport const glideStep = (position: number, velocity: number, elapsedMs: number): MotionStep => {\n const decay = Math.pow(FLING_DECAY, elapsedMs);\n const nextPosition = position + velocity * ((elapsedMs * (1 + decay)) / 2);\n const nextVelocity = velocity * decay;\n return Math.abs(nextVelocity) < FLING_STOP\n ? { position: nextPosition, velocity: 0, done: true }\n : { position: nextPosition, velocity: nextVelocity, done: false };\n};\n/**\n * One frame of a critically-damped spring toward `edge`: semi-implicit Euler\n * on x'' = −ω²(x−e) − 2ωx'. Lands exactly on the edge (position snapped,\n * velocity zeroed) once within half a pixel at negligible speed.\n */\nexport const springStep = (\n position: number,\n velocity: number,\n edge: number,\n elapsedMs: number,\n): MotionStep => {\n const nextVelocity =\n velocity +\n (-SPRING_OMEGA * SPRING_OMEGA * (position - edge) - 2 * SPRING_OMEGA * velocity) * elapsedMs;\n const nextPosition = position + nextVelocity * elapsedMs;\n if (Math.abs(nextPosition - edge) < 0.5 && Math.abs(nextVelocity) < 0.01) {\n return { position: edge, velocity: 0, done: true };\n }\n return { position: nextPosition, velocity: nextVelocity, done: false };\n};\n\n// ── tween interpolators ──\nexport const easeOutCubic = (progress: number): number => 1 - Math.pow(1 - progress, 3);\n/**\n * Geometric zoom interpolation: `from·(to/from)^progress`. Zoom is\n * multiplicative, so a constant-rate zoom moves equal ratios per unit time;\n * interpolating the level linearly makes the start rush and the end crawl\n * (and, under a focal anchor, swings the anchored point along a curve).\n */\nexport const zoomLerp = (from: number, to: number, progress: number): number =>\n from * Math.pow(to / from, progress);\n","/**\n * Camera motion over the host's frames (`ctx.clock`): the coordinate tween,\n * the zoom-anchored tween (it animates the invariant, so the focal page-point\n * holds still by construction), and the momentum and edge physics (glide,\n * spring). One frame is waited for at a time: `cancelAnimation`, every verb's\n * first act, is also \"catch\".\n */\nimport {\n cameraForAnchorAtScreen,\n clampCamera,\n type Anchor,\n type Camera,\n type Point,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { Cancel } from '@embedpdf/core';\n\nimport type { StageHostCapability } from '../host-contract';\nimport { easeOutCubic, FLING_STOP, glideStep, springStep, zoomLerp } from '../motion';\nimport type { StageServices } from '../services';\nimport type { StageCameraWrite } from './write';\n\n/** The default tween duration. */\nconst TWEEN_MS = 240;\n\nconst lerp = (from: number, to: number, progress: number) => from + (to - from) * progress;\n\nexport function createAnimation(\n { events, clock, scene }: Pick<StageServices, 'events' | 'clock' | 'scene'>,\n write: StageCameraWrite,\n) {\n const { motionEnded } = events;\n const { camera, viewport, buildScene, stayBounds, constraint } = scene;\n const { writeCamera, writeCameraUnclamped, axisTravels, syncCursorFromCamera } = write;\n\n // Cancels the frame the running motion waits for; null while nothing moves.\n let cancelFrame: Cancel | null = null;\n const cancelAnimation = () => {\n cancelFrame?.();\n cancelFrame = null;\n };\n /** A tween or fling reached its natural end. */\n const endMotion = () => {\n cancelFrame = null;\n motionEnded.emit({ camera: camera() });\n };\n\n // The tween clamps to an explicit bounds rect every frame (never a\n // re-derived current item), so animating toward a different item is not\n // clamped back. `then` runs on natural completion only: a cancelled tween\n // belongs to the verb that cancelled it.\n const animateTo = (target: Camera, bounds: Rect, durationMs = TWEEN_MS, then?: () => void) => {\n if (!clock.hasFrames) {\n writeCamera(target, bounds);\n then?.();\n return;\n }\n cancelAnimation();\n const from = camera();\n let started = false;\n let startedAt = 0;\n const tick = (now: number) => {\n if (!started) {\n started = true;\n startedAt = now; // anchor to the first real timestamp (works even when now === 0)\n }\n const progress = easeOutCubic(Math.min(1, (now - startedAt) / durationMs));\n writeCamera(\n {\n x: lerp(from.x, target.x, progress),\n y: lerp(from.y, target.y, progress),\n zoom: lerp(from.zoom, target.zoom, progress),\n },\n bounds,\n );\n if (progress < 1) {\n cancelFrame = clock.nextFrame(tick);\n } else {\n endMotion();\n then?.();\n }\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n /**\n * The zoom-anchored tween animates the invariant, not the coordinates: the\n * focal page-point stays at `point` while the scale changes. Lerping x, y\n * and zoom independently breaks that mid-flight, because holding a screen\n * point requires `x(t) = focal.x − point.x / zoom(t)`, hyperbolic in the\n * zoom, so linear coordinates swing the tapped point along a curve (a\n * visible dip). Here the zoom interpolates geometrically (zoom is\n * multiplicative) and each frame's camera derives from the anchor at that\n * zoom, then clamps: the focal point is stationary by construction, and a\n * zoom-out rails into its fit as the shrinking travel range lets the clamp\n * take over.\n */\n const animateZoomAnchored = (\n focal: Anchor,\n point: Point,\n targetZoom: number,\n durationMs = TWEEN_MS,\n then?: () => void,\n ) => {\n if (!clock.hasFrames) {\n const scene = buildScene();\n if (scene.itemCount) writeCamera(cameraForAnchorAtScreen(focal, scene, point, targetZoom));\n then?.();\n return;\n }\n cancelAnimation();\n const startZoom = camera().zoom;\n let started = false;\n let startedAt = 0;\n const tick = (now: number) => {\n if (!started) {\n started = true;\n startedAt = now;\n }\n const progress = easeOutCubic(Math.min(1, (now - startedAt) / durationMs));\n const zoom = zoomLerp(startZoom, targetZoom, progress);\n const scene = buildScene();\n if (scene.itemCount) writeCamera(cameraForAnchorAtScreen(focal, scene, point, zoom));\n if (progress < 1) {\n cancelFrame = clock.nextFrame(tick);\n } else {\n endMotion();\n then?.();\n }\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n // Momentum and edge physics, the driver over motion.ts's per-axis laws:\n // glide — the touch fling, decaying on UIScrollView's curve across free\n // travel;\n // spring — a critically-damped return to the clamp, entered when a glide\n // reaches a content edge (the remaining velocity becomes the\n // bounce) or when the motion starts displaced (released while\n // stretched).\n // Axes are independent (a diagonal fling can bounce off the bottom while\n // still gliding horizontally), and every trajectory ends on the clamp. It\n // shares the tween's frame, so cancelAnimation() is also \"catch\":\n // catching mid-bounce holds the stretch.\n const startCameraPhysics = (fingerVelocityX: number, fingerVelocityY: number) => {\n if (!clock.hasFrames) {\n writeCamera(camera()); // no host frames: snap straight into bounds\n return;\n }\n cancelAnimation();\n const zoom = camera().zoom;\n // Per-axis state in screen px (the camera moves opposite the finger;\n // positions scale by zoom once, here, so the laws read in px).\n interface AxisState {\n position: number;\n velocity: number;\n springing: boolean;\n done: boolean;\n }\n const start = camera();\n const startClamped = clampCamera(start, stayBounds(), viewport(), constraint());\n const startBounds = stayBounds();\n const startViewport = viewport();\n const axisState = (\n cameraPosition: number,\n clampedPosition: number,\n fingerVelocity: number,\n ): AxisState => ({\n position: cameraPosition * zoom,\n velocity: -fingerVelocity / 1000,\n springing: cameraPosition !== clampedPosition,\n done: false,\n });\n // A fitting axis takes no ballistic motion: no travel to glide across and\n // no bounce (rigid, like the platform), so its release velocity is\n // discarded. The spring stays armed for a displaced fitting axis.\n const axisX = axisState(\n start.x,\n startClamped.x,\n axisTravels(startBounds.x, startBounds.width, startViewport.width, zoom)\n ? fingerVelocityX\n : 0,\n );\n const axisY = axisState(\n start.y,\n startClamped.y,\n axisTravels(startBounds.y, startBounds.height, startViewport.height, zoom)\n ? fingerVelocityY\n : 0,\n );\n if (\n !axisX.springing &&\n !axisY.springing &&\n Math.hypot(axisX.velocity, axisY.velocity) < FLING_STOP\n ) {\n return;\n }\n let started = false;\n let lastFrameAt = 0;\n const tick = (now: number) => {\n cancelFrame = null;\n // The first frame assumes one 60 Hz step (anchored like the tween, so a\n // first timestamp of 0 works).\n const elapsedMs = started ? Math.min(64, Math.max(1, now - lastFrameAt)) : 16;\n started = true;\n lastFrameAt = now;\n // The clamp of the current position is each axis's home this frame: the\n // edge for a stretched axis, the rest point for a fitting one.\n const home = clampCamera(\n { x: axisX.position / zoom, y: axisY.position / zoom, zoom },\n stayBounds(),\n viewport(),\n constraint(),\n );\n const step = (axis: AxisState, edgeWorld: number) => {\n if (axis.done) return;\n const next = axis.springing\n ? springStep(axis.position, axis.velocity, edgeWorld * zoom, elapsedMs)\n : glideStep(axis.position, axis.velocity, elapsedMs);\n axis.position = next.position;\n axis.velocity = next.velocity;\n axis.done = next.done;\n };\n step(axisX, home.x);\n step(axisY, home.y);\n // A glide that left the travel range converts to a spring at the edge;\n // the incoming velocity carries in, so the bounce grows out of physics\n // rather than a scripted overshoot.\n const nextHome = clampCamera(\n { x: axisX.position / zoom, y: axisY.position / zoom, zoom },\n stayBounds(),\n viewport(),\n constraint(),\n );\n const convert = (axis: AxisState, clampedPosition: number) => {\n if (!axis.springing && Math.abs(clampedPosition * zoom - axis.position) > 1e-6) {\n axis.position = clampedPosition * zoom;\n axis.springing = true;\n axis.done = false;\n }\n };\n convert(axisX, nextHome.x);\n convert(axisY, nextHome.y);\n writeCameraUnclamped({ x: axisX.position / zoom, y: axisY.position / zoom, zoom });\n syncCursorFromCamera();\n if (axisX.done && axisY.done) {\n writeCamera(camera()); // the exact landing: clamped, snapped, settled\n motionEnded.emit({ camera: camera() });\n return;\n }\n cancelFrame = clock.nextFrame(tick);\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n return {\n cancelAnimation,\n animateTo,\n animateZoomAnchored,\n startCameraPhysics,\n api: {\n fling: (velocityX, velocityY) => startCameraPhysics(velocityX, velocityY),\n isMoving: () => cancelFrame !== null,\n stopMotion: () => {\n if (!cancelFrame) return;\n cancelAnimation();\n motionEnded.emit({ camera: camera() });\n },\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageAnimation = ReturnType<typeof createAnimation>;\n","import { NO_FRAME } from '@embedpdf/core-geometry';\nimport type { Size } from '@embedpdf/core-stage';\nimport type {\n BoxQuery,\n ResponsiveRule,\n StageBox,\n StageSettings,\n StageSettingsPatch,\n} from './contract';\n\n/**\n * Container queries for the settings bag, the pure half. The capability owns\n * the driver (when to re-resolve, how to react); the laws live here: what a\n * box is, when a query matches, and what the effective settings are. No\n * state, so they are property-testable in isolation.\n *\n * The query vocabulary is only the box: a headless, DOM-free stage knows\n * exactly one environmental fact, the viewport it was told. Anything else\n * (pointer coarseness, platform, app state) is either per event\n * (`PointerSample.pointerType`) or the app's own business via\n * `updateSettings()`.\n */\n\n/** The reported viewport as a queryable box. A square box is 'portrait' (CSS). */\nexport const boxOf = (size: Size): StageBox => ({\n width: size.width,\n height: size.height,\n orientation: size.height >= size.width ? 'portrait' : 'landscape',\n});\n\n/** All bounds inclusive, all fields optional, every condition must hold (CSS ranges). */\nexport const matchesQuery = (query: BoxQuery, box: StageBox): boolean =>\n (query.minWidth === undefined || box.width >= query.minWidth) &&\n (query.maxWidth === undefined || box.width <= query.maxWidth) &&\n (query.minHeight === undefined || box.height >= query.minHeight) &&\n (query.maxHeight === undefined || box.height <= query.maxHeight) &&\n (query.orientation === undefined || box.orientation === query.orientation);\n\nconst ruleMatches = (rule: ResponsiveRule, box: StageBox): boolean =>\n typeof rule.when === 'function' ? !!rule.when(box) : matchesQuery(rule.when, box);\n\n/**\n * Merge a patch over settings, skipping undefined values (Partial semantics).\n * Each value replaces the setting whole; a `pageFrame` that names only some\n * sides reserves 0 on the others.\n */\nexport const mergeSettings = (into: StageSettings, patch: StageSettingsPatch): StageSettings => {\n const merged = { ...into };\n let key: keyof StageSettingsPatch;\n for (key in patch) {\n const value = key === 'pageFrame' ? frameOf(patch.pageFrame) : patch[key];\n if (value !== undefined) Object.assign(merged, { [key]: value });\n }\n return merged;\n};\n\nconst frameOf = (frame: StageSettingsPatch['pageFrame']) =>\n frame === undefined ? undefined : { ...NO_FRAME, ...frame };\n\n/**\n * Setting-value equality: primitives by identity, the flat objects the\n * settings vocabulary uses (`{ px }`, `{ x, y }`, page frames, zoom specs) by\n * one level of own-key comparison. Settings values are never nested deeper.\n */\nexport const eqSetting = (left: unknown, right: unknown): boolean => {\n if (left === right) return true;\n if (typeof left !== 'object' || typeof right !== 'object' || left === null || right === null) {\n return false;\n }\n const leftKeys = Object.keys(left);\n return (\n leftKeys.length === Object.keys(right).length &&\n leftKeys.every(\n (key) => (left as Record<string, unknown>)[key] === (right as Record<string, unknown>)[key],\n )\n );\n};\n\nexport interface ResolvedResponsive {\n /** The base merged with every matching rule's patch, in source order (later wins per key). */\n effective: StageSettings;\n /** Names of the matching rules, in source order. */\n active: string[];\n}\n\nexport const resolveResponsive = (\n base: StageSettings,\n rules: readonly ResponsiveRule[],\n box: StageBox,\n): ResolvedResponsive => {\n let effective = base;\n const active: string[] = [];\n for (const rule of rules) {\n if (!ruleMatches(rule, box)) continue;\n if (rule.name !== undefined) active.push(rule.name);\n if (rule.settings) effective = mergeSettings(effective, rule.settings);\n }\n return { effective, active };\n};\n","import { ZoomMode } from '@embedpdf/core-stage';\nimport type { ResponsiveRule, StageSettings } from './contract';\nimport { eqSetting } from './responsive';\n\n/**\n * Out-of-the-box defaults: a document-reading feel. Every field is overridable\n * in `stagePlugin(config)` and at runtime through `updateSettings()`. The\n * plugin ships no named presets (\"document\", \"canvas\", …): a preset is an\n * object the app keeps and passes to `updateSettings()`, so that taxonomy\n * stays the app's concern.\n */\nexport const DEFAULT_SETTINGS: StageSettings = {\n flow: 'continuous',\n layout: 'vertical',\n spread: 'none',\n sizing: 'intrinsic',\n columns: 'square',\n bounded: true,\n padding: 24,\n gap: 16,\n pageFrame: { top: 0, right: 0, bottom: 0, left: 0 },\n direction: 'ltr',\n fitAlign: { x: 'center', y: 'center' },\n // The reading defaults: navigation lands at the top and reading start at\n // every zoom, button zoom inflates around the middle, and resizes pin the\n // top (the browser scroll model). Construction and presentation apps set\n // all of these to center/center.\n arrivalAlign: { x: 'start', y: 'start' },\n zoomAlign: { x: 'center', y: 'center' },\n anchorAlign: { x: 'start', y: 'start' },\n viewRotation: 0,\n zoom: { mode: ZoomMode.Automatic },\n scrollBehavior: 'smooth',\n interaction: true,\n panFallback: true,\n zoomGestures: true,\n // Web: 1 PDF point = 96/72 CSS px, so 100% is physically accurate. A native\n // adapter overrides this at registration with its own logical-unit factor.\n viewUnitsPerPoint: 96 / 72,\n};\n\n/**\n * Out-of-the-box responsive rules, the platform feel with zero configuration:\n * a compact container gets the thin gutter phones use (space, not device: an\n * embedded 500px pane on a desktop is compact too). Override the whole list\n * with `stagePlugin({ responsive: [...] })`; `responsive: []` opts out. The\n * 'compact' name is queryable by the app through `stage.matchesRule('compact')`.\n */\nexport const DEFAULT_RESPONSIVE: readonly ResponsiveRule[] = [\n { name: 'compact', when: { maxWidth: 600 }, settings: { padding: 4 } },\n];\n\n/**\n * How a change to each setting affects the view: the single source of truth.\n * One row per setting, completeness enforced by the compiler (`Record<keyof\n * StageSettings, …>`: adding a setting without classifying it is a type error).\n * Everything else derives from this table: the scene-cache invalidation and\n * key, `updateSettings()`'s reaction, the settings snapshot and patch picks,\n * and the React selector equality.\n *\n * 'reflow' — crosses the flow boundary: camera coordinates are meaningless\n * there, so re-place canonically onto the cursor's page.\n * 'scene' — a layout input: invalidates the scene, then re-applies the anchor.\n * 'refit' — re-resolves zoom against the (possibly re-keyed) scene: re-applies\n * the anchor without an explicit invalidation.\n * 'reclamp' — pure clamp policy: re-clamp the current camera in place.\n * 'none' — guides future verbs and the surface binding only\n * (arrival/zoom/anchor alignment, scroll behavior, input).\n *\n * The classes also carry each change's invariant — what stays fixed while the\n * view reacts: 'refit' (a zoom-intent change) holds the zoomAlign focal point;\n * 'scene' reframes (and viewport resizes) hold the anchorAlign point.\n */\nexport type SettingEffect = 'reflow' | 'scene' | 'refit' | 'reclamp' | 'none';\nexport const SETTINGS_EFFECT: Record<keyof StageSettings, SettingEffect> = {\n flow: 'reflow',\n layout: 'scene',\n spread: 'scene',\n sizing: 'scene',\n columns: 'scene',\n bounded: 'reclamp',\n padding: 'reclamp',\n gap: 'scene',\n pageFrame: 'scene',\n direction: 'scene',\n fitAlign: 'reclamp',\n arrivalAlign: 'none',\n zoomAlign: 'none',\n anchorAlign: 'none',\n viewRotation: 'scene', // a layout input: every page's footprint swaps w↔h\n zoom: 'refit',\n scrollBehavior: 'none',\n // Read by the surface binding, which rebinds its pointer input when they change.\n interaction: 'none',\n panFallback: 'none',\n zoomGestures: 'none',\n viewUnitsPerPoint: 'scene', // a layout input: changing it resizes every page\n};\nexport const SETTING_KEYS = Object.keys(SETTINGS_EFFECT) as Array<keyof StageSettings>;\n\n/** Field-by-field settings equality, derived from the registry, so a new\n * setting is covered automatically: what an adapter compares settings with. */\nexport const settingsEqual = (left: StageSettings, right: StageSettings): boolean =>\n SETTING_KEYS.every((key) => eqSetting(left[key], right[key]));\n\n/** The settings slice of a larger object (state, or a saved view), derived\n * from the registry so the shape is never spelled out by hand. */\nexport const pickSettings = (source: StageSettings): StageSettings => {\n const settings: Partial<Record<keyof StageSettings, unknown>> = {};\n for (const key of SETTING_KEYS) settings[key] = source[key];\n return settings as StageSettings;\n};\n","/**\n * The stage's session state: the flat settings bag plus the camera, the\n * viewport, the cursor and the render-commit latch. Every function below is a\n * pure transition; the controller's areas apply them with `ctx.state.update`,\n * and nothing else changes stage state.\n */\nimport type { Camera, Size } from '@embedpdf/core-stage';\n\nimport type { StageConfig, StageSettings } from './contract';\nimport { mergeSettings } from './responsive';\nimport { DEFAULT_SETTINGS } from './settings';\n\nexport interface StageState extends StageSettings {\n readonly camera: Camera;\n /**\n * One-way render-commit latch. False while the initial viewport-driven\n * placement is unresolved; true only after its camera and settings writes\n * have completed. Page and scroll screen-space reads refuse to answer while\n * false, so an adapter can never paint the placeholder camera at the origin.\n */\n readonly placed: boolean;\n /**\n * Names of the responsive rules currently matching the box, in source order.\n * State (not derived) so `matchesRule()` is reactive in every framework.\n */\n readonly activeRules: readonly string[];\n /**\n * False while the zoom is in motion, true once it has rested (about 150 ms\n * of frames without a zoom write). Device-snapping of page origins is gated\n * on this: a continuous zoom and a snapped origin cannot coexist without the\n * anchor point jittering ±0.5 device px per step, so pages place\n * fractionally while zooming and snap once at rest. Pans always snap (a pure\n * translation has no anchor error).\n */\n readonly cameraResting: boolean;\n /** The container size the host reported, in viewport px. */\n readonly viewport: Size;\n /**\n * Device pixels per view pixel (web: `window.devicePixelRatio`). Feeds each\n * page's transform so bitmaps render crisp and boxes land on the device\n * grid. Defaults to 1.\n */\n readonly dpr: number;\n /**\n * The current page index, valid in both flows. Navigation sets it; in\n * continuous flow manipulation derives it from the camera; in paged flow\n * panning never moves it (the scene is a one-item slice at this page).\n * An index, so it survives spread and layout regrouping.\n */\n readonly cursor: number;\n /**\n * What last drove the camera or cursor: `'programmatic'` for the arrival\n * and reveal verbs (the ones action executors use), `'user'` for direct\n * manipulation (wheel, drag, scrollbars, embedder scroll calls). The\n * page-state feed hands it to the actions plugin, whose cascade budget\n * counts only programmatic rounds, so user scrolling is never throttled.\n */\n readonly motionCause: 'user' | 'programmatic';\n}\n\nexport const initialStageState = (config: StageConfig): StageState => {\n // `responsive` configures the capability, not the settings: strip it so the\n // spread below stays a pure settings override.\n const { responsive: _responsive, ...overrides } = config;\n return {\n camera: { x: 0, y: 0, zoom: 1 },\n placed: false,\n cameraResting: true,\n viewport: { width: 0, height: 0 },\n dpr: 1,\n cursor: 0,\n motionCause: 'user',\n activeRules: [],\n ...mergeSettings(DEFAULT_SETTINGS, overrides),\n };\n};\n\nexport const setCamera = (state: StageState, camera: Camera): StageState =>\n state.camera === camera ? state : { ...state, camera };\n\nexport const setCameraResting = (state: StageState, resting: boolean): StageState =>\n state.cameraResting === resting ? state : { ...state, cameraResting: resting };\n\nexport const markPlaced = (state: StageState): StageState =>\n state.placed ? state : { ...state, placed: true };\n\nexport const setViewport = (state: StageState, viewport: Size): StageState =>\n state.viewport === viewport ? state : { ...state, viewport };\n\nexport const setDpr = (state: StageState, dpr: number): StageState =>\n state.dpr === dpr ? state : { ...state, dpr };\n\nexport const setCursor = (state: StageState, cursor: number): StageState =>\n state.cursor === cursor ? state : { ...state, cursor };\n\nexport const setMotionCause = (\n state: StageState,\n motionCause: StageState['motionCause'],\n): StageState => (state.motionCause === motionCause ? state : { ...state, motionCause });\n\n/**\n * Merge a settings patch. Undefined values are skipped, so a partial restore\n * never clears a setting; the area that patches decides what camera\n * follow-up the change needs.\n */\nexport function patchSettings(state: StageState, patch: Partial<StageSettings>): StageState {\n let next = state;\n let key: keyof StageSettings;\n for (key in patch) {\n const value = patch[key];\n if (value === undefined || Object.is(next[key], value)) continue;\n if (next === state) next = { ...state };\n Object.assign(next, { [key]: value });\n }\n return next;\n}\n\nexport const setActiveRules = (state: StageState, activeRules: readonly string[]): StageState =>\n state.activeRules === activeRules ? state : { ...state, activeRules };\n","/**\n * Direct manipulation: set, pan, scroll and pinch-zoom the camera, and the\n * gesture bracket. The camera moves freely and the cursor is derived from it\n * (the manipulation direction of cursor reconciliation).\n */\nimport {\n anchorAtPoint,\n cameraForAnchorAtScreen,\n cameraFromScroll,\n clampCamera,\n panByScreen,\n toWorld,\n zoomAround,\n} from '@embedpdf/core-stage';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageScrollToOptions } from '../contract';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, type StageState } from '../model';\nimport type { StagePageReads } from '../read/pages';\nimport type { StageServices } from '../services';\nimport type { StageAnimation } from './animation';\nimport type { StageCameraWrite } from './write';\n\nexport function createGestures(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n write: StageCameraWrite,\n { cancelAnimation, animateTo, startCameraPhysics }: StageAnimation,\n { scrollMetricsNow }: Pick<StagePageReads, 'scrollMetricsNow'>,\n) {\n const { camera, viewport, padding, buildScene, stayBounds, constraint } = scene;\n const {\n gesture,\n armRest,\n writeCamera,\n writeCameraUnclamped,\n rubberize,\n unrubberize,\n syncCursorFromCamera,\n markCause,\n } = write;\n\n const scrollTo = (options: StageScrollToOptions): void => {\n markCause('user');\n cancelAnimation();\n if (!buildScene().itemCount) return;\n const next = cameraFromScroll(camera(), stayBounds(), viewport(), padding(), options);\n if (options.behavior === 'smooth') {\n animateTo(next, stayBounds(), undefined, syncCursorFromCamera);\n } else {\n writeCamera(next);\n syncCursorFromCamera();\n }\n };\n\n return {\n api: {\n setCamera: (next) => {\n markCause('user');\n cancelAnimation();\n writeCamera(next);\n syncCursorFromCamera();\n },\n panBy: (dx, dy) => {\n markCause('user');\n cancelAnimation();\n if (gesture.depth > 0 && gesture.elastic) {\n // Elastic: integrate the finger on the unclamped camera and display\n // it through the resistance curve. Initialized from the displayed\n // camera's inverse, so catching a mid-bounce stretch continues\n // seamlessly.\n gesture.raw = panByScreen(gesture.raw ?? unrubberize(camera()), dx, dy);\n writeCameraUnclamped(rubberize(gesture.raw));\n } else {\n writeCamera(panByScreen(camera(), dx, dy));\n }\n syncCursorFromCamera();\n },\n scrollTo,\n scrollBy: ({ left, top, behavior }) => {\n const metrics = scrollMetricsNow();\n scrollTo({\n left: left === undefined ? undefined : metrics.scrollLeft + left,\n top: top === undefined ? undefined : metrics.scrollTop + top,\n behavior,\n });\n },\n zoomAround: (point, factor) => {\n cancelAnimation();\n const before = buildScene();\n // The page-relative focal point: the durable identity of \"what is\n // under the pointer\".\n const focal = before.itemCount ? anchorAtPoint(before, toWorld(camera(), point)) : null;\n writeCamera(zoomAround(camera(), point, factor));\n // Record the resulting level as the zoom intent (focal, so no\n // re-anchor). Inside a gesture bracket it is deferred to endGesture:\n // one patch per pinch instead of one per event.\n if (gesture.depth === 0) {\n ctx.state.update(patchSettings, { zoom: { level: camera().zoom } });\n }\n // When zoom is a layout input (a wrapped grid) the scene may just have\n // re-wrapped under the camera, leaving the old world point stale:\n // re-pin the same page-point under the pointer and clamp against the\n // new geometry. In every other mode the scene is unchanged and this\n // never runs.\n const after = buildScene();\n if (after !== before && focal && after.itemCount) {\n writeCamera(cameraForAnchorAtScreen(focal, after, point, camera().zoom));\n }\n // A zoom write in an elastic gesture (a pinch) re-bases the pan\n // integrator: the bounds just changed shape under the stretch, so\n // the displayed camera becomes the new reference.\n if (gesture.depth > 0 && gesture.elastic) gesture.raw = unrubberize(camera());\n syncCursorFromCamera();\n },\n beginGesture: (options) => {\n gesture.depth++;\n if (gesture.depth === 1) {\n cancelAnimation(); // catch: the next touch-down stops any tween or fling\n gesture.zoomed = false;\n gesture.elastic = options?.elastic === true;\n gesture.raw = null;\n }\n },\n endGesture: () => {\n if (gesture.depth === 0) return;\n gesture.depth--;\n if (gesture.depth > 0) return;\n gesture.raw = null;\n const wasElastic = gesture.elastic;\n gesture.elastic = false;\n if (gesture.zoomed) {\n gesture.zoomed = false;\n // The deferred zoom intent: one patch for the whole gesture. (In a\n // wrapped grid this may re-wrap the scene; the next reframe\n // re-anchors through the normal update path.)\n ctx.state.update(patchSettings, { zoom: { level: camera().zoom } });\n armRest(); // the gesture is over: the rest countdown runs now\n }\n syncCursorFromCamera();\n if (wasElastic) {\n // Released while stretched: spring home. A fling() right after\n // re-enters the same physics with the release velocity.\n const current = camera();\n const clamped = clampCamera(current, stayBounds(), viewport(), constraint());\n if (clamped.x !== current.x || clamped.y !== current.y) startCameraPhysics(0, 0);\n }\n },\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageGestures = ReturnType<typeof createGestures>;\n","/**\n * The camera write path: the one low-level clamped write (`writeCamera`), the\n * elastic unclamped write and its rubber-band curves, the rest detector that\n * gates device snapping, the gesture bracket state, and cursor reconciliation\n * from the camera (manipulation only; navigation sets the cursor as intent).\n */\nimport {\n clampCamera,\n anchorFromCamera,\n travelRange,\n type Camera,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { Cancel, PluginContext } from '@embedpdf/core';\n\nimport { setCamera, setCameraResting, setCursor, setMotionCause, type StageState } from '../model';\nimport { rubberIn, rubberOut } from '../motion';\nimport type { StageServices } from '../services';\n\n/** How long the zoom must hold still before the camera counts as resting. */\nconst REST_MS = 150;\n\nexport function createCameraWrite(\n ctx: PluginContext<StageState>,\n { clock, placement, scene }: Pick<StageServices, 'clock' | 'placement' | 'scene'>,\n) {\n const { camera, viewport, paged, buildScene, stayBounds, constraint } = scene;\n\n // ── the gesture bracket (touch pan and pinch) ──\n // While open, zoomAround defers its zoom-intent patch and the rest\n // countdown is held: a hesitation inside a pinch is not \"at rest\". Depth-\n // counted so nested brackets compose. An elastic gesture may also hold the\n // camera past the clamp (rubber-band); `raw` is its unclamped,\n // finger-integrated camera, which the resistance curve maps to what renders.\n const gesture = { depth: 0, zoomed: false, elastic: false, raw: null as Camera | null };\n\n // ── the camera-rest detector ──\n // Origin snapping is gated on rest (see `StageState.cameraResting`): pages\n // place fractionally while the zoom moves and snap once it has held still\n // for REST_MS.\n let cancelRest: Cancel | null = null;\n const stopRestCountdown = () => {\n cancelRest?.();\n cancelRest = null;\n };\n const armRest = () => {\n // Initial placement snaps immediately (the first paint is crisp), and a\n // host without frames keeps snapping always on: rest-gating refines live\n // gestures and is not part of the contract.\n if (!clock.hasFrames || !placement.started) return;\n ctx.state.update(setCameraResting, false);\n stopRestCountdown();\n cancelRest = clock.after(REST_MS, () => {\n cancelRest = null;\n ctx.state.update(setCameraResting, true);\n });\n };\n\n // The one low-level camera write: clamp to `bounds` and store. It never\n // touches the cursor (see syncCursorFromCamera for that policy).\n const writeCamera = (next: Camera, bounds: Rect = stayBounds()) => {\n const clamped = clampCamera(next, bounds, viewport(), constraint());\n if (clamped.zoom !== camera().zoom) {\n if (gesture.depth > 0) {\n // Mid-gesture: un-rest at once (fractional placement) but hold the\n // countdown; rest is declared at endGesture, not at a pinch hesitation.\n gesture.zoomed = true;\n ctx.state.update(setCameraResting, false);\n stopRestCountdown();\n } else {\n armRest();\n }\n }\n ctx.state.update(setCamera, clamped);\n };\n\n // ── rubber-band (elastic overscroll) ──\n // The curve pair lives in motion.ts; these adapt it to camera state. The\n // rubber softens only the edges of a scroll range: an axis whose content\n // fits the viewport has no travel, the clamp holds it at its fitAlign rest,\n // and it stays rigid however hard the finger tugs (the UIScrollView\n // default: bouncing exists only where content exceeds the bounds).\n const axisTravels = (origin: number, content: number, view: number, zoom: number): boolean =>\n !travelRange(origin, content, view, zoom, constraint().padding).fits;\n /** The unclamped finger-integrated camera → the displayed camera: clamp,\n * then re-apply the overshoot through the resistance curve, per travelling\n * axis. Inside the bounds this is exactly the clamp, and on a fitting axis\n * it is always the clamp. */\n const rubberize = (raw: Camera): Camera => {\n const clamped = clampCamera(raw, stayBounds(), viewport(), constraint());\n const size = viewport();\n const bounds = stayBounds();\n const axis = (\n rawPosition: number,\n clampedPosition: number,\n dimension: number,\n travels: boolean,\n ): number => {\n if (!travels) return clampedPosition;\n const overshootWorld = rawPosition - clampedPosition;\n if (overshootWorld === 0) return clampedPosition;\n const stretch = rubberOut(Math.abs(overshootWorld) * raw.zoom, Math.max(1, dimension));\n return clampedPosition + (Math.sign(overshootWorld) * stretch) / raw.zoom;\n };\n return {\n zoom: raw.zoom,\n x: axis(\n raw.x,\n clamped.x,\n size.width,\n axisTravels(bounds.x, bounds.width, size.width, raw.zoom),\n ),\n y: axis(\n raw.y,\n clamped.y,\n size.height,\n axisTravels(bounds.y, bounds.height, size.height, raw.zoom),\n ),\n };\n };\n /** The displayed camera → the raw position `rubberize` would have produced\n * it from. The overshoot is capped just under the asymptote so the inverse\n * stays finite whatever state a catch finds the camera in. */\n const unrubberize = (displayed: Camera): Camera => {\n const clamped = clampCamera(displayed, stayBounds(), viewport(), constraint());\n const size = viewport();\n const bounds = stayBounds();\n const axis = (\n displayedPosition: number,\n clampedPosition: number,\n dimension: number,\n travels: boolean,\n ): number => {\n if (!travels) return clampedPosition;\n const overshootWorld = displayedPosition - clampedPosition;\n if (overshootWorld === 0) return clampedPosition;\n const span = Math.max(1, dimension);\n const stretch = Math.min(Math.abs(overshootWorld) * displayed.zoom, span - 1);\n return (\n clampedPosition + (Math.sign(overshootWorld) * rubberIn(stretch, span)) / displayed.zoom\n );\n };\n return {\n zoom: displayed.zoom,\n x: axis(\n displayed.x,\n clamped.x,\n size.width,\n axisTravels(bounds.x, bounds.width, size.width, displayed.zoom),\n ),\n y: axis(\n displayed.y,\n clamped.y,\n size.height,\n axisTravels(bounds.y, bounds.height, size.height, displayed.zoom),\n ),\n };\n };\n // The elastic write path, with no clamp: used only by the elastic pan and\n // the edge spring, whose math guarantees every trajectory ends clamped.\n const writeCameraUnclamped = (next: Camera) => ctx.state.update(setCamera, next);\n\n /**\n * Cursor reconciliation, one direction per interaction:\n * navigation → the cursor is intent, set explicitly; the camera honors\n * it as far as the clamp allows, and a clamped camera\n * never revokes it.\n * manipulation → (pan, drag, pinch) the camera moves freely and the\n * cursor is derived from it. Only those verbs call this.\n * Paged flow never syncs.\n */\n const syncCursorFromCamera = () => {\n if (paged()) return;\n const scene = buildScene();\n if (!scene.itemCount) return;\n ctx.state.update(setCursor, anchorFromCamera(camera(), scene, viewport()).pageIndex);\n };\n\n /** Tag what drives the next camera or cursor change (see `StageState.motionCause`). */\n const markCause = (cause: StageState['motionCause']): void =>\n ctx.state.update(setMotionCause, cause);\n\n return {\n gesture,\n armRest,\n writeCamera,\n writeCameraUnclamped,\n axisTravels,\n rubberize,\n unrubberize,\n syncCursorFromCamera,\n markCause,\n };\n}\nexport type StageCameraWrite = ReturnType<typeof createCameraWrite>;\n","/**\n * The behavioral placement latch: it flips when initial placement starts,\n * while `StageState.placed` is the render-commit latch that flips only after\n * placement finishes. Camera behavior keys on this one; renderers key on\n * `placed`, so partial geometry is never observable.\n */\nimport type { ScrollBehaviorKind } from '../contract';\n\nexport interface PlacementLatch {\n started: boolean;\n /** The last navigation asked for before placement; placement applies it last. */\n pending: (() => void) | null;\n}\n\nexport const createPlacementLatch = (): PlacementLatch => ({ started: false, pending: null });\n\n/**\n * Run a navigation verb now, or, before the first placement, when it happens.\n * Before placement there is no viewport to move a camera in, and placement\n * would reset it anyway, so the last call waits and lands instantly after the\n * initial view: an app that reveals something as the document opens sees it\n * on the first frame.\n */\nexport function whenPlaced<Options extends { behavior?: ScrollBehaviorKind }>(\n latch: PlacementLatch,\n options: Options | undefined,\n run: (options: Options | undefined) => void,\n): void {\n if (latch.started) {\n run(options);\n return;\n }\n latch.pending = () => run({ ...options, behavior: 'instant' } as Options);\n}\n","/**\n * Anchors and arrivals. The anchor is the durable \"what am I looking at\":\n * captured before a structural change and re-applied after, one mechanism for\n * layout, spread, zoom, resize and restore. Navigation is canonical:\n * goToPage(N) always ends in the same camera state whatever the zoom or the\n * starting point.\n */\nimport {\n cameraFromAnchor,\n clampCamera,\n placeCamera,\n resolveZoom,\n type AlignmentValue,\n type Anchor,\n type Camera,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { GoToOptions } from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setCursor, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport { whenPlaced } from '../services/placement-latch';\n\nexport function createArrival(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { writeCamera, markCause }: Pick<StageCameraWrite, 'writeCamera' | 'markCause'>,\n { cancelAnimation, animateTo }: Pick<StageAnimation, 'cancelAnimation' | 'animateTo'>,\n) {\n const {\n camera,\n viewport,\n padding,\n paged,\n isFitAll,\n grouping,\n itemIndexOfPage,\n buildScene,\n sceneRect,\n itemRect,\n pageRectOf,\n cursorItem,\n fits,\n alignPoint,\n fitBox,\n boundsFor,\n constraint,\n indexOfTarget,\n } = scene;\n const state = () => ctx.state.get();\n const pageCount = () => ctx.document()?.pageCount ?? 0;\n\n /**\n * Run a placement whose resolved zoom may change the scene (in wrapped mode\n * zoom is a layout input), until the scene it placed against is the scene\n * that results. Every non-wrapped mode is stable after the first pass, and\n * wrapped fit modes converge on the second (the fit box does not depend on\n * wrapping). Capped at 3 passes for the one circular case (fit-all +\n * wrapped).\n */\n const stabilized = (place: () => void) => {\n for (let attempt = 0; attempt < 3; attempt++) {\n const before = buildScene();\n place();\n if (buildScene() === before) return;\n }\n };\n\n const applyAnchor = (anchor: Anchor, align?: AlignmentValue) => {\n stabilized(() => {\n const current = buildScene();\n if (!current.itemCount) return;\n const item = current.items[current.itemOfPage(anchor.pageIndex)];\n const zoom = resolveZoom(state().zoom, fitBox(item), viewport(), padding());\n // Resolved against the current viewport: a resize restores the anchor\n // to the new viewport's policy point (start/start keeps the top pinned).\n const at = alignPoint(align ?? state().anchorAlign, viewport());\n writeCamera(cameraFromAnchor(anchor, current, viewport(), zoom, at), boundsFor(item));\n });\n };\n /**\n * Re-apply the view after a structural, zoom or viewport change. Normally\n * anchor-preserving (keep looking at the same spot, held at the invariant\n * point). Under fit-all the subject is the whole scene, so keeping an\n * anchor is meaningless: re-place instead (which also centers the scene\n * when unbounded).\n */\n const reapply = (anchor: Anchor, align?: AlignmentValue) => {\n if (isFitAll()) goToTarget(state().cursor, { behavior: 'instant' });\n else applyAnchor(anchor, align);\n };\n\n const goToTarget = (pageIndex: number, options?: GoToOptions) => {\n markCause('programmatic');\n cancelAnimation();\n if (pageCount() === 0) return;\n const target = Math.max(0, Math.min(pageIndex, pageCount() - 1));\n ctx.state.update(setCursor, target);\n\n // The restore path (per-page view memory): the exact viewpoint instead of\n // a fresh placement.\n if (options?.viewpoint) {\n ctx.state.update(patchSettings, { zoom: options.viewpoint.zoom });\n applyAnchor(options.viewpoint.anchor);\n return;\n }\n\n // Placement against the current scene; null when there is nothing to place.\n const placement = (): { camera: Camera; bounds: Rect } | null => {\n const current = buildScene(); // paged: the (possibly new) slice; continuous: the full scene\n if (!current.itemCount) return null;\n const item = paged() ? current.items[0] : current.items[itemIndexOfPage(target)];\n const zoom = resolveZoom(state().zoom, fitBox(item), viewport(), padding());\n const subject = isFitAll()\n ? sceneRect()\n : fits(itemRect(item), zoom)\n ? itemRect(item)\n : pageRectOf(item, target);\n // The landing policy: a per-call override beats the setting, and 'keep'\n // pins that axis to the current camera.\n const landing = { ...state().arrivalAlign, ...options?.arrivalAlign };\n const placed = placeCamera(\n subject,\n viewport(),\n zoom,\n padding(),\n {\n x: landing.x === 'keep' ? 'start' : landing.x,\n y: landing.y === 'keep' ? 'start' : landing.y,\n },\n state().direction,\n );\n // Arrivals are canonical even on an unbounded stage: the landing clamps\n // within the true bounds regardless (free roam is a manipulation\n // affordance, not an arrival one), so an axis with no freedom collapses\n // to its fitAlign rest and the fit-all scene centers even unbounded.\n const bounds = boundsFor(item);\n const settled = clampCamera(placed, bounds, viewport(), { ...constraint(), bounded: true });\n return {\n camera: {\n zoom,\n x: landing.x === 'keep' ? camera().x : settled.x,\n y: landing.y === 'keep' ? camera().y : settled.y,\n },\n bounds,\n };\n };\n\n if ((options?.behavior ?? state().scrollBehavior) === 'smooth') {\n const landing = placement();\n if (landing) animateTo(landing.camera, landing.bounds);\n } else {\n // An instant placement converges with the scene (wrapped: zoom is a layout input).\n stabilized(() => {\n const landing = placement();\n if (landing) writeCamera(landing.camera, landing.bounds);\n });\n }\n };\n\n /** Step by the navigation unit: the item when it fits the viewport, else the page. */\n const step = (direction: 1 | -1, options?: GoToOptions) => {\n const item = cursorItem();\n if (!item) return;\n const { grouping: groups } = grouping();\n if (isFitAll() || fits(itemRect(item), camera().zoom)) {\n const index = Math.max(\n 0,\n Math.min(itemIndexOfPage(state().cursor) + direction, groups.length - 1),\n );\n goToTarget(groups[index][0], options);\n } else {\n goToTarget(state().cursor + direction, options);\n }\n };\n\n // Home is page 0, a fresh arrival at arrivalAlign (the clamp collapses any\n // fitting axis to its fitAlign rest point).\n const resetView = (): void => goToTarget(0, { behavior: 'instant' });\n\n return {\n stabilized,\n applyAnchor,\n reapply,\n goToTarget,\n resetView,\n api: {\n goToPage: (page, options) => {\n const index = indexOfTarget(page);\n if (index !== null) whenPlaced(placement, options, (go) => goToTarget(index, go));\n },\n goToFirstPage: (options) => whenPlaced(placement, options, (go) => goToTarget(0, go)),\n goToLastPage: (options) =>\n whenPlaced(placement, options, (go) =>\n goToTarget(Math.max(0, (ctx.document()?.pageCount ?? 1) - 1), go),\n ),\n canGoNext: () => state().cursor < pageCount() - 1,\n canGoPrevious: () => state().cursor > 0,\n nextPage: (options) => whenPlaced(placement, options, (go) => step(1, go)),\n previousPage: (options) => whenPlaced(placement, options, (go) => step(-1, go)),\n resetView,\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageArrival = ReturnType<typeof createArrival>;\n","/**\n * A destination as a reveal. A destination (ISO 32000-1 §12.3.2.2) says\n * where on a page to look and how close; the stage's reveal takes the same\n * three knobs:\n * rect — what to look at: a point for `xyz`, a rect for `fitR`, the page\n * for `fit` and the `fitB*` kinds\n * zoom — 'keep' | {level} | 'fit' | 'fit-width' | 'fit-height'\n * anchor — where it lands; 'keep' is the specification's `null`: keep the\n * current value on that axis\n *\n * Destinations are in page space, the stage's own space, so nothing converts.\n * The `fitB*` kinds fit the page's content bounding box; the whole page\n * stands in for it.\n */\nimport type { PageDestination, PdfSize } from '@embedpdf/core';\n\nimport type { RevealOptions } from './contract';\n\nexport function revealOfDestination(destination: PageDestination, size: PdfSize): RevealOptions {\n const { width, height } = size;\n switch (destination.kind) {\n case 'xyz': {\n const { x, y, zoom } = destination;\n return {\n // A null axis keeps the current camera value; the number fed in for\n // it is never read (the 'keep' anchor).\n rect: { x: x ?? 0, y: y ?? 0, width: 0, height: 0 },\n anchor: { x: x != null ? 'start' : 'keep', y: y != null ? 'start' : 'keep' },\n // A zoom of 0 means the same as null: keep the current zoom.\n zoom: zoom != null && zoom !== 0 ? { level: zoom } : 'keep',\n };\n }\n case 'fit':\n return { zoom: 'fit' };\n case 'fitB':\n return { rect: { x: 0, y: 0, width, height }, zoom: 'fit' };\n case 'fitH':\n case 'fitBH': {\n const { y } = destination;\n return {\n rect: { x: 0, y: y ?? 0, width, height: 0 },\n zoom: 'fit-width',\n anchor: { y: y != null ? 'start' : 'keep' },\n };\n }\n case 'fitV':\n case 'fitBV': {\n const { x } = destination;\n return {\n rect: { x: x ?? 0, y: 0, width: 0, height },\n zoom: 'fit-height',\n anchor: { x: x != null ? 'start' : 'keep' },\n };\n }\n case 'fitR': {\n const { x, y, width: rectWidth, height: rectHeight } = destination;\n return { rect: { x, y, width: rectWidth, height: rectHeight }, zoom: 'fit' };\n }\n }\n}\n","/**\n * Reveals and destinations. A bare reveal is not navigation: minimal\n * visibility, cursor untouched (in paged flow, revealing a page is navigating\n * to it). A positioned reveal (rect, anchor or zoom: a search hit) is an\n * arrival: the cursor is set up front, the camera lands per the anchor\n * policy, and a resolved zoom becomes the zoom intent. A destination is a\n * positioned reveal of the spot it names.\n */\nimport { revealCamera, type Camera, type Rect as StageRect } from '@embedpdf/core-stage';\nimport type { PageDestination, PluginContext, PageRef } from '@embedpdf/core';\n\nimport type { GoToDestinationOptions, RevealAnchorValue, RevealOptions } from '../contract';\nimport { revealOfDestination } from '../destination';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setCursor, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport { whenPlaced } from '../services/placement-latch';\nimport type { StageArrival } from './arrive';\n\nexport function createReveal(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { writeCamera, markCause }: Pick<StageCameraWrite, 'writeCamera' | 'markCause'>,\n { cancelAnimation, animateTo }: Pick<StageAnimation, 'cancelAnimation' | 'animateTo'>,\n { stabilized, goToTarget }: Pick<StageArrival, 'stabilized' | 'goToTarget'>,\n) {\n const {\n camera,\n viewport,\n padding,\n paged,\n itemIndexOfPage,\n worldPageFrame,\n buildScene,\n sceneRect,\n pageRectOf,\n worldRectForContent,\n boundsFor,\n indexOfTarget,\n } = scene;\n const state = () => ctx.state.get();\n\n /**\n * One axis of a positioned-reveal camera. `undefined` is 'nearest' (move\n * only when the target is outside the padded view), unless the zoom just\n * changed: then \"do not move\" is meaningless and the slack-axis rule\n * (center) applies. 'keep' never moves the axis (PDF /XYZ null).\n */\n const revealAxis = (\n anchor: RevealAnchorValue | undefined,\n cameraPosition: number,\n rectPosition: number,\n rectExtent: number,\n viewportExtent: number,\n zoom: number,\n zoomChanged: boolean,\n ): number => {\n if (anchor === 'keep') return cameraPosition;\n const inset = padding();\n if (anchor === undefined) {\n if (!zoomChanged) {\n const low = cameraPosition + inset / zoom;\n const high = cameraPosition + (viewportExtent - inset) / zoom;\n if (rectPosition >= low && rectPosition + rectExtent <= high) return cameraPosition; // already visible\n if (rectExtent > high - low || rectPosition < low) return rectPosition - inset / zoom;\n return rectPosition + rectExtent - (viewportExtent - inset) / zoom;\n }\n anchor = 'center';\n }\n if (anchor === 'start') return rectPosition - inset / zoom;\n if (anchor === 'end') return rectPosition + rectExtent - (viewportExtent - inset) / zoom;\n const fraction = anchor === 'center' ? 0.5 : Math.min(1, Math.max(0, anchor));\n return rectPosition + rectExtent / 2 - (viewportExtent * fraction) / zoom;\n };\n\n const revealAt = (pageIndex: number, options?: RevealOptions): void => {\n markCause('programmatic');\n const pageCount = ctx.document()?.pageCount ?? 0;\n if (pageCount === 0) return;\n const target = Math.max(0, Math.min(pageIndex, pageCount - 1));\n const positioned =\n !!options &&\n // `rect: null` means \"no rect\", the same as absent, so nullable sources\n // flow in without a `?? undefined`.\n (options.rect != null ||\n options.anchor !== undefined ||\n (options.zoom !== undefined && options.zoom !== 'keep'));\n\n if (!positioned) {\n // A bare reveal is not navigation: minimal visibility, cursor untouched.\n if (paged()) {\n // The page is not in the one-item slice: revealing it is navigating to it.\n goToTarget(target, options);\n return;\n }\n const current = buildScene();\n if (!current.itemCount) return;\n const page = pageRectOf(current.items[itemIndexOfPage(target)], target);\n // Reveal the outer box: pageFrame chrome (labels, buttons) belongs to\n // the page, so \"make the page visible\" includes its reserved bands.\n const frame = worldPageFrame();\n const box = {\n x: page.x - frame.left,\n y: page.y - frame.top,\n width: page.width + frame.left + frame.right,\n height: page.height + frame.top + frame.bottom,\n };\n const next = revealCamera(camera(), box, viewport(), padding());\n const now = camera();\n if (next.x === now.x && next.y === now.y) return; // already visible\n cancelAnimation();\n if ((options?.behavior ?? state().scrollBehavior) === 'smooth') {\n animateTo(next, sceneRect());\n } else {\n writeCamera(next, sceneRect());\n }\n return;\n }\n\n // A positioned reveal is an arrival at a rect or point (a search hit, a\n // PDF destination). Like navigation, the cursor is intent, set up front\n // (in paged flow this also rebuilds the one-item slice), never derived\n // from a camera that may be mid-tween.\n cancelAnimation();\n ctx.state.update(setCursor, target);\n\n const place = (): { camera: Camera; bounds: StageRect; zoomChanged: boolean } | null => {\n const current = buildScene();\n if (!current.itemCount) return null;\n const item = paged() ? current.items[0] : current.items[itemIndexOfPage(target)];\n const world = options.rect\n ? worldRectForContent(item, target, options.rect)\n : pageRectOf(item, target);\n const zoomDirective = options.zoom ?? 'keep';\n const availableWidth = Math.max(1, viewport().width - 2 * padding());\n const availableHeight = Math.max(1, viewport().height - 2 * padding());\n let zoom =\n typeof zoomDirective === 'object'\n ? zoomDirective.level\n : zoomDirective === 'fit'\n ? Math.min(availableWidth / world.width, availableHeight / world.height)\n : zoomDirective === 'fit-width'\n ? availableWidth / world.width\n : zoomDirective === 'fit-height'\n ? availableHeight / world.height\n : camera().zoom;\n // A degenerate target (a point with a fit directive) only pans.\n if (!Number.isFinite(zoom) || zoom <= 0) zoom = camera().zoom;\n const zoomChanged = zoomDirective !== 'keep';\n const anchor = options.anchor ?? {};\n return {\n camera: {\n x: revealAxis(\n anchor.x,\n camera().x,\n world.x,\n world.width,\n viewport().width,\n zoom,\n zoomChanged,\n ),\n y: revealAxis(\n anchor.y,\n camera().y,\n world.y,\n world.height,\n viewport().height,\n zoom,\n zoomChanged,\n ),\n zoom,\n },\n bounds: boundsFor(item),\n zoomChanged,\n };\n };\n\n const first = place();\n if (!first) return;\n // A resolved zoom becomes the zoom intent (like zoomAround), so later\n // resizes and refits keep the destination's magnification.\n if (first.zoomChanged) {\n ctx.state.update(patchSettings, { zoom: { level: first.camera.zoom } });\n }\n if ((options.behavior ?? state().scrollBehavior) === 'smooth') {\n // If the zoom patch re-wrapped the scene (zoom is a layout input in\n // wrapped mode), recompute once against the new geometry.\n const landing = place() ?? first;\n animateTo(landing.camera, landing.bounds);\n } else {\n stabilized(() => {\n const landing = place();\n if (landing) writeCamera(landing.camera, landing.bounds);\n });\n }\n };\n\n const reveal = (page: PageRef | number, options?: RevealOptions): void => {\n const index = indexOfTarget(page);\n if (index !== null) whenPlaced(placement, options, (go) => revealAt(index, go));\n };\n\n const goToDestination = (\n destination: PageDestination,\n options?: GoToDestinationOptions,\n ): void => {\n const layout = ctx.getPage(destination.page);\n if (!layout) return;\n const spot = revealOfDestination(destination, layout.size);\n whenPlaced(placement, { ...spot, behavior: options?.behavior }, (go) =>\n revealAt(layout.index, go),\n );\n };\n\n return {\n api: { reveal, goToDestination } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * Zoom verbs. Pointer-less zooms magnify around the zoomAlign focal point\n * (pinch and wheel pass their own pointer to `zoomAround`: physics beats\n * policy); fit modes are zoom intents written through the settings; the\n * double-tap ladder ascends reading postures.\n */\nimport { anchorAtPoint, resolveZoom, toWorld, ZOOM_MAX, ZoomMode } from '@embedpdf/core-stage';\nimport { addRotations, type PageRotation } from '@embedpdf/core-geometry';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageGestures } from '../camera/gestures';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport type { StageSettingsArea } from '../settings/settings';\n\n/** The zoom factor of one zoomIn or zoomOut step. */\nconst ZOOM_STEP = 1.2;\n\nexport function createZoom(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n { syncCursorFromCamera }: Pick<StageCameraWrite, 'syncCursorFromCamera'>,\n {\n cancelAnimation,\n animateZoomAnchored,\n }: Pick<StageAnimation, 'cancelAnimation' | 'animateZoomAnchored'>,\n gestures: StageGestures['api'],\n settings: Pick<StageSettingsArea, 'updateSettings'>,\n) {\n const { camera, viewport, padding, paged, itemIndexOfPage, buildScene, alignPoint, fitBox } =\n scene;\n const state = () => ctx.state.get();\n const zoomAlignPoint = () => alignPoint(state().zoomAlign, viewport());\n\n const setViewRotation = (viewRotation: PageRotation): void =>\n settings.updateSettings({ viewRotation });\n\n return {\n api: {\n doubleTapZoom: (point) => {\n cancelAnimation();\n const before = buildScene();\n if (!before.itemCount) return;\n const item = paged() ? before.items[0] : before.items[itemIndexOfPage(state().cursor)];\n // The ladder (the platform convention) ascends reading postures, each\n // derived from a zoom intent: see the page (automatic), read the text\n // (fit-width), inspect (2.5× the automatic fit). Stops within 10% of\n // a neighbor collapse, so on phones, where automatic is fit-width,\n // the ladder is the familiar two-state toggle.\n //\n // As on iOS, the ladder ascends only from a rung: a tap at a posture\n // moves to the next, wrapping past the top. A pinch to any other\n // level leaves the ladder, and a double-tap there resets to the base\n // fit (\"take me back to reading\"), never a further zoom-in.\n const fit = fitBox(item);\n const automatic = resolveZoom({ mode: ZoomMode.Automatic }, fit, viewport(), padding());\n const fitWidth = resolveZoom({ mode: ZoomMode.FitWidth }, fit, viewport(), padding());\n const stops = [automatic, fitWidth, Math.min(automatic * 2.5, ZOOM_MAX)]\n .sort((left, right) => left - right)\n .filter((zoom, index, all) => index === 0 || zoom > all[index - 1] * 1.1);\n // The same ±10% band the dedupe uses: \"at a posture\" tolerates fit drift.\n const near = (zoom: number, stop: number) => zoom > stop / 1.1 && zoom < stop * 1.1;\n const onRung = stops.findIndex((stop) => near(camera().zoom, stop));\n const target = onRung >= 0 ? stops[(onRung + 1) % stops.length] : stops[0];\n // The intent commits up front, as in `reveal`: a caught tween must\n // never leave the camera at an intermediate zoom while the stored\n // intent still says \"fit\", or the next refit would snap somewhere the\n // user did not ask for.\n ctx.state.update(patchSettings, { zoom: { level: target } });\n // Wrapped grids re-layout on the intent change: anchor the focal\n // point against the scene that will actually be on screen.\n const after = buildScene();\n if (!after.itemCount) return;\n const focal = anchorAtPoint(after, toWorld(camera(), point));\n // The focal-anchored tween keeps the tapped point still.\n animateZoomAnchored(focal, point, target, undefined, syncCursorFromCamera);\n },\n zoomIn: () => gestures.zoomAround(zoomAlignPoint(), ZOOM_STEP),\n zoomOut: () => gestures.zoomAround(zoomAlignPoint(), 1 / ZOOM_STEP),\n zoomTo: (zoom, options) => {\n if (typeof zoom === 'number') {\n if (options?.around) gestures.zoomAround(options.around, zoom / camera().zoom);\n else settings.updateSettings({ zoom: { level: zoom } });\n return;\n }\n settings.updateSettings({ zoom });\n },\n zoomBy: (factor, options) => gestures.zoomAround(options?.around ?? zoomAlignPoint(), factor),\n fitWidth: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitWidth } }),\n fitPage: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitPage } }),\n fitAll: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitAll } }),\n fitAutomatic: () => settings.updateSettings({ zoom: { mode: ZoomMode.Automatic } }),\n setViewRotation,\n rotateViewBy: (delta) =>\n setViewRotation(addRotations(state().viewRotation, delta === 90 ? 90 : 270)),\n } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * The page reads: laid-out pages with their transforms (PDF points → view px\n * → device px), the scroller projection, the visible set (memoized so reads\n * stay reference-stable), coordinate conversions and the camera, zoom and\n * viewpoint reads.\n */\nimport {\n cameraWorldRect,\n scrollMetrics,\n toScreen,\n toWorld,\n type PageBox,\n type ScrollMetrics,\n type Size,\n} from '@embedpdf/core-stage';\nimport {\n applyPoint,\n applyRect,\n displaySize,\n intersectRects,\n pageTransform,\n rotateScaleMatrix,\n snapToDevice,\n} from '@embedpdf/core-geometry';\nimport type { Point } from '@embedpdf/core-geometry';\nimport { memo, toPageRef, type PluginContext, type PageRef } from '@embedpdf/core';\n\nimport type { Viewpoint, VisiblePage } from '../contract';\nimport type { StageHostCapability } from '../host-contract';\nimport type { StageState } from '../model';\nimport type { StageServices } from '../services';\n\nexport function createPageReads(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n) {\n const {\n camera,\n viewport,\n dpr,\n padding,\n paged,\n buildScene,\n cacheKey,\n stayBounds,\n cursorItem,\n currentAnchor,\n } = scene;\n const state = () => ctx.state.get();\n\n // The durable identity of the page at a display index, from the registry.\n const pageObjectNumberAt = (index: number): number =>\n ctx.document()?.pages[index]?.ref.objectNumber ?? index + 1;\n\n // The un-rotated point size of a laid-out box, for when the registry entry\n // is momentarily absent. `displaySize` is its own inverse (display box →\n // content box); dividing by contentScale recovers points.\n const unrotatedPoints = (box: PageBox): Size => {\n const content = displaySize({ width: box.width, height: box.height }, box.rotation);\n return { width: content.width / box.contentScale, height: content.height / box.contentScale };\n };\n\n // Attach durable identity and the per-page transform (PDF points → view px\n // → device px). `scale` is view px per point: contentScale (world per\n // point) × zoom (view px per world); `pageSize` is the page's un-rotated\n // points from the registry. The transform depends only on zoom, rotation,\n // contentScale and dpr, so the same box yields the same transform at any pan.\n const withTransform = (box: PageBox): VisiblePage => {\n const registered = ctx.document()?.pages[box.pageIndex];\n const pageSize = registered\n ? { width: registered.size.width, height: registered.size.height }\n : unrotatedPoints(box);\n const current = camera();\n const ratio = dpr();\n // The footprint's top-left, camera-resolved. Device-snapped at rest, which\n // keeps a rotated page on the device grid; while the zoom moves it places\n // fractionally (see `StageState.cameraResting`).\n const rawX = (box.x - current.x) * current.zoom;\n const rawY = (box.y - current.y) * current.zoom;\n const resting = state().cameraResting;\n const screenX = resting ? snapToDevice(rawX, ratio) : rawX;\n const screenY = resting ? snapToDevice(rawY, ratio) : rawY;\n const transform = pageTransform({\n pageSize,\n rotation: box.rotation,\n scale: box.contentScale * current.zoom,\n // The page's physical 100%: the platform unit factor × its /UserUnit,\n // so `transform.zoom` reads as \"percent of Acrobat's 100%\" per page,\n // independent of sizing mode or camera state.\n baseScale: state().viewUnitsPerPoint * (registered?.userUnit ?? 1),\n dpr: ratio,\n });\n // The on-screen page region in points: viewport ∩ footprint in view\n // space (both axis-aligned), inverted through the transform (exact for\n // quarter-turns). The virtualizer's query already decided this coarsely;\n // it is refined per page here, once, so no adapter re-derives camera math\n // (tiling's demand reads this field).\n const size = viewport();\n const onScreen = intersectRects(\n { x: -screenX, y: -screenY, width: size.width, height: size.height },\n { x: 0, y: 0, width: transform.viewWidth, height: transform.viewHeight },\n );\n const visibleRect =\n onScreen.width > 0 && onScreen.height > 0\n ? transform.viewToPageRect(onScreen)\n : { x: 0, y: 0, width: 0, height: 0 };\n return {\n ...box,\n ref: toPageRef(pageObjectNumberAt(box.pageIndex)),\n screenX,\n screenY,\n transform,\n visibleRect,\n };\n };\n\n // The scroller projection: the camera in native DOM vocabulary, against the\n // same bounds the pan clamp uses (stayBounds: the slice item in paged flow,\n // the scene in continuous). Memoized like the visible pages: the same\n // reference until a field moves, so adapter reads can use plain equality.\n const emptyScrollMetrics: ScrollMetrics = {\n scrollLeft: 0,\n scrollTop: 0,\n scrollWidth: 0,\n scrollHeight: 0,\n clientWidth: 0,\n clientHeight: 0,\n scrollableX: false,\n scrollableY: false,\n };\n let lastMetrics: ScrollMetrics | null = null;\n const scrollMetricsNow = (): ScrollMetrics => {\n if (!state().placed) return emptyScrollMetrics;\n const metrics = scrollMetrics(\n camera(),\n buildScene().itemCount ? stayBounds() : { x: 0, y: 0, width: 0, height: 0 },\n viewport(),\n padding(),\n );\n const previous = lastMetrics;\n if (\n previous &&\n previous.scrollLeft === metrics.scrollLeft &&\n previous.scrollTop === metrics.scrollTop &&\n previous.scrollWidth === metrics.scrollWidth &&\n previous.scrollHeight === metrics.scrollHeight &&\n previous.clientWidth === metrics.clientWidth &&\n previous.clientHeight === metrics.clientHeight\n ) {\n return previous; // scrollableX/Y derive from the six numbers\n }\n lastMetrics = metrics;\n return metrics;\n };\n\n // The visible pages, memoized on everything they depend on so the read is\n // reference-stable (no useSyncExternalStore tearing loop). Paged flow\n // renders only the slice's item; continuous flow renders the camera's\n // query window.\n const noVisiblePages: VisiblePage[] = [];\n const placedVisiblePages = memo(\n () => {\n const current = camera();\n const size = viewport();\n buildScene(); // keys the scene cache that `cacheKey` reads\n return [\n cacheKey(),\n state().flow,\n current.x,\n current.y,\n current.zoom,\n size.width,\n size.height,\n dpr(),\n state().cameraResting,\n ] as const;\n },\n (_sceneKey, _flow, x, y, zoom, width, height, _dpr, _resting): VisiblePage[] => {\n const scene = buildScene();\n const items = paged()\n ? scene.items.slice(0, 1)\n : scene.query(cameraWorldRect({ x, y, zoom }, { width, height }));\n return items.flatMap((item) => item.pages).map(withTransform);\n },\n );\n const visiblePages = (): VisiblePage[] =>\n state().placed ? placedVisiblePages() : noVisiblePages;\n\n const getPageFrame = (page: PageRef | number): VisiblePage | null => {\n if (!state().placed) return null;\n const index = ctx.getPage(page)?.index ?? -1;\n if (index < 0) return null;\n const scene = buildScene();\n if (!scene.itemCount) return null;\n const box = scene.items[scene.itemOfPage(index)].pages.find(\n (candidate) => candidate.pageIndex === index,\n );\n return box ? withTransform(box) : null;\n };\n\n const pageToWorld = (page: PageRef | number, point: Point): Point | null => {\n const frame = getPageFrame(page);\n if (!frame) return null;\n // Place the page point into the page's display box through the same\n // quarter-turn matrix the layout and renderer use (`rotateScaleMatrix`),\n // so this forward transform and the adapter's inverse hit-test cannot\n // drift. `displaySize` is its own inverse, so it recovers the un-rotated\n // content size from the display box.\n const content = displaySize({ width: frame.width, height: frame.height }, frame.rotation);\n const matrix = rotateScaleMatrix(\n frame.contentScale,\n content.width,\n content.height,\n frame.rotation,\n );\n const offset = applyPoint(matrix, point);\n return { x: frame.x + offset.x, y: frame.y + offset.y };\n };\n\n // The visible entry of a page given by its ref or its index; null when it is\n // off screen or not in the document.\n const visiblePageOf = (page: PageRef | number): VisiblePage | null => {\n const objectNumber = ctx.getPage(page)?.ref.objectNumber;\n if (objectNumber === undefined) return null;\n return visiblePages().find((visible) => visible.ref.objectNumber === objectNumber) ?? null;\n };\n\n return {\n scrollMetricsNow,\n visiblePages,\n api: {\n getCamera: camera,\n getViewportSize: viewport,\n getScrollMetrics: scrollMetricsNow,\n listVisiblePages: visiblePages,\n isPageVisible: (page) => visiblePageOf(page) !== null,\n getCurrentPageIndex: () => state().cursor,\n getCurrentPage: () => ctx.document()?.pages[state().cursor]?.ref ?? null,\n getPageCount: () => ctx.document()?.pageCount ?? 0,\n listCurrentItemPages: () => {\n const item = cursorItem();\n const pages = ctx.document()?.pages ?? [];\n return item\n ? item.pageIndexes.map((index) => pages[index]).filter((page) => page !== undefined)\n : [];\n },\n getPageFrame,\n getPageAt: (point) => {\n // Find the visible page whose device-snapped display box contains the\n // point, then invert that page's transform: the same `viewToPage`\n // the per-page context's `toPagePoint` uses, so the two never drift.\n for (const page of visiblePages()) {\n const localX = point.x - page.screenX;\n const localY = point.y - page.screenY;\n if (\n localX >= 0 &&\n localY >= 0 &&\n localX <= page.transform.viewWidth &&\n localY <= page.transform.viewHeight\n ) {\n return {\n ref: page.ref,\n point: page.transform.viewToPage({ x: localX, y: localY }),\n scale: page.transform.viewScale,\n rotation: page.rotation,\n zoom: page.transform.zoom,\n };\n }\n }\n return null;\n },\n viewportToPage: (page, point) => {\n // `getPageAt` without the containment check: project onto one page's\n // plane, valid outside its bounds, through the same inverse transform.\n const target = visiblePageOf(page);\n if (!target) return null;\n return target.transform.viewToPage({\n x: point.x - target.screenX,\n y: point.y - target.screenY,\n });\n },\n pageToWorld,\n pageRectToViewport: (page, rect) => {\n const frame = getPageFrame(page);\n if (!frame) return null;\n const content = displaySize({ width: frame.width, height: frame.height }, frame.rotation);\n const matrix = rotateScaleMatrix(\n frame.contentScale,\n content.width,\n content.height,\n frame.rotation,\n );\n const world = applyRect(matrix, rect);\n const current = camera();\n const topLeft = toScreen(current, { x: frame.x + world.x, y: frame.y + world.y });\n return {\n x: topLeft.x,\n y: topLeft.y,\n width: world.width * current.zoom,\n height: world.height * current.zoom,\n };\n },\n worldToViewport: (world) => toScreen(camera(), world),\n viewportToWorld: (point) => toWorld(camera(), point),\n pageToViewport: (page, point) => {\n const world = pageToWorld(page, point);\n return world ? toScreen(camera(), world) : null;\n },\n getViewRotation: () => state().viewRotation,\n getZoomLevel: () => camera().zoom,\n getZoomMode: () => {\n const zoom = state().zoom;\n return 'mode' in zoom ? zoom.mode : 'custom';\n },\n getViewpoint: (): Viewpoint => ({ anchor: currentAnchor(), zoom: state().zoom }),\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StagePageReads = ReturnType<typeof createPageReads>;\n","/**\n * The stage's six events. Five of them are derived in one `ctx.state.onChange`\n * listener, from the state before and after each committed change, so a new\n * verb can never forget to announce a page, zoom, camera, settings or viewport\n * change. `motionEnded` is an occurrence: the camera animation emits it where a\n * tween or fling ends.\n */\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type {\n StageCameraChangedEvent,\n StageMotionEndedEvent,\n StagePageChangedEvent,\n StageSettingsChangedEvent,\n StageViewportChangedEvent,\n StageZoomChangedEvent,\n} from '../contract';\nimport type { StageState } from '../model';\nimport { eqSetting } from '../responsive';\nimport { pickSettings, SETTING_KEYS } from '../settings';\n\nexport function createEvents(ctx: PluginContext<StageState>) {\n const pageChanged = ctx.events.source<StagePageChangedEvent>();\n const zoomChanged = ctx.events.source<StageZoomChangedEvent>();\n const cameraChanged = ctx.events.source<StageCameraChangedEvent>();\n const motionEnded = ctx.events.source<StageMotionEndedEvent>();\n const settingsChanged = ctx.events.source<StageSettingsChangedEvent>();\n const viewportChanged = ctx.events.source<StageViewportChangedEvent>();\n\n ctx.state.onChange(({ previous, next }) => {\n if (previous.camera !== next.camera) {\n cameraChanged.emit({ camera: next.camera });\n if (previous.camera.zoom !== next.camera.zoom) {\n zoomChanged.emit({\n level: next.camera.zoom,\n previousLevel: previous.camera.zoom,\n mode: 'mode' in next.zoom ? next.zoom.mode : 'custom',\n });\n }\n }\n if (previous.cursor !== next.cursor) {\n pageChanged.emit({\n page: ctx.document()?.pages[next.cursor]?.ref ?? null,\n pageIndex: next.cursor,\n previousPageIndex: previous.cursor,\n });\n }\n if (previous.viewport !== next.viewport) viewportChanged.emit({ size: next.viewport });\n const changed = SETTING_KEYS.filter((key) => !eqSetting(previous[key], next[key]));\n if (changed.length) settingsChanged.emit({ settings: pickSettings(next), changed });\n });\n\n return { pageChanged, zoomChanged, cameraChanged, motionEnded, settingsChanged, viewportChanged };\n}\nexport type StageEvents = ReturnType<typeof createEvents>;\n","/**\n * The scene model: the document's item grouping, the layout, the memoized\n * scene (continuous flow lays out the whole document; paged flow a one-item\n * slice at the origin), and the pure geometry reads every area builds on:\n * fit, alignment points, clamp bounds and anchors. Reads only; nothing here\n * changes state.\n */\nimport {\n anchorFromCamera,\n gridLayout,\n groupPages,\n linearLayout,\n ZoomMode,\n type AlignmentValue,\n type AlignValue,\n type Anchor,\n type CameraConstraint,\n type PageFrame,\n type Point,\n type Rect as StageRect,\n type Scene,\n type SceneItem,\n type Size,\n} from '@embedpdf/core-stage';\nimport { addRotations, applyRect, displaySize, rotateScaleMatrix } from '@embedpdf/core-geometry';\nimport type { Rect } from '@embedpdf/core-geometry';\nimport { memo, type PluginContext, type PageRef } from '@embedpdf/core';\n\nimport type { StageSettings } from '../contract';\nimport type { StageState } from '../model';\nimport { SETTINGS_EFFECT, SETTING_KEYS } from '../settings';\n\nexport function createScene(ctx: PluginContext<StageState>) {\n const state = () => ctx.state.get();\n const camera = () => state().camera;\n const viewport = () => state().viewport;\n const dpr = () => state().dpr;\n const padding = () => state().padding;\n const paged = () => state().flow === 'paged';\n const isFitAll = () => {\n const zoom = state().zoom;\n return 'mode' in zoom && zoom.mode === ZoomMode.FitAll;\n };\n\n // The document's item model (spread grouping) is independent of the\n // rendered scene, so navigation can reason about every item while a paged\n // scene holds only one. The cursor is a page; `itemIndexOfPage` maps it,\n // which survives regrouping.\n const grouping = memo(\n () => [ctx.document()?.pageCount ?? 0, state().spread] as const,\n (pageCount, spread): { grouping: number[][]; firstPages: number[] } => {\n const groups = groupPages(pageCount, spread);\n return { grouping: groups, firstPages: groups.map((item) => item[0]) };\n },\n );\n const itemCountFull = (): number => grouping().grouping.length;\n const itemIndexOfPage = (pageIndex: number): number => {\n const firstPages = grouping().firstPages;\n let low = 0;\n let high = firstPages.length;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (firstPages[middle] <= pageIndex) low = middle + 1;\n else high = middle;\n }\n return Math.max(0, low - 1);\n };\n\n // The zoom that converts screen-px settings into world units. A fixed zoom\n // intent gives an exact, stable value (the thumbnail case); other intents\n // use the camera's current zoom, which `stabilized` converges. Screen-px\n // settings (the wrapped line width, pageFrame, `{ px }` gaps) are the only\n // way a scene depends on the viewport or the zoom.\n const effectiveZoom = (): number => {\n const zoom = state().zoom;\n return 'level' in zoom ? zoom.level : Math.max(state().camera.zoom, 0.0001);\n };\n\n // Wrapped grid: the line width (world units) the columns must fit.\n const wrapLineWidth = (): number =>\n Math.max(1, (viewport().width - 2 * padding()) / effectiveZoom());\n\n // pageFrame (screen px) → world units at the effective zoom.\n const worldPageFrame = (): PageFrame => {\n const frame = state().pageFrame;\n if (!frame.top && !frame.right && !frame.bottom && !frame.left) return frame;\n const zoom = effectiveZoom();\n return {\n top: frame.top / zoom,\n right: frame.right / zoom,\n bottom: frame.bottom / zoom,\n left: frame.left / zoom,\n };\n };\n const frameKey = (): string => {\n const frame = state().pageFrame;\n if (!frame.top && !frame.right && !frame.bottom && !frame.left) return '-';\n const world = worldPageFrame();\n return `${Math.round(world.top)},${Math.round(world.right)},${Math.round(world.bottom)},${Math.round(world.left)}`;\n };\n\n // gap → world units. A plain number is world units (the scene stays\n // zoom-invariant, the rigid-canvas default); `{ px }` converts at the\n // effective zoom like pageFrame (UI-stable spacing for browser-style lenses).\n const worldGap = (): number => {\n const gap = state().gap;\n return typeof gap === 'number' ? gap : gap.px ? gap.px / effectiveZoom() : 0;\n };\n const gapKey = (): string => {\n const gap = state().gap;\n return typeof gap === 'number' ? String(gap) : `px:${Math.round(worldGap())}`;\n };\n\n const layoutFor = (groups: number[][]): Scene => {\n const settings = state();\n // Engine page layouts structurally satisfy stage-core's page geometry\n // (`size` + `rotation`): the intrinsic page size flows straight in.\n //\n // The view rotation is composed here, and only here: each page's display\n // rotation is its /Rotate plus this lens's viewRotation. Everything\n // downstream (the display-size swap, the page transform, hit-testing, fit\n // zoom, overlays) reads the composed rotation. `size` stays the page's\n // own un-rotated points, so page space is view-rotation-invariant.\n const registryPages = ctx.document()?.pages ?? [];\n const viewRotation = settings.viewRotation;\n const pages =\n viewRotation === 0\n ? registryPages\n : registryPages.map((page) => ({\n ...page,\n rotation: addRotations(page.rotation, viewRotation),\n }));\n const pageFrame = worldPageFrame();\n const gap = worldGap();\n const viewUnitsPerPoint = settings.viewUnitsPerPoint;\n if (settings.layout === 'grid') {\n return gridLayout(pages, groups, {\n gap,\n sizing: settings.sizing,\n direction: settings.direction,\n pageFrame,\n viewUnitsPerPoint,\n columns: typeof settings.columns === 'number' ? settings.columns : undefined,\n lineWidth: settings.columns === 'auto' ? wrapLineWidth() : undefined,\n });\n }\n return linearLayout(pages, groups, {\n axis: settings.layout === 'horizontal' ? 'x' : 'y',\n gap,\n sizing: settings.sizing,\n direction: settings.direction,\n pageFrame,\n viewUnitsPerPoint,\n });\n };\n\n // The column policy's part of the scene key; 'auto' quantizes the line\n // width so sub-pixel resizes do not rebuild the scene.\n const columnsKey = (): string => {\n const settings = state();\n if (settings.layout !== 'grid') return '-';\n return settings.columns === 'auto'\n ? `auto:${Math.round(wrapLineWidth())}`\n : String(settings.columns);\n };\n\n // The scene's settings signature, derived from the settings registry: every\n // 'scene' setting contributes automatically, so a new layout-affecting\n // setting only needs its SETTINGS_EFFECT row and a stale scene cannot be\n // forgotten here. Values key by value (objects via JSON); the custom\n // functions quantize px-derived values so sub-pixel zoom and resize churn\n // does not rebuild the scene.\n const SCENE_KEY_FUNCTIONS: Partial<Record<keyof StageSettings, () => string>> = {\n columns: columnsKey,\n gap: gapKey,\n pageFrame: frameKey,\n };\n const SCENE_KEYS = SETTING_KEYS.filter((key) => SETTINGS_EFFECT[key] === 'scene');\n const settingsKey = (): string =>\n SCENE_KEYS.map((key) => {\n const keyFunction = SCENE_KEY_FUNCTIONS[key];\n if (keyFunction) return keyFunction();\n const value = state()[key];\n return typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);\n }).join('|');\n\n // The scene cache. Continuous flow lays out the whole document. Paged flow\n // is a one-item slice at the origin holding only the cursor's item, so\n // isolation is structural (no other page exists to leak into view),\n // unbounded pan is free, and coordinates stay local.\n let sceneCache: { key: string; scene: Scene } | null = null;\n // The registry signature: page count plus the kernel's monotonic\n // `revision`. The revision changes on every page mutation (rotate, move,\n // delete), so a change that keeps the page count (a rotation) still re-keys\n // the scene instead of rendering the page in its stale box.\n const documentKey = (): string => {\n const document = ctx.document();\n return document ? `${document.pageCount}.${document.revision}` : '0.0';\n };\n const buildScene = (): Scene => {\n const { grouping: groups } = grouping();\n if (state().flow === 'paged') {\n const index = groups.length\n ? Math.min(itemIndexOfPage(state().cursor), groups.length - 1)\n : 0;\n const key = `paged|${documentKey()}|${settingsKey()}|${index}`;\n if (sceneCache && sceneCache.key === key) return sceneCache.scene;\n const scene = layoutFor(groups.length ? [groups[index]] : []);\n sceneCache = { key, scene };\n return scene;\n }\n const key = `continuous|${documentKey()}|${settingsKey()}`;\n if (sceneCache && sceneCache.key === key) return sceneCache.scene;\n const scene = layoutFor(groups);\n sceneCache = { key, scene };\n return scene;\n };\n /** Drop the memoized scene (a 'scene' or 'reflow' setting changed, or a view was restored). */\n const invalidate = (): void => {\n sceneCache = null;\n };\n /** The current scene's cache key, part of the visible-pages signature. */\n const cacheKey = (): string => sceneCache!.key;\n\n // ── geometry helpers ──\n const sceneRect = (): StageRect => {\n const { width, height } = buildScene().size;\n return { x: 0, y: 0, width, height };\n };\n const itemRect = (item: SceneItem): StageRect => ({\n x: item.x,\n y: item.y,\n width: item.width,\n height: item.height,\n });\n const pageRectOf = (item: SceneItem, pageIndex: number): StageRect => {\n const box = item.pages.find((page) => page.pageIndex === pageIndex) ?? item.pages[0];\n return { x: box.x, y: box.y, width: box.width, height: box.height };\n };\n /** The item shown for the cursor: the slice's only item (paged) or the full-scene item. */\n const cursorItem = (): SceneItem => {\n const scene = buildScene();\n return paged() ? scene.items[0] : scene.items[itemIndexOfPage(state().cursor)];\n };\n\n /**\n * A page-space rect on a page → a world rect: the same quarter-turn\n * matrix `pageRectToViewport` uses, minus the camera, so a positioned\n * reveal and the rendered overlay never disagree about where a rect is.\n */\n const worldRectForContent = (item: SceneItem, pageIndex: number, rect: Rect): StageRect => {\n const box = item.pages.find((page) => page.pageIndex === pageIndex) ?? item.pages[0];\n const content = displaySize({ width: box.width, height: box.height }, box.rotation);\n const matrix = rotateScaleMatrix(box.contentScale, content.width, content.height, box.rotation);\n const world = applyRect(matrix, rect);\n return { x: box.x + world.x, y: box.y + world.y, width: world.width, height: world.height };\n };\n\n // Does this rect fit the padded viewport at this zoom? It decides the\n // navigation step size and the arrival subject, never the alignment.\n const fits = (rect: StageRect, zoom: number): boolean => {\n const size = viewport();\n const inset = padding();\n const tolerance = 0.5;\n return (\n rect.width * zoom <= size.width - 2 * inset + tolerance &&\n rect.height * zoom <= size.height - 2 * inset + tolerance\n );\n };\n // An alignment policy → a concrete viewport point: a fraction per axis\n // (start = 0, center = ½, end = 1; named x stops are logical under RTL).\n // zoomAlign and anchorAlign both resolve through this. The fraction spans\n // the padded range: 'start' is the first visible content line just inside\n // the gutter, where an arrival puts the page edge, so the reference pins\n // to the page and never to the gap above it.\n const alignFraction = (value: AlignValue): number =>\n value === 'start'\n ? 0\n : value === 'center'\n ? 0.5\n : value === 'end'\n ? 1\n : Math.min(1, Math.max(0, value));\n const alignPoint = (alignment: AlignmentValue, size: Size): Point => {\n const rtl = state().direction === 'rtl';\n const alignX =\n rtl && alignment.x === 'start' ? 'end' : rtl && alignment.x === 'end' ? 'start' : alignment.x;\n const inset = padding();\n return {\n x: inset + (size.width - 2 * inset) * alignFraction(alignX),\n y: inset + (size.height - 2 * inset) * alignFraction(alignment.y),\n };\n };\n const anchorPoint = (): Point => alignPoint(state().anchorAlign, viewport());\n\n /** The box the zoom intent fits: the whole scene (fit-all), the current\n * item (paged: per-page fit), or the document maximum (continuous: a\n * document-stable zoom). */\n const fitBox = (item: SceneItem): Size => {\n if (isFitAll()) return buildScene().size;\n return paged() ? { width: item.width, height: item.height } : buildScene().maxItemSize;\n };\n /** The clamp rect for a camera write targeting this item (the scene in continuous flow). */\n const boundsFor = (item: SceneItem): StageRect => (paged() ? itemRect(item) : sceneRect());\n /** The clamp rect for a write that stays put (pan, zoom): the slice item (paged) or the scene. */\n const stayBounds = (): StageRect => (paged() ? itemRect(buildScene().items[0]) : sceneRect());\n\n const constraint = (): CameraConstraint => ({\n bounded: state().bounded,\n padding: padding(),\n fitAlign: state().fitAlign,\n direction: state().direction,\n });\n\n const anchorAt = (at: Point): Anchor => {\n const scene = buildScene();\n return scene.itemCount\n ? anchorFromCamera(camera(), scene, viewport(), at)\n : { pageIndex: state().cursor, fx: 0.5, fy: 0 };\n };\n const currentAnchor = (): Anchor => anchorAt(anchorPoint());\n\n const indexOfPage = (page: PageRef): number => ctx.getPage(page)?.index ?? -1;\n /**\n * A page argument (a `PageRef` or a display index) as a display index, or\n * null when it names no page: a ref not in the document, or a number that\n * isn't a whole number. An index past either end is kept; arrivals clamp it.\n */\n const indexOfTarget = (page: PageRef | number): number | null => {\n if (typeof page === 'number') return Number.isInteger(page) ? page : null;\n const index = indexOfPage(page);\n return index >= 0 ? index : null;\n };\n\n return {\n camera,\n viewport,\n dpr,\n padding,\n paged,\n isFitAll,\n grouping,\n itemCountFull,\n itemIndexOfPage,\n worldPageFrame,\n buildScene,\n invalidate,\n cacheKey,\n sceneRect,\n itemRect,\n pageRectOf,\n cursorItem,\n worldRectForContent,\n fits,\n alignPoint,\n anchorPoint,\n fitBox,\n boundsFor,\n stayBounds,\n constraint,\n anchorAt,\n currentAnchor,\n indexOfPage,\n indexOfTarget,\n };\n}\nexport type StageScene = ReturnType<typeof createScene>;\n","/**\n * Plugin-private services every area is built on: the events, the host's\n * clock, the placement latch and the scene model.\n */\nimport type { PluginClock, PluginContext } from '@embedpdf/core';\n\nimport type { StageState } from '../model';\nimport { createEvents, type StageEvents } from './events';\nimport { createPlacementLatch, type PlacementLatch } from './placement-latch';\nimport { createScene, type StageScene } from './scene';\n\nexport interface StageServices {\n readonly events: StageEvents;\n /** Time, from the host (`ctx.clock`): the tweens, flings and the rest countdown run on it. */\n readonly clock: PluginClock;\n readonly placement: PlacementLatch;\n readonly scene: StageScene;\n}\n\nexport function createServices(ctx: PluginContext<StageState>): StageServices {\n return {\n events: createEvents(ctx),\n clock: ctx.clock,\n placement: createPlacementLatch(),\n scene: createScene(ctx),\n };\n}\n","/**\n * The settings bag and its responsive resolution. The base (config plus\n * `updateSettings()` changes) merged with the matching rules' patches is the effective\n * settings the state holds. `applySettings` is the one reactive applier: the\n * strongest effect among the touched settings wins ('reflow' ⊃ 'scene'/'refit'\n * ⊃ 'reclamp' ⊃ 'none'), so a breakpoint crossing gets exactly the invariant a\n * hand-written update would.\n */\nimport { memo, type PluginContext } from '@embedpdf/core';\n\nimport type {\n ResponsiveRule,\n StageConfig,\n StageSettings,\n StageSettingsPatch,\n StageViewState,\n} from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setActiveRules, setCursor, type StageState } from '../model';\nimport type { StageArrival } from '../navigation/arrive';\nimport { boxOf, eqSetting, mergeSettings, resolveResponsive } from '../responsive';\nimport type { StageServices } from '../services';\nimport { DEFAULT_RESPONSIVE, pickSettings, SETTINGS_EFFECT, SETTING_KEYS } from '../settings';\nimport type { SettingEffect } from '../settings';\n\nconst EFFECT_RANK: Record<SettingEffect, number> = {\n none: 0,\n reclamp: 1,\n refit: 2,\n scene: 3,\n reflow: 4,\n};\n\nexport function createSettings(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n config: StageConfig,\n { writeCamera }: Pick<StageCameraWrite, 'writeCamera'>,\n { cancelAnimation }: Pick<StageAnimation, 'cancelAnimation'>,\n {\n applyAnchor,\n reapply,\n goToTarget,\n }: Pick<StageArrival, 'applyAnchor' | 'reapply' | 'goToTarget'>,\n) {\n const { camera, viewport, alignPoint, anchorAt } = scene;\n const state = () => ctx.state.get();\n\n // The same object while no setting changed, so readers compare by identity.\n const snapshotSettings: () => StageSettings = memo(\n () => SETTING_KEYS.map((key) => state()[key]),\n () => pickSettings(state()),\n );\n\n /**\n * React to a settings change per the registry: the strongest effect among\n * the touched settings wins. Both the public `updateSettings()` and the\n * responsive driver land here.\n */\n const applySettings = (patch: Partial<StageSettings>) => {\n cancelAnimation();\n const touched = (effect: SettingEffect) =>\n SETTING_KEYS.some((key) => patch[key] !== undefined && SETTINGS_EFFECT[key] === effect);\n // The change's invariant point: a pure zoom-intent change ('refit' alone)\n // holds the zoomAlign focal point, so zoomTo and fit-mode switches magnify\n // around the same spot the zoom buttons do; every other reframe holds the\n // anchorAlign reference. Resolved once, used for capture and restore.\n const align =\n touched('refit') && !touched('scene') && !touched('reflow')\n ? state().zoomAlign\n : state().anchorAlign;\n const anchor = anchorAt(alignPoint(align, viewport())); // captured against the current scene\n ctx.state.update(patchSettings, patch);\n if (touched('scene')) scene.invalidate();\n if (touched('reflow')) {\n // The flow toggled: re-place onto the cursor's page under the new\n // flow's scene (camera coordinates are meaningless across the flow\n // boundary).\n goToTarget(state().cursor, { behavior: 'instant' });\n } else if (touched('scene') || touched('refit')) {\n reapply(anchor, align); // rebuild, keep the page, re-fit (fit-all re-places the scene)\n } else if (touched('reclamp')) {\n writeCamera(camera()); // the clamp policy changed: re-clamp the current camera\n }\n // 'none' (arrivalAlign, zoomAlign, anchorAlign, scrollBehavior) guides future verbs only.\n };\n\n // ── responsive settings (container queries for the settings bag) ──\n // Rules assert at transitions (box, base or rules changes), which is why\n // the sync diffs against the last effective resolution, never against live\n // state: between crossings interaction owns the state (a pinch-zoomed level\n // survives a resize unless a rule actually flips), and keys the rules do\n // not touch are never re-asserted.\n let base = snapshotSettings();\n const initialBase = base;\n let rules: readonly ResponsiveRule[] = config.responsive ?? DEFAULT_RESPONSIVE;\n let lastEffective = base; // rules first assert when a real box arrives\n const publishActive = (active: readonly string[]) => {\n const current = state().activeRules;\n if (current.length !== active.length || active.some((name, index) => name !== current[index])) {\n ctx.state.update(setActiveRules, active);\n }\n };\n /**\n * Re-resolve and apply what changed since the last resolution. `react:\n * true` routes the patch through `applySettings` (the full\n * anchor-preserving update); `react: false` (inside `setViewportSize`,\n * whose caller runs its own reframe) only lands the patch and the cache\n * invalidation and reports the strongest effect, so the caller can\n * escalate a rule-driven flow flip.\n */\n const syncResponsive = (react: boolean): SettingEffect => {\n const { effective, active } = resolveResponsive(base, rules, boxOf(viewport()));\n const patch: Partial<StageSettings> = {};\n for (const key of SETTING_KEYS) {\n if (!eqSetting(effective[key], lastEffective[key])) {\n Object.assign(patch, { [key]: effective[key] });\n }\n }\n lastEffective = effective;\n publishActive(active);\n const keys = Object.keys(patch) as Array<keyof StageSettings>;\n if (keys.length === 0) return 'none';\n if (react) {\n applySettings(patch);\n return 'none'; // reacted in full: nothing left for the caller\n }\n ctx.state.update(patchSettings, patch);\n let strongest: SettingEffect = 'none';\n for (const key of keys) {\n if (EFFECT_RANK[SETTINGS_EFFECT[key]] > EFFECT_RANK[strongest]) {\n strongest = SETTINGS_EFFECT[key];\n }\n }\n if (strongest === 'scene' || strongest === 'reflow') scene.invalidate();\n return strongest;\n };\n\n const updateSettings = (changes: StageSettingsPatch): void => {\n // Writes the responsive base; the resolver decides what actually lands (a\n // matching rule's key wins until its rule stops matching). With no rules\n // in play this is a direct update.\n base = mergeSettings(base, changes);\n syncResponsive(true);\n };\n\n const applyViewState = (view: StageViewState): void => {\n cancelAnimation();\n // A restored view is app-level state: it writes the base, and the rules\n // re-assert on top, so a snapshot saved on a desktop restores compact\n // padding on a phone. One patch carries the full effective result.\n base = mergeSettings(base, pickSettings(view));\n const { effective, active } = resolveResponsive(base, rules, boxOf(viewport()));\n lastEffective = effective;\n publishActive(active);\n ctx.state.update(patchSettings, effective);\n ctx.state.update(setCursor, view.cursor ?? 0);\n scene.invalidate();\n applyAnchor(view.anchor);\n };\n\n return {\n snapshotSettings,\n syncResponsive,\n updateSettings,\n applyViewState,\n api: {\n getSettings: snapshotSettings,\n resetSettings: () => {\n base = mergeSettings(initialBase, {});\n syncResponsive(true);\n },\n updateSettings,\n setResponsiveRules: (next) => {\n rules = next;\n syncResponsive(true);\n },\n matchesRule: (name) => state().activeRules.includes(name),\n listActiveRules: () => state().activeRules,\n applyViewState,\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageSettingsArea = ReturnType<typeof createSettings>;\n","/**\n * The view lifecycle: the viewport report (initial placement is\n * level-triggered here, the moment the stage first learns a real size and the\n * document has pages), the device pixel ratio, initial-view providers resolved\n * once by priority, the refit after page-registry changes, and the view\n * memento reads.\n */\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageViewState } from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageHostCapability } from '../host-contract';\nimport { markPlaced, setDpr, setViewport, type StageState } from '../model';\nimport type { StageArrival } from '../navigation/arrive';\nimport type { StageServices } from '../services';\nimport type { StageSettingsArea } from '../settings/settings';\n\ninterface InitialViewProvider {\n readonly priority: number;\n readonly provide: () => StageViewState | null;\n}\n\nexport function createViewLifecycle(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { cancelAnimation }: Pick<StageAnimation, 'cancelAnimation'>,\n arrive: Pick<StageArrival, 'goToTarget' | 'reapply' | 'resetView'>,\n settings: Pick<StageSettingsArea, 'snapshotSettings' | 'syncResponsive' | 'applyViewState'>,\n) {\n const { dpr, currentAnchor } = scene;\n const { goToTarget, reapply } = arrive;\n const { snapshotSettings, syncResponsive } = settings;\n const state = () => ctx.state.get();\n\n // Initial-view providers (a storage restore, a deep link, an explicit\n // prop). One owner, `placeInitial`, resolves them by priority, so there is\n // no ordering race between the providers.\n const initialViewProviders: InitialViewProvider[] = [];\n\n const placeInitial = (): void => {\n placement.started = true;\n const byPriority = [...initialViewProviders].sort(\n (left, right) => right.priority - left.priority,\n );\n let view: StageViewState | null = null;\n for (const provider of byPriority) {\n view = provider.provide();\n if (view) break;\n }\n if (view) settings.applyViewState(view);\n else arrive.resetView();\n // Navigation the app asked for before there was a viewport lands last,\n // from the initial view, so the first frame already shows it.\n const pending = placement.pending;\n placement.pending = null;\n pending?.();\n // Publish renderability last. The viewport, responsive and camera writes\n // above are ordinary observable state changes, but page and scroll reads\n // return stable empty values until this commit lands.\n ctx.state.update(markPlaced);\n };\n\n return {\n api: {\n setViewportSize: (size) => {\n // Initial placement is level-triggered here: the moment the stage\n // first learns a real size (both axes) and the document has pages,\n // resolve the initial view (providers, else a reset). Every report\n // re-checks the condition, so there is no edge to miss when the\n // viewport was sized before anyone listened.\n if (!placement.started) {\n ctx.state.update(setViewport, size);\n syncResponsive(false); // rules see the box before placement resolves\n if (size.width > 0 && size.height > 0 && (ctx.document()?.pageCount ?? 0) > 0) {\n placeInitial();\n }\n return;\n }\n // Afterwards a report with no area means the view isn't shown: a hidden tab, or an\n // element taken out of the page before its stage is torn down. There is nothing to fit\n // to, so the stage keeps its last real viewport and its view, and carries on from them\n // when it's shown again (as a browser keeps a hidden element's scroll position).\n if (size.width <= 0 || size.height <= 0) return;\n // A report of the size the stage already has says nothing new either. Hosts send\n // them (a ResizeObserver's first callback repeats the size reported at attach), and\n // treating one as a resize would cancel a navigation still animating, like a reveal\n // the app asked for as the view opened.\n const current = state().viewport;\n if (size.width === current.width && size.height === current.height) return;\n // Every real resize keeps the same page and re-resolves fit modes.\n cancelAnimation();\n const anchor = currentAnchor(); // measured against the old viewport\n ctx.state.update(setViewport, size);\n // A breakpoint crossing rides the same reframe: the rule patch lands\n // before the anchor is re-applied, so the restore resolves under the\n // new settings. Only a rule-driven flow flip escalates past reapply\n // (camera coordinates are meaningless across the flow boundary).\n const effect = syncResponsive(false);\n if (effect === 'reflow') {\n goToTarget(state().cursor, { behavior: 'instant' });\n } else {\n reapply(anchor);\n }\n },\n setDevicePixelRatio: (ratio) => {\n // A device-resolution change only affects each page transform's device\n // px (crispness) and sub-pixel box snapping, never the layout or the\n // camera: store it, and the visible pages re-key on dpr.\n if (ratio > 0 && ratio !== dpr()) ctx.state.update(setDpr, ratio);\n },\n refit: () => {\n // The page geometry changed underneath (rotate, move, delete). Treat\n // it like a viewport resize: re-resolve the zoom intent and re-place\n // against the current scene, keeping the anchored page-point. A no-op\n // before the first placement; the scene is keyed on the registry\n // revision, so `reapply` reads the new footprint.\n if (!placement.started) return;\n cancelAnimation();\n reapply(currentAnchor());\n },\n getViewState: (): StageViewState => ({\n ...snapshotSettings(),\n cursor: state().cursor,\n anchor: currentAnchor(),\n }),\n getLensId: () => ctx.id,\n provideInitialView: (priority, provide) => {\n const entry: InitialViewProvider = { priority, provide };\n initialViewProviders.push(entry);\n return () => {\n const index = initialViewProviders.indexOf(entry);\n if (index >= 0) initialViewProviders.splice(index, 1);\n };\n },\n placeInitial,\n } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * The stage controller: the composition root. It builds the plugin's services\n * once (the events, the timing seam, the scene model), wires each area with\n * the services it declares, and assembles the host capability from the areas'\n * API slices. stage-core is the pure spatial math; the areas are the impure\n * shell that writes state, caches and drives motion, and time enters only\n * through the host's clock (`ctx.clock`).\n *\n * The camera model: every camera move is defined by what it holds fixed.\n * Gestures (pan, pinch, wheel) hold the page-point under the pointer;\n * navigation lands its target at the arrivalAlign point; positioned reveals\n * and restored viewpoints hold what the call specifies; pointer-less zooms\n * hold the zoomAlign point; reframes (resize, rotation, layout changes) hold\n * the anchorAlign point; and an axis the camera cannot travel rests at fitAlign.\n */\nimport { composeApi, type PluginContext } from '@embedpdf/core';\n\nimport { createAnimation } from './camera/animation';\nimport { createGestures } from './camera/gestures';\nimport { createCameraWrite } from './camera/write';\nimport { connectStage } from './connect';\nimport type { StageConfig } from './contract';\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\nimport { createArrival } from './navigation/arrive';\nimport { createReveal } from './navigation/reveal';\nimport { createZoom } from './navigation/zoom';\nimport { createPageReads } from './read/pages';\nimport { createServices } from './services';\nimport { createSettings } from './settings/settings';\nimport { createViewLifecycle } from './view/lifecycle';\n\nexport function createStageController(\n ctx: PluginContext<StageState>,\n config: StageConfig = {},\n) {\n const services = createServices(ctx);\n const { events } = services;\n\n // Reads: pure projections of the scene and the camera.\n const reads = createPageReads(ctx, services);\n\n // The camera: the one write path, motion over the clock's frames, gestures.\n const write = createCameraWrite(ctx, services);\n const animation = createAnimation(services, write);\n const gestures = createGestures(ctx, services, write, animation, reads);\n\n // Navigation, settings, zoom and the view lifecycle.\n const arrive = createArrival(ctx, services, write, animation);\n const reveal = createReveal(ctx, services, write, animation, arrive);\n const settings = createSettings(ctx, services, config, write, animation, arrive);\n const zoom = createZoom(ctx, services, write, animation, gestures.api, settings);\n const view = createViewLifecycle(ctx, services, animation, arrive, settings);\n\n const api: StageHostCapability = composeApi('stage', [\n reads.api,\n animation.api,\n gestures.api,\n arrive.api,\n reveal.api,\n settings.api,\n zoom.api,\n view.api,\n {\n onPageChanged: events.pageChanged.on,\n onZoomChanged: events.zoomChanged.on,\n onCameraChanged: events.cameraChanged.on,\n onMotionEnded: events.motionEnded.on,\n onSettingsChanged: events.settingsChanged.on,\n onViewportChanged: events.viewportChanged.on,\n },\n ]);\n\n return {\n api,\n connect: () => connectStage(ctx, api),\n };\n}\n","import { createHostToken, definePlugin } from '@embedpdf/core';\nimport { ActionsToken } from '@embedpdf/plugin-actions/contract';\n\nimport { DEFAULT_LENS_ID } from './connect';\nimport type { StagePluginOptions } from './contract';\nimport { createStageController } from './controller';\nimport type { StageHostCapability } from './host-contract';\nimport { initialStageState } from './model';\nimport { StageToken } from './token';\n\n/**\n * The stage plugin: one lens's camera, layout, zoom and navigation over a\n * document. Document-scoped. The actions plugin is optional: with it, the\n * main lens feeds page state to it and interprets GoTo and Named page\n * actions. Pointer input is opted into by the surface binding\n * (`<Stage interaction>` / `createStageSurface`), which both forwards pointer\n * samples and registers this lens's scroll handler.\n */\nexport const stagePlugin = (options: StagePluginOptions = {}) => {\n const { id = DEFAULT_LENS_ID, token = StageToken, ...config } = options;\n return definePlugin({\n id,\n token: createHostToken<StageHostCapability>(token),\n scope: 'document',\n optional: [ActionsToken],\n state: () => initialStageState(config),\n create: (ctx) => createStageController(ctx, config),\n });\n};\n","/**\n * The Stage page's State table as code: what `useStageState()` returns, and\n * the same fields in every other framework. A second view registered with its\n * own token reads the same fields through its own capability.\n */\nimport { defineState } from '@embedpdf/core';\n\nimport { StageToken, ZoomMode } from './contract';\n\nexport const stageState = defineState(StageToken, {\n read: (stage) => ({\n zoomLevel: stage.getZoomLevel(),\n zoomMode: stage.getZoomMode(),\n currentPageIndex: stage.getCurrentPageIndex(),\n currentPage: stage.getCurrentPage(),\n pageCount: stage.getPageCount(),\n viewRotation: stage.getViewRotation(),\n activeRules: stage.listActiveRules(),\n }),\n empty: {\n zoomLevel: 1,\n zoomMode: ZoomMode.Automatic,\n currentPageIndex: 0,\n currentPage: null,\n pageCount: 0,\n viewRotation: 0,\n activeRules: [],\n },\n});\n","import type {\n InteractionHostCapability,\n InteractionHandler,\n} from '@embedpdf/plugin-interaction/contract/host';\nimport type { StageCapability } from './contract';\n\nexport interface ScrollHandlerOptions {\n /**\n * Let a drag over a page gap pan regardless of the active tool, and show a\n * grab cursor there, so the gutter always pans (outside a page there is\n * nothing to draw on or select). On-page behavior is untouched: the tool's\n * own gesture still owns page space. Default true.\n */\n panFallback?: boolean;\n}\n\n/**\n * Pan-the-camera as an interaction handler. Live under the built-in `pan` tool\n * (the `scroll` tag) and, with `panFallback`, under every tool, where it then\n * captures only page-gap drags (on-page downs belong to the active tool, which\n * claims them first at higher priority). It uses the sample's viewport delta,\n * so it pans over the whole viewport (pages and gaps).\n *\n * Cursors: a closed hand (`grabbing`) while dragging; an open hand (`grab`)\n * hovering a gap under a non-pan tool. The pan tool's own resting `grab` comes\n * from its `Tool.cursor`, so hovering it needs no claim here.\n */\nexport function createScrollHandler(\n stage: StageCapability,\n interaction: InteractionHostCapability,\n options: ScrollHandlerOptions = {},\n): InteractionHandler {\n const panFallback = options.panFallback ?? true;\n let last = { x: 0, y: 0 };\n const isPanTool = (): boolean => interaction.getActiveTool().enables.has('scroll');\n return {\n id: 'stage-scroll',\n priority: 10, // below page-aware handlers (selection, annotation), which claim first\n enabledFor: (tool) => tool.enables.has('scroll') || panFallback,\n onDown: (sample) => {\n // Fallback: a non-pan tool pans only over a gap. On a page, decline so the\n // tool's own (higher-priority) handler keeps the down it already captured.\n if (!isPanTool() && sample.page) return false;\n last = sample.viewport;\n interaction.claimCursor('stage-grab', 'grabbing', 40); // closed hand while panning\n return true; // capture the drag\n },\n onMove: (sample) => {\n stage.panBy(sample.viewport.x - last.x, sample.viewport.y - last.y);\n last = sample.viewport;\n },\n onUp: () => interaction.claimCursor('stage-grab', null),\n onHover: (sample) => {\n // An open hand over a gap when a non-pan tool would fall back to pan\n // there; cleared over a page (the tool's cursor shows). The pan tool\n // skips this: its resting `grab` is the tool cursor.\n if (panFallback && !isPanTool()) {\n interaction.claimCursor('stage-pan-fallback', sample.page ? null : 'grab', 5);\n }\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ActionsToken","NO_FRAME","ZoomMode","ZoomMode","ZOOM_MAX","ZoomMode","StageToken","ActionsToken","StageToken","ZoomMode"],"sources":["../src/working-set.ts","../src/connect.ts","../src/motion.ts","../src/camera/animation.ts","../src/responsive.ts","../src/settings.ts","../src/model.ts","../src/camera/gestures.ts","../src/camera/write.ts","../src/services/placement-latch.ts","../src/navigation/arrive.ts","../src/destination.ts","../src/navigation/reveal.ts","../src/navigation/zoom.ts","../src/read/pages.ts","../src/services/events.ts","../src/services/scene.ts","../src/services/index.ts","../src/settings/settings.ts","../src/view/lifecycle.ts","../src/controller.ts","../src/stage.plugin.ts","../src/state.ts","../src/scroll-handler.ts"],"sourcesContent":["/**\n * What this lens shows, told to the engine as the lens's working set\n * (`doc.setWorkingSet`): the engine ranks the jobs for those pages by it, and\n * keeps those pages parsed longest. Every lens tells its own, so a thumbnail\n * rail's small pages rank after the main view's.\n *\n * It comes from the pages the lens lays out (`listVisiblePages`):\n * - `visible`: a page with some of it on screen, with that part and its device\n * pixels, which rank visible pages among themselves: the page the user looks\n * at has the most;\n * - `near`: a page laid out just off screen (the scene's overscan), where the\n * view goes next.\n */\nimport type { PluginContext, WorkingSetPage } from '@embedpdf/core';\n\nimport type { VisiblePage } from './contract';\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\n\n/** A lens's working set, from the pages it lays out. */\nexport function workingSetOf(pages: readonly VisiblePage[]): WorkingSetPage[] {\n return pages.map(({ ref, visibleRect, transform }) => {\n if (visibleRect.width <= 0 || visibleRect.height <= 0) {\n return { page: ref, role: 'near', pixels: 0 };\n }\n const pixels = visibleRect.width * visibleRect.height * transform.renderScale ** 2;\n return { page: ref, role: 'visible', visible: visibleRect, pixels: Math.round(pixels) };\n });\n}\n\n/**\n * Tells the engine what the lens shows, now and whenever it changes: once per\n * camera move, so at most once per input event while the camera moves.\n */\nexport function connectWorkingSet(\n ctx: PluginContext<StageState>,\n stage: Pick<StageHostCapability, 'listVisiblePages'>,\n): void {\n let told = '';\n const tell = (shown: readonly VisiblePage[]) => {\n const pages = workingSetOf(shown);\n const key = keyOf(pages);\n if (key === told) return;\n told = key;\n ctx.doc.setWorkingSet(ctx.id, pages);\n };\n ctx.watch(() => stage.listVisiblePages(), tell);\n tell(stage.listVisiblePages());\n}\n\n/** A working set as one comparable string. */\nfunction keyOf(pages: readonly WorkingSetPage[]): string {\n return pages\n .map(({ page, role, visible, pixels }) => {\n const part = visible\n ? `${Math.round(visible.x)},${Math.round(visible.y)},${Math.round(visible.width)},${Math.round(visible.height)}`\n : '';\n return `${page.objectNumber}:${role}:${pixels}:${part}`;\n })\n .join('|');\n}\n","/**\n * The stage's wiring to its surroundings, run once every dependency exists:\n * the refit on page-registry changes and the working set told to the engine\n * (every lens) and, for the default lens only, the page-state feed and the navigation executors of the actions\n * plugin. A thumbnail lens must never report page state or win the\n * last-wins executor registry and start navigating the sidebar.\n */\nimport type { PluginContext } from '@embedpdf/core';\nimport { ActionsToken, type ActionsHostCapability } from '@embedpdf/plugin-actions/contract/host';\n\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\nimport { connectWorkingSet } from './working-set';\n\n/** The id of the main lens; additional lenses register under their own id. */\nexport const DEFAULT_LENS_ID = 'stage';\n\nexport function connectStage(ctx: PluginContext<StageState>, stage: StageHostCapability): void {\n // Rotate, move and delete change the registry revision, so the page geometry\n // under this lens changed: re-resolve the zoom intent and re-place. It\n // reacts to changes only, never to the initial value, so it cannot race the\n // level-triggered initial placement.\n ctx.watch(\n () => ctx.document()?.revision ?? 0,\n () => stage.refit(),\n );\n connectWorkingSet(ctx, stage);\n\n if (ctx.id !== DEFAULT_LENS_ID) return;\n const actions = ctx.tryGet(ActionsToken);\n if (!actions) return;\n feedPageState(ctx, stage, actions);\n registerNavigationExecutors(ctx, stage, actions);\n}\n\n/**\n * The page-state feed. The stage is authoritative for what page the viewer is\n * on; the actions plugin's lifecycle coordinator owns when page-lifecycle\n * triggers fire. The feed reports `{ currentPage, visiblePages, placed, cause }`\n * (page refs, not indexes, so reordering is safe) on placement and on every\n * change; the coordinator buffers reports until the document has opened and\n * diffs them against what it last emitted, so this side only reports.\n */\nfunction feedPageState(\n ctx: PluginContext<StageState>,\n stage: StageHostCapability,\n actions: ActionsHostCapability,\n): void {\n const snapshot = () => {\n const state = ctx.state.get();\n if (!state.placed) return null;\n return {\n currentPage: stage.getCurrentPage(),\n visiblePages: stage.listVisiblePages().map((page) => page.ref),\n cause: state.motionCause,\n };\n };\n ctx.watch(\n // The signature covers what is reported: the current page and the visible\n // page set. `cause` is left out on purpose: a cause flip alone is not a\n // page-state change and must not produce a report.\n () => {\n const current = snapshot();\n return current === null\n ? 'unplaced'\n : `${current.currentPage?.objectNumber ?? -1}|${current.visiblePages\n .map((page) => page.objectNumber)\n .sort((left, right) => left - right)\n .join(',')}`;\n },\n () => {\n const current = snapshot();\n if (current === null) return;\n actions.reportPageState({\n currentPage: current.currentPage,\n visiblePages: current.visiblePages,\n placed: true,\n cause: current.cause,\n });\n },\n );\n}\n\n/**\n * The GoTo and Named page verbs for the action engine. The dispatcher runs\n * them as deferred navigation effects, after every document node of a tree\n * succeeded, never in the middle of a walk. They move the view by its own\n * `scrollBehavior` setting, as a link does. /N Print is not handled here: the\n * dispatcher owns it (policy and the UI adapter).\n */\nfunction registerNavigationExecutors(\n ctx: PluginContext<StageState>,\n stage: StageHostCapability,\n actions: ActionsHostCapability,\n): void {\n ctx.cleanup(\n actions.registerExecutor('goto', (node) => {\n if (node.type !== 'goto') return { status: 'inert', reason: 'not a goto node' };\n if (!ctx.getPage(node.destination.page))\n return { status: 'failed', error: 'the destination page is not in this document' };\n stage.goToDestination(node.destination);\n return { status: 'executed' };\n }),\n );\n ctx.cleanup(\n actions.registerExecutor('named', (node) => {\n if (node.type !== 'named') return { status: 'inert', reason: 'not a named node' };\n switch (node.name) {\n case 'NextPage':\n stage.nextPage();\n return { status: 'executed' };\n case 'PrevPage':\n stage.previousPage();\n return { status: 'executed' };\n case 'FirstPage':\n stage.goToFirstPage();\n return { status: 'executed' };\n case 'LastPage':\n stage.goToLastPage();\n return { status: 'executed' };\n default:\n return { status: 'inert', reason: `unknown named action '${node.name}'` };\n }\n }),\n );\n}\n","/**\n * The camera's motion vocabulary, every formula pure.\n *\n * The capability owns the impure drivers (the clock's frames, state writes,\n * gesture state); the laws those drivers integrate live here, parameterized\n * by elapsed time with no state and no clock, so they are unit-testable in\n * isolation and have no plugin dependencies.\n *\n * Two families:\n * • ballistic — one per-axis law for every free motion: `glideStep` (the\n * touch fling, decaying on UIScrollView's curve) and `springStep` (a\n * critically-damped return to the clamp). A glide that reaches a content\n * edge converts to a spring with its velocity carried in, so the bounce\n * grows out of physics rather than a scripted overshoot.\n * • resistance — the iOS rubber-band curve `rubberOut` and its exact inverse\n * `rubberIn`: dragging past an edge displays an asymptotically bounded\n * stretch, and re-entering a gesture over a stretched camera (catching it\n * mid-bounce) reconstructs the finger-integrated position the curve came\n * from.\n * Plus the tween interpolators: `easeOutCubic` for coordinate tweens and\n * `zoomLerp`, a geometric zoom interpolation (zoom is multiplicative: equal\n * ratios per unit time, not equal deltas).\n */\n\n// ── constants ──\n/** Resistance coefficient of the rubber-band curve (the iOS feel). */\nexport const RUBBER = 0.55;\n/** Glide decay per ms: UIScrollView's normal deceleration rate. */\nexport const FLING_DECAY = 0.998;\n/** px/ms; below about 20 px/s the eye reads \"stopped\". */\nexport const FLING_STOP = 0.02;\n/** rad/ms; critically damped, settling in about 400 ms. */\nexport const SPRING_OMEGA = 0.015;\n\n// ── resistance (rubber-band) ──\n/**\n * Overshoot distance → displayed stretch, asymptotic to the viewport\n * dimension, so the content never leaves the screen however far the finger\n * travels. `rubberOut(0) === 0`: inside the bounds the curve is invisible.\n */\nexport const rubberOut = (distance: number, dimension: number): number =>\n (1 - 1 / ((distance * RUBBER) / dimension + 1)) * dimension;\n/** The exact inverse of `rubberOut` (defined for `stretch < dimension`). */\nexport const rubberIn = (stretch: number, dimension: number): number =>\n (stretch * dimension) / (RUBBER * (dimension - stretch));\n\n// ── ballistic (one axis, one frame) ──\n/** The state one integration step hands back; `done` means \"at rest\". */\nexport interface MotionStep {\n position: number;\n velocity: number;\n done: boolean;\n}\n/**\n * One frame of free glide: exponential velocity decay, the position advanced\n * by the midpoint integral of the decay over `elapsedMs` (exact for the\n * exponential, so frame-rate independent).\n */\nexport const glideStep = (position: number, velocity: number, elapsedMs: number): MotionStep => {\n const decay = Math.pow(FLING_DECAY, elapsedMs);\n const nextPosition = position + velocity * ((elapsedMs * (1 + decay)) / 2);\n const nextVelocity = velocity * decay;\n return Math.abs(nextVelocity) < FLING_STOP\n ? { position: nextPosition, velocity: 0, done: true }\n : { position: nextPosition, velocity: nextVelocity, done: false };\n};\n/**\n * One frame of a critically-damped spring toward `edge`: semi-implicit Euler\n * on x'' = −ω²(x−e) − 2ωx'. Lands exactly on the edge (position snapped,\n * velocity zeroed) once within half a pixel at negligible speed.\n */\nexport const springStep = (\n position: number,\n velocity: number,\n edge: number,\n elapsedMs: number,\n): MotionStep => {\n const nextVelocity =\n velocity +\n (-SPRING_OMEGA * SPRING_OMEGA * (position - edge) - 2 * SPRING_OMEGA * velocity) * elapsedMs;\n const nextPosition = position + nextVelocity * elapsedMs;\n if (Math.abs(nextPosition - edge) < 0.5 && Math.abs(nextVelocity) < 0.01) {\n return { position: edge, velocity: 0, done: true };\n }\n return { position: nextPosition, velocity: nextVelocity, done: false };\n};\n\n// ── tween interpolators ──\nexport const easeOutCubic = (progress: number): number => 1 - Math.pow(1 - progress, 3);\n/**\n * Geometric zoom interpolation: `from·(to/from)^progress`. Zoom is\n * multiplicative, so a constant-rate zoom moves equal ratios per unit time;\n * interpolating the level linearly makes the start rush and the end crawl\n * (and, under a focal anchor, swings the anchored point along a curve).\n */\nexport const zoomLerp = (from: number, to: number, progress: number): number =>\n from * Math.pow(to / from, progress);\n","/**\n * Camera motion over the host's frames (`ctx.clock`): the coordinate tween,\n * the zoom-anchored tween (it animates the invariant, so the focal page-point\n * holds still by construction), and the momentum and edge physics (glide,\n * spring). One frame is waited for at a time: `cancelAnimation`, every verb's\n * first act, is also \"catch\".\n */\nimport {\n cameraForAnchorAtScreen,\n clampCamera,\n type Anchor,\n type Camera,\n type Point,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { Cancel } from '@embedpdf/core';\n\nimport type { StageHostCapability } from '../host-contract';\nimport { easeOutCubic, FLING_STOP, glideStep, springStep, zoomLerp } from '../motion';\nimport type { StageServices } from '../services';\nimport type { StageCameraWrite } from './write';\n\n/** The default tween duration. */\nconst TWEEN_MS = 240;\n\nconst lerp = (from: number, to: number, progress: number) => from + (to - from) * progress;\n\nexport function createAnimation(\n { events, clock, scene }: Pick<StageServices, 'events' | 'clock' | 'scene'>,\n write: StageCameraWrite,\n) {\n const { motionEnded } = events;\n const { camera, viewport, buildScene, stayBounds, constraint } = scene;\n const { writeCamera, writeCameraUnclamped, axisTravels, syncCursorFromCamera } = write;\n\n // Cancels the frame the running motion waits for; null while nothing moves.\n let cancelFrame: Cancel | null = null;\n const cancelAnimation = () => {\n cancelFrame?.();\n cancelFrame = null;\n };\n /** A tween or fling reached its natural end. */\n const endMotion = () => {\n cancelFrame = null;\n motionEnded.emit({ camera: camera() });\n };\n\n // The tween clamps to an explicit bounds rect every frame (never a\n // re-derived current item), so animating toward a different item is not\n // clamped back. `then` runs on natural completion only: a cancelled tween\n // belongs to the verb that cancelled it.\n const animateTo = (target: Camera, bounds: Rect, durationMs = TWEEN_MS, then?: () => void) => {\n if (!clock.hasFrames) {\n writeCamera(target, bounds);\n then?.();\n return;\n }\n cancelAnimation();\n const from = camera();\n let started = false;\n let startedAt = 0;\n const tick = (now: number) => {\n if (!started) {\n started = true;\n startedAt = now; // anchor to the first real timestamp (works even when now === 0)\n }\n const progress = easeOutCubic(Math.min(1, (now - startedAt) / durationMs));\n writeCamera(\n {\n x: lerp(from.x, target.x, progress),\n y: lerp(from.y, target.y, progress),\n zoom: lerp(from.zoom, target.zoom, progress),\n },\n bounds,\n );\n if (progress < 1) {\n cancelFrame = clock.nextFrame(tick);\n } else {\n endMotion();\n then?.();\n }\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n /**\n * The zoom-anchored tween animates the invariant, not the coordinates: the\n * focal page-point stays at `point` while the scale changes. Lerping x, y\n * and zoom independently breaks that mid-flight, because holding a screen\n * point requires `x(t) = focal.x − point.x / zoom(t)`, hyperbolic in the\n * zoom, so linear coordinates swing the tapped point along a curve (a\n * visible dip). Here the zoom interpolates geometrically (zoom is\n * multiplicative) and each frame's camera derives from the anchor at that\n * zoom, then clamps: the focal point is stationary by construction, and a\n * zoom-out rails into its fit as the shrinking travel range lets the clamp\n * take over.\n */\n const animateZoomAnchored = (\n focal: Anchor,\n point: Point,\n targetZoom: number,\n durationMs = TWEEN_MS,\n then?: () => void,\n ) => {\n if (!clock.hasFrames) {\n const scene = buildScene();\n if (scene.itemCount) writeCamera(cameraForAnchorAtScreen(focal, scene, point, targetZoom));\n then?.();\n return;\n }\n cancelAnimation();\n const startZoom = camera().zoom;\n let started = false;\n let startedAt = 0;\n const tick = (now: number) => {\n if (!started) {\n started = true;\n startedAt = now;\n }\n const progress = easeOutCubic(Math.min(1, (now - startedAt) / durationMs));\n const zoom = zoomLerp(startZoom, targetZoom, progress);\n const scene = buildScene();\n if (scene.itemCount) writeCamera(cameraForAnchorAtScreen(focal, scene, point, zoom));\n if (progress < 1) {\n cancelFrame = clock.nextFrame(tick);\n } else {\n endMotion();\n then?.();\n }\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n // Momentum and edge physics, the driver over motion.ts's per-axis laws:\n // glide — the touch fling, decaying on UIScrollView's curve across free\n // travel;\n // spring — a critically-damped return to the clamp, entered when a glide\n // reaches a content edge (the remaining velocity becomes the\n // bounce) or when the motion starts displaced (released while\n // stretched).\n // Axes are independent (a diagonal fling can bounce off the bottom while\n // still gliding horizontally), and every trajectory ends on the clamp. It\n // shares the tween's frame, so cancelAnimation() is also \"catch\":\n // catching mid-bounce holds the stretch.\n const startCameraPhysics = (fingerVelocityX: number, fingerVelocityY: number) => {\n if (!clock.hasFrames) {\n writeCamera(camera()); // no host frames: snap straight into bounds\n return;\n }\n cancelAnimation();\n const zoom = camera().zoom;\n // Per-axis state in screen px (the camera moves opposite the finger;\n // positions scale by zoom once, here, so the laws read in px).\n interface AxisState {\n position: number;\n velocity: number;\n springing: boolean;\n done: boolean;\n }\n const start = camera();\n const startClamped = clampCamera(start, stayBounds(), viewport(), constraint());\n const startBounds = stayBounds();\n const startViewport = viewport();\n const axisState = (\n cameraPosition: number,\n clampedPosition: number,\n fingerVelocity: number,\n ): AxisState => ({\n position: cameraPosition * zoom,\n velocity: -fingerVelocity / 1000,\n springing: cameraPosition !== clampedPosition,\n done: false,\n });\n // A fitting axis takes no ballistic motion: no travel to glide across and\n // no bounce (rigid, like the platform), so its release velocity is\n // discarded. The spring stays armed for a displaced fitting axis.\n const axisX = axisState(\n start.x,\n startClamped.x,\n axisTravels(startBounds.x, startBounds.width, startViewport.width, zoom)\n ? fingerVelocityX\n : 0,\n );\n const axisY = axisState(\n start.y,\n startClamped.y,\n axisTravels(startBounds.y, startBounds.height, startViewport.height, zoom)\n ? fingerVelocityY\n : 0,\n );\n if (\n !axisX.springing &&\n !axisY.springing &&\n Math.hypot(axisX.velocity, axisY.velocity) < FLING_STOP\n ) {\n return;\n }\n let started = false;\n let lastFrameAt = 0;\n const tick = (now: number) => {\n cancelFrame = null;\n // The first frame assumes one 60 Hz step (anchored like the tween, so a\n // first timestamp of 0 works).\n const elapsedMs = started ? Math.min(64, Math.max(1, now - lastFrameAt)) : 16;\n started = true;\n lastFrameAt = now;\n // The clamp of the current position is each axis's home this frame: the\n // edge for a stretched axis, the rest point for a fitting one.\n const home = clampCamera(\n { x: axisX.position / zoom, y: axisY.position / zoom, zoom },\n stayBounds(),\n viewport(),\n constraint(),\n );\n const step = (axis: AxisState, edgeWorld: number) => {\n if (axis.done) return;\n const next = axis.springing\n ? springStep(axis.position, axis.velocity, edgeWorld * zoom, elapsedMs)\n : glideStep(axis.position, axis.velocity, elapsedMs);\n axis.position = next.position;\n axis.velocity = next.velocity;\n axis.done = next.done;\n };\n step(axisX, home.x);\n step(axisY, home.y);\n // A glide that left the travel range converts to a spring at the edge;\n // the incoming velocity carries in, so the bounce grows out of physics\n // rather than a scripted overshoot.\n const nextHome = clampCamera(\n { x: axisX.position / zoom, y: axisY.position / zoom, zoom },\n stayBounds(),\n viewport(),\n constraint(),\n );\n const convert = (axis: AxisState, clampedPosition: number) => {\n if (!axis.springing && Math.abs(clampedPosition * zoom - axis.position) > 1e-6) {\n axis.position = clampedPosition * zoom;\n axis.springing = true;\n axis.done = false;\n }\n };\n convert(axisX, nextHome.x);\n convert(axisY, nextHome.y);\n writeCameraUnclamped({ x: axisX.position / zoom, y: axisY.position / zoom, zoom });\n syncCursorFromCamera();\n if (axisX.done && axisY.done) {\n writeCamera(camera()); // the exact landing: clamped, snapped, settled\n motionEnded.emit({ camera: camera() });\n return;\n }\n cancelFrame = clock.nextFrame(tick);\n };\n cancelFrame = clock.nextFrame(tick);\n };\n\n return {\n cancelAnimation,\n animateTo,\n animateZoomAnchored,\n startCameraPhysics,\n api: {\n fling: (velocityX, velocityY) => startCameraPhysics(velocityX, velocityY),\n isMoving: () => cancelFrame !== null,\n stopMotion: () => {\n if (!cancelFrame) return;\n cancelAnimation();\n motionEnded.emit({ camera: camera() });\n },\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageAnimation = ReturnType<typeof createAnimation>;\n","import { NO_FRAME } from '@embedpdf/core-geometry';\nimport type { Size } from '@embedpdf/core-stage';\nimport type {\n BoxQuery,\n ResponsiveRule,\n StageBox,\n StageSettings,\n StageSettingsPatch,\n} from './contract';\n\n/**\n * Container queries for the settings bag, the pure half. The capability owns\n * the driver (when to re-resolve, how to react); the laws live here: what a\n * box is, when a query matches, and what the effective settings are. No\n * state, so they are property-testable in isolation.\n *\n * The query vocabulary is only the box: a headless, DOM-free stage knows\n * exactly one environmental fact, the viewport it was told. Anything else\n * (pointer coarseness, platform, app state) is either per event\n * (`PointerSample.pointerType`) or the app's own business via\n * `updateSettings()`.\n */\n\n/** The reported viewport as a queryable box. A square box is 'portrait' (CSS). */\nexport const boxOf = (size: Size): StageBox => ({\n width: size.width,\n height: size.height,\n orientation: size.height >= size.width ? 'portrait' : 'landscape',\n});\n\n/** All bounds inclusive, all fields optional, every condition must hold (CSS ranges). */\nexport const matchesQuery = (query: BoxQuery, box: StageBox): boolean =>\n (query.minWidth === undefined || box.width >= query.minWidth) &&\n (query.maxWidth === undefined || box.width <= query.maxWidth) &&\n (query.minHeight === undefined || box.height >= query.minHeight) &&\n (query.maxHeight === undefined || box.height <= query.maxHeight) &&\n (query.orientation === undefined || box.orientation === query.orientation);\n\nconst ruleMatches = (rule: ResponsiveRule, box: StageBox): boolean =>\n typeof rule.when === 'function' ? !!rule.when(box) : matchesQuery(rule.when, box);\n\n/**\n * Merge a patch over settings, skipping undefined values (Partial semantics).\n * Each value replaces the setting whole; a `pageFrame` that names only some\n * sides reserves 0 on the others.\n */\nexport const mergeSettings = (into: StageSettings, patch: StageSettingsPatch): StageSettings => {\n const merged = { ...into };\n let key: keyof StageSettingsPatch;\n for (key in patch) {\n const value = key === 'pageFrame' ? frameOf(patch.pageFrame) : patch[key];\n if (value !== undefined) Object.assign(merged, { [key]: value });\n }\n return merged;\n};\n\nconst frameOf = (frame: StageSettingsPatch['pageFrame']) =>\n frame === undefined ? undefined : { ...NO_FRAME, ...frame };\n\n/**\n * Setting-value equality: primitives by identity, the flat objects the\n * settings vocabulary uses (`{ px }`, `{ x, y }`, page frames, zoom specs) by\n * one level of own-key comparison. Settings values are never nested deeper.\n */\nexport const eqSetting = (left: unknown, right: unknown): boolean => {\n if (left === right) return true;\n if (typeof left !== 'object' || typeof right !== 'object' || left === null || right === null) {\n return false;\n }\n const leftKeys = Object.keys(left);\n return (\n leftKeys.length === Object.keys(right).length &&\n leftKeys.every(\n (key) => (left as Record<string, unknown>)[key] === (right as Record<string, unknown>)[key],\n )\n );\n};\n\nexport interface ResolvedResponsive {\n /** The base merged with every matching rule's patch, in source order (later wins per key). */\n effective: StageSettings;\n /** Names of the matching rules, in source order. */\n active: string[];\n}\n\nexport const resolveResponsive = (\n base: StageSettings,\n rules: readonly ResponsiveRule[],\n box: StageBox,\n): ResolvedResponsive => {\n let effective = base;\n const active: string[] = [];\n for (const rule of rules) {\n if (!ruleMatches(rule, box)) continue;\n if (rule.name !== undefined) active.push(rule.name);\n if (rule.settings) effective = mergeSettings(effective, rule.settings);\n }\n return { effective, active };\n};\n","import { ZoomMode } from '@embedpdf/core-stage';\nimport type { ResponsiveRule, StageSettings } from './contract';\nimport { eqSetting } from './responsive';\n\n/**\n * Out-of-the-box defaults: a document-reading feel. Every field is overridable\n * in `stagePlugin(config)` and at runtime through `updateSettings()`. The\n * plugin ships no named presets (\"document\", \"canvas\", …): a preset is an\n * object the app keeps and passes to `updateSettings()`, so that taxonomy\n * stays the app's concern.\n */\nexport const DEFAULT_SETTINGS: StageSettings = {\n flow: 'continuous',\n layout: 'vertical',\n spread: 'none',\n sizing: 'intrinsic',\n columns: 'square',\n bounded: true,\n padding: 24,\n gap: 16,\n pageFrame: { top: 0, right: 0, bottom: 0, left: 0 },\n direction: 'ltr',\n fitAlign: { x: 'center', y: 'center' },\n // The reading defaults: navigation lands at the top and reading start at\n // every zoom, button zoom inflates around the middle, and resizes pin the\n // top (the browser scroll model). Construction and presentation apps set\n // all of these to center/center.\n arrivalAlign: { x: 'start', y: 'start' },\n zoomAlign: { x: 'center', y: 'center' },\n anchorAlign: { x: 'start', y: 'start' },\n viewRotation: 0,\n zoom: { mode: ZoomMode.Automatic },\n scrollBehavior: 'smooth',\n interaction: true,\n panFallback: true,\n zoomGestures: true,\n // Web: 1 PDF point = 96/72 CSS px, so 100% is physically accurate. A native\n // adapter overrides this at registration with its own logical-unit factor.\n viewUnitsPerPoint: 96 / 72,\n};\n\n/**\n * Out-of-the-box responsive rules, the platform feel with zero configuration:\n * a compact container gets the thin gutter phones use (space, not device: an\n * embedded 500px pane on a desktop is compact too). Override the whole list\n * with `stagePlugin({ responsive: [...] })`; `responsive: []` opts out. The\n * 'compact' name is queryable by the app through `stage.matchesRule('compact')`.\n */\nexport const DEFAULT_RESPONSIVE: readonly ResponsiveRule[] = [\n { name: 'compact', when: { maxWidth: 600 }, settings: { padding: 4 } },\n];\n\n/**\n * How a change to each setting affects the view: the single source of truth.\n * One row per setting, completeness enforced by the compiler (`Record<keyof\n * StageSettings, …>`: adding a setting without classifying it is a type error).\n * Everything else derives from this table: the scene-cache invalidation and\n * key, `updateSettings()`'s reaction, the settings snapshot and patch picks,\n * and the React selector equality.\n *\n * 'reflow' — crosses the flow boundary: camera coordinates are meaningless\n * there, so re-place canonically onto the cursor's page.\n * 'scene' — a layout input: invalidates the scene, then re-applies the anchor.\n * 'refit' — re-resolves zoom against the (possibly re-keyed) scene: re-applies\n * the anchor without an explicit invalidation.\n * 'reclamp' — pure clamp policy: re-clamp the current camera in place.\n * 'none' — guides future verbs and the surface binding only\n * (arrival/zoom/anchor alignment, scroll behavior, input).\n *\n * The classes also carry each change's invariant — what stays fixed while the\n * view reacts: 'refit' (a zoom-intent change) holds the zoomAlign focal point;\n * 'scene' reframes (and viewport resizes) hold the anchorAlign point.\n */\nexport type SettingEffect = 'reflow' | 'scene' | 'refit' | 'reclamp' | 'none';\nexport const SETTINGS_EFFECT: Record<keyof StageSettings, SettingEffect> = {\n flow: 'reflow',\n layout: 'scene',\n spread: 'scene',\n sizing: 'scene',\n columns: 'scene',\n bounded: 'reclamp',\n padding: 'reclamp',\n gap: 'scene',\n pageFrame: 'scene',\n direction: 'scene',\n fitAlign: 'reclamp',\n arrivalAlign: 'none',\n zoomAlign: 'none',\n anchorAlign: 'none',\n viewRotation: 'scene', // a layout input: every page's footprint swaps w↔h\n zoom: 'refit',\n scrollBehavior: 'none',\n // Read by the surface binding, which rebinds its pointer input when they change.\n interaction: 'none',\n panFallback: 'none',\n zoomGestures: 'none',\n viewUnitsPerPoint: 'scene', // a layout input: changing it resizes every page\n};\nexport const SETTING_KEYS = Object.keys(SETTINGS_EFFECT) as Array<keyof StageSettings>;\n\n/** Field-by-field settings equality, derived from the registry, so a new\n * setting is covered automatically: what an adapter compares settings with. */\nexport const settingsEqual = (left: StageSettings, right: StageSettings): boolean =>\n SETTING_KEYS.every((key) => eqSetting(left[key], right[key]));\n\n/** The settings slice of a larger object (state, or a saved view), derived\n * from the registry so the shape is never spelled out by hand. */\nexport const pickSettings = (source: StageSettings): StageSettings => {\n const settings: Partial<Record<keyof StageSettings, unknown>> = {};\n for (const key of SETTING_KEYS) settings[key] = source[key];\n return settings as StageSettings;\n};\n","/**\n * The stage's session state: the flat settings bag plus the camera, the\n * viewport, the cursor and the render-commit latch. Every function below is a\n * pure transition; the controller's areas apply them with `ctx.state.update`,\n * and nothing else changes stage state.\n */\nimport type { Camera, Size } from '@embedpdf/core-stage';\n\nimport type { StageConfig, StageSettings } from './contract';\nimport { mergeSettings } from './responsive';\nimport { DEFAULT_SETTINGS } from './settings';\n\nexport interface StageState extends StageSettings {\n readonly camera: Camera;\n /**\n * One-way render-commit latch. False while the initial viewport-driven\n * placement is unresolved; true only after its camera and settings writes\n * have completed. Page and scroll screen-space reads refuse to answer while\n * false, so an adapter can never paint the placeholder camera at the origin.\n */\n readonly placed: boolean;\n /**\n * Names of the responsive rules currently matching the box, in source order.\n * State (not derived) so `matchesRule()` is reactive in every framework.\n */\n readonly activeRules: readonly string[];\n /**\n * False while the zoom is in motion, true once it has rested (about 150 ms\n * of frames without a zoom write). Device-snapping of page origins is gated\n * on this: a continuous zoom and a snapped origin cannot coexist without the\n * anchor point jittering ±0.5 device px per step, so pages place\n * fractionally while zooming and snap once at rest. Pans always snap (a pure\n * translation has no anchor error).\n */\n readonly cameraResting: boolean;\n /** The container size the host reported, in viewport px. */\n readonly viewport: Size;\n /**\n * Device pixels per view pixel (web: `window.devicePixelRatio`). Feeds each\n * page's transform so bitmaps render crisp and boxes land on the device\n * grid. Defaults to 1.\n */\n readonly dpr: number;\n /**\n * The current page index, valid in both flows. Navigation sets it; in\n * continuous flow manipulation derives it from the camera; in paged flow\n * panning never moves it (the scene is a one-item slice at this page).\n * An index, so it survives spread and layout regrouping.\n */\n readonly cursor: number;\n /**\n * What last drove the camera or cursor: `'programmatic'` for the arrival\n * and reveal verbs (the ones action executors use), `'user'` for direct\n * manipulation (wheel, drag, scrollbars, embedder scroll calls). The\n * page-state feed hands it to the actions plugin, whose cascade budget\n * counts only programmatic rounds, so user scrolling is never throttled.\n */\n readonly motionCause: 'user' | 'programmatic';\n}\n\nexport const initialStageState = (config: StageConfig): StageState => {\n // `responsive` configures the capability, not the settings: strip it so the\n // spread below stays a pure settings override.\n const { responsive: _responsive, ...overrides } = config;\n return {\n camera: { x: 0, y: 0, zoom: 1 },\n placed: false,\n cameraResting: true,\n viewport: { width: 0, height: 0 },\n dpr: 1,\n cursor: 0,\n motionCause: 'user',\n activeRules: [],\n ...mergeSettings(DEFAULT_SETTINGS, overrides),\n };\n};\n\nexport const setCamera = (state: StageState, camera: Camera): StageState =>\n state.camera === camera ? state : { ...state, camera };\n\nexport const setCameraResting = (state: StageState, resting: boolean): StageState =>\n state.cameraResting === resting ? state : { ...state, cameraResting: resting };\n\nexport const markPlaced = (state: StageState): StageState =>\n state.placed ? state : { ...state, placed: true };\n\nexport const setViewport = (state: StageState, viewport: Size): StageState =>\n state.viewport === viewport ? state : { ...state, viewport };\n\nexport const setDpr = (state: StageState, dpr: number): StageState =>\n state.dpr === dpr ? state : { ...state, dpr };\n\nexport const setCursor = (state: StageState, cursor: number): StageState =>\n state.cursor === cursor ? state : { ...state, cursor };\n\nexport const setMotionCause = (\n state: StageState,\n motionCause: StageState['motionCause'],\n): StageState => (state.motionCause === motionCause ? state : { ...state, motionCause });\n\n/**\n * Merge a settings patch. Undefined values are skipped, so a partial restore\n * never clears a setting; the area that patches decides what camera\n * follow-up the change needs.\n */\nexport function patchSettings(state: StageState, patch: Partial<StageSettings>): StageState {\n let next = state;\n let key: keyof StageSettings;\n for (key in patch) {\n const value = patch[key];\n if (value === undefined || Object.is(next[key], value)) continue;\n if (next === state) next = { ...state };\n Object.assign(next, { [key]: value });\n }\n return next;\n}\n\nexport const setActiveRules = (state: StageState, activeRules: readonly string[]): StageState =>\n state.activeRules === activeRules ? state : { ...state, activeRules };\n","/**\n * Direct manipulation: set, pan, scroll and pinch-zoom the camera, and the\n * gesture bracket. The camera moves freely and the cursor is derived from it\n * (the manipulation direction of cursor reconciliation).\n */\nimport {\n anchorAtPoint,\n cameraForAnchorAtScreen,\n cameraFromScroll,\n clampCamera,\n panByScreen,\n toWorld,\n zoomAround,\n} from '@embedpdf/core-stage';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageScrollToOptions } from '../contract';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, type StageState } from '../model';\nimport type { StagePageReads } from '../read/pages';\nimport type { StageServices } from '../services';\nimport type { StageAnimation } from './animation';\nimport type { StageCameraWrite } from './write';\n\nexport function createGestures(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n write: StageCameraWrite,\n { cancelAnimation, animateTo, startCameraPhysics }: StageAnimation,\n { scrollMetricsNow }: Pick<StagePageReads, 'scrollMetricsNow'>,\n) {\n const { camera, viewport, padding, buildScene, stayBounds, constraint } = scene;\n const {\n gesture,\n armRest,\n writeCamera,\n writeCameraUnclamped,\n rubberize,\n unrubberize,\n syncCursorFromCamera,\n markCause,\n } = write;\n\n const scrollTo = (options: StageScrollToOptions): void => {\n markCause('user');\n cancelAnimation();\n if (!buildScene().itemCount) return;\n const next = cameraFromScroll(camera(), stayBounds(), viewport(), padding(), options);\n if (options.behavior === 'smooth') {\n animateTo(next, stayBounds(), undefined, syncCursorFromCamera);\n } else {\n writeCamera(next);\n syncCursorFromCamera();\n }\n };\n\n return {\n api: {\n setCamera: (next) => {\n markCause('user');\n cancelAnimation();\n writeCamera(next);\n syncCursorFromCamera();\n },\n panBy: (dx, dy) => {\n markCause('user');\n cancelAnimation();\n if (gesture.depth > 0 && gesture.elastic) {\n // Elastic: integrate the finger on the unclamped camera and display\n // it through the resistance curve. Initialized from the displayed\n // camera's inverse, so catching a mid-bounce stretch continues\n // seamlessly.\n gesture.raw = panByScreen(gesture.raw ?? unrubberize(camera()), dx, dy);\n writeCameraUnclamped(rubberize(gesture.raw));\n } else {\n writeCamera(panByScreen(camera(), dx, dy));\n }\n syncCursorFromCamera();\n },\n scrollTo,\n scrollBy: ({ left, top, behavior }) => {\n const metrics = scrollMetricsNow();\n scrollTo({\n left: left === undefined ? undefined : metrics.scrollLeft + left,\n top: top === undefined ? undefined : metrics.scrollTop + top,\n behavior,\n });\n },\n zoomAround: (point, factor) => {\n cancelAnimation();\n const before = buildScene();\n // The page-relative focal point: the durable identity of \"what is\n // under the pointer\".\n const focal = before.itemCount ? anchorAtPoint(before, toWorld(camera(), point)) : null;\n writeCamera(zoomAround(camera(), point, factor));\n // Record the resulting level as the zoom intent (focal, so no\n // re-anchor). Inside a gesture bracket it is deferred to endGesture:\n // one patch per pinch instead of one per event.\n if (gesture.depth === 0) {\n ctx.state.update(patchSettings, { zoom: { level: camera().zoom } });\n }\n // When zoom is a layout input (a wrapped grid) the scene may just have\n // re-wrapped under the camera, leaving the old world point stale:\n // re-pin the same page-point under the pointer and clamp against the\n // new geometry. In every other mode the scene is unchanged and this\n // never runs.\n const after = buildScene();\n if (after !== before && focal && after.itemCount) {\n writeCamera(cameraForAnchorAtScreen(focal, after, point, camera().zoom));\n }\n // A zoom write in an elastic gesture (a pinch) re-bases the pan\n // integrator: the bounds just changed shape under the stretch, so\n // the displayed camera becomes the new reference.\n if (gesture.depth > 0 && gesture.elastic) gesture.raw = unrubberize(camera());\n syncCursorFromCamera();\n },\n beginGesture: (options) => {\n gesture.depth++;\n if (gesture.depth === 1) {\n cancelAnimation(); // catch: the next touch-down stops any tween or fling\n gesture.zoomed = false;\n gesture.elastic = options?.elastic === true;\n gesture.raw = null;\n }\n },\n endGesture: () => {\n if (gesture.depth === 0) return;\n gesture.depth--;\n if (gesture.depth > 0) return;\n gesture.raw = null;\n const wasElastic = gesture.elastic;\n gesture.elastic = false;\n if (gesture.zoomed) {\n gesture.zoomed = false;\n // The deferred zoom intent: one patch for the whole gesture. (In a\n // wrapped grid this may re-wrap the scene; the next reframe\n // re-anchors through the normal update path.)\n ctx.state.update(patchSettings, { zoom: { level: camera().zoom } });\n armRest(); // the gesture is over: the rest countdown runs now\n }\n syncCursorFromCamera();\n if (wasElastic) {\n // Released while stretched: spring home. A fling() right after\n // re-enters the same physics with the release velocity.\n const current = camera();\n const clamped = clampCamera(current, stayBounds(), viewport(), constraint());\n if (clamped.x !== current.x || clamped.y !== current.y) startCameraPhysics(0, 0);\n }\n },\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageGestures = ReturnType<typeof createGestures>;\n","/**\n * The camera write path: the one low-level clamped write (`writeCamera`), the\n * elastic unclamped write and its rubber-band curves, the rest detector that\n * gates device snapping, the gesture bracket state, and cursor reconciliation\n * from the camera (manipulation only; navigation sets the cursor as intent).\n */\nimport {\n clampCamera,\n anchorFromCamera,\n travelRange,\n type Camera,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { Cancel, PluginContext } from '@embedpdf/core';\n\nimport { setCamera, setCameraResting, setCursor, setMotionCause, type StageState } from '../model';\nimport { rubberIn, rubberOut } from '../motion';\nimport type { StageServices } from '../services';\n\n/** How long the zoom must hold still before the camera counts as resting. */\nconst REST_MS = 150;\n\nexport function createCameraWrite(\n ctx: PluginContext<StageState>,\n { clock, placement, scene }: Pick<StageServices, 'clock' | 'placement' | 'scene'>,\n) {\n const { camera, viewport, paged, buildScene, stayBounds, constraint } = scene;\n\n // ── the gesture bracket (touch pan and pinch) ──\n // While open, zoomAround defers its zoom-intent patch and the rest\n // countdown is held: a hesitation inside a pinch is not \"at rest\". Depth-\n // counted so nested brackets compose. An elastic gesture may also hold the\n // camera past the clamp (rubber-band); `raw` is its unclamped,\n // finger-integrated camera, which the resistance curve maps to what renders.\n const gesture = { depth: 0, zoomed: false, elastic: false, raw: null as Camera | null };\n\n // ── the camera-rest detector ──\n // Origin snapping is gated on rest (see `StageState.cameraResting`): pages\n // place fractionally while the zoom moves and snap once it has held still\n // for REST_MS.\n let cancelRest: Cancel | null = null;\n const stopRestCountdown = () => {\n cancelRest?.();\n cancelRest = null;\n };\n const armRest = () => {\n // Initial placement snaps immediately (the first paint is crisp), and a\n // host without frames keeps snapping always on: rest-gating refines live\n // gestures and is not part of the contract.\n if (!clock.hasFrames || !placement.started) return;\n ctx.state.update(setCameraResting, false);\n stopRestCountdown();\n cancelRest = clock.after(REST_MS, () => {\n cancelRest = null;\n ctx.state.update(setCameraResting, true);\n });\n };\n\n // The one low-level camera write: clamp to `bounds` and store. It never\n // touches the cursor (see syncCursorFromCamera for that policy).\n const writeCamera = (next: Camera, bounds: Rect = stayBounds()) => {\n const clamped = clampCamera(next, bounds, viewport(), constraint());\n if (clamped.zoom !== camera().zoom) {\n if (gesture.depth > 0) {\n // Mid-gesture: un-rest at once (fractional placement) but hold the\n // countdown; rest is declared at endGesture, not at a pinch hesitation.\n gesture.zoomed = true;\n ctx.state.update(setCameraResting, false);\n stopRestCountdown();\n } else {\n armRest();\n }\n }\n ctx.state.update(setCamera, clamped);\n };\n\n // ── rubber-band (elastic overscroll) ──\n // The curve pair lives in motion.ts; these adapt it to camera state. The\n // rubber softens only the edges of a scroll range: an axis whose content\n // fits the viewport has no travel, the clamp holds it at its fitAlign rest,\n // and it stays rigid however hard the finger tugs (the UIScrollView\n // default: bouncing exists only where content exceeds the bounds).\n const axisTravels = (origin: number, content: number, view: number, zoom: number): boolean =>\n !travelRange(origin, content, view, zoom, constraint().padding).fits;\n /** The unclamped finger-integrated camera → the displayed camera: clamp,\n * then re-apply the overshoot through the resistance curve, per travelling\n * axis. Inside the bounds this is exactly the clamp, and on a fitting axis\n * it is always the clamp. */\n const rubberize = (raw: Camera): Camera => {\n const clamped = clampCamera(raw, stayBounds(), viewport(), constraint());\n const size = viewport();\n const bounds = stayBounds();\n const axis = (\n rawPosition: number,\n clampedPosition: number,\n dimension: number,\n travels: boolean,\n ): number => {\n if (!travels) return clampedPosition;\n const overshootWorld = rawPosition - clampedPosition;\n if (overshootWorld === 0) return clampedPosition;\n const stretch = rubberOut(Math.abs(overshootWorld) * raw.zoom, Math.max(1, dimension));\n return clampedPosition + (Math.sign(overshootWorld) * stretch) / raw.zoom;\n };\n return {\n zoom: raw.zoom,\n x: axis(\n raw.x,\n clamped.x,\n size.width,\n axisTravels(bounds.x, bounds.width, size.width, raw.zoom),\n ),\n y: axis(\n raw.y,\n clamped.y,\n size.height,\n axisTravels(bounds.y, bounds.height, size.height, raw.zoom),\n ),\n };\n };\n /** The displayed camera → the raw position `rubberize` would have produced\n * it from. The overshoot is capped just under the asymptote so the inverse\n * stays finite whatever state a catch finds the camera in. */\n const unrubberize = (displayed: Camera): Camera => {\n const clamped = clampCamera(displayed, stayBounds(), viewport(), constraint());\n const size = viewport();\n const bounds = stayBounds();\n const axis = (\n displayedPosition: number,\n clampedPosition: number,\n dimension: number,\n travels: boolean,\n ): number => {\n if (!travels) return clampedPosition;\n const overshootWorld = displayedPosition - clampedPosition;\n if (overshootWorld === 0) return clampedPosition;\n const span = Math.max(1, dimension);\n const stretch = Math.min(Math.abs(overshootWorld) * displayed.zoom, span - 1);\n return (\n clampedPosition + (Math.sign(overshootWorld) * rubberIn(stretch, span)) / displayed.zoom\n );\n };\n return {\n zoom: displayed.zoom,\n x: axis(\n displayed.x,\n clamped.x,\n size.width,\n axisTravels(bounds.x, bounds.width, size.width, displayed.zoom),\n ),\n y: axis(\n displayed.y,\n clamped.y,\n size.height,\n axisTravels(bounds.y, bounds.height, size.height, displayed.zoom),\n ),\n };\n };\n // The elastic write path, with no clamp: used only by the elastic pan and\n // the edge spring, whose math guarantees every trajectory ends clamped.\n const writeCameraUnclamped = (next: Camera) => ctx.state.update(setCamera, next);\n\n /**\n * Cursor reconciliation, one direction per interaction:\n * navigation → the cursor is intent, set explicitly; the camera honors\n * it as far as the clamp allows, and a clamped camera\n * never revokes it.\n * manipulation → (pan, drag, pinch) the camera moves freely and the\n * cursor is derived from it. Only those verbs call this.\n * Paged flow never syncs.\n */\n const syncCursorFromCamera = () => {\n if (paged()) return;\n const scene = buildScene();\n if (!scene.itemCount) return;\n ctx.state.update(setCursor, anchorFromCamera(camera(), scene, viewport()).pageIndex);\n };\n\n /** Tag what drives the next camera or cursor change (see `StageState.motionCause`). */\n const markCause = (cause: StageState['motionCause']): void =>\n ctx.state.update(setMotionCause, cause);\n\n return {\n gesture,\n armRest,\n writeCamera,\n writeCameraUnclamped,\n axisTravels,\n rubberize,\n unrubberize,\n syncCursorFromCamera,\n markCause,\n };\n}\nexport type StageCameraWrite = ReturnType<typeof createCameraWrite>;\n","/**\n * The behavioral placement latch: it flips when initial placement starts,\n * while `StageState.placed` is the render-commit latch that flips only after\n * placement finishes. Camera behavior keys on this one; renderers key on\n * `placed`, so partial geometry is never observable.\n */\nimport type { ScrollBehaviorKind } from '../contract';\n\nexport interface PlacementLatch {\n started: boolean;\n /** The last navigation asked for before placement; placement applies it last. */\n pending: (() => void) | null;\n}\n\nexport const createPlacementLatch = (): PlacementLatch => ({ started: false, pending: null });\n\n/**\n * Run a navigation verb now, or, before the first placement, when it happens.\n * Before placement there is no viewport to move a camera in, and placement\n * would reset it anyway, so the last call waits and lands instantly after the\n * initial view: an app that reveals something as the document opens sees it\n * on the first frame.\n */\nexport function whenPlaced<Options extends { behavior?: ScrollBehaviorKind }>(\n latch: PlacementLatch,\n options: Options | undefined,\n run: (options: Options | undefined) => void,\n): void {\n if (latch.started) {\n run(options);\n return;\n }\n latch.pending = () => run({ ...options, behavior: 'instant' } as Options);\n}\n","/**\n * Anchors and arrivals. The anchor is the durable \"what am I looking at\":\n * captured before a structural change and re-applied after, one mechanism for\n * layout, spread, zoom, resize and restore. Navigation is canonical:\n * goToPage(N) always ends in the same camera state whatever the zoom or the\n * starting point.\n */\nimport {\n cameraFromAnchor,\n clampCamera,\n placeCamera,\n resolveZoom,\n type AlignmentValue,\n type Anchor,\n type Camera,\n type Rect,\n} from '@embedpdf/core-stage';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { GoToOptions } from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setCursor, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport { whenPlaced } from '../services/placement-latch';\n\nexport function createArrival(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { writeCamera, markCause }: Pick<StageCameraWrite, 'writeCamera' | 'markCause'>,\n { cancelAnimation, animateTo }: Pick<StageAnimation, 'cancelAnimation' | 'animateTo'>,\n) {\n const {\n camera,\n viewport,\n padding,\n paged,\n isFitAll,\n grouping,\n itemIndexOfPage,\n buildScene,\n sceneRect,\n itemRect,\n pageRectOf,\n cursorItem,\n fits,\n alignPoint,\n fitBox,\n boundsFor,\n constraint,\n indexOfTarget,\n } = scene;\n const state = () => ctx.state.get();\n const pageCount = () => ctx.document()?.pageCount ?? 0;\n\n /**\n * Run a placement whose resolved zoom may change the scene (in wrapped mode\n * zoom is a layout input), until the scene it placed against is the scene\n * that results. Every non-wrapped mode is stable after the first pass, and\n * wrapped fit modes converge on the second (the fit box does not depend on\n * wrapping). Capped at 3 passes for the one circular case (fit-all +\n * wrapped).\n */\n const stabilized = (place: () => void) => {\n for (let attempt = 0; attempt < 3; attempt++) {\n const before = buildScene();\n place();\n if (buildScene() === before) return;\n }\n };\n\n const applyAnchor = (anchor: Anchor, align?: AlignmentValue) => {\n stabilized(() => {\n const current = buildScene();\n if (!current.itemCount) return;\n const item = current.items[current.itemOfPage(anchor.pageIndex)];\n const zoom = resolveZoom(state().zoom, fitBox(item), viewport(), padding());\n // Resolved against the current viewport: a resize restores the anchor\n // to the new viewport's policy point (start/start keeps the top pinned).\n const at = alignPoint(align ?? state().anchorAlign, viewport());\n writeCamera(cameraFromAnchor(anchor, current, viewport(), zoom, at), boundsFor(item));\n });\n };\n /**\n * Re-apply the view after a structural, zoom or viewport change. Normally\n * anchor-preserving (keep looking at the same spot, held at the invariant\n * point). Under fit-all the subject is the whole scene, so keeping an\n * anchor is meaningless: re-place instead (which also centers the scene\n * when unbounded).\n */\n const reapply = (anchor: Anchor, align?: AlignmentValue) => {\n if (isFitAll()) goToTarget(state().cursor, { behavior: 'instant' });\n else applyAnchor(anchor, align);\n };\n\n const goToTarget = (pageIndex: number, options?: GoToOptions) => {\n markCause('programmatic');\n cancelAnimation();\n if (pageCount() === 0) return;\n const target = Math.max(0, Math.min(pageIndex, pageCount() - 1));\n ctx.state.update(setCursor, target);\n\n // The restore path (per-page view memory): the exact viewpoint instead of\n // a fresh placement.\n if (options?.viewpoint) {\n ctx.state.update(patchSettings, { zoom: options.viewpoint.zoom });\n applyAnchor(options.viewpoint.anchor);\n return;\n }\n\n // Placement against the current scene; null when there is nothing to place.\n const placement = (): { camera: Camera; bounds: Rect } | null => {\n const current = buildScene(); // paged: the (possibly new) slice; continuous: the full scene\n if (!current.itemCount) return null;\n const item = paged() ? current.items[0] : current.items[itemIndexOfPage(target)];\n const zoom = resolveZoom(state().zoom, fitBox(item), viewport(), padding());\n const subject = isFitAll()\n ? sceneRect()\n : fits(itemRect(item), zoom)\n ? itemRect(item)\n : pageRectOf(item, target);\n // The landing policy: a per-call override beats the setting, and 'keep'\n // pins that axis to the current camera.\n const landing = { ...state().arrivalAlign, ...options?.arrivalAlign };\n const placed = placeCamera(\n subject,\n viewport(),\n zoom,\n padding(),\n {\n x: landing.x === 'keep' ? 'start' : landing.x,\n y: landing.y === 'keep' ? 'start' : landing.y,\n },\n state().direction,\n );\n // Arrivals are canonical even on an unbounded stage: the landing clamps\n // within the true bounds regardless (free roam is a manipulation\n // affordance, not an arrival one), so an axis with no freedom collapses\n // to its fitAlign rest and the fit-all scene centers even unbounded.\n const bounds = boundsFor(item);\n const settled = clampCamera(placed, bounds, viewport(), { ...constraint(), bounded: true });\n return {\n camera: {\n zoom,\n x: landing.x === 'keep' ? camera().x : settled.x,\n y: landing.y === 'keep' ? camera().y : settled.y,\n },\n bounds,\n };\n };\n\n if ((options?.behavior ?? state().scrollBehavior) === 'smooth') {\n const landing = placement();\n if (landing) animateTo(landing.camera, landing.bounds);\n } else {\n // An instant placement converges with the scene (wrapped: zoom is a layout input).\n stabilized(() => {\n const landing = placement();\n if (landing) writeCamera(landing.camera, landing.bounds);\n });\n }\n };\n\n /** Step by the navigation unit: the item when it fits the viewport, else the page. */\n const step = (direction: 1 | -1, options?: GoToOptions) => {\n const item = cursorItem();\n if (!item) return;\n const { grouping: groups } = grouping();\n if (isFitAll() || fits(itemRect(item), camera().zoom)) {\n const index = Math.max(\n 0,\n Math.min(itemIndexOfPage(state().cursor) + direction, groups.length - 1),\n );\n goToTarget(groups[index][0], options);\n } else {\n goToTarget(state().cursor + direction, options);\n }\n };\n\n // Home is page 0, a fresh arrival at arrivalAlign (the clamp collapses any\n // fitting axis to its fitAlign rest point).\n const resetView = (): void => goToTarget(0, { behavior: 'instant' });\n\n return {\n stabilized,\n applyAnchor,\n reapply,\n goToTarget,\n resetView,\n api: {\n goToPage: (page, options) => {\n const index = indexOfTarget(page);\n if (index !== null) whenPlaced(placement, options, (go) => goToTarget(index, go));\n },\n goToFirstPage: (options) => whenPlaced(placement, options, (go) => goToTarget(0, go)),\n goToLastPage: (options) =>\n whenPlaced(placement, options, (go) =>\n goToTarget(Math.max(0, (ctx.document()?.pageCount ?? 1) - 1), go),\n ),\n canGoNext: () => state().cursor < pageCount() - 1,\n canGoPrevious: () => state().cursor > 0,\n nextPage: (options) => whenPlaced(placement, options, (go) => step(1, go)),\n previousPage: (options) => whenPlaced(placement, options, (go) => step(-1, go)),\n resetView,\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageArrival = ReturnType<typeof createArrival>;\n","/**\n * A destination as a reveal. A destination (ISO 32000-1 §12.3.2.2) says\n * where on a page to look and how close; the stage's reveal takes the same\n * three knobs:\n * rect — what to look at: a point for `xyz`, a rect for `fitR`, the page\n * for `fit` and the `fitB*` kinds\n * zoom — 'keep' | {level} | 'fit' | 'fit-width' | 'fit-height'\n * anchor — where it lands; 'keep' is the specification's `null`: keep the\n * current value on that axis\n *\n * Destinations are in page space, the stage's own space, so nothing converts.\n * The `fitB*` kinds fit the page's content bounding box; the whole page\n * stands in for it.\n */\nimport type { PageDestination, PdfSize } from '@embedpdf/core';\n\nimport type { RevealOptions } from './contract';\n\nexport function revealOfDestination(destination: PageDestination, size: PdfSize): RevealOptions {\n const { width, height } = size;\n switch (destination.kind) {\n case 'xyz': {\n const { x, y, zoom } = destination;\n return {\n // A null axis keeps the current camera value; the number fed in for\n // it is never read (the 'keep' anchor).\n rect: { x: x ?? 0, y: y ?? 0, width: 0, height: 0 },\n anchor: { x: x != null ? 'start' : 'keep', y: y != null ? 'start' : 'keep' },\n // A zoom of 0 means the same as null: keep the current zoom.\n zoom: zoom != null && zoom !== 0 ? { level: zoom } : 'keep',\n };\n }\n case 'fit':\n return { zoom: 'fit' };\n case 'fitB':\n return { rect: { x: 0, y: 0, width, height }, zoom: 'fit' };\n case 'fitH':\n case 'fitBH': {\n const { y } = destination;\n return {\n rect: { x: 0, y: y ?? 0, width, height: 0 },\n zoom: 'fit-width',\n anchor: { y: y != null ? 'start' : 'keep' },\n };\n }\n case 'fitV':\n case 'fitBV': {\n const { x } = destination;\n return {\n rect: { x: x ?? 0, y: 0, width: 0, height },\n zoom: 'fit-height',\n anchor: { x: x != null ? 'start' : 'keep' },\n };\n }\n case 'fitR': {\n const { x, y, width: rectWidth, height: rectHeight } = destination;\n return { rect: { x, y, width: rectWidth, height: rectHeight }, zoom: 'fit' };\n }\n }\n}\n","/**\n * Reveals and destinations. A bare reveal is not navigation: minimal\n * visibility, cursor untouched (in paged flow, revealing a page is navigating\n * to it). A positioned reveal (rect, anchor or zoom: a search hit) is an\n * arrival: the cursor is set up front, the camera lands per the anchor\n * policy, and a resolved zoom becomes the zoom intent. A destination is a\n * positioned reveal of the spot it names.\n */\nimport { revealCamera, type Camera, type Rect as StageRect } from '@embedpdf/core-stage';\nimport type { PageDestination, PluginContext, PageRef } from '@embedpdf/core';\n\nimport type { GoToDestinationOptions, RevealAnchorValue, RevealOptions } from '../contract';\nimport { revealOfDestination } from '../destination';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setCursor, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport { whenPlaced } from '../services/placement-latch';\nimport type { StageArrival } from './arrive';\n\nexport function createReveal(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { writeCamera, markCause }: Pick<StageCameraWrite, 'writeCamera' | 'markCause'>,\n { cancelAnimation, animateTo }: Pick<StageAnimation, 'cancelAnimation' | 'animateTo'>,\n { stabilized, goToTarget }: Pick<StageArrival, 'stabilized' | 'goToTarget'>,\n) {\n const {\n camera,\n viewport,\n padding,\n paged,\n itemIndexOfPage,\n worldPageFrame,\n buildScene,\n sceneRect,\n pageRectOf,\n worldRectForContent,\n boundsFor,\n indexOfTarget,\n } = scene;\n const state = () => ctx.state.get();\n\n /**\n * One axis of a positioned-reveal camera. `undefined` is 'nearest' (move\n * only when the target is outside the padded view), unless the zoom just\n * changed: then \"do not move\" is meaningless and the slack-axis rule\n * (center) applies. 'keep' never moves the axis (PDF /XYZ null).\n */\n const revealAxis = (\n anchor: RevealAnchorValue | undefined,\n cameraPosition: number,\n rectPosition: number,\n rectExtent: number,\n viewportExtent: number,\n zoom: number,\n zoomChanged: boolean,\n ): number => {\n if (anchor === 'keep') return cameraPosition;\n const inset = padding();\n if (anchor === undefined) {\n if (!zoomChanged) {\n const low = cameraPosition + inset / zoom;\n const high = cameraPosition + (viewportExtent - inset) / zoom;\n if (rectPosition >= low && rectPosition + rectExtent <= high) return cameraPosition; // already visible\n if (rectExtent > high - low || rectPosition < low) return rectPosition - inset / zoom;\n return rectPosition + rectExtent - (viewportExtent - inset) / zoom;\n }\n anchor = 'center';\n }\n if (anchor === 'start') return rectPosition - inset / zoom;\n if (anchor === 'end') return rectPosition + rectExtent - (viewportExtent - inset) / zoom;\n const fraction = anchor === 'center' ? 0.5 : Math.min(1, Math.max(0, anchor));\n return rectPosition + rectExtent / 2 - (viewportExtent * fraction) / zoom;\n };\n\n const revealAt = (pageIndex: number, options?: RevealOptions): void => {\n markCause('programmatic');\n const pageCount = ctx.document()?.pageCount ?? 0;\n if (pageCount === 0) return;\n const target = Math.max(0, Math.min(pageIndex, pageCount - 1));\n const positioned =\n !!options &&\n // `rect: null` means \"no rect\", the same as absent, so nullable sources\n // flow in without a `?? undefined`.\n (options.rect != null ||\n options.anchor !== undefined ||\n (options.zoom !== undefined && options.zoom !== 'keep'));\n\n if (!positioned) {\n // A bare reveal is not navigation: minimal visibility, cursor untouched.\n if (paged()) {\n // The page is not in the one-item slice: revealing it is navigating to it.\n goToTarget(target, options);\n return;\n }\n const current = buildScene();\n if (!current.itemCount) return;\n const page = pageRectOf(current.items[itemIndexOfPage(target)], target);\n // Reveal the outer box: pageFrame chrome (labels, buttons) belongs to\n // the page, so \"make the page visible\" includes its reserved bands.\n const frame = worldPageFrame();\n const box = {\n x: page.x - frame.left,\n y: page.y - frame.top,\n width: page.width + frame.left + frame.right,\n height: page.height + frame.top + frame.bottom,\n };\n const next = revealCamera(camera(), box, viewport(), padding());\n const now = camera();\n if (next.x === now.x && next.y === now.y) return; // already visible\n cancelAnimation();\n if ((options?.behavior ?? state().scrollBehavior) === 'smooth') {\n animateTo(next, sceneRect());\n } else {\n writeCamera(next, sceneRect());\n }\n return;\n }\n\n // A positioned reveal is an arrival at a rect or point (a search hit, a\n // PDF destination). Like navigation, the cursor is intent, set up front\n // (in paged flow this also rebuilds the one-item slice), never derived\n // from a camera that may be mid-tween.\n cancelAnimation();\n ctx.state.update(setCursor, target);\n\n const place = (): { camera: Camera; bounds: StageRect; zoomChanged: boolean } | null => {\n const current = buildScene();\n if (!current.itemCount) return null;\n const item = paged() ? current.items[0] : current.items[itemIndexOfPage(target)];\n const world = options.rect\n ? worldRectForContent(item, target, options.rect)\n : pageRectOf(item, target);\n const zoomDirective = options.zoom ?? 'keep';\n const availableWidth = Math.max(1, viewport().width - 2 * padding());\n const availableHeight = Math.max(1, viewport().height - 2 * padding());\n let zoom =\n typeof zoomDirective === 'object'\n ? zoomDirective.level\n : zoomDirective === 'fit'\n ? Math.min(availableWidth / world.width, availableHeight / world.height)\n : zoomDirective === 'fit-width'\n ? availableWidth / world.width\n : zoomDirective === 'fit-height'\n ? availableHeight / world.height\n : camera().zoom;\n // A degenerate target (a point with a fit directive) only pans.\n if (!Number.isFinite(zoom) || zoom <= 0) zoom = camera().zoom;\n const zoomChanged = zoomDirective !== 'keep';\n const anchor = options.anchor ?? {};\n return {\n camera: {\n x: revealAxis(\n anchor.x,\n camera().x,\n world.x,\n world.width,\n viewport().width,\n zoom,\n zoomChanged,\n ),\n y: revealAxis(\n anchor.y,\n camera().y,\n world.y,\n world.height,\n viewport().height,\n zoom,\n zoomChanged,\n ),\n zoom,\n },\n bounds: boundsFor(item),\n zoomChanged,\n };\n };\n\n const first = place();\n if (!first) return;\n // A resolved zoom becomes the zoom intent (like zoomAround), so later\n // resizes and refits keep the destination's magnification.\n if (first.zoomChanged) {\n ctx.state.update(patchSettings, { zoom: { level: first.camera.zoom } });\n }\n if ((options.behavior ?? state().scrollBehavior) === 'smooth') {\n // If the zoom patch re-wrapped the scene (zoom is a layout input in\n // wrapped mode), recompute once against the new geometry.\n const landing = place() ?? first;\n animateTo(landing.camera, landing.bounds);\n } else {\n stabilized(() => {\n const landing = place();\n if (landing) writeCamera(landing.camera, landing.bounds);\n });\n }\n };\n\n const reveal = (page: PageRef | number, options?: RevealOptions): void => {\n const index = indexOfTarget(page);\n if (index !== null) whenPlaced(placement, options, (go) => revealAt(index, go));\n };\n\n const goToDestination = (\n destination: PageDestination,\n options?: GoToDestinationOptions,\n ): void => {\n const layout = ctx.getPage(destination.page);\n if (!layout) return;\n const spot = revealOfDestination(destination, layout.size);\n whenPlaced(placement, { ...spot, behavior: options?.behavior }, (go) =>\n revealAt(layout.index, go),\n );\n };\n\n return {\n api: { reveal, goToDestination } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * Zoom verbs. Pointer-less zooms magnify around the zoomAlign focal point\n * (pinch and wheel pass their own pointer to `zoomAround`: physics beats\n * policy); fit modes are zoom intents written through the settings; the\n * double-tap ladder ascends reading postures.\n */\nimport { anchorAtPoint, resolveZoom, toWorld, ZOOM_MAX, ZoomMode } from '@embedpdf/core-stage';\nimport { addRotations, type PageRotation } from '@embedpdf/core-geometry';\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageGestures } from '../camera/gestures';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, type StageState } from '../model';\nimport type { StageServices } from '../services';\nimport type { StageSettingsArea } from '../settings/settings';\n\n/** The zoom factor of one zoomIn or zoomOut step. */\nconst ZOOM_STEP = 1.2;\n\nexport function createZoom(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n { syncCursorFromCamera }: Pick<StageCameraWrite, 'syncCursorFromCamera'>,\n {\n cancelAnimation,\n animateZoomAnchored,\n }: Pick<StageAnimation, 'cancelAnimation' | 'animateZoomAnchored'>,\n gestures: StageGestures['api'],\n settings: Pick<StageSettingsArea, 'updateSettings'>,\n) {\n const { camera, viewport, padding, paged, itemIndexOfPage, buildScene, alignPoint, fitBox } =\n scene;\n const state = () => ctx.state.get();\n const zoomAlignPoint = () => alignPoint(state().zoomAlign, viewport());\n\n const setViewRotation = (viewRotation: PageRotation): void =>\n settings.updateSettings({ viewRotation });\n\n return {\n api: {\n doubleTapZoom: (point) => {\n cancelAnimation();\n const before = buildScene();\n if (!before.itemCount) return;\n const item = paged() ? before.items[0] : before.items[itemIndexOfPage(state().cursor)];\n // The ladder (the platform convention) ascends reading postures, each\n // derived from a zoom intent: see the page (automatic), read the text\n // (fit-width), inspect (2.5× the automatic fit). Stops within 10% of\n // a neighbor collapse, so on phones, where automatic is fit-width,\n // the ladder is the familiar two-state toggle.\n //\n // As on iOS, the ladder ascends only from a rung: a tap at a posture\n // moves to the next, wrapping past the top. A pinch to any other\n // level leaves the ladder, and a double-tap there resets to the base\n // fit (\"take me back to reading\"), never a further zoom-in.\n const fit = fitBox(item);\n const automatic = resolveZoom({ mode: ZoomMode.Automatic }, fit, viewport(), padding());\n const fitWidth = resolveZoom({ mode: ZoomMode.FitWidth }, fit, viewport(), padding());\n const stops = [automatic, fitWidth, Math.min(automatic * 2.5, ZOOM_MAX)]\n .sort((left, right) => left - right)\n .filter((zoom, index, all) => index === 0 || zoom > all[index - 1] * 1.1);\n // The same ±10% band the dedupe uses: \"at a posture\" tolerates fit drift.\n const near = (zoom: number, stop: number) => zoom > stop / 1.1 && zoom < stop * 1.1;\n const onRung = stops.findIndex((stop) => near(camera().zoom, stop));\n const target = onRung >= 0 ? stops[(onRung + 1) % stops.length] : stops[0];\n // The intent commits up front, as in `reveal`: a caught tween must\n // never leave the camera at an intermediate zoom while the stored\n // intent still says \"fit\", or the next refit would snap somewhere the\n // user did not ask for.\n ctx.state.update(patchSettings, { zoom: { level: target } });\n // Wrapped grids re-layout on the intent change: anchor the focal\n // point against the scene that will actually be on screen.\n const after = buildScene();\n if (!after.itemCount) return;\n const focal = anchorAtPoint(after, toWorld(camera(), point));\n // The focal-anchored tween keeps the tapped point still.\n animateZoomAnchored(focal, point, target, undefined, syncCursorFromCamera);\n },\n zoomIn: () => gestures.zoomAround(zoomAlignPoint(), ZOOM_STEP),\n zoomOut: () => gestures.zoomAround(zoomAlignPoint(), 1 / ZOOM_STEP),\n zoomTo: (zoom, options) => {\n if (typeof zoom === 'number') {\n if (options?.around) gestures.zoomAround(options.around, zoom / camera().zoom);\n else settings.updateSettings({ zoom: { level: zoom } });\n return;\n }\n settings.updateSettings({ zoom });\n },\n zoomBy: (factor, options) => gestures.zoomAround(options?.around ?? zoomAlignPoint(), factor),\n fitWidth: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitWidth } }),\n fitPage: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitPage } }),\n fitAll: () => settings.updateSettings({ zoom: { mode: ZoomMode.FitAll } }),\n fitAutomatic: () => settings.updateSettings({ zoom: { mode: ZoomMode.Automatic } }),\n setViewRotation,\n rotateViewBy: (delta) =>\n setViewRotation(addRotations(state().viewRotation, delta === 90 ? 90 : 270)),\n } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * The page reads: laid-out pages with their transforms (PDF points → view px\n * → device px), the scroller projection, the visible set (memoized so reads\n * stay reference-stable), coordinate conversions and the camera, zoom and\n * viewpoint reads.\n */\nimport {\n cameraWorldRect,\n scrollMetrics,\n toScreen,\n toWorld,\n type PageBox,\n type ScrollMetrics,\n type Size,\n} from '@embedpdf/core-stage';\nimport {\n applyPoint,\n applyRect,\n displaySize,\n intersectRects,\n pageTransform,\n rotateScaleMatrix,\n snapToDevice,\n} from '@embedpdf/core-geometry';\nimport type { Point } from '@embedpdf/core-geometry';\nimport {\n memo,\n toPageRef,\n type PageDestination,\n type PluginContext,\n type PageRef,\n} from '@embedpdf/core';\n\nimport type { Viewpoint, VisiblePage } from '../contract';\nimport type { StageHostCapability } from '../host-contract';\nimport type { StageState } from '../model';\nimport type { StageServices } from '../services';\n\nexport function createPageReads(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n) {\n const {\n camera,\n viewport,\n dpr,\n padding,\n paged,\n buildScene,\n cacheKey,\n stayBounds,\n cursorItem,\n currentAnchor,\n } = scene;\n const state = () => ctx.state.get();\n\n // The durable identity of the page at a display index, from the registry.\n const pageObjectNumberAt = (index: number): number =>\n ctx.document()?.pages[index]?.ref.objectNumber ?? index + 1;\n\n // The un-rotated point size of a laid-out box, for when the registry entry\n // is momentarily absent. `displaySize` is its own inverse (display box →\n // content box); dividing by contentScale recovers points.\n const unrotatedPoints = (box: PageBox): Size => {\n const content = displaySize({ width: box.width, height: box.height }, box.rotation);\n return { width: content.width / box.contentScale, height: content.height / box.contentScale };\n };\n\n // Attach durable identity and the per-page transform (PDF points → view px\n // → device px). `scale` is view px per point: contentScale (world per\n // point) × zoom (view px per world); `pageSize` is the page's un-rotated\n // points from the registry. The transform depends only on zoom, rotation,\n // contentScale and dpr, so the same box yields the same transform at any pan.\n const withTransform = (box: PageBox): VisiblePage => {\n const registered = ctx.document()?.pages[box.pageIndex];\n const pageSize = registered\n ? { width: registered.size.width, height: registered.size.height }\n : unrotatedPoints(box);\n const current = camera();\n const ratio = dpr();\n // The footprint's top-left, camera-resolved. Device-snapped at rest, which\n // keeps a rotated page on the device grid; while the zoom moves it places\n // fractionally (see `StageState.cameraResting`).\n const rawX = (box.x - current.x) * current.zoom;\n const rawY = (box.y - current.y) * current.zoom;\n const resting = state().cameraResting;\n const screenX = resting ? snapToDevice(rawX, ratio) : rawX;\n const screenY = resting ? snapToDevice(rawY, ratio) : rawY;\n const transform = pageTransform({\n pageSize,\n rotation: box.rotation,\n scale: box.contentScale * current.zoom,\n // The page's physical 100%: the platform unit factor × its /UserUnit,\n // so `transform.zoom` reads as \"percent of Acrobat's 100%\" per page,\n // independent of sizing mode or camera state.\n baseScale: state().viewUnitsPerPoint * (registered?.userUnit ?? 1),\n dpr: ratio,\n });\n // The on-screen page region in points: viewport ∩ footprint in view\n // space (both axis-aligned), inverted through the transform (exact for\n // quarter-turns). The virtualizer's query already decided this coarsely;\n // it is refined per page here, once, so no adapter re-derives camera math\n // (tiling's demand reads this field).\n const size = viewport();\n const onScreen = intersectRects(\n { x: -screenX, y: -screenY, width: size.width, height: size.height },\n { x: 0, y: 0, width: transform.viewWidth, height: transform.viewHeight },\n );\n const visibleRect =\n onScreen.width > 0 && onScreen.height > 0\n ? transform.viewToPageRect(onScreen)\n : { x: 0, y: 0, width: 0, height: 0 };\n return {\n ...box,\n ref: toPageRef(pageObjectNumberAt(box.pageIndex)),\n screenX,\n screenY,\n transform,\n visibleRect,\n };\n };\n\n // The scroller projection: the camera in native DOM vocabulary, against the\n // same bounds the pan clamp uses (stayBounds: the slice item in paged flow,\n // the scene in continuous). Memoized like the visible pages: the same\n // reference until a field moves, so adapter reads can use plain equality.\n const emptyScrollMetrics: ScrollMetrics = {\n scrollLeft: 0,\n scrollTop: 0,\n scrollWidth: 0,\n scrollHeight: 0,\n clientWidth: 0,\n clientHeight: 0,\n scrollableX: false,\n scrollableY: false,\n };\n let lastMetrics: ScrollMetrics | null = null;\n const scrollMetricsNow = (): ScrollMetrics => {\n if (!state().placed) return emptyScrollMetrics;\n const metrics = scrollMetrics(\n camera(),\n buildScene().itemCount ? stayBounds() : { x: 0, y: 0, width: 0, height: 0 },\n viewport(),\n padding(),\n );\n const previous = lastMetrics;\n if (\n previous &&\n previous.scrollLeft === metrics.scrollLeft &&\n previous.scrollTop === metrics.scrollTop &&\n previous.scrollWidth === metrics.scrollWidth &&\n previous.scrollHeight === metrics.scrollHeight &&\n previous.clientWidth === metrics.clientWidth &&\n previous.clientHeight === metrics.clientHeight\n ) {\n return previous; // scrollableX/Y derive from the six numbers\n }\n lastMetrics = metrics;\n return metrics;\n };\n\n // The visible pages, memoized on everything they depend on so the read is\n // reference-stable (no useSyncExternalStore tearing loop). Paged flow\n // renders only the slice's item; continuous flow renders the camera's\n // query window.\n const noVisiblePages: VisiblePage[] = [];\n const placedVisiblePages = memo(\n () => {\n const current = camera();\n const size = viewport();\n buildScene(); // keys the scene cache that `cacheKey` reads\n return [\n cacheKey(),\n state().flow,\n current.x,\n current.y,\n current.zoom,\n size.width,\n size.height,\n dpr(),\n state().cameraResting,\n ] as const;\n },\n (_sceneKey, _flow, x, y, zoom, width, height, _dpr, _resting): VisiblePage[] => {\n const scene = buildScene();\n const items = paged()\n ? scene.items.slice(0, 1)\n : scene.query(cameraWorldRect({ x, y, zoom }, { width, height }));\n return items.flatMap((item) => item.pages).map(withTransform);\n },\n );\n const visiblePages = (): VisiblePage[] =>\n state().placed ? placedVisiblePages() : noVisiblePages;\n\n const getPageFrame = (page: PageRef | number): VisiblePage | null => {\n if (!state().placed) return null;\n const index = ctx.getPage(page)?.index ?? -1;\n if (index < 0) return null;\n const scene = buildScene();\n if (!scene.itemCount) return null;\n const box = scene.items[scene.itemOfPage(index)].pages.find(\n (candidate) => candidate.pageIndex === index,\n );\n return box ? withTransform(box) : null;\n };\n\n const pageToWorld = (page: PageRef | number, point: Point): Point | null => {\n const frame = getPageFrame(page);\n if (!frame) return null;\n // Place the page point into the page's display box through the same\n // quarter-turn matrix the layout and renderer use (`rotateScaleMatrix`),\n // so this forward transform and the adapter's inverse hit-test cannot\n // drift. `displaySize` is its own inverse, so it recovers the un-rotated\n // content size from the display box.\n const content = displaySize({ width: frame.width, height: frame.height }, frame.rotation);\n const matrix = rotateScaleMatrix(\n frame.contentScale,\n content.width,\n content.height,\n frame.rotation,\n );\n const offset = applyPoint(matrix, point);\n return { x: frame.x + offset.x, y: frame.y + offset.y };\n };\n\n // The visible entry of a page given by its ref or its index; null when it is\n // off screen or not in the document.\n const visiblePageOf = (page: PageRef | number): VisiblePage | null => {\n const objectNumber = ctx.getPage(page)?.ref.objectNumber;\n if (objectNumber === undefined) return null;\n return visiblePages().find((visible) => visible.ref.objectNumber === objectNumber) ?? null;\n };\n\n return {\n scrollMetricsNow,\n visiblePages,\n api: {\n getCamera: camera,\n getViewportSize: viewport,\n getScrollMetrics: scrollMetricsNow,\n listVisiblePages: visiblePages,\n isPageVisible: (page) => visiblePageOf(page) !== null,\n getCurrentPageIndex: () => state().cursor,\n getCurrentPage: () => ctx.document()?.pages[state().cursor]?.ref ?? null,\n getPageCount: () => ctx.document()?.pageCount ?? 0,\n listCurrentItemPages: () => {\n const item = cursorItem();\n const pages = ctx.document()?.pages ?? [];\n return item\n ? item.pageIndexes.map((index) => pages[index]).filter((page) => page !== undefined)\n : [];\n },\n getPageFrame,\n getPageAt: (point) => {\n // Find the visible page whose device-snapped display box contains the\n // point, then invert that page's transform: the same `viewToPage`\n // the per-page context's `toPagePoint` uses, so the two never drift.\n for (const page of visiblePages()) {\n const localX = point.x - page.screenX;\n const localY = point.y - page.screenY;\n if (\n localX >= 0 &&\n localY >= 0 &&\n localX <= page.transform.viewWidth &&\n localY <= page.transform.viewHeight\n ) {\n return {\n ref: page.ref,\n point: page.transform.viewToPage({ x: localX, y: localY }),\n scale: page.transform.viewScale,\n rotation: page.rotation,\n zoom: page.transform.zoom,\n };\n }\n }\n return null;\n },\n viewportToPage: (page, point) => {\n // `getPageAt` without the containment check: project onto one page's\n // plane, valid outside its bounds, through the same inverse transform.\n const target = visiblePageOf(page);\n if (!target) return null;\n return target.transform.viewToPage({\n x: point.x - target.screenX,\n y: point.y - target.screenY,\n });\n },\n pageToWorld,\n pageRectToViewport: (page, rect) => {\n const frame = getPageFrame(page);\n if (!frame) return null;\n const content = displaySize({ width: frame.width, height: frame.height }, frame.rotation);\n const matrix = rotateScaleMatrix(\n frame.contentScale,\n content.width,\n content.height,\n frame.rotation,\n );\n const world = applyRect(matrix, rect);\n const current = camera();\n const topLeft = toScreen(current, { x: frame.x + world.x, y: frame.y + world.y });\n return {\n x: topLeft.x,\n y: topLeft.y,\n width: world.width * current.zoom,\n height: world.height * current.zoom,\n };\n },\n worldToViewport: (world) => toScreen(camera(), world),\n viewportToWorld: (point) => toWorld(camera(), point),\n pageToViewport: (page, point) => {\n const world = pageToWorld(page, point);\n return world ? toScreen(camera(), world) : null;\n },\n getViewRotation: () => state().viewRotation,\n getZoomLevel: () => camera().zoom,\n getZoomMode: () => {\n const zoom = state().zoom;\n return 'mode' in zoom ? zoom.mode : 'custom';\n },\n getViewpoint: (): Viewpoint => ({ anchor: currentAnchor(), zoom: state().zoom }),\n getCurrentDestination: (): PageDestination | null => {\n // Where `goToDestination` puts a destination's point: a padding in from the viewport's\n // top-left. The page read is the first one reaching past that point; the one above it\n // may still show in the padding.\n const inset = padding();\n const current = camera();\n const first = visiblePages()\n .filter((page) => {\n const corner = toScreen(current, { x: page.x + page.width, y: page.y + page.height });\n return corner.x > inset && corner.y > inset;\n })\n .sort((left, right) => left.pageIndex - right.pageIndex)[0];\n const size = first && ctx.getPage(first.ref)?.size;\n if (!first || !size) return null;\n // That point on the page's plane, then the nearest point of the page: a quarter-turn\n // keeps the page's edges on the axes, so clamping each axis is exact.\n const corner = first.transform.viewToPage({\n x: inset - first.screenX,\n y: inset - first.screenY,\n });\n const clamp = (value: number, max: number) =>\n Math.round(Math.min(Math.max(value, 0), max) * 100) / 100;\n return {\n kind: 'xyz',\n page: first.ref,\n x: clamp(corner.x, size.width),\n y: clamp(corner.y, size.height),\n zoom: null,\n };\n },\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StagePageReads = ReturnType<typeof createPageReads>;\n","/**\n * The stage's six events. Five of them are derived in one `ctx.state.onChange`\n * listener, from the state before and after each committed change, so a new\n * verb can never forget to announce a page, zoom, camera, settings or viewport\n * change. `motionEnded` is an occurrence: the camera animation emits it where a\n * tween or fling ends.\n */\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type {\n StageCameraChangedEvent,\n StageMotionEndedEvent,\n StagePageChangedEvent,\n StageSettingsChangedEvent,\n StageViewportChangedEvent,\n StageZoomChangedEvent,\n} from '../contract';\nimport type { StageState } from '../model';\nimport { eqSetting } from '../responsive';\nimport { pickSettings, SETTING_KEYS } from '../settings';\n\nexport function createEvents(ctx: PluginContext<StageState>) {\n const pageChanged = ctx.events.source<StagePageChangedEvent>();\n const zoomChanged = ctx.events.source<StageZoomChangedEvent>();\n const cameraChanged = ctx.events.source<StageCameraChangedEvent>();\n const motionEnded = ctx.events.source<StageMotionEndedEvent>();\n const settingsChanged = ctx.events.source<StageSettingsChangedEvent>();\n const viewportChanged = ctx.events.source<StageViewportChangedEvent>();\n\n ctx.state.onChange(({ previous, next }) => {\n if (previous.camera !== next.camera) {\n cameraChanged.emit({ camera: next.camera });\n if (previous.camera.zoom !== next.camera.zoom) {\n zoomChanged.emit({\n level: next.camera.zoom,\n previousLevel: previous.camera.zoom,\n mode: 'mode' in next.zoom ? next.zoom.mode : 'custom',\n });\n }\n }\n if (previous.cursor !== next.cursor) {\n pageChanged.emit({\n page: ctx.document()?.pages[next.cursor]?.ref ?? null,\n pageIndex: next.cursor,\n previousPageIndex: previous.cursor,\n });\n }\n if (previous.viewport !== next.viewport) viewportChanged.emit({ size: next.viewport });\n const changed = SETTING_KEYS.filter((key) => !eqSetting(previous[key], next[key]));\n if (changed.length) settingsChanged.emit({ settings: pickSettings(next), changed });\n });\n\n return { pageChanged, zoomChanged, cameraChanged, motionEnded, settingsChanged, viewportChanged };\n}\nexport type StageEvents = ReturnType<typeof createEvents>;\n","/**\n * The scene model: the document's item grouping, the layout, the memoized\n * scene (continuous flow lays out the whole document; paged flow a one-item\n * slice at the origin), and the pure geometry reads every area builds on:\n * fit, alignment points, clamp bounds and anchors. Reads only; nothing here\n * changes state.\n */\nimport {\n anchorFromCamera,\n gridLayout,\n groupPages,\n linearLayout,\n ZoomMode,\n type AlignmentValue,\n type AlignValue,\n type Anchor,\n type CameraConstraint,\n type PageFrame,\n type Point,\n type Rect as StageRect,\n type Scene,\n type SceneItem,\n type Size,\n} from '@embedpdf/core-stage';\nimport { addRotations, applyRect, displaySize, rotateScaleMatrix } from '@embedpdf/core-geometry';\nimport type { Rect } from '@embedpdf/core-geometry';\nimport { memo, type PluginContext, type PageRef } from '@embedpdf/core';\n\nimport type { StageSettings } from '../contract';\nimport type { StageState } from '../model';\nimport { SETTINGS_EFFECT, SETTING_KEYS } from '../settings';\n\nexport function createScene(ctx: PluginContext<StageState>) {\n const state = () => ctx.state.get();\n const camera = () => state().camera;\n const viewport = () => state().viewport;\n const dpr = () => state().dpr;\n const padding = () => state().padding;\n const paged = () => state().flow === 'paged';\n const isFitAll = () => {\n const zoom = state().zoom;\n return 'mode' in zoom && zoom.mode === ZoomMode.FitAll;\n };\n\n // The document's item model (spread grouping) is independent of the\n // rendered scene, so navigation can reason about every item while a paged\n // scene holds only one. The cursor is a page; `itemIndexOfPage` maps it,\n // which survives regrouping.\n const grouping = memo(\n () => [ctx.document()?.pageCount ?? 0, state().spread] as const,\n (pageCount, spread): { grouping: number[][]; firstPages: number[] } => {\n const groups = groupPages(pageCount, spread);\n return { grouping: groups, firstPages: groups.map((item) => item[0]) };\n },\n );\n const itemCountFull = (): number => grouping().grouping.length;\n const itemIndexOfPage = (pageIndex: number): number => {\n const firstPages = grouping().firstPages;\n let low = 0;\n let high = firstPages.length;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (firstPages[middle] <= pageIndex) low = middle + 1;\n else high = middle;\n }\n return Math.max(0, low - 1);\n };\n\n // The zoom that converts screen-px settings into world units. A fixed zoom\n // intent gives an exact, stable value (the thumbnail case); other intents\n // use the camera's current zoom, which `stabilized` converges. Screen-px\n // settings (the wrapped line width, pageFrame, `{ px }` gaps) are the only\n // way a scene depends on the viewport or the zoom.\n const effectiveZoom = (): number => {\n const zoom = state().zoom;\n return 'level' in zoom ? zoom.level : Math.max(state().camera.zoom, 0.0001);\n };\n\n // Wrapped grid: the line width (world units) the columns must fit.\n const wrapLineWidth = (): number =>\n Math.max(1, (viewport().width - 2 * padding()) / effectiveZoom());\n\n // pageFrame (screen px) → world units at the effective zoom.\n const worldPageFrame = (): PageFrame => {\n const frame = state().pageFrame;\n if (!frame.top && !frame.right && !frame.bottom && !frame.left) return frame;\n const zoom = effectiveZoom();\n return {\n top: frame.top / zoom,\n right: frame.right / zoom,\n bottom: frame.bottom / zoom,\n left: frame.left / zoom,\n };\n };\n const frameKey = (): string => {\n const frame = state().pageFrame;\n if (!frame.top && !frame.right && !frame.bottom && !frame.left) return '-';\n const world = worldPageFrame();\n return `${Math.round(world.top)},${Math.round(world.right)},${Math.round(world.bottom)},${Math.round(world.left)}`;\n };\n\n // gap → world units. A plain number is world units (the scene stays\n // zoom-invariant, the rigid-canvas default); `{ px }` converts at the\n // effective zoom like pageFrame (UI-stable spacing for browser-style lenses).\n const worldGap = (): number => {\n const gap = state().gap;\n return typeof gap === 'number' ? gap : gap.px ? gap.px / effectiveZoom() : 0;\n };\n const gapKey = (): string => {\n const gap = state().gap;\n return typeof gap === 'number' ? String(gap) : `px:${Math.round(worldGap())}`;\n };\n\n const layoutFor = (groups: number[][]): Scene => {\n const settings = state();\n // Engine page layouts structurally satisfy stage-core's page geometry\n // (`size` + `rotation`): the intrinsic page size flows straight in.\n //\n // The view rotation is composed here, and only here: each page's display\n // rotation is its /Rotate plus this lens's viewRotation. Everything\n // downstream (the display-size swap, the page transform, hit-testing, fit\n // zoom, overlays) reads the composed rotation. `size` stays the page's\n // own un-rotated points, so page space is view-rotation-invariant.\n const registryPages = ctx.document()?.pages ?? [];\n const viewRotation = settings.viewRotation;\n const pages =\n viewRotation === 0\n ? registryPages\n : registryPages.map((page) => ({\n ...page,\n rotation: addRotations(page.rotation, viewRotation),\n }));\n const pageFrame = worldPageFrame();\n const gap = worldGap();\n const viewUnitsPerPoint = settings.viewUnitsPerPoint;\n if (settings.layout === 'grid') {\n return gridLayout(pages, groups, {\n gap,\n sizing: settings.sizing,\n direction: settings.direction,\n pageFrame,\n viewUnitsPerPoint,\n columns: typeof settings.columns === 'number' ? settings.columns : undefined,\n lineWidth: settings.columns === 'auto' ? wrapLineWidth() : undefined,\n });\n }\n return linearLayout(pages, groups, {\n axis: settings.layout === 'horizontal' ? 'x' : 'y',\n gap,\n sizing: settings.sizing,\n direction: settings.direction,\n pageFrame,\n viewUnitsPerPoint,\n });\n };\n\n // The column policy's part of the scene key; 'auto' quantizes the line\n // width so sub-pixel resizes do not rebuild the scene.\n const columnsKey = (): string => {\n const settings = state();\n if (settings.layout !== 'grid') return '-';\n return settings.columns === 'auto'\n ? `auto:${Math.round(wrapLineWidth())}`\n : String(settings.columns);\n };\n\n // The scene's settings signature, derived from the settings registry: every\n // 'scene' setting contributes automatically, so a new layout-affecting\n // setting only needs its SETTINGS_EFFECT row and a stale scene cannot be\n // forgotten here. Values key by value (objects via JSON); the custom\n // functions quantize px-derived values so sub-pixel zoom and resize churn\n // does not rebuild the scene.\n const SCENE_KEY_FUNCTIONS: Partial<Record<keyof StageSettings, () => string>> = {\n columns: columnsKey,\n gap: gapKey,\n pageFrame: frameKey,\n };\n const SCENE_KEYS = SETTING_KEYS.filter((key) => SETTINGS_EFFECT[key] === 'scene');\n const settingsKey = (): string =>\n SCENE_KEYS.map((key) => {\n const keyFunction = SCENE_KEY_FUNCTIONS[key];\n if (keyFunction) return keyFunction();\n const value = state()[key];\n return typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);\n }).join('|');\n\n // The scene cache. Continuous flow lays out the whole document. Paged flow\n // is a one-item slice at the origin holding only the cursor's item, so\n // isolation is structural (no other page exists to leak into view),\n // unbounded pan is free, and coordinates stay local.\n let sceneCache: { key: string; scene: Scene } | null = null;\n // The registry signature: page count plus the kernel's monotonic\n // `revision`. The revision changes on every page mutation (rotate, move,\n // delete), so a change that keeps the page count (a rotation) still re-keys\n // the scene instead of rendering the page in its stale box.\n const documentKey = (): string => {\n const document = ctx.document();\n return document ? `${document.pageCount}.${document.revision}` : '0.0';\n };\n const buildScene = (): Scene => {\n const { grouping: groups } = grouping();\n if (state().flow === 'paged') {\n const index = groups.length\n ? Math.min(itemIndexOfPage(state().cursor), groups.length - 1)\n : 0;\n const key = `paged|${documentKey()}|${settingsKey()}|${index}`;\n if (sceneCache && sceneCache.key === key) return sceneCache.scene;\n const scene = layoutFor(groups.length ? [groups[index]] : []);\n sceneCache = { key, scene };\n return scene;\n }\n const key = `continuous|${documentKey()}|${settingsKey()}`;\n if (sceneCache && sceneCache.key === key) return sceneCache.scene;\n const scene = layoutFor(groups);\n sceneCache = { key, scene };\n return scene;\n };\n /** Drop the memoized scene (a 'scene' or 'reflow' setting changed, or a view was restored). */\n const invalidate = (): void => {\n sceneCache = null;\n };\n /** The current scene's cache key, part of the visible-pages signature. */\n const cacheKey = (): string => sceneCache!.key;\n\n // ── geometry helpers ──\n const sceneRect = (): StageRect => {\n const { width, height } = buildScene().size;\n return { x: 0, y: 0, width, height };\n };\n const itemRect = (item: SceneItem): StageRect => ({\n x: item.x,\n y: item.y,\n width: item.width,\n height: item.height,\n });\n const pageRectOf = (item: SceneItem, pageIndex: number): StageRect => {\n const box = item.pages.find((page) => page.pageIndex === pageIndex) ?? item.pages[0];\n return { x: box.x, y: box.y, width: box.width, height: box.height };\n };\n /** The item shown for the cursor: the slice's only item (paged) or the full-scene item. */\n const cursorItem = (): SceneItem => {\n const scene = buildScene();\n return paged() ? scene.items[0] : scene.items[itemIndexOfPage(state().cursor)];\n };\n\n /**\n * A page-space rect on a page → a world rect: the same quarter-turn\n * matrix `pageRectToViewport` uses, minus the camera, so a positioned\n * reveal and the rendered overlay never disagree about where a rect is.\n */\n const worldRectForContent = (item: SceneItem, pageIndex: number, rect: Rect): StageRect => {\n const box = item.pages.find((page) => page.pageIndex === pageIndex) ?? item.pages[0];\n const content = displaySize({ width: box.width, height: box.height }, box.rotation);\n const matrix = rotateScaleMatrix(box.contentScale, content.width, content.height, box.rotation);\n const world = applyRect(matrix, rect);\n return { x: box.x + world.x, y: box.y + world.y, width: world.width, height: world.height };\n };\n\n // Does this rect fit the padded viewport at this zoom? It decides the\n // navigation step size and the arrival subject, never the alignment.\n const fits = (rect: StageRect, zoom: number): boolean => {\n const size = viewport();\n const inset = padding();\n const tolerance = 0.5;\n return (\n rect.width * zoom <= size.width - 2 * inset + tolerance &&\n rect.height * zoom <= size.height - 2 * inset + tolerance\n );\n };\n // An alignment policy → a concrete viewport point: a fraction per axis\n // (start = 0, center = ½, end = 1; named x stops are logical under RTL).\n // zoomAlign and anchorAlign both resolve through this. The fraction spans\n // the padded range: 'start' is the first visible content line just inside\n // the gutter, where an arrival puts the page edge, so the reference pins\n // to the page and never to the gap above it.\n const alignFraction = (value: AlignValue): number =>\n value === 'start'\n ? 0\n : value === 'center'\n ? 0.5\n : value === 'end'\n ? 1\n : Math.min(1, Math.max(0, value));\n const alignPoint = (alignment: AlignmentValue, size: Size): Point => {\n const rtl = state().direction === 'rtl';\n const alignX =\n rtl && alignment.x === 'start' ? 'end' : rtl && alignment.x === 'end' ? 'start' : alignment.x;\n const inset = padding();\n return {\n x: inset + (size.width - 2 * inset) * alignFraction(alignX),\n y: inset + (size.height - 2 * inset) * alignFraction(alignment.y),\n };\n };\n const anchorPoint = (): Point => alignPoint(state().anchorAlign, viewport());\n\n /** The box the zoom intent fits: the whole scene (fit-all), the current\n * item (paged: per-page fit), or the document maximum (continuous: a\n * document-stable zoom). */\n const fitBox = (item: SceneItem): Size => {\n if (isFitAll()) return buildScene().size;\n return paged() ? { width: item.width, height: item.height } : buildScene().maxItemSize;\n };\n /** The clamp rect for a camera write targeting this item (the scene in continuous flow). */\n const boundsFor = (item: SceneItem): StageRect => (paged() ? itemRect(item) : sceneRect());\n /** The clamp rect for a write that stays put (pan, zoom): the slice item (paged) or the scene. */\n const stayBounds = (): StageRect => (paged() ? itemRect(buildScene().items[0]) : sceneRect());\n\n const constraint = (): CameraConstraint => ({\n bounded: state().bounded,\n padding: padding(),\n fitAlign: state().fitAlign,\n direction: state().direction,\n });\n\n const anchorAt = (at: Point): Anchor => {\n const scene = buildScene();\n return scene.itemCount\n ? anchorFromCamera(camera(), scene, viewport(), at)\n : { pageIndex: state().cursor, fx: 0.5, fy: 0 };\n };\n const currentAnchor = (): Anchor => anchorAt(anchorPoint());\n\n const indexOfPage = (page: PageRef): number => ctx.getPage(page)?.index ?? -1;\n /**\n * A page argument (a `PageRef` or a display index) as a display index, or\n * null when it names no page: a ref not in the document, or a number that\n * isn't a whole number. An index past either end is kept; arrivals clamp it.\n */\n const indexOfTarget = (page: PageRef | number): number | null => {\n if (typeof page === 'number') return Number.isInteger(page) ? page : null;\n const index = indexOfPage(page);\n return index >= 0 ? index : null;\n };\n\n return {\n camera,\n viewport,\n dpr,\n padding,\n paged,\n isFitAll,\n grouping,\n itemCountFull,\n itemIndexOfPage,\n worldPageFrame,\n buildScene,\n invalidate,\n cacheKey,\n sceneRect,\n itemRect,\n pageRectOf,\n cursorItem,\n worldRectForContent,\n fits,\n alignPoint,\n anchorPoint,\n fitBox,\n boundsFor,\n stayBounds,\n constraint,\n anchorAt,\n currentAnchor,\n indexOfPage,\n indexOfTarget,\n };\n}\nexport type StageScene = ReturnType<typeof createScene>;\n","/**\n * Plugin-private services every area is built on: the events, the host's\n * clock, the placement latch and the scene model.\n */\nimport type { PluginClock, PluginContext } from '@embedpdf/core';\n\nimport type { StageState } from '../model';\nimport { createEvents, type StageEvents } from './events';\nimport { createPlacementLatch, type PlacementLatch } from './placement-latch';\nimport { createScene, type StageScene } from './scene';\n\nexport interface StageServices {\n readonly events: StageEvents;\n /** Time, from the host (`ctx.clock`): the tweens, flings and the rest countdown run on it. */\n readonly clock: PluginClock;\n readonly placement: PlacementLatch;\n readonly scene: StageScene;\n}\n\nexport function createServices(ctx: PluginContext<StageState>): StageServices {\n return {\n events: createEvents(ctx),\n clock: ctx.clock,\n placement: createPlacementLatch(),\n scene: createScene(ctx),\n };\n}\n","/**\n * The settings bag and its responsive resolution. The base (config plus\n * `updateSettings()` changes) merged with the matching rules' patches is the effective\n * settings the state holds. `applySettings` is the one reactive applier: the\n * strongest effect among the touched settings wins ('reflow' ⊃ 'scene'/'refit'\n * ⊃ 'reclamp' ⊃ 'none'), so a breakpoint crossing gets exactly the invariant a\n * hand-written update would.\n */\nimport { memo, type PluginContext } from '@embedpdf/core';\n\nimport type {\n ResponsiveRule,\n StageConfig,\n StageSettings,\n StageSettingsPatch,\n StageViewState,\n} from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageCameraWrite } from '../camera/write';\nimport type { StageHostCapability } from '../host-contract';\nimport { patchSettings, setActiveRules, setCursor, type StageState } from '../model';\nimport type { StageArrival } from '../navigation/arrive';\nimport { boxOf, eqSetting, mergeSettings, resolveResponsive } from '../responsive';\nimport type { StageServices } from '../services';\nimport { DEFAULT_RESPONSIVE, pickSettings, SETTINGS_EFFECT, SETTING_KEYS } from '../settings';\nimport type { SettingEffect } from '../settings';\n\nconst EFFECT_RANK: Record<SettingEffect, number> = {\n none: 0,\n reclamp: 1,\n refit: 2,\n scene: 3,\n reflow: 4,\n};\n\nexport function createSettings(\n ctx: PluginContext<StageState>,\n { scene }: Pick<StageServices, 'scene'>,\n config: StageConfig,\n { writeCamera }: Pick<StageCameraWrite, 'writeCamera'>,\n { cancelAnimation }: Pick<StageAnimation, 'cancelAnimation'>,\n {\n applyAnchor,\n reapply,\n goToTarget,\n }: Pick<StageArrival, 'applyAnchor' | 'reapply' | 'goToTarget'>,\n) {\n const { camera, viewport, alignPoint, anchorAt } = scene;\n const state = () => ctx.state.get();\n\n // The same object while no setting changed, so readers compare by identity.\n const snapshotSettings: () => StageSettings = memo(\n () => SETTING_KEYS.map((key) => state()[key]),\n () => pickSettings(state()),\n );\n\n /**\n * React to a settings change per the registry: the strongest effect among\n * the touched settings wins. Both the public `updateSettings()` and the\n * responsive driver land here.\n */\n const applySettings = (patch: Partial<StageSettings>) => {\n cancelAnimation();\n const touched = (effect: SettingEffect) =>\n SETTING_KEYS.some((key) => patch[key] !== undefined && SETTINGS_EFFECT[key] === effect);\n // The change's invariant point: a pure zoom-intent change ('refit' alone)\n // holds the zoomAlign focal point, so zoomTo and fit-mode switches magnify\n // around the same spot the zoom buttons do; every other reframe holds the\n // anchorAlign reference. Resolved once, used for capture and restore.\n const align =\n touched('refit') && !touched('scene') && !touched('reflow')\n ? state().zoomAlign\n : state().anchorAlign;\n const anchor = anchorAt(alignPoint(align, viewport())); // captured against the current scene\n ctx.state.update(patchSettings, patch);\n if (touched('scene')) scene.invalidate();\n if (touched('reflow')) {\n // The flow toggled: re-place onto the cursor's page under the new\n // flow's scene (camera coordinates are meaningless across the flow\n // boundary).\n goToTarget(state().cursor, { behavior: 'instant' });\n } else if (touched('scene') || touched('refit')) {\n reapply(anchor, align); // rebuild, keep the page, re-fit (fit-all re-places the scene)\n } else if (touched('reclamp')) {\n writeCamera(camera()); // the clamp policy changed: re-clamp the current camera\n }\n // 'none' (arrivalAlign, zoomAlign, anchorAlign, scrollBehavior) guides future verbs only.\n };\n\n // ── responsive settings (container queries for the settings bag) ──\n // Rules assert at transitions (box, base or rules changes), which is why\n // the sync diffs against the last effective resolution, never against live\n // state: between crossings interaction owns the state (a pinch-zoomed level\n // survives a resize unless a rule actually flips), and keys the rules do\n // not touch are never re-asserted.\n let base = snapshotSettings();\n const initialBase = base;\n let rules: readonly ResponsiveRule[] = config.responsive ?? DEFAULT_RESPONSIVE;\n let lastEffective = base; // rules first assert when a real box arrives\n const publishActive = (active: readonly string[]) => {\n const current = state().activeRules;\n if (current.length !== active.length || active.some((name, index) => name !== current[index])) {\n ctx.state.update(setActiveRules, active);\n }\n };\n /**\n * Re-resolve and apply what changed since the last resolution. `react:\n * true` routes the patch through `applySettings` (the full\n * anchor-preserving update); `react: false` (inside `setViewportSize`,\n * whose caller runs its own reframe) only lands the patch and the cache\n * invalidation and reports the strongest effect, so the caller can\n * escalate a rule-driven flow flip.\n */\n const syncResponsive = (react: boolean): SettingEffect => {\n const { effective, active } = resolveResponsive(base, rules, boxOf(viewport()));\n const patch: Partial<StageSettings> = {};\n for (const key of SETTING_KEYS) {\n if (!eqSetting(effective[key], lastEffective[key])) {\n Object.assign(patch, { [key]: effective[key] });\n }\n }\n lastEffective = effective;\n publishActive(active);\n const keys = Object.keys(patch) as Array<keyof StageSettings>;\n if (keys.length === 0) return 'none';\n if (react) {\n applySettings(patch);\n return 'none'; // reacted in full: nothing left for the caller\n }\n ctx.state.update(patchSettings, patch);\n let strongest: SettingEffect = 'none';\n for (const key of keys) {\n if (EFFECT_RANK[SETTINGS_EFFECT[key]] > EFFECT_RANK[strongest]) {\n strongest = SETTINGS_EFFECT[key];\n }\n }\n if (strongest === 'scene' || strongest === 'reflow') scene.invalidate();\n return strongest;\n };\n\n const updateSettings = (changes: StageSettingsPatch): void => {\n // Writes the responsive base; the resolver decides what actually lands (a\n // matching rule's key wins until its rule stops matching). With no rules\n // in play this is a direct update.\n base = mergeSettings(base, changes);\n syncResponsive(true);\n };\n\n const applyViewState = (view: StageViewState): void => {\n cancelAnimation();\n // A restored view is app-level state: it writes the base, and the rules\n // re-assert on top, so a snapshot saved on a desktop restores compact\n // padding on a phone. One patch carries the full effective result.\n base = mergeSettings(base, pickSettings(view));\n const { effective, active } = resolveResponsive(base, rules, boxOf(viewport()));\n lastEffective = effective;\n publishActive(active);\n ctx.state.update(patchSettings, effective);\n ctx.state.update(setCursor, view.cursor ?? 0);\n scene.invalidate();\n applyAnchor(view.anchor);\n };\n\n return {\n snapshotSettings,\n syncResponsive,\n updateSettings,\n applyViewState,\n api: {\n getSettings: snapshotSettings,\n resetSettings: () => {\n base = mergeSettings(initialBase, {});\n syncResponsive(true);\n },\n updateSettings,\n setResponsiveRules: (next) => {\n rules = next;\n syncResponsive(true);\n },\n matchesRule: (name) => state().activeRules.includes(name),\n listActiveRules: () => state().activeRules,\n applyViewState,\n } satisfies Partial<StageHostCapability>,\n };\n}\nexport type StageSettingsArea = ReturnType<typeof createSettings>;\n","/**\n * The view lifecycle: the viewport report (initial placement is\n * level-triggered here, the moment the stage first learns a real size and the\n * document has pages), the device pixel ratio, initial-view providers resolved\n * once by priority, the refit after page-registry changes, and the view\n * memento reads.\n */\nimport type { PluginContext } from '@embedpdf/core';\n\nimport type { StageViewState } from '../contract';\nimport type { StageAnimation } from '../camera/animation';\nimport type { StageHostCapability } from '../host-contract';\nimport { markPlaced, setDpr, setViewport, type StageState } from '../model';\nimport type { StageArrival } from '../navigation/arrive';\nimport type { StageServices } from '../services';\nimport type { StageSettingsArea } from '../settings/settings';\n\ninterface InitialViewProvider {\n readonly priority: number;\n readonly provide: () => StageViewState | null;\n}\n\nexport function createViewLifecycle(\n ctx: PluginContext<StageState>,\n { scene, placement }: Pick<StageServices, 'scene' | 'placement'>,\n { cancelAnimation }: Pick<StageAnimation, 'cancelAnimation'>,\n arrive: Pick<StageArrival, 'goToTarget' | 'reapply' | 'resetView'>,\n settings: Pick<StageSettingsArea, 'snapshotSettings' | 'syncResponsive' | 'applyViewState'>,\n) {\n const { dpr, currentAnchor } = scene;\n const { goToTarget, reapply } = arrive;\n const { snapshotSettings, syncResponsive } = settings;\n const state = () => ctx.state.get();\n\n // Initial-view providers (a storage restore, a deep link, an explicit\n // prop). One owner, `placeInitial`, resolves them by priority, so there is\n // no ordering race between the providers.\n const initialViewProviders: InitialViewProvider[] = [];\n\n const placeInitial = (): void => {\n placement.started = true;\n const byPriority = [...initialViewProviders].sort(\n (left, right) => right.priority - left.priority,\n );\n let view: StageViewState | null = null;\n for (const provider of byPriority) {\n view = provider.provide();\n if (view) break;\n }\n if (view) settings.applyViewState(view);\n else arrive.resetView();\n // Navigation the app asked for before there was a viewport lands last,\n // from the initial view, so the first frame already shows it.\n const pending = placement.pending;\n placement.pending = null;\n pending?.();\n // Publish renderability last. The viewport, responsive and camera writes\n // above are ordinary observable state changes, but page and scroll reads\n // return stable empty values until this commit lands.\n ctx.state.update(markPlaced);\n };\n\n return {\n api: {\n setViewportSize: (size) => {\n // Initial placement is level-triggered here: the moment the stage\n // first learns a real size (both axes) and the document has pages,\n // resolve the initial view (providers, else a reset). Every report\n // re-checks the condition, so there is no edge to miss when the\n // viewport was sized before anyone listened.\n if (!placement.started) {\n ctx.state.update(setViewport, size);\n syncResponsive(false); // rules see the box before placement resolves\n if (size.width > 0 && size.height > 0 && (ctx.document()?.pageCount ?? 0) > 0) {\n placeInitial();\n }\n return;\n }\n // Afterwards a report with no area means the view isn't shown: a hidden tab, or an\n // element taken out of the page before its stage is torn down. There is nothing to fit\n // to, so the stage keeps its last real viewport and its view, and carries on from them\n // when it's shown again (as a browser keeps a hidden element's scroll position).\n if (size.width <= 0 || size.height <= 0) return;\n // A report of the size the stage already has says nothing new either. Hosts send\n // them (a ResizeObserver's first callback repeats the size reported at attach), and\n // treating one as a resize would cancel a navigation still animating, like a reveal\n // the app asked for as the view opened.\n const current = state().viewport;\n if (size.width === current.width && size.height === current.height) return;\n // Every real resize keeps the same page and re-resolves fit modes.\n cancelAnimation();\n const anchor = currentAnchor(); // measured against the old viewport\n ctx.state.update(setViewport, size);\n // A breakpoint crossing rides the same reframe: the rule patch lands\n // before the anchor is re-applied, so the restore resolves under the\n // new settings. Only a rule-driven flow flip escalates past reapply\n // (camera coordinates are meaningless across the flow boundary).\n const effect = syncResponsive(false);\n if (effect === 'reflow') {\n goToTarget(state().cursor, { behavior: 'instant' });\n } else {\n reapply(anchor);\n }\n },\n setDevicePixelRatio: (ratio) => {\n // A device-resolution change only affects each page transform's device\n // px (crispness) and sub-pixel box snapping, never the layout or the\n // camera: store it, and the visible pages re-key on dpr.\n if (ratio > 0 && ratio !== dpr()) ctx.state.update(setDpr, ratio);\n },\n refit: () => {\n // The page geometry changed underneath (rotate, move, delete). Treat\n // it like a viewport resize: re-resolve the zoom intent and re-place\n // against the current scene, keeping the anchored page-point. A no-op\n // before the first placement; the scene is keyed on the registry\n // revision, so `reapply` reads the new footprint.\n if (!placement.started) return;\n cancelAnimation();\n reapply(currentAnchor());\n },\n getViewState: (): StageViewState => ({\n ...snapshotSettings(),\n cursor: state().cursor,\n anchor: currentAnchor(),\n }),\n getLensId: () => ctx.id,\n provideInitialView: (priority, provide) => {\n const entry: InitialViewProvider = { priority, provide };\n initialViewProviders.push(entry);\n return () => {\n const index = initialViewProviders.indexOf(entry);\n if (index >= 0) initialViewProviders.splice(index, 1);\n };\n },\n placeInitial,\n } satisfies Partial<StageHostCapability>,\n };\n}\n","/**\n * The stage controller: the composition root. It builds the plugin's services\n * once (the events, the timing seam, the scene model), wires each area with\n * the services it declares, and assembles the host capability from the areas'\n * API slices. stage-core is the pure spatial math; the areas are the impure\n * shell that writes state, caches and drives motion, and time enters only\n * through the host's clock (`ctx.clock`).\n *\n * The camera model: every camera move is defined by what it holds fixed.\n * Gestures (pan, pinch, wheel) hold the page-point under the pointer;\n * navigation lands its target at the arrivalAlign point; positioned reveals\n * and restored viewpoints hold what the call specifies; pointer-less zooms\n * hold the zoomAlign point; reframes (resize, rotation, layout changes) hold\n * the anchorAlign point; and an axis the camera cannot travel rests at fitAlign.\n */\nimport { composeApi, type PluginContext } from '@embedpdf/core';\n\nimport { createAnimation } from './camera/animation';\nimport { createGestures } from './camera/gestures';\nimport { createCameraWrite } from './camera/write';\nimport { connectStage } from './connect';\nimport type { StageConfig } from './contract';\nimport type { StageHostCapability } from './host-contract';\nimport type { StageState } from './model';\nimport { createArrival } from './navigation/arrive';\nimport { createReveal } from './navigation/reveal';\nimport { createZoom } from './navigation/zoom';\nimport { createPageReads } from './read/pages';\nimport { createServices } from './services';\nimport { createSettings } from './settings/settings';\nimport { createViewLifecycle } from './view/lifecycle';\n\nexport function createStageController(\n ctx: PluginContext<StageState>,\n config: StageConfig = {},\n) {\n const services = createServices(ctx);\n const { events } = services;\n\n // Reads: pure projections of the scene and the camera.\n const reads = createPageReads(ctx, services);\n\n // The camera: the one write path, motion over the clock's frames, gestures.\n const write = createCameraWrite(ctx, services);\n const animation = createAnimation(services, write);\n const gestures = createGestures(ctx, services, write, animation, reads);\n\n // Navigation, settings, zoom and the view lifecycle.\n const arrive = createArrival(ctx, services, write, animation);\n const reveal = createReveal(ctx, services, write, animation, arrive);\n const settings = createSettings(ctx, services, config, write, animation, arrive);\n const zoom = createZoom(ctx, services, write, animation, gestures.api, settings);\n const view = createViewLifecycle(ctx, services, animation, arrive, settings);\n\n const api: StageHostCapability = composeApi('stage', [\n reads.api,\n animation.api,\n gestures.api,\n arrive.api,\n reveal.api,\n settings.api,\n zoom.api,\n view.api,\n {\n onPageChanged: events.pageChanged.on,\n onZoomChanged: events.zoomChanged.on,\n onCameraChanged: events.cameraChanged.on,\n onMotionEnded: events.motionEnded.on,\n onSettingsChanged: events.settingsChanged.on,\n onViewportChanged: events.viewportChanged.on,\n },\n ]);\n\n return {\n api,\n connect: () => connectStage(ctx, api),\n };\n}\n","import { createHostToken, definePlugin } from '@embedpdf/core';\nimport { ActionsToken } from '@embedpdf/plugin-actions/contract';\n\nimport { DEFAULT_LENS_ID } from './connect';\nimport type { StagePluginOptions } from './contract';\nimport { createStageController } from './controller';\nimport type { StageHostCapability } from './host-contract';\nimport { initialStageState } from './model';\nimport { StageToken } from './token';\n\n/**\n * The stage plugin: one lens's camera, layout, zoom and navigation over a\n * document. Document-scoped. The actions plugin is optional: with it, the\n * main lens feeds page state to it and interprets GoTo and Named page\n * actions. Pointer input is opted into by the surface binding\n * (`<Stage interaction>` / `createStageSurface`), which both forwards pointer\n * samples and registers this lens's scroll handler.\n */\nexport const stagePlugin = (options: StagePluginOptions = {}) => {\n const { id = DEFAULT_LENS_ID, token = StageToken, ...config } = options;\n return definePlugin({\n id,\n token: createHostToken<StageHostCapability>(token),\n scope: 'document',\n optional: [ActionsToken],\n state: () => initialStageState(config),\n create: (ctx) => createStageController(ctx, config),\n });\n};\n","/**\n * The Stage page's State table as code: what `useStageState()` returns, and\n * the same fields in every other framework. A second view registered with its\n * own token reads the same fields through its own capability.\n */\nimport { defineState } from '@embedpdf/core';\n\nimport { StageToken, ZoomMode } from './contract';\n\nexport const stageState = defineState(StageToken, {\n read: (stage) => ({\n zoomLevel: stage.getZoomLevel(),\n zoomMode: stage.getZoomMode(),\n currentPageIndex: stage.getCurrentPageIndex(),\n currentPage: stage.getCurrentPage(),\n pageCount: stage.getPageCount(),\n viewRotation: stage.getViewRotation(),\n activeRules: stage.listActiveRules(),\n }),\n empty: {\n zoomLevel: 1,\n zoomMode: ZoomMode.Automatic,\n currentPageIndex: 0,\n currentPage: null,\n pageCount: 0,\n viewRotation: 0,\n activeRules: [],\n },\n});\n","import type {\n InteractionHostCapability,\n InteractionHandler,\n} from '@embedpdf/plugin-interaction/contract/host';\nimport type { StageCapability } from './contract';\n\nexport interface ScrollHandlerOptions {\n /**\n * Let a drag over a page gap pan regardless of the active tool, and show a\n * grab cursor there, so the gutter always pans (outside a page there is\n * nothing to draw on or select). On-page behavior is untouched: the tool's\n * own gesture still owns page space. Default true.\n */\n panFallback?: boolean;\n}\n\n/**\n * Pan-the-camera as an interaction handler. Live under the built-in `pan` tool\n * (the `scroll` tag) and, with `panFallback`, under every tool, where it then\n * captures only page-gap drags (on-page downs belong to the active tool, which\n * claims them first at higher priority). It uses the sample's viewport delta,\n * so it pans over the whole viewport (pages and gaps).\n *\n * Cursors: a closed hand (`grabbing`) while dragging; an open hand (`grab`)\n * hovering a gap under a non-pan tool. The pan tool's own resting `grab` comes\n * from its `Tool.cursor`, so hovering it needs no claim here.\n */\nexport function createScrollHandler(\n stage: StageCapability,\n interaction: InteractionHostCapability,\n options: ScrollHandlerOptions = {},\n): InteractionHandler {\n const panFallback = options.panFallback ?? true;\n let last = { x: 0, y: 0 };\n const isPanTool = (): boolean => interaction.getActiveTool().enables.has('scroll');\n return {\n id: 'stage-scroll',\n priority: 10, // below page-aware handlers (selection, annotation), which claim first\n enabledFor: (tool) => tool.enables.has('scroll') || panFallback,\n onDown: (sample) => {\n // Fallback: a non-pan tool pans only over a gap. On a page, decline so the\n // tool's own (higher-priority) handler keeps the down it already captured.\n if (!isPanTool() && sample.page) return false;\n last = sample.viewport;\n interaction.claimCursor('stage-grab', 'grabbing', 40); // closed hand while panning\n return true; // capture the drag\n },\n onMove: (sample) => {\n stage.panBy(sample.viewport.x - last.x, sample.viewport.y - last.y);\n last = sample.viewport;\n },\n onUp: () => interaction.claimCursor('stage-grab', null),\n onHover: (sample) => {\n // An open hand over a gap when a non-pan tool would fall back to pan\n // there; cleared over a page (the tool's cursor shows). The pan tool\n // skips this: its resting `grab` is the tool cursor.\n if (panFallback && !isPanTool()) {\n interaction.claimCursor('stage-pan-fallback', sample.page ? null : 'grab', 5);\n }\n },\n };\n}\n"],"mappings":"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"}