@youidian/sdk 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/login.ts","../src/hosted-modal.ts"],"sourcesContent":["import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the popup after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API popup callback landing page. */\n\tcallbackUrl?: string\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tif (launchPayload.callbackUrl) {\n\t\t\turl.searchParams.set(\"callbackUrl\", launchPayload.callbackUrl)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tif (launchPayload.callbackUrl) {\n\t\t\tsearchParams.set(\"callbackUrl\", launchPayload.callbackUrl)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nexport function handleLoginCallbackIfPresent() {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\twindow.setTimeout(() => {\n\t\ttry {\n\t\t\twindow.close()\n\t\t} catch {\n\t\t\t// Some browsers disallow script-closing the current window.\n\t\t}\n\t}, 30)\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nexport class LoginUI {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate messageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tthis.messageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login popup requested close; autoClose disabled, keeping popup open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login popup requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: this.popup?.closed ?? true,\n\t\t})\n\t\tif (this.popup && !this.popup.closed) {\n\t\t\tthis.popup.close()\n\t\t}\n\t\tthis.cleanup()\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !this.popup.closed) return\n\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\tif (!this.popup || this.popup.closed) {\n\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t})\n\t\t\t\tthis.cleanup()\n\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t}\n\t\t\t\toptions?.onClose?.()\n\t\t\t}\n\t\t}, 500)\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent()\n","export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (data: TData, container: HTMLDivElement) => void\n\twidth?: string\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): void {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/login.ts","../src/hosted-modal.ts"],"sourcesContent":["import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the popup after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API popup callback landing page. */\n\tcallbackUrl?: string\n\t/**\n\t * Whether to poll popup.closed to detect manual popup closure.\n\t * Defaults to false because COOP can make popup.closed unreliable.\n\t */\n\tmonitorPopupClosed?: boolean\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginCallbackOptions {\n\t/**\n\t * Whether the callback helper should close the current window after\n\t * publishing the login result. Defaults to false; LoginUI closes the popup\n\t * it opened after receiving the callback event.\n\t */\n\tautoClose?: boolean\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction safeIsPopupClosed(popup: Window | null) {\n\tif (!popup) return true\n\ttry {\n\t\treturn popup.closed\n\t} catch {\n\t\tlogLoginDebug(\"Unable to read popup.closed; treating popup as open\")\n\t\treturn false\n\t}\n}\n\nfunction safeClosePopup(popup: Window | null) {\n\tif (!popup) return\n\ttry {\n\t\tpopup.close()\n\t} catch {\n\t\tlogLoginDebug(\"Unable to close popup\")\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nexport function handleLoginCallbackIfPresent(options?: LoginCallbackOptions) {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\tif (options?.autoClose === true) {\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.close()\n\t\t\t} catch {\n\t\t\t\t// Some browsers disallow script-closing the current window.\n\t\t\t}\n\t\t}, 30)\n\t\treturn true\n\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"\"\n\t} catch {\n\t\t// Ignore visibility restoration failures.\n\t}\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nexport class LoginUI {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate messageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tthis.messageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login popup requested close; autoClose disabled, keeping popup open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login popup requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: safeIsPopupClosed(this.popup),\n\t\t})\n\t\tsafeClosePopup(this.popup)\n\t\tthis.cleanup()\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !safeIsPopupClosed(this.popup)) return\n\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\tif (options?.monitorPopupClosed === true) {\n\t\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\t\tif (!this.popup || safeIsPopupClosed(this.popup)) {\n\t\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t\t})\n\t\t\t\t\tthis.cleanup()\n\t\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t\t}\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t}\n\t\t\t}, 500)\n\t\t}\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent({ autoClose: false })\n","export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (data: TData, container: HTMLDivElement) => void\n\twidth?: string\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): void {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n"],"mappings":"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","names":[]}
package/dist/login.d.cts CHANGED
@@ -1 +1 @@
1
- export { L as LoginEventData, a as LoginEventType, b as LoginParams, c as LoginResult, d as LoginUI, e as LoginUIOptions, f as createLoginUI, h as handleLoginCallbackIfPresent } from './login-D_VaJqQX.cjs';
1
+ export { L as LoginCallbackOptions, a as LoginEventData, b as LoginEventType, c as LoginParams, d as LoginResult, e as LoginUI, f as LoginUIOptions, g as createLoginUI, h as handleLoginCallbackIfPresent } from './login-zl_PRUh9.cjs';
package/dist/login.d.ts CHANGED
@@ -1 +1 @@
1
- export { L as LoginEventData, a as LoginEventType, b as LoginParams, c as LoginResult, d as LoginUI, e as LoginUIOptions, f as createLoginUI, h as handleLoginCallbackIfPresent } from './login-D_VaJqQX.js';
1
+ export { L as LoginCallbackOptions, a as LoginEventData, b as LoginEventType, c as LoginParams, d as LoginResult, e as LoginUI, f as LoginUIOptions, g as createLoginUI, h as handleLoginCallbackIfPresent } from './login-zl_PRUh9.js';
package/dist/login.js CHANGED
@@ -200,9 +200,6 @@ function buildLoginUrl(params, options, launchPayload) {
200
200
  if (parentOrigin) {
201
201
  url.searchParams.set("origin", parentOrigin);
202
202
  }
203
- if (launchPayload.callbackUrl) {
204
- url.searchParams.set("callbackUrl", launchPayload.callbackUrl);
205
- }
206
203
  return appendLoginLaunchHash(url.toString(), launchPayload);
207
204
  } catch (_error) {
208
205
  const searchParams = new URLSearchParams();
@@ -215,9 +212,6 @@ function buildLoginUrl(params, options, launchPayload) {
215
212
  if (parentOrigin) {
216
213
  searchParams.set("origin", parentOrigin);
217
214
  }
218
- if (launchPayload.callbackUrl) {
219
- searchParams.set("callbackUrl", launchPayload.callbackUrl);
220
- }
221
215
  const query = searchParams.toString();
222
216
  if (!query) {
223
217
  return appendLoginLaunchHash(finalUrl, launchPayload);
@@ -298,6 +292,23 @@ function publishLoginCallback(state, data) {
298
292
  } catch {
299
293
  }
300
294
  }
295
+ function safeIsPopupClosed(popup) {
296
+ if (!popup) return true;
297
+ try {
298
+ return popup.closed;
299
+ } catch {
300
+ logLoginDebug("Unable to read popup.closed; treating popup as open");
301
+ return false;
302
+ }
303
+ }
304
+ function safeClosePopup(popup) {
305
+ if (!popup) return;
306
+ try {
307
+ popup.close();
308
+ } catch {
309
+ logLoginDebug("Unable to close popup");
310
+ }
311
+ }
301
312
  function cleanLoginCallbackUrl(url) {
302
313
  url.searchParams.delete(LOGIN_CALLBACK_MARKER);
303
314
  url.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM);
@@ -306,7 +317,7 @@ function cleanLoginCallbackUrl(url) {
306
317
  url.hash = returnHash ? `#${returnHash}` : "";
307
318
  return url.toString();
308
319
  }
309
- function handleLoginCallbackIfPresent() {
320
+ function handleLoginCallbackIfPresent(options) {
310
321
  if (typeof window === "undefined") {
311
322
  return false;
312
323
  }
@@ -332,12 +343,19 @@ function handleLoginCallbackIfPresent() {
332
343
  window.history.replaceState(null, "", cleanLoginCallbackUrl(url));
333
344
  } catch {
334
345
  }
335
- window.setTimeout(() => {
336
- try {
337
- window.close();
338
- } catch {
339
- }
340
- }, 30);
346
+ if (options?.autoClose === true) {
347
+ window.setTimeout(() => {
348
+ try {
349
+ window.close();
350
+ } catch {
351
+ }
352
+ }, 30);
353
+ return true;
354
+ }
355
+ try {
356
+ document.documentElement.style.visibility = "";
357
+ } catch {
358
+ }
341
359
  return true;
342
360
  }
343
361
  function logLoginDebug(message, details) {
@@ -459,16 +477,14 @@ var LoginUI = class {
459
477
  close() {
460
478
  logLoginInfo("close() called", {
461
479
  hasPopup: Boolean(this.popup),
462
- popupClosed: this.popup?.closed ?? true
480
+ popupClosed: safeIsPopupClosed(this.popup)
463
481
  });
464
- if (this.popup && !this.popup.closed) {
465
- this.popup.close();
466
- }
482
+ safeClosePopup(this.popup);
467
483
  this.cleanup();
468
484
  }
469
485
  openLogin(params, options) {
470
486
  if (typeof window === "undefined") return;
471
- if (this.popup && !this.popup.closed) return;
487
+ if (this.popup && !safeIsPopupClosed(this.popup)) return;
472
488
  const callbackState = createLoginCallbackState();
473
489
  const launchPayload = buildLoginLaunchPayload(
474
490
  params,
@@ -478,9 +494,14 @@ var LoginUI = class {
478
494
  const finalUrl = buildLoginUrl(params, options, launchPayload);
479
495
  logLoginInfo("Opening hosted login popup", {
480
496
  appId: params.appId,
497
+ callbackState,
498
+ callbackUrl: launchPayload.callbackUrl || null,
499
+ hasCallbackUrl: Boolean(launchPayload.callbackUrl),
481
500
  loginUrl: finalUrl,
482
501
  allowedOrigin: options?.allowedOrigin || null,
483
- autoClose: options?.autoClose ?? true
502
+ autoClose: options?.autoClose ?? true,
503
+ pageUrl: typeof window !== "undefined" ? window.location.href : null,
504
+ parentOrigin: launchPayload.origin || null
484
505
  });
485
506
  const popupWidth = 520;
486
507
  const popupHeight = 720;
@@ -540,25 +561,27 @@ var LoginUI = class {
540
561
  this.handleLoginEvent(data, options);
541
562
  };
542
563
  window.addEventListener("message", this.messageHandler);
543
- this.closeMonitor = window.setInterval(() => {
544
- if (!this.popup || this.popup.closed) {
545
- const shouldTreatAsCancel = !this.completed;
546
- logLoginInfo("Detected popup closed", {
547
- shouldTreatAsCancel
548
- });
549
- this.cleanup();
550
- if (shouldTreatAsCancel) {
551
- options?.onCancel?.();
564
+ if (options?.monitorPopupClosed === true) {
565
+ this.closeMonitor = window.setInterval(() => {
566
+ if (!this.popup || safeIsPopupClosed(this.popup)) {
567
+ const shouldTreatAsCancel = !this.completed;
568
+ logLoginInfo("Detected popup closed", {
569
+ shouldTreatAsCancel
570
+ });
571
+ this.cleanup();
572
+ if (shouldTreatAsCancel) {
573
+ options?.onCancel?.();
574
+ }
575
+ options?.onClose?.();
552
576
  }
553
- options?.onClose?.();
554
- }
555
- }, 500);
577
+ }, 500);
578
+ }
556
579
  }
557
580
  };
558
581
  function createLoginUI() {
559
582
  return new LoginUI();
560
583
  }
561
- handleLoginCallbackIfPresent();
584
+ handleLoginCallbackIfPresent({ autoClose: false });
562
585
  export {
563
586
  LoginUI,
564
587
  createLoginUI,
package/dist/login.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hosted-modal.ts","../src/login.ts"],"sourcesContent":["export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (data: TData, container: HTMLDivElement) => void\n\twidth?: string\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): void {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n","import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the popup after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API popup callback landing page. */\n\tcallbackUrl?: string\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tif (launchPayload.callbackUrl) {\n\t\t\turl.searchParams.set(\"callbackUrl\", launchPayload.callbackUrl)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tif (launchPayload.callbackUrl) {\n\t\t\tsearchParams.set(\"callbackUrl\", launchPayload.callbackUrl)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nexport function handleLoginCallbackIfPresent() {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\twindow.setTimeout(() => {\n\t\ttry {\n\t\t\twindow.close()\n\t\t} catch {\n\t\t\t// Some browsers disallow script-closing the current window.\n\t\t}\n\t}, 30)\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nexport class LoginUI {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate messageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tthis.messageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login popup requested close; autoClose disabled, keeping popup open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login popup requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: this.popup?.closed ?? true,\n\t\t})\n\t\tif (this.popup && !this.popup.closed) {\n\t\t\tthis.popup.close()\n\t\t}\n\t\tthis.cleanup()\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !this.popup.closed) return\n\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\tif (!this.popup || this.popup.closed) {\n\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t})\n\t\t\t\tthis.cleanup()\n\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t}\n\t\t\t\toptions?.onClose?.()\n\t\t\t}\n\t\t}, 500)\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent()\n"],"mappings":";;;;;AAaA,IAAM,wBAAwB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEA,IAAM,qBAAqB;AAE3B,IAAM,qBAA6C;AAAA,EAClD,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACL;AAEA,SAAS,yBAAyB,QAAoC;AACrE,QAAM,OAAO,OAAO,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAC9C,SAAO,sBAAsB,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,IAAI;AACxE;AAEO,SAAS,mBAAmB,QAAqC;AACvE,MAAI,CAAC,OAAQ;AAEb,QAAM,YAAY,OAAO,KAAK,EAAE,QAAQ,MAAM,GAAG;AACjD,MAAI,CAAC,UAAW;AAEhB,QAAM,QAAQ,UAAU,YAAY;AACpC,MAAI,mBAAmB,KAAK,GAAG;AAC9B,WAAO,mBAAmB,KAAK;AAAA,EAChC;AAEA,MAAI;AACJ,MAAI;AACH,gBAAY,KAAK,oBAAoB,SAAS,EAAE,CAAC;AAAA,EAClD,QAAQ;AACP,gBAAY;AAAA,EACb;AAEA,QAAM,aAAa,CAAC,WAAW,SAAS,EAAE,OAAO,OAAO;AAExD,aAAW,aAAa,YAAY;AACnC,UAAM,iBAAiB,UAAU,YAAY;AAE7C,QAAI,mBAAmB,cAAc,GAAG;AACvC,aAAO,mBAAmB,cAAc;AAAA,IACzC;AACA,QAAK,sBAA4C,SAAS,SAAS,GAAG;AACrE,aAAO;AAAA,IACR;AAEA,UAAM,YAAY,yBAAyB,SAAS;AACpD,QAAI,WAAW;AACd,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAEO,SAAS,mBAAuC;AACtD,MAAI,OAAO,cAAc,YAAa;AAEtC,aAAW,aAAa,UAAU,aAAa,CAAC,GAAG;AAClD,UAAM,aAAa,mBAAmB,SAAS;AAC/C,QAAI,WAAY,QAAO;AAAA,EACxB;AAEA,SAAO,mBAAmB,UAAU,QAAQ;AAC7C;AAEO,SAAS,sBAAsB,QAAyB;AAC9D,SAAO,mBAAmB,MAAM,KAAK,iBAAiB,KAAK;AAC5D;AAEO,SAAS,iBAAiB,UAAkB,QAAyB;AAC3E,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,QAAQ;AAC5B,UAAM,eAAe,IAAI,MAAM;AAC/B,QACC,CAAC,IAAI,SAAS,WAAW,GAAG,YAAY,GAAG,KAC3C,IAAI,aAAa,cAChB;AACD,UAAI,WAAW,GAAG,YAAY,GAAG,IAAI,QAAQ;AAAA,IAC9C;AACA,WAAO,IAAI,SAAS;AAAA,EACrB,SAAS,QAAQ;AAChB,UAAM,eAAe,IAAI,MAAM;AAC/B,QAAI,CAAC,SAAS,WAAW,GAAG,YAAY,GAAG,KAAK,aAAa,cAAc;AAC1E,aAAO,GAAG,YAAY,GAAG,SAAS,WAAW,GAAG,IAAI,KAAK,GAAG,GAAG,QAAQ;AAAA,IACxE;AACA,WAAO;AAAA,EACR;AACD;;;ACxDA,SAAS,UAAU,OAA+B;AACjD,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACH,WAAO,IAAI,IAAI,KAAK,EAAE;AAAA,EACvB,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,SAAS,2BAA2B;AACnC,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACvD,WAAO,OAAO,WAAW,EAAE,QAAQ,MAAM,EAAE;AAAA,EAC5C;AACA,SAAO,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACxE;AAEA,SAAS,sBAAsB,eAAuB,aAAsB;AAC3E,QAAM,UAAU,eAAe,OAAO,SAAS;AAC/C,QAAM,MAAM,IAAI,IAAI,SAAS,OAAO,SAAS,IAAI;AACjD,QAAM,aAAa,IAAI,KAAK,QAAQ,MAAM,EAAE;AAE5C,MAAI,OAAO;AACX,MAAI,aAAa,IAAI,uBAAuB,GAAG;AAC/C,MAAI,aAAa,IAAI,4BAA4B,aAAa;AAC9D,MAAI,YAAY;AACf,QAAI,aAAa,IAAI,kCAAkC,UAAU;AAAA,EAClE,OAAO;AACN,QAAI,aAAa,OAAO,gCAAgC;AAAA,EACzD;AAEA,SAAO,IAAI,SAAS;AACrB;AAEA,SAAS,wBACR,QACA,SACA,eACC;AACD,QAAM,eACL,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AAC1D,QAAM,cACL,OAAO,WAAW,eAAe,gBAC9B,sBAAsB,eAAe,SAAS,WAAW,IACzD;AAEJ,SAAO;AAAA,IACN,WAAW,SAAS,aAAa;AAAA,IACjC;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,kBAAkB,OAAO;AAAA,EAC1B;AACD;AAEA,SAAS,sBACR,UACA,SACC;AACD,QAAM,aAAa,IAAI,gBAAgB;AACvC,MAAI,QAAQ,cAAc,OAAO;AAChC,eAAW,IAAI,eAAe,OAAO;AAAA,EACtC;AACA,MAAI,QAAQ,QAAQ;AACnB,eAAW,IAAI,YAAY,QAAQ,MAAM;AAAA,EAC1C;AACA,MAAI,QAAQ,aAAa;AACxB,eAAW,IAAI,iBAAiB,QAAQ,WAAW;AAAA,EACpD;AACA,MAAI,QAAQ,kBAAkB;AAC7B,eAAW,IAAI,sBAAsB,QAAQ,gBAAgB;AAAA,EAC9D;AACA,QAAM,OAAO,WAAW,SAAS;AACjC,MAAI,CAAC,MAAM;AACV,WAAO;AAAA,EACR;AAEA,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,QAAQ;AAC5B,QAAI,OAAO;AACX,WAAO,IAAI,SAAS;AAAA,EACrB,SAAS,QAAQ;AAChB,WAAO,GAAG,QAAQ,IAAI,IAAI;AAAA,EAC3B;AACD;AAEA,SAAS,oBAAoB,SAA6B;AACzD,SAAO,kBAAkB,KAAK,UAAU,OAAO,CAAC;AACjD;AAEA,SAAS,cACR,QACA,SACA,eACS;AACT,QAAM,EAAE,OAAO,UAAU,0BAA0B,SAAS,IAAI;AAChE,QAAM,WAAW,YAAY,SAAS,QAAQ,OAAO,EAAE;AACvD,QAAM,eAAe,cAAc;AAEnC,MAAI;AACJ,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAI,CAAC,0BAA0B,KAAK,IAAI,QAAQ,GAAG;AAClD,UAAI,WACH,GAAG,IAAI,SAAS,QAAQ,OAAO,EAAE,CAAC,iBAAiB,KAAK,GAAG;AAAA,QAC1D;AAAA,QACA;AAAA,MACD;AAAA,IACF;AACA,eAAW,IAAI,SAAS;AAAA,EACzB,SAAS,QAAQ;AAChB,QAAI,0BAA0B,KAAK,OAAO,GAAG;AAC5C,iBAAW;AAAA,IACZ,OAAO;AACN,iBAAW,GAAG,OAAO,iBAAiB,KAAK,GAAG,QAAQ,WAAW,GAAG;AAAA,IACrE;AAAA,EACD;AAEA,aAAW,iBAAiB,UAAU,sBAAsB,OAAO,MAAM,CAAC;AAE1E,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,QAAQ;AAC5B,QAAI,OAAO,kBAAkB;AAC5B,UAAI,aAAa,IAAI,oBAAoB,OAAO,gBAAgB;AAAA,IACjE;AACA,QAAI,SAAS,cAAc,OAAO;AACjC,UAAI,aAAa,IAAI,aAAa,OAAO;AAAA,IAC1C;AACA,QAAI,cAAc;AACjB,UAAI,aAAa,IAAI,UAAU,YAAY;AAAA,IAC5C;AACA,QAAI,cAAc,aAAa;AAC9B,UAAI,aAAa,IAAI,eAAe,cAAc,WAAW;AAAA,IAC9D;AACA,WAAO,sBAAsB,IAAI,SAAS,GAAG,aAAa;AAAA,EAC3D,SAAS,QAAQ;AAChB,UAAM,eAAe,IAAI,gBAAgB;AACzC,QAAI,OAAO,kBAAkB;AAC5B,mBAAa,IAAI,oBAAoB,OAAO,gBAAgB;AAAA,IAC7D;AACA,QAAI,SAAS,cAAc,OAAO;AACjC,mBAAa,IAAI,aAAa,OAAO;AAAA,IACtC;AACA,QAAI,cAAc;AACjB,mBAAa,IAAI,UAAU,YAAY;AAAA,IACxC;AACA,QAAI,cAAc,aAAa;AAC9B,mBAAa,IAAI,eAAe,cAAc,WAAW;AAAA,IAC1D;AACA,UAAM,QAAQ,aAAa,SAAS;AACpC,QAAI,CAAC,OAAO;AACX,aAAO,sBAAsB,UAAU,aAAa;AAAA,IACrD;AACA,UAAM,YAAY,SAAS,SAAS,GAAG,IAAI,MAAM;AACjD,WAAO;AAAA,MACN,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,mBAAmB,MAAmC;AAC9D,SAAO;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK;AAAA,IAChB,iBAAiB,KAAK;AAAA,IACtB,YAAY,KAAK;AAAA,IACjB,MAAM,KAAK;AAAA,IACX,QAAQ,KAAK;AAAA,IACb,cAAc,KAAK;AAAA,IACnB,eAAe,KAAK;AAAA,EACrB;AACD;AAEA,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,8BAA8B;AACpC,IAAM,mCAAmC;AACzC,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AAItC,SAAS,sBAAsB,OAAsC;AACpE,MAAI;AACH,UAAM,SAAS,MAAM;AAAA,MACpB,MAAM,UAAW,IAAK,MAAM,SAAS,KAAM;AAAA,MAC3C;AAAA,IACD;AACA,UAAM,SAAS,OAAO,WAAW,KAAK,GAAG,EAAE,WAAW,KAAK,GAAG;AAC9D,UAAM,SAAS,KAAK,MAAM;AAC1B,UAAM,OAAO;AAAA,MACZ,MAAM;AAAA,QACL;AAAA,QACA,CAAC,SAAS,IAAI,KAAK,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,MAC/D,EAAE,KAAK,EAAE;AAAA,IACV;AACA,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,WAAO,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS;AAAA,EACvE,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,SAAS,4BAA4B,OAAe;AACnD,SAAO,kBAAkB,KAAK;AAC/B;AAEA,SAAS,2BAA2B,OAAe;AAClD,SAAO,GAAG,6BAA6B,GAAG,KAAK;AAChD;AAEA,SAAS,qBAAqB,OAAe,MAAsB;AAClE,MAAI;AACH,UAAM,UAAU,IAAI,iBAAiB,4BAA4B,KAAK,CAAC;AACvE,YAAQ,YAAY,IAAI;AACxB,YAAQ,MAAM;AAAA,EACf,QAAQ;AAAA,EAER;AAEA,MAAI;AACH,UAAM,aAAa,2BAA2B,KAAK;AACnD,WAAO,aAAa,QAAQ,YAAY,KAAK,UAAU,IAAI,CAAC;AAC5D,WAAO,WAAW,MAAM;AACvB,UAAI;AACH,eAAO,aAAa,WAAW,UAAU;AAAA,MAC1C,QAAQ;AAAA,MAER;AAAA,IACD,GAAG,GAAG;AAAA,EACP,QAAQ;AAAA,EAER;AAEA,MAAI;AACH,WAAO,QAAQ,YAAY,MAAM,OAAO,SAAS,MAAM;AAAA,EACxD,QAAQ;AAAA,EAER;AACD;AAEA,SAAS,sBAAsB,KAAU;AACxC,MAAI,aAAa,OAAO,qBAAqB;AAC7C,MAAI,aAAa,OAAO,0BAA0B;AAClD,QAAM,aAAa,IAAI,aAAa,IAAI,gCAAgC;AACxE,MAAI,aAAa,OAAO,gCAAgC;AACxD,MAAI,OAAO,aAAa,IAAI,UAAU,KAAK;AAC3C,SAAO,IAAI,SAAS;AACrB;AAEO,SAAS,+BAA+B;AAC9C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO;AAAA,EACR;AAEA,QAAM,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI;AACxC,MAAI,IAAI,aAAa,IAAI,qBAAqB,MAAM,KAAK;AACxD,WAAO;AAAA,EACR;AAEA,QAAM,QAAQ,IAAI,aAAa,IAAI,0BAA0B,KAAK;AAClE,QAAM,aAAa,IAAI,gBAAgB,IAAI,KAAK,QAAQ,MAAM,EAAE,CAAC;AACjE,QAAM,YAAY,WAAW,IAAI,2BAA2B;AAC5D,QAAM,OACL,aAAa,QACV,sBAAsB,SAAS,IAC/B;AAAA,IACA,MAAM;AAAA,IACN,SAAS;AAAA,EACV;AAEH,MAAI;AACH,aAAS,gBAAgB,MAAM,aAAa;AAAA,EAC7C,QAAQ;AAAA,EAER;AAEA,MAAI,SAAS,MAAM;AAClB,yBAAqB,OAAO,IAAI;AAAA,EACjC;AAEA,MAAI;AACH,WAAO,QAAQ,aAAa,MAAM,IAAI,sBAAsB,GAAG,CAAC;AAAA,EACjE,QAAQ;AAAA,EAER;AAEA,SAAO,WAAW,MAAM;AACvB,QAAI;AACH,aAAO,MAAM;AAAA,IACd,QAAQ;AAAA,IAER;AAAA,EACD,GAAG,EAAE;AAEL,SAAO;AACR;AAEA,SAAS,cAAc,SAAiB,SAAmC;AAC1E,MAAI,OAAO,YAAY,YAAa;AACpC,UAAQ,MAAM,qBAAqB,SAAS,WAAW,CAAC,CAAC;AAC1D;AAEA,SAAS,aAAa,SAAiB,SAAmC;AACzE,MAAI,OAAO,YAAY,YAAa;AACpC,UAAQ,KAAK,qBAAqB,SAAS,WAAW,CAAC,CAAC;AACzD;AAEA,SAAS,aAAa,SAAiB,SAAmC;AACzE,MAAI,OAAO,YAAY,YAAa;AACpC,UAAQ,KAAK,qBAAqB,SAAS,WAAW,CAAC,CAAC;AACzD;AAEO,IAAM,UAAN,MAAc;AAAA,EAAd;AACN,wBAAQ,SAAuB;AAC/B,wBAAQ,mBAA2C;AACnD,wBAAQ,0BAAiE;AACzE,wBAAQ,kBAAyD;AACjE,wBAAQ,gBAA8B;AACtC,wBAAQ,aAAY;AAAA;AAAA,EAEZ,UAAU;AACjB,QAAI,KAAK,iBAAiB;AACzB,WAAK,gBAAgB,MAAM;AAAA,IAC5B;AACA,QAAI,OAAO,WAAW,eAAe,KAAK,wBAAwB;AACjE,aAAO,oBAAoB,WAAW,KAAK,sBAAsB;AAAA,IAClE;AACA,QAAI,OAAO,WAAW,eAAe,KAAK,gBAAgB;AACzD,aAAO,oBAAoB,WAAW,KAAK,cAAc;AAAA,IAC1D;AACA,SAAK,kBAAkB;AACvB,SAAK,yBAAyB;AAC9B,QAAI,OAAO,WAAW,eAAe,KAAK,cAAc;AACvD,aAAO,cAAc,KAAK,YAAY;AAAA,IACvC;AACA,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,SAAK,QAAQ;AACb,SAAK,YAAY;AAAA,EAClB;AAAA,EAEQ,iBAAiB,MAAsB,SAA0B;AACxE,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,MAAM;AACpD,oBAAc,iCAAiC;AAC/C;AAAA,IACD;AAEA,iBAAa,wBAAwB;AAAA,MACpC,MAAM,KAAK;AAAA,IACZ,CAAC;AAED,YAAQ,KAAK,MAAM;AAAA,MAClB,KAAK;AACJ,YAAI,KAAK,WAAW;AACnB;AAAA,QACD;AACA,aAAK,YAAY;AACjB,qBAAa,mBAAmB;AAAA,UAC/B,SAAS,KAAK,WAAW;AAAA,UACzB,QAAQ,KAAK,UAAU;AAAA,QACxB,CAAC;AACD,iBAAS,YAAY,mBAAmB,IAAI,CAAC;AAC7C;AAAA,MACD,KAAK;AACJ,qBAAa,iBAAiB;AAC9B,iBAAS,WAAW;AACpB;AAAA,MACD,KAAK;AACJ;AAAA,MACD,KAAK;AACJ,YAAI,KAAK,WAAW;AACnB;AAAA,QACD;AACA,qBAAa,gCAAgC;AAAA,UAC5C,SAAS,KAAK,WAAW,KAAK,SAAS;AAAA,QACxC,CAAC;AACD,iBAAS,UAAU,KAAK,WAAW,KAAK,OAAO,IAAI;AACnD;AAAA,MACD,KAAK;AACJ,YAAI,SAAS,cAAc,OAAO;AACjC;AAAA,YACC;AAAA,UACD;AACA,mBAAS,UAAU;AACnB;AAAA,QACD;AACA,qBAAa,gDAAgD;AAC7D,aAAK,MAAM;AACX,iBAAS,UAAU;AACnB;AAAA,IACF;AAAA,EACD;AAAA,EAEQ,uBACP,eACA,SACC;AACD,QAAI;AACH,WAAK,kBAAkB,IAAI;AAAA,QAC1B,4BAA4B,aAAa;AAAA,MAC1C;AACA,WAAK,gBAAgB,YAAY,CAAC,UAAU;AAC3C,aAAK,iBAAiB,MAAM,MAAwB,OAAO;AAC3D,aAAK,iBAAiB,EAAE,MAAM,cAAc,GAAG,OAAO;AAAA,MACvD;AAAA,IACD,QAAQ;AACP,oBAAc,oDAAoD;AAAA,IACnE;AAEA,SAAK,yBAAyB,CAAC,UAAwB;AACtD,UACC,MAAM,QAAQ,2BAA2B,aAAa,KACtD,CAAC,MAAM,UACN;AACD;AAAA,MACD;AACA,UAAI;AACH,cAAM,OAAO,KAAK,MAAM,MAAM,QAAQ;AACtC,aAAK,iBAAiB,MAAM,OAAO;AACnC,aAAK,iBAAiB,EAAE,MAAM,cAAc,GAAG,OAAO;AAAA,MACvD,QAAQ;AACP,qBAAa,gDAAgD;AAAA,MAC9D;AAAA,IACD;AACA,WAAO,iBAAiB,WAAW,KAAK,sBAAsB;AAAA,EAC/D;AAAA,EAEA,QAAQ;AACP,iBAAa,kBAAkB;AAAA,MAC9B,UAAU,QAAQ,KAAK,KAAK;AAAA,MAC5B,aAAa,KAAK,OAAO,UAAU;AAAA,IACpC,CAAC;AACD,QAAI,KAAK,SAAS,CAAC,KAAK,MAAM,QAAQ;AACrC,WAAK,MAAM,MAAM;AAAA,IAClB;AACA,SAAK,QAAQ;AAAA,EACd;AAAA,EAEA,UAAU,QAAqB,SAA0B;AACxD,QAAI,OAAO,WAAW,YAAa;AACnC,QAAI,KAAK,SAAS,CAAC,KAAK,MAAM,OAAQ;AAEtC,UAAM,gBAAgB,yBAAyB;AAC/C,UAAM,gBAAgB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,UAAM,WAAW,cAAc,QAAQ,SAAS,aAAa;AAC7D,iBAAa,8BAA8B;AAAA,MAC1C,OAAO,OAAO;AAAA,MACd,UAAU;AAAA,MACV,eAAe,SAAS,iBAAiB;AAAA,MACzC,WAAW,SAAS,aAAa;AAAA,IAClC,CAAC;AACD,UAAM,aAAa;AACnB,UAAM,cAAc;AACpB,UAAM,OAAO,KAAK;AAAA,MACjB;AAAA,MACA,KAAK,MAAM,OAAO,WAAW,OAAO,aAAa,cAAc,CAAC;AAAA,IACjE;AACA,UAAM,MAAM,KAAK;AAAA,MAChB;AAAA,MACA,KAAK,MAAM,OAAO,WAAW,OAAO,cAAc,eAAe,CAAC;AAAA,IACnE;AACA,UAAM,WAAW;AAAA,MAChB;AAAA,MACA,SAAS,UAAU;AAAA,MACnB,UAAU,WAAW;AAAA,MACrB,QAAQ,IAAI;AAAA,MACZ,OAAO,GAAG;AAAA,MACV;AAAA,MACA;AAAA,IACD,EAAE,KAAK,GAAG;AAEV,UAAM,YAAY,oBAAoB,aAAa;AACnD,UAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,QAAQ;AACvD,QAAI,CAAC,OAAO;AACX,mBAAa,8BAA8B;AAC3C,eAAS,UAAU,yBAAyB;AAC5C;AAAA,IACD;AAEA,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,uBAAuB,eAAe,OAAO;AAElD,UAAM,gBAAgB,SAAS;AAC/B,UAAM,cAAc,UAAU,QAAQ;AAEtC,SAAK,iBAAiB,CAAC,UAAwB;AAC9C,UACC,iBACA,kBAAkB,OAClB,MAAM,WAAW,eAChB;AACD,qBAAa,iDAAiD;AAAA,UAC7D;AAAA,UACA,aAAa,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACD;AACA,UAAI,CAAC,iBAAiB,eAAe,MAAM,WAAW,aAAa;AAClE,qBAAa,gDAAgD;AAAA,UAC5D,gBAAgB;AAAA,UAChB,aAAa,MAAM;AAAA,QACpB,CAAC;AACD;AAAA,MACD;AAEA,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,MAAM;AACpD,sBAAc,uCAAuC;AACrD;AAAA,MACD;AAEA,mBAAa,wBAAwB;AAAA,QACpC,MAAM,KAAK;AAAA,QACX,aAAa,MAAM;AAAA,MACpB,CAAC;AAED,WAAK,iBAAiB,MAAM,OAAO;AAAA,IACpC;AAEA,WAAO,iBAAiB,WAAW,KAAK,cAAc;AAEtD,SAAK,eAAe,OAAO,YAAY,MAAM;AAC5C,UAAI,CAAC,KAAK,SAAS,KAAK,MAAM,QAAQ;AACrC,cAAM,sBAAsB,CAAC,KAAK;AAClC,qBAAa,yBAAyB;AAAA,UACrC;AAAA,QACD,CAAC;AACD,aAAK,QAAQ;AACb,YAAI,qBAAqB;AACxB,mBAAS,WAAW;AAAA,QACrB;AACA,iBAAS,UAAU;AAAA,MACpB;AAAA,IACD,GAAG,GAAG;AAAA,EACP;AACD;AAEO,SAAS,gBAAyB;AACxC,SAAO,IAAI,QAAQ;AACpB;AAEA,6BAA6B;","names":[]}
1
+ {"version":3,"sources":["../src/hosted-modal.ts","../src/login.ts"],"sourcesContent":["export interface HostedFrameMessage {\n\ttype: string\n\theight?: number\n}\n\ntype HostedFrameOptions<TData extends HostedFrameMessage> = {\n\tallowedOrigin?: string\n\theight?: string\n\tonCloseButton?: () => void\n\tonMessage: (data: TData, container: HTMLDivElement) => void\n\twidth?: string\n}\n\nconst SDK_SUPPORTED_LOCALES = [\n\t\"en\",\n\t\"zh-CN\",\n\t\"zh-Hant\",\n\t\"fr\",\n\t\"de\",\n\t\"ja\",\n\t\"es\",\n\t\"ko\",\n\t\"nl\",\n\t\"it\",\n\t\"pt\",\n] as const\n\nconst SDK_DEFAULT_LOCALE = \"zh-CN\"\n\nconst SDK_LOCALE_ALIASES: Record<string, string> = {\n\ten: \"en\",\n\t\"en-us\": \"en\",\n\t\"en-gb\": \"en\",\n\tzh: \"zh-CN\",\n\t\"zh-cn\": \"zh-CN\",\n\t\"zh-tw\": \"zh-Hant\",\n\t\"zh-hk\": \"zh-Hant\",\n\t\"zh-hant\": \"zh-Hant\",\n\t\"zh-hans\": \"zh-CN\",\n\tfr: \"fr\",\n\tde: \"de\",\n\tja: \"ja\",\n\tes: \"es\",\n\tko: \"ko\",\n\tnl: \"nl\",\n\tit: \"it\",\n\tpt: \"pt\",\n}\n\nfunction matchSupportedBaseLocale(locale: string): string | undefined {\n\tconst base = locale.toLowerCase().split(\"-\")[0]\n\treturn SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base)\n}\n\nexport function normalizeSdkLocale(locale?: string): string | undefined {\n\tif (!locale) return\n\n\tconst sanitized = locale.trim().replace(/_/g, \"-\")\n\tif (!sanitized) return\n\n\tconst lower = sanitized.toLowerCase()\n\tif (SDK_LOCALE_ALIASES[lower]) {\n\t\treturn SDK_LOCALE_ALIASES[lower]\n\t}\n\n\tlet canonical: string | undefined\n\ttry {\n\t\tcanonical = Intl.getCanonicalLocales(sanitized)[0]\n\t} catch {\n\t\tcanonical = undefined\n\t}\n\n\tconst candidates = [canonical, sanitized].filter(Boolean) as string[]\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase()\n\n\t\tif (SDK_LOCALE_ALIASES[candidateLower]) {\n\t\t\treturn SDK_LOCALE_ALIASES[candidateLower]\n\t\t}\n\t\tif ((SDK_SUPPORTED_LOCALES as readonly string[]).includes(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\n\t\tconst baseMatch = matchSupportedBaseLocale(candidate)\n\t\tif (baseMatch) {\n\t\t\treturn baseMatch\n\t\t}\n\t}\n}\n\nexport function getBrowserLocale(): string | undefined {\n\tif (typeof navigator === \"undefined\") return\n\n\tfor (const candidate of navigator.languages || []) {\n\t\tconst normalized = normalizeSdkLocale(candidate)\n\t\tif (normalized) return normalized\n\t}\n\n\treturn normalizeSdkLocale(navigator.language)\n}\n\nexport function getAutoResolvedLocale(locale?: string): string {\n\treturn normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE\n}\n\nexport function applyLocaleToUrl(urlValue: string, locale?: string): string {\n\tif (!locale) return urlValue\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\tconst localePrefix = `/${locale}`\n\t\tif (\n\t\t\t!url.pathname.startsWith(`${localePrefix}/`) &&\n\t\t\turl.pathname !== localePrefix\n\t\t) {\n\t\t\turl.pathname = `${localePrefix}${url.pathname}`\n\t\t}\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\tconst localePrefix = `/${locale}`\n\t\tif (!urlValue.startsWith(`${localePrefix}/`) && urlValue !== localePrefix) {\n\t\t\treturn `${localePrefix}${urlValue.startsWith(\"/\") ? \"\" : \"/\"}${urlValue}`\n\t\t}\n\t\treturn urlValue\n\t}\n}\n\nexport class HostedFrameModal<TData extends HostedFrameMessage> {\n\tprotected iframe: HTMLIFrameElement | null = null\n\tprotected modal: HTMLDivElement | null = null\n\tprotected messageHandler: ((event: MessageEvent) => void) | null = null\n\n\tprotected openHostedFrame(\n\t\turl: string,\n\t\toptions: HostedFrameOptions<TData>,\n\t): void {\n\t\tif (typeof document === \"undefined\") return\n\t\tif (this.modal) return\n\n\t\tthis.modal = document.createElement(\"div\")\n\t\tObject.assign(this.modal.style, {\n\t\t\tposition: \"fixed\",\n\t\t\ttop: \"0\",\n\t\t\tleft: \"0\",\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tbackgroundColor: \"rgba(15,23,42,0.52)\",\n\t\t\tdisplay: \"flex\",\n\t\t\talignItems: \"center\",\n\t\t\tjustifyContent: \"center\",\n\t\t\tzIndex: \"9999\",\n\t\t\ttransition: \"opacity 0.3s ease\",\n\t\t\tbackdropFilter: \"blur(14px)\",\n\t\t\tpadding: \"16px\",\n\t\t})\n\n\t\tconst container = document.createElement(\"div\")\n\t\tObject.assign(container.style, {\n\t\t\twidth: options.width || \"450px\",\n\t\t\theight: options.height || \"min(600px, 90vh)\",\n\t\t\tbackgroundColor: \"transparent\",\n\t\t\tborderRadius: \"28px\",\n\t\t\toverflow: \"visible\",\n\t\t\tposition: \"relative\",\n\t\t\tboxShadow: \"none\",\n\t\t\tmaxWidth: \"calc(100vw - 32px)\",\n\t\t\tmaxHeight: \"calc(100vh - 32px)\",\n\t\t\ttransition: \"height 180ms ease\",\n\t\t\twillChange: \"height\",\n\t\t})\n\n\t\tconst closeBtn = document.createElement(\"button\")\n\t\tcloseBtn.innerHTML = \"×\"\n\t\tObject.assign(closeBtn.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tright: \"-14px\",\n\t\t\ttop: \"-14px\",\n\t\t\tfontSize: \"20px\",\n\t\t\twidth: \"36px\",\n\t\t\theight: \"36px\",\n\t\t\tborderRadius: \"9999px\",\n\t\t\tborder: \"1px solid rgba(255,255,255,0.5)\",\n\t\t\tbackground: \"rgba(255,255,255,0.9)\",\n\t\t\tcursor: \"pointer\",\n\t\t\tcolor: \"#475569\",\n\t\t\tzIndex: \"2\",\n\t\t\tboxShadow: \"0 10px 30px rgba(15,23,42,0.16)\",\n\t\t})\n\t\tcloseBtn.onclick = () => {\n\t\t\tthis.close()\n\t\t\toptions.onCloseButton?.()\n\t\t}\n\n\t\tthis.iframe = document.createElement(\"iframe\")\n\t\tthis.iframe.src = url\n\t\tObject.assign(this.iframe.style, {\n\t\t\twidth: \"100%\",\n\t\t\theight: \"100%\",\n\t\t\tborder: \"none\",\n\t\t\tborderRadius: \"28px\",\n\t\t\tbackground: \"transparent\",\n\t\t\tdisplay: \"block\",\n\t\t})\n\n\t\tcontainer.appendChild(closeBtn)\n\t\tcontainer.appendChild(this.iframe)\n\t\tthis.modal.appendChild(container)\n\t\tdocument.body.appendChild(this.modal)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (options.allowedOrigin && options.allowedOrigin !== \"*\") {\n\t\t\t\tif (event.origin !== options.allowedOrigin) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst data = event.data as TData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toptions.onMessage(data, container)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\t}\n\n\tclose() {\n\t\tif (typeof window === \"undefined\") return\n\n\t\tif (this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t\tthis.messageHandler = null\n\t\t}\n\n\t\tif (this.modal?.parentNode) {\n\t\t\tthis.modal.parentNode.removeChild(this.modal)\n\t\t}\n\n\t\tthis.modal = null\n\t\tthis.iframe = null\n\t}\n}\n","import {\n\tapplyLocaleToUrl,\n\tgetAutoResolvedLocale,\n\ttype HostedFrameMessage,\n} from \"./hosted-modal\"\n\nexport type LoginEventType =\n\t| \"LOGIN_SUCCESS\"\n\t| \"LOGIN_CANCELLED\"\n\t| \"LOGIN_CLOSE\"\n\t| \"LOGIN_RESIZE\"\n\t| \"LOGIN_ERROR\"\n\nexport interface LoginResult {\n\tavatar?: string | null\n\tchannel?: string\n\temail?: string | null\n\texpiresAt?: string\n\tlegacyCasdoorId?: string\n\tloginToken?: string\n\tname?: string | null\n\tuserId?: string\n\twechatOpenId?: string | null\n\twechatUnionId?: string | null\n}\n\nexport interface LoginEventData extends HostedFrameMessage, LoginResult {\n\ttype: LoginEventType\n\terror?: string\n\tmessage?: string\n}\n\nexport interface LoginUIOptions {\n\t/** Origin to validate postMessage (defaults to '*', set for security) */\n\tallowedOrigin?: string\n\t/** Whether the SDK should close the popup after receiving LOGIN_CLOSE. Defaults to true. */\n\tautoClose?: boolean\n\t/** Optional same-origin URL used as the no-API popup callback landing page. */\n\tcallbackUrl?: string\n\t/**\n\t * Whether to poll popup.closed to detect manual popup closure.\n\t * Defaults to false because COOP can make popup.closed unreliable.\n\t */\n\tmonitorPopupClosed?: boolean\n\tonCancel?: () => void\n\tonClose?: () => void\n\tonError?: (message?: string, data?: LoginEventData) => void\n\tonSuccess?: (result: LoginResult) => void\n}\n\nexport interface LoginCallbackOptions {\n\t/**\n\t * Whether the callback helper should close the current window after\n\t * publishing the login result. Defaults to false; LoginUI closes the popup\n\t * it opened after receiving the callback event.\n\t */\n\tautoClose?: boolean\n}\n\nexport interface LoginParams {\n\tappId: string\n\n\t/**\n\t * @deprecated Use loginUrl instead\n\t * Defaults to https://pay.imgto.link\n\t */\n\tbaseUrl?: string\n\n\t/**\n\t * Hosted login page base URL (e.g. https://pay.youidian.com)\n\t * Defaults to https://pay.imgto.link\n\t */\n\tloginUrl?: string\n\n\t/**\n\t * Optional locale prefix to prepend to the hosted login path.\n\t * If omitted, the SDK automatically resolves the locale from the browser language.\n\t */\n\tlocale?: string\n\n\t/** Preferred provider/channel code */\n\tpreferredChannel?: string\n}\n\nfunction getOrigin(value?: string): string | null {\n\tif (!value) return null\n\ttry {\n\t\treturn new URL(value).origin\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction createLoginCallbackState() {\n\tif (typeof crypto !== \"undefined\" && crypto.randomUUID) {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\")\n\t}\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`\n}\n\nfunction buildLoginCallbackUrl(callbackState: string, callbackUrl?: string) {\n\tconst baseUrl = callbackUrl || window.location.href\n\tconst url = new URL(baseUrl, window.location.href)\n\tconst returnHash = url.hash.replace(/^#/, \"\")\n\n\turl.hash = \"\"\n\turl.searchParams.set(LOGIN_CALLBACK_MARKER, \"1\")\n\turl.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState)\n\tif (returnHash) {\n\t\turl.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash)\n\t} else {\n\t\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\t}\n\n\treturn url.toString()\n}\n\nfunction buildLoginLaunchPayload(\n\tparams: LoginParams,\n\toptions?: LoginUIOptions,\n\tcallbackState?: string,\n) {\n\tconst parentOrigin =\n\t\ttypeof window !== \"undefined\" ? window.location.origin : undefined\n\tconst callbackUrl =\n\t\ttypeof window !== \"undefined\" && callbackState\n\t\t\t? buildLoginCallbackUrl(callbackState, options?.callbackUrl)\n\t\t\t: undefined\n\n\treturn {\n\t\tautoClose: options?.autoClose ?? true,\n\t\tcallbackUrl,\n\t\tcallbackState,\n\t\torigin: parentOrigin,\n\t\tpreferredChannel: params.preferredChannel,\n\t}\n}\n\nfunction appendLoginLaunchHash(\n\turlValue: string,\n\tpayload: ReturnType<typeof buildLoginLaunchPayload>,\n) {\n\tconst hashParams = new URLSearchParams()\n\tif (payload.autoClose === false) {\n\t\thashParams.set(\"ydAutoClose\", \"false\")\n\t}\n\tif (payload.origin) {\n\t\thashParams.set(\"ydOrigin\", payload.origin)\n\t}\n\tif (payload.callbackUrl) {\n\t\thashParams.set(\"ydCallbackUrl\", payload.callbackUrl)\n\t}\n\tif (payload.preferredChannel) {\n\t\thashParams.set(\"ydPreferredChannel\", payload.preferredChannel)\n\t}\n\tconst hash = hashParams.toString()\n\tif (!hash) {\n\t\treturn urlValue\n\t}\n\n\ttry {\n\t\tconst url = new URL(urlValue)\n\t\turl.hash = hash\n\t\treturn url.toString()\n\t} catch (_error) {\n\t\treturn `${urlValue}#${hash}`\n\t}\n}\n\nfunction buildLoginPopupName(payload: LoginLaunchPayload) {\n\treturn `youidian-login:${JSON.stringify(payload)}`\n}\n\nfunction buildLoginUrl(\n\tparams: LoginParams,\n\toptions: LoginUIOptions | undefined,\n\tlaunchPayload: LoginLaunchPayload,\n): string {\n\tconst { appId, baseUrl = \"https://pay.imgto.link\", loginUrl } = params\n\tconst rawBase = (loginUrl || baseUrl).replace(/\\/$/, \"\")\n\tconst parentOrigin = launchPayload.origin\n\n\tlet finalUrl: string\n\ttry {\n\t\tconst url = new URL(rawBase)\n\t\tif (!/\\/auth\\/connect\\/[^/]+$/.test(url.pathname)) {\n\t\t\turl.pathname =\n\t\t\t\t`${url.pathname.replace(/\\/$/, \"\")}/auth/connect/${appId}`.replace(\n\t\t\t\t\t/\\/{2,}/g,\n\t\t\t\t\t\"/\",\n\t\t\t\t)\n\t\t}\n\t\tfinalUrl = url.toString()\n\t} catch (_error) {\n\t\tif (/\\/auth\\/connect\\/[^/]+$/.test(rawBase)) {\n\t\t\tfinalUrl = rawBase\n\t\t} else {\n\t\t\tfinalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\\/{2,}/g, \"/\")\n\t\t}\n\t}\n\n\tfinalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale))\n\n\ttry {\n\t\tconst url = new URL(finalUrl)\n\t\tif (params.preferredChannel) {\n\t\t\turl.searchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\turl.searchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\turl.searchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\treturn appendLoginLaunchHash(url.toString(), launchPayload)\n\t} catch (_error) {\n\t\tconst searchParams = new URLSearchParams()\n\t\tif (params.preferredChannel) {\n\t\t\tsearchParams.set(\"preferredChannel\", params.preferredChannel)\n\t\t}\n\t\tif (options?.autoClose === false) {\n\t\t\tsearchParams.set(\"autoClose\", \"false\")\n\t\t}\n\t\tif (parentOrigin) {\n\t\t\tsearchParams.set(\"origin\", parentOrigin)\n\t\t}\n\t\tconst query = searchParams.toString()\n\t\tif (!query) {\n\t\t\treturn appendLoginLaunchHash(finalUrl, launchPayload)\n\t\t}\n\t\tconst separator = finalUrl.includes(\"?\") ? \"&\" : \"?\"\n\t\treturn appendLoginLaunchHash(\n\t\t\t`${finalUrl}${separator}${query}`,\n\t\t\tlaunchPayload,\n\t\t)\n\t}\n}\n\nfunction extractLoginResult(data: LoginEventData): LoginResult {\n\treturn {\n\t\tavatar: data.avatar,\n\t\tchannel: data.channel,\n\t\temail: data.email,\n\t\texpiresAt: data.expiresAt,\n\t\tlegacyCasdoorId: data.legacyCasdoorId,\n\t\tloginToken: data.loginToken,\n\t\tname: data.name,\n\t\tuserId: data.userId,\n\t\twechatOpenId: data.wechatOpenId,\n\t\twechatUnionId: data.wechatUnionId,\n\t}\n}\n\nconst LOGIN_UI_LOG_PREFIX = \"[Youidian LoginUI]\"\nconst LOGIN_CALLBACK_MARKER = \"yd_login_callback\"\nconst LOGIN_CALLBACK_RESULT_PARAM = \"yd_login_result\"\nconst LOGIN_CALLBACK_RETURN_HASH_PARAM = \"yd_login_return_hash\"\nconst LOGIN_CALLBACK_STATE_PARAM = \"yd_login_state\"\nconst LOGIN_CALLBACK_STORAGE_PREFIX = \"yd-login-callback:\"\n\ntype LoginLaunchPayload = ReturnType<typeof buildLoginLaunchPayload>\n\nfunction decodeCallbackPayload(value: string): LoginEventData | null {\n\ttry {\n\t\tconst padded = value.padEnd(\n\t\t\tvalue.length + ((4 - (value.length % 4)) % 4),\n\t\t\t\"=\",\n\t\t)\n\t\tconst base64 = padded.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\")\n\t\tconst binary = atob(base64)\n\t\tconst json = decodeURIComponent(\n\t\t\tArray.from(\n\t\t\t\tbinary,\n\t\t\t\t(char) => `%${char.charCodeAt(0).toString(16).padStart(2, \"0\")}`,\n\t\t\t).join(\"\"),\n\t\t)\n\t\tconst parsed = JSON.parse(json) as LoginEventData\n\t\treturn parsed && typeof parsed === \"object\" && parsed.type ? parsed : null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getLoginCallbackChannelName(state: string) {\n\treturn `youidian-login:${state}`\n}\n\nfunction getLoginCallbackStorageKey(state: string) {\n\treturn `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`\n}\n\nfunction publishLoginCallback(state: string, data: LoginEventData) {\n\ttry {\n\t\tconst channel = new BroadcastChannel(getLoginCallbackChannelName(state))\n\t\tchannel.postMessage(data)\n\t\tchannel.close()\n\t} catch {\n\t\t// BroadcastChannel is not available in every embedded browser.\n\t}\n\n\ttry {\n\t\tconst storageKey = getLoginCallbackStorageKey(state)\n\t\twindow.localStorage.setItem(storageKey, JSON.stringify(data))\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey)\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup failures.\n\t\t\t}\n\t\t}, 800)\n\t} catch {\n\t\t// localStorage may be disabled; postMessage remains available below.\n\t}\n\n\ttry {\n\t\twindow.opener?.postMessage(data, window.location.origin)\n\t} catch {\n\t\t// opener is only an opportunistic fast path.\n\t}\n}\n\nfunction safeIsPopupClosed(popup: Window | null) {\n\tif (!popup) return true\n\ttry {\n\t\treturn popup.closed\n\t} catch {\n\t\tlogLoginDebug(\"Unable to read popup.closed; treating popup as open\")\n\t\treturn false\n\t}\n}\n\nfunction safeClosePopup(popup: Window | null) {\n\tif (!popup) return\n\ttry {\n\t\tpopup.close()\n\t} catch {\n\t\tlogLoginDebug(\"Unable to close popup\")\n\t}\n}\n\nfunction cleanLoginCallbackUrl(url: URL) {\n\turl.searchParams.delete(LOGIN_CALLBACK_MARKER)\n\turl.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM)\n\tconst returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM)\n\turl.hash = returnHash ? `#${returnHash}` : \"\"\n\treturn url.toString()\n}\n\nexport function handleLoginCallbackIfPresent(options?: LoginCallbackOptions) {\n\tif (typeof window === \"undefined\") {\n\t\treturn false\n\t}\n\n\tconst url = new URL(window.location.href)\n\tif (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== \"1\") {\n\t\treturn false\n\t}\n\n\tconst state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || \"\"\n\tconst hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"))\n\tconst rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM)\n\tconst data: LoginEventData | null =\n\t\trawResult && state\n\t\t\t? decodeCallbackPayload(rawResult)\n\t\t\t: {\n\t\t\t\t\ttype: \"LOGIN_ERROR\",\n\t\t\t\t\tmessage: \"Missing login callback result\",\n\t\t\t\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"hidden\"\n\t} catch {\n\t\t// This is best-effort to avoid a visible callback-page flash.\n\t}\n\n\tif (state && data) {\n\t\tpublishLoginCallback(state, data)\n\t}\n\n\ttry {\n\t\twindow.history.replaceState(null, \"\", cleanLoginCallbackUrl(url))\n\t} catch {\n\t\t// Ignore history cleanup failures.\n\t}\n\n\tif (options?.autoClose === true) {\n\t\twindow.setTimeout(() => {\n\t\t\ttry {\n\t\t\t\twindow.close()\n\t\t\t} catch {\n\t\t\t\t// Some browsers disallow script-closing the current window.\n\t\t\t}\n\t\t}, 30)\n\t\treturn true\n\t}\n\n\ttry {\n\t\tdocument.documentElement.style.visibility = \"\"\n\t} catch {\n\t\t// Ignore visibility restoration failures.\n\t}\n\n\treturn true\n}\n\nfunction logLoginDebug(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.debug(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginInfo(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.info(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nfunction logLoginWarn(message: string, details?: Record<string, unknown>) {\n\tif (typeof console === \"undefined\") return\n\tconsole.warn(LOGIN_UI_LOG_PREFIX, message, details || {})\n}\n\nexport class LoginUI {\n\tprivate popup: Window | null = null\n\tprivate callbackChannel: BroadcastChannel | null = null\n\tprivate callbackStorageHandler: ((event: StorageEvent) => void) | null = null\n\tprivate messageHandler: ((event: MessageEvent) => void) | null = null\n\tprivate closeMonitor: number | null = null\n\tprivate completed = false\n\n\tprivate cleanup() {\n\t\tif (this.callbackChannel) {\n\t\t\tthis.callbackChannel.close()\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.callbackStorageHandler) {\n\t\t\twindow.removeEventListener(\"storage\", this.callbackStorageHandler)\n\t\t}\n\t\tif (typeof window !== \"undefined\" && this.messageHandler) {\n\t\t\twindow.removeEventListener(\"message\", this.messageHandler)\n\t\t}\n\t\tthis.callbackChannel = null\n\t\tthis.callbackStorageHandler = null\n\t\tif (typeof window !== \"undefined\" && this.closeMonitor) {\n\t\t\twindow.clearInterval(this.closeMonitor)\n\t\t}\n\t\tthis.messageHandler = null\n\t\tthis.closeMonitor = null\n\t\tthis.popup = null\n\t\tthis.completed = false\n\t}\n\n\tprivate handleLoginEvent(data: LoginEventData, options?: LoginUIOptions) {\n\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\tlogLoginDebug(\"Ignored non-login event payload\")\n\t\t\treturn\n\t\t}\n\n\t\tlogLoginInfo(\"Received login event\", {\n\t\t\ttype: data.type,\n\t\t})\n\n\t\tswitch (data.type) {\n\t\t\tcase \"LOGIN_SUCCESS\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tthis.completed = true\n\t\t\t\tlogLoginInfo(\"Login succeeded\", {\n\t\t\t\t\tchannel: data.channel || null,\n\t\t\t\t\tuserId: data.userId || null,\n\t\t\t\t})\n\t\t\t\toptions?.onSuccess?.(extractLoginResult(data))\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CANCELLED\":\n\t\t\t\tlogLoginInfo(\"Login cancelled\")\n\t\t\t\toptions?.onCancel?.()\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_RESIZE\":\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_ERROR\":\n\t\t\t\tif (this.completed) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginWarn(\"Login flow reported an error\", {\n\t\t\t\t\tmessage: data.message || data.error || null,\n\t\t\t\t})\n\t\t\t\toptions?.onError?.(data.message || data.error, data)\n\t\t\t\tbreak\n\t\t\tcase \"LOGIN_CLOSE\":\n\t\t\t\tif (options?.autoClose === false) {\n\t\t\t\t\tlogLoginInfo(\n\t\t\t\t\t\t\"Login popup requested close; autoClose disabled, keeping popup open\",\n\t\t\t\t\t)\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tlogLoginInfo(\"Login popup requested close; autoClose enabled\")\n\t\t\t\tthis.close()\n\t\t\t\toptions?.onClose?.()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate listenForLoginCallback(\n\t\tcallbackState: string,\n\t\toptions?: LoginUIOptions,\n\t) {\n\t\ttry {\n\t\t\tthis.callbackChannel = new BroadcastChannel(\n\t\t\t\tgetLoginCallbackChannelName(callbackState),\n\t\t\t)\n\t\t\tthis.callbackChannel.onmessage = (event) => {\n\t\t\t\tthis.handleLoginEvent(event.data as LoginEventData, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t}\n\t\t} catch {\n\t\t\tlogLoginDebug(\"BroadcastChannel is unavailable for login callback\")\n\t\t}\n\n\t\tthis.callbackStorageHandler = (event: StorageEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key !== getLoginCallbackStorageKey(callbackState) ||\n\t\t\t\t!event.newValue\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst data = JSON.parse(event.newValue) as LoginEventData\n\t\t\t\tthis.handleLoginEvent(data, options)\n\t\t\t\tthis.handleLoginEvent({ type: \"LOGIN_CLOSE\" }, options)\n\t\t\t} catch {\n\t\t\t\tlogLoginWarn(\"Failed to parse login callback storage payload\")\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", this.callbackStorageHandler)\n\t}\n\n\tclose() {\n\t\tlogLoginInfo(\"close() called\", {\n\t\t\thasPopup: Boolean(this.popup),\n\t\t\tpopupClosed: safeIsPopupClosed(this.popup),\n\t\t})\n\t\tsafeClosePopup(this.popup)\n\t\tthis.cleanup()\n\t}\n\n\topenLogin(params: LoginParams, options?: LoginUIOptions) {\n\t\tif (typeof window === \"undefined\") return\n\t\tif (this.popup && !safeIsPopupClosed(this.popup)) return\n\n\t\tconst callbackState = createLoginCallbackState()\n\t\tconst launchPayload = buildLoginLaunchPayload(\n\t\t\tparams,\n\t\t\toptions,\n\t\t\tcallbackState,\n\t\t)\n\t\tconst finalUrl = buildLoginUrl(params, options, launchPayload)\n\t\tlogLoginInfo(\"Opening hosted login popup\", {\n\t\t\tappId: params.appId,\n\t\t\tcallbackState,\n\t\t\tcallbackUrl: launchPayload.callbackUrl || null,\n\t\t\thasCallbackUrl: Boolean(launchPayload.callbackUrl),\n\t\t\tloginUrl: finalUrl,\n\t\t\tallowedOrigin: options?.allowedOrigin || null,\n\t\t\tautoClose: options?.autoClose ?? true,\n\t\t\tpageUrl: typeof window !== \"undefined\" ? window.location.href : null,\n\t\t\tparentOrigin: launchPayload.origin || null,\n\t\t})\n\t\tconst popupWidth = 520\n\t\tconst popupHeight = 720\n\t\tconst left = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenX + (window.outerWidth - popupWidth) / 2),\n\t\t)\n\t\tconst top = Math.max(\n\t\t\t0,\n\t\t\tMath.round(window.screenY + (window.outerHeight - popupHeight) / 2),\n\t\t)\n\t\tconst features = [\n\t\t\t\"popup=yes\",\n\t\t\t`width=${popupWidth}`,\n\t\t\t`height=${popupHeight}`,\n\t\t\t`left=${left}`,\n\t\t\t`top=${top}`,\n\t\t\t\"resizable=yes\",\n\t\t\t\"scrollbars=yes\",\n\t\t].join(\",\")\n\n\t\tconst popupName = buildLoginPopupName(launchPayload)\n\t\tconst popup = window.open(finalUrl, popupName, features)\n\t\tif (!popup) {\n\t\t\tlogLoginWarn(\"Popup blocked by the browser\")\n\t\t\toptions?.onError?.(\"Login popup was blocked\")\n\t\t\treturn\n\t\t}\n\n\t\tthis.popup = popup\n\t\tthis.completed = false\n\t\tthis.listenForLoginCallback(callbackState, options)\n\n\t\tconst allowedOrigin = options?.allowedOrigin\n\t\tconst popupOrigin = getOrigin(finalUrl)\n\n\t\tthis.messageHandler = (event: MessageEvent) => {\n\t\t\tif (\n\t\t\t\tallowedOrigin &&\n\t\t\t\tallowedOrigin !== \"*\" &&\n\t\t\t\tevent.origin !== allowedOrigin\n\t\t\t) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to allowedOrigin mismatch\", {\n\t\t\t\t\tallowedOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {\n\t\t\t\tlogLoginWarn(\"Ignored message due to popup origin mismatch\", {\n\t\t\t\t\texpectedOrigin: popupOrigin,\n\t\t\t\t\teventOrigin: event.origin,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst data = event.data as LoginEventData\n\t\t\tif (!data || typeof data !== \"object\" || !data.type) {\n\t\t\t\tlogLoginDebug(\"Ignored non-login postMessage payload\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogLoginInfo(\"Received login event\", {\n\t\t\t\ttype: data.type,\n\t\t\t\teventOrigin: event.origin,\n\t\t\t})\n\n\t\t\tthis.handleLoginEvent(data, options)\n\t\t}\n\n\t\twindow.addEventListener(\"message\", this.messageHandler)\n\n\t\tif (options?.monitorPopupClosed === true) {\n\t\t\tthis.closeMonitor = window.setInterval(() => {\n\t\t\t\tif (!this.popup || safeIsPopupClosed(this.popup)) {\n\t\t\t\t\tconst shouldTreatAsCancel = !this.completed\n\t\t\t\t\tlogLoginInfo(\"Detected popup closed\", {\n\t\t\t\t\t\tshouldTreatAsCancel,\n\t\t\t\t\t})\n\t\t\t\t\tthis.cleanup()\n\t\t\t\t\tif (shouldTreatAsCancel) {\n\t\t\t\t\t\toptions?.onCancel?.()\n\t\t\t\t\t}\n\t\t\t\t\toptions?.onClose?.()\n\t\t\t\t}\n\t\t\t}, 500)\n\t\t}\n\t}\n}\n\nexport function createLoginUI(): LoginUI {\n\treturn new LoginUI()\n}\n\nhandleLoginCallbackIfPresent({ autoClose: false })\n"],"mappings":"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","names":[]}