UNPKG

@j2only/pincode

Version:

Vue.js pincode input component. Written entirely on Vue 3 Composition API with Typescript and Vite.

3 lines (2 loc) 9.58 kB
(function(e,a){typeof exports=="object"&&typeof module<"u"?module.exports=a(require("vue")):typeof define=="function"&&define.amd?define(["vue"],a):(e=typeof globalThis<"u"?globalThis:e||self,e.pincode=a(e.Vue))})(this,function(e){"use strict";var a=document.createElement("style");a.textContent=`.vue-pincode{--pc-color-button: #010101;--pc-color-button-pressed: #474747;--pc-color-button-bg: #f6f6f6;--pc-color-button-bg-pressed: #eaeaea;--pc-color-field-normal: #234567;--pc-color-field-success: #42b983;--pc-color-field-error: #eb0c0c;--pc-custom-button-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Cg fill='%23000' fill-rule='nonzero'%3E%3Cpath d='M4.1 22v-9c0-5 3.9-8.9 9-8.9h8.8A2 2 0 1 0 22 0H13C5.7 0 0 5.7 0 13v9a2 2 0 1 0 4.1 0ZM75.9 22v-9c0-5-3.9-8.9-9-8.9h-8.8A2 2 0 1 1 58 0H67c7.3 0 13 5.7 13 13v9a2 2 0 1 1-4.1 0ZM4.1 58v9c0 5 3.9 8.9 9 8.9h8.8a2 2 0 1 1 0 4.1H13C5.7 80 0 74.3 0 67v-9a2 2 0 1 1 4.1 0ZM75.9 58v9c0 5-3.9 8.9-9 8.9h-8.8a2 2 0 1 0 0 4.1H67c7.3 0 13-5.7 13-13v-9a2 2 0 1 0-4.1 0ZM21.8 30.2V36c0 1.2.8 2.2 2 2.2 1 0 2-1 2-2.2v-5.7c0-1.2-1-2.1-2-2.1-1.2 0-2 1-2 2.1ZM54.7 30.2V36c0 1.2 1 2.2 2 2.2 1.1 0 2-1 2-2.2v-5.7c0-1.2-.9-2.1-2-2.1-1 0-2 1-2 2.1ZM26 59a20 20 0 0 0 14 5.6A20 20 0 0 0 54 59a2.1 2.1 0 0 0-2.8-3.1c-3.1 3-6.8 4.4-11.2 4.4-4.4 0-8-1.5-11.2-4.4a2.1 2.1 0 0 0-2.9 3ZM40 30.2v14.7c0 1-.5 1.4-1.4 1.4h-1.4a2.1 2.1 0 1 0 0 4.2h1.4c3.3 0 5.6-2.3 5.6-5.6V30.2a2.1 2.1 0 1 0-4.2 0Z'/%3E%3C/g%3E%3C/svg%3E");padding:1rem}.vue-pincode .vue-pincode-fields{display:flex;justify-content:space-between;align-items:center;max-width:200px;padding:0 20px;margin:20px auto 50px}.vue-pincode .vue-pincode-fields span{height:.875rem;width:.875rem;box-shadow:inset 0 0 0 2px var(--pc-color-field-normal);background-color:transparent;border-radius:100%;position:relative;display:inline-block;text-align:center;transition:box-shadow .2s linear}.vue-pincode .vue-pincode-fields span.active{animation:scale .3s ease-out 1;box-shadow:inset 0 0 0 7px var(--pc-color-field-normal)}.vue-pincode .vue-pincode-fields.is-miss{animation:miss .8s ease-out 1}.vue-pincode .vue-pincode-fields.is-success{animation:success 1s ease 1}.vue-pincode .vue-pincode-fields.is-success span{box-shadow:inset 0 0 0 7px var(--pc-color-field-success)}.vue-pincode .vue-pincode-numbers{display:grid;grid-template-columns:1fr 1fr 1fr;place-items:center center;gap:1rem 1rem}.vue-pincode .vue-pincode-numbers button{display:flex;justify-content:center;align-items:center;width:4.5rem;height:4.5rem;border-radius:50%;color:var(--pc-color-button);background-color:var(--pc-color-button-bg);-webkit-user-select:none;user-select:none;font-size:1.5rem;outline:none;cursor:pointer;border:none;transition:all .125s ease-in}.vue-pincode .vue-pincode-numbers button:active{background-color:var(--pc-color-button-bg-pressed);color:var(--pc-color-button-pressed)}.vue-pincode .vue-pincode-numbers button.is-pressed{background-color:var(--pc-color-button-bg-pressed);color:var(--pc-color-button-pressed);transition:background-color .05s}.vue-pincode .vue-pincode-numbers button span{opacity:1;transition:all .2s linear}.vue-pincode .vue-pincode-numbers button span.is-custom{background:transparent var(--pc-custom-button-icon) no-repeat center;width:2rem;height:100%;background-size:contain}.vue-pincode .vue-pincode-undo:active svg{transform:rotate(-135deg)}.vue-pincode .vue-pincode-undo span{transform:translateY(3px)}.vue-pincode .vue-pincode-undo svg{width:1.75rem;height:1.75rem;transform:rotate(45deg);transition:transform .15s cubic-bezier(.85,0,.15,1);fill:var(--pc-color-button)}.vue-pincode.is-success .vue-pincode-numbers button{box-shadow:0 0 #bbcfda,0 0 #fff,inset 0 0 #d1d9e659,inset 0 0 #ffffff4d;background-color:var(--pc-color-button-bg);transform:translateY(2px);color:#36485e52}.vue-pincode.is-success .vue-pincode-numbers button span{opacity:.4}.vue-pincode.is-success .vue-pincode-numbers button span.is-custom{opacity:.1}.vue-pincode.is-success .vue-pincode-undo svg{fill:#36485e52}.vue-pincode.is-error{color:var(--pc-color-field-error)}.vue-pincode.is-error .vue-pincode-fields span{box-shadow:inset 0 0 0 7px var(--pc-color-field-error)!important}@keyframes scale{0%{transform:scale(1)}50%{transform:scale(1.5)}to{transform:scale(1)}}@keyframes success{0%{transform:scale(1);transform:translate(0)}30%{transform:scale(1.05);transform:translateY(-5px)}to{transform:scale(1);transform:translate(0)}}@keyframes miss{0%{transform:translate(0)}10%{transform:translate(-25px)}20%{transform:translate(25px)}30%{transform:translate(-20px)}40%{transform:translate(20px)}50%{transform:translate(-10px)}60%{transform:translate(10px)}70%{transform:translate(-5px)}80%{transform:translate(5px)}to{transform:translate(0)}} /*$vite$:1*/`,document.head.appendChild(a);const h={name:"UndoIcon"},v=(n,t)=>{const r=n.__vccOpts||n;for(const[o,c]of t)r[o]=c;return r},y={height:"512pt",viewBox:"0 0 512 512",width:"512pt",xmlns:"http://www.w3.org/2000/svg"};function w(n,t,r,o,c,i){return e.openBlock(),e.createElementBlock("svg",y,t[0]||(t[0]=[e.createElementVNode("path",{d:"m154.667969 213.332031h-138.667969c-8.832031 0-16-7.167969-16-16v-138.664062c0-8.832031 7.167969-16 16-16s16 7.167969 16 16v122.664062h122.667969c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"},null,-1),e.createElementVNode("path",{d:"m256 512c-68.351562 0-132.628906-26.644531-180.96875-75.03125-6.253906-6.25-6.253906-16.382812 0-22.632812 6.269531-6.273438 16.402344-6.230469 22.632812 0 42.304688 42.347656 98.515626 65.664062 158.335938 65.664062 123.519531 0 224-100.480469 224-224s-100.480469-224-224-224c-105.855469 0-200.257812 71.148438-224.449219 169.171875-2.132812 8.597656-10.75 13.824219-19.371093 11.714844-8.574219-2.132813-13.800782-10.796875-11.710938-19.371094 27.691406-112.148437 135.148438-193.515625 255.53125-193.515625 141.164062 0 256 114.835938 256 256s-114.835938 256-256 256zm0 0"},null,-1)]))}const E=v(h,[["render",w]]),B=e.defineComponent({name:"VuePincode",components:{UndoIcon:E},props:{name:{type:String,default:"pincode"},length:{type:Number,default:4},customButton:{type:Boolean,default:!1},releaseSuccess:{type:Boolean,default:!0},releaseSuccessDelay:{type:Number,default:2500},releaseErrorDelay:{type:Number,default:500},keyboardInput:{type:Boolean,default:!0},focusRequired:{type:Boolean,default:!1},activeElement:{type:Object,default:()=>document.body}},setup(n,{emit:t}){const r=e.computed(()=>n.length<2?2:n.length>8?8:n.length),o=e.ref(""),c=e.ref(!1),i=e.ref(!1),l=e.computed(()=>o.value.length),s=e.computed(()=>c.value||i.value),d=e.ref(null),{keyboardInput:b}=e.toRefs(n),g=p=>{t("clickButton"),l.value<r.value&&(o.value+=p)},u=()=>{t("clickButton"),o.value="",c.value=!1,i.value=!1},M=()=>{t("clickButton"),t("clickCustomButton")},D=()=>{c.value=!0,setTimeout(u,n.releaseErrorDelay)},S=()=>{i.value=!0,n.releaseSuccess&&setTimeout(u,n.releaseSuccessDelay)},f=p=>{var k;const m=parseInt(p.key,10);(!n.focusRequired||document.activeElement===n.activeElement||((k=document.activeElement)==null?void 0:k.outerHTML.slice(1,41))==='button class="vue-pincode-numbers-button')&&(!isNaN(m)&&m>=0&&m<=9?(d.value=m,g(m),setTimeout(()=>{d.value=null},50)):p.key==="Backspace"?o.value=o.value.slice(0,-1):p.key==="Delete"&&u())};return e.watch(o,()=>{l.value===r.value&&t("pincode",o.value)}),e.watch(b,()=>{b.value?window.addEventListener("keydown",f):window.removeEventListener("keydown",f)}),e.onMounted(()=>{n.keyboardInput&&window.addEventListener("keydown",f)}),e.onUnmounted(()=>{n.keyboardInput&&window.removeEventListener("keydown",f),u()}),{pincode:o,pincodeError:c,pincodeSuccess:i,setupLength:r,pincodeLength:l,buttonDisabled:s,activeButton:d,clickPinButton:g,resetPincode:u,clickCustomButton:M,triggerMiss:D,triggerSuccess:S}}}),C=["id"],x={class:"vue-pincode-numbers"},V=["onClick","disabled"],N={key:1},$=["disabled"],z=["disabled"];function L(n,t,r,o,c,i){const l=e.resolveComponent("undo-icon");return e.openBlock(),e.createElementBlock("div",{id:n.name,class:e.normalizeClass(["vue-pincode",{"is-success":n.pincodeSuccess,"is-error":n.pincodeError}])},[e.createElementVNode("div",{class:e.normalizeClass(["vue-pincode-fields",{"is-success":n.pincodeSuccess,"is-miss":n.pincodeError}])},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.setupLength,s=>(e.openBlock(),e.createElementBlock("span",{key:s,class:e.normalizeClass({active:n.pincodeLength>=s})},null,2))),128))],2),e.createElementVNode("div",x,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList([1,2,3,4,5,6,7,8,9],(s,d)=>e.createElementVNode("button",{key:d,class:e.normalizeClass(["vue-pincode-numbers-button shadow",{"is-pressed":n.activeButton===s}]),onClick:b=>n.clickPinButton(s),disabled:n.buttonDisabled},[e.createElementVNode("span",null,e.toDisplayString(s),1)],10,V)),64)),n.customButton?(e.openBlock(),e.createElementBlock("button",{key:0,onClick:t[0]||(t[0]=s=>n.clickCustomButton())},t[3]||(t[3]=[e.createElementVNode("span",{class:"is-custom"},null,-1)]))):(e.openBlock(),e.createElementBlock("div",N)),e.createElementVNode("button",{onClick:t[1]||(t[1]=s=>n.clickPinButton(0)),disabled:n.buttonDisabled,class:e.normalizeClass(["vue-pincode-numbers-button shadow",{"is-pressed":n.activeButton===0}])},t[4]||(t[4]=[e.createElementVNode("span",null,"0",-1)]),10,$),e.createElementVNode("button",{class:"vue-pincode-undo",onClick:t[2]||(t[2]=s=>n.resetPincode()),disabled:n.buttonDisabled},[e.createElementVNode("span",null,[e.createVNode(l)])],8,z)])],10,C)}return v(B,[["render",L]])});