@iqauth/sdk 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -31,10 +31,13 @@ __export(react_exports, {
31
31
  UserButton: () => UserButton,
32
32
  UserProfile: () => UserProfile,
33
33
  __version__: () => __version__,
34
+ isSilentSsoEligible: () => isSilentSsoEligible,
35
+ sanitizeBrandCss: () => sanitizeBrandCss,
34
36
  useAuth: () => useAuth,
35
37
  useAuthFetch: () => useAuthFetch,
36
38
  useIQAuthSignInContext: () => useIQAuthSignInContext,
37
39
  useOrganization: () => useOrganization,
40
+ useResolvedSdkBranding: () => useResolvedSdkBranding,
38
41
  useSession: () => useSession,
39
42
  useUser: () => useUser
40
43
  });
@@ -911,6 +914,12 @@ function brandStyle(branding) {
911
914
  if (branding.backgroundColor) s["--brand-bg"] = branding.backgroundColor;
912
915
  if (branding.surfaceColor) s["--brand-surface"] = branding.surfaceColor;
913
916
  if (branding.textColor) s["--brand-text"] = branding.textColor;
917
+ if (branding.borderRadius != null && branding.borderRadius !== "") {
918
+ const n = typeof branding.borderRadius === "number" ? `${branding.borderRadius}px` : String(branding.borderRadius);
919
+ s["--brand-radius"] = n;
920
+ }
921
+ if (branding.fontFamilyBody) s["--brand-font-body"] = branding.fontFamilyBody;
922
+ if (branding.fontFamilyHeading) s["--brand-font-heading"] = branding.fontFamilyHeading;
914
923
  return s;
915
924
  }
