@zinejs/core 0.8.2 → 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 (42) 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 +6 -0
  12. package/dist/{controls-DgEXR2zi.js → controls-CcOu_19g.js} +340 -196
  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 +617 -436
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.umd.js +26 -7
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/loading/loading.d.ts +1 -1
  21. package/dist/loading-DF88K9yJ.js +45 -0
  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-WXdscwp3.js → share-BrQa6aYm.js} +2 -2
  27. package/dist/{share-WXdscwp3.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-DgEXR2zi.js.map +0 -1
  38. package/dist/loading-BBK6YbSW.js +0 -45
  39. package/dist/loading-BBK6YbSW.js.map +0 -1
  40. package/dist/styles-B8fFoYm_.js +0 -40
  41. package/dist/styles-B8fFoYm_.js.map +0 -1
  42. 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-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,38 +36,38 @@ 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-WXdscwp3.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
72
  action: async (e) => {
73
73
  await e.zine.download(), e.close();
@@ -75,7 +75,7 @@ function l() {
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,7 +83,7 @@ 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
88
  action: async (e) => {
89
89
  await e.zine.print(), e.close();
@@ -91,7 +91,7 @@ function l() {
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,7 +354,7 @@ 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;
@@ -268,10 +365,10 @@ var u = class {
268
365
  constructor(e, t, n = {}) {
269
366
  this.#e = e;
270
367
  let r = t.ownerDocument;
271
- this.#t = r, this.#a = n.onDismiss, this.#n = new u(r, t, {
368
+ this.#t = r, this.#a = n.onDismiss, this.#n = new C(r, t, {
272
369
  className: "zine-outline",
273
370
  label: "Outline",
274
- width: p,
371
+ width: E,
275
372
  onDismiss: n.onDismiss,
276
373
  rtl: e.getDirection() === "rtl",
277
374
  overlay: !0,
@@ -295,7 +392,7 @@ var u = class {
295
392
  #c(e, t) {
296
393
  for (let n of e) {
297
394
  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;
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;
299
396
  else {
300
397
  let t = n.page;
301
398
  e.setAttribute("aria-label", `${n.title}, page ${t + 1}`), e.addEventListener("click", () => {
@@ -317,7 +414,7 @@ var u = class {
317
414
  for (let e of this.#i) e();
318
415
  this.#i = [], this.#n.destroy();
319
416
  }
320
- }, g = 208, _ = 180, v = 2, y = class {
417
+ }, k = 208, A = 180, j = 2, M = class {
321
418
  root;
322
419
  #e;
323
420
  #t;
@@ -327,56 +424,66 @@ var u = class {
327
424
  #a = 0;
328
425
  #o = null;
329
426
  #s;
427
+ #c = [];
330
428
  constructor(e, t, n = {}) {
331
429
  this.#e = e;
332
430
  let r = t.ownerDocument;
333
- this.#t = r, this.#s = n.onDismiss, this.#n = new u(r, t, {
431
+ this.#t = r, this.#s = n.onDismiss, this.#n = new C(r, t, {
334
432
  className: "zine-search",
335
433
  label: "Search results",
336
- width: g,
434
+ width: k,
337
435
  onDismiss: n.onDismiss,
338
436
  rtl: e.getDirection() === "rtl",
339
437
  overlay: !0,
340
438
  pageBox: () => e.getPageBox()
341
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", () => {
342
- this.#o && clearTimeout(this.#o), this.#o = setTimeout(() => void this.#l(), _);
440
+ this.#o && clearTimeout(this.#o), this.#o = setTimeout(() => void this.#u(), A);
343
441
  }), 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();
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();
346
446
  }
347
- #c(e) {
447
+ getState() {
448
+ return {
449
+ query: this.#r.value,
450
+ results: this.#c
451
+ };
452
+ }
453
+ #l(e) {
348
454
  let t = this.#t.createElement("div");
349
455
  t.className = "zine-panel-note", t.textContent = e, this.#i.replaceChildren(t);
350
456
  }
351
- async #l() {
457
+ async #u() {
352
458
  let e = this.#r.value.trim(), t = ++this.#a;
353
- if (e.length < v) {
354
- this.#i.replaceChildren();
459
+ if (e.length < j) {
460
+ this.#c = [], this.#i.replaceChildren();
355
461
  return;
356
462
  }
357
- this.#c("Searching…");
463
+ this.#l("Searching…");
358
464
  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
- }));
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;
374
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
+ }));
375
482
  }
376
483
  destroy() {
377
484
  this.#o && clearTimeout(this.#o), this.#o = null, this.#a++, this.#n.destroy();
378
485
  }
379
- }, b = class {
486
+ }, N = class {
380
487
  #e;
381
488
  #t;
382
489
  #n;
@@ -385,14 +492,14 @@ var u = class {
385
492
  #a = [];
386
493
  constructor(e, t, n = "auto", r = null) {
387
494
  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);
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);
391
498
  this.#a.push(e.on("pageChanged", ({ page: e }) => this.#c(e))), this.#a.push(e.on("flipEnd", () => this.#c())), this.#c();
392
499
  }
393
- #o(e, t, n, i) {
500
+ #o(e, t, n, r) {
394
501
  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);
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);
396
503
  for (let e of [
397
504
  "pointerdown",
398
505
  "pointerup",
@@ -433,11 +540,11 @@ var u = class {
433
540
  }
434
541
  this.#r = null;
435
542
  }
436
- }, x = {
437
- thumbnails: f,
438
- outline: h,
439
- search: y
440
- }, S = [
543
+ }, P = {
544
+ thumbnails: T,
545
+ outline: O,
546
+ search: M
547
+ }, F = [
441
548
  "pointerdown",
442
549
  "pointerup",
443
550
  "pointermove",
@@ -445,7 +552,13 @@ var u = class {
445
552
  "dblclick",
446
553
  "wheel",
447
554
  "keydown"
448
- ], 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 {
449
562
  #e;
450
563
  #t;
451
564
  #n;
@@ -460,33 +573,35 @@ var u = class {
460
573
  #d = null;
461
574
  #f = null;
462
575
  #p = null;
463
- #m;
576
+ #m = null;
464
577
  #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 = [
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 = [
473
588
  "zine-controls",
474
- `zine-controls-${a}`,
475
- s ? "zine-controls-docked" : "zine-controls-floating",
589
+ `zine-controls-${o}`,
590
+ c ? "zine-controls-docked" : "zine-controls-floating",
476
591
  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) => {
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) => {
483
598
  if (!this.#a) return;
484
599
  let t = e.target;
485
- this.#a.el.contains(t) || this.#a.trigger.contains(t) || this.#O();
600
+ this.#a.menu.contains(t) || this.#a.trigger.contains(t) || this.#T();
486
601
  };
487
- 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));
488
603
  }
489
- #g(e, t, n) {
604
+ #v(e, t, n) {
490
605
  if (!n) {
491
606
  e.appendChild(this.#n);
492
607
  return;
@@ -500,112 +615,76 @@ var u = class {
500
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;
501
616
  }
502
617
  mount(e) {
503
- this.#y(e.items ?? n);
618
+ this.#x(e.items ?? r);
504
619
  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();
620
+ t !== !1 && (this.#m = new N(this.#e, this.#l, this.#h, t === !0 ? null : t)), this.#D(), this.#O();
506
621
  }
507
622
  destroy() {
508
623
  for (let e of this.#o) e();
509
- this.#o = [], this.#O(), 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();
510
625
  let e = this.#c;
511
- 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;
512
627
  }
513
- #_(e) {
628
+ #y(e) {
514
629
  e.stopPropagation();
515
630
  }
516
- #v(e = () => this.#O()) {
631
+ #b(e = () => this.#T()) {
517
632
  return {
518
633
  zine: this.#e,
519
634
  close: e,
520
- colorScheme: this.#m
635
+ colorScheme: this.#h
521
636
  };
522
637
  }
523
- #y(t) {
524
- for (let n of t) {
638
+ #x(t) {
639
+ for (let n of I(p(t, this.#_))) {
525
640
  if (n === "|") {
526
641
  let e = this.#t.createElement("div");
527
642
  e.className = "zine-controls-sep", this.#r.appendChild(e);
528
643
  continue;
529
644
  }
530
645
  let t = e(n), r;
531
- 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({
532
647
  el: r,
533
648
  def: t
534
- })) : r = this.#S(t, "zine-controls-btn"), this.#r.appendChild(r);
649
+ }), this.#r.appendChild(r);
535
650
  }
536
651
  }
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);
652
+ #S(e, t) {
653
+ if (!e.isDisabled?.(this.#b())) {
654
+ if (e.children) {
655
+ this.#a?.trigger === t ? this.#T() : this.#C(e, t);
656
+ return;
657
+ }
658
+ v(e, t, this.#b(), () => this.#D());
548
659
  }
549
- return i.addEventListener("click", () => this.#C(e, i)), this.#i.push({
550
- el: i,
551
- def: e
552
- }), i;
553
660
  }
554
661
  #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,
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,
589
666
  trigger: t
590
- }, t.setAttribute("aria-expanded", "true"), this.#D(e, t);
667
+ }, t.setAttribute("aria-expanded", "true"), this.#w(n.el, t), n.refresh(), n.focusFirst();
591
668
  }
