vue-directional-carousel
Version:
This is a Vue 3 component that allows you to set the direction of image movement not only vertically and horizontally but also in different directions (left, right, up, down).
2 lines (1 loc) • 13.9 kB
JavaScript
(function(A,h){typeof exports=="object"&&typeof module<"u"?module.exports=h(require("vue")):typeof define=="function"&&define.amd?define(["vue"],h):(A=typeof globalThis<"u"?globalThis:A||self,A.VueDirectionalCarousel=h(A.Vue))})(this,function(A){"use strict";const h=e=>{var o;const l=[];(o=e.items)!=null&&o.length||l.push({prop:"items",message:"At least one item is required"}),e.interval!=null&&e.interval<0&&l.push({prop:"interval",message:"Interval must be a non-negative number"}),e.duration!=null&&e.duration<=0&&l.push({prop:"duration",message:"Duration must be greater than 0"});const n=/^(\d+(\.\d+)?)(px|%|rem|em|vh|vw)$/;return e.width&&!n.test(e.width)&&l.push({prop:"width",message:"Width must be a valid CSS dimension (e.g., 100%, 200px)"}),e.height&&!n.test(e.height)&&l.push({prop:"height",message:"Height must be a valid CSS dimension (e.g., 300px, 50vh)"}),l},X={style:{padding:"0px 4px 0px 4px"}},P=["onClick","aria-label","aria-current"],H=A.defineComponent({__name:"DotButtons",props:{currentIndex:{default:0},itemCount:{default:0},showDots:{type:Boolean,default:!1}},emits:["click-dot-button"],setup(e,{emit:l}){const n=l,o=e,u=A.ref({display:"flex",alignItems:"center",justifyContent:"center",flexWrap:"wrap"}),i=c=>{n("click-dot-button",c-1)},s=A.computed(()=>new Array(o.itemCount).fill({border:"none",borderRadius:"50%",backgroundColor:"gray",cursor:"pointer"}).map((c,t)=>{const a=t===(o.itemCount>o.currentIndex?o.currentIndex:0);return{...c,opacity:a?"1":"0.5",height:a?"8px":"6px",paddingInline:a?"4px":"3px"}}));return(c,t)=>(A.openBlock(),A.createElementBlock("div",{style:A.normalizeStyle(u.value)},[(A.openBlock(!0),A.createElementBlock(A.Fragment,null,A.renderList(c.itemCount,a=>(A.openBlock(),A.createElementBlock("div",X,[A.createElementVNode("button",{style:A.normalizeStyle(s.value[a-1]),onClick:B=>i(a),"aria-label":`Go to slide ${a}`,"aria-current":a-1===c.currentIndex},null,12,P)]))),256))],4))}});function x(){const e=A.ref({zIndex:1,display:"flex",justifyContent:"center",alignItems:"center",padding:"5px"}),l=A.ref({height:"20px",border:"none",color:"silver",borderRadius:"10px"});return{buttonWrapperStyle:e,buttonStyle:l,onMouseDownButton:()=>{l.value.color="gray"},onMouseUpButton:()=>{l.value.color="silver"}}}const S="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAMAAADDpiTIAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAA+vAAAPrwHWpCJtAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAZVQTFRF////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxy7YmgAAAIZ0Uk5TAAECAwQFBwgJDQ4PEBMUFxwdISIjJScoKywtLi8yMzQ1Njc6PUFERkdISktMTk9TVFVbXV9hYmRlZmdobHN0d3l6e31+gYWIiY+Qk5WWmpudpKWnqKusrq+wsrO0trq+wMHEx8jKy8zNz9LV19nb3N3e3+Dj5ujt7u/w8fLz9PX5+vv8/f4JeH4OAAAHR0lEQVR42u3deVOVBRjGYZUotTI3stJcALfEXCs1Sy1DlDC3LLc8SYWKZlGKaKGiPp+7/x1HOTMNI+993R/h+V3DgcPhZc6cV2bvfXJo8Psrtx78c/PnM8cO7Fo6x3L2+qbBsXpmowO9HS6TsM7d5ybruRs/udV5mr55O2/VCzay0Ykava3X6yVr9bhSY7d+uKaxCytdqplf/Y/U9PZon2M1cAsv1rQ31OleTVvXjWpjrUUu1qxtmqi2NuYbgUZt7+Nqc5N9rtacbWi7f9VD7wo1ZsvvVhGQuwWjVQTkbu75KgKC119FQPB6qghIXqsIiH4HqIqA5O8AR4qA5G2rIiB4HTeKgOTtqCIgeaeKgOhXgPEiIHm9VQQkb6AIiN5oEZC8ZVUEJG97ERC9/UVA9PqLgOidKAKid6kIiN61IiB6t4uA6I0VAdEbLgKi90MREL2hIiB6XxcB0dtTBETvoyIgem9OEZC9y0VA9L4oAqL3bhGQvd8JyN7RIiB63UVA9i4SkL1VTwnI3ukiIHpdUwRk73gREL3F9wnIXt8TArJ3sAjwkwABwZt/lYDsLblDQPbW3iMge90EEEAAAQQQQEDs1hFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAwS+eZogQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAY0WMEEAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEBAc7eGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIImJVbTQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEBAkoC7BBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEENGcfEkAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEDA/yhgi0NnC/j3fYfOFvDn2w6dLeDyaw6dLWDQncMFfObO2QIernDnbAFnnTlcwBpnzhbwkyuHC1jvytkCfnHkcAGbHTlbwHdunC3g9lw3zhaw2omzBRx24WwBvzpwtoCn7zhwtoCP3TdbwOfOmy3gG9fNFnDccbMFnHfbbAG/OW22gL9dFgDzEmC+CTQ/Bpo3giyrv7eCw/v7ZVB4f78Ozu7vAyHh/X0kLLy/D4WG9/ex8Oz+/jAkvL8/DQvv749Ds/v78/Dw/h4Qkd3fI2LC+3tIVHZ/j4nL7u9BkeH9PSo2u7+HRWf397j47P7+YUR2f/8yJry/fxqlv+lv+pv+pr/pb/qb/qa/6W/6m/42U1utv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7662+vZv8J/fXXX3/99ddff/31119//fXXX3/99ddff/2buDX666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//qa/6W/6m/6mv+lv+pv+pr/pb/rbjG2t/vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//rOz/z399ddff/31119//fXXX3/99ddff/31119//fXXX3/99ddff/31119//fXXX3/9Z+PW6a+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vrrr7/++uuvv/7666+//vqb/qa/6W/6m/6mv+lv+pv+pr/N6Lr1119//fXXX/+4ef5n9pbc0T9586/qH73T+kfvoP7R63uif/IW39c/esf1j17XlP5+AtA/dque6h+9i/pHr1v/7B3TP3u39I/eCv2z96X+2WvpH723pvSP3hb9s7dH/+wd1j97Q/pn70f9szesf/bG9M/ebf2zd03/7F3SP3sn9M9ev/7Z269/9rbrn71l+odvVP/sDeifvV79s9cxrn/2TumfvR36h78G3NA/e9v0z97cEf2zt0n/8LX0z16P/uHr1z/8+8Dz+mdvwaj+2Vt+V//sbXisf/b2ti1gss/VGvV+0ER7/cdWulmz1tXWr4Vai1ysaVvYxlNjhzrdq3mbd2Sa+R/tc6xmbv20Hhhwwct/c7f1+ktf/XtcqdGvAztf+PjgkY1O1PR17j43+fz64ye995OxNzZ/+9ez9UcHejtcJmgffPrV4Nkrfzy4f7N15uiBXUtdZCb2HyDq9i+SDCuqAAAAAElFTkSuQmCC",T=["src"],R=A.defineComponent({__name:"PrevButton",emits:["click-prev-button"],setup(e,{emit:l}){const n=l,{buttonWrapperStyle:o,buttonStyle:u,onMouseDownButton:i}=x(),s=()=>{n("click-prev-button")};return(c,t)=>(A.openBlock(),A.createElementBlock("div",{style:A.normalizeStyle(A.unref(o))},[A.createElementVNode("button",{class:"prev-button",style:A.normalizeStyle(A.unref(u)),onClick:s,onMousedown:t[0]||(t[0]=(...a)=>A.unref(i)&&A.unref(i)(...a)),"aria-label":"Previous slide"},[A.createElementVNode("img",{alt:"left arrow",src:A.unref(S),style:{width:"10px",borderRadius:"50%",transform:"scaleX(-1)"}},null,8,T)],36)],4))}}),L=["src"],O=A.defineComponent({__name:"NextButton",emits:["click-next-button"],setup(e,{emit:l}){const n=l,{buttonWrapperStyle:o,buttonStyle:u,onMouseUpButton:i}=x(),s=()=>{n("click-next-button")};return(c,t)=>(A.openBlock(),A.createElementBlock("div",{style:A.normalizeStyle(A.unref(o))},[A.createElementVNode("button",{class:"next-button",style:A.normalizeStyle(A.unref(u)),onClick:s,onMouseup:t[0]||(t[0]=(...a)=>A.unref(i)&&A.unref(i)(...a)),"aria-label":"Next slide"},[A.createElementVNode("img",{alt:"left arrow",src:A.unref(S),style:{width:"10px",borderRadius:"3px"}},null,8,L)],36)],4))}}),W=1e3,M="translate";function _(e,l,n,o,u){const i=A.ref(!1),s=A.computed(()=>{const m=e.direction;return{isHorizontal:["left","right"].includes(m),isReverse:["up","left"].includes(m),flexDirection:{left:"row",right:"row-reverse",up:"column",down:"column-reverse"}[m]}}),c=A.computed(()=>s.value.isHorizontal?o.value:u.value),t=A.computed(()=>{const m=l.value.length,E=n.value%m;return s.value.isReverse?E:m-(E+1%m)}),a=A.computed(()=>t.value*c.value),B=A.computed(()=>{const m=s.value.isHorizontal?"X":"Y";return`${M}${m}(-${a.value}px)`}),p=A.ref(`transform ${(e.duration??W)/1e3}s ease`),g=A.ref(p.value);return{itemsTranslate:B,defaultTransition:p,transition:g,isTransitioning:i,directionProps:s}}function q(e,l,n,o,u,i,s){const c=A.ref(null),t=A.ref(!1),a=()=>{o.value=++o.value%n.value.length,i.value=u.value},B=()=>{s.value||(o.value>=n.value.length-1?(s.value=!0,i.value="",o.value=0,requestAnimationFrame(()=>{requestAnimationFrame(()=>{i.value=u.value,o.value=1,setTimeout(()=>{s.value=!1},e.duration||1e3)})})):a())},p=()=>{c.value!==null&&(window.clearInterval(c.value),c.value=null)},g=()=>{p(),e.interval&&e.items.length>1&&!t.value&&(c.value=window.setInterval(B,e.interval))},m=()=>{B(),e.interval&&e.items.length>1&&g()},E=A.computed(()=>(o.value-1+n.value.length)%n.value.length),y=()=>{s.value||(o.value===0?(s.value=!0,i.value="",o.value=E.value,setTimeout(()=>{o.value=E.value,i.value=u.value,setTimeout(()=>{s.value=!1},e.duration||1e3)},100)):o.value=E.value,e.interval&&e.items.length>1&&g())},w=v=>{s.value||(o.value=v,e.interval&&g())};A.watch(()=>[e.interval,e.direction,e.items.length,e.pauseAutoplayOnHover],()=>{g()},{deep:!0});const C=()=>{e.pauseAutoplayOnHover&&(t.value=!0,p())},k=()=>{e.pauseAutoplayOnHover&&e.items.length>1&&(t.value=!1,g())};return A.onMounted(()=>{i.value="",e.interval&&e.items.length>1&&g()}),A.onBeforeUnmount(()=>{p()}),A.onScopeDispose(()=>{p()}),{clickNext:m,clickPrev:y,clickDot:w,pauseSlide:C,resumeSlide:k}}function j(e,l){const n=A.ref(new Map),o=A.ref(new Map),u=A.ref(new Set),i=t=>{n.value.set(t,!1),o.value.set(t,!1),u.value.add(t)},s=t=>{n.value.set(t,!1),o.value.set(t,!0)},c=t=>{if(!t||u.value.has(t))return;n.value.set(t,!0);const a=new Image;a.onload=()=>i(t),a.onerror=()=>s(t),a.src=t};return e&&l&&A.watch([e,l],()=>{const t=l.value[e.value],a=(e.value+1)%l.value.length,B=l.value[a];t!=null&&t.src&&c(t.src),B!=null&&B.src&&c(B.src)},{immediate:!0}),{loadingStates:n,errorStates:o,loadedImages:u,handleImageLoad:i,handleImageError:s,preloadImage:c}}const F=["aria-hidden"],U={class:"carousel-image-container",style:{width:"100%",height:"100%"}},G={key:0,class:"carousel-image-loading"},Z={key:1,class:"carousel-image-error"},$=["src","alt","onLoad","onError"];return((e,l)=>{const n=e.__vccOpts||e;for(const[o,u]of l)n[o]=u;return n})(A.defineComponent({__name:"DirectionalCarousel",props:{width:{default:"100%"},height:{default:"300px"},items:{},direction:{default:"right"},duration:{default:1e3},showPrev:{type:Boolean,default:!0},showNext:{type:Boolean,default:!0},showDots:{type:Boolean,default:!0},interval:{default:0},arrowOptions:{},pauseAutoplayOnHover:{type:Boolean,default:!1}},setup(e,{expose:l}){const n=e,o=()=>{const r=h(n);if(r.length>0&&(r.forEach(d=>{console.error(`DirectionalCarousel: ${d.prop} - ${d.message}`)}),r.some(d=>d.prop==="items")))throw new Error("DirectionalCarousel: Invalid props - check console for details")};A.watch(()=>({items:n.items,interval:n.interval,duration:n.duration,width:n.width,height:n.height}),o,{immediate:!0});const u=A.ref(null),i=A.computed(()=>n.items.map(r=>typeof r=="string"?{src:r}:r)),s=A.computed(()=>n.items.length),c=A.computed(()=>[...i.value,i.value[0]]),t=A.ref(0),a=A.computed(()=>{var r;return((r=u.value)==null?void 0:r.offsetWidth)??0}),B=A.computed(()=>{var r;return((r=u.value)==null?void 0:r.offsetHeight)??0}),{itemsTranslate:p,defaultTransition:g,transition:m,isTransitioning:E,directionProps:y}=_(n,c,t,a,B),{clickNext:w,clickPrev:C,clickDot:k,pauseSlide:v,resumeSlide:Q}=q(n,i,c,t,g,m,E),Y=A.computed(()=>({overflow:"hidden",width:a.value+"px",height:B.value+"px",display:"flex",justifyContent:"center",alignItems:"center"})),{loadingStates:b,errorStates:D,loadedImages:V,preloadImage:oA}=j(t,i),K=r=>{b.value.set(r,!1),V.value.add(r)},J=r=>{b.value.set(r,!1),D.value.set(r,!0)};return l({currentIndex:t}),(r,d)=>{var N,z;return A.openBlock(),A.createElementBlock("div",{style:A.normalizeStyle({overflow:"hidden",display:"flex",flexDirection:"column",width:n.width,height:n.height})},[A.createElementVNode("div",{class:"slider",style:{overflow:"hidden",position:"relative",display:"flex",width:"100%",height:"100%"},onMouseenter:d[0]||(d[0]=(...f)=>A.unref(v)&&A.unref(v)(...f)),onFocusin:d[1]||(d[1]=(...f)=>A.unref(v)&&A.unref(v)(...f)),onMouseleave:d[2]||(d[2]=(...f)=>A.unref(Q)&&A.unref(Q)(...f)),onFocusout:d[3]||(d[3]=(...f)=>A.unref(Q)&&A.unref(Q)(...f))},[(N=r.arrowOptions)!=null&&N.prev.show||r.showPrev?(A.openBlock(),A.createBlock(R,{key:0,onClickPrevButton:A.unref(C)},null,8,["onClickPrevButton"])):A.createCommentVNode("",!0),A.createElementVNode("div",{ref_key:"carouselContainer",ref:u,style:{overflow:"hidden",position:"relative",flex:1}},[A.createElementVNode("div",{class:"wrapper-carousel-items",style:A.normalizeStyle({display:"inline-flex",position:"relative",flexDirection:A.unref(y).flexDirection,transform:A.unref(p),transition:A.unref(m),pointerEvents:A.unref(E)?"none":"auto"})},[(A.openBlock(!0),A.createElementBlock(A.Fragment,null,A.renderList(c.value,(f,I)=>(A.openBlock(),A.createElementBlock("div",{key:I,style:A.normalizeStyle(Y.value),class:"carousel-item","aria-hidden":t.value!==I},[A.renderSlot(r.$slots,"item",A.mergeProps({ref_for:!0},f,{style:{width:r.width,height:r.height}}),()=>[A.createElementVNode("div",U,[A.unref(b).get(f.src)?(A.openBlock(),A.createElementBlock("div",G,[A.renderSlot(r.$slots,"loading",{},()=>[d[4]||(d[4]=A.createElementVNode("div",{class:"loading-spinner"},null,-1))],!0)])):A.unref(D).get(f.src)?(A.openBlock(),A.createElementBlock("div",Z,[A.renderSlot(r.$slots,"error",{},()=>[d[5]||(d[5]=A.createElementVNode("div",{class:"error-fallback"},[A.createElementVNode("span",null,"Failed to load image")],-1))],!0)])):(A.openBlock(),A.createElementBlock("img",{key:2,src:f.src,alt:`Slide image ${I+1} of ${s.value}`,style:A.normalizeStyle({width:"100%",opacity:A.unref(V).has(f.src)?1:0,transition:"opacity 0.2s"}),onLoad:AA=>K(f.src),onError:AA=>J(f.src)},null,44,$))])],!0)],12,F))),128))],4)],512),(z=r.arrowOptions)!=null&&z.next.show||r.showNext?(A.openBlock(),A.createBlock(O,{key:1,onClickNextButton:A.unref(w)},null,8,["onClickNextButton"])):A.createCommentVNode("",!0)],32),r.showDots?(A.openBlock(),A.createBlock(H,{key:0,"current-index":t.value,"item-count":s.value,"show-dots":r.showDots,onClickDotButton:A.unref(k)},null,8,["current-index","item-count","show-dots","onClickDotButton"])):A.createCommentVNode("",!0)],4)}}}),[["__scopeId","data-v-e58f5c3d"]])});