916
925
  async function jsonFetch(url, init) {
@@ -935,7 +944,7 @@ function useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo) {
935
944
  let cancelled = false;
936
945
  setLoading(true);
937
946
  const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/public/apps/${encodeURIComponent(appKey)}/sign-in-context?return_to=${encodeURIComponent(returnTo)}`;
938
- fetch(url).then((r) => r.json()).then((payload) => {
947
+ fetch(url, { credentials: "include" }).then((r) => r.json()).then((payload) => {
939
948
  if (cancelled) return;
940
949
  if (payload?.success === false) throw new Error(payload?.error?.message || "Failed to load sign-in context");
941
950
  setCtx(payload.data);
@@ -953,6 +962,7 @@ function useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo) {
953
962
  var SHELL_CSS = `
954
963
  .iqauth-sdk-shell {
955
964
  min-height: 100vh;
965
+ width: 100%;
956
966
  display: grid;
957
967
  grid-template-columns: 1fr;
958
968
  background: var(--brand-bg, #f7f7f6);
@@ -961,20 +971,31 @@ var SHELL_CSS = `
961
971
  .iqauth-sdk-hero { display: none; }
962
972
  .iqauth-sdk-pane {
963
973
  display: flex; flex-direction: column; align-items: center; justify-content: center;
964
- padding: 40px 16px; min-height: 100vh;
974
+ padding: 48px 24px; min-height: 100vh;
965
975
  }
966
976
  .iqauth-sdk-card {
967
- width: 100%; max-width: 420px;
977
+ width: 100%; max-width: 460px;
968
978
  background: var(--brand-surface, #ffffff);
969
979
  border: 1px solid rgba(15,23,42,0.08);
970
- border-radius: 14px;
971
- box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 8px 24px rgba(15,23,42,0.04);
980
+ border-radius: var(--brand-radius, 16px);
981
+ box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 12px 32px rgba(15,23,42,0.06);
972
982
  overflow: hidden;
973
983
  }
974
- .iqauth-sdk-card-header { padding: 28px 28px 0; }
975
- .iqauth-sdk-card-header h1 { font-size: 22px; font-weight: 600; margin: 0; line-height: 1.2; }
984
+ .iqauth-sdk-shell, .iqauth-sdk-shell input, .iqauth-sdk-shell button { font-family: var(--brand-font-body, inherit); }
985
+ .iqauth-sdk-shell h1, .iqauth-sdk-shell h2, .iqauth-sdk-shell h3 { font-family: var(--brand-font-heading, var(--brand-font-body, inherit)); }
986
+ .iqauth-sdk-shell[data-layout="centered_card"] { grid-template-columns: 1fr; }
987
+ .iqauth-sdk-shell[data-layout="centered_card"] .iqauth-sdk-hero { display: none; }
988
+ .iqauth-sdk-shell[data-layout="full_bleed"] { background-size: cover; background-position: center; background-repeat: no-repeat; }
989
+ .iqauth-sdk-shell[data-layout="full_bleed"] .iqauth-sdk-hero { display: none; }
990
+ .iqauth-sdk-shell[data-layout="full_bleed"] .iqauth-sdk-pane { background: rgba(15,23,42,0.30); }
991
+ .iqauth-sdk-shell[data-social-style="outline"] .iqauth-sdk-google-btn { background: transparent; border-color: var(--brand-primary, rgba(15,23,42,0.18)); color: var(--brand-text, inherit); }
992
+ .iqauth-sdk-shell[data-social-style="ghost"] .iqauth-sdk-google-btn { background: transparent; border-color: transparent; color: var(--brand-text, inherit); }
993
+ .iqauth-sdk-shell[data-social-style="solid"] .iqauth-sdk-google-btn { background: var(--brand-primary, #3b82f6); border-color: transparent; color: #fff; }
994
+ .iqauth-sdk-shell[data-social-style="solid"] .iqauth-sdk-google-btn:hover { background: var(--brand-primary, #3b82f6); opacity: 0.92; }
995
+ .iqauth-sdk-card-header { padding: 32px 36px 0; }
996
+ .iqauth-sdk-card-header h1 { font-size: 24px; font-weight: 600; margin: 0; line-height: 1.2; letter-spacing: -0.01em; }
976
997
  .iqauth-sdk-card-header p { margin: 8px 0 0; font-size: 14px; color: rgba(15,23,42,0.65); line-height: 1.5; }
977
- .iqauth-sdk-card-body { padding: 28px 28px 24px; display: flex; flex-direction: column; gap: 18px; }
998
+ .iqauth-sdk-card-body { padding: 32px 36px 28px; display: flex; flex-direction: column; gap: 18px; }
978
999
  .iqauth-sdk-mobile-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
979
1000
  .iqauth-sdk-mobile-brand img { height: 36px; width: auto; }
980
1001
  .iqauth-sdk-mobile-brand span { font-size: 16px; font-weight: 600; }
@@ -995,11 +1016,11 @@ var SHELL_CSS = `
995
1016
  .iqauth-sdk-google-btn:hover { background: #f8fafc; border-color: rgba(15,23,42,0.28); }
996
1017
  .iqauth-sdk-google-btn[disabled] { opacity: 0.6; cursor: not-allowed; }
997
1018
 
998
- @media (min-width: 900px) {
999
- .iqauth-sdk-shell { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
1019
+ @media (min-width: 768px) {
1020
+ .iqauth-sdk-shell:not([data-layout="centered_card"]):not([data-layout="full_bleed"]) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
1000
1021
  .iqauth-sdk-hero {
1001
1022
  display: flex; flex-direction: column; justify-content: space-between;
1002
- padding: 48px 56px; color: #ffffff;
1023
+ padding: clamp(32px, 4vw, 56px); color: #ffffff;
1003
1024
  background: linear-gradient(135deg, var(--brand-primary, #3b82f6) 0%, var(--brand-accent, #6366f1) 100%);
1004
1025
  background-size: cover; background-position: center;
1005
1026
  position: relative; overflow: hidden; min-height: 100vh;
@@ -1008,15 +1029,113 @@ var SHELL_CSS = `
1008
1029
  background-image: var(--iqauth-sdk-hero-image), linear-gradient(135deg, var(--brand-primary, #3b82f6), var(--brand-accent, #6366f1));
1009
1030
  background-blend-mode: multiply;
1010
1031
  }
1011
- .iqauth-sdk-hero-brand img { height: 44px; width: auto; filter: brightness(0) invert(1); opacity: 0.96; }
1012
- .iqauth-sdk-hero-brand .iqauth-sdk-hero-name { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
1013
- .iqauth-sdk-hero-content h2 { font-size: 34px; font-weight: 600; line-height: 1.15; margin: 0 0 14px; letter-spacing: -0.015em; }
1014
- .iqauth-sdk-hero-content p { font-size: 15px; line-height: 1.6; opacity: 0.92; margin: 0; max-width: 460px; white-space: pre-wrap; }
1032
+ .iqauth-sdk-hero-brand img { height: 40px; width: auto; filter: brightness(0) invert(1); opacity: 0.96; }
1033
+ .iqauth-sdk-hero-brand .iqauth-sdk-hero-name { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
1034
+ .iqauth-sdk-hero-content { max-width: 520px; }
1035
+ .iqauth-sdk-hero-content h2 { font-size: clamp(24px, 2.4vw, 34px); font-weight: 600; line-height: 1.2; margin: 0 0 14px; letter-spacing: -0.015em; word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; }
1036
+ .iqauth-sdk-hero-content p { font-size: 15px; line-height: 1.6; opacity: 0.92; margin: 0; white-space: pre-wrap; }
1015
1037
  .iqauth-sdk-hero-foot { font-size: 12px; opacity: 0.7; }
1016
1038
  .iqauth-sdk-mobile-brand { display: none; }
1017
1039
  }
1040
+ @media (min-width: 1280px) {
1041
+ .iqauth-sdk-shell:not([data-layout="centered_card"]):not([data-layout="full_bleed"]) { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
1042
+ }
1018
1043
  `;
1019
1044
  var sdkShellStylesInjected = false;
1045
+ var SDK_CSS_MAX_LEN = 50 * 1024;
1046
+ var SDK_CSS_FORBIDDEN = [
1047
+ /<\/?\s*style[^>]*>/gi,
1048
+ /<\/?\s*script[^>]*>/gi,
1049
+ /<!--[\s\S]*?-->/g,
1050
+ /@import\s+[^;]*;?/gi,
1051
+ /expression\s*\(/gi,
1052
+ /behavior\s*:/gi,
1053
+ /-moz-binding\s*:/gi,
1054
+ /javascript\s*:/gi,
1055
+ /vbscript\s*:/gi
1056
+ ];
1057
+ var SDK_URL_DATA_RE = /url\s*\(\s*(['"]?)\s*data\s*:[^)]*\)/gi;
1058
+ function sanitizeBrandCss(input) {
1059
+ if (!input) return "";
1060
+ let out = String(input);
1061
+ if (out.length > SDK_CSS_MAX_LEN) out = out.slice(0, SDK_CSS_MAX_LEN);
1062
+ out = out.replace(/</g, "");
1063
+ for (const re of SDK_CSS_FORBIDDEN) out = out.replace(re, "");
1064
+ out = out.replace(SDK_URL_DATA_RE, "url()");
1065
+ return out;
1066
+ }
1067
+ function SdkBrandLogo({ branding, alt, fallback }) {
1068
+ const light = branding?.logoLightUrl || branding?.logoUrl || null;
1069
+ const dark = branding?.logoDarkUrl || null;
1070
+ if (!light && !dark) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback });
1071
+ const fallbackSrc = light || dark;
1072
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("picture", { "data-iqauth-sdk-logo": "", children: [
1073
+ dark ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("source", { srcSet: dark, media: "(prefers-color-scheme: dark)" }) : null,
1074
+ light ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("source", { srcSet: light, media: "(prefers-color-scheme: light)" }) : null,
1075
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: fallbackSrc, alt })
1076
+ ] });
1077
+ }
1078
+ var sdkBrandingCache = /* @__PURE__ */ new Map();
1079
+ var SDK_BRANDING_TTL_MS = 6e4;
1080
+ function flattenBrandingPayload(data) {
1081
+ const e = data && data.effective || {};
1082
+ const meta = data && data.meta || {};
1083
+ return {
1084
+ brandName: e.brandName ?? data?.brandName ?? null,
1085
+ logoUrl: e.logoLightUrl ?? data?.logoUrl ?? null,
1086
+ logoLightUrl: e.logoLightUrl ?? data?.logoLightUrl ?? null,
1087
+ logoDarkUrl: e.logoDarkUrl ?? data?.logoDarkUrl ?? null,
1088
+ faviconUrl: e.faviconUrl ?? data?.faviconUrl ?? null,
1089
+ primaryColor: e.primaryColor ?? data?.primaryColor ?? null,
1090
+ accentColor: e.accentColor ?? data?.accentColor ?? null,
1091
+ backgroundColor: e.backgroundColor ?? data?.backgroundColor ?? null,
1092
+ surfaceColor: e.surfaceColor ?? data?.surfaceColor ?? null,
1093
+ textColor: e.textColor ?? data?.textColor ?? null,
1094
+ fontFamilyBody: e.fontFamilyBody ?? data?.fontFamilyBody ?? null,
1095
+ fontFamilyHeading: e.fontFamilyHeading ?? data?.fontFamilyHeading ?? null,
1096
+ customFontUrl: e.customFontUrl ?? data?.customFontUrl ?? null,
1097
+ borderRadius: e.borderRadius ?? data?.borderRadius ?? null,
1098
+ backgroundImageUrl: e.backgroundImageUrl ?? data?.backgroundImageUrl ?? null,
1099
+ customCss: e.customCss ?? data?.customCss ?? null,
1100
+ loginLayout: e.loginLayout ?? data?.loginLayout ?? null,
1101
+ socialButtonStyle: e.socialButtonStyle ?? data?.socialButtonStyle ?? null,
1102
+ footerText: e.footerText ?? data?.footerText ?? null,
1103
+ brandingRev: meta.brandingRev ?? data?.brandingRev ?? null
1104
+ };
1105
+ }
1106
+ function useResolvedSdkBranding(iqAuthBaseUrl, appId) {
1107
+ const ctx = (0, import_react.useContext)(IQAuthContext);
1108
+ const resolvedAppId = appId ?? ctx?.manager?.appKey ?? null;
1109
+ const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/public/branding${resolvedAppId ? `?appId=${encodeURIComponent(resolvedAppId)}` : ""}`;
1110
+ const cached = sdkBrandingCache.get(url);
1111
+ const fresh = cached && Date.now() - cached.ts < SDK_BRANDING_TTL_MS ? cached.data : null;
1112
+ const [b, setB] = (0, import_react.useState)(fresh);
1113
+ (0, import_react.useEffect)(() => {
1114
+ let cancelled = false;
1115
+ const entry = sdkBrandingCache.get(url);
1116
+ const headers = {};
1117
+ if (entry?.rev) headers["If-None-Match"] = `W/"brand-${entry.rev}"`;
1118
+ if (entry) setB(entry.data);
1119
+ fetch(url, { credentials: "include", headers }).then(async (r) => {
1120
+ if (cancelled) return;
1121
+ if (r.status === 304 && entry) {
1122
+ sdkBrandingCache.set(url, { ...entry, ts: Date.now() });
1123
+ return;
1124
+ }
1125
+ if (!r.ok) return;
1126
+ const p = await r.json().catch(() => null);
1127
+ if (!p?.data) return;
1128
+ const flat = flattenBrandingPayload(p.data);
1129
+ sdkBrandingCache.set(url, { ts: Date.now(), rev: flat.brandingRev || "", data: flat });
1130
+ setB(flat);
1131
+ }).catch(() => {
1132
+ });
1133
+ return () => {
1134
+ cancelled = true;
1135
+ };
1136
+ }, [url]);
1137
+ return b;
1138
+ }
1020
1139
  function ensureSdkShellStyles() {
1021
1140
  if (typeof document === "undefined" || sdkShellStylesInjected) return;
1022
1141
  const tag = document.createElement("style");
@@ -1062,35 +1181,61 @@ function Shell({
1062
1181
  const brandVars = brandStyle(branding);
1063
1182
  const brandName = branding?.brandName || "IQAuth";
1064
1183
  const heroImage = branding?.heroImageUrl || null;
1184
+ const layout = (branding?.loginLayout || "split_screen").toString();
1185
+ const bgImage = branding?.backgroundImageUrl || null;
1186
+ const fontUrl = branding?.customFontUrl || null;
1187
+ const socialStyle = (branding?.socialButtonStyle || "").toString();
1065
1188
  const heroStyle = heroImage ? { ["--iqauth-sdk-hero-image"]: `url("${heroImage.replace(/"/g, '\\"')}")` } : {};
1189
+ const shellStyle = {
1190
+ ...brandVars,
1191
+ ...layout === "full_bleed" && bgImage ? { backgroundImage: `linear-gradient(rgba(15,23,42,0.35), rgba(15,23,42,0.45)), url("${bgImage.replace(/"/g, '\\"')}")` } : {}
1192
+ };
1066
1193
  const supportLink = branding?.supportUrl ? branding.supportUrl : branding?.supportEmail ? `mailto:${branding.supportEmail}` : null;
1067
1194
  const hasFooterLinks = !!(branding?.termsUrl || branding?.privacyUrl || supportLink);
1068
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `iqauth-sdk-shell${className ? ` ${className}` : ""}`, style: brandVars, "data-iqauth-shell": "", children: [
1069
- branding?.customCss ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { "data-iqauth-sdk-custom": true, children: branding.customCss }) : null,
1070
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", { className: "iqauth-sdk-hero", "data-bg-image": heroImage ? "true" : "false", style: heroStyle, "aria-hidden": "true", children: [
1071
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-hero-brand", style: { display: "flex", alignItems: "center", gap: 12 }, children: branding?.logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: branding.logoUrl, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "iqauth-sdk-hero-name", children: brandName }) }),
1072
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-hero-content", children: [
1073
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: branding?.tagline || `Welcome to ${brandName}` }),
1074
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: branding?.loginSideCopy || branding?.loginSubheadline || `Sign in to continue to your ${brandName} workspace.` })
1075
- ] }),
1076
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-hero-foot", children: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${brandName}` })
1077
- ] }),
1078
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-pane", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", { style: { width: "100%", maxWidth: 420 }, children: [
1079
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-mobile-brand", children: branding?.logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: branding.logoUrl, alt: `${brandName} logo` }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: brandName }) }),
1080
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "iqauth-sdk-card", children: [
1081
- title || subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-card-header", children: [
1082
- title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: title }) : null,
1083
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: subtitle }) : null
1084
- ] }) : null,
1085
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-card-body", children })
1086
- ] }),
1087
- hasFooterLinks ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { className: "iqauth-sdk-footer", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-footer-links", children: [
1088
- branding?.termsUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: branding.termsUrl, target: "_blank", rel: "noreferrer noopener", children: "Terms" }) : null,
1089
- branding?.privacyUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: branding.privacyUrl, target: "_blank", rel: "noreferrer noopener", children: "Privacy" }) : null,
1090
- supportLink ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: supportLink, target: "_blank", rel: "noreferrer noopener", children: "Support" }) : null
1091
- ] }) }) : null
1092
- ] }) })
1093
- ] });
1195
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1196
+ "div",
1197
+ {
1198
+ className: `iqauth-sdk-shell${className ? ` ${className}` : ""}`,
1199
+ "data-layout": layout,
1200
+ "data-social-style": socialStyle || void 0,
1201
+ style: shellStyle,
1202
+ "data-iqauth-shell": "",
1203
+ "data-branding-rev": branding?.brandingRev || "",
1204
+ children: [
1205
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { "data-brand": true, children: [
1206
+ fontUrl ? `@font-face{font-family:"${(branding?.fontFamilyBody || "Brand").replace(/"/g, "")}";src:url("${fontUrl.replace(/"/g, '\\"')}");font-display:swap;}` : "",
1207
+ sanitizeBrandCss(branding?.customCss)
1208
+ ].filter(Boolean).join("\n") }),
1209
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", { className: "iqauth-sdk-hero", "data-bg-image": heroImage ? "true" : "false", style: heroStyle, "aria-hidden": "true", children: [
1210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-hero-brand", style: { display: "flex", alignItems: "center", gap: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SdkBrandLogo, { branding, alt: "", fallback: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "iqauth-sdk-hero-name", children: brandName }) }) }),
1211
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-hero-content", children: [
1212
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: branding?.tagline || `Welcome to ${brandName}` }),
1213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: branding?.loginSideCopy || branding?.loginSubheadline || `Sign in to continue to your ${brandName} workspace.` })
1214
+ ] }),
1215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-hero-foot", children: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${brandName}` })
1216
+ ] }),
1217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-pane", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", { style: { width: "100%", maxWidth: 420 }, children: [
1218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-mobile-brand", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SdkBrandLogo, { branding, alt: `${brandName} logo`, fallback: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: brandName }) }) }),
1219
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "iqauth-sdk-card", children: [
1220
+ title || subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-card-header", children: [
1221
+ title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: title }) : null,
1222
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: subtitle }) : null
1223
+ ] }) : null,
1224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "iqauth-sdk-card-body", children })
1225
+ ] }),
1226
+ hasFooterLinks || branding?.footerText ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", { className: "iqauth-sdk-footer", children: [
1227
+ branding?.footerText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-testid": "text-brand-footer-sdk", style: { fontSize: 12, opacity: 0.75 }, children: branding.footerText }) : null,
1228
+ hasFooterLinks ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "iqauth-sdk-footer-links", children: [
1229
+ branding?.termsUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: branding.termsUrl, target: "_blank", rel: "noreferrer noopener", children: "Terms" }) : null,
1230
+ branding?.privacyUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: branding.privacyUrl, target: "_blank", rel: "noreferrer noopener", children: "Privacy" }) : null,
1231
+ supportLink ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: supportLink, target: "_blank", rel: "noreferrer noopener", children: "Support" }) : null
1232
+ ] }) : null
1233
+ ] }) : null
1234
+ ] }) })
1235
+ ]
1236
+ },
1237
+ branding?.brandingRev || void 0
1238
+ );
1094
1239
  }
