vue-client-recaptcha
Version:
Build simple recaptcha for vuejs without need server
10 lines (8 loc) • 6.55 kB
JavaScript
/*
* vue-client-recaptcha
* Creator:parsajiravand
* Build simple recaptcha for vuejs without need server
* v2.0.1
* MIT License
*/
(function(f,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],a):(f=typeof globalThis<"u"?globalThis:f||self,a(f.VueClientRecaptcha={},f.Vue))})(this,(function(f,a){"use strict";const S={alphanumeric:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",numeric:"0123456789",letters:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};function P(){if(typeof crypto<"u"&&crypto.getRandomValues){const u=new Uint32Array(1);return crypto.getRandomValues(u),u[0]/4294967296}return Math.random()}function M(u={}){const C=typeof u=="function"?u:()=>u,m=a.ref("");function v(){const{chars:p=S.alphanumeric,charsPreset:r="alphanumeric",count:o=5}=C(),y=r==="custom"?p:S[r]??p;let c="";const i=y;for(let d=0;d<o;d++){const w=Math.floor(P()*i.length);c+=i[w]}return m.value=c,c}function l(p){return!!m.value&&m.value===p}function e(){return v()}return{code:m,generate:v,validate:l,reset:e}}const k=a.defineComponent({__name:"vue-client-recaptcha",props:{modelValue:{default:""},value:{default:""},chars:{default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"},charsPreset:{default:"alphanumeric"},count:{default:5},hideLines:{type:Boolean,default:!1},customTextColor:{default:""},textColors:{default:()=>[]},width:{type:[Number,Function],default:u=>u.count*30},height:{default:50},canvasClass:{default:""},icon:{default:"refresh"},captchaFont:{default:"bold 28px sans-serif"},hideRefreshIcon:{type:Boolean,default:!1},radius:{default:0},refreshLabel:{default:"Refresh captcha"},canvasLabel:{default:"Captcha image"},theme:{default:"light"},noiseDots:{default:0},noiseLines:{default:-1},distortion:{default:"lines"},audioEnabled:{type:Boolean,default:!1},simpleMode:{type:Boolean,default:!1}},emits:["isValid","update:valid","getCode","update:modelValue","refresh","ready","error"],setup(u,{expose:C,emit:m}){const v={alphanumeric:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",numeric:"0123456789",letters:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",custom:""};function l(){if(typeof crypto<"u"&&crypto.getRandomValues){const t=new Uint32Array(1);return crypto.getRandomValues(t),t[0]/4294967296}return Math.random()}const e=u,p=a.useSlots(),r=m,o=a.ref(null),y=M(()=>({chars:e.chars,charsPreset:e.charsPreset,count:e.count})),c=y.code,i=a.computed(()=>typeof e.width=="function"?e.width(e):e.width),d=a.computed(()=>e.height);a.computed(()=>e.charsPreset==="custom"?e.chars:v[e.charsPreset]||v.alphanumeric);const w=a.computed(()=>(e.modelValue!==void 0&&e.modelValue!==null?e.modelValue:e.value)??""),R=a.computed(()=>!!(c.value&&c.value===w.value));a.onMounted(()=>{if(!o.value){r("error",new Error("Canvas ref not available"));return}try{g(),r("ready")}catch(t){r("error",t)}}),a.watch([i,d],()=>{o.value&&g()},{flush:"post"}),a.watch([()=>e.distortion,()=>e.noiseDots,()=>e.noiseLines,()=>e.hideLines,()=>e.customTextColor,()=>e.textColors,()=>e.captchaFont,()=>e.simpleMode,()=>e.theme],()=>{o.value&&g()},{flush:"post"});const g=()=>{var h;if(!o.value)return;c.value="",o.value.width=i.value,o.value.height=d.value;const t=o.value.getContext("2d");if(!t){r("error",new Error("Failed to get canvas 2d context"));return}y.generate();const n=c.value;if(n){if(e.simpleMode){const s=e.theme==="dark"||e.theme==="auto"&&((h=window.matchMedia)==null?void 0:h.call(window,"(prefers-color-scheme: dark)").matches);t.fillStyle=s?"#ffffff":"#000000",t.font=e.captchaFont,t.textAlign="center",t.fillText(n,i.value/2,d.value/2+10)}else for(let s=0;s<n.length;s++){const b=n[s],V=l()*30*Math.PI/180,T=10+s*25,L=30+l()*8;t.font=e.captchaFont,t.translate(T,L),e.customTextColor?t.fillStyle=e.customTextColor:e.textColors.length?t.fillStyle=e.textColors[Math.floor(l()*e.textColors.length)]:t.fillStyle=x(),t.rotate(V),t.fillText(b,0,0),t.rotate(-V),t.translate(-T,-L)}if(!e.simpleMode){const s=!e.hideLines&&(e.distortion==="lines"||e.distortion==="both"),b=e.distortion==="dots"||e.distortion==="both";s&&E(),b&&e.noiseDots&&B()}if(A(),r("refresh",c.value),e.audioEnabled&&typeof window<"u"&&"speechSynthesis"in window){const s=new SpeechSynthesisUtterance(c.value.split("").join(" "));s.lang="en-US",s.rate=.8,window.speechSynthesis.cancel(),window.speechSynthesis.speak(s)}}},D=a.computed(()=>e.noiseLines>=0?e.noiseLines:e.count),E=()=>{if(!o.value)return;const t=o.value.getContext("2d");if(!t)return;const n=D.value;for(let h=0;h<n;h++)t.strokeStyle=x(),t.beginPath(),t.moveTo(l()*i.value,l()*d.value),t.lineTo(l()*i.value,l()*d.value),t.stroke()},B=()=>{if(!o.value||!e.noiseDots)return;const t=o.value.getContext("2d");if(!t)return;const n=i.value,h=d.value;for(let s=0;s<e.noiseDots;s++)t.fillStyle=x(),t.beginPath(),t.arc(l()*n,l()*h,1,0,Math.PI*2),t.fill()},A=()=>{r("getCode",c.value)};a.watchEffect(()=>{const t=R.value;r("isValid",t),r("update:valid",t)});const x=()=>{const t=Math.floor(l()*256),n=Math.floor(l()*256),h=Math.floor(l()*256);return`rgb(${t},${n},${h})`},_=()=>{if(!o.value)return;const t=o.value.getContext("2d");t&&(t.clearRect(0,0,i.value,d.value),g())};C({resetCaptcha:_});const F=()=>{const t=e.theme==="auto"?"vue_client_recaptcha_theme_auto":e.theme==="dark"?"vue_client_recaptcha_theme_dark":"";return a.h("div",{class:["vue_client_recaptcha",t].filter(Boolean).join(" "),style:{borderRadius:`var(--vcr-radius, ${e.radius}px)`,width:`${i.value+50}px`}},[a.h("span",{"aria-live":"polite","aria-atomic":"true",class:"vue_client_recaptcha_sr_only"},R.value?"Captcha verified":""),...e.hideRefreshIcon?[]:[a.h("div",{class:"vue_client_recaptcha_icon",role:"button",tabindex:0,"aria-label":e.refreshLabel,onClick:()=>_(),onKeydown:n=>{(n.key==="Enter"||n.key===" ")&&(n.preventDefault(),_())}},[p.icon?a.h(p.icon):a.h("svg",{class:"vue_client_recaptcha_icon_svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[a.h("path",{d:"M2 12a9 9 0 0 0 9 9c2.39 0 4.68-.94 6.4-2.6l-1.5-1.5A6.706 6.706 0 0 1 11 19c-6.24 0-9.36-7.54-4.95-11.95C10.46 2.64 18 5.77 18 12h-3l4 4h.1l3.9-4h-3a9 9 0 0 0-18 0Z",fill:"currentColor"})])])],a.h("canvas",{id:"captcha_canvas",class:`captcha_canvas ${e.canvasClass}`,role:"img","aria-label":e.canvasLabel,ref:o},c.value)])};return(t,n)=>(a.openBlock(),a.createBlock(F))}});f.VueClientRecaptcha=k,f.useCaptcha=M,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));