@returningai/widget-sdk 1.8.1 → 1.8.3

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.
@@ -12418,8 +12418,12 @@ async function authenticateServerless(config, state, onRefreshScheduled) {
12418
12418
  setTokens(config, state, data, onRefreshScheduled);
12419
12419
  state.isAuthenticated = true;
12420
12420
  return true;
12421
- } catch {
12421
+ } catch (err) {
12422
12422
  if (is4xx || attempt === maxRetries) {
12423
+ state.lastAuthError ?? (state.lastAuthError = {
12424
+ status: 0,
12425
+ error: err instanceof Error ? err.message : "Authentication failed"
12426
+ });
12423
12427
  state.isAuthenticated = false;
12424
12428
  return false;
12425
12429
  }
@@ -12438,6 +12442,7 @@ async function authenticateViaProxy(config, state, onRefreshScheduled) {
12438
12442
  );
12439
12443
  }
12440
12444
  let is4xx = false;
12445
+ let status = 0;
12441
12446
  try {
12442
12447
  const response = await fetch(config.authUrl, {
12443
12448
  method: "POST",
@@ -12445,6 +12450,7 @@ async function authenticateViaProxy(config, state, onRefreshScheduled) {
12445
12450
  headers: { "Content-Type": "application/json" }
12446
12451
  });
12447
12452
  if (!response.ok) {
12453
+ status = response.status;
12448
12454
  is4xx = response.status >= 400 && response.status < 500;
12449
12455
  throw new Error(`HTTP ${response.status}`);
12450
12456
  }
@@ -12459,12 +12465,17 @@ async function authenticateViaProxy(config, state, onRefreshScheduled) {
12459
12465
  state.accessTokenExpiry = Date.now() + ttl * 1e3;
12460
12466
  state.refreshTokenExpiry = null;
12461
12467
  state.isAuthenticated = true;
12468
+ state.lastAuthError = null;
12462
12469
  if (config.autoRefresh && onRefreshScheduled) {
12463
12470
  onRefreshScheduled();
12464
12471
  }
12465
12472
  return true;
12466
- } catch {
12473
+ } catch (err) {
12467
12474
  if (is4xx || attempt === maxRetries) {
12475
+ state.lastAuthError = {
12476
+ status,
12477
+ error: err instanceof Error ? err.message : "Authentication failed"
12478
+ };
12468
12479
  state.isAuthenticated = false;
12469
12480
  return false;
12470
12481
  }
@@ -12513,6 +12524,7 @@ async function refreshAccessToken(config, state, onRefreshScheduled, sendToken)
12513
12524
  throw new Error("Invalid refresh response");
12514
12525
  }
12515
12526
  setTokens(config, state, data, onRefreshScheduled);
12527
+ state.isAuthenticated = true;
12516
12528
  if (sendToken) sendToken();
12517
12529
  return true;
12518
12530
  } catch {
@@ -12689,12 +12701,31 @@ function waitWithTimeout(promise, timeoutMs, timeoutMessage) {
12689
12701
  );
12690
12702
  });
12691
12703
  }
