@zinejs/core 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{cssRenderer-OzRRoEa4.js → cssRenderer-Deskm2ND.js} +9 -3
- package/dist/{cssRenderer-OzRRoEa4.js.map → cssRenderer-Deskm2ND.js.map} +1 -1
- package/dist/index.js +113 -190
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +3 -3
- package/dist/index.umd.js.map +1 -1
- package/dist/renderer/types.d.ts +15 -0
- package/dist/{webglRenderer-BcNhTqG8.js → webglRenderer-D_XGumQT.js} +12 -3
- package/dist/webglRenderer-D_XGumQT.js.map +1 -0
- package/package.json +1 -1
- package/dist/engine/zoomTile.d.ts +0 -65
- package/dist/webglRenderer-BcNhTqG8.js.map +0 -1
|
@@ -98,14 +98,20 @@ var i = class {
|
|
|
98
98
|
this.#n.style.transform = `translate(${t}px, ${n}px) scale(${e})`;
|
|
99
99
|
}
|
|
100
100
|
measure() {
|
|
101
|
-
let e = this.#e, t = e?.clientWidth ?? 0, n = e?.clientHeight ?? 0, r = this.#f > 0, i = r ? this.#y() : void 0, a = r ? this.#b() : void 0
|
|
101
|
+
let e = this.#e, t = e?.clientWidth ?? 0, n = e?.clientHeight ?? 0, r = this.#f > 0, i = r ? this.#y() : void 0, a = r ? this.#b() : void 0, o = a ? (e) => ({
|
|
102
|
+
x: a.x * e,
|
|
103
|
+
y: a.y * e,
|
|
104
|
+
width: a.width * e,
|
|
105
|
+
height: a.height * e
|
|
106
|
+
}) : void 0;
|
|
102
107
|
return {
|
|
103
108
|
containerWidth: t,
|
|
104
109
|
containerHeight: n,
|
|
105
110
|
pageWidth: t / 2,
|
|
106
111
|
pageHeight: n,
|
|
107
112
|
book: i,
|
|
108
|
-
content: a
|
|
113
|
+
content: a,
|
|
114
|
+
screenAt: o
|
|
109
115
|
};
|
|
110
116
|
}
|
|
111
117
|
#x(e, t, n) {
|
|
@@ -124,4 +130,4 @@ var i = class {
|
|
|
124
130
|
//#endregion
|
|
125
131
|
export { i as CssRenderer };
|
|
126
132
|
|
|
127
|
-
//# sourceMappingURL=cssRenderer-
|
|
133
|
+
//# sourceMappingURL=cssRenderer-Deskm2ND.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cssRenderer-OzRRoEa4.js","names":["#container","#clip","#viewport","#book","#pageLeft","#makeCanvas","#pageRight","#leaf","#leafFront","#leafBack","#leafShadow","#paint","#fill","#contentShift","#trackAspect","#layoutBook","#applyShift","#fromShiftUnit","#toShiftUnit","#bookW","#pageAspect","#bookBox","#contentBox"],"sources":["../src/geometry/flipProgressToPose.ts","../src/renderer/cssRenderer.ts"],"sourcesContent":["export interface FlipPose {\n /** Turning-page rotation about the spine, radians: 0 (flat/open) → π (fully turned). */\n angle: number;\n /** Mesh cylinder-wrap curl, 0..1 — flat at the ends, peaks edge-on at t=0.5. CSS renderer ignores it. */\n curl: number;\n /** Fold-shadow intensity, 0..1 — peaks edge-on at t=0.5. */\n shadowAlpha: number;\n}\n\n/**\n * Map a 0→1 flip progress to a renderer-neutral fold pose.\n *\n * Linear in `t` on purpose — easing belongs to the animator that produces `t`,\n * so seeking to a fixed progress (e.g. the 0/.25/.5/.75/1 visual-regression stops)\n * is deterministic. The CSS renderer consumes `angle` as a spine `rotateY`; the\n * WebGL2 renderer additionally bends its mesh by `curl`.\n */\nexport function flipProgressToPose(t: number): FlipPose {\n const clamped = t < 0 ? 0 : t > 1 ? 1 : t;\n const arc = Math.sin(clamped * Math.PI);\n return {\n angle: clamped * Math.PI,\n curl: arc,\n shadowAlpha: arc,\n };\n}\n","import { flipProgressToPose } from '../geometry/flipProgressToPose';\nimport type { Spread } from '../engine/spread';\nimport type {\n FlipDirection,\n LayoutMetrics,\n PageContent,\n Renderer,\n RenderOptions,\n SpreadContent,\n} from './types';\n\nconst RAD_TO_DEG = 180 / Math.PI;\n\n/** How far to shift a spread to centre a lone page, in units of a quarter container width:\n * -1 = only a right page (cover), +1 = only a left page (back), 0 = a full spread. */\nfunction shiftUnit(content: SpreadContent): number {\n const lone = (content.left === null) !== (content.right === null);\n return lone ? (content.right !== null ? -1 : 1) : 0;\n}\n\n/**\n * Layered gradients painted over the turning leaf to fake paper depth on the flat\n * fold: a crease shadow at the spine, a soft curve sheen, and a free-edge shade.\n * The spine is the leaf's pivot edge — left for a forward flip, right for backward.\n */\nfunction foldOverlay(direction: FlipDirection): string {\n const dir = direction === 'forward' ? 'to right' : 'to left';\n return [\n `linear-gradient(${dir}, rgba(0,0,0,0.6), rgba(0,0,0,0.15) 40%, rgba(0,0,0,0) 60%)`,\n `linear-gradient(${dir}, transparent 40%, rgba(255,255,255,0.32) 66%, transparent 90%)`,\n `linear-gradient(${dir}, transparent 66%, rgba(0,0,0,0.35))`,\n ].join(',');\n}\n\n/**\n * Baseline renderer: a 2-panel CSS-3D fold. Runs on every browser, no GPU. Pages\n * are <canvas> elements; the turning leaf (front + back faces, backface-hidden)\n * rotates about the spine driven by flipProgressToPose(), with a gradient shadow\n * overlay for depth. `beginFlip` stages the surfaces; `setFlipProgress` animates.\n */\nexport class CssRenderer implements Renderer {\n #container: HTMLElement | null = null;\n #clip!: HTMLDivElement;\n #viewport!: HTMLDivElement;\n #book!: HTMLDivElement;\n #pageLeft!: HTMLCanvasElement;\n #pageRight!: HTMLCanvasElement;\n #leaf!: HTMLDivElement;\n #leafFront!: HTMLCanvasElement;\n #leafBack!: HTMLCanvasElement;\n #leafShadow!: HTMLDivElement;\n // Lone-page centering, interpolated across a flip (see the WebGL renderer).\n #fromShiftUnit = 0;\n #toShiftUnit = 0;\n // Book aspect fit: the spread is letterboxed to the page aspect (see the WebGL renderer).\n #pageAspect = 0;\n #bookW = 0;\n #fill = false;\n #contentShift = 0; // shiftUnit of the current static spread (nonzero = lone page, centered)\n\n mount(container: HTMLElement): Promise<void> {\n const doc = container.ownerDocument;\n this.#container = container;\n\n // Fixed-size clip box; NOT transformed, so zoom can't scale the crop region.\n this.#clip = doc.createElement('div');\n this.#clip.className = 'zine-clip';\n this.#clip.style.cssText = 'position:relative;width:100%;height:100%;overflow:hidden;';\n\n // Transform target for zoom/pan; lives inside the clip.\n this.#viewport = doc.createElement('div');\n this.#viewport.className = 'zine-viewport';\n this.#viewport.style.cssText = 'position:absolute;inset:0;transform-origin:0 0;';\n\n this.#book = doc.createElement('div');\n this.#book.className = 'zine-book';\n this.#book.style.cssText =\n 'position:absolute;inset:0;perspective:2000px;transform-style:preserve-3d;';\n\n this.#pageLeft = this.#makeCanvas(doc, 'zine-page-left', 'left:0;');\n this.#pageRight = this.#makeCanvas(doc, 'zine-page-right', 'right:0;');\n\n this.#leaf = doc.createElement('div');\n this.#leaf.className = 'zine-leaf';\n this.#leaf.style.cssText =\n 'position:absolute;top:0;width:50%;height:100%;transform-style:preserve-3d;display:none;';\n\n this.#leafFront = doc.createElement('canvas');\n this.#leafFront.className = 'zine-leaf-front';\n this.#leafFront.style.cssText =\n 'position:absolute;inset:0;width:100%;height:100%;backface-visibility:hidden;';\n\n this.#leafBack = doc.createElement('canvas');\n this.#leafBack.className = 'zine-leaf-back';\n this.#leafBack.style.cssText =\n 'position:absolute;inset:0;width:100%;height:100%;backface-visibility:hidden;transform:rotateY(180deg);';\n\n this.#leafShadow = doc.createElement('div');\n this.#leafShadow.className = 'zine-leaf-shadow';\n this.#leafShadow.style.cssText = 'position:absolute;inset:0;opacity:0;pointer-events:none;';\n this.#leafShadow.style.background = foldOverlay('forward'); // default; beginFlip sets per direction\n\n this.#leaf.append(this.#leafFront, this.#leafBack, this.#leafShadow);\n this.#book.append(this.#pageLeft, this.#pageRight, this.#leaf);\n this.#viewport.append(this.#book);\n this.#clip.append(this.#viewport);\n container.append(this.#clip);\n\n return Promise.resolve();\n }\n\n destroy(): void {\n this.#clip?.remove();\n this.#container = null;\n }\n\n renderSpread(_spread: Spread, content: SpreadContent, options?: RenderOptions): void {\n if (options?.fill) {\n // Single-page mode: the lone page fills the container; hide the other panel.\n this.#pageLeft.style.width = '100%';\n this.#pageRight.style.display = 'none';\n this.#paint(this.#pageLeft, content.right ?? content.left);\n } else {\n this.#pageLeft.style.width = '50%';\n this.#pageRight.style.display = '';\n this.#paint(this.#pageLeft, content.left);\n this.#paint(this.#pageRight, content.right);\n }\n this.#fill = options?.fill ?? false;\n this.#contentShift = this.#fill ? 0 : shiftUnit(content);\n this.#trackAspect(content);\n this.#layoutBook();\n this.#applyShift(this.#contentShift);\n // A fresh spread cancels any in-progress flip.\n this.#leaf.style.display = 'none';\n this.#leaf.style.transform = '';\n this.#leafShadow.style.opacity = '0';\n }\n\n beginFlip(\n from: SpreadContent,\n to: SpreadContent,\n direction: FlipDirection,\n options?: RenderOptions,\n ): void {\n if (options?.fill) {\n // Single-page: a full-width leaf turns about one edge, revealing `to` underneath.\n this.#pageLeft.style.width = '100%';\n this.#pageRight.style.display = 'none';\n this.#leaf.style.width = '100%';\n this.#leaf.style.left = '0';\n this.#leaf.style.transformOrigin = direction === 'forward' ? 'left center' : 'right center';\n this.#paint(this.#pageLeft, to.right ?? to.left);\n this.#paint(this.#leafFront, from.right ?? from.left);\n this.#paint(this.#leafBack, to.right ?? to.left);\n } else {\n this.#pageLeft.style.width = '50%';\n this.#pageRight.style.display = '';\n this.#leaf.style.width = '50%';\n if (direction === 'forward') {\n // Right page lifts and swings left about the spine. Left stays; right reveals `to`.\n this.#paint(this.#pageLeft, from.left);\n this.#paint(this.#pageRight, to.right);\n this.#paint(this.#leafFront, from.right);\n this.#paint(this.#leafBack, to.left);\n this.#leaf.style.left = '50%';\n this.#leaf.style.transformOrigin = 'left center';\n } else {\n // Left page swings right about its right edge. Right stays; left reveals `to`.\n this.#paint(this.#pageRight, from.right);\n this.#paint(this.#pageLeft, to.left);\n this.#paint(this.#leafFront, from.left);\n this.#paint(this.#leafBack, to.right);\n this.#leaf.style.left = '0';\n this.#leaf.style.transformOrigin = 'right center';\n }\n }\n this.#fromShiftUnit = options?.fill ? 0 : shiftUnit(from);\n this.#toShiftUnit = options?.fill ? 0 : shiftUnit(to);\n this.#fill = options?.fill ?? false;\n this.#trackAspect(to);\n this.#layoutBook();\n this.#applyShift(this.#fromShiftUnit);\n this.#leaf.style.display = 'block';\n this.#leaf.style.transform = 'rotateY(0deg)';\n this.#leafShadow.style.background = foldOverlay(direction);\n this.#leafShadow.style.opacity = '0';\n }\n\n setFlipProgress(t: number, direction: FlipDirection): void {\n const pose = flipProgressToPose(t);\n const deg = pose.angle * RAD_TO_DEG;\n this.#applyShift(this.#fromShiftUnit + (this.#toShiftUnit - this.#fromShiftUnit) * t);\n this.#leaf.style.display = 'block';\n this.#leaf.style.transform = `rotateY(${direction === 'forward' ? -deg : deg}deg)`;\n this.#leafShadow.style.opacity = String(pose.shadowAlpha);\n }\n\n #applyShift(unit: number): void {\n const px = unit * (this.#bookW / 4);\n this.#book.style.transform = px ? `translateX(${px}px)` : '';\n }\n\n /** Remember the page aspect (width/height) so the book can be letterboxed to it. */\n #trackAspect(content: SpreadContent): void {\n const p = content.left ?? content.right;\n if (p && p.height) this.#pageAspect = p.width / p.height;\n }\n\n /** Letterbox the 2-page book to the page aspect, centered in the container, so pages\n * fill their halves without stretching; the surround is the container background. */\n #layoutBook(): void {\n const b = this.#bookBox();\n this.#bookW = b.width;\n const s = this.#book.style;\n s.inset = 'auto';\n s.left = `${b.x}px`;\n s.top = `${b.y}px`;\n s.width = `${b.width}px`;\n s.height = `${b.height}px`;\n }\n\n /** The fitted book rect in container px (letterbox aware) — a stable 2-page area. */\n #bookBox(): { x: number; y: number; width: number; height: number } {\n const cw = this.#container?.clientWidth ?? 0;\n const ch = this.#container?.clientHeight ?? 0;\n if (this.#pageAspect <= 0 || cw <= 0 || ch <= 0) return { x: 0, y: 0, width: cw, height: ch };\n const ba = (this.#fill ? 1 : 2) * this.#pageAspect;\n let bw = cw;\n let bh = ch;\n if (ba > cw / ch) bh = cw / ba;\n else bw = ch * ba;\n return { x: (cw - bw) / 2, y: (ch - bh) / 2, width: bw, height: bh };\n }\n\n /** Where the current spread is actually painted: the book, or its centered half for a lone\n * page (mirrors #applyShift). This is what the engine hit-tests against. */\n #contentBox(): { x: number; y: number; width: number; height: number } {\n const b = this.#bookBox();\n return this.#contentShift !== 0 ? { x: b.x + b.width / 4, y: b.y, width: b.width / 2, height: b.height } : b;\n }\n\n setViewTransform(scale: number, x: number, y: number): void {\n this.#viewport.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;\n }\n\n measure(): LayoutMetrics {\n const el = this.#container;\n const w = el?.clientWidth ?? 0;\n const h = el?.clientHeight ?? 0;\n const known = this.#pageAspect > 0;\n const book = known ? this.#bookBox() : undefined;\n const content = known ? this.#contentBox() : undefined;\n return { containerWidth: w, containerHeight: h, pageWidth: w / 2, pageHeight: h, book, content };\n }\n\n #makeCanvas(doc: Document, className: string, extra: string): HTMLCanvasElement {\n const c = doc.createElement('canvas');\n c.className = className;\n c.style.cssText = `position:absolute;top:0;width:50%;height:100%;${extra}`;\n return c;\n }\n\n #paint(canvas: HTMLCanvasElement, content: PageContent | null): void {\n const ctx = canvas.getContext('2d');\n if (content === null) {\n ctx?.clearRect(0, 0, canvas.width, canvas.height);\n return;\n }\n canvas.width = content.width;\n canvas.height = content.height;\n ctx?.drawImage(content, 0, 0);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cssRenderer-Deskm2ND.js","names":["#container","#clip","#viewport","#book","#pageLeft","#makeCanvas","#pageRight","#leaf","#leafFront","#leafBack","#leafShadow","#paint","#fill","#contentShift","#trackAspect","#layoutBook","#applyShift","#fromShiftUnit","#toShiftUnit","#bookW","#pageAspect","#bookBox","#contentBox"],"sources":["../src/geometry/flipProgressToPose.ts","../src/renderer/cssRenderer.ts"],"sourcesContent":["export interface FlipPose {\n /** Turning-page rotation about the spine, radians: 0 (flat/open) → π (fully turned). */\n angle: number;\n /** Mesh cylinder-wrap curl, 0..1 — flat at the ends, peaks edge-on at t=0.5. CSS renderer ignores it. */\n curl: number;\n /** Fold-shadow intensity, 0..1 — peaks edge-on at t=0.5. */\n shadowAlpha: number;\n}\n\n/**\n * Map a 0→1 flip progress to a renderer-neutral fold pose.\n *\n * Linear in `t` on purpose — easing belongs to the animator that produces `t`,\n * so seeking to a fixed progress (e.g. the 0/.25/.5/.75/1 visual-regression stops)\n * is deterministic. The CSS renderer consumes `angle` as a spine `rotateY`; the\n * WebGL2 renderer additionally bends its mesh by `curl`.\n */\nexport function flipProgressToPose(t: number): FlipPose {\n const clamped = t < 0 ? 0 : t > 1 ? 1 : t;\n const arc = Math.sin(clamped * Math.PI);\n return {\n angle: clamped * Math.PI,\n curl: arc,\n shadowAlpha: arc,\n };\n}\n","import { flipProgressToPose } from '../geometry/flipProgressToPose';\nimport type { Spread } from '../engine/spread';\nimport type {\n FlipDirection,\n LayoutMetrics,\n PageContent,\n Renderer,\n RenderOptions,\n SpreadContent,\n} from './types';\n\nconst RAD_TO_DEG = 180 / Math.PI;\n\n/** How far to shift a spread to centre a lone page, in units of a quarter container width:\n * -1 = only a right page (cover), +1 = only a left page (back), 0 = a full spread. */\nfunction shiftUnit(content: SpreadContent): number {\n const lone = (content.left === null) !== (content.right === null);\n return lone ? (content.right !== null ? -1 : 1) : 0;\n}\n\n/**\n * Layered gradients painted over the turning leaf to fake paper depth on the flat\n * fold: a crease shadow at the spine, a soft curve sheen, and a free-edge shade.\n * The spine is the leaf's pivot edge — left for a forward flip, right for backward.\n */\nfunction foldOverlay(direction: FlipDirection): string {\n const dir = direction === 'forward' ? 'to right' : 'to left';\n return [\n `linear-gradient(${dir}, rgba(0,0,0,0.6), rgba(0,0,0,0.15) 40%, rgba(0,0,0,0) 60%)`,\n `linear-gradient(${dir}, transparent 40%, rgba(255,255,255,0.32) 66%, transparent 90%)`,\n `linear-gradient(${dir}, transparent 66%, rgba(0,0,0,0.35))`,\n ].join(',');\n}\n\n/**\n * Baseline renderer: a 2-panel CSS-3D fold. Runs on every browser, no GPU. Pages\n * are <canvas> elements; the turning leaf (front + back faces, backface-hidden)\n * rotates about the spine driven by flipProgressToPose(), with a gradient shadow\n * overlay for depth. `beginFlip` stages the surfaces; `setFlipProgress` animates.\n */\nexport class CssRenderer implements Renderer {\n #container: HTMLElement | null = null;\n #clip!: HTMLDivElement;\n #viewport!: HTMLDivElement;\n #book!: HTMLDivElement;\n #pageLeft!: HTMLCanvasElement;\n #pageRight!: HTMLCanvasElement;\n #leaf!: HTMLDivElement;\n #leafFront!: HTMLCanvasElement;\n #leafBack!: HTMLCanvasElement;\n #leafShadow!: HTMLDivElement;\n // Lone-page centering, interpolated across a flip (see the WebGL renderer).\n #fromShiftUnit = 0;\n #toShiftUnit = 0;\n // Book aspect fit: the spread is letterboxed to the page aspect (see the WebGL renderer).\n #pageAspect = 0;\n #bookW = 0;\n #fill = false;\n #contentShift = 0; // shiftUnit of the current static spread (nonzero = lone page, centered)\n\n mount(container: HTMLElement): Promise<void> {\n const doc = container.ownerDocument;\n this.#container = container;\n\n // Fixed-size clip box; NOT transformed, so zoom can't scale the crop region.\n this.#clip = doc.createElement('div');\n this.#clip.className = 'zine-clip';\n this.#clip.style.cssText = 'position:relative;width:100%;height:100%;overflow:hidden;';\n\n // Transform target for zoom/pan; lives inside the clip.\n this.#viewport = doc.createElement('div');\n this.#viewport.className = 'zine-viewport';\n this.#viewport.style.cssText = 'position:absolute;inset:0;transform-origin:0 0;';\n\n this.#book = doc.createElement('div');\n this.#book.className = 'zine-book';\n this.#book.style.cssText =\n 'position:absolute;inset:0;perspective:2000px;transform-style:preserve-3d;';\n\n this.#pageLeft = this.#makeCanvas(doc, 'zine-page-left', 'left:0;');\n this.#pageRight = this.#makeCanvas(doc, 'zine-page-right', 'right:0;');\n\n this.#leaf = doc.createElement('div');\n this.#leaf.className = 'zine-leaf';\n this.#leaf.style.cssText =\n 'position:absolute;top:0;width:50%;height:100%;transform-style:preserve-3d;display:none;';\n\n this.#leafFront = doc.createElement('canvas');\n this.#leafFront.className = 'zine-leaf-front';\n this.#leafFront.style.cssText =\n 'position:absolute;inset:0;width:100%;height:100%;backface-visibility:hidden;';\n\n this.#leafBack = doc.createElement('canvas');\n this.#leafBack.className = 'zine-leaf-back';\n this.#leafBack.style.cssText =\n 'position:absolute;inset:0;width:100%;height:100%;backface-visibility:hidden;transform:rotateY(180deg);';\n\n this.#leafShadow = doc.createElement('div');\n this.#leafShadow.className = 'zine-leaf-shadow';\n this.#leafShadow.style.cssText = 'position:absolute;inset:0;opacity:0;pointer-events:none;';\n this.#leafShadow.style.background = foldOverlay('forward'); // default; beginFlip sets per direction\n\n this.#leaf.append(this.#leafFront, this.#leafBack, this.#leafShadow);\n this.#book.append(this.#pageLeft, this.#pageRight, this.#leaf);\n this.#viewport.append(this.#book);\n this.#clip.append(this.#viewport);\n container.append(this.#clip);\n\n return Promise.resolve();\n }\n\n destroy(): void {\n this.#clip?.remove();\n this.#container = null;\n }\n\n renderSpread(_spread: Spread, content: SpreadContent, options?: RenderOptions): void {\n if (options?.fill) {\n // Single-page mode: the lone page fills the container; hide the other panel.\n this.#pageLeft.style.width = '100%';\n this.#pageRight.style.display = 'none';\n this.#paint(this.#pageLeft, content.right ?? content.left);\n } else {\n this.#pageLeft.style.width = '50%';\n this.#pageRight.style.display = '';\n this.#paint(this.#pageLeft, content.left);\n this.#paint(this.#pageRight, content.right);\n }\n this.#fill = options?.fill ?? false;\n this.#contentShift = this.#fill ? 0 : shiftUnit(content);\n this.#trackAspect(content);\n this.#layoutBook();\n this.#applyShift(this.#contentShift);\n // A fresh spread cancels any in-progress flip.\n this.#leaf.style.display = 'none';\n this.#leaf.style.transform = '';\n this.#leafShadow.style.opacity = '0';\n }\n\n beginFlip(\n from: SpreadContent,\n to: SpreadContent,\n direction: FlipDirection,\n options?: RenderOptions,\n ): void {\n if (options?.fill) {\n // Single-page: a full-width leaf turns about one edge, revealing `to` underneath.\n this.#pageLeft.style.width = '100%';\n this.#pageRight.style.display = 'none';\n this.#leaf.style.width = '100%';\n this.#leaf.style.left = '0';\n this.#leaf.style.transformOrigin = direction === 'forward' ? 'left center' : 'right center';\n this.#paint(this.#pageLeft, to.right ?? to.left);\n this.#paint(this.#leafFront, from.right ?? from.left);\n this.#paint(this.#leafBack, to.right ?? to.left);\n } else {\n this.#pageLeft.style.width = '50%';\n this.#pageRight.style.display = '';\n this.#leaf.style.width = '50%';\n if (direction === 'forward') {\n // Right page lifts and swings left about the spine. Left stays; right reveals `to`.\n this.#paint(this.#pageLeft, from.left);\n this.#paint(this.#pageRight, to.right);\n this.#paint(this.#leafFront, from.right);\n this.#paint(this.#leafBack, to.left);\n this.#leaf.style.left = '50%';\n this.#leaf.style.transformOrigin = 'left center';\n } else {\n // Left page swings right about its right edge. Right stays; left reveals `to`.\n this.#paint(this.#pageRight, from.right);\n this.#paint(this.#pageLeft, to.left);\n this.#paint(this.#leafFront, from.left);\n this.#paint(this.#leafBack, to.right);\n this.#leaf.style.left = '0';\n this.#leaf.style.transformOrigin = 'right center';\n }\n }\n this.#fromShiftUnit = options?.fill ? 0 : shiftUnit(from);\n this.#toShiftUnit = options?.fill ? 0 : shiftUnit(to);\n this.#fill = options?.fill ?? false;\n this.#trackAspect(to);\n this.#layoutBook();\n this.#applyShift(this.#fromShiftUnit);\n this.#leaf.style.display = 'block';\n this.#leaf.style.transform = 'rotateY(0deg)';\n this.#leafShadow.style.background = foldOverlay(direction);\n this.#leafShadow.style.opacity = '0';\n }\n\n setFlipProgress(t: number, direction: FlipDirection): void {\n const pose = flipProgressToPose(t);\n const deg = pose.angle * RAD_TO_DEG;\n this.#applyShift(this.#fromShiftUnit + (this.#toShiftUnit - this.#fromShiftUnit) * t);\n this.#leaf.style.display = 'block';\n this.#leaf.style.transform = `rotateY(${direction === 'forward' ? -deg : deg}deg)`;\n this.#leafShadow.style.opacity = String(pose.shadowAlpha);\n }\n\n #applyShift(unit: number): void {\n const px = unit * (this.#bookW / 4);\n this.#book.style.transform = px ? `translateX(${px}px)` : '';\n }\n\n /** Remember the page aspect (width/height) so the book can be letterboxed to it. */\n #trackAspect(content: SpreadContent): void {\n const p = content.left ?? content.right;\n if (p && p.height) this.#pageAspect = p.width / p.height;\n }\n\n /** Letterbox the 2-page book to the page aspect, centered in the container, so pages\n * fill their halves without stretching; the surround is the container background. */\n #layoutBook(): void {\n const b = this.#bookBox();\n this.#bookW = b.width;\n const s = this.#book.style;\n s.inset = 'auto';\n s.left = `${b.x}px`;\n s.top = `${b.y}px`;\n s.width = `${b.width}px`;\n s.height = `${b.height}px`;\n }\n\n /** The fitted book rect in container px (letterbox aware) — a stable 2-page area. */\n #bookBox(): { x: number; y: number; width: number; height: number } {\n const cw = this.#container?.clientWidth ?? 0;\n const ch = this.#container?.clientHeight ?? 0;\n if (this.#pageAspect <= 0 || cw <= 0 || ch <= 0) return { x: 0, y: 0, width: cw, height: ch };\n const ba = (this.#fill ? 1 : 2) * this.#pageAspect;\n let bw = cw;\n let bh = ch;\n if (ba > cw / ch) bh = cw / ba;\n else bw = ch * ba;\n return { x: (cw - bw) / 2, y: (ch - bh) / 2, width: bw, height: bh };\n }\n\n /** Where the current spread is actually painted: the book, or its centered half for a lone\n * page (mirrors #applyShift). This is what the engine hit-tests against. */\n #contentBox(): { x: number; y: number; width: number; height: number } {\n const b = this.#bookBox();\n return this.#contentShift !== 0 ? { x: b.x + b.width / 4, y: b.y, width: b.width / 2, height: b.height } : b;\n }\n\n setViewTransform(scale: number, x: number, y: number): void {\n this.#viewport.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;\n }\n\n measure(): LayoutMetrics {\n const el = this.#container;\n const w = el?.clientWidth ?? 0;\n const h = el?.clientHeight ?? 0;\n const known = this.#pageAspect > 0;\n const book = known ? this.#bookBox() : undefined;\n const content = known ? this.#contentBox() : undefined;\n // The shift lives on #book, inside the scaled #viewport, so unlike the WebGL2 renderer it\n // magnifies along with everything else and the whole box simply scales.\n const screenAt = content\n ? (scale: number): { x: number; y: number; width: number; height: number } => ({\n x: content.x * scale,\n y: content.y * scale,\n width: content.width * scale,\n height: content.height * scale,\n })\n : undefined;\n return {\n containerWidth: w,\n containerHeight: h,\n pageWidth: w / 2,\n pageHeight: h,\n book,\n content,\n screenAt,\n };\n }\n\n #makeCanvas(doc: Document, className: string, extra: string): HTMLCanvasElement {\n const c = doc.createElement('canvas');\n c.className = className;\n c.style.cssText = `position:absolute;top:0;width:50%;height:100%;${extra}`;\n return c;\n }\n\n #paint(canvas: HTMLCanvasElement, content: PageContent | null): void {\n const ctx = canvas.getContext('2d');\n if (content === null) {\n ctx?.clearRect(0, 0, canvas.width, canvas.height);\n return;\n }\n canvas.width = content.width;\n canvas.height = content.height;\n ctx?.drawImage(content, 0, 0);\n }\n}\n"],"mappings":"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"}
|