UNPKG

@engr-lukman/vue-secure-pin

Version:

A secure PIN input component for Vue.js applications with virtual keyboard and PIN masking, designed for financial applications

3 lines (2 loc) 4.79 kB
(function(u,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(u=typeof globalThis<"u"?globalThis:u||self,e(u.VueSecurePin={},u.Vue))})(this,function(u,e){"use strict";function S(c){const{maxLength:m}=c,t=e.ref(""),s=e.ref(""),l=e.computed(()=>t.value.length>=m);return{pinMasked:t,pin:s,isMaxLengthReached:l,clear:()=>{t.value="",s.value=""},pinHandler:f=>{l.value||(t.value=`${t.value||""}*`,s.value=`${s.value||""}${f}`)}}}const r={maxLength:5,isError:!1,errorMessage:"",placeholder:"Enter PIN",isEnableShuffle:!0,showKeyboard:!0,title:"Use this keyboard to enter your PIN",clearLabel:"Clear"},L={key:0,class:"numeric-keyboard__title"},B={class:"numeric-keyboard"},N={class:"numeric-keyboard__grid"},M=["onClick"],C=e.defineComponent({__name:"NumericKeyboard",props:{isEnableShuffle:{type:Boolean,default:r.isEnableShuffle},isMaxLengthReached:{type:Boolean,default:!1},title:{default:r.title},clearLabel:{default:r.clearLabel}},emits:["input","clear"],setup(c,{emit:m}){const t=c,s=m,l=e.ref([1,2,3,4,5,6,7,8,9,0]),p=i=>{if(!t.isEnableShuffle)return i;const n=[...i];for(let a=n.length-1;a>0;a--){const b=Math.floor(Math.random()*(a+1));[n[a],n[b]]=[n[b],n[a]]}return n},d=e.computed(()=>t.isEnableShuffle?p([...l.value]):l.value),f=i=>{t.isMaxLengthReached||(t.isEnableShuffle&&(l.value=p(l.value)),s("input",i))};return(i,n)=>(e.openBlock(),e.createElementBlock("div",null,[i.title?(e.openBlock(),e.createElementBlock("div",L,e.toDisplayString(i.title),1)):e.createCommentVNode("",!0),e.createElementVNode("div",B,[e.createElementVNode("div",N,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.value.slice(0,9),(a,b)=>(e.openBlock(),e.createElementBlock("button",{key:b,class:"numeric-keyboard__button",type:"button",onClick:h=>f(a)},e.toDisplayString(a),9,M))),128)),e.createElementVNode("button",{class:"numeric-keyboard__button numeric-keyboard__button--double",type:"button",onClick:n[0]||(n[0]=a=>f(d.value[d.value.length-1]))},e.toDisplayString(d.value[d.value.length-1]),1),e.createElementVNode("button",{class:"numeric-keyboard__button numeric-keyboard__button--clear",type:"button",onClick:n[1]||(n[1]=a=>i.$emit("clear"))},e.toDisplayString(i.clearLabel),1)])])]))}}),k=(c,m)=>{const t=c.__vccOpts||c;for(const[s,l]of m)t[s]=l;return t},V=k(C,[["__scopeId","data-v-c58e0ec8"]]),P={class:"pin"},$=["data-placeholder"],K={class:"pin__masked-value"},x={key:0,class:"pin__error",role:"alert"},w=e.defineComponent({__name:"SecurePin",props:{maxLength:{default:r.maxLength},isError:{type:Boolean,default:r.isError},errorMessage:{default:r.errorMessage},placeholder:{default:r.placeholder},isEnableShuffle:{type:Boolean,default:r.isEnableShuffle},showKeyboard:{type:Boolean,default:r.showKeyboard},title:{default:r.title},clearLabel:{default:r.clearLabel}},emits:["callbackEvent"],setup(c,{expose:m,emit:t}){const s=c,l=t,p=e.ref(s.showKeyboard),d=e.ref(null),{pinMasked:f,pin:i,isMaxLengthReached:n,clear:a,pinHandler:b}=S({maxLength:s.maxLength}),h=()=>{p.value=!p.value},y=()=>{a(),l("callbackEvent",{pin:"",pinMasked:""})},I=o=>{b(o),l("callbackEvent",{pin:i.value,pinMasked:f.value})},g=o=>{d.value&&!d.value.contains(o.target)&&!o.target.closest(".pin__toggle")&&(p.value=!1)};return m({clearHandler:y,toggleKeyboard:h}),e.onMounted(()=>{document.addEventListener("click",g)}),e.onUnmounted(()=>{document.removeEventListener("click",g)}),(o,E)=>(e.openBlock(),e.createElementBlock("div",P,[e.createElementVNode("div",{class:e.normalizeClass(["pin__field",{"pin__field--error":o.isError}])},[e.createElementVNode("div",{class:e.normalizeClass(["pin__display",{"pin__display--empty":!e.unref(f)}]),"data-placeholder":o.placeholder},[e.createElementVNode("div",K,e.toDisplayString(e.unref(f)),1)],10,$),e.createElementVNode("div",{class:"pin__actions"},[e.createElementVNode("div",{class:"pin__toggle",onClick:h},E[0]||(E[0]=[e.createElementVNode("span",{class:"pin__icon"},"⌨️",-1)]))]),o.isError?(e.openBlock(),e.createElementBlock("div",x,e.toDisplayString(o.errorMessage),1)):e.createCommentVNode("",!0)],2),p.value?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"keyboardPopup",ref:d,class:"pin__keyboard"},[e.createVNode(V,{"is-enable-shuffle":o.isEnableShuffle,"is-max-length-reached":e.unref(n),title:o.title,"clear-label":o.clearLabel,onInput:I,onClear:y},null,8,["is-enable-shuffle","is-max-length-reached","title","clear-label"])],512)):e.createCommentVNode("",!0)]))}}),_=k(w,[["__scopeId","data-v-c41fe822"]]);function D(c){c.component("SecurePin",_)}const H={install:D,SecurePin:_};u.SecurePin=_,u.default=H,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); //# sourceMappingURL=vue-secure-pin.umd.js.map