@embedpdf-editor/vue3-chapter-viewer 0.1.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/index.js ADDED
@@ -0,0 +1,3981 @@
1
+ import { defineComponent, computed, h, openBlock, createElementBlock, normalizeStyle, unref, normalizeClass, createVNode, withCtx, renderSlot, ref, onMounted, onBeforeUnmount, watch, createCommentVNode, Fragment, renderList, createElementVNode, toDisplayString, createBlock, resolveDynamicComponent, withModifiers, normalizeProps, guardReactiveProps } from "vue";
2
+ import { useRegistry, useCapability, EmbedPDF } from "@embedpdf/core/vue";
3
+ import { EmbedPDF as EmbedPDF2, useCapability as useCapability2 } from "@embedpdf/core/vue";
4
+ import { BasePlugin, createBehaviorEmitter, createEmitter, createPluginRegistration } from "@embedpdf/core";
5
+ import { DocumentManagerPlugin, DocumentManagerPluginPackage } from "@embedpdf/plugin-document-manager";
6
+ import { InteractionManagerPluginPackage } from "@embedpdf/plugin-interaction-manager";
7
+ import { RenderPluginPackage } from "@embedpdf/plugin-render";
8
+ import { RotatePluginPackage } from "@embedpdf/plugin-rotate";
9
+ import { SelectionPluginPackage, SelectionPlugin, glyphAt, expandToLineBoundary, rectsWithinSlice } from "@embedpdf/plugin-selection";
10
+ import { AnnotationPluginPackage, LockModeType, AnnotationPlugin, ANNOTATION_PLUGIN_ID } from "@embedpdf/plugin-annotation";
11
+ import { HistoryPluginPackage } from "@embedpdf/plugin-history";
12
+ import { RedactionPluginPackage } from "@embedpdf/plugin-redaction";
13
+ import { FormPluginPackage } from "@embedpdf/plugin-form";
14
+ import { StampPluginPackage } from "@embedpdf/plugin-stamp";
15
+ import { SignaturePluginPackage } from "@embedpdf/plugin-signature";
16
+ import { CommandsPluginPackage } from "@embedpdf/plugin-commands";
17
+ import { I18nPluginPackage } from "@embedpdf/plugin-i18n";
18
+ import { UIPluginPackage, isToolbarOpen } from "@embedpdf/plugin-ui";
19
+ import { PdfAnnotationSubtype, PdfErrorCode, uuidV4, PdfBlendMode } from "@embedpdf/models";
20
+ import { GlobalPointerProvider, PagePointerProvider } from "@embedpdf/plugin-interaction-manager/vue";
21
+ import { Rotate } from "@embedpdf/plugin-rotate/vue";
22
+ import { SelectionLayer } from "@embedpdf/plugin-selection/vue";
23
+ import { AnnotationLayer } from "@embedpdf/plugin-annotation/vue";
24
+ import { RedactionLayer } from "@embedpdf/plugin-redaction/vue";
25
+ import { RenderLayer } from "@embedpdf/plugin-render/vue";
26
+ import { usePdfiumEngine } from "@embedpdf/engines/vue";
27
+ const pe = "chapter-manager", ge = { id: pe, name: "Chapter Manager Plugin", version: "0.1.0", provides: ["chapter-manager"], requires: ["document-manager"], optional: [], defaultConfig: { manifest: { chapters: [] }, prefetchChapters: 1, unloadTimeoutMs: 6e4, autoActivateOnLoad: true } };
28
+ const fe = { kind: "first-wins" };
29
+ function me(e13, t, a) {
30
+ if (1 === t.length) return t[0].chapterId;
31
+ switch (a.kind) {
32
+ case "first-wins":
33
+ return t[0].chapterId;
34
+ case "last-wins":
35
+ return t[t.length - 1].chapterId;
36
+ case "explicit": {
37
+ const a2 = t.find((t2) => {
38
+ var a3;
39
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
40
+ });
41
+ return a2 ? a2.chapterId : t[0].chapterId;
42
+ }
43
+ case "custom":
44
+ return a.resolve(e13, t);
45
+ }
46
+ }
47
+ let ve = class {
48
+ constructor(e13) {
49
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
50
+ for (const t of e13) {
51
+ this._byGlobalNumber.set(t.globalPageNumber, t);
52
+ let e14 = this._byChapter.get(t.chapterId);
53
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
54
+ }
55
+ }
56
+ get totalPages() {
57
+ return this._pages.length;
58
+ }
59
+ list() {
60
+ return this._pages;
61
+ }
62
+ atIndex(e13) {
63
+ return this._pages[e13] ?? null;
64
+ }
65
+ byGlobalNumber(e13) {
66
+ return this._byGlobalNumber.get(e13) ?? null;
67
+ }
68
+ toGlobal(e13, t) {
69
+ const a = this._byChapter.get(e13);
70
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
71
+ }
72
+ pagesOfChapter(e13) {
73
+ return this._byChapter.get(e13) ?? [];
74
+ }
75
+ firstIndexOfChapter(e13) {
76
+ var t;
77
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
78
+ return a ? this._pages.indexOf(a) : -1;
79
+ }
80
+ };
81
+ function be(e13, t = fe) {
82
+ const a = (function(e14, t2 = fe) {
83
+ const a2 = /* @__PURE__ */ new Map();
84
+ for (const i2 of e14.chapters) {
85
+ const [e15, t3] = i2.globalPageRange;
86
+ for (let s3 = e15; s3 <= t3; s3++) {
87
+ const e16 = a2.get(s3);
88
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
89
+ }
90
+ }
91
+ const s2 = /* @__PURE__ */ new Map();
92
+ for (const [i2, o2] of a2) s2.set(i2, me(i2, o2, t2));
93
+ return s2;
94
+ })(e13, t), s = /* @__PURE__ */ new Map();
95
+ for (const n of e13.chapters) s.set(n.chapterId, n);
96
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
97
+ let r = 0;
98
+ for (const n of i) {
99
+ const e14 = a.get(n), t2 = s.get(e14);
100
+ if (!t2) continue;
101
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
102
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
103
+ }
104
+ return new ve(o);
105
+ }
106
+ const Pe = class e extends BasePlugin {
107
+ constructor(e13, t) {
108
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = fe, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
109
+ }
110
+ async initialize(e13) {
111
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? fe, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
112
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
113
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
114
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
115
+ }), this.documentManager.provides().onDocumentError((e14) => {
116
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
117
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
118
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
119
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
120
+ }
121
+ }
122
+ buildCapability() {
123
+ return { setManifest: (e13, t) => {
124
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
125
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
126
+ }
127
+ destroy() {
128
+ super.destroy();
129
+ for (const e13 of this.documentManagerUnsubs) e13();
130
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
131
+ }
132
+ setManifestInternal(t) {
133
+ const a = (function(e13) {
134
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
135
+ for (const s2 of e13.chapters) {
136
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
137
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
138
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
139
+ }
140
+ return t2;
141
+ })(t);
142
+ a.length > 0 && this.logger.warn(e.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
143
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
144
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
145
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
146
+ this.manifest = t, this.virtualPageMap = be(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
147
+ }
148
+ eagerPrefetchFromManifest() {
149
+ const e13 = this.config.prefetchChapters ?? 0;
150
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
151
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
152
+ for (let s = 0; s < a; s++) {
153
+ const e14 = this.manifest.chapters[s].chapterId;
154
+ this.chapterLastUsed.set(e14, t);
155
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
156
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
157
+ }
158
+ }
159
+ findChapter(e13) {
160
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
161
+ }
162
+ isOwnedChapter(e13) {
163
+ return !!this.findChapter(e13);
164
+ }
165
+ handleVisibleChange(e13) {
166
+ if (!this.virtualPageMap) return;
167
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
168
+ for (const n of e13) {
169
+ const e14 = this.virtualPageMap.atIndex(n);
170
+ e14 && s.add(e14.chapterId);
171
+ }
172
+ if (0 === s.size) return;
173
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
174
+ for (const n of s) {
175
+ const e14 = i.indexOf(n);
176
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
177
+ }
178
+ const r = /* @__PURE__ */ new Set();
179
+ for (const n of o) r.add(i[n]);
180
+ for (const n of r) {
181
+ this.chapterLastUsed.set(n, t);
182
+ const e14 = this.chapterStatus.get(n) ?? "idle";
183
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
184
+ }
185
+ if (this.config.autoActivateOnLoad ?? 1) {
186
+ const e14 = i.find((e15) => s.has(e15));
187
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
188
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
189
+ }
190
+ }
191
+ }
192
+ collectIdleChapters() {
193
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
194
+ if (e13 <= 0) return;
195
+ const t = Date.now();
196
+ for (const [a, s] of this.chapterStatus) {
197
+ if ("loaded" !== s) continue;
198
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
199
+ }
200
+ }
201
+ ensureChapterLoaded(e13) {
202
+ const t = this.pendingLoadPromises.get(e13);
203
+ if (t) return t;
204
+ const a = this.findChapter(e13);
205
+ if (!a) return Promise.resolve("error");
206
+ const s = this.chapterStatus.get(e13) ?? "idle";
207
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
208
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
209
+ const i = this.startLoad(a).finally(() => {
210
+ this.pendingLoadPromises.delete(e13);
211
+ });
212
+ return this.pendingLoadPromises.set(e13, i), i;
213
+ }
214
+ async resolvePdfPayload(e13) {
215
+ const t = e13.source;
216
+ if (t) {
217
+ if ("url" in t) return { url: t.url };
218
+ if ("buffer" in t) return { buffer: t.buffer };
219
+ if ("load" in t) return t.load();
220
+ }
221
+ const a = this.config.chapterPdfLoader;
222
+ if (a) return a.loadPdf(e13);
223
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
224
+ }
225
+ async startLoad(e13) {
226
+ var t;
227
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
228
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
229
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
230
+ }
231
+ waitForTerminalStatus(e13) {
232
+ return new Promise((t) => {
233
+ const a = (e14) => {
234
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
235
+ }, s = this.statusChange$.on((t2) => {
236
+ t2.chapterId === e13 && a(t2.status);
237
+ });
238
+ a(this.chapterStatus.get(e13) ?? "idle");
239
+ });
240
+ }
241
+ async handleDocumentError(t, a, s) {
242
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
243
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
244
+ const i = this.findChapter(t);
245
+ if (!i) return;
246
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
247
+ this.passwordAttempts.set(t, o);
248
+ let r = null;
249
+ try {
250
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
251
+ } catch (n) {
252
+ this.logger.error(e.id, "PasswordProvider", `Provider rejected for ${t}`, n);
253
+ }
254
+ if (!r) return void this.updateStatus(t, "password-required");
255
+ this.updateStatus(t, "loading");
256
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
257
+ }, () => {
258
+ });
259
+ }
260
+ closeChapter(e13) {
261
+ const t = this.documentManager.provides();
262
+ if (t.isDocumentOpen(e13)) {
263
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
264
+ } else this.updateStatus(e13, "closed");
265
+ }
266
+ updateStatus(e13, t, a) {
267
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
268
+ }
269
+ };
270
+ Pe.id = "chapter-manager";
271
+ let we = Pe;
272
+ const ye = { manifest: ge, create: (e13) => new we(pe, e13), reducer: (e13) => e13, initialState: {} }, Ie = "chapter-scroll", Ce = { id: Ie, name: "Chapter Scroll Plugin", version: "0.1.0", provides: ["chapter-scroll"], requires: ["chapter-manager"], optional: [], defaultConfig: { placeholderPageHeight: 1200, placeholderPageWidth: 900, bufferSize: 2, pageGap: 20 } };
273
+ const Me = { kind: "first-wins" };
274
+ function Se(e13, t, a) {
275
+ if (1 === t.length) return t[0].chapterId;
276
+ switch (a.kind) {
277
+ case "first-wins":
278
+ return t[0].chapterId;
279
+ case "last-wins":
280
+ return t[t.length - 1].chapterId;
281
+ case "explicit": {
282
+ const a2 = t.find((t2) => {
283
+ var a3;
284
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
285
+ });
286
+ return a2 ? a2.chapterId : t[0].chapterId;
287
+ }
288
+ case "custom":
289
+ return a.resolve(e13, t);
290
+ }
291
+ }
292
+ let xe = class {
293
+ constructor(e13) {
294
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
295
+ for (const t of e13) {
296
+ this._byGlobalNumber.set(t.globalPageNumber, t);
297
+ let e14 = this._byChapter.get(t.chapterId);
298
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
299
+ }
300
+ }
301
+ get totalPages() {
302
+ return this._pages.length;
303
+ }
304
+ list() {
305
+ return this._pages;
306
+ }
307
+ atIndex(e13) {
308
+ return this._pages[e13] ?? null;
309
+ }
310
+ byGlobalNumber(e13) {
311
+ return this._byGlobalNumber.get(e13) ?? null;
312
+ }
313
+ toGlobal(e13, t) {
314
+ const a = this._byChapter.get(e13);
315
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
316
+ }
317
+ pagesOfChapter(e13) {
318
+ return this._byChapter.get(e13) ?? [];
319
+ }
320
+ firstIndexOfChapter(e13) {
321
+ var t;
322
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
323
+ return a ? this._pages.indexOf(a) : -1;
324
+ }
325
+ };
326
+ function ke(e13, t = Me) {
327
+ const a = (function(e14, t2 = Me) {
328
+ const a2 = /* @__PURE__ */ new Map();
329
+ for (const i2 of e14.chapters) {
330
+ const [e15, t3] = i2.globalPageRange;
331
+ for (let s3 = e15; s3 <= t3; s3++) {
332
+ const e16 = a2.get(s3);
333
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
334
+ }
335
+ }
336
+ const s2 = /* @__PURE__ */ new Map();
337
+ for (const [i2, o2] of a2) s2.set(i2, Se(i2, o2, t2));
338
+ return s2;
339
+ })(e13, t), s = /* @__PURE__ */ new Map();
340
+ for (const n of e13.chapters) s.set(n.chapterId, n);
341
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
342
+ let r = 0;
343
+ for (const n of i) {
344
+ const e14 = a.get(n), t2 = s.get(e14);
345
+ if (!t2) continue;
346
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
347
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
348
+ }
349
+ return new xe(o);
350
+ }
351
+ const $e = class e2 extends BasePlugin {
352
+ constructor(e13, t) {
353
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = Me, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
354
+ }
355
+ async initialize(e13) {
356
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? Me, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
357
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
358
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
359
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
360
+ }), this.documentManager.provides().onDocumentError((e14) => {
361
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
362
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
363
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
364
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
365
+ }
366
+ }
367
+ buildCapability() {
368
+ return { setManifest: (e13, t) => {
369
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
370
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
371
+ }
372
+ destroy() {
373
+ super.destroy();
374
+ for (const e13 of this.documentManagerUnsubs) e13();
375
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
376
+ }
377
+ setManifestInternal(t) {
378
+ const a = (function(e13) {
379
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
380
+ for (const s2 of e13.chapters) {
381
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
382
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
383
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
384
+ }
385
+ return t2;
386
+ })(t);
387
+ a.length > 0 && this.logger.warn(e2.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
388
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
389
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
390
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
391
+ this.manifest = t, this.virtualPageMap = ke(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
392
+ }
393
+ eagerPrefetchFromManifest() {
394
+ const e13 = this.config.prefetchChapters ?? 0;
395
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
396
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
397
+ for (let s = 0; s < a; s++) {
398
+ const e14 = this.manifest.chapters[s].chapterId;
399
+ this.chapterLastUsed.set(e14, t);
400
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
401
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
402
+ }
403
+ }
404
+ findChapter(e13) {
405
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
406
+ }
407
+ isOwnedChapter(e13) {
408
+ return !!this.findChapter(e13);
409
+ }
410
+ handleVisibleChange(e13) {
411
+ if (!this.virtualPageMap) return;
412
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
413
+ for (const n of e13) {
414
+ const e14 = this.virtualPageMap.atIndex(n);
415
+ e14 && s.add(e14.chapterId);
416
+ }
417
+ if (0 === s.size) return;
418
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
419
+ for (const n of s) {
420
+ const e14 = i.indexOf(n);
421
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
422
+ }
423
+ const r = /* @__PURE__ */ new Set();
424
+ for (const n of o) r.add(i[n]);
425
+ for (const n of r) {
426
+ this.chapterLastUsed.set(n, t);
427
+ const e14 = this.chapterStatus.get(n) ?? "idle";
428
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
429
+ }
430
+ if (this.config.autoActivateOnLoad ?? 1) {
431
+ const e14 = i.find((e15) => s.has(e15));
432
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
433
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
434
+ }
435
+ }
436
+ }
437
+ collectIdleChapters() {
438
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
439
+ if (e13 <= 0) return;
440
+ const t = Date.now();
441
+ for (const [a, s] of this.chapterStatus) {
442
+ if ("loaded" !== s) continue;
443
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
444
+ }
445
+ }
446
+ ensureChapterLoaded(e13) {
447
+ const t = this.pendingLoadPromises.get(e13);
448
+ if (t) return t;
449
+ const a = this.findChapter(e13);
450
+ if (!a) return Promise.resolve("error");
451
+ const s = this.chapterStatus.get(e13) ?? "idle";
452
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
453
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
454
+ const i = this.startLoad(a).finally(() => {
455
+ this.pendingLoadPromises.delete(e13);
456
+ });
457
+ return this.pendingLoadPromises.set(e13, i), i;
458
+ }
459
+ async resolvePdfPayload(e13) {
460
+ const t = e13.source;
461
+ if (t) {
462
+ if ("url" in t) return { url: t.url };
463
+ if ("buffer" in t) return { buffer: t.buffer };
464
+ if ("load" in t) return t.load();
465
+ }
466
+ const a = this.config.chapterPdfLoader;
467
+ if (a) return a.loadPdf(e13);
468
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
469
+ }
470
+ async startLoad(e13) {
471
+ var t;
472
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
473
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
474
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
475
+ }
476
+ waitForTerminalStatus(e13) {
477
+ return new Promise((t) => {
478
+ const a = (e14) => {
479
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
480
+ }, s = this.statusChange$.on((t2) => {
481
+ t2.chapterId === e13 && a(t2.status);
482
+ });
483
+ a(this.chapterStatus.get(e13) ?? "idle");
484
+ });
485
+ }
486
+ async handleDocumentError(t, a, s) {
487
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
488
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
489
+ const i = this.findChapter(t);
490
+ if (!i) return;
491
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
492
+ this.passwordAttempts.set(t, o);
493
+ let r = null;
494
+ try {
495
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
496
+ } catch (n) {
497
+ this.logger.error(e2.id, "PasswordProvider", `Provider rejected for ${t}`, n);
498
+ }
499
+ if (!r) return void this.updateStatus(t, "password-required");
500
+ this.updateStatus(t, "loading");
501
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
502
+ }, () => {
503
+ });
504
+ }
505
+ closeChapter(e13) {
506
+ const t = this.documentManager.provides();
507
+ if (t.isDocumentOpen(e13)) {
508
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
509
+ } else this.updateStatus(e13, "closed");
510
+ }
511
+ updateStatus(e13, t, a) {
512
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
513
+ }
514
+ };
515
+ $e.id = "chapter-manager";
516
+ let Le = $e;
517
+ const ze = class extends BasePlugin {
518
+ constructor(e13, t) {
519
+ super(e13, t), this.layoutChange$ = createBehaviorEmitter(), this.visibleChange$ = createBehaviorEmitter(), this.virtualPageMap = null, this.pageSizes = /* @__PURE__ */ new Map(), this.offsets = [], this.totalHeight = 0, this.totalWidth = 0, this.viewportEl = null, this.viewportObservers = null, this.currentVisible = [], this.currentGlobalPageIndex = 0, this.chapterManagerUnsubs = [], this.chapterManager = this.registry.getPlugin(Le.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
520
+ }
521
+ async initialize(e13) {
522
+ this.config = { placeholderPageHeight: e13.placeholderPageHeight ?? 1200, placeholderPageWidth: e13.placeholderPageWidth ?? 900, bufferSize: e13.bufferSize ?? 2, pageGap: e13.pageGap ?? 20 }, this.virtualPageMap = this.chapterManager.provides().getVirtualPageMap(), this.rebuildOffsets(), this.chapterManagerUnsubs.push(this.chapterManager.provides().onManifestChange(({ map: e14 }) => {
523
+ this.virtualPageMap = e14, this.pageSizes.clear(), this.rebuildOffsets(), this.syncReadyChapterSizes(), this.recomputeVisible();
524
+ })), this.syncReadyChapterSizes();
525
+ }
526
+ isChapterDocumentReady(e13) {
527
+ const t = this.coreState.core.documents[e13];
528
+ return !(!t || "loaded" !== t.status || !t.document) && t.document.pages.length > 0;
529
+ }
530
+ refreshLayout() {
531
+ this.layoutChange$.emit(this.computeLayout());
532
+ }
533
+ syncReadyChapterSizes() {
534
+ for (const e13 of this.chapterManager.provides().getManifest().chapters) this.isChapterDocumentReady(e13.chapterId) && this.harvestChapterSizes(e13.chapterId);
535
+ this.refreshLayout();
536
+ }
537
+ onDocumentLoaded(e13) {
538
+ var t;
539
+ if (0 === ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0)) return;
540
+ const a = this.documentManager.provides();
541
+ a.getActiveDocumentId() || a.setActiveDocument(e13), this.harvestChapterSizes(e13), this.refreshLayout();
542
+ }
543
+ onDocumentClosed(e13) {
544
+ var t;
545
+ 0 !== ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0) && (this.dropChapterSizes(e13), this.refreshLayout());
546
+ }
547
+ buildCapability() {
548
+ return { registerViewport: (e13) => this.bindViewport(e13), reportChapterPageSizes: (e13, t) => this.applyChapterPageSizes(e13, t), getLayout: () => this.computeLayout(), getCurrentGlobalPageIndex: () => this.currentGlobalPageIndex, getVisibleGlobalPageIndices: () => this.currentVisible.slice(), scrollToGlobalPageIndex: (e13, t) => this.scrollToIndex(e13, t), scrollToChapter: (e13, t) => this.scrollToChapter(e13, t), scrollToGlobalPageNumber: (e13, t) => this.scrollToGlobalNumber(e13, t), scrollToGlobalPdfPoint: (e13, t, a) => this.scrollToGlobalPdfPoint(e13, t, a), onLayoutChange: this.layoutChange$.on, onVisibleChange: this.visibleChange$.on };
549
+ }
550
+ destroy() {
551
+ var e13;
552
+ super.destroy();
553
+ for (const t of this.chapterManagerUnsubs) t();
554
+ this.chapterManagerUnsubs = [], null == (e13 = this.viewportObservers) || e13.unbind(), this.viewportObservers = null, this.viewportEl = null, this.layoutChange$.clear(), this.visibleChange$.clear();
555
+ }
556
+ getPageSize(e13) {
557
+ return this.pageSizes.get(e13) ?? { width: this.config.placeholderPageWidth, height: this.config.placeholderPageHeight };
558
+ }
559
+ rebuildOffsets() {
560
+ if (!this.virtualPageMap) return this.offsets = [], this.totalHeight = 0, void (this.totalWidth = 0);
561
+ const e13 = this.virtualPageMap.totalPages;
562
+ this.offsets = new Array(e13);
563
+ let t = 0, a = 0;
564
+ for (let s = 0; s < e13; s++) {
565
+ const { width: e14, height: i } = this.getPageSize(s);
566
+ this.offsets[s] = t, t += i + this.config.pageGap, e14 > a && (a = e14);
567
+ }
568
+ this.totalHeight = e13 > 0 ? t - this.config.pageGap : 0, this.totalWidth = a, this.layoutChange$.emit(this.computeLayout());
569
+ }
570
+ applyChapterPageSizes(e13, t) {
571
+ if (!this.virtualPageMap) return;
572
+ let a = false;
573
+ for (const s of t) {
574
+ const t2 = this.virtualPageMap.toGlobal(e13, s.localPageIndex);
575
+ if (!t2) continue;
576
+ const i = this.pageSizes.get(t2.globalPageIndex);
577
+ i && i.width === s.width && i.height === s.height || (this.pageSizes.set(t2.globalPageIndex, { width: s.width, height: s.height }), a = true);
578
+ }
579
+ if (a) {
580
+ const e14 = this.currentGlobalPageIndex, t2 = this.offsets[e14] ?? 0;
581
+ if (this.rebuildOffsets(), this.viewportEl) {
582
+ const a2 = (this.offsets[e14] ?? 0) - t2;
583
+ 0 !== a2 && (this.viewportEl.scrollTop += a2);
584
+ }
585
+ this.recomputeVisible();
586
+ }
587
+ }
588
+ getChapterDocumentScale(e13) {
589
+ var t;
590
+ return (null == (t = this.coreState.core.documents[e13]) ? void 0 : t.scale) ?? 1;
591
+ }
592
+ harvestChapterSizes(e13, t = 0) {
593
+ var a;
594
+ if (!this.virtualPageMap) return;
595
+ const s = this.documentManager.provides().getDocument(e13), i = this.virtualPageMap.pagesOfChapter(e13);
596
+ if (!(null == (a = null == s ? void 0 : s.pages) ? void 0 : a.length) || 0 === i.length) return void (t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1)));
597
+ const o = this.getChapterDocumentScale(e13), r = [];
598
+ for (const n of i) {
599
+ const e14 = s.pages[n.localPageIndex];
600
+ (null == e14 ? void 0 : e14.size) && r.push({ localPageIndex: n.localPageIndex, width: e14.size.width * o, height: e14.size.height * o });
601
+ }
602
+ 0 !== r.length ? this.applyChapterPageSizes(e13, r) : t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1));
603
+ }
604
+ onScaleChanged(e13) {
605
+ const t = this.coreState.core.documents[e13];
606
+ t && "loaded" === t.status && this.chapterManager.provides().getChapter(e13) && this.harvestChapterSizes(e13);
607
+ }
608
+ dropChapterSizes(e13) {
609
+ if (!this.virtualPageMap) return;
610
+ let t = false;
611
+ for (const a of this.virtualPageMap.pagesOfChapter(e13)) this.pageSizes.delete(a.globalPageIndex) && (t = true);
612
+ t && (this.rebuildOffsets(), this.recomputeVisible());
613
+ }
614
+ bindViewport(e13) {
615
+ var t;
616
+ if (null == (t = this.viewportObservers) || t.unbind(), this.viewportEl = e13, this.viewportObservers = null, !e13) return;
617
+ const a = () => this.recomputeVisible(), s = new ResizeObserver(() => this.recomputeVisible());
618
+ e13.addEventListener("scroll", a, { passive: true }), s.observe(e13), this.viewportObservers = { unbind: () => {
619
+ e13.removeEventListener("scroll", a), s.disconnect();
620
+ } }, this.syncReadyChapterSizes(), this.recomputeVisible(), 0 === e13.clientHeight && requestAnimationFrame(() => {
621
+ requestAnimationFrame(() => this.recomputeVisible());
622
+ });
623
+ }
624
+ recomputeVisible() {
625
+ if (!this.viewportEl || !this.virtualPageMap) return;
626
+ const e13 = this.virtualPageMap.totalPages;
627
+ if (0 === e13) return this.currentVisible = [], this.currentGlobalPageIndex = 0, void this.layoutChange$.emit(this.computeLayout());
628
+ const t = this.viewportEl.scrollTop, a = t + this.viewportEl.clientHeight, s = this.findFirstVisibleIndex(t);
629
+ let i = s;
630
+ for (; i < e13; ) {
631
+ const e14 = this.getPageSize(i), t2 = this.offsets[i];
632
+ if (e14.height, t2 >= a) break;
633
+ i++;
634
+ }
635
+ const o = [];
636
+ let r = s, n = -1;
637
+ for (let l = s; l < i; l++) {
638
+ o.push(l);
639
+ const e14 = this.offsets[l], s2 = e14 + this.getPageSize(l).height, i2 = Math.max(0, Math.min(s2, a) - Math.max(e14, t));
640
+ i2 > n && (n = i2, r = l);
641
+ }
642
+ this.currentVisible = o, this.currentGlobalPageIndex = r, this.visibleChange$.emit({ visibleGlobalPageIndices: o, currentGlobalPageIndex: r }), this.chapterManager.provides().setVisibleGlobalPages(o), this.layoutChange$.emit(this.computeLayout());
643
+ }
644
+ findFirstVisibleIndex(e13) {
645
+ let t = 0, a = this.offsets.length - 1, s = 0;
646
+ for (; t <= a; ) {
647
+ const i = t + a >> 1;
648
+ this.offsets[i] <= e13 ? (s = i, t = i + 1) : a = i - 1;
649
+ }
650
+ return s;
651
+ }
652
+ computeLayout() {
653
+ const e13 = this.config.bufferSize, t = Math.max(0, (this.currentVisible[0] ?? 0) - e13), a = this.currentVisible[this.currentVisible.length - 1] ?? -1, s = Math.min(this.offsets.length - 1, (a >= 0 ? a : 0) + e13), i = [];
654
+ if (this.virtualPageMap && this.offsets.length > 0) for (let o = t; o <= s; o++) {
655
+ const e14 = this.virtualPageMap.atIndex(o);
656
+ if (!e14) continue;
657
+ const t2 = this.getPageSize(o), a2 = !this.isChapterDocumentReady(e14.chapterId);
658
+ i.push({ globalPageIndex: o, globalPageNumber: e14.globalPageNumber, chapterId: e14.chapterId, localPageIndex: e14.localPageIndex, width: t2.width, height: t2.height, offsetTop: this.offsets[o], isPlaceholder: a2 });
659
+ }
660
+ return { totalHeight: this.totalHeight, totalWidth: this.totalWidth || this.config.placeholderPageWidth, items: i, pageGap: this.config.pageGap };
661
+ }
662
+ scrollToIndex(e13, t) {
663
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length) return;
664
+ const a = (this.offsets[e13] ?? 0) - ((null == t ? void 0 : t.topOffset) ?? 0);
665
+ this.viewportEl.scrollTo({ top: a, behavior: (null == t ? void 0 : t.behavior) ?? "auto" });
666
+ }
667
+ scrollToGlobalPdfPoint(e13, t, a) {
668
+ var s;
669
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length || !this.virtualPageMap) return;
670
+ const i = (null == a ? void 0 : a.marginTop) ?? 80, o = this.virtualPageMap.atIndex(e13);
671
+ if (!o) return void this.scrollToIndex(e13, a);
672
+ const r = this.pageSizes.get(e13), n = null == (s = this.documentManager.provides().getDocument(o.chapterId)) ? void 0 : s.pages[o.localPageIndex];
673
+ if (!r || !n) return void this.scrollToIndex(e13, a);
674
+ const l = r.height / n.size.height, h2 = (this.offsets[e13] ?? 0) + t * l - i;
675
+ this.viewportEl.scrollTo({ top: Math.max(0, h2), behavior: (null == a ? void 0 : a.behavior) ?? "auto" });
676
+ }
677
+ scrollToChapter(e13, t) {
678
+ if (!this.virtualPageMap) return;
679
+ const a = this.virtualPageMap.firstIndexOfChapter(e13);
680
+ a < 0 || (this.chapterManager.provides().ensureChapterLoaded(e13), this.scrollToIndex(a, t));
681
+ }
682
+ scrollToGlobalNumber(e13, t) {
683
+ if (!this.virtualPageMap) return;
684
+ const a = this.virtualPageMap.byGlobalNumber(e13);
685
+ a && this.scrollToIndex(a.globalPageIndex, t);
686
+ }
687
+ };
688
+ ze.id = "chapter-scroll";
689
+ let Te = ze;
690
+ const De = { manifest: Ce, create: (e13) => new Te(Ie, e13), reducer: (e13) => e13, initialState: {} }, Ge = "note", Oe = { id: Ge, name: "Note Plugin", version: "0.1.0", provides: ["note"], requires: ["selection", "chapter-scroll", "chapter-manager"], optional: [], defaultConfig: { callbacks: { onCreateNote: async () => null, onActivateNote: () => {
691
+ } }, markerSize: 18 } };
692
+ const Ae = { kind: "first-wins" };
693
+ function Ne(e13, t, a) {
694
+ if (1 === t.length) return t[0].chapterId;
695
+ switch (a.kind) {
696
+ case "first-wins":
697
+ return t[0].chapterId;
698
+ case "last-wins":
699
+ return t[t.length - 1].chapterId;
700
+ case "explicit": {
701
+ const a2 = t.find((t2) => {
702
+ var a3;
703
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
704
+ });
705
+ return a2 ? a2.chapterId : t[0].chapterId;
706
+ }
707
+ case "custom":
708
+ return a.resolve(e13, t);
709
+ }
710
+ }
711
+ let Ve = class {
712
+ constructor(e13) {
713
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
714
+ for (const t of e13) {
715
+ this._byGlobalNumber.set(t.globalPageNumber, t);
716
+ let e14 = this._byChapter.get(t.chapterId);
717
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
718
+ }
719
+ }
720
+ get totalPages() {
721
+ return this._pages.length;
722
+ }
723
+ list() {
724
+ return this._pages;
725
+ }
726
+ atIndex(e13) {
727
+ return this._pages[e13] ?? null;
728
+ }
729
+ byGlobalNumber(e13) {
730
+ return this._byGlobalNumber.get(e13) ?? null;
731
+ }
732
+ toGlobal(e13, t) {
733
+ const a = this._byChapter.get(e13);
734
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
735
+ }
736
+ pagesOfChapter(e13) {
737
+ return this._byChapter.get(e13) ?? [];
738
+ }
739
+ firstIndexOfChapter(e13) {
740
+ var t;
741
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
742
+ return a ? this._pages.indexOf(a) : -1;
743
+ }
744
+ };
745
+ function _e(e13, t = Ae) {
746
+ const a = (function(e14, t2 = Ae) {
747
+ const a2 = /* @__PURE__ */ new Map();
748
+ for (const i2 of e14.chapters) {
749
+ const [e15, t3] = i2.globalPageRange;
750
+ for (let s3 = e15; s3 <= t3; s3++) {
751
+ const e16 = a2.get(s3);
752
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
753
+ }
754
+ }
755
+ const s2 = /* @__PURE__ */ new Map();
756
+ for (const [i2, o2] of a2) s2.set(i2, Ne(i2, o2, t2));
757
+ return s2;
758
+ })(e13, t), s = /* @__PURE__ */ new Map();
759
+ for (const n of e13.chapters) s.set(n.chapterId, n);
760
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
761
+ let r = 0;
762
+ for (const n of i) {
763
+ const e14 = a.get(n), t2 = s.get(e14);
764
+ if (!t2) continue;
765
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
766
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
767
+ }
768
+ return new Ve(o);
769
+ }
770
+ const Re = class e3 extends BasePlugin {
771
+ constructor(e13, t) {
772
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = Ae, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
773
+ }
774
+ async initialize(e13) {
775
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? Ae, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
776
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
777
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
778
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
779
+ }), this.documentManager.provides().onDocumentError((e14) => {
780
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
781
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
782
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
783
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
784
+ }
785
+ }
786
+ buildCapability() {
787
+ return { setManifest: (e13, t) => {
788
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
789
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
790
+ }
791
+ destroy() {
792
+ super.destroy();
793
+ for (const e13 of this.documentManagerUnsubs) e13();
794
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
795
+ }
796
+ setManifestInternal(t) {
797
+ const a = (function(e13) {
798
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
799
+ for (const s2 of e13.chapters) {
800
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
801
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
802
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
803
+ }
804
+ return t2;
805
+ })(t);
806
+ a.length > 0 && this.logger.warn(e3.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
807
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
808
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
809
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
810
+ this.manifest = t, this.virtualPageMap = _e(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
811
+ }
812
+ eagerPrefetchFromManifest() {
813
+ const e13 = this.config.prefetchChapters ?? 0;
814
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
815
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
816
+ for (let s = 0; s < a; s++) {
817
+ const e14 = this.manifest.chapters[s].chapterId;
818
+ this.chapterLastUsed.set(e14, t);
819
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
820
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
821
+ }
822
+ }
823
+ findChapter(e13) {
824
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
825
+ }
826
+ isOwnedChapter(e13) {
827
+ return !!this.findChapter(e13);
828
+ }
829
+ handleVisibleChange(e13) {
830
+ if (!this.virtualPageMap) return;
831
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
832
+ for (const n of e13) {
833
+ const e14 = this.virtualPageMap.atIndex(n);
834
+ e14 && s.add(e14.chapterId);
835
+ }
836
+ if (0 === s.size) return;
837
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
838
+ for (const n of s) {
839
+ const e14 = i.indexOf(n);
840
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
841
+ }
842
+ const r = /* @__PURE__ */ new Set();
843
+ for (const n of o) r.add(i[n]);
844
+ for (const n of r) {
845
+ this.chapterLastUsed.set(n, t);
846
+ const e14 = this.chapterStatus.get(n) ?? "idle";
847
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
848
+ }
849
+ if (this.config.autoActivateOnLoad ?? 1) {
850
+ const e14 = i.find((e15) => s.has(e15));
851
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
852
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
853
+ }
854
+ }
855
+ }
856
+ collectIdleChapters() {
857
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
858
+ if (e13 <= 0) return;
859
+ const t = Date.now();
860
+ for (const [a, s] of this.chapterStatus) {
861
+ if ("loaded" !== s) continue;
862
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
863
+ }
864
+ }
865
+ ensureChapterLoaded(e13) {
866
+ const t = this.pendingLoadPromises.get(e13);
867
+ if (t) return t;
868
+ const a = this.findChapter(e13);
869
+ if (!a) return Promise.resolve("error");
870
+ const s = this.chapterStatus.get(e13) ?? "idle";
871
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
872
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
873
+ const i = this.startLoad(a).finally(() => {
874
+ this.pendingLoadPromises.delete(e13);
875
+ });
876
+ return this.pendingLoadPromises.set(e13, i), i;
877
+ }
878
+ async resolvePdfPayload(e13) {
879
+ const t = e13.source;
880
+ if (t) {
881
+ if ("url" in t) return { url: t.url };
882
+ if ("buffer" in t) return { buffer: t.buffer };
883
+ if ("load" in t) return t.load();
884
+ }
885
+ const a = this.config.chapterPdfLoader;
886
+ if (a) return a.loadPdf(e13);
887
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
888
+ }
889
+ async startLoad(e13) {
890
+ var t;
891
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
892
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
893
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
894
+ }
895
+ waitForTerminalStatus(e13) {
896
+ return new Promise((t) => {
897
+ const a = (e14) => {
898
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
899
+ }, s = this.statusChange$.on((t2) => {
900
+ t2.chapterId === e13 && a(t2.status);
901
+ });
902
+ a(this.chapterStatus.get(e13) ?? "idle");
903
+ });
904
+ }
905
+ async handleDocumentError(t, a, s) {
906
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
907
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
908
+ const i = this.findChapter(t);
909
+ if (!i) return;
910
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
911
+ this.passwordAttempts.set(t, o);
912
+ let r = null;
913
+ try {
914
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
915
+ } catch (n) {
916
+ this.logger.error(e3.id, "PasswordProvider", `Provider rejected for ${t}`, n);
917
+ }
918
+ if (!r) return void this.updateStatus(t, "password-required");
919
+ this.updateStatus(t, "loading");
920
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
921
+ }, () => {
922
+ });
923
+ }
924
+ closeChapter(e13) {
925
+ const t = this.documentManager.provides();
926
+ if (t.isDocumentOpen(e13)) {
927
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
928
+ } else this.updateStatus(e13, "closed");
929
+ }
930
+ updateStatus(e13, t, a) {
931
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
932
+ }
933
+ };
934
+ Re.id = "chapter-manager";
935
+ let Ee = Re;
936
+ const Ue = { kind: "first-wins" };
937
+ function Fe(e13, t, a) {
938
+ if (1 === t.length) return t[0].chapterId;
939
+ switch (a.kind) {
940
+ case "first-wins":
941
+ return t[0].chapterId;
942
+ case "last-wins":
943
+ return t[t.length - 1].chapterId;
944
+ case "explicit": {
945
+ const a2 = t.find((t2) => {
946
+ var a3;
947
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
948
+ });
949
+ return a2 ? a2.chapterId : t[0].chapterId;
950
+ }
951
+ case "custom":
952
+ return a.resolve(e13, t);
953
+ }
954
+ }
955
+ let qe = class {
956
+ constructor(e13) {
957
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
958
+ for (const t of e13) {
959
+ this._byGlobalNumber.set(t.globalPageNumber, t);
960
+ let e14 = this._byChapter.get(t.chapterId);
961
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
962
+ }
963
+ }
964
+ get totalPages() {
965
+ return this._pages.length;
966
+ }
967
+ list() {
968
+ return this._pages;
969
+ }
970
+ atIndex(e13) {
971
+ return this._pages[e13] ?? null;
972
+ }
973
+ byGlobalNumber(e13) {
974
+ return this._byGlobalNumber.get(e13) ?? null;
975
+ }
976
+ toGlobal(e13, t) {
977
+ const a = this._byChapter.get(e13);
978
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
979
+ }
980
+ pagesOfChapter(e13) {
981
+ return this._byChapter.get(e13) ?? [];
982
+ }
983
+ firstIndexOfChapter(e13) {
984
+ var t;
985
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
986
+ return a ? this._pages.indexOf(a) : -1;
987
+ }
988
+ };
989
+ function We(e13, t = Ue) {
990
+ const a = (function(e14, t2 = Ue) {
991
+ const a2 = /* @__PURE__ */ new Map();
992
+ for (const i2 of e14.chapters) {
993
+ const [e15, t3] = i2.globalPageRange;
994
+ for (let s3 = e15; s3 <= t3; s3++) {
995
+ const e16 = a2.get(s3);
996
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
997
+ }
998
+ }
999
+ const s2 = /* @__PURE__ */ new Map();
1000
+ for (const [i2, o2] of a2) s2.set(i2, Fe(i2, o2, t2));
1001
+ return s2;
1002
+ })(e13, t), s = /* @__PURE__ */ new Map();
1003
+ for (const n of e13.chapters) s.set(n.chapterId, n);
1004
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
1005
+ let r = 0;
1006
+ for (const n of i) {
1007
+ const e14 = a.get(n), t2 = s.get(e14);
1008
+ if (!t2) continue;
1009
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
1010
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
1011
+ }
1012
+ return new qe(o);
1013
+ }
1014
+ const He = class e4 extends BasePlugin {
1015
+ constructor(e13, t) {
1016
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = Ue, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1017
+ }
1018
+ async initialize(e13) {
1019
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? Ue, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
1020
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
1021
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
1022
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
1023
+ }), this.documentManager.provides().onDocumentError((e14) => {
1024
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
1025
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
1026
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
1027
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
1028
+ }
1029
+ }
1030
+ buildCapability() {
1031
+ return { setManifest: (e13, t) => {
1032
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
1033
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
1034
+ }
1035
+ destroy() {
1036
+ super.destroy();
1037
+ for (const e13 of this.documentManagerUnsubs) e13();
1038
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
1039
+ }
1040
+ setManifestInternal(t) {
1041
+ const a = (function(e13) {
1042
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
1043
+ for (const s2 of e13.chapters) {
1044
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
1045
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
1046
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
1047
+ }
1048
+ return t2;
1049
+ })(t);
1050
+ a.length > 0 && this.logger.warn(e4.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
1051
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
1052
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
1053
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
1054
+ this.manifest = t, this.virtualPageMap = We(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
1055
+ }
1056
+ eagerPrefetchFromManifest() {
1057
+ const e13 = this.config.prefetchChapters ?? 0;
1058
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
1059
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
1060
+ for (let s = 0; s < a; s++) {
1061
+ const e14 = this.manifest.chapters[s].chapterId;
1062
+ this.chapterLastUsed.set(e14, t);
1063
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
1064
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
1065
+ }
1066
+ }
1067
+ findChapter(e13) {
1068
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
1069
+ }
1070
+ isOwnedChapter(e13) {
1071
+ return !!this.findChapter(e13);
1072
+ }
1073
+ handleVisibleChange(e13) {
1074
+ if (!this.virtualPageMap) return;
1075
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
1076
+ for (const n of e13) {
1077
+ const e14 = this.virtualPageMap.atIndex(n);
1078
+ e14 && s.add(e14.chapterId);
1079
+ }
1080
+ if (0 === s.size) return;
1081
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
1082
+ for (const n of s) {
1083
+ const e14 = i.indexOf(n);
1084
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
1085
+ }
1086
+ const r = /* @__PURE__ */ new Set();
1087
+ for (const n of o) r.add(i[n]);
1088
+ for (const n of r) {
1089
+ this.chapterLastUsed.set(n, t);
1090
+ const e14 = this.chapterStatus.get(n) ?? "idle";
1091
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
1092
+ }
1093
+ if (this.config.autoActivateOnLoad ?? 1) {
1094
+ const e14 = i.find((e15) => s.has(e15));
1095
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
1096
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
1097
+ }
1098
+ }
1099
+ }
1100
+ collectIdleChapters() {
1101
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
1102
+ if (e13 <= 0) return;
1103
+ const t = Date.now();
1104
+ for (const [a, s] of this.chapterStatus) {
1105
+ if ("loaded" !== s) continue;
1106
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
1107
+ }
1108
+ }
1109
+ ensureChapterLoaded(e13) {
1110
+ const t = this.pendingLoadPromises.get(e13);
1111
+ if (t) return t;
1112
+ const a = this.findChapter(e13);
1113
+ if (!a) return Promise.resolve("error");
1114
+ const s = this.chapterStatus.get(e13) ?? "idle";
1115
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
1116
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
1117
+ const i = this.startLoad(a).finally(() => {
1118
+ this.pendingLoadPromises.delete(e13);
1119
+ });
1120
+ return this.pendingLoadPromises.set(e13, i), i;
1121
+ }
1122
+ async resolvePdfPayload(e13) {
1123
+ const t = e13.source;
1124
+ if (t) {
1125
+ if ("url" in t) return { url: t.url };
1126
+ if ("buffer" in t) return { buffer: t.buffer };
1127
+ if ("load" in t) return t.load();
1128
+ }
1129
+ const a = this.config.chapterPdfLoader;
1130
+ if (a) return a.loadPdf(e13);
1131
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
1132
+ }
1133
+ async startLoad(e13) {
1134
+ var t;
1135
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
1136
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
1137
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
1138
+ }
1139
+ waitForTerminalStatus(e13) {
1140
+ return new Promise((t) => {
1141
+ const a = (e14) => {
1142
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
1143
+ }, s = this.statusChange$.on((t2) => {
1144
+ t2.chapterId === e13 && a(t2.status);
1145
+ });
1146
+ a(this.chapterStatus.get(e13) ?? "idle");
1147
+ });
1148
+ }
1149
+ async handleDocumentError(t, a, s) {
1150
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
1151
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
1152
+ const i = this.findChapter(t);
1153
+ if (!i) return;
1154
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
1155
+ this.passwordAttempts.set(t, o);
1156
+ let r = null;
1157
+ try {
1158
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
1159
+ } catch (n) {
1160
+ this.logger.error(e4.id, "PasswordProvider", `Provider rejected for ${t}`, n);
1161
+ }
1162
+ if (!r) return void this.updateStatus(t, "password-required");
1163
+ this.updateStatus(t, "loading");
1164
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
1165
+ }, () => {
1166
+ });
1167
+ }
1168
+ closeChapter(e13) {
1169
+ const t = this.documentManager.provides();
1170
+ if (t.isDocumentOpen(e13)) {
1171
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
1172
+ } else this.updateStatus(e13, "closed");
1173
+ }
1174
+ updateStatus(e13, t, a) {
1175
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
1176
+ }
1177
+ };
1178
+ He.id = "chapter-manager";
1179
+ let Be = He;
1180
+ const je = class extends BasePlugin {
1181
+ constructor(e13, t) {
1182
+ super(e13, t), this.layoutChange$ = createBehaviorEmitter(), this.visibleChange$ = createBehaviorEmitter(), this.virtualPageMap = null, this.pageSizes = /* @__PURE__ */ new Map(), this.offsets = [], this.totalHeight = 0, this.totalWidth = 0, this.viewportEl = null, this.viewportObservers = null, this.currentVisible = [], this.currentGlobalPageIndex = 0, this.chapterManagerUnsubs = [], this.chapterManager = this.registry.getPlugin(Be.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1183
+ }
1184
+ async initialize(e13) {
1185
+ this.config = { placeholderPageHeight: e13.placeholderPageHeight ?? 1200, placeholderPageWidth: e13.placeholderPageWidth ?? 900, bufferSize: e13.bufferSize ?? 2, pageGap: e13.pageGap ?? 20 }, this.virtualPageMap = this.chapterManager.provides().getVirtualPageMap(), this.rebuildOffsets(), this.chapterManagerUnsubs.push(this.chapterManager.provides().onManifestChange(({ map: e14 }) => {
1186
+ this.virtualPageMap = e14, this.pageSizes.clear(), this.rebuildOffsets(), this.syncReadyChapterSizes(), this.recomputeVisible();
1187
+ })), this.syncReadyChapterSizes();
1188
+ }
1189
+ isChapterDocumentReady(e13) {
1190
+ const t = this.coreState.core.documents[e13];
1191
+ return !(!t || "loaded" !== t.status || !t.document) && t.document.pages.length > 0;
1192
+ }
1193
+ refreshLayout() {
1194
+ this.layoutChange$.emit(this.computeLayout());
1195
+ }
1196
+ syncReadyChapterSizes() {
1197
+ for (const e13 of this.chapterManager.provides().getManifest().chapters) this.isChapterDocumentReady(e13.chapterId) && this.harvestChapterSizes(e13.chapterId);
1198
+ this.refreshLayout();
1199
+ }
1200
+ onDocumentLoaded(e13) {
1201
+ var t;
1202
+ if (0 === ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0)) return;
1203
+ const a = this.documentManager.provides();
1204
+ a.getActiveDocumentId() || a.setActiveDocument(e13), this.harvestChapterSizes(e13), this.refreshLayout();
1205
+ }
1206
+ onDocumentClosed(e13) {
1207
+ var t;
1208
+ 0 !== ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0) && (this.dropChapterSizes(e13), this.refreshLayout());
1209
+ }
1210
+ buildCapability() {
1211
+ return { registerViewport: (e13) => this.bindViewport(e13), reportChapterPageSizes: (e13, t) => this.applyChapterPageSizes(e13, t), getLayout: () => this.computeLayout(), getCurrentGlobalPageIndex: () => this.currentGlobalPageIndex, getVisibleGlobalPageIndices: () => this.currentVisible.slice(), scrollToGlobalPageIndex: (e13, t) => this.scrollToIndex(e13, t), scrollToChapter: (e13, t) => this.scrollToChapter(e13, t), scrollToGlobalPageNumber: (e13, t) => this.scrollToGlobalNumber(e13, t), scrollToGlobalPdfPoint: (e13, t, a) => this.scrollToGlobalPdfPoint(e13, t, a), onLayoutChange: this.layoutChange$.on, onVisibleChange: this.visibleChange$.on };
1212
+ }
1213
+ destroy() {
1214
+ var e13;
1215
+ super.destroy();
1216
+ for (const t of this.chapterManagerUnsubs) t();
1217
+ this.chapterManagerUnsubs = [], null == (e13 = this.viewportObservers) || e13.unbind(), this.viewportObservers = null, this.viewportEl = null, this.layoutChange$.clear(), this.visibleChange$.clear();
1218
+ }
1219
+ getPageSize(e13) {
1220
+ return this.pageSizes.get(e13) ?? { width: this.config.placeholderPageWidth, height: this.config.placeholderPageHeight };
1221
+ }
1222
+ rebuildOffsets() {
1223
+ if (!this.virtualPageMap) return this.offsets = [], this.totalHeight = 0, void (this.totalWidth = 0);
1224
+ const e13 = this.virtualPageMap.totalPages;
1225
+ this.offsets = new Array(e13);
1226
+ let t = 0, a = 0;
1227
+ for (let s = 0; s < e13; s++) {
1228
+ const { width: e14, height: i } = this.getPageSize(s);
1229
+ this.offsets[s] = t, t += i + this.config.pageGap, e14 > a && (a = e14);
1230
+ }
1231
+ this.totalHeight = e13 > 0 ? t - this.config.pageGap : 0, this.totalWidth = a, this.layoutChange$.emit(this.computeLayout());
1232
+ }
1233
+ applyChapterPageSizes(e13, t) {
1234
+ if (!this.virtualPageMap) return;
1235
+ let a = false;
1236
+ for (const s of t) {
1237
+ const t2 = this.virtualPageMap.toGlobal(e13, s.localPageIndex);
1238
+ if (!t2) continue;
1239
+ const i = this.pageSizes.get(t2.globalPageIndex);
1240
+ i && i.width === s.width && i.height === s.height || (this.pageSizes.set(t2.globalPageIndex, { width: s.width, height: s.height }), a = true);
1241
+ }
1242
+ if (a) {
1243
+ const e14 = this.currentGlobalPageIndex, t2 = this.offsets[e14] ?? 0;
1244
+ if (this.rebuildOffsets(), this.viewportEl) {
1245
+ const a2 = (this.offsets[e14] ?? 0) - t2;
1246
+ 0 !== a2 && (this.viewportEl.scrollTop += a2);
1247
+ }
1248
+ this.recomputeVisible();
1249
+ }
1250
+ }
1251
+ getChapterDocumentScale(e13) {
1252
+ var t;
1253
+ return (null == (t = this.coreState.core.documents[e13]) ? void 0 : t.scale) ?? 1;
1254
+ }
1255
+ harvestChapterSizes(e13, t = 0) {
1256
+ var a;
1257
+ if (!this.virtualPageMap) return;
1258
+ const s = this.documentManager.provides().getDocument(e13), i = this.virtualPageMap.pagesOfChapter(e13);
1259
+ if (!(null == (a = null == s ? void 0 : s.pages) ? void 0 : a.length) || 0 === i.length) return void (t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1)));
1260
+ const o = this.getChapterDocumentScale(e13), r = [];
1261
+ for (const n of i) {
1262
+ const e14 = s.pages[n.localPageIndex];
1263
+ (null == e14 ? void 0 : e14.size) && r.push({ localPageIndex: n.localPageIndex, width: e14.size.width * o, height: e14.size.height * o });
1264
+ }
1265
+ 0 !== r.length ? this.applyChapterPageSizes(e13, r) : t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1));
1266
+ }
1267
+ onScaleChanged(e13) {
1268
+ const t = this.coreState.core.documents[e13];
1269
+ t && "loaded" === t.status && this.chapterManager.provides().getChapter(e13) && this.harvestChapterSizes(e13);
1270
+ }
1271
+ dropChapterSizes(e13) {
1272
+ if (!this.virtualPageMap) return;
1273
+ let t = false;
1274
+ for (const a of this.virtualPageMap.pagesOfChapter(e13)) this.pageSizes.delete(a.globalPageIndex) && (t = true);
1275
+ t && (this.rebuildOffsets(), this.recomputeVisible());
1276
+ }
1277
+ bindViewport(e13) {
1278
+ var t;
1279
+ if (null == (t = this.viewportObservers) || t.unbind(), this.viewportEl = e13, this.viewportObservers = null, !e13) return;
1280
+ const a = () => this.recomputeVisible(), s = new ResizeObserver(() => this.recomputeVisible());
1281
+ e13.addEventListener("scroll", a, { passive: true }), s.observe(e13), this.viewportObservers = { unbind: () => {
1282
+ e13.removeEventListener("scroll", a), s.disconnect();
1283
+ } }, this.syncReadyChapterSizes(), this.recomputeVisible(), 0 === e13.clientHeight && requestAnimationFrame(() => {
1284
+ requestAnimationFrame(() => this.recomputeVisible());
1285
+ });
1286
+ }
1287
+ recomputeVisible() {
1288
+ if (!this.viewportEl || !this.virtualPageMap) return;
1289
+ const e13 = this.virtualPageMap.totalPages;
1290
+ if (0 === e13) return this.currentVisible = [], this.currentGlobalPageIndex = 0, void this.layoutChange$.emit(this.computeLayout());
1291
+ const t = this.viewportEl.scrollTop, a = t + this.viewportEl.clientHeight, s = this.findFirstVisibleIndex(t);
1292
+ let i = s;
1293
+ for (; i < e13; ) {
1294
+ const e14 = this.getPageSize(i), t2 = this.offsets[i];
1295
+ if (e14.height, t2 >= a) break;
1296
+ i++;
1297
+ }
1298
+ const o = [];
1299
+ let r = s, n = -1;
1300
+ for (let l = s; l < i; l++) {
1301
+ o.push(l);
1302
+ const e14 = this.offsets[l], s2 = e14 + this.getPageSize(l).height, i2 = Math.max(0, Math.min(s2, a) - Math.max(e14, t));
1303
+ i2 > n && (n = i2, r = l);
1304
+ }
1305
+ this.currentVisible = o, this.currentGlobalPageIndex = r, this.visibleChange$.emit({ visibleGlobalPageIndices: o, currentGlobalPageIndex: r }), this.chapterManager.provides().setVisibleGlobalPages(o), this.layoutChange$.emit(this.computeLayout());
1306
+ }
1307
+ findFirstVisibleIndex(e13) {
1308
+ let t = 0, a = this.offsets.length - 1, s = 0;
1309
+ for (; t <= a; ) {
1310
+ const i = t + a >> 1;
1311
+ this.offsets[i] <= e13 ? (s = i, t = i + 1) : a = i - 1;
1312
+ }
1313
+ return s;
1314
+ }
1315
+ computeLayout() {
1316
+ const e13 = this.config.bufferSize, t = Math.max(0, (this.currentVisible[0] ?? 0) - e13), a = this.currentVisible[this.currentVisible.length - 1] ?? -1, s = Math.min(this.offsets.length - 1, (a >= 0 ? a : 0) + e13), i = [];
1317
+ if (this.virtualPageMap && this.offsets.length > 0) for (let o = t; o <= s; o++) {
1318
+ const e14 = this.virtualPageMap.atIndex(o);
1319
+ if (!e14) continue;
1320
+ const t2 = this.getPageSize(o), a2 = !this.isChapterDocumentReady(e14.chapterId);
1321
+ i.push({ globalPageIndex: o, globalPageNumber: e14.globalPageNumber, chapterId: e14.chapterId, localPageIndex: e14.localPageIndex, width: t2.width, height: t2.height, offsetTop: this.offsets[o], isPlaceholder: a2 });
1322
+ }
1323
+ return { totalHeight: this.totalHeight, totalWidth: this.totalWidth || this.config.placeholderPageWidth, items: i, pageGap: this.config.pageGap };
1324
+ }
1325
+ scrollToIndex(e13, t) {
1326
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length) return;
1327
+ const a = (this.offsets[e13] ?? 0) - ((null == t ? void 0 : t.topOffset) ?? 0);
1328
+ this.viewportEl.scrollTo({ top: a, behavior: (null == t ? void 0 : t.behavior) ?? "auto" });
1329
+ }
1330
+ scrollToGlobalPdfPoint(e13, t, a) {
1331
+ var s;
1332
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length || !this.virtualPageMap) return;
1333
+ const i = (null == a ? void 0 : a.marginTop) ?? 80, o = this.virtualPageMap.atIndex(e13);
1334
+ if (!o) return void this.scrollToIndex(e13, a);
1335
+ const r = this.pageSizes.get(e13), n = null == (s = this.documentManager.provides().getDocument(o.chapterId)) ? void 0 : s.pages[o.localPageIndex];
1336
+ if (!r || !n) return void this.scrollToIndex(e13, a);
1337
+ const l = r.height / n.size.height, h2 = (this.offsets[e13] ?? 0) + t * l - i;
1338
+ this.viewportEl.scrollTo({ top: Math.max(0, h2), behavior: (null == a ? void 0 : a.behavior) ?? "auto" });
1339
+ }
1340
+ scrollToChapter(e13, t) {
1341
+ if (!this.virtualPageMap) return;
1342
+ const a = this.virtualPageMap.firstIndexOfChapter(e13);
1343
+ a < 0 || (this.chapterManager.provides().ensureChapterLoaded(e13), this.scrollToIndex(a, t));
1344
+ }
1345
+ scrollToGlobalNumber(e13, t) {
1346
+ if (!this.virtualPageMap) return;
1347
+ const a = this.virtualPageMap.byGlobalNumber(e13);
1348
+ a && this.scrollToIndex(a.globalPageIndex, t);
1349
+ }
1350
+ };
1351
+ je.id = "chapter-scroll";
1352
+ let Ye = je;
1353
+ const Ke = class e5 extends BasePlugin {
1354
+ constructor(e13, t) {
1355
+ super(e13, t), this.notesChange$ = createBehaviorEmitter([]), this.noteActivated$ = createEmitter(), this.notes = /* @__PURE__ */ new Map(), this.chapterScroll = this.registry.getPlugin(Ye.id), this.chapterManager = this.registry.getPlugin(Ee.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1356
+ }
1357
+ async initialize(t) {
1358
+ if (this.config = t, t.callbacks.loadNotes) try {
1359
+ const e13 = await t.callbacks.loadNotes();
1360
+ for (const t2 of e13) this.notes.set(t2.noteId, t2);
1361
+ this.notesChange$.emit(this.listAll());
1362
+ } catch (a) {
1363
+ this.logger.error(e5.id, "LoadNotes", "Failed to load notes", a);
1364
+ }
1365
+ }
1366
+ buildCapability() {
1367
+ return { createNoteFromSelection: (e13) => this.createNoteFromSelection(e13), requestCreateFromSelection: (e13) => this.requestCreateFromSelection(e13), registerNote: (e13) => this.registerNote(e13), listNotesForPage: (e13, t) => this.listAll().filter((a) => a.chapterId === e13 && a.localPageIndex === t), listAllNotes: () => this.listAll(), getNote: (e13) => this.notes.get(e13) ?? null, deleteNote: (e13) => this.deleteNote(e13), updateNoteContent: (e13, t) => this.updateNoteContent(e13, t), scrollToNote: (e13) => this.scrollToNote(e13), onNotesChange: this.notesChange$.on, onNoteActivated: this.noteActivated$.on };
1368
+ }
1369
+ registerNote(e13) {
1370
+ this.notes.set(e13.noteId, e13), this.notesChange$.emit(this.listAll());
1371
+ }
1372
+ requestEdit(e13) {
1373
+ const t = this.notes.get(e13);
1374
+ t && (this.config.callbacks.onRequestEditNote ? this.config.callbacks.onRequestEditNote(e13, t) : this.activateNote(e13));
1375
+ }
1376
+ activateNote(e13) {
1377
+ var t, a;
1378
+ const s = this.notes.get(e13);
1379
+ s && (null == (a = (t = this.config.callbacks).onActivateNote) || a.call(t, e13, s), this.noteActivated$.emit({ noteId: e13, anchor: s }));
1380
+ }
1381
+ listAll() {
1382
+ return Array.from(this.notes.values());
1383
+ }
1384
+ buildDraft(e13) {
1385
+ return { chapterId: e13.chapterId, localPageIndex: e13.localPageIndex, globalPageNumber: e13.globalPageNumber, globalPageIndex: e13.globalPageIndex, rectsPdfCoord: e13.rectsPdfCoord, endAnchor: Ze(e13.rectsPdfCoord), selectedText: e13.selectedText, content: e13.content };
1386
+ }
1387
+ async requestCreateFromSelection(e13) {
1388
+ if (0 === e13.rectsPdfCoord.length) return null;
1389
+ const t = this.buildDraft(e13), { onRequestCreateNote: a, onCreateNote: s } = this.config.callbacks;
1390
+ return a ? (a({ draft: t, complete: async (e14) => {
1391
+ const a2 = { ...t, noteId: e14 };
1392
+ this.registerNote(a2);
1393
+ } }), null) : this.createNoteFromSelection(e13);
1394
+ }
1395
+ async createNoteFromSelection(t) {
1396
+ if (0 === t.rectsPdfCoord.length) return null;
1397
+ const a = this.buildDraft(t), s = this.config.callbacks.onCreateNote;
1398
+ if (!s) return this.logger.error(e5.id, "CreateNote", "Missing onCreateNote / onRequestCreateNote"), null;
1399
+ let i = null;
1400
+ try {
1401
+ i = await s(a);
1402
+ } catch (r) {
1403
+ return this.logger.error(e5.id, "OnCreateNote", "Callback failed", r), null;
1404
+ }
1405
+ if (!i) return null;
1406
+ const o = { ...a, noteId: i.noteId };
1407
+ return this.registerNote(o), o;
1408
+ }
1409
+ async deleteNote(t) {
1410
+ var a, s;
1411
+ if (this.notes.has(t)) {
1412
+ try {
1413
+ await (null == (s = (a = this.config.callbacks).onDeleteNote) ? void 0 : s.call(a, t));
1414
+ } catch (i) {
1415
+ return void this.logger.error(e5.id, "OnDeleteNote", "Callback failed", i);
1416
+ }
1417
+ this.notes.delete(t), this.notesChange$.emit(this.listAll());
1418
+ }
1419
+ }
1420
+ async updateNoteContent(t, a) {
1421
+ var s, i;
1422
+ const o = this.notes.get(t);
1423
+ if (!o) return;
1424
+ const r = { ...o, content: a };
1425
+ try {
1426
+ await (null == (i = (s = this.config.callbacks).onUpdateNote) ? void 0 : i.call(s, r));
1427
+ } catch (n) {
1428
+ return void this.logger.error(e5.id, "OnUpdateNote", "Callback failed", n);
1429
+ }
1430
+ this.notes.set(t, r), this.notesChange$.emit(this.listAll());
1431
+ }
1432
+ async scrollToNote(e13) {
1433
+ var t;
1434
+ const a = this.notes.get(e13);
1435
+ if (!a) return;
1436
+ const s = this.chapterScroll.provides();
1437
+ await this.chapterManager.provides().ensureChapterLoaded(a.chapterId);
1438
+ (null == (t = this.documentManager.provides().getDocument(a.chapterId)) ? void 0 : t.pages[a.localPageIndex]) ? (s.scrollToGlobalPageIndex(a.globalPageIndex), await this.waitForPageInLayout(a.globalPageIndex), s.scrollToGlobalPdfPoint(a.globalPageIndex, a.endAnchor.y, { marginTop: 80 })) : s.scrollToGlobalPageIndex(a.globalPageIndex);
1439
+ }
1440
+ waitForPageInLayout(e13) {
1441
+ const t = this.chapterScroll.provides(), a = t.getLayout().items.find((t2) => t2.globalPageIndex === e13 && !t2.isPlaceholder);
1442
+ return a ? Promise.resolve(a) : new Promise((a2) => {
1443
+ const s = setTimeout(() => {
1444
+ i(), a2(null);
1445
+ }, 2500), i = t.onLayoutChange((t2) => {
1446
+ const o = t2.items.find((t3) => t3.globalPageIndex === e13 && !t3.isPlaceholder);
1447
+ o && (clearTimeout(s), i(), a2(o));
1448
+ });
1449
+ });
1450
+ }
1451
+ };
1452
+ Ke.id = "note";
1453
+ let Xe = Ke;
1454
+ function Ze(e13) {
1455
+ const t = e13[e13.length - 1];
1456
+ return { x: t.origin.x + t.size.width, y: t.origin.y + t.size.height };
1457
+ }
1458
+ const Qe = { manifest: Oe, create: (e13) => new Xe(Ge, e13), reducer: (e13) => e13, initialState: {} }, Je = "paragraph-bookmark", et = { id: Je, name: "Paragraph Bookmark Plugin", version: "0.1.0", provides: ["paragraph-bookmark"], requires: ["chapter-scroll", "chapter-manager"], optional: [], defaultConfig: {} };
1459
+ const tt = { kind: "first-wins" };
1460
+ function at(e13, t, a) {
1461
+ if (1 === t.length) return t[0].chapterId;
1462
+ switch (a.kind) {
1463
+ case "first-wins":
1464
+ return t[0].chapterId;
1465
+ case "last-wins":
1466
+ return t[t.length - 1].chapterId;
1467
+ case "explicit": {
1468
+ const a2 = t.find((t2) => {
1469
+ var a3;
1470
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
1471
+ });
1472
+ return a2 ? a2.chapterId : t[0].chapterId;
1473
+ }
1474
+ case "custom":
1475
+ return a.resolve(e13, t);
1476
+ }
1477
+ }
1478
+ let st = class {
1479
+ constructor(e13) {
1480
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
1481
+ for (const t of e13) {
1482
+ this._byGlobalNumber.set(t.globalPageNumber, t);
1483
+ let e14 = this._byChapter.get(t.chapterId);
1484
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
1485
+ }
1486
+ }
1487
+ get totalPages() {
1488
+ return this._pages.length;
1489
+ }
1490
+ list() {
1491
+ return this._pages;
1492
+ }
1493
+ atIndex(e13) {
1494
+ return this._pages[e13] ?? null;
1495
+ }
1496
+ byGlobalNumber(e13) {
1497
+ return this._byGlobalNumber.get(e13) ?? null;
1498
+ }
1499
+ toGlobal(e13, t) {
1500
+ const a = this._byChapter.get(e13);
1501
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
1502
+ }
1503
+ pagesOfChapter(e13) {
1504
+ return this._byChapter.get(e13) ?? [];
1505
+ }
1506
+ firstIndexOfChapter(e13) {
1507
+ var t;
1508
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
1509
+ return a ? this._pages.indexOf(a) : -1;
1510
+ }
1511
+ };
1512
+ function it(e13, t = tt) {
1513
+ const a = (function(e14, t2 = tt) {
1514
+ const a2 = /* @__PURE__ */ new Map();
1515
+ for (const i2 of e14.chapters) {
1516
+ const [e15, t3] = i2.globalPageRange;
1517
+ for (let s3 = e15; s3 <= t3; s3++) {
1518
+ const e16 = a2.get(s3);
1519
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
1520
+ }
1521
+ }
1522
+ const s2 = /* @__PURE__ */ new Map();
1523
+ for (const [i2, o2] of a2) s2.set(i2, at(i2, o2, t2));
1524
+ return s2;
1525
+ })(e13, t), s = /* @__PURE__ */ new Map();
1526
+ for (const n of e13.chapters) s.set(n.chapterId, n);
1527
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
1528
+ let r = 0;
1529
+ for (const n of i) {
1530
+ const e14 = a.get(n), t2 = s.get(e14);
1531
+ if (!t2) continue;
1532
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
1533
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
1534
+ }
1535
+ return new st(o);
1536
+ }
1537
+ const ot = class e6 extends BasePlugin {
1538
+ constructor(e13, t) {
1539
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = tt, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1540
+ }
1541
+ async initialize(e13) {
1542
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? tt, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
1543
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
1544
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
1545
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
1546
+ }), this.documentManager.provides().onDocumentError((e14) => {
1547
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
1548
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
1549
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
1550
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
1551
+ }
1552
+ }
1553
+ buildCapability() {
1554
+ return { setManifest: (e13, t) => {
1555
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
1556
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
1557
+ }
1558
+ destroy() {
1559
+ super.destroy();
1560
+ for (const e13 of this.documentManagerUnsubs) e13();
1561
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
1562
+ }
1563
+ setManifestInternal(t) {
1564
+ const a = (function(e13) {
1565
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
1566
+ for (const s2 of e13.chapters) {
1567
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
1568
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
1569
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
1570
+ }
1571
+ return t2;
1572
+ })(t);
1573
+ a.length > 0 && this.logger.warn(e6.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
1574
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
1575
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
1576
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
1577
+ this.manifest = t, this.virtualPageMap = it(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
1578
+ }
1579
+ eagerPrefetchFromManifest() {
1580
+ const e13 = this.config.prefetchChapters ?? 0;
1581
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
1582
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
1583
+ for (let s = 0; s < a; s++) {
1584
+ const e14 = this.manifest.chapters[s].chapterId;
1585
+ this.chapterLastUsed.set(e14, t);
1586
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
1587
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
1588
+ }
1589
+ }
1590
+ findChapter(e13) {
1591
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
1592
+ }
1593
+ isOwnedChapter(e13) {
1594
+ return !!this.findChapter(e13);
1595
+ }
1596
+ handleVisibleChange(e13) {
1597
+ if (!this.virtualPageMap) return;
1598
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
1599
+ for (const n of e13) {
1600
+ const e14 = this.virtualPageMap.atIndex(n);
1601
+ e14 && s.add(e14.chapterId);
1602
+ }
1603
+ if (0 === s.size) return;
1604
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
1605
+ for (const n of s) {
1606
+ const e14 = i.indexOf(n);
1607
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
1608
+ }
1609
+ const r = /* @__PURE__ */ new Set();
1610
+ for (const n of o) r.add(i[n]);
1611
+ for (const n of r) {
1612
+ this.chapterLastUsed.set(n, t);
1613
+ const e14 = this.chapterStatus.get(n) ?? "idle";
1614
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
1615
+ }
1616
+ if (this.config.autoActivateOnLoad ?? 1) {
1617
+ const e14 = i.find((e15) => s.has(e15));
1618
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
1619
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
1620
+ }
1621
+ }
1622
+ }
1623
+ collectIdleChapters() {
1624
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
1625
+ if (e13 <= 0) return;
1626
+ const t = Date.now();
1627
+ for (const [a, s] of this.chapterStatus) {
1628
+ if ("loaded" !== s) continue;
1629
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
1630
+ }
1631
+ }
1632
+ ensureChapterLoaded(e13) {
1633
+ const t = this.pendingLoadPromises.get(e13);
1634
+ if (t) return t;
1635
+ const a = this.findChapter(e13);
1636
+ if (!a) return Promise.resolve("error");
1637
+ const s = this.chapterStatus.get(e13) ?? "idle";
1638
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
1639
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
1640
+ const i = this.startLoad(a).finally(() => {
1641
+ this.pendingLoadPromises.delete(e13);
1642
+ });
1643
+ return this.pendingLoadPromises.set(e13, i), i;
1644
+ }
1645
+ async resolvePdfPayload(e13) {
1646
+ const t = e13.source;
1647
+ if (t) {
1648
+ if ("url" in t) return { url: t.url };
1649
+ if ("buffer" in t) return { buffer: t.buffer };
1650
+ if ("load" in t) return t.load();
1651
+ }
1652
+ const a = this.config.chapterPdfLoader;
1653
+ if (a) return a.loadPdf(e13);
1654
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
1655
+ }
1656
+ async startLoad(e13) {
1657
+ var t;
1658
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
1659
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
1660
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
1661
+ }
1662
+ waitForTerminalStatus(e13) {
1663
+ return new Promise((t) => {
1664
+ const a = (e14) => {
1665
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
1666
+ }, s = this.statusChange$.on((t2) => {
1667
+ t2.chapterId === e13 && a(t2.status);
1668
+ });
1669
+ a(this.chapterStatus.get(e13) ?? "idle");
1670
+ });
1671
+ }
1672
+ async handleDocumentError(t, a, s) {
1673
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
1674
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
1675
+ const i = this.findChapter(t);
1676
+ if (!i) return;
1677
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
1678
+ this.passwordAttempts.set(t, o);
1679
+ let r = null;
1680
+ try {
1681
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
1682
+ } catch (n) {
1683
+ this.logger.error(e6.id, "PasswordProvider", `Provider rejected for ${t}`, n);
1684
+ }
1685
+ if (!r) return void this.updateStatus(t, "password-required");
1686
+ this.updateStatus(t, "loading");
1687
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
1688
+ }, () => {
1689
+ });
1690
+ }
1691
+ closeChapter(e13) {
1692
+ const t = this.documentManager.provides();
1693
+ if (t.isDocumentOpen(e13)) {
1694
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
1695
+ } else this.updateStatus(e13, "closed");
1696
+ }
1697
+ updateStatus(e13, t, a) {
1698
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
1699
+ }
1700
+ };
1701
+ ot.id = "chapter-manager";
1702
+ let rt = ot;
1703
+ const nt = { kind: "first-wins" };
1704
+ function lt(e13, t, a) {
1705
+ if (1 === t.length) return t[0].chapterId;
1706
+ switch (a.kind) {
1707
+ case "first-wins":
1708
+ return t[0].chapterId;
1709
+ case "last-wins":
1710
+ return t[t.length - 1].chapterId;
1711
+ case "explicit": {
1712
+ const a2 = t.find((t2) => {
1713
+ var a3;
1714
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
1715
+ });
1716
+ return a2 ? a2.chapterId : t[0].chapterId;
1717
+ }
1718
+ case "custom":
1719
+ return a.resolve(e13, t);
1720
+ }
1721
+ }
1722
+ let ht = class {
1723
+ constructor(e13) {
1724
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
1725
+ for (const t of e13) {
1726
+ this._byGlobalNumber.set(t.globalPageNumber, t);
1727
+ let e14 = this._byChapter.get(t.chapterId);
1728
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
1729
+ }
1730
+ }
1731
+ get totalPages() {
1732
+ return this._pages.length;
1733
+ }
1734
+ list() {
1735
+ return this._pages;
1736
+ }
1737
+ atIndex(e13) {
1738
+ return this._pages[e13] ?? null;
1739
+ }
1740
+ byGlobalNumber(e13) {
1741
+ return this._byGlobalNumber.get(e13) ?? null;
1742
+ }
1743
+ toGlobal(e13, t) {
1744
+ const a = this._byChapter.get(e13);
1745
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
1746
+ }
1747
+ pagesOfChapter(e13) {
1748
+ return this._byChapter.get(e13) ?? [];
1749
+ }
1750
+ firstIndexOfChapter(e13) {
1751
+ var t;
1752
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
1753
+ return a ? this._pages.indexOf(a) : -1;
1754
+ }
1755
+ };
1756
+ function dt(e13, t = nt) {
1757
+ const a = (function(e14, t2 = nt) {
1758
+ const a2 = /* @__PURE__ */ new Map();
1759
+ for (const i2 of e14.chapters) {
1760
+ const [e15, t3] = i2.globalPageRange;
1761
+ for (let s3 = e15; s3 <= t3; s3++) {
1762
+ const e16 = a2.get(s3);
1763
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
1764
+ }
1765
+ }
1766
+ const s2 = /* @__PURE__ */ new Map();
1767
+ for (const [i2, o2] of a2) s2.set(i2, lt(i2, o2, t2));
1768
+ return s2;
1769
+ })(e13, t), s = /* @__PURE__ */ new Map();
1770
+ for (const n of e13.chapters) s.set(n.chapterId, n);
1771
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
1772
+ let r = 0;
1773
+ for (const n of i) {
1774
+ const e14 = a.get(n), t2 = s.get(e14);
1775
+ if (!t2) continue;
1776
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
1777
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
1778
+ }
1779
+ return new ht(o);
1780
+ }
1781
+ const ct = class e7 extends BasePlugin {
1782
+ constructor(e13, t) {
1783
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = nt, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1784
+ }
1785
+ async initialize(e13) {
1786
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? nt, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
1787
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
1788
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
1789
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
1790
+ }), this.documentManager.provides().onDocumentError((e14) => {
1791
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
1792
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
1793
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
1794
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
1795
+ }
1796
+ }
1797
+ buildCapability() {
1798
+ return { setManifest: (e13, t) => {
1799
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
1800
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
1801
+ }
1802
+ destroy() {
1803
+ super.destroy();
1804
+ for (const e13 of this.documentManagerUnsubs) e13();
1805
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
1806
+ }
1807
+ setManifestInternal(t) {
1808
+ const a = (function(e13) {
1809
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
1810
+ for (const s2 of e13.chapters) {
1811
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
1812
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
1813
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
1814
+ }
1815
+ return t2;
1816
+ })(t);
1817
+ a.length > 0 && this.logger.warn(e7.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
1818
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
1819
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
1820
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
1821
+ this.manifest = t, this.virtualPageMap = dt(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
1822
+ }
1823
+ eagerPrefetchFromManifest() {
1824
+ const e13 = this.config.prefetchChapters ?? 0;
1825
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
1826
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
1827
+ for (let s = 0; s < a; s++) {
1828
+ const e14 = this.manifest.chapters[s].chapterId;
1829
+ this.chapterLastUsed.set(e14, t);
1830
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
1831
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
1832
+ }
1833
+ }
1834
+ findChapter(e13) {
1835
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
1836
+ }
1837
+ isOwnedChapter(e13) {
1838
+ return !!this.findChapter(e13);
1839
+ }
1840
+ handleVisibleChange(e13) {
1841
+ if (!this.virtualPageMap) return;
1842
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
1843
+ for (const n of e13) {
1844
+ const e14 = this.virtualPageMap.atIndex(n);
1845
+ e14 && s.add(e14.chapterId);
1846
+ }
1847
+ if (0 === s.size) return;
1848
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
1849
+ for (const n of s) {
1850
+ const e14 = i.indexOf(n);
1851
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
1852
+ }
1853
+ const r = /* @__PURE__ */ new Set();
1854
+ for (const n of o) r.add(i[n]);
1855
+ for (const n of r) {
1856
+ this.chapterLastUsed.set(n, t);
1857
+ const e14 = this.chapterStatus.get(n) ?? "idle";
1858
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
1859
+ }
1860
+ if (this.config.autoActivateOnLoad ?? 1) {
1861
+ const e14 = i.find((e15) => s.has(e15));
1862
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
1863
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
1864
+ }
1865
+ }
1866
+ }
1867
+ collectIdleChapters() {
1868
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
1869
+ if (e13 <= 0) return;
1870
+ const t = Date.now();
1871
+ for (const [a, s] of this.chapterStatus) {
1872
+ if ("loaded" !== s) continue;
1873
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
1874
+ }
1875
+ }
1876
+ ensureChapterLoaded(e13) {
1877
+ const t = this.pendingLoadPromises.get(e13);
1878
+ if (t) return t;
1879
+ const a = this.findChapter(e13);
1880
+ if (!a) return Promise.resolve("error");
1881
+ const s = this.chapterStatus.get(e13) ?? "idle";
1882
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
1883
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
1884
+ const i = this.startLoad(a).finally(() => {
1885
+ this.pendingLoadPromises.delete(e13);
1886
+ });
1887
+ return this.pendingLoadPromises.set(e13, i), i;
1888
+ }
1889
+ async resolvePdfPayload(e13) {
1890
+ const t = e13.source;
1891
+ if (t) {
1892
+ if ("url" in t) return { url: t.url };
1893
+ if ("buffer" in t) return { buffer: t.buffer };
1894
+ if ("load" in t) return t.load();
1895
+ }
1896
+ const a = this.config.chapterPdfLoader;
1897
+ if (a) return a.loadPdf(e13);
1898
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
1899
+ }
1900
+ async startLoad(e13) {
1901
+ var t;
1902
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
1903
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
1904
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
1905
+ }
1906
+ waitForTerminalStatus(e13) {
1907
+ return new Promise((t) => {
1908
+ const a = (e14) => {
1909
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
1910
+ }, s = this.statusChange$.on((t2) => {
1911
+ t2.chapterId === e13 && a(t2.status);
1912
+ });
1913
+ a(this.chapterStatus.get(e13) ?? "idle");
1914
+ });
1915
+ }
1916
+ async handleDocumentError(t, a, s) {
1917
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
1918
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
1919
+ const i = this.findChapter(t);
1920
+ if (!i) return;
1921
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
1922
+ this.passwordAttempts.set(t, o);
1923
+ let r = null;
1924
+ try {
1925
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
1926
+ } catch (n) {
1927
+ this.logger.error(e7.id, "PasswordProvider", `Provider rejected for ${t}`, n);
1928
+ }
1929
+ if (!r) return void this.updateStatus(t, "password-required");
1930
+ this.updateStatus(t, "loading");
1931
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
1932
+ }, () => {
1933
+ });
1934
+ }
1935
+ closeChapter(e13) {
1936
+ const t = this.documentManager.provides();
1937
+ if (t.isDocumentOpen(e13)) {
1938
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
1939
+ } else this.updateStatus(e13, "closed");
1940
+ }
1941
+ updateStatus(e13, t, a) {
1942
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
1943
+ }
1944
+ };
1945
+ ct.id = "chapter-manager";
1946
+ let ut = ct;
1947
+ const pt = class extends BasePlugin {
1948
+ constructor(e13, t) {
1949
+ super(e13, t), this.layoutChange$ = createBehaviorEmitter(), this.visibleChange$ = createBehaviorEmitter(), this.virtualPageMap = null, this.pageSizes = /* @__PURE__ */ new Map(), this.offsets = [], this.totalHeight = 0, this.totalWidth = 0, this.viewportEl = null, this.viewportObservers = null, this.currentVisible = [], this.currentGlobalPageIndex = 0, this.chapterManagerUnsubs = [], this.chapterManager = this.registry.getPlugin(ut.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
1950
+ }
1951
+ async initialize(e13) {
1952
+ this.config = { placeholderPageHeight: e13.placeholderPageHeight ?? 1200, placeholderPageWidth: e13.placeholderPageWidth ?? 900, bufferSize: e13.bufferSize ?? 2, pageGap: e13.pageGap ?? 20 }, this.virtualPageMap = this.chapterManager.provides().getVirtualPageMap(), this.rebuildOffsets(), this.chapterManagerUnsubs.push(this.chapterManager.provides().onManifestChange(({ map: e14 }) => {
1953
+ this.virtualPageMap = e14, this.pageSizes.clear(), this.rebuildOffsets(), this.syncReadyChapterSizes(), this.recomputeVisible();
1954
+ })), this.syncReadyChapterSizes();
1955
+ }
1956
+ isChapterDocumentReady(e13) {
1957
+ const t = this.coreState.core.documents[e13];
1958
+ return !(!t || "loaded" !== t.status || !t.document) && t.document.pages.length > 0;
1959
+ }
1960
+ refreshLayout() {
1961
+ this.layoutChange$.emit(this.computeLayout());
1962
+ }
1963
+ syncReadyChapterSizes() {
1964
+ for (const e13 of this.chapterManager.provides().getManifest().chapters) this.isChapterDocumentReady(e13.chapterId) && this.harvestChapterSizes(e13.chapterId);
1965
+ this.refreshLayout();
1966
+ }
1967
+ onDocumentLoaded(e13) {
1968
+ var t;
1969
+ if (0 === ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0)) return;
1970
+ const a = this.documentManager.provides();
1971
+ a.getActiveDocumentId() || a.setActiveDocument(e13), this.harvestChapterSizes(e13), this.refreshLayout();
1972
+ }
1973
+ onDocumentClosed(e13) {
1974
+ var t;
1975
+ 0 !== ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0) && (this.dropChapterSizes(e13), this.refreshLayout());
1976
+ }
1977
+ buildCapability() {
1978
+ return { registerViewport: (e13) => this.bindViewport(e13), reportChapterPageSizes: (e13, t) => this.applyChapterPageSizes(e13, t), getLayout: () => this.computeLayout(), getCurrentGlobalPageIndex: () => this.currentGlobalPageIndex, getVisibleGlobalPageIndices: () => this.currentVisible.slice(), scrollToGlobalPageIndex: (e13, t) => this.scrollToIndex(e13, t), scrollToChapter: (e13, t) => this.scrollToChapter(e13, t), scrollToGlobalPageNumber: (e13, t) => this.scrollToGlobalNumber(e13, t), scrollToGlobalPdfPoint: (e13, t, a) => this.scrollToGlobalPdfPoint(e13, t, a), onLayoutChange: this.layoutChange$.on, onVisibleChange: this.visibleChange$.on };
1979
+ }
1980
+ destroy() {
1981
+ var e13;
1982
+ super.destroy();
1983
+ for (const t of this.chapterManagerUnsubs) t();
1984
+ this.chapterManagerUnsubs = [], null == (e13 = this.viewportObservers) || e13.unbind(), this.viewportObservers = null, this.viewportEl = null, this.layoutChange$.clear(), this.visibleChange$.clear();
1985
+ }
1986
+ getPageSize(e13) {
1987
+ return this.pageSizes.get(e13) ?? { width: this.config.placeholderPageWidth, height: this.config.placeholderPageHeight };
1988
+ }
1989
+ rebuildOffsets() {
1990
+ if (!this.virtualPageMap) return this.offsets = [], this.totalHeight = 0, void (this.totalWidth = 0);
1991
+ const e13 = this.virtualPageMap.totalPages;
1992
+ this.offsets = new Array(e13);
1993
+ let t = 0, a = 0;
1994
+ for (let s = 0; s < e13; s++) {
1995
+ const { width: e14, height: i } = this.getPageSize(s);
1996
+ this.offsets[s] = t, t += i + this.config.pageGap, e14 > a && (a = e14);
1997
+ }
1998
+ this.totalHeight = e13 > 0 ? t - this.config.pageGap : 0, this.totalWidth = a, this.layoutChange$.emit(this.computeLayout());
1999
+ }
2000
+ applyChapterPageSizes(e13, t) {
2001
+ if (!this.virtualPageMap) return;
2002
+ let a = false;
2003
+ for (const s of t) {
2004
+ const t2 = this.virtualPageMap.toGlobal(e13, s.localPageIndex);
2005
+ if (!t2) continue;
2006
+ const i = this.pageSizes.get(t2.globalPageIndex);
2007
+ i && i.width === s.width && i.height === s.height || (this.pageSizes.set(t2.globalPageIndex, { width: s.width, height: s.height }), a = true);
2008
+ }
2009
+ if (a) {
2010
+ const e14 = this.currentGlobalPageIndex, t2 = this.offsets[e14] ?? 0;
2011
+ if (this.rebuildOffsets(), this.viewportEl) {
2012
+ const a2 = (this.offsets[e14] ?? 0) - t2;
2013
+ 0 !== a2 && (this.viewportEl.scrollTop += a2);
2014
+ }
2015
+ this.recomputeVisible();
2016
+ }
2017
+ }
2018
+ getChapterDocumentScale(e13) {
2019
+ var t;
2020
+ return (null == (t = this.coreState.core.documents[e13]) ? void 0 : t.scale) ?? 1;
2021
+ }
2022
+ harvestChapterSizes(e13, t = 0) {
2023
+ var a;
2024
+ if (!this.virtualPageMap) return;
2025
+ const s = this.documentManager.provides().getDocument(e13), i = this.virtualPageMap.pagesOfChapter(e13);
2026
+ if (!(null == (a = null == s ? void 0 : s.pages) ? void 0 : a.length) || 0 === i.length) return void (t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1)));
2027
+ const o = this.getChapterDocumentScale(e13), r = [];
2028
+ for (const n of i) {
2029
+ const e14 = s.pages[n.localPageIndex];
2030
+ (null == e14 ? void 0 : e14.size) && r.push({ localPageIndex: n.localPageIndex, width: e14.size.width * o, height: e14.size.height * o });
2031
+ }
2032
+ 0 !== r.length ? this.applyChapterPageSizes(e13, r) : t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1));
2033
+ }
2034
+ onScaleChanged(e13) {
2035
+ const t = this.coreState.core.documents[e13];
2036
+ t && "loaded" === t.status && this.chapterManager.provides().getChapter(e13) && this.harvestChapterSizes(e13);
2037
+ }
2038
+ dropChapterSizes(e13) {
2039
+ if (!this.virtualPageMap) return;
2040
+ let t = false;
2041
+ for (const a of this.virtualPageMap.pagesOfChapter(e13)) this.pageSizes.delete(a.globalPageIndex) && (t = true);
2042
+ t && (this.rebuildOffsets(), this.recomputeVisible());
2043
+ }
2044
+ bindViewport(e13) {
2045
+ var t;
2046
+ if (null == (t = this.viewportObservers) || t.unbind(), this.viewportEl = e13, this.viewportObservers = null, !e13) return;
2047
+ const a = () => this.recomputeVisible(), s = new ResizeObserver(() => this.recomputeVisible());
2048
+ e13.addEventListener("scroll", a, { passive: true }), s.observe(e13), this.viewportObservers = { unbind: () => {
2049
+ e13.removeEventListener("scroll", a), s.disconnect();
2050
+ } }, this.syncReadyChapterSizes(), this.recomputeVisible(), 0 === e13.clientHeight && requestAnimationFrame(() => {
2051
+ requestAnimationFrame(() => this.recomputeVisible());
2052
+ });
2053
+ }
2054
+ recomputeVisible() {
2055
+ if (!this.viewportEl || !this.virtualPageMap) return;
2056
+ const e13 = this.virtualPageMap.totalPages;
2057
+ if (0 === e13) return this.currentVisible = [], this.currentGlobalPageIndex = 0, void this.layoutChange$.emit(this.computeLayout());
2058
+ const t = this.viewportEl.scrollTop, a = t + this.viewportEl.clientHeight, s = this.findFirstVisibleIndex(t);
2059
+ let i = s;
2060
+ for (; i < e13; ) {
2061
+ const e14 = this.getPageSize(i), t2 = this.offsets[i];
2062
+ if (e14.height, t2 >= a) break;
2063
+ i++;
2064
+ }
2065
+ const o = [];
2066
+ let r = s, n = -1;
2067
+ for (let l = s; l < i; l++) {
2068
+ o.push(l);
2069
+ const e14 = this.offsets[l], s2 = e14 + this.getPageSize(l).height, i2 = Math.max(0, Math.min(s2, a) - Math.max(e14, t));
2070
+ i2 > n && (n = i2, r = l);
2071
+ }
2072
+ this.currentVisible = o, this.currentGlobalPageIndex = r, this.visibleChange$.emit({ visibleGlobalPageIndices: o, currentGlobalPageIndex: r }), this.chapterManager.provides().setVisibleGlobalPages(o), this.layoutChange$.emit(this.computeLayout());
2073
+ }
2074
+ findFirstVisibleIndex(e13) {
2075
+ let t = 0, a = this.offsets.length - 1, s = 0;
2076
+ for (; t <= a; ) {
2077
+ const i = t + a >> 1;
2078
+ this.offsets[i] <= e13 ? (s = i, t = i + 1) : a = i - 1;
2079
+ }
2080
+ return s;
2081
+ }
2082
+ computeLayout() {
2083
+ const e13 = this.config.bufferSize, t = Math.max(0, (this.currentVisible[0] ?? 0) - e13), a = this.currentVisible[this.currentVisible.length - 1] ?? -1, s = Math.min(this.offsets.length - 1, (a >= 0 ? a : 0) + e13), i = [];
2084
+ if (this.virtualPageMap && this.offsets.length > 0) for (let o = t; o <= s; o++) {
2085
+ const e14 = this.virtualPageMap.atIndex(o);
2086
+ if (!e14) continue;
2087
+ const t2 = this.getPageSize(o), a2 = !this.isChapterDocumentReady(e14.chapterId);
2088
+ i.push({ globalPageIndex: o, globalPageNumber: e14.globalPageNumber, chapterId: e14.chapterId, localPageIndex: e14.localPageIndex, width: t2.width, height: t2.height, offsetTop: this.offsets[o], isPlaceholder: a2 });
2089
+ }
2090
+ return { totalHeight: this.totalHeight, totalWidth: this.totalWidth || this.config.placeholderPageWidth, items: i, pageGap: this.config.pageGap };
2091
+ }
2092
+ scrollToIndex(e13, t) {
2093
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length) return;
2094
+ const a = (this.offsets[e13] ?? 0) - ((null == t ? void 0 : t.topOffset) ?? 0);
2095
+ this.viewportEl.scrollTo({ top: a, behavior: (null == t ? void 0 : t.behavior) ?? "auto" });
2096
+ }
2097
+ scrollToGlobalPdfPoint(e13, t, a) {
2098
+ var s;
2099
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length || !this.virtualPageMap) return;
2100
+ const i = (null == a ? void 0 : a.marginTop) ?? 80, o = this.virtualPageMap.atIndex(e13);
2101
+ if (!o) return void this.scrollToIndex(e13, a);
2102
+ const r = this.pageSizes.get(e13), n = null == (s = this.documentManager.provides().getDocument(o.chapterId)) ? void 0 : s.pages[o.localPageIndex];
2103
+ if (!r || !n) return void this.scrollToIndex(e13, a);
2104
+ const l = r.height / n.size.height, h2 = (this.offsets[e13] ?? 0) + t * l - i;
2105
+ this.viewportEl.scrollTo({ top: Math.max(0, h2), behavior: (null == a ? void 0 : a.behavior) ?? "auto" });
2106
+ }
2107
+ scrollToChapter(e13, t) {
2108
+ if (!this.virtualPageMap) return;
2109
+ const a = this.virtualPageMap.firstIndexOfChapter(e13);
2110
+ a < 0 || (this.chapterManager.provides().ensureChapterLoaded(e13), this.scrollToIndex(a, t));
2111
+ }
2112
+ scrollToGlobalNumber(e13, t) {
2113
+ if (!this.virtualPageMap) return;
2114
+ const a = this.virtualPageMap.byGlobalNumber(e13);
2115
+ a && this.scrollToIndex(a.globalPageIndex, t);
2116
+ }
2117
+ };
2118
+ pt.id = "chapter-scroll";
2119
+ let gt = pt;
2120
+ function ft(e13) {
2121
+ if (0 === e13.length) throw new Error("unionRects: empty rects");
2122
+ let t = 1 / 0, a = 1 / 0, s = -1 / 0, i = -1 / 0;
2123
+ for (const o of e13) t = Math.min(t, o.origin.x), a = Math.min(a, o.origin.y), s = Math.max(s, o.origin.x + o.size.width), i = Math.max(i, o.origin.y + o.size.height);
2124
+ return { origin: { x: t, y: a }, size: { width: s - t, height: i - a } };
2125
+ }
2126
+ function mt(e13) {
2127
+ const t = e13[e13.length - 1];
2128
+ return { x: t.origin.x + t.size.width, y: t.origin.y + t.size.height };
2129
+ }
2130
+ function vt(e13, t) {
2131
+ const a = e13.origin.y, s = e13.origin.y + e13.size.height, i = t.origin.y, o = t.origin.y + t.size.height, r = Math.max(s, o) - Math.min(a, i);
2132
+ if (r <= 0) return 0;
2133
+ return Math.max(0, Math.min(s, o) - Math.max(a, i)) / r;
2134
+ }
2135
+ function bt(e13, t) {
2136
+ var a, s;
2137
+ if (e13.chapterId !== t.chapterId || e13.localPageIndex !== t.localPageIndex) return false;
2138
+ const i = (null == (a = e13.rectsPdfCoord) ? void 0 : a.length) ? e13.rectsPdfCoord : [e13.rectPdfCoord], o = (null == (s = t.rectsPdfCoord) ? void 0 : s.length) ? t.rectsPdfCoord : [t.rectPdfCoord], r = e13.markerAnchor ?? mt(i), n = t.markerAnchor ?? mt(o);
2139
+ if (Math.hypot(r.x - n.x, r.y - n.y) <= 6) return true;
2140
+ for (const l of i) for (const e14 of o) {
2141
+ if (vt(l, e14) < 0.5) continue;
2142
+ const t2 = Math.max(l.origin.x, e14.origin.x);
2143
+ if (Math.min(l.origin.x + l.size.width, e14.origin.x + e14.size.width) - t2 > 0.25 * Math.min(l.size.width, e14.size.width)) return true;
2144
+ }
2145
+ return false;
2146
+ }
2147
+ function Pt(e13, t, a, s) {
2148
+ const i = a.length > 0 ? a : [];
2149
+ if (0 === i.length) throw new Error("buildParagraphBookmarkAnchor: no rects");
2150
+ return { chapterId: e13, localPageIndex: t, globalPageIndex: null == s ? void 0 : s.globalPageIndex, globalPageNumber: null == s ? void 0 : s.globalPageNumber, rectPdfCoord: ft(i), rectsPdfCoord: i, markerAnchor: mt(i) };
2151
+ }
2152
+ async function wt(e13, t, a) {
2153
+ e13.scrollToGlobalPageIndex(t), await (function(e14, t2, a2 = 2500) {
2154
+ const s = e14.getLayout().items.find((e15) => e15.globalPageIndex === t2 && !e15.isPlaceholder);
2155
+ return s ? Promise.resolve(s) : new Promise((s2) => {
2156
+ const i = setTimeout(() => {
2157
+ o(), s2(null);
2158
+ }, a2), o = e14.onLayoutChange((e15) => {
2159
+ const a3 = e15.items.find((e16) => e16.globalPageIndex === t2 && !e16.isPlaceholder);
2160
+ a3 && (clearTimeout(i), o(), s2(a3));
2161
+ });
2162
+ });
2163
+ })(e13, t), e13.scrollToGlobalPdfPoint(t, a, { marginTop: 80 });
2164
+ }
2165
+ const yt = class e8 extends BasePlugin {
2166
+ constructor(e13, t) {
2167
+ super(e13, t), this.change$ = createBehaviorEmitter([]), this.entries = /* @__PURE__ */ new Map(), this.chapterScroll = this.registry.getPlugin(gt.id), this.chapterManager = this.registry.getPlugin(rt.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
2168
+ }
2169
+ async initialize(t) {
2170
+ var a;
2171
+ if (this.config = t, null == (a = t.callbacks) ? void 0 : a.load) try {
2172
+ const e13 = await t.callbacks.load();
2173
+ for (const t2 of e13) this.entries.set(t2.id, t2);
2174
+ this.change$.emit(this.list());
2175
+ } catch (s) {
2176
+ this.logger.error(e8.id, "Load", "Failed to load paragraph bookmarks", s);
2177
+ }
2178
+ }
2179
+ buildCapability() {
2180
+ return { addBookmark: (e13) => this.addBookmark(e13), removeBookmark: (e13) => this.removeBookmark(e13), updateBookmark: (e13, t) => this.updateBookmark(e13, t), listBookmarks: () => this.list(), getBookmark: (e13) => this.entries.get(e13) ?? null, scrollToBookmark: (e13) => this.scrollToBookmark(e13), requestRemoveBookmark: (e13) => this.requestRemoveBookmark(e13), onBookmarksChange: this.change$.on };
2181
+ }
2182
+ addBookmark(e13) {
2183
+ for (const s of this.entries.values()) if (bt(s.anchor, e13.anchor)) return s;
2184
+ const t = e13.id ?? `bm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, a = { id: t, label: e13.label, anchor: e13.anchor, metadata: e13.metadata, createdAt: Date.now() };
2185
+ return this.entries.set(t, a), this.notifyAndPersist(), a;
2186
+ }
2187
+ removeBookmark(e13) {
2188
+ var t, a, s;
2189
+ this.entries.delete(e13) && (this.notifyAndPersist(), null == (s = null == (a = null == (t = this.config) ? void 0 : t.callbacks) ? void 0 : a.onRemoveSuccess) || s.call(a, e13));
2190
+ }
2191
+ async requestRemoveBookmark(t) {
2192
+ var a, s;
2193
+ const i = this.entries.get(t);
2194
+ if (!i) return false;
2195
+ const o = null == (s = null == (a = this.config) ? void 0 : a.callbacks) ? void 0 : s.onRequestRemove;
2196
+ if (o) try {
2197
+ if (!await o(i)) return false;
2198
+ } catch (r) {
2199
+ return this.logger.error(e8.id, "RequestRemove", "callback failed", r), false;
2200
+ }
2201
+ return this.removeBookmark(t), true;
2202
+ }
2203
+ updateBookmark(e13, t) {
2204
+ const a = this.entries.get(e13);
2205
+ a && (this.entries.set(e13, { ...a, ...t }), this.notifyAndPersist());
2206
+ }
2207
+ list() {
2208
+ return Array.from(this.entries.values()).sort((e13, t) => e13.createdAt - t.createdAt);
2209
+ }
2210
+ notifyAndPersist() {
2211
+ var t, a;
2212
+ const s = this.list();
2213
+ this.change$.emit(s), (null == (a = null == (t = this.config) ? void 0 : t.callbacks) ? void 0 : a.persist) && Promise.resolve(this.config.callbacks.persist(s)).catch((t2) => this.logger.error(e8.id, "Persist", "persist callback rejected", t2));
2214
+ }
2215
+ async scrollToBookmark(e13) {
2216
+ const t = this.entries.get(e13);
2217
+ if (!t) return;
2218
+ const a = this.chapterScroll.provides();
2219
+ await this.chapterManager.provides().ensureChapterLoaded(t.anchor.chapterId);
2220
+ let s = t.anchor.globalPageIndex;
2221
+ if (void 0 === s) {
2222
+ const e14 = this.chapterManager.provides().getVirtualPageMap().toGlobal(t.anchor.chapterId, t.anchor.localPageIndex);
2223
+ if (!e14) return;
2224
+ s = e14.globalPageIndex;
2225
+ }
2226
+ const i = (function(e14) {
2227
+ if (e14.markerAnchor) return e14.markerAnchor.y;
2228
+ const t2 = e14.rectPdfCoord;
2229
+ return t2.origin.y + t2.size.height;
2230
+ })(t.anchor);
2231
+ await wt(a, s, i);
2232
+ }
2233
+ };
2234
+ yt.id = "paragraph-bookmark";
2235
+ let It = yt;
2236
+ const Ct = { manifest: et, create: (e13) => new It(Je, e13), reducer: (e13) => e13, initialState: {} }, Mt = { "annotation-toolbar": { id: "annotation-toolbar", position: { placement: "top", slot: "secondary", order: 0 }, responsive: { breakpoints: { sm: { maxWidth: 640, hide: ["add-text", "add-ink", "add-ink-highlighter", "add-insert-text", "add-replace-text", "add-comment", "add-callout"], show: ["overflow-annotation-tools"] }, md: { minWidth: 640, hide: ["overflow-annotation-tools"], show: ["add-text", "add-ink", "add-ink-highlighter", "add-insert-text", "add-replace-text", "add-comment", "add-callout"] } } }, permanent: false, categories: ["annotation"], items: [{ type: "spacer", id: "spacer-3", flex: true }, { type: "group", id: "annotation-tools", alignment: "start", gap: 2, items: [{ type: "command-button", id: "add-highlight", commandId: "annotation:add-highlight", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-highlight"] }, { type: "command-button", id: "add-strikeout", commandId: "annotation:add-strikeout", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-strikeout"] }, { type: "command-button", id: "add-underline", commandId: "annotation:add-underline", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-underline"] }, { type: "command-button", id: "add-squiggly", commandId: "annotation:add-squiggly", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-squiggly"] }, { type: "command-button", id: "add-ink", commandId: "annotation:add-ink", variant: "icon", categories: ["annotation", "annotation-ink"] }, { type: "command-button", id: "add-ink-highlighter", commandId: "annotation:add-ink-highlighter", variant: "icon", categories: ["annotation", "annotation-ink"] }, { type: "command-button", id: "add-text", commandId: "annotation:add-text", variant: "icon", categories: ["annotation", "annotation-text"] }, { type: "command-button", id: "add-insert-text", commandId: "annotation:add-insert-text", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-insert-text"] }, { type: "command-button", id: "add-replace-text", commandId: "annotation:add-replace-text", variant: "icon", categories: ["annotation", "annotation-markup", "annotation-replace-text"] }, { type: "command-button", id: "add-comment", commandId: "annotation:add-comment", variant: "icon", categories: ["annotation", "annotation-comment-tool"] }, { type: "command-button", id: "add-callout", commandId: "annotation:add-callout", variant: "icon", categories: ["annotation", "annotation-text"] }, { type: "command-button", id: "overflow-annotation-tools", commandId: "annotation:overflow-tools", variant: "icon", categories: ["annotation", "annotation-overflow"] }, { type: "divider", id: "annotation-tools-divider-1", orientation: "vertical" }, { type: "command-button", id: "toggle-annotation-style", commandId: "panel:toggle-annotation-style", variant: "icon", categories: ["panel", "panel-annotation-style"] }, { type: "divider", id: "annotation-tools-divider-2", orientation: "vertical", visibilityDependsOn: { itemIds: ["toggle-annotation-style"] } }, { type: "command-button", id: "undo-button", commandId: "history:undo", variant: "icon", categories: ["history", "history-undo"] }, { type: "command-button", id: "redo-button", commandId: "history:redo", variant: "icon", categories: ["history", "history-redo"] }] }, { type: "spacer", id: "spacer-4", flex: true }] }, "shapes-toolbar": { id: "shapes-toolbar", position: { placement: "top", slot: "secondary", order: 0 }, responsive: { breakpoints: { sm: { maxWidth: 640, hide: ["add-polygon", "add-polyline"], show: ["overflow-shapes-tools"] }, md: { minWidth: 640, hide: ["overflow-shapes-tools"], show: ["add-polygon", "add-polyline"] } } }, permanent: false, categories: ["annotation", "annotation-shape"], items: [{ type: "spacer", id: "spacer-5", flex: true }, { type: "group", id: "shapes-tools", alignment: "start", gap: 2, items: [{ type: "command-button", id: "add-rectangle", commandId: "annotation:add-rectangle", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-rectangle"] }, { type: "command-button", id: "add-circle", commandId: "annotation:add-circle", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-circle"] }, { type: "command-button", id: "add-line", commandId: "annotation:add-line", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-line"] }, { type: "command-button", id: "add-arrow", commandId: "annotation:add-arrow", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-arrow"] }, { type: "command-button", id: "add-polygon", commandId: "annotation:add-polygon", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-polygon"] }, { type: "command-button", id: "add-polyline", commandId: "annotation:add-polyline", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-polyline"] }, { type: "command-button", id: "overflow-shapes-tools", commandId: "annotation:overflow-shapes", variant: "icon", categories: ["annotation", "annotation-shape", "annotation-overflow"] }, { type: "divider", id: "shapes-tools-divider-1", orientation: "vertical" }, { type: "command-button", id: "toggle-annotation-style", commandId: "panel:toggle-annotation-style", variant: "icon", categories: ["panel", "panel-annotation-style"] }, { type: "divider", id: "shapes-tools-divider-2", orientation: "vertical", visibilityDependsOn: { itemIds: ["toggle-annotation-style"] } }, { type: "command-button", id: "undo-button", commandId: "history:undo", variant: "icon", categories: ["history", "history-undo"] }, { type: "command-button", id: "redo-button", commandId: "history:redo", variant: "icon", categories: ["history", "history-redo"] }] }, { type: "spacer", id: "spacer-6", flex: true }] }, "form-toolbar": { id: "form-toolbar", position: { placement: "top", slot: "secondary", order: 0 }, responsive: { breakpoints: { sm: { maxWidth: 640, hide: ["add-form-select", "add-form-listbox"], show: ["overflow-forms-tools"] }, md: { minWidth: 640, hide: ["overflow-forms-tools"], show: ["add-form-select", "add-form-listbox"] } } }, permanent: false, categories: ["form"], items: [{ type: "spacer", id: "spacer-form-1", flex: true }, { type: "group", id: "form-tools", alignment: "start", gap: 2, items: [{ type: "command-button", id: "add-form-textfield", commandId: "form:add-textfield", variant: "icon", categories: ["form", "form-textfield"] }, { type: "command-button", id: "add-form-checkbox", commandId: "form:add-checkbox", variant: "icon", categories: ["form", "form-checkbox"] }, { type: "command-button", id: "add-form-radio", commandId: "form:add-radio", variant: "icon", categories: ["form", "form-radio"] }, { type: "command-button", id: "add-form-select", commandId: "form:add-select", variant: "icon", categories: ["form", "form-select"] }, { type: "command-button", id: "add-form-listbox", commandId: "form:add-listbox", variant: "icon", categories: ["form", "form-listbox"] }, { type: "command-button", id: "overflow-forms-tools", commandId: "form:overflow-tools", variant: "icon", categories: ["form", "form-overflow"] }, { type: "divider", id: "form-tools-divider-1", orientation: "vertical" }, { type: "command-button", id: "toggle-annotation-style", commandId: "panel:toggle-annotation-style", variant: "icon", categories: ["panel", "panel-annotation-style"] }, { type: "command-button", id: "toggle-form-fill-mode", commandId: "form:toggle-fill-mode", variant: "icon", categories: ["form", "form-fill-mode"] }, { type: "divider", id: "form-tools-divider-2", orientation: "vertical" }, { type: "command-button", id: "undo-button", commandId: "history:undo", variant: "icon", categories: ["history", "history-undo"] }, { type: "command-button", id: "redo-button", commandId: "history:redo", variant: "icon", categories: ["history", "history-redo"] }] }, { type: "spacer", id: "spacer-form-2", flex: true }] }, "insert-toolbar": { id: "insert-toolbar", position: { placement: "top", slot: "secondary", order: 0 }, permanent: false, categories: ["insert"], items: [{ type: "spacer", id: "spacer-insert-1", flex: true }, { type: "group", id: "insert-tools", alignment: "start", gap: 2, items: [{ type: "command-button", id: "add-rubber-stamp", commandId: "insert:add-rubber-stamp", variant: "icon", categories: ["insert", "insert-rubber-stamp"] }, { type: "command-button", id: "add-signature", commandId: "insert:add-signature", variant: "icon", categories: ["insert", "insert-signature"] }, { type: "command-button", id: "add-image", commandId: "insert:add-image", variant: "icon", categories: ["insert", "insert-image"] }, { type: "divider", id: "insert-tools-divider-1", orientation: "vertical" }, { type: "command-button", id: "toggle-annotation-style", commandId: "panel:toggle-annotation-style", variant: "icon", categories: ["panel", "panel-annotation-style"] }, { type: "divider", id: "insert-tools-divider-2", orientation: "vertical", visibilityDependsOn: { itemIds: ["toggle-annotation-style"] } }, { type: "command-button", id: "undo-button", commandId: "history:undo", variant: "icon", categories: ["history", "history-undo"] }, { type: "command-button", id: "redo-button", commandId: "history:redo", variant: "icon", categories: ["history", "history-redo"] }] }, { type: "spacer", id: "spacer-insert-2", flex: true }] }, "redaction-toolbar": { id: "redaction-toolbar", position: { placement: "top", slot: "secondary", order: 0 }, permanent: false, categories: ["redaction"], items: [{ type: "spacer", id: "spacer-7", flex: true }, { type: "group", id: "redaction-tools", alignment: "start", gap: 2, items: [{ type: "command-button", id: "redact", commandId: "redaction:redact", variant: "icon", categories: ["redaction", "redaction-combined"] }, { type: "divider", id: "redaction-tools-divider-1", orientation: "vertical" }, { type: "command-button", id: "toggle-redaction-panel", commandId: "panel:toggle-redaction", variant: "icon", categories: ["panel", "panel-redaction"] }, { type: "command-button", id: "toggle-annotation-style", commandId: "panel:toggle-annotation-style", variant: "icon", categories: ["panel", "panel-annotation-style"] }, { type: "divider", id: "redaction-tools-divider-2", orientation: "vertical", visibilityDependsOn: { itemIds: ["toggle-annotation-style"] } }, { type: "command-button", id: "undo-button", commandId: "history:undo", variant: "icon", categories: ["history", "history-undo"] }, { type: "command-button", id: "redo-button", commandId: "history:redo", variant: "icon", categories: ["history", "history-redo"] }] }, { type: "spacer", id: "spacer-8", flex: true }] } };
2237
+ class St {
2238
+ constructor() {
2239
+ this.specs = [];
2240
+ }
2241
+ register(e13) {
2242
+ if (this.specs.some((t) => t.id === e13.id)) throw new Error(`OperationRegistry: duplicate operation id "${e13.id}"`);
2243
+ this.specs.push(e13);
2244
+ }
2245
+ registerAll(e13) {
2246
+ for (const t of e13) t && this.register(t);
2247
+ }
2248
+ list() {
2249
+ return this.specs;
2250
+ }
2251
+ buildToolbars() {
2252
+ const e13 = structuredClone(Mt);
2253
+ for (const t of this.specs) {
2254
+ const a = e13[t.toolbarSlot];
2255
+ if (!a) continue;
2256
+ const s = { type: "command-button", id: t.id, commandId: t.commandId, variant: "icon", ...t.icon ? { icon: t.icon } : {}, ...t.i18nKey ? { labelKey: t.i18nKey } : {}, ...t.label ? { label: t.label } : {}, categories: t.categories ?? [] };
2257
+ a.items = xt(a.items, s, t.position);
2258
+ }
2259
+ return e13;
2260
+ }
2261
+ }
2262
+ function xt(e13, t, a) {
2263
+ return (null == a ? void 0 : a.after) || (null == a ? void 0 : a.before) ? (function(e14, t2, a2) {
2264
+ const s = (e15) => {
2265
+ const i = [];
2266
+ for (const o of e15) "group" !== o.type ? a2.before && o.id === a2.before ? i.push(t2, o) : (i.push(o), a2.after && o.id === a2.after && i.push(t2)) : i.push({ ...o, items: s(o.items) });
2267
+ return i;
2268
+ };
2269
+ return s(e14);
2270
+ })(e13, t, a) : (function(e14, t2) {
2271
+ return e14.map((e15) => "group" === e15.type ? { ...e15, items: [...e15.items, t2] } : e15);
2272
+ })(e13, t);
2273
+ }
2274
+ const kt = { annotate: "annotation-toolbar", shapes: "shapes-toolbar", insert: "insert-toolbar", form: "form-toolbar", redact: "redaction-toolbar" };
2275
+ function $t() {
2276
+ return { "mode:view": { id: "mode:view", label: "View", categories: ["mode", "mode-view"], action: ({ registry: e13, documentId: t }) => {
2277
+ var _a2, _b, _c, _d;
2278
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides(), s = (_b = e13.getPlugin("interaction-manager")) == null ? void 0 : _b.provides();
2279
+ a && s && ((_c = s.forDocument(t)) == null ? void 0 : _c.activateDefaultMode(), a.forDocument(t).closeToolbarSlot("top", "secondary"), (_d = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _d.provides().forDocument(t).setLocked(((e14) => e14.getPluginConfig(ANNOTATION_PLUGIN_ID).locked ?? { type: LockModeType.None })(e13)));
2280
+ }, active: ({ state: e13, documentId: t }) => !isToolbarOpen(e13.plugins, t, "top", "secondary") }, "mode:annotate": { id: "mode:annotate", label: "Annotate", categories: ["mode", "mode-annotate", "annotation"], action: ({ registry: e13, documentId: t }) => {
2281
+ var _a2, _b;
2282
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides();
2283
+ a && (a.setActiveToolbar("top", "secondary", "annotation-toolbar", t), (_b = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _b.provides().forDocument(t).setLocked({ type: LockModeType.Include, categories: ["form"] }));
2284
+ }, active: ({ state: e13, documentId: t }) => isToolbarOpen(e13.plugins, t, "top", "secondary", "annotation-toolbar") }, "mode:shapes": { id: "mode:shapes", label: "Shapes", categories: ["mode", "mode-shapes", "annotation"], action: ({ registry: e13, documentId: t }) => {
2285
+ var _a2, _b;
2286
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides();
2287
+ a && (a.setActiveToolbar("top", "secondary", "shapes-toolbar", t), (_b = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _b.provides().forDocument(t).setLocked({ type: LockModeType.Include, categories: ["form"] }));
2288
+ }, active: ({ state: e13, documentId: t }) => isToolbarOpen(e13.plugins, t, "top", "secondary", "shapes-toolbar") }, "mode:insert": { id: "mode:insert", label: "Insert", categories: ["mode", "mode-insert", "insert"], action: ({ registry: e13, documentId: t }) => {
2289
+ var _a2, _b;
2290
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides();
2291
+ a && (a.setActiveToolbar("top", "secondary", "insert-toolbar", t), (_b = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _b.provides().forDocument(t).setLocked({ type: LockModeType.Include, categories: ["form"] }));
2292
+ }, active: ({ state: e13, documentId: t }) => isToolbarOpen(e13.plugins, t, "top", "secondary", "insert-toolbar") }, "mode:form": { id: "mode:form", label: "Form", categories: ["mode", "mode-form", "form"], action: ({ registry: e13, documentId: t }) => {
2293
+ var _a2, _b;
2294
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides();
2295
+ a && (a.setActiveToolbar("top", "secondary", "form-toolbar", t), (_b = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _b.provides().forDocument(t).setLocked({ type: LockModeType.None }));
2296
+ }, active: ({ state: e13, documentId: t }) => isToolbarOpen(e13.plugins, t, "top", "secondary", "form-toolbar") }, "mode:redact": { id: "mode:redact", label: "Redact", categories: ["mode", "mode-redact", "redaction"], action: ({ registry: e13, documentId: t }) => {
2297
+ var _a2, _b;
2298
+ const a = (_a2 = e13.getPlugin("ui")) == null ? void 0 : _a2.provides();
2299
+ a && (a.setActiveToolbar("top", "secondary", "redaction-toolbar", t), (_b = e13.getPlugin(ANNOTATION_PLUGIN_ID)) == null ? void 0 : _b.provides().forDocument(t).setLocked({ type: LockModeType.Include, categories: ["form"] }));
2300
+ }, active: ({ state: e13, documentId: t }) => isToolbarOpen(e13.plugins, t, "top", "secondary", "redaction-toolbar") } };
2301
+ }
2302
+ function Lt(e13) {
2303
+ var _a2, _b, _c, _d, _e2, _f;
2304
+ const t = e13.toolbar ?? {}, a = t.enabledModes ?? ["view", "annotate", "shapes", "insert", "form", "redact"], s = a.length > 0, { schema: i, operationRegistry: o } = (function(e14 = {}) {
2305
+ var t2, a2, s2, i2, o2, r2;
2306
+ const n2 = new Set(e14.enabledModes ?? ["view", "annotate", "shapes", "insert", "form", "redact"]), l = new St();
2307
+ (null == (t2 = e14.customOperations) ? void 0 : t2.length) && l.registerAll(e14.customOperations);
2308
+ const h2 = l.buildToolbars(), d = {};
2309
+ for (const u of n2) {
2310
+ if ("view" === u) continue;
2311
+ const e15 = kt[u];
2312
+ h2[e15] && (d[e15] = h2[e15]);
2313
+ }
2314
+ const c = (function(e15) {
2315
+ if (0 === e15.size) return null;
2316
+ const t3 = (e16, t4, a3) => ({ type: "command-button", id: `${e16}-mode`, commandId: a3, variant: "text", label: t4, categories: ["mode", e16] });
2317
+ return { id: "chapter-editor-main-toolbar", position: { placement: "top", slot: "main", order: 0 }, permanent: true, items: [{ type: "spacer", id: "main-spacer-left", flex: true }, { type: "group", id: "mode-group", alignment: "start", gap: 2, items: [...e15.has("view") ? [t3("view", "View", "mode:view")] : [], ...e15.has("annotate") ? [t3("annotate", "Annotate", "mode:annotate")] : [], ...e15.has("shapes") ? [t3("shapes", "Shapes", "mode:shapes")] : [], ...e15.has("insert") ? [t3("insert", "Insert", "mode:insert")] : [], ...e15.has("form") ? [t3("form", "Form", "mode:form")] : [], ...e15.has("redact") ? [t3("redact", "Redact", "mode:redact")] : []] }, { type: "spacer", id: "main-spacer-right", flex: true }] };
2318
+ })(n2);
2319
+ return c && (d["chapter-editor-main-toolbar"] = c), (null == (a2 = e14.extend) ? void 0 : a2.toolbars) && Object.assign(d, e14.extend.toolbars), { schema: { id: "chapter-pdf-editor-ui", version: "1.0.0", toolbars: d, menus: (null == (s2 = e14.extend) ? void 0 : s2.menus) ?? {}, sidebars: (null == (i2 = e14.extend) ? void 0 : i2.sidebars) ?? {}, modals: (null == (o2 = e14.extend) ? void 0 : o2.modals) ?? {}, selectionMenus: (null == (r2 = e14.extend) ? void 0 : r2.selectionMenus) ?? {} }, operationRegistry: l };
2320
+ })({ ...t, enabledModes: a }), r = { ...s ? $t() : {}, ...s ? zt(o.list()) : {}, ...e13.commands ?? {} }, n = [createPluginRegistration(DocumentManagerPluginPackage, { initialDocuments: [] }), createPluginRegistration(ye, { manifest: e13.manifest, overlapStrategy: e13.overlapStrategy, passwordProvider: e13.passwordProvider, chapterPdfLoader: e13.chapterPdfLoader, prefetchChapters: e13.prefetchChapters, unloadTimeoutMs: e13.unloadTimeoutMs }), createPluginRegistration(De, { placeholderPageHeight: e13.placeholderPageHeight, placeholderPageWidth: e13.placeholderPageWidth }), createPluginRegistration(InteractionManagerPluginPackage), createPluginRegistration(RenderPluginPackage), createPluginRegistration(RotatePluginPackage), createPluginRegistration(SelectionPluginPackage, { marquee: { enabled: false }, toleranceFactor: 1.2, minSelectionDragDistance: 4 }), createPluginRegistration(HistoryPluginPackage), createPluginRegistration(AnnotationPluginPackage), createPluginRegistration(RedactionPluginPackage), createPluginRegistration(FormPluginPackage), createPluginRegistration(StampPluginPackage, false === e13.loadDefaultStampLibrary ? { manifests: [] } : void 0), createPluginRegistration(SignaturePluginPackage), ...Object.keys(r).length > 0 ? [createPluginRegistration(CommandsPluginPackage, { commands: r })] : [], ...s ? [createPluginRegistration(I18nPluginPackage), createPluginRegistration(UIPluginPackage, { schema: i })] : []];
2321
+ return e13.notes && n.push(createPluginRegistration(Qe, { callbacks: e13.notes.callbacks, ui: (_b = (_a2 = e13.features) == null ? void 0 : _a2.notes) == null ? void 0 : _b.marker })), e13.bookmarks && n.push(createPluginRegistration(Ct, { callbacks: e13.bookmarks.callbacks, ui: (_d = (_c = e13.features) == null ? void 0 : _c.bookmarks) == null ? void 0 : _d.marker, hover: (_f = (_e2 = e13.features) == null ? void 0 : _e2.bookmarks) == null ? void 0 : _f.hover })), { plugins: n, uiSchema: i, operationRegistry: o };
2322
+ }
2323
+ function zt(e13) {
2324
+ const t = {};
2325
+ for (const a of e13) a.handler && (t[a.commandId] = { id: a.commandId, labelKey: a.i18nKey, label: a.label, icon: a.icon, categories: a.categories, action: ({ documentId: e14 }) => {
2326
+ var _a2;
2327
+ (_a2 = a.handler) == null ? void 0 : _a2.call(a, { documentId: e14, chapterId: e14 });
2328
+ } });
2329
+ return t;
2330
+ }
2331
+ const Tt = { markup: { enabled: true }, bookmarks: { enabled: true }, notes: { enabled: true }, selectionToolbar: { enabled: true }, zoom: { enabled: true, min: 0.5, max: 3, initial: 1 } };
2332
+ function Dt(e13) {
2333
+ var _a2, _b, _c, _d, _e2;
2334
+ return Lt({ ...e13, toolbar: e13.toolbar ?? { enabledModes: [] }, features: { ...Tt, ...e13.features, markup: { ...Tt.markup, ...(_a2 = e13.features) == null ? void 0 : _a2.markup }, bookmarks: { ...Tt.bookmarks, ...(_b = e13.features) == null ? void 0 : _b.bookmarks }, notes: { ...Tt.notes, ...(_c = e13.features) == null ? void 0 : _c.notes }, selectionToolbar: { ...Tt.selectionToolbar, ...(_d = e13.features) == null ? void 0 : _d.selectionToolbar }, zoom: { ...Tt.zoom, ...(_e2 = e13.features) == null ? void 0 : _e2.zoom } } });
2335
+ }
2336
+ function Gt(e13, t, a) {
2337
+ return Math.min(a, Math.max(t, e13));
2338
+ }
2339
+ const Ot = { position: "relative", height: "100%", width: "100%" }, At = { height: "100%", width: "100%" };
2340
+ const Nt = { kind: "first-wins" };
2341
+ function Vt(e13, t, a) {
2342
+ if (1 === t.length) return t[0].chapterId;
2343
+ switch (a.kind) {
2344
+ case "first-wins":
2345
+ return t[0].chapterId;
2346
+ case "last-wins":
2347
+ return t[t.length - 1].chapterId;
2348
+ case "explicit": {
2349
+ const a2 = t.find((t2) => {
2350
+ var a3;
2351
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
2352
+ });
2353
+ return a2 ? a2.chapterId : t[0].chapterId;
2354
+ }
2355
+ case "custom":
2356
+ return a.resolve(e13, t);
2357
+ }
2358
+ }
2359
+ let _t = class {
2360
+ constructor(e13) {
2361
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
2362
+ for (const t of e13) {
2363
+ this._byGlobalNumber.set(t.globalPageNumber, t);
2364
+ let e14 = this._byChapter.get(t.chapterId);
2365
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
2366
+ }
2367
+ }
2368
+ get totalPages() {
2369
+ return this._pages.length;
2370
+ }
2371
+ list() {
2372
+ return this._pages;
2373
+ }
2374
+ atIndex(e13) {
2375
+ return this._pages[e13] ?? null;
2376
+ }
2377
+ byGlobalNumber(e13) {
2378
+ return this._byGlobalNumber.get(e13) ?? null;
2379
+ }
2380
+ toGlobal(e13, t) {
2381
+ const a = this._byChapter.get(e13);
2382
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
2383
+ }
2384
+ pagesOfChapter(e13) {
2385
+ return this._byChapter.get(e13) ?? [];
2386
+ }
2387
+ firstIndexOfChapter(e13) {
2388
+ var t;
2389
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
2390
+ return a ? this._pages.indexOf(a) : -1;
2391
+ }
2392
+ };
2393
+ function Rt(e13, t = Nt) {
2394
+ const a = (function(e14, t2 = Nt) {
2395
+ const a2 = /* @__PURE__ */ new Map();
2396
+ for (const i2 of e14.chapters) {
2397
+ const [e15, t3] = i2.globalPageRange;
2398
+ for (let s3 = e15; s3 <= t3; s3++) {
2399
+ const e16 = a2.get(s3);
2400
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
2401
+ }
2402
+ }
2403
+ const s2 = /* @__PURE__ */ new Map();
2404
+ for (const [i2, o2] of a2) s2.set(i2, Vt(i2, o2, t2));
2405
+ return s2;
2406
+ })(e13, t), s = /* @__PURE__ */ new Map();
2407
+ for (const n of e13.chapters) s.set(n.chapterId, n);
2408
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
2409
+ let r = 0;
2410
+ for (const n of i) {
2411
+ const e14 = a.get(n), t2 = s.get(e14);
2412
+ if (!t2) continue;
2413
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
2414
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
2415
+ }
2416
+ return new _t(o);
2417
+ }
2418
+ const Et = class e9 extends BasePlugin {
2419
+ constructor(e13, t) {
2420
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = Nt, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
2421
+ }
2422
+ async initialize(e13) {
2423
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? Nt, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
2424
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
2425
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
2426
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
2427
+ }), this.documentManager.provides().onDocumentError((e14) => {
2428
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
2429
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
2430
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
2431
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
2432
+ }
2433
+ }
2434
+ buildCapability() {
2435
+ return { setManifest: (e13, t) => {
2436
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
2437
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
2438
+ }
2439
+ destroy() {
2440
+ super.destroy();
2441
+ for (const e13 of this.documentManagerUnsubs) e13();
2442
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
2443
+ }
2444
+ setManifestInternal(t) {
2445
+ const a = (function(e13) {
2446
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
2447
+ for (const s2 of e13.chapters) {
2448
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
2449
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
2450
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
2451
+ }
2452
+ return t2;
2453
+ })(t);
2454
+ a.length > 0 && this.logger.warn(e9.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
2455
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
2456
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
2457
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
2458
+ this.manifest = t, this.virtualPageMap = Rt(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
2459
+ }
2460
+ eagerPrefetchFromManifest() {
2461
+ const e13 = this.config.prefetchChapters ?? 0;
2462
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
2463
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
2464
+ for (let s = 0; s < a; s++) {
2465
+ const e14 = this.manifest.chapters[s].chapterId;
2466
+ this.chapterLastUsed.set(e14, t);
2467
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
2468
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
2469
+ }
2470
+ }
2471
+ findChapter(e13) {
2472
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
2473
+ }
2474
+ isOwnedChapter(e13) {
2475
+ return !!this.findChapter(e13);
2476
+ }
2477
+ handleVisibleChange(e13) {
2478
+ if (!this.virtualPageMap) return;
2479
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
2480
+ for (const n of e13) {
2481
+ const e14 = this.virtualPageMap.atIndex(n);
2482
+ e14 && s.add(e14.chapterId);
2483
+ }
2484
+ if (0 === s.size) return;
2485
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
2486
+ for (const n of s) {
2487
+ const e14 = i.indexOf(n);
2488
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
2489
+ }
2490
+ const r = /* @__PURE__ */ new Set();
2491
+ for (const n of o) r.add(i[n]);
2492
+ for (const n of r) {
2493
+ this.chapterLastUsed.set(n, t);
2494
+ const e14 = this.chapterStatus.get(n) ?? "idle";
2495
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
2496
+ }
2497
+ if (this.config.autoActivateOnLoad ?? 1) {
2498
+ const e14 = i.find((e15) => s.has(e15));
2499
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
2500
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
2501
+ }
2502
+ }
2503
+ }
2504
+ collectIdleChapters() {
2505
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
2506
+ if (e13 <= 0) return;
2507
+ const t = Date.now();
2508
+ for (const [a, s] of this.chapterStatus) {
2509
+ if ("loaded" !== s) continue;
2510
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
2511
+ }
2512
+ }
2513
+ ensureChapterLoaded(e13) {
2514
+ const t = this.pendingLoadPromises.get(e13);
2515
+ if (t) return t;
2516
+ const a = this.findChapter(e13);
2517
+ if (!a) return Promise.resolve("error");
2518
+ const s = this.chapterStatus.get(e13) ?? "idle";
2519
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
2520
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
2521
+ const i = this.startLoad(a).finally(() => {
2522
+ this.pendingLoadPromises.delete(e13);
2523
+ });
2524
+ return this.pendingLoadPromises.set(e13, i), i;
2525
+ }
2526
+ async resolvePdfPayload(e13) {
2527
+ const t = e13.source;
2528
+ if (t) {
2529
+ if ("url" in t) return { url: t.url };
2530
+ if ("buffer" in t) return { buffer: t.buffer };
2531
+ if ("load" in t) return t.load();
2532
+ }
2533
+ const a = this.config.chapterPdfLoader;
2534
+ if (a) return a.loadPdf(e13);
2535
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
2536
+ }
2537
+ async startLoad(e13) {
2538
+ var t;
2539
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
2540
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
2541
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
2542
+ }
2543
+ waitForTerminalStatus(e13) {
2544
+ return new Promise((t) => {
2545
+ const a = (e14) => {
2546
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
2547
+ }, s = this.statusChange$.on((t2) => {
2548
+ t2.chapterId === e13 && a(t2.status);
2549
+ });
2550
+ a(this.chapterStatus.get(e13) ?? "idle");
2551
+ });
2552
+ }
2553
+ async handleDocumentError(t, a, s) {
2554
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
2555
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
2556
+ const i = this.findChapter(t);
2557
+ if (!i) return;
2558
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
2559
+ this.passwordAttempts.set(t, o);
2560
+ let r = null;
2561
+ try {
2562
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
2563
+ } catch (n) {
2564
+ this.logger.error(e9.id, "PasswordProvider", `Provider rejected for ${t}`, n);
2565
+ }
2566
+ if (!r) return void this.updateStatus(t, "password-required");
2567
+ this.updateStatus(t, "loading");
2568
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
2569
+ }, () => {
2570
+ });
2571
+ }
2572
+ closeChapter(e13) {
2573
+ const t = this.documentManager.provides();
2574
+ if (t.isDocumentOpen(e13)) {
2575
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
2576
+ } else this.updateStatus(e13, "closed");
2577
+ }
2578
+ updateStatus(e13, t, a) {
2579
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
2580
+ }
2581
+ };
2582
+ Et.id = "chapter-manager";
2583
+ let Ut = Et;
2584
+ const Ft = class extends BasePlugin {
2585
+ constructor(e13, t) {
2586
+ super(e13, t), this.layoutChange$ = createBehaviorEmitter(), this.visibleChange$ = createBehaviorEmitter(), this.virtualPageMap = null, this.pageSizes = /* @__PURE__ */ new Map(), this.offsets = [], this.totalHeight = 0, this.totalWidth = 0, this.viewportEl = null, this.viewportObservers = null, this.currentVisible = [], this.currentGlobalPageIndex = 0, this.chapterManagerUnsubs = [], this.chapterManager = this.registry.getPlugin(Ut.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
2587
+ }
2588
+ async initialize(e13) {
2589
+ this.config = { placeholderPageHeight: e13.placeholderPageHeight ?? 1200, placeholderPageWidth: e13.placeholderPageWidth ?? 900, bufferSize: e13.bufferSize ?? 2, pageGap: e13.pageGap ?? 20 }, this.virtualPageMap = this.chapterManager.provides().getVirtualPageMap(), this.rebuildOffsets(), this.chapterManagerUnsubs.push(this.chapterManager.provides().onManifestChange(({ map: e14 }) => {
2590
+ this.virtualPageMap = e14, this.pageSizes.clear(), this.rebuildOffsets(), this.syncReadyChapterSizes(), this.recomputeVisible();
2591
+ })), this.syncReadyChapterSizes();
2592
+ }
2593
+ isChapterDocumentReady(e13) {
2594
+ const t = this.coreState.core.documents[e13];
2595
+ return !(!t || "loaded" !== t.status || !t.document) && t.document.pages.length > 0;
2596
+ }
2597
+ refreshLayout() {
2598
+ this.layoutChange$.emit(this.computeLayout());
2599
+ }
2600
+ syncReadyChapterSizes() {
2601
+ for (const e13 of this.chapterManager.provides().getManifest().chapters) this.isChapterDocumentReady(e13.chapterId) && this.harvestChapterSizes(e13.chapterId);
2602
+ this.refreshLayout();
2603
+ }
2604
+ onDocumentLoaded(e13) {
2605
+ var t;
2606
+ if (0 === ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0)) return;
2607
+ const a = this.documentManager.provides();
2608
+ a.getActiveDocumentId() || a.setActiveDocument(e13), this.harvestChapterSizes(e13), this.refreshLayout();
2609
+ }
2610
+ onDocumentClosed(e13) {
2611
+ var t;
2612
+ 0 !== ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0) && (this.dropChapterSizes(e13), this.refreshLayout());
2613
+ }
2614
+ buildCapability() {
2615
+ return { registerViewport: (e13) => this.bindViewport(e13), reportChapterPageSizes: (e13, t) => this.applyChapterPageSizes(e13, t), getLayout: () => this.computeLayout(), getCurrentGlobalPageIndex: () => this.currentGlobalPageIndex, getVisibleGlobalPageIndices: () => this.currentVisible.slice(), scrollToGlobalPageIndex: (e13, t) => this.scrollToIndex(e13, t), scrollToChapter: (e13, t) => this.scrollToChapter(e13, t), scrollToGlobalPageNumber: (e13, t) => this.scrollToGlobalNumber(e13, t), scrollToGlobalPdfPoint: (e13, t, a) => this.scrollToGlobalPdfPoint(e13, t, a), onLayoutChange: this.layoutChange$.on, onVisibleChange: this.visibleChange$.on };
2616
+ }
2617
+ destroy() {
2618
+ var e13;
2619
+ super.destroy();
2620
+ for (const t of this.chapterManagerUnsubs) t();
2621
+ this.chapterManagerUnsubs = [], null == (e13 = this.viewportObservers) || e13.unbind(), this.viewportObservers = null, this.viewportEl = null, this.layoutChange$.clear(), this.visibleChange$.clear();
2622
+ }
2623
+ getPageSize(e13) {
2624
+ return this.pageSizes.get(e13) ?? { width: this.config.placeholderPageWidth, height: this.config.placeholderPageHeight };
2625
+ }
2626
+ rebuildOffsets() {
2627
+ if (!this.virtualPageMap) return this.offsets = [], this.totalHeight = 0, void (this.totalWidth = 0);
2628
+ const e13 = this.virtualPageMap.totalPages;
2629
+ this.offsets = new Array(e13);
2630
+ let t = 0, a = 0;
2631
+ for (let s = 0; s < e13; s++) {
2632
+ const { width: e14, height: i } = this.getPageSize(s);
2633
+ this.offsets[s] = t, t += i + this.config.pageGap, e14 > a && (a = e14);
2634
+ }
2635
+ this.totalHeight = e13 > 0 ? t - this.config.pageGap : 0, this.totalWidth = a, this.layoutChange$.emit(this.computeLayout());
2636
+ }
2637
+ applyChapterPageSizes(e13, t) {
2638
+ if (!this.virtualPageMap) return;
2639
+ let a = false;
2640
+ for (const s of t) {
2641
+ const t2 = this.virtualPageMap.toGlobal(e13, s.localPageIndex);
2642
+ if (!t2) continue;
2643
+ const i = this.pageSizes.get(t2.globalPageIndex);
2644
+ i && i.width === s.width && i.height === s.height || (this.pageSizes.set(t2.globalPageIndex, { width: s.width, height: s.height }), a = true);
2645
+ }
2646
+ if (a) {
2647
+ const e14 = this.currentGlobalPageIndex, t2 = this.offsets[e14] ?? 0;
2648
+ if (this.rebuildOffsets(), this.viewportEl) {
2649
+ const a2 = (this.offsets[e14] ?? 0) - t2;
2650
+ 0 !== a2 && (this.viewportEl.scrollTop += a2);
2651
+ }
2652
+ this.recomputeVisible();
2653
+ }
2654
+ }
2655
+ getChapterDocumentScale(e13) {
2656
+ var t;
2657
+ return (null == (t = this.coreState.core.documents[e13]) ? void 0 : t.scale) ?? 1;
2658
+ }
2659
+ harvestChapterSizes(e13, t = 0) {
2660
+ var a;
2661
+ if (!this.virtualPageMap) return;
2662
+ const s = this.documentManager.provides().getDocument(e13), i = this.virtualPageMap.pagesOfChapter(e13);
2663
+ if (!(null == (a = null == s ? void 0 : s.pages) ? void 0 : a.length) || 0 === i.length) return void (t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1)));
2664
+ const o = this.getChapterDocumentScale(e13), r = [];
2665
+ for (const n of i) {
2666
+ const e14 = s.pages[n.localPageIndex];
2667
+ (null == e14 ? void 0 : e14.size) && r.push({ localPageIndex: n.localPageIndex, width: e14.size.width * o, height: e14.size.height * o });
2668
+ }
2669
+ 0 !== r.length ? this.applyChapterPageSizes(e13, r) : t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1));
2670
+ }
2671
+ onScaleChanged(e13) {
2672
+ const t = this.coreState.core.documents[e13];
2673
+ t && "loaded" === t.status && this.chapterManager.provides().getChapter(e13) && this.harvestChapterSizes(e13);
2674
+ }
2675
+ dropChapterSizes(e13) {
2676
+ if (!this.virtualPageMap) return;
2677
+ let t = false;
2678
+ for (const a of this.virtualPageMap.pagesOfChapter(e13)) this.pageSizes.delete(a.globalPageIndex) && (t = true);
2679
+ t && (this.rebuildOffsets(), this.recomputeVisible());
2680
+ }
2681
+ bindViewport(e13) {
2682
+ var t;
2683
+ if (null == (t = this.viewportObservers) || t.unbind(), this.viewportEl = e13, this.viewportObservers = null, !e13) return;
2684
+ const a = () => this.recomputeVisible(), s = new ResizeObserver(() => this.recomputeVisible());
2685
+ e13.addEventListener("scroll", a, { passive: true }), s.observe(e13), this.viewportObservers = { unbind: () => {
2686
+ e13.removeEventListener("scroll", a), s.disconnect();
2687
+ } }, this.syncReadyChapterSizes(), this.recomputeVisible(), 0 === e13.clientHeight && requestAnimationFrame(() => {
2688
+ requestAnimationFrame(() => this.recomputeVisible());
2689
+ });
2690
+ }
2691
+ recomputeVisible() {
2692
+ if (!this.viewportEl || !this.virtualPageMap) return;
2693
+ const e13 = this.virtualPageMap.totalPages;
2694
+ if (0 === e13) return this.currentVisible = [], this.currentGlobalPageIndex = 0, void this.layoutChange$.emit(this.computeLayout());
2695
+ const t = this.viewportEl.scrollTop, a = t + this.viewportEl.clientHeight, s = this.findFirstVisibleIndex(t);
2696
+ let i = s;
2697
+ for (; i < e13; ) {
2698
+ const e14 = this.getPageSize(i), t2 = this.offsets[i];
2699
+ if (e14.height, t2 >= a) break;
2700
+ i++;
2701
+ }
2702
+ const o = [];
2703
+ let r = s, n = -1;
2704
+ for (let l = s; l < i; l++) {
2705
+ o.push(l);
2706
+ const e14 = this.offsets[l], s2 = e14 + this.getPageSize(l).height, i2 = Math.max(0, Math.min(s2, a) - Math.max(e14, t));
2707
+ i2 > n && (n = i2, r = l);
2708
+ }
2709
+ this.currentVisible = o, this.currentGlobalPageIndex = r, this.visibleChange$.emit({ visibleGlobalPageIndices: o, currentGlobalPageIndex: r }), this.chapterManager.provides().setVisibleGlobalPages(o), this.layoutChange$.emit(this.computeLayout());
2710
+ }
2711
+ findFirstVisibleIndex(e13) {
2712
+ let t = 0, a = this.offsets.length - 1, s = 0;
2713
+ for (; t <= a; ) {
2714
+ const i = t + a >> 1;
2715
+ this.offsets[i] <= e13 ? (s = i, t = i + 1) : a = i - 1;
2716
+ }
2717
+ return s;
2718
+ }
2719
+ computeLayout() {
2720
+ const e13 = this.config.bufferSize, t = Math.max(0, (this.currentVisible[0] ?? 0) - e13), a = this.currentVisible[this.currentVisible.length - 1] ?? -1, s = Math.min(this.offsets.length - 1, (a >= 0 ? a : 0) + e13), i = [];
2721
+ if (this.virtualPageMap && this.offsets.length > 0) for (let o = t; o <= s; o++) {
2722
+ const e14 = this.virtualPageMap.atIndex(o);
2723
+ if (!e14) continue;
2724
+ const t2 = this.getPageSize(o), a2 = !this.isChapterDocumentReady(e14.chapterId);
2725
+ i.push({ globalPageIndex: o, globalPageNumber: e14.globalPageNumber, chapterId: e14.chapterId, localPageIndex: e14.localPageIndex, width: t2.width, height: t2.height, offsetTop: this.offsets[o], isPlaceholder: a2 });
2726
+ }
2727
+ return { totalHeight: this.totalHeight, totalWidth: this.totalWidth || this.config.placeholderPageWidth, items: i, pageGap: this.config.pageGap };
2728
+ }
2729
+ scrollToIndex(e13, t) {
2730
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length) return;
2731
+ const a = (this.offsets[e13] ?? 0) - ((null == t ? void 0 : t.topOffset) ?? 0);
2732
+ this.viewportEl.scrollTo({ top: a, behavior: (null == t ? void 0 : t.behavior) ?? "auto" });
2733
+ }
2734
+ scrollToGlobalPdfPoint(e13, t, a) {
2735
+ var s;
2736
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length || !this.virtualPageMap) return;
2737
+ const i = (null == a ? void 0 : a.marginTop) ?? 80, o = this.virtualPageMap.atIndex(e13);
2738
+ if (!o) return void this.scrollToIndex(e13, a);
2739
+ const r = this.pageSizes.get(e13), n = null == (s = this.documentManager.provides().getDocument(o.chapterId)) ? void 0 : s.pages[o.localPageIndex];
2740
+ if (!r || !n) return void this.scrollToIndex(e13, a);
2741
+ const l = r.height / n.size.height, h2 = (this.offsets[e13] ?? 0) + t * l - i;
2742
+ this.viewportEl.scrollTo({ top: Math.max(0, h2), behavior: (null == a ? void 0 : a.behavior) ?? "auto" });
2743
+ }
2744
+ scrollToChapter(e13, t) {
2745
+ if (!this.virtualPageMap) return;
2746
+ const a = this.virtualPageMap.firstIndexOfChapter(e13);
2747
+ a < 0 || (this.chapterManager.provides().ensureChapterLoaded(e13), this.scrollToIndex(a, t));
2748
+ }
2749
+ scrollToGlobalNumber(e13, t) {
2750
+ if (!this.virtualPageMap) return;
2751
+ const a = this.virtualPageMap.byGlobalNumber(e13);
2752
+ a && this.scrollToIndex(a.globalPageIndex, t);
2753
+ }
2754
+ };
2755
+ Ft.id = "chapter-scroll";
2756
+ let qt = Ft;
2757
+ const Wt = ["data-global-page-index", "data-chapter-id", "data-local-page-index"], Ht = /* @__PURE__ */ ((e13, t) => {
2758
+ const a = e13.__vccOpts || e13;
2759
+ for (const [s, i] of t) a[s] = i;
2760
+ return a;
2761
+ })(/* @__PURE__ */ defineComponent({ __name: "ChapterScroller", props: { class: {}, style: {} }, setup(e13) {
2762
+ const { provides: p } = useCapability(qt.id), g = ref(null), f = ref(null);
2763
+ let m = null;
2764
+ const v = () => {
2765
+ null == m || m(), m = null, p.value && (p.value.registerViewport(g.value), m = p.value.onLayoutChange((e14) => {
2766
+ f.value = e14;
2767
+ }));
2768
+ };
2769
+ return onMounted(v), onBeforeUnmount(() => {
2770
+ var e14;
2771
+ null == m || m(), null == (e14 = p.value) || e14.registerViewport(null);
2772
+ }), watch(p, v), (e14, t) => {
2773
+ var a, s, i;
2774
+ return openBlock(), createElementBlock("div", { ref_key: "containerRef", ref: g, "data-chapter-scroll-viewport": "", class: normalizeClass(e14.$props.class), style: normalizeStyle({ overflow: "auto", position: "relative", width: "100%", height: "100%", ...e14.$props.style }) }, [createElementVNode("div", { style: normalizeStyle({ position: "relative", width: `${(null == (a = f.value) ? void 0 : a.totalWidth) ?? 0}px`, height: `${(null == (s = f.value) ? void 0 : s.totalHeight) ?? 0}px`, margin: "0 auto" }) }, [(openBlock(true), createElementBlock(Fragment, null, renderList((null == (i = f.value) ? void 0 : i.items) ?? [], (a2) => (openBlock(), createElementBlock("div", { key: a2.globalPageIndex, "data-global-page-index": a2.globalPageIndex, "data-chapter-id": a2.chapterId, "data-local-page-index": a2.localPageIndex, style: normalizeStyle({ position: "absolute", top: `${a2.offsetTop}px`, left: "50%", transform: "translateX(-50%)", width: `${a2.width}px`, height: `${a2.height}px`, backgroundColor: a2.isPlaceholder ? "#f3f4f6" : "#fff", boxShadow: "0 1px 4px rgba(0,0,0,0.08)" }) }, [a2.isPlaceholder ? renderSlot(e14.$slots, "placeholder", { key: 0, item: a2 }, () => [t[0] || (t[0] = createElementVNode("div", { class: "chapter-scroll-placeholder" }, "Loading chapter…", -1))], true) : renderSlot(e14.$slots, "page", { key: 1, item: a2 }, void 0, true)], 12, Wt))), 128))], 4)], 6);
2775
+ };
2776
+ } }), [["__scopeId", "data-v-8a737137"]]), Bt = /* @__PURE__ */ defineComponent({ __name: "ChapterRenderLayer", props: { chapterId: {}, localPageIndex: {}, scale: {}, dpr: {}, class: {} }, setup: (e13) => (t, a) => (openBlock(), createBlock(unref(RenderLayer), { "document-id": e13.chapterId, "page-index": e13.localPageIndex, scale: e13.scale, dpr: e13.dpr, class: normalizeClass(e13.class), style: { pointerEvents: "none" } }, null, 8, ["document-id", "page-index", "scale", "dpr", "class"])) });
2777
+ const jt = { kind: "first-wins" };
2778
+ function Yt(e13, t, a) {
2779
+ if (1 === t.length) return t[0].chapterId;
2780
+ switch (a.kind) {
2781
+ case "first-wins":
2782
+ return t[0].chapterId;
2783
+ case "last-wins":
2784
+ return t[t.length - 1].chapterId;
2785
+ case "explicit": {
2786
+ const a2 = t.find((t2) => {
2787
+ var a3;
2788
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
2789
+ });
2790
+ return a2 ? a2.chapterId : t[0].chapterId;
2791
+ }
2792
+ case "custom":
2793
+ return a.resolve(e13, t);
2794
+ }
2795
+ }
2796
+ let Kt = class {
2797
+ constructor(e13) {
2798
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
2799
+ for (const t of e13) {
2800
+ this._byGlobalNumber.set(t.globalPageNumber, t);
2801
+ let e14 = this._byChapter.get(t.chapterId);
2802
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
2803
+ }
2804
+ }
2805
+ get totalPages() {
2806
+ return this._pages.length;
2807
+ }
2808
+ list() {
2809
+ return this._pages;
2810
+ }
2811
+ atIndex(e13) {
2812
+ return this._pages[e13] ?? null;
2813
+ }
2814
+ byGlobalNumber(e13) {
2815
+ return this._byGlobalNumber.get(e13) ?? null;
2816
+ }
2817
+ toGlobal(e13, t) {
2818
+ const a = this._byChapter.get(e13);
2819
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
2820
+ }
2821
+ pagesOfChapter(e13) {
2822
+ return this._byChapter.get(e13) ?? [];
2823
+ }
2824
+ firstIndexOfChapter(e13) {
2825
+ var t;
2826
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
2827
+ return a ? this._pages.indexOf(a) : -1;
2828
+ }
2829
+ };
2830
+ function Xt(e13, t = jt) {
2831
+ const a = (function(e14, t2 = jt) {
2832
+ const a2 = /* @__PURE__ */ new Map();
2833
+ for (const i2 of e14.chapters) {
2834
+ const [e15, t3] = i2.globalPageRange;
2835
+ for (let s3 = e15; s3 <= t3; s3++) {
2836
+ const e16 = a2.get(s3);
2837
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
2838
+ }
2839
+ }
2840
+ const s2 = /* @__PURE__ */ new Map();
2841
+ for (const [i2, o2] of a2) s2.set(i2, Yt(i2, o2, t2));
2842
+ return s2;
2843
+ })(e13, t), s = /* @__PURE__ */ new Map();
2844
+ for (const n of e13.chapters) s.set(n.chapterId, n);
2845
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
2846
+ let r = 0;
2847
+ for (const n of i) {
2848
+ const e14 = a.get(n), t2 = s.get(e14);
2849
+ if (!t2) continue;
2850
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
2851
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
2852
+ }
2853
+ return new Kt(o);
2854
+ }
2855
+ const Zt = class e10 extends BasePlugin {
2856
+ constructor(e13, t) {
2857
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = jt, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
2858
+ }
2859
+ async initialize(e13) {
2860
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? jt, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
2861
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
2862
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
2863
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
2864
+ }), this.documentManager.provides().onDocumentError((e14) => {
2865
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
2866
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
2867
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
2868
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
2869
+ }
2870
+ }
2871
+ buildCapability() {
2872
+ return { setManifest: (e13, t) => {
2873
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
2874
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
2875
+ }
2876
+ destroy() {
2877
+ super.destroy();
2878
+ for (const e13 of this.documentManagerUnsubs) e13();
2879
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
2880
+ }
2881
+ setManifestInternal(t) {
2882
+ const a = (function(e13) {
2883
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
2884
+ for (const s2 of e13.chapters) {
2885
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
2886
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
2887
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
2888
+ }
2889
+ return t2;
2890
+ })(t);
2891
+ a.length > 0 && this.logger.warn(e10.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
2892
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
2893
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
2894
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
2895
+ this.manifest = t, this.virtualPageMap = Xt(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
2896
+ }
2897
+ eagerPrefetchFromManifest() {
2898
+ const e13 = this.config.prefetchChapters ?? 0;
2899
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
2900
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
2901
+ for (let s = 0; s < a; s++) {
2902
+ const e14 = this.manifest.chapters[s].chapterId;
2903
+ this.chapterLastUsed.set(e14, t);
2904
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
2905
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
2906
+ }
2907
+ }
2908
+ findChapter(e13) {
2909
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
2910
+ }
2911
+ isOwnedChapter(e13) {
2912
+ return !!this.findChapter(e13);
2913
+ }
2914
+ handleVisibleChange(e13) {
2915
+ if (!this.virtualPageMap) return;
2916
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
2917
+ for (const n of e13) {
2918
+ const e14 = this.virtualPageMap.atIndex(n);
2919
+ e14 && s.add(e14.chapterId);
2920
+ }
2921
+ if (0 === s.size) return;
2922
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
2923
+ for (const n of s) {
2924
+ const e14 = i.indexOf(n);
2925
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
2926
+ }
2927
+ const r = /* @__PURE__ */ new Set();
2928
+ for (const n of o) r.add(i[n]);
2929
+ for (const n of r) {
2930
+ this.chapterLastUsed.set(n, t);
2931
+ const e14 = this.chapterStatus.get(n) ?? "idle";
2932
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
2933
+ }
2934
+ if (this.config.autoActivateOnLoad ?? 1) {
2935
+ const e14 = i.find((e15) => s.has(e15));
2936
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
2937
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
2938
+ }
2939
+ }
2940
+ }
2941
+ collectIdleChapters() {
2942
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
2943
+ if (e13 <= 0) return;
2944
+ const t = Date.now();
2945
+ for (const [a, s] of this.chapterStatus) {
2946
+ if ("loaded" !== s) continue;
2947
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
2948
+ }
2949
+ }
2950
+ ensureChapterLoaded(e13) {
2951
+ const t = this.pendingLoadPromises.get(e13);
2952
+ if (t) return t;
2953
+ const a = this.findChapter(e13);
2954
+ if (!a) return Promise.resolve("error");
2955
+ const s = this.chapterStatus.get(e13) ?? "idle";
2956
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
2957
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
2958
+ const i = this.startLoad(a).finally(() => {
2959
+ this.pendingLoadPromises.delete(e13);
2960
+ });
2961
+ return this.pendingLoadPromises.set(e13, i), i;
2962
+ }
2963
+ async resolvePdfPayload(e13) {
2964
+ const t = e13.source;
2965
+ if (t) {
2966
+ if ("url" in t) return { url: t.url };
2967
+ if ("buffer" in t) return { buffer: t.buffer };
2968
+ if ("load" in t) return t.load();
2969
+ }
2970
+ const a = this.config.chapterPdfLoader;
2971
+ if (a) return a.loadPdf(e13);
2972
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
2973
+ }
2974
+ async startLoad(e13) {
2975
+ var t;
2976
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
2977
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
2978
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
2979
+ }
2980
+ waitForTerminalStatus(e13) {
2981
+ return new Promise((t) => {
2982
+ const a = (e14) => {
2983
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
2984
+ }, s = this.statusChange$.on((t2) => {
2985
+ t2.chapterId === e13 && a(t2.status);
2986
+ });
2987
+ a(this.chapterStatus.get(e13) ?? "idle");
2988
+ });
2989
+ }
2990
+ async handleDocumentError(t, a, s) {
2991
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
2992
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
2993
+ const i = this.findChapter(t);
2994
+ if (!i) return;
2995
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
2996
+ this.passwordAttempts.set(t, o);
2997
+ let r = null;
2998
+ try {
2999
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
3000
+ } catch (n) {
3001
+ this.logger.error(e10.id, "PasswordProvider", `Provider rejected for ${t}`, n);
3002
+ }
3003
+ if (!r) return void this.updateStatus(t, "password-required");
3004
+ this.updateStatus(t, "loading");
3005
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
3006
+ }, () => {
3007
+ });
3008
+ }
3009
+ closeChapter(e13) {
3010
+ const t = this.documentManager.provides();
3011
+ if (t.isDocumentOpen(e13)) {
3012
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
3013
+ } else this.updateStatus(e13, "closed");
3014
+ }
3015
+ updateStatus(e13, t, a) {
3016
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
3017
+ }
3018
+ };
3019
+ Zt.id = "chapter-manager";
3020
+ let Qt = Zt;
3021
+ const Jt = { kind: "first-wins" };
3022
+ function ea(e13, t, a) {
3023
+ if (1 === t.length) return t[0].chapterId;
3024
+ switch (a.kind) {
3025
+ case "first-wins":
3026
+ return t[0].chapterId;
3027
+ case "last-wins":
3028
+ return t[t.length - 1].chapterId;
3029
+ case "explicit": {
3030
+ const a2 = t.find((t2) => {
3031
+ var a3;
3032
+ return null == (a3 = t2.ownedGlobalPages) ? void 0 : a3.includes(e13);
3033
+ });
3034
+ return a2 ? a2.chapterId : t[0].chapterId;
3035
+ }
3036
+ case "custom":
3037
+ return a.resolve(e13, t);
3038
+ }
3039
+ }
3040
+ class ta {
3041
+ constructor(e13) {
3042
+ this._pages = e13, this._byChapter = /* @__PURE__ */ new Map(), this._byGlobalNumber = /* @__PURE__ */ new Map();
3043
+ for (const t of e13) {
3044
+ this._byGlobalNumber.set(t.globalPageNumber, t);
3045
+ let e14 = this._byChapter.get(t.chapterId);
3046
+ e14 || (e14 = [], this._byChapter.set(t.chapterId, e14)), e14.push(t);
3047
+ }
3048
+ }
3049
+ get totalPages() {
3050
+ return this._pages.length;
3051
+ }
3052
+ list() {
3053
+ return this._pages;
3054
+ }
3055
+ atIndex(e13) {
3056
+ return this._pages[e13] ?? null;
3057
+ }
3058
+ byGlobalNumber(e13) {
3059
+ return this._byGlobalNumber.get(e13) ?? null;
3060
+ }
3061
+ toGlobal(e13, t) {
3062
+ const a = this._byChapter.get(e13);
3063
+ return a ? a.find((e14) => e14.localPageIndex === t) ?? null : null;
3064
+ }
3065
+ pagesOfChapter(e13) {
3066
+ return this._byChapter.get(e13) ?? [];
3067
+ }
3068
+ firstIndexOfChapter(e13) {
3069
+ var t;
3070
+ const a = null == (t = this._byChapter.get(e13)) ? void 0 : t[0];
3071
+ return a ? this._pages.indexOf(a) : -1;
3072
+ }
3073
+ }
3074
+ function aa(e13, t = Jt) {
3075
+ const a = (function(e14, t2 = Jt) {
3076
+ const a2 = /* @__PURE__ */ new Map();
3077
+ for (const i2 of e14.chapters) {
3078
+ const [e15, t3] = i2.globalPageRange;
3079
+ for (let s3 = e15; s3 <= t3; s3++) {
3080
+ const e16 = a2.get(s3);
3081
+ e16 ? e16.push(i2) : a2.set(s3, [i2]);
3082
+ }
3083
+ }
3084
+ const s2 = /* @__PURE__ */ new Map();
3085
+ for (const [i2, o2] of a2) s2.set(i2, ea(i2, o2, t2));
3086
+ return s2;
3087
+ })(e13, t), s = /* @__PURE__ */ new Map();
3088
+ for (const n of e13.chapters) s.set(n.chapterId, n);
3089
+ const i = Array.from(a.keys()).sort((e14, t2) => e14 - t2), o = [];
3090
+ let r = 0;
3091
+ for (const n of i) {
3092
+ const e14 = a.get(n), t2 = s.get(e14);
3093
+ if (!t2) continue;
3094
+ const [i2] = t2.globalPageRange, [l] = t2.localPageRange, h2 = l + (n - i2);
3095
+ o.push({ globalPageIndex: r++, globalPageNumber: n, chapterId: e14, localPageIndex: h2 });
3096
+ }
3097
+ return new ta(o);
3098
+ }
3099
+ const sa = class e11 extends BasePlugin {
3100
+ constructor(e13, t) {
3101
+ super(e13, t), this.statusChange$ = createBehaviorEmitter(), this.manifestChange$ = createEmitter(), this.overlapStrategy = Jt, this.chapterStatus = /* @__PURE__ */ new Map(), this.chapterLastUsed = /* @__PURE__ */ new Map(), this.passwordAttempts = /* @__PURE__ */ new Map(), this.pendingLoadPromises = /* @__PURE__ */ new Map(), this.unloadTimer = null, this.documentManagerUnsubs = [], this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
3102
+ }
3103
+ async initialize(e13) {
3104
+ if (this.config = e13, this.passwordProvider = e13.passwordProvider, this.overlapStrategy = e13.overlapStrategy ?? Jt, this.setManifestInternal(e13.manifest), this.documentManagerUnsubs.push(this.documentManager.provides().onDocumentOpened((e14) => {
3105
+ this.isOwnedChapter(e14.id) && (this.passwordAttempts.delete(e14.id), this.updateStatus(e14.id, "loaded"));
3106
+ }), this.documentManager.provides().onDocumentClosed((e14) => {
3107
+ this.isOwnedChapter(e14) && this.updateStatus(e14, "closed");
3108
+ }), this.documentManager.provides().onDocumentError((e14) => {
3109
+ this.isOwnedChapter(e14.documentId) && this.handleDocumentError(e14.documentId, e14.code, e14.message);
3110
+ })), e13.unloadTimeoutMs && e13.unloadTimeoutMs > 0) {
3111
+ const t = Math.max(5e3, Math.floor(e13.unloadTimeoutMs / 4));
3112
+ this.unloadTimer = setInterval(() => this.collectIdleChapters(), t);
3113
+ }
3114
+ }
3115
+ buildCapability() {
3116
+ return { setManifest: (e13, t) => {
3117
+ t && (this.overlapStrategy = t), this.setManifestInternal(e13);
3118
+ }, getManifest: () => this.manifest, getVirtualPageMap: () => this.virtualPageMap, setVisibleGlobalPages: (e13) => this.handleVisibleChange(e13), ensureChapterLoaded: (e13) => this.ensureChapterLoaded(e13), getChapterStatus: (e13) => this.chapterStatus.get(e13) ?? "idle", getChapter: (e13) => this.findChapter(e13), onChapterStatusChange: this.statusChange$.on, onManifestChange: this.manifestChange$.on };
3119
+ }
3120
+ destroy() {
3121
+ super.destroy();
3122
+ for (const e13 of this.documentManagerUnsubs) e13();
3123
+ this.documentManagerUnsubs = [], this.unloadTimer && clearInterval(this.unloadTimer), this.unloadTimer = null, this.statusChange$.clear(), this.manifestChange$.clear();
3124
+ }
3125
+ setManifestInternal(t) {
3126
+ const a = (function(e13) {
3127
+ const t2 = [], a2 = /* @__PURE__ */ new Set();
3128
+ for (const s2 of e13.chapters) {
3129
+ a2.has(s2.chapterId) && t2.push(`Duplicate chapterId: ${s2.chapterId}`), a2.add(s2.chapterId);
3130
+ const [e14, i2] = s2.globalPageRange, [o, r] = s2.localPageRange;
3131
+ if (e14 > i2 && t2.push(`${s2.chapterId}: invalid globalPageRange [${e14},${i2}]`), o > r && t2.push(`${s2.chapterId}: invalid localPageRange [${o},${r}]`), i2 - e14 !== r - o && t2.push(`${s2.chapterId}: page-count mismatch (global ${i2 - e14 + 1} vs local ${r - o + 1})`), s2.ownedGlobalPages) for (const a3 of s2.ownedGlobalPages) (a3 < e14 || a3 > i2) && t2.push(`${s2.chapterId}: ownedGlobalPages contains ${a3} outside range`);
3132
+ }
3133
+ return t2;
3134
+ })(t);
3135
+ a.length > 0 && this.logger.warn(e11.id, "ManifestValidation", `Chapter manifest has issues: ${a.join("; ")}`);
3136
+ const s = new Set(this.chapterStatus.keys()), i = new Set(t.chapters.map((e13) => e13.chapterId));
3137
+ for (const e13 of s) i.has(e13) || (this.closeChapter(e13), this.chapterStatus.delete(e13));
3138
+ for (const e13 of t.chapters) this.chapterStatus.has(e13.chapterId) || this.chapterStatus.set(e13.chapterId, "idle");
3139
+ this.manifest = t, this.virtualPageMap = aa(t, this.overlapStrategy), this.manifestChange$.emit({ manifest: t, map: this.virtualPageMap }), this.eagerPrefetchFromManifest();
3140
+ }
3141
+ eagerPrefetchFromManifest() {
3142
+ const e13 = this.config.prefetchChapters ?? 0;
3143
+ if (e13 <= 0 || 0 === this.manifest.chapters.length) return;
3144
+ const t = Date.now(), a = Math.min(e13, this.manifest.chapters.length);
3145
+ for (let s = 0; s < a; s++) {
3146
+ const e14 = this.manifest.chapters[s].chapterId;
3147
+ this.chapterLastUsed.set(e14, t);
3148
+ const a2 = this.chapterStatus.get(e14) ?? "idle";
3149
+ "idle" !== a2 && "closed" !== a2 && "error" !== a2 || this.ensureChapterLoaded(e14);
3150
+ }
3151
+ }
3152
+ findChapter(e13) {
3153
+ return this.manifest.chapters.find((t) => t.chapterId === e13) ?? null;
3154
+ }
3155
+ isOwnedChapter(e13) {
3156
+ return !!this.findChapter(e13);
3157
+ }
3158
+ handleVisibleChange(e13) {
3159
+ if (!this.virtualPageMap) return;
3160
+ const t = Date.now(), a = this.config.prefetchChapters ?? 1, s = /* @__PURE__ */ new Set();
3161
+ for (const n of e13) {
3162
+ const e14 = this.virtualPageMap.atIndex(n);
3163
+ e14 && s.add(e14.chapterId);
3164
+ }
3165
+ if (0 === s.size) return;
3166
+ const i = this.manifest.chapters.map((e14) => e14.chapterId), o = /* @__PURE__ */ new Set();
3167
+ for (const n of s) {
3168
+ const e14 = i.indexOf(n);
3169
+ if (-1 !== e14) for (let t2 = e14 - a; t2 <= e14 + a; t2++) t2 >= 0 && t2 < i.length && o.add(t2);
3170
+ }
3171
+ const r = /* @__PURE__ */ new Set();
3172
+ for (const n of o) r.add(i[n]);
3173
+ for (const n of r) {
3174
+ this.chapterLastUsed.set(n, t);
3175
+ const e14 = this.chapterStatus.get(n) ?? "idle";
3176
+ "idle" !== e14 && "closed" !== e14 && "error" !== e14 || this.ensureChapterLoaded(n);
3177
+ }
3178
+ if (this.config.autoActivateOnLoad ?? 1) {
3179
+ const e14 = i.find((e15) => s.has(e15));
3180
+ if (e14 && this.documentManager.provides().isDocumentOpen(e14)) {
3181
+ this.documentManager.provides().getActiveDocumentId() !== e14 && this.documentManager.provides().setActiveDocument(e14);
3182
+ }
3183
+ }
3184
+ }
3185
+ collectIdleChapters() {
3186
+ const e13 = this.config.unloadTimeoutMs ?? 6e4;
3187
+ if (e13 <= 0) return;
3188
+ const t = Date.now();
3189
+ for (const [a, s] of this.chapterStatus) {
3190
+ if ("loaded" !== s) continue;
3191
+ t - (this.chapterLastUsed.get(a) ?? 0) > e13 && this.closeChapter(a);
3192
+ }
3193
+ }
3194
+ ensureChapterLoaded(e13) {
3195
+ const t = this.pendingLoadPromises.get(e13);
3196
+ if (t) return t;
3197
+ const a = this.findChapter(e13);
3198
+ if (!a) return Promise.resolve("error");
3199
+ const s = this.chapterStatus.get(e13) ?? "idle";
3200
+ if ("loaded" === s) return this.chapterLastUsed.set(e13, Date.now()), Promise.resolve("loaded");
3201
+ if ("loading" === s) return this.waitForTerminalStatus(e13);
3202
+ const i = this.startLoad(a).finally(() => {
3203
+ this.pendingLoadPromises.delete(e13);
3204
+ });
3205
+ return this.pendingLoadPromises.set(e13, i), i;
3206
+ }
3207
+ async resolvePdfPayload(e13) {
3208
+ const t = e13.source;
3209
+ if (t) {
3210
+ if ("url" in t) return { url: t.url };
3211
+ if ("buffer" in t) return { buffer: t.buffer };
3212
+ if ("load" in t) return t.load();
3213
+ }
3214
+ const a = this.config.chapterPdfLoader;
3215
+ if (a) return a.loadPdf(e13);
3216
+ throw new Error(`Chapter "${e13.chapterId}" has no PDF source; set descriptor.source or chapterPdfLoader`);
3217
+ }
3218
+ async startLoad(e13) {
3219
+ var t;
3220
+ this.updateStatus(e13.chapterId, "loading"), this.chapterLastUsed.set(e13.chapterId, Date.now());
3221
+ const a = e13.encrypted && (null == (t = this.passwordProvider) ? void 0 : t.getCachedPassword) ? this.passwordProvider.getCachedPassword(e13.chapterId) : null, s = await this.resolvePdfPayload(e13), i = this.documentManager.provides(), o = "url" in s ? i.openDocumentUrl({ documentId: e13.chapterId, url: s.url, name: e13.title, password: a ?? void 0, autoActivate: false }) : i.openDocumentBuffer({ documentId: e13.chapterId, buffer: s.buffer, name: e13.title, password: a ?? void 0, autoActivate: false });
3222
+ return await new Promise((e14) => o.wait(() => e14(), () => e14())), this.waitForTerminalStatus(e13.chapterId);
3223
+ }
3224
+ waitForTerminalStatus(e13) {
3225
+ return new Promise((t) => {
3226
+ const a = (e14) => {
3227
+ "loaded" !== e14 && "error" !== e14 && "password-required" !== e14 && "closed" !== e14 || (s(), t(e14));
3228
+ }, s = this.statusChange$.on((t2) => {
3229
+ t2.chapterId === e13 && a(t2.status);
3230
+ });
3231
+ a(this.chapterStatus.get(e13) ?? "idle");
3232
+ });
3233
+ }
3234
+ async handleDocumentError(t, a, s) {
3235
+ if (a !== PdfErrorCode.Password) return void this.updateStatus(t, "error");
3236
+ if (!this.passwordProvider) return void this.updateStatus(t, "password-required");
3237
+ const i = this.findChapter(t);
3238
+ if (!i) return;
3239
+ const o = (this.passwordAttempts.get(t) ?? 0) + 1;
3240
+ this.passwordAttempts.set(t, o);
3241
+ let r = null;
3242
+ try {
3243
+ r = await this.passwordProvider.resolvePassword(i, o - 1);
3244
+ } catch (n) {
3245
+ this.logger.error(e11.id, "PasswordProvider", `Provider rejected for ${t}`, n);
3246
+ }
3247
+ if (!r) return void this.updateStatus(t, "password-required");
3248
+ this.updateStatus(t, "loading");
3249
+ this.documentManager.provides().retryDocument(t, { password: r }).wait(() => {
3250
+ }, () => {
3251
+ });
3252
+ }
3253
+ closeChapter(e13) {
3254
+ const t = this.documentManager.provides();
3255
+ if (t.isDocumentOpen(e13)) {
3256
+ t.closeDocument(e13).wait(() => this.updateStatus(e13, "closed"), () => this.updateStatus(e13, "closed"));
3257
+ } else this.updateStatus(e13, "closed");
3258
+ }
3259
+ updateStatus(e13, t, a) {
3260
+ this.chapterStatus.get(e13) !== t && (this.chapterStatus.set(e13, t), this.statusChange$.emit({ chapterId: e13, status: t, ..."error" === t && a ? { error: { message: a } } : {} }));
3261
+ }
3262
+ };
3263
+ sa.id = "chapter-manager";
3264
+ let ia = sa;
3265
+ const oa = class extends BasePlugin {
3266
+ constructor(e13, t) {
3267
+ super(e13, t), this.layoutChange$ = createBehaviorEmitter(), this.visibleChange$ = createBehaviorEmitter(), this.virtualPageMap = null, this.pageSizes = /* @__PURE__ */ new Map(), this.offsets = [], this.totalHeight = 0, this.totalWidth = 0, this.viewportEl = null, this.viewportObservers = null, this.currentVisible = [], this.currentGlobalPageIndex = 0, this.chapterManagerUnsubs = [], this.chapterManager = this.registry.getPlugin(ia.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
3268
+ }
3269
+ async initialize(e13) {
3270
+ this.config = { placeholderPageHeight: e13.placeholderPageHeight ?? 1200, placeholderPageWidth: e13.placeholderPageWidth ?? 900, bufferSize: e13.bufferSize ?? 2, pageGap: e13.pageGap ?? 20 }, this.virtualPageMap = this.chapterManager.provides().getVirtualPageMap(), this.rebuildOffsets(), this.chapterManagerUnsubs.push(this.chapterManager.provides().onManifestChange(({ map: e14 }) => {
3271
+ this.virtualPageMap = e14, this.pageSizes.clear(), this.rebuildOffsets(), this.syncReadyChapterSizes(), this.recomputeVisible();
3272
+ })), this.syncReadyChapterSizes();
3273
+ }
3274
+ isChapterDocumentReady(e13) {
3275
+ const t = this.coreState.core.documents[e13];
3276
+ return !(!t || "loaded" !== t.status || !t.document) && t.document.pages.length > 0;
3277
+ }
3278
+ refreshLayout() {
3279
+ this.layoutChange$.emit(this.computeLayout());
3280
+ }
3281
+ syncReadyChapterSizes() {
3282
+ for (const e13 of this.chapterManager.provides().getManifest().chapters) this.isChapterDocumentReady(e13.chapterId) && this.harvestChapterSizes(e13.chapterId);
3283
+ this.refreshLayout();
3284
+ }
3285
+ onDocumentLoaded(e13) {
3286
+ var t;
3287
+ if (0 === ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0)) return;
3288
+ const a = this.documentManager.provides();
3289
+ a.getActiveDocumentId() || a.setActiveDocument(e13), this.harvestChapterSizes(e13), this.refreshLayout();
3290
+ }
3291
+ onDocumentClosed(e13) {
3292
+ var t;
3293
+ 0 !== ((null == (t = this.virtualPageMap) ? void 0 : t.pagesOfChapter(e13).length) ?? 0) && (this.dropChapterSizes(e13), this.refreshLayout());
3294
+ }
3295
+ buildCapability() {
3296
+ return { registerViewport: (e13) => this.bindViewport(e13), reportChapterPageSizes: (e13, t) => this.applyChapterPageSizes(e13, t), getLayout: () => this.computeLayout(), getCurrentGlobalPageIndex: () => this.currentGlobalPageIndex, getVisibleGlobalPageIndices: () => this.currentVisible.slice(), scrollToGlobalPageIndex: (e13, t) => this.scrollToIndex(e13, t), scrollToChapter: (e13, t) => this.scrollToChapter(e13, t), scrollToGlobalPageNumber: (e13, t) => this.scrollToGlobalNumber(e13, t), scrollToGlobalPdfPoint: (e13, t, a) => this.scrollToGlobalPdfPoint(e13, t, a), onLayoutChange: this.layoutChange$.on, onVisibleChange: this.visibleChange$.on };
3297
+ }
3298
+ destroy() {
3299
+ var e13;
3300
+ super.destroy();
3301
+ for (const t of this.chapterManagerUnsubs) t();
3302
+ this.chapterManagerUnsubs = [], null == (e13 = this.viewportObservers) || e13.unbind(), this.viewportObservers = null, this.viewportEl = null, this.layoutChange$.clear(), this.visibleChange$.clear();
3303
+ }
3304
+ getPageSize(e13) {
3305
+ return this.pageSizes.get(e13) ?? { width: this.config.placeholderPageWidth, height: this.config.placeholderPageHeight };
3306
+ }
3307
+ rebuildOffsets() {
3308
+ if (!this.virtualPageMap) return this.offsets = [], this.totalHeight = 0, void (this.totalWidth = 0);
3309
+ const e13 = this.virtualPageMap.totalPages;
3310
+ this.offsets = new Array(e13);
3311
+ let t = 0, a = 0;
3312
+ for (let s = 0; s < e13; s++) {
3313
+ const { width: e14, height: i } = this.getPageSize(s);
3314
+ this.offsets[s] = t, t += i + this.config.pageGap, e14 > a && (a = e14);
3315
+ }
3316
+ this.totalHeight = e13 > 0 ? t - this.config.pageGap : 0, this.totalWidth = a, this.layoutChange$.emit(this.computeLayout());
3317
+ }
3318
+ applyChapterPageSizes(e13, t) {
3319
+ if (!this.virtualPageMap) return;
3320
+ let a = false;
3321
+ for (const s of t) {
3322
+ const t2 = this.virtualPageMap.toGlobal(e13, s.localPageIndex);
3323
+ if (!t2) continue;
3324
+ const i = this.pageSizes.get(t2.globalPageIndex);
3325
+ i && i.width === s.width && i.height === s.height || (this.pageSizes.set(t2.globalPageIndex, { width: s.width, height: s.height }), a = true);
3326
+ }
3327
+ if (a) {
3328
+ const e14 = this.currentGlobalPageIndex, t2 = this.offsets[e14] ?? 0;
3329
+ if (this.rebuildOffsets(), this.viewportEl) {
3330
+ const a2 = (this.offsets[e14] ?? 0) - t2;
3331
+ 0 !== a2 && (this.viewportEl.scrollTop += a2);
3332
+ }
3333
+ this.recomputeVisible();
3334
+ }
3335
+ }
3336
+ getChapterDocumentScale(e13) {
3337
+ var t;
3338
+ return (null == (t = this.coreState.core.documents[e13]) ? void 0 : t.scale) ?? 1;
3339
+ }
3340
+ harvestChapterSizes(e13, t = 0) {
3341
+ var a;
3342
+ if (!this.virtualPageMap) return;
3343
+ const s = this.documentManager.provides().getDocument(e13), i = this.virtualPageMap.pagesOfChapter(e13);
3344
+ if (!(null == (a = null == s ? void 0 : s.pages) ? void 0 : a.length) || 0 === i.length) return void (t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1)));
3345
+ const o = this.getChapterDocumentScale(e13), r = [];
3346
+ for (const n of i) {
3347
+ const e14 = s.pages[n.localPageIndex];
3348
+ (null == e14 ? void 0 : e14.size) && r.push({ localPageIndex: n.localPageIndex, width: e14.size.width * o, height: e14.size.height * o });
3349
+ }
3350
+ 0 !== r.length ? this.applyChapterPageSizes(e13, r) : t < 60 && requestAnimationFrame(() => this.harvestChapterSizes(e13, t + 1));
3351
+ }
3352
+ onScaleChanged(e13) {
3353
+ const t = this.coreState.core.documents[e13];
3354
+ t && "loaded" === t.status && this.chapterManager.provides().getChapter(e13) && this.harvestChapterSizes(e13);
3355
+ }
3356
+ dropChapterSizes(e13) {
3357
+ if (!this.virtualPageMap) return;
3358
+ let t = false;
3359
+ for (const a of this.virtualPageMap.pagesOfChapter(e13)) this.pageSizes.delete(a.globalPageIndex) && (t = true);
3360
+ t && (this.rebuildOffsets(), this.recomputeVisible());
3361
+ }
3362
+ bindViewport(e13) {
3363
+ var t;
3364
+ if (null == (t = this.viewportObservers) || t.unbind(), this.viewportEl = e13, this.viewportObservers = null, !e13) return;
3365
+ const a = () => this.recomputeVisible(), s = new ResizeObserver(() => this.recomputeVisible());
3366
+ e13.addEventListener("scroll", a, { passive: true }), s.observe(e13), this.viewportObservers = { unbind: () => {
3367
+ e13.removeEventListener("scroll", a), s.disconnect();
3368
+ } }, this.syncReadyChapterSizes(), this.recomputeVisible(), 0 === e13.clientHeight && requestAnimationFrame(() => {
3369
+ requestAnimationFrame(() => this.recomputeVisible());
3370
+ });
3371
+ }
3372
+ recomputeVisible() {
3373
+ if (!this.viewportEl || !this.virtualPageMap) return;
3374
+ const e13 = this.virtualPageMap.totalPages;
3375
+ if (0 === e13) return this.currentVisible = [], this.currentGlobalPageIndex = 0, void this.layoutChange$.emit(this.computeLayout());
3376
+ const t = this.viewportEl.scrollTop, a = t + this.viewportEl.clientHeight, s = this.findFirstVisibleIndex(t);
3377
+ let i = s;
3378
+ for (; i < e13; ) {
3379
+ const e14 = this.getPageSize(i), t2 = this.offsets[i];
3380
+ if (e14.height, t2 >= a) break;
3381
+ i++;
3382
+ }
3383
+ const o = [];
3384
+ let r = s, n = -1;
3385
+ for (let l = s; l < i; l++) {
3386
+ o.push(l);
3387
+ const e14 = this.offsets[l], s2 = e14 + this.getPageSize(l).height, i2 = Math.max(0, Math.min(s2, a) - Math.max(e14, t));
3388
+ i2 > n && (n = i2, r = l);
3389
+ }
3390
+ this.currentVisible = o, this.currentGlobalPageIndex = r, this.visibleChange$.emit({ visibleGlobalPageIndices: o, currentGlobalPageIndex: r }), this.chapterManager.provides().setVisibleGlobalPages(o), this.layoutChange$.emit(this.computeLayout());
3391
+ }
3392
+ findFirstVisibleIndex(e13) {
3393
+ let t = 0, a = this.offsets.length - 1, s = 0;
3394
+ for (; t <= a; ) {
3395
+ const i = t + a >> 1;
3396
+ this.offsets[i] <= e13 ? (s = i, t = i + 1) : a = i - 1;
3397
+ }
3398
+ return s;
3399
+ }
3400
+ computeLayout() {
3401
+ const e13 = this.config.bufferSize, t = Math.max(0, (this.currentVisible[0] ?? 0) - e13), a = this.currentVisible[this.currentVisible.length - 1] ?? -1, s = Math.min(this.offsets.length - 1, (a >= 0 ? a : 0) + e13), i = [];
3402
+ if (this.virtualPageMap && this.offsets.length > 0) for (let o = t; o <= s; o++) {
3403
+ const e14 = this.virtualPageMap.atIndex(o);
3404
+ if (!e14) continue;
3405
+ const t2 = this.getPageSize(o), a2 = !this.isChapterDocumentReady(e14.chapterId);
3406
+ i.push({ globalPageIndex: o, globalPageNumber: e14.globalPageNumber, chapterId: e14.chapterId, localPageIndex: e14.localPageIndex, width: t2.width, height: t2.height, offsetTop: this.offsets[o], isPlaceholder: a2 });
3407
+ }
3408
+ return { totalHeight: this.totalHeight, totalWidth: this.totalWidth || this.config.placeholderPageWidth, items: i, pageGap: this.config.pageGap };
3409
+ }
3410
+ scrollToIndex(e13, t) {
3411
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length) return;
3412
+ const a = (this.offsets[e13] ?? 0) - ((null == t ? void 0 : t.topOffset) ?? 0);
3413
+ this.viewportEl.scrollTo({ top: a, behavior: (null == t ? void 0 : t.behavior) ?? "auto" });
3414
+ }
3415
+ scrollToGlobalPdfPoint(e13, t, a) {
3416
+ var s;
3417
+ if (!this.viewportEl || e13 < 0 || e13 >= this.offsets.length || !this.virtualPageMap) return;
3418
+ const i = (null == a ? void 0 : a.marginTop) ?? 80, o = this.virtualPageMap.atIndex(e13);
3419
+ if (!o) return void this.scrollToIndex(e13, a);
3420
+ const r = this.pageSizes.get(e13), n = null == (s = this.documentManager.provides().getDocument(o.chapterId)) ? void 0 : s.pages[o.localPageIndex];
3421
+ if (!r || !n) return void this.scrollToIndex(e13, a);
3422
+ const l = r.height / n.size.height, h2 = (this.offsets[e13] ?? 0) + t * l - i;
3423
+ this.viewportEl.scrollTo({ top: Math.max(0, h2), behavior: (null == a ? void 0 : a.behavior) ?? "auto" });
3424
+ }
3425
+ scrollToChapter(e13, t) {
3426
+ if (!this.virtualPageMap) return;
3427
+ const a = this.virtualPageMap.firstIndexOfChapter(e13);
3428
+ a < 0 || (this.chapterManager.provides().ensureChapterLoaded(e13), this.scrollToIndex(a, t));
3429
+ }
3430
+ scrollToGlobalNumber(e13, t) {
3431
+ if (!this.virtualPageMap) return;
3432
+ const a = this.virtualPageMap.byGlobalNumber(e13);
3433
+ a && this.scrollToIndex(a.globalPageIndex, t);
3434
+ }
3435
+ };
3436
+ oa.id = "chapter-scroll";
3437
+ let ra = oa;
3438
+ const na = class e12 extends BasePlugin {
3439
+ constructor(e13, t) {
3440
+ super(e13, t), this.notesChange$ = createBehaviorEmitter([]), this.noteActivated$ = createEmitter(), this.notes = /* @__PURE__ */ new Map(), this.chapterScroll = this.registry.getPlugin(ra.id), this.chapterManager = this.registry.getPlugin(Qt.id), this.documentManager = this.registry.getPlugin(DocumentManagerPlugin.id);
3441
+ }
3442
+ async initialize(t) {
3443
+ if (this.config = t, t.callbacks.loadNotes) try {
3444
+ const e13 = await t.callbacks.loadNotes();
3445
+ for (const t2 of e13) this.notes.set(t2.noteId, t2);
3446
+ this.notesChange$.emit(this.listAll());
3447
+ } catch (a) {
3448
+ this.logger.error(e12.id, "LoadNotes", "Failed to load notes", a);
3449
+ }
3450
+ }
3451
+ buildCapability() {
3452
+ return { createNoteFromSelection: (e13) => this.createNoteFromSelection(e13), requestCreateFromSelection: (e13) => this.requestCreateFromSelection(e13), registerNote: (e13) => this.registerNote(e13), listNotesForPage: (e13, t) => this.listAll().filter((a) => a.chapterId === e13 && a.localPageIndex === t), listAllNotes: () => this.listAll(), getNote: (e13) => this.notes.get(e13) ?? null, deleteNote: (e13) => this.deleteNote(e13), updateNoteContent: (e13, t) => this.updateNoteContent(e13, t), scrollToNote: (e13) => this.scrollToNote(e13), onNotesChange: this.notesChange$.on, onNoteActivated: this.noteActivated$.on };
3453
+ }
3454
+ registerNote(e13) {
3455
+ this.notes.set(e13.noteId, e13), this.notesChange$.emit(this.listAll());
3456
+ }
3457
+ requestEdit(e13) {
3458
+ const t = this.notes.get(e13);
3459
+ t && (this.config.callbacks.onRequestEditNote ? this.config.callbacks.onRequestEditNote(e13, t) : this.activateNote(e13));
3460
+ }
3461
+ activateNote(e13) {
3462
+ var t, a;
3463
+ const s = this.notes.get(e13);
3464
+ s && (null == (a = (t = this.config.callbacks).onActivateNote) || a.call(t, e13, s), this.noteActivated$.emit({ noteId: e13, anchor: s }));
3465
+ }
3466
+ listAll() {
3467
+ return Array.from(this.notes.values());
3468
+ }
3469
+ buildDraft(e13) {
3470
+ return { chapterId: e13.chapterId, localPageIndex: e13.localPageIndex, globalPageNumber: e13.globalPageNumber, globalPageIndex: e13.globalPageIndex, rectsPdfCoord: e13.rectsPdfCoord, endAnchor: ha(e13.rectsPdfCoord), selectedText: e13.selectedText, content: e13.content };
3471
+ }
3472
+ async requestCreateFromSelection(e13) {
3473
+ if (0 === e13.rectsPdfCoord.length) return null;
3474
+ const t = this.buildDraft(e13), { onRequestCreateNote: a, onCreateNote: s } = this.config.callbacks;
3475
+ return a ? (a({ draft: t, complete: async (e14) => {
3476
+ const a2 = { ...t, noteId: e14 };
3477
+ this.registerNote(a2);
3478
+ } }), null) : this.createNoteFromSelection(e13);
3479
+ }
3480
+ async createNoteFromSelection(t) {
3481
+ if (0 === t.rectsPdfCoord.length) return null;
3482
+ const a = this.buildDraft(t), s = this.config.callbacks.onCreateNote;
3483
+ if (!s) return this.logger.error(e12.id, "CreateNote", "Missing onCreateNote / onRequestCreateNote"), null;
3484
+ let i = null;
3485
+ try {
3486
+ i = await s(a);
3487
+ } catch (r) {
3488
+ return this.logger.error(e12.id, "OnCreateNote", "Callback failed", r), null;
3489
+ }
3490
+ if (!i) return null;
3491
+ const o = { ...a, noteId: i.noteId };
3492
+ return this.registerNote(o), o;
3493
+ }
3494
+ async deleteNote(t) {
3495
+ var a, s;
3496
+ if (this.notes.has(t)) {
3497
+ try {
3498
+ await (null == (s = (a = this.config.callbacks).onDeleteNote) ? void 0 : s.call(a, t));
3499
+ } catch (i) {
3500
+ return void this.logger.error(e12.id, "OnDeleteNote", "Callback failed", i);
3501
+ }
3502
+ this.notes.delete(t), this.notesChange$.emit(this.listAll());
3503
+ }
3504
+ }
3505
+ async updateNoteContent(t, a) {
3506
+ var s, i;
3507
+ const o = this.notes.get(t);
3508
+ if (!o) return;
3509
+ const r = { ...o, content: a };
3510
+ try {
3511
+ await (null == (i = (s = this.config.callbacks).onUpdateNote) ? void 0 : i.call(s, r));
3512
+ } catch (n) {
3513
+ return void this.logger.error(e12.id, "OnUpdateNote", "Callback failed", n);
3514
+ }
3515
+ this.notes.set(t, r), this.notesChange$.emit(this.listAll());
3516
+ }
3517
+ async scrollToNote(e13) {
3518
+ var t;
3519
+ const a = this.notes.get(e13);
3520
+ if (!a) return;
3521
+ const s = this.chapterScroll.provides();
3522
+ await this.chapterManager.provides().ensureChapterLoaded(a.chapterId);
3523
+ (null == (t = this.documentManager.provides().getDocument(a.chapterId)) ? void 0 : t.pages[a.localPageIndex]) ? (s.scrollToGlobalPageIndex(a.globalPageIndex), await this.waitForPageInLayout(a.globalPageIndex), s.scrollToGlobalPdfPoint(a.globalPageIndex, a.endAnchor.y, { marginTop: 80 })) : s.scrollToGlobalPageIndex(a.globalPageIndex);
3524
+ }
3525
+ waitForPageInLayout(e13) {
3526
+ const t = this.chapterScroll.provides(), a = t.getLayout().items.find((t2) => t2.globalPageIndex === e13 && !t2.isPlaceholder);
3527
+ return a ? Promise.resolve(a) : new Promise((a2) => {
3528
+ const s = setTimeout(() => {
3529
+ i(), a2(null);
3530
+ }, 2500), i = t.onLayoutChange((t2) => {
3531
+ const o = t2.items.find((t3) => t3.globalPageIndex === e13 && !t3.isPlaceholder);
3532
+ o && (clearTimeout(s), i(), a2(o));
3533
+ });
3534
+ });
3535
+ }
3536
+ };
3537
+ na.id = "note";
3538
+ let la = na;
3539
+ function ha(e13) {
3540
+ const t = e13[e13.length - 1];
3541
+ return { x: t.origin.x + t.size.width, y: t.origin.y + t.size.height };
3542
+ }
3543
+ function da(e13) {
3544
+ const { markerPdf: t, lineRects: a, sx: s, sy: i, cssPageWidth: o, iconSize: r, gapPx: n = 6 } = e13, l = (a == null ? void 0 : a.length) ? a[a.length - 1] : void 0;
3545
+ let h2, d;
3546
+ l ? (h2 = (l.origin.x + l.size.width) * s + n, d = l.origin.y * i + (l.size.height * i - r) / 2) : (h2 = t.x * s - r / 2, d = t.y * i - r - n);
3547
+ const c = Math.max(0, o - r - 2);
3548
+ return h2 > c && (h2 = c), d < 0 && (d = 0), { left: h2, top: d };
3549
+ }
3550
+ const ca = { key: 0, style: { position: "absolute", inset: "0", pointerEvents: "none", zIndex: 25 } }, ua = ["onMouseenter"], pa = ["data-note-marker-zone", "onMouseenter", "onMouseleave"], ga = ["onClick"], fa = ["onClick"], ma = ["onClick"], va = /* @__PURE__ */ defineComponent({ __name: "NoteMarkerLayer", props: { chapterId: {}, localPageIndex: {}, pdfPageWidth: {}, pdfPageHeight: {}, cssPageWidth: {}, cssPageHeight: {}, ui: {} }, setup(e13) {
3551
+ const a = e13, { provides: l } = useCapability(la.id), u = ref([]), p = ref(null), b = ref(null);
3552
+ watch(l, (e14) => {
3553
+ if (e14) return e14.onNotesChange((e15) => {
3554
+ u.value = e15.filter((e16) => e16.chapterId === a.chapterId && e16.localPageIndex === a.localPageIndex);
3555
+ });
3556
+ }, { immediate: true });
3557
+ let P = null;
3558
+ watch(b, (e14) => {
3559
+ P && (document.removeEventListener("mousedown", P), P = null), e14 && (P = (t) => {
3560
+ var _a2;
3561
+ const a2 = t.target;
3562
+ ((_a2 = a2.closest) == null ? void 0 : _a2.call(a2, `[data-note-marker-zone="${e14}"]`)) || (b.value = null, p.value = null);
3563
+ }, document.addEventListener("mousedown", P));
3564
+ }), onBeforeUnmount(() => {
3565
+ P && document.removeEventListener("mousedown", P);
3566
+ });
3567
+ const w = computed(() => {
3568
+ var _a2;
3569
+ return ((_a2 = a.ui) == null ? void 0 : _a2.iconSize) ?? 16;
3570
+ }), y = computed(() => {
3571
+ var _a2;
3572
+ return ((_a2 = a.ui) == null ? void 0 : _a2.highlightColor) ?? "rgba(245, 158, 11, 0.08)";
3573
+ });
3574
+ function I(e14) {
3575
+ const t = a.cssPageWidth / a.pdfPageWidth, s = a.cssPageHeight / a.pdfPageHeight, i = w.value, { left: o, top: r } = da({ markerPdf: e14.endAnchor, lineRects: e14.rectsPdfCoord, sx: t, sy: s, cssPageWidth: a.cssPageWidth, iconSize: i }), n = (function(e15, t2, a2) {
3576
+ let s2 = 1 / 0, i2 = 1 / 0, o2 = -1 / 0, r2 = -1 / 0;
3577
+ for (const n2 of e15) s2 = Math.min(s2, n2.origin.x * t2), i2 = Math.min(i2, n2.origin.y * a2), o2 = Math.max(o2, (n2.origin.x + n2.size.width) * t2), r2 = Math.max(r2, (n2.origin.y + n2.size.height) * a2);
3578
+ return { left: s2, top: i2, width: o2 - s2, height: r2 - i2 };
3579
+ })(e14.rectsPdfCoord, t, s), l2 = b.value === e14.noteId ? 72 : 0, h2 = Math.max(0, Math.min(n.left, o) - 8), d = Math.max(0, Math.min(n.top, r) - 8);
3580
+ return { zoneLeft: h2, zoneTop: d, zoneW: Math.min(a.cssPageWidth, Math.max(n.left + n.width, o + i) + 8) - h2, zoneH: Math.max(n.top + n.height, r + i + 6 + l2) + 8 - d, iconLeft: o, iconTop: r, sx: t, sy: s };
3581
+ }
3582
+ return (t, a2) => unref(l) && u.value.length && e13.pdfPageWidth && e13.pdfPageHeight ? (openBlock(), createElementBlock("div", ca, [(openBlock(true), createElementBlock(Fragment, null, renderList(u.value, (e14) => (openBlock(), createElementBlock(Fragment, { key: e14.noteId }, [(openBlock(true), createElementBlock(Fragment, null, renderList(e14.rectsPdfCoord, (t2, a3) => (openBlock(), createElementBlock("div", { key: `${e14.noteId}-bg-${a3}`, style: normalizeStyle({ position: "absolute", left: t2.origin.x * I(e14).sx + "px", top: t2.origin.y * I(e14).sy + "px", width: t2.size.width * I(e14).sx + "px", height: t2.size.height * I(e14).sy + "px", background: y.value, borderRadius: "2px", pointerEvents: "auto" }), onMouseenter: (t3) => p.value = e14.noteId }, null, 44, ua))), 128)), p.value === e14.noteId || b.value === e14.noteId ? (openBlock(), createElementBlock("div", { key: 0, "data-note-marker-zone": e14.noteId, style: normalizeStyle({ position: "absolute", left: `${I(e14).zoneLeft}px`, top: `${I(e14).zoneTop}px`, width: `${I(e14).zoneW}px`, height: `${I(e14).zoneH}px`, pointerEvents: "auto", zIndex: 26 }), onMouseenter: (t2) => p.value = e14.noteId, onMouseleave: (t2) => b.value !== e14.noteId && (p.value = null) }, [createElementVNode("button", { type: "button", title: "笔记", style: normalizeStyle({ position: "absolute", left: I(e14).iconLeft - I(e14).zoneLeft + "px", top: I(e14).iconTop - I(e14).zoneTop + "px", width: `${w.value}px`, height: `${w.value}px`, border: "none", borderRadius: "50%", background: "#f59e0b", color: "#fff", cursor: "pointer", fontSize: "11px", padding: 0 }), onMousedown: a2[0] || (a2[0] = withModifiers(() => {
3583
+ }, ["stop"])), onClick: withModifiers((t2) => b.value = b.value === e14.noteId ? null : e14.noteId, ["stop"]) }, " 💬 ", 44, ga), b.value === e14.noteId ? (openBlock(), createElementBlock("div", { key: 0, style: normalizeStyle({ position: "absolute", left: I(e14).iconLeft - I(e14).zoneLeft + "px", top: `${I(e14).iconTop - I(e14).zoneTop + w.value + 4}px`, minWidth: "120px", padding: "6px", borderRadius: "8px", background: "#fff", border: "1px solid #e5e7eb", boxShadow: "0 4px 12px rgba(0,0,0,0.12)", zIndex: 30 }), onMousedown: a2[1] || (a2[1] = withModifiers(() => {
3584
+ }, ["stop"])) }, [createElementVNode("button", { type: "button", style: { display: "block", width: "100%", padding: "6px 8px", "font-size": "12px", border: "none", "border-radius": "4px", background: "transparent", color: "#334155", cursor: "pointer", "text-align": "left" }, onClick: (t2) => (function(e15) {
3585
+ var _a2;
3586
+ (_a2 = l.value) == null ? void 0 : _a2.requestEditNote(e15.noteId, e15);
3587
+ })(e14) }, " 编辑 ", 8, fa), createElementVNode("button", { type: "button", style: { display: "block", width: "100%", padding: "6px 8px", "font-size": "12px", border: "none", "border-radius": "4px", background: "transparent", color: "#dc2626", cursor: "pointer", "text-align": "left" }, onClick: (t2) => {
3588
+ var _a2;
3589
+ return a3 = e14.noteId, (_a2 = l.value) == null ? void 0 : _a2.requestDeleteNote(a3), void (b.value = null);
3590
+ var a3;
3591
+ } }, " 删除 ", 8, ma)], 36)) : createCommentVNode("", true)], 44, pa)) : createCommentVNode("", true)], 64))), 128))])) : createCommentVNode("", true);
3592
+ } }), ba = { key: 0, style: { position: "absolute", inset: "0", pointerEvents: "none" } }, Pa = ["title", "onClick"], wa = ["onClick"], ya = /* @__PURE__ */ defineComponent({ __name: "BookmarkMarkerLayer", props: { chapterId: {}, localPageIndex: {}, pdfPageWidth: {}, pdfPageHeight: {}, cssPageWidth: {}, cssPageHeight: {}, ui: {} }, setup(e13) {
3593
+ const a = e13, { provides: l } = useCapability(It.id), u = ref([]), p = ref(null), b = ref(null);
3594
+ function P() {
3595
+ const e14 = l.value;
3596
+ e14 && (u.value = e14.listBookmarks().filter((e15) => e15.anchor.chapterId === a.chapterId && e15.anchor.localPageIndex === a.localPageIndex));
3597
+ }
3598
+ watch(l, (e14) => {
3599
+ if (e14) return P(), e14.onBookmarksChange(P);
3600
+ }, { immediate: true });
3601
+ let w = null;
3602
+ watch(p, (e14) => {
3603
+ w && (document.removeEventListener("mousedown", w), w = null), e14 && (w = (e15) => {
3604
+ var _a2;
3605
+ ((_a2 = b.value) == null ? void 0 : _a2.contains(e15.target)) || (p.value = null);
3606
+ }, document.addEventListener("mousedown", w));
3607
+ }), onBeforeUnmount(() => {
3608
+ w && document.removeEventListener("mousedown", w);
3609
+ });
3610
+ const y = computed(() => {
3611
+ var _a2;
3612
+ return ((_a2 = a.ui) == null ? void 0 : _a2.iconSize) ?? 16;
3613
+ });
3614
+ function I(e14) {
3615
+ const { left: t, top: s } = (function(e15) {
3616
+ var _a2;
3617
+ const t2 = a.cssPageWidth / a.pdfPageWidth, s2 = a.cssPageHeight / a.pdfPageHeight, i = ((_a2 = e15.anchor.rectsPdfCoord) == null ? void 0 : _a2.length) ? e15.anchor.rectsPdfCoord : [e15.anchor.rectPdfCoord];
3618
+ return da({ markerPdf: e15.anchor.markerAnchor ?? { x: e15.anchor.rectPdfCoord.origin.x + e15.anchor.rectPdfCoord.size.width, y: e15.anchor.rectPdfCoord.origin.y + e15.anchor.rectPdfCoord.size.height }, lineRects: i, sx: t2, sy: s2, cssPageWidth: a.cssPageWidth, iconSize: y.value });
3619
+ })(e14);
3620
+ return { position: "absolute", left: `${Math.max(0, t - 6)}px`, top: `${Math.max(0, s - 6)}px`, width: `${y.value + 12}px`, height: `${y.value + 12}px`, pointerEvents: "auto", zIndex: 20 };
3621
+ }
3622
+ return (t, a2) => unref(l) && u.value.length && e13.pdfPageWidth && e13.pdfPageHeight ? (openBlock(), createElementBlock("div", ba, [(openBlock(true), createElementBlock(Fragment, null, renderList(u.value, (e14) => (openBlock(), createElementBlock("div", { key: e14.id, style: normalizeStyle(I(e14)), onMousedown: a2[1] || (a2[1] = withModifiers(() => {
3623
+ }, ["stop"])) }, [createElementVNode("button", { type: "button", title: e14.label, style: normalizeStyle({ position: "absolute", left: "6px", top: "6px", width: `${y.value}px`, height: `${y.value}px`, border: "none", borderRadius: "4px", background: "#3b82f6", color: "#fff", cursor: "pointer", boxShadow: "0 2px 6px rgba(37, 99, 235, 0.35)", fontSize: "11px", padding: 0 }), onClick: withModifiers((t2) => p.value = p.value === e14.id ? null : e14.id, ["stop"]) }, " 🔖 ", 12, Pa), p.value === e14.id ? (openBlock(), createElementBlock("div", { key: 0, ref_for: true, ref_key: "deleteMenuRef", ref: b, style: { position: "absolute", left: "6px", top: "-36px", zIndex: 30, pointerEvents: "auto", minWidth: "88px", padding: "4px", borderRadius: "6px", background: "#fff", border: "1px solid #e5e7eb", boxShadow: "0 4px 12px rgba(0,0,0,0.12)" }, onClick: a2[0] || (a2[0] = withModifiers(() => {
3624
+ }, ["stop"])) }, [createElementVNode("button", { type: "button", style: { width: "100%", padding: "6px 8px", "font-size": "12px", border: "none", "border-radius": "4px", background: "transparent", color: "#dc2626", cursor: "pointer", "text-align": "left" }, onClick: (t2) => (async function(e15) {
3625
+ const t3 = l.value;
3626
+ if (!t3) return;
3627
+ await t3.requestRemoveBookmark(e15) && (p.value = null);
3628
+ })(e14.id) }, " 删除书签 ", 8, wa)], 512)) : createCommentVNode("", true)], 36))), 128))])) : createCommentVNode("", true);
3629
+ } });
3630
+ function Ia(e13) {
3631
+ return e13.chapterId;
3632
+ }
3633
+ function Ca(e13, t) {
3634
+ e13.wait(t, () => {
3635
+ });
3636
+ }
3637
+ const Ma = /* @__PURE__ */ defineComponent({ __name: "ChapterPageSurface", props: { item: {}, features: {}, showNoteMarkers: { type: Boolean }, showBookmarkMarkers: { type: Boolean }, showRedactionLayer: { type: Boolean }, noteMarkerUi: {}, bookmarkMarkerUi: {}, buildSelectionMenu: { type: Function }, createNote: {}, annotationSelectionMenu: {}, redactionSelectionMenu: {}, renderPageOverlay: { type: Function } }, setup(e13) {
3638
+ const t = e13, a = computed(() => Ia(t.item));
3639
+ !(function(e14) {
3640
+ const { provides: t2 } = useCapability(DocumentManagerPlugin.id);
3641
+ watch([t2, e14], ([e15, t3]) => {
3642
+ e15 && t3 && e15.isDocumentOpen(t3) && e15.setActiveDocument(t3);
3643
+ }, { immediate: true });
3644
+ })(a);
3645
+ const { provides: s } = useCapability(DocumentManagerPlugin.id), { provides: r } = useCapability(SelectionPlugin.id), n = computed(() => {
3646
+ var _a2, _b;
3647
+ return (_b = (_a2 = s.value) == null ? void 0 : _a2.getDocument(a.value)) == null ? void 0 : _b.pages[t.item.localPageIndex];
3648
+ });
3649
+ function l(e14, a2) {
3650
+ const s2 = t.createNote.value;
3651
+ if (s2) return (t2) => {
3652
+ var _a2;
3653
+ const i = { position: "absolute", pointerEvents: "auto", left: "50%", transform: "translateX(-50%)", top: ((_a2 = t2.placement) == null ? void 0 : _a2.suggestTop) ? -40 : t2.rect.size.height + 8 };
3654
+ return h("div", t2.menuWrapperProps, [h("div", { style: i }, h("button", { type: "button", style: { padding: "6px 10px", fontSize: "12px", border: "1px solid #e2e8f0", borderRadius: "6px", background: "#fff", cursor: "pointer" }, onClick: () => {
3655
+ if (!r.value) return;
3656
+ const t3 = r.value.getHighlightRectsForPage(e14.localPageIndex, a2);
3657
+ Ca(r.value.getSelectedText(a2), (a3) => {
3658
+ s2((function(e15, t4, a4) {
3659
+ return { chapterId: e15.chapterId, localPageIndex: e15.localPageIndex, globalPageIndex: e15.globalPageIndex, globalPageNumber: e15.globalPageNumber, rectsPdfCoord: t4, selectedText: a4 };
3660
+ })(e14, t3, a3.join("\n")));
3661
+ });
3662
+ } }, "添加附注"))]);
3663
+ };
3664
+ }
3665
+ const h$1 = computed(() => {
3666
+ const e14 = t.buildSelectionMenu, s2 = { item: t.item, defaultMenu: l(t.item, a.value), createNote: t.createNote.value };
3667
+ if (e14) {
3668
+ const t2 = e14(s2);
3669
+ if (t2) return t2;
3670
+ }
3671
+ return s2.defaultMenu;
3672
+ }), d = computed(() => {
3673
+ var _a2;
3674
+ return (_a2 = t.renderPageOverlay) == null ? void 0 : _a2.call(t, t.item);
3675
+ });
3676
+ return (t2, s2) => e13.item.isPlaceholder ? createCommentVNode("", true) : (openBlock(), createBlock(unref(GlobalPointerProvider), { key: 0, "document-id": a.value }, { default: withCtx(() => [createVNode(unref(Rotate), { "document-id": a.value, "page-index": e13.item.localPageIndex, style: { backgroundColor: "#fff" } }, { default: withCtx(() => [createVNode(unref(PagePointerProvider), { "document-id": a.value, "page-index": e13.item.localPageIndex }, { default: withCtx(() => [createVNode(unref(Bt), { "chapter-id": a.value, "local-page-index": e13.item.localPageIndex }, null, 8, ["chapter-id", "local-page-index"]), createVNode(unref(SelectionLayer), { "document-id": a.value, "page-index": e13.item.localPageIndex, "selection-menu": h$1.value }, null, 8, ["document-id", "page-index", "selection-menu"]), e13.showRedactionLayer ? (openBlock(), createBlock(unref(RedactionLayer), { key: 0, "document-id": a.value, "page-index": e13.item.localPageIndex, "selection-menu": e13.redactionSelectionMenu }, null, 8, ["document-id", "page-index", "selection-menu"])) : createCommentVNode("", true), createVNode(unref(AnnotationLayer), { "document-id": a.value, "page-index": e13.item.localPageIndex, "selection-menu": e13.annotationSelectionMenu }, null, 8, ["document-id", "page-index", "selection-menu"]), e13.showBookmarkMarkers && n.value ? (openBlock(), createBlock(ya, { key: 1, "chapter-id": a.value, "local-page-index": e13.item.localPageIndex, "pdf-page-width": n.value.size.width, "pdf-page-height": n.value.size.height, "css-page-width": e13.item.width, "css-page-height": e13.item.height, ui: e13.bookmarkMarkerUi }, null, 8, ["chapter-id", "local-page-index", "pdf-page-width", "pdf-page-height", "css-page-width", "css-page-height", "ui"])) : createCommentVNode("", true), d.value ? (openBlock(), createBlock(resolveDynamicComponent(d.value), { key: 2 })) : createCommentVNode("", true), e13.showNoteMarkers && n.value ? (openBlock(), createBlock(va, { key: 3, "chapter-id": a.value, "local-page-index": e13.item.localPageIndex, "pdf-page-width": n.value.size.width, "pdf-page-height": n.value.size.height, "css-page-width": e13.item.width, "css-page-height": e13.item.height, ui: e13.noteMarkerUi }, null, 8, ["chapter-id", "local-page-index", "pdf-page-width", "pdf-page-height", "css-page-width", "css-page-height", "ui"])) : createCommentVNode("", true), renderSlot(t2.$slots, "default")]), _: 3 }, 8, ["document-id", "page-index"])]), _: 3 }, 8, ["document-id", "page-index"])]), _: 3 }, 8, ["document-id"]));
3677
+ } });
3678
+ const Sa = /* @__PURE__ */ defineComponent({ __name: "HoverBookmarkLayer", props: { item: {}, pdfPageWidth: {}, pdfPageHeight: {}, cssPageWidth: {}, cssPageHeight: {}, hoverUi: {} }, setup(e13) {
3679
+ const a = e13, l = computed(() => Ia(a.item)), { provides: d } = useCapability(SelectionPlugin.id), { provides: c } = useCapability(It.id), u = ref(null), p = ref(null), b = ref(null), P = ref(null), w = computed(() => {
3680
+ var _a2;
3681
+ return ((_a2 = a.hoverUi) == null ? void 0 : _a2.iconSize) ?? 16;
3682
+ }), y = computed(() => P.value ?? b.value);
3683
+ let I = null, M = 0;
3684
+ function S() {
3685
+ const e14 = d.value;
3686
+ if (!e14) return;
3687
+ const t = e14.forDocument(l.value).getState().geometry[a.item.localPageIndex];
3688
+ t && (p.value = t);
3689
+ }
3690
+ watch([d, l, () => a.item.localPageIndex], ([e14]) => {
3691
+ if (I == null ? void 0 : I(), I = null, cancelAnimationFrame(M), p.value = null, !e14) return;
3692
+ const t = e14.forDocument(l.value);
3693
+ I = t.onSelectionChange(S);
3694
+ let s = false;
3695
+ const i = () => {
3696
+ if (!s) {
3697
+ try {
3698
+ if (S(), t.getState().geometry[a.item.localPageIndex]) return;
3699
+ } catch {
3700
+ }
3701
+ M = requestAnimationFrame(i);
3702
+ }
3703
+ };
3704
+ return i(), () => {
3705
+ s = true, cancelAnimationFrame(M), I == null ? void 0 : I(), I = null;
3706
+ };
3707
+ }, { immediate: true });
3708
+ let x = null;
3709
+ watch([p, () => a.pdfPageWidth, P, d], () => {
3710
+ x && (document.removeEventListener("mousemove", x), x = null), p.value && a.pdfPageWidth && (x = (e14) => {
3711
+ if (P.value) return;
3712
+ const t = d.value;
3713
+ if (t) try {
3714
+ if (t.forDocument(l.value).getState().selecting) return void (b.value = null);
3715
+ } catch {
3716
+ }
3717
+ const s = u.value;
3718
+ if (!s) return;
3719
+ const i = s.getBoundingClientRect();
3720
+ if (e14.clientX < i.left || e14.clientX > i.right || e14.clientY < i.top || e14.clientY > i.bottom) return void (b.value = null);
3721
+ const o = (function(e15, t2) {
3722
+ const a2 = glyphAt(e15, t2);
3723
+ if (a2 < 0) return null;
3724
+ const s2 = expandToLineBoundary(e15, a2);
3725
+ if (!s2) return null;
3726
+ const i2 = rectsWithinSlice(e15, s2.from, s2.to);
3727
+ return 0 === i2.length ? null : { lineRects: i2, charFrom: s2.from, charTo: s2.to };
3728
+ })(p.value, { x: (e14.clientX - i.left) / (a.cssPageWidth / a.pdfPageWidth), y: (e14.clientY - i.top) / (a.cssPageHeight / a.pdfPageHeight) });
3729
+ b.value = (o == null ? void 0 : o.lineRects) ?? null;
3730
+ }, document.addEventListener("mousemove", x));
3731
+ }, { immediate: true }), onBeforeUnmount(() => {
3732
+ x && document.removeEventListener("mousemove", x), cancelAnimationFrame(M), I == null ? void 0 : I();
3733
+ });
3734
+ const k = computed(() => {
3735
+ const e14 = y.value;
3736
+ return (e14 == null ? void 0 : e14.length) ? Pt(a.item.chapterId, a.item.localPageIndex, e14, { globalPageIndex: a.item.globalPageIndex, globalPageNumber: a.item.globalPageNumber }) : null;
3737
+ }), $ = computed(() => {
3738
+ const e14 = k.value, t = c.value;
3739
+ return !(!e14 || !t) && t.listBookmarks().some((t2) => bt(t2.anchor, e14));
3740
+ });
3741
+ function L() {
3742
+ const e14 = c.value, t = k.value;
3743
+ e14 && t && !$.value && (e14.addBookmark({ label: `书签 ${/* @__PURE__ */ (/* @__PURE__ */ new Date()).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" })}`, anchor: t }), b.value = null, P.value = null);
3744
+ }
3745
+ const z = computed(() => {
3746
+ const e14 = y.value, t = e14 == null ? void 0 : e14[e14.length - 1];
3747
+ if (!t || !a.pdfPageWidth) return null;
3748
+ const s = a.cssPageWidth / a.pdfPageWidth, i = a.cssPageHeight / a.pdfPageHeight, o = w.value;
3749
+ return { iconLeft: Math.min((t.origin.x + t.size.width) * s + 6, Math.max(0, a.cssPageWidth - o - 2)), iconTop: t.origin.y * i + (t.size.height * i - o) / 2, zoneLeft: Math.max(0, (t.origin.x + t.size.width) * s - 4), zoneTop: Math.max(0, t.origin.y * i - 4), size: o };
3750
+ });
3751
+ return (t, a2) => {
3752
+ var _a2;
3753
+ return unref(c) && e13.pdfPageWidth && e13.pdfPageHeight ? (openBlock(), createElementBlock("div", { key: 0, ref_key: "rootRef", ref: u, style: { position: "absolute", inset: "0", zIndex: 14, pointerEvents: "none" } }, [z.value && y.value && !$.value ? (openBlock(), createElementBlock("div", { key: 0, style: normalizeStyle({ position: "absolute", left: `${z.value.zoneLeft}px`, top: `${z.value.zoneTop}px`, width: `${z.value.size + 20}px`, height: `${(((_a2 = y.value[y.value.length - 1]) == null ? void 0 : _a2.size.height) ?? 0) * (e13.cssPageHeight / e13.pdfPageHeight) + z.value.size + 12}px`, pointerEvents: "auto" }), onMouseenter: a2[0] || (a2[0] = (e14) => P.value = y.value), onMouseleave: a2[1] || (a2[1] = (e14) => P.value = null) }, [createElementVNode("button", { type: "button", title: "添加书签", style: normalizeStyle({ position: "absolute", left: z.value.iconLeft - z.value.zoneLeft + "px", top: z.value.iconTop - z.value.zoneTop + "px", width: `${z.value.size}px`, height: `${z.value.size}px`, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", background: "#3b82f6", color: "#fff", border: "none", borderRadius: "4px", boxShadow: "0 2px 8px rgba(37, 99, 235, 0.45)", fontSize: "12px", padding: 0 }), onClick: withModifiers(L, ["stop"]) }, " 🔖 ", 4)], 36)) : createCommentVNode("", true)], 512)) : createCommentVNode("", true);
3754
+ };
3755
+ } }), xa = { highlight: { offsetY: 0 }, underline: { offsetY: 2.5 }, squiggly: { offsetY: 0 }, strikeout: { offsetY: 0 } }, ka = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, squiggly: PdfAnnotationSubtype.SQUIGGLY, strikeout: PdfAnnotationSubtype.STRIKEOUT };
3756
+ function $a(e13, t) {
3757
+ return 0 === t ? e13 : e13.map((e14) => ({ origin: { x: e14.origin.x, y: e14.origin.y + t }, size: { ...e14.size } }));
3758
+ }
3759
+ function La(e13) {
3760
+ let t = 1 / 0, a = 1 / 0, s = -1 / 0, i = -1 / 0;
3761
+ for (const o of e13) t = Math.min(t, o.origin.x), a = Math.min(a, o.origin.y), s = Math.max(s, o.origin.x + o.size.width), i = Math.max(i, o.origin.y + o.size.height);
3762
+ return { origin: { x: t, y: a }, size: { width: s - t, height: i - a } };
3763
+ }
3764
+ function za(e13, t, a, s, i) {
3765
+ const o = a.forDocument(e13), r = s.forDocument(e13);
3766
+ if (!o || !r) return false;
3767
+ const n = "highlight" === t ? "highlight" : "underline" === t ? "underline" : "squiggly" === t ? "squiggly" : "strikeout", l = a.getTool(n);
3768
+ if (!l) return false;
3769
+ const h2 = l.defaults, d = (function(e14, t2) {
3770
+ return { ...xa[e14], ...null == t2 ? void 0 : t2[e14] };
3771
+ })(t, i), c = r.getFormattedSelection();
3772
+ if (0 === c.length) return false;
3773
+ o.setLocked({ type: LockModeType.Exclude, categories: ["markup", "shape"] });
3774
+ for (const u of c) {
3775
+ const e14 = uuidV4(), a2 = d.color ?? h2.color ?? h2.strokeColor, s2 = d.opacity ?? h2.opacity, i2 = d.thickness ?? h2.strokeWidth, r2 = d.offsetY ?? 0, n2 = "underline" === t || "squiggly" === t || "strikeout" === t ? $a(u.segmentRects, r2) : u.segmentRects, l2 = "underline" === t || "squiggly" === t || "strikeout" === t ? La(n2) : u.rect;
3776
+ o.createAnnotation(u.pageIndex, { id: e14, created: /* @__PURE__ */ new Date(), flags: ["print"], type: ka[t], ..."highlight" === t ? { blendMode: PdfBlendMode.Multiply } : {}, strokeColor: a2, opacity: s2, ...null != i2 ? { strokeWidth: i2 } : {}, pageIndex: u.pageIndex, rect: l2, segmentRects: n2 });
3777
+ }
3778
+ return r.clear(), true;
3779
+ }
3780
+ const Ta = { key: 0, width: "24", height: "24", viewBox: "0 0 28 28", fill: "none", "aria-hidden": "" }, Da = { key: 0, x: "5", y: "4", width: "18", height: "20", rx: "3", fill: "#fde047" }, Ga = { key: 1, d: "M6 22h16", stroke: "#dc2626", "stroke-width": "2.2", "stroke-linecap": "round" }, Oa = { key: 2, d: "M6 22c2-2 3-2 5 0s3 2 5 0 3-2 5 0", stroke: "#dc2626", "stroke-width": "2", "stroke-linecap": "round", fill: "none" }, Aa = { key: 3, d: "M5 14h18", stroke: "#dc2626", "stroke-width": "2.2", "stroke-linecap": "round" }, Na = { key: 1, width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "" }, Va = /* @__PURE__ */ defineComponent({ __name: "SelectionToolbarIcons", props: { kind: {} }, setup: (e13) => (t, a) => "note" !== e13.kind ? (openBlock(), createElementBlock("svg", Ta, ["highlight" === e13.kind ? (openBlock(), createElementBlock("rect", Da)) : createCommentVNode("", true), a[0] || (a[0] = createElementVNode("text", { x: "14", y: "19", "text-anchor": "middle", "font-size": "15", "font-weight": "700", "font-family": "system-ui, -apple-system, sans-serif", fill: "#0f172a" }, " A ", -1)), "underline" === e13.kind ? (openBlock(), createElementBlock("path", Ga)) : "squiggly" === e13.kind ? (openBlock(), createElementBlock("path", Oa)) : "strikeout" === e13.kind ? (openBlock(), createElementBlock("path", Aa)) : createCommentVNode("", true)])) : (openBlock(), createElementBlock("svg", Na, [...a[1] || (a[1] = [createElementVNode("path", { d: "M8 3h8l4 4v14H8V3z", fill: "#fef3c7", stroke: "#d97706", "stroke-width": "1.2", "stroke-linejoin": "round" }, null, -1), createElementVNode("path", { d: "M16 3v4h4", stroke: "#d97706", "stroke-width": "1.2" }, null, -1), createElementVNode("path", { d: "M10 12h6M10 16h4", stroke: "#92400e", "stroke-width": "1.2", "stroke-linecap": "round" }, null, -1)])])) }), _a = ["title", "aria-label", "onMouseenter", "onClick"], Ra = ["title", "onMouseenter", "onClick"], Ea = { style: { "font-size": "11px", "font-weight": "600" } }, Ua = /* @__PURE__ */ defineComponent({ __name: "SelectionToolbarCard", props: { placementAbove: { type: Boolean }, anchorHeight: {}, hiddenBuiltinActions: {}, extraActions: {} }, emits: ["action"], setup(e13, { emit: a }) {
3781
+ const s = e13, i = a, l = [{ id: "highlight", label: "高亮背景" }, { id: "underline", label: "下划线" }, { id: "squiggly", label: "波浪线" }, { id: "strikeout", label: "删除线" }, { id: "note", label: "添加笔记" }], u = computed(() => new Set(s.hiddenBuiltinActions ?? [])), p = computed(() => l.filter((e14) => "note" !== e14.id && !u.value.has(e14.id))), g = computed(() => !u.value.has("note")), m = computed(() => [...s.extraActions ?? []].sort((e14, t) => (e14.order ?? 0) - (t.order ?? 0))), b = ref(null), w = computed(() => ({ position: "absolute", pointerEvents: "auto", left: "50%", transform: "translateX(-50%)", top: s.placementAbove ? void 0 : `${s.anchorHeight + 10}px`, bottom: s.placementAbove ? `${s.anchorHeight + 10}px` : void 0, display: "flex", alignItems: "center", gap: "2px", padding: "4px 6px", borderRadius: "12px", background: "rgba(255, 255, 255, 0.96)", border: "1px solid rgba(15, 23, 42, 0.06)", boxShadow: "0 2px 8px rgba(15, 23, 42, 0.08), 0 12px 32px rgba(15, 23, 42, 0.1)", backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)" }));
3782
+ function y(e14, t = false) {
3783
+ return { display: "flex", alignItems: "center", justifyContent: "center", width: "32px", height: "32px", padding: 0, margin: 0, border: "none", borderRadius: "8px", background: b.value === e14 ? t ? "#fffbeb" : "#f1f5f9" : "transparent", color: t ? "#b45309" : "#334155", cursor: "pointer", flexShrink: 0, WebkitAppearance: "none", appearance: "none" };
3784
+ }
3785
+ const C = { width: "1px", height: "20px", margin: "0 4px", background: "rgba(15, 23, 42, 0.1)", flexShrink: 0 };
3786
+ return (e14, t) => (openBlock(), createElementBlock("div", { role: "toolbar", "aria-label": "选区工具", style: normalizeStyle(w.value) }, [(openBlock(true), createElementBlock(Fragment, null, renderList(p.value, (e15) => (openBlock(), createElementBlock("button", { key: e15.id, type: "button", title: e15.label, "aria-label": e15.label, style: normalizeStyle(y(e15.id)), onMouseenter: (t2) => b.value = e15.id, onMouseleave: t[0] || (t[0] = (e16) => b.value = null), onClick: (t2) => i("action", e15.id) }, [createVNode(Va, { kind: e15.id }, null, 8, ["kind"])], 44, _a))), 128)), (openBlock(true), createElementBlock(Fragment, null, renderList(m.value, (e15) => (openBlock(), createElementBlock("button", { key: e15.id, type: "button", title: e15.label, style: normalizeStyle(y(e15.id)), onMouseenter: (t2) => b.value = e15.id, onMouseleave: t[1] || (t[1] = (e16) => b.value = null), onClick: (t2) => i("action", e15.id) }, [createElementVNode("span", Ea, toDisplayString(e15.label.slice(0, 2)), 1)], 44, Ra))), 128)), g.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", { style: C, "aria-hidden": "" }), createElementVNode("button", { type: "button", title: "添加笔记", "aria-label": "添加笔记", style: normalizeStyle(y("note", true)), onMouseenter: t[2] || (t[2] = (e15) => b.value = "note"), onMouseleave: t[3] || (t[3] = (e15) => b.value = null), onClick: t[4] || (t[4] = (e15) => i("action", "note")) }, [createVNode(Va, { kind: "note" })], 36)], 64)) : createCommentVNode("", true)], 4));
3787
+ } }), Fa = { highlight: "highlight", underline: "underline", squiggly: "squiggly", strikeout: "strikeout" };
3788
+ const qa = /* @__PURE__ */ defineComponent({ __name: "PdfChapterViewport", props: { className: {}, features: {}, buildSelectionMenu: {}, annotationSelectionMenu: {}, redactionSelectionMenu: {}, showNoteMarkers: { type: Boolean, default: true }, showBookmarkMarkers: { type: Boolean, default: true }, showRedactionLayer: { type: Boolean, default: false }, renderPageOverlay: {}, onExtraSelectionAction: {} }, setup(e13) {
3789
+ const t = e13, a = (function() {
3790
+ const { registry: e14 } = useRegistry();
3791
+ return computed(() => {
3792
+ var _a2, _b, _c;
3793
+ const t2 = (_c = (_b = (_a2 = e14.value) == null ? void 0 : _a2.getPlugin(Xe.id)) == null ? void 0 : _b.provides) == null ? void 0 : _c.call(_b);
3794
+ return t2 ? (e15) => t2.createNoteFromSelection(e15) : null;
3795
+ });
3796
+ })(), s = (function() {
3797
+ const { registry: e14 } = useRegistry();
3798
+ return computed(() => {
3799
+ var _a2;
3800
+ return !!((_a2 = e14.value) == null ? void 0 : _a2.getPlugin(Xe.id));
3801
+ });
3802
+ })(), i = (function() {
3803
+ const { registry: e14 } = useRegistry();
3804
+ return computed(() => {
3805
+ var _a2;
3806
+ return !!((_a2 = e14.value) == null ? void 0 : _a2.getPlugin(It.id));
3807
+ });
3808
+ })(), h$1 = computed(() => {
3809
+ var _a2, _b;
3810
+ return t.showNoteMarkers && s.value && false !== ((_b = (_a2 = t.features) == null ? void 0 : _a2.notes) == null ? void 0 : _b.enabled);
3811
+ }), d = computed(() => {
3812
+ var _a2, _b;
3813
+ return t.showBookmarkMarkers && i.value && false !== ((_b = (_a2 = t.features) == null ? void 0 : _a2.bookmarks) == null ? void 0 : _b.enabled);
3814
+ }), c = computed(() => {
3815
+ var _a2, _b;
3816
+ return i.value && false !== ((_b = (_a2 = t.features) == null ? void 0 : _a2.bookmarks) == null ? void 0 : _b.enabled);
3817
+ }), p = (function(e14, t2) {
3818
+ const a2 = computed(() => {
3819
+ var _a2;
3820
+ return (_a2 = e14()) == null ? void 0 : _a2.selectionToolbar;
3821
+ }), s2 = computed(() => {
3822
+ var _a2, _b;
3823
+ return false !== ((_b = (_a2 = e14()) == null ? void 0 : _a2.markup) == null ? void 0 : _b.enabled);
3824
+ }), i2 = computed(() => {
3825
+ var _a2, _b;
3826
+ return false !== ((_b = (_a2 = e14()) == null ? void 0 : _a2.notes) == null ? void 0 : _b.enabled);
3827
+ }), { provides: o } = useCapability(SelectionPlugin.id), { provides: r } = useCapability(AnnotationPlugin.id), { provides: n } = useCapability(Xe.id);
3828
+ return computed(() => {
3829
+ var _a2, _b, _c;
3830
+ if (false !== ((_a2 = a2.value) == null ? void 0 : _a2.enabled) && (s2.value || i2.value || ((_c = (_b = a2.value) == null ? void 0 : _b.extraActions) == null ? void 0 : _c.length))) return (l) => {
3831
+ const h$12 = Ia(l.item);
3832
+ return (d2) => {
3833
+ var _a3, _b2, _c2;
3834
+ return h("div", d2.menuWrapperProps, h(Ua, { placementAbove: !!((_a3 = d2.placement) == null ? void 0 : _a3.suggestTop), anchorHeight: d2.rect.size.height, hiddenBuiltinActions: (_b2 = a2.value) == null ? void 0 : _b2.hiddenBuiltinActions, extraActions: (_c2 = a2.value) == null ? void 0 : _c2.extraActions, onAction: (a3) => {
3835
+ var _a4, _b3, _c3;
3836
+ if ("highlight" !== a3 && "underline" !== a3 && "squiggly" !== a3 && "strikeout" !== a3) {
3837
+ if ("note" === a3) {
3838
+ if (!o.value || !n.value || !i2.value) return;
3839
+ const e15 = o.value.getHighlightRectsForPage(l.item.localPageIndex, h$12);
3840
+ return void Ca(o.value.getSelectedText(h$12), (t3) => {
3841
+ var _a5;
3842
+ (_a5 = n.value) == null ? void 0 : _a5.requestCreateFromSelection({ chapterId: l.item.chapterId, localPageIndex: l.item.localPageIndex, globalPageIndex: l.item.globalPageIndex, globalPageNumber: l.item.globalPageNumber, rectsPdfCoord: e15, selectedText: t3.join("\n") });
3843
+ });
3844
+ }
3845
+ (_a4 = t2 == null ? void 0 : t2.onExtraAction) == null ? void 0 : _a4.call(t2, a3, l);
3846
+ } else {
3847
+ if (!o.value || !r.value || !s2.value) return;
3848
+ za(h$12, Fa[a3], r.value, o.value, (_c3 = (_b3 = e14()) == null ? void 0 : _b3.markup) == null ? void 0 : _c3.styles);
3849
+ }
3850
+ } }));
3851
+ };
3852
+ };
3853
+ });
3854
+ })(() => t.features, { onExtraAction: t.onExtraSelectionAction }), m = computed(() => {
3855
+ if (t.buildSelectionMenu || p.value) return (e14) => {
3856
+ const a2 = p.value ? p.value(e14) : e14.defaultMenu;
3857
+ return t.buildSelectionMenu ? t.buildSelectionMenu({ ...e14, defaultMenu: a2 }) : a2;
3858
+ };
3859
+ }), { provides: v } = useCapability(DocumentManagerPlugin.id);
3860
+ function w(e14) {
3861
+ var _a2;
3862
+ const a2 = [];
3863
+ if (c.value) {
3864
+ const s3 = (function(e15) {
3865
+ var _a3, _b, _c, _d;
3866
+ const a3 = Ia(e15), s4 = (_b = (_a3 = v.value) == null ? void 0 : _a3.getDocument(a3)) == null ? void 0 : _b.pages[e15.localPageIndex];
3867
+ return e15.isPlaceholder || !s4 ? null : h(Sa, { item: e15, pdfPageWidth: s4.size.width, pdfPageHeight: s4.size.height, cssPageWidth: e15.width, cssPageHeight: e15.height, hoverUi: (_d = (_c = t.features) == null ? void 0 : _c.bookmarks) == null ? void 0 : _d.hover });
3868
+ })(e14);
3869
+ s3 && a2.push(s3);
3870
+ }
3871
+ const s2 = (_a2 = t.renderPageOverlay) == null ? void 0 : _a2.call(t, e14);
3872
+ if (s2 && a2.push(s2), a2.length) return h("div", a2);
3873
+ }
3874
+ return (t2, s2) => (openBlock(), createElementBlock("div", { class: normalizeClass(e13.className), style: normalizeStyle(e13.className ? void 0 : unref(Ot)) }, [createVNode(unref(Ht), { class: normalizeClass(e13.className) }, { page: withCtx(({ item: t3 }) => {
3875
+ var _a2, _b, _c, _d;
3876
+ return [createVNode(Ma, { item: t3, features: e13.features, "show-note-markers": h$1.value, "show-bookmark-markers": d.value, "show-redaction-layer": e13.showRedactionLayer, "note-marker-ui": (_b = (_a2 = e13.features) == null ? void 0 : _a2.notes) == null ? void 0 : _b.marker, "bookmark-marker-ui": (_d = (_c = e13.features) == null ? void 0 : _c.bookmarks) == null ? void 0 : _d.marker, "build-selection-menu": m.value, "create-note": unref(a), "annotation-selection-menu": e13.annotationSelectionMenu, "redaction-selection-menu": e13.redactionSelectionMenu, "render-page-overlay": w }, null, 8, ["item", "features", "show-note-markers", "show-bookmark-markers", "show-redaction-layer", "note-marker-ui", "bookmark-marker-ui", "build-selection-menu", "create-note", "annotation-selection-menu", "redaction-selection-menu"])];
3877
+ }), _: 1 }, 8, ["class"]), renderSlot(t2.$slots, "default")], 6));
3878
+ } }), Wa = /* @__PURE__ */ defineComponent({ __name: "ChapterPdfViewer", props: { engine: {}, editorOptions: {}, features: {}, className: {}, viewportClassName: {}, onExtraSelectionAction: { type: Function } }, setup(e13) {
3879
+ var _a2;
3880
+ const h2 = e13, d = computed(() => ({ ...Tt, ...h2.features })), c = computed(() => Dt({ ...h2.editorOptions, features: d.value })), p = computed(() => {
3881
+ var _a3;
3882
+ return false !== ((_a3 = d.value.zoom) == null ? void 0 : _a3.enabled);
3883
+ }), m = ref(((_a2 = d.value.zoom) == null ? void 0 : _a2.initial) ?? 1), w = ref(null);
3884
+ let y = null;
3885
+ const I = () => {
3886
+ var _a3, _b;
3887
+ if (y == null ? void 0 : y(), y = null, !p.value || !w.value) return;
3888
+ const e14 = w.value.querySelector("[data-chapter-scroll-viewport]");
3889
+ e14 && (y = (function({ container: e15, getScale: t, setScale: a, minZoom: s = 0.5, maxZoom: i = 3 }) {
3890
+ let o = 0, r = 1, n = null, l = 1, h3 = 1;
3891
+ const d2 = (e16) => {
3892
+ (e16.ctrlKey || e16.metaKey) && (e16.preventDefault(), null === n ? (h3 = t(), l = 1) : clearTimeout(n), l *= 1 - 0.01 * e16.deltaY, l = Gt(l, 0.1, 10), a(Gt(h3 * l, s, i)), n = setTimeout(() => {
3893
+ n = null;
3894
+ }, 120));
3895
+ }, c2 = /* @__PURE__ */ new Map(), u = (e16) => {
3896
+ if (c2.set(e16.pointerId, { x: e16.clientX, y: e16.clientY }), 2 === c2.size) {
3897
+ const [e17, a2] = [...c2.values()];
3898
+ o = Math.hypot(a2.x - e17.x, a2.y - e17.y), r = t();
3899
+ }
3900
+ }, p2 = (e16) => {
3901
+ if (c2.has(e16.pointerId) && (c2.set(e16.pointerId, { x: e16.clientX, y: e16.clientY }), 2 === c2.size && o > 0)) {
3902
+ e16.preventDefault();
3903
+ const [t2, n2] = [...c2.values()], l2 = Math.hypot(n2.x - t2.x, n2.y - t2.y);
3904
+ a(Gt(r * (l2 / o), s, i));
3905
+ }
3906
+ }, g = (e16) => {
3907
+ c2.delete(e16.pointerId), c2.size < 2 && (o = 0);
3908
+ };
3909
+ return e15.addEventListener("wheel", d2, { passive: false }), e15.addEventListener("pointerdown", u), e15.addEventListener("pointermove", p2, { passive: false }), e15.addEventListener("pointerup", g), e15.addEventListener("pointercancel", g), () => {
3910
+ e15.removeEventListener("wheel", d2), e15.removeEventListener("pointerdown", u), e15.removeEventListener("pointermove", p2), e15.removeEventListener("pointerup", g), e15.removeEventListener("pointercancel", g), n && clearTimeout(n);
3911
+ };
3912
+ })({ container: e14, getScale: () => m.value, setScale: (e15) => {
3913
+ m.value = e15;
3914
+ }, minZoom: ((_a3 = d.value.zoom) == null ? void 0 : _a3.min) ?? 0.5, maxZoom: ((_b = d.value.zoom) == null ? void 0 : _b.max) ?? 3 }));
3915
+ };
3916
+ return onMounted(I), onBeforeUnmount(() => y == null ? void 0 : y()), watch([p, m, d], I), (t, a) => (openBlock(), createElementBlock("div", { ref_key: "rootRef", ref: w, class: normalizeClass(e13.className), style: normalizeStyle(e13.className ? void 0 : unref(Ot)) }, [createVNode(unref(EmbedPDF), { engine: e13.engine, plugins: c.value.plugins }, { default: withCtx(({ pluginsReady: a2 }) => [a2 ? (openBlock(), createElementBlock("div", { key: 0, style: normalizeStyle(p.value ? { ...unref(At), transform: `scale(${m.value})`, transformOrigin: "top center" } : unref(At)) }, [createVNode(qa, { class: normalizeClass(e13.viewportClassName), features: d.value, "on-extra-selection-action": e13.onExtraSelectionAction }, null, 8, ["class", "features", "on-extra-selection-action"]), renderSlot(t.$slots, "default")], 4)) : createCommentVNode("", true)]), _: 3 }, 8, ["engine", "plugins"])], 6));
3917
+ } }), Ha = { class: "chapter-tree-row" }, Ba = ["aria-expanded"], ja = { key: 1, class: "chapter-tree-toggle-spacer", "aria-hidden": "" }, Ya = { class: "chapter-tree-label" }, Ka = { class: "chapter-tree-meta" }, Xa = { key: 0 }, Za = (e13, t) => {
3918
+ const a = e13.__vccOpts || e13;
3919
+ for (const [s, i] of t) a[s] = i;
3920
+ return a;
3921
+ }, Qa = /* @__PURE__ */ Za(/* @__PURE__ */ defineComponent({ __name: "ChapterTreeItem", props: { node: {}, depth: {}, activeChapterId: {}, chapterStatus: {} }, emits: ["select"], setup(e13) {
3922
+ const a = { idle: "未加载", loading: "加载中", loaded: "已加载", closed: "已卸载", error: "失败", "password-required": "需密码" }, s = e13, i = computed(() => s.node.children ?? []), n = computed(() => i.value.length > 0), d = ref(s.depth < 1), c = computed(() => s.activeChapterId === s.node.id), u = computed(() => s.chapterStatus[s.node.id] ?? "idle"), g = computed(() => !n.value);
3923
+ return (t, s2) => (openBlock(), createElementBlock("li", null, [createElementVNode("div", Ha, [n.value ? (openBlock(), createElementBlock("button", { key: 0, type: "button", class: "chapter-tree-toggle", "aria-expanded": d.value, onClick: s2[0] || (s2[0] = (e14) => d.value = !d.value) }, toDisplayString(d.value ? "▼" : "▶"), 9, Ba)) : (openBlock(), createElementBlock("span", ja)), createElementVNode("button", { type: "button", class: normalizeClass(["chapter-tree-btn", { "chapter-tree-btn-active": c.value }]), onClick: s2[1] || (s2[1] = (a2) => t.$emit("select", e13.node.id)) }, [createElementVNode("div", Ya, toDisplayString(e13.node.title), 1), createElementVNode("div", Ka, [createElementVNode("span", null, " 第 " + toDisplayString(e13.node.startPage) + toDisplayString(e13.node.endPage !== e13.node.startPage ? `–${e13.node.endPage}` : "") + " 页 ", 1), g.value ? (openBlock(), createElementBlock("span", Xa, toDisplayString(a[u.value]), 1)) : createCommentVNode("", true)])], 2)]), n.value && d.value ? (openBlock(), createBlock(Ja, { key: 0, nodes: i.value, depth: e13.depth + 1, "active-chapter-id": e13.activeChapterId, "chapter-status": e13.chapterStatus, onSelect: s2[2] || (s2[2] = (e14) => t.$emit("select", e14)) }, null, 8, ["nodes", "depth", "active-chapter-id", "chapter-status"])) : createCommentVNode("", true)]));
3924
+ } }), [["__scopeId", "data-v-315bbf7a"]]), Ja = /* @__PURE__ */ Za(/* @__PURE__ */ defineComponent({ __name: "ChapterTreeList", props: { nodes: {}, depth: {}, activeChapterId: {}, chapterStatus: {} }, emits: ["select"], setup: (e13) => (t, a) => (openBlock(), createElementBlock("ul", { class: "chapter-tree-list", style: normalizeStyle({ marginLeft: e13.depth > 0 ? "12px" : "0" }) }, [(openBlock(true), createElementBlock(Fragment, null, renderList(e13.nodes, (s) => (openBlock(), createBlock(Qa, { key: s.id, node: s, depth: e13.depth, "active-chapter-id": e13.activeChapterId, "chapter-status": e13.chapterStatus, onSelect: a[0] || (a[0] = (e14) => t.$emit("select", e14)) }, null, 8, ["node", "depth", "active-chapter-id", "chapter-status"]))), 128))], 4)) }), [["__scopeId", "data-v-eb742e4f"]]), es = { class: "chapter-tree" }, ts = { class: "chapter-tree-nav", "aria-label": "章节目录" }, as = /* @__PURE__ */ Za(/* @__PURE__ */ defineComponent({ __name: "ChapterTreePanel", props: { tree: {}, activeChapterId: {} }, emits: ["active-chapter-change"], setup(e13, { emit: a }) {
3925
+ const n = e13, l = a, { provides: d } = useCapability(Te.id), { provides: c } = useCapability(we.id), u = ref({});
3926
+ function p() {
3927
+ if (!c.value) return;
3928
+ const e14 = {}, t = (a2) => {
3929
+ var _a2;
3930
+ for (const s of a2) e14[s.id] = c.value.getChapterStatus(s.id), ((_a2 = s.children) == null ? void 0 : _a2.length) && t(s.children);
3931
+ };
3932
+ t(n.tree), u.value = e14;
3933
+ }
3934
+ watch([c, () => n.tree], p, { immediate: true });
3935
+ let g = null;
3936
+ function f(e14) {
3937
+ var _a2;
3938
+ l("active-chapter-change", e14), (_a2 = d.value) == null ? void 0 : _a2.scrollToChapter(e14);
3939
+ }
3940
+ return watch(c, (e14) => {
3941
+ g == null ? void 0 : g(), g = e14 ? e14.onChapterStatusChange(p) : null;
3942
+ }, { immediate: true }), onBeforeUnmount(() => g == null ? void 0 : g()), (t, a2) => (openBlock(), createElementBlock("aside", es, [a2[0] || (a2[0] = createElementVNode("h2", { class: "chapter-tree-title" }, "章节目录", -1)), createElementVNode("nav", ts, [createVNode(Ja, { nodes: e13.tree, depth: 0, "active-chapter-id": e13.activeChapterId, "chapter-status": u.value, onSelect: f }, null, 8, ["nodes", "active-chapter-id", "chapter-status"])])]));
3943
+ } }), [["__scopeId", "data-v-d7a0838d"]]);
3944
+ class ss {
3945
+ constructor(e13) {
3946
+ this.cb = e13;
3947
+ }
3948
+ resolvePassword(e13, t) {
3949
+ return this.cb(e13, t);
3950
+ }
3951
+ }
3952
+ function is(e13) {
3953
+ return { manifest: e13.manifest, chapterPdfLoader: e13.chapterPdfLoader, overlapStrategy: { kind: "first-wins" }, passwordProvider: new ss(async () => null), prefetchChapters: 1, loadDefaultStampLibrary: false, unloadTimeoutMs: 12e4, toolbar: { enabledModes: [] }, bookmarks: e13.bookmarks, notes: e13.notes };
3954
+ }
3955
+ const _sfc_main = /* @__PURE__ */ defineComponent({
3956
+ __name: "ChapterPdfViewer",
3957
+ props: {
3958
+ viewerProps: {}
3959
+ },
3960
+ setup(__props) {
3961
+ return (_ctx, _cache) => {
3962
+ return openBlock(), createBlock(unref(Wa), normalizeProps(guardReactiveProps(__props.viewerProps)), null, 16);
3963
+ };
3964
+ }
3965
+ });
3966
+ export {
3967
+ ss as CallbackPasswordProvider,
3968
+ _sfc_main as ChapterPdfViewer,
3969
+ as as ChapterTreePanel,
3970
+ Tt as DEFAULT_CHAPTER_VIEWER_FEATURES,
3971
+ EmbedPDF2 as EmbedPDF,
3972
+ qa as PdfChapterViewport,
3973
+ za as applySelectionMarkup,
3974
+ Pt as buildParagraphBookmarkAnchor,
3975
+ Dt as createChapterViewerEditor,
3976
+ is as createChapterViewerEditorOptions,
3977
+ Lt as createPdfChapterEditor,
3978
+ useCapability2 as useCapability,
3979
+ usePdfiumEngine
3980
+ };
3981
+ //# sourceMappingURL=index.js.map