react-book-reader 1.0.0 → 1.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.
@@ -0,0 +1,748 @@
1
+ const I = (o) => new Promise((t) => setTimeout(t, o)), C = (o, t, e) => {
2
+ let i;
3
+ return (...s) => {
4
+ const n = () => {
5
+ i = null, o(...s);
6
+ };
7
+ i && clearTimeout(i), i = setTimeout(n, t);
8
+ };
9
+ }, S = (o, t, e) => e * (t - o) + o, B = (o) => 1 - (1 - o) * (1 - o), V = (o, t, e, i, s) => new Promise((n) => {
10
+ let r;
11
+ const a = (h) => {
12
+ if (document.hidden)
13
+ return s(S(o, t, 1)), n();
14
+ r ??= h;
15
+ const c = Math.min(1, (h - r) / e);
16
+ s(S(o, t, i(c))), c < 1 ? requestAnimationFrame(a) : n();
17
+ };
18
+ if (document.hidden)
19
+ return s(S(o, t, 1)), n();
20
+ requestAnimationFrame(a);
21
+ }), N = (o) => {
22
+ if (!o?.collapsed) return o;
23
+ const { endOffset: t, endContainer: e } = o;
24
+ if (e.nodeType === 1) {
25
+ const i = e.childNodes[t];
26
+ return i?.nodeType === 1 ? i : e;
27
+ }
28
+ if (t + 1 < e.length) o.setEnd(e, t + 1);
29
+ else if (t > 1) o.setStart(e, t - 1);
30
+ else return e.parentNode;
31
+ return o;
32
+ }, v = (o, t, e, i = e) => {
33
+ const s = o.createRange();
34
+ return s.setStart(t, e), s.setEnd(t, i), s;
35
+ }, E = (o, t, e, i = 0, s = t.nodeValue.length) => {
36
+ if (s - i === 1)
37
+ return e(v(o, t, i), v(o, t, s)) < 0 ? i : s;
38
+ const n = Math.floor(i + (s - i) / 2), r = e(v(o, t, i, n), v(o, t, n, s));
39
+ return r < 0 ? E(o, t, e, i, n) : r > 0 ? E(o, t, e, n, s) : n;
40
+ }, {
41
+ SHOW_ELEMENT: O,
42
+ SHOW_TEXT: F,
43
+ SHOW_CDATA_SECTION: D,
44
+ FILTER_ACCEPT: R,
45
+ FILTER_REJECT: M,
46
+ FILTER_SKIP: L
47
+ } = NodeFilter, j = O | F | D, b = (o) => {
48
+ let t = 1 / 0, e = -1 / 0, i = 1 / 0, s = -1 / 0;
49
+ for (const n of o.getClientRects())
50
+ i = Math.min(i, n.left), t = Math.min(t, n.top), e = Math.max(e, n.right), s = Math.max(s, n.bottom);
51
+ return new DOMRect(i, t, e - i, s - t);
52
+ }, $ = (o, t, e, i) => {
53
+ const s = (l) => {
54
+ const m = l.localName?.toLowerCase();
55
+ if (m === "script" || m === "style") return M;
56
+ if (l.nodeType === 1) {
57
+ const { left: u, right: g } = i(l.getBoundingClientRect());
58
+ if (g < t || u > e) return M;
59
+ if (u >= t && g <= e) return R;
60
+ } else {
61
+ if (!l.nodeValue?.trim()) return L;
62
+ const u = o.createRange();
63
+ u.selectNodeContents(l);
64
+ const { left: g, right: p } = i(u.getBoundingClientRect());
65
+ if (p >= t && g <= e) return R;
66
+ }
67
+ return L;
68
+ }, n = o.createTreeWalker(o.body, j, { acceptNode: s }), r = [];
69
+ for (let l = n.nextNode(); l; l = n.nextNode())
70
+ r.push(l);
71
+ const a = r[0] ?? o.body, h = r[r.length - 1] ?? a, c = a.nodeType === 1 ? 0 : E(o, a, (l, m) => {
72
+ const u = i(b(l)), g = i(b(m));
73
+ return u.right < t && g.left > t ? 0 : g.left > t ? -1 : 1;
74
+ }), f = h.nodeType === 1 ? 0 : E(o, h, (l, m) => {
75
+ const u = i(b(l)), g = i(b(m));
76
+ return u.right < e && g.left > e ? 0 : g.left > e ? -1 : 1;
77
+ }), d = o.createRange();
78
+ return d.setStart(a, c), d.setEnd(h, f), d;
79
+ }, A = (o) => {
80
+ const t = document.createRange();
81
+ return t.setStart(o.anchorNode, o.anchorOffset), t.setEnd(o.focusNode, o.focusOffset), t.collapsed;
82
+ }, w = (o, t) => {
83
+ let e;
84
+ if (o.startContainer ? e = o.cloneRange() : o.nodeType && (e = document.createRange(), e.selectNode(o)), e) {
85
+ const i = e.startContainer.ownerDocument.defaultView.getSelection();
86
+ i && (i.removeAllRanges(), t === -1 ? e.collapse(!0) : t === 1 && e.collapse(), i.addRange(e));
87
+ }
88
+ }, W = (o) => {
89
+ const { defaultView: t } = o, { writingMode: e, direction: i } = t.getComputedStyle(o.body), s = e === "vertical-rl" || e === "vertical-lr", n = o.body.dir === "rtl" || i === "rtl" || o.documentElement.dir === "rtl";
90
+ return { vertical: s, rtl: n };
91
+ }, _ = (o) => {
92
+ const t = o.defaultView.getComputedStyle(o.body);
93
+ return t.backgroundColor === "rgba(0, 0, 0, 0)" && t.backgroundImage === "none" ? o.defaultView.getComputedStyle(o.documentElement).background : t.background;
94
+ }, P = (o, t) => Array.from({ length: o }, () => {
95
+ const e = document.createElement("div"), i = document.createElement("div");
96
+ return e.append(i), i.setAttribute("part", t), e;
97
+ }), x = (o, t) => {
98
+ const { style: e } = o;
99
+ for (const [i, s] of Object.entries(t)) e.setProperty(i, s, "important");
100
+ };
101
+ class q {
102
+ #a = new ResizeObserver(() => this.expand());
103
+ #r = document.createElement("div");
104
+ #i = document.createElement("iframe");
105
+ #l = document.createRange();
106
+ #e;
107
+ #s = !1;
108
+ #c = !1;
109
+ #t = !0;
110
+ #n;
111
+ #o = {};
112
+ constructor({ container: t, onExpand: e }) {
113
+ this.container = t, this.onExpand = e, this.#i.setAttribute("part", "filter"), this.#r.append(this.#i), Object.assign(this.#r.style, {
114
+ boxSizing: "content-box",
115
+ position: "relative",
116
+ overflow: "hidden",
117
+ flex: "0 0 auto",
118
+ width: "100%",
119
+ height: "100%",
120
+ display: "flex",
121
+ justifyContent: "center",
122
+ alignItems: "center"
123
+ }), Object.assign(this.#i.style, {
124
+ overflow: "hidden",
125
+ border: "0",
126
+ display: "none",
127
+ width: "100%",
128
+ height: "100%"
129
+ }), this.#i.setAttribute("sandbox", "allow-same-origin allow-scripts"), this.#i.setAttribute("scrolling", "no");
130
+ }
131
+ get element() {
132
+ return this.#r;
133
+ }
134
+ get document() {
135
+ return this.#i.contentDocument;
136
+ }
137
+ async load(t, e, i) {
138
+ if (typeof t != "string") throw new Error(`${t} is not string`);
139
+ return new Promise((s) => {
140
+ this.#i.addEventListener("load", () => {
141
+ const n = this.document;
142
+ e?.(n), this.#i.style.display = "block";
143
+ const { vertical: r, rtl: a } = W(n), h = _(n);
144
+ this.#i.style.display = "none", this.#s = r, this.#c = a, this.#l.selectNodeContents(n.body);
145
+ const c = i?.({ vertical: r, rtl: a, background: h });
146
+ this.#i.style.display = "block", this.render(c), this.#a.observe(n.body), n.fonts.ready.then(() => this.expand()), s();
147
+ }, { once: !0 }), this.#i.src = t;
148
+ });
149
+ }
150
+ render(t) {
151
+ t && (this.#t = t.flow !== "scrolled", this.#o = t, this.#t ? this.columnize(t) : this.scrolled(t));
152
+ }
153
+ scrolled({ gap: t, columnWidth: e }) {
154
+ const i = this.#s, s = this.document;
155
+ x(s.documentElement, {
156
+ "box-sizing": "border-box",
157
+ padding: i ? `${t}px 0` : `0 ${t}px`,
158
+ "column-width": "auto",
159
+ height: "auto",
160
+ width: "auto"
161
+ }), x(s.body, {
162
+ [i ? "max-height" : "max-width"]: `${e}px`,
163
+ margin: "auto"
164
+ }), this.setImageSize(), this.expand();
165
+ }
166
+ columnize({ width: t, height: e, gap: i, columnWidth: s }) {
167
+ const n = this.#s;
168
+ this.#n = n ? e : t;
169
+ const r = this.document;
170
+ x(r.documentElement, {
171
+ "box-sizing": "border-box",
172
+ "column-width": `${Math.trunc(s)}px`,
173
+ "column-gap": `${i}px`,
174
+ "column-fill": "auto",
175
+ ...n ? { width: `${t}px` } : { height: `${e}px` },
176
+ padding: n ? `${i / 2}px 0` : `0 ${i / 2}px`,
177
+ overflow: "hidden",
178
+ // force wrap long words
179
+ "overflow-wrap": "break-word",
180
+ // reset some potentially problematic props
181
+ position: "static",
182
+ border: "0",
183
+ margin: "0",
184
+ "max-height": "none",
185
+ "max-width": "none",
186
+ "min-height": "none",
187
+ "min-width": "none",
188
+ // fix glyph clipping in WebKit
189
+ "-webkit-line-box-contain": "block glyphs replaced"
190
+ }), x(r.body, {
191
+ "max-height": "none",
192
+ "max-width": "none",
193
+ margin: "0"
194
+ }), this.setImageSize(), this.expand();
195
+ }
196
+ setImageSize() {
197
+ const { width: t, height: e, margin: i } = this.#o, s = this.#s, n = this.document;
198
+ for (const r of n.body.querySelectorAll("img, svg, video")) {
199
+ const { maxHeight: a, maxWidth: h } = n.defaultView.getComputedStyle(r);
200
+ x(r, {
201
+ "max-height": s ? a !== "none" && a !== "0px" ? a : "100%" : `${e - i * 2}px`,
202
+ "max-width": s ? `${t - i * 2}px` : h !== "none" && h !== "0px" ? h : "100%",
203
+ "object-fit": "contain",
204
+ "page-break-inside": "avoid",
205
+ "break-inside": "avoid",
206
+ "box-sizing": "border-box"
207
+ });
208
+ }
209
+ }
210
+ expand() {
211
+ const { documentElement: t } = this.document;
212
+ if (this.#t) {
213
+ const e = this.#s ? "height" : "width", i = this.#s ? "width" : "height", s = this.#l.getBoundingClientRect(), n = t.getBoundingClientRect(), a = (this.#s ? 0 : this.#c ? n.right - s.right : s.left - n.left) + s[e], c = Math.ceil(a / this.#n) * this.#n;
214
+ this.#r.style.padding = "0", this.#i.style[e] = `${c}px`, this.#r.style[e] = `${c + this.#n * 2}px`, this.#i.style[i] = "100%", this.#r.style[i] = "100%", t.style[e] = `${this.#n}px`, this.#e && (this.#e.element.style.margin = "0", this.#e.element.style.left = this.#s ? "0" : `${this.#n}px`, this.#e.element.style.top = this.#s ? `${this.#n}px` : "0", this.#e.element.style[e] = `${c}px`, this.#e.redraw());
215
+ } else {
216
+ const e = this.#s ? "width" : "height", i = this.#s ? "height" : "width", n = t.getBoundingClientRect()[e], { margin: r } = this.#o, a = this.#s ? `0 ${r}px` : `${r}px 0`;
217
+ this.#r.style.padding = a, this.#i.style[e] = `${n}px`, this.#r.style[e] = `${n}px`, this.#i.style[i] = "100%", this.#r.style[i] = "100%", this.#e && (this.#e.element.style.margin = a, this.#e.element.style.left = "0", this.#e.element.style.top = "0", this.#e.element.style[e] = `${n}px`, this.#e.redraw());
218
+ }
219
+ this.onExpand();
220
+ }
221
+ set overlayer(t) {
222
+ this.#e = t, this.#r.append(t.element);
223
+ }
224
+ get overlayer() {
225
+ return this.#e;
226
+ }
227
+ destroy() {
228
+ this.document && this.#a.unobserve(this.document.body);
229
+ }
230
+ }
231
+ class H extends HTMLElement {
232
+ static observedAttributes = [
233
+ "flow",
234
+ "gap",
235
+ "margin",
236
+ "max-inline-size",
237
+ "max-block-size",
238
+ "max-column-count"
239
+ ];
240
+ #a = this.attachShadow({ mode: "closed" });
241
+ #r = new ResizeObserver(() => this.render());
242
+ #i;
243
+ #l;
244
+ #e;
245
+ #s;
246
+ #c;
247
+ #t;
248
+ #n = !1;
249
+ #o = !1;
250
+ #g = 0;
251
+ #d = -1;
252
+ #h = 0;
253
+ // anchor view to a fraction (0-1), Range, or Element
254
+ #E = !1;
255
+ #x = !1;
256
+ // while true, prevent any further navigation
257
+ #T;
258
+ #k = /* @__PURE__ */ new WeakMap();
259
+ #C = matchMedia("(prefers-color-scheme: dark)");
260
+ #S;
261
+ #m;
262
+ #v;
263
+ #_;
264
+ #R;
265
+ constructor() {
266
+ super(), this.#a.innerHTML = `<style>
267
+ :host {
268
+ display: block;
269
+ container-type: size;
270
+ }
271
+ :host, #top {
272
+ box-sizing: border-box;
273
+ position: relative;
274
+ overflow: hidden;
275
+ width: 100%;
276
+ height: 100%;
277
+ }
278
+ #top {
279
+ --_gap: 7%;
280
+ --_margin: 48px;
281
+ --_max-inline-size: 720px;
282
+ --_max-block-size: 1440px;
283
+ --_max-column-count: 2;
284
+ --_max-column-count-portrait: 1;
285
+ --_max-column-count-spread: var(--_max-column-count);
286
+ --_half-gap: calc(var(--_gap) / 2);
287
+ --_max-width: calc(var(--_max-inline-size) * var(--_max-column-count-spread));
288
+ --_max-height: var(--_max-block-size);
289
+ display: grid;
290
+ grid-template-columns:
291
+ minmax(var(--_half-gap), 1fr)
292
+ var(--_half-gap)
293
+ minmax(0, calc(var(--_max-width) - var(--_gap)))
294
+ var(--_half-gap)
295
+ minmax(var(--_half-gap), 1fr);
296
+ grid-template-rows:
297
+ minmax(var(--_margin), 1fr)
298
+ minmax(0, var(--_max-height))
299
+ minmax(var(--_margin), 1fr);
300
+ &.vertical {
301
+ --_max-column-count-spread: var(--_max-column-count-portrait);
302
+ --_max-width: var(--_max-block-size);
303
+ --_max-height: calc(var(--_max-inline-size) * var(--_max-column-count-spread));
304
+ }
305
+ @container (orientation: portrait) {
306
+ & {
307
+ --_max-column-count-spread: var(--_max-column-count-portrait);
308
+ }
309
+ &.vertical {
310
+ --_max-column-count-spread: var(--_max-column-count);
311
+ }
312
+ }
313
+ }
314
+ #background {
315
+ grid-column: 1 / -1;
316
+ grid-row: 1 / -1;
317
+ }
318
+ #container {
319
+ grid-column: 2 / 5;
320
+ grid-row: 2;
321
+ overflow: hidden;
322
+ }
323
+ :host([flow="scrolled"]) #container {
324
+ grid-column: 1 / -1;
325
+ grid-row: 1 / -1;
326
+ overflow: auto;
327
+ }
328
+ #header {
329
+ grid-column: 3 / 4;
330
+ grid-row: 1;
331
+ }
332
+ #footer {
333
+ grid-column: 3 / 4;
334
+ grid-row: 3;
335
+ align-self: end;
336
+ }
337
+ #header, #footer {
338
+ display: grid;
339
+ height: var(--_margin);
340
+ }
341
+ :is(#header, #footer) > * {
342
+ display: flex;
343
+ align-items: center;
344
+ min-width: 0;
345
+ }
346
+ :is(#header, #footer) > * > * {
347
+ width: 100%;
348
+ overflow: hidden;
349
+ white-space: nowrap;
350
+ text-overflow: ellipsis;
351
+ text-align: center;
352
+ font-size: .75em;
353
+ opacity: .6;
354
+ }
355
+ </style>
356
+ <div id="top">
357
+ <div id="background" part="filter"></div>
358
+ <div id="header"></div>
359
+ <div id="container"></div>
360
+ <div id="footer"></div>
361
+ </div>
362
+ `, this.#i = this.#a.getElementById("top"), this.#l = this.#a.getElementById("background"), this.#e = this.#a.getElementById("container"), this.#s = this.#a.getElementById("header"), this.#c = this.#a.getElementById("footer"), this.#r.observe(this.#e), this.#e.addEventListener("scroll", () => this.dispatchEvent(new Event("scroll"))), this.#e.addEventListener("scroll", C(() => {
363
+ this.scrolled && (this.#E ? this.#E = !1 : this.#w("scroll"));
364
+ }, 250));
365
+ const t = { passive: !1 };
366
+ this.addEventListener("touchstart", this.#L.bind(this), t), this.addEventListener("touchmove", this.#$.bind(this), t), this.addEventListener("touchend", this.#A.bind(this)), this.addEventListener("load", ({ detail: { doc: i } }) => {
367
+ i.addEventListener("touchstart", this.#L.bind(this), t), i.addEventListener("touchmove", this.#$.bind(this), t), i.addEventListener("touchend", this.#A.bind(this));
368
+ }), this.addEventListener("relocate", ({ detail: i }) => {
369
+ i.reason === "selection" ? w(this.#h, 0) : i.reason === "navigation" && (this.#h === 1 ? w(i.range, 1) : typeof this.#h == "number" ? w(i.range, -1) : w(this.#h, -1));
370
+ });
371
+ const e = C((i, s) => {
372
+ if (!s.rangeCount) return;
373
+ const n = s.getRangeAt(0), r = A(s);
374
+ r && n.compareBoundaryPoints(Range.START_TO_START, i) < 0 ? this.prev() : !r && n.compareBoundaryPoints(Range.END_TO_END, i) > 0 && this.next();
375
+ }, 700);
376
+ this.addEventListener("load", ({ detail: { doc: i } }) => {
377
+ let s = !1;
378
+ i.addEventListener("pointerdown", () => s = !0), i.addEventListener("pointerup", () => s = !1);
379
+ let n = !1;
380
+ i.addEventListener("keydown", () => n = !0), i.addEventListener("keyup", () => n = !1), i.addEventListener("selectionchange", () => {
381
+ if (this.scrolled) return;
382
+ const r = this.#R;
383
+ if (!r) return;
384
+ const a = i.getSelection();
385
+ if (a.rangeCount) {
386
+ if (s && a.type === "Range")
387
+ e(r, a);
388
+ else if (n) {
389
+ const h = a.getRangeAt(0).cloneRange();
390
+ A(a) || h.collapse(), this.#y(h);
391
+ }
392
+ }
393
+ }), i.addEventListener("focusin", (r) => this.scrolled ? null : (
394
+ // NOTE: `requestAnimationFrame` is needed in WebKit
395
+ requestAnimationFrame(() => this.#y(r.target))
396
+ ));
397
+ }), this.#S = () => {
398
+ this.#t && (this.#l.style.background = _(this.#t.document));
399
+ }, this.#C.addEventListener("change", this.#S);
400
+ }
401
+ attributeChangedCallback(t, e, i) {
402
+ switch (t) {
403
+ case "flow":
404
+ this.render();
405
+ break;
406
+ case "gap":
407
+ case "margin":
408
+ case "max-block-size":
409
+ case "max-column-count":
410
+ this.#i.style.setProperty("--_" + t, i);
411
+ break;
412
+ case "max-inline-size":
413
+ this.#i.style.setProperty("--_" + t, i), this.render();
414
+ break;
415
+ }
416
+ }
417
+ open(t) {
418
+ this.bookDir = t.dir, this.sections = t.sections, t.transformTarget?.addEventListener("data", ({ detail: e }) => {
419
+ if (e.type !== "text/css") return;
420
+ const i = innerWidth, s = innerHeight;
421
+ e.data = Promise.resolve(e.data).then((n) => n.replace(new RegExp("(?<=[{\\s;])-epub-", "gi"), "").replace(/(\d*\.?\d+)vw/gi, (r, a) => parseFloat(a) * i / 100 + "px").replace(/(\d*\.?\d+)vh/gi, (r, a) => parseFloat(a) * s / 100 + "px").replace(/page-break-(after|before|inside)\s*:/gi, (r, a) => `-webkit-column-break-${a}:`).replace(/break-(after|before|inside)\s*:\s*(avoid-)?page/gi, (r, a, h) => `break-${a}: ${h ?? ""}column`));
422
+ });
423
+ }
424
+ #V() {
425
+ return this.#t && (this.#t.destroy(), this.#e.removeChild(this.#t.element)), this.#t = new q({
426
+ container: this,
427
+ onExpand: () => this.#y(this.#h)
428
+ }), this.#e.append(this.#t.element), this.#t;
429
+ }
430
+ #M({ vertical: t, rtl: e, background: i }) {
431
+ this.#n = t, this.#o = e, this.#i.classList.toggle("vertical", t), this.#l.style.background = i;
432
+ const { width: s, height: n } = this.#e.getBoundingClientRect(), r = t ? n : s, a = getComputedStyle(this.#i), h = parseFloat(a.getPropertyValue("--_max-inline-size")), c = parseInt(a.getPropertyValue("--_max-column-count-spread")), f = parseFloat(a.getPropertyValue("--_margin"));
433
+ this.#g = f;
434
+ const d = parseFloat(a.getPropertyValue("--_gap")) / 100, l = -d / (d - 1) * r, m = this.getAttribute("flow");
435
+ if (m === "scrolled") {
436
+ this.setAttribute("dir", t ? "rtl" : "ltr"), this.#i.style.padding = "0";
437
+ const y = h;
438
+ return this.heads = null, this.feet = null, this.#s.replaceChildren(), this.#c.replaceChildren(), { flow: m, margin: f, gap: l, columnWidth: y };
439
+ }
440
+ const u = Math.min(c, Math.ceil(r / h)), g = r / u - l;
441
+ this.setAttribute("dir", e ? "rtl" : "ltr");
442
+ const p = t ? Math.min(2, Math.ceil(s / h)) : u, z = {
443
+ gridTemplateColumns: `repeat(${p}, 1fr)`,
444
+ gap: `${l}px`,
445
+ direction: this.bookDir === "rtl" ? "rtl" : "ltr"
446
+ };
447
+ Object.assign(this.#s.style, z), Object.assign(this.#c.style, z);
448
+ const T = P(p, "head"), k = P(p, "foot");
449
+ return this.heads = T.map((y) => y.children[0]), this.feet = k.map((y) => y.children[0]), this.#s.replaceChildren(...T), this.#c.replaceChildren(...k), { height: n, width: s, margin: f, gap: l, columnWidth: g };
450
+ }
451
+ render() {
452
+ this.#t && (this.#t.render(this.#M({
453
+ vertical: this.#n,
454
+ rtl: this.#o
455
+ })), this.#y(this.#h));
456
+ }
457
+ get scrolled() {
458
+ return this.getAttribute("flow") === "scrolled";
459
+ }
460
+ get scrollProp() {
461
+ const { scrolled: t } = this;
462
+ return this.#n ? t ? "scrollLeft" : "scrollTop" : t ? "scrollTop" : "scrollLeft";
463
+ }
464
+ get sideProp() {
465
+ const { scrolled: t } = this;
466
+ return this.#n ? t ? "width" : "height" : t ? "height" : "width";
467
+ }
468
+ get size() {
469
+ return this.#e.getBoundingClientRect()[this.sideProp];
470
+ }
471
+ get viewSize() {
472
+ return this.#t.element.getBoundingClientRect()[this.sideProp];
473
+ }
474
+ get start() {
475
+ return Math.abs(this.#e[this.scrollProp]);
476
+ }
477
+ get end() {
478
+ return this.start + this.size;
479
+ }
480
+ get page() {
481
+ return Math.floor((this.start + this.end) / 2 / this.size);
482
+ }
483
+ get pages() {
484
+ return Math.round(this.viewSize / this.size);
485
+ }
486
+ scrollBy(t, e) {
487
+ const i = this.#n ? e : t, s = this.#e, { scrollProp: n } = this, [r, a, h] = this.#m, c = this.#o, f = c ? r - h : r - a, d = c ? r + a : r + h;
488
+ s[n] = Math.max(f, Math.min(
489
+ d,
490
+ s[n] + i
491
+ ));
492
+ }
493
+ snap(t, e) {
494
+ const i = this.#n ? e : t, [s, n, r] = this.#m, { start: a, end: h, pages: c, size: f } = this, d = Math.abs(s) - n, l = Math.abs(s) + r, m = i * (this.#o ? -f : f), u = Math.floor(
495
+ Math.max(d, Math.min(l, (a + h) / 2 + (isNaN(m) ? 0 : m))) / f
496
+ );
497
+ this.#p(u, "snap").then(() => {
498
+ const g = u <= 0 ? -1 : u >= c - 1 ? 1 : null;
499
+ if (g) return this.#z({
500
+ index: this.#u(g),
501
+ anchor: g < 0 ? () => 1 : () => 0
502
+ });
503
+ });
504
+ }
505
+ #L(t) {
506
+ const e = t.changedTouches[0];
507
+ this.#v = {
508
+ x: e?.screenX,
509
+ y: e?.screenY,
510
+ t: t.timeStamp,
511
+ vx: 0,
512
+ xy: 0
513
+ };
514
+ }
515
+ #$(t) {
516
+ const e = this.#v;
517
+ if (e.pinched || (e.pinched = globalThis.visualViewport.scale > 1, this.scrolled || e.pinched)) return;
518
+ if (t.touches.length > 1) {
519
+ this.#_ && t.preventDefault();
520
+ return;
521
+ }
522
+ t.preventDefault();
523
+ const i = t.changedTouches[0], s = i.screenX, n = i.screenY, r = e.x - s, a = e.y - n, h = t.timeStamp - e.t;
524
+ e.x = s, e.y = n, e.t = t.timeStamp, e.vx = r / h, e.vy = a / h, this.#_ = !0, this.scrollBy(r, a);
525
+ }
526
+ #A() {
527
+ this.#_ = !1, !this.scrolled && requestAnimationFrame(() => {
528
+ globalThis.visualViewport.scale === 1 && this.snap(this.#v.vx, this.#v.vy);
529
+ });
530
+ }
531
+ // allows one to process rects as if they were LTR and horizontal
532
+ #b() {
533
+ if (this.scrolled) {
534
+ const e = this.viewSize, i = this.#g;
535
+ return this.#n ? ({ left: s, right: n }) => ({ left: e - n - i, right: e - s - i }) : ({ top: s, bottom: n }) => ({ left: s + i, right: n + i });
536
+ }
537
+ const t = this.pages * this.size;
538
+ return this.#o ? ({ left: e, right: i }) => ({ left: t - i, right: t - e }) : this.#n ? ({ top: e, bottom: i }) => ({ left: e, right: i }) : (e) => e;
539
+ }
540
+ async #N(t, e) {
541
+ if (this.scrolled) {
542
+ const s = this.#b()(t).left - this.#g;
543
+ return this.#f(s, e);
544
+ }
545
+ const i = this.#b()(t).left;
546
+ return this.#p(Math.floor(i / this.size) + (this.#o ? -1 : 1), e);
547
+ }
548
+ async #f(t, e, i) {
549
+ const s = this.#e, { scrollProp: n, size: r } = this;
550
+ if (s[n] === t) {
551
+ this.#m = [t, this.atStart ? 0 : r, this.atEnd ? 0 : r], this.#w(e);
552
+ return;
553
+ }
554
+ if (this.scrolled && this.#n && (t = -t), (e === "snap" || i) && this.hasAttribute("animated")) return V(
555
+ s[n],
556
+ t,
557
+ 300,
558
+ B,
559
+ (a) => s[n] = a
560
+ ).then(() => {
561
+ this.#m = [t, this.atStart ? 0 : r, this.atEnd ? 0 : r], this.#w(e);
562
+ });
563
+ s[n] = t, this.#m = [t, this.atStart ? 0 : r, this.atEnd ? 0 : r], this.#w(e);
564
+ }
565
+ async #p(t, e, i) {
566
+ const s = this.size * (this.#o ? -t : t);
567
+ return this.#f(s, e, i);
568
+ }
569
+ async scrollToAnchor(t, e) {
570
+ return this.#y(t, e ? "selection" : "navigation");
571
+ }
572
+ async #y(t, e = "anchor") {
573
+ this.#h = t;
574
+ const i = N(t)?.getClientRects?.();
575
+ if (i) {
576
+ const a = Array.from(i).find((h) => h.width > 0 && h.height > 0) || i[0];
577
+ if (!a) return;
578
+ await this.#N(a, e);
579
+ return;
580
+ }
581
+ if (this.scrolled) {
582
+ await this.#f(t * this.viewSize, e);
583
+ return;
584
+ }
585
+ const { pages: s } = this;
586
+ if (!s) return;
587
+ const n = s - 2, r = Math.round(t * (n - 1));
588
+ await this.#p(r + 1, e);
589
+ }
590
+ #O() {
591
+ if (this.scrolled) return $(
592
+ this.#t.document,
593
+ this.start + this.#g,
594
+ this.end - this.#g,
595
+ this.#b()
596
+ );
597
+ const t = this.#o ? -this.size : this.size;
598
+ return $(
599
+ this.#t.document,
600
+ this.start - t,
601
+ this.end - t,
602
+ this.#b()
603
+ );
604
+ }
605
+ #w(t) {
606
+ const e = this.#O();
607
+ this.#R = e, t !== "selection" && t !== "navigation" && t !== "anchor" ? this.#h = e : this.#E = !0;
608
+ const i = this.#d, s = { reason: t, range: e, index: i };
609
+ if (this.scrolled) s.fraction = this.start / this.viewSize;
610
+ else if (this.pages > 0) {
611
+ const { page: n, pages: r } = this;
612
+ this.#s.style.visibility = n > 1 ? "visible" : "hidden", s.fraction = (n - 1) / (r - 2), s.size = 1 / (r - 2);
613
+ }
614
+ this.dispatchEvent(new CustomEvent("relocate", { detail: s }));
615
+ }
616
+ async #P(t) {
617
+ const { index: e, src: i, anchor: s, onLoad: n, select: r } = await t;
618
+ this.#d = e;
619
+ const a = this.#t?.document?.hasFocus();
620
+ if (i) {
621
+ const h = this.#V(), c = (d) => {
622
+ if (d.head) {
623
+ const l = d.createElement("style");
624
+ d.head.prepend(l);
625
+ const m = d.createElement("style");
626
+ d.head.append(m), this.#k.set(d, [l, m]);
627
+ }
628
+ n?.({ doc: d, index: e });
629
+ }, f = this.#M.bind(this);
630
+ await h.load(i, c, f), this.dispatchEvent(new CustomEvent("create-overlayer", {
631
+ detail: {
632
+ doc: h.document,
633
+ index: e,
634
+ attach: (d) => h.overlayer = d
635
+ }
636
+ })), this.#t = h;
637
+ }
638
+ await this.scrollToAnchor((typeof s == "function" ? s(this.#t.document) : s) ?? 0, r), a && this.focusView();
639
+ }
640
+ #I(t) {
641
+ return t >= 0 && t <= this.sections.length - 1;
642
+ }
643
+ async #z({ index: t, anchor: e, select: i }) {
644
+ if (t === this.#d) await this.#P({ index: t, anchor: e, select: i });
645
+ else {
646
+ const s = this.#d, n = (r) => {
647
+ this.sections[s]?.unload?.(), this.setStyles(this.#T), this.dispatchEvent(new CustomEvent("load", { detail: r }));
648
+ };
649
+ await this.#P(Promise.resolve(this.sections[t].load()).then((r) => ({ index: t, src: r, anchor: e, onLoad: n, select: i })).catch((r) => (console.warn(r), console.warn(new Error(`Failed to load section ${t}`)), {})));
650
+ }
651
+ }
652
+ async goTo(t) {
653
+ if (this.#x) return;
654
+ const e = await t;
655
+ if (this.#I(e.index)) return this.#z(e);
656
+ }
657
+ #F(t) {
658
+ if (!this.#t) return !0;
659
+ if (this.scrolled)
660
+ return this.start > 0 ? this.#f(
661
+ Math.max(0, this.start - (t ?? this.size)),
662
+ null,
663
+ !0
664
+ ) : !0;
665
+ if (this.atStart) return;
666
+ const e = this.page - 1;
667
+ return this.#p(e, "page", !0).then(() => e <= 0);
668
+ }
669
+ #D(t) {
670
+ if (!this.#t) return !0;
671
+ if (this.scrolled)
672
+ return this.viewSize - this.end > 2 ? this.#f(
673
+ Math.min(this.viewSize, t ? this.start + t : this.end),
674
+ null,
675
+ !0
676
+ ) : !0;
677
+ if (this.atEnd) return;
678
+ const e = this.page + 1, i = this.pages;
679
+ return this.#p(e, "page", !0).then(() => e >= i - 1);
680
+ }
681
+ get atStart() {
682
+ return this.#u(-1) == null && this.page <= 1;
683
+ }
684
+ get atEnd() {
685
+ return this.#u(1) == null && this.page >= this.pages - 2;
686
+ }
687
+ #u(t) {
688
+ for (let e = this.#d + t; this.#I(e); e += t)
689
+ if (this.sections[e]?.linear !== "no") return e;
690
+ }
691
+ async #B(t, e) {
692
+ if (this.#x) return;
693
+ this.#x = !0;
694
+ const i = t === -1, s = await (i ? this.#F(e) : this.#D(e));
695
+ s && await this.#z({
696
+ index: this.#u(t),
697
+ anchor: i ? () => 1 : () => 0
698
+ }), (s || !this.hasAttribute("animated")) && await I(100), this.#x = !1;
699
+ }
700
+ prev(t) {
701
+ return this.#B(-1, t);
702
+ }
703
+ next(t) {
704
+ return this.#B(1, t);
705
+ }
706
+ prevSection() {
707
+ return this.goTo({ index: this.#u(-1) });
708
+ }
709
+ nextSection() {
710
+ return this.goTo({ index: this.#u(1) });
711
+ }
712
+ firstSection() {
713
+ const t = this.sections.findIndex((e) => e.linear !== "no");
714
+ return this.goTo({ index: t });
715
+ }
716
+ lastSection() {
717
+ const t = this.sections.findLastIndex((e) => e.linear !== "no");
718
+ return this.goTo({ index: t });
719
+ }
720
+ getContents() {
721
+ return this.#t ? [{
722
+ index: this.#d,
723
+ overlayer: this.#t.overlayer,
724
+ doc: this.#t.document
725
+ }] : [];
726
+ }
727
+ setStyles(t) {
728
+ this.#T = t;
729
+ const e = this.#k.get(this.#t?.document);
730
+ if (!e) return;
731
+ const [i, s] = e;
732
+ if (Array.isArray(t)) {
733
+ const [n, r] = t;
734
+ i.textContent = n, s.textContent = r;
735
+ } else s.textContent = t;
736
+ requestAnimationFrame(() => this.#l.style.background = _(this.#t.document)), this.#t?.document?.fonts?.ready?.then(() => this.#t.expand());
737
+ }
738
+ focusView() {
739
+ this.#t.document.defaultView.focus();
740
+ }
741
+ destroy() {
742
+ this.#r.unobserve(this), this.#t.destroy(), this.#t = null, this.sections[this.#d]?.unload?.(), this.#C.removeEventListener("change", this.#S);
743
+ }
744
+ }
745
+ customElements.define("foliate-paginator", H);
746
+ export {
747
+ H as Paginator
748
+ };