@openpageflip/core 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,60 @@
1
1
  # @openpageflip/core
2
2
 
3
- Framework-agnostic page-turn engine. Successor to [`page-flip`](https://www.npmjs.com/package/page-flip) (StPageFlip).
3
+ Framework-agnostic page-turn engine. Successor to [`page-flip`](https://www.npmjs.com/package/page-flip) (StPageFlip): the same look, pixel-matched against the original in the test suite, on modern internals.
4
4
 
5
- Pre-1.0 and under construction. The plan, decisions and status live in the [repository's SPEC.md](https://github.com/benhonda/openpageflip/blob/main/SPEC.md).
5
+ Docs, live demos, the API reference and the changelog: **https://benhonda.github.io/openpageflip/**
6
6
 
7
7
  ```sh
8
8
  bun add @openpageflip/core
9
9
  ```
10
10
 
11
+ The container's children are the pages. `data-density="hard"` makes a page rigid.
12
+
13
+ <!-- example: apps/docs/src/examples/core/pages.html -->
14
+ ```html
15
+ <div id="book">
16
+ <div class="page page-cover" data-density="hard">
17
+ <h2>OpenPageFlip</h2>
18
+ <p>A page-turn effect for the web</p>
19
+ </div>
20
+ <div class="page">
21
+ <h3>Drag a corner</h3>
22
+ <p>Pick up any corner and pull. Let go past the middle and the page turns. Let go early and it settles back.</p>
23
+ </div>
24
+ <div class="page">
25
+ <h3>Or just click</h3>
26
+ <p>A click on either half turns the page that way. On a touch screen, a swipe does the same.</p>
27
+ </div>
28
+ <div class="page">
29
+ <h3>Hard and soft</h3>
30
+ <p>Covers are hard: they swing as one rigid sheet. Inner pages bend along the fold, like paper.</p>
31
+ </div>
32
+ <div class="page">
33
+ <h3>Any HTML</h3>
34
+ <p>Pages are ordinary elements. Text, images, forms, video: whatever a page holds keeps working.</p>
35
+ </div>
36
+ <div class="page page-cover" data-density="hard">
37
+ <p>The end</p>
38
+ </div>
39
+ </div>
40
+ ```
41
+ <!-- /example -->
42
+
43
+ <!-- example: apps/docs/src/examples/core/quickstart.ts -->
11
44
  ```ts
12
45
  import "@openpageflip/core/styles.css";
13
- import { Layout } from "@openpageflip/core";
46
+ import { type Book, createBook } from "@openpageflip/core";
47
+
48
+ /** The container's children are the pages, in reading order. */
49
+ export function mount(container: HTMLElement): Book {
50
+ return createBook(container, {
51
+ width: 400, // base page size; with size "stretch" only the ratio matters
52
+ height: 560,
53
+ size: "stretch", // scale to the container, portrait when it gets narrow
54
+ cover: true, // first and last pages stand alone
55
+ });
56
+ }
14
57
  ```
58
+ <!-- /example -->
15
59
 
16
- A CDN build is published as `dist/index.iife.js` and exposes `window.OpenPageFlip`.
60
+ The code above is the docs site's own example and runs in its test suite. Pre-1.0: the plan, decisions and status live in the repository's [SPEC.md](https://github.com/benhonda/openpageflip/blob/main/SPEC.md).
package/dist/index.d.ts CHANGED
@@ -1,3 +1,22 @@
1
+ //#region src/animation.d.ts
2
+ /** Time and frame sources, injectable so tests can step animations by hand. */
3
+ type Clock = {
4
+ now(): number;
5
+ requestFrame(callback: (time: number) => void): number;
6
+ cancelFrame(handle: number): void;
7
+ };
8
+ //#endregion
9
+ //#region src/events.d.ts
10
+ type Listener<T> = (event: T) => void;
11
+ type Emitter<Events extends Record<string, unknown>> = {
12
+ on<K extends keyof Events>(name: K, listener: Listener<Events[K]>, options?: {
13
+ signal?: AbortSignal;
14
+ }): () => void;
15
+ off<K extends keyof Events>(name: K, listener: Listener<Events[K]>): void;
16
+ emit<K extends keyof Events>(name: K, event: Events[K]): void;
17
+ clear(): void;
18
+ };
19
+ //#endregion
1
20
  //#region src/options.d.ts
2
21
  /**
3
22
  * Public option vocabularies. Plain `as const` objects instead of enums so they survive
@@ -10,12 +29,6 @@ declare const Layout: {
10
29
  readonly spread: "spread";
11
30
  };
12
31
  type Layout = (typeof Layout)[keyof typeof Layout];
13
- /** Reading direction. `rtl` flips the spine to the right for manga and Hebrew/Arabic books. */
14
- declare const Direction: {
15
- readonly ltr: "ltr";
16
- readonly rtl: "rtl";
17
- };
18
- type Direction = (typeof Direction)[keyof typeof Direction];
19
32
  /** Which corner a programmatic flip lifts. */
20
33
  declare const FlipCorner: {
21
34
  readonly top: "top";
@@ -28,6 +41,270 @@ declare const PageDensity: {
28
41
  readonly hard: "hard";
29
42
  };
30
43
  type PageDensity = (typeof PageDensity)[keyof typeof PageDensity];
44
+ /** Which way a page is turning: `forward` reads on, `back` returns to the previous spread. */
45
+ declare const FlipDirection: {
46
+ readonly forward: "forward";
47
+ readonly back: "back";
48
+ };
49
+ type FlipDirection = (typeof FlipDirection)[keyof typeof FlipDirection];
50
+ /** What the book is showing: one page (`portrait`) or a two-page spread (`landscape`). */
51
+ declare const Orientation: {
52
+ readonly portrait: "portrait";
53
+ readonly landscape: "landscape";
54
+ };
55
+ type Orientation = (typeof Orientation)[keyof typeof Orientation];
56
+ /** What the book is doing right now. */
57
+ declare const FlipState: {
58
+ /** Nothing in motion. */
59
+ readonly read: "read";
60
+ /** A corner is lifted because the pointer hovers over it. */
61
+ readonly foldCorner: "fold_corner";
62
+ /** The user is dragging a corner. */
63
+ readonly userFold: "user_fold";
64
+ /** A flip animation is running. */
65
+ readonly flipping: "flipping";
66
+ };
67
+ type FlipState = (typeof FlipState)[keyof typeof FlipState];
68
+ /** How the book sizes itself. */
69
+ declare const SizeMode: {
70
+ /** Pages are exactly `width` x `height` CSS pixels. */
71
+ readonly fixed: "fixed";
72
+ /** Pages scale to the container, keeping the `width:height` ratio, between `minWidth` and `maxWidth`. */
73
+ readonly stretch: "stretch";
74
+ };
75
+ type SizeMode = (typeof SizeMode)[keyof typeof SizeMode];
76
+ /** When a click or tap turns the page. */
77
+ declare const ClickMode: {
78
+ readonly anywhere: "anywhere";
79
+ readonly corners: "corners";
80
+ readonly off: "off";
81
+ };
82
+ type ClickMode = (typeof ClickMode)[keyof typeof ClickMode];
83
+ type BookOptions = {
84
+ /** Base page width in CSS pixels. With `size: "stretch"` only the `width:height` ratio matters. */
85
+ readonly width: number;
86
+ /** Base page height in CSS pixels. */
87
+ readonly height: number;
88
+ /** @default "fixed" */
89
+ readonly size?: SizeMode;
90
+ /** Narrowest single page in `stretch` mode; below twice this the book goes portrait. @default 100 */
91
+ readonly minWidth?: number;
92
+ /** Widest single page in `stretch` mode. @default 2000 */
93
+ readonly maxWidth?: number;
94
+ /** @default "auto" */
95
+ readonly layout?: Layout;
96
+ /** Show the first and last pages alone, as hard covers. @default false */
97
+ readonly cover?: boolean;
98
+ /** Zero-based page to open on. @default 0 */
99
+ readonly startPage?: number;
100
+ /** Duration of a full flip in milliseconds. Shorter flips take proportionally less. @default 1000 */
101
+ readonly flipDuration?: number;
102
+ /** Easing for the corner's path, `t` in 0..1. @default linear */
103
+ readonly easing?: (t: number) => number;
104
+ /** @default true */
105
+ readonly shadows?: boolean;
106
+ /** 0 hides shadows, 1 is full strength. @default 1 */
107
+ readonly shadowOpacity?: number;
108
+ /** Size the container to the book (aspect ratio and max width). @default true */
109
+ readonly autoSize?: boolean;
110
+ /** @default "anywhere" */
111
+ readonly click?: ClickMode;
112
+ /** Let the pointer drag a corner. @default true */
113
+ readonly drag?: boolean;
114
+ /** Turn the page on a quick horizontal swipe. @default true */
115
+ readonly swipe?: boolean;
116
+ /** Minimum swipe travel in CSS pixels. @default 30 */
117
+ readonly swipeDistance?: number;
118
+ /** Lift a corner when the mouse hovers over it. @default true */
119
+ readonly hoverCorners?: boolean;
120
+ /**
121
+ * Pointer events starting on an element matching this selector never start a flip.
122
+ * `false` turns this off.
123
+ * @default "a, button, input, textarea, select, [data-opf-no-flip]"
124
+ */
125
+ readonly ignoreDragOn?: string | false;
126
+ /** Page elements. @default the container's children */
127
+ readonly pages?: Iterable<HTMLElement>;
128
+ };
129
+ type ResolvedOptions = Required<Omit<BookOptions, "pages">>;
130
+ //#endregion
131
+ //#region src/layout.d.ts
132
+ /** Where the book sits inside its container, in container CSS pixels. */
133
+ type BookRect = {
134
+ readonly left: number;
135
+ readonly top: number;
136
+ /** Always two pages wide, even in portrait, where only the right half is visible. */
137
+ readonly width: number;
138
+ readonly height: number;
139
+ readonly pageWidth: number;
140
+ };
141
+ type LayoutResult = {
142
+ readonly orientation: Orientation;
143
+ readonly rect: BookRect;
144
+ };
145
+ type LayoutOptions = Pick<ResolvedOptions, "size" | "width" | "height" | "minWidth" | "maxWidth" | "layout">;
146
+ /**
147
+ * Page size and orientation for a container. Same arithmetic as the original, so the book lands
148
+ * on the same pixels; `layout` only overrides the "is the container too narrow" decision.
149
+ */
150
+ declare function computeLayout(containerWidth: number, containerHeight: number, options: LayoutOptions): LayoutResult;
151
+ //#endregion
152
+ //#region src/book.d.ts
153
+ type BookEvents = {
154
+ /** The book is laid out and showing `startPage`. Fires once, after `createBook` returns. */
155
+ init: {
156
+ readonly page: number;
157
+ readonly orientation: Orientation;
158
+ };
159
+ /** Pages were replaced with `setPages`. */
160
+ update: {
161
+ readonly page: number;
162
+ readonly orientation: Orientation;
163
+ };
164
+ /** A different spread is showing. `page` is the first page of it. */
165
+ flip: {
166
+ readonly page: number;
167
+ };
168
+ changeState: {
169
+ readonly state: FlipState;
170
+ };
171
+ changeOrientation: {
172
+ readonly orientation: Orientation;
173
+ };
174
+ };
175
+ type Book = {
176
+ /** First page of the open spread, zero-based. */
177
+ readonly page: number;
178
+ readonly pageCount: number;
179
+ readonly orientation: Orientation;
180
+ readonly state: FlipState;
181
+ readonly rect: BookRect;
182
+ on: Emitter<BookEvents>["on"];
183
+ off: Emitter<BookEvents>["off"];
184
+ /** Animated turns. Resolve with `false` when there is nothing to turn to. */
185
+ flipNext(corner?: FlipCorner): Promise<boolean>;
186
+ flipPrev(corner?: FlipCorner): Promise<boolean>;
187
+ flipTo(page: number, corner?: FlipCorner): Promise<boolean>;
188
+ /** Instant turns. */
189
+ turnTo(page: number): void;
190
+ turnNext(): void;
191
+ turnPrev(): void;
192
+ /** Replace the page elements. Keeps the current page where possible. */
193
+ setPages(pages: Iterable<HTMLElement>): void;
194
+ /** Re-measure the container and redraw. Resizes are handled automatically; call this after other layout changes. */
195
+ update(): void;
196
+ /** Redraw the current frame without measuring, after something else rewrote page attributes. Cheap. */
197
+ redraw(): void;
198
+ /** Stop everything, drop listeners and observers, and restore the DOM. */
199
+ destroy(): void;
200
+ };
201
+ type CreateBookOptions = BookOptions & {
202
+ /** Time and frame source, replaceable in tests. */
203
+ readonly clock?: Clock;
204
+ };
205
+ declare function createBook(container: HTMLElement, userOptions: CreateBookOptions): Book;
206
+ //#endregion
207
+ //#region src/geometry/point.d.ts
208
+ /**
209
+ * Plane geometry primitives for the fold calculation. Pure functions, no DOM.
210
+ *
211
+ * The maths derives from StPageFlip's `Helper` (MIT, Oleg Litovski). Where the original's
212
+ * behaviour is quirky, the quirk is kept and commented, because the renderer's look depends on
213
+ * it and the parity tests in `test/fold.parity.test.ts` hold this module to the original.
214
+ */
215
+ type Point = {
216
+ readonly x: number;
217
+ readonly y: number;
218
+ };
219
+ /** A line through two points. Used as an infinite line, not a bounded segment. */
220
+ type Segment = readonly [Point, Point];
221
+ type Rect = {
222
+ readonly left: number;
223
+ readonly top: number;
224
+ readonly width: number;
225
+ readonly height: number;
226
+ };
227
+ /** The four corners of a rectangle after rotation, so no longer axis-aligned. */
228
+ type RectPoints = {
229
+ readonly topLeft: Point;
230
+ readonly topRight: Point;
231
+ readonly bottomLeft: Point;
232
+ readonly bottomRight: Point;
233
+ };
234
+ //#endregion
235
+ //#region src/geometry/fold.d.ts
236
+ type FoldInput = {
237
+ readonly direction: FlipDirection;
238
+ readonly corner: FlipCorner;
239
+ readonly pageWidth: number;
240
+ readonly pageHeight: number;
241
+ /** Drag point in active-page coordinates: origin at the page's top-left, x grows toward the outer edge. */
242
+ readonly point: Point;
243
+ };
244
+ /** Where the fold line meets the page edges. A `null` edge is not crossed. */
245
+ type FoldIntersections = {
246
+ readonly top: Point | null;
247
+ readonly side: Point | null;
248
+ readonly bottom: Point | null;
249
+ };
250
+ type Fold = {
251
+ /** Rotation of the flipping page in radians, signed by direction. */
252
+ readonly angle: number;
253
+ /** Where the dragged corner ended up after clamping to what paper can do. */
254
+ readonly position: Point;
255
+ /** 0 at rest, 100 fully turned. */
256
+ readonly progress: number;
257
+ /** Corners of the flipping page after rotation. */
258
+ readonly rect: RectPoints;
259
+ readonly intersections: FoldIntersections;
260
+ /** Visible part of the flipping page, as a polygon in page coordinates. */
261
+ readonly flippingClip: readonly Point[];
262
+ /** Part of the page underneath that the fold reveals. */
263
+ readonly bottomClip: readonly Point[];
264
+ /** Where the flipping page's own origin corner sits. */
265
+ readonly activeCorner: Point;
266
+ readonly bottomPagePosition: Point;
267
+ /** Drop-shadow origin and rotation, or `null` when the fold crosses no usable edges. */
268
+ readonly shadow: {
269
+ readonly start: Point;
270
+ readonly angle: number;
271
+ } | null;
272
+ };
273
+ /**
274
+ * Returns `null` when the point is degenerate (the corner is at rest, or the fold line would
275
+ * coincide with a page edge). Callers keep the previous fold for that frame, as the original did.
276
+ */
277
+ declare function computeFold(input: FoldInput): Fold | null;
278
+ //#endregion
279
+ //#region src/controller.d.ts
280
+ type ShadowData = {
281
+ readonly pos: Point;
282
+ readonly angle: number;
283
+ readonly width: number;
284
+ readonly opacity: number;
285
+ readonly direction: FlipDirection;
286
+ /** 0..200: the original doubled flip progress for its hard-page shadow curve. */
287
+ readonly progress: number;
288
+ };
289
+ type FlipFrame = {
290
+ readonly direction: FlipDirection;
291
+ readonly corner: FlipCorner;
292
+ readonly flipping: number;
293
+ readonly bottom: number;
294
+ readonly fold: Fold;
295
+ readonly progress: number;
296
+ /** Rotation about the spine for hard pages, in degrees. */
297
+ readonly hardAngle: number;
298
+ readonly shadow: ShadowData | null;
299
+ };
300
+ /** Everything a renderer needs to draw one moment of the book. */
301
+ type Frame = {
302
+ readonly rect: BookRect;
303
+ readonly orientation: Orientation;
304
+ readonly left: number | null;
305
+ readonly right: number | null;
306
+ readonly flip: FlipFrame | null;
307
+ };
31
308
  //#endregion
32
- export { Direction, FlipCorner, Layout, PageDensity };
309
+ export { type Book, type BookEvents, type BookOptions, type BookRect, ClickMode, type Clock, type CreateBookOptions, type Emitter, FlipCorner, FlipDirection, type FlipFrame, FlipState, type Fold, type FoldInput, type FoldIntersections, type Frame, Layout, type LayoutOptions, type LayoutResult, type Listener, Orientation, PageDensity, type Point, type Rect, type RectPoints, type ResolvedOptions, type Segment, type ShadowData, SizeMode, computeFold, computeLayout, createBook };
33
310
  //# sourceMappingURL=index.d.ts.map
@@ -1,37 +1,2 @@
1
- var OpenPageFlip = (function(exports) {
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- //#region src/options.ts
4
- /**
5
- * Public option vocabularies. Plain `as const` objects instead of enums so they survive
6
- * `isolatedModules`, `erasableSyntaxOnly`, and consumers who only speak string literals.
7
- */
8
- /** How many pages are visible at once. `auto` picks by container width. */
9
- const Layout = {
10
- auto: "auto",
11
- single: "single",
12
- spread: "spread"
13
- };
14
- /** Reading direction. `rtl` flips the spine to the right for manga and Hebrew/Arabic books. */
15
- const Direction = {
16
- ltr: "ltr",
17
- rtl: "rtl"
18
- };
19
- /** Which corner a programmatic flip lifts. */
20
- const FlipCorner = {
21
- top: "top",
22
- bottom: "bottom"
23
- };
24
- /** `hard` pages rotate as a rigid sheet (covers); `soft` pages bend along the fold. */
25
- const PageDensity = {
26
- soft: "soft",
27
- hard: "hard"
28
- };
29
- //#endregion
30
- exports.Direction = Direction;
31
- exports.FlipCorner = FlipCorner;
32
- exports.Layout = Layout;
33
- exports.PageDensity = PageDensity;
34
- return exports;
35
- })({});
36
-
1
+ var OpenPageFlip=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t={now:()=>performance.now(),requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e)};function n(e,t){let n=e.now(),r=null,i=!1,a=()=>{i||(i=!0,r!==null&&e.cancelFrame(r),r=null,t.onFrame(1),t.onEnd())},o=s=>{if(r=null,i)return;let c=t.duration<=0?1:Math.min(1,Math.max(0,(s-n)/t.duration));if(c>=1){a();return}t.onFrame(t.easing(c)),r=e.requestFrame(o)};return t.duration<=0?a():r=e.requestFrame(o),{finish:a,cancel:()=>{i=!0,r!==null&&e.cancelFrame(r),r=null}}}let r={auto:`auto`,single:`single`,spread:`spread`},i={top:`top`,bottom:`bottom`},a={soft:`soft`,hard:`hard`},o={forward:`forward`,back:`back`},s={portrait:`portrait`,landscape:`landscape`},c={read:`read`,foldCorner:`fold_corner`,userFold:`user_fold`,flipping:`flipping`},l={fixed:`fixed`,stretch:`stretch`},u={anywhere:`anywhere`,corners:`corners`,off:`off`},d={size:l.fixed,minWidth:100,maxWidth:2e3,layout:r.auto,cover:!1,startPage:0,flipDuration:1e3,easing:e=>e,shadows:!0,shadowOpacity:1,autoSize:!0,click:u.anywhere,drag:!0,swipe:!0,swipeDistance:30,hoverCorners:!0,ignoreDragOn:`a, button, input, textarea, select, [data-opf-no-flip]`};function f(e,t){return Object.values(e).some(e=>e===t)}function p(e){let{pages:t,...n}=e,i={...d,...n},a=e=>{let t=i[e];if(!(Number.isFinite(t)&&t>0))throw TypeError(`@openpageflip/core: "${e}" must be a positive number, got ${String(t)}`)};if(a(`width`),a(`height`),a(`flipDuration`),a(`minWidth`),a(`maxWidth`),i.maxWidth<i.minWidth)throw TypeError(`@openpageflip/core: "maxWidth" (${i.maxWidth}) is below "minWidth" (${i.minWidth})`);if(!f(l,i.size))throw TypeError(`@openpageflip/core: unknown "size" ${String(i.size)}`);if(!f(r,i.layout))throw TypeError(`@openpageflip/core: unknown "layout" ${String(i.layout)}`);if(!f(u,i.click))throw TypeError(`@openpageflip/core: unknown "click" ${String(i.click)}`);if(!(i.shadowOpacity>=0&&i.shadowOpacity<=1))throw TypeError(`@openpageflip/core: "shadowOpacity" must be within 0..1, got ${i.shadowOpacity}`);if(!Number.isInteger(i.startPage)||i.startPage<0)throw TypeError(`@openpageflip/core: "startPage" must be a non-negative integer, got ${i.startPage}`);if(i.ignoreDragOn!==!1)try{document.createElement(`div`).matches(i.ignoreDragOn)}catch{throw TypeError(`@openpageflip/core: "ignoreDragOn" is not a valid selector: ${i.ignoreDragOn}`)}return i}function m(e,t){return{x:e.x-t.left,y:e.y-t.top}}function h(e,t,n){return{x:n===o.forward?e.x-t.left-t.width/2:t.width/2-e.x+t.left,y:e.y-t.top}}function g(e,t,n){return{x:n===o.forward?e.x+t.left+t.width/2:t.width/2-e.x+t.left,y:e.y+t.top}}function _(e,t){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}function v(e,t){let n=e[0].y-e[1].y,r=t[0].y-t[1].y,i=e[1].x-e[0].x,a=t[1].x-t[0].x;return Math.acos((n*r+i*a)/(Math.sqrt(n*n+i*i)*Math.sqrt(r*r+a*a)))}function y(e,t){return t.x>=e.left&&t.x<=e.left+e.width&&t.y>=e.top&&t.y<=e.top+e.height}function b(e,t,n){let r=Math.cos(n),i=Math.sin(n);return{x:e.x*r+e.y*i+t.x,y:e.y*r-e.x*i+t.y}}function x(e,t,n){if(_(e,n)<=t)return n;let r=e.x,i=e.y,a=n.x,o=n.y,s=Math.sqrt(t**2*(r-a)**2/((r-a)**2+(i-o)**2))+r;n.x<0&&(s*=-1);let c=(s-r)*(i-o)/(r-a)+i;return r-a+i===0&&(c=t),{x:s,y:c}}let S=Symbol(`collinear`);function C(e,t){let n=e[0].y-e[1].y,r=t[0].y-t[1].y,i=e[1].x-e[0].x,a=t[1].x-t[0].x,o=e[0].x*e[1].y-e[1].x*e[0].y,s=t[0].x*t[1].y-t[1].x*t[0].y,c=-((o*a-s*i)/(n*a-r*i)),l=-((n*s-r*o)/(n*a-r*i));if(Number.isFinite(c)&&Number.isFinite(l))return{x:c,y:l};let u=n*s-r*o,d=i*s-a*o;return Math.abs(u-d)<.1?S:null}function w(e,t,n){let r=C(t,n);return r===null||r===S||y(e,r)?r:null}function T(e){let{direction:t,corner:n,pageWidth:r,pageHeight:a}=e,s=E(e);if(s===null)return null;let{position:c,angle:l,rect:u}=s,d=A(e,c,u);if(d===null)return null;let{top:f,side:p,bottom:m}=d,h=[u.topLeft];f&&h.push(f);let g=!1;p===null?g=!0:h.push(p),m&&h.push(m),(g||n===i.bottom)&&h.push(u.bottomLeft);let y=[];f&&y.push(f),n===i.top?y.push({x:r,y:0}):(f!==null&&y.push({x:r,y:0}),y.push({x:r,y:a})),p===null?n===i.top&&y.push({x:r,y:a}):(f===null||_(p,f)>=10)&&y.push(p),m&&y.push(m),f&&y.push(f);let b=n===i.top?f:p??f,x=b!==p&&p!==null?p:m,S=null;if(b!==null&&x!==null){let e=v([b,x],[{x:0,y:0},{x:r,y:0}]);S={start:b,angle:t===o.forward?e:Math.PI-e}}return{angle:t===o.forward?-l:l,position:c,progress:Math.abs((c.x-r)/(2*r)*100),rect:u,intersections:d,flippingClip:h,bottomClip:y,activeCorner:t===o.forward?u.topLeft:u.topRight,bottomPagePosition:t===o.back?{x:r,y:0}:{x:0,y:0},shadow:S}}function E(e){let{corner:t,pageWidth:n,pageHeight:r}=e,a=e.point,o=D(e,a);if(o===null)return null;let s=t===i.top?{x:0,y:0}:{x:0,y:r},c=t===i.top?{x:0,y:r}:{x:0,y:0},l=x(s,n,a);if(l!==a&&(a=l,o=D(e,a),o===null))return null;let u=t===i.top?o.rect.bottomRight:o.rect.topRight,d=t===i.top?o.rect.topLeft:o.rect.bottomLeft;return u.x<=0&&(a=x(c,Math.sqrt(n**2+r**2),d),o=D(e,a),o===null)||Math.abs(a.x-n)<1&&Math.abs(a.y)<1?null:{position:a,...o}}function D(e,t){let n=O(e,t);return n===null?null:{angle:n,rect:k(e,t,n)}}function O(e,t){let{corner:n,pageWidth:r,pageHeight:a}=e,o=r-t.x+1,s=n===i.bottom?a-t.y:t.y,c=2*Math.acos(o/Math.sqrt(s*s+o*o));s<0&&(c=-c);let l=Math.PI-c;return!Number.isFinite(c)||l>=0&&l<.003?null:n===i.bottom?-c:c}function k(e,t,n){let{corner:r,pageWidth:a,pageHeight:o}=e,s=r===i.top?0:-o;return{topLeft:b({x:0,y:s},t,n),topRight:b({x:a,y:s},t,n),bottomLeft:b({x:0,y:s+o},t,n),bottomRight:b({x:a,y:s+o},t,n)}}function A(e,t,n){let{corner:r,pageWidth:a,pageHeight:o}=e,s={left:-1,top:-1,width:a+2,height:o+2},c=[{x:0,y:0},{x:a,y:0}],l=[{x:a,y:0},{x:a,y:o}],u=[{x:0,y:o},{x:a,y:o}],d=r===i.top?w(s,[t,n.topRight],c):w(s,[n.topLeft,n.topRight],c),f=r===i.top?w(s,[t,n.bottomLeft],l):w(s,[t,n.topLeft],l),p=w(s,[n.bottomLeft,n.bottomRight],u);return d===S||f===S||p===S?null:{top:d,side:f,bottom:p}}function j(e,t,n){let r=new Set,i=[],a=0;n&&e>0&&(r.add(0),i.push([0]),a=1);for(let t=a;t<e;t+=2)t<e-1?i.push([t,t+1]):(i.push([t]),r.add(t));let o=Array.from({length:e},(e,t)=>[t]);return{spreads:t===s.portrait?o:i,hardByPosition:r}}function M(e,t){let n=e.findIndex(e=>e[0]===t||e[1]===t);return n===-1?null:n}function N(e,t,n,r){let i=e[n];return i===void 0?{left:null,right:null}:i.length===2?{left:i[0],right:i[1]}:t===s.landscape&&i[0]===r-1?{left:i[0],right:null}:{left:null,right:i[0]}}function P(e,t,n,r){let i=r===o.forward;if(t===s.portrait){let t=e[n]?.[0],r=e[i?n+1:n-1]?.[0];return t===void 0||r===void 0?null:i?{flipping:t,bottom:r}:{flipping:r,bottom:r}}let a=e[i?n+1:n-1];return a===void 0?null:a.length===1?{flipping:a[0],bottom:a[0]}:i?{flipping:a[0],bottom:a[1]}:{flipping:a[1],bottom:a[0]}}var F=class{pages;spreads=[];spreadIndex=0;currentPage=0;orientation;rect;left=null;right=null;state=c.read;session=null;tween=null;settleTween=null;pressStart=null;dragged=!1;options;clock;hooks;constructor(e,t,n,r,i){this.options=e,this.clock=t,this.hooks=n,this.pages=r,this.orientation=i.orientation,this.rect=i.rect,this.rebuildSpreads()}get page(){return this.currentPage}get pageCount(){return this.pages.length}get currentState(){return this.state}get currentOrientation(){return this.orientation}get bookRect(){return this.rect}setPages(e){this.endSession(),this.pages=e,this.rebuildSpreads(),this.showPage(Math.min(this.currentPage,Math.max(0,e.length-1)))}setLayout(e){let t=e.rect.pageWidth!==this.rect.pageWidth||e.rect.height!==this.rect.height;this.rect=e.rect;let n=e.orientation!==this.orientation;return t&&!n&&this.endSession(),n&&(this.endSession(),this.orientation=e.orientation,this.rebuildSpreads()),this.showPage(this.currentPage),n}rebuildSpreads(){let{spreads:e,hardByPosition:t}=j(this.pages.length,this.orientation,this.options.cover);this.spreads=e;for(let[e,n]of this.pages.entries())t.has(e)&&(n.density=a.hard,n.drawingDensity=a.hard)}showPage(e){let t=M(this.spreads,e);if(t===null)throw RangeError(`@openpageflip/core: page ${e} is out of range (0..${this.pages.length-1})`);this.spreadIndex=t,this.showSpread()}showNext(){this.spreadIndex<this.spreads.length-1&&(this.spreadIndex++,this.showSpread())}showPrev(){this.spreadIndex>0&&(this.spreadIndex--,this.showSpread())}showSpread(){let{left:e,right:t}=N(this.spreads,this.orientation,this.spreadIndex,this.pages.length);this.left=e,this.right=t;let n=this.spreads[this.spreadIndex],r=n===void 0?this.currentPage:n[0],i=r!==this.currentPage;this.currentPage=r,this.render(),i&&this.hooks.onPage(r)}flipNext(e){return this.flipFrom({x:this.rect.left+this.rect.pageWidth*2-10,y:e===i.top?1:this.rect.height-2})}flipPrev(e){return this.flipFrom({x:this.rect.left+10,y:e===i.top?1:this.rect.height-2})}flipTo(e,t){this.tween?.finish();let n=M(this.spreads,e);return n===null||n===this.spreadIndex?Promise.resolve(!1):n>this.spreadIndex?(this.spreadIndex=n-1,this.syncCurrentPage(),this.flipNext(t)):(this.spreadIndex=n+1,this.syncCurrentPage(),this.flipPrev(t))}syncCurrentPage(){let e=this.spreads[this.spreadIndex];e!==void 0&&(this.currentPage=e[0])}flipFrom(e){this.session!==null&&this.tween?.finish();let t=this.start(e);if(t===null)return Promise.resolve(!1);this.setState(c.flipping);let{pageWidth:n,pageHeight:r}=t,a=r/10,o=t.corner===i.bottom?r-a:a,s=t.corner===i.bottom?r:0,l={x:n-a,y:o};return this.applyFold(l),this.animateTo(l,{x:-n,y:s},!0,!0)}release(){let e=this.session;if(e===null||e.fold===null)return Promise.resolve(!1);let t=e.fold.position,n=e.corner===i.bottom?e.pageHeight:0;return t.x<=0?this.animateTo(t,{x:-e.pageWidth,y:n},!0,!0):this.animateTo(t,{x:e.pageWidth,y:n},!1,!0)}animateTo(e,t,r,i){this.tween?.finish();let a=t.x-e.x,s=t.y-e.y,l=Math.min(1,Math.max(Math.abs(a),Math.abs(s))/1e3)*this.options.flipDuration;return new Promise(t=>{this.settleTween=t,this.tween=n(this.clock,{duration:l,easing:this.options.easing,onFrame:t=>this.applyFold({x:e.x+a*t,y:e.y+s*t}),onEnd:()=>{this.tween=null,this.settleTween=null;let e=this.session;if(e===null){t(!1);return}r&&(e.direction===o.back?this.showPrev():this.showNext()),i&&(this.endSession(),this.setState(c.read),this.render()),t(r)}})})}hover(e){if(this.state!==c.read&&this.state!==c.foldCorner)return;let{pageWidth:t,height:n}=this.rect;if(!this.isOnCorner(e)){if(this.session===null)return;this.setState(c.read),this.tween?.finish(),this.release();return}if(this.session!==null){this.applyFold(h(e,this.rect,this.session.direction));return}let r=this.start(e);if(r===null)return;this.setState(c.foldCorner),this.applyFold({x:t-1,y:1});let a=r.corner===i.bottom?n-1:1,o=r.corner===i.bottom?n-50:50;this.animateTo({x:t-1,y:a},{x:t-50,y:o},!1,!1)}hoverEnd(){this.state===c.foldCorner&&(this.setState(c.read),this.tween?.finish(),this.release())}pointerDown(e){this.state===c.flipping&&this.tween?.finish(),this.pressStart=e,this.dragged=!1}pointerDrag(e){if(this.pressStart===null||!this.dragged&&_(this.pressStart,e)<=5||(this.dragged=!0,!this.options.drag))return;let t=this.session??this.start(this.pressStart);t!==null&&(this.setState(c.userFold),this.applyFold(h(e,this.rect,t.direction)))}pointerUp(e){if(this.pressStart!==null){if(this.pressStart=null,this.dragged){this.release();return}this.click(e)}}pointerCancel(){this.pressStart!==null&&(this.pressStart=null,this.dragged&&this.release())}swipe(e,t){this.pressStart=null;let n=this.session;if(n!==null&&n.fold!==null){if(n.direction!==e)return this.release();let r=t===i.bottom?n.pageHeight:0;return this.animateTo(n.fold.position,{x:-n.pageWidth,y:r},!0,!0)}return e===o.forward?this.flipNext(t):this.flipPrev(t)}click(e){this.options.click!==u.off&&(this.options.click===u.corners&&!this.isOnCorner(e)||this.flipFrom(e))}start(e){this.endSession();let t=m(e,this.rect),n=this.directionAt(t),r=t.y>=this.rect.height/2?i.bottom:i.top;if(!(n===o.forward?this.currentPage<this.pages.length-1:this.currentPage>=1))return null;let c=P(this.spreads,this.orientation,this.spreadIndex,n);if(c===null)return null;if(this.orientation===s.landscape){let e=this.pages[c.flipping],t=this.pages[n===o.back?c.flipping+1:c.flipping-1];e!==void 0&&t!==void 0&&e.density!==t.density&&(e.drawingDensity=a.hard,t.drawingDensity=a.hard)}return this.session={direction:n,corner:r,flipping:c.flipping,bottom:c.bottom,pageWidth:this.rect.pageWidth,pageHeight:this.rect.height,fold:null,progress:0,hardAngle:0,shadow:null},this.session}endSession(){this.tween?.cancel(),this.tween=null,this.settleTween?.(!1),this.settleTween=null,this.session=null;for(let e of this.pages)e.drawingDensity=e.density}applyFold(e){let t=this.session;if(t===null)return;let n=T({direction:t.direction,corner:t.corner,pageWidth:t.pageWidth,pageHeight:t.pageHeight,point:e});if(n===null)return;let{progress:r}=n;t.fold=n,t.progress=r,t.hardAngle=(t.direction===o.forward?90:-90)*((200-r*2)/100),t.shadow=this.options.shadows&&n.shadow!==null?{pos:n.shadow.start,angle:n.shadow.angle,width:t.pageWidth*3/4*(r/100),opacity:(100-r)*(100*this.options.shadowOpacity)/100/100,direction:t.direction,progress:r*2}:null,this.render()}directionAt(e){return this.orientation===s.portrait?e.x-this.rect.pageWidth<=this.rect.width/5?o.back:o.forward:e.x<this.rect.width/2?o.back:o.forward}isOnCorner(e){let{pageWidth:t,height:n,width:r}=this.rect,i=Math.sqrt(t**2+n**2)/5,a=m(e,this.rect);return a.x>0&&a.y>0&&a.x<r&&a.y<n&&(a.x<i||a.x>r-i)&&(a.y<i||a.y>n-i)}setState(e){this.state!==e&&(this.state=e,this.hooks.onState(e))}frame(){let e=this.session;return{rect:this.rect,orientation:this.orientation,left:this.left,right:this.right,flip:e!==null&&e.fold!==null?{direction:e.direction,corner:e.corner,flipping:e.flipping,bottom:e.bottom,fold:e.fold,progress:e.progress,hardAngle:e.hardAngle,shadow:e.shadow}:null}}redraw(){this.render()}render(){this.hooks.onFrame(this.frame())}destroy(){this.endSession()}};function I(){let e=new Map,t=(t,n)=>{e.get(t)?.delete(n)};return{on(n,r,i){let a=e.get(n);a===void 0&&(a=new Set,e.set(n,a));let o=()=>t(n,r);return i?.signal?.aborted?o:(a.add(r),i?.signal?.addEventListener(`abort`,o,{once:!0}),o)},off:t,emit(t,n){let r=e.get(t);if(r!==void 0)for(let e of[...r])e(n)},clear(){e.clear()}}}function L(e,t,n){let r=null,a=t=>{let n=e.getBoundingClientRect();return{x:t.clientX-n.left,y:t.clientY-n.top}},s=i=>{if(r!==null||i.pointerType===`mouse`&&i.button!==0||n.ignoreDragOn!==!1&&i.target instanceof Element&&i.target.closest(n.ignoreDragOn)!==null)return;let o=a(i);r={id:i.pointerId,start:o,startedAt:i.timeStamp};try{e.setPointerCapture(i.pointerId)}catch{}t.pointerDown(o),i.pointerType===`mouse`&&i.preventDefault()},c=e=>{if(r!==null){e.pointerId===r.id&&t.pointerDrag(a(e));return}e.pointerType===`mouse`&&n.hoverCorners&&t.hover(a(e))},l=e=>{if(r===null||e.pointerId!==r.id)return;let{start:s,startedAt:c}=r;r=null;let l=a(e),u=l.x-s.x,d=l.y-s.y,f=e.timeStamp-c<250;if(n.swipe&&f&&Math.abs(u)>n.swipeDistance&&Math.abs(d)<n.swipeDistance*2){let e=t.bookRect,n=s.y-e.top<e.height/2?i.top:i.bottom;t.swipe(u>0?o.back:o.forward,n);return}t.pointerUp(l)},u=e=>{r!==null&&e.pointerId===r.id&&(r=null,t.pointerCancel())},d=e=>{r===null&&e.pointerType===`mouse`&&t.hoverEnd()};return e.addEventListener(`pointerdown`,s),e.addEventListener(`pointermove`,c,{passive:!0}),e.addEventListener(`pointerup`,l),e.addEventListener(`pointercancel`,u),e.addEventListener(`pointerleave`,d),()=>{e.removeEventListener(`pointerdown`,s),e.removeEventListener(`pointermove`,c),e.removeEventListener(`pointerup`,l),e.removeEventListener(`pointercancel`,u),e.removeEventListener(`pointerleave`,d)}}function R(e,t,n){let i={x:e/2,y:t/2},a=n.width/n.height,o=e=>n.layout===r.single||n.layout===r.auto&&e?s.portrait:s.landscape,c,u=n.width,d=n.height;n.size===l.stretch?(c=o(e<n.minWidth*2),u=c===s.portrait?e:e/2,u>n.maxWidth&&(u=n.maxWidth),d=u/a,d>t&&(d=t,u=d*a)):c=o(e<u*2);let f=c===s.portrait?i.x-u/2-u:i.x-u;return{orientation:c,rect:{left:f,top:i.y-d/2,width:u*2,height:d,pageWidth:u}}}function z(e,t){return e.map((e,n)=>{let r=t.has(n)||e.dataset.density===a.hard?a.hard:a.soft;return{element:e,density:r,drawingDensity:r}})}let B={flat:1,bottom:3,hardShadow:4,flipping:5,hardInnerShadow:5,shadow:10},V={book:`opf-book`,page:`opf-page`,left:`opf-page--left`,right:`opf-page--right`,flat:`opf-page--flat`,soft:`opf-page--soft`,hard:`opf-page--hard`,shadow:`opf-shadow`},H=[`display`,`position`,`zIndex`,`left`,`top`,`width`,`height`,`transformOrigin`,`transform`,`clipPath`,`backfaceVisibility`];function U(e,t){for(let n of H)e.style[n]=t[n]??``}var W=class{shadows;pages=[];saved=new Map;clone=null;hidden=new Set;container;options;constructor(e,t){this.container=e,this.options=t,e.classList.add(V.book);let n=t=>{let n=document.createElement(`div`);return n.className=`${V.shadow} ${V.shadow}--${t}`,n.style.display=`none`,e.append(n),n};this.shadows={outer:n(`outer`),inner:n(`inner`),hardOuter:n(`hard-outer`),hardInner:n(`hard-inner`)},this.applyContainerSizing()}setPages(e){for(let t of this.pages)e.some(e=>e.element===t.element)||this.restore(t.element);this.pages=e,this.hidden.clear();for(let t of e)this.saved.has(t.element)||(this.saved.set(t.element,{cssText:t.element.style.cssText,className:t.element.className}),t.element.classList.add(V.page),t.element.parentElement!==this.container&&this.container.append(t.element))}applyContainerSizing(e=s.landscape){let{autoSize:t,size:n,width:i,height:a,minWidth:o,maxWidth:c,layout:u}=this.options;if(!t)return;let d=u===r.spread?2:1,f=u===r.single?1:2,p=this.container.style;p.width=`100%`,p.minWidth=`${(n===l.fixed?i:o)*d}px`,p.maxWidth=`${(n===l.fixed?i:c)*f}px`,p.aspectRatio=e===s.portrait?`${i} / ${a}`:`${i*2} / ${a}`}render(e){let{rect:t,flip:n}=e,r=new Set;for(let t of[e.left,e.right,n?.flipping,n?.bottom])t!=null&&r.add(t);for(let[e,t]of this.pages.entries())r.has(e)?this.hidden.delete(e):this.hidden.has(e)||(U(t.element,{display:`none`}),this.hidden.add(e));let i=n!==null&&this.pages[n.flipping]?.drawingDensity===a.hard;if(e.orientation!==s.portrait&&e.left!==null&&(n!==null&&n.direction===o.back&&i?this.drawHard(e.left,`left`,180+n.hardAngle,B.flipping,t):this.drawFlat(e.left,`left`,t)),e.right!==null&&(n!==null&&n.direction===o.forward&&i?this.drawHard(e.right,`right`,180+n.hardAngle,B.flipping,t):this.drawFlat(e.right,`right`,t)),n===null){this.dropClone(),this.hideShadows();return}let c=!i&&n.flipping===e.right;c||this.dropClone();let l=n.direction===o.back?`left`:`right`;(e.orientation!==s.portrait||n.direction!==o.back)&&(i?this.drawHard(n.bottom,l,0,B.bottom,t):this.drawSoft(n.bottom,l,n.fold.bottomClip,n.fold.bottomPagePosition,0,n.direction,B.bottom,t));let u=n.direction===o.forward&&e.orientation!==s.portrait?`left`:`right`;i?this.drawHard(n.flipping,u,n.hardAngle,B.flipping,t):this.drawSoft(n.flipping,u,n.fold.flippingClip,n.fold.activeCorner,n.fold.angle,n.direction,B.flipping,t,c),n.shadow===null?this.hideShadows():i?(this.hideSoftShadows(),this.drawHardShadows(n.shadow,t)):(this.hideHardShadows(),this.drawSoftShadows(n.shadow,n.fold.rect,t))}element(e,t,n=!1){let r=this.pages[e];if(r===void 0)return null;let i=n?this.cloneOf(r.element):r.element;return i.classList.add(V.page),i.classList.toggle(V.hard,r.drawingDensity===a.hard),i.classList.toggle(V.soft,r.drawingDensity===a.soft),i.classList.toggle(V.left,t===`left`),i.classList.toggle(V.right,t===`right`),i}cloneOf(e){if(this.clone?.source===e)return this.clone.element;this.dropClone();let t=e.cloneNode(!0);if(!(t instanceof HTMLElement))throw TypeError(`@openpageflip/core: a page clone is not an element`);t.removeAttribute(`id`);for(let e of t.querySelectorAll(`[id]`))e.removeAttribute(`id`);return t.setAttribute(`aria-hidden`,`true`),t.inert=!0,t.dataset.opfClone=``,e.after(t),this.clone={source:e,element:t},t}dropClone(){this.clone?.element.remove(),this.clone=null}drawFlat(e,t,n){let r=this.element(e,t);if(r===null)return;r.classList.add(V.flat);let i=t===`right`?n.left+n.pageWidth:n.left;U(r,{position:`absolute`,display:`block`,height:`${n.height}px`,left:`${i}px`,top:`${n.top}px`,width:`${n.pageWidth}px`,zIndex:String(B.flat)})}drawSoft(e,t,n,r,i,a,s,c,l=!1){let u=this.element(e,t,l);if(u===null)return;u.classList.remove(V.flat);let d=g(r,c,a),f=n.map(e=>{let t=b(a===o.back?{x:-e.x+r.x,y:e.y-r.y}:{x:e.x-r.x,y:e.y-r.y},{x:0,y:0},i);return`${t.x}px ${t.y}px`}).join(`, `);U(u,{position:`absolute`,display:`block`,zIndex:String(s),left:`0`,top:`0`,width:`${c.pageWidth}px`,height:`${c.height}px`,transformOrigin:`0 0`,clipPath:`polygon(${f})`,transform:`translate3d(${d.x}px, ${d.y}px, 0) rotate(${i}rad)`})}drawHard(e,t,n,r,i){let a=this.element(e,t);if(a===null)return;a.classList.remove(V.flat);let o=i.left+i.width/2;U(a,{position:`absolute`,display:`block`,zIndex:String(r),left:`0`,top:`0`,width:`${i.pageWidth}px`,height:`${i.height}px`,backfaceVisibility:`hidden`,clipPath:`none`,transformOrigin:t===`left`?`${i.pageWidth}px 0`:`0 0`,transform:t===`left`?`translate3d(${i.left}px, ${i.top}px, 0) rotateY(${n}deg)`:`translate3d(${o}px, ${i.top}px, 0) rotateY(${n}deg)`})}drawSoftShadows(e,t,n){let r=e.direction===o.forward,i=g(e.pos,n,e.direction),a=e.angle+3*Math.PI/2,s=(t,n)=>t.map(t=>{let i=b(r?{x:t.x-e.pos.x,y:t.y-e.pos.y}:{x:-t.x+e.pos.x,y:t.y-e.pos.y},{x:n,y:100},a);return`${i.x}px ${i.y}px`}).join(`, `),c=r?0:e.width,l=s([{x:0,y:0},{x:n.pageWidth,y:0},{x:n.pageWidth,y:n.height},{x:0,y:n.height}],c);this.shadows.outer.style.cssText=`display: block; z-index: ${B.shadow}; width: ${e.width}px; height: ${n.height*2}px; background: linear-gradient(${r?`to right`:`to left`}, rgba(0, 0, 0, ${e.opacity}), rgba(0, 0, 0, 0)); transform-origin: ${c}px 100px; transform: translate3d(${i.x-c}px, ${i.y-100}px, 0) rotate(${a}rad); clip-path: polygon(${l});`;let u=e.width*3/4,d=r?u:0,f=s([t.topLeft,t.topRight,t.bottomRight,t.bottomLeft],d);this.shadows.inner.style.cssText=`display: block; z-index: ${B.shadow}; width: ${u}px; height: ${n.height*2}px; background: linear-gradient(${r?`to left`:`to right`}, rgba(0, 0, 0, ${e.opacity}) 5%, rgba(0, 0, 0, 0.05) 15%, rgba(0, 0, 0, ${e.opacity}) 35%, rgba(0, 0, 0, 0) 100%); transform-origin: ${d}px 100px; transform: translate3d(${i.x-d}px, ${i.y-100}px, 0) rotate(${a}rad); clip-path: polygon(${f});`}drawHardShadows(e,t){let n=e.progress>100?200-e.progress:e.progress,r=Math.min(t.pageWidth,(100-n)*(2.5*t.pageWidth)/100+20),i=t.left+t.width/2,a=e.direction===o.forward&&e.progress>100||e.direction===o.back&&e.progress<=100,s=`display: block; width: ${r}px; height: ${t.height}px; left: ${i}px; top: ${t.top}px; transform-origin: 0 0;`;this.shadows.hardInner.style.cssText=`${s} z-index: ${B.hardInnerShadow}; background: linear-gradient(to right, rgba(0, 0, 0, ${e.opacity*n/100}) 5%, rgba(0, 0, 0, 0) 100%); transform: translate3d(0, 0, 0)${a?``:` rotateY(180deg)`};`,this.shadows.hardOuter.style.cssText=`${s} z-index: ${B.hardShadow}; background: linear-gradient(to left, rgba(0, 0, 0, ${e.opacity}) 5%, rgba(0, 0, 0, 0) 100%); transform: translate3d(0, 0, 0)${a?` rotateY(180deg)`:``};`}hideSoftShadows(){this.shadows.outer.style.cssText=`display: none`,this.shadows.inner.style.cssText=`display: none`}hideHardShadows(){this.shadows.hardOuter.style.cssText=`display: none`,this.shadows.hardInner.style.cssText=`display: none`}hideShadows(){this.hideSoftShadows(),this.hideHardShadows()}restore(e){let t=this.saved.get(e);t!==void 0&&(e.style.cssText=t.cssText,e.className=t.className,this.saved.delete(e))}destroy(){this.dropClone(),this.hidden.clear();for(let e of this.pages)this.restore(e.element);this.pages=[];for(let e of Object.values(this.shadows))e.remove();this.container.classList.remove(V.book);let e=this.container.style;e.width=``,e.minWidth=``,e.maxWidth=``,e.aspectRatio=``}};function G(e,n){let{clock:r=t,...a}=n,o=p(a),s=Array.from(a.pages??e.children).filter(e=>e instanceof HTMLElement);if(s.length===0)throw TypeError(`@openpageflip/core: createBook needs at least one page element`);if(o.startPage>=s.length)throw TypeError(`@openpageflip/core: "startPage" ${o.startPage} is out of range for ${s.length} pages`);let c=I(),l=new W(e,o),u=matchMedia(`(prefers-reduced-motion: reduce)`),d=()=>{let t=e.clientWidth,{orientation:n}=R(t,e.clientHeight,o);return l.applyContainerSizing(n),R(t,e.clientHeight,o)},f=e=>{let{hardByPosition:t}=j(e.length,`landscape`,o.cover);return z(e,t)},m=f(s);l.setPages(m);let h=new F({...o,get flipDuration(){return u.matches?0:o.flipDuration}},r,{onFrame:e=>l.render(e),onPage:e=>c.emit(`flip`,{page:e}),onState:e=>c.emit(`changeState`,{state:e})},m,d()),g=()=>{let e=d();h.setLayout(e)&&c.emit(`changeOrientation`,{orientation:e.orientation})},_={width:e.clientWidth,height:e.clientHeight},v=null,y=new ResizeObserver(()=>{v===null&&(v=r.requestFrame(()=>{v=null;let t={width:e.clientWidth,height:e.clientHeight};(t.width!==_.width||t.height!==_.height)&&(_=t,g())}))});y.observe(e);let b=L(e,h,o);return h.showPage(o.startPage),queueMicrotask(()=>c.emit(`init`,{page:h.page,orientation:h.currentOrientation})),{get page(){return h.page},get pageCount(){return h.pageCount},get orientation(){return h.currentOrientation},get state(){return h.currentState},get rect(){return h.bookRect},on:c.on,off:c.off,flipNext:(e=i.top)=>h.flipNext(e),flipPrev:(e=i.top)=>h.flipPrev(e),flipTo:(e,t=i.top)=>h.flipTo(e,t),turnTo:e=>h.showPage(e),turnNext:()=>h.showNext(),turnPrev:()=>h.showPrev(),setPages(e){let t=Array.from(e);if(t.length===0)throw TypeError(`@openpageflip/core: setPages needs at least one page element`);m=f(t),l.setPages(m),h.setPages(m),c.emit(`update`,{page:h.page,orientation:h.currentOrientation})},update:g,redraw:()=>h.redraw(),destroy(){y.disconnect(),v!==null&&r.cancelFrame(v),b(),h.destroy(),l.destroy(),c.clear()}}}return e.ClickMode=u,e.FlipCorner=i,e.FlipDirection=o,e.FlipState=c,e.Layout=r,e.Orientation=s,e.PageDensity=a,e.SizeMode=l,e.computeFold=T,e.computeLayout=R,e.createBook=G,e})({});
37
2
  //# sourceMappingURL=index.iife.js.map