12692
- async function waitForBundleMountReadiness(mountResult, firstPaint, timeoutMs = BUNDLE_READY_TIMEOUT_MS) {
12693
- const resolvedMountResult = isPromiseLike(mountResult) ? await waitWithTimeout(
12704
+ function resolveBundleMountResult(mountResult, timeoutMs = BUNDLE_READY_TIMEOUT_MS) {
12705
+ return isPromiseLike(mountResult) ? waitWithTimeout(
12694
12706
  mountResult,
12695
12707
  timeoutMs,
12696
12708
  `Widget bundle mount did not resolve within ${timeoutMs}ms`
12697
- ) : mountResult;
12709
+ ) : Promise.resolve(mountResult);
12710
+ }
12711
+ function createBundleMountCleanup(mountResult) {
12712
+ if (typeof mountResult !== "object" || mountResult === null || !("unmount" in mountResult)) {
12713
+ return void 0;
12714
+ }
12715
+ const unmount = mountResult.unmount;
12716
+ if (typeof unmount !== "function") return void 0;
12717
+ let unmounted = false;
12718
+ return () => {
12719
+ if (unmounted) return;
12720
+ unmounted = true;
12721
+ unmount.call(mountResult);
12722
+ };
12723
+ }
12724
+ async function waitForBundleMountReadiness(mountResult, firstPaint, timeoutMs = BUNDLE_READY_TIMEOUT_MS) {
12725
+ const resolvedMountResult = await resolveBundleMountResult(
12726
+ mountResult,
12727
+ timeoutMs
12728
+ );
12698
12729
  if (!isReadyHandle(resolvedMountResult)) {
12699
12730
  await firstPaint;
12700
12731
  return "first-paint";
@@ -12706,11 +12737,51 @@ async function waitForBundleMountReadiness(mountResult, firstPaint, timeoutMs =
12706
12737
  );
12707
12738
  return "deep-ready";
12708
12739
  }
12740
+ const MAX_PRELOAD_ASSETS = 24;
12741
+ function resolveBundlePreloadAssets(bundleUrl, manifest) {
12742
+ if (manifest.version !== 1) return [];
12743
+ const normalizedBundleUrl = new URL(bundleUrl);
12744
+ const bundleDirectory = new URL("./", normalizedBundleUrl);
12745
+ const candidates = [
12746
+ ...(Array.isArray(manifest.scripts) ? manifest.scripts : []).map((value) => ({
12747
+ value,
12748
+ rel: "modulepreload",
12749
+ as: "script",
12750
+ extension: ".js"
12751
+ })),
12752
+ ...(Array.isArray(manifest.styles) ? manifest.styles : []).map((value) => ({
12753
+ value,
12754
+ rel: "preload",
12755
+ as: "style",
12756
+ extension: ".css"
12757
+ }))
12758
+ ];
12759
+ const seen = /* @__PURE__ */ new Set();
12760
+ const assets = [];
12761
+ for (const candidate of candidates) {
12762
+ if (assets.length >= MAX_PRELOAD_ASSETS) break;
12763
+ if (typeof candidate.value !== "string") continue;
12764
+ let resolved;
12765
+ try {
12766
+ resolved = new URL(candidate.value, bundleDirectory);
12767
+ } catch {
12768
+ continue;
12769
+ }
12770
+ if (resolved.origin !== bundleDirectory.origin || !resolved.pathname.startsWith(bundleDirectory.pathname) || !resolved.pathname.endsWith(candidate.extension) || seen.has(resolved.href)) {
12771
+ continue;
12772
+ }
12773
+ seen.add(resolved.href);
12774
+ assets.push({ url: resolved.href, rel: candidate.rel, as: candidate.as });
12775
+ }
12776
+ return assets;
12777
+ }
12709
12778
  function createBundleRuntimeWarmer({
12710
12779
  preloadScript: preloadScript2,
12780
+ preloadBundleAssets: preloadBundleAssets2,
12711
12781
  baseUrl
12712
12782
  }) {
12713
12783
  const preloadPromises = /* @__PURE__ */ new Map();
12784
+ const deepPreloadPromises = /* @__PURE__ */ new Map();
12714
12785
  return function warmBundleRuntime2(globalName, bundleUrl) {
12715
12786
  const normalizedUrl = normalizeBundleUrl(bundleUrl, baseUrl());
12716
12787
  if (preloadPromises.has(normalizedUrl)) return;
@@ -12718,6 +12789,12 @@ function createBundleRuntimeWarmer({
12718
12789
  preloadPromises.delete(normalizedUrl);
12719
12790
  });
12720
12791
  preloadPromises.set(normalizedUrl, preloadPromise);
12792
+ if (preloadBundleAssets2 && !deepPreloadPromises.has(normalizedUrl)) {
12793
+ const deepPreloadPromise = preloadBundleAssets2(normalizedUrl).catch(() => {
12794
+ deepPreloadPromises.delete(normalizedUrl);
12795
+ });
12796
+ deepPreloadPromises.set(normalizedUrl, deepPreloadPromise);
12797
+ }
12721
12798
  };
12722
12799
  }
12723
12800
  function isWidgetBundleRuntime(value) {
@@ -12797,6 +12874,35 @@ function preloadScript(url) {
12797
12874
  document.head.appendChild(link);
12798
12875
  });
12799
12876
  }
12877
+ const preloadedBundleAssets = /* @__PURE__ */ new Set();
12878
+ function appendBundleAssetPreload(asset) {
12879
+ const cacheKey = `${asset.rel}:${asset.url}`;
12880
+ if (preloadedBundleAssets.has(cacheKey)) return;
12881
+ const link = document.createElement("link");
12882
+ link.rel = asset.rel;
12883
+ link.as = asset.as;
12884
+ link.href = asset.url;
12885
+ link.crossOrigin = "anonymous";
12886
+ link.onload = () => void 0;
12887
+ link.onerror = () => {
12888
+ preloadedBundleAssets.delete(cacheKey);
12889
+ link.remove();
12890
+ };
12891
+ preloadedBundleAssets.add(cacheKey);
12892
+ document.head.appendChild(link);
12893
+ }
12894
+ async function preloadBundleAssets(bundleUrl) {
12895
+ const manifestUrl = new URL("./preload-manifest.json", bundleUrl);
12896
+ const response = await fetch(manifestUrl, {
12897
+ credentials: "omit",
12898
+ headers: { Accept: "application/json" }
12899
+ });
12900
+ if (!response.ok) throw new Error(`Bundle preload manifest returned ${response.status}`);
12901
+ const manifest = await response.json();
12902
+ for (const asset of resolveBundlePreloadAssets(bundleUrl, manifest)) {
12903
+ appendBundleAssetPreload(asset);
12904
+ }
12905
+ }
12800
12906
  const loadBrowserBundleRuntime = createBundleRuntimeLoader({
12801
12907
  loadScript: appendScript,
12802
12908
  readGlobal: (globalName) => window[globalName],
@@ -12804,6 +12910,7 @@ const loadBrowserBundleRuntime = createBundleRuntimeLoader({
12804
12910
  });
12805
12911
  const warmBrowserBundleRuntime = createBundleRuntimeWarmer({
12806
12912
  preloadScript,
12913
+ preloadBundleAssets,
12807
12914
  baseUrl: () => document.baseURI
12808
12915
  });
12809
12916
  function warmBundleRuntime(globalName, bundleUrl) {
@@ -13059,6 +13166,100 @@ function dispatchHostCallback(input) {
13059
13166
  }
13060
13167
  );
13061
13168
  }
13169
+ const SUPPORTED_WIDGET_LANGUAGES = [
13170
+ "en",
13171
+ "de",
13172
+ "es",
13173
+ "fr",
13174
+ "it",
13175
+ "pt",
13176
+ "pl",
13177
+ "da",
13178
+ "nl",
13179
+ "ru",
13180
+ "chs",
13181
+ "el",
13182
+ "ko",
13183
+ "cht",
13184
+ "th",
13185
+ "ja",
13186
+ "id",
13187
+ "vt",
13188
+ "ms",
13189
+ "hi",
13190
+ "fil",
13191
+ "ta",
13192
+ "tr",
13193
+ "ar",
13194
+ "mn",
13195
+ "sw"
13196
+ ];
13197
+ const supportedWidgetLanguages = new Set(SUPPORTED_WIDGET_LANGUAGES);
13198
+ const warnedUnsupportedLanguages = /* @__PURE__ */ new Set();
13199
+ const LANGUAGE_TAG_PATTERN = /^[a-z]{2,8}(?:-[a-z0-9]{1,8})*$/;
13200
+ function resolveWidgetLanguage(language) {
13201
+ const normalized = language == null ? void 0 : language.trim().toLowerCase().replace(/_/g, "-");
13202
+ if (!normalized || !LANGUAGE_TAG_PATTERN.test(normalized)) return void 0;
13203
+ const segments = normalized.split("-");
13204
+ const primaryLanguage = segments[0];
13205
+ if (primaryLanguage === "zh") {
13206
+ if (segments.includes("hant")) {
13207
+ return "cht";
13208
+ }
13209
+ if (segments.includes("hans")) {
13210
+ return "chs";
13211
+ }
13212
+ if (segments.includes("tw") || segments.includes("hk") || segments.includes("mo")) {
13213
+ return "cht";
13214
+ }
13215
+ if (segments.includes("cn") || segments.includes("sg")) {
13216
+ return "chs";
13217
+ }
13218
+ return void 0;
13219
+ }
13220
+ if (primaryLanguage === "vi" || primaryLanguage === "vt") {
13221
+ return "vt";
13222
+ }
13223
+ return supportedWidgetLanguages.has(primaryLanguage) ? primaryLanguage : void 0;
13224
+ }
13225
+ function warnUnsupportedWidgetLanguage(language) {
13226
+ const value = language.trim();
13227
+ if (!value) return;
13228
+ const warningKey = value.toLowerCase();
13229
+ if (warnedUnsupportedLanguages.has(warningKey)) return;
13230
+ warnedUnsupportedLanguages.add(warningKey);
13231
+ console.warn(
13232
+ `[rai-widget] Unsupported language "${value.slice(
13233
+ 0,
13234
+ 80
13235
+ )}". Falling back to the browser language. Supported language codes: ${SUPPORTED_WIDGET_LANGUAGES.join(
13236
+ ", "
13237
+ )}.`
13238
+ );
13239
+ }
13240
+ const PERCENTAGE_HEIGHT = /^(\d+(?:\.\d+)?)%$/;
13241
+ function parsePercentageHeight(value) {
13242
+ const match = value.trim().match(PERCENTAGE_HEIGHT);
13243
+ if (!match) return null;
13244
+ const percentage = Number(match[1]);
13245
+ return Number.isFinite(percentage) && percentage > 0 ? percentage : null;
13246
+ }
13247
+ function resolvePercentageViewportHeight(value, viewportHeight) {
13248
+ const percentage = parsePercentageHeight(value);
13249
+ return percentage === null ? 0 : viewportHeight * percentage / 100;
13250
+ }
13251
+ function resolveCollapsedRestoredHeight({
13252
+ originalHeight,
13253
+ restoredHeight,
13254
+ resolvedHeight,
13255
+ isRendered
13256
+ }) {
13257
+ if (!isRendered || Number.isFinite(restoredHeight) && restoredHeight > 0) {
13258
+ return null;
13259
+ }
13260
+ const percentage = parsePercentageHeight(originalHeight);
13261
+ return percentage === null ? `${resolvedHeight}px` : `${percentage}vh`;
13262
+ }
13062
13263
  function debounce(fn, wait) {
13063
13264
  let timer = null;
13064
13265
  return {
@@ -13213,6 +13414,54 @@ function setupMessageListener(config, state, _shadow, iframe, onRefreshScheduled
13213
13414
  heightSetter.cancel();
13214
13415
  };
13215
13416
  }
13417
+ async function resolveStartupAuthentication(authentication, loadErrorSettings) {
13418
+ const authenticated = await authentication;
13419
+ if (authenticated) {
13420
+ void loadErrorSettings({ skipCache: true }).catch(() => {
13421
+ });
13422
+ return true;
13423
+ }
13424
+ try {
13425
+ await loadErrorSettings();
13426
+ } catch {
13427
+ }
13428
+ return false;
13429
+ }
13430
+ function resolveWidgetPreconnectOrigins(config, baseUrl) {
13431
+ const values = [
13432
+ config.apiUrl,
13433
+ config.v2ApiUrl,
13434
+ config.authUrl,
13435
+ config.bundleUrl,
13436
+ config.widgetUrl,
13437
+ config.widgetDomain
13438
+ ];
13439
+ const origins = [];
13440
+ for (const value of values) {
13441
+ if (!value) continue;
13442
+ try {
13443
+ const url = new URL(value, baseUrl);
13444
+ if ((url.protocol === "http:" || url.protocol === "https:") && !origins.includes(url.origin)) {
13445
+ origins.push(url.origin);
13446
+ }
13447
+ } catch {
13448
+ }
13449
+ }
13450
+ return origins;
13451
+ }
13452
+ function ensureWidgetPreconnects(origins, targetDocument) {
13453
+ const documentTarget = document;
13454
+ for (const origin of origins) {
13455
+ const id = `rai-widget-preconnect-${origin.replace(/[^a-z0-9]+/gi, "-")}`;
13456
+ if (documentTarget.getElementById(id)) continue;
13457
+ const link = documentTarget.createElement("link");
13458
+ link.id = id;
13459
+ link.rel = "preconnect";
13460
+ link.href = origin;
13461
+ link.crossOrigin = "anonymous";
13462
+ documentTarget.head.appendChild(link);
13463
+ }
13464
+ }
13216
13465
  const widgetCSS = ':host{display:block;position:relative;width:100%;height:100%}.rai-loader{position:absolute;top:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;background:var(--rai-loading-background, var(--background-5, var(--rai-loader-bg, #ffffff)));border-radius:8px;z-index:10;transition:opacity .3s ease-out;font-family:var(--rai-loader-font, "Roboto", system-ui, -apple-system, sans-serif)}.rai-loader.fade-out{opacity:0;pointer-events:none}.rai-loader-pending-settings{visibility:hidden}.rai-loader-text{margin:.5rem 0 0;font-family:var(--rai-loading-text-font, var(--rai-loader-font, "Roboto", system-ui, -apple-system, sans-serif));font-size:var(--rai-loading-text-size, 1.125rem);line-height:1.75rem;font-weight:var(--rai-loading-text-weight, 400);font-style:var(--rai-loading-text-style, normal);text-decoration:var(--rai-loading-text-decoration, none);letter-spacing:normal;color:var(--rai-loading-text-color, var(--accent-1, var(--rai-accent, #000000)));text-align:center}@media (min-width: 768px){.rai-loader-text{font-size:var(--rai-loading-text-size, 1.5rem);line-height:2rem}}.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-lottie-loader{width:100px;height:100px}.rai-lottie-loader svg{width:100%!important;height:100%!important}.rai-lottie-spinner{width:32px;height:32px;margin:34px auto;border:3px solid var(--rai-text4, #6b7280);border-top-color:var(--rai-accent, #000000);border-radius:50%;animation:rai-spin .7s linear infinite}@keyframes rai-spin{to{transform:rotate(360deg)}}.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-custom-error{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.tiptap strong.tw-font-bold,.tiptap b.tw-font-bold{font-weight:700}.tiptap em.tw-font-italic,.tiptap i.tw-font-italic{font-style:italic}.tiptap a.tiptap-rich-text-link{color:#3b82f6;text-decoration:underline;position:relative;display:inline-block;width:fit-content}.tiptap a.tiptap-rich-text-link:hover{color:#3b82f6cc;text-decoration:none}.tiptap a.tiptap-rich-text-link:not([title=""]):before{content:attr(title);position:absolute;top:-2rem;left:50%;transform:translate(-50%);white-space:nowrap;border-radius:.25rem;background-color:#000;padding:.25rem .5rem;color:#fff;opacity:0;transition:opacity .2s;pointer-events:none}.tiptap a.tiptap-rich-text-link:not([title=""]):hover:before{opacity:1}.tiptap p[style*="text-align: left"]{text-align:left}.tiptap p[style*="text-align: center"]{text-align:center}.tiptap p[style*="text-align: right"]{text-align:right}.tiptap p[style*="text-align: justify"]{text-align:justify}.tiptap u{text-decoration:underline}.tiptap.ProseMirror{background-color:transparent;height:fit-content!important;word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-feature-settings:"liga" 0;padding:0;width:100%;overflow-y:auto}.tiptap{line-height:1.6;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.tiptap p{margin:.5em 0}.tiptap p:first-child{margin-top:0}.tiptap p:last-child{margin-bottom:0}.tiptap img{max-width:100%;height:auto;display:block}.tiptap p[style*="text-align: left"] img{margin-left:0;margin-right:auto}.tiptap p[style*="text-align: center"] img{margin-left:auto;margin-right:auto}.tiptap p[style*="text-align: right"] img{margin-left:auto;margin-right:0}.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}';
13217
13466
  const DEFINED_ATTRS = /* @__PURE__ */ new Set([
13218
13467
  "community-id",
@@ -13233,6 +13482,7 @@ const DEFINED_ATTRS = /* @__PURE__ */ new Set([
13233
13482
  "max-retries",
13234
13483
  "retry-delay",
13235
13484
  "height-debounce",
13485
+ "language",
13236
13486
  "locale",
13237
13487
  "custom-data",
13238
13488
  "retry-label",
@@ -13493,6 +13743,13 @@ function readConfig(el2, existingId) {
13493
13743
  return void 0;
13494
13744
  }
13495
13745
  })();
13746
+ const explicitLanguage = get("language").trim();
13747
+ const legacyLocale = get("locale").trim();
13748
+ const requestedLanguage = explicitLanguage || legacyLocale || void 0;
13749
+ const language = resolveWidgetLanguage(requestedLanguage);
13750
+ if (requestedLanguage && !language) {
13751
+ warnUnsupportedWidgetLanguage(requestedLanguage);
13752
+ }
13496
13753
  return {
13497
13754
  communityId,
13498
13755
  channelId,
@@ -13518,7 +13775,12 @@ function readConfig(el2, existingId) {
13518
13775
  // #2
13519
13776
  heightDebounce: num("height-debounce", 100),
13520
13777
  // #4
13521
- locale: get("locale") || void 0,
13778
+ // `language` is the canonical forced widget locale. Keep `locale` as a
13779
+ // backwards-compatible alias only when it supplied the selected value.
13780
+ // Unsupported explicit values are omitted so the widget uses its existing
13781
+ // browser-language fallback.
13782
+ language,
13783
+ locale: !explicitLanguage && legacyLocale ? language : void 0,
13522
13784
  // #5
13523
13785
  customData,
13524
13786
  // #8
@@ -13580,6 +13842,8 @@ class BaseWidget extends HTMLElement {
13580
13842
  __publicField(this, "config");
13581
13843
  __publicField(this, "state", createInitialState());
13582
13844
  __publicField(this, "loaderEl", null);
13845
+ __publicField(this, "loaderHeightRestore", null);
13846
+ __publicField(this, "loaderHeightObserver", null);
13583
13847
  __publicField(this, "errorEl", null);
13584
13848
  __publicField(this, "msgEl", null);
13585
13849
  __publicField(this, "cleanupListener");
@@ -13591,14 +13855,21 @@ class BaseWidget extends HTMLElement {
13591
13855
  __publicField(this, "hasAttemptedInit", false);
13592
13856
  __publicField(this, "initGeneration", 0);
13593
13857
  __publicField(this, "lottieInstances", []);
13594
- __publicField(this, "renderedLoaderAnimationKey", null);
13595
13858
  __publicField(this, "callbackRegistry", new WidgetCallbackRegistry());
13596
13859
  __publicField(this, "bannerNode", null);
13597
13860
  __publicField(this, "releaseAutoThemeDisableLease");
13861
+ __publicField(this, "bundleUnmount");
13598
13862
  this.shadow = this.attachShadow({ mode: "closed" });
13599
13863
  }
13600
13864
  static get observedAttributes() {
13601
- return ["embed-token", "data-embed-token"];
13865
+ return [
13866
+ "embed-token",
13867
+ "data-embed-token",
13868
+ "language",
13869
+ "data-language",
13870
+ "locale",
13871
+ "data-locale"
13872
+ ];
13602
13873
  }
13603
13874
  registerCallback(callbackName, callback) {
13604
13875
  this.callbackRegistry.registerCallback(callbackName, callback);
@@ -13610,6 +13881,9 @@ class BaseWidget extends HTMLElement {
13610
13881
  this.config = readConfig(this, void 0);
13611
13882
  this.identitySignature = identitySignatureForConfig(this.config);
13612
13883
  this.setupIdentityAttributeObserver();
13884
+ ensureWidgetPreconnects(
13885
+ resolveWidgetPreconnectOrigins(this.config, document.baseURI)
13886
+ );
13613
13887
  const style = document.createElement("style");
13614
13888
  style.textContent = widgetCSS;
13615
13889
  this.shadow.appendChild(style);
@@ -13645,13 +13919,23 @@ class BaseWidget extends HTMLElement {
13645
13919
  (_c = this.identityAttributeObserver) == null ? void 0 : _c.disconnect();
13646
13920
  this.teardownMountedWidget();
13647
13921
  this.clearLottieInstances();
13922
+ this.restoreLoaderHeight();
13648
13923
  this.removeBanner();
13649
13924
  clearState(this.state);
13650
13925
  }
13651
13926
  attributeChangedCallback(name, oldValue, newValue) {
13652
13927
  if (oldValue === newValue) return;
13653
- if (name !== "embed-token" && name !== "data-embed-token") return;
13654
- this.handleIdentityConfigChange();
13928
+ if (name === "embed-token" || name === "data-embed-token") {
13929
+ this.handleIdentityConfigChange();
13930
+ return;
13931
+ }
13932
+ if (this.isConnected && this.config) {
13933
+ if (this.hasAttemptedInit) {
13934
+ void this.reload();
13935
+ } else {
13936
+ this.config = readConfig(this, this.config.communityId);
13937
+ }
13938
+ }
13655
13939
  }
13656
13940
  setupIdentityAttributeObserver() {
13657
13941
  var _a;
@@ -13807,22 +14091,6 @@ class BaseWidget extends HTMLElement {
13807
14091
  textEl.hidden = !loadingText.enabled;
13808
14092
  }
13809
14093
  }
13810
- getLoadingAnimationRenderKey() {
13811
- var _a, _b, _c;
13812
- const animation = this.state.loadingAnimation;
13813
- const theme = this.config.theme === "dark" ? "dark" : "light";
13814
- const custom = (animation == null ? void 0 : animation.type) === "custom" ? ((_a = animation.custom) == null ? void 0 : _a[theme]) || ((_b = animation.custom) == null ? void 0 : _b.light) || ((_c = animation.custom) == null ? void 0 : _c.dark) : void 0;
13815
- return JSON.stringify({
13816
- theme,
13817
- type: (animation == null ? void 0 : animation.type) ?? null,
13818
- preset: (animation == null ? void 0 : animation.preset) ?? null,
13819
- custom: custom ? {
13820
- type: custom.type ?? null,
13821
- html: custom.html ?? null,
13822
- lottie: custom.lottie ?? null
13823
- } : null
13824
- });
13825
- }
13826
14094
  renderShell() {
13827
14095
  this.loaderEl = document.createElement("div");
13828
14096
  this.loaderEl.className = "rai-loader";
@@ -13834,6 +14102,7 @@ class BaseWidget extends HTMLElement {
13834
14102
  textEl.textContent = this.config.loadingText;
13835
14103
  this.loaderEl.appendChild(textEl);
13836
14104
  this.shadow.appendChild(this.loaderEl);
14105
+ this.freezeIframeLoaderHeight();
13837
14106
  this.applyLoadingSettings();
13838
14107
  this.fetchAndRenderLoader();
13839
14108
  this.errorEl = document.createElement("div");
@@ -13854,11 +14123,9 @@ class BaseWidget extends HTMLElement {
13854
14123
  * Loads the community loading animation + theme palette from cache or API
13855
14124
  * and renders the configured animation above the loading text.
13856
14125
  *
13857
- * Stale-while-revalidate:
13858
- * - Cache hit → apply palette & render animation synchronously, fire
13859
- * background refresh.
13860
- * - Cache miss → retain the initial shell; await network; apply palette +
13861
- * render the resolved animation or fallback.
14126
+ * Cached settings are applied synchronously. On a first visit, settings load
14127
+ * alongside authentication so the generic loader stays hidden until the
14128
+ * configured animation is known. This request never blocks widget launch.
13862
14129
  */
13863
14130
  async fetchAndRenderLoader() {
13864
14131
  var _a;
@@ -13867,26 +14134,14 @@ class BaseWidget extends HTMLElement {
13867
14134
  applyErrorSettingsToState(this.state, cached);
13868
14135
  this.applyLoadingSettings();
13869
14136
  this.renderLoaderAnimation();
13870
- void fetchErrorSettings(this.config, this.state, { skipCache: true }).then(() => {
13871
- var _a2;
13872
- if (!this.loaderEl) return;
13873
- const theme2 = this.config.theme === "dark" ? "dark" : "light";
13874
- const palette2 = (_a2 = this.state.themePalette) == null ? void 0 : _a2[theme2];
13875
- if (palette2) this.applyPalette(palette2);
13876
- if (this.state.font) this.applyFont(this.state.font);
13877
- this.applyLoadingSettings();
13878
- if (this.renderedLoaderAnimationKey !== this.getLoadingAnimationRenderKey()) {
13879
- this.renderLoaderAnimation();
13880
- }
13881
- }).catch(() => {
13882
- });
13883
14137
  return;
13884
14138
  }
13885
14139
  try {
13886
14140
  await fetchErrorSettings(this.config, this.state);
13887
14141
  } catch {
13888
14142
  }
13889
- if (!this.loaderEl) return;
14143
+ const loaderEl = this.loaderEl;
14144
+ if (!loaderEl) return;
13890
14145
  if (!this.config.themeExplicit && (this.state.defaultColorSchema === "light" || this.state.defaultColorSchema === "dark") && this.state.defaultColorSchema !== this.config.theme) {
13891
14146
  this.config.theme = this.state.defaultColorSchema;
13892
14147
  }
@@ -13896,7 +14151,7 @@ class BaseWidget extends HTMLElement {
13896
14151
  if (this.state.font) this.applyFont(this.state.font);
13897
14152
  this.applyLoadingSettings();
13898
14153
  this.renderLoaderAnimation();
13899
- this.loaderEl.classList.remove("rai-loader-pending-settings");
14154
+ loaderEl.classList.remove("rai-loader-pending-settings");
13900
14155
  }
13901
14156
  /**
13902
14157
  * Append the loading animation above the text. Removes any previous
@@ -13905,7 +14160,6 @@ class BaseWidget extends HTMLElement {
13905
14160
  */
13906
14161
  renderLoaderAnimation() {
13907
14162
  if (!this.loaderEl) return;
13908
- this.renderedLoaderAnimationKey = this.getLoadingAnimationRenderKey();
13909
14163
  this.clearLottieInstances();
13910
14164
  const existing = this.loaderEl.querySelector(".rai-loader-anim");
13911
14165
  if (existing) existing.remove();
@@ -13992,9 +14246,82 @@ class BaseWidget extends HTMLElement {
13992
14246
  setTimeout(() => {
13993
14247
  loader.remove();
13994
14248
  lottieInstances.forEach((instance) => instance.destroy());
14249
+ this.restoreLoaderHeight();
13995
14250
  }, 300);
13996
14251
  this.loaderEl = null;
13997
14252
  }
14253
+ /**
14254
+ * Keep percentage-based iframe embeds at their resolved startup height while
14255
+ * the SDK loader is visible. The child iframe may resize during auth/data
14256
+ * loading; without this pin the loader's 100% centering moves with the host.
14257
+ */
14258
+ freezeIframeLoaderHeight() {
14259
+ var _a;
14260
+ if (this.config.bundleUrl || this.loaderHeightRestore) return;
14261
+ const measuredHeight = this.getBoundingClientRect().height;
14262
+ const isRendered = this.getClientRects().length > 0;
14263
+ const hasPercentageHeight = parsePercentageHeight(this.style.height) !== null;
14264
+ const percentageHeight = resolvePercentageViewportHeight(
14265
+ this.style.height,
14266
+ window.innerHeight
14267
+ );
14268
+ if (measuredHeight <= 0 && hasPercentageHeight && !isRendered) {
14269
+ this.deferIframeLoaderHeightFreeze();
14270
+ return;
14271
+ }
14272
+ const resolvedHeight = measuredHeight > 0 ? measuredHeight : percentageHeight;
14273
+ if (!Number.isFinite(resolvedHeight) || resolvedHeight <= 0) return;
14274
+ (_a = this.loaderHeightObserver) == null ? void 0 : _a.disconnect();
14275
+ this.loaderHeightObserver = null;
14276
+ this.loaderHeightRestore = {
14277
+ value: this.style.getPropertyValue("height"),
14278
+ priority: this.style.getPropertyPriority("height"),
14279
+ resolvedHeight
14280
+ };
14281
+ this.style.setProperty("height", `${resolvedHeight}px`);
14282
+ }
14283
+ deferIframeLoaderHeightFreeze() {
14284
+ if (this.loaderHeightObserver || typeof ResizeObserver === "undefined") {
14285
+ return;
14286
+ }
14287
+ this.loaderHeightObserver = new ResizeObserver(() => {
14288
+ var _a, _b;
14289
+ if (!this.isConnected || !this.loaderEl || this.config.bundleUrl) {
14290
+ (_a = this.loaderHeightObserver) == null ? void 0 : _a.disconnect();
14291
+ this.loaderHeightObserver = null;
14292
+ return;
14293
+ }
14294
+ if (this.getClientRects().length === 0) return;
14295
+ (_b = this.loaderHeightObserver) == null ? void 0 : _b.disconnect();
14296
+ this.loaderHeightObserver = null;
14297
+ this.freezeIframeLoaderHeight();
14298
+ });
14299
+ this.loaderHeightObserver.observe(this);
14300
+ }
14301
+ restoreLoaderHeight() {
14302
+ var _a;
14303
+ (_a = this.loaderHeightObserver) == null ? void 0 : _a.disconnect();
14304
+ this.loaderHeightObserver = null;
14305
+ if (!this.loaderHeightRestore) return;
14306
+ const { value, priority, resolvedHeight } = this.loaderHeightRestore;
14307
+ this.loaderHeightRestore = null;
14308
+ if (value) {
14309
+ this.style.setProperty("height", value, priority);
14310
+ } else {
14311
+ this.style.removeProperty("height");
14312
+ }
14313
+ const restoredHeight = this.getBoundingClientRect().height;
14314
+ const isRendered = this.isConnected && this.getClientRects().length > 0;
14315
+ const collapsedFallback = resolveCollapsedRestoredHeight({
14316
+ originalHeight: value,
14317
+ restoredHeight,
14318
+ resolvedHeight,
14319
+ isRendered
14320
+ });
14321
+ if (collapsedFallback) {
14322
+ this.style.setProperty("height", collapsedFallback, priority);
14323
+ }
14324
+ }
13998
14325
  /**
13999
14326
  * Resolve after a legacy bundle's first rendered child has reached a paint.
14000
14327
  * This remains the fallback for bundles that do not expose a deep-ready
@@ -14207,14 +14534,10 @@ class BaseWidget extends HTMLElement {
14207
14534
  this.config.bundleUrl
14208
14535
  );
14209
14536
  }
14210
- const errorSettingsPromise = fetchErrorSettings(this.config, this.state);
14211
- const finishStartup = async (authentication) => {
14212
- const [authenticated] = await Promise.all([
14213
- authentication,
14214
- errorSettingsPromise
14215
- ]);
14216
- return authenticated;
14217
- };
14537
+ const finishStartup = (authentication) => resolveStartupAuthentication(
14538
+ authentication,
14539
+ (options) => fetchErrorSettings(this.config, this.state, options)
14540
+ );
14218
14541
  const launchWidget = () => {
14219
14542
  var _a;
14220
14543
  if (!this.isCurrentInit(initId)) return;
@@ -14314,6 +14637,13 @@ class BaseWidget extends HTMLElement {
14314
14637
  }
14315
14638
  teardownMountedWidget() {
14316
14639
  var _a;
14640
+ const bundleUnmount = this.bundleUnmount;
14641
+ this.bundleUnmount = void 0;
14642
+ try {
14643
+ bundleUnmount == null ? void 0 : bundleUnmount();
14644
+ } catch (error) {
14645
+ console.error("[rai-widget] Bundle unmount failed:", error);
14646
+ }
14317
14647
  (_a = this.releaseAutoThemeDisableLease) == null ? void 0 : _a.call(this);
14318
14648
  this.releaseAutoThemeDisableLease = void 0;
14319
14649
  if (this.cleanupListener) {
@@ -14389,6 +14719,7 @@ class BaseWidget extends HTMLElement {
14389
14719
  async mountWidget(initId) {
14390
14720
  var _a;
14391
14721
  let container = null;
14722
+ let cleanupBundleMount;
14392
14723
  try {
14393
14724
  this.teardownMountedWidget();
14394
14725
  const autoHeight = this.config.height.trim().toLowerCase() === "auto";
@@ -14451,6 +14782,7 @@ class BaseWidget extends HTMLElement {
14451
14782
  // injected by SSR for the explicit `/open-widget` route.
14452
14783
  isOpenWidget: !this.state.accessToken,
14453
14784
  defaultColorSchema: this.config.widgetType === "custom" && !this.config.themeExplicit ? null : colorMode,
14785
+ language: this.config.language,
14454
14786
  // Bundle loading screens are rendered beneath an instance-scoped
14455
14787
  // provider. Do not put these values on window: pages can mount several
14456
14788
  // widget types at once.
@@ -14473,8 +14805,20 @@ class BaseWidget extends HTMLElement {
14473
14805
  transport: "bundle"
14474
14806
  })
14475
14807
  });
14476
- await waitForBundleMountReadiness(mountResult, firstPaint);
14808
+ const resolvedMountResult = await resolveBundleMountResult(mountResult);
14809
+ cleanupBundleMount = createBundleMountCleanup(resolvedMountResult);
14477
14810
  if (!this.isCurrentInit(initId) || !container.isConnected) {
14811
+ cleanupBundleMount == null ? void 0 : cleanupBundleMount();
14812
+ container.remove();
14813
+ return;
14814
+ }
14815
+ this.bundleUnmount = cleanupBundleMount;
14816
+ await waitForBundleMountReadiness(resolvedMountResult, firstPaint);
14817
+ if (!this.isCurrentInit(initId) || !container.isConnected) {
14818
+ cleanupBundleMount == null ? void 0 : cleanupBundleMount();
14819
+ if (this.bundleUnmount === cleanupBundleMount) {
14820
+ this.bundleUnmount = void 0;
14821
+ }
14478
14822
  container.remove();
14479
14823
  return;
14480
14824
  }
@@ -14482,11 +14826,16 @@ class BaseWidget extends HTMLElement {
14482
14826
  this.hideLoader();
14483
14827
  this.emit("rai-mounted");
14484
14828
  } catch (err) {
14829
+ cleanupBundleMount == null ? void 0 : cleanupBundleMount();
14830
+ if (this.bundleUnmount === cleanupBundleMount) {
14831
+ this.bundleUnmount = void 0;
14832
+ }
14485
14833
  if (!this.isCurrentInit(initId)) {
14486
14834
  container == null ? void 0 : container.remove();
14487
14835
  return;
14488
14836
  }
14489
14837
  console.error("[rai-widget] Bundle mount failed:", err);
14838
+ container == null ? void 0 : container.remove();
14490
14839
  (_a = this.releaseAutoThemeDisableLease) == null ? void 0 : _a.call(this);
14491
14840
  this.releaseAutoThemeDisableLease = void 0;
14492
14841
  this.showError();
@@ -14510,13 +14859,15 @@ class BaseWidget extends HTMLElement {
14510
14859
  () => this.scheduleRefresh()
14511
14860
  );
14512
14861
  if (ok) pushToken();
14862
+ else this.handleSessionExpired();
14513
14863
  } else {
14514
- await refreshAccessToken(
14864
+ const ok = await refreshAccessToken(
14515
14865
  this.config,
14516
14866
  this.state,
14517
14867
  () => this.scheduleRefresh(),
14518
14868
  pushToken
14519
14869
  );
14870
+ if (!ok) this.handleSessionExpired();
14520
14871
  }
14521
14872
  };
14522
14873
  if (delay > 0) {
@@ -14532,6 +14883,35 @@ class BaseWidget extends HTMLElement {
14532
14883
  sendTokenToWidget(this.config, this.state, iframe);
14533
14884
  }, 12e4);
14534
14885
  }
14886
+ /**
14887
+ * A background refresh exhausted every recovery path — /auth/refresh failed
14888
+ * and the re-auth that follows it failed too, so `state.isAuthenticated` is
14889
+ * now false and there is no live token.
14890
+ *
14891
+ * Every startup auth path already calls showError() on failure; this one is
14892
+ * reached from a timer, so without it the widget stays mounted showing stale
14893
+ * content while isAuthenticated() reports false to the host page — which is
14894
+ * how a signed-in user ends up looking at content meant for signed-out users.
14895
+ * The event gives hosts a signal to re-mint credentials instead of polling.
14896
+ */
14897
+ handleSessionExpired() {
14898
+ var _a;
14899
+ if (this.state.refreshTimer) {
14900
+ clearTimeout(this.state.refreshTimer);
14901
+ this.state.refreshTimer = null;
14902
+ }
14903
+ (_a = this.state).lastAuthError ?? (_a.lastAuthError = {
14904
+ status: 401,
14905
+ error: "Session expired",
14906
+ hint: "The widget session could not be renewed. Reload to sign in again."
14907
+ });
14908
+ this.emit("rai-session-expired", {
14909
+ communityId: this.config.communityId,
14910
+ widgetType: this.config.widgetType,
14911
+ lastAuthError: this.state.lastAuthError ?? void 0
14912
+ });
14913
+ this.showError();
14914
+ }
14535
14915
  // ── Logout helper ─────────────────────────────────────────────────────
14536
14916
  async logoutAndClear() {
14537
14917
  await logout(this.config, this.state);
@@ -14578,6 +14958,7 @@ class StoreWidget extends BaseWidget {
14578
14958
  url.searchParams.set("containerId", config.container);
14579
14959
  url.searchParams.set("connectType", "simple");
14580
14960
  url.searchParams.set("mode", "private");
14961
+ if (config.language) url.searchParams.set("language", config.language);
14581
14962
  if (config.locale) url.searchParams.set("locale", config.locale);
14582
14963
  return url.toString();
14583
14964
  }
@@ -14588,10 +14969,12 @@ class ChannelWidget extends BaseWidget {
14588
14969
  try {
14589
14970
  const u = new URL(base);
14590
14971
  u.searchParams.set("color", config.theme);
14972
+ if (config.language) u.searchParams.set("language", config.language);
14591
14973
  if (config.locale) u.searchParams.set("locale", config.locale);
14592
14974
  return u.toString();
14593
14975
  } catch {
14594
14976
  const params = [`color=${config.theme}`];
14977
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14595
14978
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14596
14979
  return `${base}?${params.join("&")}`;
14597
14980
  }
@@ -14603,10 +14986,12 @@ class MilestoneWidget extends BaseWidget {
14603
14986
  try {
14604
14987
  const u = new URL(base);
14605
14988
  u.searchParams.set("color", config.theme);
14989
+ if (config.language) u.searchParams.set("language", config.language);
14606
14990
  if (config.locale) u.searchParams.set("locale", config.locale);
14607
14991
  return u.toString();
14608
14992
  } catch {
14609
14993
  const params = [`color=${config.theme}`];
14994
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14610
14995
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14611
14996
  return `${base}?${params.join("&")}`;
14612
14997
  }
@@ -14618,10 +15003,12 @@ class SocialWidget extends BaseWidget {
14618
15003
  try {
14619
15004
  const u = new URL(base);
14620
15005
  u.searchParams.set("color", config.theme);
15006
+ if (config.language) u.searchParams.set("language", config.language);
14621
15007
  if (config.locale) u.searchParams.set("locale", config.locale);
14622
15008
  return u.toString();
14623
15009
  } catch {
14624
15010
  const params = [`color=${config.theme}`];
15011
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14625
15012
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14626
15013
  return `${base}?${params.join("&")}`;
14627
15014
  }
@@ -14633,10 +15020,12 @@ class CurrencyWidget extends BaseWidget {
14633
15020
  try {
14634
15021
  const u = new URL(base);
14635
15022
  u.searchParams.set("color", config.theme);
15023
+ if (config.language) u.searchParams.set("language", config.language);
14636
15024
  if (config.locale) u.searchParams.set("locale", config.locale);
14637
15025
  return u.toString();
14638
15026
  } catch {
14639
15027
  const params = [`color=${config.theme}`];
15028
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14640
15029
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14641
15030
  return `${base}?${params.join("&")}`;
14642
15031
  }
@@ -14648,10 +15037,12 @@ class ReferralWidget extends BaseWidget {
14648
15037
  try {
14649
15038
  const u = new URL(base);
14650
15039
  u.searchParams.set("color", config.theme);
15040
+ if (config.language) u.searchParams.set("language", config.language);
14651
15041
  if (config.locale) u.searchParams.set("locale", config.locale);
14652
15042
  return u.toString();
14653
15043
  } catch {
14654
15044
  const params = [`color=${config.theme}`];
15045
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14655
15046
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14656
15047
  return `${base}?${params.join("&")}`;
14657
15048
  }
@@ -14664,17 +15055,19 @@ class CustomWidget extends BaseWidget {
14664
15055
  const u = new URL(base);
14665
15056
  u.searchParams.set("auth", "postmessage");
14666
15057
  if (config.themeExplicit) u.searchParams.set("color", config.theme);
15058
+ if (config.language) u.searchParams.set("language", config.language);
14667
15059
  if (config.locale) u.searchParams.set("locale", config.locale);
14668
15060
  return u.toString();
14669
15061
  } catch {
14670
15062
  const params = ["auth=postmessage"];
14671
15063
  if (config.themeExplicit) params.push(`color=${config.theme}`);
15064
+ if (config.language) params.push(`language=${encodeURIComponent(config.language)}`);
14672
15065
  if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
14673
15066
  return params.length > 0 ? `${base}?${params.join("&")}` : base;
14674
15067
  }
14675
15068
  }
14676
15069
  }
14677
- console.log(`[rai-widget] v${"1.8.1"}`);
15070
+ console.log(`[rai-widget] v${"1.8.3"}`);
14678
15071
  class StoreWidgetCompat extends StoreWidget {
14679
15072
  }
14680
15073
  const WIDGET_REGISTRY = [
@@ -14738,7 +15131,7 @@ function exposePublicApi() {
14738
15131
  })();
14739
15132
  const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
14740
15133
  window.ReturningAIWidget = {
14741
- version: "1.8.1",
15134
+ version: "1.8.3",
14742
15135
  reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
14743
15136
  logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
14744
15137
  isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,