1095
1240
  function Field({ label, children }) {
1096
1241
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 13 }, children: [
@@ -1160,7 +1305,15 @@ function ErrorBanner({ message }) {
1160
1305
  color: "#b91c1c"
1161
1306
  }, children: message });
1162
1307
  }
1163
- function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
1308
+ function isSilentSsoEligible(ctx, effectivePrompt) {
1309
+ if (!ctx) return false;
1310
+ if (effectivePrompt === "login") return false;
1311
+ if (!ctx.session) return false;
1312
+ if (!ctx.app.defaultClientId) return false;
1313
+ if (!ctx.returnAllowed) return false;
1314
+ return true;
1315
+ }
1316
+ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className, prompt }) {
1164
1317
  const { ctx, loading, error } = useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo);
1165
1318
  const [email, setEmail] = (0, import_react.useState)("");
1166
1319
  const [password, setPassword] = (0, import_react.useState)("");
@@ -1169,6 +1322,18 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
1169
1322
  const [mfa, setMfa] = (0, import_react.useState)(null);
1170
1323
  const [tenantSel, setTenantSel] = (0, import_react.useState)(null);
1171
1324
  const [oauthExchanging, setOauthExchanging] = (0, import_react.useState)(false);
1325
+ const [silent, setSilent] = (0, import_react.useState)("idle");
1326
+ const [forcePrompt, setForcePrompt] = (0, import_react.useState)(false);
1327
+ const effectivePrompt = (0, import_react.useMemo)(() => {
1328
+ if (prompt === "login" || forcePrompt) return "login";
1329
+ if (typeof window !== "undefined") {
1330
+ try {
1331
+ if (new URLSearchParams(window.location.search).get("prompt") === "login") return "login";
1332
+ } catch {
1333
+ }
1334
+ }
1335
+ return void 0;
1336
+ }, [prompt, forcePrompt]);
1172
1337
  const oidcPayload = () => ({
1173
1338
  client_id: ctx?.app.defaultClientId,
1174
1339
  redirect_uri: returnTo,
@@ -1258,6 +1423,58 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
1258
1423
  const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/google?redirect_uri=${encodeURIComponent(bridgeUrl)}&client_id=${encodeURIComponent(ctx.app.defaultClientId)}`;
1259
1424
  window.location.href = url;
1260
1425
  };
1426
+ (0, import_react.useEffect)(() => {
1427
+ if (loading || error || !ctx) return;
1428
+ if (effectivePrompt === "login") {
1429
+ setSilent("skipped");
1430
+ return;
1431
+ }
1432
+ if (silent !== "idle") return;
1433
+ if (!ctx.session || !ctx.app.defaultClientId || !ctx.returnAllowed) {
1434
+ setSilent("skipped");
1435
+ return;
1436
+ }
1437
+ setSilent("trying");
1438
+ (async () => {
1439
+ try {
1440
+ const r = await fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/oidc/sso-resume`, {
1441
+ method: "POST",
1442
+ headers: { "Content-Type": "application/json" },
1443
+ credentials: "include",
1444
+ body: JSON.stringify(oidcPayload())
1445
+ });
1446
+ const payload = await r.json().catch(() => ({}));
1447
+ if (payload?.type === "redirect" && payload.redirectUrl) {
1448
+ (onRedirect || ((u) => {
1449
+ window.location.replace(u);
1450
+ }))(payload.redirectUrl);
1451
+ return;
1452
+ }
1453
+ if (payload?.type === "tenant_selection") {
1454
+ setTenantSel({ token: payload.tenantSelectionToken, tenants: payload.tenants || [] });
1455
+ setSilent("failed");
1456
+ return;
1457
+ }
1458
+ setSilent("failed");
1459
+ } catch {
1460
+ setSilent("failed");
1461
+ }
1462
+ })();
1463
+ }, [loading, error, ctx, effectivePrompt]);
1464
+ const switchAccount = (e) => {
1465
+ if (e) e.preventDefault();
1466
+ setForcePrompt(true);
1467
+ setSilent("skipped");
1468
+ setTenantSel(null);
1469
+ if (typeof window !== "undefined") {
1470
+ try {
1471
+ const u = new URL(window.location.href);
1472
+ u.searchParams.set("prompt", "login");
1473
+ window.history.replaceState({}, "", u.toString());
1474
+ } catch {
1475
+ }
1476
+ }
1477
+ };
1261
1478
  (0, import_react.useEffect)(() => {
1262
1479
  if (!ctx?.app.defaultClientId) return;
1263
1480
  const params = new URLSearchParams(window.location.search);
@@ -1295,6 +1512,13 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
1295
1512
  if (loading || oauthExchanging) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shell, { branding: ctx?.branding || null, className, title: oauthExchanging ? "Completing sign-in\u2026" : "Loading\u2026", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: oauthExchanging ? "Completing sign-in\u2026" : "Loading\u2026" }) });
