UNPKG

vue-reader

Version:

An vue-reader for vue powered by EpubJS

2 lines (1 loc) 11 kB
import{defineComponent as e,getCurrentInstance as t,h as o,toRefs as n,ref as a,watch as r,onMounted as i,onBeforeUnmount as s,version as l,Transition as c,reactive as u,onUnmounted as p}from"vue-demi";import d from"epubjs";function b(e,t){void 0===t&&(t={});var o=t.insertAt;if(e&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css","top"===o&&n.firstChild?n.insertBefore(a,n.firstChild):n.appendChild(a),a.styleSheet?a.styleSheet.cssText=e:a.appendChild(document.createTextNode(e))}}b(".reader{inset:50px 50px 20px;position:absolute}.viewHolder{height:100%;position:relative;width:100%}#viewer{height:100%}");var f=e({name:"EpubView",model:{prop:"location",event:"update:location"},emits:{"update:location":e=>!0,select:(e,t)=>!0,keyup:e=>!0,keyPress:e=>!0},props:{url:{required:!0},location:{},tocChanged:{type:Function},getRendition:{type:Function},epubInitOptions:{type:Object,default:()=>({})},epubOptions:{type:Object,default:()=>({})}},setup(e,c){const{emit:u,slots:p,expose:b}=c,f=t(),g=o.bind(f),{url:v,location:h}=n(e),{tocChanged:x,getRendition:m,epubInitOptions:w,epubOptions:y}=e,k=a(null),A=a([]),B=a(!1);let E=null,C=null;const L=async()=>{E&&E.destroy(),v.value&&(E=d(v.value,w),E.loaded.navigation.then((({toc:e})=>{B.value=!0,A.value=e,x&&x(e),R()})))},R=()=>{const e=k.value||f?.refs?.viewer;C=E.renderTo(e,{width:"100%",height:"100%",...y}),T(),m&&m(C),"string"==typeof h?.value||"number"==typeof h?.value?C.display(h.value):A.value.length>0&&A?.value[0]?.href?C.display(A.value[0].href):C.display()},X=e=>{"next"===e?M():"prev"===e&&z()},T=()=>{C&&(C.on("rendered",((e,t)=>{var o,n;t?.iframe?.contentWindow.focus(),y?.flow?.includes("scrolled")||function(e,t){let o,n=0;e.addEventListener("wheel",(e=>{e.ignore||(e.ignore=!0,clearTimeout(o),n+=e.deltaY,o=setTimeout((()=>{if(Math.abs(n)>=750){let e=Math.sign(n)>0?"next":"prev";t(e),n=0}n=0}),50))}))}(t.document,X),function(e,t){let o,n,a;e.addEventListener("touchstart",(e=>{e.ignore||(e.ignore=!0,o=e.changedTouches[0].pageX,n=e.changedTouches[0].pageY,a=Date.now())}),!1),e.addEventListener("touchend",(r=>{if(r.ignore)return;r.ignore=!0;const i=r.changedTouches[0].pageX-o,s=r.changedTouches[0].pageY-n;Date.now()-a<=500&&(Math.abs(i)>=50&&Math.abs(s)<=200?t(i<0?"next":"prev"):Math.abs(s)>=50&&Math.abs(i)<=200?t(s<0?"up":"down"):(e?.defaultView?.getSelection()?.removeAllRanges(),e.dispatchEvent(new MouseEvent("click",{clientX:o,clientY:n})),r.preventDefault()))}),!1)}(t.document,X),o=t.document,n=X,o.addEventListener("keyup",(e=>{"ArrowUp"===e.key||"ArrowRight"===e.key?n("next"):"ArrowDown"!==e.key&&"ArrowLeft"!==e.key||n("prev")}),!1)})),C.on("locationChanged",S),C.on("displayError",(e=>console.error("error rendering book",e))),C.on("selected",((e,t)=>u("select",e,t))),C.on("keyup",(e=>u("keyPress",e))))},S=e=>{const t=e.start;h?.value!==t&&u("update:location",t)};r(v,(()=>{L()}));const M=()=>{C?.next()},z=()=>{C?.prev()},P=e=>{"string"==typeof e&&C.display(e),"number"==typeof e&&C.display(e)};if(i((()=>{L()})),s((()=>{E?.destroy()})),b)b({nextPage:M,prevPage:z,setLocation:P});else{(e=>{if(!f)throw new Error("expose should be called in setup().");const t=Object.keys(e);t.forEach((t=>{f.proxy[t]=e[t]})),s((()=>{t.forEach((e=>{f.proxy[e]=void 0}))}))})({nextPage:M,prevPage:z,setLocation:P})}return()=>g("div",{class:"reader"},[g("div",{class:"viewHolder"},[g("div",{ref:parseFloat(l)>=2.7?k:"viewer",class:"view",id:"viewer",attrs:{id:"viewer"},style:{display:B.value?null:"none"}}),!B.value&&g("div",p.loadingView?.())])])}});b('.container{height:100%;overflow:hidden;position:relative}.containerExpanded{-webkit-transform:translateX(256px);transform:translateX(256px)}.readerArea{height:100%;position:relative;-webkit-transition:all .3s ease;transition:all .3s ease;width:100%;z-index:1}.container .titleArea{color:#999;left:50px;overflow:hidden;position:absolute;right:50px;text-align:center;text-overflow:ellipsis;top:20px;white-space:nowrap}.tocBackground{left:256px;right:0;z-index:1}.tocArea,.tocBackground{bottom:0;position:absolute;top:0}.tocArea{-webkit-overflow-scrolling:touch;background:#f2f2f2;left:0;overflow-y:auto;padding:10px 0;width:256px;z-index:0}.tocArea::-webkit-scrollbar{height:5px;width:5px}.tocArea::-webkit-scrollbar-thumb:vertical{background-color:rgba(0,0,0,.1);border-radius:.5rem;height:5px}.tocArea .tocAreaButton{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;border-bottom:1px solid #ddd;-webkit-box-sizing:border-box;box-sizing:border-box;color:#aaa;cursor:pointer;display:block;font-family:sans-serif;font-size:.9em;outline:none;padding:.9em 1em;position:relative;text-align:left;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.tocArea .tocAreaButton:hover{background:rgba(0,0,0,.05)}.tocArea .tocAreaButton:active{background:rgba(0,0,0,.1)}.tocArea .active{border-bottom:2px solid #1565c0;color:#1565c0}.tocArea .tocAreaButton .expansion{background-color:#a2a5b4;cursor:pointer;right:12px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);width:10px}.tocArea .tocAreaButton .expansion,.tocArea .tocAreaButton .expansion:after,.tocArea .tocAreaButton .expansion:before{position:absolute;-webkit-transition:top .3s ease-in-out,-webkit-transform .3s ease-in-out;transition:top .3s ease-in-out,-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out,top .3s ease-in-out;transition:transform .3s ease-in-out,top .3s ease-in-out,-webkit-transform .3s ease-in-out}.tocArea .tocAreaButton .expansion:after,.tocArea .tocAreaButton .expansion:before{background-color:currentcolor;border-radius:2px;content:"";height:2px;width:6px}.tocArea .tocAreaButton .expansion:before{-webkit-transform:rotate(-45deg) translateX(2.5px);transform:rotate(-45deg) translateX(2.5px)}.tocArea .tocAreaButton .expansion:after{-webkit-transform:rotate(45deg) translateX(-2.5px);transform:rotate(45deg) translateX(-2.5px)}.tocArea .tocAreaButton .open:before{-webkit-transform:rotate(45deg) translateX(2.5px);transform:rotate(45deg) translateX(2.5px)}.tocArea .tocAreaButton .open:after{-webkit-transform:rotate(-45deg) translateX(-2.5px);transform:rotate(-45deg) translateX(-2.5px)}.tocButton{background:none;border:none;border-radius:2px;cursor:pointer;height:32px;left:10px;outline:none;position:absolute;top:10px;width:32px}.tocButtonBar{background:#ccc;height:2px;left:50%;margin:-1px -30%;position:absolute;top:50%;-webkit-transition:all .5s ease;transition:all .5s ease;width:60%}.tocButtonExpanded{background:#f2f2f2}.arrow{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;color:#e2e2e2;cursor:pointer;font-family:arial,sans-serif;font-size:64px;font-weight:400;margin-top:-32px;outline:none;padding:0 10px;position:absolute;top:50%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.arrow:hover{color:#777}.arrow:disabled{color:#e2e2e2;cursor:not-allowed}.prev{left:1px}.next{right:1px}.loadingView{color:#ccc;left:10%;margin-top:-.5em;position:absolute;right:10%;text-align:center;top:50%}');const g=e({name:"TocComponent",props:{toc:{type:Array,default:()=>[]},current:{type:[String,Number],default:""},setLocation:{type:Function,required:!0},isSubmenu:{type:Boolean,default:!1,required:!1}},setup(e){const a=t(),r=o.bind(a),{setLocation:i,isSubmenu:s}=e,{toc:l,current:u}=n(e);return()=>r("div",null,l.value.map(((e,t)=>r("div",{key:t},[r("button",{class:["tocAreaButton",e.href===u.value?"active":""],on:{click:()=>{e.subitems.length>0?(e.expansion=!e.expansion,i(e.href,!1)):i(e.href)}},onClick:()=>{e.subitems.length>0?(e.expansion=!e.expansion,i(e.href,!1)):i(e.href)}},[s?" ".repeat(4)+e.label:e.label,e.subitems&&e.subitems.length>0&&r("div",{class:(e.expansion?"open":"")+" expansion"})]),e.subitems&&e.subitems.length>0&&r(c,{name:"collapse-transition"},{default:()=>r("div",{style:{display:e.expansion?void 0:"none"}},[r(g,{toc:e.subitems,current:u.value,setLocation:i,isSubmenu:!0,attrs:{toc:l.value,current:u.value,setLocation:i,isSubmenu:!0}})])})]))))}});var v=e({name:"VueReader",emits:{progress:e=>!0},props:{url:{required:!0},title:String,showToc:{type:Boolean,default:!0},tocChanged:{type:Function},getRendition:{type:Function},backgroundColor:{type:String,default:"#fff"}},setup(e,r){const{emit:i,slots:c,expose:d,attrs:b}=r,v=t(),h=o.bind(v),x=a(null),m=a(null),w=a(""),{tocChanged:y,getRendition:k}=e,{title:A,url:B,showToc:E,backgroundColor:C}=n(e),L=u({toc:[],expandedToc:!1}),{toc:R,expandedToc:X}=n(L),T=a(""),S=()=>{X.value=!X.value},M=e=>{R.value=e.map((e=>({...e,expansion:!1}))),y&&y(e)},z=e=>{k&&k(e),e.on("relocated",(e=>{m.value=e}));const t=e.book;t.ready.then((()=>{const e=t.package.metadata;T.value=e.title})),e.hooks.content.register((({document:e})=>{const t=Array.from(e.querySelectorAll("a"));if(t.length){const e=Math.floor(t.length/2);t.slice(0,e).forEach((o=>{if(o.href){const n=o.href.split("#")[1],a=t.slice(e).find((e=>e.id===n));a&&a.parentNode&&(o.title=a.parentNode.textContent)}}))}}))},P=(e,t=!0)=>{const o=x.value||v?.refs.epubRef;o?.setLocation(e),w.value=e,X.value=!t},V=XMLHttpRequest.prototype.open,q=e=>{i("progress",Math.floor(e.loaded/e.total*100))};XMLHttpRequest.prototype.open=function(e,t){t===B.value&&this.addEventListener("progress",q),V.apply(this,arguments)},p((()=>{XMLHttpRequest.prototype.open=V}));const O=()=>{const e=x.value||v?.refs.epubRef;e?.nextPage()},F=()=>{const e=x.value||v?.refs.epubRef;e?.prevPage()};if(d)d({setLocation:P,next:O,pre:F});else{(e=>{if(!v)throw new Error("expose should be called in setup().");const t=Object.keys(e);t.forEach((t=>{v.proxy[t]=e[t]})),s((()=>{t.forEach((e=>{v.proxy[e]=void 0}))}))})({setLocation:P,next:O,pre:F})}return()=>h("div",{class:"container"},[h("div",{class:["readerArea",{containerExpanded:X.value}],style:{backgroundColor:C.value}},[E.value&&h("button",{class:["tocButton",{tocButtonExpanded:X.value}],type:"button",on:{click:S},onClick:S},[h("span",{class:"tocButtonBar",style:"top: 35%"}),h("span",{class:"tocButtonBar",style:"top: 66%"})]),h("div",{class:"titleArea",title:T.value},c.title?c.title?.():A.value||T.value),h(f,{ref:parseFloat(l)<2.7?"epubRef":x,url:B.value,tocChanged:M,getRendition:z,...b,attrs:{url:B.value,tocChanged:M,getRendition:z,...b},on:{...r.listeners}},{loadingView:()=>h("div",{class:"loadingView"},c.loadingView?c.loadingView?.():"Loading...")}),h("button",{class:"arrow pre",on:{click:F},onClick:F,domProps:{disabled:m.value?.atStart},disabled:m.value?.atStart},"‹"),h("button",{class:"arrow next",on:{click:O},onClick:O,domProps:{disabled:m.value?.atEnd},disabled:m.value?.atEnd},"›")]),E.value&&h("div",[h("div",{class:"tocArea"},[h(g,{toc:R.value,current:w.value,setLocation:P,attrs:{toc:R.value,current:w.value,setLocation:P}})]),X.value&&h("div",{class:["tocBackground"],onClick:S,on:{click:S}})])])}});export{f as EpubView,v as VueReader,v as default};