592
- #D(e, t) {
669
+ #w(e, t) {
593
670
  let n = this.#n.getBoundingClientRect(), r = t.getBoundingClientRect(), i = e.getBoundingClientRect();
594
671
  if (!n.width || !i.width) return;
595
672
  let a = r.left - n.left + r.width / 2 - i.width / 2;
596
673
  a = Math.max(4, Math.min(a, n.width - i.width - 4)), e.style.left = `${a}px`;
597
674
  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`;
675
+ e.style.top = `${this.#g === "bottom" || s >= 0 ? s : o}px`;
599
676
  }
600
- #O() {
677
+ #T() {
601
678
  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();
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();
604
683
  }
605
- #k(e) {
684
+ #E(e) {
606
685
  if (e.key === "Escape" && this.#a) {
607
686
  let { trigger: t } = this.#a;
608
- this.#O(), t.focus(), e.preventDefault();
687
+ this.#T(), t.focus(), e.preventDefault();
609
688
  return;
610
689
  }
611
690
  let t = [...this.#n.querySelectorAll("button, input")], n = t.indexOf(this.#t.activeElement);
@@ -613,32 +692,13 @@ var u = class {
613
692
  let r = e.key === "ArrowRight" || e.key === "ArrowDown" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowUp" ? -1 : 0;
614
693
  r !== 0 && (t[(n + r + t.length) % t.length]?.focus(), e.preventDefault());
615
694
  }
616
- #A() {
617
- let e = this.#v();
695
+ #D() {
696
+ let e = this.#b();
618
697
  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)));
