@rift-finance/react 0.2.0 → 0.3.0

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.
@@ -29,6 +29,6 @@ interface RiftProviderProps extends RiftConfig {
29
29
  autoOpen?: boolean;
30
30
  persist?: boolean;
31
31
  }
32
- export declare function RiftProvider({ apiKey, widgetUrl, children, autoOpen, persist, }: RiftProviderProps): import("react/jsx-runtime").JSX.Element;
32
+ export declare function RiftProvider({ apiKey, environment, widgetUrl, children, autoOpen, persist, }: RiftProviderProps): import("react/jsx-runtime").JSX.Element;
33
33
  export {};
34
34
  //# sourceMappingURL=RiftProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RiftProvider.d.ts","sourceRoot":"","sources":["../src/RiftProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,UAAU,EAAa,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAuBzE,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3C,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAID,wBAAgB,cAAc,IAAI,gBAAgB,CAQjD;AAED,UAAU,iBAAkB,SAAQ,UAAU;IAC5C,QAAQ,EAAE,SAAS,CAAC;IAGpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsBD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,OAAc,GACf,EAAE,iBAAiB,2CAoRnB"}
1
+ {"version":3,"file":"RiftProvider.d.ts","sourceRoot":"","sources":["../src/RiftProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,UAAU,EAAa,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAiCzE,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3C,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAID,wBAAgB,cAAc,IAAI,gBAAgB,CAQjD;AAED,UAAU,iBAAkB,SAAQ,UAAU;IAC5C,QAAQ,EAAE,SAAS,CAAC;IAGpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsBD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAgB,EAChB,OAAc,GACf,EAAE,iBAAiB,2CAqRnB"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("react/jsx-runtime"),r=require("react");let f=null,O=!1,M=[],A=null;const d=new Map;function z(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,9)}`}function Y(e){if(typeof document>"u")return Promise.reject(new Error("Cannot mount refresh iframe outside the browser"));if(f&&O)return Promise.resolve();if(A=new URL(e.widgetUrl).origin,!f){f=document.createElement("iframe"),f.setAttribute("aria-hidden","true"),f.setAttribute("tabindex","-1"),f.title="Rift session refresh",f.style.cssText="position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;";const o=new URLSearchParams({key:e.apiKey,headless:"1"});f.src=`${e.widgetUrl.replace(/\/$/,"")}/?${o.toString()}`,document.body.appendChild(f),window.addEventListener("message",a=>{if(a.origin!==A)return;const t=a.data;if(!(!t||typeof t!="object"||typeof t.type!="string")&&t.type.startsWith("rift:")){if(t.type==="rift:ready"){O=!0,M.forEach(n=>n()),M=[];return}if(t.type==="rift:refresh-result"){const n=d.get(t.requestId);n&&(d.delete(t.requestId),n.resolve({accessToken:t.accessToken,expiresAt:t.expiresAt,expiresIn:t.expiresIn}));return}if(t.type==="rift:refresh-error"){const n=d.get(t.requestId);n&&(d.delete(t.requestId),n.reject(new Error(t.message||"Refresh failed")));return}if(t.type==="rift:logout-result"){const n=d.get(t.requestId);n&&(d.delete(t.requestId),n.resolve({accessToken:"",expiresAt:"",expiresIn:0}))}}})}return O?Promise.resolve():new Promise(o=>{M.push(o),setTimeout(()=>{if(!O){const a=M.shift();a&&a()}},8e3)})}async function N(e){if(await Y(e),!f?.contentWindow||!A)throw new Error("Refresh iframe is not available");const o=z();return new Promise((a,t)=>{d.set(o,{resolve:a,reject:t}),f.contentWindow.postMessage({type:"rift:refresh-request",requestId:o},A),setTimeout(()=>{const n=d.get(o);n&&(d.delete(o),n.reject(new Error("Refresh timed out")))},1e4)})}async function V(e){try{if(await Y(e),!f?.contentWindow||!A)return;const o=z();await new Promise(a=>{d.set(o,{resolve:()=>a(),reject:()=>a()}),f.contentWindow.postMessage({type:"rift:logout-request",requestId:o},A),setTimeout(()=>{d.delete(o),a()},5e3)})}catch{}}const Z="https://widget.riftfi.xyz",q="rift:identity",K=60,G=r.createContext(null);function J(){const e=r.useContext(G);if(!e)throw new Error("[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>");return e}function ee(){if(typeof window>"u")return null;try{const e=localStorage.getItem(q);return e?JSON.parse(e):null}catch{return null}}function te(e){if(!(typeof window>"u"))try{e?localStorage.setItem(q,JSON.stringify(e)):localStorage.removeItem(q)}catch{}}function re({apiKey:e,widgetUrl:o,children:a,autoOpen:t=!1,persist:n=!0}){const c=o||Z,p=r.useMemo(()=>{try{return new URL(c).origin}catch{return c}},[c]),[y,P]=r.useState(null),[l,b]=r.useState(!1),[k,D]=r.useState("signin"),[R,E]=r.useState(!1),[S,v]=r.useState(null),[L,U]=r.useState(540),[T,C]=r.useState(0),x=r.useRef(null);x.current=y;const g=r.useRef(null),m=r.useCallback(s=>{P(s),n&&te(s?{user:s.user,address:s.address,btcAddress:s.btcAddress}:null)},[n]);r.useEffect(()=>{if(!n)return;const s=ee();if(!s)return;let u=!0;return(async()=>{try{const i=await N({apiKey:e,widgetUrl:c});if(!u)return;m({user:s.user,address:s.address,btcAddress:s.btcAddress,accessToken:i.accessToken,expiresAt:i.expiresAt})}catch{if(!u)return;m(null)}})(),()=>{u=!1}},[]);const j=r.useCallback(s=>{D(s?.mode||"signin"),v(null),E(!1),C(u=>u+1),b(!0)},[]),_=r.useCallback(()=>{b(!1),E(!1)},[]),W=r.useCallback(async()=>{await V({apiKey:e,widgetUrl:c}),m(null)},[e,c,m]),F=r.useCallback(async()=>{const s=x.current;if(!s)throw new Error("Not signed in");const u=s.expiresAt?new Date(s.expiresAt).getTime():null,i=Date.now();return!(!u||u-i<K*1e3)&&s.accessToken?s.accessToken:(g.current||(g.current=(async()=>{try{const w=await N({apiKey:e,widgetUrl:c}),B=x.current;if(!B)throw new Error("Signed out during refresh");const Q={...B,accessToken:w.accessToken,expiresAt:w.expiresAt};return m(Q),w.accessToken}catch(w){throw m(null),w instanceof Error?w:new Error(String(w))}finally{g.current=null}})()),g.current)},[e,c,m]);r.useEffect(()=>{if(typeof window>"u")return;const s=u=>{if(u.origin!==p)return;const i=u.data;if(!(!i||typeof i!="object"||typeof i.type!="string")&&i.type.startsWith("rift:"))switch(i.type){case"rift:ready":l&&E(!0);break;case"rift:close":_();break;case"rift:resize":U(Math.max(360,Math.min(820,i.height+8)));break;case"rift:signin-success":{const h={user:i.user,address:i.address,btcAddress:i.btcAddress,accessToken:i.accessToken,expiresAt:i.expiresAt};m(h),b(!1);break}case"rift:signin-error":v(i.message);break}};return window.addEventListener("message",s),()=>window.removeEventListener("message",s)},[p,_,m,l]),r.useEffect(()=>{if(!(typeof document>"u")&&l){const s=document.documentElement.style.overflow;return document.documentElement.style.overflow="hidden",()=>{document.documentElement.style.overflow=s}}},[l]),r.useEffect(()=>{t&&!y&&j()},[]);const $=r.useMemo(()=>{const s=new URLSearchParams({key:e,mode:k,origin:typeof window<"u"?window.location.origin:"",t:String(T)});if(typeof document<"u"){const u=document.documentElement,i=u.getAttribute("data-theme");let h=null;i==="dark"||i==="light"?h=i:(u.classList.contains("dark")||document.body?.classList.contains("dark")||window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)&&(h="dark"),h&&s.set("theme",h)}return`${c.replace(/\/$/,"")}/?${s.toString()}`},[e,k,T,c]),H=r.useCallback(()=>{},[]),X=r.useMemo(()=>({apiKey:e,widgetUrl:c,user:y,isOpen:l,isReady:R,error:S,open:j,close:_,signOut:W,getAccessToken:F,_iframeSrc:$,_iframeHeight:L,_onIframeLoad:H}),[e,c,y,l,R,S,j,_,W,F,$,L,H]);return I.jsx(G.Provider,{value:X,children:a})}const se="rgba(15,15,20,0.55)",ne=6,ie=480,oe=18;function ae({onSuccess:e,onError:o,onClose:a,maxHeight:t,maxWidth:n=ie,radius:c=oe,backdrop:p,backdropStyle:y,iframeStyle:P}){const{isOpen:l,isReady:b,error:k,close:D,user:R,_iframeSrc:E,_iframeHeight:S,_onIframeLoad:v}=J();if(r.useEffect(()=>{R&&e&&e(R)},[R,e]),r.useEffect(()=>{k&&o&&o(k)},[k,o]),r.useEffect(()=>{!l&&a&&a()},[l]),!l)return null;const L=p?.color??se,U=p?.blur??ne,T=U>0?`blur(${U}px)`:void 0;let C=S,x;return typeof t=="number"?C=Math.min(S,t):typeof t=="string"&&(x=t),I.jsxs("div",{role:"dialog","aria-modal":"true","aria-label":"Sign in",onClick:g=>{g.target===g.currentTarget&&D()},style:{position:"fixed",inset:0,zIndex:2147483646,background:L,backdropFilter:T,WebkitBackdropFilter:T,display:"flex",alignItems:"center",justifyContent:"center",padding:16,animation:"rift-fade 180ms ease-out",...y},children:[I.jsx("style",{children:"@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }"}),!b&&I.jsx("div",{"aria-hidden":!0,style:{position:"absolute",color:"rgba(255,255,255,0.75)",fontSize:13,fontFamily:"Inter, ui-sans-serif, system-ui, sans-serif"},children:"Loading sign-in…"}),I.jsx("iframe",{src:E,onLoad:v,title:"Rift sign-in",allow:"publickey-credentials-get; identity-credentials-get",style:{border:0,background:"transparent",colorScheme:"light",width:"100%",maxWidth:n,height:C,maxHeight:x,borderRadius:c,boxShadow:"0 24px 60px -12px rgba(0,0,0,0.35)",transition:"height 200ms ease",opacity:b?1:0,...P}})]})}function ce(){const{user:e,isOpen:o,open:a,close:t,signOut:n,getAccessToken:c,error:p}=J();return{user:e,isAuthenticated:!!e,isOpen:o,open:a,close:t,signOut:n,getAccessToken:c,error:p}}exports.RiftAuth=ae;exports.RiftProvider=re;exports.useRift=ce;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("react/jsx-runtime"),r=require("react");let d=null,j=!1,D=[],x=null;const f=new Map;function Y(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,9)}`}function G(e){if(typeof document>"u")return Promise.reject(new Error("Cannot mount refresh iframe outside the browser"));if(d&&j)return Promise.resolve();if(x=new URL(e.widgetUrl).origin,!d){d=document.createElement("iframe"),d.setAttribute("aria-hidden","true"),d.setAttribute("tabindex","-1"),d.title="Rift session refresh",d.style.cssText="position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;";const i=new URLSearchParams({key:e.apiKey,headless:"1"});d.src=`${e.widgetUrl.replace(/\/$/,"")}/?${i.toString()}`,document.body.appendChild(d),window.addEventListener("message",a=>{if(a.origin!==x)return;const t=a.data;if(!(!t||typeof t!="object"||typeof t.type!="string")&&t.type.startsWith("rift:")){if(t.type==="rift:ready"){j=!0,D.forEach(o=>o()),D=[];return}if(t.type==="rift:refresh-result"){const o=f.get(t.requestId);o&&(f.delete(t.requestId),o.resolve({accessToken:t.accessToken,expiresAt:t.expiresAt,expiresIn:t.expiresIn}));return}if(t.type==="rift:refresh-error"){const o=f.get(t.requestId);o&&(f.delete(t.requestId),o.reject(new Error(t.message||"Refresh failed")));return}if(t.type==="rift:logout-result"){const o=f.get(t.requestId);o&&(f.delete(t.requestId),o.resolve({accessToken:"",expiresAt:"",expiresIn:0}))}}})}return j?Promise.resolve():new Promise(i=>{D.push(i),setTimeout(()=>{if(!j){const a=D.shift();a&&a()}},8e3)})}async function z(e){if(await G(e),!d?.contentWindow||!x)throw new Error("Refresh iframe is not available");const i=Y();return new Promise((a,t)=>{f.set(i,{resolve:a,reject:t}),d.contentWindow.postMessage({type:"rift:refresh-request",requestId:i},x),setTimeout(()=>{const o=f.get(i);o&&(f.delete(i),o.reject(new Error("Refresh timed out")))},1e4)})}async function Z(e){try{if(await G(e),!d?.contentWindow||!x)return;const i=Y();await new Promise(a=>{f.set(i,{resolve:()=>a(),reject:()=>a()}),d.contentWindow.postMessage({type:"rift:logout-request",requestId:i},x),setTimeout(()=>{f.delete(i),a()},5e3)})}catch{}}const K={production:"https://widget.riftfi.xyz",sandbox:"https://widget.sandbox.riftfi.com"},W="rift:identity",ee=60,J=r.createContext(null);function V(){const e=r.useContext(J);if(!e)throw new Error("[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>");return e}function te(){if(typeof window>"u")return null;try{const e=localStorage.getItem(W);return e?JSON.parse(e):null}catch{return null}}function re(e){if(!(typeof window>"u"))try{e?localStorage.setItem(W,JSON.stringify(e)):localStorage.removeItem(W)}catch{}}function se({apiKey:e,environment:i,widgetUrl:a,children:t,autoOpen:o=!1,persist:h=!0}){const c=a||K[i??"production"],v=r.useMemo(()=>{try{return new URL(c).origin}catch{return c}},[c]),[y,R]=r.useState(null),[l,p]=r.useState(!1),[L,A]=r.useState("signin"),[_,b]=r.useState(!1),[C,U]=r.useState(null),[E,O]=r.useState(540),[S,M]=r.useState(0),k=r.useRef(null);k.current=y;const T=r.useRef(null),m=r.useCallback(s=>{R(s),h&&re(s?{user:s.user,address:s.address,btcAddress:s.btcAddress}:null)},[h]);r.useEffect(()=>{if(!h)return;const s=te();if(!s)return;let u=!0;return(async()=>{try{const n=await z({apiKey:e,widgetUrl:c});if(!u)return;m({user:s.user,address:s.address,btcAddress:s.btcAddress,accessToken:n.accessToken,expiresAt:n.expiresAt})}catch{if(!u)return;m(null)}})(),()=>{u=!1}},[]);const q=r.useCallback(s=>{A(s?.mode||"signin"),U(null),b(!1),M(u=>u+1),p(!0)},[]),P=r.useCallback(()=>{p(!1),b(!1)},[]),F=r.useCallback(async()=>{await Z({apiKey:e,widgetUrl:c}),m(null)},[e,c,m]),$=r.useCallback(async()=>{const s=k.current;if(!s)throw new Error("Not signed in");const u=s.expiresAt?new Date(s.expiresAt).getTime():null,n=Date.now();return!(!u||u-n<ee*1e3)&&s.accessToken?s.accessToken:(T.current||(T.current=(async()=>{try{const w=await z({apiKey:e,widgetUrl:c}),N=k.current;if(!N)throw new Error("Signed out during refresh");const Q={...N,accessToken:w.accessToken,expiresAt:w.expiresAt};return m(Q),w.accessToken}catch(w){throw m(null),w instanceof Error?w:new Error(String(w))}finally{T.current=null}})()),T.current)},[e,c,m]);r.useEffect(()=>{if(typeof window>"u")return;const s=u=>{if(u.origin!==v)return;const n=u.data;if(!(!n||typeof n!="object"||typeof n.type!="string")&&n.type.startsWith("rift:"))switch(n.type){case"rift:ready":l&&b(!0);break;case"rift:close":P();break;case"rift:resize":O(Math.max(360,Math.min(820,n.height+8)));break;case"rift:signin-success":{const g={user:n.user,address:n.address,btcAddress:n.btcAddress,accessToken:n.accessToken,expiresAt:n.expiresAt};m(g),p(!1);break}case"rift:signin-error":U(n.message);break}};return window.addEventListener("message",s),()=>window.removeEventListener("message",s)},[v,P,m,l]),r.useEffect(()=>{if(!(typeof document>"u")&&l){const s=document.documentElement.style.overflow;return document.documentElement.style.overflow="hidden",()=>{document.documentElement.style.overflow=s}}},[l]),r.useEffect(()=>{o&&!y&&q()},[]);const B=r.useMemo(()=>{const s=new URLSearchParams({key:e,mode:L,origin:typeof window<"u"?window.location.origin:"",t:String(S)});if(typeof document<"u"){const u=document.documentElement,n=u.getAttribute("data-theme");let g=null;n==="dark"||n==="light"?g=n:(u.classList.contains("dark")||document.body?.classList.contains("dark")||window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)&&(g="dark"),g&&s.set("theme",g)}return`${c.replace(/\/$/,"")}/?${s.toString()}`},[e,L,S,c]),H=r.useCallback(()=>{},[]),X=r.useMemo(()=>({apiKey:e,widgetUrl:c,user:y,isOpen:l,isReady:_,error:C,open:q,close:P,signOut:F,getAccessToken:$,_iframeSrc:B,_iframeHeight:E,_onIframeLoad:H}),[e,c,y,l,_,C,q,P,F,$,B,E,H]);return I.jsx(J.Provider,{value:X,children:t})}const ne="rgba(15,15,20,0.55)",ie=6,oe=480,ae=18;function ce({onSuccess:e,onError:i,onClose:a,maxHeight:t,maxWidth:o=oe,radius:h=ae,backdrop:c,backdropStyle:v,iframeStyle:y}){const{isOpen:R,isReady:l,error:p,close:L,user:A,_iframeSrc:_,_iframeHeight:b,_onIframeLoad:C}=V();if(r.useEffect(()=>{A&&e&&e(A)},[A,e]),r.useEffect(()=>{p&&i&&i(p)},[p,i]),r.useEffect(()=>{!R&&a&&a()},[R]),!R)return null;const U=c?.color??ne,E=c?.blur??ie,O=E>0?`blur(${E}px)`:void 0;let S=b,M;return typeof t=="number"?S=Math.min(b,t):typeof t=="string"&&(M=t),I.jsxs("div",{role:"dialog","aria-modal":"true","aria-label":"Sign in",onClick:k=>{k.target===k.currentTarget&&L()},style:{position:"fixed",inset:0,zIndex:2147483646,background:U,backdropFilter:O,WebkitBackdropFilter:O,display:"flex",alignItems:"center",justifyContent:"center",padding:16,animation:"rift-fade 180ms ease-out",...v},children:[I.jsx("style",{children:"@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }"}),!l&&I.jsx("div",{"aria-hidden":!0,style:{position:"absolute",color:"rgba(255,255,255,0.75)",fontSize:13,fontFamily:"Inter, ui-sans-serif, system-ui, sans-serif"},children:"Loading sign-in…"}),I.jsx("iframe",{src:_,onLoad:C,title:"Rift sign-in",allow:"publickey-credentials-get; identity-credentials-get",style:{border:0,background:"transparent",colorScheme:"light",width:"100%",maxWidth:o,height:S,maxHeight:M,borderRadius:h,boxShadow:"0 24px 60px -12px rgba(0,0,0,0.35)",transition:"height 200ms ease",opacity:l?1:0,...y}})]})}function ue(){const{user:e,isOpen:i,open:a,close:t,signOut:o,getAccessToken:h,error:c}=V();return{user:e,isAuthenticated:!!e,isOpen:i,open:a,close:t,signOut:o,getAccessToken:h,error:c}}exports.RiftAuth=ce;exports.RiftProvider=se;exports.useRift=ue;
2
2
  //# sourceMappingURL=rift-react.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"rift-react.cjs","sources":["../src/silentRefresh.ts","../src/RiftProvider.tsx","../src/RiftAuth.tsx","../src/useRift.ts"],"sourcesContent":["/**\n * Silent-refresh bridge.\n *\n * The v2 backend session sits behind an httpOnly refresh cookie scoped\n * to the widget origin (widget.riftfi.xyz → service.riftfi.xyz). The\n * cookie cannot be read or sent from the merchant's own JS — only\n * widget-origin code can use it. So to refresh, we mount a HIDDEN\n * widget iframe in `?headless=1` mode and ask it (via postMessage) to\n * call /auth/refresh on our behalf. It posts the new access token back.\n *\n * This module owns that iframe as a singleton: we lazily create it on\n * the first refresh request, keep it alive across the page's lifetime,\n * and use a requestId-based pending map so concurrent refresh calls\n * dedupe to one network round trip.\n */\n\nlet iframe: HTMLIFrameElement | null = null;\nlet ready = false;\nlet readyResolvers: Array<() => void> = [];\nlet widgetOrigin: string | null = null;\n\ninterface Pending {\n resolve: (value: RefreshSuccess) => void;\n reject: (err: Error) => void;\n}\nconst pending = new Map<string, Pending>();\n\nexport interface RefreshSuccess {\n accessToken: string;\n expiresAt: string;\n expiresIn: number;\n}\n\nfunction uuid(): string {\n // Lightweight ID — doesn't need crypto strength, just unique per page.\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction ensureMounted(opts: { apiKey: string; widgetUrl: string }): Promise<void> {\n if (typeof document === \"undefined\") {\n return Promise.reject(new Error(\"Cannot mount refresh iframe outside the browser\"));\n }\n if (iframe && ready) return Promise.resolve();\n\n widgetOrigin = new URL(opts.widgetUrl).origin;\n\n if (!iframe) {\n iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.setAttribute(\"tabindex\", \"-1\");\n iframe.title = \"Rift session refresh\";\n iframe.style.cssText =\n \"position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;\";\n const params = new URLSearchParams({\n key: opts.apiKey,\n headless: \"1\",\n });\n iframe.src = `${opts.widgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n document.body.appendChild(iframe);\n\n window.addEventListener(\"message\", (e) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n if (data.type === \"rift:ready\") {\n ready = true;\n readyResolvers.forEach((r) => r());\n readyResolvers = [];\n return;\n }\n if (data.type === \"rift:refresh-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n expiresIn: data.expiresIn,\n });\n }\n return;\n }\n if (data.type === \"rift:refresh-error\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.reject(new Error(data.message || \"Refresh failed\"));\n }\n return;\n }\n if (data.type === \"rift:logout-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({ accessToken: \"\", expiresAt: \"\", expiresIn: 0 });\n }\n }\n });\n }\n\n if (ready) return Promise.resolve();\n return new Promise((resolve) => {\n readyResolvers.push(resolve);\n // Safety net: if the iframe somehow never posts ready (e.g. blocked\n // by browser privacy mode), reject after 8s so callers can surface\n // a useful error.\n setTimeout(() => {\n if (!ready) {\n const r = readyResolvers.shift();\n if (r) r();\n }\n }, 8000);\n });\n}\n\nexport async function silentRefresh(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<RefreshSuccess> {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) {\n throw new Error(\"Refresh iframe is not available\");\n }\n const requestId = uuid();\n return new Promise<RefreshSuccess>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:refresh-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n const slot = pending.get(requestId);\n if (slot) {\n pending.delete(requestId);\n slot.reject(new Error(\"Refresh timed out\"));\n }\n }, 10000);\n });\n}\n\nexport async function silentLogout(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<void> {\n try {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) return;\n const requestId = uuid();\n await new Promise<void>((resolve) => {\n pending.set(requestId, {\n resolve: () => resolve(),\n reject: () => resolve(), // logout is idempotent — never reject\n });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:logout-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n pending.delete(requestId);\n resolve();\n }, 5000);\n });\n } catch {\n /* logout is best-effort */\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport type { RiftConfig, RiftEvent, RiftMode, RiftUser } from \"./types\";\nimport { silentLogout, silentRefresh } from \"./silentRefresh\";\n\nconst DEFAULT_WIDGET_URL = \"https://widget.riftfi.xyz\";\n\n// v2 session-mode policy: the access token lives in memory only. We\n// persist a small \"identity hint\" (user id, address, btcAddress) so the\n// UI can render an authenticated state on hard reload, but the actual\n// access JWT is re-issued via the refresh cookie. Refresh tokens live\n// in an httpOnly cookie scoped to the widget origin — totally invisible\n// to this code, which is the whole point.\nconst IDENTITY_STORAGE_KEY = \"rift:identity\";\n\ninterface PersistedIdentity {\n user: string;\n address: string;\n btcAddress?: string;\n}\n\n// Refresh proactively this many seconds before the access token expires.\n// Keeps API calls from racing the actual expiry.\nconst REFRESH_LEEWAY_SECONDS = 60;\n\ninterface RiftContextValue {\n apiKey: string;\n widgetUrl: string;\n user: RiftUser | null;\n isOpen: boolean;\n isReady: boolean;\n error: string | null;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Returns a valid access token, refreshing silently if the current\n * one is missing or about to expire. Rejects if the user is signed\n * out or the refresh fails (in which case state is cleared and the\n * caller should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n _iframeSrc: string;\n _iframeHeight: number;\n _onIframeLoad: () => void;\n}\n\nconst RiftContext = createContext<RiftContextValue | null>(null);\n\nexport function useRiftContext(): RiftContextValue {\n const ctx = useContext(RiftContext);\n if (!ctx) {\n throw new Error(\n \"[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>\"\n );\n }\n return ctx;\n}\n\ninterface RiftProviderProps extends RiftConfig {\n children: ReactNode;\n // Auto-open the modal on mount. Most apps will leave this false and call\n // open() in response to a user clicking \"Sign in\".\n autoOpen?: boolean;\n // Restore the persisted identity (just the user id / address — never\n // the access token) on mount, then silently refresh to mint a token.\n // Default: true.\n persist?: boolean;\n}\n\nfunction loadIdentity(): PersistedIdentity | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(IDENTITY_STORAGE_KEY);\n return raw ? (JSON.parse(raw) as PersistedIdentity) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveIdentity(id: PersistedIdentity | null) {\n if (typeof window === \"undefined\") return;\n try {\n if (id) localStorage.setItem(IDENTITY_STORAGE_KEY, JSON.stringify(id));\n else localStorage.removeItem(IDENTITY_STORAGE_KEY);\n } catch {\n /* private mode / quota — non-fatal */\n }\n}\n\nexport function RiftProvider({\n apiKey,\n widgetUrl,\n children,\n autoOpen = false,\n persist = true,\n}: RiftProviderProps) {\n const resolvedWidgetUrl = widgetUrl || DEFAULT_WIDGET_URL;\n const widgetOrigin = useMemo(() => {\n try {\n return new URL(resolvedWidgetUrl).origin;\n } catch {\n return resolvedWidgetUrl;\n }\n }, [resolvedWidgetUrl]);\n\n const [user, setUser] = useState<RiftUser | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [mode, setMode] = useState<RiftMode>(\"signin\");\n const [isReady, setIsReady] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [iframeHeight, setIframeHeight] = useState(540);\n const [openToken, setOpenToken] = useState(0);\n\n // Hot ref to the current user — getAccessToken() reads from this so\n // it never closes over a stale React state snapshot.\n const userRef = useRef<RiftUser | null>(null);\n userRef.current = user;\n\n // Dedupe in-flight refreshes: if multiple API calls hit\n // getAccessToken() simultaneously and the token is stale, we only\n // want one network call.\n const refreshInFlight = useRef<Promise<string> | null>(null);\n\n const setAndPersist = useCallback(\n (next: RiftUser | null) => {\n setUser(next);\n if (persist) {\n saveIdentity(\n next\n ? {\n user: next.user,\n address: next.address,\n btcAddress: next.btcAddress,\n }\n : null\n );\n }\n },\n [persist]\n );\n\n // On mount, if we have a persisted identity, try a silent refresh to\n // rehydrate the access token. If it fails, drop the identity — the\n // user will be prompted to sign in again on first action.\n useEffect(() => {\n if (!persist) return;\n const identity = loadIdentity();\n if (!identity) return;\n let alive = true;\n (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n if (!alive) return;\n setAndPersist({\n user: identity.user,\n address: identity.address,\n btcAddress: identity.btcAddress,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n });\n } catch {\n if (!alive) return;\n // Refresh failed — likely cookie expired or revoked. Clear the\n // identity hint so the UI shows the signed-out state.\n setAndPersist(null);\n }\n })();\n return () => {\n alive = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const open = useCallback((opts?: { mode?: RiftMode }) => {\n setMode(opts?.mode || \"signin\");\n setError(null);\n setIsReady(false);\n setOpenToken((t) => t + 1);\n setIsOpen(true);\n }, []);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setIsReady(false);\n }, []);\n\n const signOut = useCallback(async () => {\n await silentLogout({ apiKey, widgetUrl: resolvedWidgetUrl });\n setAndPersist(null);\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n const getAccessToken = useCallback(async (): Promise<string> => {\n const current = userRef.current;\n if (!current) throw new Error(\"Not signed in\");\n\n const expiresAt = current.expiresAt\n ? new Date(current.expiresAt).getTime()\n : null;\n const now = Date.now();\n const needsRefresh =\n !expiresAt || expiresAt - now < REFRESH_LEEWAY_SECONDS * 1000;\n\n if (!needsRefresh && current.accessToken) {\n return current.accessToken;\n }\n\n if (refreshInFlight.current) {\n return refreshInFlight.current;\n }\n\n refreshInFlight.current = (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n const latest = userRef.current;\n if (!latest) throw new Error(\"Signed out during refresh\");\n const next: RiftUser = {\n ...latest,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n };\n setAndPersist(next);\n return result.accessToken;\n } catch (err: any) {\n // Refresh failed — wipe state so the host UI can prompt re-auth.\n setAndPersist(null);\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n refreshInFlight.current = null;\n }\n })();\n return refreshInFlight.current;\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n // Listen for messages from the VISIBLE login iframe (not the silent\n // refresh one — that one's events are handled inside silentRefresh.ts).\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const handler = (e: MessageEvent) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data as RiftEvent | undefined;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n switch (data.type) {\n case \"rift:ready\":\n // Only treat as \"modal ready\" while it's open — the silent\n // refresh iframe also emits ready, but we don't care here.\n if (isOpen) setIsReady(true);\n break;\n case \"rift:close\":\n close();\n break;\n case \"rift:resize\":\n setIframeHeight(Math.max(360, Math.min(820, data.height + 8)));\n break;\n case \"rift:signin-success\": {\n const next: RiftUser = {\n user: data.user,\n address: data.address,\n btcAddress: data.btcAddress,\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n };\n setAndPersist(next);\n setIsOpen(false);\n break;\n }\n case \"rift:signin-error\":\n setError(data.message);\n break;\n // refresh / logout result events belong to silentRefresh.ts —\n // ignore them here.\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [widgetOrigin, close, setAndPersist, isOpen]);\n\n // Lock host page scroll while the modal is open.\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n if (isOpen) {\n const prev = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n return () => {\n document.documentElement.style.overflow = prev;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (autoOpen && !user) open();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const iframeSrc = useMemo(() => {\n const params = new URLSearchParams({\n key: apiKey,\n mode,\n origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n t: String(openToken),\n });\n\n // Best-effort: match the host page's theme so the modal blends in\n // instead of flashing white over a dark site. Checks data-theme,\n // the `dark` class convention, then system preference.\n if (typeof document !== \"undefined\") {\n const html = document.documentElement;\n const attr = html.getAttribute(\"data-theme\");\n let theme: string | null = null;\n if (attr === \"dark\" || attr === \"light\") theme = attr;\n else if (\n html.classList.contains(\"dark\") ||\n document.body?.classList.contains(\"dark\")\n )\n theme = \"dark\";\n else if (\n window.matchMedia &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n )\n theme = \"dark\";\n if (theme) params.set(\"theme\", theme);\n }\n\n return `${resolvedWidgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n }, [apiKey, mode, openToken, resolvedWidgetUrl]);\n\n const onIframeLoad = useCallback(() => {\n /* readiness is signalled via postMessage, not the load event */\n }, []);\n\n const value = useMemo<RiftContextValue>(\n () => ({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n _iframeSrc: iframeSrc,\n _iframeHeight: iframeHeight,\n _onIframeLoad: onIframeLoad,\n }),\n [\n apiKey,\n resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n iframeSrc,\n iframeHeight,\n onIframeLoad,\n ]\n );\n\n return <RiftContext.Provider value={value}>{children}</RiftContext.Provider>;\n}\n","import { useEffect, type CSSProperties } from \"react\";\nimport { useRiftContext } from \"./RiftProvider\";\nimport type { RiftUser } from \"./types\";\n\ninterface BackdropStyle {\n /** Backdrop fill colour. Default `rgba(15,15,20,0.55)` (dark scrim). */\n color?: string;\n /** CSS `backdrop-filter: blur(<px>)`. Default 6, set 0 to disable. */\n blur?: number;\n}\n\ninterface RiftAuthProps {\n // Optional event hooks so callers don't have to compose useEffect by hand.\n onSuccess?: (user: RiftUser) => void;\n onError?: (message: string) => void;\n onClose?: () => void;\n\n /**\n * Cap the modal height. Pass a number for px (e.g. `600`) or a CSS\n * string for viewport units (`\"70vh\"`). The iframe scrolls\n * internally if its content exceeds this. Defaults to no cap; the\n * widget reports its natural height via postMessage.\n */\n maxHeight?: number | string;\n\n /**\n * Cap the modal width. Defaults to 480 (px). Pass any CSS length.\n */\n maxWidth?: number | string;\n\n /**\n * Corner radius on the modal. Defaults to 18 (px).\n */\n radius?: number | string;\n\n /**\n * Backdrop styling. See `BackdropStyle`. Each field falls back to\n * the default if omitted.\n */\n backdrop?: BackdropStyle;\n\n /**\n * Extra style applied to the backdrop wrapper. Use for things outside\n * the typed `backdrop` knob (custom transitions, z-index, etc.).\n */\n backdropStyle?: CSSProperties;\n\n /**\n * Extra style applied to the iframe. Useful for borders, custom\n * shadows, or filters that the typed props don't cover.\n */\n iframeStyle?: CSSProperties;\n}\n\nconst DEFAULT_BACKDROP_COLOR = \"rgba(15,15,20,0.55)\";\nconst DEFAULT_BACKDROP_BLUR = 6;\nconst DEFAULT_MAX_WIDTH = 480;\nconst DEFAULT_RADIUS = 18;\n\n/**\n * Renders the modal backdrop + iframe whenever the provider's `isOpen` is\n * true. Place this once near the root of your app (typically just inside\n * <RiftProvider>); call `useRift().open()` to show it.\n *\n * All visual knobs are overridable from the host: see `maxHeight`,\n * `maxWidth`, `radius`, `backdrop`, plus escape hatches `backdropStyle`\n * and `iframeStyle` for anything else.\n */\nexport function RiftAuth({\n onSuccess,\n onError,\n onClose,\n maxHeight,\n maxWidth = DEFAULT_MAX_WIDTH,\n radius = DEFAULT_RADIUS,\n backdrop,\n backdropStyle,\n iframeStyle,\n}: RiftAuthProps) {\n const {\n isOpen,\n isReady,\n error,\n close,\n user,\n _iframeSrc,\n _iframeHeight,\n _onIframeLoad,\n } = useRiftContext();\n\n useEffect(() => {\n if (user && onSuccess) onSuccess(user);\n }, [user, onSuccess]);\n\n useEffect(() => {\n if (error && onError) onError(error);\n }, [error, onError]);\n\n useEffect(() => {\n if (!isOpen && onClose) onClose();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const backdropColor = backdrop?.color ?? DEFAULT_BACKDROP_COLOR;\n const backdropBlur = backdrop?.blur ?? DEFAULT_BACKDROP_BLUR;\n const blurCss = backdropBlur > 0 ? `blur(${backdropBlur}px)` : undefined;\n\n // Resolve the iframe's final height. The widget posts its desired\n // height via `rift:resize`; we honor it but clamp to `maxHeight` if\n // the host asked us to. For numeric maxHeight, we min() against the\n // reported height (so a fixed modal doesn't grow past it). For string\n // values like \"70vh\", we hand the limit to CSS via `maxHeight` and\n // let the browser do the math, but still cap our height attribute by\n // the reported natural height so we don't reserve unused space.\n let iframeHeight: number | string = _iframeHeight;\n let iframeMaxHeight: number | string | undefined;\n if (typeof maxHeight === \"number\") {\n iframeHeight = Math.min(_iframeHeight, maxHeight);\n } else if (typeof maxHeight === \"string\") {\n iframeMaxHeight = maxHeight;\n }\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Sign in\"\n onClick={(e) => {\n if (e.target === e.currentTarget) close();\n }}\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483646,\n background: backdropColor,\n backdropFilter: blurCss,\n WebkitBackdropFilter: blurCss,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n animation: \"rift-fade 180ms ease-out\",\n ...backdropStyle,\n }}\n >\n <style>{`@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }`}</style>\n {!isReady && (\n <div\n aria-hidden\n style={{\n position: \"absolute\",\n color: \"rgba(255,255,255,0.75)\",\n fontSize: 13,\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, sans-serif\",\n }}\n >\n Loading sign-in…\n </div>\n )}\n <iframe\n src={_iframeSrc}\n onLoad={_onIframeLoad}\n title=\"Rift sign-in\"\n allow=\"publickey-credentials-get; identity-credentials-get\"\n style={{\n border: 0,\n background: \"transparent\",\n colorScheme: \"light\",\n width: \"100%\",\n maxWidth,\n height: iframeHeight,\n maxHeight: iframeMaxHeight,\n borderRadius: radius,\n boxShadow: \"0 24px 60px -12px rgba(0,0,0,0.35)\",\n transition: \"height 200ms ease\",\n opacity: isReady ? 1 : 0,\n ...iframeStyle,\n }}\n />\n </div>\n );\n}\n","import { useRiftContext } from \"./RiftProvider\";\nimport type { RiftMode, RiftUser } from \"./types\";\n\ninterface UseRiftReturn {\n user: RiftUser | null;\n isAuthenticated: boolean;\n isOpen: boolean;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Async getter for a valid access token. Use this when calling Rift /\n * your backend — it returns the current token if fresh, or silently\n * refreshes via a hidden iframe if near expiry. Rejects when the user\n * isn't signed in or the refresh fails (in which case auth state is\n * cleared and the host should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n error: string | null;\n}\n\n/**\n * Read auth state and drive the widget from anywhere inside <RiftProvider>.\n *\n * const { user, isAuthenticated, open, signOut, getAccessToken } = useRift();\n * return isAuthenticated\n * ? <button onClick={signOut}>Sign out</button>\n * : <button onClick={() => open({ mode: 'signup' })}>Get started</button>;\n *\n * // When calling your backend with Rift's session JWT:\n * const token = await getAccessToken();\n * fetch('/api/my-thing', { headers: { Authorization: `Bearer ${token}` } });\n */\nexport function useRift(): UseRiftReturn {\n const { user, isOpen, open, close, signOut, getAccessToken, error } =\n useRiftContext();\n return {\n user,\n isAuthenticated: !!user,\n isOpen,\n open,\n close,\n signOut,\n getAccessToken,\n error,\n };\n}\n"],"names":["iframe","ready","readyResolvers","widgetOrigin","pending","uuid","ensureMounted","opts","params","e","data","r","slot","resolve","silentRefresh","requestId","reject","silentLogout","DEFAULT_WIDGET_URL","IDENTITY_STORAGE_KEY","REFRESH_LEEWAY_SECONDS","RiftContext","createContext","useRiftContext","ctx","useContext","loadIdentity","raw","saveIdentity","id","RiftProvider","apiKey","widgetUrl","children","autoOpen","persist","resolvedWidgetUrl","useMemo","user","setUser","useState","isOpen","setIsOpen","mode","setMode","isReady","setIsReady","error","setError","iframeHeight","setIframeHeight","openToken","setOpenToken","userRef","useRef","refreshInFlight","setAndPersist","useCallback","next","useEffect","identity","alive","result","open","t","close","signOut","getAccessToken","current","expiresAt","now","latest","err","handler","prev","iframeSrc","html","attr","theme","onIframeLoad","value","jsx","DEFAULT_BACKDROP_COLOR","DEFAULT_BACKDROP_BLUR","DEFAULT_MAX_WIDTH","DEFAULT_RADIUS","RiftAuth","onSuccess","onError","onClose","maxHeight","maxWidth","radius","backdrop","backdropStyle","iframeStyle","_iframeSrc","_iframeHeight","_onIframeLoad","backdropColor","backdropBlur","blurCss","iframeMaxHeight","jsxs","useRift"],"mappings":"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"}