1296
1513
  if (error || !ctx) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shell, { branding: null, className, title: "Application unavailable", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorBanner, { message: error || "Failed to load app context" }) });
1297
1514
  if (!ctx.returnAllowed) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shell, { branding: ctx.branding, className, title: "Invalid redirect", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorBanner, { message: `returnTo "${returnTo}" is not in this app's allowed origins.` }) });
1515
+ const silentEligible = isSilentSsoEligible(ctx, effectivePrompt);
1516
+ if (silentEligible && silent !== "failed") {
1517
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Shell, { branding: ctx.branding, className, title: "Signing you in\u2026", subtitle: ctx.session ? `Welcome back, ${ctx.session.name || ctx.session.email}.` : void 0, children: [
1518
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { "data-testid": "text-silent-resume", style: { fontSize: 14, opacity: 0.8 }, children: "Resuming your session." }),
1519
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "#", onClick: switchAccount, "data-testid": "link-switch-account", style: { fontSize: 13 }, children: "Not you? Use a different account" })
1520
+ ] });
1521
+ }
1298
1522
  const cardTitle = ctx.branding?.loginHeadline || `Sign in to ${ctx.app.name}`;
1299
1523
  const cardSubtitle = ctx.branding?.loginSubheadline || void 0;
1300
1524
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Shell, { branding: ctx.branding, className, title: cardTitle, subtitle: cardSubtitle, children: [
@@ -1344,7 +1568,11 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
1344
1568
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { label: "Password", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { style: inputStyle(), type: "password", autoComplete: "current-password", required: true, value: password, onChange: (e) => setPassword(e.target.value) }) }),
1345
1569
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PrimaryButton, { type: "submit", disabled: submitting || !email || !password, children: submitting ? "Signing in\u2026" : "Sign in" })
1346
1570
  ] })