698
+ let r = n.children ? S(n, e, this.#_) : n.isVisible?.(e);
699
+ b(t, n, e, this.#t, r);
630
700
  }
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
- });
701
+ this.#a?.menu.refresh(), this.#s && this.#t.activeElement !== this.#s && (this.#s.value = String(this.#e.getPage() + 1));
642
702
  }
643
703
  makePageInput() {
644
704
  let e = this.#t.createElement("div");
@@ -663,29 +723,32 @@ var u = class {
663
723
  return this.#d;
664
724
  }
665
725
  hasOutline() {
666
- return this.#f === !0;
726
+ return this.#p === !0;
667
727
  }
668
- #N() {
669
- 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) => {
670
730
  if (e.length === 0) return;
671
- this.#f = !0, this.#A();
731
+ this.#p = !0, this.#D();
672
732
  let t = this.#a;
673
733
  if (t) {
674
734
  let e = this.#i.find((e) => e.el === t.trigger)?.def;
675
- this.#O(), e && this.#T(e, t.trigger);
735
+ this.#T(), e && this.#C(e, t.trigger);
676
736
  }
677
737
  }));
678
738
  }
679
739
  togglePanel(e) {
680
740
  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();
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();
682
745
  }
683
746
  };
684
- function w(e) {
685
- l(), t({
747
+ function R(e) {
748
+ u(), t({
686
749
  id: "thumbnails",
687
750
  title: () => e.openPanel() === "thumbnails" ? "Hide thumbnails" : "Show thumbnails",
688
- icon: a.thumbnails,
751
+ icon: o.thumbnails,
689
752
  isVisible: (e) => e.zine.isDocument(),
690
753
  isActive: () => e.openPanel() === "thumbnails",
691
754
  action: (t) => {
@@ -694,7 +757,7 @@ function w(e) {
694
757
  }), t({
695
758
  id: "outline",
696
759
  title: () => e.openPanel() === "outline" ? "Hide outline" : "Show outline",
697
- icon: a.outline,
760
+ icon: o.outline,
698
761
  isVisible: () => e.hasOutline(),
699
762
  isActive: () => e.openPanel() === "outline",
700
763
  action: (t) => {
@@ -707,19 +770,100 @@ function w(e) {
707
770
  }), t({
708
771
  id: "search",
709
772
  title: () => e.openPanel() === "search" ? "Hide search" : "Search",
710
- icon: a.search,
773
+ icon: o.search,
711
774
  isVisible: (e) => e.zine.canSearch(),
712
775
  isActive: () => e.openPanel() === "search",
713
776
  action: () => e.togglePanel("search")
714
777
  });
715
778
  }
716
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
717
857
  //#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();
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();
721
865
  }
722
866
  //#endregion
723
- export { T as mountControls };
867
+ export { U as mountContextMenu, H as mountControls };
724
868
 
725
- //# sourceMappingURL=controls-DgEXR2zi.js.map
869
+ //# sourceMappingURL=controls-CcOu_19g.js.map