@zinejs/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,828 @@
1
+ //#region src/engine/spread.ts
2
+ function e(e, t = {}) {
3
+ let { direction: n = "ltr", cover: r = !1, singlePage: i = !1 } = t;
4
+ if (e <= 0) return [];
5
+ let a = (t) => t >= 0 && t < e ? t : null, o = [];
6
+ if (i) for (let t = 0; t < e; t++) o.push({
7
+ left: null,
8
+ right: t
9
+ });
10
+ else if (r) {
11
+ o.push({
12
+ left: null,
13
+ right: 0
14
+ });
15
+ for (let t = 1; t < e; t += 2) o.push({
16
+ left: a(t),
17
+ right: a(t + 1)
18
+ });
19
+ } else for (let t = 0; t < e; t += 2) o.push({
20
+ left: a(t),
21
+ right: a(t + 1)
22
+ });
23
+ return n === "rtl" ? o.map((e) => ({
24
+ left: e.right,
25
+ right: e.left
26
+ })) : o;
27
+ }
28
+ function t(e, t) {
29
+ return e < t;
30
+ }
31
+ //#endregion
32
+ //#region src/engine/virtualizer.ts
33
+ function n(e, t, n) {
34
+ let r = [], i = Math.max(0, e - n), a = Math.min(t - 1, e + n);
35
+ for (let e = i; e <= a; e++) r.push(e);
36
+ return r;
37
+ }
38
+ var r = class {
39
+ #e;
40
+ #t = /* @__PURE__ */ new Set();
41
+ constructor(e = 2) {
42
+ this.#e = e;
43
+ }
44
+ get mounted() {
45
+ return [...this.#t].sort((e, t) => e - t);
46
+ }
47
+ update(e, t) {
48
+ let r = new Set(n(e, t, this.#e)), i = [...r].filter((e) => !this.#t.has(e)).sort((e, t) => e - t), a = [...this.#t].filter((e) => !r.has(e)).sort((e, t) => e - t);
49
+ for (let e of a) this.#t.delete(e);
50
+ for (let e of i) this.#t.add(e);
51
+ return {
52
+ toMount: i,
53
+ toEvict: a
54
+ };
55
+ }
56
+ }, i = class {
57
+ #e = /* @__PURE__ */ new Map();
58
+ on(e, t) {
59
+ let n = this.#e.get(e);
60
+ return n || (n = /* @__PURE__ */ new Set(), this.#e.set(e, n)), n.add(t), () => this.off(e, t);
61
+ }
62
+ off(e, t) {
63
+ this.#e.get(e)?.delete(t);
64
+ }
65
+ emit(e, ...t) {
66
+ let n = t[0], r = this.#e.get(e);
67
+ if (r) for (let e of [...r]) e(n);
68
+ }
69
+ clear() {
70
+ this.#e.clear();
71
+ }
72
+ }, a = {
73
+ idle: {
74
+ grab: "dragging",
75
+ panStart: "zoomed-panning",
76
+ flip: "animating"
77
+ },
78
+ dragging: { release: "animating" },
79
+ animating: { settle: "idle" },
80
+ "zoomed-panning": { panEnd: "idle" }
81
+ };
82
+ function o(e, t) {
83
+ return a[e][t] ?? null;
84
+ }
85
+ var s = class {
86
+ #e;
87
+ constructor(e = "idle") {
88
+ this.#e = e;
89
+ }
90
+ get state() {
91
+ return this.#e;
92
+ }
93
+ send(e) {
94
+ let t = o(this.#e, e);
95
+ return t !== null && (this.#e = t), t;
96
+ }
97
+ }, c = .3, l = class {
98
+ #e;
99
+ #t = null;
100
+ #n = null;
101
+ #r = null;
102
+ #i = null;
103
+ constructor(e = {}) {
104
+ this.#e = e;
105
+ }
106
+ get active() {
107
+ return this.#t !== null;
108
+ }
109
+ down(e, t, n, r) {
110
+ if (this.#t !== null) return;
111
+ this.#t = e;
112
+ let i = {
113
+ x: t,
114
+ y: n,
115
+ t: r
116
+ };
117
+ this.#n = i, this.#r = i, this.#i = i, this.#e.onStart?.({
118
+ x: t,
119
+ y: n,
120
+ t: r
121
+ });
122
+ }
123
+ move(e, t, n, r) {
124
+ e !== this.#t || this.#n === null || (this.#r = this.#i, this.#i = {
125
+ x: t,
126
+ y: n,
127
+ t: r
128
+ }, this.#e.onMove?.({
129
+ x: t,
130
+ y: n,
131
+ dx: t - this.#n.x,
132
+ dy: n - this.#n.y
133
+ }));
134
+ }
135
+ up(e, t, n, r) {
136
+ this.#a(e, t, n, r, !1);
137
+ }
138
+ cancel(e, t, n, r) {
139
+ this.#a(e, t, n, r, !0);
140
+ }
141
+ #a(e, t, n, r, i) {
142
+ if (e !== this.#t || this.#n === null) return;
143
+ let a = this.#n, o = this.#i ?? a, s = this.#r ?? a, l = o.t - s.t, u = l > 0 ? (o.x - s.x) / l : 0, d = l > 0 ? (o.y - s.y) / l : 0, f = Math.hypot(u, d);
144
+ this.#o(), this.#e.onEnd?.({
145
+ x: t,
146
+ y: n,
147
+ dx: t - a.x,
148
+ dy: n - a.y,
149
+ dt: r - a.t,
150
+ vx: u,
151
+ vy: d,
152
+ swipe: !i && f > c,
153
+ canceled: i
154
+ });
155
+ }
156
+ #o() {
157
+ this.#t = null, this.#n = null, this.#r = null, this.#i = null;
158
+ }
159
+ };
160
+ function u(e, t) {
161
+ let { pointer: n, pinch: r } = t, i = (e) => {
162
+ let t = e;
163
+ n?.down(t.pointerId, t.clientX, t.clientY, t.timeStamp), r?.down(t.pointerId, t.clientX, t.clientY);
164
+ }, a = (e) => {
165
+ let t = e;
166
+ n?.move(t.pointerId, t.clientX, t.clientY, t.timeStamp), r?.move(t.pointerId, t.clientX, t.clientY);
167
+ }, o = (e) => {
168
+ let t = e;
169
+ n?.up(t.pointerId, t.clientX, t.clientY, t.timeStamp), r?.up(t.pointerId);
170
+ }, s = (e) => {
171
+ let t = e;
172
+ n?.cancel(t.pointerId, t.clientX, t.clientY, t.timeStamp), r?.cancel(t.pointerId);
173
+ };
174
+ return e.addEventListener("pointerdown", i), e.addEventListener("pointermove", a), e.addEventListener("pointerup", o), e.addEventListener("pointercancel", s), () => {
175
+ e.removeEventListener("pointerdown", i), e.removeEventListener("pointermove", a), e.removeEventListener("pointerup", o), e.removeEventListener("pointercancel", s);
176
+ };
177
+ }
178
+ function d(e, t) {
179
+ return Math.hypot(e.x - t.x, e.y - t.y);
180
+ }
181
+ var f = class {
182
+ #e;
183
+ #t = /* @__PURE__ */ new Map();
184
+ #n = 0;
185
+ #r = !1;
186
+ constructor(e = {}) {
187
+ this.#e = e;
188
+ }
189
+ get pinching() {
190
+ return this.#r;
191
+ }
192
+ down(e, t, n) {
193
+ if (!(this.#t.has(e) || this.#t.size >= 2) && (this.#t.set(e, {
194
+ x: t,
195
+ y: n
196
+ }), this.#t.size === 2)) {
197
+ let { a: e, b: t } = this.#a();
198
+ this.#n = d(e, t), this.#r = !0, this.#e.onPinchStart?.({
199
+ centerX: (e.x + t.x) / 2,
200
+ centerY: (e.y + t.y) / 2,
201
+ distance: this.#n
202
+ });
203
+ }
204
+ }
205
+ move(e, t, n) {
206
+ let r = this.#t.get(e);
207
+ if (!r || (r.x = t, r.y = n, !this.#r)) return;
208
+ let { a: i, b: a } = this.#a();
209
+ this.#e.onPinchMove?.({
210
+ centerX: (i.x + a.x) / 2,
211
+ centerY: (i.y + a.y) / 2,
212
+ scale: this.#n > 0 ? d(i, a) / this.#n : 1
213
+ });
214
+ }
215
+ up(e) {
216
+ this.#i(e);
217
+ }
218
+ cancel(e) {
219
+ this.#i(e);
220
+ }
221
+ #i(e) {
222
+ this.#t.delete(e) && this.#r && this.#t.size < 2 && (this.#r = !1, this.#n = 0, this.#e.onPinchEnd?.());
223
+ }
224
+ #a() {
225
+ let e = [...this.#t.values()], t = e[0], n = e[1];
226
+ if (!t || !n) throw Error("pinch requires two active pointers");
227
+ return {
228
+ a: t,
229
+ b: n
230
+ };
231
+ }
232
+ };
233
+ //#endregion
234
+ //#region src/geometry/hitTest.ts
235
+ function p(e, t, n) {
236
+ let { width: r, height: i } = t;
237
+ if (e.x < 0 || e.x > r || e.y < 0 || e.y > i) return "outside";
238
+ let a = e.x <= n || e.x >= r - n, o = e.y <= n || e.y >= i - n;
239
+ return a && o ? "corner" : "page";
240
+ }
241
+ //#endregion
242
+ //#region src/renderer/select.ts
243
+ var m = {
244
+ css: async () => new (await (import("./cssRenderer-BACNXO8M.js"))).CssRenderer(),
245
+ webgl2: async () => new (await (import("./webglRenderer-D-1UyC-B.js"))).WebglRenderer()
246
+ }, h = !0;
247
+ function g(e) {
248
+ return typeof e == "object" && !!e && !Array.isArray(e) && typeof e.mount == "function";
249
+ }
250
+ function _(e) {
251
+ return e.gpu && h ? ["webgl2", "css"] : ["css"];
252
+ }
253
+ function v() {
254
+ return { gpu: y() };
255
+ }
256
+ function y() {
257
+ try {
258
+ return !!document.createElement("canvas").getContext("webgl2");
259
+ } catch {
260
+ return !1;
261
+ }
262
+ }
263
+ async function b(e = "auto", t = v()) {
264
+ if (g(e)) return e;
265
+ let n = Array.isArray(e) ? e : e === "auto" ? _(t) : [e];
266
+ for (let e of n) {
267
+ if (e === "webgl2" && !t.gpu) continue;
268
+ let n = m[e];
269
+ if (n) return n();
270
+ }
271
+ throw n.length === 1 && n[0] === "webgl2" && !t.gpu ? Error("renderer: 'webgl2' was forced but this device has no WebGL2. Use 'css' or 'auto'.") : Error(`renderer: none of [${n.join(", ")}] could be loaded — use 'css' or 'auto'.`);
272
+ }
273
+ //#endregion
274
+ //#region src/zine.ts
275
+ var x = .25, S = .0015, C = 6, w = 250, T = class {
276
+ #e;
277
+ #t;
278
+ #n = new i();
279
+ #r = new r(2);
280
+ #i = new s();
281
+ #a;
282
+ #o;
283
+ #s;
284
+ #c;
285
+ #l;
286
+ #u;
287
+ #d;
288
+ #f = !1;
289
+ #p;
290
+ #m = [];
291
+ #h = 0;
292
+ #g = 0;
293
+ #_ = {
294
+ left: null,
295
+ right: null
296
+ };
297
+ #v;
298
+ #y;
299
+ #b;
300
+ #x;
301
+ #S;
302
+ #C = null;
303
+ #w = !1;
304
+ #T = 1;
305
+ #E = 0;
306
+ #D = 0;
307
+ #O = null;
308
+ #k = !1;
309
+ #A = !1;
310
+ #j = null;
311
+ #M = null;
312
+ #N = null;
313
+ #P = null;
314
+ #F = null;
315
+ #I = null;
316
+ #L = !1;
317
+ #R = 1;
318
+ #z = !1;
319
+ #B = null;
320
+ #V = null;
321
+ #H = null;
322
+ #U = null;
323
+ #W = null;
324
+ #G;
325
+ debug = { setFlipProgress: (e, t) => {
326
+ this.#O?.setFlipProgress(e, t);
327
+ } };
328
+ constructor(e, t) {
329
+ k(e, t), this.#e = e, t.width !== void 0 && (e.style.width = `${t.width}px`), t.height !== void 0 && (e.style.height = `${t.height}px`), this.#t = t.source;
330
+ let n = t.direction ?? "ltr", r = t.cover ?? !1;
331
+ this.#a = n, this.#o = r, this.#s = t.clickToFlip ?? "edge", this.#c = t.clickZoneSize ?? 64, this.#d = t.singlePageThreshold ?? 640, this.#p = t.startPage, typeof this.#t.open != "function" && this.#ke(), this.#v = t.flipDuration ?? 800, this.#y = t.zoom?.enabled ?? !0, this.#b = t.zoom?.wheel ?? !0;
332
+ let i = t.zoom?.doubleClick, a = i === !1 ? [] : [...i ?? [
333
+ 1,
334
+ 2,
335
+ 4
336
+ ]].sort((e, t) => e - t);
337
+ this.#x = a.length > 0 ? a : null, this.#S = t.zoom?.max ?? 4;
338
+ let o = this.#y && this.#x !== null, s = t.zoom?.doubleClickInFlipZone ?? this.#s === "half";
339
+ this.#l = this.#s !== "off" && o && s && t.clickFlipDelay !== 0, this.#u = this.#l ? t.clickFlipDelay ?? w : 0, this.#G = this.#fe(t.renderer ?? "auto");
340
+ }
341
+ get ready() {
342
+ return this.#G;
343
+ }
344
+ getPageCount() {
345
+ return this.#t.pageCount;
346
+ }
347
+ getPage() {
348
+ return this.#g;
349
+ }
350
+ flipNext() {
351
+ this.#q(this.#h + 1);
352
+ }
353
+ flipPrev() {
354
+ this.#q(this.#h - 1);
355
+ }
356
+ flipTo(e) {
357
+ let t = E(e, 0, Math.max(0, this.#t.pageCount - 1));
358
+ this.#q(this.#Oe(t));
359
+ }
360
+ getZoom() {
361
+ return this.#T;
362
+ }
363
+ setZoom(e, t) {
364
+ if (!this.#O || !this.#y) return;
365
+ let n = E(e, 1, this.#S), r = this.#O.measure(), i = t ?? {
366
+ x: r.containerWidth / 2,
367
+ y: r.containerHeight / 2
368
+ }, a = this.#T, o = n === 1 ? 0 : i.x - n / a * (i.x - this.#E), s = n === 1 ? 0 : i.y - n / a * (i.y - this.#D);
369
+ [o, s] = this.#K(o, s, n, r.containerWidth, r.containerHeight), this.#T = n, this.#E = o, this.#D = s, this.#O.setViewTransform(n, o, s), this.#n.emit("zoomChanged", { scale: n });
370
+ }
371
+ resetZoom() {
372
+ this.setZoom(1);
373
+ }
374
+ #K(e, t, n, r, i) {
375
+ return [E(e, r * (1 - n), 0), E(t, i * (1 - n), 0)];
376
+ }
377
+ on(e, t) {
378
+ return this.#n.on(e, t);
379
+ }
380
+ destroy() {
381
+ this.#A = !0, this.#j !== null && cancelAnimationFrame(this.#j), this.#ae(), this.#C?.disconnect(), this.#W?.(), this.#H?.(), this.#U?.(), this.#V?.(), this.#O?.destroy(), this.#O = null, this.#t.destroy(), this.#n.clear();
382
+ }
383
+ #q(e) {
384
+ if (e < 0 || e >= this.#m.length || e === this.#h || this.#i.send("flip") === null) return;
385
+ let t = e > this.#h ? "forward" : "backward", n = this.#Z(e);
386
+ this.#n.emit("flipStart", {
387
+ from: this.#g,
388
+ to: n
389
+ }), this.#J(e, t, n);
390
+ }
391
+ async #J(e, t, n) {
392
+ let r = this.#m[e], i = r ? await this.#Te(r) : {
393
+ left: null,
394
+ right: null
395
+ };
396
+ this.#O?.beginFlip(this.#_, i, t, { fill: this.#f }), this.#Y(0, 1, t, () => this.#X(e, n, i));
397
+ }
398
+ #Y(e, t, n, r) {
399
+ let i = this.#ye() * Math.abs(t - e);
400
+ if (i <= 0) {
401
+ this.#O?.setFlipProgress(t, n), r();
402
+ return;
403
+ }
404
+ let a = performance.now(), o = (s) => {
405
+ let c = Math.min(1, (s - a) / i);
406
+ this.#O?.setFlipProgress(e + (t - e) * D(c), n), c < 1 ? this.#j = requestAnimationFrame(o) : (this.#j = null, r());
407
+ };
408
+ this.#j = requestAnimationFrame(o);
409
+ }
410
+ #X(e, t, n) {
411
+ let r = this.#m[e];
412
+ this.#h = e, this.#g = t, this.#_ = n, r && this.#Se(r, n), this.#De(), this.#i.send("settle"), this.#ve(), this.#n.emit("pageChanged", { page: t }), this.#n.emit("flipEnd", { page: t });
413
+ }
414
+ #Z(e) {
415
+ let t = this.#m[e];
416
+ if (!t) return this.#g;
417
+ let n = [t.left, t.right].filter((e) => e !== null);
418
+ return n.length > 0 ? Math.min(...n) : this.#g;
419
+ }
420
+ #Q(e, t) {
421
+ if (this.#L || !this.#O || this.#i.state !== "idle") return;
422
+ if (this.#ae(), this.#T > 1) {
423
+ if (this.#i.send("panStart") === null) return;
424
+ this.#I = {
425
+ baseTx: this.#E,
426
+ baseTy: this.#D
427
+ };
428
+ return;
429
+ }
430
+ let n = this.#e.getBoundingClientRect(), r = {
431
+ x: e - n.left,
432
+ y: t - n.top
433
+ };
434
+ this.#P = r;
435
+ let { containerWidth: i, containerHeight: a } = this.#O.measure(), o = Math.min(i, a) * x;
436
+ if (p(r, {
437
+ width: i,
438
+ height: a
439
+ }, o) !== "corner") return;
440
+ let s = r.x > i / 2, c = this.#a === "rtl" ? !s : s, l = this.#h + (c ? 1 : -1);
441
+ l < 0 || l >= this.#m.length || (this.#N = {
442
+ direction: c ? "forward" : "backward",
443
+ targetIndex: l,
444
+ toPage: this.#Z(l),
445
+ width: i
446
+ });
447
+ }
448
+ #$() {
449
+ let e = this.#N;
450
+ e && (this.#N = null, this.#i.send("grab") !== null && (this.#M = {
451
+ direction: e.direction,
452
+ targetIndex: e.targetIndex,
453
+ toPage: e.toPage,
454
+ toContent: {
455
+ left: null,
456
+ right: null
457
+ },
458
+ width: e.width,
459
+ t: 0
460
+ }, this.#n.emit("flipStart", {
461
+ from: this.#g,
462
+ to: e.toPage
463
+ }), this.#ee(e.targetIndex, e.direction)));
464
+ }
465
+ async #ee(e, t) {
466
+ let n = this.#m[e], r = n ? await this.#Te(n) : {
467
+ left: null,
468
+ right: null
469
+ };
470
+ this.#M?.targetIndex === e && (this.#M.toContent = r, this.#O?.beginFlip(this.#_, r, t, { fill: this.#f }), this.#O?.setFlipProgress(this.#M.t, t));
471
+ }
472
+ #te(e, t) {
473
+ if (this.#L) return;
474
+ if (this.#I) {
475
+ if (!this.#O) return;
476
+ let n = this.#O.measure(), [r, i] = this.#K(this.#I.baseTx + e, this.#I.baseTy + t, this.#T, n.containerWidth, n.containerHeight);
477
+ this.#E = r, this.#D = i, this.#O.setViewTransform(this.#T, r, i);
478
+ return;
479
+ }
480
+ this.#N && Math.hypot(e, t) > C && this.#$();
481
+ let n = this.#M;
482
+ n && (n.t = E((n.direction === "forward" ? -e : e) / n.width, 0, 1), this.#O?.setFlipProgress(n.t, n.direction));
483
+ }
484
+ #ne(e) {
485
+ if (this.#L) return;
486
+ if (this.#I) {
487
+ this.#I = null, this.#i.send("panEnd");
488
+ return;
489
+ }
490
+ let t = this.#M;
491
+ if (!t) {
492
+ this.#N = null, this.#re(e);
493
+ return;
494
+ }
495
+ this.#M = null, this.#i.send("release");
496
+ let n = e.swipe && (t.direction === "forward" ? e.dx < 0 : e.dx > 0);
497
+ t.t >= .5 || n ? this.#Y(t.t, 1, t.direction, () => this.#X(t.targetIndex, t.toPage, t.toContent)) : this.#Y(t.t, 0, t.direction, () => this.#oe());
498
+ }
499
+ #re(e) {
500
+ if (this.#s === "off" || this.#T > 1 || !this.#P || Math.abs(e.dx) > C || Math.abs(e.dy) > C) return;
501
+ let t = this.#ie(this.#P);
502
+ if (!t) return;
503
+ let n = this.#h + (t === "forward" ? 1 : -1);
504
+ if (!(n < 0 || n >= this.#m.length)) {
505
+ if (this.#ae(), this.#u <= 0) {
506
+ this.#q(n);
507
+ return;
508
+ }
509
+ this.#F = setTimeout(() => {
510
+ this.#F = null, this.#q(n);
511
+ }, this.#u);
512
+ }
513
+ }
514
+ #ie(e) {
515
+ if (!this.#O) return null;
516
+ let { containerWidth: t } = this.#O.measure(), n;
517
+ if (n = this.#s === "half" ? e.x > t / 2 ? "right" : "left" : e.x <= this.#c ? "left" : e.x >= t - this.#c ? "right" : null, !n) return null;
518
+ let r = this.#a === "rtl" ? "left" : "right";
519
+ return n === r ? "forward" : "backward";
520
+ }
521
+ #ae() {
522
+ this.#F !== null && (clearTimeout(this.#F), this.#F = null);
523
+ }
524
+ #oe() {
525
+ let e = this.#m[this.#h];
526
+ e && this.#Se(e, this.#_), this.#i.send("settle"), this.#n.emit("flipEnd", { page: this.#g });
527
+ }
528
+ #se() {
529
+ if (this.#N = null, this.#ae(), this.#M) {
530
+ this.#M = null, this.#i.send("release"), this.#i.send("settle");
531
+ let e = this.#m[this.#h];
532
+ e && this.#Se(e, this.#_);
533
+ } else this.#I && (this.#I = null, this.#i.send("panEnd"));
534
+ this.#L = !0, this.#R = this.#T;
535
+ }
536
+ #ce(e, t, n) {
537
+ if (!this.#L) return;
538
+ let r = this.#e.getBoundingClientRect();
539
+ this.setZoom(this.#R * n, {
540
+ x: e - r.left,
541
+ y: t - r.top
542
+ });
543
+ }
544
+ #le() {
545
+ this.#L = !1;
546
+ }
547
+ #ue() {
548
+ let e = (e) => {
549
+ if (!this.#b || !this.#y || !(e.ctrlKey || e.metaKey)) return;
550
+ e.preventDefault();
551
+ let t = this.#e.getBoundingClientRect(), n = Math.exp(-e.deltaY * S);
552
+ this.setZoom(this.#T * n, {
553
+ x: e.clientX - t.left,
554
+ y: e.clientY - t.top
555
+ });
556
+ };
557
+ this.#e.addEventListener("wheel", e, { passive: !1 }), this.#H = () => this.#e.removeEventListener("wheel", e);
558
+ }
559
+ #de() {
560
+ let e = (e) => {
561
+ let t = this.#x;
562
+ if (!this.#y || t === null) return;
563
+ if (this.#T <= 1 && this.#s !== "off" && !this.#l) {
564
+ let t = this.#e.getBoundingClientRect(), n = {
565
+ x: e.clientX - t.left,
566
+ y: e.clientY - t.top
567
+ };
568
+ if (this.#ie(n) !== null) return;
569
+ }
570
+ this.#ae(), e.preventDefault();
571
+ let n = t.find((e) => e > this.#T + 1e-6) ?? t[0] ?? this.#T, r = this.#e.getBoundingClientRect();
572
+ this.setZoom(n, {
573
+ x: e.clientX - r.left,
574
+ y: e.clientY - r.top
575
+ });
576
+ };
577
+ this.#e.addEventListener("dblclick", e), this.#U = () => this.#e.removeEventListener("dblclick", e);
578
+ }
579
+ async #fe(e) {
580
+ let t = b(e);
581
+ typeof this.#t.open == "function" && (await this.#t.open(), this.#ke()), this.#t.prefetch([this.#g]);
582
+ let n = await t, r = await this.#pe(n);
583
+ this.#O = r, this.#be(r.measure().containerWidth);
584
+ let i = new l({
585
+ onStart: (e) => this.#Q(e.x, e.y),
586
+ onMove: (e) => this.#te(e.dx, e.dy),
587
+ onEnd: (e) => this.#ne(e)
588
+ }), a = new f({
589
+ onPinchStart: () => this.#se(),
590
+ onPinchMove: (e) => this.#ce(e.centerX, e.centerY, e.scale),
591
+ onPinchEnd: () => this.#le()
592
+ });
593
+ this.#V = u(this.#e, {
594
+ pointer: i,
595
+ pinch: a
596
+ }), this.#ue(), this.#de(), this.#he(), this.#W = this.#ge(), await this.#xe(), this.#Ce(), this.#De(), this.#ve(), this.#n.emit("ready");
597
+ }
598
+ async #pe(e) {
599
+ try {
600
+ return await e.mount(this.#e), e.onFatal?.(() => {
601
+ this.#me();
602
+ }), e;
603
+ } catch {
604
+ e.destroy();
605
+ let t = await b("css");
606
+ return await t.mount(this.#e), this.#k = !0, this.#n.emit("rendererFallback", {
607
+ from: "webgl2",
608
+ to: "css"
609
+ }), t;
610
+ }
611
+ }
612
+ async #me() {
613
+ if (this.#k || this.#A) return;
614
+ this.#k = !0, this.#O?.destroy(), this.#O = null;
615
+ let e = await b("css");
616
+ if (this.#A) {
617
+ e.destroy();
618
+ return;
619
+ }
620
+ await e.mount(this.#e), this.#O = e, this.#be(e.measure().containerWidth), await this.#xe(), this.#n.emit("rendererFallback", {
621
+ from: "webgl2",
622
+ to: "css"
623
+ });
624
+ }
625
+ #he() {
626
+ if (typeof matchMedia != "function") return;
627
+ let e = matchMedia("(prefers-reduced-motion: reduce)");
628
+ this.#z = e.matches, e.addEventListener?.("change", (e) => {
629
+ this.#z = e.matches;
630
+ });
631
+ }
632
+ #ge() {
633
+ let e = this.#e, t = e.ownerDocument;
634
+ if (!t || typeof e.setAttribute != "function") return null;
635
+ e.hasAttribute("tabindex") || (e.tabIndex = 0), e.setAttribute("aria-roledescription", "flipbook");
636
+ let n = (e) => this.#_e(e);
637
+ e.addEventListener("keydown", n);
638
+ let r = t.createElement("div");
639
+ return r.setAttribute("aria-live", "polite"), r.setAttribute("aria-atomic", "true"), r.style.cssText = "position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;", e.appendChild(r), this.#B = r, () => {
640
+ e.removeEventListener("keydown", n), r.remove(), this.#B = null;
641
+ };
642
+ }
643
+ #_e(e) {
644
+ let t = this.#a === "rtl" ? "ArrowLeft" : "ArrowRight";
645
+ switch (e.key) {
646
+ case "ArrowRight":
647
+ case "ArrowLeft":
648
+ e.key === t ? this.flipNext() : this.flipPrev(), e.preventDefault();
649
+ break;
650
+ case "Home":
651
+ this.flipTo(0), e.preventDefault();
652
+ break;
653
+ case "End":
654
+ this.flipTo(this.#t.pageCount - 1), e.preventDefault();
655
+ break;
656
+ default: break;
657
+ }
658
+ }
659
+ #ve() {
660
+ this.#B && (this.#B.textContent = `Page ${this.#g + 1} of ${this.#t.pageCount}`);
661
+ }
662
+ #ye() {
663
+ return this.#z ? 0 : this.#v;
664
+ }
665
+ update() {
666
+ !this.#O || this.#i.state !== "idle" || (this.#be(this.#O.measure().containerWidth), this.#xe());
667
+ }
668
+ #be(n) {
669
+ let r = t(n, this.#d);
670
+ r !== this.#f && (this.#f = r, this.#m = e(this.#t.pageCount, {
671
+ direction: this.#a,
672
+ cover: this.#o,
673
+ singlePage: r
674
+ }), this.#h = this.#Oe(this.#g));
675
+ }
676
+ async #xe() {
677
+ let e = this.#m[this.#h];
678
+ !e || !this.#O || (this.#_ = await this.#Te(e), this.#Se(e, this.#_));
679
+ }
680
+ #Se(e, t) {
681
+ this.#O?.renderSpread(e, t, { fill: this.#f });
682
+ }
683
+ #Ce() {
684
+ typeof ResizeObserver > "u" || (this.#C = new ResizeObserver(() => this.#we()), this.#C.observe(this.#e));
685
+ }
686
+ #we() {
687
+ this.#w || (this.#w = !0, requestAnimationFrame(() => {
688
+ this.#w = !1, this.update();
689
+ }));
690
+ }
691
+ async #Te(e) {
692
+ let [t, n] = await Promise.all([this.#Ee(e.left), this.#Ee(e.right)]);
693
+ return {
694
+ left: t,
695
+ right: n
696
+ };
697
+ }
698
+ async #Ee(e) {
699
+ if (e === null) return null;
700
+ try {
701
+ return await this.#t.get(e);
702
+ } catch (t) {
703
+ return this.#n.emit("sourceError", {
704
+ index: e,
705
+ error: t
706
+ }), null;
707
+ }
708
+ }
709
+ #De() {
710
+ let { toMount: e } = this.#r.update(this.#h, this.#m.length), t = [];
711
+ for (let n of e) {
712
+ let e = this.#m[n];
713
+ e?.left != null && t.push(e.left), e?.right != null && t.push(e.right);
714
+ }
715
+ this.#t.prefetch(t);
716
+ }
717
+ #Oe(e) {
718
+ let t = this.#m.findIndex((t) => t.left === e || t.right === e);
719
+ return t === -1 ? 0 : t;
720
+ }
721
+ #ke() {
722
+ let t = this.#t.pageCount;
723
+ if (!Number.isInteger(t) || t < 1) throw Error(`Zine: source has ${t} pages; a Source must have at least 1 page.`);
724
+ let n = this.#p;
725
+ if (n !== void 0 && (!Number.isInteger(n) || n < 0 || n >= t)) throw Error(`Zine: startPage ${JSON.stringify(n)} is out of range for a ${t}-page book (valid 0..${t - 1}).`);
726
+ this.#m = e(t, {
727
+ direction: this.#a,
728
+ cover: this.#o
729
+ }), this.#g = E(n ?? 0, 0, t - 1), this.#h = this.#Oe(this.#g);
730
+ }
731
+ };
732
+ function E(e, t, n) {
733
+ return e < t ? t : e > n ? n : e;
734
+ }
735
+ function D(e) {
736
+ return e < .5 ? 4 * e * e * e : 1 - (-2 * e + 2) ** 3 / 2;
737
+ }
738
+ function O(e) {
739
+ return e === null ? "null" : Array.isArray(e) ? "array" : typeof e;
740
+ }
741
+ function k(e, t) {
742
+ if (typeof e != "object" || !e || typeof e.appendChild != "function" || typeof e.addEventListener != "function") throw Error(`Zine: container must be a DOM element; received ${O(e)}.`);
743
+ if (typeof t != "object" || !t) throw Error("Zine: an options object with a `source` is required.");
744
+ let n = t, r = n.source;
745
+ if (typeof r != "object" || !r || typeof r.get != "function" || typeof r.pageCount != "number") throw Error("Zine: `source` is required and must be a Source, e.g. new ImageSource(urls).");
746
+ let i = n.startPage;
747
+ if (i !== void 0 && (typeof i != "number" || !Number.isInteger(i) || i < 0)) throw Error(`Zine: startPage must be a non-negative integer; got ${JSON.stringify(i)}.`);
748
+ let a = n.direction;
749
+ if (a !== void 0 && a !== "ltr" && a !== "rtl") throw Error(`Zine: direction must be 'ltr' or 'rtl'; got ${JSON.stringify(a)}.`);
750
+ let o = n.clickToFlip;
751
+ if (o !== void 0 && ![
752
+ "edge",
753
+ "half",
754
+ "off"
755
+ ].includes(o)) throw Error(`Zine: clickToFlip must be 'edge', 'half', or 'off'; got ${JSON.stringify(o)}.`);
756
+ A(n.width, "width", 1), A(n.height, "height", 1), A(n.flipDuration, "flipDuration", 0), A(n.clickZoneSize, "clickZoneSize", 0), A(n.clickFlipDelay, "clickFlipDelay", 0), A(n.singlePageThreshold, "singlePageThreshold", 0), j(n.zoom), M(n.renderer);
757
+ }
758
+ function A(e, t, n) {
759
+ if (e !== void 0 && (typeof e != "number" || !Number.isFinite(e) || e < n)) throw Error(`Zine: ${t} must be a number >= ${n}; got ${JSON.stringify(e)}.`);
760
+ }
761
+ function j(e) {
762
+ if (e === void 0) return;
763
+ if (typeof e != "object" || !e || Array.isArray(e)) throw Error("Zine: zoom must be an object, e.g. { max: 4 }.");
764
+ let t = e;
765
+ if (t.enabled !== void 0 && typeof t.enabled != "boolean") throw Error(`Zine: zoom.enabled must be a boolean; got ${JSON.stringify(t.enabled)}.`);
766
+ if (t.wheel !== void 0 && typeof t.wheel != "boolean") throw Error(`Zine: zoom.wheel must be a boolean; got ${JSON.stringify(t.wheel)}.`);
767
+ if (t.doubleClickInFlipZone !== void 0 && typeof t.doubleClickInFlipZone != "boolean") throw Error(`Zine: zoom.doubleClickInFlipZone must be a boolean; got ${JSON.stringify(t.doubleClickInFlipZone)}.`);
768
+ if (t.doubleClick !== void 0 && t.doubleClick !== !1) {
769
+ let e = t.doubleClick;
770
+ if (!Array.isArray(e) || e.some((e) => typeof e != "number" || !Number.isFinite(e) || e < 1)) throw Error("Zine: zoom.doubleClick must be false or an array of zoom levels >= 1, e.g. [1, 2, 4].");
771
+ }
772
+ A(t.max, "zoom.max", 1);
773
+ }
774
+ function M(e) {
775
+ if (e !== void 0) {
776
+ if (typeof e == "string") {
777
+ if (e !== "auto" && e !== "css" && e !== "webgl2") throw Error(`Zine: renderer '${e}' is not recognized; use 'auto', 'css', 'webgl2', an array of those, or a custom Renderer.`);
778
+ return;
779
+ }
780
+ if (Array.isArray(e)) {
781
+ for (let t of e) if (t !== "css" && t !== "webgl2") throw Error(`Zine: renderer order array may only contain 'css' or 'webgl2'; got ${JSON.stringify(t)}.`);
782
+ return;
783
+ }
784
+ if (!(typeof e == "object" && e && typeof e.mount == "function")) throw Error("Zine: renderer must be 'auto', 'css', 'webgl2', an array of those, or a custom Renderer instance.");
785
+ }
786
+ }
787
+ //#endregion
788
+ //#region src/source/imageSource.ts
789
+ var N = class {
790
+ pageCount;
791
+ fit;
792
+ #e;
793
+ #t;
794
+ #n = /* @__PURE__ */ new Map();
795
+ constructor(e, t = {}) {
796
+ this.#e = e, this.pageCount = e.length, this.#t = t.preload ?? 1, this.fit = t.fit ?? "contain";
797
+ }
798
+ get(e) {
799
+ let t = this.#r(e);
800
+ for (let t = 1; t <= this.#t; t++) this.prefetch([e - t, e + t]);
801
+ return t;
802
+ }
803
+ prefetch(e) {
804
+ for (let t of e) t >= 0 && t < this.pageCount && this.#r(t).catch(() => {});
805
+ }
806
+ destroy() {
807
+ for (let e of this.#n.values()) e.then((e) => e.close()).catch(() => {});
808
+ this.#n.clear();
809
+ }
810
+ #r(e) {
811
+ let t = this.#n.get(e);
812
+ if (t) return t;
813
+ let n = this.#e[e];
814
+ if (n === void 0) return Promise.reject(/* @__PURE__ */ RangeError(`ImageSource: page ${e} is out of range (0..${this.pageCount - 1}).`));
815
+ let r = (async () => {
816
+ let t = await fetch(n);
817
+ if (!t.ok) throw Error(`ImageSource: failed to fetch page ${e} (${n}) — HTTP ${t.status}.`);
818
+ return createImageBitmap(await t.blob());
819
+ })().catch((t) => {
820
+ throw this.#n.delete(e), t;
821
+ });
822
+ return this.#n.set(e, r), r;
823
+ }
824
+ };
825
+ //#endregion
826
+ export { N as ImageSource, T as Zine };
827
+
828
+ //# sourceMappingURL=index.js.map