@toneflix/flipbook 0.2.1 → 0.2.2
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/flipbook.iife.js +4 -4
- package/dist/index.cjs +62 -30
- package/dist/index.d.cts +7 -4
- package/dist/index.d.mts +7 -4
- package/dist/index.mjs +63 -32
- package/dist/style.css +307 -0
- package/package.json +2 -2
package/dist/flipbook.iife.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var Flipbook=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=(e,t)=>({x:e.x-t.x,y:e.y-t.y}),n=(e,t)=>e.x*t.x+e.y*t.y,r=e=>Math.hypot(e.x,e.y);var i=class e{a;b;c;d;e;f;constructor(e=1,t=0,n=0,r=1,i=0,a=0){this.a=e,this.b=t,this.c=n,this.d=r,this.e=i,this.f=a}static translate(t,n){return new e(1,0,0,1,t,n)}static rotate(t){let n=Math.cos(t),r=Math.sin(t);return new e(n,r,-r,n,0,0)}static scale(t,n=t){return new e(t,0,0,n,0,0)}static reflect(t,r){let{x:i,y:a}=r,o=2*n(t,r);return new e(1-2*i*i,-2*i*a,-2*i*a,1-2*a*a,o*i,o*a)}after(t){let{a:n,b:r,c:i,d:a,e:o,f:s}=this;return new e(n*t.a+i*t.b,r*t.a+a*t.b,n*t.c+i*t.d,r*t.c+a*t.d,n*t.e+i*t.f+o,r*t.e+a*t.f+s)}invert(){let{a:t,b:n,c:r,d:i,e:a,f:o}=this,s=t*i-n*r;return new e(i/s,-n/s,-r/s,t/s,(r*o-i*a)/s,(n*a-t*o)/s)}apply(e){return{x:this.a*e.x+this.c*e.y+this.e,y:this.b*e.x+this.d*e.y+this.f}}toCss(){return`matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.e}, ${this.f})`}place(e,t){let n=this.apply({x:e/2,y:t/2}),r=this.a*this.d-this.b*this.c<0,i=r?Math.atan2(-this.b,-this.a):Math.atan2(this.b,this.a);return{left:n.x-e/2,top:n.y-t/2,width:e,height:t,angle:i,mirror:r}}},a=class e{width;height;origin;point;center;normal;progress;flat;folded;constructor(n,i,a,o){this.width=n,this.height=i,this.origin=a,this.point=e.attach(o,a,i);let s=t(a,this.point),c=r(s),l=[{x:0,y:0},{x:n,y:0},{x:n,y:i},{x:0,y:i}];this.center={x:(a.x+this.point.x)/2,y:(a.y+this.point.y)/2},this.progress=Math.min(1,c/Math.max(1,2*a.x)),c<.5?(this.normal={x:1,y:0},this.flat=l,this.folded=[]):(this.normal={x:s.x/c,y:s.y/c},this.flat=this.clip(l,-1),this.folded=this.clip(l,1))}static attach(e,n,i){let a=[{x:0,y:0},{x:0,y:i}],o=e;for(let e=0;e<3;e++)for(let e of a){let i=r(t(n,e)),a=t(o,e),s=r(a);s>i&&(o={x:e.x+a.x*i/s,y:e.y+a.y*i/s})}return o}static hinge(e,t,n){let r=Math.max(-1,Math.min(1,n*t.x/Math.max(1,e.x)));return-Math.acos(r)*180/Math.PI}get shade(){return Math.min(1,this.progress*8)*Math.min(1,(1-this.progress)*6)}reflect(e){let r=2*n(t(e,this.center),this.normal);return{x:e.x-r*this.normal.x,y:e.y-r*this.normal.y}}get reflection(){return i.reflect(this.center,this.normal)}get flap(){return this.folded.map(e=>this.reflect(e))}flapMatrix(e){let{x:t,y:n}=this.normal,r=e===1?-1:1,i=e*(1-2*t*t)*r,a=-2*t*n*r,o=-2*e*t*n,s=1-2*n*n,c=this.reflect({x:e===1?this.width:0,y:0});return`matrix(${i}, ${a}, ${o}, ${s}, ${e*c.x}, ${c.y})`}clip(e,r){let i=[],a=e=>r*n(t(e,this.center),this.normal)>=0;return e.forEach((o,s)=>{let c=e[(s+e.length-1)%e.length],l=r*n(t(c,this.center),this.normal),u=r*n(t(o,this.center),this.normal);if(a(o)!==a(c)){let e=l/(l-u);i.push({x:c.x+(o.x-c.x)*e,y:c.y+(o.y-c.y)*e})}a(o)&&i.push(o)}),i}};let o={fall:.0075,auto:.0055,peek:.02,flick:170,lift:.12},s={now:()=>performance.now(),request:e=>requestAnimationFrame(e),cancel:e=>cancelAnimationFrame(e)},c=()=>typeof matchMedia==`function`&&matchMedia(`(prefers-reduced-motion: reduce)`).matches;var l=class{listener;physics;mode=`idle`;origin={x:0,y:0};point={x:0,y:0};stiff=!1;size={width:1,height:1};position={x:0,y:0};velocity={x:0,y:0};target={x:0,y:0};omega=o.fall;lift=0;turned=!1;trail=[];handle=0;last=0;scheduler;reducedMotion;constructor(e,t={}){this.listener=e,this.physics={...o,...t.physics},this.scheduler=t.scheduler??s,this.reducedMotion=t.reducedMotion??c}get active(){return this.mode!==`idle`}get dragging(){return this.mode===`drag`}get peeking(){return this.mode===`peek`}get frame(){return{origin:this.origin,point:this.point,stiff:this.stiff}}grab(e,t,n,r){this.size=n,this.origin=e,this.stiff=r,this.mode=`drag`,this.trail=[],this.stop(),this.moveTo(t)}drag(e){this.mode===`drag`&&this.moveTo(e)}release(){if(this.mode!==`drag`)return!1;let e=this.speed(),t=this.point.x+e.x*this.physics.flick;return this.fall(t<0,e,this.physics.fall),this.turned}turn(e,t,n){this.size=t,this.origin=e,this.stiff=n,this.point={...e},this.fall(!0,{x:0,y:0},this.physics.auto)}peek(e,t,n,r){this.mode!==`drag`&&this.mode!==`fall`&&((this.mode===`idle`||this.origin.x!==e.x||this.origin.y!==e.y)&&(this.size=n,this.origin=e,this.stiff=r,this.point={...e},this.position={...this.point},this.velocity={x:0,y:0},this.lift=0),this.mode=`peek`,this.omega=this.physics.peek,this.target=t,this.turned=t.x<0,this.run())}unpeek(){this.mode===`peek`&&(this.mode=`fall`,this.target=this.turned?{x:-this.origin.x,y:this.origin.y}:{...this.origin},this.run())}finish(){if(this.mode===`idle`)return;let e=this.mode===`fall`?this.turned:this.point.x<0;this.stop(),this.mode=`idle`,this.listener.settle(e)}cancel(){this.stop(),this.mode=`idle`}moveTo(e){let t=this.stiff?{x:Math.max(-this.origin.x,Math.min(this.origin.x,e.x)),y:this.origin.y}:a.attach(e,this.origin,this.size.height),n=this.scheduler.now();this.point=t,this.trail.push({p:t,t:n}),this.trail=this.trail.filter(e=>n-e.t<100),this.listener.frame(this.frame)}speed(){if(this.trail.length<2)return{x:0,y:0};let e=this.trail[0],t=this.trail[this.trail.length-1],n=Math.max(1,t.t-e.t);return{x:(t.p.x-e.p.x)/n,y:(t.p.y-e.p.y)/n}}fall(e,t,n){this.reducedMotion()?(this.stop(),this.mode=`idle`,this.listener.settle(e)):(this.mode=`fall`,this.turned=e,this.omega=n,this.target=e?{x:-this.origin.x,y:this.origin.y}:{...this.origin},this.lift=this.stiff?0:this.size.height*this.physics.lift*(this.origin.y>this.size.height/2?-1:1),this.position={x:this.point.x,y:this.point.y-this.arc(this.point.x)},this.velocity=t,this.run())}arc(e){let t=Math.max(1,this.origin.x),n=Math.min(1,Math.abs(e)/t);return this.lift*(1-n*n)}run(){this.handle||=(this.last=this.scheduler.now(),this.scheduler.request(this.tick))}stop(){this.handle&&this.scheduler.cancel(this.handle),this.handle=0}tick=e=>{let n=Math.min(48,e-this.last),i=this.omega;this.last=e;for(let e=0;e<n;e+=4){let t=Math.min(4,n-e);for(let e of[`x`,`y`]){let n=i*i*(this.target[e]-this.position[e])-2*i*this.velocity[e];this.velocity[e]+=n*t,this.position[e]+=this.velocity[e]*t}}let o={x:this.position.x,y:this.position.y+(this.mode===`fall`?this.arc(this.position.x):0)};this.point=this.stiff?{x:o.x,y:this.origin.y}:a.attach(o,this.origin,this.size.height),this.listener.frame(this.frame);let s=r(t(this.target,this.position))<.5&&r(this.velocity)<.02;s&&this.mode===`fall`?(this.handle=0,this.mode=`idle`,this.listener.settle(this.turned)):this.handle=s?0:this.scheduler.request(this.tick)}};let u={single:{label:`Full bleed`,slots:1},framed:{label:`Framed`,slots:1},pair:{label:`Pair`,slots:2},grid:{label:`Grid`,slots:4},collage:{label:`Collage`,slots:3},text:{label:`Words`,slots:0},triptych:{label:`Triptych`,slots:3},mosaic:{label:`Mosaic`,slots:3},strip:{label:`Film strip`,slots:3},contact:{label:`Contact sheet`,slots:6},scatter:{label:`Loose prints`,slots:3},story:{label:`Story`,slots:1}},d=(e,t,n,r=7,i=108,a=3)=>{let o=(i-a*(n-1))/n;return Array.from({length:n},(n,i)=>({x:e,y:r+i*(o+a),width:t,height:o}))},f={x:7,y:118,width:86,height:10},p={triptych:{slots:[7,36.67,66.33].map(e=>({x:e,y:14,width:26.67,height:94})),caption:{...f,y:114}},mosaic:{slots:[{x:7,y:7,width:51,height:108},...d(61,32,2)],caption:f},strip:{slots:d(7,86,3),caption:f},contact:{slots:d(7,41.5,3).flatMap((e,t)=>[e,d(51.5,41.5,3)[t]]),caption:f},scatter:{slots:[{x:9,y:9,width:54,height:41,rotate:-4},{x:38,y:43,width:54,height:41,rotate:3},{x:11,y:80,width:48,height:35,rotate:-2}],caption:{...f,x:63,y:92,width:30,height:28},loose:!0},story:{slots:[{x:7,y:7,width:86,height:66}],caption:{x:9,y:80,width:82,height:45},prose:!0}},m={classic:{label:`Classic`,cloth:`#5a1d22`,ink:`#e2c58f`,stage:[`#4a2a27`,`#22140f`,`#0d0807`]},linen:{label:`Linen`,cloth:`#e6dcc6`,ink:`#3d3226`,stage:[`#4a4134`,`#241f18`,`#0e0c09`]},midnight:{label:`Midnight`,cloth:`#141b2e`,ink:`#d5dbe8`,stage:[`#27324d`,`#121827`,`#07090f`]}},h={ivory:{label:`Ivory`,swatch:`#fbf8f1`},white:{label:`White`,swatch:`#ffffff`},kraft:{label:`Kraft`,swatch:`#d8c4a2`},charcoal:{label:`Charcoal`,swatch:`#2a2826`}},g={none:{label:`Plain`,description:`The photo printed straight onto the page`},hairline:{label:`Hairline`,description:`A fine printed rule around the photo`},double:{label:`Double rule`,description:`Two printed rules, like a classic album keyline`},mat:{label:`Gallery mat`,description:`A wide printed mat with a thin frame line`},corners:{label:`Photo corners`,description:`Printed album corners holding the photo`},deckle:{label:`Deckled edge`,description:`A vintage print with a scalloped border`},plate:{label:`Plate mark`,description:`The photo sits in a plate pressed into the paper`},feather:{label:`Soft edge`,description:`The photo fades into the paper at its edges`},oval:{label:`Oval`,description:`An oval cameo inside a fine printed ring`},botanical:{label:`Botanical`,description:`Line-drawn sprigs of leaves around a fine rule`},watercolor:{label:`Watercolour`,description:`A wash of soft colour printed around a mat`},arcs:{label:`Rainbow arcs`,description:`A printed border of little rainbow arcs around a mat`},gilt:{label:`Gilt`,description:`An engraved border printed in gold ink`},woodgrain:{label:`Woodgrain`,description:`A printed woodgrain border around a mat`}},_={watercolor:3,arcs:3,gilt:2.6,woodgrain:3};function v(e,t,n=`none`){return e.layout===`single`?`none`:t?.frame??y(e,n)}function y(e,t=`none`){return e.layout===`single`?`none`:e.frame??t}var b=class e{pageCount;faces;leaves;spread;stiffCovers;constructor(t,{spread:n,stiffCovers:r=!0}){this.pageCount=t;let i=Array.from({length:t},(e,t)=>({kind:`page`,index:t})),a=n&&t%2==1?[{kind:`blank`}]:[];this.spread=n,this.stiffCovers=r,this.faces=[{kind:`cover`},{kind:`title`},...i,...a,{kind:`colophon`},{kind:`back`}],this.leaves=n?e.pair(this.faces):this.faces.map(e=>({front:e,back:{kind:`blank`}}))}static pair(e){let t=[];for(let n=0;n<e.length;n+=2)t.push({front:e[n],back:e[n+1]});return t}get length(){return this.leaves.length}flippedForFace(e){return this.spread?Math.ceil(e/2):e}flippedForPage(e){return!e||e<1||e>this.pageCount?0:this.flippedForFace(e+1)}convert(e,t){return t.spread===this.spread?Math.min(e,this.length):this.spread?Math.ceil(e/2):Math.max(0,e*2-1)}isStiff(e){let{front:t,back:n}=this.leaves[e]??{};return this.stiffCovers&&(t?.kind===`cover`||t?.kind===`back`||n?.kind===`back`)}visible(e){return e<=0?[this.leaves[0].front]:e>=this.length?[this.spread?this.leaves[this.length-1].back:this.faces[this.faces.length-1]]:this.spread?[this.leaves[e-1].back,this.leaves[e].front]:[this.leaves[e].front]}stops(){if(!this.spread)return this.faces.map((e,t)=>({flipped:t,faces:[e]}));let e=[{flipped:0,faces:[this.faces[0]]}];for(let t=1;t<this.faces.length-1;t+=2)e.push({flipped:this.flippedForFace(t),faces:[this.faces[t],this.faces[t+1]]});return e.push({flipped:this.length,faces:[this.faces[this.faces.length-1]]}),e}label(t){if(t<=0)return`Cover`;if(t>=this.length)return`Back cover`;let n=e.pageNumbers(this.visible(t));return n.length===0?this.visible(t).some(e=>e.kind===`title`)?`Title page`:`The end`:n.length===1?`Page ${n[0]} of ${this.pageCount}`:`Pages ${n[0]}–${n[1]} of ${this.pageCount}`}static describe(t){let n=e.pageNumbers(t);return n.length?`page ${n.join(` and `)}`:t[0].kind===`back`?`the back cover`:t[0].kind===`cover`?`the cover`:`the title page`}static pageNumbers(e){return e.filter(e=>e.kind===`page`).map(e=>e.index+1)}};let x={edgeX:.15,edgeY:.08,peek:!0};var S=class{events;flipped;active=null;layout;width=0;height=0;grip;engine;press=null;grabStart={x:0,y:0};grabDir=1;grabReach=1;constructor(e,t,n={}){this.events=t,this.layout=e,this.flipped=Math.max(0,Math.min(e.length,n.flipped??0)),this.grip={...x,...n.grip},this.engine=new l({frame:e=>this.active&&this.events.frame(e,this.active),settle:e=>this.settle(e)},n)}get size(){return{width:this.width,height:this.height}}get atStart(){return this.flipped===0}get atEnd(){return this.flipped===this.layout.length}get settled(){return!this.active||this.active.peek}get label(){return this.layout.label(this.flipped)}configure({layout:e,width:t,height:n}){let r=e&&e!==this.layout,i=t!==void 0&&t!==this.width||n!==void 0&&n!==this.height;(r||i)&&(e&&r&&(this.flipped=e.convert(this.flipped,this.layout),this.layout=e),this.width=t??this.width,this.height=n??this.height,this.engine.cancel(),this.active=null,this.press=null,this.events.change())}go(e){let t=Math.max(0,Math.min(this.layout.length,e));if(t===this.flipped||this.width===0)return;if(this.engine.active&&!this.engine.peeking){this.engine.finish();return}if(this.engine.cancel(),this.events.flip(),Math.abs(t-this.flipped)!==1){this.active=null,this.flipped=t,this.events.change();return}let n=Math.min(t,this.flipped),r=this.layout.isStiff(n);this.begin({leaf:n,dir:t>this.flipped?1:-1,stiff:r,peek:!1}),this.engine.turn({x:this.width,y:r?this.height/2:this.height},this.size,r)}next(){this.go(this.flipped+1)}prev(){this.go(this.flipped-1)}hover(e){if(this.press||this.engine.dragging)return;let t=this.grip.peek?this.cornerAt(e):null;if(!t){this.engine.unpeek();return}let{width:n,height:r}=this,i=t.x>0?1:-1,a=i===1?this.flipped:this.flipped-1,o=this.layout.isStiff(a),s={x:n,y:o?r/2:t.y},c={x:i*(e.x-t.x),y:e.y-t.y},l=Math.hypot(c.x,c.y)||1,u=Math.max(n*.12,Math.min(n*.2,l*2)),d={x:n+c.x/l*u,y:o?s.y:t.y+c.y/l*u};(this.active?.leaf!==a||this.active.dir!==i)&&this.begin({leaf:a,dir:i,stiff:o,peek:!0}),this.engine.peek(s,d,this.size,o)}leave(){this.engine.unpeek()}down(e,t){this.press={at:e,id:t,grabbed:!1}}move(e,t){let n=this.press;if(!n||n.id!==t)return!1;let r=e.x-n.at.x,i=e.y-n.at.y;if(!n.grabbed){if(Math.hypot(r,i)<6||this.engine.active&&!this.engine.peeking)return!1;let e=(this.engine.peeking&&this.active?{...this.active,origin:this.engine.frame.origin,start:this.engine.frame.point}:null)??this.holdAt(n.at);if(!e)return!1;n.grabbed=!0,this.grabStart=e.start,this.grabDir=e.dir,this.grabReach=!this.layout.spread&&e.dir===-1?2:1,this.begin({leaf:e.leaf,dir:e.dir,stiff:e.stiff,peek:!1}),this.engine.grab(e.origin,e.start,this.size,e.stiff)}return this.engine.drag({x:this.grabStart.x+this.grabDir*this.grabReach*r,y:this.grabStart.y+i}),!0}up(e,t){let n=this.press;return!n||n.id!==t?null:(this.press=null,n.grabbed?(this.engine.release()&&this.events.flip(),`turn`):Math.abs(e.x-n.at.x)<8&&Math.abs(e.y-n.at.y)<8?`tap`:null)}cancel(){this.press=null,this.engine.dragging&&this.engine.release()}destroy(){this.engine.cancel()}begin(e){this.active=e,this.events.change()}settle(e){let t=this.active;if(!t)return;let n=t.dir===1?e:!e;this.flipped=n?t.leaf+1:t.leaf,this.active=null,this.events.change()}holdAt(e){let{width:t,height:n,layout:r}=this,i=r.spread?e.x>=0:e.x>=t*.3,a=i?this.flipped:this.flipped-1;if(a<0||a>=r.length)return null;let o=i?e:{x:r.spread?-e.x:t,y:e.y},s=o.x>t*(1-this.grip.edgeX),c=o.y<n*this.grip.edgeY,l=o.y>n*(1-this.grip.edgeY),u=r.isStiff(a),d={x:s||!(c||l)?t:Math.max(1,o.x),y:u?n/2:c?0:l?n:Math.max(0,Math.min(n,o.y))};return{leaf:a,dir:i?1:-1,origin:d,stiff:u,start:d}}cornerAt(e){let{width:t,height:n,layout:r,flipped:i}=this,a=Math.max(36,t*.12);return[...i<r.length?[{x:t,y:0},{x:t,y:n}]:[],...r.spread&&i>0?[{x:-t,y:0},{x:-t,y:n}]:[]].find(t=>Math.hypot(e.x-t.x,e.y-t.y)<a)??null}};let C={previous:`Previous page`,next:`Next page`,soundOn:`Turn page sound on`,soundOff:`Turn page sound off`,fullscreen:`Full screen`,exitFullscreen:`Exit full screen`,byline:e=>`by ${e}`,rotateTitle:`Turn your phone sideways`,rotateBody:`Photo books open across two pages, just like the real thing.`,rotateFullscreen:`Open full screen`,rotateSingle:`Read one page at a time`};function w(e,t={},...n){let r=document.createElement(e);for(let[e,n]of Object.entries(t))e===`style`?Object.assign(r.style,n):n!=null&&n!==!1&&r.setAttribute(e,n===!0?``:String(n));return T(r,n),r}function T(e,t){for(let n of t)n&&e.append(n)}function E(e){let t=document.createElement(`template`);return t.innerHTML=e.trim(),t.content.firstElementChild}async function D(e){try{!document.fullscreenElement&&e.requestFullscreen&&await e.requestFullscreen({navigationUI:`hide`})}catch{}try{let e=screen.orientation;if(e?.lock)return await e.lock(`landscape`),!0}catch{}return!1}function O(e){let t=matchMedia(`(orientation: portrait)`),n=matchMedia(`(pointer: coarse)`),r=()=>e({portrait:t.matches,touch:n.matches});return r(),t.addEventListener(`change`,r),n.addEventListener(`change`,r),window.addEventListener(`resize`,r),()=>{t.removeEventListener(`change`,r),n.removeEventListener(`change`,r),window.removeEventListener(`resize`,r)}}let k=[14,24,34,44,54,64,74].map((e,t)=>({x:e,angle:t%2?38:-38,length:26-t*2})),A=e=>E(`<svg viewBox="0 0 100 40" class="fb-print-frame-sprig is-${e}" fill="none" stroke="currentColor" stroke-linecap="round" aria-hidden="true">
|
|
1
|
+
var Flipbook=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=(e,t)=>({x:e.x-t.x,y:e.y-t.y}),n=(e,t)=>e.x*t.x+e.y*t.y,r=e=>Math.hypot(e.x,e.y);var i=class e{a;b;c;d;e;f;constructor(e=1,t=0,n=0,r=1,i=0,a=0){this.a=e,this.b=t,this.c=n,this.d=r,this.e=i,this.f=a}static translate(t,n){return new e(1,0,0,1,t,n)}static rotate(t){let n=Math.cos(t),r=Math.sin(t);return new e(n,r,-r,n,0,0)}static scale(t,n=t){return new e(t,0,0,n,0,0)}static reflect(t,r){let{x:i,y:a}=r,o=2*n(t,r);return new e(1-2*i*i,-2*i*a,-2*i*a,1-2*a*a,o*i,o*a)}after(t){let{a:n,b:r,c:i,d:a,e:o,f:s}=this;return new e(n*t.a+i*t.b,r*t.a+a*t.b,n*t.c+i*t.d,r*t.c+a*t.d,n*t.e+i*t.f+o,r*t.e+a*t.f+s)}invert(){let{a:t,b:n,c:r,d:i,e:a,f:o}=this,s=t*i-n*r;return new e(i/s,-n/s,-r/s,t/s,(r*o-i*a)/s,(n*a-t*o)/s)}apply(e){return{x:this.a*e.x+this.c*e.y+this.e,y:this.b*e.x+this.d*e.y+this.f}}toCss(){return`matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.e}, ${this.f})`}place(e,t){let n=this.apply({x:e/2,y:t/2}),r=this.a*this.d-this.b*this.c<0,i=r?Math.atan2(-this.b,-this.a):Math.atan2(this.b,this.a);return{left:n.x-e/2,top:n.y-t/2,width:e,height:t,angle:i,mirror:r}}},a=class e{width;height;origin;point;center;normal;progress;flat;folded;constructor(n,i,a,o){this.width=n,this.height=i,this.origin=a,this.point=e.attach(o,a,i);let s=t(a,this.point),c=r(s),l=[{x:0,y:0},{x:n,y:0},{x:n,y:i},{x:0,y:i}];this.center={x:(a.x+this.point.x)/2,y:(a.y+this.point.y)/2},this.progress=Math.min(1,c/Math.max(1,2*a.x)),c<.5?(this.normal={x:1,y:0},this.flat=l,this.folded=[]):(this.normal={x:s.x/c,y:s.y/c},this.flat=this.clip(l,-1),this.folded=this.clip(l,1))}static attach(e,n,i){let a=[{x:0,y:0},{x:0,y:i}],o=e;for(let e=0;e<3;e++)for(let e of a){let i=r(t(n,e)),a=t(o,e),s=r(a);s>i&&(o={x:e.x+a.x*i/s,y:e.y+a.y*i/s})}return o}static hinge(e,t,n){let r=Math.max(-1,Math.min(1,n*t.x/Math.max(1,e.x)));return-Math.acos(r)*180/Math.PI}get shade(){return Math.min(1,this.progress*8)*Math.min(1,(1-this.progress)*6)}reflect(e){let r=2*n(t(e,this.center),this.normal);return{x:e.x-r*this.normal.x,y:e.y-r*this.normal.y}}get reflection(){return i.reflect(this.center,this.normal)}get flap(){return this.folded.map(e=>this.reflect(e))}flapMatrix(e){let{x:t,y:n}=this.normal,r=e===1?-1:1,i=e*(1-2*t*t)*r,a=-2*t*n*r,o=-2*e*t*n,s=1-2*n*n,c=this.reflect({x:e===1?this.width:0,y:0});return`matrix(${i}, ${a}, ${o}, ${s}, ${e*c.x}, ${c.y})`}clip(e,r){let i=[],a=e=>r*n(t(e,this.center),this.normal)>=0;return e.forEach((o,s)=>{let c=e[(s+e.length-1)%e.length],l=r*n(t(c,this.center),this.normal),u=r*n(t(o,this.center),this.normal);if(a(o)!==a(c)){let e=l/(l-u);i.push({x:c.x+(o.x-c.x)*e,y:c.y+(o.y-c.y)*e})}a(o)&&i.push(o)}),i}};let o={fall:.0075,auto:.0055,peek:.02,flick:170,lift:.12},s={now:()=>performance.now(),request:e=>requestAnimationFrame(e),cancel:e=>cancelAnimationFrame(e)},c=()=>typeof matchMedia==`function`&&matchMedia(`(prefers-reduced-motion: reduce)`).matches;var l=class{listener;physics;mode=`idle`;origin={x:0,y:0};point={x:0,y:0};stiff=!1;size={width:1,height:1};position={x:0,y:0};velocity={x:0,y:0};target={x:0,y:0};omega=o.fall;lift=0;turned=!1;trail=[];handle=0;last=0;scheduler;reducedMotion;constructor(e,t={}){this.listener=e,this.physics={...o,...t.physics},this.scheduler=t.scheduler??s,this.reducedMotion=t.reducedMotion??c}get active(){return this.mode!==`idle`}get dragging(){return this.mode===`drag`}get peeking(){return this.mode===`peek`}get frame(){return{origin:this.origin,point:this.point,stiff:this.stiff}}grab(e,t,n,r){this.size=n,this.origin=e,this.stiff=r,this.mode=`drag`,this.trail=[],this.stop(),this.moveTo(t)}drag(e){this.mode===`drag`&&this.moveTo(e)}release(){if(this.mode!==`drag`)return!1;let e=this.speed(),t=this.point.x+e.x*this.physics.flick;return this.fall(t<0,e,this.physics.fall),this.turned}turn(e,t,n){this.size=t,this.origin=e,this.stiff=n,this.point={...e},this.fall(!0,{x:0,y:0},this.physics.auto)}peek(e,t,n,r){this.mode!==`drag`&&this.mode!==`fall`&&((this.mode===`idle`||this.origin.x!==e.x||this.origin.y!==e.y)&&(this.size=n,this.origin=e,this.stiff=r,this.point={...e},this.position={...this.point},this.velocity={x:0,y:0},this.lift=0),this.mode=`peek`,this.omega=this.physics.peek,this.target=t,this.turned=t.x<0,this.run())}unpeek(){this.mode===`peek`&&(this.mode=`fall`,this.target=this.turned?{x:-this.origin.x,y:this.origin.y}:{...this.origin},this.run())}finish(){if(this.mode===`idle`)return;let e=this.mode===`fall`?this.turned:this.point.x<0;this.stop(),this.mode=`idle`,this.listener.settle(e)}cancel(){this.stop(),this.mode=`idle`}moveTo(e){let t=this.stiff?{x:Math.max(-this.origin.x,Math.min(this.origin.x,e.x)),y:this.origin.y}:a.attach(e,this.origin,this.size.height),n=this.scheduler.now();this.point=t,this.trail.push({p:t,t:n}),this.trail=this.trail.filter(e=>n-e.t<100),this.listener.frame(this.frame)}speed(){if(this.trail.length<2)return{x:0,y:0};let e=this.trail[0],t=this.trail[this.trail.length-1],n=Math.max(1,t.t-e.t);return{x:(t.p.x-e.p.x)/n,y:(t.p.y-e.p.y)/n}}fall(e,t,n){this.reducedMotion()?(this.stop(),this.mode=`idle`,this.listener.settle(e)):(this.mode=`fall`,this.turned=e,this.omega=n,this.target=e?{x:-this.origin.x,y:this.origin.y}:{...this.origin},this.lift=this.stiff?0:this.size.height*this.physics.lift*(this.origin.y>this.size.height/2?-1:1),this.position={x:this.point.x,y:this.point.y-this.arc(this.point.x)},this.velocity=t,this.run())}arc(e){let t=Math.max(1,this.origin.x),n=Math.min(1,Math.abs(e)/t);return this.lift*(1-n*n)}run(){this.handle||=(this.last=this.scheduler.now(),this.scheduler.request(this.tick))}stop(){this.handle&&this.scheduler.cancel(this.handle),this.handle=0}tick=e=>{let n=Math.min(48,e-this.last),i=this.omega;this.last=e;for(let e=0;e<n;e+=4){let t=Math.min(4,n-e);for(let e of[`x`,`y`]){let n=i*i*(this.target[e]-this.position[e])-2*i*this.velocity[e];this.velocity[e]+=n*t,this.position[e]+=this.velocity[e]*t}}let o={x:this.position.x,y:this.position.y+(this.mode===`fall`?this.arc(this.position.x):0)};this.point=this.stiff?{x:o.x,y:this.origin.y}:a.attach(o,this.origin,this.size.height),this.listener.frame(this.frame);let s=r(t(this.target,this.position))<.5&&r(this.velocity)<.02;s&&this.mode===`fall`?(this.handle=0,this.mode=`idle`,this.listener.settle(this.turned)):this.handle=s?0:this.scheduler.request(this.tick)}};let u={single:{label:`Full bleed`,slots:1},framed:{label:`Framed`,slots:1},pair:{label:`Pair`,slots:2},grid:{label:`Grid`,slots:4},collage:{label:`Collage`,slots:3},text:{label:`Words`,slots:0},triptych:{label:`Triptych`,slots:3},mosaic:{label:`Mosaic`,slots:3},strip:{label:`Film strip`,slots:3},contact:{label:`Contact sheet`,slots:6},scatter:{label:`Loose prints`,slots:3},story:{label:`Story`,slots:1}},d=(e,t,n,r=7,i=108,a=3)=>{let o=(i-a*(n-1))/n;return Array.from({length:n},(n,i)=>({x:e,y:r+i*(o+a),width:t,height:o}))},f={x:7,y:118,width:86,height:10},p={triptych:{slots:[7,36.67,66.33].map(e=>({x:e,y:14,width:26.67,height:94})),caption:{...f,y:114}},mosaic:{slots:[{x:7,y:7,width:51,height:108},...d(61,32,2)],caption:f},strip:{slots:d(7,86,3),caption:f},contact:{slots:d(7,41.5,3).flatMap((e,t)=>[e,d(51.5,41.5,3)[t]]),caption:f},scatter:{slots:[{x:9,y:9,width:54,height:41,rotate:-4},{x:38,y:43,width:54,height:41,rotate:3},{x:11,y:80,width:48,height:35,rotate:-2}],caption:{...f,x:63,y:92,width:30,height:28},loose:!0},story:{slots:[{x:7,y:7,width:86,height:66}],caption:{x:9,y:80,width:82,height:45},prose:!0}},m={classic:{label:`Classic`,cloth:`#5a1d22`,ink:`#e2c58f`,stage:[`#4a2a27`,`#22140f`,`#0d0807`]},linen:{label:`Linen`,cloth:`#e6dcc6`,ink:`#3d3226`,stage:[`#4a4134`,`#241f18`,`#0e0c09`]},midnight:{label:`Midnight`,cloth:`#141b2e`,ink:`#d5dbe8`,stage:[`#27324d`,`#121827`,`#07090f`]},leather:{label:`Tan leather`,cloth:`#6b3f24`,ink:`#ecc77d`,stage:[`#4d3121`,`#24170f`,`#0d0805`]},sage:{label:`Sage`,cloth:`#5d6f5c`,ink:`#f1e9d2`,stage:[`#3c4a3c`,`#1c241c`,`#0a0d0a`]},blush:{label:`Blush`,cloth:`#d8b4a8`,ink:`#5a2f2a`,stage:[`#5a4440`,`#2a1f1d`,`#100b0a`]}},h={classic:{label:`Classic`,description:`A ruled panel with the title over an inset photo`},gilt:{label:`Gilt`,description:`Gold rules and corner flourishes around an oval portrait`},window:{label:`Window`,description:`The photo set into a window pressed into the board`},label:{label:`Tipped-in print`,description:`A print held by photo corners over a paper title label`},deco:{label:`Art deco`,description:`Gold rays rising to an arched photo`},image:{label:`Full image`,description:`Your photo across the whole cover, finished like the board`}},g={ivory:{label:`Ivory`,swatch:`#fbf8f1`},white:{label:`White`,swatch:`#ffffff`},kraft:{label:`Kraft`,swatch:`#d8c4a2`},charcoal:{label:`Charcoal`,swatch:`#2a2826`}},_={none:{label:`Plain`,description:`The photo printed straight onto the page`},hairline:{label:`Hairline`,description:`A fine printed rule around the photo`},double:{label:`Double rule`,description:`Two printed rules, like a classic album keyline`},mat:{label:`Gallery mat`,description:`A wide printed mat with a thin frame line`},corners:{label:`Photo corners`,description:`Printed album corners holding the photo`},deckle:{label:`Deckled edge`,description:`A vintage print with a scalloped border`},plate:{label:`Plate mark`,description:`The photo sits in a plate pressed into the paper`},feather:{label:`Soft edge`,description:`The photo fades into the paper at its edges`},oval:{label:`Oval`,description:`An oval cameo inside a fine printed ring`},botanical:{label:`Botanical`,description:`Line-drawn sprigs of leaves around a fine rule`},watercolor:{label:`Watercolour`,description:`A wash of soft colour printed around a mat`},arcs:{label:`Rainbow arcs`,description:`A printed border of little rainbow arcs around a mat`},gilt:{label:`Gilt`,description:`An engraved border printed in gold ink`},woodgrain:{label:`Woodgrain`,description:`A printed woodgrain border around a mat`}},v={watercolor:3,arcs:3,gilt:2.6,woodgrain:3};function y(e){return e.coverText??e.coverDesign!==`image`}function b(e,t,n=`none`){return e.layout===`single`?`none`:t?.frame??x(e,n)}function x(e,t=`none`){return e.layout===`single`?`none`:e.frame??t}var S=class e{pageCount;faces;leaves;spread;stiffCovers;constructor(t,{spread:n,stiffCovers:r=!0}){this.pageCount=t;let i=Array.from({length:t},(e,t)=>({kind:`page`,index:t})),a=n&&t%2==1?[{kind:`blank`}]:[];this.spread=n,this.stiffCovers=r,this.faces=[{kind:`cover`},{kind:`title`},...i,...a,{kind:`colophon`},{kind:`back`}],this.leaves=n?e.pair(this.faces):this.faces.map(e=>({front:e,back:{kind:`blank`}}))}static pair(e){let t=[];for(let n=0;n<e.length;n+=2)t.push({front:e[n],back:e[n+1]});return t}get length(){return this.leaves.length}flippedForFace(e){return this.spread?Math.ceil(e/2):e}flippedForPage(e){return!e||e<1||e>this.pageCount?0:this.flippedForFace(e+1)}convert(e,t){return t.spread===this.spread?Math.min(e,this.length):this.spread?Math.ceil(e/2):Math.max(0,e*2-1)}isStiff(e){let{front:t,back:n}=this.leaves[e]??{};return this.stiffCovers&&(t?.kind===`cover`||t?.kind===`back`||n?.kind===`back`)}visible(e){return e<=0?[this.leaves[0].front]:e>=this.length?[this.spread?this.leaves[this.length-1].back:this.faces[this.faces.length-1]]:this.spread?[this.leaves[e-1].back,this.leaves[e].front]:[this.leaves[e].front]}stops(){if(!this.spread)return this.faces.map((e,t)=>({flipped:t,faces:[e]}));let e=[{flipped:0,faces:[this.faces[0]]}];for(let t=1;t<this.faces.length-1;t+=2)e.push({flipped:this.flippedForFace(t),faces:[this.faces[t],this.faces[t+1]]});return e.push({flipped:this.length,faces:[this.faces[this.faces.length-1]]}),e}label(t){if(t<=0)return`Cover`;if(t>=this.length)return`Back cover`;let n=e.pageNumbers(this.visible(t));return n.length===0?this.visible(t).some(e=>e.kind===`title`)?`Title page`:`The end`:n.length===1?`Page ${n[0]} of ${this.pageCount}`:`Pages ${n[0]}–${n[1]} of ${this.pageCount}`}static describe(t){let n=e.pageNumbers(t);return n.length?`page ${n.join(` and `)}`:t[0].kind===`back`?`the back cover`:t[0].kind===`cover`?`the cover`:`the title page`}static pageNumbers(e){return e.filter(e=>e.kind===`page`).map(e=>e.index+1)}};let C={edgeX:.15,edgeY:.08,peek:!0};var w=class{events;flipped;active=null;layout;width=0;height=0;grip;engine;press=null;grabStart={x:0,y:0};grabDir=1;grabReach=1;constructor(e,t,n={}){this.events=t,this.layout=e,this.flipped=Math.max(0,Math.min(e.length,n.flipped??0)),this.grip={...C,...n.grip},this.engine=new l({frame:e=>this.active&&this.events.frame(e,this.active),settle:e=>this.settle(e)},n)}get size(){return{width:this.width,height:this.height}}get atStart(){return this.flipped===0}get atEnd(){return this.flipped===this.layout.length}get settled(){return!this.active||this.active.peek}get label(){return this.layout.label(this.flipped)}configure({layout:e,width:t,height:n}){let r=e&&e!==this.layout,i=t!==void 0&&t!==this.width||n!==void 0&&n!==this.height;(r||i)&&(e&&r&&(this.flipped=e.convert(this.flipped,this.layout),this.layout=e),this.width=t??this.width,this.height=n??this.height,this.engine.cancel(),this.active=null,this.press=null,this.events.change())}go(e){let t=Math.max(0,Math.min(this.layout.length,e));if(t===this.flipped||this.width===0)return;if(this.engine.active&&!this.engine.peeking){this.engine.finish();return}if(this.engine.cancel(),this.events.flip(),Math.abs(t-this.flipped)!==1){this.active=null,this.flipped=t,this.events.change();return}let n=Math.min(t,this.flipped),r=this.layout.isStiff(n);this.begin({leaf:n,dir:t>this.flipped?1:-1,stiff:r,peek:!1}),this.engine.turn({x:this.width,y:r?this.height/2:this.height},this.size,r)}next(){this.go(this.flipped+1)}prev(){this.go(this.flipped-1)}hover(e){if(this.press||this.engine.dragging)return;let t=this.grip.peek?this.cornerAt(e):null;if(!t){this.engine.unpeek();return}let{width:n,height:r}=this,i=t.x>0?1:-1,a=i===1?this.flipped:this.flipped-1,o=this.layout.isStiff(a),s={x:n,y:o?r/2:t.y},c={x:i*(e.x-t.x),y:e.y-t.y},l=Math.hypot(c.x,c.y)||1,u=Math.max(n*.12,Math.min(n*.2,l*2)),d={x:n+c.x/l*u,y:o?s.y:t.y+c.y/l*u};(this.active?.leaf!==a||this.active.dir!==i)&&this.begin({leaf:a,dir:i,stiff:o,peek:!0}),this.engine.peek(s,d,this.size,o)}leave(){this.engine.unpeek()}down(e,t){this.press={at:e,id:t,grabbed:!1}}move(e,t){let n=this.press;if(!n||n.id!==t)return!1;let r=e.x-n.at.x,i=e.y-n.at.y;if(!n.grabbed){if(Math.hypot(r,i)<6||this.engine.active&&!this.engine.peeking)return!1;let e=(this.engine.peeking&&this.active?{...this.active,origin:this.engine.frame.origin,start:this.engine.frame.point}:null)??this.holdAt(n.at);if(!e)return!1;n.grabbed=!0,this.grabStart=e.start,this.grabDir=e.dir,this.grabReach=!this.layout.spread&&e.dir===-1?2:1,this.begin({leaf:e.leaf,dir:e.dir,stiff:e.stiff,peek:!1}),this.engine.grab(e.origin,e.start,this.size,e.stiff)}return this.engine.drag({x:this.grabStart.x+this.grabDir*this.grabReach*r,y:this.grabStart.y+i}),!0}up(e,t){let n=this.press;return!n||n.id!==t?null:(this.press=null,n.grabbed?(this.engine.release()&&this.events.flip(),`turn`):Math.abs(e.x-n.at.x)<8&&Math.abs(e.y-n.at.y)<8?`tap`:null)}cancel(){this.press=null,this.engine.dragging&&this.engine.release()}destroy(){this.engine.cancel()}begin(e){this.active=e,this.events.change()}settle(e){let t=this.active;if(!t)return;let n=t.dir===1?e:!e;this.flipped=n?t.leaf+1:t.leaf,this.active=null,this.events.change()}holdAt(e){let{width:t,height:n,layout:r}=this,i=r.spread?e.x>=0:e.x>=t*.3,a=i?this.flipped:this.flipped-1;if(a<0||a>=r.length)return null;let o=i?e:{x:r.spread?-e.x:t,y:e.y},s=o.x>t*(1-this.grip.edgeX),c=o.y<n*this.grip.edgeY,l=o.y>n*(1-this.grip.edgeY),u=r.isStiff(a),d={x:s||!(c||l)?t:Math.max(1,o.x),y:u?n/2:c?0:l?n:Math.max(0,Math.min(n,o.y))};return{leaf:a,dir:i?1:-1,origin:d,stiff:u,start:d}}cornerAt(e){let{width:t,height:n,layout:r,flipped:i}=this,a=Math.max(36,t*.12);return[...i<r.length?[{x:t,y:0},{x:t,y:n}]:[],...r.spread&&i>0?[{x:-t,y:0},{x:-t,y:n}]:[]].find(t=>Math.hypot(e.x-t.x,e.y-t.y)<a)??null}};let T={previous:`Previous page`,next:`Next page`,soundOn:`Turn page sound on`,soundOff:`Turn page sound off`,fullscreen:`Full screen`,exitFullscreen:`Exit full screen`,byline:e=>`by ${e}`,rotateTitle:`Turn your phone sideways`,rotateBody:`Photo books open across two pages, just like the real thing.`,rotateFullscreen:`Open full screen`,rotateSingle:`Read one page at a time`},E={viewBox:`0 0 40 40`,strokes:[{d:`M3 37V12Q3 3 12 3H37`,width:1},{d:`M7 37V16Q7 7 16 7H37`,width:.6},{d:`M12 12C16 10 20 12 20 16C20 19 17 20 15.5 18.5`,width:.8}],fills:[`M16 7C18 10 21 11 24 10C22 8 19 7 16 7Z`,`M7 16C10 18 11 21 10 24C8 22 7 19 7 16Z`,`M10.7 12a1.3 1.3 0 1 0 2.6 0a1.3 1.3 0 1 0 -2.6 0Z`]},D={viewBox:`0 0 100 133.33`,strokes:[...Array.from({length:17},(e,t)=>({d:`M50 124L${(12+t/16*76).toFixed(2)} 16`,width:.25,opacity:.3})),{d:`M5 5H95V128.33H5Z`,width:.5},{d:`M11 8H89L92 11V122.33L89 125.33H11L8 122.33V11Z`,width:.35},{d:`M30 126.33A20 20 0 0 1 70 126.33`,width:.35,opacity:.6},{d:`M38 126.33A12 12 0 0 1 62 126.33`,width:.35,opacity:.6}],fills:[`M50 8.5L52 11L50 13.5L48 11Z`]};function O(e,t={},...n){let r=document.createElement(e);for(let[e,n]of Object.entries(t))e===`style`?Object.assign(r.style,n):n!=null&&n!==!1&&r.setAttribute(e,n===!0?``:String(n));return ee(r,n),r}function ee(e,t){for(let n of t)n&&e.append(n)}function k(e){let t=document.createElement(`template`);return t.innerHTML=e.trim(),t.content.firstElementChild}async function A(e){try{!document.fullscreenElement&&e.requestFullscreen&&await e.requestFullscreen({navigationUI:`hide`})}catch{}try{let e=screen.orientation;if(e?.lock)return await e.lock(`landscape`),!0}catch{}return!1}function j(e){let t=matchMedia(`(orientation: portrait)`),n=matchMedia(`(pointer: coarse)`),r=()=>e({portrait:t.matches,touch:n.matches});return r(),t.addEventListener(`change`,r),n.addEventListener(`change`,r),window.addEventListener(`resize`,r),()=>{t.removeEventListener(`change`,r),n.removeEventListener(`change`,r),window.removeEventListener(`resize`,r)}}let M=[`tl`,`tr`,`bl`,`br`];function N(e,t){let n=e.strokes.map(({d:e,width:t,opacity:n=1})=>`<path d="${e}" fill="none" stroke="currentColor" stroke-width="${t}" stroke-opacity="${n}"/>`).join(``),r=e.fills.map(e=>`<path d="${e}" fill="currentColor"/>`).join(``);return`<svg viewBox="${e.viewBox}" class="${t}" preserveAspectRatio="none" aria-hidden="true">${n}${r}</svg>`}let P=()=>M.map(e=>k(N(E,`fb-fleuron is-${e}`))),F=(e,t,n)=>e.cover&&O(`div`,{class:t},n?B(e.cover,`fb-photo`):O(`div`,{class:`fb-placeholder`})),I=e=>O(`h1`,{class:`fb-serif fb-cover-title`},e.title),L=e=>e.kicker&&O(`p`,{class:`fb-kicker`},e.kicker),R=e=>e.subtitle&&O(`p`,{class:`fb-serif fb-italic fb-cover-subtitle`},e.subtitle);function te(e,t){let n=y(e);switch(e.coverDesign??`classic`){case`gilt`:return[O(`div`,{class:`fb-cover-frame`}),...P(),O(`div`,{class:`fb-cover-stack`},n&&L(e),n&&I(e),F(e,`fb-cover-photo is-oval`,t),n&&R(e))];case`window`:return[F(e,`fb-cover-window`,t)||O(`div`,{class:`fb-cover-window is-empty`},z()),n&&O(`div`,{class:`fb-cover-stamp`},L(e),I(e),R(e))];case`label`:return[e.cover&&O(`div`,{class:`fb-cover-print`},F(e,`fb-cover-print-photo`,t),...M.map(e=>O(`span`,{class:`fb-print-frame-corner is-${e}`,"aria-hidden":`true`}))),n&&O(`div`,{class:`fb-cover-label ${e.cover?``:`is-alone`}`},L(e),I(e),R(e))];case`deco`:return[k(N(D,`fb-cover-rays`)),O(`div`,{class:`fb-cover-stack is-deco`},n&&L(e),F(e,`fb-cover-photo is-arch`,t),n&&I(e),n&&R(e))];case`image`:return[e.cover&&O(`div`,{class:`fb-cover-art`},t?B(e.cover,`fb-photo`):O(`div`,{class:`fb-placeholder`})),e.cover&&O(`div`,{class:`fb-cover-tint`}),n&&O(`div`,{class:`fb-cover-caption ${e.cover?``:`is-plain`}`},L(e),I(e),R(e))];default:return[O(`div`,{class:`fb-cover-panel`},n&&L(e),n&&I(e),F(e,`fb-cover-photo`,t)||n&&R(e))]}}let ne=(e,t,...n)=>O(`div`,{class:`fb-cover fb-cover-${e.theme??`classic`} fb-design-${e.coverDesign??`classic`}`},...n,O(`div`,{class:`fb-hinge is-${t}`}),O(`div`,{class:`fb-cover-finish`,"aria-hidden":`true`}));function re(e,t=!0){return ne(e,`left`,...te(e,t))}function ie(e){let t=e.coverDesign===`gilt`;return ne(e,`right`,t&&O(`div`,{class:`fb-cover-frame`}),...t?P():[],O(`div`,{class:`fb-imprint`},z(),e.imprint&&O(`p`,{class:`fb-kicker`,style:{marginTop:`2cqw`,fontSize:`2.4cqw`,opacity:`0.6`}},e.imprint)))}let ae=[14,24,34,44,54,64,74].map((e,t)=>({x:e,angle:t%2?38:-38,length:26-t*2})),oe=e=>k(`<svg viewBox="0 0 100 40" class="fb-print-frame-sprig is-${e}" fill="none" stroke="currentColor" stroke-linecap="round" aria-hidden="true">
|
|
2
2
|
<path d="M4 20 Q 50 17, 92 20" stroke-width="1.2"/>
|
|
3
|
-
${
|
|
4
|
-
</svg>`),
|
|
3
|
+
${ae.map(({x:e,angle:t,length:n})=>`<g transform="translate(${e} 20) rotate(${t}) scale(${n/20})"><path d="M0 0 C 5 -5, 14 -5, 20 0 C 14 5, 5 5, 0 0 Z" stroke-width="1"/><path d="M2 0 L 16 0" stroke-width="0.6"/></g>`).join(``)}
|
|
4
|
+
</svg>`),z=()=>k(`<svg viewBox="0 0 40 40" class="fb-ornament" aria-hidden="true">
|
|
5
5
|
<circle cx="20" cy="20" r="18.5" fill="none" stroke="currentColor" stroke-opacity="0.6"/>
|
|
6
6
|
<path d="M20 9 L 27 20 L 20 31 L 13 20 Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/>
|
|
7
7
|
<circle cx="20" cy="20" r="2.2" fill="currentColor"/>
|
|
8
|
-
</svg>`),M=(e,t)=>w(`img`,{src:e.src,alt:e.alt??``,draggable:`false`,decoding:`async`,width:e.width??void 0,height:e.height??void 0,class:t}),N=({x:e,y:t,width:n,height:r,rotate:i})=>({left:`${e}cqw`,top:`${t}cqw`,width:`${n}cqw`,height:`${r}cqw`,...i?{transform:`rotate(${i}deg)`}:{}}),P=e=>w(`div`,{class:`fb-page-surface ${e?`is-${e}`:``}`,"aria-hidden":`true`},w(`div`,{class:`fb-page-surface-grain`}),e&&w(`div`,{class:`fb-page-surface-gutter`}),e&&w(`div`,{class:`fb-page-surface-sheen`})),F=(e,t,n=!0,r=!0)=>w(`p`,{class:`fb-serif ${n?`fb-italic`:``} ${r?`fb-center`:``}`,style:t},e);function I(e,t,n=`cover`,r=!0,i=1){let a=e?.width&&e.height?e.width/e.height:4/3,o=w(`div`,{class:`fb-print-frame-box`,style:{fontSize:`${i}cqw`}}),s=w(`div`,{class:`fb-print-frame fb-frame-${t} ${n===`contain`?`is-contained`:``}`});if(n===`contain`&&s.style.setProperty(`--ratio`,String(a)),_[t]&&s.append(w(`span`,{class:`fb-print-frame-band`,"aria-hidden":`true`})),s.append(e&&r?M(e,`fb-print-photo fb-print-frame-photo`):w(`div`,{class:`fb-print-frame-photo fb-placeholder`})),t===`corners`)for(let e of[`tl`,`tr`,`bl`,`br`])s.append(w(`span`,{class:`fb-print-frame-corner is-${e}`,"aria-hidden":`true`}));return t===`botanical`&&s.append(A(`tl`),A(`br`)),o.append(s),o}function L(e,t,n={}){let{layout:r,caption:i,photos:a}=e,{number:o,side:s,showImages:c=!0,onSlotClick:l,activeSlot:u}=n,d=p[r],f=w(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page`}),m=(n,r=``,i=!1,o)=>{let s=a[n]??null,d=v(e,s,t.frame),f=w(`div`,{class:[`fb-slot`,r,i&&`is-framed`,l&&`is-editable`,l&&u===n&&`is-active`].filter(Boolean).join(` `),role:l?`button`:void 0,"aria-label":l?`Photo slot ${n+1}`:void 0,style:o});return l&&f.addEventListener(`click`,()=>l(n)),f.append(s?I(s,d,i?`contain`:`cover`,c):w(`div`,{class:`fb-slot-empty`},l?`Add a photo`:``)),f},h=(e,...t)=>w(`div`,{class:`fb-column`,style:e},...t),g=i?F(i,{fontSize:`3.8cqw`}):null;switch(r){case`single`:f.append(m(0,`fb-bleed`)),i&&f.append(w(`div`,{class:`fb-caption-over`},i));break;case`framed`:f.append(h({padding:`10cqw 9cqw 6cqw`},w(`div`,{class:`fb-grow`},m(0,`fb-fill`,!0)),F(i??``,{marginTop:`5cqw`,fontSize:`4.2cqw`,minHeight:`6cqw`,lineHeight:`1.35`})));break;case`pair`:f.append(h({padding:`7cqw`,gap:`4cqw`},m(0,`fb-grow`),m(1,`fb-grow`),g));break;case`grid`:f.append(h({padding:`7cqw`,gap:`3cqw`},w(`div`,{class:`fb-grid fb-grow`,style:{gap:`3cqw`}},...[0,1,2,3].map(e=>m(e))),g));break;case`collage`:f.append(h({padding:`7cqw`,gap:`3cqw`},m(0,`fb-grow-large`),w(`div`,{class:`fb-row fb-grow`,style:{gap:`3cqw`}},m(1,`fb-grow`),m(2,`fb-grow`)),g));break;case`text`:f.append(w(`div`,{class:`fb-column fb-center`,style:{alignItems:`center`,justifyContent:`center`,padding:`14cqw 12cqw`}},w(`span`,{class:`fb-serif`,style:{fontSize:`18cqw`,lineHeight:`0.6`,opacity:`0.3`},"aria-hidden":`true`},`“`),F(i||(l?`Write something in the caption box below.`:``),{marginTop:`4cqw`,fontSize:`6cqw`,lineHeight:`1.4`,textWrap:`balance`},!0,!1)))}return d&&(f.append(...d.slots.map((e,t)=>m(t,`fb-placed ${d.loose?`is-loose`:``}`,!1,N(e)))),i&&f.append(w(`p`,{class:`fb-placed-caption fb-serif ${d.prose?`is-prose`:`fb-italic`}`,style:N(d.caption)},i))),o!==void 0&&r!==`single`&&f.append(w(`span`,{class:`fb-page-number`,style:s===`left`?{left:`0`}:{right:`0`}},String(o))),f.append(P(s)),f}function R(e,t=!0){let n=w(`div`,{class:`fb-cover-panel`},e.kicker&&w(`p`,{class:`fb-kicker`},e.kicker),w(`h1`,{class:`fb-serif`,style:{marginTop:`5cqw`,fontSize:`9cqw`,fontWeight:`500`,lineHeight:`1.05`,textWrap:`balance`}},e.title));return e.cover?n.append(w(`div`,{class:`fb-cover-photo`},t?M(e.cover,`fb-photo`):w(`div`,{class:`fb-placeholder`}))):e.subtitle&&n.append(F(e.subtitle,{marginTop:`6cqw`,fontSize:`4cqw`,opacity:`0.8`},!0,!1)),w(`div`,{class:`fb-cover fb-cover-${e.theme??`classic`}`},w(`div`,{class:`fb-hinge is-left`}),n)}function z(e){return w(`div`,{class:`fb-cover fb-cover-${e.theme??`classic`}`},w(`div`,{class:`fb-hinge is-right`}),w(`div`,{class:`fb-imprint`},j(),e.imprint&&w(`p`,{class:`fb-kicker`,style:{marginTop:`2cqw`,fontSize:`2.4cqw`,opacity:`0.6`}},e.imprint)))}function B(e,t,n){let r=[e.author,e.year].filter(Boolean).join(` · `);return w(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page fb-center`,style:{alignItems:`center`,justifyContent:`center`,padding:`12cqw`}},j(),w(`h2`,{class:`fb-serif`,style:{marginTop:`6cqw`,fontSize:`7.5cqw`,fontWeight:`400`,lineHeight:`1.1`,textWrap:`balance`}},e.title),e.subtitle&&F(e.subtitle,{marginTop:`4cqw`,fontSize:`4cqw`,lineHeight:`1.45`},!0,!1),w(`div`,{style:{marginTop:`7cqw`,height:`1px`,width:`20cqw`,background:`currentColor`,opacity:`0.3`}}),r&&w(`p`,{style:{marginTop:`5cqw`,fontSize:`2.6cqw`,letterSpacing:`0.2em`,textTransform:`uppercase`}},r),P(n))}function V(e,t,n){return w(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page fb-center`,style:{alignItems:`center`,justifyContent:`flex-end`,padding:`12cqw`,opacity:`0.9`}},e.colophon&&F(e.colophon,{fontSize:`3.6cqw`},!0,!1),P(n))}function H(e,t){return w(`div`,{class:`fb-paper fb-paper-${e.paper} fb-page`},P(t))}function U(e,t,n,r=!0){let i={paper:t.paper??`ivory`,frame:t.frame??`none`};switch(e.kind){case`cover`:return R(t);case`back`:return z(t);case`title`:return B(t,i,n);case`colophon`:return V(t,i,n);case`blank`:return H(i,n);case`page`:return L(t.pages[e.index],i,{number:r?e.index+1:void 0,side:n})}}let W=null;function G(e=.18){try{W??=new AudioContext;let t=W.createBuffer(1,Math.floor(W.sampleRate*.45),W.sampleRate),n=t.getChannelData(0);for(let e=0;e<n.length;e++){let t=e/n.length,r=Math.sin(Math.PI*Math.min(1,t*2.2))*(1-t)**1.5;n[e]=(Math.random()*2-1)*r*(.6+.4*Math.sin(t*40))}let r=W.createBufferSource(),i=W.createBiquadFilter(),a=W.createGain();r.buffer=t,i.type=`bandpass`,i.frequency.value=2200,i.Q.value=.6,a.gain.value=e,r.connect(i).connect(a).connect(W.destination),r.start()}catch{}}let K=3/4,q=`flipbook:sound`,J={layout:`auto`,controls:!0,autoHide:3200,thumbnails:!0,soundButton:!0,sound:!1,fullscreenButton:!0,landscape:!0,keyboard:!0,stiffCovers:!0,shading:1,labels:C},Y=[{name:`under`,z:2},{name:`bend`,z:4},{name:`shadow`,z:5},{name:`curl`,z:7}],X=(e,t=0,n=0)=>e.length?`polygon(${e.map(e=>`${(e.x+t).toFixed(2)}px ${(e.y+n).toFixed(2)}px`).join(`, `)})`:`polygon(0 0)`,Z=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="${e}" stroke-linecap="round" stroke-linejoin="round"/></svg>`,Q={prev:Z(`M15 6l-6 6 6 6`),next:Z(`M9 6l6 6-6 6`),expand:Z(`M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5`),collapse:Z(`M9 4v5H4M15 4v5h5M9 20v-5H4M15 20v-5h5`),soundOn:Z(`M4 10v4h3l5 4V6L7 10H4zM16 9a4 4 0 0 1 0 6M18.5 6.5a8 8 0 0 1 0 11`),soundOff:Z(`M4 10v4h3l5 4V6L7 10H4zM17 10l4 4M21 10l-4 4`),grid:`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="5" width="8" height="14" rx="1"/><rect x="13" y="5" width="8" height="14" rx="1"/></svg>`,phone:`<svg viewBox="0 0 64 64" class="fb-rotate-hint" aria-hidden="true"><rect x="20" y="6" width="24" height="52" rx="4" fill="none" stroke="currentColor" stroke-width="2.5"/><circle cx="32" cy="51" r="2" fill="currentColor"/></svg>`},$=()=>{try{return localStorage.getItem(q)}catch{return null}};var ee=class e{container;root;reader;settings;layout;size={width:0,height:0};orientation={portrait:!1,touch:!1};portraitChoice=`ask`;soundOn;stripOpen=!1;chromeVisible=!0;hideTimer;lastPlace=``;rendering=!1;dirty=!1;faces=/* @__PURE__ */ new Map;overlays=/* @__PURE__ */ new Map;cleanups=[];els;constructor(t,n){this.container=t,this.settings=e.resolve(n),this.soundOn=this.settings.sound,this.layout=this.buildLayout(),this.reader=new S(this.layout,{frame:(e,t)=>this.paint(e,t),change:()=>this.render(),flip:()=>{this.soundOn&&G(),this.settings.onFlip?.()}},{flipped:this.layout.flippedForPage(this.settings.startPage),physics:n.physics,grip:n.grip}),this.root=w(`div`,{class:`fb-root`}),this.els=this.build(),t.append(this.root);let r=$();this.settings.soundButton&&r&&(this.soundOn=r===`on`),this.listen(),this.poke(),this.render()}update(t){let n=t.book&&t.book!==this.settings.book;this.settings=e.resolve({...this.settings,...t,labels:{...this.settings.labels,...t.labels}}),t.sound!==void 0&&(this.soundOn=t.sound),t.physics&&(this.reader.engine.physics={...this.reader.engine.physics,...t.physics}),t.grip&&(this.reader.grip={...this.reader.grip,...t.grip}),(n||t.stiffCovers!==void 0)&&this.clearFaces(),this.els.title.textContent=this.settings.book.title,this.poke(),this.render()}next(){this.reader.next()}prev(){this.reader.prev()}go(e){this.reader.go(e)}goToPage(e){this.reader.go(this.reader.layout.flippedForPage(e))}destroy(){this.reader.destroy(),clearTimeout(this.hideTimer),this.cleanups.forEach(e=>e()),this.root.remove()}static resolve(e){let t=Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0));return{...J,...t,labels:{...C,...e.labels}}}get spread(){let{layout:e,landscape:t}=this.settings,n=t&&this.orientation.touch&&this.orientation.portrait,r=this.els?.stage.getBoundingClientRect(),i=!!r&&r.width>0&&r.width/r.height<.95;return e===`auto`?!(n&&this.portraitChoice===`single`)&&!i:e===`spread`}buildLayout(){return new b(this.settings.book.pages.length,{spread:this.spread,stiffCovers:this.settings.stiffCovers})}build(){let e=(e,t,n)=>{let r=w(`button`,{type:`button`,class:`fb-button`,"aria-label":e,title:e});return r.append(E(t)),r.addEventListener(`click`,n),r},t=w(`h1`,{class:`fb-title`},this.settings.book.title),n=w(`p`,{class:`fb-byline`}),r=e(``,Q.soundOff,()=>this.toggleSound()),i=e(``,Q.expand,()=>this.toggleFullscreen()),a=w(`div`,{class:`fb-bar-group`},r,i),o=w(`div`,{class:`fb-bar fb-bar-top`},w(`div`,{class:`fb-bar-group`},w(`div`,{class:`fb-heading`},t,n)),a),s=w(`div`,{class:`fb-book-shadow`}),c=w(`div`,{class:`fb-edge`}),l=w(`div`,{class:`fb-edge`}),u=w(`div`,{class:`fb-spine`}),d=w(`div`,{class:`fb-book`},s,c,l,u),f=w(`div`,{class:`fb-stage`},d),p=e(``,Q.prev,()=>this.reader.prev()),m=e(``,Q.next,()=>this.reader.next()),h=w(`button`,{type:`button`,class:`fb-pages-button`,"aria-live":`polite`}),g=w(`div`,{class:`fb-bar fb-bar-bottom`},p,h,m);h.addEventListener(`click`,()=>{this.settings.thumbnails&&(this.stripOpen=!this.stripOpen,this.render())});for(let{name:e,z:t}of Y){let n=w(`div`,{class:`fb-light`}),r=w(`div`,{class:`fb-overlay`,style:{zIndex:String(t)}},n);this.overlays.set(e,{clip:r,light:n})}return this.root.append(o,f,g),{top:o,title:t,byline:n,topRight:a,sound:r,fullscreen:i,stage:f,book:d,shadow:s,leftEdge:c,rightEdge:l,spine:u,bottom:g,prev:p,pages:h,next:m,strip:null,rotate:null}}listen(){let{stage:e}=this.els,t=(e,t,n)=>{e.addEventListener(t,n),this.cleanups.push(()=>e.removeEventListener(t,n))},n=new ResizeObserver(()=>this.render());n.observe(e),this.cleanups.push(()=>n.disconnect()),this.cleanups.push(O(e=>{this.orientation=e,this.render()})),t(e,`pointerdown`,e=>{e.button===0&&this.reader.down(this.toBook(e),e.pointerId)}),t(e,`pointermove`,t=>{let n=this.toBook(t);this.poke(),t.pointerType===`mouse`&&this.reader.hover(n),this.reader.move(n,t.pointerId)&&!e.hasPointerCapture(t.pointerId)&&e.setPointerCapture(t.pointerId)}),t(e,`pointerup`,t=>{if(this.reader.up(this.toBook(t),t.pointerId)!==`tap`)return;let n=e.getBoundingClientRect(),r=t.clientX-n.left;r>n.width*2/3?this.reader.next():r<n.width/3&&this.reader.prev()}),t(e,`pointerleave`,()=>this.reader.leave()),t(e,`pointercancel`,()=>this.reader.cancel()),t(this.root,`keydown`,e=>this.settings.keyboard===!0&&this.onKey(e)),t(window,`keydown`,e=>this.settings.keyboard===`global`&&this.onKey(e)),t(document,`fullscreenchange`,()=>this.render())}onKey(e){e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLSelectElement||([`ArrowRight`,`PageDown`,` `].includes(e.key)?(e.preventDefault(),this.reader.next()):[`ArrowLeft`,`PageUp`].includes(e.key)?(e.preventDefault(),this.reader.prev()):e.key===`Home`?this.reader.go(0):e.key===`End`?this.reader.go(this.reader.layout.length):e.key===`Escape`&&this.stripOpen&&(this.stripOpen=!1,this.render()))}toBook(e){let t=this.els.book.getBoundingClientRect();return{x:e.clientX-(t.left+(this.layout.spread?t.width/2:0)),y:e.clientY-t.top}}poke(){let{autoHide:e}=this.settings;clearTimeout(this.hideTimer),this.chromeVisible||(this.chromeVisible=!0,this.renderChrome()),e!==!1&&(this.hideTimer=setTimeout(()=>{this.chromeVisible=!1,this.renderChrome()},e))}toggleSound(){this.soundOn=!this.soundOn,this.soundOn&&G();try{localStorage.setItem(q,this.soundOn?`on`:`off`)}catch{}this.renderChrome()}async toggleFullscreen(){document.fullscreenElement?await document.exitFullscreen().catch(()=>{}):await D(this.root)}clearFaces(){this.faces.forEach(e=>e.remove()),this.faces.clear()}render(){if(this.rendering)this.dirty=!0;else{this.rendering=!0;do this.dirty=!1,this.renderOnce();while(this.dirty);this.rendering=!1}}renderOnce(){let{settings:t,reader:n,els:r}=this,{book:i,controls:a}=t,o=r.stage.getBoundingClientRect(),s=this.spread;(s!==this.layout.spread||i.pages.length!==this.layout.pageCount||t.stiffCovers!==this.layout.stiffCovers)&&(this.layout=this.buildLayout(),this.clearFaces());let c=s?2:1,l=!a||o.height<500?16:Math.min(150,o.height*.16),u=Math.max(0,o.width-(s?64:24)),d=Math.max(0,o.height-l),f=Math.floor(Math.min(d*K,u/c)),p=Math.floor(f/K);this.size={width:f,height:p},n.configure({layout:this.layout,width:f,height:p});let{flipped:m,active:h,settled:g,atStart:_,atEnd:v}=n,y=this.layout.leaves,b=0;s&&_&&g&&(b=-f/2),s&&v&&g&&(b=f/2),this.root.style.background=t.background??e.stageTint(i),this.root.tabIndex=t.keyboard===!0?0:-1,r.book.hidden=f<=0,Object.assign(r.book.style,{width:`${f*c}px`,height:`${p}px`,transform:`translateX(${b}px)`,cursor:n.engine.dragging?`grabbing`:`grab`,clipPath:s?``:`inset(-50% -50% -50% 0)`}),Object.assign(r.shadow.style,{left:s&&_&&g?`52%`:`2%`,right:s&&v&&g?`52%`:`2%`});let x=s&&!_&&!v,S=e=>Math.min(10,Math.max(0,e)*.8),C=x&&m>1?S(m-1):0,w=(x||s&&_)&&m<y.length-1?S(y.length-m-1):0;Object.assign(r.leftEdge.style,{display:C?``:`none`,left:`${-C}px`,width:`${C}px`}),Object.assign(r.rightEdge.style,{display:w?``:`none`,right:`${-w}px`,width:`${w}px`}),r.spine.style.left=`${s?f:0}px`,this.renderFaces(h,m,f,p),this.renderOverlays(h,f,p),this.renderChrome(),this.renderStrip(),this.renderRotatePrompt();let T=`${s}:${m}`;T!==this.lastPlace&&(this.lastPlace=T,t.onPageChange?.({flipped:m,label:n.label,faces:this.layout.visible(m)}))}renderFaces(e,t,n,r){let i=this.layout.leaves,a=e?.leaf??null,o=e?.dir??1,s=a===null?t:a+1,c=a===null?t-1:a-1,l=/* @__PURE__ */ new Set;for(let u=Math.max(0,t-2);u<=Math.min(i.length-1,t+1);u++)for(let t of[`front`,`back`]){let d=`${u}:${t}`,f=u===a?t===`front`==(o===1)?`turning`:`flap`:t===`front`?u===s?`right`:`spare`:u===c&&this.layout.spread?`left`:`spare`,p=f===`left`||f===`turning`&&o===-1&&!e?.stiff,m=this.faces.get(d);m||(m=w(`div`,{class:`fb-face`}),m.append(U(t===`front`?i[u].front:i[u].back,this.settings.book,t===`front`?`right`:`left`)),this.faces.set(d,m),this.els.spine.append(m)),l.add(d),Object.assign(m.style,{left:`${p?-n:0}px`,width:`${n}px`,height:`${r}px`,zIndex:String({right:1,left:1,turning:3,flap:6,spare:0}[f]),visibility:f===`spare`?`hidden`:`visible`}),m.setAttribute(`aria-hidden`,String(f!==`left`&&f!==`right`)),u!==a&&Object.assign(m.style,{transform:``,transformOrigin:``,clipPath:``})}for(let[e,t]of this.faces)l.has(e)||(t.remove(),this.faces.delete(e));e&&this.paint(this.reader.engine.frame,e)}renderOverlays(e,t,n){let r=!!e&&!e.stiff,i=e=>`${(t*e).toFixed(1)}px`,a={under:`linear-gradient(to right, rgb(0 0 0 / 0.42), rgb(0 0 0 / 0.2) ${i(.05)}, rgb(0 0 0 / 0.06) ${i(.16)}, transparent ${i(.3)})`,bend:`linear-gradient(to right, rgb(0 0 0 / 0.16), rgb(0 0 0 / 0.04) ${i(.05)}, transparent ${i(.1)})`,shadow:`rgb(0 0 0 / 0.55)`,curl:`linear-gradient(to right, rgb(0 0 0 / 0.3), rgb(0 0 0 / 0.1) ${i(.035)}, rgb(255 255 255 / 0.2) ${i(.11)}, rgb(255 255 255 / 0.06) ${i(.25)}, rgb(0 0 0 / 0.05) ${i(.6)}, rgb(0 0 0 / 0.12) ${i(1)})`};for(let[e,{clip:i,light:o}]of this.overlays){if(!r){i.remove();continue}let s=e===`shadow`;Object.assign(i.style,{left:`${-t}px`,top:`${-n}px`,width:`${t*2}px`,height:`${n*3}px`,filter:s?`blur(${Math.max(3,t*.012)}px)`:``}),Object.assign(o.style,s?{inset:`0`,background:a[e]}:{width:`${t*3}px`,height:`${n*4}px`,background:a[e]}),i.isConnected||this.els.spine.append(i)}r&&e&&this.paint(this.reader.engine.frame,e)}paint(e,t){let{width:n,height:r}=this.size,i=t.dir,o=this.faces.get(`${t.leaf}:front`),s=this.faces.get(`${t.leaf}:back`);if(e.stiff){let t=`perspective(${Math.max(1800,n*5)}px) rotateY(${a.hinge(e.origin,e.point,i)}deg)`;o&&Object.assign(o.style,{transformOrigin:`0 50%`,transform:t,clipPath:``}),s&&Object.assign(s.style,{transformOrigin:`0 50%`,transform:`${t} translateX(${n}px) rotateY(180deg)`,clipPath:``});return}let c=i===1?o:s,l=i===1?s:o,u=new a(n,r,e.origin,e.point),d=u.shade*this.settings.shading;c&&Object.assign(c.style,{transformOrigin:``,transform:``,clipPath:X(u.flat.map(e=>({x:i===1?e.x:n-e.x,y:e.y})))}),l&&Object.assign(l.style,{transformOrigin:`0 0`,transform:u.flapMatrix(i),clipPath:X(u.folded.map(e=>({x:i===1?n-e.x:e.x,y:e.y})))});let f=(e,t,a,o)=>{let s=this.overlays.get(e);if(!s)return;let c=X(t.map(e=>({x:i*e.x,y:e.y})),n,r);if(s.clip.style.opacity=String(o),e===`shadow`){s.light.style.clipPath=c;return}let l=Math.atan2(a*u.normal.y,i*a*u.normal.x);s.clip.style.clipPath=c,s.light.style.transform=`translate(${i*u.center.x+n}px, ${u.center.y+r}px) rotate(${l}rad) translateY(-50%)`};f(`under`,u.folded,1,d),f(`bend`,u.flat,-1,d),f(`shadow`,u.flap,-1,d*.6),f(`curl`,u.flap,-1,d)}renderChrome(){let{els:e,settings:t,reader:n}=this,{labels:r}=t,i=this.chromeVisible||this.stripOpen,a=document.fullscreenElement===this.root,o=(e,t,n)=>{e.setAttribute(`aria-label`,t),e.title=t,n&&e.replaceChildren(E(n))};e.top.hidden=!t.controls,e.bottom.hidden=!t.controls,e.top.classList.toggle(`is-hidden`,!i),e.bottom.classList.toggle(`is-hidden`,!i),e.title.textContent=t.book.title,e.byline.textContent=t.book.author?r.byline(t.book.author):``,e.byline.hidden=!t.book.author,e.sound.hidden=!t.soundButton,e.fullscreen.hidden=!t.fullscreenButton,o(e.sound,this.soundOn?r.soundOff:r.soundOn,this.soundOn?Q.soundOn:Q.soundOff),o(e.fullscreen,a?r.exitFullscreen:r.fullscreen,a?Q.collapse:Q.expand),o(e.prev,r.previous),o(e.next,r.next),e.prev.disabled=n.atStart,e.next.disabled=n.atEnd,e.pages.replaceChildren(...t.thumbnails?[E(Q.grid)]:[],n.label),e.pages.setAttribute(`aria-expanded`,String(this.stripOpen))}renderStrip(){let e=this.stripOpen&&this.settings.thumbnails,{book:t}=this.settings;if(!e){this.els.strip?.remove(),this.els.strip=null;return}let n=w(`div`,{class:`fb-strip-list`});for(let e of this.layout.stops()){let r=w(`button`,{type:`button`,class:`fb-strip-stop`,"aria-current":String(e.flipped===this.reader.flipped),"aria-label":`Go to ${b.describe(e.faces)}`});for(let n of e.faces)r.append(w(`div`,{class:`fb-strip-face`},U(n,t,void 0,!1)));r.addEventListener(`click`,()=>{this.stripOpen=!1,this.reader.go(e.flipped),this.render()}),n.append(r)}let r=w(`div`,{class:`fb-strip`},n);this.els.strip?.remove(),this.els.strip=r,this.els.bottom.before(r),n.querySelector(`[aria-current='true']`)?.scrollIntoView({inline:`center`,block:`nearest`})}renderRotatePrompt(){let{landscape:e,layout:t,labels:n}=this.settings;if(!(e&&t!==`single`&&this.orientation.touch&&this.orientation.portrait&&this.portraitChoice===`ask`)){this.els.rotate?.remove(),this.els.rotate=null;return}if(this.els.rotate)return;let r=w(`button`,{type:`button`,class:`fb-rotate-primary`},n.rotateFullscreen),i=w(`button`,{type:`button`,class:`fb-rotate-secondary`},n.rotateSingle);r.addEventListener(`click`,()=>D(this.root)),i.addEventListener(`click`,()=>{this.portraitChoice=`single`,this.render()}),this.els.rotate=w(`div`,{class:`fb-rotate`},E(Q.phone),w(`div`,{},w(`p`,{class:`fb-rotate-title`},n.rotateTitle),w(`p`,{class:`fb-rotate-body`},n.rotateBody)),r,i),this.root.append(this.els.rotate)}static stageTint(e){let[t,n,r]=m[e.theme??`classic`].stage;return`radial-gradient(ellipse at 50% 40%, ${t} 0%, ${n} 55%, ${r} 100%)`}};return e.Affine=i,e.BANDED_FRAMES=_,e.BookLayout=b,e.COVER_THEMES=m,e.DEFAULT_GRIP=x,e.DEFAULT_LABELS=C,e.DEFAULT_PHYSICS=o,e.FRAME_STYLES=g,e.Flipbook=ee,e.FlipbookReader=S,e.Fold=a,e.PAGE_LAYOUTS=u,e.PAPER_COLORS=h,e.PLACED_LAYOUTS=p,e.PageTurn=l,e.dot=n,e.enterLandscape=D,e.frameOf=y,e.length=r,e.photoFrame=v,e.playPageTurn=G,e.printedPhoto=I,e.renderBackCover=z,e.renderBlank=H,e.renderColophon=V,e.renderCover=R,e.renderFace=U,e.renderPage=L,e.renderTitlePage=B,e.sub=t,e.watchOrientation=O,e})({});
|
|
8
|
+
</svg>`),B=(e,t)=>O(`img`,{src:e.src,alt:e.alt??``,draggable:`false`,decoding:`async`,width:e.width??void 0,height:e.height??void 0,class:t}),V=({x:e,y:t,width:n,height:r,rotate:i})=>({left:`${e}cqw`,top:`${t}cqw`,width:`${n}cqw`,height:`${r}cqw`,...i?{transform:`rotate(${i}deg)`}:{}}),H=e=>O(`div`,{class:`fb-page-surface ${e?`is-${e}`:``}`,"aria-hidden":`true`},O(`div`,{class:`fb-page-surface-grain`}),e&&O(`div`,{class:`fb-page-surface-gutter`}),e&&O(`div`,{class:`fb-page-surface-sheen`})),U=(e,t,n=!0,r=!0)=>O(`p`,{class:`fb-serif ${n?`fb-italic`:``} ${r?`fb-center`:``}`,style:t},e);function W(e,t,n=`cover`,r=!0,i=1){let a=e?.width&&e.height?e.width/e.height:4/3,o=O(`div`,{class:`fb-print-frame-box`,style:{fontSize:`${i}cqw`}}),s=O(`div`,{class:`fb-print-frame fb-frame-${t} ${n===`contain`?`is-contained`:``}`});if(n===`contain`&&s.style.setProperty(`--ratio`,String(a)),v[t]&&s.append(O(`span`,{class:`fb-print-frame-band`,"aria-hidden":`true`})),s.append(e&&r?B(e,`fb-print-photo fb-print-frame-photo`):O(`div`,{class:`fb-print-frame-photo fb-placeholder`})),t===`corners`)for(let e of[`tl`,`tr`,`bl`,`br`])s.append(O(`span`,{class:`fb-print-frame-corner is-${e}`,"aria-hidden":`true`}));return t===`botanical`&&s.append(oe(`tl`),oe(`br`)),o.append(s),o}function G(e,t,n={}){let{layout:r,caption:i,photos:a}=e,{number:o,side:s,showImages:c=!0,onSlotClick:l,activeSlot:u}=n,d=p[r],f=O(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page`}),m=(n,r=``,i=!1,o)=>{let s=a[n]??null,d=b(e,s,t.frame),f=O(`div`,{class:[`fb-slot`,r,i&&`is-framed`,l&&`is-editable`,l&&u===n&&`is-active`].filter(Boolean).join(` `),role:l?`button`:void 0,"aria-label":l?`Photo slot ${n+1}`:void 0,style:o});return l&&f.addEventListener(`click`,()=>l(n)),f.append(s?W(s,d,i?`contain`:`cover`,c):O(`div`,{class:`fb-slot-empty`},l?`Add a photo`:``)),f},h=(e,...t)=>O(`div`,{class:`fb-column`,style:e},...t),g=i?U(i,{fontSize:`3.8cqw`}):null;switch(r){case`single`:f.append(m(0,`fb-bleed`)),i&&f.append(O(`div`,{class:`fb-caption-over`},i));break;case`framed`:f.append(h({padding:`10cqw 9cqw 6cqw`},O(`div`,{class:`fb-grow`},m(0,`fb-fill`,!0)),U(i??``,{marginTop:`5cqw`,fontSize:`4.2cqw`,minHeight:`6cqw`,lineHeight:`1.35`})));break;case`pair`:f.append(h({padding:`7cqw`,gap:`4cqw`},m(0,`fb-grow`),m(1,`fb-grow`),g));break;case`grid`:f.append(h({padding:`7cqw`,gap:`3cqw`},O(`div`,{class:`fb-grid fb-grow`,style:{gap:`3cqw`}},...[0,1,2,3].map(e=>m(e))),g));break;case`collage`:f.append(h({padding:`7cqw`,gap:`3cqw`},m(0,`fb-grow-large`),O(`div`,{class:`fb-row fb-grow`,style:{gap:`3cqw`}},m(1,`fb-grow`),m(2,`fb-grow`)),g));break;case`text`:f.append(O(`div`,{class:`fb-column fb-center`,style:{alignItems:`center`,justifyContent:`center`,padding:`14cqw 12cqw`}},O(`span`,{class:`fb-serif`,style:{fontSize:`18cqw`,lineHeight:`0.6`,opacity:`0.3`},"aria-hidden":`true`},`“`),U(i||(l?`Write something in the caption box below.`:``),{marginTop:`4cqw`,fontSize:`6cqw`,lineHeight:`1.4`,textWrap:`balance`},!0,!1)))}return d&&(f.append(...d.slots.map((e,t)=>m(t,`fb-placed ${d.loose?`is-loose`:``}`,!1,V(e)))),i&&f.append(O(`p`,{class:`fb-placed-caption fb-serif ${d.prose?`is-prose`:`fb-italic`}`,style:V(d.caption)},i))),o!==void 0&&r!==`single`&&f.append(O(`span`,{class:`fb-page-number`,style:s===`left`?{left:`0`}:{right:`0`}},String(o))),f.append(H(s)),f}function K(e,t,n){let r=[e.author,e.year].filter(Boolean).join(` · `);return O(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page fb-center`,style:{alignItems:`center`,justifyContent:`center`,padding:`12cqw`}},z(),O(`h2`,{class:`fb-serif`,style:{marginTop:`6cqw`,fontSize:`7.5cqw`,fontWeight:`400`,lineHeight:`1.1`,textWrap:`balance`}},e.title),e.subtitle&&U(e.subtitle,{marginTop:`4cqw`,fontSize:`4cqw`,lineHeight:`1.45`},!0,!1),O(`div`,{style:{marginTop:`7cqw`,height:`1px`,width:`20cqw`,background:`currentColor`,opacity:`0.3`}}),r&&O(`p`,{style:{marginTop:`5cqw`,fontSize:`2.6cqw`,letterSpacing:`0.2em`,textTransform:`uppercase`}},r),H(n))}function q(e,t,n){return O(`div`,{class:`fb-paper fb-paper-${t.paper} fb-page fb-center`,style:{alignItems:`center`,justifyContent:`flex-end`,padding:`12cqw`,opacity:`0.9`}},e.colophon&&U(e.colophon,{fontSize:`3.6cqw`},!0,!1),H(n))}function se(e,t){return O(`div`,{class:`fb-paper fb-paper-${e.paper} fb-page`},H(t))}function J(e,t,n,r=!0){let i={paper:t.paper??`ivory`,frame:t.frame??`none`};switch(e.kind){case`cover`:return re(t);case`back`:return ie(t);case`title`:return K(t,i,n);case`colophon`:return q(t,i,n);case`blank`:return se(i,n);case`page`:return G(t.pages[e.index],i,{number:r?e.index+1:void 0,side:n})}}let Y=null;function X(e=.18){try{Y??=new AudioContext;let t=Y.createBuffer(1,Math.floor(Y.sampleRate*.45),Y.sampleRate),n=t.getChannelData(0);for(let e=0;e<n.length;e++){let t=e/n.length,r=Math.sin(Math.PI*Math.min(1,t*2.2))*(1-t)**1.5;n[e]=(Math.random()*2-1)*r*(.6+.4*Math.sin(t*40))}let r=Y.createBufferSource(),i=Y.createBiquadFilter(),a=Y.createGain();r.buffer=t,i.type=`bandpass`,i.frequency.value=2200,i.Q.value=.6,a.gain.value=e,r.connect(i).connect(a).connect(Y.destination),r.start()}catch{}}let ce=3/4,le=`flipbook:sound`,ue={layout:`auto`,controls:!0,autoHide:3200,thumbnails:!0,soundButton:!0,sound:!1,fullscreenButton:!0,landscape:!0,keyboard:!0,stiffCovers:!0,shading:1,labels:T},de=[{name:`under`,z:2},{name:`bend`,z:4},{name:`shadow`,z:5},{name:`curl`,z:7}],Z=(e,t=0,n=0)=>e.length?`polygon(${e.map(e=>`${(e.x+t).toFixed(2)}px ${(e.y+n).toFixed(2)}px`).join(`, `)})`:`polygon(0 0)`,Q=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="${e}" stroke-linecap="round" stroke-linejoin="round"/></svg>`,$={prev:Q(`M15 6l-6 6 6 6`),next:Q(`M9 6l6 6-6 6`),expand:Q(`M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5`),collapse:Q(`M9 4v5H4M15 4v5h5M9 20v-5H4M15 20v-5h5`),soundOn:Q(`M4 10v4h3l5 4V6L7 10H4zM16 9a4 4 0 0 1 0 6M18.5 6.5a8 8 0 0 1 0 11`),soundOff:Q(`M4 10v4h3l5 4V6L7 10H4zM17 10l4 4M21 10l-4 4`),grid:`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="5" width="8" height="14" rx="1"/><rect x="13" y="5" width="8" height="14" rx="1"/></svg>`,phone:`<svg viewBox="0 0 64 64" class="fb-rotate-hint" aria-hidden="true"><rect x="20" y="6" width="24" height="52" rx="4" fill="none" stroke="currentColor" stroke-width="2.5"/><circle cx="32" cy="51" r="2" fill="currentColor"/></svg>`},fe=()=>{try{return localStorage.getItem(le)}catch{return null}};var pe=class e{container;root;reader;settings;layout;size={width:0,height:0};orientation={portrait:!1,touch:!1};portraitChoice=`ask`;soundOn;stripOpen=!1;chromeVisible=!0;hideTimer;lastPlace=``;rendering=!1;dirty=!1;faces=/* @__PURE__ */ new Map;overlays=/* @__PURE__ */ new Map;cleanups=[];els;constructor(t,n){this.container=t,this.settings=e.resolve(n),this.soundOn=this.settings.sound,this.layout=this.buildLayout(),this.reader=new w(this.layout,{frame:(e,t)=>this.paint(e,t),change:()=>this.render(),flip:()=>{this.soundOn&&X(),this.settings.onFlip?.()}},{flipped:this.layout.flippedForPage(this.settings.startPage),physics:n.physics,grip:n.grip}),this.root=O(`div`,{class:`fb-root`}),this.els=this.build(),t.append(this.root);let r=fe();this.settings.soundButton&&r&&(this.soundOn=r===`on`),this.listen(),this.poke(),this.render()}update(t){let n=t.book&&t.book!==this.settings.book;this.settings=e.resolve({...this.settings,...t,labels:{...this.settings.labels,...t.labels}}),t.sound!==void 0&&(this.soundOn=t.sound),t.physics&&(this.reader.engine.physics={...this.reader.engine.physics,...t.physics}),t.grip&&(this.reader.grip={...this.reader.grip,...t.grip}),(n||t.stiffCovers!==void 0)&&this.clearFaces(),this.els.title.textContent=this.settings.book.title,this.poke(),this.render()}next(){this.reader.next()}prev(){this.reader.prev()}go(e){this.reader.go(e)}goToPage(e){this.reader.go(this.reader.layout.flippedForPage(e))}destroy(){this.reader.destroy(),clearTimeout(this.hideTimer),this.cleanups.forEach(e=>e()),this.root.remove()}static resolve(e){let t=Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0));return{...ue,...t,labels:{...T,...e.labels}}}get spread(){let{layout:e,landscape:t}=this.settings,n=t&&this.orientation.touch&&this.orientation.portrait,r=this.els?.stage.getBoundingClientRect(),i=!!r&&r.width>0&&r.width/r.height<.95;return e===`auto`?!(n&&this.portraitChoice===`single`)&&!i:e===`spread`}buildLayout(){return new S(this.settings.book.pages.length,{spread:this.spread,stiffCovers:this.settings.stiffCovers})}build(){let e=(e,t,n)=>{let r=O(`button`,{type:`button`,class:`fb-button`,"aria-label":e,title:e});return r.append(k(t)),r.addEventListener(`click`,n),r},t=O(`h1`,{class:`fb-title`},this.settings.book.title),n=O(`p`,{class:`fb-byline`}),r=e(``,$.soundOff,()=>this.toggleSound()),i=e(``,$.expand,()=>this.toggleFullscreen()),a=O(`div`,{class:`fb-bar-group`},r,i),o=O(`div`,{class:`fb-bar fb-bar-top`},O(`div`,{class:`fb-bar-group`},O(`div`,{class:`fb-heading`},t,n)),a),s=O(`div`,{class:`fb-book-shadow`}),c=O(`div`,{class:`fb-edge`}),l=O(`div`,{class:`fb-edge`}),u=O(`div`,{class:`fb-spine`}),d=O(`div`,{class:`fb-book`},s,c,l,u),f=O(`div`,{class:`fb-stage`},d),p=e(``,$.prev,()=>this.reader.prev()),m=e(``,$.next,()=>this.reader.next()),h=O(`button`,{type:`button`,class:`fb-pages-button`,"aria-live":`polite`}),g=O(`div`,{class:`fb-bar fb-bar-bottom`},p,h,m);h.addEventListener(`click`,()=>{this.settings.thumbnails&&(this.stripOpen=!this.stripOpen,this.render())});for(let{name:e,z:t}of de){let n=O(`div`,{class:`fb-light`}),r=O(`div`,{class:`fb-overlay`,style:{zIndex:String(t)}},n);this.overlays.set(e,{clip:r,light:n})}return this.root.append(o,f,g),{top:o,title:t,byline:n,topRight:a,sound:r,fullscreen:i,stage:f,book:d,shadow:s,leftEdge:c,rightEdge:l,spine:u,bottom:g,prev:p,pages:h,next:m,strip:null,rotate:null}}listen(){let{stage:e}=this.els,t=(e,t,n)=>{e.addEventListener(t,n),this.cleanups.push(()=>e.removeEventListener(t,n))},n=new ResizeObserver(()=>this.render());n.observe(e),this.cleanups.push(()=>n.disconnect()),this.cleanups.push(j(e=>{this.orientation=e,this.render()})),t(e,`pointerdown`,e=>{e.button===0&&this.reader.down(this.toBook(e),e.pointerId)}),t(e,`pointermove`,t=>{let n=this.toBook(t);this.poke(),t.pointerType===`mouse`&&this.reader.hover(n),this.reader.move(n,t.pointerId)&&!e.hasPointerCapture(t.pointerId)&&e.setPointerCapture(t.pointerId)}),t(e,`pointerup`,t=>{if(this.reader.up(this.toBook(t),t.pointerId)!==`tap`)return;let n=e.getBoundingClientRect(),r=t.clientX-n.left;r>n.width*2/3?this.reader.next():r<n.width/3&&this.reader.prev()}),t(e,`pointerleave`,()=>this.reader.leave()),t(e,`pointercancel`,()=>this.reader.cancel()),t(this.root,`keydown`,e=>this.settings.keyboard===!0&&this.onKey(e)),t(window,`keydown`,e=>this.settings.keyboard===`global`&&this.onKey(e)),t(document,`fullscreenchange`,()=>this.render())}onKey(e){e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLSelectElement||([`ArrowRight`,`PageDown`,` `].includes(e.key)?(e.preventDefault(),this.reader.next()):[`ArrowLeft`,`PageUp`].includes(e.key)?(e.preventDefault(),this.reader.prev()):e.key===`Home`?this.reader.go(0):e.key===`End`?this.reader.go(this.reader.layout.length):e.key===`Escape`&&this.stripOpen&&(this.stripOpen=!1,this.render()))}toBook(e){let t=this.els.book.getBoundingClientRect();return{x:e.clientX-(t.left+(this.layout.spread?t.width/2:0)),y:e.clientY-t.top}}poke(){let{autoHide:e}=this.settings;clearTimeout(this.hideTimer),this.chromeVisible||(this.chromeVisible=!0,this.renderChrome()),e!==!1&&(this.hideTimer=setTimeout(()=>{this.chromeVisible=!1,this.renderChrome()},e))}toggleSound(){this.soundOn=!this.soundOn,this.soundOn&&X();try{localStorage.setItem(le,this.soundOn?`on`:`off`)}catch{}this.renderChrome()}async toggleFullscreen(){document.fullscreenElement?await document.exitFullscreen().catch(()=>{}):await A(this.root)}clearFaces(){this.faces.forEach(e=>e.remove()),this.faces.clear()}render(){if(this.rendering)this.dirty=!0;else{this.rendering=!0;do this.dirty=!1,this.renderOnce();while(this.dirty);this.rendering=!1}}renderOnce(){let{settings:t,reader:n,els:r}=this,{book:i,controls:a}=t,o=r.stage.getBoundingClientRect(),s=this.spread;(s!==this.layout.spread||i.pages.length!==this.layout.pageCount||t.stiffCovers!==this.layout.stiffCovers)&&(this.layout=this.buildLayout(),this.clearFaces());let c=s?2:1,l=!a||o.height<500?16:Math.min(150,o.height*.16),u=Math.max(0,o.width-(s?64:24)),d=Math.max(0,o.height-l),f=Math.floor(Math.min(d*ce,u/c)),p=Math.floor(f/ce);this.size={width:f,height:p},n.configure({layout:this.layout,width:f,height:p});let{flipped:m,active:h,settled:g,atStart:_,atEnd:v}=n,y=this.layout.leaves,b=0;s&&_&&g&&(b=-f/2),s&&v&&g&&(b=f/2),this.root.style.background=t.background??e.stageTint(i),this.root.tabIndex=t.keyboard===!0?0:-1,r.book.hidden=f<=0,Object.assign(r.book.style,{width:`${f*c}px`,height:`${p}px`,transform:`translateX(${b}px)`,cursor:n.engine.dragging?`grabbing`:`grab`,clipPath:s?``:`inset(-50% -50% -50% 0)`}),Object.assign(r.shadow.style,{left:s&&_&&g?`52%`:`2%`,right:s&&v&&g?`52%`:`2%`});let x=s&&!_&&!v,S=e=>Math.min(10,Math.max(0,e)*.8),C=x&&m>1?S(m-1):0,w=(x||s&&_)&&m<y.length-1?S(y.length-m-1):0;Object.assign(r.leftEdge.style,{display:C?``:`none`,left:`${-C}px`,width:`${C}px`}),Object.assign(r.rightEdge.style,{display:w?``:`none`,right:`${-w}px`,width:`${w}px`}),r.spine.style.left=`${s?f:0}px`,this.renderFaces(h,m,f,p),this.renderOverlays(h,f,p),this.renderChrome(),this.renderStrip(),this.renderRotatePrompt();let T=`${s}:${m}`;T!==this.lastPlace&&(this.lastPlace=T,t.onPageChange?.({flipped:m,label:n.label,faces:this.layout.visible(m)}))}renderFaces(e,t,n,r){let i=this.layout.leaves,a=e?.leaf??null,o=e?.dir??1,s=a===null?t:a+1,c=a===null?t-1:a-1,l=/* @__PURE__ */ new Set;for(let u=Math.max(0,t-2);u<=Math.min(i.length-1,t+1);u++)for(let t of[`front`,`back`]){let d=`${u}:${t}`,f=u===a?t===`front`==(o===1)?`turning`:`flap`:t===`front`?u===s?`right`:`spare`:u===c&&this.layout.spread?`left`:`spare`,p=f===`left`||f===`turning`&&o===-1&&!e?.stiff,m=this.faces.get(d);m||(m=O(`div`,{class:`fb-face`}),m.append(J(t===`front`?i[u].front:i[u].back,this.settings.book,t===`front`?`right`:`left`)),this.faces.set(d,m),this.els.spine.append(m)),l.add(d),Object.assign(m.style,{left:`${p?-n:0}px`,width:`${n}px`,height:`${r}px`,zIndex:String({right:1,left:1,turning:3,flap:6,spare:0}[f]),visibility:f===`spare`?`hidden`:`visible`}),m.setAttribute(`aria-hidden`,String(f!==`left`&&f!==`right`)),u!==a&&Object.assign(m.style,{transform:``,transformOrigin:``,clipPath:``})}for(let[e,t]of this.faces)l.has(e)||(t.remove(),this.faces.delete(e));e&&this.paint(this.reader.engine.frame,e)}renderOverlays(e,t,n){let r=!!e&&!e.stiff,i=e=>`${(t*e).toFixed(1)}px`,a={under:`linear-gradient(to right, rgb(0 0 0 / 0.42), rgb(0 0 0 / 0.2) ${i(.05)}, rgb(0 0 0 / 0.06) ${i(.16)}, transparent ${i(.3)})`,bend:`linear-gradient(to right, rgb(0 0 0 / 0.16), rgb(0 0 0 / 0.04) ${i(.05)}, transparent ${i(.1)})`,shadow:`rgb(0 0 0 / 0.55)`,curl:`linear-gradient(to right, rgb(0 0 0 / 0.3), rgb(0 0 0 / 0.1) ${i(.035)}, rgb(255 255 255 / 0.2) ${i(.11)}, rgb(255 255 255 / 0.06) ${i(.25)}, rgb(0 0 0 / 0.05) ${i(.6)}, rgb(0 0 0 / 0.12) ${i(1)})`};for(let[e,{clip:i,light:o}]of this.overlays){if(!r){i.remove();continue}let s=e===`shadow`;Object.assign(i.style,{left:`${-t}px`,top:`${-n}px`,width:`${t*2}px`,height:`${n*3}px`,filter:s?`blur(${Math.max(3,t*.012)}px)`:``}),Object.assign(o.style,s?{inset:`0`,background:a[e]}:{width:`${t*3}px`,height:`${n*4}px`,background:a[e]}),i.isConnected||this.els.spine.append(i)}r&&e&&this.paint(this.reader.engine.frame,e)}paint(e,t){let{width:n,height:r}=this.size,i=t.dir,o=this.faces.get(`${t.leaf}:front`),s=this.faces.get(`${t.leaf}:back`);if(e.stiff){let t=`perspective(${Math.max(1800,n*5)}px) rotateY(${a.hinge(e.origin,e.point,i)}deg)`;o&&Object.assign(o.style,{transformOrigin:`0 50%`,transform:t,clipPath:``}),s&&Object.assign(s.style,{transformOrigin:`0 50%`,transform:`${t} translateX(${n}px) rotateY(180deg)`,clipPath:``});return}let c=i===1?o:s,l=i===1?s:o,u=new a(n,r,e.origin,e.point),d=u.shade*this.settings.shading;c&&Object.assign(c.style,{transformOrigin:``,transform:``,clipPath:Z(u.flat.map(e=>({x:i===1?e.x:n-e.x,y:e.y})))}),l&&Object.assign(l.style,{transformOrigin:`0 0`,transform:u.flapMatrix(i),clipPath:Z(u.folded.map(e=>({x:i===1?n-e.x:e.x,y:e.y})))});let f=(e,t,a,o)=>{let s=this.overlays.get(e);if(!s)return;let c=Z(t.map(e=>({x:i*e.x,y:e.y})),n,r);if(s.clip.style.opacity=String(o),e===`shadow`){s.light.style.clipPath=c;return}let l=Math.atan2(a*u.normal.y,i*a*u.normal.x);s.clip.style.clipPath=c,s.light.style.transform=`translate(${i*u.center.x+n}px, ${u.center.y+r}px) rotate(${l}rad) translateY(-50%)`};f(`under`,u.folded,1,d),f(`bend`,u.flat,-1,d),f(`shadow`,u.flap,-1,d*.6),f(`curl`,u.flap,-1,d)}renderChrome(){let{els:e,settings:t,reader:n}=this,{labels:r}=t,i=this.chromeVisible||this.stripOpen,a=document.fullscreenElement===this.root,o=(e,t,n)=>{e.setAttribute(`aria-label`,t),e.title=t,n&&e.replaceChildren(k(n))};e.top.hidden=!t.controls,e.bottom.hidden=!t.controls,e.top.classList.toggle(`is-hidden`,!i),e.bottom.classList.toggle(`is-hidden`,!i),e.title.textContent=t.book.title,e.byline.textContent=t.book.author?r.byline(t.book.author):``,e.byline.hidden=!t.book.author,e.sound.hidden=!t.soundButton,e.fullscreen.hidden=!t.fullscreenButton,o(e.sound,this.soundOn?r.soundOff:r.soundOn,this.soundOn?$.soundOn:$.soundOff),o(e.fullscreen,a?r.exitFullscreen:r.fullscreen,a?$.collapse:$.expand),o(e.prev,r.previous),o(e.next,r.next),e.prev.disabled=n.atStart,e.next.disabled=n.atEnd,e.pages.replaceChildren(...t.thumbnails?[k($.grid)]:[],n.label),e.pages.setAttribute(`aria-expanded`,String(this.stripOpen))}renderStrip(){let e=this.stripOpen&&this.settings.thumbnails,{book:t}=this.settings;if(!e){this.els.strip?.remove(),this.els.strip=null;return}let n=O(`div`,{class:`fb-strip-list`});for(let e of this.layout.stops()){let r=O(`button`,{type:`button`,class:`fb-strip-stop`,"aria-current":String(e.flipped===this.reader.flipped),"aria-label":`Go to ${S.describe(e.faces)}`});for(let n of e.faces)r.append(O(`div`,{class:`fb-strip-face`},J(n,t,void 0,!1)));r.addEventListener(`click`,()=>{this.stripOpen=!1,this.reader.go(e.flipped),this.render()}),n.append(r)}let r=O(`div`,{class:`fb-strip`},n);this.els.strip?.remove(),this.els.strip=r,this.els.bottom.before(r),n.querySelector(`[aria-current='true']`)?.scrollIntoView({inline:`center`,block:`nearest`})}renderRotatePrompt(){let{landscape:e,layout:t,labels:n}=this.settings;if(!(e&&t!==`single`&&this.orientation.touch&&this.orientation.portrait&&this.portraitChoice===`ask`)){this.els.rotate?.remove(),this.els.rotate=null;return}if(this.els.rotate)return;let r=O(`button`,{type:`button`,class:`fb-rotate-primary`},n.rotateFullscreen),i=O(`button`,{type:`button`,class:`fb-rotate-secondary`},n.rotateSingle);r.addEventListener(`click`,()=>A(this.root)),i.addEventListener(`click`,()=>{this.portraitChoice=`single`,this.render()}),this.els.rotate=O(`div`,{class:`fb-rotate`},k($.phone),O(`div`,{},O(`p`,{class:`fb-rotate-title`},n.rotateTitle),O(`p`,{class:`fb-rotate-body`},n.rotateBody)),r,i),this.root.append(this.els.rotate)}static stageTint(e){let[t,n,r]=m[e.theme??`classic`].stage;return`radial-gradient(ellipse at 50% 40%, ${t} 0%, ${n} 55%, ${r} 100%)`}};return e.Affine=i,e.BANDED_FRAMES=v,e.BookLayout=S,e.COVER_DESIGNS=h,e.COVER_THEMES=m,e.DECO=D,e.DEFAULT_GRIP=C,e.DEFAULT_LABELS=T,e.DEFAULT_PHYSICS=o,e.FLEURON=E,e.FRAME_STYLES=_,e.Flipbook=pe,e.FlipbookReader=w,e.Fold=a,e.PAGE_LAYOUTS=u,e.PAPER_COLORS=g,e.PLACED_LAYOUTS=p,e.PageTurn=l,e.coverArtMarkup=N,e.coverHasText=y,e.dot=n,e.enterLandscape=A,e.frameOf=x,e.length=r,e.photoFrame=b,e.playPageTurn=X,e.printedPhoto=W,e.renderBackCover=ie,e.renderBlank=se,e.renderColophon=q,e.renderCover=re,e.renderFace=J,e.renderPage=G,e.renderTitlePage=K,e.sub=t,e.watchOrientation=j,e})({});
|
package/dist/index.cjs
CHANGED
|
@@ -54,6 +54,67 @@ function watchOrientation(onChange) {
|
|
|
54
54
|
window.removeEventListener("resize", update);
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
// src/cover.ts
|
|
58
|
+
const CORNERS = [
|
|
59
|
+
"tl",
|
|
60
|
+
"tr",
|
|
61
|
+
"bl",
|
|
62
|
+
"br"
|
|
63
|
+
];
|
|
64
|
+
/** SVG markup for a piece of cover line art, drawn in the current ink. */
|
|
65
|
+
function coverArtMarkup(art, className) {
|
|
66
|
+
const strokes = art.strokes.map(({ d, width, opacity = 1 }) => `<path d="${d}" fill="none" stroke="currentColor" stroke-width="${width}" stroke-opacity="${opacity}"/>`).join("");
|
|
67
|
+
const fills = art.fills.map((d) => `<path d="${d}" fill="currentColor"/>`).join("");
|
|
68
|
+
return `<svg viewBox="${art.viewBox}" class="${className}" preserveAspectRatio="none" aria-hidden="true">${strokes}${fills}</svg>`;
|
|
69
|
+
}
|
|
70
|
+
const fleurons = () => CORNERS.map((corner) => svg(coverArtMarkup(_toneflix_flipbook_core.FLEURON, `fb-fleuron is-${corner}`)));
|
|
71
|
+
const photo = (book, className, showImages) => book.cover && h("div", { class: className }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" }));
|
|
72
|
+
const title = (book) => h("h1", { class: "fb-serif fb-cover-title" }, book.title);
|
|
73
|
+
const kicker = (book) => book.kicker && h("p", { class: "fb-kicker" }, book.kicker);
|
|
74
|
+
const subtitle = (book) => book.subtitle && h("p", { class: "fb-serif fb-italic fb-cover-subtitle" }, book.subtitle);
|
|
75
|
+
/** The design's own layout, between the hinge and the finish. */
|
|
76
|
+
function design(book, showImages) {
|
|
77
|
+
const text = (0, _toneflix_flipbook_core.coverHasText)(book);
|
|
78
|
+
switch (book.coverDesign ?? "classic") {
|
|
79
|
+
case "gilt": return [
|
|
80
|
+
h("div", { class: "fb-cover-frame" }),
|
|
81
|
+
...fleurons(),
|
|
82
|
+
h("div", { class: "fb-cover-stack" }, text && kicker(book), text && title(book), photo(book, "fb-cover-photo is-oval", showImages), text && subtitle(book))
|
|
83
|
+
];
|
|
84
|
+
case "window": return [photo(book, "fb-cover-window", showImages) || h("div", { class: "fb-cover-window is-empty" }, ornament()), text && h("div", { class: "fb-cover-stamp" }, kicker(book), title(book), subtitle(book))];
|
|
85
|
+
case "label": return [book.cover && h("div", { class: "fb-cover-print" }, photo(book, "fb-cover-print-photo", showImages), ...CORNERS.map((corner) => h("span", {
|
|
86
|
+
class: `fb-print-frame-corner is-${corner}`,
|
|
87
|
+
"aria-hidden": "true"
|
|
88
|
+
}))), text && h("div", { class: `fb-cover-label ${book.cover ? "" : "is-alone"}` }, kicker(book), title(book), subtitle(book))];
|
|
89
|
+
case "deco": return [svg(coverArtMarkup(_toneflix_flipbook_core.DECO, "fb-cover-rays")), h("div", { class: "fb-cover-stack is-deco" }, text && kicker(book), photo(book, "fb-cover-photo is-arch", showImages), text && title(book), text && subtitle(book))];
|
|
90
|
+
case "image": return [
|
|
91
|
+
book.cover && h("div", { class: "fb-cover-art" }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" })),
|
|
92
|
+
book.cover && h("div", { class: "fb-cover-tint" }),
|
|
93
|
+
text && h("div", { class: `fb-cover-caption ${book.cover ? "" : "is-plain"}` }, kicker(book), title(book), subtitle(book))
|
|
94
|
+
];
|
|
95
|
+
default: return [h("div", { class: "fb-cover-panel" }, text && kicker(book), text && title(book), photo(book, "fb-cover-photo", showImages) || text && subtitle(book))];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const shell = (book, hinge, ...children) => h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"} fb-design-${book.coverDesign ?? "classic"}` }, ...children, h("div", { class: `fb-hinge is-${hinge}` }), h("div", {
|
|
99
|
+
class: "fb-cover-finish",
|
|
100
|
+
"aria-hidden": "true"
|
|
101
|
+
}));
|
|
102
|
+
/** The front cover, laid out by the book's `coverDesign`. */
|
|
103
|
+
function renderCover(book, showImages = true) {
|
|
104
|
+
return shell(book, "left", ...design(book, showImages));
|
|
105
|
+
}
|
|
106
|
+
/** The back cover: the same board, with the imprint. */
|
|
107
|
+
function renderBackCover(book) {
|
|
108
|
+
const gilt = book.coverDesign === "gilt";
|
|
109
|
+
return shell(book, "right", gilt && h("div", { class: "fb-cover-frame" }), ...gilt ? fleurons() : [], h("div", { class: "fb-imprint" }, ornament(), book.imprint && h("p", {
|
|
110
|
+
class: "fb-kicker",
|
|
111
|
+
style: {
|
|
112
|
+
marginTop: "2cqw",
|
|
113
|
+
fontSize: "2.4cqw",
|
|
114
|
+
opacity: "0.6"
|
|
115
|
+
}
|
|
116
|
+
}, book.imprint)));
|
|
117
|
+
}
|
|
57
118
|
// src/pages.ts
|
|
58
119
|
const LEAVES = [
|
|
59
120
|
14,
|
|
@@ -237,36 +298,6 @@ function renderPage(page, look, options = {}) {
|
|
|
237
298
|
root.append(surface(side));
|
|
238
299
|
return root;
|
|
239
300
|
}
|
|
240
|
-
/** The front cover: cloth with the title and an inset photo. */
|
|
241
|
-
function renderCover(book, showImages = true) {
|
|
242
|
-
const panel = h("div", { class: "fb-cover-panel" }, book.kicker && h("p", { class: "fb-kicker" }, book.kicker), h("h1", {
|
|
243
|
-
class: "fb-serif",
|
|
244
|
-
style: {
|
|
245
|
-
marginTop: "5cqw",
|
|
246
|
-
fontSize: "9cqw",
|
|
247
|
-
fontWeight: "500",
|
|
248
|
-
lineHeight: "1.05",
|
|
249
|
-
textWrap: "balance"
|
|
250
|
-
}
|
|
251
|
-
}, book.title));
|
|
252
|
-
if (book.cover) panel.append(h("div", { class: "fb-cover-photo" }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" })));
|
|
253
|
-
else if (book.subtitle) panel.append(serif(book.subtitle, {
|
|
254
|
-
marginTop: "6cqw",
|
|
255
|
-
fontSize: "4cqw",
|
|
256
|
-
opacity: "0.8"
|
|
257
|
-
}, true, false));
|
|
258
|
-
return h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"}` }, h("div", { class: "fb-hinge is-left" }), panel);
|
|
259
|
-
}
|
|
260
|
-
function renderBackCover(book) {
|
|
261
|
-
return h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"}` }, h("div", { class: "fb-hinge is-right" }), h("div", { class: "fb-imprint" }, ornament(), book.imprint && h("p", {
|
|
262
|
-
class: "fb-kicker",
|
|
263
|
-
style: {
|
|
264
|
-
marginTop: "2cqw",
|
|
265
|
-
fontSize: "2.4cqw",
|
|
266
|
-
opacity: "0.6"
|
|
267
|
-
}
|
|
268
|
-
}, book.imprint)));
|
|
269
|
-
}
|
|
270
301
|
function renderTitlePage(book, look, side) {
|
|
271
302
|
const credit = [book.author, book.year].filter(Boolean).join(" · ");
|
|
272
303
|
return h("div", {
|
|
@@ -1024,6 +1055,7 @@ var Flipbook = class Flipbook {
|
|
|
1024
1055
|
}
|
|
1025
1056
|
};
|
|
1026
1057
|
exports.Flipbook = Flipbook;
|
|
1058
|
+
exports.coverArtMarkup = coverArtMarkup;
|
|
1027
1059
|
exports.enterLandscape = enterLandscape;
|
|
1028
1060
|
exports.playPageTurn = playPageTurn;
|
|
1029
1061
|
exports.printedPhoto = printedPhoto;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Face, FlipbookBook, FlipbookLabels, FlipbookPage, FlipbookPhoto, FlipbookReader, FrameStyle, GripOptions, PaperColor, TurnPhysics } from "@toneflix/flipbook-core";
|
|
1
|
+
import { CoverArt, Face, FlipbookBook, FlipbookLabels, FlipbookPage, FlipbookPhoto, FlipbookReader, FrameStyle, GripOptions, PaperColor, TurnPhysics } from "@toneflix/flipbook-core";
|
|
2
2
|
export * from "@toneflix/flipbook-core";
|
|
3
3
|
interface FlipbookPlace {
|
|
4
4
|
/** How many leaves lie on the left: 0 is the closed front cover. */
|
|
@@ -117,14 +117,17 @@ interface PageOptions {
|
|
|
117
117
|
export declare function printedPhoto(photo: FlipbookPhoto | null, frame: FrameStyle, fit?: 'cover' | 'contain', show?: boolean, scale?: number): HTMLDivElement;
|
|
118
118
|
/** The inside of one book page. The parent must have `container-type: size`. */
|
|
119
119
|
export declare function renderPage(page: FlipbookPage, look: PageLook, options?: PageOptions): HTMLDivElement;
|
|
120
|
-
/** The front cover: cloth with the title and an inset photo. */
|
|
121
|
-
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
122
|
-
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
123
120
|
export declare function renderTitlePage(book: FlipbookBook, look: PageLook, side?: Side): HTMLDivElement;
|
|
124
121
|
export declare function renderColophon(book: FlipbookBook, look: PageLook, side?: Side): HTMLDivElement;
|
|
125
122
|
export declare function renderBlank(look: PageLook, side?: Side): HTMLDivElement;
|
|
126
123
|
/** Any face of a book. Page numbers and the spine curve need `side`. */
|
|
127
124
|
export declare function renderFace(face: Face, book: FlipbookBook, side?: Side, numbered?: boolean): HTMLDivElement;
|
|
125
|
+
/** SVG markup for a piece of cover line art, drawn in the current ink. */
|
|
126
|
+
export declare function coverArtMarkup(art: CoverArt, className: string): string;
|
|
127
|
+
/** The front cover, laid out by the book's `coverDesign`. */
|
|
128
|
+
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
129
|
+
/** The back cover: the same board, with the imprint. */
|
|
130
|
+
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
128
131
|
/**
|
|
129
132
|
* A soft paper swish made from filtered noise, so no audio file is needed. Browsers only allow
|
|
130
133
|
* audio after a user gesture, which a page turn always is.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Face, FlipbookBook, FlipbookLabels, FlipbookPage, FlipbookPhoto, FlipbookReader, FrameStyle, GripOptions, PaperColor, TurnPhysics } from "@toneflix/flipbook-core";
|
|
1
|
+
import { CoverArt, Face, FlipbookBook, FlipbookLabels, FlipbookPage, FlipbookPhoto, FlipbookReader, FrameStyle, GripOptions, PaperColor, TurnPhysics } from "@toneflix/flipbook-core";
|
|
2
2
|
export * from "@toneflix/flipbook-core";
|
|
3
3
|
interface FlipbookPlace {
|
|
4
4
|
/** How many leaves lie on the left: 0 is the closed front cover. */
|
|
@@ -117,14 +117,17 @@ interface PageOptions {
|
|
|
117
117
|
export declare function printedPhoto(photo: FlipbookPhoto | null, frame: FrameStyle, fit?: 'cover' | 'contain', show?: boolean, scale?: number): HTMLDivElement;
|
|
118
118
|
/** The inside of one book page. The parent must have `container-type: size`. */
|
|
119
119
|
export declare function renderPage(page: FlipbookPage, look: PageLook, options?: PageOptions): HTMLDivElement;
|
|
120
|
-
/** The front cover: cloth with the title and an inset photo. */
|
|
121
|
-
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
122
|
-
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
123
120
|
export declare function renderTitlePage(book: FlipbookBook, look: PageLook, side?: Side): HTMLDivElement;
|
|
124
121
|
export declare function renderColophon(book: FlipbookBook, look: PageLook, side?: Side): HTMLDivElement;
|
|
125
122
|
export declare function renderBlank(look: PageLook, side?: Side): HTMLDivElement;
|
|
126
123
|
/** Any face of a book. Page numbers and the spine curve need `side`. */
|
|
127
124
|
export declare function renderFace(face: Face, book: FlipbookBook, side?: Side, numbered?: boolean): HTMLDivElement;
|
|
125
|
+
/** SVG markup for a piece of cover line art, drawn in the current ink. */
|
|
126
|
+
export declare function coverArtMarkup(art: CoverArt, className: string): string;
|
|
127
|
+
/** The front cover, laid out by the book's `coverDesign`. */
|
|
128
|
+
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
129
|
+
/** The back cover: the same board, with the imprint. */
|
|
130
|
+
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
128
131
|
/**
|
|
129
132
|
* A soft paper swish made from filtered noise, so no audio file is needed. Browsers only allow
|
|
130
133
|
* audio after a user gesture, which a page turn always is.
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BANDED_FRAMES, BookLayout, COVER_THEMES, DEFAULT_LABELS, FlipbookReader, Fold, PLACED_LAYOUTS, photoFrame } from "@toneflix/flipbook-core";
|
|
1
|
+
import { BANDED_FRAMES, BookLayout, COVER_THEMES, DECO, DEFAULT_LABELS, FLEURON, FlipbookReader, Fold, PLACED_LAYOUTS, coverHasText, photoFrame } from "@toneflix/flipbook-core";
|
|
2
2
|
export * from "@toneflix/flipbook-core";
|
|
3
3
|
// src/dom.ts
|
|
4
4
|
/** Creates an element. Strings become text, so book content is never parsed as HTML. */
|
|
@@ -54,6 +54,67 @@ function watchOrientation(onChange) {
|
|
|
54
54
|
window.removeEventListener("resize", update);
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
// src/cover.ts
|
|
58
|
+
const CORNERS = [
|
|
59
|
+
"tl",
|
|
60
|
+
"tr",
|
|
61
|
+
"bl",
|
|
62
|
+
"br"
|
|
63
|
+
];
|
|
64
|
+
/** SVG markup for a piece of cover line art, drawn in the current ink. */
|
|
65
|
+
function coverArtMarkup(art, className) {
|
|
66
|
+
const strokes = art.strokes.map(({ d, width, opacity = 1 }) => `<path d="${d}" fill="none" stroke="currentColor" stroke-width="${width}" stroke-opacity="${opacity}"/>`).join("");
|
|
67
|
+
const fills = art.fills.map((d) => `<path d="${d}" fill="currentColor"/>`).join("");
|
|
68
|
+
return `<svg viewBox="${art.viewBox}" class="${className}" preserveAspectRatio="none" aria-hidden="true">${strokes}${fills}</svg>`;
|
|
69
|
+
}
|
|
70
|
+
const fleurons = () => CORNERS.map((corner) => svg(coverArtMarkup(FLEURON, `fb-fleuron is-${corner}`)));
|
|
71
|
+
const photo = (book, className, showImages) => book.cover && h("div", { class: className }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" }));
|
|
72
|
+
const title = (book) => h("h1", { class: "fb-serif fb-cover-title" }, book.title);
|
|
73
|
+
const kicker = (book) => book.kicker && h("p", { class: "fb-kicker" }, book.kicker);
|
|
74
|
+
const subtitle = (book) => book.subtitle && h("p", { class: "fb-serif fb-italic fb-cover-subtitle" }, book.subtitle);
|
|
75
|
+
/** The design's own layout, between the hinge and the finish. */
|
|
76
|
+
function design(book, showImages) {
|
|
77
|
+
const text = coverHasText(book);
|
|
78
|
+
switch (book.coverDesign ?? "classic") {
|
|
79
|
+
case "gilt": return [
|
|
80
|
+
h("div", { class: "fb-cover-frame" }),
|
|
81
|
+
...fleurons(),
|
|
82
|
+
h("div", { class: "fb-cover-stack" }, text && kicker(book), text && title(book), photo(book, "fb-cover-photo is-oval", showImages), text && subtitle(book))
|
|
83
|
+
];
|
|
84
|
+
case "window": return [photo(book, "fb-cover-window", showImages) || h("div", { class: "fb-cover-window is-empty" }, ornament()), text && h("div", { class: "fb-cover-stamp" }, kicker(book), title(book), subtitle(book))];
|
|
85
|
+
case "label": return [book.cover && h("div", { class: "fb-cover-print" }, photo(book, "fb-cover-print-photo", showImages), ...CORNERS.map((corner) => h("span", {
|
|
86
|
+
class: `fb-print-frame-corner is-${corner}`,
|
|
87
|
+
"aria-hidden": "true"
|
|
88
|
+
}))), text && h("div", { class: `fb-cover-label ${book.cover ? "" : "is-alone"}` }, kicker(book), title(book), subtitle(book))];
|
|
89
|
+
case "deco": return [svg(coverArtMarkup(DECO, "fb-cover-rays")), h("div", { class: "fb-cover-stack is-deco" }, text && kicker(book), photo(book, "fb-cover-photo is-arch", showImages), text && title(book), text && subtitle(book))];
|
|
90
|
+
case "image": return [
|
|
91
|
+
book.cover && h("div", { class: "fb-cover-art" }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" })),
|
|
92
|
+
book.cover && h("div", { class: "fb-cover-tint" }),
|
|
93
|
+
text && h("div", { class: `fb-cover-caption ${book.cover ? "" : "is-plain"}` }, kicker(book), title(book), subtitle(book))
|
|
94
|
+
];
|
|
95
|
+
default: return [h("div", { class: "fb-cover-panel" }, text && kicker(book), text && title(book), photo(book, "fb-cover-photo", showImages) || text && subtitle(book))];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const shell = (book, hinge, ...children) => h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"} fb-design-${book.coverDesign ?? "classic"}` }, ...children, h("div", { class: `fb-hinge is-${hinge}` }), h("div", {
|
|
99
|
+
class: "fb-cover-finish",
|
|
100
|
+
"aria-hidden": "true"
|
|
101
|
+
}));
|
|
102
|
+
/** The front cover, laid out by the book's `coverDesign`. */
|
|
103
|
+
function renderCover(book, showImages = true) {
|
|
104
|
+
return shell(book, "left", ...design(book, showImages));
|
|
105
|
+
}
|
|
106
|
+
/** The back cover: the same board, with the imprint. */
|
|
107
|
+
function renderBackCover(book) {
|
|
108
|
+
const gilt = book.coverDesign === "gilt";
|
|
109
|
+
return shell(book, "right", gilt && h("div", { class: "fb-cover-frame" }), ...gilt ? fleurons() : [], h("div", { class: "fb-imprint" }, ornament(), book.imprint && h("p", {
|
|
110
|
+
class: "fb-kicker",
|
|
111
|
+
style: {
|
|
112
|
+
marginTop: "2cqw",
|
|
113
|
+
fontSize: "2.4cqw",
|
|
114
|
+
opacity: "0.6"
|
|
115
|
+
}
|
|
116
|
+
}, book.imprint)));
|
|
117
|
+
}
|
|
57
118
|
// src/pages.ts
|
|
58
119
|
const LEAVES = [
|
|
59
120
|
14,
|
|
@@ -237,36 +298,6 @@ function renderPage(page, look, options = {}) {
|
|
|
237
298
|
root.append(surface(side));
|
|
238
299
|
return root;
|
|
239
300
|
}
|
|
240
|
-
/** The front cover: cloth with the title and an inset photo. */
|
|
241
|
-
function renderCover(book, showImages = true) {
|
|
242
|
-
const panel = h("div", { class: "fb-cover-panel" }, book.kicker && h("p", { class: "fb-kicker" }, book.kicker), h("h1", {
|
|
243
|
-
class: "fb-serif",
|
|
244
|
-
style: {
|
|
245
|
-
marginTop: "5cqw",
|
|
246
|
-
fontSize: "9cqw",
|
|
247
|
-
fontWeight: "500",
|
|
248
|
-
lineHeight: "1.05",
|
|
249
|
-
textWrap: "balance"
|
|
250
|
-
}
|
|
251
|
-
}, book.title));
|
|
252
|
-
if (book.cover) panel.append(h("div", { class: "fb-cover-photo" }, showImages ? image(book.cover, "fb-photo") : h("div", { class: "fb-placeholder" })));
|
|
253
|
-
else if (book.subtitle) panel.append(serif(book.subtitle, {
|
|
254
|
-
marginTop: "6cqw",
|
|
255
|
-
fontSize: "4cqw",
|
|
256
|
-
opacity: "0.8"
|
|
257
|
-
}, true, false));
|
|
258
|
-
return h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"}` }, h("div", { class: "fb-hinge is-left" }), panel);
|
|
259
|
-
}
|
|
260
|
-
function renderBackCover(book) {
|
|
261
|
-
return h("div", { class: `fb-cover fb-cover-${book.theme ?? "classic"}` }, h("div", { class: "fb-hinge is-right" }), h("div", { class: "fb-imprint" }, ornament(), book.imprint && h("p", {
|
|
262
|
-
class: "fb-kicker",
|
|
263
|
-
style: {
|
|
264
|
-
marginTop: "2cqw",
|
|
265
|
-
fontSize: "2.4cqw",
|
|
266
|
-
opacity: "0.6"
|
|
267
|
-
}
|
|
268
|
-
}, book.imprint)));
|
|
269
|
-
}
|
|
270
301
|
function renderTitlePage(book, look, side) {
|
|
271
302
|
const credit = [book.author, book.year].filter(Boolean).join(" · ");
|
|
272
303
|
return h("div", {
|
|
@@ -1023,4 +1054,4 @@ var Flipbook = class Flipbook {
|
|
|
1023
1054
|
return `radial-gradient(ellipse at 50% 40%, ${inner} 0%, ${middle} 55%, ${outer} 100%)`;
|
|
1024
1055
|
}
|
|
1025
1056
|
};
|
|
1026
|
-
export { Flipbook, enterLandscape, playPageTurn, printedPhoto, renderBackCover, renderBlank, renderColophon, renderCover, renderFace, renderPage, renderTitlePage, watchOrientation };
|
|
1057
|
+
export { Flipbook, coverArtMarkup, enterLandscape, playPageTurn, printedPhoto, renderBackCover, renderBlank, renderColophon, renderCover, renderFace, renderPage, renderTitlePage, watchOrientation };
|
package/dist/style.css
CHANGED
|
@@ -805,6 +805,313 @@
|
|
|
805
805
|
color: #e8e2d6;
|
|
806
806
|
}
|
|
807
807
|
|
|
808
|
+
.fb-cover-leather {
|
|
809
|
+
background-color: #6b3f24;
|
|
810
|
+
background-image:
|
|
811
|
+
radial-gradient(ellipse at 30% 18%, rgb(255 220 170 / 0.12), transparent 50%),
|
|
812
|
+
radial-gradient(ellipse at 50% 55%, transparent 50%, rgb(0 0 0 / 0.35)),
|
|
813
|
+
repeating-radial-gradient(circle at 20% 30%, rgb(0 0 0 / 0.06) 0 1px, transparent 1px 4px),
|
|
814
|
+
repeating-radial-gradient(circle at 70% 80%, rgb(255 255 255 / 0.03) 0 1px, transparent 1px 5px);
|
|
815
|
+
color: #ecc77d;
|
|
816
|
+
}
|
|
817
|
+
.fb-cover-sage {
|
|
818
|
+
background-color: #5d6f5c;
|
|
819
|
+
background-image:
|
|
820
|
+
radial-gradient(circle at 30% 20%, rgb(255 255 255 / 0.08), transparent 45%),
|
|
821
|
+
repeating-linear-gradient(0deg, rgb(0 0 0 / 0.05) 0 1px, transparent 1px 3px),
|
|
822
|
+
repeating-linear-gradient(90deg, rgb(255 255 255 / 0.03) 0 1px, transparent 1px 3px);
|
|
823
|
+
color: #f1e9d2;
|
|
824
|
+
}
|
|
825
|
+
.fb-cover-blush {
|
|
826
|
+
background-color: #d8b4a8;
|
|
827
|
+
background-image:
|
|
828
|
+
radial-gradient(circle at 30% 20%, rgb(255 255 255 / 0.18), transparent 45%),
|
|
829
|
+
repeating-linear-gradient(0deg, rgb(90 40 30 / 0.05) 0 1px, transparent 1px 3px),
|
|
830
|
+
repeating-linear-gradient(90deg, rgb(90 40 30 / 0.04) 0 1px, transparent 1px 3px);
|
|
831
|
+
color: #5a2f2a;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/* Cover designs. Ink is the cover's text colour; foil and stamping come from layered text shadows. */
|
|
835
|
+
.fb-cover .fb-cover-title {
|
|
836
|
+
margin-top: 5cqw;
|
|
837
|
+
font-size: 9cqw;
|
|
838
|
+
font-weight: 500;
|
|
839
|
+
line-height: 1.05;
|
|
840
|
+
text-wrap: balance;
|
|
841
|
+
text-shadow:
|
|
842
|
+
0 0.15cqw 0 rgb(0 0 0 / 0.35),
|
|
843
|
+
0 -0.1cqw 0 rgb(255 255 255 / 0.12);
|
|
844
|
+
}
|
|
845
|
+
.fb-cover .fb-cover-subtitle {
|
|
846
|
+
margin-top: 5cqw;
|
|
847
|
+
font-size: 4cqw;
|
|
848
|
+
opacity: 0.85;
|
|
849
|
+
}
|
|
850
|
+
.fb-cover-finish {
|
|
851
|
+
position: absolute;
|
|
852
|
+
inset: 0;
|
|
853
|
+
pointer-events: none;
|
|
854
|
+
background:
|
|
855
|
+
linear-gradient(115deg, rgb(255 255 255 / 0.1), transparent 35%, transparent 70%, rgb(255 255 255 / 0.05)),
|
|
856
|
+
radial-gradient(ellipse at 50% 50%, transparent 60%, rgb(0 0 0 / 0.22)), url('./textures/grain-fine.webp');
|
|
857
|
+
background-size: auto, auto, 40cqw;
|
|
858
|
+
box-shadow:
|
|
859
|
+
inset 0 0 0 0.3cqw rgb(0 0 0 / 0.12),
|
|
860
|
+
inset 0 0 2cqw rgb(0 0 0 / 0.18);
|
|
861
|
+
mix-blend-mode: soft-light;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.fb-cover-stack {
|
|
865
|
+
position: absolute;
|
|
866
|
+
inset: 14cqw 12cqw;
|
|
867
|
+
display: flex;
|
|
868
|
+
flex-direction: column;
|
|
869
|
+
align-items: center;
|
|
870
|
+
justify-content: center;
|
|
871
|
+
text-align: center;
|
|
872
|
+
}
|
|
873
|
+
.fb-cover-frame {
|
|
874
|
+
position: absolute;
|
|
875
|
+
inset: 5cqw;
|
|
876
|
+
border: 0.35cqw solid currentColor;
|
|
877
|
+
outline: 0.15cqw solid currentColor;
|
|
878
|
+
outline-offset: -1.6cqw;
|
|
879
|
+
opacity: 0.85;
|
|
880
|
+
}
|
|
881
|
+
.fb-fleuron {
|
|
882
|
+
position: absolute;
|
|
883
|
+
width: 18cqw;
|
|
884
|
+
height: 18cqw;
|
|
885
|
+
}
|
|
886
|
+
.fb-fleuron.is-tl {
|
|
887
|
+
top: 3.6cqw;
|
|
888
|
+
left: 3.6cqw;
|
|
889
|
+
}
|
|
890
|
+
.fb-fleuron.is-tr {
|
|
891
|
+
top: 3.6cqw;
|
|
892
|
+
right: 3.6cqw;
|
|
893
|
+
transform: scaleX(-1);
|
|
894
|
+
}
|
|
895
|
+
.fb-fleuron.is-bl {
|
|
896
|
+
bottom: 3.6cqw;
|
|
897
|
+
left: 3.6cqw;
|
|
898
|
+
transform: scaleY(-1);
|
|
899
|
+
}
|
|
900
|
+
.fb-fleuron.is-br {
|
|
901
|
+
right: 3.6cqw;
|
|
902
|
+
bottom: 3.6cqw;
|
|
903
|
+
transform: scale(-1);
|
|
904
|
+
}
|
|
905
|
+
.fb-design-gilt .fb-cover-frame,
|
|
906
|
+
.fb-design-gilt .fb-fleuron {
|
|
907
|
+
filter: drop-shadow(0 0.15cqw 0 rgb(0 0 0 / 0.3));
|
|
908
|
+
}
|
|
909
|
+
.fb-cover-photo.is-oval {
|
|
910
|
+
width: 52cqw;
|
|
911
|
+
height: 64cqw;
|
|
912
|
+
max-height: none;
|
|
913
|
+
flex: none;
|
|
914
|
+
margin: 6cqw 0 0;
|
|
915
|
+
border-radius: 50%;
|
|
916
|
+
border: 0.6cqw solid currentColor;
|
|
917
|
+
box-shadow:
|
|
918
|
+
0 0 0 1.2cqw color-mix(in srgb, currentColor 0%, transparent),
|
|
919
|
+
0 0 0 1.5cqw color-mix(in srgb, currentColor 55%, transparent),
|
|
920
|
+
inset 0 0 3cqw rgb(0 0 0 / 0.45);
|
|
921
|
+
}
|
|
922
|
+
.fb-design-gilt .fb-cover-title {
|
|
923
|
+
font-size: 8cqw;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
.fb-cover-window {
|
|
927
|
+
position: absolute;
|
|
928
|
+
top: 10cqw;
|
|
929
|
+
left: 12cqw;
|
|
930
|
+
right: 12cqw;
|
|
931
|
+
height: 76cqw;
|
|
932
|
+
overflow: hidden;
|
|
933
|
+
border-radius: 0.6cqw;
|
|
934
|
+
box-shadow:
|
|
935
|
+
inset 0 0.8cqw 1.6cqw rgb(0 0 0 / 0.55),
|
|
936
|
+
inset 0 -0.3cqw 0.6cqw rgb(255 255 255 / 0.12),
|
|
937
|
+
0 0.3cqw 0 rgb(255 255 255 / 0.1),
|
|
938
|
+
0 -0.3cqw 0 rgb(0 0 0 / 0.25);
|
|
939
|
+
}
|
|
940
|
+
.fb-cover-window::after {
|
|
941
|
+
content: '';
|
|
942
|
+
position: absolute;
|
|
943
|
+
inset: 0;
|
|
944
|
+
box-shadow:
|
|
945
|
+
inset 0 1.2cqw 2cqw rgb(0 0 0 / 0.5),
|
|
946
|
+
inset 0.6cqw 0 1.2cqw rgb(0 0 0 / 0.25),
|
|
947
|
+
inset -0.6cqw 0 1.2cqw rgb(0 0 0 / 0.2);
|
|
948
|
+
pointer-events: none;
|
|
949
|
+
}
|
|
950
|
+
.fb-cover-window.is-empty {
|
|
951
|
+
display: flex;
|
|
952
|
+
align-items: center;
|
|
953
|
+
justify-content: center;
|
|
954
|
+
background: rgb(0 0 0 / 0.12);
|
|
955
|
+
}
|
|
956
|
+
.fb-cover-window.is-empty .fb-ornament {
|
|
957
|
+
width: 16cqw;
|
|
958
|
+
height: 16cqw;
|
|
959
|
+
opacity: 0.6;
|
|
960
|
+
}
|
|
961
|
+
.fb-cover-stamp {
|
|
962
|
+
position: absolute;
|
|
963
|
+
left: 10cqw;
|
|
964
|
+
right: 10cqw;
|
|
965
|
+
top: 92cqw;
|
|
966
|
+
bottom: 8cqw;
|
|
967
|
+
display: flex;
|
|
968
|
+
flex-direction: column;
|
|
969
|
+
align-items: center;
|
|
970
|
+
justify-content: center;
|
|
971
|
+
text-align: center;
|
|
972
|
+
}
|
|
973
|
+
.fb-cover-stamp .fb-cover-title {
|
|
974
|
+
margin-top: 1.5cqw;
|
|
975
|
+
font-size: 7.5cqw;
|
|
976
|
+
text-shadow:
|
|
977
|
+
0 -0.15cqw 0 rgb(0 0 0 / 0.45),
|
|
978
|
+
0 0.15cqw 0 rgb(255 255 255 / 0.18);
|
|
979
|
+
}
|
|
980
|
+
.fb-cover-stamp .fb-cover-subtitle {
|
|
981
|
+
margin-top: 2cqw;
|
|
982
|
+
font-size: 3.4cqw;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
.fb-cover-print {
|
|
986
|
+
position: absolute;
|
|
987
|
+
top: 11cqw;
|
|
988
|
+
left: 16cqw;
|
|
989
|
+
right: 16cqw;
|
|
990
|
+
height: 62cqw;
|
|
991
|
+
padding: 2.4cqw;
|
|
992
|
+
background: #f7f2e7;
|
|
993
|
+
box-shadow:
|
|
994
|
+
0 0.6cqw 1.2cqw rgb(0 0 0 / 0.35),
|
|
995
|
+
0 2cqw 4cqw -1.6cqw rgb(0 0 0 / 0.45);
|
|
996
|
+
transform: rotate(-2.5deg);
|
|
997
|
+
color: #2b2520;
|
|
998
|
+
font-size: 1.1cqw;
|
|
999
|
+
}
|
|
1000
|
+
.fb-cover-print-photo {
|
|
1001
|
+
position: relative;
|
|
1002
|
+
width: 100%;
|
|
1003
|
+
height: 100%;
|
|
1004
|
+
overflow: hidden;
|
|
1005
|
+
}
|
|
1006
|
+
.fb-cover-print .fb-print-frame-corner {
|
|
1007
|
+
z-index: 1;
|
|
1008
|
+
background: #1f1b18;
|
|
1009
|
+
}
|
|
1010
|
+
.fb-cover-label {
|
|
1011
|
+
position: absolute;
|
|
1012
|
+
left: 18cqw;
|
|
1013
|
+
right: 18cqw;
|
|
1014
|
+
top: 84cqw;
|
|
1015
|
+
padding: 4cqw 4cqw 4.5cqw;
|
|
1016
|
+
background: #f4eddc url('./textures/paper-fine.webp');
|
|
1017
|
+
background-size: 50cqw;
|
|
1018
|
+
box-shadow:
|
|
1019
|
+
0 0.3cqw 0.8cqw rgb(0 0 0 / 0.3),
|
|
1020
|
+
inset 0 0 0 1.2cqw #f4eddc,
|
|
1021
|
+
inset 0 0 0 1.4cqw rgb(60 45 30 / 0.5);
|
|
1022
|
+
color: #3a2f25;
|
|
1023
|
+
text-align: center;
|
|
1024
|
+
}
|
|
1025
|
+
.fb-cover-label.is-alone {
|
|
1026
|
+
top: 44cqw;
|
|
1027
|
+
}
|
|
1028
|
+
.fb-cover-label .fb-cover-title {
|
|
1029
|
+
margin-top: 1cqw;
|
|
1030
|
+
font-size: 6.4cqw;
|
|
1031
|
+
text-shadow: none;
|
|
1032
|
+
}
|
|
1033
|
+
.fb-cover-label .fb-kicker {
|
|
1034
|
+
font-size: 2.2cqw;
|
|
1035
|
+
}
|
|
1036
|
+
.fb-cover-label .fb-cover-subtitle {
|
|
1037
|
+
margin-top: 1.5cqw;
|
|
1038
|
+
font-size: 3cqw;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.fb-cover-rays {
|
|
1042
|
+
position: absolute;
|
|
1043
|
+
inset: 0;
|
|
1044
|
+
width: 100%;
|
|
1045
|
+
height: 100%;
|
|
1046
|
+
opacity: 0.9;
|
|
1047
|
+
}
|
|
1048
|
+
.fb-cover-stack.is-deco {
|
|
1049
|
+
inset: 17cqw 14cqw 10cqw;
|
|
1050
|
+
justify-content: flex-start;
|
|
1051
|
+
}
|
|
1052
|
+
.fb-cover-photo.is-arch {
|
|
1053
|
+
width: 56cqw;
|
|
1054
|
+
height: 62cqw;
|
|
1055
|
+
max-height: none;
|
|
1056
|
+
flex: none;
|
|
1057
|
+
margin: 4cqw 0 0;
|
|
1058
|
+
border: 0.5cqw solid currentColor;
|
|
1059
|
+
border-radius: 28cqw 28cqw 0 0;
|
|
1060
|
+
box-shadow:
|
|
1061
|
+
0 0 0 1.4cqw transparent,
|
|
1062
|
+
0 0 0 1.7cqw color-mix(in srgb, currentColor 60%, transparent),
|
|
1063
|
+
inset 0 0 3cqw rgb(0 0 0 / 0.45);
|
|
1064
|
+
}
|
|
1065
|
+
.fb-design-deco .fb-cover-title {
|
|
1066
|
+
margin-top: 7cqw;
|
|
1067
|
+
font-size: 6.6cqw;
|
|
1068
|
+
font-weight: 400;
|
|
1069
|
+
letter-spacing: 0.12em;
|
|
1070
|
+
text-transform: uppercase;
|
|
1071
|
+
}
|
|
1072
|
+
.fb-design-deco .fb-cover-subtitle {
|
|
1073
|
+
margin-top: 2.5cqw;
|
|
1074
|
+
font-size: 3.4cqw;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.fb-cover-art {
|
|
1078
|
+
position: absolute;
|
|
1079
|
+
inset: 0;
|
|
1080
|
+
}
|
|
1081
|
+
.fb-cover-tint {
|
|
1082
|
+
position: absolute;
|
|
1083
|
+
inset: 0;
|
|
1084
|
+
background: currentColor;
|
|
1085
|
+
mix-blend-mode: soft-light;
|
|
1086
|
+
opacity: 0.18;
|
|
1087
|
+
}
|
|
1088
|
+
.fb-design-image .fb-cover-finish {
|
|
1089
|
+
mix-blend-mode: overlay;
|
|
1090
|
+
opacity: 0.9;
|
|
1091
|
+
}
|
|
1092
|
+
.fb-cover-caption {
|
|
1093
|
+
position: absolute;
|
|
1094
|
+
left: 0;
|
|
1095
|
+
right: 0;
|
|
1096
|
+
bottom: 0;
|
|
1097
|
+
padding: 26cqw 10cqw 10cqw;
|
|
1098
|
+
background: linear-gradient(to top, rgb(0 0 0 / 0.65), rgb(0 0 0 / 0.25) 55%, transparent);
|
|
1099
|
+
color: #fff;
|
|
1100
|
+
text-align: center;
|
|
1101
|
+
}
|
|
1102
|
+
.fb-cover-caption.is-plain {
|
|
1103
|
+
top: 0;
|
|
1104
|
+
display: flex;
|
|
1105
|
+
flex-direction: column;
|
|
1106
|
+
justify-content: center;
|
|
1107
|
+
background: none;
|
|
1108
|
+
color: inherit;
|
|
1109
|
+
}
|
|
1110
|
+
.fb-cover-caption .fb-cover-title {
|
|
1111
|
+
margin-top: 2cqw;
|
|
1112
|
+
text-shadow: 0 0.3cqw 1.2cqw rgb(0 0 0 / 0.5);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
808
1115
|
.fb-cover-classic {
|
|
809
1116
|
background-color: #5a1d22;
|
|
810
1117
|
background-image:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toneflix/flipbook",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "An expressive flipbook for creating personalised and interactive reading and photo viewing experiences, for any web page, no framework needed.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://toneflix.github.io/flipbook/frameworks/vanilla",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dist"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@toneflix/flipbook-core": "^0.2.
|
|
49
|
+
"@toneflix/flipbook-core": "^0.2.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"tsdown": "^0.23.5",
|