@qrauth/web-components 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +18 -4
- package/dist/base.d.ts +35 -0
- package/dist/login.d.ts +10 -2
- package/dist/qrauth-components.esm.js +45 -45
- package/dist/qrauth-components.js +45 -45
- package/package.json +5 -5
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/* @qrauth/web-components v0.4.
|
|
2
|
-
"use strict";var QRAuthComponents=(()=>{var
|
|
3
|
-
]))+`;E.KANJI=new RegExp(
|
|
4
|
-
Make sure your charset is UTF-8`);t=(t>>>8&255)*192+(t&255),i.put(t,13)}};
|
|
5
|
-
Suggested mode is: `+h.toString(r));switch(t===h.KANJI&&!
|
|
1
|
+
/* @qrauth/web-components v0.4.2 — https://qrauth.io */
|
|
2
|
+
"use strict";var QRAuthComponents=(()=>{var Ye=Object.create;var V=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Je=Object.getPrototypeOf,We=Object.prototype.hasOwnProperty;var Ze=(i,e,t)=>e in i?V(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var g=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),tr=(i,e)=>{for(var t in e)V(i,t,{get:e[t],enumerable:!0})},zt=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Xe(e))!We.call(i,n)&&n!==t&&V(i,n,{get:()=>e[n],enumerable:!(r=Ge(e,n))||r.enumerable});return i};var er=(i,e,t)=>(t=i!=null?Ye(Je(i)):{},zt(e||!i||!i.__esModule?V(t,"default",{value:i,enumerable:!0}):t,i)),rr=i=>zt(V({},"__esModule",{value:!0}),i);var p=(i,e,t)=>Ze(i,typeof e!="symbol"?e+"":e,t);var Ot=g((ni,Ht)=>{Ht.exports=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}});var S=g(T=>{var bt,ir=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];T.getSymbolSize=function(e){if(!e)throw new Error('"version" cannot be null or undefined');if(e<1||e>40)throw new Error('"version" should be in range from 1 to 40');return e*4+17};T.getSymbolTotalCodewords=function(e){return ir[e]};T.getBCHDigit=function(i){let e=0;for(;i!==0;)e++,i>>>=1;return e};T.setToSJISFunction=function(e){if(typeof e!="function")throw new Error('"toSJISFunc" is not a valid function.');bt=e};T.isKanjiModeEnabled=function(){return typeof bt<"u"};T.toSJIS=function(e){return bt(e)}});var et=g(v=>{v.L={bit:1};v.M={bit:0};v.Q={bit:3};v.H={bit:2};function nr(i){if(typeof i!="string")throw new Error("Param is not a string");switch(i.toLowerCase()){case"l":case"low":return v.L;case"m":case"medium":return v.M;case"q":case"quartile":return v.Q;case"h":case"high":return v.H;default:throw new Error("Unknown EC Level: "+i)}}v.isValid=function(e){return e&&typeof e.bit<"u"&&e.bit>=0&&e.bit<4};v.from=function(e,t){if(v.isValid(e))return e;try{return nr(e)}catch{return t}}});var Yt=g((ai,Kt)=>{function jt(){this.buffer=[],this.length=0}jt.prototype={get:function(i){let e=Math.floor(i/8);return(this.buffer[e]>>>7-i%8&1)===1},put:function(i,e){for(let t=0;t<e;t++)this.putBit((i>>>e-t-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(i){let e=Math.floor(this.length/8);this.buffer.length<=e&&this.buffer.push(0),i&&(this.buffer[e]|=128>>>this.length%8),this.length++}};Kt.exports=jt});var Xt=g((li,Gt)=>{function z(i){if(!i||i<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=i,this.data=new Uint8Array(i*i),this.reservedBit=new Uint8Array(i*i)}z.prototype.set=function(i,e,t,r){let n=i*this.size+e;this.data[n]=t,r&&(this.reservedBit[n]=!0)};z.prototype.get=function(i,e){return this.data[i*this.size+e]};z.prototype.xor=function(i,e,t){this.data[i*this.size+e]^=t};z.prototype.isReserved=function(i,e){return this.reservedBit[i*this.size+e]};Gt.exports=z});var Jt=g(rt=>{var sr=S().getSymbolSize;rt.getRowColCoords=function(e){if(e===1)return[];let t=Math.floor(e/7)+2,r=sr(e),n=r===145?26:Math.ceil((r-13)/(2*t-2))*2,s=[r-7];for(let o=1;o<t-1;o++)s[o]=s[o-1]-n;return s.push(6),s.reverse()};rt.getPositions=function(e){let t=[],r=rt.getRowColCoords(e),n=r.length;for(let s=0;s<n;s++)for(let o=0;o<n;o++)s===0&&o===0||s===0&&o===n-1||s===n-1&&o===0||t.push([r[s],r[o]]);return t}});var te=g(Zt=>{var or=S().getSymbolSize,Wt=7;Zt.getPositions=function(e){let t=or(e);return[[0,0],[t-Wt,0],[0,t-Wt]]}});var ee=g(f=>{f.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var R={N1:3,N2:3,N3:40,N4:10};f.isValid=function(e){return e!=null&&e!==""&&!isNaN(e)&&e>=0&&e<=7};f.from=function(e){return f.isValid(e)?parseInt(e,10):void 0};f.getPenaltyN1=function(e){let t=e.size,r=0,n=0,s=0,o=null,a=null;for(let l=0;l<t;l++){n=s=0,o=a=null;for(let d=0;d<t;d++){let c=e.get(l,d);c===o?n++:(n>=5&&(r+=R.N1+(n-5)),o=c,n=1),c=e.get(d,l),c===a?s++:(s>=5&&(r+=R.N1+(s-5)),a=c,s=1)}n>=5&&(r+=R.N1+(n-5)),s>=5&&(r+=R.N1+(s-5))}return r};f.getPenaltyN2=function(e){let t=e.size,r=0;for(let n=0;n<t-1;n++)for(let s=0;s<t-1;s++){let o=e.get(n,s)+e.get(n,s+1)+e.get(n+1,s)+e.get(n+1,s+1);(o===4||o===0)&&r++}return r*R.N2};f.getPenaltyN3=function(e){let t=e.size,r=0,n=0,s=0;for(let o=0;o<t;o++){n=s=0;for(let a=0;a<t;a++)n=n<<1&2047|e.get(o,a),a>=10&&(n===1488||n===93)&&r++,s=s<<1&2047|e.get(a,o),a>=10&&(s===1488||s===93)&&r++}return r*R.N3};f.getPenaltyN4=function(e){let t=0,r=e.data.length;for(let s=0;s<r;s++)t+=e.data[s];return Math.abs(Math.ceil(t*100/r/5)-10)*R.N4};function ar(i,e,t){switch(i){case f.Patterns.PATTERN000:return(e+t)%2===0;case f.Patterns.PATTERN001:return e%2===0;case f.Patterns.PATTERN010:return t%3===0;case f.Patterns.PATTERN011:return(e+t)%3===0;case f.Patterns.PATTERN100:return(Math.floor(e/2)+Math.floor(t/3))%2===0;case f.Patterns.PATTERN101:return e*t%2+e*t%3===0;case f.Patterns.PATTERN110:return(e*t%2+e*t%3)%2===0;case f.Patterns.PATTERN111:return(e*t%3+(e+t)%2)%2===0;default:throw new Error("bad maskPattern:"+i)}}f.applyMask=function(e,t){let r=t.size;for(let n=0;n<r;n++)for(let s=0;s<r;s++)t.isReserved(s,n)||t.xor(s,n,ar(e,s,n))};f.getBestMask=function(e,t){let r=Object.keys(f.Patterns).length,n=0,s=1/0;for(let o=0;o<r;o++){t(o),f.applyMask(o,e);let a=f.getPenaltyN1(e)+f.getPenaltyN2(e)+f.getPenaltyN3(e)+f.getPenaltyN4(e);f.applyMask(o,e),a<s&&(s=a,n=o)}return n}});var yt=g(vt=>{var C=et(),it=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],nt=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];vt.getBlocksCount=function(e,t){switch(t){case C.L:return it[(e-1)*4+0];case C.M:return it[(e-1)*4+1];case C.Q:return it[(e-1)*4+2];case C.H:return it[(e-1)*4+3];default:return}};vt.getTotalCodewordsCount=function(e,t){switch(t){case C.L:return nt[(e-1)*4+0];case C.M:return nt[(e-1)*4+1];case C.Q:return nt[(e-1)*4+2];case C.H:return nt[(e-1)*4+3];default:return}}});var re=g(ot=>{var Q=new Uint8Array(512),st=new Uint8Array(256);(function(){let e=1;for(let t=0;t<255;t++)Q[t]=e,st[e]=t,e<<=1,e&256&&(e^=285);for(let t=255;t<512;t++)Q[t]=Q[t-255]})();ot.log=function(e){if(e<1)throw new Error("log("+e+")");return st[e]};ot.exp=function(e){return Q[e]};ot.mul=function(e,t){return e===0||t===0?0:Q[st[e]+st[t]]}});var ie=g(H=>{var xt=re();H.mul=function(e,t){let r=new Uint8Array(e.length+t.length-1);for(let n=0;n<e.length;n++)for(let s=0;s<t.length;s++)r[n+s]^=xt.mul(e[n],t[s]);return r};H.mod=function(e,t){let r=new Uint8Array(e);for(;r.length-t.length>=0;){let n=r[0];for(let o=0;o<t.length;o++)r[o]^=xt.mul(t[o],n);let s=0;for(;s<r.length&&r[s]===0;)s++;r=r.slice(s)}return r};H.generateECPolynomial=function(e){let t=new Uint8Array([1]);for(let r=0;r<e;r++)t=H.mul(t,new Uint8Array([1,xt.exp(r)]));return t}});var oe=g((fi,se)=>{var ne=ie();function _t(i){this.genPoly=void 0,this.degree=i,this.degree&&this.initialize(this.degree)}_t.prototype.initialize=function(e){this.degree=e,this.genPoly=ne.generateECPolynomial(this.degree)};_t.prototype.encode=function(e){if(!this.genPoly)throw new Error("Encoder not initialized");let t=new Uint8Array(e.length+this.degree);t.set(e);let r=ne.mod(t,this.genPoly),n=this.degree-r.length;if(n>0){let s=new Uint8Array(this.degree);return s.set(r,n),s}return r};se.exports=_t});var wt=g(ae=>{ae.isValid=function(e){return!isNaN(e)&&e>=1&&e<=40}});var Et=g(E=>{var le="[0-9]+",lr="[A-Z $%*+\\-./:]+",O="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";O=O.replace(/u/g,"\\u");var dr="(?:(?![A-Z0-9 $%*+\\-./:]|"+O+`)(?:.|[\r
|
|
3
|
+
]))+`;E.KANJI=new RegExp(O,"g");E.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");E.BYTE=new RegExp(dr,"g");E.NUMERIC=new RegExp(le,"g");E.ALPHANUMERIC=new RegExp(lr,"g");var cr=new RegExp("^"+O+"$"),ur=new RegExp("^"+le+"$"),hr=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");E.testKanji=function(e){return cr.test(e)};E.testNumeric=function(e){return ur.test(e)};E.testAlphanumeric=function(e){return hr.test(e)}});var A=g(b=>{var pr=wt(),It=Et();b.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]};b.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]};b.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]};b.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]};b.MIXED={bit:-1};b.getCharCountIndicator=function(e,t){if(!e.ccBits)throw new Error("Invalid mode: "+e);if(!pr.isValid(t))throw new Error("Invalid version: "+t);return t>=1&&t<10?e.ccBits[0]:t<27?e.ccBits[1]:e.ccBits[2]};b.getBestModeForData=function(e){return It.testNumeric(e)?b.NUMERIC:It.testAlphanumeric(e)?b.ALPHANUMERIC:It.testKanji(e)?b.KANJI:b.BYTE};b.toString=function(e){if(e&&e.id)return e.id;throw new Error("Invalid mode")};b.isValid=function(e){return e&&e.bit&&e.ccBits};function gr(i){if(typeof i!="string")throw new Error("Param is not a string");switch(i.toLowerCase()){case"numeric":return b.NUMERIC;case"alphanumeric":return b.ALPHANUMERIC;case"kanji":return b.KANJI;case"byte":return b.BYTE;default:throw new Error("Unknown mode: "+i)}}b.from=function(e,t){if(b.isValid(e))return e;try{return gr(e)}catch{return t}}});var pe=g(M=>{var at=S(),fr=yt(),de=et(),B=A(),kt=wt(),ue=7973,ce=at.getBCHDigit(ue);function mr(i,e,t){for(let r=1;r<=40;r++)if(e<=M.getCapacity(r,t,i))return r}function he(i,e){return B.getCharCountIndicator(i,e)+4}function br(i,e){let t=0;return i.forEach(function(r){let n=he(r.mode,e);t+=n+r.getBitsLength()}),t}function vr(i,e){for(let t=1;t<=40;t++)if(br(i,t)<=M.getCapacity(t,e,B.MIXED))return t}M.from=function(e,t){return kt.isValid(e)?parseInt(e,10):t};M.getCapacity=function(e,t,r){if(!kt.isValid(e))throw new Error("Invalid QR Code version");typeof r>"u"&&(r=B.BYTE);let n=at.getSymbolTotalCodewords(e),s=fr.getTotalCodewordsCount(e,t),o=(n-s)*8;if(r===B.MIXED)return o;let a=o-he(r,e);switch(r){case B.NUMERIC:return Math.floor(a/10*3);case B.ALPHANUMERIC:return Math.floor(a/11*2);case B.KANJI:return Math.floor(a/13);case B.BYTE:default:return Math.floor(a/8)}};M.getBestVersionForData=function(e,t){let r,n=de.from(t,de.M);if(Array.isArray(e)){if(e.length>1)return vr(e,n);if(e.length===0)return 1;r=e[0]}else r=e;return mr(r.mode,r.getLength(),n)};M.getEncodedBits=function(e){if(!kt.isValid(e)||e<7)throw new Error("Invalid QR Code version");let t=e<<12;for(;at.getBCHDigit(t)-ce>=0;)t^=ue<<at.getBCHDigit(t)-ce;return e<<12|t}});var be=g(me=>{var St=S(),fe=1335,yr=21522,ge=St.getBCHDigit(fe);me.getEncodedBits=function(e,t){let r=e.bit<<3|t,n=r<<10;for(;St.getBCHDigit(n)-ge>=0;)n^=fe<<St.getBCHDigit(n)-ge;return(r<<10|n)^yr}});var ye=g((_i,ve)=>{var xr=A();function N(i){this.mode=xr.NUMERIC,this.data=i.toString()}N.getBitsLength=function(e){return 10*Math.floor(e/3)+(e%3?e%3*3+1:0)};N.prototype.getLength=function(){return this.data.length};N.prototype.getBitsLength=function(){return N.getBitsLength(this.data.length)};N.prototype.write=function(e){let t,r,n;for(t=0;t+3<=this.data.length;t+=3)r=this.data.substr(t,3),n=parseInt(r,10),e.put(n,10);let s=this.data.length-t;s>0&&(r=this.data.substr(t),n=parseInt(r,10),e.put(n,s*3+1))};ve.exports=N});var _e=g((wi,xe)=>{var _r=A(),Ct=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function D(i){this.mode=_r.ALPHANUMERIC,this.data=i}D.getBitsLength=function(e){return 11*Math.floor(e/2)+6*(e%2)};D.prototype.getLength=function(){return this.data.length};D.prototype.getBitsLength=function(){return D.getBitsLength(this.data.length)};D.prototype.write=function(e){let t;for(t=0;t+2<=this.data.length;t+=2){let r=Ct.indexOf(this.data[t])*45;r+=Ct.indexOf(this.data[t+1]),e.put(r,11)}this.data.length%2&&e.put(Ct.indexOf(this.data[t]),6)};xe.exports=D});var Ee=g((Ei,we)=>{var wr=A();function U(i){this.mode=wr.BYTE,typeof i=="string"?this.data=new TextEncoder().encode(i):this.data=new Uint8Array(i)}U.getBitsLength=function(e){return e*8};U.prototype.getLength=function(){return this.data.length};U.prototype.getBitsLength=function(){return U.getBitsLength(this.data.length)};U.prototype.write=function(i){for(let e=0,t=this.data.length;e<t;e++)i.put(this.data[e],8)};we.exports=U});var ke=g((Ii,Ie)=>{var Er=A(),Ir=S();function L(i){this.mode=Er.KANJI,this.data=i}L.getBitsLength=function(e){return e*13};L.prototype.getLength=function(){return this.data.length};L.prototype.getBitsLength=function(){return L.getBitsLength(this.data.length)};L.prototype.write=function(i){let e;for(e=0;e<this.data.length;e++){let t=Ir.toSJIS(this.data[e]);if(t>=33088&&t<=40956)t-=33088;else if(t>=57408&&t<=60351)t-=49472;else throw new Error("Invalid SJIS character: "+this.data[e]+`
|
|
4
|
+
Make sure your charset is UTF-8`);t=(t>>>8&255)*192+(t&255),i.put(t,13)}};Ie.exports=L});var Se=g((ki,At)=>{"use strict";var j={single_source_shortest_paths:function(i,e,t){var r={},n={};n[e]=0;var s=j.PriorityQueue.make();s.push(e,0);for(var o,a,l,d,c,m,u,y,I;!s.empty();){o=s.pop(),a=o.value,d=o.cost,c=i[a]||{};for(l in c)c.hasOwnProperty(l)&&(m=c[l],u=d+m,y=n[l],I=typeof n[l]>"u",(I||y>u)&&(n[l]=u,s.push(l,u),r[l]=a))}if(typeof t<"u"&&typeof n[t]>"u"){var k=["Could not find a path from ",e," to ",t,"."].join("");throw new Error(k)}return r},extract_shortest_path_from_predecessor_list:function(i,e){for(var t=[],r=e,n;r;)t.push(r),n=i[r],r=i[r];return t.reverse(),t},find_path:function(i,e,t){var r=j.single_source_shortest_paths(i,e,t);return j.extract_shortest_path_from_predecessor_list(r,t)},PriorityQueue:{make:function(i){var e=j.PriorityQueue,t={},r;i=i||{};for(r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);return t.queue=[],t.sorter=i.sorter||e.default_sorter,t},default_sorter:function(i,e){return i.cost-e.cost},push:function(i,e){var t={value:i,cost:e};this.queue.push(t),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};typeof At<"u"&&(At.exports=j)});var qe=g(F=>{var h=A(),Be=ye(),Te=_e(),Re=Ee(),Me=ke(),K=Et(),lt=S(),kr=Se();function Ce(i){return unescape(encodeURIComponent(i)).length}function Y(i,e,t){let r=[],n;for(;(n=i.exec(t))!==null;)r.push({data:n[0],index:n.index,mode:e,length:n[0].length});return r}function Pe(i){let e=Y(K.NUMERIC,h.NUMERIC,i),t=Y(K.ALPHANUMERIC,h.ALPHANUMERIC,i),r,n;return lt.isKanjiModeEnabled()?(r=Y(K.BYTE,h.BYTE,i),n=Y(K.KANJI,h.KANJI,i)):(r=Y(K.BYTE_KANJI,h.BYTE,i),n=[]),e.concat(t,r,n).sort(function(o,a){return o.index-a.index}).map(function(o){return{data:o.data,mode:o.mode,length:o.length}})}function Bt(i,e){switch(e){case h.NUMERIC:return Be.getBitsLength(i);case h.ALPHANUMERIC:return Te.getBitsLength(i);case h.KANJI:return Me.getBitsLength(i);case h.BYTE:return Re.getBitsLength(i)}}function Sr(i){return i.reduce(function(e,t){let r=e.length-1>=0?e[e.length-1]:null;return r&&r.mode===t.mode?(e[e.length-1].data+=t.data,e):(e.push(t),e)},[])}function Cr(i){let e=[];for(let t=0;t<i.length;t++){let r=i[t];switch(r.mode){case h.NUMERIC:e.push([r,{data:r.data,mode:h.ALPHANUMERIC,length:r.length},{data:r.data,mode:h.BYTE,length:r.length}]);break;case h.ALPHANUMERIC:e.push([r,{data:r.data,mode:h.BYTE,length:r.length}]);break;case h.KANJI:e.push([r,{data:r.data,mode:h.BYTE,length:Ce(r.data)}]);break;case h.BYTE:e.push([{data:r.data,mode:h.BYTE,length:Ce(r.data)}])}}return e}function Ar(i,e){let t={},r={start:{}},n=["start"];for(let s=0;s<i.length;s++){let o=i[s],a=[];for(let l=0;l<o.length;l++){let d=o[l],c=""+s+l;a.push(c),t[c]={node:d,lastCount:0},r[c]={};for(let m=0;m<n.length;m++){let u=n[m];t[u]&&t[u].node.mode===d.mode?(r[u][c]=Bt(t[u].lastCount+d.length,d.mode)-Bt(t[u].lastCount,d.mode),t[u].lastCount+=d.length):(t[u]&&(t[u].lastCount=d.length),r[u][c]=Bt(d.length,d.mode)+4+h.getCharCountIndicator(d.mode,e))}}n=a}for(let s=0;s<n.length;s++)r[n[s]].end=0;return{map:r,table:t}}function Ae(i,e){let t,r=h.getBestModeForData(i);if(t=h.from(e,r),t!==h.BYTE&&t.bit<r.bit)throw new Error('"'+i+'" cannot be encoded with mode '+h.toString(t)+`.
|
|
5
|
+
Suggested mode is: `+h.toString(r));switch(t===h.KANJI&&!lt.isKanjiModeEnabled()&&(t=h.BYTE),t){case h.NUMERIC:return new Be(i);case h.ALPHANUMERIC:return new Te(i);case h.KANJI:return new Me(i);case h.BYTE:return new Re(i)}}F.fromArray=function(e){return e.reduce(function(t,r){return typeof r=="string"?t.push(Ae(r,null)):r.data&&t.push(Ae(r.data,r.mode)),t},[])};F.fromString=function(e,t){let r=Pe(e,lt.isKanjiModeEnabled()),n=Cr(r),s=Ar(n,t),o=kr.find_path(s.map,"start","end"),a=[];for(let l=1;l<o.length-1;l++)a.push(s.table[o[l]].node);return F.fromArray(Sr(a))};F.rawSplit=function(e){return F.fromArray(Pe(e,lt.isKanjiModeEnabled()))}});var De=g(Ne=>{var ct=S(),Tt=et(),Br=Yt(),Tr=Xt(),Rr=Jt(),Mr=te(),Pt=ee(),qt=yt(),Pr=oe(),dt=pe(),qr=be(),Nr=A(),Rt=qe();function Dr(i,e){let t=i.size,r=Mr.getPositions(e);for(let n=0;n<r.length;n++){let s=r[n][0],o=r[n][1];for(let a=-1;a<=7;a++)if(!(s+a<=-1||t<=s+a))for(let l=-1;l<=7;l++)o+l<=-1||t<=o+l||(a>=0&&a<=6&&(l===0||l===6)||l>=0&&l<=6&&(a===0||a===6)||a>=2&&a<=4&&l>=2&&l<=4?i.set(s+a,o+l,!0,!0):i.set(s+a,o+l,!1,!0))}}function Ur(i){let e=i.size;for(let t=8;t<e-8;t++){let r=t%2===0;i.set(t,6,r,!0),i.set(6,t,r,!0)}}function Lr(i,e){let t=Rr.getPositions(e);for(let r=0;r<t.length;r++){let n=t[r][0],s=t[r][1];for(let o=-2;o<=2;o++)for(let a=-2;a<=2;a++)o===-2||o===2||a===-2||a===2||o===0&&a===0?i.set(n+o,s+a,!0,!0):i.set(n+o,s+a,!1,!0)}}function Fr(i,e){let t=i.size,r=dt.getEncodedBits(e),n,s,o;for(let a=0;a<18;a++)n=Math.floor(a/3),s=a%3+t-8-3,o=(r>>a&1)===1,i.set(n,s,o,!0),i.set(s,n,o,!0)}function Mt(i,e,t){let r=i.size,n=qr.getEncodedBits(e,t),s,o;for(s=0;s<15;s++)o=(n>>s&1)===1,s<6?i.set(s,8,o,!0):s<8?i.set(s+1,8,o,!0):i.set(r-15+s,8,o,!0),s<8?i.set(8,r-s-1,o,!0):s<9?i.set(8,15-s-1+1,o,!0):i.set(8,15-s-1,o,!0);i.set(r-8,8,1,!0)}function $r(i,e){let t=i.size,r=-1,n=t-1,s=7,o=0;for(let a=t-1;a>0;a-=2)for(a===6&&a--;;){for(let l=0;l<2;l++)if(!i.isReserved(n,a-l)){let d=!1;o<e.length&&(d=(e[o]>>>s&1)===1),i.set(n,a-l,d),s--,s===-1&&(o++,s=7)}if(n+=r,n<0||t<=n){n-=r,r=-r;break}}}function Vr(i,e,t){let r=new Br;t.forEach(function(l){r.put(l.mode.bit,4),r.put(l.getLength(),Nr.getCharCountIndicator(l.mode,i)),l.write(r)});let n=ct.getSymbolTotalCodewords(i),s=qt.getTotalCodewordsCount(i,e),o=(n-s)*8;for(r.getLengthInBits()+4<=o&&r.put(0,4);r.getLengthInBits()%8!==0;)r.putBit(0);let a=(o-r.getLengthInBits())/8;for(let l=0;l<a;l++)r.put(l%2?17:236,8);return zr(r,i,e)}function zr(i,e,t){let r=ct.getSymbolTotalCodewords(e),n=qt.getTotalCodewordsCount(e,t),s=r-n,o=qt.getBlocksCount(e,t),a=r%o,l=o-a,d=Math.floor(r/o),c=Math.floor(s/o),m=c+1,u=d-c,y=new Pr(u),I=0,k=new Array(o),$t=new Array(o),gt=0,Ke=new Uint8Array(i.buffer);for(let q=0;q<o;q++){let mt=q<l?c:m;k[q]=Ke.slice(I,I+mt),$t[q]=y.encode(k[q]),I+=mt,gt=Math.max(gt,mt)}let ft=new Uint8Array(r),Vt=0,_,w;for(_=0;_<gt;_++)for(w=0;w<o;w++)_<k[w].length&&(ft[Vt++]=k[w][_]);for(_=0;_<u;_++)for(w=0;w<o;w++)ft[Vt++]=$t[w][_];return ft}function Qr(i,e,t,r){let n;if(Array.isArray(i))n=Rt.fromArray(i);else if(typeof i=="string"){let d=e;if(!d){let c=Rt.rawSplit(i);d=dt.getBestVersionForData(c,t)}n=Rt.fromString(i,d||40)}else throw new Error("Invalid data");let s=dt.getBestVersionForData(n,t);if(!s)throw new Error("The amount of data is too big to be stored in a QR Code");if(!e)e=s;else if(e<s)throw new Error(`
|
|
6
6
|
The chosen QR Code version cannot contain this amount of data.
|
|
7
7
|
Minimum version required to store current data is: `+s+`.
|
|
8
|
-
`);let o=
|
|
9
|
-
`;return typeof r=="function"&&r(null,
|
|
8
|
+
`);let o=Vr(e,t,n),a=ct.getSymbolSize(e),l=new Tr(a);return Dr(l,e),Ur(l),Lr(l,e),Mt(l,t,0),e>=7&&Fr(l,e),$r(l,o),isNaN(r)&&(r=Pt.getBestMask(l,Mt.bind(null,l,t))),Pt.applyMask(r,l),Mt(l,t,r),{modules:l,version:e,errorCorrectionLevel:t,maskPattern:r,segments:n}}Ne.create=function(e,t){if(typeof e>"u"||e==="")throw new Error("No input text");let r=Tt.M,n,s;return typeof t<"u"&&(r=Tt.from(t.errorCorrectionLevel,Tt.M),n=dt.from(t.version),s=Pt.from(t.maskPattern),t.toSJISFunc&&ct.setToSJISFunction(t.toSJISFunc)),Qr(e,n,r,s)}});var Nt=g(P=>{function Ue(i){if(typeof i=="number"&&(i=i.toString()),typeof i!="string")throw new Error("Color should be defined as hex string");let e=i.slice().replace("#","").split("");if(e.length<3||e.length===5||e.length>8)throw new Error("Invalid hex color: "+i);(e.length===3||e.length===4)&&(e=Array.prototype.concat.apply([],e.map(function(r){return[r,r]}))),e.length===6&&e.push("F","F");let t=parseInt(e.join(""),16);return{r:t>>24&255,g:t>>16&255,b:t>>8&255,a:t&255,hex:"#"+e.slice(0,6).join("")}}P.getOptions=function(e){e||(e={}),e.color||(e.color={});let t=typeof e.margin>"u"||e.margin===null||e.margin<0?4:e.margin,r=e.width&&e.width>=21?e.width:void 0,n=e.scale||4;return{width:r,scale:r?4:n,margin:t,color:{dark:Ue(e.color.dark||"#000000ff"),light:Ue(e.color.light||"#ffffffff")},type:e.type,rendererOpts:e.rendererOpts||{}}};P.getScale=function(e,t){return t.width&&t.width>=e+t.margin*2?t.width/(e+t.margin*2):t.scale};P.getImageWidth=function(e,t){let r=P.getScale(e,t);return Math.floor((e+t.margin*2)*r)};P.qrToImageData=function(e,t,r){let n=t.modules.size,s=t.modules.data,o=P.getScale(n,r),a=Math.floor((n+r.margin*2)*o),l=r.margin*o,d=[r.color.light,r.color.dark];for(let c=0;c<a;c++)for(let m=0;m<a;m++){let u=(c*a+m)*4,y=r.color.light;if(c>=l&&m>=l&&c<a-l&&m<a-l){let I=Math.floor((c-l)/o),k=Math.floor((m-l)/o);y=d[s[I*n+k]?1:0]}e[u++]=y.r,e[u++]=y.g,e[u++]=y.b,e[u]=y.a}}});var Le=g(ut=>{var Dt=Nt();function Hr(i,e,t){i.clearRect(0,0,e.width,e.height),e.style||(e.style={}),e.height=t,e.width=t,e.style.height=t+"px",e.style.width=t+"px"}function Or(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}ut.render=function(e,t,r){let n=r,s=t;typeof n>"u"&&(!t||!t.getContext)&&(n=t,t=void 0),t||(s=Or()),n=Dt.getOptions(n);let o=Dt.getImageWidth(e.modules.size,n),a=s.getContext("2d"),l=a.createImageData(o,o);return Dt.qrToImageData(l.data,e,n),Hr(a,s,o),a.putImageData(l,0,0),s};ut.renderToDataURL=function(e,t,r){let n=r;typeof n>"u"&&(!t||!t.getContext)&&(n=t,t=void 0),n||(n={});let s=ut.render(e,t,n),o=n.type||"image/png",a=n.rendererOpts||{};return s.toDataURL(o,a.quality)}});var Ve=g($e=>{var jr=Nt();function Fe(i,e){let t=i.a/255,r=e+'="'+i.hex+'"';return t<1?r+" "+e+'-opacity="'+t.toFixed(2).slice(1)+'"':r}function Ut(i,e,t){let r=i+e;return typeof t<"u"&&(r+=" "+t),r}function Kr(i,e,t){let r="",n=0,s=!1,o=0;for(let a=0;a<i.length;a++){let l=Math.floor(a%e),d=Math.floor(a/e);!l&&!s&&(s=!0),i[a]?(o++,a>0&&l>0&&i[a-1]||(r+=s?Ut("M",l+t,.5+d+t):Ut("m",n,0),n=0,s=!1),l+1<e&&i[a+1]||(r+=Ut("h",o),o=0)):n++}return r}$e.render=function(e,t,r){let n=jr.getOptions(t),s=e.modules.size,o=e.modules.data,a=s+n.margin*2,l=n.color.light.a?"<path "+Fe(n.color.light,"fill")+' d="M0 0h'+a+"v"+a+'H0z"/>':"",d="<path "+Fe(n.color.dark,"stroke")+' d="'+Kr(o,s,n.margin)+'"/>',c='viewBox="0 0 '+a+" "+a+'"',u='<svg xmlns="http://www.w3.org/2000/svg" '+(n.width?'width="'+n.width+'" height="'+n.width+'" ':"")+c+' shape-rendering="crispEdges">'+l+d+`</svg>
|
|
9
|
+
`;return typeof r=="function"&&r(null,u),u}});var Qe=g(G=>{var Yr=Ot(),Lt=De(),ze=Le(),Gr=Ve();function Ft(i,e,t,r,n){let s=[].slice.call(arguments,1),o=s.length,a=typeof s[o-1]=="function";if(!a&&!Yr())throw new Error("Callback required as last argument");if(a){if(o<2)throw new Error("Too few arguments provided");o===2?(n=t,t=e,e=r=void 0):o===3&&(e.getContext&&typeof n>"u"?(n=r,r=void 0):(n=r,r=t,t=e,e=void 0))}else{if(o<1)throw new Error("Too few arguments provided");return o===1?(t=e,e=r=void 0):o===2&&!e.getContext&&(r=t,t=e,e=void 0),new Promise(function(l,d){try{let c=Lt.create(t,r);l(i(c,e,r))}catch(c){d(c)}})}try{let l=Lt.create(t,r);n(null,i(l,e,r))}catch(l){n(l)}}G.create=Lt.create;G.toCanvas=Ft.bind(null,ze.render);G.toDataURL=Ft.bind(null,ze.renderToDataURL);G.toString=Ft.bind(null,function(i,e,t){return Gr.render(i,t)})});var ti={};tr(ti,{QRAuthElement:()=>x,QRAuthEphemeral:()=>W,QRAuthLogin:()=>J,QRAuthTwoFA:()=>Z});var tt="X-QRAuth-Code-Verifier";function Qt(i,e){let t=(i??"").trim();if(!t)return null;let r;try{r=new URL(t,e)}catch{return null}return r.protocol==="https:"||r.protocol==="http:"?r.href:null}var x=class extends HTMLElement{constructor(){super();p(this,"shadow");p(this,"_sseConnection",null);p(this,"_pollInterval",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["tenant","theme","base-url","force-mode","mobile-fallback-only"]}get tenant(){return this.getAttribute("tenant")||""}get theme(){return this.getAttribute("theme")||"light"}get baseUrl(){let t=this.getAttribute("base-url");return t!==null?t:"https://qrauth.io"}connectedCallback(){this.render()}disconnectedCallback(){this.cleanup()}attributeChangedCallback(t,r,n){r!==n&&this.render()}isMobileLike(){if(typeof window>"u")return!1;let t=this.getAttribute("force-mode");if(t==="mobile")return!0;if(t==="desktop"||this.hasAttribute("mobile-fallback-only"))return!1;if(typeof window.matchMedia=="function"){let r=window.matchMedia("(pointer: coarse)").matches,n=window.matchMedia("(hover: none)").matches;if(r&&n)return!0}return/Android|iPhone|iPad|iPod|Mobile|Tablet|BlackBerry|Opera Mini/i.test(navigator.userAgent)}connectSSE(t){this.disconnectSSE(),this._sseConnection=new EventSource(t),this._sseConnection.onerror=()=>{this.disconnectSSE()}}onSSEEvent(t,r){this._sseConnection&&this._sseConnection.addEventListener(t,n=>{let s=n;try{r(JSON.parse(s.data))}catch{}})}disconnectSSE(){this._sseConnection&&(this._sseConnection.close(),this._sseConnection=null)}startPolling(t,r,n,s){this.stopPolling();let o=async()=>{try{let a=await fetch(t,{headers:s});a.ok&&n(await a.json())}catch{}};o(),this._pollInterval=setInterval(o,r)}stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null)}cleanup(){this.disconnectSSE(),this.stopPolling()}setErrorText(t){if(!t)return;let r=this.shadow.querySelector(".state-error .subtitle");r&&(r.textContent=t)}isApprovalWithoutIdentity(t,r){return t&&!r?.user}callGlobal(t,r){if(!t||!Object.prototype.hasOwnProperty.call(window,t))return;let n=window[t];if(typeof n=="function")try{n.call(window,r)}catch(s){console.error(`[qrauth] ${t} threw:`,s)}}navigate(t){window.location.href=t}emit(t,r){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,detail:r}))}async generateCodeVerifier(){let t=new Uint8Array(32);return crypto.getRandomValues(t),this._base64url(t)}async computeCodeChallenge(t){let n=new TextEncoder().encode(t),s=await crypto.subtle.digest("SHA-256",n);return this._base64url(new Uint8Array(s))}_base64url(t){let r=Array.from(t,n=>String.fromCodePoint(n)).join("");return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}getBaseStyles(){return`
|
|
10
10
|
:host {
|
|
11
11
|
display: inline-block;
|
|
12
12
|
font-family: var(--qrauth-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
|
|
@@ -37,7 +37,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
37
37
|
--_btn-hover: var(--qrauth-btn-hover, #2e4578);
|
|
38
38
|
}
|
|
39
39
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
40
|
-
`}};var
|
|
40
|
+
`}};var He=er(Qe(),1);function $(i,e=440){if(!i)return"";let t=Math.max(1,Math.floor(Number.isFinite(e)?e:440)),r;try{r=He.default.create(i,{errorCorrectionLevel:"M"})}catch{return""}let n=r.modules,s=4,o=n.size+s*2,a=t/o,l="";for(let d=0;d<n.size;d++)for(let c=0;c<n.size;c++)if(n.data[d*n.size+c]){let m=(c+s)*a,u=(d+s)*a;l+=`<rect x="${m.toFixed(2)}" y="${u.toFixed(2)}" width="${a.toFixed(2)}" height="${a.toFixed(2)}"/>`}return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${t}" width="${t}" height="${t}" shape-rendering="crispEdges" role="img" aria-label="QR code"><rect width="100%" height="100%" fill="#ffffff"/><g fill="#000000">${l}</g></svg>`}var X=`<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
41
41
|
<path d="M48 24 H152 Q166 24 166 38 V108 Q166 156 100 182 Q34 156 34 108 V38 Q34 24 48 24 Z"
|
|
42
42
|
fill="none" stroke="#fff" stroke-width="5"/>
|
|
43
43
|
<g fill="#fff" opacity="0.2">
|
|
@@ -54,12 +54,12 @@ Minimum version required to store current data is: `+s+`.
|
|
|
54
54
|
<path d="M62 104 L88 134 L144 64"
|
|
55
55
|
fill="none" stroke="#fff" stroke-width="15"
|
|
56
56
|
stroke-linecap="round" stroke-linejoin="round"/>
|
|
57
|
-
</svg>`,
|
|
57
|
+
</svg>`,Oe=`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
58
58
|
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" fill="currentColor"/>
|
|
59
|
-
</svg>`,
|
|
59
|
+
</svg>`,Xr=`<svg class="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
60
60
|
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2.5"
|
|
61
61
|
stroke-dasharray="31.416" stroke-dashoffset="10" stroke-linecap="round"/>
|
|
62
|
-
</svg>`,J=class extends
|
|
62
|
+
</svg>`,J=class extends x{constructor(){super(...arguments);p(this,"_sessionId",null);p(this,"_sessionToken",null);p(this,"_codeVerifier",null);p(this,"_status","idle");p(this,"_expiresAt",null);p(this,"_currentQrUrl",null);p(this,"_timerInterval",null);p(this,"_pollTimeout",null)}static get observedAttributes(){return[...super.observedAttributes,"scopes","redirect-url","on-auth","display","animated","redirect-uri"]}get scopes(){return this.getAttribute("scopes")||"identity"}get redirectUrl(){return this.getAttribute("redirect-url")}get onAuth(){return this.getAttribute("on-auth")}get display(){return this.getAttribute("display")||"button"}get animated(){return this.hasAttribute("animated")}get redirectUri(){return this.getAttribute("redirect-uri")}get forceMode(){let t=this.getAttribute("force-mode");return t==="mobile"||t==="desktop"?t:"auto"}get mobileFallbackOnly(){return this.hasAttribute("mobile-fallback-only")}disconnectedCallback(){super.disconnectedCallback(),this._clearTimers()}render(){this.display==="inline"?this._renderInline():this._renderButton()}_renderButton(){this.shadow.innerHTML=`
|
|
63
63
|
<style>
|
|
64
64
|
${this.getBaseStyles()}
|
|
65
65
|
:host { display: inline-block; }
|
|
@@ -125,7 +125,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
125
125
|
</style>
|
|
126
126
|
|
|
127
127
|
<button class="btn" id="open-btn" aria-label="Sign in with QRAuth">
|
|
128
|
-
<span class="btn-icon">${
|
|
128
|
+
<span class="btn-icon">${X}</span>
|
|
129
129
|
Sign in with QRAuth
|
|
130
130
|
</button>
|
|
131
131
|
|
|
@@ -184,7 +184,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
184
184
|
</div>
|
|
185
185
|
`,this._bindInlineEvents()}_inlineIdleContent(){return`
|
|
186
186
|
<button class="start-btn" id="start-btn" aria-label="Sign in with QRAuth">
|
|
187
|
-
<span class="btn-icon">${
|
|
187
|
+
<span class="btn-icon">${X}</span>
|
|
188
188
|
Sign in with QRAuth
|
|
189
189
|
</button>
|
|
190
190
|
`}_modalContent(){return`
|
|
@@ -194,13 +194,13 @@ Minimum version required to store current data is: `+s+`.
|
|
|
194
194
|
</div>
|
|
195
195
|
`}_bodyForStatus(t,r){switch(t){case"idle":return`
|
|
196
196
|
<div class="state-header">
|
|
197
|
-
<div class="brand-icon">${
|
|
197
|
+
<div class="brand-icon">${X}</div>
|
|
198
198
|
<h3>Sign in with QRAuth</h3>
|
|
199
199
|
<p>Secure, passwordless authentication</p>
|
|
200
200
|
</div>
|
|
201
201
|
`;case"loading":return`
|
|
202
202
|
<div class="state-loading">
|
|
203
|
-
<div class="spinner-wrap">${
|
|
203
|
+
<div class="spinner-wrap">${Xr}</div>
|
|
204
204
|
<p class="status-text">Generating QR code...</p>
|
|
205
205
|
</div>
|
|
206
206
|
`;case"pending":case"SCANNED":{if(this.isMobileLike())return this._mobilePendingBody(t,r);let n=t==="SCANNED";return`
|
|
@@ -214,7 +214,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
214
214
|
<div class="footer">Secured by <a href="https://qrauth.io" target="_blank" rel="noopener">QRAuth</a></div>
|
|
215
215
|
`}case"APPROVED":return`
|
|
216
216
|
<div class="state-approved">
|
|
217
|
-
<div class="success-icon">${
|
|
217
|
+
<div class="success-icon">${Oe}</div>
|
|
218
218
|
<h3>Identity verified!</h3>
|
|
219
219
|
<p class="subtitle">You are now signed in</p>
|
|
220
220
|
</div>
|
|
@@ -236,20 +236,20 @@ Minimum version required to store current data is: `+s+`.
|
|
|
236
236
|
<div class="state-error">
|
|
237
237
|
<div class="error-icon">⚠</div>
|
|
238
238
|
<h3>Something went wrong</h3>
|
|
239
|
-
<p class="subtitle"
|
|
239
|
+
<p class="subtitle">Failed to start authentication.</p>
|
|
240
240
|
<button class="retry-btn" id="retry-btn">Try again</button>
|
|
241
241
|
</div>
|
|
242
242
|
`;default:return""}}_qrFrameHtml(t,r){let n=$(t,440);return`
|
|
243
243
|
<div class="qr-frame ${r?"scanned":""}${this.animated?" animated":""}">
|
|
244
244
|
<div class="qr-image" role="img" aria-label="QR Code for authentication">${n}</div>
|
|
245
|
-
<div class="qr-badge">${
|
|
246
|
-
${r?'<div class="scanned-overlay"><span class="scanned-check">'+
|
|
245
|
+
<div class="qr-badge">${X}</div>
|
|
246
|
+
${r?'<div class="scanned-overlay"><span class="scanned-check">'+Oe+"</span></div>":""}
|
|
247
247
|
</div>
|
|
248
248
|
`}_mobilePendingBody(t,r){let n=t==="SCANNED";return`
|
|
249
249
|
<h3>Sign in with QRAuth</h3>
|
|
250
250
|
<p class="subtitle">Tap continue to verify on this device.</p>
|
|
251
251
|
<button class="mobile-cta" id="mobile-cta" type="button">
|
|
252
|
-
<span class="btn-icon">${
|
|
252
|
+
<span class="btn-icon">${X}</span>
|
|
253
253
|
Continue with QRAuth
|
|
254
254
|
</button>
|
|
255
255
|
<div class="status-text ${n?"status-scanned":""}">
|
|
@@ -514,7 +514,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
514
514
|
}
|
|
515
515
|
.footer a { color: var(--_disabled); text-decoration: none; }
|
|
516
516
|
.footer a:hover { text-decoration: underline; }
|
|
517
|
-
`}_bindButtonEvents(){this.shadow.getElementById("open-btn")?.addEventListener("click",()=>{this._openModal(),this._startAuth()});let r=this.shadow.getElementById("overlay");r?.addEventListener("click",n=>{n.target===r&&this._closeModal()}),this._bindModalButtons()}_bindInlineEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>{this._startAuth()})}_bindModalButtons(){this.shadow.getElementById("close-btn")?.addEventListener("click",()=>this._closeModal()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry()),this.shadow.getElementById("mobile-cta")?.addEventListener("click",()=>this._openApprovalPage())}_openApprovalPage(){if(!this._sessionToken)return;let t=new URL(`${this.baseUrl}/a/${this._sessionToken}`);t.searchParams.set("dr","1");let r=t.toString();window.open(r,"_blank","noopener")||(window.location.href=r)}_openModal(){this.shadow.getElementById("overlay")?.classList.remove("hidden"),this._updateBody(this._bodyForStatus("idle"))}_closeModal(){this.shadow.getElementById("overlay")?.classList.add("hidden"),this._clearTimers(),this._sessionId=null,this._sessionToken=null,this._codeVerifier=null,this._status="idle",this._expiresAt=null,this._currentQrUrl=null}async _startAuth(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{this._codeVerifier=await this.generateCodeVerifier();let t=await this.computeCodeChallenge(this._codeVerifier),r={"Content-Type":"application/json","X-Client-Id":this.tenant},n={scopes:this.scopes.split(/\s+/).filter(Boolean),codeChallenge:t,codeChallengeMethod:"S256"};this.redirectUri&&(n.redirectUrl=this.redirectUri);let s=await fetch(`${this.baseUrl}/api/v1/auth-sessions`,{method:"POST",headers:r,body:JSON.stringify(n)});if(!s.ok){let a=await s.json().catch(()=>({message:"Failed to create session"}));throw new Error(a.message??"Failed to create session")}let o=await s.json();this._sessionId=o.sessionId,this._sessionToken=o.token||(o.qrUrl?o.qrUrl.split("/").pop()??null:null),this._expiresAt=new Date(o.expiresAt).getTime(),this._currentQrUrl=o.qrUrl??null,this._status="pending",this._updateBody(this._bodyForStatus("pending",{qrUrl:o.qrUrl})),this._bindModalButtons(),this._startCountdown(),this._beginPolling(o.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error",{
|
|
517
|
+
`}_bindButtonEvents(){this.shadow.getElementById("open-btn")?.addEventListener("click",()=>{this._openModal(),this._startAuth()});let r=this.shadow.getElementById("overlay");r?.addEventListener("click",n=>{n.target===r&&this._closeModal()}),this._bindModalButtons()}_bindInlineEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>{this._startAuth()})}_bindModalButtons(){this.shadow.getElementById("close-btn")?.addEventListener("click",()=>this._closeModal()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry()),this.shadow.getElementById("mobile-cta")?.addEventListener("click",()=>this._openApprovalPage())}_openApprovalPage(){if(!this._sessionToken)return;let t=new URL(`${this.baseUrl}/a/${this._sessionToken}`);t.searchParams.set("dr","1");let r=t.toString();window.open(r,"_blank","noopener")||(window.location.href=r)}_openModal(){this.shadow.getElementById("overlay")?.classList.remove("hidden"),this._updateBody(this._bodyForStatus("idle"))}_closeModal(){this.shadow.getElementById("overlay")?.classList.add("hidden"),this._clearTimers(),this._sessionId=null,this._sessionToken=null,this._codeVerifier=null,this._status="idle",this._expiresAt=null,this._currentQrUrl=null}async _startAuth(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{this._codeVerifier=await this.generateCodeVerifier();let t=await this.computeCodeChallenge(this._codeVerifier),r={"Content-Type":"application/json","X-Client-Id":this.tenant},n={scopes:this.scopes.split(/\s+/).filter(Boolean),codeChallenge:t,codeChallengeMethod:"S256"};this.redirectUri&&(n.redirectUrl=this.redirectUri);let s=await fetch(`${this.baseUrl}/api/v1/auth-sessions`,{method:"POST",headers:r,body:JSON.stringify(n)});if(!s.ok){let a=await s.json().catch(()=>({message:"Failed to create session"}));throw new Error(a.message??"Failed to create session")}let o=await s.json();this._sessionId=o.sessionId,this._sessionToken=o.token||(o.qrUrl?o.qrUrl.split("/").pop()??null:null),this._expiresAt=new Date(o.expiresAt).getTime(),this._currentQrUrl=o.qrUrl??null,this._status="pending",this._updateBody(this._bodyForStatus("pending",{qrUrl:o.qrUrl})),this._bindModalButtons(),this._startCountdown(),this._beginPolling(o.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error")),this.setErrorText(r),this._bindModalButtons(),this.emit("qrauth:error",{message:r})}}_failWithoutIdentity(){let t="Sign-in could not be confirmed. Please try again.";this._status="error",this._updateBody(this._bodyForStatus("error")),this.setErrorText(t),this._bindModalButtons(),this.emit("qrauth:error",{message:t})}_retry(){if(this._clearTimers(),this._sessionId=null,this._sessionToken=null,this._codeVerifier=null,this._status="idle",this._expiresAt=null,this._currentQrUrl=null,this.display==="inline"){let t=this.shadow.getElementById("inline-body");t&&(t.innerHTML=this._inlineIdleContent(),this._bindInlineEvents())}else this._startAuth()}_beginPolling(t){let r="PENDING",n=2e3,s=5e3,o=0,a=20,l=async()=>{if(!this._sessionId)return;let d=`${this.baseUrl}/api/v1/auth-sessions/${t}`,c={"X-Client-Id":this.tenant};this._codeVerifier&&(c[tt]=this._codeVerifier);try{let u=await(await fetch(d,{headers:c})).json();if(o=0,n=2e3,u.status!==r&&(r=u.status,this._handleStatusChange(u.status,u),["APPROVED","DENIED","EXPIRED"].includes(u.status)))return;this._pollTimeout=setTimeout(l,n)}catch{if(o++,o>=a){this._handleStatusChange("EXPIRED",void 0);return}n=Math.min(n*1.5,s),this._pollTimeout=setTimeout(l,n)}};this._pollTimeout=setTimeout(l,n)}_handleStatusChange(t,r){switch(this._status=t,t){case"SCANNED":{this._updateBody(this._bodyForStatus("SCANNED",{qrUrl:this._currentQrUrl??"",timerHtml:this._formatTimer()})),this._bindModalButtons(),this.emit("qrauth:scanned",r);break}case"APPROVED":{if(this._clearTimers(),this.isApprovalWithoutIdentity(!!this._codeVerifier,r)){this._failWithoutIdentity();break}this._updateBody(this._bodyForStatus("APPROVED")),this._bindModalButtons(),this.emit("qrauth:authenticated",{sessionId:r?.sessionId,user:r?.user,signature:r?.signature}),this.callGlobal(this.onAuth,r);let n=Qt(this.redirectUrl,window.location.href);this.redirectUrl&&!n&&console.warn("[qrauth-login] redirect-url ignored: only http(s) and relative URLs are followed."),n?setTimeout(()=>this.navigate(n),1500):this.display==="button"&&setTimeout(()=>this._closeModal(),2200);break}case"DENIED":this._clearTimers(),this._updateBody(this._bodyForStatus("DENIED")),this._bindModalButtons(),this.emit("qrauth:denied");break;case"EXPIRED":this._clearTimers(),this._status="EXPIRED",this._updateBody(this._bodyForStatus("EXPIRED")),this._bindModalButtons(),this.emit("qrauth:expired");break}}_startCountdown(){this._timerInterval=setInterval(()=>{let t=this.shadow.getElementById("timer");if(!t||!this._expiresAt)return;let r=Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3));t.textContent=r>0?this._formatTimer(r):"",r<=0&&(clearInterval(this._timerInterval),this._timerInterval=null,(this._status==="pending"||this._status==="SCANNED")&&this._handleStatusChange("EXPIRED",void 0))},1e3)}_formatTimer(t){let r=t??(this._expiresAt?Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3)):0),n=Math.floor(r/60),s=r%60;return`Expires in ${n}:${s<10?"0":""}${s}`}_updateBody(t){let r=this.display==="inline"?this.shadow.getElementById("inline-body"):this.shadow.getElementById("modal-body");r&&(r.innerHTML=t)}_clearTimers(){this._timerInterval&&(clearInterval(this._timerInterval),this._timerInterval=null),this._pollTimeout&&(clearTimeout(this._pollTimeout),this._pollTimeout=null)}};customElements.define("qrauth-login",J);var ht=`<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
518
518
|
<path d="M48 24 H152 Q166 24 166 38 V108 Q166 156 100 182 Q34 156 34 108 V38 Q34 24 48 24 Z"
|
|
519
519
|
fill="none" stroke="#fff" stroke-width="5"/>
|
|
520
520
|
<g fill="#fff" opacity="0.2">
|
|
@@ -531,12 +531,12 @@ Minimum version required to store current data is: `+s+`.
|
|
|
531
531
|
<path d="M62 104 L88 134 L144 64"
|
|
532
532
|
fill="none" stroke="#fff" stroke-width="15"
|
|
533
533
|
stroke-linecap="round" stroke-linejoin="round"/>
|
|
534
|
-
</svg>`,
|
|
534
|
+
</svg>`,Jr=`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
535
535
|
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" fill="currentColor"/>
|
|
536
|
-
</svg>`,
|
|
536
|
+
</svg>`,Wr=`<svg class="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
537
537
|
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2.5"
|
|
538
538
|
stroke-dasharray="31.416" stroke-dashoffset="10" stroke-linecap="round"/>
|
|
539
|
-
</svg>`,W=class extends
|
|
539
|
+
</svg>`,W=class extends x{constructor(){super(...arguments);p(this,"_sessionId",null);p(this,"_claimUrl",null);p(this,"_status","idle");p(this,"_expiresAt",null);p(this,"_timerInterval",null);p(this,"_pollTimeout",null)}static get observedAttributes(){return[...super.observedAttributes,"scopes","ttl","max-uses","device-binding","display"]}get scopes(){return this.getAttribute("scopes")||"access"}get ttl(){return this.getAttribute("ttl")||"30m"}get maxUses(){return parseInt(this.getAttribute("max-uses")||"1",10)}get deviceBinding(){return this.hasAttribute("device-binding")}get display(){return this.getAttribute("display")||"inline"}get forceMode(){let t=this.getAttribute("force-mode");return t==="mobile"||t==="desktop"?t:"auto"}get mobileFallbackOnly(){return this.hasAttribute("mobile-fallback-only")}disconnectedCallback(){super.disconnectedCallback(),this._clearTimers()}render(){this.display==="button"?this._renderButton():this._renderInline()}_renderButton(){this.shadow.innerHTML=`
|
|
540
540
|
<style>
|
|
541
541
|
${this.getBaseStyles()}
|
|
542
542
|
:host { display: inline-block; }
|
|
@@ -602,7 +602,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
602
602
|
</style>
|
|
603
603
|
|
|
604
604
|
<button class="btn" id="open-btn" aria-label="Get access QR code">
|
|
605
|
-
<span class="btn-icon">${
|
|
605
|
+
<span class="btn-icon">${ht}</span>
|
|
606
606
|
Get Access QR
|
|
607
607
|
</button>
|
|
608
608
|
|
|
@@ -661,7 +661,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
661
661
|
</div>
|
|
662
662
|
`,this._bindInlineEvents()}_inlineIdleContent(){return`
|
|
663
663
|
<button class="start-btn" id="start-btn" aria-label="Get access QR code">
|
|
664
|
-
<span class="btn-icon">${
|
|
664
|
+
<span class="btn-icon">${ht}</span>
|
|
665
665
|
Get Access QR
|
|
666
666
|
</button>
|
|
667
667
|
`}_modalContent(){return`
|
|
@@ -671,28 +671,28 @@ Minimum version required to store current data is: `+s+`.
|
|
|
671
671
|
</div>
|
|
672
672
|
`}_bodyForStatus(t,r){switch(t){case"idle":return`
|
|
673
673
|
<div class="state-header">
|
|
674
|
-
<div class="brand-icon">${
|
|
674
|
+
<div class="brand-icon">${ht}</div>
|
|
675
675
|
<h3>Ephemeral Access</h3>
|
|
676
676
|
<p>Scan to claim temporary access</p>
|
|
677
677
|
</div>
|
|
678
678
|
`;case"loading":return`
|
|
679
679
|
<div class="state-loading">
|
|
680
|
-
<div class="spinner-wrap">${
|
|
680
|
+
<div class="spinner-wrap">${Wr}</div>
|
|
681
681
|
<p class="status-text">Generating access QR...</p>
|
|
682
682
|
</div>
|
|
683
|
-
`;case"active":{let n=$(r?.claimUrl??"",440),s=r?.useCount??0,o=r?.maxUses??1,l=o>1?`<div class="use-badge">${s}/${o} claimed</div>`:"";return`
|
|
683
|
+
`;case"active":{let n=$(r?.claimUrl??"",440),s=Math.trunc(Number(r?.useCount??0))||0,o=Math.trunc(Number(r?.maxUses??1))||1,l=o>1?`<div class="use-badge">${s}/${o} claimed</div>`:"";return`
|
|
684
684
|
<h3>Scan to Access</h3>
|
|
685
685
|
<p class="subtitle">Present this QR code to gain entry</p>
|
|
686
686
|
<div class="qr-frame">
|
|
687
687
|
<div class="qr-image" role="img" aria-label="Ephemeral access QR code">${n}</div>
|
|
688
|
-
<div class="qr-badge">${
|
|
688
|
+
<div class="qr-badge">${ht}</div>
|
|
689
689
|
</div>
|
|
690
690
|
${l}
|
|
691
691
|
<div class="timer" id="timer">${r?.timerHtml??""}</div>
|
|
692
692
|
<div class="footer">Secured by <a href="https://qrauth.io" target="_blank" rel="noopener">QRAuth</a></div>
|
|
693
693
|
`}case"CLAIMED":return`
|
|
694
694
|
<div class="state-claimed">
|
|
695
|
-
<div class="success-icon">${
|
|
695
|
+
<div class="success-icon">${Jr}</div>
|
|
696
696
|
<h3>Access granted!</h3>
|
|
697
697
|
<p class="subtitle">The QR code has been claimed successfully</p>
|
|
698
698
|
</div>
|
|
@@ -713,7 +713,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
713
713
|
<div class="state-error">
|
|
714
714
|
<div class="error-icon">⚠</div>
|
|
715
715
|
<h3>Something went wrong</h3>
|
|
716
|
-
<p class="subtitle"
|
|
716
|
+
<p class="subtitle">Failed to create ephemeral session.</p>
|
|
717
717
|
<button class="retry-btn" id="retry-btn">Try again</button>
|
|
718
718
|
</div>
|
|
719
719
|
`;default:return""}}_sharedModalStyles(){return`
|
|
@@ -899,7 +899,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
899
899
|
}
|
|
900
900
|
.footer a { color: var(--_disabled); text-decoration: none; }
|
|
901
901
|
.footer a:hover { text-decoration: underline; }
|
|
902
|
-
`}_bindButtonEvents(){this.shadow.getElementById("open-btn")?.addEventListener("click",()=>{this._openModal(),this._startSession()});let r=this.shadow.getElementById("overlay");r?.addEventListener("click",n=>{n.target===r&&this._closeModal()}),this._bindModalButtons()}_bindInlineEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>{this._startSession()})}_bindModalButtons(){this.shadow.getElementById("close-btn")?.addEventListener("click",()=>this._closeModal()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry())}_openModal(){this.shadow.getElementById("overlay")?.classList.remove("hidden"),this._updateBody(this._bodyForStatus("idle"))}_closeModal(){this.shadow.getElementById("overlay")?.classList.add("hidden"),this._clearTimers(),this._sessionId=null,this._claimUrl=null,this._status="idle",this._expiresAt=null}async _startSession(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{let t=await fetch(`${this.baseUrl}/api/v1/ephemeral`,{method:"POST",headers:{"Content-Type":"application/json","X-Client-Id":this.tenant},body:JSON.stringify({scopes:this.scopes.split(/\s+/).filter(Boolean),ttl:this.ttl,maxUses:this.maxUses,deviceBinding:this.deviceBinding})});if(!t.ok){let n=await t.json().catch(()=>({message:"Failed to create session"}));throw new Error(n.message??"Failed to create session")}let r=await t.json();this._sessionId=r.sessionId,this._claimUrl=r.claimUrl,this._expiresAt=new Date(r.expiresAt).getTime(),this._status="active",this._updateBody(this._bodyForStatus("active",{claimUrl:r.claimUrl,timerHtml:this._formatTimer(),useCount:0,maxUses:r.maxUses})),this._bindModalButtons(),this._startCountdown(),this._beginPolling(r.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error",
|
|
902
|
+
`}_bindButtonEvents(){this.shadow.getElementById("open-btn")?.addEventListener("click",()=>{this._openModal(),this._startSession()});let r=this.shadow.getElementById("overlay");r?.addEventListener("click",n=>{n.target===r&&this._closeModal()}),this._bindModalButtons()}_bindInlineEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>{this._startSession()})}_bindModalButtons(){this.shadow.getElementById("close-btn")?.addEventListener("click",()=>this._closeModal()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry())}_openModal(){this.shadow.getElementById("overlay")?.classList.remove("hidden"),this._updateBody(this._bodyForStatus("idle"))}_closeModal(){this.shadow.getElementById("overlay")?.classList.add("hidden"),this._clearTimers(),this._sessionId=null,this._claimUrl=null,this._status="idle",this._expiresAt=null}async _startSession(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{let t=await fetch(`${this.baseUrl}/api/v1/ephemeral`,{method:"POST",headers:{"Content-Type":"application/json","X-Client-Id":this.tenant},body:JSON.stringify({scopes:this.scopes.split(/\s+/).filter(Boolean),ttl:this.ttl,maxUses:this.maxUses,deviceBinding:this.deviceBinding})});if(!t.ok){let n=await t.json().catch(()=>({message:"Failed to create session"}));throw new Error(n.message??"Failed to create session")}let r=await t.json();this._sessionId=r.sessionId,this._claimUrl=r.claimUrl,this._expiresAt=new Date(r.expiresAt).getTime(),this._status="active",this._updateBody(this._bodyForStatus("active",{claimUrl:r.claimUrl,timerHtml:this._formatTimer(),useCount:0,maxUses:r.maxUses})),this._bindModalButtons(),this._startCountdown(),this._beginPolling(r.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error")),this.setErrorText(r),this._bindModalButtons(),this.emit("qrauth:error",{message:r})}}_retry(){if(this._clearTimers(),this._sessionId=null,this._claimUrl=null,this._status="idle",this._expiresAt=null,this.display==="inline"){let t=this.shadow.getElementById("inline-body");t&&(t.innerHTML=this._inlineIdleContent(),this._bindInlineEvents())}else this._startSession()}_beginPolling(t){let r=2e3,n=5e3,s=0,o=20,a=async()=>{if(this._sessionId)try{let d=await(await fetch(`${this.baseUrl}/api/v1/ephemeral/${t}`,{headers:{"X-Client-Id":this.tenant}})).json();if(s=0,r=2e3,this._handleStatusChange(d.status,d),["CLAIMED","EXPIRED","REVOKED"].includes(d.status)){if(d.status==="CLAIMED"&&d.useCount<d.maxUses){this._updateBody(this._bodyForStatus("active",{claimUrl:this._claimUrl??void 0,timerHtml:this._formatTimer(),useCount:d.useCount,maxUses:d.maxUses})),this._bindModalButtons(),this._pollTimeout=setTimeout(a,r);return}return}this._pollTimeout=setTimeout(a,r)}catch{if(s++,s>=o){this._handleStatusChange("EXPIRED",void 0);return}r=Math.min(r*1.5,n),this._pollTimeout=setTimeout(a,r)}};this._pollTimeout=setTimeout(a,r)}_handleStatusChange(t,r){switch(t){case"CLAIMED":{this._clearTimers(),this._status="CLAIMED",this._updateBody(this._bodyForStatus("CLAIMED")),this._bindModalButtons(),this.emit("qrauth:claimed",{sessionId:r?.sessionId,status:r?.status,scopes:r?.scopes,metadata:r?.metadata,useCount:r?.useCount,maxUses:r?.maxUses}),this.display==="button"&&setTimeout(()=>this._closeModal(),2200);break}case"EXPIRED":this._clearTimers(),this._status="EXPIRED",this._updateBody(this._bodyForStatus("EXPIRED")),this._bindModalButtons(),this.emit("qrauth:expired");break;case"REVOKED":this._clearTimers(),this._status="REVOKED",this._updateBody(this._bodyForStatus("REVOKED")),this._bindModalButtons(),this.emit("qrauth:revoked");break}}_startCountdown(){this._timerInterval=setInterval(()=>{let t=this.shadow.getElementById("timer");if(!t||!this._expiresAt)return;let r=Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3));t.textContent=r>0?this._formatTimer(r):"",r<=0&&(clearInterval(this._timerInterval),this._timerInterval=null,this._status==="active"&&this._handleStatusChange("EXPIRED",void 0))},1e3)}_formatTimer(t){let r=t??(this._expiresAt?Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3)):0),n=Math.floor(r/60),s=r%60;return`Expires in ${n}:${s<10?"0":""}${s}`}_updateBody(t){let r=this.display==="inline"?this.shadow.getElementById("inline-body"):this.shadow.getElementById("modal-body");r&&(r.innerHTML=t)}_clearTimers(){this._timerInterval&&(clearInterval(this._timerInterval),this._timerInterval=null),this._pollTimeout&&(clearTimeout(this._pollTimeout),this._pollTimeout=null)}};customElements.define("qrauth-ephemeral",W);var pt=`<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
903
903
|
<path d="M48 24 H152 Q166 24 166 38 V108 Q166 156 100 182 Q34 156 34 108 V38 Q34 24 48 24 Z"
|
|
904
904
|
fill="none" stroke="#fff" stroke-width="5"/>
|
|
905
905
|
<g fill="#fff" opacity="0.2">
|
|
@@ -916,12 +916,12 @@ Minimum version required to store current data is: `+s+`.
|
|
|
916
916
|
<path d="M62 104 L88 134 L144 64"
|
|
917
917
|
fill="none" stroke="#fff" stroke-width="15"
|
|
918
918
|
stroke-linecap="round" stroke-linejoin="round"/>
|
|
919
|
-
</svg>`,
|
|
919
|
+
</svg>`,je=`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
920
920
|
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" fill="currentColor"/>
|
|
921
|
-
</svg>`,
|
|
921
|
+
</svg>`,Zr=`<svg class="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
922
922
|
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2.5"
|
|
923
923
|
stroke-dasharray="31.416" stroke-dashoffset="10" stroke-linecap="round"/>
|
|
924
|
-
</svg>`,Z=class extends
|
|
924
|
+
</svg>`,Z=class extends x{constructor(){super(...arguments);p(this,"_sessionId",null);p(this,"_sessionToken",null);p(this,"_codeVerifier",null);p(this,"_status","idle");p(this,"_expiresAt",null);p(this,"_currentQrUrl",null);p(this,"_timerInterval",null);p(this,"_pollTimeout",null)}static get observedAttributes(){return[...super.observedAttributes,"session-token","scopes","auto-start","redirect-uri"]}get sessionToken(){return this.getAttribute("session-token")}get scopes(){return this.getAttribute("scopes")||"identity"}get autoStart(){return this.hasAttribute("auto-start")}get redirectUri(){return this.getAttribute("redirect-uri")}get forceMode(){let t=this.getAttribute("force-mode");return t==="mobile"||t==="desktop"?t:"auto"}get mobileFallbackOnly(){return this.hasAttribute("mobile-fallback-only")}connectedCallback(){super.connectedCallback(),this.autoStart&&this._startAuth()}disconnectedCallback(){super.disconnectedCallback(),this._clearTimers()}render(){this.shadow.innerHTML=`
|
|
925
925
|
<style>
|
|
926
926
|
${this.getBaseStyles()}
|
|
927
927
|
:host { display: block; }
|
|
@@ -1004,18 +1004,18 @@ Minimum version required to store current data is: `+s+`.
|
|
|
1004
1004
|
`;switch(t){case"idle":return`
|
|
1005
1005
|
${n}
|
|
1006
1006
|
<div class="state-header">
|
|
1007
|
-
<div class="brand-icon">${
|
|
1007
|
+
<div class="brand-icon">${pt}</div>
|
|
1008
1008
|
<h3>Verify your identity</h3>
|
|
1009
1009
|
<p class="subtitle">Scan the QR code with your phone to confirm it's you</p>
|
|
1010
1010
|
</div>
|
|
1011
1011
|
<button class="start-btn" id="start-btn" aria-label="Start 2FA verification">
|
|
1012
|
-
<span class="btn-icon">${
|
|
1012
|
+
<span class="btn-icon">${pt}</span>
|
|
1013
1013
|
Verify your identity
|
|
1014
1014
|
</button>
|
|
1015
1015
|
`;case"loading":return`
|
|
1016
1016
|
${n}
|
|
1017
1017
|
<div class="state-loading">
|
|
1018
|
-
<div class="spinner-wrap">${
|
|
1018
|
+
<div class="spinner-wrap">${Zr}</div>
|
|
1019
1019
|
<p class="status-text">Generating QR code...</p>
|
|
1020
1020
|
</div>
|
|
1021
1021
|
`;case"pending":case"SCANNED":{if(this.isMobileLike())return this._mobilePendingBody(t,r,n);let s=t==="SCANNED";return`
|
|
@@ -1030,7 +1030,7 @@ Minimum version required to store current data is: `+s+`.
|
|
|
1030
1030
|
<div class="footer">Secured by <a href="https://qrauth.io" target="_blank" rel="noopener">QRAuth</a></div>
|
|
1031
1031
|
`}case"APPROVED":return`
|
|
1032
1032
|
<div class="state-approved">
|
|
1033
|
-
<div class="success-icon">${
|
|
1033
|
+
<div class="success-icon">${je}</div>
|
|
1034
1034
|
<h3>Identity verified!</h3>
|
|
1035
1035
|
<p class="subtitle">Second factor confirmed</p>
|
|
1036
1036
|
</div>
|
|
@@ -1052,21 +1052,21 @@ Minimum version required to store current data is: `+s+`.
|
|
|
1052
1052
|
<div class="state-error">
|
|
1053
1053
|
<div class="error-icon">⚠</div>
|
|
1054
1054
|
<h3>Something went wrong</h3>
|
|
1055
|
-
<p class="subtitle"
|
|
1055
|
+
<p class="subtitle">Failed to start verification.</p>
|
|
1056
1056
|
<button class="retry-btn" id="retry-btn">Try again</button>
|
|
1057
1057
|
</div>
|
|
1058
1058
|
`;default:return""}}_qrFrameHtml(t,r){let n=$(t,320);return`
|
|
1059
1059
|
<div class="qr-frame ${r?"scanned":""}">
|
|
1060
1060
|
<div class="qr-image" role="img" aria-label="QR Code for 2FA verification">${n}</div>
|
|
1061
|
-
<div class="qr-badge">${
|
|
1062
|
-
${r?'<div class="scanned-overlay"><span class="scanned-check">'+
|
|
1061
|
+
<div class="qr-badge">${pt}</div>
|
|
1062
|
+
${r?'<div class="scanned-overlay"><span class="scanned-check">'+je+"</span></div>":""}
|
|
1063
1063
|
</div>
|
|
1064
1064
|
`}_mobilePendingBody(t,r,n=""){let s=t==="SCANNED";return`
|
|
1065
1065
|
${n}
|
|
1066
1066
|
<h3>Verify your identity</h3>
|
|
1067
1067
|
<p class="subtitle">Tap continue to verify on this device.</p>
|
|
1068
1068
|
<button class="mobile-cta" id="mobile-cta" type="button">
|
|
1069
|
-
<span class="btn-icon">${
|
|
1069
|
+
<span class="btn-icon">${pt}</span>
|
|
1070
1070
|
Continue with QRAuth
|
|
1071
1071
|
</button>
|
|
1072
1072
|
<div class="status-text ${s?"status-scanned":""}">
|
|
@@ -1310,5 +1310,5 @@ Minimum version required to store current data is: `+s+`.
|
|
|
1310
1310
|
}
|
|
1311
1311
|
.footer a { color: var(--_disabled); text-decoration: none; }
|
|
1312
1312
|
.footer a:hover { text-decoration: underline; }
|
|
1313
|
-
`}_bindBodyEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>this._startAuth()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry()),this.shadow.getElementById("mobile-cta")?.addEventListener("click",()=>this._openApprovalPage())}_openApprovalPage(){if(!this._sessionToken)return;let t=new URL(`${this.baseUrl}/a/${this._sessionToken}`);t.searchParams.set("dr","1");let r=t.toString();window.open(r,"_blank","noopener")||(window.location.href=r)}async _startAuth(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{this._codeVerifier=await this.generateCodeVerifier();let t=await this.computeCodeChallenge(this._codeVerifier),r={"Content-Type":"application/json","X-Client-Id":this.tenant},n={scopes:this.scopes.split(/\s+/).filter(Boolean),codeChallenge:t,codeChallengeMethod:"S256"};this.redirectUri&&(n.redirectUrl=this.redirectUri);let s=await fetch(`${this.baseUrl}/api/v1/auth-sessions`,{method:"POST",headers:r,body:JSON.stringify(n)});if(!s.ok){let a=await s.json().catch(()=>({message:"Failed to create session"}));throw new Error(a.message??"Failed to create session")}let o=await s.json();this._sessionId=o.sessionId,this._sessionToken=o.token||(o.qrUrl?o.qrUrl.split("/").pop()??null:null),this._expiresAt=new Date(o.expiresAt).getTime(),this._currentQrUrl=o.qrUrl??null,this._status="pending",this._updateBody(this._bodyForStatus("pending",{qrUrl:o.qrUrl})),this._bindBodyEvents(),this._startCountdown(),this._beginPolling(o.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error",
|
|
1313
|
+
`}_bindBodyEvents(){this.shadow.getElementById("start-btn")?.addEventListener("click",()=>this._startAuth()),this.shadow.getElementById("retry-btn")?.addEventListener("click",()=>this._retry()),this.shadow.getElementById("mobile-cta")?.addEventListener("click",()=>this._openApprovalPage())}_openApprovalPage(){if(!this._sessionToken)return;let t=new URL(`${this.baseUrl}/a/${this._sessionToken}`);t.searchParams.set("dr","1");let r=t.toString();window.open(r,"_blank","noopener")||(window.location.href=r)}async _startAuth(){this._status="loading",this._updateBody(this._bodyForStatus("loading"));try{this._codeVerifier=await this.generateCodeVerifier();let t=await this.computeCodeChallenge(this._codeVerifier),r={"Content-Type":"application/json","X-Client-Id":this.tenant},n={scopes:this.scopes.split(/\s+/).filter(Boolean),codeChallenge:t,codeChallengeMethod:"S256"};this.redirectUri&&(n.redirectUrl=this.redirectUri);let s=await fetch(`${this.baseUrl}/api/v1/auth-sessions`,{method:"POST",headers:r,body:JSON.stringify(n)});if(!s.ok){let a=await s.json().catch(()=>({message:"Failed to create session"}));throw new Error(a.message??"Failed to create session")}let o=await s.json();this._sessionId=o.sessionId,this._sessionToken=o.token||(o.qrUrl?o.qrUrl.split("/").pop()??null:null),this._expiresAt=new Date(o.expiresAt).getTime(),this._currentQrUrl=o.qrUrl??null,this._status="pending",this._updateBody(this._bodyForStatus("pending",{qrUrl:o.qrUrl})),this._bindBodyEvents(),this._startCountdown(),this._beginPolling(o.sessionId)}catch(t){let r=t instanceof Error?t.message:"Unexpected error";this._status="error",this._updateBody(this._bodyForStatus("error")),this.setErrorText(r),this._bindBodyEvents(),this.emit("qrauth:error",{message:r})}}_retry(){this._clearTimers(),this._sessionId=null,this._sessionToken=null,this._codeVerifier=null,this._status="idle",this._expiresAt=null,this._currentQrUrl=null,this._updateBody(this._bodyForStatus("idle")),this._bindBodyEvents()}_beginPolling(t){let r="PENDING",n=2e3,s=5e3,o=0,a=20,l=async()=>{if(!this._sessionId)return;let d=`${this.baseUrl}/api/v1/auth-sessions/${t}`,c={"X-Client-Id":this.tenant};this._codeVerifier&&(c[tt]=this._codeVerifier);try{let u=await(await fetch(d,{headers:c})).json();if(o=0,n=2e3,u.status!==r&&(r=u.status,this._handleStatusChange(u.status,u),["APPROVED","DENIED","EXPIRED"].includes(u.status)))return;this._pollTimeout=setTimeout(l,n)}catch{if(o++,o>=a){this._handleStatusChange("EXPIRED",void 0);return}n=Math.min(n*1.5,s),this._pollTimeout=setTimeout(l,n)}};this._pollTimeout=setTimeout(l,n)}_handleStatusChange(t,r){switch(this._status=t,t){case"SCANNED":{this._updateBody(this._bodyForStatus("SCANNED",{qrUrl:this._currentQrUrl??"",timerHtml:this._formatTimer()})),this._bindBodyEvents();break}case"APPROVED":{if(this._clearTimers(),this.isApprovalWithoutIdentity(!!this._codeVerifier,r)){let n="Verification could not be confirmed. Please try again.";this._status="error",this._updateBody(this._bodyForStatus("error")),this.setErrorText(n),this.emit("qrauth:error",{message:n});break}this._updateBody(this._bodyForStatus("APPROVED")),this.emit("qrauth:verified",{sessionId:r?.sessionId,user:r?.user,signature:r?.signature});break}case"DENIED":this._clearTimers(),this._updateBody(this._bodyForStatus("DENIED")),this._bindBodyEvents(),this.emit("qrauth:denied");break;case"EXPIRED":this._clearTimers(),this._status="EXPIRED",this._updateBody(this._bodyForStatus("EXPIRED")),this._bindBodyEvents(),this.emit("qrauth:expired");break}}_startCountdown(){this._timerInterval=setInterval(()=>{let t=this.shadow.getElementById("timer");if(!t||!this._expiresAt)return;let r=Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3));t.textContent=r>0?this._formatTimer(r):"",r<=0&&(clearInterval(this._timerInterval),this._timerInterval=null,(this._status==="pending"||this._status==="SCANNED")&&this._handleStatusChange("EXPIRED",void 0))},1e3)}_formatTimer(t){let r=t??(this._expiresAt?Math.max(0,Math.floor((this._expiresAt-Date.now())/1e3)):0),n=Math.floor(r/60),s=r%60;return`Expires in ${n}:${s<10?"0":""}${s}`}_updateBody(t){let r=this.shadow.getElementById("body");r&&(r.innerHTML=t)}_clearTimers(){this._timerInterval&&(clearInterval(this._timerInterval),this._timerInterval=null),this._pollTimeout&&(clearTimeout(this._pollTimeout),this._pollTimeout=null)}};customElements.define("qrauth-2fa",Z);return rr(ti);})();
|
|
1314
1314
|
//# sourceMappingURL=qrauth-components.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qrauth/web-components",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "QRAuth Web Components — drop-in authentication elements",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/qrauth-components.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dev": "tsc --watch",
|
|
26
26
|
"test": "vitest run",
|
|
27
27
|
"test:watch": "vitest",
|
|
28
|
-
"prepublishOnly": "npm run build"
|
|
28
|
+
"prepublishOnly": "npm run build && (grep -rEl \"https?://api\\.qrserver\\.com\" dist/ && echo 'qrserver host in dist — refusing to publish' && exit 1 || true)"
|
|
29
29
|
},
|
|
30
30
|
"keywords": [
|
|
31
31
|
"qrauth",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/qrcode": "^1.5.5",
|
|
57
|
-
"esbuild": "
|
|
58
|
-
"happy-dom": "^
|
|
59
|
-
"typescript": "
|
|
57
|
+
"esbuild": "0.28.0",
|
|
58
|
+
"happy-dom": "^20.10.2",
|
|
59
|
+
"typescript": "5.9.3",
|
|
60
60
|
"vitest": "^2.1.9"
|
|
61
61
|
}
|
|
62
62
|
}
|