1347
- ] })
1571
+ ] }),
1572
+ (silent === "failed" || effectivePrompt === "login" && ctx.session) && !mfa ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { marginTop: 12, fontSize: 13, opacity: 0.75 }, children: [
1573
+ silent === "failed" && ctx.session ? "Couldn't resume your session. " : null,
1574
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "#", onClick: switchAccount, "data-testid": "link-switch-account", children: "Use a different account" })
1575
+ ] }) : null
1348
1576
  ] });
1349
1577
  }
1350
1578
  function SignUp({ iqAuthBaseUrl, appKey, returnTo, onSuccess, className }) {
@@ -1395,6 +1623,9 @@ function initialsOf(name, email) {
1395
1623
  function UserButton({ iqAuthBaseUrl, accountUrl, onSignOut, className }) {
1396
1624
  const [user, setUser] = (0, import_react.useState)(null);
1397
1625
  const [open, setOpen] = (0, import_react.useState)(false);
1626
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
1627
+ const accent = branding?.accentColor || "#6366f1";
1628
+ const primary = branding?.primaryColor || "#0f172a";
1398
1629
  (0, import_react.useEffect)(() => {
1399
1630
  let cancelled = false;
1400
1631
  fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/me`, { credentials: "include" }).then((r) => r.json()).then((p) => {
@@ -1415,59 +1646,69 @@ function UserButton({ iqAuthBaseUrl, accountUrl, onSignOut, className }) {
1415
1646
  };
1416
1647
  if (!user) return null;
1417
1648
  const target = accountUrl || `${iqAuthBaseUrl.replace(/\/$/, "")}/account`;
1418
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: { position: "relative", display: "inline-block" }, children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1420
- "button",
1421
- {
1422
- type: "button",
1423
- "aria-haspopup": "menu",
1424
- "aria-expanded": open,
1425
- onClick: () => setOpen((o) => !o),
1426
- style: {
1427
- width: 32,
1428
- height: 32,
1429
- borderRadius: "50%",
1430
- background: "var(--brand-accent, #6366f1)",
1431
- color: "#fff",
1432
- border: "none",
1433
- cursor: "pointer",
1434
- fontSize: 12,
1435
- fontWeight: 600
1436
- },
1437
- children: user.picture ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: user.picture, alt: user.name, style: { width: "100%", height: "100%", borderRadius: "50%" } }) : initialsOf(user.name, user.email)
1438
- }
1439
- ),
1440
- open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "menu", style: {
1441
- position: "absolute",
1442
- right: 0,
1443
- top: 40,
1444
- minWidth: 200,
1445
- background: "#fff",
1446
- border: "1px solid rgba(15,23,42,0.12)",
1447
- borderRadius: 8,
1448
- boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
1449
- padding: 8,
1450
- zIndex: 100
1451
- }, children: [
1452
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 10px", fontSize: 12, opacity: 0.7, borderBottom: "1px solid rgba(15,23,42,0.06)" }, children: [
1453
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 500, color: "#0f172a" }, children: user.name }),
1454
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: user.email })
1455
- ] }),
1456
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: target, role: "menuitem", style: { display: "block", padding: "8px 10px", fontSize: 13, color: "#0f172a", textDecoration: "none" }, children: "Account" }),
1457
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1458
- "button",
1459
- {
1460
- role: "menuitem",
1461
- type: "button",
1462
- onClick: signOut2,
1463
- style: { display: "block", width: "100%", textAlign: "left", padding: "8px 10px", fontSize: 13, background: "transparent", border: "none", cursor: "pointer", color: "#b91c1c" },
1464
- children: "Sign out"
1465
- }
1466
- )
1467
- ] }) : null
1468
- ] });
1649
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1650
+ "div",
1651
+ {
1652
+ className,
1653
+ style: { position: "relative", display: "inline-block", ...brandStyle(branding) },
1654
+ "data-iqauth-sdk-userbutton": "",
1655
+ "data-branding-rev": branding?.brandingRev || "",
1656
+ children: [
1657
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1658
+ "button",
1659
+ {
1660
+ type: "button",
1661
+ "aria-haspopup": "menu",
1662
+ "aria-expanded": open,
1663
+ onClick: () => setOpen((o) => !o),
1664
+ style: {
1665
+ width: 32,
1666
+ height: 32,
1667
+ borderRadius: "50%",
1668
+ background: accent,
1669
+ color: "#fff",
1670
+ border: "none",
1671
+ cursor: "pointer",
1672
+ fontSize: 12,
1673
+ fontWeight: 600
1674
+ },
1675
+ children: user.picture ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: user.picture, alt: user.name, style: { width: "100%", height: "100%", borderRadius: "50%" } }) : initialsOf(user.name, user.email)
1676
+ }
1677
+ ),
1678
+ open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "menu", style: {
1679
+ position: "absolute",
1680
+ right: 0,
1681
+ top: 40,
1682
+ minWidth: 200,
1683
+ background: "#fff",
1684
+ border: "1px solid rgba(15,23,42,0.12)",
1685
+ borderRadius: 8,
1686
+ boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
1687
+ padding: 8,
1688
+ zIndex: 100
1689
+ }, children: [
1690
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "8px 10px", fontSize: 12, opacity: 0.7, borderBottom: "1px solid rgba(15,23,42,0.06)" }, children: [
1691
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 500, color: "#0f172a" }, children: user.name }),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: user.email })
1693
+ ] }),
1694
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: target, role: "menuitem", style: { display: "block", padding: "8px 10px", fontSize: 13, color: primary, textDecoration: "none" }, children: "Account" }),
1695
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1696
+ "button",
1697
+ {
1698
+ role: "menuitem",
1699
+ type: "button",
1700
+ onClick: signOut2,
1701
+ style: { display: "block", width: "100%", textAlign: "left", padding: "8px 10px", fontSize: 13, background: "transparent", border: "none", cursor: "pointer", color: "#b91c1c" },
1702
+ children: "Sign out"
1703
+ }
1704
+ )
1705
+ ] }) : null
1706
+ ]
1707
+ }
1708
+ );
1469
1709
  }
1470
1710
  function UserProfile({ iqAuthBaseUrl, className }) {
1711
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
1471
1712
  const [user, setUser] = (0, import_react.useState)(null);
1472
1713
  const [oldPassword, setOldPassword] = (0, import_react.useState)("");
1473
1714
  const [newPassword, setNewPassword] = (0, import_react.useState)("");
@@ -1501,8 +1742,8 @@ function UserProfile({ iqAuthBaseUrl, className }) {
1501
1742
  await fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/sessions/${sessionId}`, { method: "DELETE", credentials: "include" });
1502
1743
  setSessions((prev) => prev.filter((s) => s.id !== sessionId));
1503
1744
  };
1504
- if (!user) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shell, { branding: null, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Loading account\u2026" }) });
1505
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Shell, { branding: null, className, children: [
1745
+ if (!user) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Shell, { branding, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Loading account\u2026" }) });
1746
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Shell, { branding, className, children: [
1506
1747
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { style: { fontSize: 20, fontWeight: 600, margin: "0 0 12px" }, children: "Your account" }),
1507
1748
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-labelledby": "iqauth-profile", style: { marginBottom: 20 }, children: [
1508
1749
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { id: "iqauth-profile", style: { fontSize: 14, fontWeight: 600 }, children: "Profile" }),
@@ -1537,6 +1778,8 @@ function UserProfile({ iqAuthBaseUrl, className }) {
1537
1778
  ] });
1538
1779
  }
1539
1780
  function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }) {
1781
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
1782
+ const accent = branding?.accentColor || "#6366f1";
1540
1783
  const [memberships, setMemberships] = (0, import_react.useState)([]);
1541
1784
  const [activeTenantId, setActiveTenantId] = (0, import_react.useState)(null);
1542
1785
  const [open, setOpen] = (0, import_react.useState)(false);
@@ -1562,55 +1805,64 @@ function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }) {
1562
1805
  }
1563
1806
  };