1
+ {"version":3,"file":"rift-react.cjs","sources":["../src/silentRefresh.ts","../src/RiftProvider.tsx","../src/RiftAuth.tsx","../src/useRift.ts"],"sourcesContent":["/**\n * Silent-refresh bridge.\n *\n * The v2 backend session sits behind an httpOnly refresh cookie scoped\n * to the widget origin (widget.riftfi.xyz → service.riftfi.xyz). The\n * cookie cannot be read or sent from the merchant's own JS — only\n * widget-origin code can use it. So to refresh, we mount a HIDDEN\n * widget iframe in `?headless=1` mode and ask it (via postMessage) to\n * call /auth/refresh on our behalf. It posts the new access token back.\n *\n * This module owns that iframe as a singleton: we lazily create it on\n * the first refresh request, keep it alive across the page's lifetime,\n * and use a requestId-based pending map so concurrent refresh calls\n * dedupe to one network round trip.\n */\n\nlet iframe: HTMLIFrameElement | null = null;\nlet ready = false;\nlet readyResolvers: Array<() => void> = [];\nlet widgetOrigin: string | null = null;\n\ninterface Pending {\n resolve: (value: RefreshSuccess) => void;\n reject: (err: Error) => void;\n}\nconst pending = new Map<string, Pending>();\n\nexport interface RefreshSuccess {\n accessToken: string;\n expiresAt: string;\n expiresIn: number;\n}\n\nfunction uuid(): string {\n // Lightweight ID — doesn't need crypto strength, just unique per page.\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction ensureMounted(opts: { apiKey: string; widgetUrl: string }): Promise<void> {\n if (typeof document === \"undefined\") {\n return Promise.reject(new Error(\"Cannot mount refresh iframe outside the browser\"));\n }\n if (iframe && ready) return Promise.resolve();\n\n widgetOrigin = new URL(opts.widgetUrl).origin;\n\n if (!iframe) {\n iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.setAttribute(\"tabindex\", \"-1\");\n iframe.title = \"Rift session refresh\";\n iframe.style.cssText =\n \"position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;\";\n const params = new URLSearchParams({\n key: opts.apiKey,\n headless: \"1\",\n });\n iframe.src = `${opts.widgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n document.body.appendChild(iframe);\n\n window.addEventListener(\"message\", (e) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n if (data.type === \"rift:ready\") {\n ready = true;\n readyResolvers.forEach((r) => r());\n readyResolvers = [];\n return;\n }\n if (data.type === \"rift:refresh-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n expiresIn: data.expiresIn,\n });\n }\n return;\n }\n if (data.type === \"rift:refresh-error\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.reject(new Error(data.message || \"Refresh failed\"));\n }\n return;\n }\n if (data.type === \"rift:logout-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({ accessToken: \"\", expiresAt: \"\", expiresIn: 0 });\n }\n }\n });\n }\n\n if (ready) return Promise.resolve();\n return new Promise((resolve) => {\n readyResolvers.push(resolve);\n // Safety net: if the iframe somehow never posts ready (e.g. blocked\n // by browser privacy mode), reject after 8s so callers can surface\n // a useful error.\n setTimeout(() => {\n if (!ready) {\n const r = readyResolvers.shift();\n if (r) r();\n }\n }, 8000);\n });\n}\n\nexport async function silentRefresh(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<RefreshSuccess> {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) {\n throw new Error(\"Refresh iframe is not available\");\n }\n const requestId = uuid();\n return new Promise<RefreshSuccess>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:refresh-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n const slot = pending.get(requestId);\n if (slot) {\n pending.delete(requestId);\n slot.reject(new Error(\"Refresh timed out\"));\n }\n }, 10000);\n });\n}\n\nexport async function silentLogout(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<void> {\n try {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) return;\n const requestId = uuid();\n await new Promise<void>((resolve) => {\n pending.set(requestId, {\n resolve: () => resolve(),\n reject: () => resolve(), // logout is idempotent — never reject\n });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:logout-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n pending.delete(requestId);\n resolve();\n }, 5000);\n });\n } catch {\n /* logout is best-effort */\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport type { RiftConfig, RiftEvent, RiftMode, RiftUser } from \"./types\";\nimport { silentLogout, silentRefresh } from \"./silentRefresh\";\n\n// Widget URL by environment. The widget is a separate Vite SPA that\n// gets built once per environment (the backend URL is baked into the\n// bundle), so picking the environment here is equivalent to picking\n// which deployed widget the iframe loads.\n//\n// Override either by passing `widgetUrl=` directly (wins over\n// `environment`), or self-host and point at your own URL.\nconst WIDGET_URL_BY_ENV: Record<\"production\" | \"sandbox\", string> = {\n production: \"https://widget.riftfi.xyz\",\n sandbox: \"https://widget.sandbox.riftfi.com\",\n};\n\n// v2 session-mode policy: the access token lives in memory only. We\n// persist a small \"identity hint\" (user id, address, btcAddress) so the\n// UI can render an authenticated state on hard reload, but the actual\n// access JWT is re-issued via the refresh cookie. Refresh tokens live\n// in an httpOnly cookie scoped to the widget origin — totally invisible\n// to this code, which is the whole point.\nconst IDENTITY_STORAGE_KEY = \"rift:identity\";\n\ninterface PersistedIdentity {\n user: string;\n address: string;\n btcAddress?: string;\n}\n\n// Refresh proactively this many seconds before the access token expires.\n// Keeps API calls from racing the actual expiry.\nconst REFRESH_LEEWAY_SECONDS = 60;\n\ninterface RiftContextValue {\n apiKey: string;\n widgetUrl: string;\n user: RiftUser | null;\n isOpen: boolean;\n isReady: boolean;\n error: string | null;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Returns a valid access token, refreshing silently if the current\n * one is missing or about to expire. Rejects if the user is signed\n * out or the refresh fails (in which case state is cleared and the\n * caller should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n _iframeSrc: string;\n _iframeHeight: number;\n _onIframeLoad: () => void;\n}\n\nconst RiftContext = createContext<RiftContextValue | null>(null);\n\nexport function useRiftContext(): RiftContextValue {\n const ctx = useContext(RiftContext);\n if (!ctx) {\n throw new Error(\n \"[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>\"\n );\n }\n return ctx;\n}\n\ninterface RiftProviderProps extends RiftConfig {\n children: ReactNode;\n // Auto-open the modal on mount. Most apps will leave this false and call\n // open() in response to a user clicking \"Sign in\".\n autoOpen?: boolean;\n // Restore the persisted identity (just the user id / address — never\n // the access token) on mount, then silently refresh to mint a token.\n // Default: true.\n persist?: boolean;\n}\n\nfunction loadIdentity(): PersistedIdentity | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(IDENTITY_STORAGE_KEY);\n return raw ? (JSON.parse(raw) as PersistedIdentity) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveIdentity(id: PersistedIdentity | null) {\n if (typeof window === \"undefined\") return;\n try {\n if (id) localStorage.setItem(IDENTITY_STORAGE_KEY, JSON.stringify(id));\n else localStorage.removeItem(IDENTITY_STORAGE_KEY);\n } catch {\n /* private mode / quota — non-fatal */\n }\n}\n\nexport function RiftProvider({\n apiKey,\n environment,\n widgetUrl,\n children,\n autoOpen = false,\n persist = true,\n}: RiftProviderProps) {\n const resolvedWidgetUrl =\n widgetUrl || WIDGET_URL_BY_ENV[environment ?? \"production\"];\n const widgetOrigin = useMemo(() => {\n try {\n return new URL(resolvedWidgetUrl).origin;\n } catch {\n return resolvedWidgetUrl;\n }\n }, [resolvedWidgetUrl]);\n\n const [user, setUser] = useState<RiftUser | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [mode, setMode] = useState<RiftMode>(\"signin\");\n const [isReady, setIsReady] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [iframeHeight, setIframeHeight] = useState(540);\n const [openToken, setOpenToken] = useState(0);\n\n // Hot ref to the current user — getAccessToken() reads from this so\n // it never closes over a stale React state snapshot.\n const userRef = useRef<RiftUser | null>(null);\n userRef.current = user;\n\n // Dedupe in-flight refreshes: if multiple API calls hit\n // getAccessToken() simultaneously and the token is stale, we only\n // want one network call.\n const refreshInFlight = useRef<Promise<string> | null>(null);\n\n const setAndPersist = useCallback(\n (next: RiftUser | null) => {\n setUser(next);\n if (persist) {\n saveIdentity(\n next\n ? {\n user: next.user,\n address: next.address,\n btcAddress: next.btcAddress,\n }\n : null\n );\n }\n },\n [persist]\n );\n\n // On mount, if we have a persisted identity, try a silent refresh to\n // rehydrate the access token. If it fails, drop the identity — the\n // user will be prompted to sign in again on first action.\n useEffect(() => {\n if (!persist) return;\n const identity = loadIdentity();\n if (!identity) return;\n let alive = true;\n (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n if (!alive) return;\n setAndPersist({\n user: identity.user,\n address: identity.address,\n btcAddress: identity.btcAddress,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n });\n } catch {\n if (!alive) return;\n // Refresh failed — likely cookie expired or revoked. Clear the\n // identity hint so the UI shows the signed-out state.\n setAndPersist(null);\n }\n })();\n return () => {\n alive = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const open = useCallback((opts?: { mode?: RiftMode }) => {\n setMode(opts?.mode || \"signin\");\n setError(null);\n setIsReady(false);\n setOpenToken((t) => t + 1);\n setIsOpen(true);\n }, []);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setIsReady(false);\n }, []);\n\n const signOut = useCallback(async () => {\n await silentLogout({ apiKey, widgetUrl: resolvedWidgetUrl });\n setAndPersist(null);\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n const getAccessToken = useCallback(async (): Promise<string> => {\n const current = userRef.current;\n if (!current) throw new Error(\"Not signed in\");\n\n const expiresAt = current.expiresAt\n ? new Date(current.expiresAt).getTime()\n : null;\n const now = Date.now();\n const needsRefresh =\n !expiresAt || expiresAt - now < REFRESH_LEEWAY_SECONDS * 1000;\n\n if (!needsRefresh && current.accessToken) {\n return current.accessToken;\n }\n\n if (refreshInFlight.current) {\n return refreshInFlight.current;\n }\n\n refreshInFlight.current = (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n const latest = userRef.current;\n if (!latest) throw new Error(\"Signed out during refresh\");\n const next: RiftUser = {\n ...latest,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n };\n setAndPersist(next);\n return result.accessToken;\n } catch (err: any) {\n // Refresh failed — wipe state so the host UI can prompt re-auth.\n setAndPersist(null);\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n refreshInFlight.current = null;\n }\n })();\n return refreshInFlight.current;\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n // Listen for messages from the VISIBLE login iframe (not the silent\n // refresh one — that one's events are handled inside silentRefresh.ts).\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const handler = (e: MessageEvent) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data as RiftEvent | undefined;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n switch (data.type) {\n case \"rift:ready\":\n // Only treat as \"modal ready\" while it's open — the silent\n // refresh iframe also emits ready, but we don't care here.\n if (isOpen) setIsReady(true);\n break;\n case \"rift:close\":\n close();\n break;\n case \"rift:resize\":\n setIframeHeight(Math.max(360, Math.min(820, data.height + 8)));\n break;\n case \"rift:signin-success\": {\n const next: RiftUser = {\n user: data.user,\n address: data.address,\n btcAddress: data.btcAddress,\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n };\n setAndPersist(next);\n setIsOpen(false);\n break;\n }\n case \"rift:signin-error\":\n setError(data.message);\n break;\n // refresh / logout result events belong to silentRefresh.ts —\n // ignore them here.\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [widgetOrigin, close, setAndPersist, isOpen]);\n\n // Lock host page scroll while the modal is open.\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n if (isOpen) {\n const prev = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n return () => {\n document.documentElement.style.overflow = prev;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (autoOpen && !user) open();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const iframeSrc = useMemo(() => {\n const params = new URLSearchParams({\n key: apiKey,\n mode,\n origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n t: String(openToken),\n });\n\n // Best-effort: match the host page's theme so the modal blends in\n // instead of flashing white over a dark site. Checks data-theme,\n // the `dark` class convention, then system preference.\n if (typeof document !== \"undefined\") {\n const html = document.documentElement;\n const attr = html.getAttribute(\"data-theme\");\n let theme: string | null = null;\n if (attr === \"dark\" || attr === \"light\") theme = attr;\n else if (\n html.classList.contains(\"dark\") ||\n document.body?.classList.contains(\"dark\")\n )\n theme = \"dark\";\n else if (\n window.matchMedia &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n )\n theme = \"dark\";\n if (theme) params.set(\"theme\", theme);\n }\n\n return `${resolvedWidgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n }, [apiKey, mode, openToken, resolvedWidgetUrl]);\n\n const onIframeLoad = useCallback(() => {\n /* readiness is signalled via postMessage, not the load event */\n }, []);\n\n const value = useMemo<RiftContextValue>(\n () => ({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n _iframeSrc: iframeSrc,\n _iframeHeight: iframeHeight,\n _onIframeLoad: onIframeLoad,\n }),\n [\n apiKey,\n resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n iframeSrc,\n iframeHeight,\n onIframeLoad,\n ]\n );\n\n return <RiftContext.Provider value={value}>{children}</RiftContext.Provider>;\n}\n","import { useEffect, type CSSProperties } from \"react\";\nimport { useRiftContext } from \"./RiftProvider\";\nimport type { RiftUser } from \"./types\";\n\ninterface BackdropStyle {\n /** Backdrop fill colour. Default `rgba(15,15,20,0.55)` (dark scrim). */\n color?: string;\n /** CSS `backdrop-filter: blur(<px>)`. Default 6, set 0 to disable. */\n blur?: number;\n}\n\ninterface RiftAuthProps {\n // Optional event hooks so callers don't have to compose useEffect by hand.\n onSuccess?: (user: RiftUser) => void;\n onError?: (message: string) => void;\n onClose?: () => void;\n\n /**\n * Cap the modal height. Pass a number for px (e.g. `600`) or a CSS\n * string for viewport units (`\"70vh\"`). The iframe scrolls\n * internally if its content exceeds this. Defaults to no cap; the\n * widget reports its natural height via postMessage.\n */\n maxHeight?: number | string;\n\n /**\n * Cap the modal width. Defaults to 480 (px). Pass any CSS length.\n */\n maxWidth?: number | string;\n\n /**\n * Corner radius on the modal. Defaults to 18 (px).\n */\n radius?: number | string;\n\n /**\n * Backdrop styling. See `BackdropStyle`. Each field falls back to\n * the default if omitted.\n */\n backdrop?: BackdropStyle;\n\n /**\n * Extra style applied to the backdrop wrapper. Use for things outside\n * the typed `backdrop` knob (custom transitions, z-index, etc.).\n */\n backdropStyle?: CSSProperties;\n\n /**\n * Extra style applied to the iframe. Useful for borders, custom\n * shadows, or filters that the typed props don't cover.\n */\n iframeStyle?: CSSProperties;\n}\n\nconst DEFAULT_BACKDROP_COLOR = \"rgba(15,15,20,0.55)\";\nconst DEFAULT_BACKDROP_BLUR = 6;\nconst DEFAULT_MAX_WIDTH = 480;\nconst DEFAULT_RADIUS = 18;\n\n/**\n * Renders the modal backdrop + iframe whenever the provider's `isOpen` is\n * true. Place this once near the root of your app (typically just inside\n * <RiftProvider>); call `useRift().open()` to show it.\n *\n * All visual knobs are overridable from the host: see `maxHeight`,\n * `maxWidth`, `radius`, `backdrop`, plus escape hatches `backdropStyle`\n * and `iframeStyle` for anything else.\n */\nexport function RiftAuth({\n onSuccess,\n onError,\n onClose,\n maxHeight,\n maxWidth = DEFAULT_MAX_WIDTH,\n radius = DEFAULT_RADIUS,\n backdrop,\n backdropStyle,\n iframeStyle,\n}: RiftAuthProps) {\n const {\n isOpen,\n isReady,\n error,\n close,\n user,\n _iframeSrc,\n _iframeHeight,\n _onIframeLoad,\n } = useRiftContext();\n\n useEffect(() => {\n if (user && onSuccess) onSuccess(user);\n }, [user, onSuccess]);\n\n useEffect(() => {\n if (error && onError) onError(error);\n }, [error, onError]);\n\n useEffect(() => {\n if (!isOpen && onClose) onClose();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const backdropColor = backdrop?.color ?? DEFAULT_BACKDROP_COLOR;\n const backdropBlur = backdrop?.blur ?? DEFAULT_BACKDROP_BLUR;\n const blurCss = backdropBlur > 0 ? `blur(${backdropBlur}px)` : undefined;\n\n // Resolve the iframe's final height. The widget posts its desired\n // height via `rift:resize`; we honor it but clamp to `maxHeight` if\n // the host asked us to. For numeric maxHeight, we min() against the\n // reported height (so a fixed modal doesn't grow past it). For string\n // values like \"70vh\", we hand the limit to CSS via `maxHeight` and\n // let the browser do the math, but still cap our height attribute by\n // the reported natural height so we don't reserve unused space.\n let iframeHeight: number | string = _iframeHeight;\n let iframeMaxHeight: number | string | undefined;\n if (typeof maxHeight === \"number\") {\n iframeHeight = Math.min(_iframeHeight, maxHeight);\n } else if (typeof maxHeight === \"string\") {\n iframeMaxHeight = maxHeight;\n }\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Sign in\"\n onClick={(e) => {\n if (e.target === e.currentTarget) close();\n }}\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483646,\n background: backdropColor,\n backdropFilter: blurCss,\n WebkitBackdropFilter: blurCss,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n animation: \"rift-fade 180ms ease-out\",\n ...backdropStyle,\n }}\n >\n <style>{`@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }`}</style>\n {!isReady && (\n <div\n aria-hidden\n style={{\n position: \"absolute\",\n color: \"rgba(255,255,255,0.75)\",\n fontSize: 13,\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, sans-serif\",\n }}\n >\n Loading sign-in…\n </div>\n )}\n <iframe\n src={_iframeSrc}\n onLoad={_onIframeLoad}\n title=\"Rift sign-in\"\n allow=\"publickey-credentials-get; identity-credentials-get\"\n style={{\n border: 0,\n background: \"transparent\",\n colorScheme: \"light\",\n width: \"100%\",\n maxWidth,\n height: iframeHeight,\n maxHeight: iframeMaxHeight,\n borderRadius: radius,\n boxShadow: \"0 24px 60px -12px rgba(0,0,0,0.35)\",\n transition: \"height 200ms ease\",\n opacity: isReady ? 1 : 0,\n ...iframeStyle,\n }}\n />\n </div>\n );\n}\n","import { useRiftContext } from \"./RiftProvider\";\nimport type { RiftMode, RiftUser } from \"./types\";\n\ninterface UseRiftReturn {\n user: RiftUser | null;\n isAuthenticated: boolean;\n isOpen: boolean;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Async getter for a valid access token. Use this when calling Rift /\n * your backend — it returns the current token if fresh, or silently\n * refreshes via a hidden iframe if near expiry. Rejects when the user\n * isn't signed in or the refresh fails (in which case auth state is\n * cleared and the host should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n error: string | null;\n}\n\n/**\n * Read auth state and drive the widget from anywhere inside <RiftProvider>.\n *\n * const { user, isAuthenticated, open, signOut, getAccessToken } = useRift();\n * return isAuthenticated\n * ? <button onClick={signOut}>Sign out</button>\n * : <button onClick={() => open({ mode: 'signup' })}>Get started</button>;\n *\n * // When calling your backend with Rift's session JWT:\n * const token = await getAccessToken();\n * fetch('/api/my-thing', { headers: { Authorization: `Bearer ${token}` } });\n */\nexport function useRift(): UseRiftReturn {\n const { user, isOpen, open, close, signOut, getAccessToken, error } =\n useRiftContext();\n return {\n user,\n isAuthenticated: !!user,\n isOpen,\n open,\n close,\n signOut,\n getAccessToken,\n error,\n };\n}\n"],"names":["iframe","ready","readyResolvers","widgetOrigin","pending","uuid","ensureMounted","opts","params","e","data","r","slot","resolve","silentRefresh","requestId","reject","silentLogout","WIDGET_URL_BY_ENV","IDENTITY_STORAGE_KEY","REFRESH_LEEWAY_SECONDS","RiftContext","createContext","useRiftContext","ctx","useContext","loadIdentity","raw","saveIdentity","id","RiftProvider","apiKey","environment","widgetUrl","children","autoOpen","persist","resolvedWidgetUrl","useMemo","user","setUser","useState","isOpen","setIsOpen","mode","setMode","isReady","setIsReady","error","setError","iframeHeight","setIframeHeight","openToken","setOpenToken","userRef","useRef","refreshInFlight","setAndPersist","useCallback","next","useEffect","identity","alive","result","open","t","close","signOut","getAccessToken","current","expiresAt","now","latest","err","handler","prev","iframeSrc","html","attr","theme","onIframeLoad","value","jsx","DEFAULT_BACKDROP_COLOR","DEFAULT_BACKDROP_BLUR","DEFAULT_MAX_WIDTH","DEFAULT_RADIUS","RiftAuth","onSuccess","onError","onClose","maxHeight","maxWidth","radius","backdrop","backdropStyle","iframeStyle","_iframeSrc","_iframeHeight","_onIframeLoad","backdropColor","backdropBlur","blurCss","iframeMaxHeight","jsxs","useRift"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { jsx as P, jsxs as te } from "react/jsx-runtime";
2
- import { createContext as re, useMemo as j, useState as w, useRef as G, useCallback as E, useEffect as y, useContext as ne } from "react";
3
- let d = null, C = !1, M = [], T = null;
1
+ import { jsx as j, jsxs as re } from "react/jsx-runtime";
2
+ import { createContext as ne, useMemo as $, useState as w, useRef as J, useCallback as A, useEffect as y, useContext as se } from "react";
3
+ let d = null, W = !1, q = [], R = null;
4
4
  const u = /* @__PURE__ */ new Map();
5
5
  function X() {
6
6
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;
@@ -8,24 +8,24 @@ function X() {
8
8
  function Q(e) {
9
9
  if (typeof document > "u")
10
10
  return Promise.reject(new Error("Cannot mount refresh iframe outside the browser"));
11
- if (d && C) return Promise.resolve();
12
- if (T = new URL(e.widgetUrl).origin, !d) {
11
+ if (d && W) return Promise.resolve();
12
+ if (R = new URL(e.widgetUrl).origin, !d) {
13
13
  d = document.createElement("iframe"), d.setAttribute("aria-hidden", "true"), d.setAttribute("tabindex", "-1"), d.title = "Rift session refresh", d.style.cssText = "position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;";
14
- const i = new URLSearchParams({
14
+ const s = new URLSearchParams({
15
15
  key: e.apiKey,
16
16
  headless: "1"
17
17
  });
18
- d.src = `${e.widgetUrl.replace(/\/$/, "")}/?${i.toString()}`, document.body.appendChild(d), window.addEventListener("message", (o) => {
19
- if (o.origin !== T) return;
18
+ d.src = `${e.widgetUrl.replace(/\/$/, "")}/?${s.toString()}`, document.body.appendChild(d), window.addEventListener("message", (o) => {
19
+ if (o.origin !== R) return;
20
20
  const t = o.data;
21
21
  if (!(!t || typeof t != "object" || typeof t.type != "string") && t.type.startsWith("rift:")) {
22
22
  if (t.type === "rift:ready") {
23
- C = !0, M.forEach((n) => n()), M = [];
23
+ W = !0, q.forEach((i) => i()), q = [];
24
24
  return;
25
25
  }
26
26
  if (t.type === "rift:refresh-result") {
27
- const n = u.get(t.requestId);
28
- n && (u.delete(t.requestId), n.resolve({
27
+ const i = u.get(t.requestId);
28
+ i && (u.delete(t.requestId), i.resolve({
29
29
  accessToken: t.accessToken,
30
30
  expiresAt: t.expiresAt,
31
31
  expiresIn: t.expiresIn
@@ -33,102 +33,106 @@ function Q(e) {
33
33
  return;
34
34
  }
35
35
  if (t.type === "rift:refresh-error") {
36
- const n = u.get(t.requestId);
37
- n && (u.delete(t.requestId), n.reject(new Error(t.message || "Refresh failed")));
36
+ const i = u.get(t.requestId);
37
+ i && (u.delete(t.requestId), i.reject(new Error(t.message || "Refresh failed")));
38
38
  return;
39
39
  }
40
40
  if (t.type === "rift:logout-result") {
41
- const n = u.get(t.requestId);
42
- n && (u.delete(t.requestId), n.resolve({ accessToken: "", expiresAt: "", expiresIn: 0 }));
41
+ const i = u.get(t.requestId);
42
+ i && (u.delete(t.requestId), i.resolve({ accessToken: "", expiresAt: "", expiresIn: 0 }));
43
43
  }
44
44
  }
45
45
  });
46
46
  }
47
- return C ? Promise.resolve() : new Promise((i) => {
48
- M.push(i), setTimeout(() => {
49
- if (!C) {
50
- const o = M.shift();
47
+ return W ? Promise.resolve() : new Promise((s) => {
48
+ q.push(s), setTimeout(() => {
49
+ if (!W) {
50
+ const o = q.shift();
51
51
  o && o();
52
52
  }
53
53
  }, 8e3);
54
54
  });
55
55
  }
56
- async function J(e) {
57
- if (await Q(e), !d?.contentWindow || !T)
56
+ async function V(e) {
57
+ if (await Q(e), !d?.contentWindow || !R)
58
58
  throw new Error("Refresh iframe is not available");
59
- const i = X();
59
+ const s = X();
60
60
  return new Promise((o, t) => {
61
- u.set(i, { resolve: o, reject: t }), d.contentWindow.postMessage(
62
- { type: "rift:refresh-request", requestId: i },
63
- T
61
+ u.set(s, { resolve: o, reject: t }), d.contentWindow.postMessage(
62
+ { type: "rift:refresh-request", requestId: s },
63
+ R
64
64
  ), setTimeout(() => {
65
- const n = u.get(i);
66
- n && (u.delete(i), n.reject(new Error("Refresh timed out")));
65
+ const i = u.get(s);
66
+ i && (u.delete(s), i.reject(new Error("Refresh timed out")));
67
67
  }, 1e4);
68
68
  });
69
69
  }
70
- async function se(e) {
70
+ async function ie(e) {
71
71
  try {
72
- if (await Q(e), !d?.contentWindow || !T) return;
73
- const i = X();
72
+ if (await Q(e), !d?.contentWindow || !R) return;
73
+ const s = X();
74
74
  await new Promise((o) => {
75
- u.set(i, {
75
+ u.set(s, {
76
76
  resolve: () => o(),
77
77
  reject: () => o()
78
78
  // logout is idempotent — never reject
79
79
  }), d.contentWindow.postMessage(
80
- { type: "rift:logout-request", requestId: i },
81
- T
80
+ { type: "rift:logout-request", requestId: s },
81
+ R
82
82
  ), setTimeout(() => {
83
- u.delete(i), o();
83
+ u.delete(s), o();
84
84
  }, 5e3);
85
85
  });
86
86
  } catch {
87
87
  }
88
88
  }
89
- const ie = "https://widget.riftfi.xyz", $ = "rift:identity", oe = 60, V = re(null);
90
- function Z() {
91
- const e = ne(V);
89
+ const oe = {
90
+ production: "https://widget.riftfi.xyz",
91
+ sandbox: "https://widget.sandbox.riftfi.com"
92
+ }, B = "rift:identity", ae = 60, Z = ne(null);
93
+ function K() {
94
+ const e = se(Z);
92
95
  if (!e)
93
96
  throw new Error(
94
97
  "[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>"
95
98
  );
96
99
  return e;
97
100
  }
98
- function ae() {
101
+ function ce() {
99
102
  if (typeof window > "u") return null;
100
103
  try {
101
- const e = localStorage.getItem($);
104
+ const e = localStorage.getItem(B);
102
105
  return e ? JSON.parse(e) : null;
103
106
  } catch {
104
107
  return null;
105
108
  }
106
109
  }
107
- function ce(e) {
110
+ function de(e) {
108
111
  if (!(typeof window > "u"))
109
112
  try {
110
- e ? localStorage.setItem($, JSON.stringify(e)) : localStorage.removeItem($);
113
+ e ? localStorage.setItem(B, JSON.stringify(e)) : localStorage.removeItem(B);
111
114
  } catch {
112
115
  }
113
116
  }
114
- function pe({
117
+ function he({
115
118
  apiKey: e,
116
- widgetUrl: i,
117
- children: o,
118
- autoOpen: t = !1,
119
- persist: n = !0
119
+ environment: s,
120
+ widgetUrl: o,
121
+ children: t,
122
+ autoOpen: i = !1,
123
+ persist: g = !0
120
124
  }) {
121
- const a = i || ie, p = j(() => {
125
+ const a = o || oe[s ?? "production"], L = $(() => {
122
126
  try {
123
127
  return new URL(a).origin;
124
128
  } catch {
125
129
  return a;
126
130
  }
127
- }, [a]), [b, W] = w(null), [f, k] = w(!1), [A, q] = w("signin"), [x, I] = w(!1), [v, L] = w(null), [U, _] = w(540), [S, O] = w(0), R = G(null);
128
- R.current = b;
129
- const m = G(null), l = E(
131
+ }, [a]), [b, E] = w(null), [f, p] = w(!1), [_, I] = w("signin"), [U, k] = w(!1), [O, C] = w(null), [T, D] = w(540), [v, M] = w(0), x = J(null);
132
+ x.current = b;
133
+ const S = J(null), l = A(
130
134
  (r) => {
131
- W(r), n && ce(
135
+ E(r), g && de(
132
136
  r ? {
133
137
  user: r.user,
134
138
  address: r.address,
@@ -136,16 +140,16 @@ function pe({
136
140
  } : null
137
141
  );
138
142
  },
139
- [n]
143
+ [g]
140
144
  );
141
145
  y(() => {
142
- if (!n) return;
143
- const r = ae();
146
+ if (!g) return;
147
+ const r = ce();
144
148
  if (!r) return;
145
149
  let c = !0;
146
150
  return (async () => {
147
151
  try {
148
- const s = await J({
152
+ const n = await V({
149
153
  apiKey: e,
150
154
  widgetUrl: a
151
155
  });
@@ -154,8 +158,8 @@ function pe({
154
158
  user: r.user,
155
159
  address: r.address,
156
160
  btcAddress: r.btcAddress,
157
- accessToken: s.accessToken,
158
- expiresAt: s.expiresAt
161
+ accessToken: n.accessToken,
162
+ expiresAt: n.expiresAt
159
163
  });
160
164
  } catch {
161
165
  if (!c) return;
@@ -165,70 +169,70 @@ function pe({
165
169
  c = !1;
166
170
  };
167
171
  }, []);
168
- const F = E((r) => {
169
- q(r?.mode || "signin"), L(null), I(!1), O((c) => c + 1), k(!0);
170
- }, []), D = E(() => {
171
- k(!1), I(!1);
172
- }, []), H = E(async () => {
173
- await se({ apiKey: e, widgetUrl: a }), l(null);
174
- }, [e, a, l]), B = E(async () => {
175
- const r = R.current;
172
+ const F = A((r) => {
173
+ I(r?.mode || "signin"), C(null), k(!1), M((c) => c + 1), p(!0);
174
+ }, []), P = A(() => {
175
+ p(!1), k(!1);
176
+ }, []), H = A(async () => {
177
+ await ie({ apiKey: e, widgetUrl: a }), l(null);
178
+ }, [e, a, l]), N = A(async () => {
179
+ const r = x.current;
176
180
  if (!r) throw new Error("Not signed in");
177
- const c = r.expiresAt ? new Date(r.expiresAt).getTime() : null, s = Date.now();
178
- return !(!c || c - s < oe * 1e3) && r.accessToken ? r.accessToken : (m.current || (m.current = (async () => {
181
+ const c = r.expiresAt ? new Date(r.expiresAt).getTime() : null, n = Date.now();
182
+ return !(!c || c - n < ae * 1e3) && r.accessToken ? r.accessToken : (S.current || (S.current = (async () => {
179
183
  try {
180
- const h = await J({
184
+ const h = await V({
181
185
  apiKey: e,
182
186
  widgetUrl: a
183
- }), Y = R.current;
184
- if (!Y) throw new Error("Signed out during refresh");
185
- const ee = {
186
- ...Y,
187
+ }), G = x.current;
188
+ if (!G) throw new Error("Signed out during refresh");
189
+ const te = {
190
+ ...G,
187
191
  accessToken: h.accessToken,
188
192
  expiresAt: h.expiresAt
189
193
  };
190
- return l(ee), h.accessToken;
194
+ return l(te), h.accessToken;
191
195
  } catch (h) {
192
196
  throw l(null), h instanceof Error ? h : new Error(String(h));
193
197
  } finally {
194
- m.current = null;
198
+ S.current = null;
195
199
  }
196
- })()), m.current);
200
+ })()), S.current);
197
201
  }, [e, a, l]);
198
202
  y(() => {
199
203
  if (typeof window > "u") return;
200
204
  const r = (c) => {
201
- if (c.origin !== p) return;
202
- const s = c.data;
203
- if (!(!s || typeof s != "object" || typeof s.type != "string") && s.type.startsWith("rift:"))
204
- switch (s.type) {
205
+ if (c.origin !== L) return;
206
+ const n = c.data;
207
+ if (!(!n || typeof n != "object" || typeof n.type != "string") && n.type.startsWith("rift:"))
208
+ switch (n.type) {
205
209
  case "rift:ready":
206
- f && I(!0);
210
+ f && k(!0);
207
211
  break;
208
212
  case "rift:close":
209
- D();
213
+ P();
210
214
  break;
211
215
  case "rift:resize":
212
- _(Math.max(360, Math.min(820, s.height + 8)));
216
+ D(Math.max(360, Math.min(820, n.height + 8)));
213
217
  break;
214
218
  case "rift:signin-success": {
215
- const g = {
216
- user: s.user,
217
- address: s.address,
218
- btcAddress: s.btcAddress,
219
- accessToken: s.accessToken,
220
- expiresAt: s.expiresAt
219
+ const m = {
220
+ user: n.user,
221
+ address: n.address,
222
+ btcAddress: n.btcAddress,
223
+ accessToken: n.accessToken,
224
+ expiresAt: n.expiresAt
221
225
  };
222
- l(g), k(!1);
226
+ l(m), p(!1);
223
227
  break;
224
228
  }
225
229
  case "rift:signin-error":
226
- L(s.message);
230
+ C(n.message);
227
231
  break;
228
232
  }
229
233
  };
230
234
  return window.addEventListener("message", r), () => window.removeEventListener("message", r);
231
- }, [p, D, l, f]), y(() => {
235
+ }, [L, P, l, f]), y(() => {
232
236
  if (!(typeof document > "u") && f) {
233
237
  const r = document.documentElement.style.overflow;
234
238
  return document.documentElement.style.overflow = "hidden", () => {
@@ -236,113 +240,113 @@ function pe({
236
240
  };
237
241
  }
238
242
  }, [f]), y(() => {
239
- t && !b && F();
243
+ i && !b && F();
240
244
  }, []);
241
- const N = j(() => {
245
+ const z = $(() => {
242
246
  const r = new URLSearchParams({
243
247
  key: e,
244
- mode: A,
248
+ mode: _,
245
249
  origin: typeof window < "u" ? window.location.origin : "",
246
- t: String(S)
250
+ t: String(v)
247
251
  });
248
252
  if (typeof document < "u") {
249
- const c = document.documentElement, s = c.getAttribute("data-theme");
250
- let g = null;
251
- s === "dark" || s === "light" ? g = s : (c.classList.contains("dark") || document.body?.classList.contains("dark") || window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) && (g = "dark"), g && r.set("theme", g);
253
+ const c = document.documentElement, n = c.getAttribute("data-theme");
254
+ let m = null;
255
+ n === "dark" || n === "light" ? m = n : (c.classList.contains("dark") || document.body?.classList.contains("dark") || window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) && (m = "dark"), m && r.set("theme", m);
252
256
  }
253
257
  return `${a.replace(/\/$/, "")}/?${r.toString()}`;
254
- }, [e, A, S, a]), z = E(() => {
255
- }, []), K = j(
258
+ }, [e, _, v, a]), Y = A(() => {
259
+ }, []), ee = $(
256
260
  () => ({
257
261
  apiKey: e,
258
262
  widgetUrl: a,
259
263
  user: b,
260
264
  isOpen: f,
261
- isReady: x,
262
- error: v,
265
+ isReady: U,
266
+ error: O,
263
267
  open: F,
264
- close: D,
268
+ close: P,
265
269
  signOut: H,
266
- getAccessToken: B,
267
- _iframeSrc: N,
268
- _iframeHeight: U,
269
- _onIframeLoad: z
270
+ getAccessToken: N,
271
+ _iframeSrc: z,
272
+ _iframeHeight: T,
273
+ _onIframeLoad: Y
270
274
  }),
271
275
  [
272
276
  e,
273
277
  a,
274
278
  b,
275
279
  f,
276
- x,
277
- v,
280
+ U,
281
+ O,
278
282
  F,
279
- D,
283
+ P,
280
284
  H,
281
- B,
282
285
  N,
283
- U,
284
- z
286
+ z,
287
+ T,
288
+ Y
285
289
  ]
286
290
  );
287
- return /* @__PURE__ */ P(V.Provider, { value: K, children: o });
291
+ return /* @__PURE__ */ j(Z.Provider, { value: ee, children: t });
288
292
  }
289
- const de = "rgba(15,15,20,0.55)", ue = 6, fe = 480, le = 18;
290
- function he({
293
+ const ue = "rgba(15,15,20,0.55)", fe = 6, le = 480, me = 18;
294
+ function we({
291
295
  onSuccess: e,
292
- onError: i,
296
+ onError: s,
293
297
  onClose: o,
294
298
  maxHeight: t,
295
- maxWidth: n = fe,
296
- radius: a = le,
297
- backdrop: p,
298
- backdropStyle: b,
299
- iframeStyle: W
299
+ maxWidth: i = le,
300
+ radius: g = me,
301
+ backdrop: a,
302
+ backdropStyle: L,
303
+ iframeStyle: b
300
304
  }) {
301
305
  const {
302
- isOpen: f,
303
- isReady: k,
304
- error: A,
305
- close: q,
306
- user: x,
307
- _iframeSrc: I,
308
- _iframeHeight: v,
309
- _onIframeLoad: L
310
- } = Z();
306
+ isOpen: E,
307
+ isReady: f,
308
+ error: p,
309
+ close: _,
310
+ user: I,
311
+ _iframeSrc: U,
312
+ _iframeHeight: k,
313
+ _onIframeLoad: O
314
+ } = K();
311
315
  if (y(() => {
312
- x && e && e(x);
313
- }, [x, e]), y(() => {
314
- A && i && i(A);
315
- }, [A, i]), y(() => {
316
- !f && o && o();
317
- }, [f]), !f) return null;
318
- const U = p?.color ?? de, _ = p?.blur ?? ue, S = _ > 0 ? `blur(${_}px)` : void 0;
319
- let O = v, R;
320
- return typeof t == "number" ? O = Math.min(v, t) : typeof t == "string" && (R = t), /* @__PURE__ */ te(
316
+ I && e && e(I);
317
+ }, [I, e]), y(() => {
318
+ p && s && s(p);
319
+ }, [p, s]), y(() => {
320
+ !E && o && o();
321
+ }, [E]), !E) return null;
322
+ const C = a?.color ?? ue, T = a?.blur ?? fe, D = T > 0 ? `blur(${T}px)` : void 0;
323
+ let v = k, M;
324
+ return typeof t == "number" ? v = Math.min(k, t) : typeof t == "string" && (M = t), /* @__PURE__ */ re(
321
325
  "div",
322
326
  {
323
327
  role: "dialog",
324
328
  "aria-modal": "true",
325
329
  "aria-label": "Sign in",
326
- onClick: (m) => {
327
- m.target === m.currentTarget && q();
330
+ onClick: (x) => {
331
+ x.target === x.currentTarget && _();
328
332
  },
329
333
  style: {
330
334
  position: "fixed",
331
335
  inset: 0,
332
336
  zIndex: 2147483646,
333
- background: U,
334
- backdropFilter: S,
335
- WebkitBackdropFilter: S,
337
+ background: C,
338
+ backdropFilter: D,
339
+ WebkitBackdropFilter: D,
336
340
  display: "flex",
337
341
  alignItems: "center",
338
342
  justifyContent: "center",
339
343
  padding: 16,
340
344
  animation: "rift-fade 180ms ease-out",
341
- ...b
345
+ ...L
342
346
  },
343
347
  children: [
344
- /* @__PURE__ */ P("style", { children: "@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }" }),
345
- !k && /* @__PURE__ */ P(
348
+ /* @__PURE__ */ j("style", { children: "@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }" }),
349
+ !f && /* @__PURE__ */ j(
346
350
  "div",
347
351
  {
348
352
  "aria-hidden": !0,
@@ -355,11 +359,11 @@ function he({
355
359
  children: "Loading sign-in…"
356
360
  }
357
361
  ),
358
- /* @__PURE__ */ P(
362
+ /* @__PURE__ */ j(
359
363
  "iframe",
360
364
  {
361
- src: I,
362
- onLoad: L,
365
+ src: U,
366
+ onLoad: O,
363
367
  title: "Rift sign-in",
364
368
  allow: "publickey-credentials-get; identity-credentials-get",
365
369
  style: {
@@ -367,14 +371,14 @@ function he({
367
371
  background: "transparent",
368
372
  colorScheme: "light",
369
373
  width: "100%",
370
- maxWidth: n,
371
- height: O,
372
- maxHeight: R,
373
- borderRadius: a,
374
+ maxWidth: i,
375
+ height: v,
376
+ maxHeight: M,
377
+ borderRadius: g,
374
378
  boxShadow: "0 24px 60px -12px rgba(0,0,0,0.35)",
375
379
  transition: "height 200ms ease",
376
- opacity: k ? 1 : 0,
377
- ...W
380
+ opacity: f ? 1 : 0,
381
+ ...b
378
382
  }
379
383
  }
380
384
  )
@@ -382,22 +386,22 @@ function he({
382
386
  }
383
387
  );
384
388
  }
385
- function we() {
386
- const { user: e, isOpen: i, open: o, close: t, signOut: n, getAccessToken: a, error: p } = Z();
389
+ function ye() {
390
+ const { user: e, isOpen: s, open: o, close: t, signOut: i, getAccessToken: g, error: a } = K();
387
391
  return {
388
392
  user: e,
389
393
  isAuthenticated: !!e,
390
- isOpen: i,
394
+ isOpen: s,
391
395
  open: o,
392
396
  close: t,
393
- signOut: n,
394
- getAccessToken: a,
395
- error: p
397
+ signOut: i,
398
+ getAccessToken: g,
399
+ error: a
396
400
  };
397
401
  }
398
402
  export {
399
- he as RiftAuth,
400
- pe as RiftProvider,
401
- we as useRift
403
+ we as RiftAuth,
404
+ he as RiftProvider,
405
+ ye as useRift
402
406
  };
403
407
  //# sourceMappingURL=rift-react.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rift-react.js","sources":["../src/silentRefresh.ts","../src/RiftProvider.tsx","../src/RiftAuth.tsx","../src/useRift.ts"],"sourcesContent":["/**\n * Silent-refresh bridge.\n *\n * The v2 backend session sits behind an httpOnly refresh cookie scoped\n * to the widget origin (widget.riftfi.xyz → service.riftfi.xyz). The\n * cookie cannot be read or sent from the merchant's own JS — only\n * widget-origin code can use it. So to refresh, we mount a HIDDEN\n * widget iframe in `?headless=1` mode and ask it (via postMessage) to\n * call /auth/refresh on our behalf. It posts the new access token back.\n *\n * This module owns that iframe as a singleton: we lazily create it on\n * the first refresh request, keep it alive across the page's lifetime,\n * and use a requestId-based pending map so concurrent refresh calls\n * dedupe to one network round trip.\n */\n\nlet iframe: HTMLIFrameElement | null = null;\nlet ready = false;\nlet readyResolvers: Array<() => void> = [];\nlet widgetOrigin: string | null = null;\n\ninterface Pending {\n resolve: (value: RefreshSuccess) => void;\n reject: (err: Error) => void;\n}\nconst pending = new Map<string, Pending>();\n\nexport interface RefreshSuccess {\n accessToken: string;\n expiresAt: string;\n expiresIn: number;\n}\n\nfunction uuid(): string {\n // Lightweight ID — doesn't need crypto strength, just unique per page.\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction ensureMounted(opts: { apiKey: string; widgetUrl: string }): Promise<void> {\n if (typeof document === \"undefined\") {\n return Promise.reject(new Error(\"Cannot mount refresh iframe outside the browser\"));\n }\n if (iframe && ready) return Promise.resolve();\n\n widgetOrigin = new URL(opts.widgetUrl).origin;\n\n if (!iframe) {\n iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.setAttribute(\"tabindex\", \"-1\");\n iframe.title = \"Rift session refresh\";\n iframe.style.cssText =\n \"position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;\";\n const params = new URLSearchParams({\n key: opts.apiKey,\n headless: \"1\",\n });\n iframe.src = `${opts.widgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n document.body.appendChild(iframe);\n\n window.addEventListener(\"message\", (e) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n if (data.type === \"rift:ready\") {\n ready = true;\n readyResolvers.forEach((r) => r());\n readyResolvers = [];\n return;\n }\n if (data.type === \"rift:refresh-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n expiresIn: data.expiresIn,\n });\n }\n return;\n }\n if (data.type === \"rift:refresh-error\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.reject(new Error(data.message || \"Refresh failed\"));\n }\n return;\n }\n if (data.type === \"rift:logout-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({ accessToken: \"\", expiresAt: \"\", expiresIn: 0 });\n }\n }\n });\n }\n\n if (ready) return Promise.resolve();\n return new Promise((resolve) => {\n readyResolvers.push(resolve);\n // Safety net: if the iframe somehow never posts ready (e.g. blocked\n // by browser privacy mode), reject after 8s so callers can surface\n // a useful error.\n setTimeout(() => {\n if (!ready) {\n const r = readyResolvers.shift();\n if (r) r();\n }\n }, 8000);\n });\n}\n\nexport async function silentRefresh(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<RefreshSuccess> {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) {\n throw new Error(\"Refresh iframe is not available\");\n }\n const requestId = uuid();\n return new Promise<RefreshSuccess>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:refresh-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n const slot = pending.get(requestId);\n if (slot) {\n pending.delete(requestId);\n slot.reject(new Error(\"Refresh timed out\"));\n }\n }, 10000);\n });\n}\n\nexport async function silentLogout(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<void> {\n try {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) return;\n const requestId = uuid();\n await new Promise<void>((resolve) => {\n pending.set(requestId, {\n resolve: () => resolve(),\n reject: () => resolve(), // logout is idempotent — never reject\n });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:logout-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n pending.delete(requestId);\n resolve();\n }, 5000);\n });\n } catch {\n /* logout is best-effort */\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport type { RiftConfig, RiftEvent, RiftMode, RiftUser } from \"./types\";\nimport { silentLogout, silentRefresh } from \"./silentRefresh\";\n\nconst DEFAULT_WIDGET_URL = \"https://widget.riftfi.xyz\";\n\n// v2 session-mode policy: the access token lives in memory only. We\n// persist a small \"identity hint\" (user id, address, btcAddress) so the\n// UI can render an authenticated state on hard reload, but the actual\n// access JWT is re-issued via the refresh cookie. Refresh tokens live\n// in an httpOnly cookie scoped to the widget origin — totally invisible\n// to this code, which is the whole point.\nconst IDENTITY_STORAGE_KEY = \"rift:identity\";\n\ninterface PersistedIdentity {\n user: string;\n address: string;\n btcAddress?: string;\n}\n\n// Refresh proactively this many seconds before the access token expires.\n// Keeps API calls from racing the actual expiry.\nconst REFRESH_LEEWAY_SECONDS = 60;\n\ninterface RiftContextValue {\n apiKey: string;\n widgetUrl: string;\n user: RiftUser | null;\n isOpen: boolean;\n isReady: boolean;\n error: string | null;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Returns a valid access token, refreshing silently if the current\n * one is missing or about to expire. Rejects if the user is signed\n * out or the refresh fails (in which case state is cleared and the\n * caller should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n _iframeSrc: string;\n _iframeHeight: number;\n _onIframeLoad: () => void;\n}\n\nconst RiftContext = createContext<RiftContextValue | null>(null);\n\nexport function useRiftContext(): RiftContextValue {\n const ctx = useContext(RiftContext);\n if (!ctx) {\n throw new Error(\n \"[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>\"\n );\n }\n return ctx;\n}\n\ninterface RiftProviderProps extends RiftConfig {\n children: ReactNode;\n // Auto-open the modal on mount. Most apps will leave this false and call\n // open() in response to a user clicking \"Sign in\".\n autoOpen?: boolean;\n // Restore the persisted identity (just the user id / address — never\n // the access token) on mount, then silently refresh to mint a token.\n // Default: true.\n persist?: boolean;\n}\n\nfunction loadIdentity(): PersistedIdentity | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(IDENTITY_STORAGE_KEY);\n return raw ? (JSON.parse(raw) as PersistedIdentity) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveIdentity(id: PersistedIdentity | null) {\n if (typeof window === \"undefined\") return;\n try {\n if (id) localStorage.setItem(IDENTITY_STORAGE_KEY, JSON.stringify(id));\n else localStorage.removeItem(IDENTITY_STORAGE_KEY);\n } catch {\n /* private mode / quota — non-fatal */\n }\n}\n\nexport function RiftProvider({\n apiKey,\n widgetUrl,\n children,\n autoOpen = false,\n persist = true,\n}: RiftProviderProps) {\n const resolvedWidgetUrl = widgetUrl || DEFAULT_WIDGET_URL;\n const widgetOrigin = useMemo(() => {\n try {\n return new URL(resolvedWidgetUrl).origin;\n } catch {\n return resolvedWidgetUrl;\n }\n }, [resolvedWidgetUrl]);\n\n const [user, setUser] = useState<RiftUser | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [mode, setMode] = useState<RiftMode>(\"signin\");\n const [isReady, setIsReady] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [iframeHeight, setIframeHeight] = useState(540);\n const [openToken, setOpenToken] = useState(0);\n\n // Hot ref to the current user — getAccessToken() reads from this so\n // it never closes over a stale React state snapshot.\n const userRef = useRef<RiftUser | null>(null);\n userRef.current = user;\n\n // Dedupe in-flight refreshes: if multiple API calls hit\n // getAccessToken() simultaneously and the token is stale, we only\n // want one network call.\n const refreshInFlight = useRef<Promise<string> | null>(null);\n\n const setAndPersist = useCallback(\n (next: RiftUser | null) => {\n setUser(next);\n if (persist) {\n saveIdentity(\n next\n ? {\n user: next.user,\n address: next.address,\n btcAddress: next.btcAddress,\n }\n : null\n );\n }\n },\n [persist]\n );\n\n // On mount, if we have a persisted identity, try a silent refresh to\n // rehydrate the access token. If it fails, drop the identity — the\n // user will be prompted to sign in again on first action.\n useEffect(() => {\n if (!persist) return;\n const identity = loadIdentity();\n if (!identity) return;\n let alive = true;\n (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n if (!alive) return;\n setAndPersist({\n user: identity.user,\n address: identity.address,\n btcAddress: identity.btcAddress,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n });\n } catch {\n if (!alive) return;\n // Refresh failed — likely cookie expired or revoked. Clear the\n // identity hint so the UI shows the signed-out state.\n setAndPersist(null);\n }\n })();\n return () => {\n alive = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const open = useCallback((opts?: { mode?: RiftMode }) => {\n setMode(opts?.mode || \"signin\");\n setError(null);\n setIsReady(false);\n setOpenToken((t) => t + 1);\n setIsOpen(true);\n }, []);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setIsReady(false);\n }, []);\n\n const signOut = useCallback(async () => {\n await silentLogout({ apiKey, widgetUrl: resolvedWidgetUrl });\n setAndPersist(null);\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n const getAccessToken = useCallback(async (): Promise<string> => {\n const current = userRef.current;\n if (!current) throw new Error(\"Not signed in\");\n\n const expiresAt = current.expiresAt\n ? new Date(current.expiresAt).getTime()\n : null;\n const now = Date.now();\n const needsRefresh =\n !expiresAt || expiresAt - now < REFRESH_LEEWAY_SECONDS * 1000;\n\n if (!needsRefresh && current.accessToken) {\n return current.accessToken;\n }\n\n if (refreshInFlight.current) {\n return refreshInFlight.current;\n }\n\n refreshInFlight.current = (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n const latest = userRef.current;\n if (!latest) throw new Error(\"Signed out during refresh\");\n const next: RiftUser = {\n ...latest,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n };\n setAndPersist(next);\n return result.accessToken;\n } catch (err: any) {\n // Refresh failed — wipe state so the host UI can prompt re-auth.\n setAndPersist(null);\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n refreshInFlight.current = null;\n }\n })();\n return refreshInFlight.current;\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n // Listen for messages from the VISIBLE login iframe (not the silent\n // refresh one — that one's events are handled inside silentRefresh.ts).\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const handler = (e: MessageEvent) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data as RiftEvent | undefined;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n switch (data.type) {\n case \"rift:ready\":\n // Only treat as \"modal ready\" while it's open — the silent\n // refresh iframe also emits ready, but we don't care here.\n if (isOpen) setIsReady(true);\n break;\n case \"rift:close\":\n close();\n break;\n case \"rift:resize\":\n setIframeHeight(Math.max(360, Math.min(820, data.height + 8)));\n break;\n case \"rift:signin-success\": {\n const next: RiftUser = {\n user: data.user,\n address: data.address,\n btcAddress: data.btcAddress,\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n };\n setAndPersist(next);\n setIsOpen(false);\n break;\n }\n case \"rift:signin-error\":\n setError(data.message);\n break;\n // refresh / logout result events belong to silentRefresh.ts —\n // ignore them here.\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [widgetOrigin, close, setAndPersist, isOpen]);\n\n // Lock host page scroll while the modal is open.\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n if (isOpen) {\n const prev = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n return () => {\n document.documentElement.style.overflow = prev;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (autoOpen && !user) open();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const iframeSrc = useMemo(() => {\n const params = new URLSearchParams({\n key: apiKey,\n mode,\n origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n t: String(openToken),\n });\n\n // Best-effort: match the host page's theme so the modal blends in\n // instead of flashing white over a dark site. Checks data-theme,\n // the `dark` class convention, then system preference.\n if (typeof document !== \"undefined\") {\n const html = document.documentElement;\n const attr = html.getAttribute(\"data-theme\");\n let theme: string | null = null;\n if (attr === \"dark\" || attr === \"light\") theme = attr;\n else if (\n html.classList.contains(\"dark\") ||\n document.body?.classList.contains(\"dark\")\n )\n theme = \"dark\";\n else if (\n window.matchMedia &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n )\n theme = \"dark\";\n if (theme) params.set(\"theme\", theme);\n }\n\n return `${resolvedWidgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n }, [apiKey, mode, openToken, resolvedWidgetUrl]);\n\n const onIframeLoad = useCallback(() => {\n /* readiness is signalled via postMessage, not the load event */\n }, []);\n\n const value = useMemo<RiftContextValue>(\n () => ({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n _iframeSrc: iframeSrc,\n _iframeHeight: iframeHeight,\n _onIframeLoad: onIframeLoad,\n }),\n [\n apiKey,\n resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n iframeSrc,\n iframeHeight,\n onIframeLoad,\n ]\n );\n\n return <RiftContext.Provider value={value}>{children}</RiftContext.Provider>;\n}\n","import { useEffect, type CSSProperties } from \"react\";\nimport { useRiftContext } from \"./RiftProvider\";\nimport type { RiftUser } from \"./types\";\n\ninterface BackdropStyle {\n /** Backdrop fill colour. Default `rgba(15,15,20,0.55)` (dark scrim). */\n color?: string;\n /** CSS `backdrop-filter: blur(<px>)`. Default 6, set 0 to disable. */\n blur?: number;\n}\n\ninterface RiftAuthProps {\n // Optional event hooks so callers don't have to compose useEffect by hand.\n onSuccess?: (user: RiftUser) => void;\n onError?: (message: string) => void;\n onClose?: () => void;\n\n /**\n * Cap the modal height. Pass a number for px (e.g. `600`) or a CSS\n * string for viewport units (`\"70vh\"`). The iframe scrolls\n * internally if its content exceeds this. Defaults to no cap; the\n * widget reports its natural height via postMessage.\n */\n maxHeight?: number | string;\n\n /**\n * Cap the modal width. Defaults to 480 (px). Pass any CSS length.\n */\n maxWidth?: number | string;\n\n /**\n * Corner radius on the modal. Defaults to 18 (px).\n */\n radius?: number | string;\n\n /**\n * Backdrop styling. See `BackdropStyle`. Each field falls back to\n * the default if omitted.\n */\n backdrop?: BackdropStyle;\n\n /**\n * Extra style applied to the backdrop wrapper. Use for things outside\n * the typed `backdrop` knob (custom transitions, z-index, etc.).\n */\n backdropStyle?: CSSProperties;\n\n /**\n * Extra style applied to the iframe. Useful for borders, custom\n * shadows, or filters that the typed props don't cover.\n */\n iframeStyle?: CSSProperties;\n}\n\nconst DEFAULT_BACKDROP_COLOR = \"rgba(15,15,20,0.55)\";\nconst DEFAULT_BACKDROP_BLUR = 6;\nconst DEFAULT_MAX_WIDTH = 480;\nconst DEFAULT_RADIUS = 18;\n\n/**\n * Renders the modal backdrop + iframe whenever the provider's `isOpen` is\n * true. Place this once near the root of your app (typically just inside\n * <RiftProvider>); call `useRift().open()` to show it.\n *\n * All visual knobs are overridable from the host: see `maxHeight`,\n * `maxWidth`, `radius`, `backdrop`, plus escape hatches `backdropStyle`\n * and `iframeStyle` for anything else.\n */\nexport function RiftAuth({\n onSuccess,\n onError,\n onClose,\n maxHeight,\n maxWidth = DEFAULT_MAX_WIDTH,\n radius = DEFAULT_RADIUS,\n backdrop,\n backdropStyle,\n iframeStyle,\n}: RiftAuthProps) {\n const {\n isOpen,\n isReady,\n error,\n close,\n user,\n _iframeSrc,\n _iframeHeight,\n _onIframeLoad,\n } = useRiftContext();\n\n useEffect(() => {\n if (user && onSuccess) onSuccess(user);\n }, [user, onSuccess]);\n\n useEffect(() => {\n if (error && onError) onError(error);\n }, [error, onError]);\n\n useEffect(() => {\n if (!isOpen && onClose) onClose();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const backdropColor = backdrop?.color ?? DEFAULT_BACKDROP_COLOR;\n const backdropBlur = backdrop?.blur ?? DEFAULT_BACKDROP_BLUR;\n const blurCss = backdropBlur > 0 ? `blur(${backdropBlur}px)` : undefined;\n\n // Resolve the iframe's final height. The widget posts its desired\n // height via `rift:resize`; we honor it but clamp to `maxHeight` if\n // the host asked us to. For numeric maxHeight, we min() against the\n // reported height (so a fixed modal doesn't grow past it). For string\n // values like \"70vh\", we hand the limit to CSS via `maxHeight` and\n // let the browser do the math, but still cap our height attribute by\n // the reported natural height so we don't reserve unused space.\n let iframeHeight: number | string = _iframeHeight;\n let iframeMaxHeight: number | string | undefined;\n if (typeof maxHeight === \"number\") {\n iframeHeight = Math.min(_iframeHeight, maxHeight);\n } else if (typeof maxHeight === \"string\") {\n iframeMaxHeight = maxHeight;\n }\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Sign in\"\n onClick={(e) => {\n if (e.target === e.currentTarget) close();\n }}\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483646,\n background: backdropColor,\n backdropFilter: blurCss,\n WebkitBackdropFilter: blurCss,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n animation: \"rift-fade 180ms ease-out\",\n ...backdropStyle,\n }}\n >\n <style>{`@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }`}</style>\n {!isReady && (\n <div\n aria-hidden\n style={{\n position: \"absolute\",\n color: \"rgba(255,255,255,0.75)\",\n fontSize: 13,\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, sans-serif\",\n }}\n >\n Loading sign-in…\n </div>\n )}\n <iframe\n src={_iframeSrc}\n onLoad={_onIframeLoad}\n title=\"Rift sign-in\"\n allow=\"publickey-credentials-get; identity-credentials-get\"\n style={{\n border: 0,\n background: \"transparent\",\n colorScheme: \"light\",\n width: \"100%\",\n maxWidth,\n height: iframeHeight,\n maxHeight: iframeMaxHeight,\n borderRadius: radius,\n boxShadow: \"0 24px 60px -12px rgba(0,0,0,0.35)\",\n transition: \"height 200ms ease\",\n opacity: isReady ? 1 : 0,\n ...iframeStyle,\n }}\n />\n </div>\n );\n}\n","import { useRiftContext } from \"./RiftProvider\";\nimport type { RiftMode, RiftUser } from \"./types\";\n\ninterface UseRiftReturn {\n user: RiftUser | null;\n isAuthenticated: boolean;\n isOpen: boolean;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Async getter for a valid access token. Use this when calling Rift /\n * your backend — it returns the current token if fresh, or silently\n * refreshes via a hidden iframe if near expiry. Rejects when the user\n * isn't signed in or the refresh fails (in which case auth state is\n * cleared and the host should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n error: string | null;\n}\n\n/**\n * Read auth state and drive the widget from anywhere inside <RiftProvider>.\n *\n * const { user, isAuthenticated, open, signOut, getAccessToken } = useRift();\n * return isAuthenticated\n * ? <button onClick={signOut}>Sign out</button>\n * : <button onClick={() => open({ mode: 'signup' })}>Get started</button>;\n *\n * // When calling your backend with Rift's session JWT:\n * const token = await getAccessToken();\n * fetch('/api/my-thing', { headers: { Authorization: `Bearer ${token}` } });\n */\nexport function useRift(): UseRiftReturn {\n const { user, isOpen, open, close, signOut, getAccessToken, error } =\n useRiftContext();\n return {\n user,\n isAuthenticated: !!user,\n isOpen,\n open,\n close,\n signOut,\n getAccessToken,\n error,\n };\n}\n"],"names":["iframe","ready","readyResolvers","widgetOrigin","pending","uuid","ensureMounted","opts","params","e","data","r","slot","resolve","silentRefresh","requestId","reject","silentLogout","DEFAULT_WIDGET_URL","IDENTITY_STORAGE_KEY","REFRESH_LEEWAY_SECONDS","RiftContext","createContext","useRiftContext","ctx","useContext","loadIdentity","raw","saveIdentity","id","RiftProvider","apiKey","widgetUrl","children","autoOpen","persist","resolvedWidgetUrl","useMemo","user","setUser","useState","isOpen","setIsOpen","mode","setMode","isReady","setIsReady","error","setError","iframeHeight","setIframeHeight","openToken","setOpenToken","userRef","useRef","refreshInFlight","setAndPersist","useCallback","next","useEffect","identity","alive","result","open","t","close","signOut","getAccessToken","current","expiresAt","now","latest","err","handler","prev","iframeSrc","html","attr","theme","onIframeLoad","value","jsx","DEFAULT_BACKDROP_COLOR","DEFAULT_BACKDROP_BLUR","DEFAULT_MAX_WIDTH","DEFAULT_RADIUS","RiftAuth","onSuccess","onError","onClose","maxHeight","maxWidth","radius","backdrop","backdropStyle","iframeStyle","_iframeSrc","_iframeHeight","_onIframeLoad","backdropColor","backdropBlur","blurCss","iframeMaxHeight","jsxs","useRift"],"mappings":"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"}
1
+ {"version":3,"file":"rift-react.js","sources":["../src/silentRefresh.ts","../src/RiftProvider.tsx","../src/RiftAuth.tsx","../src/useRift.ts"],"sourcesContent":["/**\n * Silent-refresh bridge.\n *\n * The v2 backend session sits behind an httpOnly refresh cookie scoped\n * to the widget origin (widget.riftfi.xyz → service.riftfi.xyz). The\n * cookie cannot be read or sent from the merchant's own JS — only\n * widget-origin code can use it. So to refresh, we mount a HIDDEN\n * widget iframe in `?headless=1` mode and ask it (via postMessage) to\n * call /auth/refresh on our behalf. It posts the new access token back.\n *\n * This module owns that iframe as a singleton: we lazily create it on\n * the first refresh request, keep it alive across the page's lifetime,\n * and use a requestId-based pending map so concurrent refresh calls\n * dedupe to one network round trip.\n */\n\nlet iframe: HTMLIFrameElement | null = null;\nlet ready = false;\nlet readyResolvers: Array<() => void> = [];\nlet widgetOrigin: string | null = null;\n\ninterface Pending {\n resolve: (value: RefreshSuccess) => void;\n reject: (err: Error) => void;\n}\nconst pending = new Map<string, Pending>();\n\nexport interface RefreshSuccess {\n accessToken: string;\n expiresAt: string;\n expiresIn: number;\n}\n\nfunction uuid(): string {\n // Lightweight ID — doesn't need crypto strength, just unique per page.\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction ensureMounted(opts: { apiKey: string; widgetUrl: string }): Promise<void> {\n if (typeof document === \"undefined\") {\n return Promise.reject(new Error(\"Cannot mount refresh iframe outside the browser\"));\n }\n if (iframe && ready) return Promise.resolve();\n\n widgetOrigin = new URL(opts.widgetUrl).origin;\n\n if (!iframe) {\n iframe = document.createElement(\"iframe\");\n iframe.setAttribute(\"aria-hidden\", \"true\");\n iframe.setAttribute(\"tabindex\", \"-1\");\n iframe.title = \"Rift session refresh\";\n iframe.style.cssText =\n \"position:absolute;width:1px;height:1px;border:0;opacity:0;pointer-events:none;left:-9999px;top:-9999px;\";\n const params = new URLSearchParams({\n key: opts.apiKey,\n headless: \"1\",\n });\n iframe.src = `${opts.widgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n document.body.appendChild(iframe);\n\n window.addEventListener(\"message\", (e) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n if (data.type === \"rift:ready\") {\n ready = true;\n readyResolvers.forEach((r) => r());\n readyResolvers = [];\n return;\n }\n if (data.type === \"rift:refresh-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n expiresIn: data.expiresIn,\n });\n }\n return;\n }\n if (data.type === \"rift:refresh-error\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.reject(new Error(data.message || \"Refresh failed\"));\n }\n return;\n }\n if (data.type === \"rift:logout-result\") {\n const slot = pending.get(data.requestId);\n if (slot) {\n pending.delete(data.requestId);\n slot.resolve({ accessToken: \"\", expiresAt: \"\", expiresIn: 0 });\n }\n }\n });\n }\n\n if (ready) return Promise.resolve();\n return new Promise((resolve) => {\n readyResolvers.push(resolve);\n // Safety net: if the iframe somehow never posts ready (e.g. blocked\n // by browser privacy mode), reject after 8s so callers can surface\n // a useful error.\n setTimeout(() => {\n if (!ready) {\n const r = readyResolvers.shift();\n if (r) r();\n }\n }, 8000);\n });\n}\n\nexport async function silentRefresh(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<RefreshSuccess> {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) {\n throw new Error(\"Refresh iframe is not available\");\n }\n const requestId = uuid();\n return new Promise<RefreshSuccess>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:refresh-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n const slot = pending.get(requestId);\n if (slot) {\n pending.delete(requestId);\n slot.reject(new Error(\"Refresh timed out\"));\n }\n }, 10000);\n });\n}\n\nexport async function silentLogout(opts: {\n apiKey: string;\n widgetUrl: string;\n}): Promise<void> {\n try {\n await ensureMounted(opts);\n if (!iframe?.contentWindow || !widgetOrigin) return;\n const requestId = uuid();\n await new Promise<void>((resolve) => {\n pending.set(requestId, {\n resolve: () => resolve(),\n reject: () => resolve(), // logout is idempotent — never reject\n });\n iframe!.contentWindow!.postMessage(\n { type: \"rift:logout-request\", requestId },\n widgetOrigin!\n );\n setTimeout(() => {\n pending.delete(requestId);\n resolve();\n }, 5000);\n });\n } catch {\n /* logout is best-effort */\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport type { RiftConfig, RiftEvent, RiftMode, RiftUser } from \"./types\";\nimport { silentLogout, silentRefresh } from \"./silentRefresh\";\n\n// Widget URL by environment. The widget is a separate Vite SPA that\n// gets built once per environment (the backend URL is baked into the\n// bundle), so picking the environment here is equivalent to picking\n// which deployed widget the iframe loads.\n//\n// Override either by passing `widgetUrl=` directly (wins over\n// `environment`), or self-host and point at your own URL.\nconst WIDGET_URL_BY_ENV: Record<\"production\" | \"sandbox\", string> = {\n production: \"https://widget.riftfi.xyz\",\n sandbox: \"https://widget.sandbox.riftfi.com\",\n};\n\n// v2 session-mode policy: the access token lives in memory only. We\n// persist a small \"identity hint\" (user id, address, btcAddress) so the\n// UI can render an authenticated state on hard reload, but the actual\n// access JWT is re-issued via the refresh cookie. Refresh tokens live\n// in an httpOnly cookie scoped to the widget origin — totally invisible\n// to this code, which is the whole point.\nconst IDENTITY_STORAGE_KEY = \"rift:identity\";\n\ninterface PersistedIdentity {\n user: string;\n address: string;\n btcAddress?: string;\n}\n\n// Refresh proactively this many seconds before the access token expires.\n// Keeps API calls from racing the actual expiry.\nconst REFRESH_LEEWAY_SECONDS = 60;\n\ninterface RiftContextValue {\n apiKey: string;\n widgetUrl: string;\n user: RiftUser | null;\n isOpen: boolean;\n isReady: boolean;\n error: string | null;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Returns a valid access token, refreshing silently if the current\n * one is missing or about to expire. Rejects if the user is signed\n * out or the refresh fails (in which case state is cleared and the\n * caller should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n _iframeSrc: string;\n _iframeHeight: number;\n _onIframeLoad: () => void;\n}\n\nconst RiftContext = createContext<RiftContextValue | null>(null);\n\nexport function useRiftContext(): RiftContextValue {\n const ctx = useContext(RiftContext);\n if (!ctx) {\n throw new Error(\n \"[@rift/react] useRift() / <RiftAuth> must be used inside <RiftProvider>\"\n );\n }\n return ctx;\n}\n\ninterface RiftProviderProps extends RiftConfig {\n children: ReactNode;\n // Auto-open the modal on mount. Most apps will leave this false and call\n // open() in response to a user clicking \"Sign in\".\n autoOpen?: boolean;\n // Restore the persisted identity (just the user id / address — never\n // the access token) on mount, then silently refresh to mint a token.\n // Default: true.\n persist?: boolean;\n}\n\nfunction loadIdentity(): PersistedIdentity | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(IDENTITY_STORAGE_KEY);\n return raw ? (JSON.parse(raw) as PersistedIdentity) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveIdentity(id: PersistedIdentity | null) {\n if (typeof window === \"undefined\") return;\n try {\n if (id) localStorage.setItem(IDENTITY_STORAGE_KEY, JSON.stringify(id));\n else localStorage.removeItem(IDENTITY_STORAGE_KEY);\n } catch {\n /* private mode / quota — non-fatal */\n }\n}\n\nexport function RiftProvider({\n apiKey,\n environment,\n widgetUrl,\n children,\n autoOpen = false,\n persist = true,\n}: RiftProviderProps) {\n const resolvedWidgetUrl =\n widgetUrl || WIDGET_URL_BY_ENV[environment ?? \"production\"];\n const widgetOrigin = useMemo(() => {\n try {\n return new URL(resolvedWidgetUrl).origin;\n } catch {\n return resolvedWidgetUrl;\n }\n }, [resolvedWidgetUrl]);\n\n const [user, setUser] = useState<RiftUser | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [mode, setMode] = useState<RiftMode>(\"signin\");\n const [isReady, setIsReady] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [iframeHeight, setIframeHeight] = useState(540);\n const [openToken, setOpenToken] = useState(0);\n\n // Hot ref to the current user — getAccessToken() reads from this so\n // it never closes over a stale React state snapshot.\n const userRef = useRef<RiftUser | null>(null);\n userRef.current = user;\n\n // Dedupe in-flight refreshes: if multiple API calls hit\n // getAccessToken() simultaneously and the token is stale, we only\n // want one network call.\n const refreshInFlight = useRef<Promise<string> | null>(null);\n\n const setAndPersist = useCallback(\n (next: RiftUser | null) => {\n setUser(next);\n if (persist) {\n saveIdentity(\n next\n ? {\n user: next.user,\n address: next.address,\n btcAddress: next.btcAddress,\n }\n : null\n );\n }\n },\n [persist]\n );\n\n // On mount, if we have a persisted identity, try a silent refresh to\n // rehydrate the access token. If it fails, drop the identity — the\n // user will be prompted to sign in again on first action.\n useEffect(() => {\n if (!persist) return;\n const identity = loadIdentity();\n if (!identity) return;\n let alive = true;\n (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n if (!alive) return;\n setAndPersist({\n user: identity.user,\n address: identity.address,\n btcAddress: identity.btcAddress,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n });\n } catch {\n if (!alive) return;\n // Refresh failed — likely cookie expired or revoked. Clear the\n // identity hint so the UI shows the signed-out state.\n setAndPersist(null);\n }\n })();\n return () => {\n alive = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const open = useCallback((opts?: { mode?: RiftMode }) => {\n setMode(opts?.mode || \"signin\");\n setError(null);\n setIsReady(false);\n setOpenToken((t) => t + 1);\n setIsOpen(true);\n }, []);\n\n const close = useCallback(() => {\n setIsOpen(false);\n setIsReady(false);\n }, []);\n\n const signOut = useCallback(async () => {\n await silentLogout({ apiKey, widgetUrl: resolvedWidgetUrl });\n setAndPersist(null);\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n const getAccessToken = useCallback(async (): Promise<string> => {\n const current = userRef.current;\n if (!current) throw new Error(\"Not signed in\");\n\n const expiresAt = current.expiresAt\n ? new Date(current.expiresAt).getTime()\n : null;\n const now = Date.now();\n const needsRefresh =\n !expiresAt || expiresAt - now < REFRESH_LEEWAY_SECONDS * 1000;\n\n if (!needsRefresh && current.accessToken) {\n return current.accessToken;\n }\n\n if (refreshInFlight.current) {\n return refreshInFlight.current;\n }\n\n refreshInFlight.current = (async () => {\n try {\n const result = await silentRefresh({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n });\n const latest = userRef.current;\n if (!latest) throw new Error(\"Signed out during refresh\");\n const next: RiftUser = {\n ...latest,\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n };\n setAndPersist(next);\n return result.accessToken;\n } catch (err: any) {\n // Refresh failed — wipe state so the host UI can prompt re-auth.\n setAndPersist(null);\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n refreshInFlight.current = null;\n }\n })();\n return refreshInFlight.current;\n }, [apiKey, resolvedWidgetUrl, setAndPersist]);\n\n // Listen for messages from the VISIBLE login iframe (not the silent\n // refresh one — that one's events are handled inside silentRefresh.ts).\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const handler = (e: MessageEvent) => {\n if (e.origin !== widgetOrigin) return;\n const data = e.data as RiftEvent | undefined;\n if (!data || typeof data !== \"object\" || typeof data.type !== \"string\") return;\n if (!data.type.startsWith(\"rift:\")) return;\n\n switch (data.type) {\n case \"rift:ready\":\n // Only treat as \"modal ready\" while it's open — the silent\n // refresh iframe also emits ready, but we don't care here.\n if (isOpen) setIsReady(true);\n break;\n case \"rift:close\":\n close();\n break;\n case \"rift:resize\":\n setIframeHeight(Math.max(360, Math.min(820, data.height + 8)));\n break;\n case \"rift:signin-success\": {\n const next: RiftUser = {\n user: data.user,\n address: data.address,\n btcAddress: data.btcAddress,\n accessToken: data.accessToken,\n expiresAt: data.expiresAt,\n };\n setAndPersist(next);\n setIsOpen(false);\n break;\n }\n case \"rift:signin-error\":\n setError(data.message);\n break;\n // refresh / logout result events belong to silentRefresh.ts —\n // ignore them here.\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, [widgetOrigin, close, setAndPersist, isOpen]);\n\n // Lock host page scroll while the modal is open.\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n if (isOpen) {\n const prev = document.documentElement.style.overflow;\n document.documentElement.style.overflow = \"hidden\";\n return () => {\n document.documentElement.style.overflow = prev;\n };\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (autoOpen && !user) open();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const iframeSrc = useMemo(() => {\n const params = new URLSearchParams({\n key: apiKey,\n mode,\n origin: typeof window !== \"undefined\" ? window.location.origin : \"\",\n t: String(openToken),\n });\n\n // Best-effort: match the host page's theme so the modal blends in\n // instead of flashing white over a dark site. Checks data-theme,\n // the `dark` class convention, then system preference.\n if (typeof document !== \"undefined\") {\n const html = document.documentElement;\n const attr = html.getAttribute(\"data-theme\");\n let theme: string | null = null;\n if (attr === \"dark\" || attr === \"light\") theme = attr;\n else if (\n html.classList.contains(\"dark\") ||\n document.body?.classList.contains(\"dark\")\n )\n theme = \"dark\";\n else if (\n window.matchMedia &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n )\n theme = \"dark\";\n if (theme) params.set(\"theme\", theme);\n }\n\n return `${resolvedWidgetUrl.replace(/\\/$/, \"\")}/?${params.toString()}`;\n }, [apiKey, mode, openToken, resolvedWidgetUrl]);\n\n const onIframeLoad = useCallback(() => {\n /* readiness is signalled via postMessage, not the load event */\n }, []);\n\n const value = useMemo<RiftContextValue>(\n () => ({\n apiKey,\n widgetUrl: resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n _iframeSrc: iframeSrc,\n _iframeHeight: iframeHeight,\n _onIframeLoad: onIframeLoad,\n }),\n [\n apiKey,\n resolvedWidgetUrl,\n user,\n isOpen,\n isReady,\n error,\n open,\n close,\n signOut,\n getAccessToken,\n iframeSrc,\n iframeHeight,\n onIframeLoad,\n ]\n );\n\n return <RiftContext.Provider value={value}>{children}</RiftContext.Provider>;\n}\n","import { useEffect, type CSSProperties } from \"react\";\nimport { useRiftContext } from \"./RiftProvider\";\nimport type { RiftUser } from \"./types\";\n\ninterface BackdropStyle {\n /** Backdrop fill colour. Default `rgba(15,15,20,0.55)` (dark scrim). */\n color?: string;\n /** CSS `backdrop-filter: blur(<px>)`. Default 6, set 0 to disable. */\n blur?: number;\n}\n\ninterface RiftAuthProps {\n // Optional event hooks so callers don't have to compose useEffect by hand.\n onSuccess?: (user: RiftUser) => void;\n onError?: (message: string) => void;\n onClose?: () => void;\n\n /**\n * Cap the modal height. Pass a number for px (e.g. `600`) or a CSS\n * string for viewport units (`\"70vh\"`). The iframe scrolls\n * internally if its content exceeds this. Defaults to no cap; the\n * widget reports its natural height via postMessage.\n */\n maxHeight?: number | string;\n\n /**\n * Cap the modal width. Defaults to 480 (px). Pass any CSS length.\n */\n maxWidth?: number | string;\n\n /**\n * Corner radius on the modal. Defaults to 18 (px).\n */\n radius?: number | string;\n\n /**\n * Backdrop styling. See `BackdropStyle`. Each field falls back to\n * the default if omitted.\n */\n backdrop?: BackdropStyle;\n\n /**\n * Extra style applied to the backdrop wrapper. Use for things outside\n * the typed `backdrop` knob (custom transitions, z-index, etc.).\n */\n backdropStyle?: CSSProperties;\n\n /**\n * Extra style applied to the iframe. Useful for borders, custom\n * shadows, or filters that the typed props don't cover.\n */\n iframeStyle?: CSSProperties;\n}\n\nconst DEFAULT_BACKDROP_COLOR = \"rgba(15,15,20,0.55)\";\nconst DEFAULT_BACKDROP_BLUR = 6;\nconst DEFAULT_MAX_WIDTH = 480;\nconst DEFAULT_RADIUS = 18;\n\n/**\n * Renders the modal backdrop + iframe whenever the provider's `isOpen` is\n * true. Place this once near the root of your app (typically just inside\n * <RiftProvider>); call `useRift().open()` to show it.\n *\n * All visual knobs are overridable from the host: see `maxHeight`,\n * `maxWidth`, `radius`, `backdrop`, plus escape hatches `backdropStyle`\n * and `iframeStyle` for anything else.\n */\nexport function RiftAuth({\n onSuccess,\n onError,\n onClose,\n maxHeight,\n maxWidth = DEFAULT_MAX_WIDTH,\n radius = DEFAULT_RADIUS,\n backdrop,\n backdropStyle,\n iframeStyle,\n}: RiftAuthProps) {\n const {\n isOpen,\n isReady,\n error,\n close,\n user,\n _iframeSrc,\n _iframeHeight,\n _onIframeLoad,\n } = useRiftContext();\n\n useEffect(() => {\n if (user && onSuccess) onSuccess(user);\n }, [user, onSuccess]);\n\n useEffect(() => {\n if (error && onError) onError(error);\n }, [error, onError]);\n\n useEffect(() => {\n if (!isOpen && onClose) onClose();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n const backdropColor = backdrop?.color ?? DEFAULT_BACKDROP_COLOR;\n const backdropBlur = backdrop?.blur ?? DEFAULT_BACKDROP_BLUR;\n const blurCss = backdropBlur > 0 ? `blur(${backdropBlur}px)` : undefined;\n\n // Resolve the iframe's final height. The widget posts its desired\n // height via `rift:resize`; we honor it but clamp to `maxHeight` if\n // the host asked us to. For numeric maxHeight, we min() against the\n // reported height (so a fixed modal doesn't grow past it). For string\n // values like \"70vh\", we hand the limit to CSS via `maxHeight` and\n // let the browser do the math, but still cap our height attribute by\n // the reported natural height so we don't reserve unused space.\n let iframeHeight: number | string = _iframeHeight;\n let iframeMaxHeight: number | string | undefined;\n if (typeof maxHeight === \"number\") {\n iframeHeight = Math.min(_iframeHeight, maxHeight);\n } else if (typeof maxHeight === \"string\") {\n iframeMaxHeight = maxHeight;\n }\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Sign in\"\n onClick={(e) => {\n if (e.target === e.currentTarget) close();\n }}\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483646,\n background: backdropColor,\n backdropFilter: blurCss,\n WebkitBackdropFilter: blurCss,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n animation: \"rift-fade 180ms ease-out\",\n ...backdropStyle,\n }}\n >\n <style>{`@keyframes rift-fade { from { opacity: 0 } to { opacity: 1 } }`}</style>\n {!isReady && (\n <div\n aria-hidden\n style={{\n position: \"absolute\",\n color: \"rgba(255,255,255,0.75)\",\n fontSize: 13,\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, sans-serif\",\n }}\n >\n Loading sign-in…\n </div>\n )}\n <iframe\n src={_iframeSrc}\n onLoad={_onIframeLoad}\n title=\"Rift sign-in\"\n allow=\"publickey-credentials-get; identity-credentials-get\"\n style={{\n border: 0,\n background: \"transparent\",\n colorScheme: \"light\",\n width: \"100%\",\n maxWidth,\n height: iframeHeight,\n maxHeight: iframeMaxHeight,\n borderRadius: radius,\n boxShadow: \"0 24px 60px -12px rgba(0,0,0,0.35)\",\n transition: \"height 200ms ease\",\n opacity: isReady ? 1 : 0,\n ...iframeStyle,\n }}\n />\n </div>\n );\n}\n","import { useRiftContext } from \"./RiftProvider\";\nimport type { RiftMode, RiftUser } from \"./types\";\n\ninterface UseRiftReturn {\n user: RiftUser | null;\n isAuthenticated: boolean;\n isOpen: boolean;\n open: (opts?: { mode?: RiftMode }) => void;\n close: () => void;\n signOut: () => Promise<void>;\n /**\n * Async getter for a valid access token. Use this when calling Rift /\n * your backend — it returns the current token if fresh, or silently\n * refreshes via a hidden iframe if near expiry. Rejects when the user\n * isn't signed in or the refresh fails (in which case auth state is\n * cleared and the host should prompt re-auth).\n */\n getAccessToken: () => Promise<string>;\n error: string | null;\n}\n\n/**\n * Read auth state and drive the widget from anywhere inside <RiftProvider>.\n *\n * const { user, isAuthenticated, open, signOut, getAccessToken } = useRift();\n * return isAuthenticated\n * ? <button onClick={signOut}>Sign out</button>\n * : <button onClick={() => open({ mode: 'signup' })}>Get started</button>;\n *\n * // When calling your backend with Rift's session JWT:\n * const token = await getAccessToken();\n * fetch('/api/my-thing', { headers: { Authorization: `Bearer ${token}` } });\n */\nexport function useRift(): UseRiftReturn {\n const { user, isOpen, open, close, signOut, getAccessToken, error } =\n useRiftContext();\n return {\n user,\n isAuthenticated: !!user,\n isOpen,\n open,\n close,\n signOut,\n getAccessToken,\n error,\n };\n}\n"],"names":["iframe","ready","readyResolvers","widgetOrigin","pending","uuid","ensureMounted","opts","params","e","data","r","slot","resolve","silentRefresh","requestId","reject","silentLogout","WIDGET_URL_BY_ENV","IDENTITY_STORAGE_KEY","REFRESH_LEEWAY_SECONDS","RiftContext","createContext","useRiftContext","ctx","useContext","loadIdentity","raw","saveIdentity","id","RiftProvider","apiKey","environment","widgetUrl","children","autoOpen","persist","resolvedWidgetUrl","useMemo","user","setUser","useState","isOpen","setIsOpen","mode","setMode","isReady","setIsReady","error","setError","iframeHeight","setIframeHeight","openToken","setOpenToken","userRef","useRef","refreshInFlight","setAndPersist","useCallback","next","useEffect","identity","alive","result","open","t","close","signOut","getAccessToken","current","expiresAt","now","latest","err","handler","prev","iframeSrc","html","attr","theme","onIframeLoad","value","jsx","DEFAULT_BACKDROP_COLOR","DEFAULT_BACKDROP_BLUR","DEFAULT_MAX_WIDTH","DEFAULT_RADIUS","RiftAuth","onSuccess","onError","onClose","maxHeight","maxWidth","radius","backdrop","backdropStyle","iframeStyle","_iframeSrc","_iframeHeight","_onIframeLoad","backdropColor","backdropBlur","blurCss","iframeMaxHeight","jsxs","useRift"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -14,6 +14,7 @@ export interface RiftUser {
14
14
  }
15
15
  export interface RiftConfig {
16
16
  apiKey: string;
17
+ environment?: "production" | "sandbox";
17
18
  widgetUrl?: string;
18
19
  }
19
20
  export type RiftEvent = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IAEzB,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9C;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IAEzB,MAAM,EAAE,MAAM,CAAC;IAcf,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAGvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9C;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rift-finance/react",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "React bindings for the Rift sign-in widget. Drop in <RiftProvider>, render <RiftAuth>, and read auth state with useRift().",
5
5
  "repository": {
6
6
  "type": "git",