vue-book-reader
Version:
vue-book-reader is a vue wrapper for [foliate-js](https://github.com/johnfactotum/foliate-js) - library for rendering e-books in the browser. Supports EPUB, MOBI, KF8 (AZW3), FB2, CBZ, PDF (experimental; requires PDF.js), or add support for other formats
737 lines (736 loc) • 29.3 kB
JavaScript
var te = Object.defineProperty;
var ee = (o, s, t) => s in o ? te(o, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[s] = t;
var jt = (o, s, t) => (ee(o, typeof s != "symbol" ? s + "" : s, t), t), $t = (o, s, t) => {
if (!s.has(o))
throw TypeError("Cannot " + t);
};
var e = (o, s, t) => ($t(o, s, "read from private field"), t ? t.call(o) : s.get(o)), l = (o, s, t) => {
if (s.has(o))
throw TypeError("Cannot add the same private member more than once");
s instanceof WeakSet ? s.add(o) : s.set(o, t);
}, m = (o, s, t, i) => ($t(o, s, "write to private field"), i ? i.call(o, t) : s.set(o, t), t);
var c = (o, s, t) => ($t(o, s, "access private method"), t);
const ie = (o) => new Promise((s) => setTimeout(s, o)), se = (o, s, t) => {
let i;
return (...n) => {
const r = () => {
i = null, t || o(...n);
}, h = t && !i;
i && clearTimeout(i), i = setTimeout(r, s), h && o(...n);
};
}, ne = (o, s, t) => t * (s - o) + o, re = (o) => 1 - (1 - o) * (1 - o), oe = (o, s, t, i, n) => new Promise((r) => {
let h;
const a = (d) => {
h ?? (h = d);
const u = Math.min(1, (d - h) / t);
n(ne(o, s, i(u))), u < 1 ? requestAnimationFrame(a) : r();
};
requestAnimationFrame(a);
}), he = (o) => {
if (!(o != null && o.collapsed))
return o;
const { endOffset: s, endContainer: t } = o;
if (t.nodeType === 1)
return t;
if (s + 1 < t.length)
o.setEnd(t, s + 1);
else if (s > 1)
o.setStart(t, s - 1);
else
return t.parentNode;
return o;
}, bt = (o, s, t, i = t) => {
const n = o.createRange();
return n.setStart(s, t), n.setEnd(s, i), n;
}, Et = (o, s, t, i = 0, n = s.nodeValue.length) => {
if (n - i === 1)
return t(bt(o, s, i), bt(o, s, n)) < 0 ? i : n;
const r = Math.floor(i + (n - i) / 2), h = t(bt(o, s, i, r), bt(o, s, r, n));
return h < 0 ? Et(o, s, t, i, r) : h > 0 ? Et(o, s, t, r, n) : r;
}, {
SHOW_ELEMENT: ae,
SHOW_TEXT: le,
SHOW_CDATA_SECTION: ce,
FILTER_ACCEPT: Dt,
FILTER_REJECT: Wt,
FILTER_SKIP: qt
} = NodeFilter, de = ae | le | ce, Ht = (o, s, t, i) => {
const n = (f) => {
var _, b;
const w = (_ = f.localName) == null ? void 0 : _.toLowerCase();
if (w === "script" || w === "style")
return Wt;
if (f.nodeType === 1) {
const { left: T, right: L } = i(f.getBoundingClientRect());
if (L < s || T > t)
return Wt;
if (T >= s && L <= t)
return Dt;
} else {
if (!((b = f.nodeValue) != null && b.trim()))
return qt;
const T = o.createRange();
T.selectNodeContents(f);
const { left: L, right: wt } = i(T.getBoundingClientRect());
if (wt >= s && L <= t)
return Dt;
}
return qt;
}, r = o.createTreeWalker(o.body, de, { acceptNode: n }), h = [];
for (let f = r.nextNode(); f; f = r.nextNode())
h.push(f);
const a = h[0] ?? o.body, d = h[h.length - 1] ?? a, u = a.nodeType === 1 ? 0 : Et(o, a, (f, w) => {
const _ = i(f.getBoundingClientRect()), b = i(w.getBoundingClientRect());
return _.right < s && b.left > s ? 0 : b.left > s ? -1 : 1;
}), v = d.nodeType === 1 ? 0 : Et(o, d, (f, w) => {
const _ = i(f.getBoundingClientRect()), b = i(w.getBoundingClientRect());
return _.right < t && b.left > t ? 0 : b.left > t ? -1 : 1;
}), p = o.createRange();
return p.setStart(a, u), p.setEnd(d, v), p;
}, ue = (o) => {
const { defaultView: s } = o, { writingMode: t, direction: i } = s.getComputedStyle(o.body), n = t === "vertical-rl" || t === "vertical-lr", r = o.body.dir === "rtl" || i === "rtl" || o.documentElement.dir === "rtl";
return { vertical: n, rtl: r };
}, At = (o) => {
const s = o.defaultView.getComputedStyle(o.body);
return s.backgroundColor === "rgba(0, 0, 0, 0)" && s.backgroundImage === "none" ? o.defaultView.getComputedStyle(o.documentElement).background : s.background;
}, Qt = (o, s) => Array.from({ length: o }, () => {
const t = document.createElement("div"), i = document.createElement("div");
return t.append(i), i.setAttribute("part", s), t;
}), st = (o, s) => {
const { style: t } = o;
for (const [i, n] of Object.entries(s))
t.setProperty(i, n, "important");
};
var ot, E, x, ht, y, S, at, J, M, K;
class me {
constructor({ container: s, onExpand: t }) {
l(this, ot, new ResizeObserver(() => this.expand()));
l(this, E, document.createElement("div"));
l(this, x, document.createElement("iframe"));
l(this, ht, document.createRange());
l(this, y, void 0);
l(this, S, !1);
l(this, at, !1);
l(this, J, !0);
l(this, M, void 0);
l(this, K, {});
this.container = s, this.onExpand = t, e(this, x).setAttribute("part", "filter"), e(this, E).append(e(this, x)), Object.assign(e(this, E).style, {
boxSizing: "content-box",
position: "relative",
overflow: "hidden",
flex: "0 0 auto",
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center"
}), Object.assign(e(this, x).style, {
overflow: "hidden",
border: "0",
display: "none",
width: "100%",
height: "100%"
}), e(this, x).setAttribute("sandbox", "allow-same-origin allow-scripts"), e(this, x).setAttribute("scrolling", "no");
}
get element() {
return e(this, E);
}
get document() {
return e(this, x).contentDocument;
}
async load(s, t, i) {
if (typeof s != "string")
throw new Error(`${s} is not string`);
return new Promise((n) => {
e(this, x).addEventListener("load", () => {
const r = this.document;
t == null || t(r), e(this, x).style.display = "block";
const { vertical: h, rtl: a } = ue(r), d = At(r);
e(this, x).style.display = "none", m(this, S, h), m(this, at, a), e(this, ht).selectNodeContents(r.body);
const u = i == null ? void 0 : i({ vertical: h, rtl: a, background: d });
e(this, x).style.display = "block", this.render(u), e(this, ot).observe(r.body), r.fonts.ready.then(() => this.expand()), n();
}, { once: !0 }), e(this, x).src = s;
});
}
render(s) {
s && (m(this, J, s.flow !== "scrolled"), m(this, K, s), e(this, J) ? this.columnize(s) : this.scrolled(s));
}
scrolled({ gap: s, columnWidth: t }) {
const i = e(this, S), n = this.document;
st(n.documentElement, {
"box-sizing": "border-box",
padding: i ? `${s}px 0` : `0 ${s}px`,
"column-width": "auto",
height: "auto",
width: "auto"
}), st(n.body, {
[i ? "max-height" : "max-width"]: `${t}px`,
margin: "auto"
}), this.setImageSize(), this.expand();
}
columnize({ width: s, height: t, gap: i, columnWidth: n }) {
const r = e(this, S);
m(this, M, r ? t : s);
const h = this.document;
st(h.documentElement, {
"box-sizing": "border-box",
"column-width": `${Math.trunc(n)}px`,
"column-gap": `${i}px`,
"column-fill": "auto",
...r ? { width: `${s}px` } : { height: `${t}px` },
padding: r ? `${i / 2}px 0` : `0 ${i / 2}px`,
overflow: "hidden",
// force wrap long words
"overflow-wrap": "break-word",
// reset some potentially problematic props
position: "static",
border: "0",
margin: "0",
"max-height": "none",
"max-width": "none",
"min-height": "none",
"min-width": "none",
// fix glyph clipping in WebKit
"-webkit-line-box-contain": "block glyphs replaced"
}), st(h.body, {
"max-height": "none",
"max-width": "none",
margin: "0"
}), this.setImageSize(), this.expand();
}
setImageSize() {
const { width: s, height: t, margin: i } = e(this, K), n = e(this, S), r = this.document;
for (const h of r.body.querySelectorAll("img, svg, video")) {
const { maxHeight: a, maxWidth: d } = r.defaultView.getComputedStyle(h);
st(h, {
"max-height": n ? a !== "none" && a !== "0px" ? a : "100%" : `${t - i * 2}px`,
"max-width": n ? `${s - i * 2}px` : d !== "none" && d !== "0px" ? d : "100%",
"object-fit": "contain",
"page-break-inside": "avoid",
"break-inside": "avoid",
"box-sizing": "border-box"
});
}
}
expand() {
const { documentElement: s } = this.document;
if (e(this, J)) {
const t = e(this, S) ? "height" : "width", i = e(this, S) ? "width" : "height", n = e(this, ht).getBoundingClientRect(), r = s.getBoundingClientRect(), a = (e(this, S) ? 0 : e(this, at) ? r.right - n.right : n.left - r.left) + n[t], u = Math.ceil(a / e(this, M)) * e(this, M);
e(this, E).style.padding = "0", e(this, x).style[t] = `${u}px`, e(this, E).style[t] = `${u + e(this, M) * 2}px`, e(this, x).style[i] = "100%", e(this, E).style[i] = "100%", s.style[t] = `${e(this, M)}px`, e(this, y) && (e(this, y).element.style.margin = "0", e(this, y).element.style.left = e(this, S) ? "0" : `${e(this, M)}px`, e(this, y).element.style.top = e(this, S) ? `${e(this, M)}px` : "0", e(this, y).element.style[t] = `${u}px`, e(this, y).redraw());
} else {
const t = e(this, S) ? "width" : "height", i = e(this, S) ? "height" : "width", r = s.getBoundingClientRect()[t], { margin: h } = e(this, K), a = e(this, S) ? `0 ${h}px` : `${h}px 0`;
e(this, E).style.padding = a, e(this, x).style[t] = `${r}px`, e(this, E).style[t] = `${r}px`, e(this, x).style[i] = "100%", e(this, E).style[i] = "100%", e(this, y) && (e(this, y).element.style.margin = a, e(this, y).element.style.left = "0", e(this, y).element.style.top = "0", e(this, y).element.style[t] = `${r}px`, e(this, y).redraw());
}
this.onExpand();
}
set overlayer(s) {
m(this, y, s), e(this, E).append(s.element);
}
get overlayer() {
return e(this, y);
}
destroy() {
this.document && e(this, ot).unobserve(this.document.body);
}
}
ot = new WeakMap(), E = new WeakMap(), x = new WeakMap(), ht = new WeakMap(), y = new WeakMap(), S = new WeakMap(), at = new WeakMap(), J = new WeakMap(), M = new WeakMap(), K = new WeakMap();
var A, lt, R, D, z, V, W, g, C, k, P, $, I, U, q, ct, dt, ut, Z, N, H, tt, zt, Gt, mt, Rt, gt, Pt, pt, It, ft, Bt, Q, nt, _t, Yt, O, G, F, Y, Ct, Jt, Tt, Kt, X, rt, xt, Lt, yt, Vt, et, St, kt, Ut, Mt, Zt, B, j, vt, Nt;
class Xt extends HTMLElement {
constructor() {
super();
l(this, zt);
l(this, mt);
l(this, gt);
l(this, pt);
l(this, ft);
// allows one to process rects as if they were LTR and horizontal
l(this, Q);
l(this, _t);
l(this, O);
l(this, F);
l(this, Ct);
l(this, Tt);
l(this, X);
l(this, xt);
l(this, yt);
l(this, et);
l(this, kt);
l(this, Mt);
l(this, B);
l(this, vt);
l(this, A, this.attachShadow({ mode: "closed" }));
l(this, lt, new ResizeObserver(() => this.render()));
l(this, R, void 0);
l(this, D, void 0);
l(this, z, void 0);
l(this, V, void 0);
l(this, W, void 0);
l(this, g, void 0);
l(this, C, !1);
l(this, k, !1);
l(this, P, 0);
l(this, $, -1);
l(this, I, 0);
// anchor view to a fraction (0-1), Range, or Element
l(this, U, !1);
l(this, q, !1);
// while true, prevent any further navigation
l(this, ct, void 0);
l(this, dt, /* @__PURE__ */ new WeakMap());
l(this, ut, matchMedia("(prefers-color-scheme: dark)"));
l(this, Z, void 0);
l(this, N, void 0);
l(this, H, void 0);
l(this, tt, void 0);
e(this, A).innerHTML = `<style>
:host {
display: block;
container-type: size;
}
:host, #top {
box-sizing: border-box;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
#top {
--_gap: 7%;
--_margin: 48px;
--_max-inline-size: 720px;
--_max-block-size: 1440px;
--_max-column-count: 2;
--_max-column-count-portrait: 1;
--_max-column-count-spread: var(--_max-column-count);
--_half-gap: calc(var(--_gap) / 2);
--_max-width: calc(var(--_max-inline-size) * var(--_max-column-count-spread));
--_max-height: var(--_max-block-size);
display: grid;
grid-template-columns:
minmax(var(--_half-gap), 1fr)
var(--_half-gap)
minmax(0, calc(var(--_max-width) - var(--_gap)))
var(--_half-gap)
minmax(var(--_half-gap), 1fr);
grid-template-rows:
minmax(var(--_margin), 1fr)
minmax(0, var(--_max-height))
minmax(var(--_margin), 1fr);
&.vertical {
--_max-column-count-spread: var(--_max-column-count-portrait);
--_max-width: var(--_max-block-size);
--_max-height: calc(var(--_max-inline-size) * var(--_max-column-count-spread));
}
(orientation: portrait) {
& {
--_max-column-count-spread: var(--_max-column-count-portrait);
}
&.vertical {
--_max-column-count-spread: var(--_max-column-count);
}
}
}
#background {
grid-column: 1 / -1;
grid-row: 1 / -1;
}
#container {
grid-column: 2 / 5;
grid-row: 2;
overflow: hidden;
}
:host([flow="scrolled"]) #container {
grid-column: 1 / -1;
grid-row: 1 / -1;
overflow: auto;
}
#header {
grid-column: 3 / 4;
grid-row: 1;
}
#footer {
grid-column: 3 / 4;
grid-row: 3;
align-self: end;
}
#header, #footer {
display: grid;
height: var(--_margin);
}
:is(#header, #footer) > * {
display: flex;
align-items: center;
min-width: 0;
}
:is(#header, #footer) > * > * {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
font-size: .75em;
opacity: .6;
}
</style>
<div id="top">
<div id="background" part="filter"></div>
<div id="header"></div>
<div id="container"></div>
<div id="footer"></div>
</div>
`, m(this, R, e(this, A).getElementById("top")), m(this, D, e(this, A).getElementById("background")), m(this, z, e(this, A).getElementById("container")), m(this, V, e(this, A).getElementById("header")), m(this, W, e(this, A).getElementById("footer")), e(this, lt).observe(e(this, z)), e(this, z).addEventListener("scroll", se(() => {
this.scrolled && (e(this, U) ? m(this, U, !1) : c(this, X, rt).call(this, "scroll"));
}, 250));
const t = { passive: !1 };
this.addEventListener("touchstart", c(this, gt, Pt).bind(this), t), this.addEventListener("touchmove", c(this, pt, It).bind(this), t), this.addEventListener("touchend", c(this, ft, Bt).bind(this)), this.addEventListener("load", ({ detail: { doc: i } }) => {
i.addEventListener("touchstart", c(this, gt, Pt).bind(this), t), i.addEventListener("touchmove", c(this, pt, It).bind(this), t), i.addEventListener("touchend", c(this, ft, Bt).bind(this));
}), m(this, Z, () => {
e(this, g) && (e(this, D).style.background = At(e(this, g).document));
}), e(this, ut).addEventListener("change", e(this, Z));
}
attributeChangedCallback(t, i, n) {
switch (t) {
case "flow":
this.render();
break;
case "gap":
case "margin":
case "max-block-size":
case "max-column-count":
e(this, R).style.setProperty("--_" + t, n);
break;
case "max-inline-size":
e(this, R).style.setProperty("--_" + t, n), this.render();
break;
}
}
open(t) {
this.bookDir = t.dir, this.sections = t.sections;
}
render() {
e(this, g) && (e(this, g).render(c(this, mt, Rt).call(this, {
vertical: e(this, C),
rtl: e(this, k)
})), this.scrollToAnchor(e(this, I)));
}
get scrolled() {
return this.getAttribute("flow") === "scrolled";
}
get scrollProp() {
const { scrolled: t } = this;
return e(this, C) ? t ? "scrollLeft" : "scrollTop" : t ? "scrollTop" : "scrollLeft";
}
get sideProp() {
const { scrolled: t } = this;
return e(this, C) ? t ? "width" : "height" : t ? "height" : "width";
}
get size() {
return e(this, z).getBoundingClientRect()[this.sideProp];
}
get viewSize() {
return e(this, g).element.getBoundingClientRect()[this.sideProp];
}
get start() {
return Math.abs(e(this, z)[this.scrollProp]);
}
get end() {
return this.start + this.size;
}
get page() {
return Math.floor((this.start + this.end) / 2 / this.size);
}
get pages() {
return Math.round(this.viewSize / this.size);
}
scrollBy(t, i) {
const n = e(this, C) ? i : t, r = e(this, z), { scrollProp: h } = this, [a, d, u] = e(this, N), v = e(this, k), p = v ? a - u : a - d, f = v ? a + d : a + u;
r[h] = Math.max(p, Math.min(
f,
r[h] + n
));
}
snap(t, i) {
const n = e(this, C) ? i : t, [r, h, a] = e(this, N), { start: d, end: u, pages: v, size: p } = this, f = Math.abs(r) - h, w = Math.abs(r) + a, _ = n * (e(this, k) ? -p : p), b = Math.floor(
Math.max(f, Math.min(w, (d + u) / 2 + (isNaN(_) ? 0 : _))) / p
);
c(this, F, Y).call(this, b, "snap").then(() => {
const T = b <= 0 ? -1 : b >= v - 1 ? 1 : null;
if (T)
return c(this, et, St).call(this, {
index: c(this, B, j).call(this, T),
anchor: T < 0 ? () => 1 : () => 0
});
});
}
async scrollToAnchor(t, i) {
var d, u;
m(this, I, t);
const n = (u = (d = he(t)) == null ? void 0 : d.getClientRects) == null ? void 0 : u.call(d);
if (n) {
const v = Array.from(n).find((p) => p.width > 0 && p.height > 0) || n[0];
if (!v)
return;
await c(this, _t, Yt).call(this, v, "anchor"), i && c(this, Ct, Jt).call(this);
return;
}
if (this.scrolled) {
await c(this, O, G).call(this, t * this.viewSize, "anchor");
return;
}
const { pages: r } = this;
if (!r)
return;
const h = r - 2, a = Math.round(t * (h - 1));
await c(this, F, Y).call(this, a + 1, "anchor");
}
async goTo(t) {
if (e(this, q))
return;
const i = await t;
if (c(this, yt, Vt).call(this, i.index))
return c(this, et, St).call(this, i);
}
get atStart() {
return c(this, B, j).call(this, -1) == null && this.page <= 1;
}
get atEnd() {
return c(this, B, j).call(this, 1) == null && this.page >= this.pages - 2;
}
prev(t) {
return c(this, vt, Nt).call(this, -1, t);
}
next(t) {
return c(this, vt, Nt).call(this, 1, t);
}
prevSection() {
return this.goTo({ index: c(this, B, j).call(this, -1) });
}
nextSection() {
return this.goTo({ index: c(this, B, j).call(this, 1) });
}
firstSection() {
const t = this.sections.findIndex((i) => i.linear !== "no");
return this.goTo({ index: t });
}
lastSection() {
const t = this.sections.findLastIndex((i) => i.linear !== "no");
return this.goTo({ index: t });
}
getContents() {
return e(this, g) ? [{
index: e(this, $),
overlayer: e(this, g).overlayer,
doc: e(this, g).document
}] : [];
}
setStyles(t) {
var h, a, d, u, v;
m(this, ct, t);
const i = e(this, dt).get((h = e(this, g)) == null ? void 0 : h.document);
if (!i)
return;
const [n, r] = i;
if (Array.isArray(t)) {
const [p, f] = t;
n.textContent = p, r.textContent = f;
} else
r.textContent = t;
e(this, D).style.background = At(e(this, g).document), (v = (u = (d = (a = e(this, g)) == null ? void 0 : a.document) == null ? void 0 : d.fonts) == null ? void 0 : u.ready) == null || v.then(() => e(this, g).expand());
}
destroy() {
var t, i;
e(this, lt).unobserve(this), e(this, g).destroy(), m(this, g, null), (i = (t = this.sections[e(this, $)]) == null ? void 0 : t.unload) == null || i.call(t), e(this, ut).removeEventListener("change", e(this, Z));
}
}
A = new WeakMap(), lt = new WeakMap(), R = new WeakMap(), D = new WeakMap(), z = new WeakMap(), V = new WeakMap(), W = new WeakMap(), g = new WeakMap(), C = new WeakMap(), k = new WeakMap(), P = new WeakMap(), $ = new WeakMap(), I = new WeakMap(), U = new WeakMap(), q = new WeakMap(), ct = new WeakMap(), dt = new WeakMap(), ut = new WeakMap(), Z = new WeakMap(), N = new WeakMap(), H = new WeakMap(), tt = new WeakMap(), zt = new WeakSet(), Gt = function() {
return e(this, g) && (e(this, g).destroy(), e(this, z).removeChild(e(this, g).element)), m(this, g, new me({
container: this,
onExpand: () => this.scrollToAnchor(e(this, I))
})), e(this, z).append(e(this, g).element), e(this, g);
}, mt = new WeakSet(), Rt = function({ vertical: t, rtl: i, background: n }) {
m(this, C, t), m(this, k, i), e(this, R).classList.toggle("vertical", t), e(this, D).style.background = n;
const { width: r, height: h } = e(this, z).getBoundingClientRect(), a = t ? h : r, d = getComputedStyle(e(this, R)), u = parseFloat(d.getPropertyValue("--_max-inline-size")), v = parseInt(d.getPropertyValue("--_max-column-count-spread")), p = parseFloat(d.getPropertyValue("--_margin"));
m(this, P, p);
const f = parseFloat(d.getPropertyValue("--_gap")) / 100, w = -f / (f - 1) * a, _ = this.getAttribute("flow");
if (_ === "scrolled") {
this.setAttribute("dir", t ? "rtl" : "ltr"), e(this, R).style.padding = "0";
const it = u;
return this.heads = null, this.feet = null, e(this, V).replaceChildren(), e(this, W).replaceChildren(), { flow: _, margin: p, gap: w, columnWidth: it };
}
const b = Math.min(v, Math.ceil(a / u)), T = a / b - w;
this.setAttribute("dir", i ? "rtl" : "ltr");
const L = t ? Math.min(2, Math.ceil(r / u)) : b, wt = {
gridTemplateColumns: `repeat(${L}, 1fr)`,
gap: `${w}px`,
direction: this.bookDir === "rtl" ? "rtl" : "ltr"
};
Object.assign(e(this, V).style, wt), Object.assign(e(this, W).style, wt);
const Ot = Qt(L, "head"), Ft = Qt(L, "foot");
return this.heads = Ot.map((it) => it.children[0]), this.feet = Ft.map((it) => it.children[0]), e(this, V).replaceChildren(...Ot), e(this, W).replaceChildren(...Ft), { height: h, width: r, margin: p, gap: w, columnWidth: T };
}, gt = new WeakSet(), Pt = function(t) {
const i = t.changedTouches[0];
m(this, H, {
x: i == null ? void 0 : i.screenX,
y: i == null ? void 0 : i.screenY,
t: t.timeStamp,
vx: 0,
xy: 0
});
}, pt = new WeakSet(), It = function(t) {
const i = e(this, H);
if (i.pinched || (i.pinched = globalThis.visualViewport.scale > 1, this.scrolled || i.pinched))
return;
if (t.touches.length > 1) {
e(this, tt) && t.preventDefault();
return;
}
t.preventDefault();
const n = t.changedTouches[0], r = n.screenX, h = n.screenY, a = i.x - r, d = i.y - h, u = t.timeStamp - i.t;
i.x = r, i.y = h, i.t = t.timeStamp, i.vx = a / u, i.vy = d / u, m(this, tt, !0), this.scrollBy(a, d);
}, ft = new WeakSet(), Bt = function() {
m(this, tt, !1), !this.scrolled && requestAnimationFrame(() => {
globalThis.visualViewport.scale === 1 && this.snap(e(this, H).vx, e(this, H).vy);
});
}, Q = new WeakSet(), nt = function() {
if (this.scrolled) {
const i = this.viewSize, n = e(this, P);
return e(this, C) ? ({ left: r, right: h }) => ({ left: i - h - n, right: i - r - n }) : ({ top: r, bottom: h }) => ({ left: r + n, right: h + n });
}
const t = this.pages * this.size;
return e(this, k) ? ({ left: i, right: n }) => ({ left: t - n, right: t - i }) : e(this, C) ? ({ top: i, bottom: n }) => ({ left: i, right: n }) : (i) => i;
}, _t = new WeakSet(), Yt = async function(t, i) {
if (this.scrolled) {
const r = c(this, Q, nt).call(this)(t).left - e(this, P);
return c(this, O, G).call(this, r, i);
}
const n = c(this, Q, nt).call(this)(t).left + e(this, P) / 2;
return c(this, F, Y).call(this, Math.floor(n / this.size) + (e(this, k) ? -1 : 1), i);
}, O = new WeakSet(), G = async function(t, i, n) {
const r = e(this, z), { scrollProp: h, size: a } = this;
if (r[h] === t) {
m(this, N, [t, this.atStart ? 0 : a, this.atEnd ? 0 : a]), c(this, X, rt).call(this, i);
return;
}
if (this.scrolled && e(this, C) && (t = -t), (i === "snap" || n) && this.hasAttribute("animated"))
return oe(
r[h],
t,
300,
re,
(d) => r[h] = d
).then(() => {
m(this, N, [t, this.atStart ? 0 : a, this.atEnd ? 0 : a]), c(this, X, rt).call(this, i);
});
r[h] = t, m(this, N, [t, this.atStart ? 0 : a, this.atEnd ? 0 : a]), c(this, X, rt).call(this, i);
}, F = new WeakSet(), Y = async function(t, i, n) {
const r = this.size * (e(this, k) ? -t : t);
return c(this, O, G).call(this, r, i, n);
}, Ct = new WeakSet(), Jt = function() {
const { defaultView: t } = e(this, g).document;
if (e(this, I).startContainer) {
const i = t.getSelection();
i.removeAllRanges(), i.addRange(e(this, I));
}
}, Tt = new WeakSet(), Kt = function() {
if (this.scrolled)
return Ht(
e(this, g).document,
this.start + e(this, P),
this.end - e(this, P),
c(this, Q, nt).call(this)
);
const t = e(this, k) ? -this.size : this.size;
return Ht(
e(this, g).document,
this.start - t,
this.end - t,
c(this, Q, nt).call(this)
);
}, X = new WeakSet(), rt = function(t) {
const i = c(this, Tt, Kt).call(this);
t !== "anchor" ? m(this, I, i) : m(this, U, !0);
const n = e(this, $), r = { reason: t, range: i, index: n };
if (this.scrolled)
r.fraction = this.start / this.viewSize;
else if (this.pages > 0) {
const { page: h, pages: a } = this;
e(this, V).style.visibility = h > 1 ? "visible" : "hidden", r.fraction = (h - 1) / (a - 2), r.size = 1 / (a - 2);
}
this.dispatchEvent(new CustomEvent("relocate", { detail: r }));
}, xt = new WeakSet(), Lt = async function(t) {
const { index: i, src: n, anchor: r, onLoad: h, select: a } = await t;
if (m(this, $, i), n) {
const d = c(this, zt, Gt).call(this), u = (p) => {
if (p.head) {
const f = p.createElement("style");
p.head.prepend(f);
const w = p.createElement("style");
p.head.append(w), e(this, dt).set(p, [f, w]);
}
h == null || h({ doc: p, index: i });
}, v = c(this, mt, Rt).bind(this);
await d.load(n, u, v), this.dispatchEvent(new CustomEvent("create-overlayer", {
detail: {
doc: d.document,
index: i,
attach: (p) => d.overlayer = p
}
})), m(this, g, d);
}
await this.scrollToAnchor((typeof r == "function" ? r(e(this, g).document) : r) ?? 0, a);
}, yt = new WeakSet(), Vt = function(t) {
return t >= 0 && t <= this.sections.length - 1;
}, et = new WeakSet(), St = async function({ index: t, anchor: i, select: n }) {
if (t === e(this, $))
await c(this, xt, Lt).call(this, { index: t, anchor: i, select: n });
else {
const r = e(this, $), h = (a) => {
var d, u;
(u = (d = this.sections[r]) == null ? void 0 : d.unload) == null || u.call(d), this.setStyles(e(this, ct)), this.dispatchEvent(new CustomEvent("load", { detail: a }));
};
await c(this, xt, Lt).call(this, Promise.resolve(this.sections[t].load()).then((a) => ({ index: t, src: a, anchor: i, onLoad: h, select: n })).catch((a) => (console.warn(a), console.warn(new Error(`Failed to load section ${t}`)), {})));
}
}, kt = new WeakSet(), Ut = function(t) {
if (!e(this, g))
return !0;
if (this.scrolled)
return this.start > 0 ? c(this, O, G).call(this, Math.max(0, this.start - (t ?? this.size)), null, !0) : !0;
if (this.atStart)
return;
const i = this.page - 1;
return c(this, F, Y).call(this, i, "page", !0).then(() => i <= 0);
}, Mt = new WeakSet(), Zt = function(t) {
if (!e(this, g))
return !0;
if (this.scrolled)
return this.viewSize - this.end > 2 ? c(this, O, G).call(this, Math.min(this.viewSize, t ? this.start + t : this.end), null, !0) : !0;
if (this.atEnd)
return;
const i = this.page + 1, n = this.pages;
return c(this, F, Y).call(this, i, "page", !0).then(() => i >= n - 1);
}, B = new WeakSet(), j = function(t) {
var i;
for (let n = e(this, $) + t; c(this, yt, Vt).call(this, n); n += t)
if (((i = this.sections[n]) == null ? void 0 : i.linear) !== "no")
return n;
}, vt = new WeakSet(), Nt = async function(t, i) {
if (e(this, q))
return;
m(this, q, !0);
const n = t === -1, r = await (n ? c(this, kt, Ut).call(this, i) : c(this, Mt, Zt).call(this, i));
r && await c(this, et, St).call(this, {
index: c(this, B, j).call(this, t),
anchor: n ? () => 1 : () => 0
}), (r || !this.hasAttribute("animated")) && await ie(100), m(this, q, !1);
}, jt(Xt, "observedAttributes", [
"flow",
"gap",
"margin",
"max-inline-size",
"max-block-size",
"max-column-count"
]);
customElements.define("foliate-paginator", Xt);
export {
Xt as Paginator
};