@toneflix/flipbook 0.3.4 → 0.3.5
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 +1 -1
- package/dist/index.cjs +8 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +8 -2
- package/package.json +2 -2
package/dist/flipbook.iife.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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`,fullscreenPrompt:`Tap to open 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`},ee={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`]},E={x:50,y:124},te={viewBox:`0 0 100 133.33`,strokes:[...Array.from({length:17},(e,t)=>{let n=12+t/16*76,r=(E.y-88)/(E.y-16);return{d:`M${(E.x+(n-E.x)*r).toFixed(2)} 88L${n.toFixed(2)} 16`,width:.25,opacity:.3}}),{d:`M5 5H95V128.33H5Z`,width:.5},{d:`M11 8H89L92 11V122.33L89 125.33H11L8 122.33V11Z`,width:.35}],fills:[`M50 8.5L52 11L50 13.5L48 11Z`,`M50 119.83L52 122.33L50 124.83L48 122.33Z`]},D={min:1,max:4},O=(e,t,n)=>Math.min(n,Math.max(t,e)),k=(e,t)=>Math.round(e*10**t)/10**t;var A=class e{static CENTRE=new e;x;y;zoom;constructor(e=50,t=50,n=1){this.x=O(Number.isFinite(e)?e:50,0,100),this.y=O(Number.isFinite(t)?t:50,0,100),this.zoom=O(Number.isFinite(n)?n:1,D.min,D.max)}static of(t){return t?new e(t.x,t.y,t.zoom):e.CENTRE}get isCentred(){return this.x===50&&this.y===50&&this.zoom===1}rect(e,t){let n=t?.width&&t.height?t.width/t.height:e.width/(e.height||1),r=Math.max(e.width/n,e.height)*this.zoom,i=r*n;return{left:(e.width-i)*this.x/100,top:(e.height-r)*this.y/100,width:i,height:r}}pan(t,n,r,i){let{width:a,height:o}=this.rect(r,i),s=a-r.width,c=o-r.height,l=s>0?this.x-t/s*100:this.x,u=c>0?this.y-n/c*100:this.y;return new e(l,u,this.zoom)}zoomTo(t){return new e(this.x,this.y,t)}movable(e,t){let{width:n,height:r}=this.rect(e,t);return{x:n-e.width>.5,y:r-e.height>.5}}get css(){let e=`${this.x}% ${this.y}%`;return{objectPosition:e,transform:this.zoom===1?``:`scale(${this.zoom})`,transformOrigin:e}}equals(t){let n=e.of(t);return this.x===n.x&&this.y===n.y&&this.zoom===n.zoom}toJSON(){return{x:k(this.x,1),y:k(this.y,1),zoom:k(this.zoom,2)}}};function j(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 ne(r,n),r}function ne(e,t){for(let n of t)n&&e.append(n)}function M(e){let t=document.createElement(`template`);return t.innerHTML=e.trim(),t.content.firstElementChild}async function N(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 P(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 re=[`tl`,`tr`,`bl`,`br`];function F(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 ie=()=>re.map(e=>M(F(ee,`fb-fleuron is-${e}`))),I=(e,t,n)=>e.cover&&j(`div`,{class:t},n?W(e.cover,`fb-photo`):j(`div`,{class:`fb-placeholder`})),L=e=>j(`h1`,{class:`fb-serif fb-cover-title`},e.title),R=e=>e.kicker&&j(`p`,{class:`fb-kicker`},e.kicker),z=e=>e.subtitle&&j(`p`,{class:`fb-serif fb-italic fb-cover-subtitle`},e.subtitle);function ae(e,t){let n=y(e);switch(e.coverDesign??`classic`){case`gilt`:return[j(`div`,{class:`fb-cover-frame`}),...ie(),j(`div`,{class:`fb-cover-stack`},n&&R(e),n&&L(e),I(e,`fb-cover-photo is-oval`,t),n&&z(e))];case`window`:return[I(e,`fb-cover-window`,t)||j(`div`,{class:`fb-cover-window is-empty`},U()),n&&j(`div`,{class:`fb-cover-stamp`},R(e),L(e),z(e))];case`label`:return[e.cover&&j(`div`,{class:`fb-cover-print`},I(e,`fb-cover-print-photo`,t),...re.map(e=>j(`span`,{class:`fb-print-frame-corner is-${e}`,"aria-hidden":`true`}))),n&&j(`div`,{class:`fb-cover-label ${e.cover?``:`is-alone`}`},R(e),L(e),z(e))];case`deco`:return[M(F(te,`fb-cover-rays`)),j(`div`,{class:`fb-cover-stack is-deco`},n&&R(e),I(e,`fb-cover-photo is-arch`,t),n&&L(e),n&&z(e))];case`image`:return[e.cover&&j(`div`,{class:`fb-cover-art`},t?W(e.cover,`fb-photo`):j(`div`,{class:`fb-placeholder`})),e.cover&&j(`div`,{class:`fb-cover-tint`}),n&&j(`div`,{class:`fb-cover-caption ${e.cover?``:`is-plain`}`},R(e),L(e),z(e))];default:return[j(`div`,{class:`fb-cover-panel`},n&&R(e),n&&L(e),I(e,`fb-cover-photo`,t)||n&&z(e))]}}let B=(e,t,...n)=>j(`div`,{class:`fb-cover fb-cover-${e.theme??`classic`} fb-design-${e.coverDesign??`classic`}`},...n,j(`div`,{class:`fb-hinge is-${t}`}),j(`div`,{class:`fb-cover-finish`,"aria-hidden":`true`}));function oe(e,t=!0){return B(e,`left`,...ae(e,t))}function se(e){let t=e.coverDesign===`gilt`;return B(e,`right`,t&&j(`div`,{class:`fb-cover-frame`}),...t?ie():[],j(`div`,{class:`fb-imprint`},U(),e.imprint&&j(`p`,{class:`fb-kicker`,style:{marginTop:`2cqw`,fontSize:`2.4cqw`,opacity:`0.6`}},e.imprint)))}let V={pan:2,zoom:.1};var ce=class{el;options;crop;pointers=/* @__PURE__ */ new Map;gesture=null;abort=new AbortController;settle;constructor(e,t){this.el=e,this.options=t,this.crop=A.of(t.position);let n=this.abort.signal;e.classList.add(`fb-positioning`),e.tabIndex=0,e.setAttribute(`aria-roledescription`,`photo position`),e.setAttribute(`aria-keyshortcuts`,`ArrowLeft ArrowRight ArrowUp ArrowDown + -`),e.addEventListener(`pointerdown`,e=>this.down(e),{signal:n}),e.addEventListener(`pointermove`,e=>this.move(e),{signal:n}),e.addEventListener(`pointerup`,e=>this.up(e),{signal:n}),e.addEventListener(`pointercancel`,e=>this.up(e),{signal:n}),e.addEventListener(`wheel`,e=>this.wheel(e),{signal:n,passive:!1}),e.addEventListener(`keydown`,e=>this.key(e),{signal:n}),e.addEventListener(`dragstart`,e=>e.preventDefault(),{signal:n})}get position(){return this.crop.toJSON()}set position(e){this.crop=A.of(e),this.paint()}destroy(){clearTimeout(this.settle),this.abort.abort(),this.el.classList.remove(`fb-positioning`,`is-moving`),this.el.removeAttribute(`tabindex`),this.el.removeAttribute(`aria-roledescription`),this.el.removeAttribute(`aria-keyshortcuts`)}get image(){return this.el.querySelector(`img`)}get box(){let e=this.image;return{width:e?.clientWidth??0,height:e?.clientHeight??0}}get natural(){let e=this.image;return e?.naturalWidth?{width:e.naturalWidth,height:e.naturalHeight}:null}paint(){let e=this.image;e&&Object.assign(e.style,this.crop.css)}commit(){this.options.onChange(this.crop.toJSON())}spread(){let[e,t]=[...this.pointers.values()];return e&&t?Math.hypot(e.x-t.x,e.y-t.y):0}down(e){e.button===0&&this.image&&(e.stopPropagation(),this.el.setPointerCapture(e.pointerId),this.el.classList.add(`is-moving`),this.pointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),this.gesture={crop:this.crop,spread:this.spread()})}move(e){let t=this.pointers.get(e.pointerId);if(t&&this.gesture){if(e.stopPropagation(),this.pointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),this.pointers.size>1)this.gesture.spread&&(this.crop=this.crop.zoomTo(this.gesture.crop.zoom*this.spread()/this.gesture.spread));else{let n=this.el.getBoundingClientRect().width/(this.el.offsetWidth||1);this.crop=this.crop.pan((e.clientX-t.x)/n,(e.clientY-t.y)/n,this.box,this.natural)}this.paint()}}up(e){this.pointers.delete(e.pointerId)&&(e.stopPropagation(),this.gesture=this.pointers.size?{crop:this.crop,spread:this.spread()}:null,this.pointers.size||(this.el.classList.remove(`is-moving`),this.commit()))}wheel(e){e.preventDefault(),this.crop=this.crop.zoomTo(this.crop.zoom*Math.exp(-e.deltaY/500)),this.paint(),clearTimeout(this.settle),this.settle=setTimeout(()=>this.commit(),250)}key(e){let t={ArrowLeft:()=>new A(this.crop.x+V.pan,this.crop.y,this.crop.zoom),ArrowRight:()=>new A(this.crop.x-V.pan,this.crop.y,this.crop.zoom),ArrowUp:()=>new A(this.crop.x,this.crop.y+V.pan,this.crop.zoom),ArrowDown:()=>new A(this.crop.x,this.crop.y-V.pan,this.crop.zoom),"+":()=>this.crop.zoomTo(this.crop.zoom+V.zoom),"=":()=>this.crop.zoomTo(this.crop.zoom+V.zoom),"-":()=>this.crop.zoomTo(this.crop.zoom-V.zoom),0:()=>A.CENTRE}[e.key]?.();t&&(e.preventDefault(),e.stopPropagation(),this.crop=t,this.paint(),this.commit())}};let le=[14,24,34,44,54,64,74].map((e,t)=>({x:e,angle:t%2?38:-38,length:26-t*2})),H=e=>M(`<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`,fullscreenPrompt:`Tap to open 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`},ee={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`]},E={x:50,y:124},te={viewBox:`0 0 100 133.33`,strokes:[...Array.from({length:17},(e,t)=>{let n=12+t/16*76,r=(E.y-88)/(E.y-16);return{d:`M${(E.x+(n-E.x)*r).toFixed(2)} 88L${n.toFixed(2)} 16`,width:.25,opacity:.3}}),{d:`M5 5H95V128.33H5Z`,width:.5},{d:`M11 8H89L92 11V122.33L89 125.33H11L8 122.33V11Z`,width:.35}],fills:[`M50 8.5L52 11L50 13.5L48 11Z`,`M50 119.83L52 122.33L50 124.83L48 122.33Z`]},D={min:1,max:4},O=(e,t,n)=>Math.min(n,Math.max(t,e)),k=(e,t)=>Math.round(e*10**t)/10**t;var A=class e{static CENTRE=new e;x;y;zoom;constructor(e=50,t=50,n=1){this.x=O(Number.isFinite(e)?e:50,0,100),this.y=O(Number.isFinite(t)?t:50,0,100),this.zoom=O(Number.isFinite(n)?n:1,D.min,D.max)}static of(t){return t?new e(t.x,t.y,t.zoom):e.CENTRE}get isCentred(){return this.x===50&&this.y===50&&this.zoom===1}rect(e,t){let n=t?.width&&t.height?t.width/t.height:e.width/(e.height||1),r=Math.max(e.width/n,e.height)*this.zoom,i=r*n;return{left:(e.width-i)*this.x/100,top:(e.height-r)*this.y/100,width:i,height:r}}pan(t,n,r,i){let{width:a,height:o}=this.rect(r,i),s=a-r.width,c=o-r.height,l=s>0?this.x-t/s*100:this.x,u=c>0?this.y-n/c*100:this.y;return new e(l,u,this.zoom)}zoomTo(t){return new e(this.x,this.y,t)}movable(e,t){let{width:n,height:r}=this.rect(e,t);return{x:n-e.width>.5,y:r-e.height>.5}}get css(){let e=`${this.x}% ${this.y}%`;return{objectPosition:e,transform:this.zoom===1?``:`scale(${this.zoom})`,transformOrigin:e}}equals(t){let n=e.of(t);return this.x===n.x&&this.y===n.y&&this.zoom===n.zoom}toJSON(){return{x:k(this.x,1),y:k(this.y,1),zoom:k(this.zoom,2)}}};function j(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 ne(r,n),r}function ne(e,t){for(let n of t)n&&e.append(n)}function M(e){let t=document.createElement(`template`);return t.innerHTML=e.trim(),t.content.firstElementChild}async function N(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 P(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 re=[`tl`,`tr`,`bl`,`br`];function F(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 ie=()=>re.map(e=>M(F(ee,`fb-fleuron is-${e}`))),I=(e,t,n)=>e.cover&&j(`div`,{class:t},n?W(e.cover,`fb-photo`):j(`div`,{class:`fb-placeholder`})),L=e=>j(`h1`,{class:`fb-serif fb-cover-title`},e.title),R=e=>e.kicker&&j(`p`,{class:`fb-kicker`},e.kicker),z=e=>e.subtitle&&j(`p`,{class:`fb-serif fb-italic fb-cover-subtitle`},e.subtitle);function ae(e,t){let n=y(e);switch(e.coverDesign??`classic`){case`gilt`:return[j(`div`,{class:`fb-cover-frame`}),...ie(),j(`div`,{class:`fb-cover-stack`},n&&R(e),n&&L(e),I(e,`fb-cover-photo is-oval`,t),n&&z(e))];case`window`:return[I(e,`fb-cover-window`,t)||j(`div`,{class:`fb-cover-window is-empty`},U()),n&&j(`div`,{class:`fb-cover-stamp`},R(e),L(e),z(e))];case`label`:return[e.cover&&j(`div`,{class:`fb-cover-print`},I(e,`fb-cover-print-photo`,t),...re.map(e=>j(`span`,{class:`fb-print-frame-corner is-${e}`,"aria-hidden":`true`}))),n&&j(`div`,{class:`fb-cover-label ${e.cover?``:`is-alone`}`},R(e),L(e),z(e))];case`deco`:return[M(F(te,`fb-cover-rays`)),j(`div`,{class:`fb-cover-stack is-deco`},n&&R(e),I(e,`fb-cover-photo is-arch`,t),n&&L(e),n&&z(e))];case`image`:return[e.cover&&j(`div`,{class:`fb-cover-art`},t?W(e.cover,`fb-photo`):j(`div`,{class:`fb-placeholder`})),e.cover&&j(`div`,{class:`fb-cover-tint`}),n&&j(`div`,{class:`fb-cover-caption ${e.cover?``:`is-plain`}`},R(e),L(e),z(e))];default:return[j(`div`,{class:`fb-cover-panel`},n&&R(e),n&&L(e),I(e,`fb-cover-photo`,t)||n&&z(e))]}}let B=(e,t,...n)=>j(`div`,{class:`fb-cover fb-cover-${e.theme??`classic`} fb-design-${e.coverDesign??`classic`}`},...n,j(`div`,{class:`fb-hinge is-${t}`}),j(`div`,{class:`fb-cover-finish`,"aria-hidden":`true`}));function oe(e,t=!0){return B(e,`left`,...ae(e,t))}function se(e){let t=e.coverDesign===`gilt`;return B(e,`right`,t&&j(`div`,{class:`fb-cover-frame`}),...t?ie():[],j(`div`,{class:`fb-imprint`},U(),e.brand&&j(`p`,{class:`fb-kicker`,style:{marginTop:`2cqw`,fontSize:`3cqw`}},e.brand),e.imprint&&j(`p`,{class:`fb-kicker`,style:{marginTop:`2cqw`,fontSize:`2.4cqw`,opacity:`0.6`}},e.imprint)))}let V={pan:2,zoom:.1};var ce=class{el;options;crop;pointers=/* @__PURE__ */ new Map;gesture=null;abort=new AbortController;settle;constructor(e,t){this.el=e,this.options=t,this.crop=A.of(t.position);let n=this.abort.signal;e.classList.add(`fb-positioning`),e.tabIndex=0,e.setAttribute(`aria-roledescription`,`photo position`),e.setAttribute(`aria-keyshortcuts`,`ArrowLeft ArrowRight ArrowUp ArrowDown + -`),e.addEventListener(`pointerdown`,e=>this.down(e),{signal:n}),e.addEventListener(`pointermove`,e=>this.move(e),{signal:n}),e.addEventListener(`pointerup`,e=>this.up(e),{signal:n}),e.addEventListener(`pointercancel`,e=>this.up(e),{signal:n}),e.addEventListener(`wheel`,e=>this.wheel(e),{signal:n,passive:!1}),e.addEventListener(`keydown`,e=>this.key(e),{signal:n}),e.addEventListener(`dragstart`,e=>e.preventDefault(),{signal:n})}get position(){return this.crop.toJSON()}set position(e){this.crop=A.of(e),this.paint()}destroy(){clearTimeout(this.settle),this.abort.abort(),this.el.classList.remove(`fb-positioning`,`is-moving`),this.el.removeAttribute(`tabindex`),this.el.removeAttribute(`aria-roledescription`),this.el.removeAttribute(`aria-keyshortcuts`)}get image(){return this.el.querySelector(`img`)}get box(){let e=this.image;return{width:e?.clientWidth??0,height:e?.clientHeight??0}}get natural(){let e=this.image;return e?.naturalWidth?{width:e.naturalWidth,height:e.naturalHeight}:null}paint(){let e=this.image;e&&Object.assign(e.style,this.crop.css)}commit(){this.options.onChange(this.crop.toJSON())}spread(){let[e,t]=[...this.pointers.values()];return e&&t?Math.hypot(e.x-t.x,e.y-t.y):0}down(e){e.button===0&&this.image&&(e.stopPropagation(),this.el.setPointerCapture(e.pointerId),this.el.classList.add(`is-moving`),this.pointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),this.gesture={crop:this.crop,spread:this.spread()})}move(e){let t=this.pointers.get(e.pointerId);if(t&&this.gesture){if(e.stopPropagation(),this.pointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),this.pointers.size>1)this.gesture.spread&&(this.crop=this.crop.zoomTo(this.gesture.crop.zoom*this.spread()/this.gesture.spread));else{let n=this.el.getBoundingClientRect().width/(this.el.offsetWidth||1);this.crop=this.crop.pan((e.clientX-t.x)/n,(e.clientY-t.y)/n,this.box,this.natural)}this.paint()}}up(e){this.pointers.delete(e.pointerId)&&(e.stopPropagation(),this.gesture=this.pointers.size?{crop:this.crop,spread:this.spread()}:null,this.pointers.size||(this.el.classList.remove(`is-moving`),this.commit()))}wheel(e){e.preventDefault(),this.crop=this.crop.zoomTo(this.crop.zoom*Math.exp(-e.deltaY/500)),this.paint(),clearTimeout(this.settle),this.settle=setTimeout(()=>this.commit(),250)}key(e){let t={ArrowLeft:()=>new A(this.crop.x+V.pan,this.crop.y,this.crop.zoom),ArrowRight:()=>new A(this.crop.x-V.pan,this.crop.y,this.crop.zoom),ArrowUp:()=>new A(this.crop.x,this.crop.y+V.pan,this.crop.zoom),ArrowDown:()=>new A(this.crop.x,this.crop.y-V.pan,this.crop.zoom),"+":()=>this.crop.zoomTo(this.crop.zoom+V.zoom),"=":()=>this.crop.zoomTo(this.crop.zoom+V.zoom),"-":()=>this.crop.zoomTo(this.crop.zoom-V.zoom),0:()=>A.CENTRE}[e.key]?.();t&&(e.preventDefault(),e.stopPropagation(),this.crop=t,this.paint(),this.commit())}};let le=[14,24,34,44,54,64,74].map((e,t)=>({x:e,angle:t%2?38:-38,length:26-t*2})),H=e=>M(`<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
3
|
${le.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
4
|
</svg>`),U=()=>M(`<svg viewBox="0 0 40 40" class="fb-ornament" aria-hidden="true">
|
package/dist/index.cjs
CHANGED
|
@@ -103,10 +103,16 @@ const shell = (book, hinge, ...children) => h("div", { class: `fb-cover fb-cover
|
|
|
103
103
|
function renderCover(book, showImages = true) {
|
|
104
104
|
return shell(book, "left", ...design(book, showImages));
|
|
105
105
|
}
|
|
106
|
-
/** The back cover: the same board, with the imprint. */
|
|
106
|
+
/** The back cover: the same board, with the brand and imprint. */
|
|
107
107
|
function renderBackCover(book) {
|
|
108
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.
|
|
109
|
+
return shell(book, "right", gilt && h("div", { class: "fb-cover-frame" }), ...gilt ? fleurons() : [], h("div", { class: "fb-imprint" }, ornament(), book.brand && h("p", {
|
|
110
|
+
class: "fb-kicker",
|
|
111
|
+
style: {
|
|
112
|
+
marginTop: "2cqw",
|
|
113
|
+
fontSize: "3cqw"
|
|
114
|
+
}
|
|
115
|
+
}, book.brand), book.imprint && h("p", {
|
|
110
116
|
class: "fb-kicker",
|
|
111
117
|
style: {
|
|
112
118
|
marginTop: "2cqw",
|
package/dist/index.d.cts
CHANGED
|
@@ -170,7 +170,7 @@ export declare class PhotoPositioner {
|
|
|
170
170
|
export declare function coverArtMarkup(art: CoverArt, className: string): string;
|
|
171
171
|
/** The front cover, laid out by the book's `coverDesign`. */
|
|
172
172
|
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
173
|
-
/** The back cover: the same board, with the imprint. */
|
|
173
|
+
/** The back cover: the same board, with the brand and imprint. */
|
|
174
174
|
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
175
175
|
/**
|
|
176
176
|
* A soft paper swish made from filtered noise, so no audio file is needed. Browsers only allow
|
package/dist/index.d.mts
CHANGED
|
@@ -170,7 +170,7 @@ export declare class PhotoPositioner {
|
|
|
170
170
|
export declare function coverArtMarkup(art: CoverArt, className: string): string;
|
|
171
171
|
/** The front cover, laid out by the book's `coverDesign`. */
|
|
172
172
|
export declare function renderCover(book: FlipbookBook, showImages?: boolean): HTMLDivElement;
|
|
173
|
-
/** The back cover: the same board, with the imprint. */
|
|
173
|
+
/** The back cover: the same board, with the brand and imprint. */
|
|
174
174
|
export declare function renderBackCover(book: FlipbookBook): HTMLDivElement;
|
|
175
175
|
/**
|
|
176
176
|
* A soft paper swish made from filtered noise, so no audio file is needed. Browsers only allow
|
package/dist/index.mjs
CHANGED
|
@@ -103,10 +103,16 @@ const shell = (book, hinge, ...children) => h("div", { class: `fb-cover fb-cover
|
|
|
103
103
|
function renderCover(book, showImages = true) {
|
|
104
104
|
return shell(book, "left", ...design(book, showImages));
|
|
105
105
|
}
|
|
106
|
-
/** The back cover: the same board, with the imprint. */
|
|
106
|
+
/** The back cover: the same board, with the brand and imprint. */
|
|
107
107
|
function renderBackCover(book) {
|
|
108
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.
|
|
109
|
+
return shell(book, "right", gilt && h("div", { class: "fb-cover-frame" }), ...gilt ? fleurons() : [], h("div", { class: "fb-imprint" }, ornament(), book.brand && h("p", {
|
|
110
|
+
class: "fb-kicker",
|
|
111
|
+
style: {
|
|
112
|
+
marginTop: "2cqw",
|
|
113
|
+
fontSize: "3cqw"
|
|
114
|
+
}
|
|
115
|
+
}, book.brand), book.imprint && h("p", {
|
|
110
116
|
class: "fb-kicker",
|
|
111
117
|
style: {
|
|
112
118
|
marginTop: "2cqw",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toneflix/flipbook",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
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.3.
|
|
49
|
+
"@toneflix/flipbook-core": "^0.3.5"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"tsdown": "^0.23.5",
|