html-flip-book-vanilla 0.0.0-alpha.21 → 0.0.0-alpha.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"flipbook.d.ts","sourceRoot":"","sources":["../src/flipbook.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAyCtD,cAAM,QAAQ;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwC;IACxE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAG/B;IACF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;IACjE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0B;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAmB;IACtC,gBAAgB;;;MAAkB;IAElC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,sBAAsB,CAA0C;IAExE,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAErE,OAAO,CAAC,kBAAkB;IAG1B,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,sBAAsB,GAcjC;gBAEW,OAAO,EAAE,eAAe;IAYpC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAQ;IAgKtC,OAAO,CAAC,4BAA4B;IA8BpC,OAAO,CAAC,YAAY;IAqBpB,OAAO,KAAK,iBAAiB,GAO5B;IAMD,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,YAAY;IA0EpB,OAAO,CAAC,SAAS;IAkDjB,OAAO,CAAC,gBAAgB,CAOtB;IAEF,OAAO,CAAC,eAAe,CAerB;IAEF,OAAO,CAAC,eAAe,CA2CpB;IAEH,OAAO,CAAC,gBAAgB,CAEtB;IAEF,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,QAAQ;IA4BhB,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAKD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAKD,IAAI,UAAU,IAAI,OAAO,CAGxB;IAKD,OAAO,CAAC,4BAA4B;IAa9B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgChD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAkEnC,OAAO,CAAC,kBAAkB;IAQ1B,OAAO;CAeP;AAED,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"flipbook.d.ts","sourceRoot":"","sources":["../src/flipbook.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AACtB,OAAO,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAyCtD,cAAM,QAAQ;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwC;IACxE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAG/B;IACF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;IACjE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0B;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAmB;IACtC,gBAAgB;;;MAAkB;IAElC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,sBAAsB,CAA0C;IAExE,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAErE,OAAO,CAAC,kBAAkB;IAG1B,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,sBAAsB,GAcjC;gBAEW,OAAO,EAAE,eAAe;IAYpC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAQ;IAgKtC,OAAO,CAAC,4BAA4B;IA8BpC,OAAO,CAAC,YAAY;IAqBpB,OAAO,KAAK,iBAAiB,GAO5B;IAMD,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,YAAY;IA0EpB,OAAO,CAAC,SAAS;IAkDjB,OAAO,CAAC,gBAAgB,CAOtB;IAEF,OAAO,CAAC,eAAe,CAerB;IAEF,OAAO,CAAC,eAAe,CA2CpB;IAEH,OAAO,CAAC,gBAAgB,CAEtB;IAEF,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,QAAQ;IA4BhB,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAKD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAKD,IAAI,UAAU,IAAI,OAAO,CAGxB;IAKD,OAAO,CAAC,4BAA4B;IAa9B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgChD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmFnC,OAAO,CAAC,kBAAkB;IAQ1B,OAAO;CAeP;AAED,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,CAAC"}
package/dist/flipbook.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import A from "hammerjs";
2
2
  import { throttle as b } from "throttle-debounce";
3
- var l = /* @__PURE__ */ ((v) => (v.Forward = "Forward", v.Backward = "Backward", v.None = "None", v))(l || {});
3
+ var c = /* @__PURE__ */ ((v) => (v.Forward = "Forward", v.Backward = "Backward", v.None = "None", v))(c || {});
4
4
  const R = 1.1, E = 0.9, k = 8;
5
5
  class D {
6
- constructor(t, e, i, s, c) {
7
- this.index = t, this.pages = e, this.bookProperties = s, this.onTurned = c, this.wrappedFlipPosition = i ? 1 : 0;
6
+ constructor(t, e, i, s, r) {
7
+ this.index = t, this.pages = e, this.bookProperties = s, this.onTurned = r, this.wrappedFlipPosition = i ? 1 : 0;
8
8
  }
9
9
  currentAnimation = null;
10
10
  targetFlipPosition = null;
@@ -37,28 +37,28 @@ class D {
37
37
  }
38
38
  async flipToPosition(t, e = 225) {
39
39
  return this.currentAnimation && await this.currentAnimation, this.flipPosition === t ? Promise.resolve() : this.targetFlipPosition === t ? this.currentAnimation ?? Promise.resolve() : (this.targetFlipPosition = t, this.currentAnimation = new Promise((i) => {
40
- const s = this.flipPosition, o = Math.abs(t - s) * 180 / e * 1e3, n = performance.now(), h = (f) => {
40
+ const s = this.flipPosition, o = Math.abs(t - s) * 180 / e * 1e3, n = performance.now(), l = (f) => {
41
41
  const d = f - n;
42
42
  if (d < 0) {
43
- requestAnimationFrame(h);
43
+ requestAnimationFrame(l);
44
44
  return;
45
45
  }
46
- const r = Math.min(d / o, 1), a = s + r * (t - s);
47
- this.applyTransform(a), this.flipPosition = Math.max(0, Math.min(1, a)), (this.flipPosition === 1 || this.flipPosition === 0) && this.onTurned(this.flipPosition === 1 ? l.Forward : l.Backward), r < 1 ? requestAnimationFrame(h) : (this.currentAnimation = null, this.targetFlipPosition = null, i());
46
+ const a = Math.min(d / o, 1), h = s + a * (t - s);
47
+ this.applyTransform(h), this.flipPosition = Math.max(0, Math.min(1, h)), (this.flipPosition === 1 || this.flipPosition === 0) && this.onTurned(this.flipPosition === 1 ? c.Forward : c.Backward), a < 1 ? requestAnimationFrame(l) : (this.currentAnimation = null, this.targetFlipPosition = null, i());
48
48
  };
49
- requestAnimationFrame(h);
49
+ requestAnimationFrame(l);
50
50
  }), this.currentAnimation);
51
51
  }
52
52
  async efficientFlipToPosition(t, e = 2e4) {
53
53
  return b(1, this.flipToPosition.bind(this))(t, e);
54
54
  }
55
55
  applyTransform(t) {
56
- const e = Math.max(0, Math.min(1, t)), i = Math.sin(e * Math.PI), s = Math.max(i, this.hoverShadow), c = Math.min(1, s * R), o = Math.min(1, s * E), n = `${(s * k).toFixed(3)}px`;
57
- this.pages.forEach((h, f) => {
56
+ const e = Math.max(0, Math.min(1, t)), i = Math.sin(e * Math.PI), s = Math.max(i, this.hoverShadow), r = Math.min(1, s * R), o = Math.min(1, s * E), n = `${(s * k).toFixed(3)}px`;
57
+ this.pages.forEach((l, f) => {
58
58
  const d = this.bookProperties.isLTR;
59
- if (!h) return;
60
- const r = f % 2 + 1 === 1, u = `${r ? d ? e > 0.5 ? 180 - e * 180 : -e * 180 : e > 0.5 ? -(180 - e * 180) : e * 180 : d ? e < 0.5 ? -e * 180 : 180 - e * 180 : e < 0.5 ? e * 180 : -(180 - e * 180)}deg`, L = `${r ? d ? "100%" : "-100%" : "0px"}`, g = r ? e > 0.5 ? -1 : 1 : e < 0.5 ? -1 : 1, m = r ? d ? "left" : "right" : d ? "right" : "left", w = m === "left" ? "right" : "left";
61
- h.style.transform = `translateX(${L})rotateY(${u})scaleX(${g})`, h.style.transformOrigin = m, h.style.zIndex = `${e > 0.5 ? h.dataset.pageIndex : this.bookProperties.pagesCount - h.dataset.pageIndex}`, h.style.setProperty("--inner-shadow-shadow", c.toFixed(3)), h.style.setProperty("--inner-shadow-highlight", o.toFixed(3)), h.style.setProperty("--inner-shadow-lift", n), h.style.setProperty("--inner-shadow-edge", w);
59
+ if (!l) return;
60
+ const a = f % 2 + 1 === 1, u = `${a ? d ? e > 0.5 ? 180 - e * 180 : -e * 180 : e > 0.5 ? -(180 - e * 180) : e * 180 : d ? e < 0.5 ? -e * 180 : 180 - e * 180 : e < 0.5 ? e * 180 : -(180 - e * 180)}deg`, L = `${a ? d ? "100%" : "-100%" : "0px"}`, g = a ? e > 0.5 ? -1 : 1 : e < 0.5 ? -1 : 1, m = a ? d ? "left" : "right" : d ? "right" : "left", w = m === "left" ? "right" : "left";
61
+ l.style.transform = `translateX(${L})rotateY(${u})scaleX(${g})`, l.style.transformOrigin = m, l.style.zIndex = `${e > 0.5 ? l.dataset.pageIndex : this.bookProperties.pagesCount - l.dataset.pageIndex}`, l.style.setProperty("--inner-shadow-shadow", r.toFixed(3)), l.style.setProperty("--inner-shadow-highlight", o.toFixed(3)), l.style.setProperty("--inner-shadow-lift", n), l.style.setProperty("--inner-shadow-edge", w);
62
62
  });
63
63
  }
64
64
  }
@@ -106,7 +106,7 @@ class S {
106
106
  // flipping state - supports concurrent page flipping
107
107
  activeFlips = /* @__PURE__ */ new Map();
108
108
  pendingFlipStartingPos = 0;
109
- pendingFlipDirection = l.None;
109
+ pendingFlipDirection = c.None;
110
110
  isDragging = !1;
111
111
  hoveredLeaf;
112
112
  touchStartingPos = { x: 0, y: 0 };
@@ -145,33 +145,33 @@ class S {
145
145
  if (!s.length)
146
146
  throw new Error("No pages found in flipbook");
147
147
  this.pageElements = Array.from(s), this.leaves.splice(0, this.leaves.length);
148
- const c = Math.ceil(this.pagesCount / 2), n = new P(this.bookElement.clientWidth / 2, this.bookElement.clientHeight).aspectRatioFit(this.coverAspectRatio), h = new P(
148
+ const r = Math.ceil(this.pagesCount / 2), n = new P(this.bookElement.clientWidth / 2, this.bookElement.clientHeight).aspectRatioFit(this.coverAspectRatio), l = new P(
149
149
  n.width * this.leafAspectRatio.width / this.coverAspectRatio.width,
150
150
  n.height * this.leafAspectRatio.height / this.coverAspectRatio.height
151
151
  );
152
- this.bookElement.style.perspective = `${Math.min(h.width * 2, h.height) * 2}px`, this.pageElements.forEach((r, a) => {
153
- r.style.width = `${h.width}px`, r.style.height = `${h.height}px`, r.style.zIndex = `${this.pagesCount - a}`, r.dataset.pageIndex = a.toString(), r.style[this.isLTR ? "left" : "right"] = `${(i.clientWidth - 2 * h.width) / 2}px`, r.style.top = `${(i.clientHeight - h.height) / 2}px`, r.dataset.pageSemanticName = this.pageSemantics?.indexToSemanticName(a) ?? "", r.dataset.pageTitle = this.pageSemantics?.indexToTitle(a) ?? "";
154
- const u = Math.floor(a / 2), L = (a + 1) % 2 === 1, g = this.initialTurnedLeaves.has(u), m = this.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0, w = u === m || u === m - 1 && g;
155
- if (r.classList.add(
152
+ this.bookElement.style.perspective = `${Math.min(l.width * 2, l.height) * 2}px`, this.pageElements.forEach((a, h) => {
153
+ a.style.width = `${l.width}px`, a.style.height = `${l.height}px`, a.style.zIndex = `${this.pagesCount - h}`, a.dataset.pageIndex = h.toString(), a.style[this.isLTR ? "left" : "right"] = `${(i.clientWidth - 2 * l.width) / 2}px`, a.style.top = `${(i.clientHeight - l.height) / 2}px`, a.dataset.pageSemanticName = this.pageSemantics?.indexToSemanticName(h) ?? "", a.dataset.pageTitle = this.pageSemantics?.indexToTitle(h) ?? "";
154
+ const u = Math.floor(h / 2), L = (h + 1) % 2 === 1, g = this.initialTurnedLeaves.has(u), m = this.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0, w = u === m || u === m - 1 && g;
155
+ if (a.classList.add(
156
156
  L ? "odd" : "even",
157
157
  ...w ? ["current-page"] : []
158
158
  ), L) {
159
159
  if (g) {
160
160
  const p = `translateX(${this.isLTR ? "100%" : "-100%"})rotateY(${this.isLTR ? "180deg" : "-180deg"})scaleX(-1)`;
161
- r.style.transform = p, r.style.transformOrigin = this.isLTR ? "left" : "right", r.style.zIndex = `${a}`;
161
+ a.style.transform = p, a.style.transformOrigin = this.isLTR ? "left" : "right", a.style.zIndex = `${h}`;
162
162
  } else
163
- r.style.transform = `translateX(${this.isLTR ? "" : "-"}100%)`, r.style.zIndex = `${this.pagesCount - a}`;
163
+ a.style.transform = `translateX(${this.isLTR ? "" : "-"}100%)`, a.style.zIndex = `${this.pagesCount - h}`;
164
164
  this.leaves[u] = new D(
165
165
  u,
166
- [r, void 0],
166
+ [a, void 0],
167
167
  g,
168
168
  {
169
169
  isLTR: this.isLTR,
170
- leavesCount: c,
170
+ leavesCount: r,
171
171
  pagesCount: this.pagesCount
172
172
  },
173
173
  (F) => {
174
- const p = F === l.Forward ? a + 2 === this.pagesCount ? [a + 1] : [a + 1, a + 2] : a === 0 ? [a] : [a - 1, a];
174
+ const p = F === c.Forward ? h + 2 === this.pagesCount ? [h + 1] : [h + 1, h + 2] : h === 0 ? [h] : [h - 1, h];
175
175
  if (this.prevVisiblePageIndices && this.prevVisiblePageIndices.length === p.length && p.every((x, M) => x === this.prevVisiblePageIndices?.[M]))
176
176
  return;
177
177
  const y = this.prevVisiblePageIndices;
@@ -179,12 +179,12 @@ class S {
179
179
  }
180
180
  );
181
181
  } else
182
- g ? (r.style.transform = `translateX(0px)rotateY(${this.isLTR ? "180deg" : "-180deg"})scaleX(1)`, r.style.transformOrigin = this.isLTR ? "right" : "left", r.style.zIndex = `${a}`) : (r.style.transform = `scaleX(-1)translateX(${this.isLTR ? "-" : ""}100%)`, r.style.zIndex = `${this.pagesCount - a}`), this.leaves[u].pages[1] = r;
182
+ g ? (a.style.transform = `translateX(0px)rotateY(${this.isLTR ? "180deg" : "-180deg"})scaleX(1)`, a.style.transformOrigin = this.isLTR ? "right" : "left", a.style.zIndex = `${h}`) : (a.style.transform = `scaleX(-1)translateX(${this.isLTR ? "-" : ""}100%)`, a.style.zIndex = `${this.pagesCount - h}`), this.leaves[u].pages[1] = a;
183
183
  });
184
184
  const d = (this.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0) * 2;
185
185
  if (d >= this.pagesCount) {
186
- const a = (Math.ceil(this.pagesCount / 2) - 1) * 2;
187
- this.prevVisiblePageIndices = a + 1 < this.pagesCount ? [a, a + 1] : [a];
186
+ const h = (Math.ceil(this.pagesCount / 2) - 1) * 2;
187
+ this.prevVisiblePageIndices = h + 1 < this.pagesCount ? [h, h + 1] : [h];
188
188
  } else
189
189
  this.prevVisiblePageIndices = d + 1 < this.pagesCount ? [d, d + 1] : [d];
190
190
  this.hammer = new A(this.bookElement), this.hammer.on("panstart", this.onDragStart.bind(this)), this.hammer.on("panmove", this.onDragUpdate.bind(this)), this.hammer.on("panend", this.onDragEnd.bind(this)), this.bookElement.addEventListener("touchstart", this.handleTouchStart.bind(this), {
@@ -205,10 +205,10 @@ class S {
205
205
  return;
206
206
  const t = this.leaves.length;
207
207
  if (t === 0) return;
208
- const [e, i] = this.currentOrTurningLeaves, s = i?.index ?? e?.index ?? 0, c = Math.max(0, s - this.leavesBuffer), o = Math.min(t - 1, s + this.leavesBuffer);
208
+ const [e, i] = this.currentOrTurningLeaves, s = i?.index ?? e?.index ?? 0, r = Math.max(0, s - this.leavesBuffer), o = Math.min(t - 1, s + this.leavesBuffer);
209
209
  for (let n = 0; n < t; n++) {
210
- const h = this.leaves[n], f = n >= c && n <= o;
211
- for (const d of h.pages)
210
+ const l = this.leaves[n], f = n >= r && n <= o;
211
+ for (const d of l.pages)
212
212
  d && (d.style.display = f ? "" : "none");
213
213
  }
214
214
  }
@@ -237,7 +237,7 @@ class S {
237
237
  * Excludes leaves that are already being flipped.
238
238
  */
239
239
  getNextAvailableLeaf(t) {
240
- if (t === l.Forward) {
240
+ if (t === c.Forward) {
241
241
  const [, e] = this.currentOrTurningLeaves;
242
242
  if (!e) return;
243
243
  for (let i = e.index; i < this.leaves.length; i++) {
@@ -246,7 +246,7 @@ class S {
246
246
  return s;
247
247
  }
248
248
  return;
249
- } else if (t === l.Backward) {
249
+ } else if (t === c.Backward) {
250
250
  const [e] = this.currentOrTurningLeaves;
251
251
  if (!e) return;
252
252
  for (let i = e.index; i >= 0; i--) {
@@ -260,18 +260,18 @@ class S {
260
260
  onDragStart(t) {
261
261
  if (!this.isInsideNoFlipZone(t.srcEvent?.target ?? null)) {
262
262
  if (this.currentManualFlip) {
263
- this.pendingFlipDirection = l.None, this.pendingFlipStartingPos = 0;
263
+ this.pendingFlipDirection = c.None, this.pendingFlipStartingPos = 0;
264
264
  return;
265
265
  }
266
- this.isDragging = !0, this.clearHoverShadow(), this.pendingFlipStartingPos = t.center.x, this.pendingFlipDirection = l.None;
266
+ this.isDragging = !0, this.clearHoverShadow(), this.pendingFlipStartingPos = t.center.x, this.pendingFlipDirection = c.None;
267
267
  }
268
268
  }
269
269
  onDragUpdate(t) {
270
270
  let e = this.currentManualFlip;
271
- const i = t.center.x, s = this.bookElement?.clientWidth ?? 0, c = this.isLTR ? this.pendingFlipStartingPos - i : i - this.pendingFlipStartingPos;
272
- if (Math.abs(c) > s || c === 0) return;
273
- const o = this.pendingFlipDirection !== l.None ? this.pendingFlipDirection : c > 0 ? l.Forward : l.Backward;
274
- if (this.pendingFlipDirection === l.None && (this.pendingFlipDirection = o), !e) {
271
+ const i = t.center.x, s = this.bookElement?.clientWidth ?? 0, r = this.isLTR ? this.pendingFlipStartingPos - i : i - this.pendingFlipStartingPos;
272
+ if (Math.abs(r) > s || r === 0) return;
273
+ const o = this.pendingFlipDirection !== c.None ? this.pendingFlipDirection : r > 0 ? c.Forward : c.Backward;
274
+ if (this.pendingFlipDirection === c.None && (this.pendingFlipDirection = o), !e) {
275
275
  for (const n of this.activeFlips.values())
276
276
  if (n.isDuringAutoFlip && n.direction !== o)
277
277
  return;
@@ -287,16 +287,16 @@ class S {
287
287
  isDuringAutoFlip: !1
288
288
  }, this.activeFlips.set(n.index, e);
289
289
  }
290
- switch (e.delta = c, e.direction) {
291
- case l.Forward: {
292
- const n = c / s;
293
- if (n > 1 || c < 0) return;
290
+ switch (e.delta = r, e.direction) {
291
+ case c.Forward: {
292
+ const n = r / s;
293
+ if (n > 1 || r < 0) return;
294
294
  e.leaf.efficientFlipToPosition(n);
295
295
  break;
296
296
  }
297
- case l.Backward: {
298
- const n = 1 - Math.abs(c) / s;
299
- if (n < 0 || c > 0) return;
297
+ case c.Backward: {
298
+ const n = 1 - Math.abs(r) / s;
299
+ if (n < 0 || r > 0) return;
300
300
  e.leaf.efficientFlipToPosition(n);
301
301
  break;
302
302
  }
@@ -305,22 +305,22 @@ class S {
305
305
  onDragEnd(t) {
306
306
  const e = this.currentManualFlip;
307
307
  if (!e) {
308
- this.pendingFlipDirection = l.None, this.pendingFlipStartingPos = 0, this.isDragging = !1, this.clearHoverShadow();
308
+ this.pendingFlipDirection = c.None, this.pendingFlipStartingPos = 0, this.isDragging = !1, this.clearHoverShadow();
309
309
  return;
310
310
  }
311
311
  const i = t.velocityX * 1e3;
312
312
  let s;
313
313
  switch (e.direction) {
314
- case l.Forward:
314
+ case c.Forward:
315
315
  (this.isLTR ? i < -this.fastDeltaThreshold : i > this.fastDeltaThreshold) || e.leaf.flipPosition >= 0.5 ? s = 1 : s = 0;
316
316
  break;
317
- case l.Backward:
317
+ case c.Backward:
318
318
  (this.isLTR ? i > this.fastDeltaThreshold : i < -this.fastDeltaThreshold) || e.leaf.flipPosition <= 0.5 ? s = 0 : s = 1;
319
319
  break;
320
320
  default:
321
321
  return;
322
322
  }
323
- e.isDuringAutoFlip = !0, this.pendingFlipDirection = l.None, this.pendingFlipStartingPos = 0, this.isDragging = !1, e.leaf.flipToPosition(s).then(() => {
323
+ e.isDuringAutoFlip = !0, this.pendingFlipDirection = c.None, this.pendingFlipStartingPos = 0, this.isDragging = !1, e.leaf.flipToPosition(s).then(() => {
324
324
  this.activeFlips.delete(e.leaf.index);
325
325
  });
326
326
  }
@@ -344,18 +344,18 @@ class S {
344
344
  }
345
345
  const e = this.bookElement.getBoundingClientRect();
346
346
  if (e.width <= 0) return;
347
- const i = t.clientX - e.left, s = e.width * I, c = i <= s, o = i >= e.width - s;
348
- if (!c && !o) {
347
+ const i = t.clientX - e.left, s = e.width * I, r = i <= s, o = i >= e.width - s;
348
+ if (!r && !o) {
349
349
  this.clearHoverShadow();
350
350
  return;
351
351
  }
352
- const n = this.isLTR ? o : c, h = n ? l.Forward : l.Backward, f = this.getNextAvailableLeaf(h);
352
+ const n = this.isLTR ? o : r, l = n ? c.Forward : c.Backward, f = this.getNextAvailableLeaf(l);
353
353
  if (!f) {
354
354
  this.clearHoverShadow();
355
355
  return;
356
356
  }
357
- const d = n ? this.isLTR ? e.width - i : i : this.isLTR ? i : e.width - i, a = (1 - Math.min(1, d / s)) * $;
358
- this.hoveredLeaf && this.hoveredLeaf !== f && this.hoveredLeaf.setHoverShadow(0), this.hoveredLeaf = f, f.setHoverShadow(a);
357
+ const d = n ? this.isLTR ? e.width - i : i : this.isLTR ? i : e.width - i, h = (1 - Math.min(1, d / s)) * $;
358
+ this.hoveredLeaf && this.hoveredLeaf !== f && this.hoveredLeaf.setHoverShadow(0), this.hoveredLeaf = f, f.setHoverShadow(h);
359
359
  });
360
360
  handleMouseLeave = () => {
361
361
  this.clearHoverShadow();
@@ -365,8 +365,8 @@ class S {
365
365
  }
366
366
  onTurned(t, e) {
367
367
  for (let i = 0; i < this.pageElements.length; i++) {
368
- const s = this.pageElements[i], c = t.includes(i), o = e?.includes(i);
369
- (c ? s.classList.add : !e || !o ? () => null : s.classList.remove).bind(s.classList)("current-page");
368
+ const s = this.pageElements[i], r = t.includes(i), o = e?.includes(i);
369
+ (r ? s.classList.add : !e || !o ? () => null : s.classList.remove).bind(s.classList)("current-page");
370
370
  }
371
371
  this.updateLeavesBufferVisibility(), this.onPageChanged && this.onPageChanged(this.currentPageIndex);
372
372
  }
@@ -410,13 +410,13 @@ class S {
410
410
  * @returns Promise that resolves when the flip animation completes
411
411
  */
412
412
  async flipNext() {
413
- if (this.hasActiveAutoFlipInDirection(l.Backward))
413
+ if (this.hasActiveAutoFlipInDirection(c.Backward))
414
414
  return;
415
- const t = this.getNextAvailableLeaf(l.Forward);
415
+ const t = this.getNextAvailableLeaf(c.Forward);
416
416
  if (!t) return;
417
417
  const e = {
418
418
  leaf: t,
419
- direction: l.Forward,
419
+ direction: c.Forward,
420
420
  startingPos: 0,
421
421
  delta: 0,
422
422
  isDuringAutoFlip: !0
@@ -433,13 +433,13 @@ class S {
433
433
  * @returns Promise that resolves when the flip animation completes
434
434
  */
435
435
  async flipPrev() {
436
- if (this.hasActiveAutoFlipInDirection(l.Forward))
436
+ if (this.hasActiveAutoFlipInDirection(c.Forward))
437
437
  return;
438
- const t = this.getNextAvailableLeaf(l.Backward);
438
+ const t = this.getNextAvailableLeaf(c.Backward);
439
439
  if (!t) return;
440
440
  const e = {
441
441
  leaf: t,
442
- direction: l.Backward,
442
+ direction: c.Backward,
443
443
  startingPos: 0,
444
444
  delta: 0,
445
445
  isDuringAutoFlip: !0
@@ -484,15 +484,19 @@ class S {
484
484
  );
485
485
  return;
486
486
  }
487
- const e = Math.floor(t / 2), i = t === this.pagesCount - 1, s = t % 2 === 1, c = i && s;
487
+ const e = t === this.pagesCount - 1, i = t % 2 === 1, s = e && i;
488
+ let r;
489
+ t <= 0 ? r = -1 : s ? r = this.leaves.length - 1 : r = Math.floor((t - 1) / 2);
488
490
  for (let o = 0; o < this.leaves.length; o++) {
489
- const n = this.leaves[o], h = o < e || c && o === e;
490
- h && !n.isTurned ? (n.flipPosition = 1, this.applyLeafTransform(n, 1)) : !h && n.isTurned && (n.flipPosition = 0, this.applyLeafTransform(n, 0));
491
+ const n = this.leaves[o], l = o <= r;
492
+ l && !n.isTurned ? (n.flipPosition = 1, this.applyLeafTransform(n, 1)) : !l && n.isTurned && (n.flipPosition = 0, this.applyLeafTransform(n, 0));
491
493
  }
492
- if (c)
494
+ if (s)
493
495
  this.prevVisiblePageIndices = [t];
496
+ else if (r < 0)
497
+ this.prevVisiblePageIndices = 1 < this.pagesCount ? [0, 1] : [0];
494
498
  else {
495
- const o = e * 2;
499
+ const o = r * 2 + 1;
496
500
  this.prevVisiblePageIndices = o + 1 < this.pagesCount ? [o, o + 1] : [o];
497
501
  }
498
502
  for (let o = 0; o < this.pageElements.length; o++) {
@@ -1 +1 @@
1
- {"version":3,"file":"flipbook.js","sources":["../src/flip-direction.ts","../src/leaf.ts","../src/aspect-ratio.ts","../src/size.ts","../src/flipbook.ts"],"sourcesContent":["export enum FlipDirection {\n\tForward = \"Forward\",\n\tBackward = \"Backward\",\n\tNone = \"None\",\n}\n","import { throttle } from \"throttle-debounce\";\nimport type { IntRange } from \"type-fest\";\nimport { FlipDirection } from \"./flip-direction\";\n\n/** Multiplier for shadow intensity (slightly stronger than base) */\nconst SHADOW_STRENGTH_MULTIPLIER = 1.1;\n/** Multiplier for highlight intensity (slightly weaker than base) */\nconst HIGHLIGHT_STRENGTH_MULTIPLIER = 0.9;\n/** Maximum lift in pixels for the shadow effect */\nconst SHADOW_LIFT_PX = 8;\n\n// number between 1 to infinity\nexport type DegreesPerSecond = IntRange<1, typeof Infinity>;\nexport type FlipPosition = IntRange<0, 2>;\nexport const FLIPPED = true;\nexport const NOT_FLIPPED = false;\nexport class Leaf {\n\tprivate currentAnimation: Promise<void> | null = null;\n\tprivate targetFlipPosition: FlipPosition | null = null;\n\tprivate wrappedFlipPosition: number;\n\tprivate hoverShadow = 0;\n\n\tconstructor(\n\t\treadonly index: number,\n\t\treadonly pages: [HTMLElement, HTMLElement | undefined],\n\t\tisFlipped: boolean,\n\t\tprivate readonly bookProperties: {\n\t\t\tisLTR: boolean;\n\t\t\tpagesCount: number;\n\t\t\tleavesCount: number;\n\t\t},\n\t\tprivate readonly onTurned: (direction: FlipDirection) => void,\n\t) {\n\t\tthis.wrappedFlipPosition = isFlipped ? 1 : 0;\n\t\t// TODO: rethink this\n\t\t// if(isFlipped) {\n\t\t// // this.flipToPosition(1);\n\t\t// }\n\t}\n\n\tget isTurned(): boolean {\n\t\treturn this.flipPosition === 1;\n\t}\n\tget isTurning(): boolean {\n\t\treturn this.flipPosition !== 0;\n\t}\n\tget isCover(): boolean {\n\t\treturn this.isFirst || this.isLast;\n\t}\n\tget isFirst(): boolean {\n\t\treturn this.index === 0;\n\t}\n\tget isLast(): boolean {\n\t\treturn this.index === this.bookProperties.leavesCount - 1;\n\t}\n\tset flipPosition(value: number) {\n\t\tthis.wrappedFlipPosition = Math.max(0, Math.min(1, value)) as FlipPosition;\n\t}\n\tget flipPosition(): number {\n\t\treturn this.wrappedFlipPosition;\n\t}\n\n\tsetHoverShadow(progress: number): void {\n\t\tconst clamped = Math.max(0, Math.min(1, progress));\n\t\tif (this.hoverShadow === clamped) return;\n\t\tthis.hoverShadow = clamped;\n\t\tthis.applyTransform(this.flipPosition);\n\t}\n\n\tasync flipToPosition(\n\t\tflipPosition: FlipPosition,\n\t\tvelocity: DegreesPerSecond = 225 as DegreesPerSecond,\n\t) {\n\t\tif (this.currentAnimation) {\n\t\t\tawait this.currentAnimation;\n\t\t}\n\n\t\tif (this.flipPosition === flipPosition) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\n\t\tif (this.targetFlipPosition === flipPosition) {\n\t\t\treturn this.currentAnimation ?? Promise.resolve();\n\t\t}\n\n\t\tthis.targetFlipPosition = flipPosition;\n\n\t\tthis.currentAnimation = new Promise<void>((resolve) => {\n\t\t\tconst currentFlipPosition = this.flipPosition;\n\t\t\tconst distance = Math.abs(flipPosition - currentFlipPosition);\n\t\t\tconst duration = ((distance * 180) / velocity) * 1000; // duration in milliseconds\n\n\t\t\tconst start = performance.now();\n\t\t\tconst step = (timestamp: number) => {\n\t\t\t\tconst elapsed = timestamp - start;\n\n\t\t\t\tif (elapsed < 0) {\n\t\t\t\t\trequestAnimationFrame(step);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst progress = Math.min(elapsed / duration, 1);\n\t\t\t\tconst newPosition = currentFlipPosition + progress * (flipPosition - currentFlipPosition);\n\n\t\t\t\tthis.applyTransform(newPosition);\n\n\t\t\t\t// Ensure the new position is within valid bounds [0, 1]\n\t\t\t\tthis.flipPosition = Math.max(0, Math.min(1, newPosition)) as FlipPosition;\n\t\t\t\tif (this.flipPosition === 1 || this.flipPosition === 0) {\n\t\t\t\t\tthis.onTurned(this.flipPosition === 1 ? FlipDirection.Forward : FlipDirection.Backward);\n\t\t\t\t}\n\t\t\t\t// Detailed log for debugging\n\t\t\t\t// console.log(\n\t\t\t\t// `Timestamp: ${timestamp}, Elapsed: ${elapsed}, Progress: ${progress}, Current Position: ${currentFlipPosition}, Requested Position: ${flipPosition}, New Position: ${this.flipPosition}`\n\t\t\t\t// );\n\n\t\t\t\tif (progress < 1) {\n\t\t\t\t\trequestAnimationFrame(step);\n\t\t\t\t} else {\n\t\t\t\t\tthis.currentAnimation = null;\n\t\t\t\t\tthis.targetFlipPosition = null;\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trequestAnimationFrame(step);\n\t\t});\n\n\t\treturn this.currentAnimation;\n\t}\n\n\tasync efficientFlipToPosition(\n\t\tflipPosition: FlipPosition,\n\t\tvelocity: DegreesPerSecond = 20000 as DegreesPerSecond,\n\t) {\n\t\treturn throttle(1, this.flipToPosition.bind(this))(flipPosition, velocity);\n\t}\n\n\tapplyTransform(position: number): void {\n\t\tconst clampedPosition = Math.max(0, Math.min(1, position));\n\t\tconst shadowFromFlip = Math.sin(clampedPosition * Math.PI);\n\t\tconst shadowProgress = Math.max(shadowFromFlip, this.hoverShadow);\n\t\tconst shadowStrength = Math.min(1, shadowProgress * SHADOW_STRENGTH_MULTIPLIER);\n\t\tconst highlightStrength = Math.min(1, shadowProgress * HIGHLIGHT_STRENGTH_MULTIPLIER);\n\t\tconst lift = `${(shadowProgress * SHADOW_LIFT_PX).toFixed(3)}px`;\n\n\t\tthis.pages.forEach((page, index) => {\n\t\t\tconst isLTR = this.bookProperties.isLTR;\n\t\t\tif (!page) return;\n\n\t\t\tconst isOdd = (index % 2) + 1 === 1;\n\t\t\tconst degrees = isOdd\n\t\t\t\t? isLTR\n\t\t\t\t\t? clampedPosition > 0.5\n\t\t\t\t\t\t? 180 - clampedPosition * 180\n\t\t\t\t\t\t: -clampedPosition * 180\n\t\t\t\t\t: clampedPosition > 0.5\n\t\t\t\t\t\t? -(180 - clampedPosition * 180)\n\t\t\t\t\t\t: clampedPosition * 180\n\t\t\t\t: isLTR\n\t\t\t\t\t? clampedPosition < 0.5\n\t\t\t\t\t\t? -clampedPosition * 180\n\t\t\t\t\t\t: 180 - clampedPosition * 180\n\t\t\t\t\t: clampedPosition < 0.5\n\t\t\t\t\t\t? clampedPosition * 180\n\t\t\t\t\t\t: -(180 - clampedPosition * 180);\n\t\t\tconst rotateY = `${degrees}deg`;\n\t\t\tconst translateX = `${isOdd ? (isLTR ? \"100%\" : \"-100%\") : \"0px\"}`;\n\t\t\tconst scaleX = isOdd ? (clampedPosition > 0.5 ? -1 : 1) : clampedPosition < 0.5 ? -1 : 1;\n\t\t\tconst origin = isOdd ? (isLTR ? \"left\" : \"right\") : isLTR ? \"right\" : \"left\";\n\t\t\tconst edge = origin === \"left\" ? \"right\" : \"left\";\n\n\t\t\tpage.style.transform = `translateX(${translateX})rotateY(${rotateY})scaleX(${scaleX})`;\n\t\t\tpage.style.transformOrigin = origin;\n\t\t\tpage.style.zIndex = `${\n\t\t\t\tclampedPosition > 0.5\n\t\t\t\t\t? page.dataset.pageIndex\n\t\t\t\t\t: this.bookProperties.pagesCount - (page.dataset.pageIndex as unknown as number)\n\t\t\t}`;\n\t\t\tpage.style.setProperty(\"--inner-shadow-shadow\", shadowStrength.toFixed(3));\n\t\t\tpage.style.setProperty(\"--inner-shadow-highlight\", highlightStrength.toFixed(3));\n\t\t\tpage.style.setProperty(\"--inner-shadow-lift\", lift);\n\t\t\tpage.style.setProperty(\"--inner-shadow-edge\", edge);\n\t\t});\n\t}\n}\n","export interface AspectRatio {\n\twidth: number;\n\theight: number;\n}\nexport class AspectRatioImpl implements AspectRatio {\n\tstatic from(aspectRatio: AspectRatio) {\n\t\treturn new AspectRatioImpl(aspectRatio.width, aspectRatio.height);\n\t}\n\tconstructor(\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t) {}\n\tget value(): number {\n\t\treturn this.width / this.height;\n\t}\n}\n","import { type AspectRatio, AspectRatioImpl } from \"./aspect-ratio\";\n\nexport class Size {\n\taspectRatio: AspectRatioImpl;\n\taspectRatioFit(rhsAspectRatio: AspectRatio) {\n\t\tconst rhsAspectRatioValue = AspectRatioImpl.from(rhsAspectRatio).value;\n\t\treturn this.aspectRatio.value > rhsAspectRatioValue\n\t\t\t? new Size(this.height * rhsAspectRatioValue, this.height)\n\t\t\t: new Size(this.width, this.width / rhsAspectRatioValue);\n\t}\n\tconstructor(\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t) {\n\t\tthis.aspectRatio = new AspectRatioImpl(width, height);\n\t}\n\tget asString(): string {\n\t\treturn `${this.width}x${this.height}`;\n\t}\n}\n","import \"./pages.scss\";\nimport \"./flipbook.scss\";\nimport Hammer from \"hammerjs\";\nimport { throttle } from \"throttle-debounce\";\nimport type { AspectRatio } from \"./aspect-ratio\";\nimport type { FlipBookOptions } from \"./flip-book-options\";\nimport { FlipDirection } from \"./flip-direction\";\nimport { type FlipPosition, Leaf } from \"./leaf\";\nimport type { PageSemantics } from \"./page-semantics\";\nimport { Size } from \"./size\";\n\n/** Default threshold for fast flip detection (in ms) */\nconst DEFAULT_FAST_DELTA = 500;\n\n/** Percentage of book width that triggers hover shadow effect */\nconst EDGE_ZONE_RATIO = 0.18;\n/** Maximum hover shadow strength (0-1) */\nconst HOVER_STRENGTH_MAX = 0.12;\n/** Throttle interval for mouse move handler in ms */\nconst MOUSE_MOVE_THROTTLE_MS = 16;\n\n/** State for a single flip operation - enables concurrent page flipping */\ninterface FlipState {\n\tleaf: Leaf;\n\tdirection: FlipDirection;\n\tstartingPos: number;\n\tdelta: number;\n\tisDuringAutoFlip: boolean;\n}\n\n/**\n * Core FlipBook class for creating realistic page-flip animations.\n *\n * @example\n * ```typescript\n * import { FlipBook } from 'html-flip-book-vanilla';\n *\n * const flipBook = new FlipBook({\n * pagesCount: 10,\n * direction: 'ltr',\n * });\n *\n * flipBook.render('#book-container');\n *\n * // Navigate programmatically\n * await flipBook.flipNext();\n * await flipBook.goToPage(5);\n * ```\n */\nclass FlipBook {\n\tbookElement?: HTMLElement;\n\tprivate pageElements: HTMLElement[] = [];\n\tprivate readonly pagesCount: number;\n\tprivate readonly leafAspectRatio: AspectRatio = { width: 2, height: 3 };\n\tprivate readonly coverAspectRatio: AspectRatio = {\n\t\twidth: 2.15,\n\t\theight: 3.15,\n\t};\n\tprivate readonly direction: \"rtl\" | \"ltr\" = \"ltr\";\n\tprivate readonly fastDeltaThreshold: number = DEFAULT_FAST_DELTA;\n\tprivate readonly initialTurnedLeaves: Set<number> = new Set();\n\tprivate readonly onPageChanged?: (pageIndex: number) => void;\n\tprivate readonly pageSemantics: PageSemantics | undefined;\n\tprivate readonly leavesBuffer?: number;\n\tprivate leaves: Leaf[] = [];\n\t// flipping state - supports concurrent page flipping\n\tprivate activeFlips: Map<number, FlipState> = new Map();\n\tprivate pendingFlipStartingPos = 0;\n\tprivate pendingFlipDirection: FlipDirection = FlipDirection.None;\n\tprivate isDragging = false;\n\tprivate hoveredLeaf: Leaf | undefined;\n\ttouchStartingPos = { x: 0, y: 0 };\n\t/** True when the current touch started inside a [data-flipbook-no-flip] element (e.g. carousel). */\n\tprivate touchStartedInNoFlipZone = false;\n\tprivate prevVisiblePageIndices: [number] | [number, number] | undefined;\n\t// Hammer instance for cleanup\n\tprivate hammer: HammerManager | undefined;\n\n\tprivate static readonly NO_FLIP_SELECTOR = \"[data-flipbook-no-flip]\";\n\n\tprivate isInsideNoFlipZone(el: EventTarget | null): boolean {\n\t\treturn el instanceof Element && el.closest(FlipBook.NO_FLIP_SELECTOR) != null;\n\t}\n\tprivate get isLTR(): boolean {\n\t\treturn this.direction === \"ltr\";\n\t}\n\n\tprivate get currentOrTurningLeaves(): [Leaf | undefined, Leaf | undefined] {\n\t\tlet secondLeafIndex = -1;\n\t\tfor (let i = this.leaves.length - 1; i >= 0; i--) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\tif (leaf.isTurned || leaf.isTurning) {\n\t\t\t\tsecondLeafIndex = leaf.index + 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn secondLeafIndex === -1\n\t\t\t? [undefined, this.leaves[0]]\n\t\t\t: secondLeafIndex === this.leaves.length\n\t\t\t\t? [this.leaves[secondLeafIndex - 1], undefined]\n\t\t\t\t: [this.leaves[secondLeafIndex - 1], this.leaves[secondLeafIndex]];\n\t}\n\n\tconstructor(options: FlipBookOptions) {\n\t\tthis.pagesCount = options.pagesCount;\n\t\tthis.leafAspectRatio = options.leafAspectRatio || this.leafAspectRatio;\n\t\tthis.coverAspectRatio = options.coverAspectRatio || this.coverAspectRatio;\n\t\tthis.direction = options.direction || this.direction;\n\t\tthis.fastDeltaThreshold = options.fastDeltaThreshold ?? this.fastDeltaThreshold;\n\t\tthis.initialTurnedLeaves = new Set(options.initialTurnedLeaves ?? []);\n\t\tthis.pageSemantics = options.pageSemantics;\n\t\tthis.onPageChanged = options.onPageChanged;\n\t\tthis.leavesBuffer = options.leavesBuffer;\n\t}\n\n\trender(selector: string, debug = false) {\n\t\tconst bookElement = document.querySelector(selector);\n\t\tif (!bookElement) {\n\t\t\tthrow new Error(`Couldn't find container with selector: ${selector}`);\n\t\t}\n\t\tthis.bookElement = bookElement as HTMLElement;\n\t\tif (!this.bookElement.classList.contains(\"flipbook\")) {\n\t\t\tthis.bookElement.classList.add(\"flipbook\");\n\t\t}\n\n\t\tconst pageElements = bookElement.querySelectorAll(\".page\");\n\t\tif (!pageElements.length) {\n\t\t\tthrow new Error(\"No pages found in flipbook\");\n\t\t}\n\t\tthis.pageElements = Array.from(pageElements) as HTMLElement[];\n\t\tthis.leaves.splice(0, this.leaves.length);\n\t\tconst leavesCount = Math.ceil(this.pagesCount / 2);\n\t\tconst maxCoverSize = new Size(this.bookElement.clientWidth / 2, this.bookElement.clientHeight);\n\t\tconst coverSize = maxCoverSize.aspectRatioFit(this.coverAspectRatio);\n\t\tconst leafSize = new Size(\n\t\t\t(coverSize.width * this.leafAspectRatio.width) / this.coverAspectRatio.width,\n\t\t\t(coverSize.height * this.leafAspectRatio.height) / this.coverAspectRatio.height,\n\t\t);\n\t\tthis.bookElement.style.perspective = `${Math.min(leafSize.width * 2, leafSize.height) * 2}px`;\n\t\tthis.pageElements.forEach((pageElement, pageIndex) => {\n\t\t\tpageElement.style.width = `${leafSize.width}px`;\n\t\t\tpageElement.style.height = `${leafSize.height}px`;\n\n\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\tpageElement.dataset.pageIndex = pageIndex.toString();\n\t\t\tpageElement.style[this.isLTR ? \"left\" : \"right\"] =\n\t\t\t\t`${(bookElement.clientWidth - 2 * leafSize.width) / 2}px`;\n\t\t\tpageElement.style.top = `${(bookElement.clientHeight - leafSize.height) / 2}px`;\n\t\t\tpageElement.dataset.pageSemanticName =\n\t\t\t\tthis.pageSemantics?.indexToSemanticName(pageIndex) ?? \"\";\n\t\t\tpageElement.dataset.pageTitle = this.pageSemantics?.indexToTitle(pageIndex) ?? \"\";\n\n\t\t\tconst leafIndex = Math.floor(pageIndex / 2);\n\t\t\tconst isOddPage = (pageIndex + 1) % 2 === 1;\n\t\t\tconst isInitiallyTurned = this.initialTurnedLeaves.has(leafIndex);\n\n\t\t\t// Determine current page based on initial turned leaves\n\t\t\t// Current pages are the first two visible pages after all initially turned leaves\n\t\t\tconst firstVisibleLeafIndex =\n\t\t\t\tthis.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0;\n\t\t\tconst isCurrentPage =\n\t\t\t\tleafIndex === firstVisibleLeafIndex ||\n\t\t\t\t(leafIndex === firstVisibleLeafIndex - 1 && isInitiallyTurned);\n\n\t\t\tpageElement.classList.add(\n\t\t\t\tisOddPage ? \"odd\" : \"even\",\n\t\t\t\t...(isCurrentPage ? [\"current-page\"] : []),\n\t\t\t);\n\t\t\tif (isOddPage) {\n\t\t\t\t// Apply correct initial transform based on turned state\n\t\t\t\tif (isInitiallyTurned) {\n\t\t\t\t\t// Fully turned: rotateY(180) or similar based on direction\n\t\t\t\t\tconst scaleX = -1;\n\t\t\t\t\tconst transform = `translateX(${this.isLTR ? \"100%\" : \"-100%\"})rotateY(${this.isLTR ? \"180deg\" : \"-180deg\"})scaleX(${scaleX})`;\n\t\t\t\t\tpageElement.style.transform = transform;\n\t\t\t\t\tpageElement.style.transformOrigin = this.isLTR ? \"left\" : \"right\";\n\t\t\t\t\tpageElement.style.zIndex = `${pageIndex}`; // Turned pages have lower z-index\n\t\t\t\t} else {\n\t\t\t\t\tpageElement.style.transform = `translateX(${this.isLTR ? `` : `-`}100%)`;\n\t\t\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\t\t}\n\n\t\t\t\tthis.leaves[leafIndex] = new Leaf(\n\t\t\t\t\tleafIndex,\n\t\t\t\t\t[pageElement, undefined],\n\t\t\t\t\tisInitiallyTurned,\n\t\t\t\t\t{\n\t\t\t\t\t\tisLTR: this.isLTR,\n\t\t\t\t\t\tleavesCount: leavesCount,\n\t\t\t\t\t\tpagesCount: this.pagesCount,\n\t\t\t\t\t},\n\t\t\t\t\t(direction: FlipDirection) => {\n\t\t\t\t\t\tconst currentVisiblePageIndices: [number] | [number, number] =\n\t\t\t\t\t\t\tdirection === FlipDirection.Forward\n\t\t\t\t\t\t\t\t? pageIndex + 2 === this.pagesCount\n\t\t\t\t\t\t\t\t\t? [pageIndex + 1]\n\t\t\t\t\t\t\t\t\t: [pageIndex + 1, pageIndex + 2]\n\t\t\t\t\t\t\t\t: pageIndex === 0\n\t\t\t\t\t\t\t\t\t? [pageIndex]\n\t\t\t\t\t\t\t\t\t: [pageIndex - 1, pageIndex];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.prevVisiblePageIndices &&\n\t\t\t\t\t\t\tthis.prevVisiblePageIndices.length === currentVisiblePageIndices.length &&\n\t\t\t\t\t\t\tcurrentVisiblePageIndices.every((v, i) => v === this.prevVisiblePageIndices?.[i])\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prevVisiblePageIndices = this.prevVisiblePageIndices;\n\t\t\t\t\t\tthis.prevVisiblePageIndices = currentVisiblePageIndices;\n\n\t\t\t\t\t\t// TODO expose to outside using https://github.com/open-draft/strict-event-emitter, and just be a consumer internally\n\t\t\t\t\t\tthis.onTurned(currentVisiblePageIndices, prevVisiblePageIndices);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Even page (back side of leaf)\n\t\t\t\tif (isInitiallyTurned) {\n\t\t\t\t\t// Fully turned: apply matching transform for back side\n\t\t\t\t\tconst scaleX = 1;\n\t\t\t\t\tpageElement.style.transform = `translateX(0px)rotateY(${this.isLTR ? \"180deg\" : \"-180deg\"})scaleX(${scaleX})`;\n\t\t\t\t\tpageElement.style.transformOrigin = this.isLTR ? \"right\" : \"left\";\n\t\t\t\t\tpageElement.style.zIndex = `${pageIndex}`; // Turned pages have lower z-index\n\t\t\t\t} else {\n\t\t\t\t\tpageElement.style.transform = `scaleX(-1)translateX(${this.isLTR ? `-` : ``}100%)`;\n\t\t\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\t\t}\n\t\t\t\tthis.leaves[leafIndex].pages[1] = pageElement;\n\t\t\t}\n\t\t});\n\n\t\t// Set initial visible page indices based on initially turned leaves\n\t\tconst firstVisibleLeafIndex =\n\t\t\tthis.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0;\n\t\tconst firstVisiblePageIndex = firstVisibleLeafIndex * 2;\n\n\t\t// Handle edge case where all leaves are turned (showing last page only)\n\t\tif (firstVisiblePageIndex >= this.pagesCount) {\n\t\t\t// All leaves are turned - show the last page(s)\n\t\t\tconst lastLeafIndex = Math.ceil(this.pagesCount / 2) - 1;\n\t\t\tconst lastLeafFirstPage = lastLeafIndex * 2;\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tlastLeafFirstPage + 1 < this.pagesCount\n\t\t\t\t\t? [lastLeafFirstPage, lastLeafFirstPage + 1]\n\t\t\t\t\t: [lastLeafFirstPage];\n\t\t} else {\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tfirstVisiblePageIndex + 1 < this.pagesCount\n\t\t\t\t\t? [firstVisiblePageIndex, firstVisiblePageIndex + 1]\n\t\t\t\t\t: [firstVisiblePageIndex];\n\t\t}\n\n\t\tthis.hammer = new Hammer(this.bookElement);\n\t\tthis.hammer.on(\"panstart\", this.onDragStart.bind(this));\n\t\tthis.hammer.on(\"panmove\", this.onDragUpdate.bind(this));\n\t\tthis.hammer.on(\"panend\", this.onDragEnd.bind(this));\n\t\tthis.bookElement.addEventListener(\"touchstart\", this.handleTouchStart.bind(this), {\n\t\t\tpassive: false,\n\t\t});\n\t\tthis.bookElement.addEventListener(\"touchmove\", this.handleTouchMove.bind(this), {\n\t\t\tpassive: false,\n\t\t});\n\t\tthis.bookElement.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\tthis.handleMouseMove as unknown as EventListener,\n\t\t);\n\t\tthis.bookElement.addEventListener(\"mouseleave\", this.handleMouseLeave as EventListener);\n\t\t// Apply initial leaves buffer visibility\n\t\tthis.updateLeavesBufferVisibility();\n\t\tif (debug) this.fillDebugBar();\n\t}\n\n\t/**\n\t * Update visibility of leaves based on the buffer setting.\n\t * Leaves outside the buffer range are hidden for performance.\n\t */\n\tprivate updateLeavesBufferVisibility(): void {\n\t\tif (this.leavesBuffer === undefined) {\n\t\t\treturn; // No buffer - all leaves stay visible\n\t\t}\n\n\t\tconst leavesCount = this.leaves.length;\n\t\tif (leavesCount === 0) return;\n\n\t\t// Find the current leaf index (the first non-turned leaf, or last leaf if all turned)\n\t\tconst [leftLeaf, rightLeaf] = this.currentOrTurningLeaves;\n\t\tconst currentLeafIndex = rightLeaf?.index ?? leftLeaf?.index ?? 0;\n\n\t\t// Calculate buffer range\n\t\tconst bufferStart = Math.max(0, currentLeafIndex - this.leavesBuffer);\n\t\tconst bufferEnd = Math.min(leavesCount - 1, currentLeafIndex + this.leavesBuffer);\n\n\t\t// Update visibility of all leaves\n\t\tfor (let i = 0; i < leavesCount; i++) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\tconst isWithinBuffer = i >= bufferStart && i <= bufferEnd;\n\n\t\t\t// Update both pages of the leaf\n\t\t\tfor (const page of leaf.pages) {\n\t\t\t\tif (page) {\n\t\t\t\t\tpage.style.display = isWithinBuffer ? \"\" : \"none\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fillDebugBar() {\n\t\tconst debugBar = document.createElement(\"div\");\n\t\tdebugBar.className = \"flipbook-debug-bar\";\n\t\tthis.bookElement?.appendChild(debugBar);\n\t\tsetInterval(() => {\n\t\t\t// Populate debug bar with relevant information\n\t\t\tconst activeFlipsInfo = Array.from(this.activeFlips.entries())\n\t\t\t\t.map(([idx, state]) => `${idx}:${state.leaf.flipPosition.toFixed(2)}`)\n\t\t\t\t.join(\", \");\n\t\t\tdebugBar.innerHTML = `\n <div>Direction: ${this.isLTR ? \"LTR\" : \"RTL\"}</div>\n <div>Active Flips: ${this.activeFlips.size} [${activeFlipsInfo}]</div>\n <div>Pending Flip dir: ${this.pendingFlipDirection}</div>\n `;\n\t\t}, 10);\n\t}\n\n\t/**\n\t * Get the current manually-controlled flip state (the one being dragged).\n\t * Returns undefined if no manual flip is in progress.\n\t */\n\tprivate get currentManualFlip(): FlipState | undefined {\n\t\tfor (const state of this.activeFlips.values()) {\n\t\t\tif (!state.isDuringAutoFlip) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Find the next available leaf for flipping in the given direction.\n\t * Excludes leaves that are already being flipped.\n\t */\n\tprivate getNextAvailableLeaf(direction: FlipDirection): Leaf | undefined {\n\t\tif (direction === FlipDirection.Forward) {\n\t\t\t// Find the rightmost leaf that's not already flipping\n\t\t\t// Start from the current right leaf and go forward\n\t\t\tconst [, rightLeaf] = this.currentOrTurningLeaves;\n\t\t\tif (!rightLeaf) return undefined;\n\n\t\t\t// Find a leaf that's not in activeFlips\n\t\t\tfor (let i = rightLeaf.index; i < this.leaves.length; i++) {\n\t\t\t\tconst leaf = this.leaves[i];\n\t\t\t\tif (!this.activeFlips.has(leaf.index) && !leaf.isTurned) {\n\t\t\t\t\treturn leaf;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} else if (direction === FlipDirection.Backward) {\n\t\t\t// Find the leftmost leaf that's not already flipping\n\t\t\tconst [leftLeaf] = this.currentOrTurningLeaves;\n\t\t\tif (!leftLeaf) return undefined;\n\n\t\t\t// Find a leaf that's not in activeFlips\n\t\t\tfor (let i = leftLeaf.index; i >= 0; i--) {\n\t\t\t\tconst leaf = this.leaves[i];\n\t\t\t\tif (!this.activeFlips.has(leaf.index) && (leaf.isTurned || leaf.isTurning)) {\n\t\t\t\t\treturn leaf;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate onDragStart(event: HammerInput) {\n\t\t// Do not start flip when gesture begins inside a no-flip zone (e.g. horizontal carousel)\n\t\tif (this.isInsideNoFlipZone(event.srcEvent?.target ?? null)) {\n\t\t\treturn;\n\t\t}\n\t\t// Allow starting a new flip even if others are in auto-flip mode\n\t\t// Only block if we already have a manual flip in progress\n\t\tif (this.currentManualFlip) {\n\t\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\t\tthis.pendingFlipStartingPos = 0;\n\t\t\treturn;\n\t\t}\n\t\tthis.isDragging = true;\n\t\tthis.clearHoverShadow();\n\t\tthis.pendingFlipStartingPos = event.center.x;\n\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t}\n\n\tprivate onDragUpdate(event: HammerInput) {\n\t\t// Get or create the current manual flip state\n\t\tlet flipState = this.currentManualFlip;\n\n\t\tconst currentPos = event.center.x;\n\t\tconst bookWidth = this.bookElement?.clientWidth ?? 0;\n\n\t\t// Calculate delta\n\t\tconst delta = this.isLTR\n\t\t\t? this.pendingFlipStartingPos - currentPos\n\t\t\t: currentPos - this.pendingFlipStartingPos;\n\n\t\tif (Math.abs(delta) > bookWidth) return;\n\t\tif (delta === 0) return;\n\n\t\t// Determine direction on first meaningful movement\n\t\tconst direction =\n\t\t\tthis.pendingFlipDirection !== FlipDirection.None\n\t\t\t\t? this.pendingFlipDirection\n\t\t\t\t: delta > 0\n\t\t\t\t\t? FlipDirection.Forward\n\t\t\t\t\t: FlipDirection.Backward;\n\n\t\t// Lock in direction for this flip\n\t\tif (this.pendingFlipDirection === FlipDirection.None) {\n\t\t\tthis.pendingFlipDirection = direction;\n\t\t}\n\n\t\t// Block starting a new flip in opposite direction while auto-flip is in progress\n\t\t// This prevents visual glitches when swiping backward while a forward flip is animating\n\t\tif (!flipState) {\n\t\t\tfor (const state of this.activeFlips.values()) {\n\t\t\t\tif (state.isDuringAutoFlip && state.direction !== direction) {\n\t\t\t\t\t// There's an auto-flip in the opposite direction - block this new flip\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we don't have a flip state yet, create one\n\t\tif (!flipState) {\n\t\t\tconst leaf = this.getNextAvailableLeaf(direction);\n\t\t\tif (!leaf) return;\n\n\t\t\tflipState = {\n\t\t\t\tleaf,\n\t\t\t\tdirection,\n\t\t\t\tstartingPos: this.pendingFlipStartingPos,\n\t\t\t\tdelta: 0,\n\t\t\t\tisDuringAutoFlip: false,\n\t\t\t};\n\t\t\tthis.activeFlips.set(leaf.index, flipState);\n\t\t}\n\n\t\t// Update delta\n\t\tflipState.delta = delta;\n\n\t\t// Calculate and apply flip position\n\t\tswitch (flipState.direction) {\n\t\t\tcase FlipDirection.Forward: {\n\t\t\t\tconst posForward = (delta / bookWidth) as FlipPosition;\n\t\t\t\tif (posForward > 1 || delta < 0) return;\n\t\t\t\tflipState.leaf.efficientFlipToPosition(posForward);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase FlipDirection.Backward: {\n\t\t\t\tconst posBackward = (1 - Math.abs(delta) / bookWidth) as FlipPosition;\n\t\t\t\tif (posBackward < 0 || delta > 0) return;\n\t\t\t\tflipState.leaf.efficientFlipToPosition(posBackward);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onDragEnd(event: HammerInput) {\n\t\tconst flipState = this.currentManualFlip;\n\t\tif (!flipState) {\n\t\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\t\tthis.pendingFlipStartingPos = 0;\n\t\t\tthis.isDragging = false;\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst ppsX = event.velocityX * 1000; // pixels per second\n\t\tlet flipTo: FlipPosition;\n\n\t\tswitch (flipState.direction) {\n\t\t\tcase FlipDirection.Forward:\n\t\t\t\tif (\n\t\t\t\t\t(this.isLTR ? ppsX < -this.fastDeltaThreshold : ppsX > this.fastDeltaThreshold) ||\n\t\t\t\t\tflipState.leaf.flipPosition >= 0.5\n\t\t\t\t) {\n\t\t\t\t\tflipTo = 1;\n\t\t\t\t} else {\n\t\t\t\t\tflipTo = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase FlipDirection.Backward:\n\t\t\t\tif (\n\t\t\t\t\t(this.isLTR ? ppsX > this.fastDeltaThreshold : ppsX < -this.fastDeltaThreshold) ||\n\t\t\t\t\tflipState.leaf.flipPosition <= 0.5\n\t\t\t\t) {\n\t\t\t\t\tflipTo = 0;\n\t\t\t\t} else {\n\t\t\t\t\tflipTo = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Mark as auto-flip and reset pending state\n\t\tflipState.isDuringAutoFlip = true;\n\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\tthis.pendingFlipStartingPos = 0;\n\t\tthis.isDragging = false;\n\n\t\t// Complete the flip asynchronously - don't block new flips!\n\t\tflipState.leaf.flipToPosition(flipTo).then(() => {\n\t\t\tthis.activeFlips.delete(flipState.leaf.index);\n\t\t});\n\t}\n\n\tprivate handleTouchStart = (e: TouchEvent) => {\n\t\tif (e.touches.length > 1) {\n\t\t\treturn;\n\t\t}\n\t\tconst touch = e.touches[0];\n\t\tthis.touchStartingPos = { x: touch.pageX, y: touch.pageY };\n\t\tthis.touchStartedInNoFlipZone = this.isInsideNoFlipZone(e.target);\n\t};\n\n\tprivate handleTouchMove = (e: TouchEvent) => {\n\t\tif (e.touches.length > 1) {\n\t\t\treturn;\n\t\t}\n\t\t// Allow horizontal scroll (e.g. carousel) when touch started inside a no-flip zone\n\t\tif (this.touchStartedInNoFlipZone) {\n\t\t\treturn;\n\t\t}\n\t\tconst touch = e.touches[0];\n\t\tconst deltaX = touch.pageX - this.touchStartingPos.x;\n\t\tconst deltaY = touch.pageY - this.touchStartingPos.y;\n\t\t// only allow vertical scrolling, as if allowing horizontal scrolling, it will interfere with the flip gesture (for touch devices)\n\t\tif (Math.abs(deltaX) > Math.abs(deltaY)) {\n\t\t\te.preventDefault();\n\t\t}\n\t};\n\n\tprivate handleMouseMove = throttle(MOUSE_MOVE_THROTTLE_MS, (event: MouseEvent) => {\n\t\tif (!this.bookElement) return;\n\t\tif (this.isDragging || this.currentManualFlip || this.activeFlips.size > 0) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.bookElement.getBoundingClientRect();\n\t\tif (rect.width <= 0) return;\n\n\t\tconst x = event.clientX - rect.left;\n\t\tconst edgeZone = rect.width * EDGE_ZONE_RATIO;\n\t\tconst isLeftEdge = x <= edgeZone;\n\t\tconst isRightEdge = x >= rect.width - edgeZone;\n\n\t\tif (!isLeftEdge && !isRightEdge) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst isForward = this.isLTR ? isRightEdge : isLeftEdge;\n\t\tconst direction = isForward ? FlipDirection.Forward : FlipDirection.Backward;\n\t\tconst leaf = this.getNextAvailableLeaf(direction);\n\t\tif (!leaf) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst distanceFromEdge = isForward\n\t\t\t? this.isLTR\n\t\t\t\t? rect.width - x\n\t\t\t\t: x\n\t\t\t: this.isLTR\n\t\t\t\t? x\n\t\t\t\t: rect.width - x;\n\t\tconst edgeProgress = 1 - Math.min(1, distanceFromEdge / edgeZone);\n\t\tconst hoverStrength = edgeProgress * HOVER_STRENGTH_MAX;\n\n\t\tif (this.hoveredLeaf && this.hoveredLeaf !== leaf) {\n\t\t\tthis.hoveredLeaf.setHoverShadow(0);\n\t\t}\n\t\tthis.hoveredLeaf = leaf;\n\t\tleaf.setHoverShadow(hoverStrength);\n\t});\n\n\tprivate handleMouseLeave = () => {\n\t\tthis.clearHoverShadow();\n\t};\n\n\tprivate clearHoverShadow() {\n\t\tif (this.hoveredLeaf) {\n\t\t\tthis.hoveredLeaf.setHoverShadow(0);\n\t\t\tthis.hoveredLeaf = undefined;\n\t\t}\n\t}\n\tprivate onTurned(\n\t\tcurrentVisiblePageIndices: [number] | [number, number],\n\t\tprevVisibilePageIndices?: [number] | [number, number],\n\t) {\n\t\tfor (let i = 0; i < this.pageElements.length; i++) {\n\t\t\tconst pageElement = this.pageElements[i];\n\t\t\tconst inCurrent = currentVisiblePageIndices.includes(i);\n\t\t\tconst inPrev = prevVisibilePageIndices?.includes(i);\n\t\t\tconst action = inCurrent\n\t\t\t\t? pageElement.classList.add\n\t\t\t\t: !prevVisibilePageIndices || !inPrev\n\t\t\t\t\t? () => null\n\t\t\t\t\t: pageElement.classList.remove;\n\t\t\taction.bind(pageElement.classList)(\"current-page\");\n\t\t}\n\t\t// Update leaves buffer visibility after turn completes\n\t\tthis.updateLeavesBufferVisibility();\n\t\t// Notify React/consumer so content buffer can update (e.g. mount content for new visible range)\n\t\tif (this.onPageChanged) {\n\t\t\tthis.onPageChanged(this.currentPageIndex);\n\t\t}\n\t\t// TODO expose to outside using https://github.com/open-draft/strict-event-emitter, and just be a consumer internally.\n\t\t// TODO: set prev-page / next-page classes for prev/next pages as accordingally\n\t}\n\t/**\n\t * Get the index of the current (leftmost visible) page.\n\t * Returns 0 if no pages are visible.\n\t */\n\tget currentPageIndex(): number {\n\t\treturn this.prevVisiblePageIndices?.[0] ?? 0;\n\t}\n\n\t/**\n\t * Get the total number of pages in the flipbook.\n\t */\n\tget totalPages(): number {\n\t\treturn this.pagesCount;\n\t}\n\n\t/**\n\t * Check if the book is currently showing the first page(s).\n\t */\n\tget isFirstPage(): boolean {\n\t\treturn this.currentPageIndex === 0;\n\t}\n\n\t/**\n\t * Check if the book is currently showing the last page(s).\n\t */\n\tget isLastPage(): boolean {\n\t\tconst lastPageIndex = this.pagesCount - 1;\n\t\treturn this.prevVisiblePageIndices?.includes(lastPageIndex) ?? false;\n\t}\n\n\t/**\n\t * Check if there's an active auto-flip in the given direction.\n\t */\n\tprivate hasActiveAutoFlipInDirection(direction: FlipDirection): boolean {\n\t\tfor (const state of this.activeFlips.values()) {\n\t\t\tif (state.isDuringAutoFlip && state.direction === direction) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Animate flip to the next page.\n\t * @returns Promise that resolves when the flip animation completes\n\t */\n\tasync flipNext(): Promise<void> {\n\t\t// Block if there's an active auto-flip in the opposite direction\n\t\tif (this.hasActiveAutoFlipInDirection(FlipDirection.Backward)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst leaf = this.getNextAvailableLeaf(FlipDirection.Forward);\n\t\tif (!leaf) return;\n\n\t\tconst flipState: FlipState = {\n\t\t\tleaf,\n\t\t\tdirection: FlipDirection.Forward,\n\t\t\tstartingPos: 0,\n\t\t\tdelta: 0,\n\t\t\tisDuringAutoFlip: true,\n\t\t};\n\t\tthis.activeFlips.set(leaf.index, flipState);\n\n\t\ttry {\n\t\t\tawait leaf.flipToPosition(1);\n\t\t} finally {\n\t\t\tthis.activeFlips.delete(leaf.index);\n\t\t}\n\t}\n\n\t/**\n\t * Animate flip to the previous page.\n\t * @returns Promise that resolves when the flip animation completes\n\t */\n\tasync flipPrev(): Promise<void> {\n\t\t// Block if there's an active auto-flip in the opposite direction\n\t\tif (this.hasActiveAutoFlipInDirection(FlipDirection.Forward)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst leaf = this.getNextAvailableLeaf(FlipDirection.Backward);\n\t\tif (!leaf) return;\n\n\t\tconst flipState: FlipState = {\n\t\t\tleaf,\n\t\t\tdirection: FlipDirection.Backward,\n\t\t\tstartingPos: 0,\n\t\t\tdelta: 0,\n\t\t\tisDuringAutoFlip: true,\n\t\t};\n\t\tthis.activeFlips.set(leaf.index, flipState);\n\n\t\ttry {\n\t\t\tawait leaf.flipToPosition(0);\n\t\t} finally {\n\t\t\tthis.activeFlips.delete(leaf.index);\n\t\t}\n\t}\n\n\t/**\n\t * Animate to a specific page index.\n\t * Flips through pages sequentially to reach the target.\n\t * @param pageIndex - The target page index (0-based)\n\t * @returns Promise that resolves when all flip animations complete\n\t */\n\tasync goToPage(pageIndex: number): Promise<void> {\n\t\tif (pageIndex < 0 || pageIndex >= this.pagesCount) {\n\t\t\tconsole.warn(\n\t\t\t\t`goToPage: Invalid page index ${pageIndex}. Must be between 0 and ${this.pagesCount - 1}.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst targetLeafIndex = Math.floor(pageIndex / 2);\n\t\tconst currentLeafIndex = Math.floor(this.currentPageIndex / 2);\n\n\t\tif (targetLeafIndex === currentLeafIndex) {\n\t\t\treturn; // Already at the target page\n\t\t}\n\n\t\tif (targetLeafIndex > currentLeafIndex) {\n\t\t\t// Flip forward\n\t\t\tfor (let i = currentLeafIndex; i < targetLeafIndex; i++) {\n\t\t\t\tawait this.flipNext();\n\t\t\t}\n\t\t} else {\n\t\t\t// Flip backward\n\t\t\tfor (let i = currentLeafIndex; i > targetLeafIndex; i--) {\n\t\t\t\tawait this.flipPrev();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Jump to a specific page instantly without animation.\n\t * @param pageIndex - The target page index (0-based)\n\t */\n\tjumpToPage(pageIndex: number): void {\n\t\tif (pageIndex < 0 || pageIndex >= this.pagesCount) {\n\t\t\tconsole.warn(\n\t\t\t\t`jumpToPage: Invalid page index ${pageIndex}. Must be between 0 and ${this.pagesCount - 1}.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst targetLeafIndex = Math.floor(pageIndex / 2);\n\t\tconst isLastPage = pageIndex === this.pagesCount - 1;\n\t\tconst isOddPage = pageIndex % 2 === 1;\n\t\t// If targeting the last page and it's odd (back of leaf), close the book reversed\n\t\tconst closeBookReversed = isLastPage && isOddPage;\n\n\t\t// Set all leaves before target as turned, all after as not turned\n\t\tfor (let i = 0; i < this.leaves.length; i++) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\t// Turn leaves before target, or the target leaf itself if closing book reversed\n\t\t\tconst shouldBeTurned = i < targetLeafIndex || (closeBookReversed && i === targetLeafIndex);\n\n\t\t\tif (shouldBeTurned && !leaf.isTurned) {\n\t\t\t\t// Turn this leaf instantly\n\t\t\t\tleaf.flipPosition = 1;\n\t\t\t\tthis.applyLeafTransform(leaf, 1);\n\t\t\t} else if (!shouldBeTurned && leaf.isTurned) {\n\t\t\t\t// Unturn this leaf instantly\n\t\t\t\tleaf.flipPosition = 0;\n\t\t\t\tthis.applyLeafTransform(leaf, 0);\n\t\t\t}\n\t\t}\n\n\t\t// Update visible page indices\n\t\tif (closeBookReversed) {\n\t\t\t// Closed reversed: only show the last page\n\t\t\tthis.prevVisiblePageIndices = [pageIndex];\n\t\t} else {\n\t\t\tconst firstVisiblePageIndex = targetLeafIndex * 2;\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tfirstVisiblePageIndex + 1 < this.pagesCount\n\t\t\t\t\t? [firstVisiblePageIndex, firstVisiblePageIndex + 1]\n\t\t\t\t\t: [firstVisiblePageIndex];\n\t\t}\n\n\t\t// Update current-page classes\n\t\tfor (let i = 0; i < this.pageElements.length; i++) {\n\t\t\tconst pageElement = this.pageElements[i];\n\t\t\tif (this.prevVisiblePageIndices.includes(i)) {\n\t\t\t\tpageElement.classList.add(\"current-page\");\n\t\t\t} else {\n\t\t\t\tpageElement.classList.remove(\"current-page\");\n\t\t\t}\n\t\t}\n\n\t\t// Update leaves buffer visibility\n\t\tthis.updateLeavesBufferVisibility();\n\n\t\t// Notify callback\n\t\tif (this.onPageChanged) {\n\t\t\tthis.onPageChanged(this.currentPageIndex);\n\t\t}\n\t}\n\n\t/**\n\t * Apply transform styles to a leaf's pages for a given flip position.\n\t * Used for instant positioning (jumpToPage).\n\t */\n\tprivate applyLeafTransform(leaf: Leaf, position: number): void {\n\t\tleaf.applyTransform(position);\n\t}\n\n\t/**\n\t * Clean up event listeners and Hammer instance.\n\t * Should be called when the FlipBook is no longer needed.\n\t */\n\tdestroy() {\n\t\tif (this.hammer) {\n\t\t\tthis.hammer.destroy();\n\t\t\tthis.hammer = undefined;\n\t\t}\n\t\tif (this.bookElement) {\n\t\t\tthis.bookElement.removeEventListener(\"touchstart\", this.handleTouchStart as EventListener);\n\t\t\tthis.bookElement.removeEventListener(\"touchmove\", this.handleTouchMove as EventListener);\n\t\t\tthis.bookElement.removeEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\tthis.handleMouseMove as unknown as EventListener,\n\t\t\t);\n\t\t\tthis.bookElement.removeEventListener(\"mouseleave\", this.handleMouseLeave as EventListener);\n\t\t}\n\t}\n}\n\nexport { FlipBook, type PageSemantics };\n"],"names":["FlipDirection","SHADOW_STRENGTH_MULTIPLIER","HIGHLIGHT_STRENGTH_MULTIPLIER","SHADOW_LIFT_PX","Leaf","index","pages","isFlipped","bookProperties","onTurned","value","progress","clamped","flipPosition","velocity","resolve","currentFlipPosition","duration","start","step","timestamp","elapsed","newPosition","throttle","position","clampedPosition","shadowFromFlip","shadowProgress","shadowStrength","highlightStrength","lift","page","isLTR","isOdd","rotateY","translateX","scaleX","origin","edge","AspectRatioImpl","width","height","aspectRatio","Size","rhsAspectRatio","rhsAspectRatioValue","DEFAULT_FAST_DELTA","EDGE_ZONE_RATIO","HOVER_STRENGTH_MAX","MOUSE_MOVE_THROTTLE_MS","FlipBook","el","secondLeafIndex","i","leaf","options","selector","debug","bookElement","pageElements","leavesCount","coverSize","leafSize","pageElement","pageIndex","leafIndex","isOddPage","isInitiallyTurned","firstVisibleLeafIndex","isCurrentPage","transform","direction","currentVisiblePageIndices","v","prevVisiblePageIndices","firstVisiblePageIndex","lastLeafFirstPage","Hammer","leftLeaf","rightLeaf","currentLeafIndex","bufferStart","bufferEnd","isWithinBuffer","debugBar","activeFlipsInfo","idx","state","event","flipState","currentPos","bookWidth","delta","posForward","posBackward","ppsX","flipTo","e","touch","deltaX","deltaY","rect","x","edgeZone","isLeftEdge","isRightEdge","isForward","distanceFromEdge","hoverStrength","prevVisibilePageIndices","inCurrent","inPrev","lastPageIndex","targetLeafIndex","isLastPage","closeBookReversed","shouldBeTurned"],"mappings":"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"}
1
+ {"version":3,"file":"flipbook.js","sources":["../src/flip-direction.ts","../src/leaf.ts","../src/aspect-ratio.ts","../src/size.ts","../src/flipbook.ts"],"sourcesContent":["export enum FlipDirection {\n\tForward = \"Forward\",\n\tBackward = \"Backward\",\n\tNone = \"None\",\n}\n","import { throttle } from \"throttle-debounce\";\nimport type { IntRange } from \"type-fest\";\nimport { FlipDirection } from \"./flip-direction\";\n\n/** Multiplier for shadow intensity (slightly stronger than base) */\nconst SHADOW_STRENGTH_MULTIPLIER = 1.1;\n/** Multiplier for highlight intensity (slightly weaker than base) */\nconst HIGHLIGHT_STRENGTH_MULTIPLIER = 0.9;\n/** Maximum lift in pixels for the shadow effect */\nconst SHADOW_LIFT_PX = 8;\n\n// number between 1 to infinity\nexport type DegreesPerSecond = IntRange<1, typeof Infinity>;\nexport type FlipPosition = IntRange<0, 2>;\nexport const FLIPPED = true;\nexport const NOT_FLIPPED = false;\nexport class Leaf {\n\tprivate currentAnimation: Promise<void> | null = null;\n\tprivate targetFlipPosition: FlipPosition | null = null;\n\tprivate wrappedFlipPosition: number;\n\tprivate hoverShadow = 0;\n\n\tconstructor(\n\t\treadonly index: number,\n\t\treadonly pages: [HTMLElement, HTMLElement | undefined],\n\t\tisFlipped: boolean,\n\t\tprivate readonly bookProperties: {\n\t\t\tisLTR: boolean;\n\t\t\tpagesCount: number;\n\t\t\tleavesCount: number;\n\t\t},\n\t\tprivate readonly onTurned: (direction: FlipDirection) => void,\n\t) {\n\t\tthis.wrappedFlipPosition = isFlipped ? 1 : 0;\n\t\t// TODO: rethink this\n\t\t// if(isFlipped) {\n\t\t// // this.flipToPosition(1);\n\t\t// }\n\t}\n\n\tget isTurned(): boolean {\n\t\treturn this.flipPosition === 1;\n\t}\n\tget isTurning(): boolean {\n\t\treturn this.flipPosition !== 0;\n\t}\n\tget isCover(): boolean {\n\t\treturn this.isFirst || this.isLast;\n\t}\n\tget isFirst(): boolean {\n\t\treturn this.index === 0;\n\t}\n\tget isLast(): boolean {\n\t\treturn this.index === this.bookProperties.leavesCount - 1;\n\t}\n\tset flipPosition(value: number) {\n\t\tthis.wrappedFlipPosition = Math.max(0, Math.min(1, value)) as FlipPosition;\n\t}\n\tget flipPosition(): number {\n\t\treturn this.wrappedFlipPosition;\n\t}\n\n\tsetHoverShadow(progress: number): void {\n\t\tconst clamped = Math.max(0, Math.min(1, progress));\n\t\tif (this.hoverShadow === clamped) return;\n\t\tthis.hoverShadow = clamped;\n\t\tthis.applyTransform(this.flipPosition);\n\t}\n\n\tasync flipToPosition(\n\t\tflipPosition: FlipPosition,\n\t\tvelocity: DegreesPerSecond = 225 as DegreesPerSecond,\n\t) {\n\t\tif (this.currentAnimation) {\n\t\t\tawait this.currentAnimation;\n\t\t}\n\n\t\tif (this.flipPosition === flipPosition) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\n\t\tif (this.targetFlipPosition === flipPosition) {\n\t\t\treturn this.currentAnimation ?? Promise.resolve();\n\t\t}\n\n\t\tthis.targetFlipPosition = flipPosition;\n\n\t\tthis.currentAnimation = new Promise<void>((resolve) => {\n\t\t\tconst currentFlipPosition = this.flipPosition;\n\t\t\tconst distance = Math.abs(flipPosition - currentFlipPosition);\n\t\t\tconst duration = ((distance * 180) / velocity) * 1000; // duration in milliseconds\n\n\t\t\tconst start = performance.now();\n\t\t\tconst step = (timestamp: number) => {\n\t\t\t\tconst elapsed = timestamp - start;\n\n\t\t\t\tif (elapsed < 0) {\n\t\t\t\t\trequestAnimationFrame(step);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst progress = Math.min(elapsed / duration, 1);\n\t\t\t\tconst newPosition = currentFlipPosition + progress * (flipPosition - currentFlipPosition);\n\n\t\t\t\tthis.applyTransform(newPosition);\n\n\t\t\t\t// Ensure the new position is within valid bounds [0, 1]\n\t\t\t\tthis.flipPosition = Math.max(0, Math.min(1, newPosition)) as FlipPosition;\n\t\t\t\tif (this.flipPosition === 1 || this.flipPosition === 0) {\n\t\t\t\t\tthis.onTurned(this.flipPosition === 1 ? FlipDirection.Forward : FlipDirection.Backward);\n\t\t\t\t}\n\t\t\t\t// Detailed log for debugging\n\t\t\t\t// console.log(\n\t\t\t\t// `Timestamp: ${timestamp}, Elapsed: ${elapsed}, Progress: ${progress}, Current Position: ${currentFlipPosition}, Requested Position: ${flipPosition}, New Position: ${this.flipPosition}`\n\t\t\t\t// );\n\n\t\t\t\tif (progress < 1) {\n\t\t\t\t\trequestAnimationFrame(step);\n\t\t\t\t} else {\n\t\t\t\t\tthis.currentAnimation = null;\n\t\t\t\t\tthis.targetFlipPosition = null;\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trequestAnimationFrame(step);\n\t\t});\n\n\t\treturn this.currentAnimation;\n\t}\n\n\tasync efficientFlipToPosition(\n\t\tflipPosition: FlipPosition,\n\t\tvelocity: DegreesPerSecond = 20000 as DegreesPerSecond,\n\t) {\n\t\treturn throttle(1, this.flipToPosition.bind(this))(flipPosition, velocity);\n\t}\n\n\tapplyTransform(position: number): void {\n\t\tconst clampedPosition = Math.max(0, Math.min(1, position));\n\t\tconst shadowFromFlip = Math.sin(clampedPosition * Math.PI);\n\t\tconst shadowProgress = Math.max(shadowFromFlip, this.hoverShadow);\n\t\tconst shadowStrength = Math.min(1, shadowProgress * SHADOW_STRENGTH_MULTIPLIER);\n\t\tconst highlightStrength = Math.min(1, shadowProgress * HIGHLIGHT_STRENGTH_MULTIPLIER);\n\t\tconst lift = `${(shadowProgress * SHADOW_LIFT_PX).toFixed(3)}px`;\n\n\t\tthis.pages.forEach((page, index) => {\n\t\t\tconst isLTR = this.bookProperties.isLTR;\n\t\t\tif (!page) return;\n\n\t\t\tconst isOdd = (index % 2) + 1 === 1;\n\t\t\tconst degrees = isOdd\n\t\t\t\t? isLTR\n\t\t\t\t\t? clampedPosition > 0.5\n\t\t\t\t\t\t? 180 - clampedPosition * 180\n\t\t\t\t\t\t: -clampedPosition * 180\n\t\t\t\t\t: clampedPosition > 0.5\n\t\t\t\t\t\t? -(180 - clampedPosition * 180)\n\t\t\t\t\t\t: clampedPosition * 180\n\t\t\t\t: isLTR\n\t\t\t\t\t? clampedPosition < 0.5\n\t\t\t\t\t\t? -clampedPosition * 180\n\t\t\t\t\t\t: 180 - clampedPosition * 180\n\t\t\t\t\t: clampedPosition < 0.5\n\t\t\t\t\t\t? clampedPosition * 180\n\t\t\t\t\t\t: -(180 - clampedPosition * 180);\n\t\t\tconst rotateY = `${degrees}deg`;\n\t\t\tconst translateX = `${isOdd ? (isLTR ? \"100%\" : \"-100%\") : \"0px\"}`;\n\t\t\tconst scaleX = isOdd ? (clampedPosition > 0.5 ? -1 : 1) : clampedPosition < 0.5 ? -1 : 1;\n\t\t\tconst origin = isOdd ? (isLTR ? \"left\" : \"right\") : isLTR ? \"right\" : \"left\";\n\t\t\tconst edge = origin === \"left\" ? \"right\" : \"left\";\n\n\t\t\tpage.style.transform = `translateX(${translateX})rotateY(${rotateY})scaleX(${scaleX})`;\n\t\t\tpage.style.transformOrigin = origin;\n\t\t\tpage.style.zIndex = `${\n\t\t\t\tclampedPosition > 0.5\n\t\t\t\t\t? page.dataset.pageIndex\n\t\t\t\t\t: this.bookProperties.pagesCount - (page.dataset.pageIndex as unknown as number)\n\t\t\t}`;\n\t\t\tpage.style.setProperty(\"--inner-shadow-shadow\", shadowStrength.toFixed(3));\n\t\t\tpage.style.setProperty(\"--inner-shadow-highlight\", highlightStrength.toFixed(3));\n\t\t\tpage.style.setProperty(\"--inner-shadow-lift\", lift);\n\t\t\tpage.style.setProperty(\"--inner-shadow-edge\", edge);\n\t\t});\n\t}\n}\n","export interface AspectRatio {\n\twidth: number;\n\theight: number;\n}\nexport class AspectRatioImpl implements AspectRatio {\n\tstatic from(aspectRatio: AspectRatio) {\n\t\treturn new AspectRatioImpl(aspectRatio.width, aspectRatio.height);\n\t}\n\tconstructor(\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t) {}\n\tget value(): number {\n\t\treturn this.width / this.height;\n\t}\n}\n","import { type AspectRatio, AspectRatioImpl } from \"./aspect-ratio\";\n\nexport class Size {\n\taspectRatio: AspectRatioImpl;\n\taspectRatioFit(rhsAspectRatio: AspectRatio) {\n\t\tconst rhsAspectRatioValue = AspectRatioImpl.from(rhsAspectRatio).value;\n\t\treturn this.aspectRatio.value > rhsAspectRatioValue\n\t\t\t? new Size(this.height * rhsAspectRatioValue, this.height)\n\t\t\t: new Size(this.width, this.width / rhsAspectRatioValue);\n\t}\n\tconstructor(\n\t\tpublic readonly width: number,\n\t\tpublic readonly height: number,\n\t) {\n\t\tthis.aspectRatio = new AspectRatioImpl(width, height);\n\t}\n\tget asString(): string {\n\t\treturn `${this.width}x${this.height}`;\n\t}\n}\n","import \"./pages.scss\";\nimport \"./flipbook.scss\";\nimport Hammer from \"hammerjs\";\nimport { throttle } from \"throttle-debounce\";\nimport type { AspectRatio } from \"./aspect-ratio\";\nimport type { FlipBookOptions } from \"./flip-book-options\";\nimport { FlipDirection } from \"./flip-direction\";\nimport { type FlipPosition, Leaf } from \"./leaf\";\nimport type { PageSemantics } from \"./page-semantics\";\nimport { Size } from \"./size\";\n\n/** Default threshold for fast flip detection (in ms) */\nconst DEFAULT_FAST_DELTA = 500;\n\n/** Percentage of book width that triggers hover shadow effect */\nconst EDGE_ZONE_RATIO = 0.18;\n/** Maximum hover shadow strength (0-1) */\nconst HOVER_STRENGTH_MAX = 0.12;\n/** Throttle interval for mouse move handler in ms */\nconst MOUSE_MOVE_THROTTLE_MS = 16;\n\n/** State for a single flip operation - enables concurrent page flipping */\ninterface FlipState {\n\tleaf: Leaf;\n\tdirection: FlipDirection;\n\tstartingPos: number;\n\tdelta: number;\n\tisDuringAutoFlip: boolean;\n}\n\n/**\n * Core FlipBook class for creating realistic page-flip animations.\n *\n * @example\n * ```typescript\n * import { FlipBook } from 'html-flip-book-vanilla';\n *\n * const flipBook = new FlipBook({\n * pagesCount: 10,\n * direction: 'ltr',\n * });\n *\n * flipBook.render('#book-container');\n *\n * // Navigate programmatically\n * await flipBook.flipNext();\n * await flipBook.goToPage(5);\n * ```\n */\nclass FlipBook {\n\tbookElement?: HTMLElement;\n\tprivate pageElements: HTMLElement[] = [];\n\tprivate readonly pagesCount: number;\n\tprivate readonly leafAspectRatio: AspectRatio = { width: 2, height: 3 };\n\tprivate readonly coverAspectRatio: AspectRatio = {\n\t\twidth: 2.15,\n\t\theight: 3.15,\n\t};\n\tprivate readonly direction: \"rtl\" | \"ltr\" = \"ltr\";\n\tprivate readonly fastDeltaThreshold: number = DEFAULT_FAST_DELTA;\n\tprivate readonly initialTurnedLeaves: Set<number> = new Set();\n\tprivate readonly onPageChanged?: (pageIndex: number) => void;\n\tprivate readonly pageSemantics: PageSemantics | undefined;\n\tprivate readonly leavesBuffer?: number;\n\tprivate leaves: Leaf[] = [];\n\t// flipping state - supports concurrent page flipping\n\tprivate activeFlips: Map<number, FlipState> = new Map();\n\tprivate pendingFlipStartingPos = 0;\n\tprivate pendingFlipDirection: FlipDirection = FlipDirection.None;\n\tprivate isDragging = false;\n\tprivate hoveredLeaf: Leaf | undefined;\n\ttouchStartingPos = { x: 0, y: 0 };\n\t/** True when the current touch started inside a [data-flipbook-no-flip] element (e.g. carousel). */\n\tprivate touchStartedInNoFlipZone = false;\n\tprivate prevVisiblePageIndices: [number] | [number, number] | undefined;\n\t// Hammer instance for cleanup\n\tprivate hammer: HammerManager | undefined;\n\n\tprivate static readonly NO_FLIP_SELECTOR = \"[data-flipbook-no-flip]\";\n\n\tprivate isInsideNoFlipZone(el: EventTarget | null): boolean {\n\t\treturn el instanceof Element && el.closest(FlipBook.NO_FLIP_SELECTOR) != null;\n\t}\n\tprivate get isLTR(): boolean {\n\t\treturn this.direction === \"ltr\";\n\t}\n\n\tprivate get currentOrTurningLeaves(): [Leaf | undefined, Leaf | undefined] {\n\t\tlet secondLeafIndex = -1;\n\t\tfor (let i = this.leaves.length - 1; i >= 0; i--) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\tif (leaf.isTurned || leaf.isTurning) {\n\t\t\t\tsecondLeafIndex = leaf.index + 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn secondLeafIndex === -1\n\t\t\t? [undefined, this.leaves[0]]\n\t\t\t: secondLeafIndex === this.leaves.length\n\t\t\t\t? [this.leaves[secondLeafIndex - 1], undefined]\n\t\t\t\t: [this.leaves[secondLeafIndex - 1], this.leaves[secondLeafIndex]];\n\t}\n\n\tconstructor(options: FlipBookOptions) {\n\t\tthis.pagesCount = options.pagesCount;\n\t\tthis.leafAspectRatio = options.leafAspectRatio || this.leafAspectRatio;\n\t\tthis.coverAspectRatio = options.coverAspectRatio || this.coverAspectRatio;\n\t\tthis.direction = options.direction || this.direction;\n\t\tthis.fastDeltaThreshold = options.fastDeltaThreshold ?? this.fastDeltaThreshold;\n\t\tthis.initialTurnedLeaves = new Set(options.initialTurnedLeaves ?? []);\n\t\tthis.pageSemantics = options.pageSemantics;\n\t\tthis.onPageChanged = options.onPageChanged;\n\t\tthis.leavesBuffer = options.leavesBuffer;\n\t}\n\n\trender(selector: string, debug = false) {\n\t\tconst bookElement = document.querySelector(selector);\n\t\tif (!bookElement) {\n\t\t\tthrow new Error(`Couldn't find container with selector: ${selector}`);\n\t\t}\n\t\tthis.bookElement = bookElement as HTMLElement;\n\t\tif (!this.bookElement.classList.contains(\"flipbook\")) {\n\t\t\tthis.bookElement.classList.add(\"flipbook\");\n\t\t}\n\n\t\tconst pageElements = bookElement.querySelectorAll(\".page\");\n\t\tif (!pageElements.length) {\n\t\t\tthrow new Error(\"No pages found in flipbook\");\n\t\t}\n\t\tthis.pageElements = Array.from(pageElements) as HTMLElement[];\n\t\tthis.leaves.splice(0, this.leaves.length);\n\t\tconst leavesCount = Math.ceil(this.pagesCount / 2);\n\t\tconst maxCoverSize = new Size(this.bookElement.clientWidth / 2, this.bookElement.clientHeight);\n\t\tconst coverSize = maxCoverSize.aspectRatioFit(this.coverAspectRatio);\n\t\tconst leafSize = new Size(\n\t\t\t(coverSize.width * this.leafAspectRatio.width) / this.coverAspectRatio.width,\n\t\t\t(coverSize.height * this.leafAspectRatio.height) / this.coverAspectRatio.height,\n\t\t);\n\t\tthis.bookElement.style.perspective = `${Math.min(leafSize.width * 2, leafSize.height) * 2}px`;\n\t\tthis.pageElements.forEach((pageElement, pageIndex) => {\n\t\t\tpageElement.style.width = `${leafSize.width}px`;\n\t\t\tpageElement.style.height = `${leafSize.height}px`;\n\n\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\tpageElement.dataset.pageIndex = pageIndex.toString();\n\t\t\tpageElement.style[this.isLTR ? \"left\" : \"right\"] =\n\t\t\t\t`${(bookElement.clientWidth - 2 * leafSize.width) / 2}px`;\n\t\t\tpageElement.style.top = `${(bookElement.clientHeight - leafSize.height) / 2}px`;\n\t\t\tpageElement.dataset.pageSemanticName =\n\t\t\t\tthis.pageSemantics?.indexToSemanticName(pageIndex) ?? \"\";\n\t\t\tpageElement.dataset.pageTitle = this.pageSemantics?.indexToTitle(pageIndex) ?? \"\";\n\n\t\t\tconst leafIndex = Math.floor(pageIndex / 2);\n\t\t\tconst isOddPage = (pageIndex + 1) % 2 === 1;\n\t\t\tconst isInitiallyTurned = this.initialTurnedLeaves.has(leafIndex);\n\n\t\t\t// Determine current page based on initial turned leaves\n\t\t\t// Current pages are the first two visible pages after all initially turned leaves\n\t\t\tconst firstVisibleLeafIndex =\n\t\t\t\tthis.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0;\n\t\t\tconst isCurrentPage =\n\t\t\t\tleafIndex === firstVisibleLeafIndex ||\n\t\t\t\t(leafIndex === firstVisibleLeafIndex - 1 && isInitiallyTurned);\n\n\t\t\tpageElement.classList.add(\n\t\t\t\tisOddPage ? \"odd\" : \"even\",\n\t\t\t\t...(isCurrentPage ? [\"current-page\"] : []),\n\t\t\t);\n\t\t\tif (isOddPage) {\n\t\t\t\t// Apply correct initial transform based on turned state\n\t\t\t\tif (isInitiallyTurned) {\n\t\t\t\t\t// Fully turned: rotateY(180) or similar based on direction\n\t\t\t\t\tconst scaleX = -1;\n\t\t\t\t\tconst transform = `translateX(${this.isLTR ? \"100%\" : \"-100%\"})rotateY(${this.isLTR ? \"180deg\" : \"-180deg\"})scaleX(${scaleX})`;\n\t\t\t\t\tpageElement.style.transform = transform;\n\t\t\t\t\tpageElement.style.transformOrigin = this.isLTR ? \"left\" : \"right\";\n\t\t\t\t\tpageElement.style.zIndex = `${pageIndex}`; // Turned pages have lower z-index\n\t\t\t\t} else {\n\t\t\t\t\tpageElement.style.transform = `translateX(${this.isLTR ? `` : `-`}100%)`;\n\t\t\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\t\t}\n\n\t\t\t\tthis.leaves[leafIndex] = new Leaf(\n\t\t\t\t\tleafIndex,\n\t\t\t\t\t[pageElement, undefined],\n\t\t\t\t\tisInitiallyTurned,\n\t\t\t\t\t{\n\t\t\t\t\t\tisLTR: this.isLTR,\n\t\t\t\t\t\tleavesCount: leavesCount,\n\t\t\t\t\t\tpagesCount: this.pagesCount,\n\t\t\t\t\t},\n\t\t\t\t\t(direction: FlipDirection) => {\n\t\t\t\t\t\tconst currentVisiblePageIndices: [number] | [number, number] =\n\t\t\t\t\t\t\tdirection === FlipDirection.Forward\n\t\t\t\t\t\t\t\t? pageIndex + 2 === this.pagesCount\n\t\t\t\t\t\t\t\t\t? [pageIndex + 1]\n\t\t\t\t\t\t\t\t\t: [pageIndex + 1, pageIndex + 2]\n\t\t\t\t\t\t\t\t: pageIndex === 0\n\t\t\t\t\t\t\t\t\t? [pageIndex]\n\t\t\t\t\t\t\t\t\t: [pageIndex - 1, pageIndex];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tthis.prevVisiblePageIndices &&\n\t\t\t\t\t\t\tthis.prevVisiblePageIndices.length === currentVisiblePageIndices.length &&\n\t\t\t\t\t\t\tcurrentVisiblePageIndices.every((v, i) => v === this.prevVisiblePageIndices?.[i])\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst prevVisiblePageIndices = this.prevVisiblePageIndices;\n\t\t\t\t\t\tthis.prevVisiblePageIndices = currentVisiblePageIndices;\n\n\t\t\t\t\t\t// TODO expose to outside using https://github.com/open-draft/strict-event-emitter, and just be a consumer internally\n\t\t\t\t\t\tthis.onTurned(currentVisiblePageIndices, prevVisiblePageIndices);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Even page (back side of leaf)\n\t\t\t\tif (isInitiallyTurned) {\n\t\t\t\t\t// Fully turned: apply matching transform for back side\n\t\t\t\t\tconst scaleX = 1;\n\t\t\t\t\tpageElement.style.transform = `translateX(0px)rotateY(${this.isLTR ? \"180deg\" : \"-180deg\"})scaleX(${scaleX})`;\n\t\t\t\t\tpageElement.style.transformOrigin = this.isLTR ? \"right\" : \"left\";\n\t\t\t\t\tpageElement.style.zIndex = `${pageIndex}`; // Turned pages have lower z-index\n\t\t\t\t} else {\n\t\t\t\t\tpageElement.style.transform = `scaleX(-1)translateX(${this.isLTR ? `-` : ``}100%)`;\n\t\t\t\t\tpageElement.style.zIndex = `${this.pagesCount - pageIndex}`;\n\t\t\t\t}\n\t\t\t\tthis.leaves[leafIndex].pages[1] = pageElement;\n\t\t\t}\n\t\t});\n\n\t\t// Set initial visible page indices based on initially turned leaves\n\t\tconst firstVisibleLeafIndex =\n\t\t\tthis.initialTurnedLeaves.size > 0 ? Math.max(...this.initialTurnedLeaves) + 1 : 0;\n\t\tconst firstVisiblePageIndex = firstVisibleLeafIndex * 2;\n\n\t\t// Handle edge case where all leaves are turned (showing last page only)\n\t\tif (firstVisiblePageIndex >= this.pagesCount) {\n\t\t\t// All leaves are turned - show the last page(s)\n\t\t\tconst lastLeafIndex = Math.ceil(this.pagesCount / 2) - 1;\n\t\t\tconst lastLeafFirstPage = lastLeafIndex * 2;\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tlastLeafFirstPage + 1 < this.pagesCount\n\t\t\t\t\t? [lastLeafFirstPage, lastLeafFirstPage + 1]\n\t\t\t\t\t: [lastLeafFirstPage];\n\t\t} else {\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tfirstVisiblePageIndex + 1 < this.pagesCount\n\t\t\t\t\t? [firstVisiblePageIndex, firstVisiblePageIndex + 1]\n\t\t\t\t\t: [firstVisiblePageIndex];\n\t\t}\n\n\t\tthis.hammer = new Hammer(this.bookElement);\n\t\tthis.hammer.on(\"panstart\", this.onDragStart.bind(this));\n\t\tthis.hammer.on(\"panmove\", this.onDragUpdate.bind(this));\n\t\tthis.hammer.on(\"panend\", this.onDragEnd.bind(this));\n\t\tthis.bookElement.addEventListener(\"touchstart\", this.handleTouchStart.bind(this), {\n\t\t\tpassive: false,\n\t\t});\n\t\tthis.bookElement.addEventListener(\"touchmove\", this.handleTouchMove.bind(this), {\n\t\t\tpassive: false,\n\t\t});\n\t\tthis.bookElement.addEventListener(\n\t\t\t\"mousemove\",\n\t\t\tthis.handleMouseMove as unknown as EventListener,\n\t\t);\n\t\tthis.bookElement.addEventListener(\"mouseleave\", this.handleMouseLeave as EventListener);\n\t\t// Apply initial leaves buffer visibility\n\t\tthis.updateLeavesBufferVisibility();\n\t\tif (debug) this.fillDebugBar();\n\t}\n\n\t/**\n\t * Update visibility of leaves based on the buffer setting.\n\t * Leaves outside the buffer range are hidden for performance.\n\t */\n\tprivate updateLeavesBufferVisibility(): void {\n\t\tif (this.leavesBuffer === undefined) {\n\t\t\treturn; // No buffer - all leaves stay visible\n\t\t}\n\n\t\tconst leavesCount = this.leaves.length;\n\t\tif (leavesCount === 0) return;\n\n\t\t// Find the current leaf index (the first non-turned leaf, or last leaf if all turned)\n\t\tconst [leftLeaf, rightLeaf] = this.currentOrTurningLeaves;\n\t\tconst currentLeafIndex = rightLeaf?.index ?? leftLeaf?.index ?? 0;\n\n\t\t// Calculate buffer range\n\t\tconst bufferStart = Math.max(0, currentLeafIndex - this.leavesBuffer);\n\t\tconst bufferEnd = Math.min(leavesCount - 1, currentLeafIndex + this.leavesBuffer);\n\n\t\t// Update visibility of all leaves\n\t\tfor (let i = 0; i < leavesCount; i++) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\tconst isWithinBuffer = i >= bufferStart && i <= bufferEnd;\n\n\t\t\t// Update both pages of the leaf\n\t\t\tfor (const page of leaf.pages) {\n\t\t\t\tif (page) {\n\t\t\t\t\tpage.style.display = isWithinBuffer ? \"\" : \"none\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fillDebugBar() {\n\t\tconst debugBar = document.createElement(\"div\");\n\t\tdebugBar.className = \"flipbook-debug-bar\";\n\t\tthis.bookElement?.appendChild(debugBar);\n\t\tsetInterval(() => {\n\t\t\t// Populate debug bar with relevant information\n\t\t\tconst activeFlipsInfo = Array.from(this.activeFlips.entries())\n\t\t\t\t.map(([idx, state]) => `${idx}:${state.leaf.flipPosition.toFixed(2)}`)\n\t\t\t\t.join(\", \");\n\t\t\tdebugBar.innerHTML = `\n <div>Direction: ${this.isLTR ? \"LTR\" : \"RTL\"}</div>\n <div>Active Flips: ${this.activeFlips.size} [${activeFlipsInfo}]</div>\n <div>Pending Flip dir: ${this.pendingFlipDirection}</div>\n `;\n\t\t}, 10);\n\t}\n\n\t/**\n\t * Get the current manually-controlled flip state (the one being dragged).\n\t * Returns undefined if no manual flip is in progress.\n\t */\n\tprivate get currentManualFlip(): FlipState | undefined {\n\t\tfor (const state of this.activeFlips.values()) {\n\t\t\tif (!state.isDuringAutoFlip) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Find the next available leaf for flipping in the given direction.\n\t * Excludes leaves that are already being flipped.\n\t */\n\tprivate getNextAvailableLeaf(direction: FlipDirection): Leaf | undefined {\n\t\tif (direction === FlipDirection.Forward) {\n\t\t\t// Find the rightmost leaf that's not already flipping\n\t\t\t// Start from the current right leaf and go forward\n\t\t\tconst [, rightLeaf] = this.currentOrTurningLeaves;\n\t\t\tif (!rightLeaf) return undefined;\n\n\t\t\t// Find a leaf that's not in activeFlips\n\t\t\tfor (let i = rightLeaf.index; i < this.leaves.length; i++) {\n\t\t\t\tconst leaf = this.leaves[i];\n\t\t\t\tif (!this.activeFlips.has(leaf.index) && !leaf.isTurned) {\n\t\t\t\t\treturn leaf;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} else if (direction === FlipDirection.Backward) {\n\t\t\t// Find the leftmost leaf that's not already flipping\n\t\t\tconst [leftLeaf] = this.currentOrTurningLeaves;\n\t\t\tif (!leftLeaf) return undefined;\n\n\t\t\t// Find a leaf that's not in activeFlips\n\t\t\tfor (let i = leftLeaf.index; i >= 0; i--) {\n\t\t\t\tconst leaf = this.leaves[i];\n\t\t\t\tif (!this.activeFlips.has(leaf.index) && (leaf.isTurned || leaf.isTurning)) {\n\t\t\t\t\treturn leaf;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate onDragStart(event: HammerInput) {\n\t\t// Do not start flip when gesture begins inside a no-flip zone (e.g. horizontal carousel)\n\t\tif (this.isInsideNoFlipZone(event.srcEvent?.target ?? null)) {\n\t\t\treturn;\n\t\t}\n\t\t// Allow starting a new flip even if others are in auto-flip mode\n\t\t// Only block if we already have a manual flip in progress\n\t\tif (this.currentManualFlip) {\n\t\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\t\tthis.pendingFlipStartingPos = 0;\n\t\t\treturn;\n\t\t}\n\t\tthis.isDragging = true;\n\t\tthis.clearHoverShadow();\n\t\tthis.pendingFlipStartingPos = event.center.x;\n\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t}\n\n\tprivate onDragUpdate(event: HammerInput) {\n\t\t// Get or create the current manual flip state\n\t\tlet flipState = this.currentManualFlip;\n\n\t\tconst currentPos = event.center.x;\n\t\tconst bookWidth = this.bookElement?.clientWidth ?? 0;\n\n\t\t// Calculate delta\n\t\tconst delta = this.isLTR\n\t\t\t? this.pendingFlipStartingPos - currentPos\n\t\t\t: currentPos - this.pendingFlipStartingPos;\n\n\t\tif (Math.abs(delta) > bookWidth) return;\n\t\tif (delta === 0) return;\n\n\t\t// Determine direction on first meaningful movement\n\t\tconst direction =\n\t\t\tthis.pendingFlipDirection !== FlipDirection.None\n\t\t\t\t? this.pendingFlipDirection\n\t\t\t\t: delta > 0\n\t\t\t\t\t? FlipDirection.Forward\n\t\t\t\t\t: FlipDirection.Backward;\n\n\t\t// Lock in direction for this flip\n\t\tif (this.pendingFlipDirection === FlipDirection.None) {\n\t\t\tthis.pendingFlipDirection = direction;\n\t\t}\n\n\t\t// Block starting a new flip in opposite direction while auto-flip is in progress\n\t\t// This prevents visual glitches when swiping backward while a forward flip is animating\n\t\tif (!flipState) {\n\t\t\tfor (const state of this.activeFlips.values()) {\n\t\t\t\tif (state.isDuringAutoFlip && state.direction !== direction) {\n\t\t\t\t\t// There's an auto-flip in the opposite direction - block this new flip\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we don't have a flip state yet, create one\n\t\tif (!flipState) {\n\t\t\tconst leaf = this.getNextAvailableLeaf(direction);\n\t\t\tif (!leaf) return;\n\n\t\t\tflipState = {\n\t\t\t\tleaf,\n\t\t\t\tdirection,\n\t\t\t\tstartingPos: this.pendingFlipStartingPos,\n\t\t\t\tdelta: 0,\n\t\t\t\tisDuringAutoFlip: false,\n\t\t\t};\n\t\t\tthis.activeFlips.set(leaf.index, flipState);\n\t\t}\n\n\t\t// Update delta\n\t\tflipState.delta = delta;\n\n\t\t// Calculate and apply flip position\n\t\tswitch (flipState.direction) {\n\t\t\tcase FlipDirection.Forward: {\n\t\t\t\tconst posForward = (delta / bookWidth) as FlipPosition;\n\t\t\t\tif (posForward > 1 || delta < 0) return;\n\t\t\t\tflipState.leaf.efficientFlipToPosition(posForward);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase FlipDirection.Backward: {\n\t\t\t\tconst posBackward = (1 - Math.abs(delta) / bookWidth) as FlipPosition;\n\t\t\t\tif (posBackward < 0 || delta > 0) return;\n\t\t\t\tflipState.leaf.efficientFlipToPosition(posBackward);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onDragEnd(event: HammerInput) {\n\t\tconst flipState = this.currentManualFlip;\n\t\tif (!flipState) {\n\t\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\t\tthis.pendingFlipStartingPos = 0;\n\t\t\tthis.isDragging = false;\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst ppsX = event.velocityX * 1000; // pixels per second\n\t\tlet flipTo: FlipPosition;\n\n\t\tswitch (flipState.direction) {\n\t\t\tcase FlipDirection.Forward:\n\t\t\t\tif (\n\t\t\t\t\t(this.isLTR ? ppsX < -this.fastDeltaThreshold : ppsX > this.fastDeltaThreshold) ||\n\t\t\t\t\tflipState.leaf.flipPosition >= 0.5\n\t\t\t\t) {\n\t\t\t\t\tflipTo = 1;\n\t\t\t\t} else {\n\t\t\t\t\tflipTo = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase FlipDirection.Backward:\n\t\t\t\tif (\n\t\t\t\t\t(this.isLTR ? ppsX > this.fastDeltaThreshold : ppsX < -this.fastDeltaThreshold) ||\n\t\t\t\t\tflipState.leaf.flipPosition <= 0.5\n\t\t\t\t) {\n\t\t\t\t\tflipTo = 0;\n\t\t\t\t} else {\n\t\t\t\t\tflipTo = 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Mark as auto-flip and reset pending state\n\t\tflipState.isDuringAutoFlip = true;\n\t\tthis.pendingFlipDirection = FlipDirection.None;\n\t\tthis.pendingFlipStartingPos = 0;\n\t\tthis.isDragging = false;\n\n\t\t// Complete the flip asynchronously - don't block new flips!\n\t\tflipState.leaf.flipToPosition(flipTo).then(() => {\n\t\t\tthis.activeFlips.delete(flipState.leaf.index);\n\t\t});\n\t}\n\n\tprivate handleTouchStart = (e: TouchEvent) => {\n\t\tif (e.touches.length > 1) {\n\t\t\treturn;\n\t\t}\n\t\tconst touch = e.touches[0];\n\t\tthis.touchStartingPos = { x: touch.pageX, y: touch.pageY };\n\t\tthis.touchStartedInNoFlipZone = this.isInsideNoFlipZone(e.target);\n\t};\n\n\tprivate handleTouchMove = (e: TouchEvent) => {\n\t\tif (e.touches.length > 1) {\n\t\t\treturn;\n\t\t}\n\t\t// Allow horizontal scroll (e.g. carousel) when touch started inside a no-flip zone\n\t\tif (this.touchStartedInNoFlipZone) {\n\t\t\treturn;\n\t\t}\n\t\tconst touch = e.touches[0];\n\t\tconst deltaX = touch.pageX - this.touchStartingPos.x;\n\t\tconst deltaY = touch.pageY - this.touchStartingPos.y;\n\t\t// only allow vertical scrolling, as if allowing horizontal scrolling, it will interfere with the flip gesture (for touch devices)\n\t\tif (Math.abs(deltaX) > Math.abs(deltaY)) {\n\t\t\te.preventDefault();\n\t\t}\n\t};\n\n\tprivate handleMouseMove = throttle(MOUSE_MOVE_THROTTLE_MS, (event: MouseEvent) => {\n\t\tif (!this.bookElement) return;\n\t\tif (this.isDragging || this.currentManualFlip || this.activeFlips.size > 0) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.bookElement.getBoundingClientRect();\n\t\tif (rect.width <= 0) return;\n\n\t\tconst x = event.clientX - rect.left;\n\t\tconst edgeZone = rect.width * EDGE_ZONE_RATIO;\n\t\tconst isLeftEdge = x <= edgeZone;\n\t\tconst isRightEdge = x >= rect.width - edgeZone;\n\n\t\tif (!isLeftEdge && !isRightEdge) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst isForward = this.isLTR ? isRightEdge : isLeftEdge;\n\t\tconst direction = isForward ? FlipDirection.Forward : FlipDirection.Backward;\n\t\tconst leaf = this.getNextAvailableLeaf(direction);\n\t\tif (!leaf) {\n\t\t\tthis.clearHoverShadow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst distanceFromEdge = isForward\n\t\t\t? this.isLTR\n\t\t\t\t? rect.width - x\n\t\t\t\t: x\n\t\t\t: this.isLTR\n\t\t\t\t? x\n\t\t\t\t: rect.width - x;\n\t\tconst edgeProgress = 1 - Math.min(1, distanceFromEdge / edgeZone);\n\t\tconst hoverStrength = edgeProgress * HOVER_STRENGTH_MAX;\n\n\t\tif (this.hoveredLeaf && this.hoveredLeaf !== leaf) {\n\t\t\tthis.hoveredLeaf.setHoverShadow(0);\n\t\t}\n\t\tthis.hoveredLeaf = leaf;\n\t\tleaf.setHoverShadow(hoverStrength);\n\t});\n\n\tprivate handleMouseLeave = () => {\n\t\tthis.clearHoverShadow();\n\t};\n\n\tprivate clearHoverShadow() {\n\t\tif (this.hoveredLeaf) {\n\t\t\tthis.hoveredLeaf.setHoverShadow(0);\n\t\t\tthis.hoveredLeaf = undefined;\n\t\t}\n\t}\n\tprivate onTurned(\n\t\tcurrentVisiblePageIndices: [number] | [number, number],\n\t\tprevVisibilePageIndices?: [number] | [number, number],\n\t) {\n\t\tfor (let i = 0; i < this.pageElements.length; i++) {\n\t\t\tconst pageElement = this.pageElements[i];\n\t\t\tconst inCurrent = currentVisiblePageIndices.includes(i);\n\t\t\tconst inPrev = prevVisibilePageIndices?.includes(i);\n\t\t\tconst action = inCurrent\n\t\t\t\t? pageElement.classList.add\n\t\t\t\t: !prevVisibilePageIndices || !inPrev\n\t\t\t\t\t? () => null\n\t\t\t\t\t: pageElement.classList.remove;\n\t\t\taction.bind(pageElement.classList)(\"current-page\");\n\t\t}\n\t\t// Update leaves buffer visibility after turn completes\n\t\tthis.updateLeavesBufferVisibility();\n\t\t// Notify React/consumer so content buffer can update (e.g. mount content for new visible range)\n\t\tif (this.onPageChanged) {\n\t\t\tthis.onPageChanged(this.currentPageIndex);\n\t\t}\n\t\t// TODO expose to outside using https://github.com/open-draft/strict-event-emitter, and just be a consumer internally.\n\t\t// TODO: set prev-page / next-page classes for prev/next pages as accordingally\n\t}\n\t/**\n\t * Get the index of the current (leftmost visible) page.\n\t * Returns 0 if no pages are visible.\n\t */\n\tget currentPageIndex(): number {\n\t\treturn this.prevVisiblePageIndices?.[0] ?? 0;\n\t}\n\n\t/**\n\t * Get the total number of pages in the flipbook.\n\t */\n\tget totalPages(): number {\n\t\treturn this.pagesCount;\n\t}\n\n\t/**\n\t * Check if the book is currently showing the first page(s).\n\t */\n\tget isFirstPage(): boolean {\n\t\treturn this.currentPageIndex === 0;\n\t}\n\n\t/**\n\t * Check if the book is currently showing the last page(s).\n\t */\n\tget isLastPage(): boolean {\n\t\tconst lastPageIndex = this.pagesCount - 1;\n\t\treturn this.prevVisiblePageIndices?.includes(lastPageIndex) ?? false;\n\t}\n\n\t/**\n\t * Check if there's an active auto-flip in the given direction.\n\t */\n\tprivate hasActiveAutoFlipInDirection(direction: FlipDirection): boolean {\n\t\tfor (const state of this.activeFlips.values()) {\n\t\t\tif (state.isDuringAutoFlip && state.direction === direction) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Animate flip to the next page.\n\t * @returns Promise that resolves when the flip animation completes\n\t */\n\tasync flipNext(): Promise<void> {\n\t\t// Block if there's an active auto-flip in the opposite direction\n\t\tif (this.hasActiveAutoFlipInDirection(FlipDirection.Backward)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst leaf = this.getNextAvailableLeaf(FlipDirection.Forward);\n\t\tif (!leaf) return;\n\n\t\tconst flipState: FlipState = {\n\t\t\tleaf,\n\t\t\tdirection: FlipDirection.Forward,\n\t\t\tstartingPos: 0,\n\t\t\tdelta: 0,\n\t\t\tisDuringAutoFlip: true,\n\t\t};\n\t\tthis.activeFlips.set(leaf.index, flipState);\n\n\t\ttry {\n\t\t\tawait leaf.flipToPosition(1);\n\t\t} finally {\n\t\t\tthis.activeFlips.delete(leaf.index);\n\t\t}\n\t}\n\n\t/**\n\t * Animate flip to the previous page.\n\t * @returns Promise that resolves when the flip animation completes\n\t */\n\tasync flipPrev(): Promise<void> {\n\t\t// Block if there's an active auto-flip in the opposite direction\n\t\tif (this.hasActiveAutoFlipInDirection(FlipDirection.Forward)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst leaf = this.getNextAvailableLeaf(FlipDirection.Backward);\n\t\tif (!leaf) return;\n\n\t\tconst flipState: FlipState = {\n\t\t\tleaf,\n\t\t\tdirection: FlipDirection.Backward,\n\t\t\tstartingPos: 0,\n\t\t\tdelta: 0,\n\t\t\tisDuringAutoFlip: true,\n\t\t};\n\t\tthis.activeFlips.set(leaf.index, flipState);\n\n\t\ttry {\n\t\t\tawait leaf.flipToPosition(0);\n\t\t} finally {\n\t\t\tthis.activeFlips.delete(leaf.index);\n\t\t}\n\t}\n\n\t/**\n\t * Animate to a specific page index.\n\t * Flips through pages sequentially to reach the target.\n\t * @param pageIndex - The target page index (0-based)\n\t * @returns Promise that resolves when all flip animations complete\n\t */\n\tasync goToPage(pageIndex: number): Promise<void> {\n\t\tif (pageIndex < 0 || pageIndex >= this.pagesCount) {\n\t\t\tconsole.warn(\n\t\t\t\t`goToPage: Invalid page index ${pageIndex}. Must be between 0 and ${this.pagesCount - 1}.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst targetLeafIndex = Math.floor(pageIndex / 2);\n\t\tconst currentLeafIndex = Math.floor(this.currentPageIndex / 2);\n\n\t\tif (targetLeafIndex === currentLeafIndex) {\n\t\t\treturn; // Already at the target page\n\t\t}\n\n\t\tif (targetLeafIndex > currentLeafIndex) {\n\t\t\t// Flip forward\n\t\t\tfor (let i = currentLeafIndex; i < targetLeafIndex; i++) {\n\t\t\t\tawait this.flipNext();\n\t\t\t}\n\t\t} else {\n\t\t\t// Flip backward\n\t\t\tfor (let i = currentLeafIndex; i > targetLeafIndex; i--) {\n\t\t\t\tawait this.flipPrev();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Jump to a specific page instantly without animation.\n\t * @param pageIndex - The target page index (0-based)\n\t */\n\tjumpToPage(pageIndex: number): void {\n\t\tif (pageIndex < 0 || pageIndex >= this.pagesCount) {\n\t\t\tconsole.warn(\n\t\t\t\t`jumpToPage: Invalid page index ${pageIndex}. Must be between 0 and ${this.pagesCount - 1}.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst isLastPage = pageIndex === this.pagesCount - 1;\n\t\tconst isOddPage = pageIndex % 2 === 1;\n\t\t// If targeting the last page and it's odd (back of leaf), close the book reversed\n\t\tconst closeBookReversed = isLastPage && isOddPage;\n\n\t\t// Determine which leaf should be the last one turned.\n\t\t// A leaf's pages are visible as follows:\n\t\t// - At position 0 (not turned): its even page (front) is visible\n\t\t// - At position 1 (turned): its odd page (back) is visible\n\t\t// The visible spread after turning leaf k is [2k+1, 2k+2]:\n\t\t// back of leaf k (odd) + front of leaf k+1 (even).\n\t\t// For page 0, no leaves need to be turned (initial spread [0, 1]).\n\t\tlet lastTurnedLeafIndex: number;\n\t\tif (pageIndex <= 0) {\n\t\t\tlastTurnedLeafIndex = -1; // No leaves turned\n\t\t} else if (closeBookReversed) {\n\t\t\tlastTurnedLeafIndex = this.leaves.length - 1; // All leaves turned\n\t\t} else {\n\t\t\tlastTurnedLeafIndex = Math.floor((pageIndex - 1) / 2);\n\t\t}\n\n\t\t// Set all leaves up to lastTurnedLeafIndex as turned, all after as not turned\n\t\tfor (let i = 0; i < this.leaves.length; i++) {\n\t\t\tconst leaf = this.leaves[i];\n\t\t\tconst shouldBeTurned = i <= lastTurnedLeafIndex;\n\n\t\t\tif (shouldBeTurned && !leaf.isTurned) {\n\t\t\t\t// Turn this leaf instantly\n\t\t\t\tleaf.flipPosition = 1;\n\t\t\t\tthis.applyLeafTransform(leaf, 1);\n\t\t\t} else if (!shouldBeTurned && leaf.isTurned) {\n\t\t\t\t// Unturn this leaf instantly\n\t\t\t\tleaf.flipPosition = 0;\n\t\t\t\tthis.applyLeafTransform(leaf, 0);\n\t\t\t}\n\t\t}\n\n\t\t// Update visible page indices\n\t\tif (closeBookReversed) {\n\t\t\t// Closed reversed: only show the last page\n\t\t\tthis.prevVisiblePageIndices = [pageIndex];\n\t\t} else if (lastTurnedLeafIndex < 0) {\n\t\t\t// No leaves turned: initial spread\n\t\t\tthis.prevVisiblePageIndices = 1 < this.pagesCount ? [0, 1] : [0];\n\t\t} else {\n\t\t\tconst firstVisiblePageIndex = lastTurnedLeafIndex * 2 + 1;\n\t\t\tthis.prevVisiblePageIndices =\n\t\t\t\tfirstVisiblePageIndex + 1 < this.pagesCount\n\t\t\t\t\t? [firstVisiblePageIndex, firstVisiblePageIndex + 1]\n\t\t\t\t\t: [firstVisiblePageIndex];\n\t\t}\n\n\t\t// Update current-page classes\n\t\tfor (let i = 0; i < this.pageElements.length; i++) {\n\t\t\tconst pageElement = this.pageElements[i];\n\t\t\tif (this.prevVisiblePageIndices.includes(i)) {\n\t\t\t\tpageElement.classList.add(\"current-page\");\n\t\t\t} else {\n\t\t\t\tpageElement.classList.remove(\"current-page\");\n\t\t\t}\n\t\t}\n\n\t\t// Update leaves buffer visibility\n\t\tthis.updateLeavesBufferVisibility();\n\n\t\t// Notify callback\n\t\tif (this.onPageChanged) {\n\t\t\tthis.onPageChanged(this.currentPageIndex);\n\t\t}\n\t}\n\n\t/**\n\t * Apply transform styles to a leaf's pages for a given flip position.\n\t * Used for instant positioning (jumpToPage).\n\t */\n\tprivate applyLeafTransform(leaf: Leaf, position: number): void {\n\t\tleaf.applyTransform(position);\n\t}\n\n\t/**\n\t * Clean up event listeners and Hammer instance.\n\t * Should be called when the FlipBook is no longer needed.\n\t */\n\tdestroy() {\n\t\tif (this.hammer) {\n\t\t\tthis.hammer.destroy();\n\t\t\tthis.hammer = undefined;\n\t\t}\n\t\tif (this.bookElement) {\n\t\t\tthis.bookElement.removeEventListener(\"touchstart\", this.handleTouchStart as EventListener);\n\t\t\tthis.bookElement.removeEventListener(\"touchmove\", this.handleTouchMove as EventListener);\n\t\t\tthis.bookElement.removeEventListener(\n\t\t\t\t\"mousemove\",\n\t\t\t\tthis.handleMouseMove as unknown as EventListener,\n\t\t\t);\n\t\t\tthis.bookElement.removeEventListener(\"mouseleave\", this.handleMouseLeave as EventListener);\n\t\t}\n\t}\n}\n\nexport { FlipBook, type PageSemantics };\n"],"names":["FlipDirection","SHADOW_STRENGTH_MULTIPLIER","HIGHLIGHT_STRENGTH_MULTIPLIER","SHADOW_LIFT_PX","Leaf","index","pages","isFlipped","bookProperties","onTurned","value","progress","clamped","flipPosition","velocity","resolve","currentFlipPosition","duration","start","step","timestamp","elapsed","newPosition","throttle","position","clampedPosition","shadowFromFlip","shadowProgress","shadowStrength","highlightStrength","lift","page","isLTR","isOdd","rotateY","translateX","scaleX","origin","edge","AspectRatioImpl","width","height","aspectRatio","Size","rhsAspectRatio","rhsAspectRatioValue","DEFAULT_FAST_DELTA","EDGE_ZONE_RATIO","HOVER_STRENGTH_MAX","MOUSE_MOVE_THROTTLE_MS","FlipBook","el","secondLeafIndex","i","leaf","options","selector","debug","bookElement","pageElements","leavesCount","coverSize","leafSize","pageElement","pageIndex","leafIndex","isOddPage","isInitiallyTurned","firstVisibleLeafIndex","isCurrentPage","transform","direction","currentVisiblePageIndices","v","prevVisiblePageIndices","firstVisiblePageIndex","lastLeafFirstPage","Hammer","leftLeaf","rightLeaf","currentLeafIndex","bufferStart","bufferEnd","isWithinBuffer","debugBar","activeFlipsInfo","idx","state","event","flipState","currentPos","bookWidth","delta","posForward","posBackward","ppsX","flipTo","e","touch","deltaX","deltaY","rect","x","edgeZone","isLeftEdge","isRightEdge","isForward","distanceFromEdge","hoverStrength","prevVisibilePageIndices","inCurrent","inPrev","lastPageIndex","targetLeafIndex","isLastPage","closeBookReversed","lastTurnedLeafIndex","shouldBeTurned"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "html-flip-book-vanilla",
3
- "version": "0.0.0-alpha.21",
3
+ "version": "0.0.0-alpha.23",
4
4
  "description": "Flipbook component for HTML (vanilla JavaScript)",
5
5
  "author": "DoradSoft",
6
6
  "type": "module",