@iqauth/sdk 2.0.4 → 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.
Files changed (43) hide show
  1. package/dist/browser-session.d.mts +1 -1
  2. package/dist/browser-session.d.ts +1 -1
  3. package/dist/browser-session.js +4 -1
  4. package/dist/browser-session.mjs +1 -1
  5. package/dist/{chunk-JQWYIIIS.mjs → chunk-MDUHPQMM.mjs} +4 -1
  6. package/dist/{chunk-73R6BEGO.mjs → chunk-ZESHDJDU.mjs} +1 -1
  7. package/dist/{client-CggvJmmm.d.ts → client-DXbHb2ul.d.ts} +1 -1
  8. package/dist/{client-C1DXfB8Z.d.mts → client-Dv4v92Mj.d.mts} +1 -1
  9. package/dist/{express-BKAXB5Nl.d.ts → express-B4o3P8vK.d.ts} +1 -1
  10. package/dist/{express-CpfyYTmw.d.mts → express-BZmF1llh.d.mts} +1 -1
  11. package/dist/express.d.mts +3 -3
  12. package/dist/express.d.ts +3 -3
  13. package/dist/express.js +4 -1
  14. package/dist/express.mjs +2 -2
  15. package/dist/fastify.d.mts +6 -0
  16. package/dist/fastify.d.ts +6 -0
  17. package/dist/fastify.js +21 -3
  18. package/dist/fastify.mjs +18 -3
  19. package/dist/hono.js +4 -1
  20. package/dist/hono.mjs +1 -1
  21. package/dist/index.d.mts +2 -2
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.js +4 -1
  24. package/dist/index.mjs +2 -2
  25. package/dist/mobile.d.mts +1 -1
  26. package/dist/mobile.d.ts +1 -1
  27. package/dist/mobile.js +4 -1
  28. package/dist/mobile.mjs +1 -1
  29. package/dist/next.js +4 -1
  30. package/dist/next.mjs +1 -1
  31. package/dist/react.d.mts +64 -2
  32. package/dist/react.d.ts +64 -2
  33. package/dist/react.js +501 -132
  34. package/dist/react.mjs +498 -132
  35. package/dist/server.d.mts +2 -2
  36. package/dist/server.d.ts +2 -2
  37. package/dist/server.js +4 -1
  38. package/dist/server.mjs +2 -2
  39. package/dist/service.d.mts +1 -1
  40. package/dist/service.d.ts +1 -1
  41. package/dist/service.js +4 -1
  42. package/dist/service.mjs +1 -1
  43. package/package.json +1 -1
package/dist/react.mjs CHANGED
@@ -212,6 +212,12 @@ function brandStyle(branding) {
212
212
  if (branding.backgroundColor) s["--brand-bg"] = branding.backgroundColor;
213
213
  if (branding.surfaceColor) s["--brand-surface"] = branding.surfaceColor;
214
214
  if (branding.textColor) s["--brand-text"] = branding.textColor;
215
+ if (branding.borderRadius != null && branding.borderRadius !== "") {
216
+ const n = typeof branding.borderRadius === "number" ? `${branding.borderRadius}px` : String(branding.borderRadius);
217
+ s["--brand-radius"] = n;
218
+ }
219
+ if (branding.fontFamilyBody) s["--brand-font-body"] = branding.fontFamilyBody;
220
+ if (branding.fontFamilyHeading) s["--brand-font-heading"] = branding.fontFamilyHeading;
215
221
  return s;
216
222
  }
