@returningai/widget-sdk 1.1.0 → 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 +4 -1
- package/dist/rai-widget.iife.js +1 -1
- package/dist/rai-widget.js +35 -7
- package/dist/types/ReferralWidget.d.ts +5 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/types.d.ts +2 -1
- package/package.json +1 -1
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_...
|
|
@@ -381,6 +383,7 @@ All attributes can be provided with or without the `data-` prefix.
|
|
|
381
383
|
| `widget-url` | No | — | URL served inside the iframe — from Community Settings (iframe mode only) |
|
|
382
384
|
| `bundle-url` | No | — | URL to the widget IIFE bundle — triggers bundle mode (non-iframe) |
|
|
383
385
|
| `embed-token` | Access Key only | — | Short-lived JWT from your server. Required for Access Key Embed; absent for Public and Authenticated Embed |
|
|
386
|
+
| `v2-api-url` | No | — | Base URL for the V2 API (embed token validation). Only needed when V2 API lives on a different host than `api-url` |
|
|
384
387
|
| `auth-url` | Auth Embed only | — | Your backend auth endpoint — enables Authenticated Embed mode |
|
|
385
388
|
| `auto-refresh` | No | `true` | Automatically refresh access token before expiry |
|
|
386
389
|
| `debug` | No | `false` | Enable verbose console logging |
|
|
@@ -421,7 +424,7 @@ After the SDK loads, `window.ReturningAIWidget` is available:
|
|
|
421
424
|
|
|
422
425
|
```javascript
|
|
423
426
|
// Check the loaded version
|
|
424
|
-
window.ReturningAIWidget.version // e.g. "1.
|
|
427
|
+
window.ReturningAIWidget.version // e.g. "1.1.2"
|
|
425
428
|
|
|
426
429
|
// Reload the widget (re-runs auth flow)
|
|
427
430
|
await window.ReturningAIWidget.reload()
|
package/dist/rai-widget.iife.js
CHANGED
|
@@ -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"]),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}}(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{return(await fetch(`${e.apiUrl}/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.0");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 S(){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 A(){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.0",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",S):S(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",A):A(),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}({});
|
package/dist/rai-widget.js
CHANGED
|
@@ -248,7 +248,8 @@ async function logout(config, state) {
|
|
|
248
248
|
}
|
|
249
249
|
async function validateEmbedToken(config) {
|
|
250
250
|
try {
|
|
251
|
-
const
|
|
251
|
+
const baseUrl = config.v2ApiUrl || config.apiUrl;
|
|
252
|
+
const res = await fetch(`${baseUrl}/v2/api/widget-access-keys/validate`, {
|
|
252
253
|
method: "POST",
|
|
253
254
|
headers: { "Content-Type": "application/json" },
|
|
254
255
|
body: JSON.stringify({ embedToken: config.embedToken })
|
|
@@ -429,14 +430,16 @@ const DEFINED_ATTRS = /* @__PURE__ */ new Set([
|
|
|
429
430
|
"retry-label",
|
|
430
431
|
"auth-url",
|
|
431
432
|
"bundle-url",
|
|
432
|
-
"embed-token"
|
|
433
|
+
"embed-token",
|
|
434
|
+
"v2-api-url"
|
|
433
435
|
]);
|
|
434
436
|
const WIDGET_GLOBALS = {
|
|
435
437
|
store: "RaiStoreWidget",
|
|
436
438
|
channel: "RaiChannelWidget",
|
|
437
439
|
social: "RaiSocialWidget",
|
|
438
440
|
milestone: "RaiMilestoneWidget",
|
|
439
|
-
"currency-view": "RaiCurrencyWidget"
|
|
441
|
+
"currency-view": "RaiCurrencyWidget",
|
|
442
|
+
"referral-conditions": "RaiReferralWidget"
|
|
440
443
|
};
|
|
441
444
|
const TAG_TO_TYPE = {
|
|
442
445
|
"RAI-STORE-WIDGET": "store",
|
|
@@ -444,6 +447,7 @@ const TAG_TO_TYPE = {
|
|
|
444
447
|
"RAI-MILESTONE-WIDGET": "milestone",
|
|
445
448
|
"RAI-SOCIAL-WIDGET": "social",
|
|
446
449
|
"RAI-CURRENCY-WIDGET": "currency-view",
|
|
450
|
+
"RAI-REFERRAL-WIDGET": "referral-conditions",
|
|
447
451
|
"RAI-WIDGET": "store"
|
|
448
452
|
// deprecated alias
|
|
449
453
|
};
|
|
@@ -551,8 +555,10 @@ function readConfig(el, existingId) {
|
|
|
551
555
|
// authenticated embed
|
|
552
556
|
bundleUrl: get("bundle-url") || void 0,
|
|
553
557
|
// bundle mode
|
|
554
|
-
embedToken: get("embed-token") || void 0
|
|
558
|
+
embedToken: get("embed-token") || void 0,
|
|
555
559
|
// required — issued by customer's server
|
|
560
|
+
v2ApiUrl: get("v2-api-url") || void 0
|
|
561
|
+
// separate V2 API host for embed-token validation
|
|
556
562
|
};
|
|
557
563
|
}
|
|
558
564
|
function createInitialState() {
|
|
@@ -795,6 +801,9 @@ class BaseWidget extends HTMLElement {
|
|
|
795
801
|
for (const v of endpointVars) {
|
|
796
802
|
if (!w[v]) w[v] = this.config.apiUrl;
|
|
797
803
|
}
|
|
804
|
+
;
|
|
805
|
+
window.__IS_WIDGET__ = true;
|
|
806
|
+
window.guest_token = this.state.accessToken;
|
|
798
807
|
await loadScript(this.config.bundleUrl);
|
|
799
808
|
const globalName = WIDGET_GLOBALS[this.config.widgetType];
|
|
800
809
|
const widgetGlobal = window[globalName];
|
|
@@ -839,6 +848,9 @@ class BaseWidget extends HTMLElement {
|
|
|
839
848
|
const delay = this.state.accessTokenExpiry - Date.now() - 6e4;
|
|
840
849
|
const pushToken = () => {
|
|
841
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
|
+
}
|
|
842
854
|
};
|
|
843
855
|
const doRefresh = async () => {
|
|
844
856
|
if (this.config.authUrl) {
|
|
@@ -952,7 +964,20 @@ class CurrencyWidget extends BaseWidget {
|
|
|
952
964
|
}
|
|
953
965
|
}
|
|
954
966
|
}
|
|
955
|
-
|
|
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"}`);
|
|
956
981
|
class StoreWidgetCompat extends StoreWidget {
|
|
957
982
|
}
|
|
958
983
|
const WIDGET_REGISTRY = [
|
|
@@ -961,6 +986,7 @@ const WIDGET_REGISTRY = [
|
|
|
961
986
|
["rai-milestone-widget", MilestoneWidget],
|
|
962
987
|
["rai-social-widget", SocialWidget],
|
|
963
988
|
["rai-currency-widget", CurrencyWidget],
|
|
989
|
+
["rai-referral-widget", ReferralWidget],
|
|
964
990
|
["rai-widget", StoreWidgetCompat]
|
|
965
991
|
// deprecated alias — use <rai-store-widget> instead
|
|
966
992
|
];
|
|
@@ -974,7 +1000,8 @@ const WIDGET_CLASS_MAP = {
|
|
|
974
1000
|
channel: ChannelWidget,
|
|
975
1001
|
milestone: MilestoneWidget,
|
|
976
1002
|
social: SocialWidget,
|
|
977
|
-
"currency-view": CurrencyWidget
|
|
1003
|
+
"currency-view": CurrencyWidget,
|
|
1004
|
+
"referral-conditions": ReferralWidget
|
|
978
1005
|
};
|
|
979
1006
|
const ALL_WIDGET_SELECTOR = WIDGET_REGISTRY.map(([tag]) => tag).join(", ");
|
|
980
1007
|
function bootstrapFromScriptTag() {
|
|
@@ -1012,7 +1039,7 @@ function exposePublicApi() {
|
|
|
1012
1039
|
})();
|
|
1013
1040
|
const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
|
|
1014
1041
|
window.ReturningAIWidget = {
|
|
1015
|
-
version: "1.1.
|
|
1042
|
+
version: "1.1.2",
|
|
1016
1043
|
reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
|
|
1017
1044
|
logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
|
|
1018
1045
|
isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
|
|
@@ -1028,6 +1055,7 @@ export {
|
|
|
1028
1055
|
ChannelWidget,
|
|
1029
1056
|
CurrencyWidget,
|
|
1030
1057
|
MilestoneWidget,
|
|
1058
|
+
ReferralWidget,
|
|
1031
1059
|
SocialWidget,
|
|
1032
1060
|
StoreWidget
|
|
1033
1061
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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 };
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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;
|
|
@@ -29,6 +29,7 @@ export interface WidgetConfig {
|
|
|
29
29
|
authUrl?: string;
|
|
30
30
|
bundleUrl?: string;
|
|
31
31
|
embedToken?: string;
|
|
32
|
+
v2ApiUrl?: string;
|
|
32
33
|
}
|
|
33
34
|
export interface WidgetState {
|
|
34
35
|
accessToken: string | null;
|