@zinejs/core 0.8.2 → 0.9.1

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