@zinejs/core 0.8.0 → 0.9.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.
Files changed (41) hide show
  1. package/README.md +27 -49
  2. package/dist/{bundled-Cp43MIt0.js → bundled-ESapkNsS.js} +34 -34
  3. package/dist/bundled-ESapkNsS.js.map +1 -0
  4. package/dist/controls/contextMenu.d.ts +16 -0
  5. package/dist/controls/controls.d.ts +10 -3
  6. package/dist/controls/icons.d.ts +2 -2
  7. package/dist/controls/menu.d.ts +68 -0
  8. package/dist/controls/search.d.ts +15 -2
  9. package/dist/controls/styles.d.ts +1 -1
  10. package/dist/controls/toolbar.d.ts +1 -1
  11. package/dist/controls/types.d.ts +13 -2
  12. package/dist/{controls-Djjk8Yac.js → controls-CcOu_19g.js} +355 -199
  13. package/dist/controls-CcOu_19g.js.map +1 -0
  14. package/dist/curls.js +1 -1
  15. package/dist/geometry/curls/cone.d.ts +4 -3
  16. package/dist/index.js +644 -450
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.umd.js +61 -13
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/loading/loading.d.ts +1 -1
  21. package/dist/{loading-C0qbANt2.js → loading-DF88K9yJ.js} +2 -2
  22. package/dist/loading-DF88K9yJ.js.map +1 -0
  23. package/dist/renderer/gl/texture.d.ts +13 -2
  24. package/dist/renderer/types.d.ts +6 -0
  25. package/dist/renderer/webglRenderer.d.ts +1 -0
  26. package/dist/{share-DXAfK9rJ.js → share-BrQa6aYm.js} +2 -2
  27. package/dist/{share-DXAfK9rJ.js.map → share-BrQa6aYm.js.map} +1 -1
  28. package/dist/source/types.d.ts +5 -0
  29. package/dist/styles-D_zOGk2q.js +40 -0
  30. package/dist/styles-D_zOGk2q.js.map +1 -0
  31. package/dist/{webglRenderer-nGRruZk2.js → webglRenderer-CmQ_mUrX.js} +113 -101
  32. package/dist/webglRenderer-CmQ_mUrX.js.map +1 -0
  33. package/dist/zine.d.ts +52 -1
  34. package/options.schema.json +49 -0
  35. package/package.json +2 -2
  36. package/dist/bundled-Cp43MIt0.js.map +0 -1
  37. package/dist/controls-Djjk8Yac.js.map +0 -1
  38. package/dist/loading-C0qbANt2.js.map +0 -1
  39. package/dist/styles-CgCzjFUk.js +0 -40
  40. package/dist/styles-CgCzjFUk.js.map +0 -1
  41. package/dist/webglRenderer-nGRruZk2.js.map +0 -1
@@ -1,18 +1,18 @@
1
- import { i as e, n as t, t as n } from "./registry-5nuYFMd4.js";
2
- import { i as r, n as i, r as a, t as o } from "./styles-CgCzjFUk.js";
1
+ import { i as e, n as t, r as n, t as r } from "./registry-5nuYFMd4.js";
2
+ import { i, n as a, r as o, t as s } from "./styles-D_zOGk2q.js";
3
3
  //#region src/controls/builtins.ts
