fun-tab
Version:
A mobile touch-swappable tabs component for Vue3
3 lines (2 loc) • 7.05 kB
JavaScript
import{defineComponent as W,ref as n,watch as le,provide as ne,toRef as q,openBlock as N,createElementBlock as $,createElementVNode as _,renderSlot as k,inject as we,computed as D,onMounted as ue,onUnmounted as ge,normalizeStyle as R,createTextVNode as ye,toDisplayString as ie,createCommentVNode as Fe,nextTick as Ve,onBeforeUnmount as xe}from"vue";const z=Symbol();var P=(e,u)=>{const l=e.__vccOpts||e;for(const[o,i]of u)l[o]=i;return l};const Se=W({name:"FunTabBar",props:{modelValue:{type:[String,Number],default:""},activeColor:{type:String,default:"#1677ff"}},emits:["update:modelValue","change"],setup(e,{emit:u}){const l=n(e.modelValue);le(()=>e.modelValue,i=>{l.value=i});const o=i=>{l.value=i,u("update:modelValue",i),u("change",i)};ne(z,{activeValue:l,activeColor:q(e,"activeColor"),setActiveValue:o})}}),Ae={class:"fun-tab-bar"},_e={class:"fun-tab-bar-wrap"};function Be(e,u,l,o,i,s){return N(),$("div",Ae,[_("div",_e,[k(e.$slots,"default")])])}var j=P(Se,[["render",Be],["__file","tab-bar.vue"]]);const Ce=W({name:"FunTabItem",props:{title:String,name:[String,Number],badge:[String,Number]},setup(e){const u=we(z),l=n(),o=D(()=>u?.activeValue.value===e.name?{color:u?.activeColor.value}:{}),i=()=>{u?.setActiveValue(e.name)},s={name:q(e,"name"),el:l};return ue(()=>{u.addItem?.(s)}),ge(()=>{u.removeItem?.(s)}),{el:l,style:o,handleClick:i}}}),Te={class:"fun-tab-item__wrap"},Ee={class:"fun-tab-item__label"},Me={key:0,class:"fun-tab-item__badge"};function Ne(e,u,l,o,i,s){return N(),$("div",{ref:"el",style:R(e.style),class:"fun-tab-item",onClick:u[0]||(u[0]=(...w)=>e.handleClick&&e.handleClick(...w))},[_("div",Te,[k(e.$slots,"icon"),_("div",Ee,[k(e.$slots,"default",{},()=>[ye(ie(e.title),1)])]),e.badge?(N(),$("div",Me,ie(e.badge),1)):Fe("v-if",!0)])],4)}var O=P(Ce,[["render",Ne],["__file","tab-item.vue"]]);const U=window;function $e(){let e=0;const u=["webkit","moz"];for(let l=0;l<u.length&&!window.requestAnimationFrame;++l)window.requestAnimationFrame=U[u[l]+"RequestAnimationFrame"],window.cancelAnimationFrame=U[u[l]+"CancelAnimationFrame"]||U[u[l]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(l){const o=Date.now(),i=o-e,s=Math.max(0,16.7-i),w=window.setTimeout(function(){l(i)},s);return e=o+s,w}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(l){clearTimeout(l)})}const ke=W({name:"FunTabs",props:{modelValue:{type:[String,Number],default:""},lineWidth:{type:[Number,String],default:30},lineHeight:{type:Number,default:3},activeColor:{type:String,default:"#1677ff"},additionalX:{type:Number,default:50},reBoundExponent:{type:Number,default:10,validator(e){return e>0}},inertialDuration:{type:Number,default:1e3,validator(e){return e>0}},reBoundingDuration:{type:Number,default:360}},emits:["update:modelValue","change"],setup(e,{emit:u,expose:l}){let o=null;const i=[],s=n(),w=n(),F=n(e.modelValue),L=n(0),g=n(0),y=n(0),v=n(0),m=n(0),B=n(!1),f=n(!1),t=n(0),C=n(0),d=n(0),p=n(0),I=n(0),V=n(0),x=n(16.7),T=n(0),E=n(0),S=n(0),K=n(.001),b=n(.001),oe=D(()=>{const a=f.value&&!B.value?e.reBoundingDuration:0;return{transitionTimingFunction:f.value?"cubic-bezier(0.25, 0.46, 0.45, 0.94)":"cubic-bezier(0.1, 0.57, 0.1, 1)",transitionDuration:`${a}ms`,transform:`translate3d(${t.value}px, 0px, 0px)`}}),ve=D(()=>({transition:"all 300ms",width:`${g.value}px`,height:`${e.lineHeight}px`,transform:`translate3d(${L.value}px, 0, 0)`,backgroundColor:e.activeColor})),X=D(()=>p.value<=C.value);le(()=>e.modelValue,a=>{F.value=a,M()});const M=()=>{o||(o=new Promise(a=>{Ve(()=>{G(),a(),o=null})}))},re=a=>{F.value=a,u("update:modelValue",a),u("change",a)},se=a=>{i.push(a),M()},me=a=>{const r=i.findIndex(c=>c.name===a.name);r!==-1&&(i.splice(r,1),M())},ce={activeValue:F,activeColor:q(e,"activeColor"),addItem:se,removeItem:me,setActiveValue:re};ne(z,ce);const G=()=>{y.value=s.value.offsetWidth,v.value=w.value.offsetWidth-y.value,pe(),fe()},J=()=>(f.value=!1,t.value>0?(f.value=!0,t.value=0):t.value<-v.value&&(f.value=!0,t.value=-v.value),f.value),de=()=>{X.value?t.value<=0&&t.value+v.value>0||t.value>0?t.value+=p.value-d.value:t.value+v.value<=0&&(t.value+=e.additionalX*(p.value-d.value)/(y.value+Math.abs(t.value+v.value))):t.value>=0?t.value+=e.additionalX*(p.value-d.value)/(y.value+t.value):(t.value<=0&&t.value+v.value>=0||t.value+v.value<=0)&&(t.value+=p.value-d.value),d.value=p.value},Q=()=>{if(E.value=Date.now(),x.value=E.value-T.value,X.value?t.value<=-v.value?(b.value*=(e.reBoundExponent+Math.abs(t.value+v.value))/e.reBoundExponent,m.value=Math.min(m.value-b.value,0)):m.value=Math.min(m.value-b.value*x.value,0):t.value>=0?(b.value*=(e.reBoundExponent+t.value)/e.reBoundExponent,m.value=Math.max(m.value-b.value,0)):m.value=Math.max(m.value-b.value*x.value,0),t.value+=m.value*x.value/2,Math.abs(m.value)<=K.value){J();return}T.value=E.value,S.value=requestAnimationFrame(Q)},Y=()=>{if(!i.length)return;const a=i.find(r=>r.name.value===F.value);return a&&a.el.value},fe=()=>{const a=Y();if(!a)return;const r=a.offsetWidth,c=a.offsetLeft,{lineWidth:h}=e;h==="auto"?g.value=r:h<1?g.value=r*h:g.value=h,L.value=c+(r-g.value)/2},pe=()=>{const a=Y();if(!a)return;const r=a.offsetLeft,c=(y.value-a.offsetWidth)/2;let h=0;const te=Math.abs(t.value);r<=te+c?h=c-(r+t.value):h=-(r-te-c);let A=h+t.value;A>0&&(A=0),A<-v.value&&(A=-v.value),f.value=!0,t.value=A},Z=a=>{a.stopPropagation(),cancelAnimationFrame(S.value),d.value=a.touches[0].clientX},ee=a=>{v.value<=0||(a.preventDefault(),a.stopPropagation(),B.value=!0,I.value=V.value,C.value=d.value,p.value=a.touches[0].clientX,de(),V.value=a.timeStamp)},ae=a=>{if(B.value=!1,J())cancelAnimationFrame(S.value);else{let r=a.timeStamp-V.value,c=V.value-I.value;if(c=c>0?c:8,r>100)return;m.value=(d.value-C.value)/c,b.value=m.value/e.inertialDuration,T.value=Date.now(),S.value=requestAnimationFrame(Q)}},be=()=>{const a=s.value;a.addEventListener("touchstart",Z,!1),a.addEventListener("touchmove",ee,!1),a.addEventListener("touchend",ae,!1)},he=()=>{const a=s.value;a.removeEventListener("touchstart",Z),a.removeEventListener("touchmove",ee),a.removeEventListener("touchend",ae)};return ue(()=>{$e(),be(),M()}),xe(()=>{he()}),l({resize:G}),{viewAreaRef:s,listRef:w,activeValue:F,lineOffset:L,activeLineWidth:g,viewAreaWidth:y,offsetX:v,speed:m,touching:B,reBounding:f,translateX:t,startX:C,lastX:d,currentX:p,startMoveTime:I,endMoveTime:V,frameTime:x,frameStartTime:T,frameEndTime:E,inertiaFrame:S,zeroSpeed:K,acceleration:b,listStyle:oe,activeBarStyle:ve,isMoveLeft:X}}}),De={ref:"viewAreaRef",class:"fun-tabs"};function Le(e,u,l,o,i,s){return N(),$("div",De,[_("div",{ref:"listRef",style:R(e.listStyle),class:"fun-tabs__tab-list"},[k(e.$slots,"default"),_("div",{style:R(e.activeBarStyle),class:"fun-tabs__active-line"},null,4)],4)],512)}var H=P(ke,[["render",Le],["__file","tabs.vue"]]);const Ie=e=>{e.component(H.name,H),e.component(O.name,O),e.component(j.name,j)};var Xe={install:Ie};export{j as FunTabBar,O as FunTabItem,H as FunTabs,Xe as default};
//# sourceMappingURL=index.full.min.js.map