@returningai/widget-sdk 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -236,6 +236,8 @@ The SDK scans for the loader `<script>` tag, reads its `data-*` attributes, crea
236
236
 
237
237
  Credentials live only in your server environment. Your server calls RAI to get a short-lived embed token and injects it into the page response — no secret ever reaches the browser.
238
238
 
239
+ **Create an access key pair:** Go to **Community Settings > Integrations > SDK Access** in your ReturningAI dashboard and click **Create SDK Key**. The `accessKey` is shown once — save it securely.
240
+
239
241
  ```
240
242
  Your server env:
241
243
  RAI_ACCESS_ID = rai_...
@@ -422,7 +424,7 @@ After the SDK loads, `window.ReturningAIWidget` is available:
422
424
 
423
425
  ```javascript
424
426
  // Check the loaded version
425
- window.ReturningAIWidget.version // e.g. "1.1.1"
427
+ window.ReturningAIWidget.version // e.g. "1.1.2"
426
428
 
427
429
  // Reload the widget (re-runs auth flow)
428
430
  await window.ReturningAIWidget.reload()
@@ -1 +1 @@
1
- var RaiWidget=function(e){"use strict";var t=Object.defineProperty,r=(e,r,i)=>((e,r,i)=>r in e?t(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i)(e,"symbol"!=typeof r?r+"":r,i);function i(e){return`${e.storagePrefix}-${e.widgetId}-auth`}function a(e){return`${e.storagePrefix}-${e.widgetId}-error-settings`}function s(e){try{localStorage.removeItem(i(e))}catch{}}function n(e){return!e||Date.now()>=e-6e4}function o(e,t,r,a){t.accessToken=r.accessToken,t.refreshToken=r.refreshToken,t.tokenFamily=r.tokenFamily??null;const s=Date.now();t.accessTokenExpiry=s+1e3*r.accessTokenTTL,t.refreshTokenExpiry=s+1e3*r.refreshTokenTTL,function(e,t){try{const r={refreshToken:t.refreshToken,tokenFamily:t.tokenFamily,refreshTokenExpiry:t.refreshTokenExpiry};localStorage.setItem(i(e),JSON.stringify(r))}catch{}}(e,t),e.autoRefresh&&a&&a()}async function l(e,t,r){const i=crypto.randomUUID(),a=Date.now(),s=e.maxRetries??3,n=e.retryDelay??500;for(let l=0;l<=s;l++){l>0&&await new Promise(e=>setTimeout(e,n*(1<<l-1)));let c=!1;try{const s=await fetch(`${e.apiUrl}/${e.widgetId}/auth/serverless`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({nonce:i,timestamp:a,widgetType:e.widgetType,userIdentifiers:e.userIdentifiers}),credentials:"include"});if(!s.ok){c=s.status>=400&&s.status<500;const e=await s.json().catch(()=>({error:"Authentication failed"}));throw new Error(e.error||`HTTP ${s.status}`)}const n=await s.json();if(!n.accessToken||!n.refreshToken)throw new Error("Invalid authentication response");return o(e,t,n,r),t.isAuthenticated=!0,!0}catch{if(c||l===s)return t.isAuthenticated=!1,!1}}return t.isAuthenticated=!1,!1}async function c(e,t,r){const i=e.maxRetries??3,a=e.retryDelay??500;for(let s=0;s<=i;s++){s>0&&await new Promise(e=>setTimeout(e,a*(1<<s-1)));let n=!1;try{const i=await fetch(e.authUrl,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"}});if(!i.ok)throw n=i.status>=400&&i.status<500,new Error(`HTTP ${i.status}`);const a=await i.json();if(!a.token)throw new Error("Invalid proxy auth response");const s=a.expiresIn??300;return t.accessToken=a.token,t.refreshToken=null,t.tokenFamily=null,t.accessTokenExpiry=Date.now()+1e3*s,t.refreshTokenExpiry=null,t.isAuthenticated=!0,e.autoRefresh&&r&&r(),!0}catch{if(n||s===i)return t.isAuthenticated=!1,!1}}return t.isAuthenticated=!1,!1}async function d(e,t,r,i){return t.isRefreshing?t.refreshPromise:!!t.refreshToken&&(t.isRefreshing=!0,t.refreshPromise=(async()=>{try{const a=await fetch(`${e.apiUrl}/${e.widgetId}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.refreshToken}`},body:JSON.stringify({widgetType:e.widgetType})});if(!a.ok){if(401===a.status||403===a.status)return u(t),s(e),l(e,t,r);const i=await a.json().catch(()=>({error:"Token refresh failed"}));throw new Error(i.error||`HTTP ${a.status}`)}const n=await a.json();if(!n.accessToken||!n.refreshToken)throw new Error("Invalid refresh response");return o(e,t,n,r),i&&i(),!0}catch{return u(t),s(e),l(e,t,r)}finally{t.isRefreshing=!1,t.refreshPromise=null}})(),t.refreshPromise)}async function h(e,t){const r=function(e){try{const t=localStorage.getItem(a(e));if(!t)return null;const r=JSON.parse(t);return r.cachedAt&&Date.now()-r.cachedAt<36e5?r:(localStorage.removeItem(a(e)),null)}catch{return null}}(e);if(r)return r.configured&&(t.errorSettings={errorMessage:r.errorMessage,modalColor:r.modalColor,backgroundImage:r.backgroundImage}),t.errorSettings;try{const r=await fetch(`${e.apiUrl}/${e.widgetId}/auth/error-settings?widgetType=${e.widgetType}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!r.ok)return null;const i=await r.json();return function(e,t){try{localStorage.setItem(a(e),JSON.stringify({...t,cachedAt:Date.now()}))}catch{}}(e,i),i.configured&&(t.errorSettings={errorMessage:i.errorMessage,modalColor:i.modalColor,backgroundImage:i.backgroundImage}),t.errorSettings}catch{return null}}function u(e){e.accessToken=null,e.refreshToken=null,e.tokenFamily=null,e.accessTokenExpiry=null,e.refreshTokenExpiry=null,e.isAuthenticated=!1,e.isRefreshing=!1,e.refreshPromise=null,e.refreshTimer&&(clearTimeout(e.refreshTimer),e.refreshTimer=null),e.syncTimer&&(clearInterval(e.syncTimer),e.syncTimer=null)}function f(e,t,r){var i;if(t.accessToken)try{null==(i=r.contentWindow)||i.postMessage({type:"RETURNINGAI_WIDGET_TOKEN",value:{widgetId:e.widgetId,token:t.accessToken,...void 0!==e.customData&&{customData:e.customData}}},e.widgetDomain)}catch{}}function m(e,t,r,i,a,s,o,h){const u=function(e,t){let r=null;return{call(i){r&&clearTimeout(r),r=setTimeout(()=>{e(i),r=null},t)},cancel(){r&&(clearTimeout(r),r=null)}}}(e=>{i.style.height=`${e}px`,null==h||h("rai-height-change",{height:e})},e.heightDebounce??100),f=async r=>{var f;if(r.origin!==e.widgetDomain)return;if(!r.data||"string"!=typeof r.data.type)return;const{type:m,containerId:g,widgetId:p,payload:y}=r.data;switch(m){case"RETURNINGAI_WIDGET_REQUEST_TOKEN":try{const r=await async function(e,t,r){if(t.accessToken&&!n(t.accessTokenExpiry))return t.accessToken;if(e.authUrl){if(await c(e,t,r)&&t.accessToken)return t.accessToken;throw new Error("Unable to obtain valid token")}if(await d(e,t,r)&&t.accessToken)return t.accessToken;if(await l(e,t,r)&&t.accessToken)return t.accessToken;throw new Error("Unable to obtain valid token")}(e,t,a);null==(f=i.contentWindow)||f.postMessage({type:"RETURNINGAI_WIDGET_TOKEN",value:{token:r,widgetId:e.widgetId,...void 0!==e.customData&&{customData:e.customData}}},e.widgetDomain)}catch{}break;case"WIDGET_HEIGHT_UPDATE":{const e=Number(null==y?void 0:y.height);Number.isFinite(e)&&e>0&&u.call(e);break}case"WIDGET_READY":if(void 0!==p&&p!==e.widgetId)break;if(void 0!==g&&g!==e.container)break;i.classList.add("loaded"),o&&o(),null==h||h("rai-ready");break;case"WIDGET_ERROR":o&&o();break;case"WIDGET_LOGOUT":s&&await s()}};return window.addEventListener("message",f),()=>{window.removeEventListener("message",f),u.cancel()}}const g=new Set(["community-id","channel-id","widget-id","widget-type","theme","container","width","height","api-url","widget-url","auto-refresh","debug","storage-prefix","max-retries","retry-delay","height-debounce","locale","custom-data","retry-label","auth-url","bundle-url","embed-token","v2-api-url"]),p={store:"RaiStoreWidget",channel:"RaiChannelWidget",social:"RaiSocialWidget",milestone:"RaiMilestoneWidget","currency-view":"RaiCurrencyWidget"},y={"RAI-STORE-WIDGET":"store","RAI-CHANNEL-WIDGET":"channel","RAI-MILESTONE-WIDGET":"milestone","RAI-SOCIAL-WIDGET":"social","RAI-CURRENCY-WIDGET":"currency-view","RAI-WIDGET":"store"};class w extends HTMLElement{constructor(){super(),r(this,"shadow"),r(this,"config"),r(this,"state",{accessToken:null,refreshToken:null,tokenFamily:null,accessTokenExpiry:null,refreshTokenExpiry:null,refreshTimer:null,syncTimer:null,iframe:null,isAuthenticated:!1,isRefreshing:!1,refreshPromise:null,errorSettings:null}),r(this,"loaderEl",null),r(this,"errorEl",null),r(this,"msgEl",null),r(this,"cleanupListener"),r(this,"intersectionObserver"),r(this,"themeObserver"),this.shadow=this.attachShadow({mode:"closed"})}connectedCallback(){this.config=function(e,t){const r=t=>e.getAttribute(t)??e.getAttribute(`data-${t}`)??"",i=(e,t)=>{const i=parseInt(r(e),10);return Number.isFinite(i)&&i>=0?i:t},a=!!r("community-id"),s=r("community-id")||r("widget-id")||t||"";if(s&&!/^[a-zA-Z0-9_\-=]{8,}$/.test(s))throw new Error(`[rai-widget] Invalid community-id: "${s}"`);const n=r("channel-id")||void 0;if(n&&!/^[a-zA-Z0-9_\-=]{8,}$/.test(n))throw new Error(`[rai-widget] Invalid channel-id: "${n}"`);const o=r("widget-type")||y[e.tagName]||"store";let l;l=a?"store"===o?s:"channel"===o?n?btoa(n):s:s?btoa(s):s:s;let c,d=r("widget-url")||"https://widget.returningai.com";d.endsWith("store-widget")&&(d=`${d}/${s}/open-widget`);try{c=new URL(d).origin}catch{c=d}if(d.includes("store-widget")){const e=new URL(d);e.searchParams.set("color",r("theme")||"light"),d=e.toString()}const h=r("container")||r("data-container")||`returning-ai-widget-${s}`,u={};Array.from(e.attributes).forEach(e=>{const t=e.name.toLowerCase();if(!t.startsWith("data-"))return;const r=t.slice(5);g.has(r)||(u[t]=e.value)});const f=(()=>{const e=r("custom-data");if(e)try{return JSON.parse(e)}catch{return}})();return{communityId:s,channelId:n,widgetId:l,widgetType:o,theme:r("theme")||"light",container:h,width:r("width")||"100%",height:r("height")||"600px",apiUrl:r("api-url")||"https://sgtr-eks-widgets.genesiv.org",widgetUrl:d,widgetDomain:c,autoRefresh:"false"!==r("auto-refresh"),debug:"true"===r("debug"),storagePrefix:r("storage-prefix")||"returning-ai-widget",userIdentifiers:u,maxRetries:i("max-retries",3),retryDelay:i("retry-delay",500),heightDebounce:i("height-debounce",100),locale:r("locale")||void 0,customData:f,authUrl:r("auth-url")||void 0,bundleUrl:r("bundle-url")||void 0,embedToken:r("embed-token")||void 0,v2ApiUrl:r("v2-api-url")||void 0}}(this,void 0);const e=document.createElement("style");e.textContent=":host{display:block;position:relative;width:100%;height:100%}.rai-loader{position:absolute;top:0;left:0;display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:var(--rai-loader-bg, #ffffff);border-radius:8px;z-index:10;transition:opacity .3s ease-out}.rai-loader.fade-out{opacity:0;pointer-events:none}.rai-error{display:none;position:absolute;top:0;left:0;width:100%;height:100%;align-items:center;justify-content:center;flex-direction:column;gap:12px;background:var(--rai-error-bg, #1a1a1a);border-radius:8px;padding:24px;box-sizing:border-box;text-align:center;color:var(--rai-error-text, #9ca3af);font-family:system-ui,-apple-system,sans-serif;z-index:10}.rai-error.visible{display:flex}iframe{display:block;border:none;opacity:0;transition:opacity .3s ease-in}iframe.loaded{opacity:1}.rai-sdk-loader{position:relative;width:75px;height:100px}.rai-sdk-loader__bar{position:absolute;bottom:0;width:10px;height:50%;background:var(--rai-accent, #000000);transform-origin:center bottom;box-shadow:1px 1px #0003}.rai-sdk-loader__bar:nth-child(1){left:0;transform:scaleY(.2);animation:rai-sdk-barUp1 4s infinite}.rai-sdk-loader__bar:nth-child(2){left:15px;transform:scaleY(.4);animation:rai-sdk-barUp2 4s infinite}.rai-sdk-loader__bar:nth-child(3){left:30px;transform:scaleY(.6);animation:rai-sdk-barUp3 4s infinite}.rai-sdk-loader__bar:nth-child(4){left:45px;transform:scaleY(.8);animation:rai-sdk-barUp4 4s infinite}.rai-sdk-loader__bar:nth-child(5){left:60px;transform:scale(1);animation:rai-sdk-barUp5 4s infinite}.rai-sdk-loader__ball{position:absolute;bottom:10px;left:0;width:10px;height:10px;background:var(--rai-accent, #000000);border-radius:50%;animation:rai-sdk-ball 4s infinite}@keyframes rai-sdk-ball{0%{transform:translate(0)}5%{transform:translate(8px,-14px)}10%{transform:translate(15px,-10px)}17%{transform:translate(23px,-24px)}20%{transform:translate(30px,-20px)}27%{transform:translate(38px,-34px)}30%{transform:translate(45px,-30px)}37%{transform:translate(53px,-44px)}40%{transform:translate(60px,-40px)}50%{transform:translate(60px)}57%{transform:translate(53px,-14px)}60%{transform:translate(45px,-10px)}67%{transform:translate(37px,-24px)}70%{transform:translate(30px,-20px)}77%{transform:translate(22px,-34px)}80%{transform:translate(15px,-30px)}87%{transform:translate(7px,-44px)}90%{transform:translateY(-40px)}to{transform:translate(0)}}@keyframes rai-sdk-barUp1{0%{transform:scaleY(.2)}40%{transform:scaleY(.2)}50%{transform:scale(1)}90%{transform:scale(1)}to{transform:scaleY(.2)}}@keyframes rai-sdk-barUp2{0%{transform:scaleY(.4)}40%{transform:scaleY(.4)}50%{transform:scaleY(.8)}90%{transform:scaleY(.8)}to{transform:scaleY(.4)}}@keyframes rai-sdk-barUp3{0%{transform:scaleY(.6)}to{transform:scaleY(.6)}}@keyframes rai-sdk-barUp4{0%{transform:scaleY(.8)}40%{transform:scaleY(.8)}50%{transform:scaleY(.4)}90%{transform:scaleY(.4)}to{transform:scaleY(.8)}}@keyframes rai-sdk-barUp5{0%{transform:scale(1)}40%{transform:scale(1)}50%{transform:scaleY(.2)}90%{transform:scaleY(.2)}to{transform:scale(1)}}#loading-square{width:75px;aspect-ratio:1;display:flex;color:var(--rai-accent, #000000);background:linear-gradient(currentColor 0 0) right / 51% 100%,linear-gradient(currentColor 0 0) bottom / 100% 51%;background-repeat:no-repeat;animation:l16-0 2s infinite linear .25s}#loading-square>div{width:50%;height:50%;background:currentColor;animation:l16-1 .5s infinite linear}@keyframes l16-0{0%,12.49%{transform:rotate(0)}12.5%,37.49%{transform:rotate(90deg)}37.5%,62.49%{transform:rotate(180deg)}62.5%,87.49%{transform:rotate(270deg)}87.5%,to{transform:rotate(360deg)}}@keyframes l16-1{0%{transform:perspective(80px) rotate3d(-1,-1,0,0)}80%,to{transform:perspective(80px) rotate3d(-1,-1,0,-180deg)}}#loading-circle{width:75px;aspect-ratio:1;display:grid;grid:50%/50%;color:var(--rai-accent, #000000);border-radius:50%;--_g: no-repeat linear-gradient(currentColor 0 0);background:var(--_g),var(--_g),var(--_g);background-size:50.1% 50.1%;animation:l9-0 1.5s infinite steps(1) alternate,l9-0-0 3s infinite steps(1) alternate}#loading-circle>div{background:var(--rai-text4, #6b7280);border-top-left-radius:100px;transform:perspective(150px) rotateY(0) rotateX(0);transform-origin:bottom right;animation:l9-1 1.5s infinite linear alternate}@keyframes l9-0{0%{background-position:0 100%,100% 100%,100% 0}33%{background-position:100% 100%,100% 100%,100% 0}66%{background-position:100% 0,100% 0,100% 0}}@keyframes l9-0-0{0%{transform:scaleX(1) rotate(0)}50%{transform:scaleX(-1) rotate(-90deg)}}@keyframes l9-1{16.5%{transform:perspective(150px) rotateX(-90deg) rotateY(0) rotateX(0);filter:grayscale(.8)}33%{transform:perspective(150px) rotateX(-180deg) rotateY(0) rotateX(0)}66%{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(0)}to{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(-180deg);filter:grayscale(.8)}}.rai-retry-btn{padding:8px 20px;border:none;border-radius:6px;background:var(--rai-accent, #000000);color:var(--rai-error-bg, #ffffff);font-size:14px;font-family:system-ui,-apple-system,sans-serif;cursor:pointer}.rai-retry-btn:hover{opacity:.85}",this.shadow.appendChild(e);const t=this.config.theme,r="dark"===t?"#ffffff":"#000000",i="dark"===t?"#9ca3af":"#6b7280",a="dark"===t?"#1a1a1a":"#ffffff";this.style.width=this.config.width,this.style.height=this.config.height,this.style.setProperty("--rai-accent",r),this.style.setProperty("--rai-text4",i),this.style.setProperty("--rai-loader-bg",a),this.style.setProperty("--rai-error-bg",a),this.renderShell(),this.hasAttribute("eager")?this.init():(this.intersectionObserver=new IntersectionObserver(e=>{e[0].isIntersecting&&(this.intersectionObserver.disconnect(),this.intersectionObserver=void 0,this.init())}),this.intersectionObserver.observe(this))}disconnectedCallback(){var e,t;null==(e=this.intersectionObserver)||e.disconnect(),null==(t=this.themeObserver)||t.disconnect(),this.cleanupListener&&this.cleanupListener(),u(this.state)}emit(e,t){this.dispatchEvent(new CustomEvent(e,{bubbles:!0,composed:!0,detail:t??{}}))}renderShell(){this.loaderEl=document.createElement("div"),this.loaderEl.className="rai-loader",this.loaderEl.appendChild(this.createDefaultLoader()),this.shadow.appendChild(this.loaderEl),this.errorEl=document.createElement("div"),this.errorEl.className="rai-error",this.msgEl=document.createElement("span"),this.msgEl.className="rai-error-msg",this.msgEl.textContent="Authentication failed. Please try again later.",this.errorEl.appendChild(this.msgEl);const e=this.getAttribute("retry-label")||this.getAttribute("data-retry-label")||"Retry",t=document.createElement("button");t.className="rai-retry-btn",t.textContent=e,t.addEventListener("click",()=>this.reload()),this.errorEl.appendChild(t),this.shadow.appendChild(this.errorEl)}createDefaultLoader(){const e=document.createElement("div");e.className="rai-sdk-loader";for(let r=0;r<5;r++){const t=document.createElement("div");t.className="rai-sdk-loader__bar",e.appendChild(t)}const t=document.createElement("div");return t.className="rai-sdk-loader__ball",e.appendChild(t),e}hideLoader(){this.loaderEl&&(this.loaderEl.classList.add("fade-out"),setTimeout(()=>{var e;return null==(e=this.loaderEl)?void 0:e.remove()},300),this.loaderEl=null)}showError(){var e,t;this.hideLoader(),this.errorEl&&((null==(e=this.state.errorSettings)?void 0:e.errorMessage)&&this.msgEl&&(this.msgEl.textContent=this.state.errorSettings.errorMessage),this.errorEl.classList.add("visible")),this.emit("rai-error",{message:(null==(t=this.msgEl)?void 0:t.textContent)??"Authentication failed"})}async init(){if(!this.config.communityId)return void this.showError();if(await h(this.config,this.state),this.config.embedToken){if(!(await async function(e){try{const t=e.v2ApiUrl||e.apiUrl;return(await fetch(`${t}/v2/api/widget-access-keys/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({embedToken:e.embedToken})})).ok}catch{return!1}}(this.config)))return void this.showError()}const e=()=>{this.config.bundleUrl?this.mountWidget():this.createIframe()};if(this.config.authUrl){return void(await c(this.config,this.state,()=>this.scheduleRefresh())?(this.emit("rai-authenticated"),e()):this.showError())}if(function(e,t){try{const r=localStorage.getItem(i(e));if(!r)return!1;const a=JSON.parse(r);return a.refreshToken&&!n(a.refreshTokenExpiry)?(t.refreshToken=a.refreshToken,t.tokenFamily=a.tokenFamily,t.refreshTokenExpiry=a.refreshTokenExpiry,!0):(s(e),!1)}catch{return!1}}(this.config,this.state)){return await d(this.config,this.state,()=>this.scheduleRefresh())?(this.state.isAuthenticated=!0,this.emit("rai-authenticated"),void e()):void this.showError()}await l(this.config,this.state,()=>this.scheduleRefresh())?(this.emit("rai-authenticated"),e()):this.showError()}createIframe(){const e=document.createElement("iframe");e.src=this.buildWidgetUrl(this.config),e.allow="clipboard-write",e.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"),e.frameBorder="0",e.scrolling="no",e.style.width=this.config.width,e.style.height=this.config.height,e.style.border="none",e.style.display="block",e.onload=()=>{f(this.config,this.state,e),this.schedulePeriodicSync(e)},e.onerror=()=>{this.showError()},this.state.iframe=e,this.shadow.appendChild(e),this.cleanupListener=m(this.config,this.state,this.shadow,e,()=>this.scheduleRefresh(),()=>this.logoutAndClear(),()=>this.hideLoader(),(e,t)=>this.emit(e,t))}async mountWidget(){try{const t=window,r=["api_url","base_url","auth_api","socket_path_v2","socket_path","channel_api"];for(const e of r)t[e]||(t[e]=this.config.apiUrl);await(e=this.config.bundleUrl,new Promise((t,r)=>{const i=document.createElement("script");i.src=e,i.onload=()=>t(),i.onerror=()=>r(new Error(`Failed to load ${e}`)),document.head.appendChild(i)}));const i=p[this.config.widgetType],a=window[i];if(!(null==a?void 0:a.mount))throw new Error(`window.${i}.mount not found after loading bundle`);const s=document.createElement("div");if(s.style.cssText="position: relative; width: 100%; height: 100%;",this.appendChild(s),!this.shadow.querySelector("slot")){const e=document.createElement("slot");this.shadow.appendChild(e)}this.loaderEl&&(this.loaderEl.remove(),this.loaderEl=null),a.mount(s,{widgetType:this.config.widgetType,communityId:this.config.communityId,channelId:this.config.channelId,widgetId:this.config.communityId,apiUrl:this.config.apiUrl,token:this.state.accessToken,basePath:"/",isPreview:!1,isOpenWidget:!0,defaultColorSchema:"dark"===this.config.theme?"dark":"light"}),this.emit("rai-mounted")}catch(t){console.error("[rai-widget] Bundle mount failed:",t),this.showError()}var e}scheduleRefresh(){if(this.state.refreshTimer&&clearTimeout(this.state.refreshTimer),!this.state.accessTokenExpiry)return;const e=this.state.accessTokenExpiry-Date.now()-6e4,t=()=>{this.state.iframe&&f(this.config,this.state,this.state.iframe)},r=async()=>{if(this.config.authUrl){await c(this.config,this.state,()=>this.scheduleRefresh())&&t()}else await d(this.config,this.state,()=>this.scheduleRefresh(),t)};e>0?this.state.refreshTimer=setTimeout(r,e):r()}schedulePeriodicSync(e){this.state.syncTimer&&clearInterval(this.state.syncTimer),this.state.syncTimer=setInterval(()=>{this.state.accessToken&&f(this.config,this.state,e)},12e4)}async logoutAndClear(){await async function(e,t){if(t.accessToken)try{await fetch(`${e.apiUrl}/${e.widgetId}/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.accessToken}`},body:JSON.stringify({refreshToken:t.refreshToken})})}catch{}u(t),s(e)}(this.config,this.state),this.shadow.querySelectorAll("iframe").forEach(e=>e.remove()),this.emit("rai-logout")}async reload(){u(this.state),this.shadow.querySelectorAll("iframe").forEach(e=>e.remove()),await this.init()}async logoutPublic(){await this.logoutAndClear()}isAuthenticated(){return this.state.isAuthenticated&&null!==this.state.accessToken}getTokenInfo(){return{hasAccessToken:!!this.state.accessToken,hasRefreshToken:!!this.state.refreshToken,accessTokenExpiry:this.state.accessTokenExpiry?new Date(this.state.accessTokenExpiry):null,refreshTokenExpiry:this.state.refreshTokenExpiry?new Date(this.state.refreshTokenExpiry):null,isAccessTokenValid:!!this.state.accessToken&&!n(this.state.accessTokenExpiry),isRefreshTokenValid:!!this.state.refreshToken&&!n(this.state.refreshTokenExpiry)}}}class k extends w{buildWidgetUrl(e){const t=new URL(e.widgetUrl);return t.searchParams.set("color",e.theme),t.searchParams.set("containerId",e.container),t.searchParams.set("connectType","simple"),t.searchParams.set("mode","private"),e.locale&&t.searchParams.set("locale",e.locale),t.toString()}}class b extends w{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("channel-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class T extends w{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("milestone-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class v extends w{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("social-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class E extends w{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("currency-overview-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}console.log("[rai-widget] v1.1.1");const x=[["rai-store-widget",k],["rai-channel-widget",b],["rai-milestone-widget",T],["rai-social-widget",v],["rai-currency-widget",E],["rai-widget",class extends k{}]];for(const[R,C]of x)customElements.get(R)||customElements.define(R,C);const I={store:k,channel:b,milestone:T,social:v,"currency-view":E},U=x.map(([e])=>e).join(", ");function A(){var e,t;const r=((null==(e=document.currentScript)?void 0:e.hasAttribute("data-widget-id"))||(null==(t=document.currentScript)?void 0:t.hasAttribute("data-community-id"))?document.currentScript:null)||document.querySelector("script[data-widget-id], script[data-community-id]");if(!r)return;const i=r.getAttribute("data-community-id")||r.getAttribute("data-widget-id");if(!i)return;const a=r.getAttribute("data-container")||`returning-ai-widget-${i}`,s=document.getElementById(a);if(!s)return;"static"===getComputedStyle(s).position&&(s.style.position="relative");const n=r.getAttribute("data-widget-type")??"store",o=new(I[n]??k);Array.from(r.attributes).forEach(e=>{o.setAttribute(e.name,e.value)}),s.appendChild(o)}function S(){const e=(()=>{var e,t;const r=((null==(e=document.currentScript)?void 0:e.hasAttribute("data-widget-id"))||(null==(t=document.currentScript)?void 0:t.hasAttribute("data-community-id"))?document.currentScript:null)||document.querySelector("script[data-widget-id], script[data-community-id]");if(!r)return null;const i=r.getAttribute("data-container")||`returning-ai-widget-${r.getAttribute("data-community-id")||r.getAttribute("data-widget-id")}`;return document.getElementById(i)})(),t=null==e?void 0:e.querySelector(U);window.ReturningAIWidget={version:"1.1.1",reload:()=>(null==t?void 0:t.reload())??Promise.resolve(),logout:()=>(null==t?void 0:t.logoutPublic())??Promise.resolve(),isAuthenticated:()=>(null==t?void 0:t.isAuthenticated())??!1,getTokenInfo:()=>(null==t?void 0:t.getTokenInfo())??{}}}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",A):A(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",S):S(),e.ChannelWidget=b,e.CurrencyWidget=E,e.MilestoneWidget=T,e.SocialWidget=v,e.StoreWidget=k,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({});
1
+ var RaiWidget=function(e){"use strict";var t=Object.defineProperty,r=(e,r,i)=>((e,r,i)=>r in e?t(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i)(e,"symbol"!=typeof r?r+"":r,i);function i(e){return`${e.storagePrefix}-${e.widgetId}-auth`}function a(e){return`${e.storagePrefix}-${e.widgetId}-error-settings`}function s(e){try{localStorage.removeItem(i(e))}catch{}}function n(e){return!e||Date.now()>=e-6e4}function o(e,t,r,a){t.accessToken=r.accessToken,t.refreshToken=r.refreshToken,t.tokenFamily=r.tokenFamily??null;const s=Date.now();t.accessTokenExpiry=s+1e3*r.accessTokenTTL,t.refreshTokenExpiry=s+1e3*r.refreshTokenTTL,function(e,t){try{const r={refreshToken:t.refreshToken,tokenFamily:t.tokenFamily,refreshTokenExpiry:t.refreshTokenExpiry};localStorage.setItem(i(e),JSON.stringify(r))}catch{}}(e,t),e.autoRefresh&&a&&a()}async function l(e,t,r){const i=crypto.randomUUID(),a=Date.now(),s=e.maxRetries??3,n=e.retryDelay??500;for(let l=0;l<=s;l++){l>0&&await new Promise(e=>setTimeout(e,n*(1<<l-1)));let c=!1;try{const s=await fetch(`${e.apiUrl}/${e.widgetId}/auth/serverless`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({nonce:i,timestamp:a,widgetType:e.widgetType,userIdentifiers:e.userIdentifiers}),credentials:"include"});if(!s.ok){c=s.status>=400&&s.status<500;const e=await s.json().catch(()=>({error:"Authentication failed"}));throw new Error(e.error||`HTTP ${s.status}`)}const n=await s.json();if(!n.accessToken||!n.refreshToken)throw new Error("Invalid authentication response");return o(e,t,n,r),t.isAuthenticated=!0,!0}catch{if(c||l===s)return t.isAuthenticated=!1,!1}}return t.isAuthenticated=!1,!1}async function c(e,t,r){const i=e.maxRetries??3,a=e.retryDelay??500;for(let s=0;s<=i;s++){s>0&&await new Promise(e=>setTimeout(e,a*(1<<s-1)));let n=!1;try{const i=await fetch(e.authUrl,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"}});if(!i.ok)throw n=i.status>=400&&i.status<500,new Error(`HTTP ${i.status}`);const a=await i.json();if(!a.token)throw new Error("Invalid proxy auth response");const s=a.expiresIn??300;return t.accessToken=a.token,t.refreshToken=null,t.tokenFamily=null,t.accessTokenExpiry=Date.now()+1e3*s,t.refreshTokenExpiry=null,t.isAuthenticated=!0,e.autoRefresh&&r&&r(),!0}catch{if(n||s===i)return t.isAuthenticated=!1,!1}}return t.isAuthenticated=!1,!1}async function d(e,t,r,i){return t.isRefreshing?t.refreshPromise:!!t.refreshToken&&(t.isRefreshing=!0,t.refreshPromise=(async()=>{try{const a=await fetch(`${e.apiUrl}/${e.widgetId}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.refreshToken}`},body:JSON.stringify({widgetType:e.widgetType})});if(!a.ok){if(401===a.status||403===a.status)return u(t),s(e),l(e,t,r);const i=await a.json().catch(()=>({error:"Token refresh failed"}));throw new Error(i.error||`HTTP ${a.status}`)}const n=await a.json();if(!n.accessToken||!n.refreshToken)throw new Error("Invalid refresh response");return o(e,t,n,r),i&&i(),!0}catch{return u(t),s(e),l(e,t,r)}finally{t.isRefreshing=!1,t.refreshPromise=null}})(),t.refreshPromise)}async function h(e,t){const r=function(e){try{const t=localStorage.getItem(a(e));if(!t)return null;const r=JSON.parse(t);return r.cachedAt&&Date.now()-r.cachedAt<36e5?r:(localStorage.removeItem(a(e)),null)}catch{return null}}(e);if(r)return r.configured&&(t.errorSettings={errorMessage:r.errorMessage,modalColor:r.modalColor,backgroundImage:r.backgroundImage}),t.errorSettings;try{const r=await fetch(`${e.apiUrl}/${e.widgetId}/auth/error-settings?widgetType=${e.widgetType}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!r.ok)return null;const i=await r.json();return function(e,t){try{localStorage.setItem(a(e),JSON.stringify({...t,cachedAt:Date.now()}))}catch{}}(e,i),i.configured&&(t.errorSettings={errorMessage:i.errorMessage,modalColor:i.modalColor,backgroundImage:i.backgroundImage}),t.errorSettings}catch{return null}}function u(e){e.accessToken=null,e.refreshToken=null,e.tokenFamily=null,e.accessTokenExpiry=null,e.refreshTokenExpiry=null,e.isAuthenticated=!1,e.isRefreshing=!1,e.refreshPromise=null,e.refreshTimer&&(clearTimeout(e.refreshTimer),e.refreshTimer=null),e.syncTimer&&(clearInterval(e.syncTimer),e.syncTimer=null)}function f(e,t,r){var i;if(t.accessToken)try{null==(i=r.contentWindow)||i.postMessage({type:"RETURNINGAI_WIDGET_TOKEN",value:{widgetId:e.widgetId,token:t.accessToken,...void 0!==e.customData&&{customData:e.customData}}},e.widgetDomain)}catch{}}function m(e,t,r,i,a,s,o,h){const u=function(e,t){let r=null;return{call(i){r&&clearTimeout(r),r=setTimeout(()=>{e(i),r=null},t)},cancel(){r&&(clearTimeout(r),r=null)}}}(e=>{i.style.height=`${e}px`,null==h||h("rai-height-change",{height:e})},e.heightDebounce??100),f=async r=>{var f;if(r.origin!==e.widgetDomain)return;if(!r.data||"string"!=typeof r.data.type)return;const{type:m,containerId:g,widgetId:p,payload:w}=r.data;switch(m){case"RETURNINGAI_WIDGET_REQUEST_TOKEN":try{const r=await async function(e,t,r){if(t.accessToken&&!n(t.accessTokenExpiry))return t.accessToken;if(e.authUrl){if(await c(e,t,r)&&t.accessToken)return t.accessToken;throw new Error("Unable to obtain valid token")}if(await d(e,t,r)&&t.accessToken)return t.accessToken;if(await l(e,t,r)&&t.accessToken)return t.accessToken;throw new Error("Unable to obtain valid token")}(e,t,a);null==(f=i.contentWindow)||f.postMessage({type:"RETURNINGAI_WIDGET_TOKEN",value:{token:r,widgetId:e.widgetId,...void 0!==e.customData&&{customData:e.customData}}},e.widgetDomain)}catch{}break;case"WIDGET_HEIGHT_UPDATE":{const e=Number(null==w?void 0:w.height);Number.isFinite(e)&&e>0&&u.call(e);break}case"WIDGET_READY":if(void 0!==p&&p!==e.widgetId)break;if(void 0!==g&&g!==e.container)break;i.classList.add("loaded"),o&&o(),null==h||h("rai-ready");break;case"WIDGET_ERROR":o&&o();break;case"WIDGET_LOGOUT":s&&await s()}};return window.addEventListener("message",f),()=>{window.removeEventListener("message",f),u.cancel()}}const g=new Set(["community-id","channel-id","widget-id","widget-type","theme","container","width","height","api-url","widget-url","auto-refresh","debug","storage-prefix","max-retries","retry-delay","height-debounce","locale","custom-data","retry-label","auth-url","bundle-url","embed-token","v2-api-url"]),p={store:"RaiStoreWidget",channel:"RaiChannelWidget",social:"RaiSocialWidget",milestone:"RaiMilestoneWidget","currency-view":"RaiCurrencyWidget","referral-conditions":"RaiReferralWidget"},w={"RAI-STORE-WIDGET":"store","RAI-CHANNEL-WIDGET":"channel","RAI-MILESTONE-WIDGET":"milestone","RAI-SOCIAL-WIDGET":"social","RAI-CURRENCY-WIDGET":"currency-view","RAI-REFERRAL-WIDGET":"referral-conditions","RAI-WIDGET":"store"};class y extends HTMLElement{constructor(){super(),r(this,"shadow"),r(this,"config"),r(this,"state",{accessToken:null,refreshToken:null,tokenFamily:null,accessTokenExpiry:null,refreshTokenExpiry:null,refreshTimer:null,syncTimer:null,iframe:null,isAuthenticated:!1,isRefreshing:!1,refreshPromise:null,errorSettings:null}),r(this,"loaderEl",null),r(this,"errorEl",null),r(this,"msgEl",null),r(this,"cleanupListener"),r(this,"intersectionObserver"),r(this,"themeObserver"),this.shadow=this.attachShadow({mode:"closed"})}connectedCallback(){this.config=function(e,t){const r=t=>e.getAttribute(t)??e.getAttribute(`data-${t}`)??"",i=(e,t)=>{const i=parseInt(r(e),10);return Number.isFinite(i)&&i>=0?i:t},a=!!r("community-id"),s=r("community-id")||r("widget-id")||t||"";if(s&&!/^[a-zA-Z0-9_\-=]{8,}$/.test(s))throw new Error(`[rai-widget] Invalid community-id: "${s}"`);const n=r("channel-id")||void 0;if(n&&!/^[a-zA-Z0-9_\-=]{8,}$/.test(n))throw new Error(`[rai-widget] Invalid channel-id: "${n}"`);const o=r("widget-type")||w[e.tagName]||"store";let l;l=a?"store"===o?s:"channel"===o?n?btoa(n):s:s?btoa(s):s:s;let c,d=r("widget-url")||"https://widget.returningai.com";d.endsWith("store-widget")&&(d=`${d}/${s}/open-widget`);try{c=new URL(d).origin}catch{c=d}if(d.includes("store-widget")){const e=new URL(d);e.searchParams.set("color",r("theme")||"light"),d=e.toString()}const h=r("container")||r("data-container")||`returning-ai-widget-${s}`,u={};Array.from(e.attributes).forEach(e=>{const t=e.name.toLowerCase();if(!t.startsWith("data-"))return;const r=t.slice(5);g.has(r)||(u[t]=e.value)});const f=(()=>{const e=r("custom-data");if(e)try{return JSON.parse(e)}catch{return}})();return{communityId:s,channelId:n,widgetId:l,widgetType:o,theme:r("theme")||"light",container:h,width:r("width")||"100%",height:r("height")||"600px",apiUrl:r("api-url")||"https://sgtr-eks-widgets.genesiv.org",widgetUrl:d,widgetDomain:c,autoRefresh:"false"!==r("auto-refresh"),debug:"true"===r("debug"),storagePrefix:r("storage-prefix")||"returning-ai-widget",userIdentifiers:u,maxRetries:i("max-retries",3),retryDelay:i("retry-delay",500),heightDebounce:i("height-debounce",100),locale:r("locale")||void 0,customData:f,authUrl:r("auth-url")||void 0,bundleUrl:r("bundle-url")||void 0,embedToken:r("embed-token")||void 0,v2ApiUrl:r("v2-api-url")||void 0}}(this,void 0);const e=document.createElement("style");e.textContent=":host{display:block;position:relative;width:100%;height:100%}.rai-loader{position:absolute;top:0;left:0;display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:var(--rai-loader-bg, #ffffff);border-radius:8px;z-index:10;transition:opacity .3s ease-out}.rai-loader.fade-out{opacity:0;pointer-events:none}.rai-error{display:none;position:absolute;top:0;left:0;width:100%;height:100%;align-items:center;justify-content:center;flex-direction:column;gap:12px;background:var(--rai-error-bg, #1a1a1a);border-radius:8px;padding:24px;box-sizing:border-box;text-align:center;color:var(--rai-error-text, #9ca3af);font-family:system-ui,-apple-system,sans-serif;z-index:10}.rai-error.visible{display:flex}iframe{display:block;border:none;opacity:0;transition:opacity .3s ease-in}iframe.loaded{opacity:1}.rai-sdk-loader{position:relative;width:75px;height:100px}.rai-sdk-loader__bar{position:absolute;bottom:0;width:10px;height:50%;background:var(--rai-accent, #000000);transform-origin:center bottom;box-shadow:1px 1px #0003}.rai-sdk-loader__bar:nth-child(1){left:0;transform:scaleY(.2);animation:rai-sdk-barUp1 4s infinite}.rai-sdk-loader__bar:nth-child(2){left:15px;transform:scaleY(.4);animation:rai-sdk-barUp2 4s infinite}.rai-sdk-loader__bar:nth-child(3){left:30px;transform:scaleY(.6);animation:rai-sdk-barUp3 4s infinite}.rai-sdk-loader__bar:nth-child(4){left:45px;transform:scaleY(.8);animation:rai-sdk-barUp4 4s infinite}.rai-sdk-loader__bar:nth-child(5){left:60px;transform:scale(1);animation:rai-sdk-barUp5 4s infinite}.rai-sdk-loader__ball{position:absolute;bottom:10px;left:0;width:10px;height:10px;background:var(--rai-accent, #000000);border-radius:50%;animation:rai-sdk-ball 4s infinite}@keyframes rai-sdk-ball{0%{transform:translate(0)}5%{transform:translate(8px,-14px)}10%{transform:translate(15px,-10px)}17%{transform:translate(23px,-24px)}20%{transform:translate(30px,-20px)}27%{transform:translate(38px,-34px)}30%{transform:translate(45px,-30px)}37%{transform:translate(53px,-44px)}40%{transform:translate(60px,-40px)}50%{transform:translate(60px)}57%{transform:translate(53px,-14px)}60%{transform:translate(45px,-10px)}67%{transform:translate(37px,-24px)}70%{transform:translate(30px,-20px)}77%{transform:translate(22px,-34px)}80%{transform:translate(15px,-30px)}87%{transform:translate(7px,-44px)}90%{transform:translateY(-40px)}to{transform:translate(0)}}@keyframes rai-sdk-barUp1{0%{transform:scaleY(.2)}40%{transform:scaleY(.2)}50%{transform:scale(1)}90%{transform:scale(1)}to{transform:scaleY(.2)}}@keyframes rai-sdk-barUp2{0%{transform:scaleY(.4)}40%{transform:scaleY(.4)}50%{transform:scaleY(.8)}90%{transform:scaleY(.8)}to{transform:scaleY(.4)}}@keyframes rai-sdk-barUp3{0%{transform:scaleY(.6)}to{transform:scaleY(.6)}}@keyframes rai-sdk-barUp4{0%{transform:scaleY(.8)}40%{transform:scaleY(.8)}50%{transform:scaleY(.4)}90%{transform:scaleY(.4)}to{transform:scaleY(.8)}}@keyframes rai-sdk-barUp5{0%{transform:scale(1)}40%{transform:scale(1)}50%{transform:scaleY(.2)}90%{transform:scaleY(.2)}to{transform:scale(1)}}#loading-square{width:75px;aspect-ratio:1;display:flex;color:var(--rai-accent, #000000);background:linear-gradient(currentColor 0 0) right / 51% 100%,linear-gradient(currentColor 0 0) bottom / 100% 51%;background-repeat:no-repeat;animation:l16-0 2s infinite linear .25s}#loading-square>div{width:50%;height:50%;background:currentColor;animation:l16-1 .5s infinite linear}@keyframes l16-0{0%,12.49%{transform:rotate(0)}12.5%,37.49%{transform:rotate(90deg)}37.5%,62.49%{transform:rotate(180deg)}62.5%,87.49%{transform:rotate(270deg)}87.5%,to{transform:rotate(360deg)}}@keyframes l16-1{0%{transform:perspective(80px) rotate3d(-1,-1,0,0)}80%,to{transform:perspective(80px) rotate3d(-1,-1,0,-180deg)}}#loading-circle{width:75px;aspect-ratio:1;display:grid;grid:50%/50%;color:var(--rai-accent, #000000);border-radius:50%;--_g: no-repeat linear-gradient(currentColor 0 0);background:var(--_g),var(--_g),var(--_g);background-size:50.1% 50.1%;animation:l9-0 1.5s infinite steps(1) alternate,l9-0-0 3s infinite steps(1) alternate}#loading-circle>div{background:var(--rai-text4, #6b7280);border-top-left-radius:100px;transform:perspective(150px) rotateY(0) rotateX(0);transform-origin:bottom right;animation:l9-1 1.5s infinite linear alternate}@keyframes l9-0{0%{background-position:0 100%,100% 100%,100% 0}33%{background-position:100% 100%,100% 100%,100% 0}66%{background-position:100% 0,100% 0,100% 0}}@keyframes l9-0-0{0%{transform:scaleX(1) rotate(0)}50%{transform:scaleX(-1) rotate(-90deg)}}@keyframes l9-1{16.5%{transform:perspective(150px) rotateX(-90deg) rotateY(0) rotateX(0);filter:grayscale(.8)}33%{transform:perspective(150px) rotateX(-180deg) rotateY(0) rotateX(0)}66%{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(0)}to{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(-180deg);filter:grayscale(.8)}}.rai-retry-btn{padding:8px 20px;border:none;border-radius:6px;background:var(--rai-accent, #000000);color:var(--rai-error-bg, #ffffff);font-size:14px;font-family:system-ui,-apple-system,sans-serif;cursor:pointer}.rai-retry-btn:hover{opacity:.85}",this.shadow.appendChild(e);const t=this.config.theme,r="dark"===t?"#ffffff":"#000000",i="dark"===t?"#9ca3af":"#6b7280",a="dark"===t?"#1a1a1a":"#ffffff";this.style.width=this.config.width,this.style.height=this.config.height,this.style.setProperty("--rai-accent",r),this.style.setProperty("--rai-text4",i),this.style.setProperty("--rai-loader-bg",a),this.style.setProperty("--rai-error-bg",a),this.renderShell(),this.hasAttribute("eager")?this.init():(this.intersectionObserver=new IntersectionObserver(e=>{e[0].isIntersecting&&(this.intersectionObserver.disconnect(),this.intersectionObserver=void 0,this.init())}),this.intersectionObserver.observe(this))}disconnectedCallback(){var e,t;null==(e=this.intersectionObserver)||e.disconnect(),null==(t=this.themeObserver)||t.disconnect(),this.cleanupListener&&this.cleanupListener(),u(this.state)}emit(e,t){this.dispatchEvent(new CustomEvent(e,{bubbles:!0,composed:!0,detail:t??{}}))}renderShell(){this.loaderEl=document.createElement("div"),this.loaderEl.className="rai-loader",this.loaderEl.appendChild(this.createDefaultLoader()),this.shadow.appendChild(this.loaderEl),this.errorEl=document.createElement("div"),this.errorEl.className="rai-error",this.msgEl=document.createElement("span"),this.msgEl.className="rai-error-msg",this.msgEl.textContent="Authentication failed. Please try again later.",this.errorEl.appendChild(this.msgEl);const e=this.getAttribute("retry-label")||this.getAttribute("data-retry-label")||"Retry",t=document.createElement("button");t.className="rai-retry-btn",t.textContent=e,t.addEventListener("click",()=>this.reload()),this.errorEl.appendChild(t),this.shadow.appendChild(this.errorEl)}createDefaultLoader(){const e=document.createElement("div");e.className="rai-sdk-loader";for(let r=0;r<5;r++){const t=document.createElement("div");t.className="rai-sdk-loader__bar",e.appendChild(t)}const t=document.createElement("div");return t.className="rai-sdk-loader__ball",e.appendChild(t),e}hideLoader(){this.loaderEl&&(this.loaderEl.classList.add("fade-out"),setTimeout(()=>{var e;return null==(e=this.loaderEl)?void 0:e.remove()},300),this.loaderEl=null)}showError(){var e,t;this.hideLoader(),this.errorEl&&((null==(e=this.state.errorSettings)?void 0:e.errorMessage)&&this.msgEl&&(this.msgEl.textContent=this.state.errorSettings.errorMessage),this.errorEl.classList.add("visible")),this.emit("rai-error",{message:(null==(t=this.msgEl)?void 0:t.textContent)??"Authentication failed"})}async init(){if(!this.config.communityId)return void this.showError();if(await h(this.config,this.state),this.config.embedToken){if(!(await async function(e){try{const t=e.v2ApiUrl||e.apiUrl;return(await fetch(`${t}/v2/api/widget-access-keys/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({embedToken:e.embedToken})})).ok}catch{return!1}}(this.config)))return void this.showError()}const e=()=>{this.config.bundleUrl?this.mountWidget():this.createIframe()};if(this.config.authUrl){return void(await c(this.config,this.state,()=>this.scheduleRefresh())?(this.emit("rai-authenticated"),e()):this.showError())}if(function(e,t){try{const r=localStorage.getItem(i(e));if(!r)return!1;const a=JSON.parse(r);return a.refreshToken&&!n(a.refreshTokenExpiry)?(t.refreshToken=a.refreshToken,t.tokenFamily=a.tokenFamily,t.refreshTokenExpiry=a.refreshTokenExpiry,!0):(s(e),!1)}catch{return!1}}(this.config,this.state)){return await d(this.config,this.state,()=>this.scheduleRefresh())?(this.state.isAuthenticated=!0,this.emit("rai-authenticated"),void e()):void this.showError()}await l(this.config,this.state,()=>this.scheduleRefresh())?(this.emit("rai-authenticated"),e()):this.showError()}createIframe(){const e=document.createElement("iframe");e.src=this.buildWidgetUrl(this.config),e.allow="clipboard-write",e.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"),e.frameBorder="0",e.scrolling="no",e.style.width=this.config.width,e.style.height=this.config.height,e.style.border="none",e.style.display="block",e.onload=()=>{f(this.config,this.state,e),this.schedulePeriodicSync(e)},e.onerror=()=>{this.showError()},this.state.iframe=e,this.shadow.appendChild(e),this.cleanupListener=m(this.config,this.state,this.shadow,e,()=>this.scheduleRefresh(),()=>this.logoutAndClear(),()=>this.hideLoader(),(e,t)=>this.emit(e,t))}async mountWidget(){try{const t=window,r=["api_url","base_url","auth_api","socket_path_v2","socket_path","channel_api"];for(const e of r)t[e]||(t[e]=this.config.apiUrl);window.__IS_WIDGET__=!0,window.guest_token=this.state.accessToken,await(e=this.config.bundleUrl,new Promise((t,r)=>{const i=document.createElement("script");i.src=e,i.onload=()=>t(),i.onerror=()=>r(new Error(`Failed to load ${e}`)),document.head.appendChild(i)}));const i=p[this.config.widgetType],a=window[i];if(!(null==a?void 0:a.mount))throw new Error(`window.${i}.mount not found after loading bundle`);const s=document.createElement("div");if(s.style.cssText="position: relative; width: 100%; height: 100%;",this.appendChild(s),!this.shadow.querySelector("slot")){const e=document.createElement("slot");this.shadow.appendChild(e)}this.loaderEl&&(this.loaderEl.remove(),this.loaderEl=null),a.mount(s,{widgetType:this.config.widgetType,communityId:this.config.communityId,channelId:this.config.channelId,widgetId:this.config.communityId,apiUrl:this.config.apiUrl,token:this.state.accessToken,basePath:"/",isPreview:!1,isOpenWidget:!0,defaultColorSchema:"dark"===this.config.theme?"dark":"light"}),this.emit("rai-mounted")}catch(t){console.error("[rai-widget] Bundle mount failed:",t),this.showError()}var e}scheduleRefresh(){if(this.state.refreshTimer&&clearTimeout(this.state.refreshTimer),!this.state.accessTokenExpiry)return;const e=this.state.accessTokenExpiry-Date.now()-6e4,t=()=>{this.state.iframe&&f(this.config,this.state,this.state.iframe),this.config.bundleUrl&&this.state.accessToken&&(window.guest_token=this.state.accessToken)},r=async()=>{if(this.config.authUrl){await c(this.config,this.state,()=>this.scheduleRefresh())&&t()}else await d(this.config,this.state,()=>this.scheduleRefresh(),t)};e>0?this.state.refreshTimer=setTimeout(r,e):r()}schedulePeriodicSync(e){this.state.syncTimer&&clearInterval(this.state.syncTimer),this.state.syncTimer=setInterval(()=>{this.state.accessToken&&f(this.config,this.state,e)},12e4)}async logoutAndClear(){await async function(e,t){if(t.accessToken)try{await fetch(`${e.apiUrl}/${e.widgetId}/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.accessToken}`},body:JSON.stringify({refreshToken:t.refreshToken})})}catch{}u(t),s(e)}(this.config,this.state),this.shadow.querySelectorAll("iframe").forEach(e=>e.remove()),this.emit("rai-logout")}async reload(){u(this.state),this.shadow.querySelectorAll("iframe").forEach(e=>e.remove()),await this.init()}async logoutPublic(){await this.logoutAndClear()}isAuthenticated(){return this.state.isAuthenticated&&null!==this.state.accessToken}getTokenInfo(){return{hasAccessToken:!!this.state.accessToken,hasRefreshToken:!!this.state.refreshToken,accessTokenExpiry:this.state.accessTokenExpiry?new Date(this.state.accessTokenExpiry):null,refreshTokenExpiry:this.state.refreshTokenExpiry?new Date(this.state.refreshTokenExpiry):null,isAccessTokenValid:!!this.state.accessToken&&!n(this.state.accessTokenExpiry),isRefreshTokenValid:!!this.state.refreshToken&&!n(this.state.refreshTokenExpiry)}}}class k extends y{buildWidgetUrl(e){const t=new URL(e.widgetUrl);return t.searchParams.set("color",e.theme),t.searchParams.set("containerId",e.container),t.searchParams.set("connectType","simple"),t.searchParams.set("mode","private"),e.locale&&t.searchParams.set("locale",e.locale),t.toString()}}class b extends y{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("channel-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class T extends y{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("milestone-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class v extends y{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("social-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class E extends y{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("currency-overview-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}class x extends y{buildWidgetUrl(e){const t=e.widgetUrl.endsWith("referral-conditions-widget")?`${e.widgetUrl}/${e.widgetId}`:e.widgetUrl;if(!e.locale)return t;try{const r=new URL(t);return r.searchParams.set("locale",e.locale),r.toString()}catch{return`${t}?locale=${encodeURIComponent(e.locale)}`}}}console.log("[rai-widget] v1.1.2");const I=[["rai-store-widget",k],["rai-channel-widget",b],["rai-milestone-widget",T],["rai-social-widget",v],["rai-currency-widget",E],["rai-referral-widget",x],["rai-widget",class extends k{}]];for(const[C,$]of I)customElements.get(C)||customElements.define(C,$);const U={store:k,channel:b,milestone:T,social:v,"currency-view":E,"referral-conditions":x},A=I.map(([e])=>e).join(", ");function R(){var e,t;const r=((null==(e=document.currentScript)?void 0:e.hasAttribute("data-widget-id"))||(null==(t=document.currentScript)?void 0:t.hasAttribute("data-community-id"))?document.currentScript:null)||document.querySelector("script[data-widget-id], script[data-community-id]");if(!r)return;const i=r.getAttribute("data-community-id")||r.getAttribute("data-widget-id");if(!i)return;const a=r.getAttribute("data-container")||`returning-ai-widget-${i}`,s=document.getElementById(a);if(!s)return;"static"===getComputedStyle(s).position&&(s.style.position="relative");const n=r.getAttribute("data-widget-type")??"store",o=new(U[n]??k);Array.from(r.attributes).forEach(e=>{o.setAttribute(e.name,e.value)}),s.appendChild(o)}function S(){const e=(()=>{var e,t;const r=((null==(e=document.currentScript)?void 0:e.hasAttribute("data-widget-id"))||(null==(t=document.currentScript)?void 0:t.hasAttribute("data-community-id"))?document.currentScript:null)||document.querySelector("script[data-widget-id], script[data-community-id]");if(!r)return null;const i=r.getAttribute("data-container")||`returning-ai-widget-${r.getAttribute("data-community-id")||r.getAttribute("data-widget-id")}`;return document.getElementById(i)})(),t=null==e?void 0:e.querySelector(A);window.ReturningAIWidget={version:"1.1.2",reload:()=>(null==t?void 0:t.reload())??Promise.resolve(),logout:()=>(null==t?void 0:t.logoutPublic())??Promise.resolve(),isAuthenticated:()=>(null==t?void 0:t.isAuthenticated())??!1,getTokenInfo:()=>(null==t?void 0:t.getTokenInfo())??{}}}return"loading"===document.readyState?document.addEventListener("DOMContentLoaded",R):R(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",S):S(),e.ChannelWidget=b,e.CurrencyWidget=E,e.MilestoneWidget=T,e.ReferralWidget=x,e.SocialWidget=v,e.StoreWidget=k,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({});
@@ -438,7 +438,8 @@ const WIDGET_GLOBALS = {
438
438
  channel: "RaiChannelWidget",
439
439
  social: "RaiSocialWidget",
440
440
  milestone: "RaiMilestoneWidget",
441
- "currency-view": "RaiCurrencyWidget"
441
+ "currency-view": "RaiCurrencyWidget",
442
+ "referral-conditions": "RaiReferralWidget"
442
443
  };
443
444
  const TAG_TO_TYPE = {
444
445
  "RAI-STORE-WIDGET": "store",
@@ -446,6 +447,7 @@ const TAG_TO_TYPE = {
446
447
  "RAI-MILESTONE-WIDGET": "milestone",
447
448
  "RAI-SOCIAL-WIDGET": "social",
448
449
  "RAI-CURRENCY-WIDGET": "currency-view",
450
+ "RAI-REFERRAL-WIDGET": "referral-conditions",
449
451
  "RAI-WIDGET": "store"
450
452
  // deprecated alias
451
453
  };
@@ -799,6 +801,9 @@ class BaseWidget extends HTMLElement {
799
801
  for (const v of endpointVars) {
800
802
  if (!w[v]) w[v] = this.config.apiUrl;
801
803
  }
804
+ ;
805
+ window.__IS_WIDGET__ = true;
806
+ window.guest_token = this.state.accessToken;
802
807
  await loadScript(this.config.bundleUrl);
803
808
  const globalName = WIDGET_GLOBALS[this.config.widgetType];
804
809
  const widgetGlobal = window[globalName];
@@ -843,6 +848,9 @@ class BaseWidget extends HTMLElement {
843
848
  const delay = this.state.accessTokenExpiry - Date.now() - 6e4;
844
849
  const pushToken = () => {
845
850
  if (this.state.iframe) sendTokenToWidget(this.config, this.state, this.state.iframe);
851
+ if (this.config.bundleUrl && this.state.accessToken) {
852
+ window.guest_token = this.state.accessToken;
853
+ }
846
854
  };
847
855
  const doRefresh = async () => {
848
856
  if (this.config.authUrl) {
@@ -956,7 +964,20 @@ class CurrencyWidget extends BaseWidget {
956
964
  }
957
965
  }
958
966
  }
959
- console.log(`[rai-widget] v${"1.1.1"}`);
967
+ class ReferralWidget extends BaseWidget {
968
+ buildWidgetUrl(config) {
969
+ const base = config.widgetUrl.endsWith("referral-conditions-widget") ? `${config.widgetUrl}/${config.widgetId}` : config.widgetUrl;
970
+ if (!config.locale) return base;
971
+ try {
972
+ const u = new URL(base);
973
+ u.searchParams.set("locale", config.locale);
974
+ return u.toString();
975
+ } catch {
976
+ return `${base}?locale=${encodeURIComponent(config.locale)}`;
977
+ }
978
+ }
979
+ }
980
+ console.log(`[rai-widget] v${"1.1.2"}`);
960
981
  class StoreWidgetCompat extends StoreWidget {
961
982
  }
962
983
  const WIDGET_REGISTRY = [
@@ -965,6 +986,7 @@ const WIDGET_REGISTRY = [
965
986
  ["rai-milestone-widget", MilestoneWidget],
966
987
  ["rai-social-widget", SocialWidget],
967
988
  ["rai-currency-widget", CurrencyWidget],
989
+ ["rai-referral-widget", ReferralWidget],
968
990
  ["rai-widget", StoreWidgetCompat]
969
991
  // deprecated alias — use <rai-store-widget> instead
970
992
  ];
@@ -978,7 +1000,8 @@ const WIDGET_CLASS_MAP = {
978
1000
  channel: ChannelWidget,
979
1001
  milestone: MilestoneWidget,
980
1002
  social: SocialWidget,
981
- "currency-view": CurrencyWidget
1003
+ "currency-view": CurrencyWidget,
1004
+ "referral-conditions": ReferralWidget
982
1005
  };
983
1006
  const ALL_WIDGET_SELECTOR = WIDGET_REGISTRY.map(([tag]) => tag).join(", ");
984
1007
  function bootstrapFromScriptTag() {
@@ -1016,7 +1039,7 @@ function exposePublicApi() {
1016
1039
  })();
1017
1040
  const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
1018
1041
  window.ReturningAIWidget = {
1019
- version: "1.1.1",
1042
+ version: "1.1.2",
1020
1043
  reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
1021
1044
  logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
1022
1045
  isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
@@ -1032,6 +1055,7 @@ export {
1032
1055
  ChannelWidget,
1033
1056
  CurrencyWidget,
1034
1057
  MilestoneWidget,
1058
+ ReferralWidget,
1035
1059
  SocialWidget,
1036
1060
  StoreWidget
1037
1061
  };
@@ -0,0 +1,5 @@
1
+ import type { WidgetConfig } from './types';
2
+ import { BaseWidget } from './BaseWidget';
3
+ export declare class ReferralWidget extends BaseWidget {
4
+ protected buildWidgetUrl(config: WidgetConfig): string;
5
+ }
@@ -3,6 +3,7 @@ import { ChannelWidget } from './ChannelWidget';
3
3
  import { MilestoneWidget } from './MilestoneWidget';
4
4
  import { SocialWidget } from './SocialWidget';
5
5
  import { CurrencyWidget } from './CurrencyWidget';
6
+ import { ReferralWidget } from './ReferralWidget';
6
7
  declare global {
7
8
  interface Window {
8
9
  ReturningAIWidget: {
@@ -14,4 +15,4 @@ declare global {
14
15
  };
15
16
  }
16
17
  }
17
- export { StoreWidget, ChannelWidget, MilestoneWidget, SocialWidget, CurrencyWidget };
18
+ export { StoreWidget, ChannelWidget, MilestoneWidget, SocialWidget, CurrencyWidget, ReferralWidget };
@@ -9,7 +9,7 @@ export interface WidgetConfig {
9
9
  * Set to the same value as communityId by readConfig().
10
10
  */
11
11
  widgetId: string;
12
- widgetType: 'store' | 'channel' | 'milestone' | 'social' | 'currency-view';
12
+ widgetType: 'store' | 'channel' | 'milestone' | 'social' | 'currency-view' | 'referral-conditions';
13
13
  theme: 'light' | 'dark';
14
14
  container: string;
15
15
  width: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@returningai/widget-sdk",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Shadow DOM isolated widget SDK for ReturningAI",
5
5
  "main": "dist/rai-widget.iife.js",
6
6
  "module": "dist/rai-widget.js",