1564
1807
  const active = memberships.find((m) => m.tenantId === activeTenantId);
1565
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: { position: "relative", display: "inline-block" }, children: [
1566
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1567
- "button",
1568
- {
1569
- type: "button",
1570
- "aria-haspopup": "menu",
1571
- "aria-expanded": open,
1572
- onClick: () => setOpen((o) => !o),
1573
- style: { background: "transparent", border: "1px solid rgba(15,23,42,0.15)", padding: "6px 12px", borderRadius: 6, cursor: "pointer", fontSize: 13 },
1574
- children: active?.tenantName || active?.tenantSlug || "Select organization"
1575
- }
1576
- ),
1577
- open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "menu", style: {
1578
- position: "absolute",
1579
- left: 0,
1580
- top: 36,
1581
- minWidth: 220,
1582
- background: "#fff",
1583
- border: "1px solid rgba(15,23,42,0.12)",
1584
- borderRadius: 8,
1585
- boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
1586
- padding: 8,
1587
- zIndex: 100
1588
- }, children: memberships.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 13, opacity: 0.6, padding: "4px 6px" }, children: "No memberships" }) : memberships.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1589
- "button",
1590
- {
1591
- role: "menuitem",
1592
- type: "button",
1593
- onClick: () => switchTo(m.tenantId),
1594
- style: {
1595
- display: "block",
1596
- width: "100%",
1597
- textAlign: "left",
1598
- padding: "8px 10px",
1599
- background: m.tenantId === activeTenantId ? "rgba(99,102,241,0.08)" : "transparent",
1600
- border: "none",
1601
- borderRadius: 4,
1602
- cursor: "pointer",
1603
- fontSize: 13,
1604
- color: "#0f172a"
1605
- },
1606
- children: [
1607
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 500 }, children: m.tenantName || m.tenantSlug || m.tenantId }),
1608
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 11, opacity: 0.6 }, children: m.roles.join(", ") })
1609
- ]
1610
- },
1611
- m.tenantId
1612
- )) }) : null
1613
- ] });
1808
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1809
+ "div",
1810
+ {
1811
+ className,
1812
+ style: { position: "relative", display: "inline-block", ...brandStyle(branding) },
1813
+ "data-iqauth-sdk-orgswitcher": "",
1814
+ "data-branding-rev": branding?.brandingRev || "",
1815
+ children: [
1816
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1817
+ "button",
1818
+ {
1819
+ type: "button",
1820
+ "aria-haspopup": "menu",
1821
+ "aria-expanded": open,
1822
+ onClick: () => setOpen((o) => !o),
1823
+ style: { background: "transparent", border: `1px solid ${accent}55`, color: branding?.primaryColor || "#0f172a", padding: "6px 12px", borderRadius: 6, cursor: "pointer", fontSize: 13 },
1824
+ children: active?.tenantName || active?.tenantSlug || "Select organization"
1825
+ }
1826
+ ),
1827
+ open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "menu", style: {
1828
+ position: "absolute",
1829
+ left: 0,
1830
+ top: 36,
1831
+ minWidth: 220,
1832
+ background: "#fff",
1833
+ border: "1px solid rgba(15,23,42,0.12)",
1834
+ borderRadius: 8,
1835
+ boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
1836
+ padding: 8,
1837
+ zIndex: 100
1838
+ }, children: memberships.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 13, opacity: 0.6, padding: "4px 6px" }, children: "No memberships" }) : memberships.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1839
+ "button",
1840
+ {
1841
+ role: "menuitem",
1842
+ type: "button",
1843
+ onClick: () => switchTo(m.tenantId),
1844
+ style: {
1845
+ display: "block",
1846
+ width: "100%",
1847
+ textAlign: "left",
1848
+ padding: "8px 10px",
1849
+ background: m.tenantId === activeTenantId ? `${accent}14` : "transparent",
1850
+ border: "none",
1851
+ borderRadius: 4,
1852
+ cursor: "pointer",
1853
+ fontSize: 13,
1854
+ color: "#0f172a"
1855
+ },
1856
+ children: [
1857
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 500 }, children: m.tenantName || m.tenantSlug || m.tenantId }),
1858
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 11, opacity: 0.6 }, children: m.roles.join(", ") })
1859
+ ]
1860
+ },
1861
+ m.tenantId
1862
+ )) }) : null
1863
+ ]
1864
+ }
1865
+ );
1614
1866
  }
1615
1867
  var __version__ = "phase-bc-1.0.0";
1616
1868
  // Annotate the CommonJS export names for ESM import in node:
@@ -1626,10 +1878,13 @@ var __version__ = "phase-bc-1.0.0";
1626
1878
  UserButton,
1627
1879
  UserProfile,
1628
1880
  __version__,
1881
+ isSilentSsoEligible,
1882
+ sanitizeBrandCss,
1629
1883
  useAuth,
1630
1884
  useAuthFetch,
1631
1885
  useIQAuthSignInContext,
1632
1886
  useOrganization,
1887
+ useResolvedSdkBranding,
1633
1888
  useSession,
1634
1889
  useUser
1635
1890
  });