4
- var s = Math.SQRT2, c = (e) => e.zine.container.ownerDocument?.fullscreenElement === e.zine.container;
5
- function l() {
4
+ var c = Math.SQRT2, l = (e) => e.zine.container.ownerDocument?.fullscreenElement === e.zine.container;
5
+ function u() {
6
6
  t({
7
7
  id: "prev",
8
8
  title: "Previous page",
9
- icon: a.prev,
9
+ icon: o.prev,
10
10
  isDisabled: (e) => !e.zine.canFlipPrev(),
11
11
  action: (e) => e.zine.flipPrev()
12
12
  }), t({
13
13
  id: "next",
14
14
  title: "Next page",
15
- icon: a.next,
15
+ icon: o.next,
16
16
  isDisabled: (e) => !e.zine.canFlipNext(),
17
17
  action: (e) => e.zine.flipNext()
18
18
  });
@@ -20,7 +20,7 @@ function l() {
20
20
  t({
21
21
  id: "first",
22
22
  title: "First page",
23
- icon: (t) => e(t) ? a.last : a.first,
23
+ icon: (t) => e(t) ? o.last : o.first,
24
24
  isDisabled: (e) => !e.zine.canFlipPrev(),
25
25
  action: (e) => {
26
26
  e.zine.flipTo(0), e.close();
@@ -28,7 +28,7 @@ function l() {
28
28
  }), t({
29
29
  id: "last",
30
30
  title: "Last page",
31
- icon: (t) => e(t) ? a.first : a.last,
31
+ icon: (t) => e(t) ? o.first : o.last,
32
32
  isDisabled: (e) => !e.zine.canFlipNext(),
33
33
  action: (e) => {
34
34
  e.zine.flipTo(e.zine.getPageCount() - 1), e.close();
@@ -36,46 +36,46 @@ function l() {
36
36
  }), t({
37
37
  id: "zoomIn",
38
38
  title: "Zoom in",
39
- icon: a.zoomIn,
39
+ icon: o.zoomIn,
40
40
  isDisabled: (e) => e.zine.getZoom() >= e.zine.getMaxZoom() - 1e-6,
41
- action: (e) => e.zine.setZoom(e.zine.getZoom() * s)
41
+ action: (e) => e.zine.setZoom(e.zine.getZoom() * c)
42
42
  }), t({
43
43
  id: "zoomOut",
44
44
  title: "Zoom out",
45
- icon: a.zoomOut,
45
+ icon: o.zoomOut,
46
46
  isDisabled: (e) => e.zine.getZoom() <= 1.000001,
47
- action: (e) => e.zine.setZoom(e.zine.getZoom() / s)
47
+ action: (e) => e.zine.setZoom(e.zine.getZoom() / c)
48
48
  }), t({
49
49
  id: "fullscreen",
50
50
  title: "Fullscreen",
51
- icon: a.fullscreen,
51
+ icon: o.fullscreen,
52
52
  isVisible: (e) => typeof e.zine.container.requestFullscreen == "function",
53
- isActive: c,
53
+ isActive: l,
54
54
  action: (e) => {
55
55
  let t = e.zine.container.ownerDocument;
56
- c(e) ? t?.exitFullscreen?.() : e.zine.container.requestFullscreen?.(), e.close();
56
+ l(e) ? t?.exitFullscreen?.() : e.zine.container.requestFullscreen?.(), e.close();
57
57
  }
58
58
  }), t({
59
59
  id: "share",
60
60
  title: "Share",
61
- icon: a.share,
61
+ icon: o.share,
62
62
  action: (e) => {
63
- e.close(), import("./share-DXAfK9rJ.js").then(({ ShareDialog: t }) => new t(e.zine, e.zine.container, e.colorScheme)).catch(() => {
63
+ e.close(), import("./share-BrQa6aYm.js").then(({ ShareDialog: t }) => new t(e.zine, e.zine.container, e.colorScheme)).catch(() => {
64
64
  navigator.clipboard?.writeText(e.zine.pageLink()).catch(() => {});
65
65
  });
66
66
  }
67
67
  }), t({
68
68
  id: "download",
69
69
  title: "Download PDF",
70
- icon: a.download,
70
+ icon: o.download,
71
71
  isVisible: (e) => e.zine.canDownload(),
72
- action: (e) => {
73
- e.zine.download(), e.close();
72
+ action: async (e) => {
73
+ await e.zine.download(), e.close();
74
74
  }
75
75
  }), t({
76
76
  id: "spread",
77
77
  title: (e) => e.zine.isSinglePage() ? "Show two pages" : "Show one page",
78
- icon: (e) => e.zine.isSinglePage() ? a.twoPages : a.onePage,
78
+ icon: (e) => e.zine.isSinglePage() ? o.twoPages : o.onePage,
79
79
  isVisible: (e) => !e.zine.isResponsiveSingle(),
80
80
  action: (e) => {
81
81
  e.zine.toggleSpreadMode(), e.close();
@@ -83,15 +83,15 @@ function l() {
83
83
  }), t({
84
84
  id: "print",
85
85
  title: "Print",
86
- icon: a.print,
86
+ icon: o.print,
87
87
  isVisible: (e) => e.zine.canPrint(),
88
- action: (e) => {
89
- e.zine.print(), e.close();
88
+ action: async (e) => {
89
+ await e.zine.print(), e.close();
90
90
  }
91
91
  }), t({
92
92
  id: "menu",
93
93
  title: "More",
94
- icon: a.menu,
94
+ icon: o.menu,
95
95
  children: [
96
96
  "first",
97
97
  "last",
@@ -104,8 +104,105 @@ function l() {
104
104
  });
105
105
  }
106
106
  //#endregion
107
+ //#region src/controls/menu.ts
108
+ var d = /* @__PURE__ */ new Set();
109
+ function f(e) {
110
+ return e === "|" ? null : typeof e == "string" ? e : e.id;
111
+ }
112
+ function p(e, t) {
113
+ return t.size ? e.filter((e) => {
114
+ let n = f(e);
115
+ return n === null || !t.has(n);
116
+ }) : e;
117
+ }
118
+ function m(e, t) {
119
+ return typeof e.title == "function" ? e.title(t) : e.title;
120
+ }
121
+ function h(e, t) {
122
+ return typeof e.icon == "function" ? e.icon(t) : e.icon;
123
+ }
124
+ function g(e) {
125
+ return e instanceof HTMLButtonElement || e instanceof HTMLInputElement ? [e] : [...e.querySelectorAll("button, input")];
126
+ }
127
+ function _(e, t) {
128
+ e.classList.toggle("zine-controls-busy", t), e.setAttribute("aria-busy", String(t)), e.disabled = t;
129
+ }
130
+ function v(e, t, n, r) {
131
+ if (e.isDisabled?.(n) || t.classList.contains("zine-controls-busy")) return;
132
+ let i = e.action?.(n);
133
+ i && typeof i.then == "function" && (_(t, !0), i.finally(() => {
134
+ _(t, !1), r();
135
+ })), r();
136
+ }
137
+ function y(e, t, n, r, a, o = !1) {
138
+ let s = e.createElement("button"), c = m(t, r), l = h(t, r);
139
+ if (s.type = "button", s.className = n, s.title = c, s.setAttribute("aria-label", c), l && s.appendChild(i(e, l)), o || !l) {
140
+ let t = e.createElement("span");
141
+ t.className = "zine-controls-label", t.textContent = c, s.appendChild(t);
142
+ }
143
+ return s.addEventListener("click", () => a(t, s)), s;
144
+ }
145
+ function b(e, t, n, r, a) {
146
+ let o = a ?? t.isVisible?.(n);
147
+ o !== void 0 && (e.style.display = o ? "" : "none");
148
+ let s = e.classList.contains("zine-controls-busy"), c = (t.isDisabled?.(n) ?? !1) || s, l = g(e);
149
+ for (let e of l) e.disabled = c;
150
+ if (l.length || e.setAttribute("aria-disabled", String(c)), e.classList.toggle("zine-controls-off", c), t.isActive && e.setAttribute("aria-pressed", String(t.isActive(n))), typeof t.title == "function") {
151
+ let r = t.title(n);
152
+ e.title = r, e.setAttribute("aria-label", r);
153
+ let i = e.querySelector(".zine-controls-label");
154
+ i && (i.textContent = r);
155
+ }
156
+ typeof t.icon == "function" && e.querySelector("svg")?.replaceWith(i(r, t.icon(n)));
157
+ }
158
+ var x = class {
159
+ el;
160
+ #e;
161
+ #t;
162
+ #n;
163
+ #r;
164
+ #i = [];
165
+ constructor(e, t, n, r = d) {
166
+ this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.el = e.createElement("div"), this.el.className = "zine-controls-menu", this.el.setAttribute("role", "menu");
167
+ }
168
+ build(t) {
169
+ this.el.replaceChildren(), this.#i = [];
170
+ let n = this.#t();
171
+ for (let r of p(t, this.#r)) {
172
+ if (r === "|") continue;
173
+ let t = e(r);
174
+ if (t.isVisible && !t.isVisible(n)) continue;
175
+ let i;
176
+ i = t.render ? t.render(this.#t()) : y(this.#e, t, "zine-controls-btn", n, (e, t) => v(e, t, this.#t(), this.#n), !0), i.setAttribute("role", "menuitem"), this.el.appendChild(i), this.#i.push({
177
+ el: i,
178
+ def: t
179
+ });
180
+ }
181
+ }
182
+ refresh() {
183
+ let e = this.#t();
184
+ for (let { el: t, def: n } of this.#i) b(t, n, e, this.#e);
185
+ }
186
+ contains(e) {
187
+ return e !== null && this.el.contains(e);
188
+ }
189
+ focusFirst() {
190
+ this.el.querySelector("button")?.focus();
191
+ }
192
+ destroy() {
193
+ this.el.remove(), this.#i = [];
194
+ }
195
+ };
196
+ function S(t, n, r = d) {
197
+ return t.isVisible && !t.isVisible(n) ? !1 : p(t.children ?? [], r).some((t) => {
198
+ if (t === "|") return !1;
199
+ let r = e(t);
200
+ return !r.isVisible || r.isVisible(n);
201
+ });
202
+ }
203
+ //#endregion
107
204
  //#region src/controls/sidebar.ts
108
- var u = class {
205
+ var C = class {
109
206
  root;
110
207
  #e;
111
208
  #t = null;
@@ -147,7 +244,7 @@ var u = class {
147
244
  }
148
245
  #d(e, t) {
149
246
  let n = e.createElement("button");
150
- if (n.type = "button", n.className = "zine-panel-close", n.setAttribute("aria-label", "Close"), n.appendChild(r(e, a.close)), n.addEventListener("click", (e) => {
247
+ if (n.type = "button", n.className = "zine-panel-close", n.setAttribute("aria-label", "Close"), n.appendChild(i(e, o.close)), n.addEventListener("click", (e) => {
151
248
  e.stopPropagation(), t();
152
249
  }), this.#e.appendChild(n), this.#r = n, this.#t) {
153
250
  let n = e.createElement("div");
@@ -170,7 +267,7 @@ var u = class {
170
267
  }
171
268
  this.#t = null;
172
269
  }
173
- }, d = 78, f = class {
270
+ }, w = 78, T = class {
174
271
  root;
175
272
  #e;
176
273
  #t;
@@ -181,7 +278,7 @@ var u = class {
181
278
  constructor(e, t, n = {}) {
182
279
  this.#e = e;
183
280
  let r = t.ownerDocument;
184
- this.#t = r, this.#n = new u(r, t, {
281
+ this.#t = r, this.#n = new C(r, t, {
185
282
  className: "zine-thumbs",
186
283
  label: "Pages",
187
284
  width: 90,
@@ -235,7 +332,7 @@ var u = class {
235
332
  let r = n.width, i = n.height;
236
333
  if (!r || !i) return;
237
334
  let a = Math.min(2, globalThis.devicePixelRatio || 1), o = this.#t.createElement("canvas");
238
- o.width = Math.max(1, Math.round(d * a)), o.height = Math.max(1, Math.round(d * i / r * a)), o.className = "zine-thumbs-img";
335
+ o.width = Math.max(1, Math.round(w * a)), o.height = Math.max(1, Math.round(w * i / r * a)), o.className = "zine-thumbs-img";
239
336
  let s = o.getContext("2d");
240
337
  if (s) {
241
338
  try {
@@ -257,55 +354,58 @@ var u = class {
257
354
  for (let e of this.#a) e();
258
355
  this.#a = [], this.#i?.disconnect(), this.#i = null, this.#n.destroy();
259
356
  }
260
- }, p = 208, m = 12, h = class {
357
+ }, E = 208, D = 12, O = class {
261
358
  root;
262
359
  #e;
263
360
  #t;
264
361
  #n;
265
362
  #r = [];
266
363
  #i = [];
364
+ #a;
267
365
  constructor(e, t, n = {}) {
268
366
  this.#e = e;
269
367
  let r = t.ownerDocument;
270
- this.#t = r, this.#n = new u(r, t, {
368
+ this.#t = r, this.#a = n.onDismiss, this.#n = new C(r, t, {
271
369
  className: "zine-outline",
272
370
  label: "Outline",
273
- width: p,
371
+ width: E,
274
372
  onDismiss: n.onDismiss,
275
373
  rtl: e.getDirection() === "rtl",
276
374
  overlay: !0,
277
375
  pageBox: () => e.getPageBox()
278
- }), this.root = this.#n.root, this.#a("Loading…"), this.#o(), this.#i.push(e.on("pageChanged", () => this.#c()));
376
+ }), this.root = this.#n.root, this.#o("Loading…"), this.#s(), this.#i.push(e.on("pageChanged", () => this.#l()));
279
377
  }
280
- #a(e) {
378
+ #o(e) {
281
379
  let t = this.#t.createElement("div");
282
380
  t.className = "zine-panel-note", t.textContent = e, this.#n.root.replaceChildren(t);
283
381
  }
284
- async #o() {
382
+ async #s() {
285
383
  let e = await this.#e.getOutline();
286
384
  if (this.#n.root.isConnected) {
287
385
  if (e.length === 0) {
288
- this.#a("This document has no outline.");
386
+ this.#o("This document has no outline.");
289
387
  return;
290
388
  }
291
- this.#n.root.replaceChildren(), this.#s(e, 0), this.#c();
389
+ this.#n.root.replaceChildren(), this.#c(e, 0), this.#l();
292
390
  }
293
391
  }
294
- #s(e, t) {
392
+ #c(e, t) {
295
393
  for (let n of e) {
296
394
  let e = this.#t.createElement("button");
297
- if (e.type = "button", e.className = "zine-outline-row", e.setAttribute("role", "option"), e.style.paddingLeft = `${8 + t * m}px`, e.textContent = n.title, e.title = n.title, n.page === null) e.disabled = !0;
395
+ if (e.type = "button", e.className = "zine-outline-row", e.setAttribute("role", "option"), e.style.paddingLeft = `${8 + t * D}px`, e.textContent = n.title, e.title = n.title, n.page === null) e.disabled = !0;
298
396
  else {
299
397
  let t = n.page;
300
- e.setAttribute("aria-label", `${n.title}, page ${t + 1}`), e.addEventListener("click", () => this.#e.flipTo(t)), this.#r.push({
398
+ e.setAttribute("aria-label", `${n.title}, page ${t + 1}`), e.addEventListener("click", () => {
399
+ this.#e.flipTo(t), this.#a?.();
400
+ }), this.#r.push({
301
401
  el: e,
302
402
  page: t
303
403
  });
304
404
  }
305
- this.#n.root.appendChild(e), n.children.length > 0 && this.#s(n.children, t + 1);
405
+ this.#n.root.appendChild(e), n.children.length > 0 && this.#c(n.children, t + 1);
306
406
  }
307
407
  }
308
- #c() {
408
+ #l() {
309
409
  let e = this.#e.getPage(), t = null, n = -1;
310
410
  for (let { el: r, page: i } of this.#r) r.classList.remove("zine-panel-active"), r.removeAttribute("aria-selected"), i <= e && i >= n && (t = r, n = i);
311
411
  t && (t.classList.add("zine-panel-active"), t.setAttribute("aria-selected", "true"), t.scrollIntoView?.({ block: "nearest" }));
@@ -314,7 +414,7 @@ var u = class {
314
414
  for (let e of this.#i) e();
315
415
  this.#i = [], this.#n.destroy();
316
416
  }
317
- }, g = 208, _ = 180, v = 2, y = class {
417
+ }, k = 208, A = 180, j = 2, M = class {
318
418
  root;
319
419
  #e;
320
420
  #t;
@@ -323,54 +423,67 @@ var u = class {
323
423
  #i;
324
424
  #a = 0;
325
425
  #o = null;
426
+ #s;
427
+ #c = [];
326
428
  constructor(e, t, n = {}) {
327
429
  this.#e = e;
328
430
  let r = t.ownerDocument;
329
- this.#t = r, this.#n = new u(r, t, {
431
+ this.#t = r, this.#s = n.onDismiss, this.#n = new C(r, t, {
330
432
  className: "zine-search",
331
433
  label: "Search results",
332
- width: g,
434
+ width: k,
333
435
  onDismiss: n.onDismiss,
334
436
  rtl: e.getDirection() === "rtl",
335
437
  overlay: !0,
336
438
  pageBox: () => e.getPageBox()
337
439
  }), this.root = this.#n.root, this.#r = r.createElement("input"), this.#r.type = "search", this.#r.className = "zine-search-input", this.#r.placeholder = "Search…", this.#r.setAttribute("aria-label", "Search the document"), this.#r.addEventListener("input", () => {
338
- this.#o && clearTimeout(this.#o), this.#o = setTimeout(() => void this.#c(), _);
440
+ this.#o && clearTimeout(this.#o), this.#o = setTimeout(() => void this.#u(), A);
339
441
  }), this.#r.addEventListener("keydown", (e) => {
340
- e.key === "Enter" && (this.#o && clearTimeout(this.#o), this.#c());
341
- }), this.#i = r.createElement("div"), this.#i.className = "zine-search-hits", this.#n.root.append(this.#r, this.#i), this.#r.focus();
442
+ e.key === "Enter" && (this.#o && clearTimeout(this.#o), this.#u());
443
+ }), this.#i = r.createElement("div"), this.#i.className = "zine-search-hits", this.#n.root.append(this.#r, this.#i);
444
+ let i = n.state;
445
+ i && i.query && (this.#r.value = i.query, this.#a++, this.#d(i.query, i.results)), this.#r.focus();
446
+ }
447
+ getState() {
448
+ return {
449
+ query: this.#r.value,
450
+ results: this.#c
451
+ };
342
452
  }
343
- #s(e) {
453
+ #l(e) {
344
454
  let t = this.#t.createElement("div");
345
455
  t.className = "zine-panel-note", t.textContent = e, this.#i.replaceChildren(t);
346
456
  }
347
- async #c() {
457
+ async #u() {
348
458
  let e = this.#r.value.trim(), t = ++this.#a;
349
- if (e.length < v) {
350
- this.#i.replaceChildren();
459
+ if (e.length < j) {
460
+ this.#c = [], this.#i.replaceChildren();
351
461
  return;
352
462
  }
353
- this.#s("Searching…");
463
+ this.#l("Searching…");
354
464
  let n = await this.#e.search(e);
355
- if (!(t !== this.#a || !this.#n.root.isConnected)) {
356
- if (n.length === 0) {
357
- this.#s(`No matches for “${e}”`);
358
- return;
359
- }
360
- this.#i.replaceChildren(...n.map((e) => {
361
- let t = this.#t.createElement("button");
362
- t.type = "button", t.className = "zine-search-hit", t.setAttribute("role", "option"), t.setAttribute("aria-label", `Page ${e.page + 1}: ${e.excerpt}`);
363
- let n = this.#t.createElement("span");
364
- n.className = "zine-search-page", n.textContent = `Page ${e.page + 1}`;
365
- let r = this.#t.createElement("small");
366
- return r.textContent = e.excerpt, t.append(n, r), t.addEventListener("click", () => this.#e.flipTo(e.page)), t;
367
- }));
465
+ t !== this.#a || !this.#n.root.isConnected || this.#d(e, n);
466
+ }
467
+ #d(e, t) {
468
+ if (this.#c = t, t.length === 0) {
469
+ this.#l(`No matches for “${e}”`);
470
+ return;
368
471
  }
472
+ this.#i.replaceChildren(...t.map((e) => {
473
+ let t = this.#t.createElement("button");
474
+ t.type = "button", t.className = "zine-search-hit", t.setAttribute("role", "option"), t.setAttribute("aria-label", `Page ${e.page + 1}: ${e.excerpt}`);
475
+ let n = this.#t.createElement("span");
476
+ n.className = "zine-search-page", n.textContent = `Page ${e.page + 1}`;
477
+ let r = this.#t.createElement("small");
478
+ return r.textContent = e.excerpt, t.append(n, r), t.addEventListener("click", () => {
479
+ this.#e.flipTo(e.page), this.#s?.();
480
+ }), t;
481
+ }));
369
482
  }
370
483
  destroy() {
371
484
  this.#o && clearTimeout(this.#o), this.#o = null, this.#a++, this.#n.destroy();
372
485
  }
373
- }, b = class {
486
+ }, N = class {
374
487
  #e;
375
488
  #t;
376
489
  #n;
@@ -379,14 +492,14 @@ var u = class {
379
492
  #a = [];
380
493
  constructor(e, t, n = "auto", r = null) {
381
494
  this.#e = e, this.#i = r;
382
- let i = t.ownerDocument, s = e.getDirection() === "rtl";
383
- if (this.#t = this.#o(i, s ? a.next : a.prev, "Previous page", () => e.flipPrev()), this.#n = this.#o(i, s ? a.prev : a.next, "Next page", () => e.flipNext()), this.#s(i, t), this.#r) o(this.#r, n);
384
- else for (let e of [this.#t, this.#n]) o(e, n);
495
+ let i = t.ownerDocument, a = e.getDirection() === "rtl";
496
+ if (this.#t = this.#o(i, a ? o.next : o.prev, "Previous page", () => e.flipPrev()), this.#n = this.#o(i, a ? o.prev : o.next, "Next page", () => e.flipNext()), this.#s(i, t), this.#r) s(this.#r, n);
497
+ else for (let e of [this.#t, this.#n]) s(e, n);
385
498
  this.#a.push(e.on("pageChanged", ({ page: e }) => this.#c(e))), this.#a.push(e.on("flipEnd", () => this.#c())), this.#c();
386
499
  }
387
- #o(e, t, n, i) {
500
+ #o(e, t, n, r) {
388
501
  let a = e.createElement("button");
389
- a.type = "button", a.className = "zine-arrow", a.title = n, a.setAttribute("aria-label", n), a.appendChild(r(e, t)), a.addEventListener("click", i);
502
+ a.type = "button", a.className = "zine-arrow", a.title = n, a.setAttribute("aria-label", n), a.appendChild(i(e, t)), a.addEventListener("click", r);
390
503
  for (let e of [
391
504
  "pointerdown",
392
505
  "pointerup",
@@ -427,11 +540,11 @@ var u = class {
427
540
  }
428
541
  this.#r = null;
429
542
  }
430
- }, x = {
431
- thumbnails: f,
432
- outline: h,
433
- search: y
434
- }, S = [
543
+ }, P = {
544
+ thumbnails: T,
545
+ outline: O,
546
+ search: M
547
+ }, F = [
435
548
  "pointerdown",
436
549
  "pointerup",
437
550
  "pointermove",
@@ -439,7 +552,13 @@ var u = class {
439
552
  "dblclick",
440
553
  "wheel",
441
554
  "keydown"
442
- ], C = class {
555
+ ];
556
+ function I(e) {
557
+ let t = [];
558
+ for (let n of e) n === "|" && (t.length === 0 || t[t.length - 1] === "|") || t.push(n);
559
+ return t[t.length - 1] === "|" && t.pop(), t;
560
+ }
561
+ var L = class {
443
562
  #e;
444
563
  #t;
445
564
  #n;
@@ -454,33 +573,35 @@ var u = class {
454
573
  #d = null;
455
574
  #f = null;
456
575
  #p = null;
457
- #m;
576
+ #m = null;
458
577
  #h;
459
- constructor(e, t, n) {
460
- this.#e = e, this.#l = t;
461
- let r = t.ownerDocument;
462
- this.#t = r, i(r), this.#m = n.colorScheme ?? "auto";
463
- let a = n.position ?? "bottom";
464
- this.#h = a;
465
- let s = n.docked ?? !0;
466
- this.#n = r.createElement("div"), this.#n.className = [
578
+ #g;
579
+ #_;
580
+ constructor(e, t, n, r = /* @__PURE__ */ new Set()) {
581
+ this.#e = e, this.#l = t, this.#_ = r;
582
+ let i = t.ownerDocument;
583
+ this.#t = i, a(i), this.#h = n.colorScheme ?? "auto";
584
+ let o = n.position ?? "bottom";
585
+ this.#g = o;
586
+ let c = n.docked ?? !0;
587
+ this.#n = i.createElement("div"), this.#n.className = [
467
588
  "zine-controls",
468
- `zine-controls-${a}`,
469
- s ? "zine-controls-docked" : "zine-controls-floating",
589
+ `zine-controls-${o}`,
590
+ c ? "zine-controls-docked" : "zine-controls-floating",
470
591
  n.className
471
- ].filter(Boolean).join(" "), this.#n.setAttribute("role", "toolbar"), this.#n.setAttribute("aria-label", "Flipbook controls"), o(this.#n, this.#m), this.#r = r.createElement("div"), this.#r.className = "zine-controls-bar", this.#n.appendChild(this.#r), this.#n.addEventListener("keydown", (e) => this.#O(e));
472
- for (let e of S) this.#n.addEventListener(e, (e) => this.#_(e));
473
- this.#g(t, a, s);
474
- let c = () => this.#k();
475
- this.#o.push(e.on("pageChanged", c)), this.#o.push(e.on("zoomChanged", c)), this.#o.push(e.on("flipEnd", c));
476
- let l = (e) => {
592
+ ].filter(Boolean).join(" "), this.#n.setAttribute("role", "toolbar"), this.#n.setAttribute("aria-label", "Flipbook controls"), s(this.#n, this.#h), this.#r = i.createElement("div"), this.#r.className = "zine-controls-bar", this.#n.appendChild(this.#r), this.#n.addEventListener("keydown", (e) => this.#E(e));
593
+ for (let e of F) this.#n.addEventListener(e, (e) => this.#y(e));
594
+ this.#v(t, o, c);
595
+ let l = () => this.#D();
596
+ this.#o.push(e.on("pageChanged", l)), this.#o.push(e.on("zoomChanged", l)), this.#o.push(e.on("flipEnd", l));
597
+ let u = (e) => {
477
598
  if (!this.#a) return;
478
599
  let t = e.target;
479
- this.#a.el.contains(t) || this.#a.trigger.contains(t) || this.#D();
600
+ this.#a.menu.contains(t) || this.#a.trigger.contains(t) || this.#T();
480
601
  };
481
- r.addEventListener("pointerdown", l, !0), this.#o.push(() => r.removeEventListener("pointerdown", l, !0));
602
+ i.addEventListener("pointerdown", u, !0), this.#o.push(() => i.removeEventListener("pointerdown", u, !0));
482
603
  }
483
- #g(e, t, n) {
604
+ #v(e, t, n) {
484
605
  if (!n) {
485
606
  e.appendChild(this.#n);
486
607
  return;
@@ -494,106 +615,76 @@ var u = class {
494
615
  i.className = `zine-controls-wrap zine-controls-wrap-${t}`, r.insertBefore(i, e), i.appendChild(e), t === "top" || t === "left" ? i.insertBefore(this.#n, e) : i.appendChild(this.#n), this.#c = i;
495
616
  }
496
617
  mount(e) {
497
- this.#y(e.items ?? n);
618
+ this.#x(e.items ?? r);
498
619
  let t = e.arrows ?? !0;
499
- t !== !1 && (this.#p = new b(this.#e, this.#l, this.#m, t === !0 ? null : t)), this.#k(), this.#M();
620
+ t !== !1 && (this.#m = new N(this.#e, this.#l, this.#h, t === !0 ? null : t)), this.#D(), this.#O();
500
621
  }
501
622
  destroy() {
502
623
  for (let e of this.#o) e();
503
- this.#o = [], this.#D(), this.#u?.destroy(), this.#u = null, this.#d = null, this.#n.remove();
624
+ this.#o = [], this.#T(), this.#u?.destroy(), this.#u = null, this.#d = null, this.#n.remove();
504
625
  let e = this.#c;
505
- e?.parentNode && (e.parentNode.insertBefore(e.firstChild, e), e.remove()), this.#c = null, this.#p?.destroy(), this.#p = null;
626
+ e?.parentNode && (e.parentNode.insertBefore(e.firstChild, e), e.remove()), this.#c = null, this.#m?.destroy(), this.#m = null;
506
627
  }
507
- #_(e) {
628
+ #y(e) {
508
629
  e.stopPropagation();
509
630
  }
510
- #v(e = () => this.#D()) {
631
+ #b(e = () => this.#T()) {
511
632
  return {
512
633
  zine: this.#e,
513
634
  close: e,
514
- colorScheme: this.#m
635
+ colorScheme: this.#h
515
636
  };
516
637
  }
517
- #y(t) {
518
- for (let n of t) {
638
+ #x(t) {
639
+ for (let n of I(p(t, this.#_))) {
519
640
  if (n === "|") {
520
641
  let e = this.#t.createElement("div");
521
642
  e.className = "zine-controls-sep", this.#r.appendChild(e);
522
643
  continue;
523
644
  }
524
645
  let t = e(n), r;
525
- t.render ? (r = t.render(this.#v()), this.#i.push({
646
+ r = t.render ? t.render(this.#b()) : y(this.#t, t, "zine-controls-btn", this.#b(), (e, t) => this.#S(e, t)), this.#i.push({
526
647
  el: r,
527
648
  def: t
528
- })) : r = this.#S(t, "zine-controls-btn"), this.#r.appendChild(r);
649
+ }), this.#r.appendChild(r);
529
650
  }
530
651
  }
531
- #b(e) {
532
- return typeof e.title == "function" ? e.title(this.#v()) : e.title;
533
- }
534
- #x(e) {
535
- return typeof e.icon == "function" ? e.icon(this.#v()) : e.icon;
536
- }
537
- #S(e, t, n = !1) {
538
- let i = this.#t.createElement("button"), a = this.#b(e), o = this.#x(e);
539
- if (i.type = "button", i.className = t, i.title = a, i.setAttribute("aria-label", a), o && i.appendChild(r(this.#t, o)), n || !o) {
540
- let e = this.#t.createElement("span");
541
- e.className = "zine-controls-label", e.textContent = a, i.appendChild(e);
542
- }
543
- return i.addEventListener("click", () => this.#C(e, i)), this.#i.push({
544
- el: i,
545
- def: e
546
- }), i;
547
- }
548
- #C(e, t) {
549
- if (!e.isDisabled?.(this.#v())) {
652
+ #S(e, t) {
653
+ if (!e.isDisabled?.(this.#b())) {
550
654
  if (e.children) {
551
- this.#a?.trigger === t ? this.#D() : this.#w(e, t);
655
+ this.#a?.trigger === t ? this.#T() : this.#C(e, t);
552
656
  return;
553
657
  }
554
- e.action?.(this.#v()), this.#k();
555
- }
556
- }
557
- #w(t, n) {
558
- this.#D();
559
- let r = this.#t.createElement("div");
560
- r.className = "zine-controls-menu", r.setAttribute("role", "menu");
561
- let i = this.#v();
562
- for (let n of t.children ?? []) {
563
- if (n === "|") continue;
564
- let t = e(n);
565
- if (t.isVisible && !t.isVisible(i)) continue;
566
- let a;
567
- t.render ? (a = t.render(this.#v()), this.#i.push({
568
- el: a,
569
- def: t
570
- })) : a = this.#S(t, "zine-controls-btn", !0), a.setAttribute("role", "menuitem"), r.appendChild(a);
658
+ v(e, t, this.#b(), () => this.#D());
571
659
  }
572
- this.#T(r, n), this.#k(), r.querySelector("button")?.focus();
573
660
  }
574
- #T(e, t) {
575
- this.#n.appendChild(e), this.#a = {
576
- el: e,
661
+ #C(e, t) {
662
+ this.#T();
663
+ let n = new x(this.#t, () => this.#b(), () => this.#D(), this.#_);
664
+ n.build(e.children ?? []), this.#n.appendChild(n.el), this.#a = {
665
+ menu: n,
577
666
  trigger: t
578
- }, t.setAttribute("aria-expanded", "true"), this.#E(e, t);
667
+ }, t.setAttribute("aria-expanded", "true"), this.#w(n.el, t), n.refresh(), n.focusFirst();
579
668
  }
580
- #E(e, t) {
669
+ #w(e, t) {
581
670
  let n = this.#n.getBoundingClientRect(), r = t.getBoundingClientRect(), i = e.getBoundingClientRect();
582
671
  if (!n.width || !i.width) return;
583
672
  let a = r.left - n.left + r.width / 2 - i.width / 2;
584
673
  a = Math.max(4, Math.min(a, n.width - i.width - 4)), e.style.left = `${a}px`;
585
674
  let o = r.bottom - n.top + 6, s = r.top - n.top - i.height - 6;
586
- e.style.top = `${this.#h === "bottom" || s >= 0 ? s : o}px`;
675
+ e.style.top = `${this.#g === "bottom" || s >= 0 ? s : o}px`;
587
676
  }
588
- #D() {
677
+ #T() {
589
678
  if (!this.#a) return;
590
- let { el: e, trigger: t } = this.#a;
591
- this.#a = null, t.removeAttribute("aria-expanded"), this.#i = this.#i.filter((t) => !e.contains(t.el)), e.remove(), this.#t.activeElement && e.contains(this.#t.activeElement) && t.focus();
679
+ let { menu: e, trigger: t } = this.#a;
680
+ this.#a = null, t.removeAttribute("aria-expanded");
681
+ let n = this.#t.activeElement !== null && e.contains(this.#t.activeElement);
682
+ e.destroy(), n && t.focus();
592
683
  }
593
- #O(e) {
684
+ #E(e) {
594
685
  if (e.key === "Escape" && this.#a) {
595
686
  let { trigger: t } = this.#a;
596
- this.#D(), t.focus(), e.preventDefault();
687
+ this.#T(), t.focus(), e.preventDefault();
597
688
  return;
598
689
  }
599
690
  let t = [...this.#n.querySelectorAll("button, input")], n = t.indexOf(this.#t.activeElement);
@@ -601,32 +692,13 @@ var u = class {
601
692
  let r = e.key === "ArrowRight" || e.key === "ArrowDown" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowUp" ? -1 : 0;
602
693
  r !== 0 && (t[(n + r + t.length) % t.length]?.focus(), e.preventDefault());
603
694
  }
604
- #k() {
605
- let e = this.#v();
695
+ #D() {
696
+ let e = this.#b();
606
697
  for (let { el: t, def: n } of this.#i) {
607
- let i = n.children ? this.#j(n, e) : n.isVisible?.(e);
608
- i !== void 0 && (t.style.display = i ? "" : "none");
609
- let a = n.isDisabled?.(e) ?? !1;
610
- for (let e of this.#A(t)) e.disabled = a;
611
- if (this.#A(t).length || t.setAttribute("aria-disabled", String(a)), t.classList.toggle("zine-controls-off", a), n.isActive && t.setAttribute("aria-pressed", String(n.isActive(e))), typeof n.title == "function") {
612
- let r = n.title(e);
613
- t.title = r, t.setAttribute("aria-label", r);
614
- let i = t.querySelector(".zine-controls-label");
615
- i && (i.textContent = r);
616
- }
617
- typeof n.icon == "function" && t.querySelector("svg")?.replaceWith(r(this.#t, n.icon(e)));
698
+ let r = n.children ? S(n, e, this.#_) : n.isVisible?.(e);
699
+ b(t, n, e, this.#t, r);
618
700
  }
619
- this.#s && this.#t.activeElement !== this.#s && (this.#s.value = String(this.#e.getPage() + 1));
620
- }
621
- #A(e) {
622
- return e instanceof HTMLButtonElement || e instanceof HTMLInputElement ? [e] : [...e.querySelectorAll("button, input")];
623
- }
624
- #j(t, n) {
625
- return t.isVisible && !t.isVisible(n) ? !1 : (t.children ?? []).some((t) => {
626
- if (t === "|") return !1;
627
- let r = e(t);
628
- return !r.isVisible || r.isVisible(n);
629
- });
701
+ this.#a?.menu.refresh(), this.#s && this.#t.activeElement !== this.#s && (this.#s.value = String(this.#e.getPage() + 1));
630
702
  }
631
703
  makePageInput() {
632
704
  let e = this.#t.createElement("div");
@@ -651,29 +723,32 @@ var u = class {
651
723
  return this.#d;
652
724
  }
653
725
  hasOutline() {
654
- return this.#f === !0;
726
+ return this.#p === !0;
655
727
  }
656
- #M() {
657
- this.#f !== null || !this.#e.canOutline() || (this.#f = !1, this.#e.getOutline().then((e) => {
728
+ #O() {
729
+ this.#p !== null || !this.#e.canOutline() || (this.#p = !1, this.#e.getOutline().then((e) => {
658
730
  if (e.length === 0) return;
659
- this.#f = !0, this.#k();
731
+ this.#p = !0, this.#D();
660
732
  let t = this.#a;
661
733
  if (t) {
662
734
  let e = this.#i.find((e) => e.el === t.trigger)?.def;
663
- this.#D(), e && this.#w(e, t.trigger);
735
+ this.#T(), e && this.#C(e, t.trigger);
664
736
  }
665
737
  }));
666
738
  }
667
739
  togglePanel(e) {
668
740
  let t = this.#d;
669
- this.#u?.destroy(), this.#u = null, this.#d = null, t !== e && (this.#u = new x[e](this.#e, this.#l, { onDismiss: () => this.togglePanel(e) }), o(this.#u.root, this.#m), this.#d = e), this.#k();
741
+ this.#u instanceof M && (this.#f = this.#u.getState()), this.#u?.destroy(), this.#u = null, this.#d = null, t !== e && (this.#u = new P[e](this.#e, this.#l, {
742
+ onDismiss: () => this.togglePanel(e),
743
+ ...e === "search" && this.#f ? { state: this.#f } : {}
744
+ }), s(this.#u.root, this.#h), this.#d = e), this.#D();
670
745
  }
671
746
  };
672
- function w(e) {
673
- l(), t({
747
+ function R(e) {
748
+ u(), t({
674
749
  id: "thumbnails",
675
750
  title: () => e.openPanel() === "thumbnails" ? "Hide thumbnails" : "Show thumbnails",
676
- icon: a.thumbnails,
751
+ icon: o.thumbnails,
677
752
  isVisible: (e) => e.zine.isDocument(),
678
753
  isActive: () => e.openPanel() === "thumbnails",
679
754
  action: (t) => {
@@ -682,7 +757,7 @@ function w(e) {
682
757
  }), t({
683
758
  id: "outline",
684
759
  title: () => e.openPanel() === "outline" ? "Hide outline" : "Show outline",
685
- icon: a.outline,
760
+ icon: o.outline,
686
761
  isVisible: () => e.hasOutline(),
687
762
  isActive: () => e.openPanel() === "outline",
688
763
  action: (t) => {
@@ -695,19 +770,100 @@ function w(e) {
695
770
  }), t({
696
771
  id: "search",
697
772
  title: () => e.openPanel() === "search" ? "Hide search" : "Search",
698
- icon: a.search,
773
+ icon: o.search,
699
774
  isVisible: (e) => e.zine.canSearch(),
700
775
  isActive: () => e.openPanel() === "search",
701
776
  action: () => e.togglePanel("search")
702
777
  });
703
778
  }
704
779
  //#endregion
780
+ //#region src/controls/contextMenu.ts
781
+ var z = [
782
+ "zoomIn",
783
+ "zoomOut",
784
+ "|",
785
+ "prev",
786
+ "next",
787
+ "|",
788
+ "fullscreen",
789
+ "|",
790
+ "print",
791
+ "download",
792
+ "share"
793
+ ], B = /* @__PURE__ */ new Set([
794
+ "pageInput",
795
+ "thumbnails",
796
+ "outline",
797
+ "search"
798
+ ]), V = class {
799
+ #e;
800
+ #t;
801
+ #n;
802
+ #r;
803
+ #i;
804
+ #a;
805
+ #o = null;
806
+ #s = [];
807
+ constructor(e, t, r = {}, i = /* @__PURE__ */ new Set()) {
808
+ this.#e = e, this.#t = t, this.#a = i, this.#n = t.ownerDocument, u(), a(this.#n), this.#i = r.colorScheme ?? "auto", this.#r = (r.items ?? z).filter((e) => typeof e != "string" || !B.has(e) || n(e) !== void 0);
809
+ let o = (e) => {
810
+ e.preventDefault(), this.#l(e.clientX, e.clientY);
811
+ };
812
+ this.#t.addEventListener("contextmenu", o), this.#s.push(() => this.#t.removeEventListener("contextmenu", o));
813
+ let s = (e) => {
814
+ this.#o && !this.#o.contains(e.target) && this.#d();
815
+ }, c = (e) => {
816
+ e.key === "Escape" && this.#o && (this.#d(), e.preventDefault());
817
+ };
818
+ this.#n.addEventListener("pointerdown", s, !0), this.#n.addEventListener("keydown", c, !0), this.#s.push(() => this.#n.removeEventListener("pointerdown", s, !0)), this.#s.push(() => this.#n.removeEventListener("keydown", c, !0));
819
+ let l = () => this.#o?.refresh();
820
+ this.#s.push(e.on("pageChanged", l)), this.#s.push(e.on("zoomChanged", l)), this.#s.push(e.on("flipEnd", l));
821
+ }
822
+ #c() {
823
+ return {
824
+ zine: this.#e,
825
+ close: () => this.#d(),
826
+ colorScheme: this.#i
827
+ };
828
+ }
829
+ #l(e, t) {
830
+ this.#d();
831
+ let n = new x(this.#n, () => this.#c(), () => this.#o?.refresh(), this.#a);
832
+ if (n.build(this.#r), !n.el.querySelector("button")) return;
833
+ let r = this.#n.createElement("div");
834
+ r.className = "zine-context-layer", s(r, this.#i), r.appendChild(n.el), this.#t.appendChild(r), this.#o = n, n.refresh(), this.#u(n.el, e, t), n.focusFirst();
835
+ }
836
+ #u(e, t, n) {
837
+ let r = this.#t.getBoundingClientRect(), i = e.getBoundingClientRect();
838
+ if (!i.width) {
839
+ e.style.left = `${t}px`, e.style.top = `${n}px`;
840
+ return;
841
+ }
842
+ let a = Math.min(t, r.right - i.width - 4), o = Math.min(n, r.bottom - i.height - 4);
843
+ e.style.left = `${Math.max(r.left + 4, a)}px`, e.style.top = `${Math.max(r.top + 4, o)}px`;
844
+ }
845
+ #d() {
846
+ if (!this.#o) return;
847
+ let e = this.#o.el.parentElement, t = this.#n.activeElement !== null && this.#o.contains(this.#n.activeElement);
848
+ this.#o.destroy(), e?.remove(), this.#o = null, t && typeof this.#t.focus == "function" && this.#t.focus();
849
+ }
850
+ destroy() {
851
+ this.#d();
852
+ for (let e of this.#s) e();
853
+ this.#s = [];
854
+ }
855
+ };
856
+ //#endregion
705
857
  //#region src/controls/controls.ts
706
- function T(e, t, n = {}) {
707
- let r = new C(e, t, n);
708
- return w(r), r.mount(n), () => r.destroy();
858
+ function H(e, t, n = {}, r = /* @__PURE__ */ new Set()) {
859
+ let i = new L(e, t, n, r);
860
+ return R(i), i.mount(n), () => i.destroy();
861
+ }
862
+ function U(e, t, n = {}, r = /* @__PURE__ */ new Set()) {
863
+ let i = new V(e, t, n, r);
864
+ return () => i.destroy();
709
865
  }
710
866
  //#endregion
711
- export { T as mountControls };
867
+ export { U as mountContextMenu, H as mountControls };
712
868
 
713
- //# sourceMappingURL=controls-Djjk8Yac.js.map
869
+ //# sourceMappingURL=controls-CcOu_19g.js.map