@embedpdf/plugin-zoom 1.4.1 → 2.0.0-next.0
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/hammer-DhVzwxwy.cjs +7 -0
- package/dist/{hammer-Bs-QCG8V.cjs.map → hammer-DhVzwxwy.cjs.map} +1 -1
- package/dist/hammer-e1aXHboh.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +342 -158
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +32 -9
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/reducer.d.ts +2 -1
- package/dist/lib/types.d.ts +32 -16
- package/dist/lib/zoom-plugin.d.ts +22 -15
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +47 -26
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +47 -26
- package/dist/react/index.js.map +1 -1
- package/dist/shared/components/marquee-zoom.d.ts +3 -6
- package/dist/shared/components/pinch-wrapper.d.ts +2 -1
- package/dist/shared/hooks/use-pinch-zoom.d.ts +1 -1
- package/dist/shared/hooks/use-zoom.d.ts +8 -4
- package/dist/shared/utils/pinch-zoom-logic.d.ts +2 -1
- package/dist/shared-preact/components/marquee-zoom.d.ts +3 -6
- package/dist/shared-preact/components/pinch-wrapper.d.ts +2 -1
- package/dist/shared-preact/hooks/use-pinch-zoom.d.ts +1 -1
- package/dist/shared-preact/hooks/use-zoom.d.ts +8 -4
- package/dist/shared-preact/utils/pinch-zoom-logic.d.ts +2 -1
- package/dist/shared-react/components/marquee-zoom.d.ts +3 -6
- package/dist/shared-react/components/pinch-wrapper.d.ts +2 -1
- package/dist/shared-react/hooks/use-pinch-zoom.d.ts +1 -1
- package/dist/shared-react/hooks/use-zoom.d.ts +8 -4
- package/dist/shared-react/utils/pinch-zoom-logic.d.ts +2 -1
- package/dist/shared-svelte/utils/pinch-zoom-logic.d.ts +2 -1
- package/dist/shared-vue/utils/pinch-zoom-logic.d.ts +2 -1
- package/dist/svelte/components/MarqueeZoom.svelte.d.ts +3 -1
- package/dist/svelte/components/PinchWrapper.svelte.d.ts +1 -0
- package/dist/svelte/hooks/use-pinch-zoom.svelte.d.ts +5 -1
- package/dist/svelte/hooks/use-zoom.svelte.d.ts +11 -5
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.js +108 -53
- package/dist/svelte/index.js.map +1 -1
- package/dist/vue/components/marquee-zoom.vue.d.ts +5 -2
- package/dist/vue/components/pinch-wrapper.vue.d.ts +6 -2
- package/dist/vue/hooks/use-pinch-zoom.d.ts +6 -1
- package/dist/vue/hooks/use-zoom.d.ts +17 -10
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +99 -58
- package/dist/vue/index.js.map +1 -1
- package/package.json +10 -10
- package/dist/hammer-Bs-QCG8V.cjs +0 -7
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clamp, BasePlugin, createEmitter, createBehaviorEmitter,
|
|
1
|
+
import { clamp, BasePlugin, createEmitter, createBehaviorEmitter, setScale } from "@embedpdf/core";
|
|
2
2
|
import { rotateRect } from "@embedpdf/models";
|
|
3
3
|
var ZoomMode = /* @__PURE__ */ ((ZoomMode2) => {
|
|
4
4
|
ZoomMode2["Automatic"] = "automatic";
|
|
@@ -18,7 +18,7 @@ const manifest = {
|
|
|
18
18
|
version: "1.0.0",
|
|
19
19
|
provides: ["zoom"],
|
|
20
20
|
requires: ["viewport", "scroll"],
|
|
21
|
-
optional: ["interaction-manager"],
|
|
21
|
+
optional: ["interaction-manager", "spread"],
|
|
22
22
|
defaultConfig: {
|
|
23
23
|
enabled: true,
|
|
24
24
|
defaultZoomLevel: ZoomMode.Automatic,
|
|
@@ -119,37 +119,92 @@ const manifest = {
|
|
|
119
119
|
]
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
};
|
|
122
|
+
const INIT_ZOOM_STATE = "ZOOM/INIT_STATE";
|
|
123
|
+
const CLEANUP_ZOOM_STATE = "ZOOM/CLEANUP_STATE";
|
|
124
|
+
const SET_ACTIVE_DOCUMENT = "ZOOM/SET_ACTIVE_DOCUMENT";
|
|
125
|
+
const SET_ZOOM_LEVEL = "ZOOM/SET_ZOOM_LEVEL";
|
|
126
|
+
const SET_MARQUEE_ZOOM_ACTIVE = "ZOOM/SET_MARQUEE_ZOOM_ACTIVE";
|
|
127
|
+
function initZoomState(documentId, state) {
|
|
128
|
+
return { type: INIT_ZOOM_STATE, payload: { documentId, state } };
|
|
129
129
|
}
|
|
130
|
-
function
|
|
131
|
-
return {
|
|
132
|
-
type: SET_INITIAL_ZOOM_LEVEL,
|
|
133
|
-
payload: { zoomLevel }
|
|
134
|
-
};
|
|
130
|
+
function cleanupZoomState(documentId) {
|
|
131
|
+
return { type: CLEANUP_ZOOM_STATE, payload: documentId };
|
|
135
132
|
}
|
|
136
|
-
|
|
133
|
+
function setZoomLevel(documentId, zoomLevel, currentZoomLevel) {
|
|
134
|
+
return { type: SET_ZOOM_LEVEL, payload: { documentId, zoomLevel, currentZoomLevel } };
|
|
135
|
+
}
|
|
136
|
+
function setMarqueeZoomActive(documentId, isActive) {
|
|
137
|
+
return { type: SET_MARQUEE_ZOOM_ACTIVE, payload: { documentId, isActive } };
|
|
138
|
+
}
|
|
139
|
+
const initialDocumentState = {
|
|
137
140
|
zoomLevel: ZoomMode.Automatic,
|
|
138
|
-
currentZoomLevel: 1
|
|
141
|
+
currentZoomLevel: 1,
|
|
142
|
+
isMarqueeZoomActive: false
|
|
143
|
+
};
|
|
144
|
+
const initialState = {
|
|
145
|
+
documents: {},
|
|
146
|
+
activeDocumentId: null
|
|
139
147
|
};
|
|
140
148
|
const zoomReducer = (state = initialState, action) => {
|
|
141
149
|
switch (action.type) {
|
|
142
|
-
case
|
|
150
|
+
case INIT_ZOOM_STATE: {
|
|
151
|
+
const { documentId, state: docState } = action.payload;
|
|
143
152
|
return {
|
|
144
153
|
...state,
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
documents: {
|
|
155
|
+
...state.documents,
|
|
156
|
+
[documentId]: docState
|
|
157
|
+
},
|
|
158
|
+
// Set as active if no active document
|
|
159
|
+
activeDocumentId: state.activeDocumentId ?? documentId
|
|
147
160
|
};
|
|
148
|
-
|
|
161
|
+
}
|
|
162
|
+
case CLEANUP_ZOOM_STATE: {
|
|
163
|
+
const documentId = action.payload;
|
|
164
|
+
const { [documentId]: removed, ...remainingDocs } = state.documents;
|
|
149
165
|
return {
|
|
150
166
|
...state,
|
|
151
|
-
|
|
167
|
+
documents: remainingDocs,
|
|
168
|
+
activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId
|
|
152
169
|
};
|
|
170
|
+
}
|
|
171
|
+
case SET_ACTIVE_DOCUMENT: {
|
|
172
|
+
return {
|
|
173
|
+
...state,
|
|
174
|
+
activeDocumentId: action.payload
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
case SET_ZOOM_LEVEL: {
|
|
178
|
+
const { documentId, zoomLevel, currentZoomLevel } = action.payload;
|
|
179
|
+
const docState = state.documents[documentId];
|
|
180
|
+
if (!docState) return state;
|
|
181
|
+
return {
|
|
182
|
+
...state,
|
|
183
|
+
documents: {
|
|
184
|
+
...state.documents,
|
|
185
|
+
[documentId]: {
|
|
186
|
+
...docState,
|
|
187
|
+
zoomLevel,
|
|
188
|
+
currentZoomLevel
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
case SET_MARQUEE_ZOOM_ACTIVE: {
|
|
194
|
+
const { documentId, isActive } = action.payload;
|
|
195
|
+
const docState = state.documents[documentId];
|
|
196
|
+
if (!docState) return state;
|
|
197
|
+
return {
|
|
198
|
+
...state,
|
|
199
|
+
documents: {
|
|
200
|
+
...state.documents,
|
|
201
|
+
[documentId]: {
|
|
202
|
+
...docState,
|
|
203
|
+
isMarqueeZoomActive: isActive
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
153
208
|
default:
|
|
154
209
|
return state;
|
|
155
210
|
}
|
|
@@ -201,9 +256,8 @@ function createMarqueeHandler(opts) {
|
|
|
201
256
|
};
|
|
202
257
|
}
|
|
203
258
|
const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
204
|
-
/* ------------------------------------------------------------------ */
|
|
205
259
|
constructor(id, registry, cfg) {
|
|
206
|
-
var _a;
|
|
260
|
+
var _a, _b, _c;
|
|
207
261
|
super(id, registry);
|
|
208
262
|
this.zoom$ = createEmitter();
|
|
209
263
|
this.state$ = createBehaviorEmitter();
|
|
@@ -212,129 +266,215 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
212
266
|
this.scroll = registry.getPlugin("scroll").provides();
|
|
213
267
|
const interactionManager = registry.getPlugin("interaction-manager");
|
|
214
268
|
this.interactionManager = (interactionManager == null ? void 0 : interactionManager.provides()) ?? null;
|
|
269
|
+
const spread = registry.getPlugin("spread");
|
|
270
|
+
this.spread = (spread == null ? void 0 : spread.provides()) ?? null;
|
|
215
271
|
this.minZoom = cfg.minZoom ?? 0.25;
|
|
216
272
|
this.maxZoom = cfg.maxZoom ?? 10;
|
|
217
273
|
this.zoomStep = cfg.zoomStep ?? 0.1;
|
|
274
|
+
this.defaultZoomLevel = cfg.defaultZoomLevel;
|
|
218
275
|
this.presets = cfg.presets ?? [];
|
|
219
276
|
this.zoomRanges = this.normalizeRanges(cfg.zoomRanges ?? []);
|
|
220
|
-
this.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
277
|
+
this.viewport.onViewportResize(
|
|
278
|
+
(event) => this.recalcAuto(event.documentId, VerticalZoomFocus.Top),
|
|
279
|
+
{
|
|
280
|
+
mode: "debounce",
|
|
281
|
+
wait: 150,
|
|
282
|
+
keyExtractor: (event) => event.documentId
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
(_a = this.spread) == null ? void 0 : _a.onSpreadChange((event) => {
|
|
286
|
+
this.recalcAuto(event.documentId, VerticalZoomFocus.Top);
|
|
224
287
|
});
|
|
225
|
-
this.
|
|
226
|
-
this.coreStore.onAction(SET_PAGES, () => this.recalcAuto(VerticalZoomFocus.Top));
|
|
227
|
-
this.coreStore.onAction(SET_DOCUMENT, () => this.recalcAuto(VerticalZoomFocus.Top));
|
|
228
|
-
(_a = this.interactionManager) == null ? void 0 : _a.registerMode({
|
|
288
|
+
(_b = this.interactionManager) == null ? void 0 : _b.registerMode({
|
|
229
289
|
id: "marqueeZoom",
|
|
230
290
|
scope: "page",
|
|
231
291
|
exclusive: true,
|
|
232
292
|
cursor: "zoom-in"
|
|
233
293
|
});
|
|
234
|
-
this.
|
|
294
|
+
(_c = this.interactionManager) == null ? void 0 : _c.onModeChange((state) => {
|
|
295
|
+
const isMarqueeActive = state.activeMode === "marqueeZoom";
|
|
296
|
+
const docState = this.getDocumentState(state.documentId);
|
|
297
|
+
if (docState && docState.isMarqueeZoomActive !== isMarqueeActive) {
|
|
298
|
+
this.dispatch(setMarqueeZoomActive(state.documentId, isMarqueeActive));
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
// ─────────────────────────────────────────────────────────
|
|
303
|
+
// Document Lifecycle Hooks (from BasePlugin)
|
|
304
|
+
// ─────────────────────────────────────────────────────────
|
|
305
|
+
onDocumentLoadingStarted(documentId) {
|
|
306
|
+
this.viewport.gate("zoom", documentId);
|
|
307
|
+
const docState = {
|
|
308
|
+
...initialDocumentState,
|
|
309
|
+
zoomLevel: this.defaultZoomLevel
|
|
310
|
+
};
|
|
311
|
+
this.dispatch(initZoomState(documentId, docState));
|
|
312
|
+
this.logger.debug(
|
|
313
|
+
"ZoomPlugin",
|
|
314
|
+
"DocumentOpened",
|
|
315
|
+
`Initialized zoom state for document: ${documentId}`
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
onDocumentLoaded(documentId) {
|
|
319
|
+
this.recalcAuto(documentId, VerticalZoomFocus.Top);
|
|
320
|
+
}
|
|
321
|
+
onDocumentClosed(documentId) {
|
|
322
|
+
this.dispatch(cleanupZoomState(documentId));
|
|
323
|
+
this.logger.debug(
|
|
324
|
+
"ZoomPlugin",
|
|
325
|
+
"DocumentClosed",
|
|
326
|
+
`Cleaned up zoom state for document: ${documentId}`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
onRotationChanged(documentId) {
|
|
330
|
+
this.recalcAuto(documentId, VerticalZoomFocus.Top);
|
|
235
331
|
}
|
|
236
|
-
/*
|
|
237
|
-
|
|
238
|
-
|
|
332
|
+
/*
|
|
333
|
+
protected override onPagesChanged(documentId: string): void {
|
|
334
|
+
// Recalculate auto modes when pages change
|
|
335
|
+
this.recalcAuto(documentId, VerticalZoomFocus.Top);
|
|
336
|
+
}*/
|
|
337
|
+
// ─────────────────────────────────────────────────────────
|
|
338
|
+
// Capability
|
|
339
|
+
// ─────────────────────────────────────────────────────────
|
|
239
340
|
buildCapability() {
|
|
240
341
|
return {
|
|
241
|
-
|
|
242
|
-
|
|
342
|
+
// Active document operations
|
|
343
|
+
requestZoom: (level, c) => this.requestZoom(level, c),
|
|
344
|
+
requestZoomBy: (d, c) => this.requestZoomBy(d, c),
|
|
243
345
|
zoomIn: () => this.zoomIn(),
|
|
244
346
|
zoomOut: () => this.zoomOut(),
|
|
245
347
|
zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect),
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
(_a = this.interactionManager) == null ? void 0 : _a.activate("marqueeZoom");
|
|
255
|
-
},
|
|
256
|
-
disableMarqueeZoom: () => {
|
|
257
|
-
var _a;
|
|
258
|
-
(_a = this.interactionManager) == null ? void 0 : _a.activateDefaultMode();
|
|
259
|
-
},
|
|
260
|
-
toggleMarqueeZoom: () => {
|
|
261
|
-
var _a, _b, _c;
|
|
262
|
-
if (((_a = this.interactionManager) == null ? void 0 : _a.getActiveMode()) === "marqueeZoom") {
|
|
263
|
-
(_b = this.interactionManager) == null ? void 0 : _b.activateDefaultMode();
|
|
264
|
-
} else {
|
|
265
|
-
(_c = this.interactionManager) == null ? void 0 : _c.activate("marqueeZoom");
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
isMarqueeZoomActive: () => {
|
|
269
|
-
var _a;
|
|
270
|
-
return ((_a = this.interactionManager) == null ? void 0 : _a.getActiveMode()) === "marqueeZoom";
|
|
271
|
-
},
|
|
348
|
+
enableMarqueeZoom: () => this.enableMarqueeZoom(),
|
|
349
|
+
disableMarqueeZoom: () => this.disableMarqueeZoom(),
|
|
350
|
+
toggleMarqueeZoom: () => this.toggleMarqueeZoom(),
|
|
351
|
+
isMarqueeZoomActive: () => this.isMarqueeZoomActive(),
|
|
352
|
+
getState: () => this.getDocumentStateOrThrow(),
|
|
353
|
+
// Document-scoped operations
|
|
354
|
+
forDocument: (documentId) => this.createZoomScope(documentId),
|
|
355
|
+
// Global
|
|
272
356
|
registerMarqueeOnPage: (opts) => this.registerMarqueeOnPage(opts),
|
|
273
|
-
|
|
274
|
-
|
|
357
|
+
getPresets: () => this.presets,
|
|
358
|
+
// Events
|
|
359
|
+
onZoomChange: this.zoom$.on,
|
|
360
|
+
onStateChange: this.state$.on
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
// ─────────────────────────────────────────────────────────
|
|
364
|
+
// Document Scoping
|
|
365
|
+
// ─────────────────────────────────────────────────────────
|
|
366
|
+
createZoomScope(documentId) {
|
|
367
|
+
return {
|
|
368
|
+
requestZoom: (level, c) => this.requestZoom(level, c, documentId),
|
|
369
|
+
requestZoomBy: (d, c) => this.requestZoomBy(d, c, documentId),
|
|
370
|
+
zoomIn: () => this.zoomIn(documentId),
|
|
371
|
+
zoomOut: () => this.zoomOut(documentId),
|
|
372
|
+
zoomToArea: (pageIndex, rect) => this.zoomToArea(pageIndex, rect, documentId),
|
|
373
|
+
enableMarqueeZoom: () => this.enableMarqueeZoom(documentId),
|
|
374
|
+
disableMarqueeZoom: () => this.disableMarqueeZoom(documentId),
|
|
375
|
+
toggleMarqueeZoom: () => this.toggleMarqueeZoom(documentId),
|
|
376
|
+
isMarqueeZoomActive: () => this.isMarqueeZoomActive(documentId),
|
|
377
|
+
getState: () => this.getDocumentStateOrThrow(documentId),
|
|
378
|
+
onZoomChange: (listener) => this.zoom$.on((event) => {
|
|
379
|
+
if (event.documentId === documentId) listener(event);
|
|
380
|
+
}),
|
|
381
|
+
onStateChange: (listener) => this.state$.on((event) => {
|
|
382
|
+
if (event.documentId === documentId) listener(event.state);
|
|
383
|
+
})
|
|
275
384
|
};
|
|
276
385
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
386
|
+
// ─────────────────────────────────────────────────────────
|
|
387
|
+
// State Helpers
|
|
388
|
+
// ─────────────────────────────────────────────────────────
|
|
389
|
+
getDocumentState(documentId) {
|
|
390
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
391
|
+
return this.state.documents[id] ?? null;
|
|
280
392
|
}
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
393
|
+
getDocumentStateOrThrow(documentId) {
|
|
394
|
+
const state = this.getDocumentState(documentId);
|
|
395
|
+
if (!state) {
|
|
396
|
+
throw new Error(`Zoom state not found for document: ${documentId ?? "active"}`);
|
|
397
|
+
}
|
|
398
|
+
return state;
|
|
284
399
|
}
|
|
285
|
-
|
|
286
|
-
|
|
400
|
+
// ─────────────────────────────────────────────────────────
|
|
401
|
+
// Core Operations
|
|
402
|
+
// ─────────────────────────────────────────────────────────
|
|
403
|
+
requestZoom(level, center, documentId) {
|
|
404
|
+
this.handleRequest({ level, center }, documentId);
|
|
287
405
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
this.
|
|
406
|
+
requestZoomBy(delta, center, documentId) {
|
|
407
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
408
|
+
const docState = this.getDocumentStateOrThrow(id);
|
|
409
|
+
const cur = docState.currentZoomLevel;
|
|
410
|
+
const target = this.toZoom(cur + delta);
|
|
411
|
+
this.handleRequest({ level: target, center }, id);
|
|
293
412
|
}
|
|
294
|
-
|
|
295
|
-
this.
|
|
413
|
+
zoomIn(documentId) {
|
|
414
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
415
|
+
const docState = this.getDocumentStateOrThrow(id);
|
|
416
|
+
const cur = docState.currentZoomLevel;
|
|
417
|
+
this.handleRequest({ level: cur, delta: this.stepFor(cur) }, id);
|
|
296
418
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
419
|
+
zoomOut(documentId) {
|
|
420
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
421
|
+
const docState = this.getDocumentStateOrThrow(id);
|
|
422
|
+
const cur = docState.currentZoomLevel;
|
|
423
|
+
this.handleRequest({ level: cur, delta: -this.stepFor(cur) }, id);
|
|
302
424
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
return r ? r.step : this.zoomStep;
|
|
425
|
+
zoomToArea(pageIndex, rect, documentId) {
|
|
426
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
427
|
+
this.handleZoomToArea(id, pageIndex, rect);
|
|
307
428
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
429
|
+
enableMarqueeZoom(documentId) {
|
|
430
|
+
var _a;
|
|
431
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
432
|
+
(_a = this.interactionManager) == null ? void 0 : _a.forDocument(id).activate("marqueeZoom");
|
|
311
433
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return;
|
|
434
|
+
disableMarqueeZoom(documentId) {
|
|
435
|
+
var _a;
|
|
436
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
437
|
+
(_a = this.interactionManager) == null ? void 0 : _a.forDocument(id).activateDefaultMode();
|
|
438
|
+
}
|
|
439
|
+
toggleMarqueeZoom(documentId) {
|
|
440
|
+
var _a;
|
|
441
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
442
|
+
const scope = (_a = this.interactionManager) == null ? void 0 : _a.forDocument(id);
|
|
443
|
+
if ((scope == null ? void 0 : scope.getActiveMode()) === "marqueeZoom") {
|
|
444
|
+
scope.activateDefaultMode();
|
|
445
|
+
} else {
|
|
446
|
+
scope == null ? void 0 : scope.activate("marqueeZoom");
|
|
326
447
|
}
|
|
327
|
-
|
|
328
|
-
|
|
448
|
+
}
|
|
449
|
+
isMarqueeZoomActive(documentId) {
|
|
450
|
+
var _a;
|
|
451
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
452
|
+
return ((_a = this.interactionManager) == null ? void 0 : _a.forDocument(id).getActiveMode()) === "marqueeZoom";
|
|
453
|
+
}
|
|
454
|
+
// ─────────────────────────────────────────────────────────
|
|
455
|
+
// Main Zoom Logic
|
|
456
|
+
// ─────────────────────────────────────────────────────────
|
|
457
|
+
handleRequest({ level, delta = 0, center, focus = VerticalZoomFocus.Center, align = "keep" }, documentId) {
|
|
458
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
459
|
+
const docState = this.getDocumentStateOrThrow(id);
|
|
460
|
+
const coreDoc = this.coreState.core.documents[id];
|
|
461
|
+
if (!coreDoc) return;
|
|
462
|
+
const viewport = this.viewport.forDocument(id);
|
|
463
|
+
const metrics = viewport.getMetrics();
|
|
464
|
+
const oldZoom = docState.currentZoomLevel;
|
|
465
|
+
if (metrics.clientWidth === 0 || metrics.clientHeight === 0) {
|
|
329
466
|
return;
|
|
330
467
|
}
|
|
468
|
+
const base = typeof level === "number" ? level : this.computeZoomForMode(id, level, metrics);
|
|
469
|
+
if (base === false) return;
|
|
331
470
|
const exactZoom = clamp(base + delta, this.minZoom, this.maxZoom);
|
|
332
|
-
const newZoom = Math.floor(exactZoom *
|
|
471
|
+
const newZoom = Math.floor(exactZoom * 1e3) / 1e3;
|
|
333
472
|
const focusPoint = center ?? {
|
|
334
473
|
vx: metrics.clientWidth / 2,
|
|
335
474
|
vy: focus === VerticalZoomFocus.Top ? 0 : metrics.clientHeight / 2
|
|
336
475
|
};
|
|
337
476
|
const { desiredScrollLeft, desiredScrollTop } = this.computeScrollForZoomChange(
|
|
477
|
+
id,
|
|
338
478
|
metrics,
|
|
339
479
|
oldZoom,
|
|
340
480
|
newZoom,
|
|
@@ -342,20 +482,23 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
342
482
|
align
|
|
343
483
|
);
|
|
344
484
|
if (!isNaN(desiredScrollLeft) && !isNaN(desiredScrollTop)) {
|
|
345
|
-
this.viewportPlugin.setViewportScrollMetrics({
|
|
485
|
+
this.viewportPlugin.setViewportScrollMetrics(id, {
|
|
346
486
|
scrollLeft: desiredScrollLeft,
|
|
347
487
|
scrollTop: desiredScrollTop
|
|
348
488
|
});
|
|
349
489
|
}
|
|
350
|
-
this.dispatch(setZoomLevel(typeof level === "number" ? newZoom : level, newZoom));
|
|
351
|
-
this.dispatchCoreAction(setScale(newZoom));
|
|
352
|
-
this.
|
|
353
|
-
|
|
490
|
+
this.dispatch(setZoomLevel(id, typeof level === "number" ? newZoom : level, newZoom));
|
|
491
|
+
this.dispatchCoreAction(setScale(newZoom, id));
|
|
492
|
+
if (this.viewport.isGated(id)) {
|
|
493
|
+
this.viewport.releaseGate("zoom", id);
|
|
494
|
+
}
|
|
495
|
+
viewport.scrollTo({
|
|
354
496
|
x: desiredScrollLeft,
|
|
355
497
|
y: desiredScrollTop,
|
|
356
498
|
behavior: "instant"
|
|
357
499
|
});
|
|
358
500
|
const evt = {
|
|
501
|
+
documentId: id,
|
|
359
502
|
oldZoom,
|
|
360
503
|
newZoom,
|
|
361
504
|
level,
|
|
@@ -366,23 +509,18 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
366
509
|
};
|
|
367
510
|
this.zoom$.emit(evt);
|
|
368
511
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const spreads = getPagesWithRotatedSize(this.coreState.core);
|
|
375
|
-
if (!spreads.length) return false;
|
|
376
|
-
const pgGap = this.scroll.getPageGap();
|
|
512
|
+
computeZoomForMode(documentId, mode, vp) {
|
|
513
|
+
const coreDoc = this.coreState.core.documents[documentId];
|
|
514
|
+
if (!coreDoc) return false;
|
|
515
|
+
const scrollScope = this.scroll.forDocument(documentId);
|
|
516
|
+
const pgGap = scrollScope ? this.scroll.getPageGap() : 0;
|
|
377
517
|
const vpGap = this.viewport.getViewportGap();
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
518
|
+
const spreads = scrollScope.getSpreadPagesWithRotatedSize();
|
|
519
|
+
if (!spreads.length) return false;
|
|
520
|
+
if (vp.clientWidth === 0 || vp.clientHeight === 0) return false;
|
|
381
521
|
const availableWidth = vp.clientWidth - 2 * vpGap;
|
|
382
522
|
const availableHeight = vp.clientHeight - 2 * vpGap;
|
|
383
|
-
if (availableWidth <= 0 || availableHeight <= 0)
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
523
|
+
if (availableWidth <= 0 || availableHeight <= 0) return false;
|
|
386
524
|
let maxContentW = 0, maxContentH = 0;
|
|
387
525
|
spreads.forEach((spread) => {
|
|
388
526
|
const contentW = spread.reduce((s, p, i) => s + p.rotatedSize.width + (i ? pgGap : 0), 0);
|
|
@@ -397,14 +535,13 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
397
535
|
return Math.min(availableWidth / maxContentW, availableHeight / maxContentH);
|
|
398
536
|
case ZoomMode.Automatic:
|
|
399
537
|
return Math.min(availableWidth / maxContentW, 1);
|
|
400
|
-
/* istanbul ignore next */
|
|
401
538
|
default:
|
|
402
539
|
return 1;
|
|
403
540
|
}
|
|
404
541
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const layout =
|
|
542
|
+
computeScrollForZoomChange(documentId, vp, oldZoom, newZoom, focus, align = "keep") {
|
|
543
|
+
const scrollScope = this.scroll.forDocument(documentId);
|
|
544
|
+
const layout = scrollScope.getLayout();
|
|
408
545
|
const vpGap = this.viewport.getViewportGap();
|
|
409
546
|
const contentW = layout.totalContentSize.width;
|
|
410
547
|
const contentH = layout.totalContentSize.height;
|
|
@@ -426,24 +563,26 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
426
563
|
desiredScrollTop: Math.max(0, desiredScrollTop)
|
|
427
564
|
};
|
|
428
565
|
}
|
|
429
|
-
handleZoomToArea(pageIndex, rect) {
|
|
430
|
-
const
|
|
431
|
-
|
|
566
|
+
handleZoomToArea(documentId, pageIndex, rect) {
|
|
567
|
+
const coreDoc = this.coreState.core.documents[documentId];
|
|
568
|
+
if (!coreDoc) return;
|
|
569
|
+
const rotation = coreDoc.rotation;
|
|
570
|
+
const viewport = this.viewport.forDocument(documentId);
|
|
571
|
+
const vp = viewport.getMetrics();
|
|
432
572
|
const vpGap = this.viewport.getViewportGap();
|
|
433
|
-
const
|
|
573
|
+
const docState = this.getDocumentStateOrThrow(documentId);
|
|
574
|
+
const oldZ = docState.currentZoomLevel;
|
|
434
575
|
const availableW = vp.clientWidth - 2 * vpGap;
|
|
435
576
|
const availableH = vp.clientHeight - 2 * vpGap;
|
|
436
|
-
const
|
|
577
|
+
const scrollScope = this.scroll.forDocument(documentId);
|
|
578
|
+
const layout = scrollScope.getLayout();
|
|
437
579
|
const vItem = layout.virtualItems.find(
|
|
438
580
|
(it) => it.pageLayouts.some((p) => p.pageIndex === pageIndex)
|
|
439
581
|
);
|
|
440
582
|
if (!vItem) return;
|
|
441
583
|
const pageRel = vItem.pageLayouts.find((p) => p.pageIndex === pageIndex);
|
|
442
584
|
const rotatedRect = rotateRect(
|
|
443
|
-
{
|
|
444
|
-
width: pageRel.width,
|
|
445
|
-
height: pageRel.height
|
|
446
|
-
},
|
|
585
|
+
{ width: pageRel.width, height: pageRel.height },
|
|
447
586
|
rect,
|
|
448
587
|
rotation
|
|
449
588
|
);
|
|
@@ -459,21 +598,38 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
459
598
|
const offYold = off(availableH, layout.totalContentSize.height, oldZ);
|
|
460
599
|
const centerVX = vpGap + offXold + cxContent * oldZ - vp.scrollLeft;
|
|
461
600
|
const centerVY = vpGap + offYold + cyContent * oldZ - vp.scrollTop;
|
|
462
|
-
this.handleRequest(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
601
|
+
this.handleRequest(
|
|
602
|
+
{
|
|
603
|
+
level: targetZoom,
|
|
604
|
+
center: { vx: centerVX, vy: centerVY },
|
|
605
|
+
align: "center"
|
|
606
|
+
},
|
|
607
|
+
documentId
|
|
608
|
+
);
|
|
467
609
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (
|
|
472
|
-
this.handleRequest({ level:
|
|
610
|
+
recalcAuto(documentId, focus) {
|
|
611
|
+
const docState = this.getDocumentState(documentId);
|
|
612
|
+
if (!docState) return;
|
|
613
|
+
if (docState.zoomLevel === ZoomMode.Automatic || docState.zoomLevel === ZoomMode.FitPage || docState.zoomLevel === ZoomMode.FitWidth) {
|
|
614
|
+
this.handleRequest({ level: docState.zoomLevel, focus }, documentId);
|
|
615
|
+
}
|
|
473
616
|
}
|
|
474
|
-
|
|
475
|
-
|
|
617
|
+
// ─────────────────────────────────────────────────────────
|
|
618
|
+
// Helpers
|
|
619
|
+
// ─────────────────────────────────────────────────────────
|
|
620
|
+
normalizeRanges(ranges) {
|
|
621
|
+
return [...ranges].filter((r) => r.step > 0 && r.max > r.min).sort((a, b) => a.min - b.min);
|
|
476
622
|
}
|
|
623
|
+
stepFor(zoom) {
|
|
624
|
+
const r = this.zoomRanges.find((r2) => zoom >= r2.min && zoom < r2.max);
|
|
625
|
+
return r ? r.step : this.zoomStep;
|
|
626
|
+
}
|
|
627
|
+
toZoom(v) {
|
|
628
|
+
return parseFloat(clamp(v, this.minZoom, this.maxZoom).toFixed(2));
|
|
629
|
+
}
|
|
630
|
+
// ─────────────────────────────────────────────────────────
|
|
631
|
+
// Marquee Zoom
|
|
632
|
+
// ─────────────────────────────────────────────────────────
|
|
477
633
|
registerMarqueeOnPage(opts) {
|
|
478
634
|
if (!this.interactionManager) {
|
|
479
635
|
this.logger.warn(
|
|
@@ -484,13 +640,13 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
484
640
|
return () => {
|
|
485
641
|
};
|
|
486
642
|
}
|
|
487
|
-
const
|
|
488
|
-
if (!document) {
|
|
643
|
+
const coreDoc = this.coreState.core.documents[opts.documentId];
|
|
644
|
+
if (!coreDoc || !coreDoc.document) {
|
|
489
645
|
this.logger.warn("ZoomPlugin", "DocumentNotFound", "Document not found");
|
|
490
646
|
return () => {
|
|
491
647
|
};
|
|
492
648
|
}
|
|
493
|
-
const page = document.pages[opts.pageIndex];
|
|
649
|
+
const page = coreDoc.document.pages[opts.pageIndex];
|
|
494
650
|
if (!page) {
|
|
495
651
|
this.logger.warn("ZoomPlugin", "PageNotFound", `Page ${opts.pageIndex} not found`);
|
|
496
652
|
return () => {
|
|
@@ -502,22 +658,49 @@ const _ZoomPlugin = class _ZoomPlugin extends BasePlugin {
|
|
|
502
658
|
onPreview: opts.callback.onPreview,
|
|
503
659
|
onCommit: (rect) => {
|
|
504
660
|
var _a, _b;
|
|
505
|
-
this.zoomToArea(opts.pageIndex, rect);
|
|
661
|
+
this.zoomToArea(opts.pageIndex, rect, opts.documentId);
|
|
506
662
|
(_b = (_a = opts.callback).onCommit) == null ? void 0 : _b.call(_a, rect);
|
|
507
663
|
},
|
|
508
664
|
onSmallDrag: () => {
|
|
509
665
|
var _a, _b;
|
|
510
|
-
this.zoomIn();
|
|
666
|
+
this.zoomIn(opts.documentId);
|
|
511
667
|
(_b = (_a = opts.callback).onSmallDrag) == null ? void 0 : _b.call(_a);
|
|
512
668
|
}
|
|
513
669
|
});
|
|
514
670
|
const off = this.interactionManager.registerHandlers({
|
|
671
|
+
documentId: opts.documentId,
|
|
515
672
|
modeId: "marqueeZoom",
|
|
516
673
|
handlers,
|
|
517
674
|
pageIndex: opts.pageIndex
|
|
518
675
|
});
|
|
519
676
|
return off;
|
|
520
677
|
}
|
|
678
|
+
// ─────────────────────────────────────────────────────────
|
|
679
|
+
// Store Update Handlers
|
|
680
|
+
// ─────────────────────────────────────────────────────────
|
|
681
|
+
onStoreUpdated(prevState, newState) {
|
|
682
|
+
for (const documentId in newState.documents) {
|
|
683
|
+
const prevDoc = prevState.documents[documentId];
|
|
684
|
+
const newDoc = newState.documents[documentId];
|
|
685
|
+
if (prevDoc && newDoc && (prevDoc.currentZoomLevel !== newDoc.currentZoomLevel || prevDoc.zoomLevel !== newDoc.zoomLevel || prevDoc.isMarqueeZoomActive !== newDoc.isMarqueeZoomActive)) {
|
|
686
|
+
this.state$.emit({
|
|
687
|
+
documentId,
|
|
688
|
+
state: newDoc
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
// ─────────────────────────────────────────────────────────
|
|
694
|
+
// Lifecycle
|
|
695
|
+
// ─────────────────────────────────────────────────────────
|
|
696
|
+
async initialize() {
|
|
697
|
+
this.logger.info("ZoomPlugin", "Initialize", "Zoom plugin initialized");
|
|
698
|
+
}
|
|
699
|
+
async destroy() {
|
|
700
|
+
this.zoom$.clear();
|
|
701
|
+
this.state$.clear();
|
|
702
|
+
super.destroy();
|
|
703
|
+
}
|
|
521
704
|
};
|
|
522
705
|
_ZoomPlugin.id = "zoom";
|
|
523
706
|
let ZoomPlugin = _ZoomPlugin;
|
|
@@ -533,6 +716,7 @@ export {
|
|
|
533
716
|
ZoomMode,
|
|
534
717
|
ZoomPlugin,
|
|
535
718
|
ZoomPluginPackage,
|
|
719
|
+
initialDocumentState,
|
|
536
720
|
initialState,
|
|
537
721
|
manifest
|
|
538
722
|
};
|