217
223
  async function jsonFetch(url, init) {
@@ -236,7 +242,7 @@ function useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo) {
236
242
  let cancelled = false;
237
243
  setLoading(true);
238
244
  const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/public/apps/${encodeURIComponent(appKey)}/sign-in-context?return_to=${encodeURIComponent(returnTo)}`;
239
- fetch(url).then((r) => r.json()).then((payload) => {
245
+ fetch(url, { credentials: "include" }).then((r) => r.json()).then((payload) => {
240
246
  if (cancelled) return;
241
247
  if (payload?.success === false) throw new Error(payload?.error?.message || "Failed to load sign-in context");
242
248
  setCtx(payload.data);
@@ -251,28 +257,282 @@ function useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo) {
251
257
  }, [iqAuthBaseUrl, appKey, returnTo]);
252
258
  return { ctx, loading, error };
253
259
  }
260
+ var SHELL_CSS = `
261
+ .iqauth-sdk-shell {
262
+ min-height: 100vh;
263
+ width: 100%;
264
+ display: grid;
265
+ grid-template-columns: 1fr;
266
+ background: var(--brand-bg, #f7f7f6);
267
+ color: var(--brand-text, #0f172a);
268
+ }
269
+ .iqauth-sdk-hero { display: none; }
270
+ .iqauth-sdk-pane {
271
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
272
+ padding: 48px 24px; min-height: 100vh;
273
+ }
274
+ .iqauth-sdk-card {
275
+ width: 100%; max-width: 460px;
276
+ background: var(--brand-surface, #ffffff);
277
+ border: 1px solid rgba(15,23,42,0.08);
278
+ border-radius: var(--brand-radius, 16px);
279
+ box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 12px 32px rgba(15,23,42,0.06);
280
+ overflow: hidden;
281
+ }
282
+ .iqauth-sdk-shell, .iqauth-sdk-shell input, .iqauth-sdk-shell button { font-family: var(--brand-font-body, inherit); }
283
+ .iqauth-sdk-shell h1, .iqauth-sdk-shell h2, .iqauth-sdk-shell h3 { font-family: var(--brand-font-heading, var(--brand-font-body, inherit)); }
284
+ .iqauth-sdk-shell[data-layout="centered_card"] { grid-template-columns: 1fr; }
285
+ .iqauth-sdk-shell[data-layout="centered_card"] .iqauth-sdk-hero { display: none; }
286
+ .iqauth-sdk-shell[data-layout="full_bleed"] { background-size: cover; background-position: center; background-repeat: no-repeat; }
287
+ .iqauth-sdk-shell[data-layout="full_bleed"] .iqauth-sdk-hero { display: none; }
288
+ .iqauth-sdk-shell[data-layout="full_bleed"] .iqauth-sdk-pane { background: rgba(15,23,42,0.30); }
289
+ .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); }
290
+ .iqauth-sdk-shell[data-social-style="ghost"] .iqauth-sdk-google-btn { background: transparent; border-color: transparent; color: var(--brand-text, inherit); }
291
+ .iqauth-sdk-shell[data-social-style="solid"] .iqauth-sdk-google-btn { background: var(--brand-primary, #3b82f6); border-color: transparent; color: #fff; }
292
+ .iqauth-sdk-shell[data-social-style="solid"] .iqauth-sdk-google-btn:hover { background: var(--brand-primary, #3b82f6); opacity: 0.92; }
293
+ .iqauth-sdk-card-header { padding: 32px 36px 0; }
294
+ .iqauth-sdk-card-header h1 { font-size: 24px; font-weight: 600; margin: 0; line-height: 1.2; letter-spacing: -0.01em; }
295
+ .iqauth-sdk-card-header p { margin: 8px 0 0; font-size: 14px; color: rgba(15,23,42,0.65); line-height: 1.5; }
296
+ .iqauth-sdk-card-body { padding: 32px 36px 28px; display: flex; flex-direction: column; gap: 18px; }
297
+ .iqauth-sdk-mobile-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
298
+ .iqauth-sdk-mobile-brand img { height: 36px; width: auto; }
299
+ .iqauth-sdk-mobile-brand span { font-size: 16px; font-weight: 600; }
300
+ .iqauth-sdk-footer { margin-top: 20px; text-align: center; font-size: 13px; color: rgba(15,23,42,0.55); display: flex; flex-direction: column; gap: 8px; align-items: center; }
301
+ .iqauth-sdk-footer-links { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }
302
+ .iqauth-sdk-footer-links a { color: inherit; opacity: 0.75; text-decoration: none; }
303
+ .iqauth-sdk-footer-links a:hover { opacity: 1; text-decoration: underline; }
304
+ .iqauth-sdk-divider { display: flex; align-items: center; gap: 10px; font-size: 12px; color: rgba(15,23,42,0.45); text-transform: uppercase; letter-spacing: 0.08em; }
305
+ .iqauth-sdk-divider::before, .iqauth-sdk-divider::after { content: ""; flex: 1; height: 1px; background: rgba(15,23,42,0.1); }
306
+ .iqauth-sdk-google-btn {
307
+ display: inline-flex; align-items: center; justify-content: center; gap: 10px;
308
+ width: 100%; padding: 10px 16px; border-radius: 8px;
309
+ background: #fff; color: #0f172a;
310
+ border: 1px solid rgba(15,23,42,0.18);
311
+ font-size: 14px; font-weight: 500; cursor: pointer;
312
+ transition: background 120ms ease, border-color 120ms ease;
313
+ }
314
+ .iqauth-sdk-google-btn:hover { background: #f8fafc; border-color: rgba(15,23,42,0.28); }
315
+ .iqauth-sdk-google-btn[disabled] { opacity: 0.6; cursor: not-allowed; }
316
+
317
+ @media (min-width: 768px) {
318
+ .iqauth-sdk-shell:not([data-layout="centered_card"]):not([data-layout="full_bleed"]) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
319
+ .iqauth-sdk-hero {
320
+ display: flex; flex-direction: column; justify-content: space-between;
321
+ padding: clamp(32px, 4vw, 56px); color: #ffffff;
322
+ background: linear-gradient(135deg, var(--brand-primary, #3b82f6) 0%, var(--brand-accent, #6366f1) 100%);
323
+ background-size: cover; background-position: center;
324
+ position: relative; overflow: hidden; min-height: 100vh;
325
+ }
326
+ .iqauth-sdk-hero[data-bg-image="true"] {
327
+ background-image: var(--iqauth-sdk-hero-image), linear-gradient(135deg, var(--brand-primary, #3b82f6), var(--brand-accent, #6366f1));
328
+ background-blend-mode: multiply;
329
+ }
330
+ .iqauth-sdk-hero-brand img { height: 40px; width: auto; filter: brightness(0) invert(1); opacity: 0.96; }
331
+ .iqauth-sdk-hero-brand .iqauth-sdk-hero-name { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
332
+ .iqauth-sdk-hero-content { max-width: 520px; }
333
+ .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; }
334
+ .iqauth-sdk-hero-content p { font-size: 15px; line-height: 1.6; opacity: 0.92; margin: 0; white-space: pre-wrap; }
335
+ .iqauth-sdk-hero-foot { font-size: 12px; opacity: 0.7; }
336
+ .iqauth-sdk-mobile-brand { display: none; }
337
+ }
338
+ @media (min-width: 1280px) {
339
+ .iqauth-sdk-shell:not([data-layout="centered_card"]):not([data-layout="full_bleed"]) { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
340
+ }
341
+ `;
342
+ var sdkShellStylesInjected = false;
343
+ var SDK_CSS_MAX_LEN = 50 * 1024;
344
+ var SDK_CSS_FORBIDDEN = [
345
+ /<\/?\s*style[^>]*>/gi,
346
+ /<\/?\s*script[^>]*>/gi,
347
+ /<!--[\s\S]*?-->/g,
348
+ /@import\s+[^;]*;?/gi,
349
+ /expression\s*\(/gi,
350
+ /behavior\s*:/gi,
351
+ /-moz-binding\s*:/gi,
352
+ /javascript\s*:/gi,
353
+ /vbscript\s*:/gi
354
+ ];
355
+ var SDK_URL_DATA_RE = /url\s*\(\s*(['"]?)\s*data\s*:[^)]*\)/gi;
356
+ function sanitizeBrandCss(input) {
357
+ if (!input) return "";
358
+ let out = String(input);
359
+ if (out.length > SDK_CSS_MAX_LEN) out = out.slice(0, SDK_CSS_MAX_LEN);
360
+ out = out.replace(/</g, "");
361
+ for (const re of SDK_CSS_FORBIDDEN) out = out.replace(re, "");
362
+ out = out.replace(SDK_URL_DATA_RE, "url()");
363
+ return out;
364
+ }
365
+ function SdkBrandLogo({ branding, alt, fallback }) {
366
+ const light = branding?.logoLightUrl || branding?.logoUrl || null;
367
+ const dark = branding?.logoDarkUrl || null;
368
+ if (!light && !dark) return /* @__PURE__ */ jsx(Fragment2, { children: fallback });
369
+ const fallbackSrc = light || dark;
370
+ return /* @__PURE__ */ jsxs("picture", { "data-iqauth-sdk-logo": "", children: [
371
+ dark ? /* @__PURE__ */ jsx("source", { srcSet: dark, media: "(prefers-color-scheme: dark)" }) : null,
372
+ light ? /* @__PURE__ */ jsx("source", { srcSet: light, media: "(prefers-color-scheme: light)" }) : null,
373
+ /* @__PURE__ */ jsx("img", { src: fallbackSrc, alt })
374
+ ] });
375
+ }
376
+ var sdkBrandingCache = /* @__PURE__ */ new Map();
377
+ var SDK_BRANDING_TTL_MS = 6e4;
378
+ function flattenBrandingPayload(data) {
379
+ const e = data && data.effective || {};
380
+ const meta = data && data.meta || {};
381
+ return {
382
+ brandName: e.brandName ?? data?.brandName ?? null,
383
+ logoUrl: e.logoLightUrl ?? data?.logoUrl ?? null,
384
+ logoLightUrl: e.logoLightUrl ?? data?.logoLightUrl ?? null,
385
+ logoDarkUrl: e.logoDarkUrl ?? data?.logoDarkUrl ?? null,
386
+ faviconUrl: e.faviconUrl ?? data?.faviconUrl ?? null,
387
+ primaryColor: e.primaryColor ?? data?.primaryColor ?? null,
388
+ accentColor: e.accentColor ?? data?.accentColor ?? null,
389
+ backgroundColor: e.backgroundColor ?? data?.backgroundColor ?? null,
390
+ surfaceColor: e.surfaceColor ?? data?.surfaceColor ?? null,
391
+ textColor: e.textColor ?? data?.textColor ?? null,
392
+ fontFamilyBody: e.fontFamilyBody ?? data?.fontFamilyBody ?? null,
393
+ fontFamilyHeading: e.fontFamilyHeading ?? data?.fontFamilyHeading ?? null,
394
+ customFontUrl: e.customFontUrl ?? data?.customFontUrl ?? null,
395
+ borderRadius: e.borderRadius ?? data?.borderRadius ?? null,
396
+ backgroundImageUrl: e.backgroundImageUrl ?? data?.backgroundImageUrl ?? null,
397
+ customCss: e.customCss ?? data?.customCss ?? null,
398
+ loginLayout: e.loginLayout ?? data?.loginLayout ?? null,
399
+ socialButtonStyle: e.socialButtonStyle ?? data?.socialButtonStyle ?? null,
400
+ footerText: e.footerText ?? data?.footerText ?? null,
401
+ brandingRev: meta.brandingRev ?? data?.brandingRev ?? null
402
+ };
403
+ }
404
+ function useResolvedSdkBranding(iqAuthBaseUrl, appId) {
405
+ const ctx = useContext(IQAuthContext);
406
+ const resolvedAppId = appId ?? ctx?.manager?.appKey ?? null;
407
+ const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/public/branding${resolvedAppId ? `?appId=${encodeURIComponent(resolvedAppId)}` : ""}`;
408
+ const cached = sdkBrandingCache.get(url);
409
+ const fresh = cached && Date.now() - cached.ts < SDK_BRANDING_TTL_MS ? cached.data : null;
410
+ const [b, setB] = useState(fresh);
411
+ useEffect(() => {
412
+ let cancelled = false;
413
+ const entry = sdkBrandingCache.get(url);
414
+ const headers = {};
415
+ if (entry?.rev) headers["If-None-Match"] = `W/"brand-${entry.rev}"`;
416
+ if (entry) setB(entry.data);
417
+ fetch(url, { credentials: "include", headers }).then(async (r) => {
418
+ if (cancelled) return;
419
+ if (r.status === 304 && entry) {
420
+ sdkBrandingCache.set(url, { ...entry, ts: Date.now() });
421
+ return;
422
+ }
423
+ if (!r.ok) return;
424
+ const p = await r.json().catch(() => null);
425
+ if (!p?.data) return;
426
+ const flat = flattenBrandingPayload(p.data);
427
+ sdkBrandingCache.set(url, { ts: Date.now(), rev: flat.brandingRev || "", data: flat });
428
+ setB(flat);
429
+ }).catch(() => {
430
+ });
431
+ return () => {
432
+ cancelled = true;
433
+ };
434
+ }, [url]);
435
+ return b;
436
+ }
437
+ function ensureSdkShellStyles() {
438
+ if (typeof document === "undefined" || sdkShellStylesInjected) return;
439
+ const tag = document.createElement("style");
440
+ tag.setAttribute("data-iqauth-sdk-shell", "");
441
+ tag.textContent = SHELL_CSS;
442
+ document.head.appendChild(tag);
443
+ sdkShellStylesInjected = true;
444
+ }
445
+ function useDocumentBranding(branding, fallbackTitle) {
446
+ useEffect(() => {
447
+ if (typeof document === "undefined") return;
448
+ const prevTitle = document.title;
449
+ const brandName = branding?.brandName || "IQAuth";
450
+ document.title = `${fallbackTitle} \xB7 ${brandName}`;
451
+ let linkEl = null;
452
+ let prevHref = null;
453
+ if (branding?.faviconUrl) {
454
+ linkEl = document.querySelector("link[rel='icon']");
455
+ if (!linkEl) {
456
+ linkEl = document.createElement("link");
457
+ linkEl.rel = "icon";
458
+ document.head.appendChild(linkEl);
459
+ } else {
460
+ prevHref = linkEl.href;
461
+ }
462
+ linkEl.href = branding.faviconUrl;
463
+ }
464
+ return () => {
465
+ document.title = prevTitle;
466
+ if (linkEl && prevHref !== null) linkEl.href = prevHref;
467
+ };
468
+ }, [branding?.brandName, branding?.faviconUrl, fallbackTitle]);
469
+ }
254
470
  function Shell({
255
471
  branding,
256
472
  className,
257
- children
473
+ children,
474
+ title,
475
+ subtitle
258
476
  }) {
477
+ ensureSdkShellStyles();
478
+ useDocumentBranding(branding, title || "Sign in");
479
+ const brandVars = brandStyle(branding);
480
+ const brandName = branding?.brandName || "IQAuth";
481
+ const heroImage = branding?.heroImageUrl || null;
482
+ const layout = (branding?.loginLayout || "split_screen").toString();
483
+ const bgImage = branding?.backgroundImageUrl || null;
484
+ const fontUrl = branding?.customFontUrl || null;
485
+ const socialStyle = (branding?.socialButtonStyle || "").toString();
486
+ const heroStyle = heroImage ? { ["--iqauth-sdk-hero-image"]: `url("${heroImage.replace(/"/g, '\\"')}")` } : {};
487
+ const shellStyle = {
488
+ ...brandVars,
489
+ ...layout === "full_bleed" && bgImage ? { backgroundImage: `linear-gradient(rgba(15,23,42,0.35), rgba(15,23,42,0.45)), url("${bgImage.replace(/"/g, '\\"')}")` } : {}
490
+ };
491
+ const supportLink = branding?.supportUrl ? branding.supportUrl : branding?.supportEmail ? `mailto:${branding.supportEmail}` : null;
492
+ const hasFooterLinks = !!(branding?.termsUrl || branding?.privacyUrl || supportLink);
259
493
  return /* @__PURE__ */ jsxs(
260
494
  "div",
261
495
  {
262
- className,
263
- style: {
264
- background: "var(--brand-surface, #ffffff)",
265
- color: "var(--brand-text, #0f172a)",
266
- border: "1px solid rgba(15,23,42,0.08)",
267
- borderRadius: 12,
268
- padding: 24,
269
- ...brandStyle(branding)
270
- },
496
+ className: `iqauth-sdk-shell${className ? ` ${className}` : ""}`,
497
+ "data-layout": layout,
498
+ "data-social-style": socialStyle || void 0,
499
+ style: shellStyle,
500
+ "data-iqauth-shell": "",
501
+ "data-branding-rev": branding?.brandingRev || "",
271
502
  children: [
272
- branding?.logoUrl ? /* @__PURE__ */ jsx("img", { src: branding.logoUrl, alt: branding.brandName || "", style: { height: 28, width: "auto", marginBottom: 16 } }) : null,
273
- children
503
+ /* @__PURE__ */ jsx("style", { "data-brand": true, children: [
504
+ fontUrl ? `@font-face{font-family:"${(branding?.fontFamilyBody || "Brand").replace(/"/g, "")}";src:url("${fontUrl.replace(/"/g, '\\"')}");font-display:swap;}` : "",
505
+ sanitizeBrandCss(branding?.customCss)
506
+ ].filter(Boolean).join("\n") }),
507
+ /* @__PURE__ */ jsxs("aside", { className: "iqauth-sdk-hero", "data-bg-image": heroImage ? "true" : "false", style: heroStyle, "aria-hidden": "true", children: [
508
+ /* @__PURE__ */ jsx("div", { className: "iqauth-sdk-hero-brand", style: { display: "flex", alignItems: "center", gap: 12 }, children: /* @__PURE__ */ jsx(SdkBrandLogo, { branding, alt: "", fallback: /* @__PURE__ */ jsx("span", { className: "iqauth-sdk-hero-name", children: brandName }) }) }),
509
+ /* @__PURE__ */ jsxs("div", { className: "iqauth-sdk-hero-content", children: [
510
+ /* @__PURE__ */ jsx("h2", { children: branding?.tagline || `Welcome to ${brandName}` }),
511
+ /* @__PURE__ */ jsx("p", { children: branding?.loginSideCopy || branding?.loginSubheadline || `Sign in to continue to your ${brandName} workspace.` })
512
+ ] }),
513
+ /* @__PURE__ */ jsx("div", { className: "iqauth-sdk-hero-foot", children: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${brandName}` })
514
+ ] }),
515
+ /* @__PURE__ */ jsx("div", { className: "iqauth-sdk-pane", children: /* @__PURE__ */ jsxs("main", { style: { width: "100%", maxWidth: 420 }, children: [
516
+ /* @__PURE__ */ jsx("div", { className: "iqauth-sdk-mobile-brand", children: /* @__PURE__ */ jsx(SdkBrandLogo, { branding, alt: `${brandName} logo`, fallback: /* @__PURE__ */ jsx("span", { children: brandName }) }) }),
517
+ /* @__PURE__ */ jsxs("section", { className: "iqauth-sdk-card", children: [
518
+ title || subtitle ? /* @__PURE__ */ jsxs("div", { className: "iqauth-sdk-card-header", children: [
519
+ title ? /* @__PURE__ */ jsx("h1", { children: title }) : null,
520
+ subtitle ? /* @__PURE__ */ jsx("p", { children: subtitle }) : null
521
+ ] }) : null,
522
+ /* @__PURE__ */ jsx("div", { className: "iqauth-sdk-card-body", children })
523
+ ] }),
524
+ hasFooterLinks || branding?.footerText ? /* @__PURE__ */ jsxs("footer", { className: "iqauth-sdk-footer", children: [
525
+ branding?.footerText ? /* @__PURE__ */ jsx("div", { "data-testid": "text-brand-footer-sdk", style: { fontSize: 12, opacity: 0.75 }, children: branding.footerText }) : null,
526
+ hasFooterLinks ? /* @__PURE__ */ jsxs("div", { className: "iqauth-sdk-footer-links", children: [
527
+ branding?.termsUrl ? /* @__PURE__ */ jsx("a", { href: branding.termsUrl, target: "_blank", rel: "noreferrer noopener", children: "Terms" }) : null,
528
+ branding?.privacyUrl ? /* @__PURE__ */ jsx("a", { href: branding.privacyUrl, target: "_blank", rel: "noreferrer noopener", children: "Privacy" }) : null,
529
+ supportLink ? /* @__PURE__ */ jsx("a", { href: supportLink, target: "_blank", rel: "noreferrer noopener", children: "Support" }) : null
530
+ ] }) : null
531
+ ] }) : null
532
+ ] }) })
274
533
  ]
275
- }
534
+ },
535
+ branding?.brandingRev || void 0
276
536
  );
277
537
  }
278
538
  function Field({ label, children }) {
@@ -343,7 +603,15 @@ function ErrorBanner({ message }) {
343
603
  color: "#b91c1c"
344
604
  }, children: message });
345
605
  }
346
- function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
606
+ function isSilentSsoEligible(ctx, effectivePrompt) {
607
+ if (!ctx) return false;
608
+ if (effectivePrompt === "login") return false;
609
+ if (!ctx.session) return false;
610
+ if (!ctx.app.defaultClientId) return false;
611
+ if (!ctx.returnAllowed) return false;
612
+ return true;
613
+ }
614
+ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className, prompt }) {
347
615
  const { ctx, loading, error } = useIQAuthSignInContext(iqAuthBaseUrl, appKey, returnTo);
348
616
  const [email, setEmail] = useState("");
349
617
  const [password, setPassword] = useState("");
@@ -352,6 +620,18 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
352
620
  const [mfa, setMfa] = useState(null);
353
621
  const [tenantSel, setTenantSel] = useState(null);
354
622
  const [oauthExchanging, setOauthExchanging] = useState(false);
623
+ const [silent, setSilent] = useState("idle");
624
+ const [forcePrompt, setForcePrompt] = useState(false);
625
+ const effectivePrompt = useMemo(() => {
626
+ if (prompt === "login" || forcePrompt) return "login";
627
+ if (typeof window !== "undefined") {
628
+ try {
629
+ if (new URLSearchParams(window.location.search).get("prompt") === "login") return "login";
630
+ } catch {
631
+ }
632
+ }
633
+ return void 0;
634
+ }, [prompt, forcePrompt]);
355
635
  const oidcPayload = () => ({
356
636
  client_id: ctx?.app.defaultClientId,
357
637
  redirect_uri: returnTo,
@@ -441,6 +721,58 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
441
721
  const url = `${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/google?redirect_uri=${encodeURIComponent(bridgeUrl)}&client_id=${encodeURIComponent(ctx.app.defaultClientId)}`;
442
722
  window.location.href = url;
443
723
  };
724
+ useEffect(() => {
725
+ if (loading || error || !ctx) return;
726
+ if (effectivePrompt === "login") {
727
+ setSilent("skipped");
728
+ return;
729
+ }
730
+ if (silent !== "idle") return;
731
+ if (!ctx.session || !ctx.app.defaultClientId || !ctx.returnAllowed) {
732
+ setSilent("skipped");
733
+ return;
734
+ }
735
+ setSilent("trying");
736
+ (async () => {
737
+ try {
738
+ const r = await fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/oidc/sso-resume`, {
739
+ method: "POST",
740
+ headers: { "Content-Type": "application/json" },
741
+ credentials: "include",
742
+ body: JSON.stringify(oidcPayload())
743
+ });
744
+ const payload = await r.json().catch(() => ({}));
745
+ if (payload?.type === "redirect" && payload.redirectUrl) {
746
+ (onRedirect || ((u) => {
747
+ window.location.replace(u);
748
+ }))(payload.redirectUrl);
749
+ return;
750
+ }
751
+ if (payload?.type === "tenant_selection") {
752
+ setTenantSel({ token: payload.tenantSelectionToken, tenants: payload.tenants || [] });
753
+ setSilent("failed");
754
+ return;
755
+ }
756
+ setSilent("failed");
757
+ } catch {
758
+ setSilent("failed");
759
+ }
760
+ })();
761
+ }, [loading, error, ctx, effectivePrompt]);
762
+ const switchAccount = (e) => {
763
+ if (e) e.preventDefault();
764
+ setForcePrompt(true);
765
+ setSilent("skipped");
766
+ setTenantSel(null);
767
+ if (typeof window !== "undefined") {
768
+ try {
769
+ const u = new URL(window.location.href);
770
+ u.searchParams.set("prompt", "login");
771
+ window.history.replaceState({}, "", u.toString());
772
+ } catch {
773
+ }
774
+ }
775
+ };
444
776
  useEffect(() => {
445
777
  if (!ctx?.app.defaultClientId) return;
446
778
  const params = new URLSearchParams(window.location.search);
@@ -475,13 +807,20 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
475
807
  setOauthExchanging(false);
476
808
  })();
477
809
  }, [ctx?.app.defaultClientId]);
478
- if (loading || oauthExchanging) return /* @__PURE__ */ jsx(Shell, { branding: ctx?.branding || null, className, children: /* @__PURE__ */ jsx("p", { children: oauthExchanging ? "Completing sign-in\u2026" : "Loading\u2026" }) });
479
- if (error || !ctx) return /* @__PURE__ */ jsx(Shell, { branding: null, className, children: /* @__PURE__ */ jsx(ErrorBanner, { message: error || "Failed to load app context" }) });
480
- if (!ctx.returnAllowed) return /* @__PURE__ */ jsx(Shell, { branding: ctx.branding, className, children: /* @__PURE__ */ jsx(ErrorBanner, { message: `returnTo "${returnTo}" is not in this app's allowed origins.` }) });
481
- return /* @__PURE__ */ jsxs(Shell, { branding: ctx.branding, className, children: [
482
- /* @__PURE__ */ jsx("h2", { style: { fontSize: 20, fontWeight: 600, margin: "0 0 12px" }, children: ctx.branding?.loginHeadline || `Sign in to ${ctx.app.name}` }),
483
- ctx.branding?.loginSubheadline ? /* @__PURE__ */ jsx("p", { style: { marginBottom: 16, fontSize: 13, opacity: 0.7 }, children: ctx.branding.loginSubheadline }) : null,
484
- formError ? /* @__PURE__ */ jsx("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ jsx(ErrorBanner, { message: formError }) }) : null,
810
+ if (loading || oauthExchanging) return /* @__PURE__ */ jsx(Shell, { branding: ctx?.branding || null, className, title: oauthExchanging ? "Completing sign-in\u2026" : "Loading\u2026", children: /* @__PURE__ */ jsx("p", { children: oauthExchanging ? "Completing sign-in\u2026" : "Loading\u2026" }) });
811
+ if (error || !ctx) return /* @__PURE__ */ jsx(Shell, { branding: null, className, title: "Application unavailable", children: /* @__PURE__ */ jsx(ErrorBanner, { message: error || "Failed to load app context" }) });
812
+ if (!ctx.returnAllowed) return /* @__PURE__ */ jsx(Shell, { branding: ctx.branding, className, title: "Invalid redirect", children: /* @__PURE__ */ jsx(ErrorBanner, { message: `returnTo "${returnTo}" is not in this app's allowed origins.` }) });
813
+ const silentEligible = isSilentSsoEligible(ctx, effectivePrompt);
814
+ if (silentEligible && silent !== "failed") {
815
+ return /* @__PURE__ */ 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: [
816
+ /* @__PURE__ */ jsx("p", { "data-testid": "text-silent-resume", style: { fontSize: 14, opacity: 0.8 }, children: "Resuming your session." }),
817
+ /* @__PURE__ */ jsx("a", { href: "#", onClick: switchAccount, "data-testid": "link-switch-account", style: { fontSize: 13 }, children: "Not you? Use a different account" })
818
+ ] });
819
+ }
820
+ const cardTitle = ctx.branding?.loginHeadline || `Sign in to ${ctx.app.name}`;
821
+ const cardSubtitle = ctx.branding?.loginSubheadline || void 0;
822
+ return /* @__PURE__ */ jsxs(Shell, { branding: ctx.branding, className, title: cardTitle, subtitle: cardSubtitle, children: [
823
+ formError ? /* @__PURE__ */ jsx(ErrorBanner, { message: formError }) : null,
485
824
  tenantSel ? /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": "Choose tenant", style: { display: "flex", flexDirection: "column", gap: 8 }, children: tenantSel.tenants.map((t) => /* @__PURE__ */ jsxs(
486
825
  "button",
487
826
  {
@@ -511,27 +850,27 @@ function SignIn({ iqAuthBaseUrl, appKey, returnTo, onRedirect, className }) {
511
850
  /* @__PURE__ */ jsx(GhostButton, { type: "button", onClick: () => setMfa({ ...mfa, backup: !mfa.backup, code: "" }), children: mfa.backup ? "Use verification code" : "Use backup code" })
512
851
  ] }) : /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
513
852
  ctx.providers?.google ? /* @__PURE__ */ jsxs(Fragment2, { children: [
514
- /* @__PURE__ */ jsxs(GhostButton, { type: "button", onClick: startGoogleLogin, disabled: submitting, "aria-label": "Continue with Google", style: { display: "flex", alignItems: "center", justifyContent: "center", gap: 10 }, children: [
853
+ /* @__PURE__ */ jsxs("button", { type: "button", className: "iqauth-sdk-google-btn", onClick: startGoogleLogin, disabled: submitting, "aria-label": ctx.branding?.googleButtonLabel || "Continue with Google", children: [
515
854
  /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
516
855
  /* @__PURE__ */ jsx("path", { fill: "#4285F4", d: "M17.64 9.2c0-.64-.06-1.25-.17-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.71v2.26h2.92a8.78 8.78 0 0 0 2.68-6.61z" }),
517
856
  /* @__PURE__ */ jsx("path", { fill: "#34A853", d: "M9 18c2.43 0 4.47-.81 5.96-2.18l-2.92-2.26a5.4 5.4 0 0 1-8.04-2.83H.96v2.33A9 9 0 0 0 9 18z" }),
518
857
  /* @__PURE__ */ jsx("path", { fill: "#FBBC05", d: "M3.96 10.71A5.41 5.41 0 0 1 3.68 9c0-.59.1-1.17.29-1.71V4.96H.96a9 9 0 0 0 0 8.08l3-2.33z" }),
519
858
  /* @__PURE__ */ jsx("path", { fill: "#EA4335", d: "M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.59A9 9 0 0 0 .96 4.96l3 2.33A5.4 5.4 0 0 1 9 3.58z" })
520
859
  ] }),
521
- "Continue with Google"
860
+ ctx.branding?.googleButtonLabel || "Continue with Google"
522
861
  ] }),
523
- /* @__PURE__ */ jsxs("div", { role: "separator", "aria-label": "or", style: { display: "flex", alignItems: "center", gap: 10, fontSize: 12, opacity: 0.6 }, children: [
524
- /* @__PURE__ */ jsx("span", { style: { flex: 1, height: 1, background: "rgba(15,23,42,0.12)" } }),
525
- "OR",
526
- /* @__PURE__ */ jsx("span", { style: { flex: 1, height: 1, background: "rgba(15,23,42,0.12)" } })
527
- ] })
862
+ /* @__PURE__ */ jsx("div", { role: "separator", "aria-label": "or", className: "iqauth-sdk-divider", children: "OR" })
528
863
  ] }) : null,
529
864
  /* @__PURE__ */ jsxs("form", { onSubmit: submitLogin, style: { display: "flex", flexDirection: "column", gap: 12 }, "aria-label": `Sign in to ${ctx.app.name}`, children: [
530
865
  /* @__PURE__ */ jsx(Field, { label: "Email", children: /* @__PURE__ */ jsx("input", { style: inputStyle(), type: "email", autoComplete: "email", required: true, value: email, onChange: (e) => setEmail(e.target.value) }) }),
531
866
  /* @__PURE__ */ jsx(Field, { label: "Password", children: /* @__PURE__ */ jsx("input", { style: inputStyle(), type: "password", autoComplete: "current-password", required: true, value: password, onChange: (e) => setPassword(e.target.value) }) }),
532
867
  /* @__PURE__ */ jsx(PrimaryButton, { type: "submit", disabled: submitting || !email || !password, children: submitting ? "Signing in\u2026" : "Sign in" })
533
868
  ] })
534
- ] })
869
+ ] }),
870
+ (silent === "failed" || effectivePrompt === "login" && ctx.session) && !mfa ? /* @__PURE__ */ jsxs("p", { style: { marginTop: 12, fontSize: 13, opacity: 0.75 }, children: [
871
+ silent === "failed" && ctx.session ? "Couldn't resume your session. " : null,
872
+ /* @__PURE__ */ jsx("a", { href: "#", onClick: switchAccount, "data-testid": "link-switch-account", children: "Use a different account" })
873
+ ] }) : null
535
874
  ] });
536
875
  }
537
876
  function SignUp({ iqAuthBaseUrl, appKey, returnTo, onSuccess, className }) {
@@ -582,6 +921,9 @@ function initialsOf(name, email) {
582
921
  function UserButton({ iqAuthBaseUrl, accountUrl, onSignOut, className }) {
583
922
  const [user, setUser] = useState(null);
584
923
  const [open, setOpen] = useState(false);
924
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
925
+ const accent = branding?.accentColor || "#6366f1";
926
+ const primary = branding?.primaryColor || "#0f172a";
585
927
  useEffect(() => {
586
928
  let cancelled = false;
587
929
  fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/me`, { credentials: "include" }).then((r) => r.json()).then((p) => {
@@ -602,59 +944,69 @@ function UserButton({ iqAuthBaseUrl, accountUrl, onSignOut, className }) {
602
944
  };
603
945
  if (!user) return null;
604
946
  const target = accountUrl || `${iqAuthBaseUrl.replace(/\/$/, "")}/account`;
605
- return /* @__PURE__ */ jsxs("div", { className, style: { position: "relative", display: "inline-block" }, children: [
606
- /* @__PURE__ */ jsx(
607
- "button",
608
- {
609
- type: "button",
610
- "aria-haspopup": "menu",
611
- "aria-expanded": open,
612
- onClick: () => setOpen((o) => !o),
613
- style: {
614
- width: 32,
615
- height: 32,
616
- borderRadius: "50%",
617
- background: "var(--brand-accent, #6366f1)",
618
- color: "#fff",
619
- border: "none",
620
- cursor: "pointer",
621
- fontSize: 12,
622
- fontWeight: 600
623
- },
624
- children: user.picture ? /* @__PURE__ */ jsx("img", { src: user.picture, alt: user.name, style: { width: "100%", height: "100%", borderRadius: "50%" } }) : initialsOf(user.name, user.email)
625
- }
626
- ),
627
- open ? /* @__PURE__ */ jsxs("div", { role: "menu", style: {
628
- position: "absolute",
629
- right: 0,
630
- top: 40,
631
- minWidth: 200,
632
- background: "#fff",
633
- border: "1px solid rgba(15,23,42,0.12)",
634
- borderRadius: 8,
635
- boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
636
- padding: 8,
637
- zIndex: 100
638
- }, children: [
639
- /* @__PURE__ */ jsxs("div", { style: { padding: "8px 10px", fontSize: 12, opacity: 0.7, borderBottom: "1px solid rgba(15,23,42,0.06)" }, children: [
640
- /* @__PURE__ */ jsx("div", { style: { fontWeight: 500, color: "#0f172a" }, children: user.name }),
641
- /* @__PURE__ */ jsx("div", { children: user.email })
642
- ] }),
643
- /* @__PURE__ */ jsx("a", { href: target, role: "menuitem", style: { display: "block", padding: "8px 10px", fontSize: 13, color: "#0f172a", textDecoration: "none" }, children: "Account" }),
644
- /* @__PURE__ */ jsx(
645
- "button",
646
- {
647
- role: "menuitem",
648
- type: "button",
649
- onClick: signOut2,
650
- style: { display: "block", width: "100%", textAlign: "left", padding: "8px 10px", fontSize: 13, background: "transparent", border: "none", cursor: "pointer", color: "#b91c1c" },
651
- children: "Sign out"
652
- }
653
- )
654
- ] }) : null
655
- ] });
947
+ return /* @__PURE__ */ jsxs(
948
+ "div",
949
+ {
950
+ className,
951
+ style: { position: "relative", display: "inline-block", ...brandStyle(branding) },
952
+ "data-iqauth-sdk-userbutton": "",
953
+ "data-branding-rev": branding?.brandingRev || "",
954
+ children: [
955
+ /* @__PURE__ */ jsx(
956
+ "button",
957
+ {
958
+ type: "button",
959
+ "aria-haspopup": "menu",
960
+ "aria-expanded": open,
961
+ onClick: () => setOpen((o) => !o),
962
+ style: {
963
+ width: 32,
964
+ height: 32,
965
+ borderRadius: "50%",
966
+ background: accent,
967
+ color: "#fff",
968
+ border: "none",
969
+ cursor: "pointer",
970
+ fontSize: 12,
971
+ fontWeight: 600
972
+ },
973
+ children: user.picture ? /* @__PURE__ */ jsx("img", { src: user.picture, alt: user.name, style: { width: "100%", height: "100%", borderRadius: "50%" } }) : initialsOf(user.name, user.email)
974
+ }
975
+ ),
976
+ open ? /* @__PURE__ */ jsxs("div", { role: "menu", style: {
977
+ position: "absolute",
978
+ right: 0,
979
+ top: 40,
980
+ minWidth: 200,
981
+ background: "#fff",
982
+ border: "1px solid rgba(15,23,42,0.12)",
983
+ borderRadius: 8,
984
+ boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
985
+ padding: 8,
986
+ zIndex: 100
987
+ }, children: [
988
+ /* @__PURE__ */ jsxs("div", { style: { padding: "8px 10px", fontSize: 12, opacity: 0.7, borderBottom: "1px solid rgba(15,23,42,0.06)" }, children: [
989
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 500, color: "#0f172a" }, children: user.name }),
990
+ /* @__PURE__ */ jsx("div", { children: user.email })
991
+ ] }),
992
+ /* @__PURE__ */ jsx("a", { href: target, role: "menuitem", style: { display: "block", padding: "8px 10px", fontSize: 13, color: primary, textDecoration: "none" }, children: "Account" }),
993
+ /* @__PURE__ */ jsx(
994
+ "button",
995
+ {
996
+ role: "menuitem",
997
+ type: "button",
998
+ onClick: signOut2,
999
+ style: { display: "block", width: "100%", textAlign: "left", padding: "8px 10px", fontSize: 13, background: "transparent", border: "none", cursor: "pointer", color: "#b91c1c" },
1000
+ children: "Sign out"
1001
+ }
1002
+ )
1003
+ ] }) : null
1004
+ ]
1005
+ }
1006
+ );
656
1007
  }
657
1008
  function UserProfile({ iqAuthBaseUrl, className }) {
1009
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
658
1010
  const [user, setUser] = useState(null);
659
1011
  const [oldPassword, setOldPassword] = useState("");
660
1012
  const [newPassword, setNewPassword] = useState("");
@@ -688,8 +1040,8 @@ function UserProfile({ iqAuthBaseUrl, className }) {
688
1040
  await fetch(`${iqAuthBaseUrl.replace(/\/$/, "")}/api/v1/auth/sessions/${sessionId}`, { method: "DELETE", credentials: "include" });
689
1041
  setSessions((prev) => prev.filter((s) => s.id !== sessionId));
690
1042
  };
691
- if (!user) return /* @__PURE__ */ jsx(Shell, { branding: null, className, children: /* @__PURE__ */ jsx("p", { children: "Loading account\u2026" }) });
692
- return /* @__PURE__ */ jsxs(Shell, { branding: null, className, children: [
1043
+ if (!user) return /* @__PURE__ */ jsx(Shell, { branding, className, children: /* @__PURE__ */ jsx("p", { children: "Loading account\u2026" }) });
1044
+ return /* @__PURE__ */ jsxs(Shell, { branding, className, children: [
693
1045
  /* @__PURE__ */ jsx("h2", { style: { fontSize: 20, fontWeight: 600, margin: "0 0 12px" }, children: "Your account" }),
694
1046
  /* @__PURE__ */ jsxs("section", { "aria-labelledby": "iqauth-profile", style: { marginBottom: 20 }, children: [
695
1047
  /* @__PURE__ */ jsx("h3", { id: "iqauth-profile", style: { fontSize: 14, fontWeight: 600 }, children: "Profile" }),
@@ -724,6 +1076,8 @@ function UserProfile({ iqAuthBaseUrl, className }) {
724
1076
  ] });
725
1077
  }
726
1078
  function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }) {
1079
+ const branding = useResolvedSdkBranding(iqAuthBaseUrl);
1080
+ const accent = branding?.accentColor || "#6366f1";
727
1081
  const [memberships, setMemberships] = useState([]);
728
1082
  const [activeTenantId, setActiveTenantId] = useState(null);
729
1083
  const [open, setOpen] = useState(false);
@@ -749,55 +1103,64 @@ function OrganizationSwitcher({ iqAuthBaseUrl, onSwitched, className }) {
749
1103
  }
750
1104
  };
751
1105
  const active = memberships.find((m) => m.tenantId === activeTenantId);
752
- return /* @__PURE__ */ jsxs("div", { className, style: { position: "relative", display: "inline-block" }, children: [
753
- /* @__PURE__ */ jsx(
754
- "button",
755
- {
756
- type: "button",
757
- "aria-haspopup": "menu",
758
- "aria-expanded": open,
759
- onClick: () => setOpen((o) => !o),
760
- style: { background: "transparent", border: "1px solid rgba(15,23,42,0.15)", padding: "6px 12px", borderRadius: 6, cursor: "pointer", fontSize: 13 },
761
- children: active?.tenantName || active?.tenantSlug || "Select organization"
762
- }
763
- ),
764
- open ? /* @__PURE__ */ jsx("div", { role: "menu", style: {
765
- position: "absolute",
766
- left: 0,
767
- top: 36,
768
- minWidth: 220,
769
- background: "#fff",
770
- border: "1px solid rgba(15,23,42,0.12)",
771
- borderRadius: 8,
772
- boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
773
- padding: 8,
774
- zIndex: 100
775
- }, children: memberships.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: 13, opacity: 0.6, padding: "4px 6px" }, children: "No memberships" }) : memberships.map((m) => /* @__PURE__ */ jsxs(
776
- "button",
777
- {
778
- role: "menuitem",
779
- type: "button",
780
- onClick: () => switchTo(m.tenantId),
781
- style: {
782
- display: "block",
783
- width: "100%",
784
- textAlign: "left",
785
- padding: "8px 10px",
786
- background: m.tenantId === activeTenantId ? "rgba(99,102,241,0.08)" : "transparent",
787
- border: "none",
788
- borderRadius: 4,
789
- cursor: "pointer",
790
- fontSize: 13,
791
- color: "#0f172a"
792
- },
793
- children: [
794
- /* @__PURE__ */ jsx("div", { style: { fontWeight: 500 }, children: m.tenantName || m.tenantSlug || m.tenantId }),
795
- /* @__PURE__ */ jsx("div", { style: { fontSize: 11, opacity: 0.6 }, children: m.roles.join(", ") })
796
- ]
797
- },
798
- m.tenantId
799
- )) }) : null
800
- ] });
1106
+ return /* @__PURE__ */ jsxs(
1107
+ "div",
1108
+ {
1109
+ className,
1110
+ style: { position: "relative", display: "inline-block", ...brandStyle(branding) },
1111
+ "data-iqauth-sdk-orgswitcher": "",
1112
+ "data-branding-rev": branding?.brandingRev || "",
1113
+ children: [
1114
+ /* @__PURE__ */ jsx(
1115
+ "button",
1116
+ {
1117
+ type: "button",
1118
+ "aria-haspopup": "menu",
1119
+ "aria-expanded": open,
1120
+ onClick: () => setOpen((o) => !o),
1121
+ style: { background: "transparent", border: `1px solid ${accent}55`, color: branding?.primaryColor || "#0f172a", padding: "6px 12px", borderRadius: 6, cursor: "pointer", fontSize: 13 },
1122
+ children: active?.tenantName || active?.tenantSlug || "Select organization"
1123
+ }
1124
+ ),
1125
+ open ? /* @__PURE__ */ jsx("div", { role: "menu", style: {
1126
+ position: "absolute",
1127
+ left: 0,
1128
+ top: 36,
1129
+ minWidth: 220,
1130
+ background: "#fff",
1131
+ border: "1px solid rgba(15,23,42,0.12)",
1132
+ borderRadius: 8,
1133
+ boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
1134
+ padding: 8,
1135
+ zIndex: 100
1136
+ }, children: memberships.length === 0 ? /* @__PURE__ */ jsx("p", { style: { fontSize: 13, opacity: 0.6, padding: "4px 6px" }, children: "No memberships" }) : memberships.map((m) => /* @__PURE__ */ jsxs(
1137
+ "button",
1138
+ {
1139
+ role: "menuitem",
1140
+ type: "button",
1141
+ onClick: () => switchTo(m.tenantId),
1142
+ style: {
1143
+ display: "block",
1144
+ width: "100%",
1145
+ textAlign: "left",
1146
+ padding: "8px 10px",
1147
+ background: m.tenantId === activeTenantId ? `${accent}14` : "transparent",
1148
+ border: "none",
1149
+ borderRadius: 4,
1150
+ cursor: "pointer",
1151
+ fontSize: 13,
1152
+ color: "#0f172a"
1153
+ },
1154
+ children: [
1155
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 500 }, children: m.tenantName || m.tenantSlug || m.tenantId }),
1156
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, opacity: 0.6 }, children: m.roles.join(", ") })
1157
+ ]
1158
+ },
1159
+ m.tenantId
1160
+ )) }) : null
1161
+ ]
1162
+ }
1163
+ );
801
1164
  }
802
1165
  var __version__ = "phase-bc-1.0.0";
803
1166
  export {
@@ -812,10 +1175,13 @@ export {
812
1175
  UserButton,
813
1176
  UserProfile,
814
1177
  __version__,
1178
+ isSilentSsoEligible,
1179
+ sanitizeBrandCss,
815
1180
  useAuth,
816
1181
  useAuthFetch,
817
1182
  useIQAuthSignInContext,
818
1183
  useOrganization,
1184
+ useResolvedSdkBranding,
819
1185
  useSession,
820
1186
  useUser
821
1187
  };