UNPKG

vue-sticky-element

Version:

A simple vue sticky component wrapper that will stick to screen when scrolled past it

2 lines (1 loc) 4.8 kB
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("vue"),u=require("v-scroll-threshold");function y(e,s){if(l.cloneVNode)return l.cloneVNode(e,{...e.props});const i=e.children&&e.children.map(c=>y(c,s)),t=s(e.tag,e.data,i);return t.text=e.text,t.isComment=e.isComment,t.componentOptions=e.componentOptions,t.elm=e.elm,t.context=e.context,t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t}function v(e,s){return typeof l.withDirectives=="function"?l.withDirectives(e,s):e}function b(e){const s={threshold:e.directiveThreshold,callback:e.toggleStickiness,scrollBackThreshold:e.scrollBackThreshold,scrollElement:e.scrollElement},i={[e.visibleOnDirection]:!0};return typeof l.withDirectives=="function"?[u,s,"",i]:{name:"scroll-threshold",value:s,modifiers:i}}function k(e){if(Object.is(e,-0))return!0}function S(e,s=500){let i;return(...t)=>{clearTimeout(i),i=setTimeout(()=>{e.apply(null,t)},s)}}const m={passive:!0},h={directives:{"scroll-threshold":u},props:{visibleOnDirection:{type:String,default:"up",validator:e=>["up","down","disabled"].includes(e)},stickMode:{type:String,default:"element-end",validator:e=>["element-end","element-start"].includes(e)},stuckClass:{type:String,default:"vue-sticky-element--stuck"},showClass:{type:String,default:"vue-sticky-element--show"},hideClass:{type:String,default:"vue-sticky-element--hide"},transitionClass:{type:String,default:"vue-sticky-element--transition"},transitionDuration:{type:Number,default:50},scrollBackThreshold:{type:Number,default:65},skipChecks:{type:Boolean,default:!1},forceShow:{type:Boolean,default:!1},scrollElement:{type:Object,default:void 0}},emits:["stuck","show"],data(){return{navbarStuck:!1,navbarShow:!1,applyTransition:!1,height:void 0,forceHide:!1,observer:void 0,lastScrollPos:void 0,scrollBackValue:void 0}},computed:{alwaysStick(){return this.visibleOnDirection==="disabled"},shouldApplyTransition(){return!this.alwaysStick},stickWithElementStart(){return this.stickMode==="element-start"},directiveThreshold(){return this.stickWithElementStart?0:this.height||0}},mounted(){const e=()=>{var s;this.height=(s=this.$el.firstElementChild)==null?void 0:s.clientHeight};typeof window<"u"&&("ResizeObserver"in window?(this.observer=new ResizeObserver(e),this.observer.observe(this.$el)):(this.observer=S(e),window.addEventListener("resize",this.observer,m))),e()},beforeUnmount(){this.crossBeforeUnmount()},beforeDestroy(){this.crossBeforeUnmount()},methods:{addHide(){this.forceHide=!0},removeHide(){this.forceHide=!1},toggleStickiness(e,s){this.skipChecks||(e<0||k(e)?(this.navbarStuck=!1,this.$emit("stuck",!1),this.shouldApplyTransition&&this.$nextTick().then(()=>{this.applyTransition=!1})):e>0&&(this.height=this.$el?this.$el.clientHeight:this.height,this.navbarStuck=!0,this.$emit("stuck",!0),this.shouldApplyTransition&&this.$nextTick().then(()=>{setTimeout(()=>{this.applyTransition=!0},this.transitionDuration)})),this.navbarStuck&&(s||this.alwaysStick)?(this.navbarShow=!0,this.$emit("show",!0)):(this.navbarShow=!1,this.$emit("show",!1)))},crossBeforeUnmount(){this.observer&&("disconnect"in this.observer?(this.observer.disconnect(),this.observer=void 0):window.removeEventListener("resize",this.observer,m))}},render(e){const s=l.h?l.h:e;let i;if("$scopedSlots"in this?i=this.$scopedSlots.default():"$slots"in this&&(i=this.$slots.default()),!(i&&i[0]))return l.h?null:e();const t=y(i[0],s),c={"vue-sticky-element":!0,[this.stuckClass]:this.navbarStuck,[this.showClass]:this.navbarShow||this.forceShow,[this.hideClass]:this.forceHide,[this.transitionClass]:this.applyTransition};t.props?(t.props.class?typeof t.props.class=="string"&&(t.props.class=t.props.class.split(" ")):t.props.class=[],Array.isArray(t.props.class)&&(t.props.class=t.props.class.reduce((r,n)=>(r[n]=!0,r),{})),t.props.class={...t.props.class,...c},t.props.class=Object.entries(t.props.class).map(([r,n])=>n?r:null).filter(r=>r).join(" ")):t.data&&(t.data.class?typeof t.data.class=="string"&&(t.data.class=t.data.class.split(" ")):t.data.class=[],Array.isArray(t.data.class)&&(t.data.class=t.data.class.reduce((r,n)=>(r[n]=!0,r),{})),t.data.class={...t.data.class,...c},t.data.class=Object.entries(t.data.class).map(([r,n])=>n?r:null).filter(r=>r).join(" "));const d={},f={"pointer-events":"none"},p=[b(this)];return this.height&&(d.height=`${this.height}px`,f.height=`${this.height}px`),v(s("div",{style:d,...typeof l.withDirectives!="function"?{directives:p}:{}},[t,s("div",{style:f})]),p)}};const a=function(s){a.installed||(a.installed=!0,s.component("VueStickyElement",h),s.use(u))},w={install:a};let o=null;typeof window<"u"?o=window.Vue:typeof global<"u"&&(o=global.Vue);o&&o.use&&o.use(w);h.install=a;exports.VueStickyElement=h;exports.default=h;exports.install=a;