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