UNPKG

vue3-otp-input

Version:

A fully customizable, OTP (one-time password) input component built with Vue 3.x and Vue Composition API.

2 lines (1 loc) 5.39 kB
"use strict";const n=require("vue"),E={style:{display:"flex","align-items":"center"}},j=["type","inputmode","placeholder","disabled","maxlength","value"],A={key:0},P=["innerHTML"],L=n.defineComponent({__name:"single-otp-input",props:{inputType:{default:"tel"},inputmode:{default:"numeric"},value:{default:""},separator:{default:""},focus:{type:Boolean,default:!1},inputClasses:{default:""},conditionalClass:{default:""},shouldAutoFocus:{type:Boolean,default:!1},isLastChild:{type:Boolean,default:!1},placeholder:{default:""},isDisabled:{type:Boolean,default:!1}},emits:["on-change","on-keydown","on-paste","on-focus","on-blur"],setup(k,{emit:C}){const i=k,o=C,c=n.ref(i.value||""),a=n.ref(null),l=e=>{const u=e.target.value;return u&&u.trim().length>1?(e.clipboardData={getData:()=>u.trim()},o("on-paste",e)):o("on-change",u)},f=e=>e>=65&&e<=90,O=e=>e>=48&&e<=57||e>=96&&e<=105,B=e=>{i.isDisabled&&e.preventDefault();const u=e||window.event,d=u.which?u.which:u.keyCode;if(/iPhone|iPad|iPod/.test(navigator.userAgent)){o("on-keydown",e);return}O(d)||i.inputType==="letter-numeric"&&f(d)||[8,9,13,37,39,46,86].includes(d)?o("on-keydown",e):u.preventDefault()},h=e=>o("on-paste",e),r=()=>(a.value.select(),o("on-focus")),m=()=>o("on-blur"),v=n.computed(()=>["letter-numeric","number"].includes(i.inputType)?"text":i.inputType);return n.watch(()=>i.value,(e,u)=>{e!==u&&(c.value=e)}),n.watch(()=>i.focus,(e,u)=>{u!==e&&a.value&&i.focus&&(a.value.focus(),a.value.select())}),n.onMounted(()=>{a.value&&i.focus&&i.shouldAutoFocus&&(a.value.focus(),a.value.select())}),(e,u)=>(n.openBlock(),n.createElementBlock("div",E,[n.createElementVNode("input",{"data-test":"single-input",type:v.value,inputmode:e.inputmode,placeholder:e.placeholder,disabled:e.isDisabled,ref_key:"input",ref:a,min:"0",max:"9",maxlength:e.isLastChild?1:void 0,pattern:"[0-9]",value:c.value,class:n.normalizeClass([e.inputClasses,e.conditionalClass,{"is-complete":c.value}]),onInput:l,onKeydown:B,onPaste:h,onFocus:r,onBlur:m},null,42,j),!e.isLastChild&&e.separator?(n.openBlock(),n.createElementBlock("span",A,[n.createElementVNode("span",{innerHTML:e.separator},null,8,P)])):n.createCommentVNode("",!0)]))}}),_={style:{display:"flex"},class:"otp-input-container"},K={key:0,autocomplete:"off",name:"hidden",type:"text",style:{display:"none"}},N=8,$=37,M=39,R=46,V=n.defineComponent({__name:"vue3-otp-input",props:{value:{default:""},numInputs:{default:4},separator:{default:""},inputClasses:{default:""},conditionalClass:{default:()=>[]},inputType:{},inputmode:{default:"text"},shouldAutoFocus:{type:Boolean,default:!1},placeholder:{default:()=>[]},isDisabled:{type:Boolean,default:!1},shouldFocusOrder:{type:Boolean}},emits:["update:value","on-change","on-complete"],setup(k,{expose:C,emit:i}){const o=k,c=i,a=n.ref(0),l=n.ref([]),f=n.ref([]);n.watch(()=>o.value,t=>{if(t.length===o.numInputs||l.value.length===0){const s=t.split("");l.value=s}},{immediate:!0});const O=t=>{a.value=t},B=()=>{a.value!==o.numInputs-1&&(a.value=-1)},h=()=>l.value.join("").length===o.numInputs?(c("update:value",l.value.join("")),c("on-complete",l.value.join(""))):"Wait until the user enters the required number of characters",r=t=>{a.value=Math.max(Math.min(o.numInputs-1,t),0)},m=()=>{r(a.value+1)},v=()=>{r(a.value-1)},e=t=>{f.value=Object.assign([],l.value),l.value[a.value]=t.toString(),f.value.join("")!==l.value.join("")&&(c("update:value",l.value.join("")),c("on-change",l.value.join("")),h())},u=t=>{t.preventDefault();const s=t.clipboardData.getData("text/plain").slice(0,o.numInputs-a.value).split("");if(o.inputType==="number"&&!s.join("").match(/^\d+$/)||o.inputType==="letter-numeric"&&!s.join("").match(/^\w+$/))return"Invalid pasted data";const p=l.value.slice(0,a.value).concat(s);return p.slice(0,o.numInputs).forEach(function(y,g){l.value[g]=y}),r(p.slice(0,o.numInputs).length),h()},d=t=>{e(t),a.value<o.numInputs-1&&m()},b=()=>{l.value.length>0&&(c("update:value",""),c("on-change","")),l.value=[],a.value=0},D=t=>{const s=t.split("");s.length===o.numInputs&&(l.value=s,c("update:value",l.value.join("")),c("on-complete",l.value.join("")))},w=(t,s)=>{switch(t.keyCode){case N:t.preventDefault(),e(""),v();break;case R:t.preventDefault(),e("");break;case $:t.preventDefault(),v();break;case M:t.preventDefault(),m();break;default:T(s);break}},T=t=>{o.shouldFocusOrder&&setTimeout(()=>{const s=l.value.join("").length;t-s>=0&&(a.value=s,l.value[t]="")},100)};return C({clearInput:b,fillInput:D}),(t,s)=>(n.openBlock(),n.createElementBlock("div",_,[t.inputType==="password"?(n.openBlock(),n.createElementBlock("input",K)):n.createCommentVNode("",!0),(n.openBlock(!0),n.createElementBlock(n.Fragment,null,n.renderList(t.numInputs,(F,p)=>{var y,g;return n.openBlock(),n.createBlock(L,{key:p,focus:a.value===p,value:l.value[p],separator:t.separator,"input-type":t.inputType,inputmode:t.inputmode,"input-classes":t.inputClasses,conditionalClass:(y=t.conditionalClass)==null?void 0:y[p],"is-last-child":p===t.numInputs-1,"should-auto-focus":t.shouldAutoFocus,placeholder:(g=t.placeholder)==null?void 0:g[p],"is-disabled":t.isDisabled,onOnChange:d,onOnKeydown:I=>w(I,p),onOnPaste:u,onOnFocus:I=>O(p),onOnBlur:B},null,8,["focus","value","separator","input-type","inputmode","input-classes","conditionalClass","is-last-child","should-auto-focus","placeholder","is-disabled","onOnKeydown","onOnFocus"])}),128))]))}});module.exports=V;