@embedpdf/plugin-zoom 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +34 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +35 -19
- package/dist/index.js.map +1 -1
- package/dist/preact/index.cjs +7 -10
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.cts +3 -15
- package/dist/preact/index.d.ts +3 -15
- package/dist/preact/index.js +8 -11
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +7 -10
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +3 -15
- package/dist/react/index.d.ts +3 -15
- package/dist/react/index.js +8 -11
- package/dist/react/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
ZoomMode: () => ZoomMode,
|
|
26
26
|
ZoomPlugin: () => ZoomPlugin,
|
|
27
27
|
ZoomPluginPackage: () => ZoomPluginPackage,
|
|
28
|
+
initialState: () => initialState,
|
|
28
29
|
manifest: () => manifest
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -113,29 +114,25 @@ var manifest = {
|
|
|
113
114
|
value: "automatic" /* Automatic */
|
|
114
115
|
},
|
|
115
116
|
{
|
|
116
|
-
name: "
|
|
117
|
-
value: 0.
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: "20%",
|
|
121
|
-
value: 0.2
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
name: "30%",
|
|
125
|
-
value: 0.3
|
|
117
|
+
name: "25%",
|
|
118
|
+
value: 0.25
|
|
126
119
|
},
|
|
127
120
|
{
|
|
128
121
|
name: "50%",
|
|
129
122
|
value: 0.5
|
|
130
123
|
},
|
|
131
|
-
{
|
|
132
|
-
name: "70%",
|
|
133
|
-
value: 0.7
|
|
134
|
-
},
|
|
135
124
|
{
|
|
136
125
|
name: "100%",
|
|
137
126
|
value: 1
|
|
138
127
|
},
|
|
128
|
+
{
|
|
129
|
+
name: "125%",
|
|
130
|
+
value: 1.25
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "150%",
|
|
134
|
+
value: 1.5
|
|
135
|
+
},
|
|
139
136
|
{
|
|
140
137
|
name: "200%",
|
|
141
138
|
value: 2
|
|
@@ -143,6 +140,14 @@ var manifest = {
|
|
|
143
140
|
{
|
|
144
141
|
name: "400%",
|
|
145
142
|
value: 4
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "800%",
|
|
146
|
+
value: 8
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "1600%",
|
|
150
|
+
value: 16
|
|
146
151
|
}
|
|
147
152
|
]
|
|
148
153
|
}
|
|
@@ -167,8 +172,7 @@ function setInitialZoomLevel(zoomLevel) {
|
|
|
167
172
|
// src/lib/reducer.ts
|
|
168
173
|
var initialState = {
|
|
169
174
|
zoomLevel: "automatic" /* Automatic */,
|
|
170
|
-
currentZoomLevel: 1
|
|
171
|
-
zoomReady: false
|
|
175
|
+
currentZoomLevel: 1
|
|
172
176
|
};
|
|
173
177
|
var zoomReducer = (state = initialState, action) => {
|
|
174
178
|
switch (action.type) {
|
|
@@ -176,8 +180,7 @@ var zoomReducer = (state = initialState, action) => {
|
|
|
176
180
|
return {
|
|
177
181
|
...state,
|
|
178
182
|
zoomLevel: action.payload.zoomLevel,
|
|
179
|
-
currentZoomLevel: action.payload.currentZoomLevel
|
|
180
|
-
zoomReady: true
|
|
183
|
+
currentZoomLevel: action.payload.currentZoomLevel
|
|
181
184
|
};
|
|
182
185
|
case SET_INITIAL_ZOOM_LEVEL:
|
|
183
186
|
return {
|
|
@@ -199,6 +202,7 @@ var ZoomPlugin = class extends import_core.BasePlugin {
|
|
|
199
202
|
/* internals */
|
|
200
203
|
/* ------------------------------------------------------------------ */
|
|
201
204
|
this.zoom$ = (0, import_core.createEmitter)();
|
|
205
|
+
this.state$ = (0, import_core.createBehaviorEmitter)();
|
|
202
206
|
this.viewportPlugin = registry.getPlugin("viewport");
|
|
203
207
|
this.viewport = this.viewportPlugin.provides();
|
|
204
208
|
this.scroll = registry.getPlugin("scroll").provides();
|
|
@@ -231,6 +235,7 @@ var ZoomPlugin = class extends import_core.BasePlugin {
|
|
|
231
235
|
buildCapability() {
|
|
232
236
|
return {
|
|
233
237
|
onZoomChange: this.zoom$.on,
|
|
238
|
+
onStateChange: this.state$.on,
|
|
234
239
|
zoomIn: () => {
|
|
235
240
|
const cur = this.state.currentZoomLevel;
|
|
236
241
|
return this.handleRequest({ level: cur, delta: this.stepFor(cur) });
|
|
@@ -252,6 +257,13 @@ var ZoomPlugin = class extends import_core.BasePlugin {
|
|
|
252
257
|
disableMarqueeZoom: () => {
|
|
253
258
|
this.interactionManager?.activate("default");
|
|
254
259
|
},
|
|
260
|
+
toggleMarqueeZoom: () => {
|
|
261
|
+
if (this.interactionManager?.getActiveMode() === "marqueeZoom") {
|
|
262
|
+
this.interactionManager?.activate("default");
|
|
263
|
+
} else {
|
|
264
|
+
this.interactionManager?.activate("marqueeZoom");
|
|
265
|
+
}
|
|
266
|
+
},
|
|
255
267
|
isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === "marqueeZoom",
|
|
256
268
|
getState: () => this.state,
|
|
257
269
|
getPresets: () => this.presets
|
|
@@ -433,6 +445,9 @@ var ZoomPlugin = class extends import_core.BasePlugin {
|
|
|
433
445
|
if (s.zoomLevel === "automatic" /* Automatic */ || s.zoomLevel === "fit-page" /* FitPage */ || s.zoomLevel === "fit-width" /* FitWidth */)
|
|
434
446
|
this.handleRequest({ level: s.zoomLevel, focus });
|
|
435
447
|
}
|
|
448
|
+
onStoreUpdated(_prevState, newState) {
|
|
449
|
+
this.state$.emit(newState);
|
|
450
|
+
}
|
|
436
451
|
};
|
|
437
452
|
ZoomPlugin.id = "zoom";
|
|
438
453
|
|
|
@@ -450,6 +465,7 @@ var ZoomPluginPackage = {
|
|
|
450
465
|
ZoomMode,
|
|
451
466
|
ZoomPlugin,
|
|
452
467
|
ZoomPluginPackage,
|
|
468
|
+
initialState,
|
|
453
469
|
manifest
|
|
454
470
|
});
|
|
455
471
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/zoom-plugin.ts","../src/lib/index.ts"],"sourcesContent":["export * from './lib';\n","import { BasePluginConfig } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange(handler: (e: ZoomChangeEvent) => void): () => void;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n zoomReady: boolean; // whether the zoom is ready to be used\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager'],\n defaultConfig: {\n enabled: true,\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '10%',\n value: 0.1,\n },\n {\n name: '20%',\n value: 0.2,\n },\n {\n name: '30%',\n value: 0.3,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '70%',\n value: 0.7,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n zoomReady: false,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n zoomReady: true,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n };\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect } from '@embedpdf/models';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n /* ------------------------------------------------------------------ */\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n zoomIn: () => {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n },\n zoomOut: () => {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n },\n zoomToArea: (pageIndex, rect) => this.handleZoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activate('default');\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom */\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(pageIndex: number, rect: Rect) {\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n /* 1 – numeric zoom so the rect fits -------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rect.size.width, availableH / rect.size.height),\n );\n\n /* 2 — absolute page position in content coordinates --------------- */\n const layout = this.scroll.getLayout();\n\n // the VirtualItem that actually contains the requested page\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n // the page-layout _inside_ that virtual item\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* add the virtual-item's own offset to get absolute coords */\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n /* 3 — centre of the marquee in content space ---------------------- */\n const cxContent = pageAbsX + rect.origin.x + rect.size.width / 2;\n const cyContent = pageAbsY + rect.origin.y + rect.size.height / 2;\n\n /* 4 – viewport coords of that centre *before* zoom ----------------- */\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n /* 4 – reuse the generic handler ------------------------------------ */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, _engine, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"mappings":"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","names":["ZoomMode","VerticalZoomFocus","r"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/types.ts","../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/zoom-plugin.ts","../src/lib/index.ts"],"sourcesContent":["export * from './lib';\n","import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { Rect } from '@embedpdf/models';\nimport { ViewportMetrics } from '@embedpdf/plugin-viewport';\n\n/* ------------------------------------------------------------------ */\n/* public */\n/* ------------------------------------------------------------------ */\n\nexport enum ZoomMode {\n Automatic = 'automatic',\n FitPage = 'fit-page',\n FitWidth = 'fit-width',\n}\n\nexport type ZoomLevel = ZoomMode | number;\n\nexport interface Point {\n vx: number;\n vy: number;\n}\n\nexport interface ZoomChangeEvent {\n /** old and new *actual* scale factors */\n oldZoom: number;\n newZoom: number;\n\n /** level used to obtain the newZoom (number | mode) */\n level: ZoomLevel;\n\n /** viewport point kept under the finger / mouse‑wheel focus */\n center: Point;\n\n /** where the viewport should scroll to after the scale change */\n desiredScrollLeft: number;\n desiredScrollTop: number;\n\n /** metrics at the moment the zoom was requested */\n viewport: ViewportMetrics;\n}\n\nexport interface ZoomCapability {\n /** subscribe – returns the unsubscribe function */\n onZoomChange: EventHook<ZoomChangeEvent>;\n /** subscribe – returns the unsubscribe function */\n onStateChange: EventHook<ZoomState>;\n\n /** absolute requests -------------------------------------------------- */\n requestZoom(level: ZoomLevel, center?: Point): void;\n /** relative requests -------------------------------------------------- */\n requestZoomBy(delta: number, center?: Point): void;\n\n /** absolute requests -------------------------------------------------- */\n zoomIn(): void;\n zoomOut(): void;\n\n zoomToArea(pageIndex: number, rect: Rect): void;\n\n /** zoom in on an area -------------------------------------------------- */\n enableMarqueeZoom(): void;\n disableMarqueeZoom(): void;\n toggleMarqueeZoom(): void;\n isMarqueeZoomActive(): boolean;\n\n getState(): ZoomState;\n getPresets(): ZoomPreset[];\n}\n\n/* ------------------------------------------------------------------ */\n/* config / store */\n/* ------------------------------------------------------------------ */\n\nexport interface ZoomRangeStep {\n min: number;\n max: number;\n step: number;\n}\n\nexport interface ZoomPreset {\n name: string;\n value: ZoomLevel;\n icon?: string;\n}\n\nexport interface ZoomPluginConfig extends BasePluginConfig {\n defaultZoomLevel: ZoomLevel;\n minZoom?: number;\n maxZoom?: number;\n zoomStep?: number;\n zoomRanges?: ZoomRangeStep[]; // Define different step sizes for different zoom ranges\n presets?: ZoomPreset[]; // Preset zoom options for dropdown\n}\n\nexport interface ZoomState {\n zoomLevel: ZoomLevel; // last **requested** level\n currentZoomLevel: number; // actual numeric factor\n}\n\nexport enum VerticalZoomFocus {\n Center,\n Top,\n}\n\nexport interface ZoomRequest {\n level: ZoomLevel;\n delta?: number;\n center?: Point;\n focus?: VerticalZoomFocus;\n /** Scroll so that the focal point ends up …\n * ▸ `\"keep\"` (default) at the same viewport coords\n * ▸ `\"center\"` centred in the viewport */\n align?: 'keep' | 'center';\n}\n","import { PluginManifest } from '@embedpdf/core';\n\nimport { ZoomMode, ZoomPluginConfig } from './types';\n\nexport const ZOOM_PLUGIN_ID = 'zoom';\n\nexport const manifest: PluginManifest<ZoomPluginConfig> = {\n id: ZOOM_PLUGIN_ID,\n name: 'Zoom Plugin',\n version: '1.0.0',\n provides: ['zoom'],\n requires: ['viewport', 'scroll'],\n optional: ['interaction-manager'],\n defaultConfig: {\n enabled: true,\n defaultZoomLevel: ZoomMode.Automatic,\n minZoom: 0.2,\n maxZoom: 60,\n zoomStep: 0.1,\n zoomRanges: [\n {\n min: 0.2,\n max: 0.5,\n step: 0.05,\n },\n {\n min: 0.5,\n max: 1.0,\n step: 0.1,\n },\n {\n min: 1.0,\n max: 2.0,\n step: 0.2,\n },\n {\n min: 2.0,\n max: 4.0,\n step: 0.4,\n },\n {\n min: 4.0,\n max: 10.0,\n step: 0.8,\n },\n {\n min: 10.0,\n max: 20.0,\n step: 1.6,\n },\n {\n min: 20.0,\n max: 40.0,\n step: 3.2,\n },\n {\n min: 40.0,\n max: 60.0,\n step: 6.4,\n },\n ],\n presets: [\n {\n name: 'Fit Page',\n value: ZoomMode.FitPage,\n },\n {\n name: 'Fit Width',\n value: ZoomMode.FitWidth,\n },\n {\n name: 'Automatic',\n value: ZoomMode.Automatic,\n },\n {\n name: '25%',\n value: 0.25,\n },\n {\n name: '50%',\n value: 0.5,\n },\n {\n name: '100%',\n value: 1,\n },\n {\n name: '125%',\n value: 1.25,\n },\n {\n name: '150%',\n value: 1.5,\n },\n {\n name: '200%',\n value: 2,\n },\n {\n name: '400%',\n value: 4,\n },\n {\n name: '800%',\n value: 8,\n },\n {\n name: '1600%',\n value: 16,\n },\n ],\n },\n};\n","import { Action } from '@embedpdf/core';\n\nimport { ZoomLevel } from './types';\n\n// Action Types\nexport const SET_ZOOM_LEVEL = 'SET_ZOOM_LEVEL';\nexport const SET_INITIAL_ZOOM_LEVEL = 'SET_INITIAL_ZOOM_LEVEL';\n\n// Action Interfaces\nexport interface SetZoomLevelAction extends Action {\n type: typeof SET_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n currentZoomLevel: number;\n };\n}\n\nexport interface SetInitialZoomLevelAction extends Action {\n type: typeof SET_INITIAL_ZOOM_LEVEL;\n payload: {\n zoomLevel: ZoomLevel;\n };\n}\n\n// Union Type for All Actions\nexport type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;\n\n// Action Creators\nexport function setZoomLevel(zoomLevel: ZoomLevel, currentZoomLevel: number): SetZoomLevelAction {\n return {\n type: SET_ZOOM_LEVEL,\n payload: { zoomLevel, currentZoomLevel },\n };\n}\n\nexport function setInitialZoomLevel(zoomLevel: ZoomLevel): SetInitialZoomLevelAction {\n return {\n type: SET_INITIAL_ZOOM_LEVEL,\n payload: { zoomLevel },\n };\n}\n","import { Reducer } from '@embedpdf/core';\n\nimport { SET_INITIAL_ZOOM_LEVEL, SET_ZOOM_LEVEL, ZoomAction } from './actions';\nimport { ZoomState, ZoomMode } from './types';\n\nexport const initialState: ZoomState = {\n zoomLevel: ZoomMode.Automatic,\n currentZoomLevel: 1,\n};\n\nexport const zoomReducer: Reducer<ZoomState, ZoomAction> = (state = initialState, action) => {\n switch (action.type) {\n case SET_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n currentZoomLevel: action.payload.currentZoomLevel,\n };\n case SET_INITIAL_ZOOM_LEVEL:\n return {\n ...state,\n zoomLevel: action.payload.zoomLevel,\n };\n default:\n return state;\n }\n};\n","import {\n BasePlugin,\n PluginRegistry,\n createEmitter,\n clamp,\n setScale,\n SET_PAGES,\n SET_DOCUMENT,\n getPagesWithRotatedSize,\n SET_ROTATION,\n createBehaviorEmitter,\n} from '@embedpdf/core';\nimport { ScrollPlugin, ScrollCapability } from '@embedpdf/plugin-scroll';\nimport { ViewportPlugin, ViewportCapability, ViewportMetrics } from '@embedpdf/plugin-viewport';\n\nimport { setInitialZoomLevel, setZoomLevel, ZoomAction } from './actions';\nimport {\n ZoomPluginConfig,\n ZoomState,\n ZoomMode,\n Point,\n ZoomChangeEvent,\n ZoomCapability,\n ZoomPreset,\n ZoomRangeStep,\n VerticalZoomFocus,\n ZoomRequest,\n} from './types';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { Rect } from '@embedpdf/models';\n\nexport class ZoomPlugin extends BasePlugin<\n ZoomPluginConfig,\n ZoomCapability,\n ZoomState,\n ZoomAction\n> {\n static readonly id = 'zoom' as const;\n /* ------------------------------------------------------------------ */\n /* internals */\n /* ------------------------------------------------------------------ */\n private readonly zoom$ = createEmitter<ZoomChangeEvent>();\n private readonly state$ = createBehaviorEmitter<ZoomState>();\n private readonly viewport: ViewportCapability;\n private readonly viewportPlugin: ViewportPlugin;\n private readonly scroll: ScrollCapability;\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly presets: ZoomPreset[];\n private readonly zoomRanges: ZoomRangeStep[];\n\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private readonly zoomStep: number;\n\n /* ------------------------------------------------------------------ */\n constructor(id: string, registry: PluginRegistry, cfg: ZoomPluginConfig) {\n super(id, registry);\n\n this.viewportPlugin = registry.getPlugin<ViewportPlugin>('viewport')!;\n this.viewport = this.viewportPlugin.provides();\n this.scroll = registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n this.minZoom = cfg.minZoom ?? 0.25;\n this.maxZoom = cfg.maxZoom ?? 10;\n this.zoomStep = cfg.zoomStep ?? 0.1;\n this.presets = cfg.presets ?? [];\n this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);\n this.dispatch(setInitialZoomLevel(cfg.defaultZoomLevel));\n /* keep \"automatic\" modes up to date -------------------------------- */\n this.viewport.onViewportResize(() => this.recalcAuto(VerticalZoomFocus.Top), {\n mode: 'debounce',\n wait: 150,\n });\n this.coreStore.onAction(SET_ROTATION, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));\n this.interactionManager?.registerMode({\n id: 'marqueeZoom',\n scope: 'page',\n exclusive: true,\n cursor: 'zoom-in',\n });\n this.resetReady();\n }\n\n /* ------------------------------------------------------------------ */\n /* capability */\n /* ------------------------------------------------------------------ */\n protected buildCapability(): ZoomCapability {\n return {\n onZoomChange: this.zoom$.on,\n onStateChange: this.state$.on,\n zoomIn: () => {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: this.stepFor(cur) });\n },\n zoomOut: () => {\n const cur = this.state.currentZoomLevel;\n return this.handleRequest({ level: cur, delta: -this.stepFor(cur) });\n },\n zoomToArea: (pageIndex, rect) => this.handleZoomToArea(pageIndex, rect),\n requestZoom: (level, c) => this.handleRequest({ level, center: c }),\n requestZoomBy: (d, c) => {\n const cur = this.state.currentZoomLevel;\n const target = this.toZoom(cur + d);\n return this.handleRequest({ level: target, center: c });\n },\n enableMarqueeZoom: () => {\n this.interactionManager?.activate('marqueeZoom');\n },\n disableMarqueeZoom: () => {\n this.interactionManager?.activate('default');\n },\n toggleMarqueeZoom: () => {\n if (this.interactionManager?.getActiveMode() === 'marqueeZoom') {\n this.interactionManager?.activate('default');\n } else {\n this.interactionManager?.activate('marqueeZoom');\n }\n },\n isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === 'marqueeZoom',\n getState: () => this.state,\n getPresets: () => this.presets,\n };\n }\n\n /* ------------------------------------------------------------------ */\n /* plugin life‑cycle */\n /* ------------------------------------------------------------------ */\n async initialize(): Promise<void> {\n /* apply the initial zoom */\n }\n\n async destroy() {\n this.zoom$.clear();\n }\n\n /**\n * Sort ranges once, make sure they are sane\n */\n private normalizeRanges(ranges: ZoomRangeStep[]): ZoomRangeStep[] {\n return [...ranges]\n .filter((r) => r.step > 0 && r.max > r.min) // basic sanity\n .sort((a, b) => a.min - b.min);\n }\n\n /** pick the step that applies to a given numeric zoom */\n private stepFor(zoom: number): number {\n const r = this.zoomRanges.find((r) => zoom >= r.min && zoom < r.max);\n return r ? r.step : this.zoomStep; // fallback\n }\n\n /** clamp + round helper reused later */\n private toZoom(v: number) {\n return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));\n }\n\n /* ------------------------------------------------------------------ */\n /* main entry – handles **every** zoom request */\n /* ------------------------------------------------------------------ */\n private handleRequest({\n level,\n delta = 0,\n center,\n focus = VerticalZoomFocus.Center,\n align = 'keep',\n }: ZoomRequest) {\n const metrics = this.viewport.getMetrics();\n const oldZoom = this.state.currentZoomLevel;\n\n if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {\n return;\n }\n\n /* ------------------------------------------------------------------ */\n /* step 1 – resolve the **target numeric zoom** */\n /* ------------------------------------------------------------------ */\n const base = typeof level === 'number' ? level : this.computeZoomForMode(level, metrics);\n\n if (base === false) {\n return;\n }\n const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);\n const newZoom = Math.floor(exactZoom * 100) / 100;\n\n /* ------------------------------------------------------------------ */\n /* step 2 – figure out the viewport point we should keep under focus */\n /* ------------------------------------------------------------------ */\n const focusPoint: Point = center ?? {\n vx: metrics.clientWidth / 2,\n vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2,\n };\n\n /* ------------------------------------------------------------------ */\n /* step 3 – translate that into desired scroll offsets */\n /* ------------------------------------------------------------------ */\n const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(\n metrics,\n oldZoom,\n newZoom,\n focusPoint,\n align,\n );\n\n /* ------------------------------------------------------------------ */\n /* step 4 – dispatch + notify */\n /* ------------------------------------------------------------------ */\n\n if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {\n this.viewportPlugin.setViewportScrollMetrics({\n scrollLeft: desiredScrollLeft,\n scrollTop: desiredScrollTop,\n });\n }\n\n this.dispatch(setZoomLevel(typeof level === 'number' ? newZoom : level, newZoom));\n this.dispatchCoreAction(setScale(newZoom));\n this.markReady();\n\n this.viewport.scrollTo({\n x: desiredScrollLeft,\n y: desiredScrollTop,\n behavior: 'instant',\n });\n\n const evt: ZoomChangeEvent = {\n oldZoom,\n newZoom,\n level,\n center: focusPoint,\n desiredScrollLeft,\n desiredScrollTop,\n viewport: metrics,\n };\n\n this.zoom$.emit(evt);\n }\n\n /* ------------------------------------------------------------------ */\n /* helpers */\n /* ------------------------------------------------------------------ */\n\n /** numeric zoom for Automatic / FitPage / FitWidth */\n private computeZoomForMode(mode: ZoomMode, vp: ViewportMetrics): number | false {\n const spreads = getPagesWithRotatedSize(this.coreState.core);\n if (!spreads.length) return false;\n\n const pgGap = this.scroll.getPageGap();\n const vpGap = this.viewport.getViewportGap();\n\n if (vp.clientWidth === 0 || vp.clientHeight === 0) {\n return false;\n }\n\n // Available space after accounting for fixed viewport gaps\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n if (availableWidth <= 0 || availableHeight <= 0) {\n return false;\n }\n\n let maxContentW = 0,\n maxContentH = 0;\n\n spreads.forEach((spread) => {\n // Only include scalable content (pages + page gaps), not viewport gaps\n const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);\n const contentH = Math.max(...spread.map((p) => p.rotatedSize.height));\n maxContentW = Math.max(maxContentW, contentW);\n maxContentH = Math.max(maxContentH, contentH);\n });\n\n switch (mode) {\n case ZoomMode.FitWidth:\n return availableWidth / maxContentW;\n case ZoomMode.FitPage:\n return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);\n case ZoomMode.Automatic:\n return Math.min(availableWidth / maxContentW, 1);\n /* istanbul ignore next */\n default:\n return 1;\n }\n }\n\n /** where to scroll so that *focus* stays stable after scaling */\n private computeScrollForZoomChange(\n vp: ViewportMetrics,\n oldZoom: number,\n newZoom: number,\n focus: Point,\n align: 'keep' | 'center' = 'keep',\n ) {\n /* unscaled content size ------------------------------------------- */\n const layout = this.scroll.getLayout();\n const vpGap = this.viewport.getViewportGap();\n\n const contentW = layout.totalContentSize.width;\n const contentH = layout.totalContentSize.height;\n\n // Available space for content (excluding fixed viewport gaps)\n const availableWidth = vp.clientWidth - 2 * vpGap;\n const availableHeight = vp.clientHeight - 2 * vpGap;\n\n /* helper: offset if content is narrower than available space ------- */\n const off = (availableSpace: number, cw: number, zoom: number) =>\n cw * zoom < availableSpace ? (availableSpace - cw * zoom) / 2 : 0;\n\n const offXold = off(availableWidth, contentW, oldZoom);\n const offYold = off(availableHeight, contentH, oldZoom);\n\n const offXnew = off(availableWidth, contentW, newZoom);\n const offYnew = off(availableHeight, contentH, newZoom);\n\n /* content coords of the focal point -------------------------------- */\n // Adjust focus point to account for vpGap and centering offset\n const cx = (vp.scrollLeft + focus.vx - vpGap - offXold) / oldZoom;\n const cy = (vp.scrollTop + focus.vy - vpGap - offYold) / oldZoom;\n\n /* new scroll so that (cx,cy) appears under focus again ------------- */\n const baseLeft = cx * newZoom + vpGap + offXnew;\n const baseTop = cy * newZoom + vpGap + offYnew;\n\n const desiredScrollLeft =\n align === 'center' ? baseLeft - vp.clientWidth / 2 : baseLeft - focus.vx;\n const desiredScrollTop =\n align === 'center' ? baseTop - vp.clientHeight / 2 : baseTop - focus.vy;\n\n return {\n desiredScrollLeft: Math.max(0, desiredScrollLeft),\n desiredScrollTop: Math.max(0, desiredScrollTop),\n };\n }\n\n private handleZoomToArea(pageIndex: number, rect: Rect) {\n const vp = this.viewport.getMetrics();\n const vpGap = this.viewport.getViewportGap();\n const oldZ = this.state.currentZoomLevel;\n\n const availableW = vp.clientWidth - 2 * vpGap;\n const availableH = vp.clientHeight - 2 * vpGap;\n\n /* 1 – numeric zoom so the rect fits -------------------------------- */\n const targetZoom = this.toZoom(\n Math.min(availableW / rect.size.width, availableH / rect.size.height),\n );\n\n /* 2 — absolute page position in content coordinates --------------- */\n const layout = this.scroll.getLayout();\n\n // the VirtualItem that actually contains the requested page\n const vItem = layout.virtualItems.find((it) =>\n it.pageLayouts.some((p) => p.pageIndex === pageIndex),\n );\n if (!vItem) return;\n\n // the page-layout _inside_ that virtual item\n const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex)!;\n\n /* add the virtual-item's own offset to get absolute coords */\n const pageAbsX = vItem.x + pageRel.x;\n const pageAbsY = vItem.y + pageRel.y;\n\n /* 3 — centre of the marquee in content space ---------------------- */\n const cxContent = pageAbsX + rect.origin.x + rect.size.width / 2;\n const cyContent = pageAbsY + rect.origin.y + rect.size.height / 2;\n\n /* 4 – viewport coords of that centre *before* zoom ----------------- */\n const off = (avail: number, cw: number, z: number) =>\n cw * z < avail ? (avail - cw * z) / 2 : 0;\n\n const offXold = off(availableW, layout.totalContentSize.width, oldZ);\n const offYold = off(availableH, layout.totalContentSize.height, oldZ);\n\n const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;\n const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;\n\n /* 4 – reuse the generic handler ------------------------------------ */\n this.handleRequest({\n level: targetZoom,\n center: { vx: centerVX, vy: centerVY },\n align: 'center',\n });\n }\n\n /** recalculates Automatic / Fit* when viewport or pages change */\n private recalcAuto(focus?: VerticalZoomFocus) {\n const s = this.state;\n if (\n s.zoomLevel === ZoomMode.Automatic ||\n s.zoomLevel === ZoomMode.FitPage ||\n s.zoomLevel === ZoomMode.FitWidth\n )\n this.handleRequest({ level: s.zoomLevel, focus });\n }\n\n override onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void {\n this.state$.emit(newState);\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { ZoomAction } from './actions';\nimport { manifest, ZOOM_PLUGIN_ID } from './manifest';\nimport { zoomReducer, initialState } from './reducer';\nimport { ZoomPluginConfig, ZoomState } from './types';\nimport { ZoomPlugin } from './zoom-plugin';\n\nexport const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction> =\n {\n manifest,\n create: (registry, _engine, config) => new ZoomPlugin(ZOOM_PLUGIN_ID, registry, config),\n reducer: zoomReducer,\n initialState,\n };\n\nexport * from './zoom-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAK,WAAL,kBAAKA,cAAL;AACL,EAAAA,UAAA,eAAY;AACZ,EAAAA,UAAA,aAAU;AACV,EAAAA,UAAA,cAAW;AAHD,SAAAA;AAAA,GAAA;AAyFL,IAAK,oBAAL,kBAAKC,uBAAL;AACL,EAAAA,sCAAA;AACA,EAAAA,sCAAA;AAFU,SAAAA;AAAA,GAAA;;;AC7FL,IAAM,iBAAiB;AAEvB,IAAM,WAA6C;AAAA,EACxD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,MAAM;AAAA,EACjB,UAAU,CAAC,YAAY,QAAQ;AAAA,EAC/B,UAAU,CAAC,qBAAqB;AAAA,EAChC,eAAe;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,MACV;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;;;AC3GO,IAAM,iBAAiB;AACvB,IAAM,yBAAyB;AAsB/B,SAAS,aAAa,WAAsB,kBAA8C;AAC/F,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,EAAE,WAAW,iBAAiB;AAAA,EACzC;AACF;AAEO,SAAS,oBAAoB,WAAiD;AACnF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,EAAE,UAAU;AAAA,EACvB;AACF;;;ACnCO,IAAM,eAA0B;AAAA,EACrC;AAAA,EACA,kBAAkB;AACpB;AAEO,IAAM,cAA8C,CAAC,QAAQ,cAAc,WAAW;AAC3F,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW,OAAO,QAAQ;AAAA,QAC1B,kBAAkB,OAAO,QAAQ;AAAA,MACnC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW,OAAO,QAAQ;AAAA,MAC5B;AAAA,IACF;AACE,aAAO;AAAA,EACX;AACF;;;AC1BA,kBAWO;AAuBA,IAAM,aAAN,cAAyB,uBAK9B;AAAA;AAAA,EAmBA,YAAY,IAAY,UAA0B,KAAuB;AACvE,UAAM,IAAI,QAAQ;AAfpB;AAAA;AAAA;AAAA,SAAiB,YAAQ,2BAA+B;AACxD,SAAiB,aAAS,mCAAiC;AAgBzD,SAAK,iBAAiB,SAAS,UAA0B,UAAU;AACnE,SAAK,WAAW,KAAK,eAAe,SAAS;AAC7C,SAAK,SAAS,SAAS,UAAwB,QAAQ,EAAG,SAAS;AACnE,UAAM,qBAAqB,SAAS,UAAoC,qBAAqB;AAC7F,SAAK,qBAAqB,oBAAoB,SAAS,KAAK;AAC5D,SAAK,UAAU,IAAI,WAAW;AAC9B,SAAK,UAAU,IAAI,WAAW;AAC9B,SAAK,WAAW,IAAI,YAAY;AAChC,SAAK,UAAU,IAAI,WAAW,CAAC;AAC/B,SAAK,aAAa,KAAK,gBAAgB,IAAI,cAAc,CAAC,CAAC;AAC3D,SAAK,SAAS,oBAAoB,IAAI,gBAAgB,CAAC;AAEvD,SAAK,SAAS,iBAAiB,MAAM,KAAK,sBAAgC,GAAG;AAAA,MAC3E,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AACD,SAAK,UAAU,SAAS,0BAAc,MAAM,KAAK,sBAAgC,CAAC;AAClF,SAAK,UAAU,SAAS,uBAAW,MAAM,KAAK,sBAAgC,CAAC;AAC/E,SAAK,UAAU,SAAS,0BAAc,MAAM,KAAK,sBAAgC,CAAC;AAClF,SAAK,oBAAoB,aAAa;AAAA,MACpC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,WAAW;AAAA,MACX,QAAQ;AAAA,IACV,CAAC;AACD,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKU,kBAAkC;AAC1C,WAAO;AAAA,MACL,cAAc,KAAK,MAAM;AAAA,MACzB,eAAe,KAAK,OAAO;AAAA,MAC3B,QAAQ,MAAM;AACZ,cAAM,MAAM,KAAK,MAAM;AACvB,eAAO,KAAK,cAAc,EAAE,OAAO,KAAK,OAAO,KAAK,QAAQ,GAAG,EAAE,CAAC;AAAA,MACpE;AAAA,MACA,SAAS,MAAM;AACb,cAAM,MAAM,KAAK,MAAM;AACvB,eAAO,KAAK,cAAc,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,QAAQ,GAAG,EAAE,CAAC;AAAA,MACrE;AAAA,MACA,YAAY,CAAC,WAAW,SAAS,KAAK,iBAAiB,WAAW,IAAI;AAAA,MACtE,aAAa,CAAC,OAAO,MAAM,KAAK,cAAc,EAAE,OAAO,QAAQ,EAAE,CAAC;AAAA,MAClE,eAAe,CAAC,GAAG,MAAM;AACvB,cAAM,MAAM,KAAK,MAAM;AACvB,cAAM,SAAS,KAAK,OAAO,MAAM,CAAC;AAClC,eAAO,KAAK,cAAc,EAAE,OAAO,QAAQ,QAAQ,EAAE,CAAC;AAAA,MACxD;AAAA,MACA,mBAAmB,MAAM;AACvB,aAAK,oBAAoB,SAAS,aAAa;AAAA,MACjD;AAAA,MACA,oBAAoB,MAAM;AACxB,aAAK,oBAAoB,SAAS,SAAS;AAAA,MAC7C;AAAA,MACA,mBAAmB,MAAM;AACvB,YAAI,KAAK,oBAAoB,cAAc,MAAM,eAAe;AAC9D,eAAK,oBAAoB,SAAS,SAAS;AAAA,QAC7C,OAAO;AACL,eAAK,oBAAoB,SAAS,aAAa;AAAA,QACjD;AAAA,MACF;AAAA,MACA,qBAAqB,MAAM,KAAK,oBAAoB,cAAc,MAAM;AAAA,MACxE,UAAU,MAAM,KAAK;AAAA,MACrB,YAAY,MAAM,KAAK;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA4B;AAAA,EAElC;AAAA,EAEA,MAAM,UAAU;AACd,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,QAA0C;AAChE,WAAO,CAAC,GAAG,MAAM,EACd,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AAAA,EACjC;AAAA;AAAA,EAGQ,QAAQ,MAAsB;AACpC,UAAM,IAAI,KAAK,WAAW,KAAK,CAACC,OAAM,QAAQA,GAAE,OAAO,OAAOA,GAAE,GAAG;AACnE,WAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EAC3B;AAAA;AAAA,EAGQ,OAAO,GAAW;AACxB,WAAO,eAAW,mBAAM,GAAG,KAAK,SAAS,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc;AAAA,IACpB;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV,GAAgB;AACd,UAAM,UAAU,KAAK,SAAS,WAAW;AACzC,UAAM,UAAU,KAAK,MAAM;AAE3B,QAAI,QAAQ,gBAAgB,KAAK,QAAQ,iBAAiB,GAAG;AAC3D;AAAA,IACF;AAKA,UAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,mBAAmB,OAAO,OAAO;AAEvF,QAAI,SAAS,OAAO;AAClB;AAAA,IACF;AACA,UAAM,gBAAY,mBAAM,OAAO,OAAO,KAAK,SAAS,KAAK,OAAO;AAChE,UAAM,UAAU,KAAK,MAAM,YAAY,GAAG,IAAI;AAK9C,UAAM,aAAoB,UAAU;AAAA,MAClC,IAAI,QAAQ,cAAc;AAAA,MAC1B,IAAI,wBAAkC,IAAI,QAAQ,eAAe;AAAA,IACnE;AAKA,UAAM,EAAE,mBAAmB,iBAAiB,IAAI,KAAK;AAAA,MACnD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAMA,QAAI,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,gBAAgB,GAAG;AACzD,WAAK,eAAe,yBAAyB;AAAA,QAC3C,YAAY;AAAA,QACZ,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,SAAK,SAAS,aAAa,OAAO,UAAU,WAAW,UAAU,OAAO,OAAO,CAAC;AAChF,SAAK,uBAAmB,sBAAS,OAAO,CAAC;AACzC,SAAK,UAAU;AAEf,SAAK,SAAS,SAAS;AAAA,MACrB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,MAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ;AAEA,SAAK,MAAM,KAAK,GAAG;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAmB,MAAgB,IAAqC;AAC9E,UAAM,cAAU,qCAAwB,KAAK,UAAU,IAAI;AAC3D,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAE5B,UAAM,QAAQ,KAAK,OAAO,WAAW;AACrC,UAAM,QAAQ,KAAK,SAAS,eAAe;AAE3C,QAAI,GAAG,gBAAgB,KAAK,GAAG,iBAAiB,GAAG;AACjD,aAAO;AAAA,IACT;AAGA,UAAM,iBAAiB,GAAG,cAAc,IAAI;AAC5C,UAAM,kBAAkB,GAAG,eAAe,IAAI;AAE9C,QAAI,kBAAkB,KAAK,mBAAmB,GAAG;AAC/C,aAAO;AAAA,IACT;AAEA,QAAI,cAAc,GAChB,cAAc;AAEhB,YAAQ,QAAQ,CAAC,WAAW;AAE1B,YAAM,WAAW,OAAO,OAAO,CAAC,GAAG,GAAG,MAAM,IAAI,EAAE,YAAY,SAAS,IAAI,QAAQ,IAAI,CAAC;AACxF,YAAM,WAAW,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;AACpE,oBAAc,KAAK,IAAI,aAAa,QAAQ;AAC5C,oBAAc,KAAK,IAAI,aAAa,QAAQ;AAAA,IAC9C,CAAC;AAED,YAAQ,MAAM;AAAA,MACZ;AACE,eAAO,iBAAiB;AAAA,MAC1B;AACE,eAAO,KAAK,IAAI,iBAAiB,aAAa,kBAAkB,WAAW;AAAA,MAC7E;AACE,eAAO,KAAK,IAAI,iBAAiB,aAAa,CAAC;AAAA;AAAA,MAEjD;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAGQ,2BACN,IACA,SACA,SACA,OACA,QAA2B,QAC3B;AAEA,UAAM,SAAS,KAAK,OAAO,UAAU;AACrC,UAAM,QAAQ,KAAK,SAAS,eAAe;AAE3C,UAAM,WAAW,OAAO,iBAAiB;AACzC,UAAM,WAAW,OAAO,iBAAiB;AAGzC,UAAM,iBAAiB,GAAG,cAAc,IAAI;AAC5C,UAAM,kBAAkB,GAAG,eAAe,IAAI;AAG9C,UAAM,MAAM,CAAC,gBAAwB,IAAY,SAC/C,KAAK,OAAO,kBAAkB,iBAAiB,KAAK,QAAQ,IAAI;AAElE,UAAM,UAAU,IAAI,gBAAgB,UAAU,OAAO;AACrD,UAAM,UAAU,IAAI,iBAAiB,UAAU,OAAO;AAEtD,UAAM,UAAU,IAAI,gBAAgB,UAAU,OAAO;AACrD,UAAM,UAAU,IAAI,iBAAiB,UAAU,OAAO;AAItD,UAAM,MAAM,GAAG,aAAa,MAAM,KAAK,QAAQ,WAAW;AAC1D,UAAM,MAAM,GAAG,YAAY,MAAM,KAAK,QAAQ,WAAW;AAGzD,UAAM,WAAW,KAAK,UAAU,QAAQ;AACxC,UAAM,UAAU,KAAK,UAAU,QAAQ;AAEvC,UAAM,oBACJ,UAAU,WAAW,WAAW,GAAG,cAAc,IAAI,WAAW,MAAM;AACxE,UAAM,mBACJ,UAAU,WAAW,UAAU,GAAG,eAAe,IAAI,UAAU,MAAM;AAEvE,WAAO;AAAA,MACL,mBAAmB,KAAK,IAAI,GAAG,iBAAiB;AAAA,MAChD,kBAAkB,KAAK,IAAI,GAAG,gBAAgB;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,iBAAiB,WAAmB,MAAY;AACtD,UAAM,KAAK,KAAK,SAAS,WAAW;AACpC,UAAM,QAAQ,KAAK,SAAS,eAAe;AAC3C,UAAM,OAAO,KAAK,MAAM;AAExB,UAAM,aAAa,GAAG,cAAc,IAAI;AACxC,UAAM,aAAa,GAAG,eAAe,IAAI;AAGzC,UAAM,aAAa,KAAK;AAAA,MACtB,KAAK,IAAI,aAAa,KAAK,KAAK,OAAO,aAAa,KAAK,KAAK,MAAM;AAAA,IACtE;AAGA,UAAM,SAAS,KAAK,OAAO,UAAU;AAGrC,UAAM,QAAQ,OAAO,aAAa;AAAA,MAAK,CAAC,OACtC,GAAG,YAAY,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAAA,IACtD;AACA,QAAI,CAAC,MAAO;AAGZ,UAAM,UAAU,MAAM,YAAY,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAGvE,UAAM,WAAW,MAAM,IAAI,QAAQ;AACnC,UAAM,WAAW,MAAM,IAAI,QAAQ;AAGnC,UAAM,YAAY,WAAW,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ;AAC/D,UAAM,YAAY,WAAW,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS;AAGhE,UAAM,MAAM,CAAC,OAAe,IAAY,MACtC,KAAK,IAAI,SAAS,QAAQ,KAAK,KAAK,IAAI;AAE1C,UAAM,UAAU,IAAI,YAAY,OAAO,iBAAiB,OAAO,IAAI;AACnE,UAAM,UAAU,IAAI,YAAY,OAAO,iBAAiB,QAAQ,IAAI;AAEpE,UAAM,WAAW,QAAQ,UAAU,YAAY,OAAO,GAAG;AACzD,UAAM,WAAW,QAAQ,UAAU,YAAY,OAAO,GAAG;AAGzD,SAAK,cAAc;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ,EAAE,IAAI,UAAU,IAAI,SAAS;AAAA,MACrC,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,WAAW,OAA2B;AAC5C,UAAM,IAAI,KAAK;AACf,QACE,EAAE,6CACF,EAAE,0CACF,EAAE;AAEF,WAAK,cAAc,EAAE,OAAO,EAAE,WAAW,MAAM,CAAC;AAAA,EACpD;AAAA,EAES,eAAe,YAAuB,UAA2B;AACxE,SAAK,OAAO,KAAK,QAAQ;AAAA,EAC3B;AACF;AAlXa,WAMK,KAAK;;;AChChB,IAAM,oBACX;AAAA,EACE;AAAA,EACA,QAAQ,CAAC,UAAU,SAAS,WAAW,IAAI,WAAW,gBAAgB,UAAU,MAAM;AAAA,EACtF,SAAS;AAAA,EACT;AACF;","names":["ZoomMode","VerticalZoomFocus","r"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BasePluginConfig, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
|
|
1
|
+
import { BasePluginConfig, EventHook, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
|
|
2
2
|
import { Rect } from '@embedpdf/models';
|
|
3
3
|
import { ViewportMetrics } from '@embedpdf/plugin-viewport';
|
|
4
4
|
|
|
@@ -28,7 +28,9 @@ interface ZoomChangeEvent {
|
|
|
28
28
|
}
|
|
29
29
|
interface ZoomCapability {
|
|
30
30
|
/** subscribe – returns the unsubscribe function */
|
|
31
|
-
onZoomChange
|
|
31
|
+
onZoomChange: EventHook<ZoomChangeEvent>;
|
|
32
|
+
/** subscribe – returns the unsubscribe function */
|
|
33
|
+
onStateChange: EventHook<ZoomState>;
|
|
32
34
|
/** absolute requests -------------------------------------------------- */
|
|
33
35
|
requestZoom(level: ZoomLevel, center?: Point): void;
|
|
34
36
|
/** relative requests -------------------------------------------------- */
|
|
@@ -40,6 +42,7 @@ interface ZoomCapability {
|
|
|
40
42
|
/** zoom in on an area -------------------------------------------------- */
|
|
41
43
|
enableMarqueeZoom(): void;
|
|
42
44
|
disableMarqueeZoom(): void;
|
|
45
|
+
toggleMarqueeZoom(): void;
|
|
43
46
|
isMarqueeZoomActive(): boolean;
|
|
44
47
|
getState(): ZoomState;
|
|
45
48
|
getPresets(): ZoomPreset[];
|
|
@@ -65,7 +68,6 @@ interface ZoomPluginConfig extends BasePluginConfig {
|
|
|
65
68
|
interface ZoomState {
|
|
66
69
|
zoomLevel: ZoomLevel;
|
|
67
70
|
currentZoomLevel: number;
|
|
68
|
-
zoomReady: boolean;
|
|
69
71
|
}
|
|
70
72
|
declare enum VerticalZoomFocus {
|
|
71
73
|
Center = 0,
|
|
@@ -99,9 +101,12 @@ interface SetInitialZoomLevelAction extends Action {
|
|
|
99
101
|
}
|
|
100
102
|
type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;
|
|
101
103
|
|
|
104
|
+
declare const initialState: ZoomState;
|
|
105
|
+
|
|
102
106
|
declare class ZoomPlugin extends BasePlugin<ZoomPluginConfig, ZoomCapability, ZoomState, ZoomAction> {
|
|
103
107
|
static readonly id: "zoom";
|
|
104
108
|
private readonly zoom$;
|
|
109
|
+
private readonly state$;
|
|
105
110
|
private readonly viewport;
|
|
106
111
|
private readonly viewportPlugin;
|
|
107
112
|
private readonly scroll;
|
|
@@ -131,6 +136,7 @@ declare class ZoomPlugin extends BasePlugin<ZoomPluginConfig, ZoomCapability, Zo
|
|
|
131
136
|
private handleZoomToArea;
|
|
132
137
|
/** recalculates Automatic / Fit* when viewport or pages change */
|
|
133
138
|
private recalcAuto;
|
|
139
|
+
onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void;
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
declare const ZOOM_PLUGIN_ID = "zoom";
|
|
@@ -138,4 +144,4 @@ declare const manifest: PluginManifest<ZoomPluginConfig>;
|
|
|
138
144
|
|
|
139
145
|
declare const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction>;
|
|
140
146
|
|
|
141
|
-
export { type Point, VerticalZoomFocus, ZOOM_PLUGIN_ID, type ZoomCapability, type ZoomChangeEvent, type ZoomLevel, ZoomMode, ZoomPlugin, type ZoomPluginConfig, ZoomPluginPackage, type ZoomPreset, type ZoomRangeStep, type ZoomRequest, type ZoomState, manifest };
|
|
147
|
+
export { type Point, VerticalZoomFocus, ZOOM_PLUGIN_ID, type ZoomCapability, type ZoomChangeEvent, type ZoomLevel, ZoomMode, ZoomPlugin, type ZoomPluginConfig, ZoomPluginPackage, type ZoomPreset, type ZoomRangeStep, type ZoomRequest, type ZoomState, initialState, manifest };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BasePluginConfig, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
|
|
1
|
+
import { BasePluginConfig, EventHook, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
|
|
2
2
|
import { Rect } from '@embedpdf/models';
|
|
3
3
|
import { ViewportMetrics } from '@embedpdf/plugin-viewport';
|
|
4
4
|
|
|
@@ -28,7 +28,9 @@ interface ZoomChangeEvent {
|
|
|
28
28
|
}
|
|
29
29
|
interface ZoomCapability {
|
|
30
30
|
/** subscribe – returns the unsubscribe function */
|
|
31
|
-
onZoomChange
|
|
31
|
+
onZoomChange: EventHook<ZoomChangeEvent>;
|
|
32
|
+
/** subscribe – returns the unsubscribe function */
|
|
33
|
+
onStateChange: EventHook<ZoomState>;
|
|
32
34
|
/** absolute requests -------------------------------------------------- */
|
|
33
35
|
requestZoom(level: ZoomLevel, center?: Point): void;
|
|
34
36
|
/** relative requests -------------------------------------------------- */
|
|
@@ -40,6 +42,7 @@ interface ZoomCapability {
|
|
|
40
42
|
/** zoom in on an area -------------------------------------------------- */
|
|
41
43
|
enableMarqueeZoom(): void;
|
|
42
44
|
disableMarqueeZoom(): void;
|
|
45
|
+
toggleMarqueeZoom(): void;
|
|
43
46
|
isMarqueeZoomActive(): boolean;
|
|
44
47
|
getState(): ZoomState;
|
|
45
48
|
getPresets(): ZoomPreset[];
|
|
@@ -65,7 +68,6 @@ interface ZoomPluginConfig extends BasePluginConfig {
|
|
|
65
68
|
interface ZoomState {
|
|
66
69
|
zoomLevel: ZoomLevel;
|
|
67
70
|
currentZoomLevel: number;
|
|
68
|
-
zoomReady: boolean;
|
|
69
71
|
}
|
|
70
72
|
declare enum VerticalZoomFocus {
|
|
71
73
|
Center = 0,
|
|
@@ -99,9 +101,12 @@ interface SetInitialZoomLevelAction extends Action {
|
|
|
99
101
|
}
|
|
100
102
|
type ZoomAction = SetZoomLevelAction | SetInitialZoomLevelAction;
|
|
101
103
|
|
|
104
|
+
declare const initialState: ZoomState;
|
|
105
|
+
|
|
102
106
|
declare class ZoomPlugin extends BasePlugin<ZoomPluginConfig, ZoomCapability, ZoomState, ZoomAction> {
|
|
103
107
|
static readonly id: "zoom";
|
|
104
108
|
private readonly zoom$;
|
|
109
|
+
private readonly state$;
|
|
105
110
|
private readonly viewport;
|
|
106
111
|
private readonly viewportPlugin;
|
|
107
112
|
private readonly scroll;
|
|
@@ -131,6 +136,7 @@ declare class ZoomPlugin extends BasePlugin<ZoomPluginConfig, ZoomCapability, Zo
|
|
|
131
136
|
private handleZoomToArea;
|
|
132
137
|
/** recalculates Automatic / Fit* when viewport or pages change */
|
|
133
138
|
private recalcAuto;
|
|
139
|
+
onStoreUpdated(_prevState: ZoomState, newState: ZoomState): void;
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
declare const ZOOM_PLUGIN_ID = "zoom";
|
|
@@ -138,4 +144,4 @@ declare const manifest: PluginManifest<ZoomPluginConfig>;
|
|
|
138
144
|
|
|
139
145
|
declare const ZoomPluginPackage: PluginPackage<ZoomPlugin, ZoomPluginConfig, ZoomState, ZoomAction>;
|
|
140
146
|
|
|
141
|
-
export { type Point, VerticalZoomFocus, ZOOM_PLUGIN_ID, type ZoomCapability, type ZoomChangeEvent, type ZoomLevel, ZoomMode, ZoomPlugin, type ZoomPluginConfig, ZoomPluginPackage, type ZoomPreset, type ZoomRangeStep, type ZoomRequest, type ZoomState, manifest };
|
|
147
|
+
export { type Point, VerticalZoomFocus, ZOOM_PLUGIN_ID, type ZoomCapability, type ZoomChangeEvent, type ZoomLevel, ZoomMode, ZoomPlugin, type ZoomPluginConfig, ZoomPluginPackage, type ZoomPreset, type ZoomRangeStep, type ZoomRequest, type ZoomState, initialState, manifest };
|
package/dist/index.js
CHANGED
|
@@ -82,29 +82,25 @@ var manifest = {
|
|
|
82
82
|
value: "automatic" /* Automatic */
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
|
-
name: "
|
|
86
|
-
value: 0.
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "20%",
|
|
90
|
-
value: 0.2
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
name: "30%",
|
|
94
|
-
value: 0.3
|
|
85
|
+
name: "25%",
|
|
86
|
+
value: 0.25
|
|
95
87
|
},
|
|
96
88
|
{
|
|
97
89
|
name: "50%",
|
|
98
90
|
value: 0.5
|
|
99
91
|
},
|
|
100
|
-
{
|
|
101
|
-
name: "70%",
|
|
102
|
-
value: 0.7
|
|
103
|
-
},
|
|
104
92
|
{
|
|
105
93
|
name: "100%",
|
|
106
94
|
value: 1
|
|
107
95
|
},
|
|
96
|
+
{
|
|
97
|
+
name: "125%",
|
|
98
|
+
value: 1.25
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "150%",
|
|
102
|
+
value: 1.5
|
|
103
|
+
},
|
|
108
104
|
{
|
|
109
105
|
name: "200%",
|
|
110
106
|
value: 2
|
|
@@ -112,6 +108,14 @@ var manifest = {
|
|
|
112
108
|
{
|
|
113
109
|
name: "400%",
|
|
114
110
|
value: 4
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "800%",
|
|
114
|
+
value: 8
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "1600%",
|
|
118
|
+
value: 16
|
|
115
119
|
}
|
|
116
120
|
]
|
|
117
121
|
}
|
|
@@ -136,8 +140,7 @@ function setInitialZoomLevel(zoomLevel) {
|
|
|
136
140
|
// src/lib/reducer.ts
|
|
137
141
|
var initialState = {
|
|
138
142
|
zoomLevel: "automatic" /* Automatic */,
|
|
139
|
-
currentZoomLevel: 1
|
|
140
|
-
zoomReady: false
|
|
143
|
+
currentZoomLevel: 1
|
|
141
144
|
};
|
|
142
145
|
var zoomReducer = (state = initialState, action) => {
|
|
143
146
|
switch (action.type) {
|
|
@@ -145,8 +148,7 @@ var zoomReducer = (state = initialState, action) => {
|
|
|
145
148
|
return {
|
|
146
149
|
...state,
|
|
147
150
|
zoomLevel: action.payload.zoomLevel,
|
|
148
|
-
currentZoomLevel: action.payload.currentZoomLevel
|
|
149
|
-
zoomReady: true
|
|
151
|
+
currentZoomLevel: action.payload.currentZoomLevel
|
|
150
152
|
};
|
|
151
153
|
case SET_INITIAL_ZOOM_LEVEL:
|
|
152
154
|
return {
|
|
@@ -167,7 +169,8 @@ import {
|
|
|
167
169
|
SET_PAGES,
|
|
168
170
|
SET_DOCUMENT,
|
|
169
171
|
getPagesWithRotatedSize,
|
|
170
|
-
SET_ROTATION
|
|
172
|
+
SET_ROTATION,
|
|
173
|
+
createBehaviorEmitter
|
|
171
174
|
} from "@embedpdf/core";
|
|
172
175
|
var ZoomPlugin = class extends BasePlugin {
|
|
173
176
|
/* ------------------------------------------------------------------ */
|
|
@@ -177,6 +180,7 @@ var ZoomPlugin = class extends BasePlugin {
|
|
|
177
180
|
/* internals */
|
|
178
181
|
/* ------------------------------------------------------------------ */
|
|
179
182
|
this.zoom$ = createEmitter();
|
|
183
|
+
this.state$ = createBehaviorEmitter();
|
|
180
184
|
this.viewportPlugin = registry.getPlugin("viewport");
|
|
181
185
|
this.viewport = this.viewportPlugin.provides();
|
|
182
186
|
this.scroll = registry.getPlugin("scroll").provides();
|
|
@@ -209,6 +213,7 @@ var ZoomPlugin = class extends BasePlugin {
|
|
|
209
213
|
buildCapability() {
|
|
210
214
|
return {
|
|
211
215
|
onZoomChange: this.zoom$.on,
|
|
216
|
+
onStateChange: this.state$.on,
|
|
212
217
|
zoomIn: () => {
|
|
213
218
|
const cur = this.state.currentZoomLevel;
|
|
214
219
|
return this.handleRequest({ level: cur, delta: this.stepFor(cur) });
|
|
@@ -230,6 +235,13 @@ var ZoomPlugin = class extends BasePlugin {
|
|
|
230
235
|
disableMarqueeZoom: () => {
|
|
231
236
|
this.interactionManager?.activate("default");
|
|
232
237
|
},
|
|
238
|
+
toggleMarqueeZoom: () => {
|
|
239
|
+
if (this.interactionManager?.getActiveMode() === "marqueeZoom") {
|
|
240
|
+
this.interactionManager?.activate("default");
|
|
241
|
+
} else {
|
|
242
|
+
this.interactionManager?.activate("marqueeZoom");
|
|
243
|
+
}
|
|
244
|
+
},
|
|
233
245
|
isMarqueeZoomActive: () => this.interactionManager?.getActiveMode() === "marqueeZoom",
|
|
234
246
|
getState: () => this.state,
|
|
235
247
|
getPresets: () => this.presets
|
|
@@ -411,6 +423,9 @@ var ZoomPlugin = class extends BasePlugin {
|
|
|
411
423
|
if (s.zoomLevel === "automatic" /* Automatic */ || s.zoomLevel === "fit-page" /* FitPage */ || s.zoomLevel === "fit-width" /* FitWidth */)
|
|
412
424
|
this.handleRequest({ level: s.zoomLevel, focus });
|
|
413
425
|
}
|
|
426
|
+
onStoreUpdated(_prevState, newState) {
|
|
427
|
+
this.state$.emit(newState);
|
|
428
|
+
}
|
|
414
429
|
};
|
|
415
430
|
ZoomPlugin.id = "zoom";
|
|
416
431
|
|
|
@@ -427,6 +442,7 @@ export {
|
|
|
427
442
|
ZoomMode,
|
|
428
443
|
ZoomPlugin,
|
|
429
444
|
ZoomPluginPackage,
|
|
445
|
+
initialState,
|
|
430
446
|
manifest
|
|
431
447
|
};
|
|
432
448
|
//# sourceMappingURL=index.js.map
|