@thunderid/react 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ThunderIDReactClient.d.ts +5 -0
- package/dist/ThunderIDReactClient.d.ts.map +1 -1
- package/dist/ThunderIDReactClient.js +11 -1
- package/dist/ThunderIDReactClient.js.map +1 -1
- package/dist/cjs/ThunderIDReactClient.cjs +11 -1
- package/dist/cjs/ThunderIDReactClient.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs +1 -0
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignIn/SignIn.cjs +2 -3
- package/dist/cjs/components/presentation/auth/SignIn/SignIn.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs +1 -0
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs.map +1 -1
- package/dist/cjs/components/primitives/AffixedField/AffixedField.cjs +11 -1
- package/dist/cjs/components/primitives/AffixedField/AffixedField.cjs.map +1 -1
- package/dist/cjs/components/primitives/Checkbox/Checkbox.cjs +11 -1
- package/dist/cjs/components/primitives/Checkbox/Checkbox.cjs.map +1 -1
- package/dist/cjs/components/primitives/DatePicker/DatePicker.cjs +11 -1
- package/dist/cjs/components/primitives/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/cjs/components/primitives/FormControl/FormControl.cjs +2 -1
- package/dist/cjs/components/primitives/FormControl/FormControl.cjs.map +1 -1
- package/dist/cjs/components/primitives/MultiInput/MultiInput.cjs +11 -2
- package/dist/cjs/components/primitives/MultiInput/MultiInput.cjs.map +1 -1
- package/dist/cjs/components/primitives/OtpField/OtpField.cjs +9 -0
- package/dist/cjs/components/primitives/OtpField/OtpField.cjs.map +1 -1
- package/dist/cjs/components/primitives/Select/Select.cjs +8 -0
- package/dist/cjs/components/primitives/Select/Select.cjs.map +1 -1
- package/dist/cjs/components/primitives/TextField/TextField.cjs +11 -1
- package/dist/cjs/components/primitives/TextField/TextField.cjs.map +1 -1
- package/dist/cjs/components/primitives/Toggle/Toggle.cjs +10 -1
- package/dist/cjs/components/primitives/Toggle/Toggle.cjs.map +1 -1
- package/dist/cjs/contexts/Theme/ThemeProvider.cjs +1 -1
- package/dist/cjs/contexts/Theme/ThemeProvider.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +6 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts +4 -0
- package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js +1 -0
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js.map +1 -1
- package/dist/components/presentation/auth/SignIn/SignIn.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignIn/SignIn.js +2 -3
- package/dist/components/presentation/auth/SignIn/SignIn.js.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts +4 -0
- package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js +1 -0
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js.map +1 -1
- package/dist/components/primitives/AffixedField/AffixedField.d.ts.map +1 -1
- package/dist/components/primitives/AffixedField/AffixedField.js +11 -1
- package/dist/components/primitives/AffixedField/AffixedField.js.map +1 -1
- package/dist/components/primitives/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/primitives/Checkbox/Checkbox.js +10 -1
- package/dist/components/primitives/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/primitives/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/primitives/DatePicker/DatePicker.js +10 -1
- package/dist/components/primitives/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/primitives/FormControl/FormControl.d.ts +4 -0
- package/dist/components/primitives/FormControl/FormControl.d.ts.map +1 -1
- package/dist/components/primitives/FormControl/FormControl.js +2 -1
- package/dist/components/primitives/FormControl/FormControl.js.map +1 -1
- package/dist/components/primitives/MultiInput/MultiInput.d.ts.map +1 -1
- package/dist/components/primitives/MultiInput/MultiInput.js +12 -3
- package/dist/components/primitives/MultiInput/MultiInput.js.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.d.ts.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.js +10 -1
- package/dist/components/primitives/OtpField/OtpField.js.map +1 -1
- package/dist/components/primitives/Select/Select.d.ts.map +1 -1
- package/dist/components/primitives/Select/Select.js +9 -1
- package/dist/components/primitives/Select/Select.js.map +1 -1
- package/dist/components/primitives/TextField/TextField.d.ts.map +1 -1
- package/dist/components/primitives/TextField/TextField.js +10 -1
- package/dist/components/primitives/TextField/TextField.js.map +1 -1
- package/dist/components/primitives/Toggle/Toggle.d.ts.map +1 -1
- package/dist/components/primitives/Toggle/Toggle.js +9 -1
- package/dist/components/primitives/Toggle/Toggle.js.map +1 -1
- package/dist/contexts/Theme/ThemeProvider.d.ts.map +1 -1
- package/dist/contexts/Theme/ThemeProvider.js +1 -1
- package/dist/contexts/Theme/ThemeProvider.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts +4 -3
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.js +6 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignIn.cjs","names":["submitActions: EmbeddedFlowComponent[]","SignIn: FC<SignInProps>","useThunderID","useTranslation","challengeTokenRef: any","initializationAttemptedRef: any","oauthCodeProcessedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","urlParams: any","url: any","ThunderIDRuntimeError","EmbeddedSignInFlowType","redirectURL: any","EmbeddedSignInFlowStatus","extractErrorMessage","finalRedirectUrl: any","effectiveApplicationId: any","storedExecutionId: any","resumeExecutionId: any","error: any","response: EmbeddedSignInFlowResponse","ThunderIDAPIError","EmbeddedFlowType","normalizeFlowResponse","err: any","currentUrlParams: any","effectiveExecutionId: any","processedInputs: Record<string, any>","consentReason: string | undefined","consentPromptRawData: any","purposes: any[]","found: any","submitAction: any","ConsentConstants","reason: string | undefined","decisions: any","effectiveExecutionIdForPasskey: any","responseFieldErrors: FieldError[] | undefined","timeoutMs: number","actionId: string | undefined","timerId: ReturnType<typeof setTimeout>","inputs: Record<string, string>","passkeyResponse: any","handlePasskeyAuthentication","passkeyResponseObj: any","handlePasskeyRegistration","renderPropFieldErrors: Record<string, string>","BaseSignIn"],"sources":["../../../../../../src/components/presentation/auth/SignIn/SignIn.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ThunderIDRuntimeError,\n ThunderIDAPIError,\n ConsentConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowType,\n EmbeddedSignInFlowResponse,\n EmbeddedSignInFlowRequest,\n EmbeddedSignInFlowStatus,\n EmbeddedSignInFlowType,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n logger,\n} from '@thunderid/browser';\nimport {FC, ReactElement, useState, useEffect, useRef, ReactNode} from 'react';\n// eslint-disable-next-line import/no-named-as-default\nimport BaseSignIn, {BaseSignInProps} from './BaseSignIn';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../../hooks/useOAuthCallback';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../../utils/flowTransformer';\nimport {initiateOAuthRedirect} from '../../../../utils/oauth';\nimport {handlePasskeyAuthentication, handlePasskeyRegistration} from '../../../../utils/passkey';\n\n/**\n * Render props function parameters\n */\nexport interface SignInRenderProps {\n /**\n * Additional data from the flow response containing contextual information\n * like consent prompt details and session timeouts.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Current flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * Current error if any\n */\n error: Error | null;\n\n /**\n * Server-side field-level validation errors from the most recent flow response,\n * collapsed to one message per field (first error wins). Empty when no validation\n * failures are active. Render-prop consumers should display these alongside their\n * own client-side validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to manually initialize the flow\n */\n initialize: () => Promise<void>;\n\n /**\n * Whether the flow has been initialized\n */\n isInitialized: boolean;\n\n /**\n * Loading state indicator\n */\n isLoading: boolean;\n\n /**\n * Flag indicating whether the flow step timeout has expired.\n * Consuming components can use this to disable submit buttons.\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Function to submit authentication data (primary)\n */\n onSubmit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n}\n\n/**\n * Props for the SignIn component.\n * Matches the interface from the main SignIn component for consistency.\n */\nexport interface SignInProps {\n /**\n * Render props function for custom UI\n */\n children?: (props: SignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: BaseSignInProps['variant'];\n}\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n challenge: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Sentinel input key carrying the reason a consent prompt was submitted. It is folded into the\n * compiled `consent_decisions` payload and stripped from the inputs, like `__consent_opt__` keys.\n */\nconst CONSENT_REASON_KEY = '__consent_reason__';\n\n/** Flattens a component tree into a single list, parents before their children. */\nconst flattenComponents = (comps: EmbeddedFlowComponent[] | undefined): EmbeddedFlowComponent[] =>\n (comps ?? []).flatMap((comp: EmbeddedFlowComponent) => [comp, ...flattenComponents(comp.components)]);\n\n/**\n * Finds the action to submit an expired consent prompt with. A non-primary submit action is\n * preferred so the payload reads as a denial, falling back to any submit action because the server\n * needs an action to route the prompt node. Returns undefined when the view has neither.\n */\nconst findConsentSubmitActionId = (comps: EmbeddedFlowComponent[] | undefined): string | undefined => {\n const submitActions: EmbeddedFlowComponent[] = flattenComponents(comps).filter(\n (comp: EmbeddedFlowComponent) => comp.id && comp.eventType?.toUpperCase() === 'SUBMIT',\n );\n const denyAction: EmbeddedFlowComponent | undefined = submitActions.find(\n (comp: EmbeddedFlowComponent) => comp.variant?.toLowerCase() !== 'primary',\n );\n\n return (denyAction ?? submitActions[0])?.id;\n};\n\n/**\n * A component-driven SignIn component that provides authentication flow with pre-built styling.\n * This component handles the flow API calls for authentication and delegates UI logic to BaseSignIn.\n * It automatically transforms simple input-based responses into component-driven UI format.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => {\n * console.log('Authentication successful:', authData);\n * }}\n * onError={(error) => {\n * console.error('Authentication failed:', error);\n * }}\n * size=\"medium\"\n * variant=\"outlined\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => console.log('Success:', authData)}\n * onError={(error) => console.error('Error:', error)}\n * >\n * {({signIn, isLoading, components, error, isInitialized}) => (\n * <div className=\"custom-signin\">\n * <h1>Custom Sign In</h1>\n * {!isInitialized ? (\n * <p>Initializing...</p>\n * ) : error ? (\n * <div className=\"error\">{error.message}</div>\n * ) : (\n * <form onSubmit={(e) => {\n * e.preventDefault();\n * signIn({inputs: {username: 'user', password: 'pass'}});\n * }}>\n * <button type=\"submit\" disabled={isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign In'}\n * </button>\n * </form>\n * )}\n * </div>\n * )}\n * </SignIn>\n * );\n * };\n * ```\n */\nconst SignIn: FC<SignInProps> = ({\n className,\n preferences,\n size = 'medium',\n onSuccess,\n onError,\n variant,\n children,\n revalidateOnChangeAfterBlur,\n}: SignInProps): ReactElement => {\n const {applicationId, afterSignInUrl, signIn, isInitialized, isLoading, meta, getStorageManager, scopes, vendor} =\n useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n\n // State management for the flow\n const [components, setComponents] = useState<EmbeddedFlowComponent[]>([]);\n const [additionalData, setAdditionalData] = useState<Record<string, any>>({});\n // Server-side validation errors from the most recent flow response. Updated on every\n // submission; cleared when the next submission begins so stale errors don't linger.\n const [serverFieldErrors, setServerFieldErrors] = useState<FieldError[] | null>(null);\n const [currentExecutionId, setCurrentExecutionId] = useState<string | null>(null);\n const challengeTokenRef: any = useRef<string | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [flowError, setFlowError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isTimeoutDisabled, setIsTimeoutDisabled] = useState<boolean>(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const initializationAttemptedRef: any = useRef(false);\n const oauthCodeProcessedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // Deadline this component has already auto-submitted for, so a re-run of the timeout effect\n // cannot submit the same expired step twice.\n const timeoutSubmittedForRef = useRef<number | null>(null);\n // The timeout effect is keyed on the deadline alone, so a step that arrives carrying the same\n // deadline would otherwise leave the pending timer holding the previous step's context.\n const timeoutContextRef = useRef<{\n components: EmbeddedFlowComponent[];\n hasConsentPrompt: boolean;\n submit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n } | null>(null);\n /**\n * Sets executionId between sessionStorage and state.\n * This ensures both are always in sync.\n */\n const setExecutionId = (executionId: string | null): void => {\n setCurrentExecutionId(executionId);\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n } else {\n sessionStorage.removeItem(`${vendor}_execution_id`);\n }\n };\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Clear all flow-related storage and state.\n */\n const clearFlowState = async (): Promise<void> => {\n // Clear the expired flow state to prevent rendering a stale form with a null executionId.\n // Kept before the first await so callers that do not await this function still apply the\n // reset in one batch, ahead of the setError that follows.\n setExecutionId(null);\n setComponents([]);\n setAdditionalData({});\n setIsFlowInitialized(false);\n await setChallengeToken(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n setIsTimeoutDisabled(false);\n // Reset refs to allow new flows to start properly\n oauthCodeProcessedRef.current = false;\n };\n\n /**\n * Parse URL parameters used in flows.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n\n return {\n applicationId: urlParams.get('applicationId'),\n authId: urlParams.get('authId'),\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n errorDescription: urlParams.get('error_description'),\n executionId: urlParams.get('executionId'),\n nonce: urlParams.get('nonce'),\n state: urlParams.get('state'),\n };\n };\n\n /**\n * Handle authId from URL and persist it via the storage manager so it survives URL cleanup.\n * ThunderIDReactClient.signIn() reads authId from storageManager.getHybridDataParameter('authId'),\n * not from raw sessionStorage, so we must use the same storage path here.\n */\n const handleAuthId = async (authId: string | null): Promise<void> => {\n if (authId) {\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.setHybridDataParameter?.('authId', authId);\n } catch {\n logger.warn('Failed to store authId in hybrid storage.');\n }\n }\n };\n\n /**\n * Clean up OAuth-related URL parameters from the browser URL.\n */\n const cleanupOAuthUrlParams = (includeNonce = false): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('error');\n url.searchParams.delete('error_description');\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n if (includeNonce) {\n url.searchParams.delete('nonce');\n }\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Clean up flow-related URL parameters (executionId, authId) from the browser URL.\n * Used after executionId is set in state to prevent using invalidated executionId from URL.\n */\n const cleanupFlowUrlParams = (): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('authId');\n url.searchParams.delete('applicationId');\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Set error state and call onError callback.\n * Ensures isFlowInitialized is true so errors can be displayed in the UI.\n */\n const setError = (error: Error): void => {\n setFlowError(error);\n setIsFlowInitialized(true);\n onError?.(error);\n };\n\n /**\n * Handle OAuth error from URL parameters.\n * Clears flow state, creates error, and cleans up URL.\n */\n const handleOAuthError = (error: string, errorDescription: string | null): void => {\n clearFlowState();\n const errorMessage: any = errorDescription || `OAuth error: ${error}`;\n const err: any = new ThunderIDRuntimeError(errorMessage, 'SIGN_IN_ERROR', 'react');\n setError(err);\n cleanupOAuthUrlParams(true);\n };\n\n /**\n * Handle REDIRECTION response by storing flow state and redirecting to OAuth provider.\n */\n const handleRedirection = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.type === EmbeddedSignInFlowType.Redirection) {\n const redirectURL: any = (response.data as any)?.redirectURL || (response as any)?.redirectURL;\n\n if (redirectURL && window?.location) {\n if (response.executionId) {\n setExecutionId(response.executionId);\n }\n await setChallengeToken(response.challengeToken ?? null);\n\n const urlParams: any = getUrlParams();\n await handleAuthId(urlParams.authId);\n\n initiateOAuthRedirect(redirectURL, vendor);\n return true;\n }\n }\n return false;\n };\n\n /**\n * Handle ERROR and COMPLETE responses. Returns true if fully handled.\n * ERROR + executionId: recoverable — session preserved for retry.\n * ERROR + no executionId: terminal — clear state and surface the error.\n */\n const handleTerminalResponse = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error) {\n // Propagate OAuth error to the client\n if (response.redirectUrl && window?.location) {\n setIsSubmitting(false);\n await clearFlowState();\n cleanupOAuthUrlParams(true);\n onError?.(new Error(extractErrorMessage(response, t)));\n window.location.href = response.redirectUrl;\n\n return true;\n }\n\n if (response.executionId) {\n // Recoverable: session still alive. Show inline error without firing onError.\n setExecutionId(response.executionId);\n await setChallengeToken(response.challengeToken ?? null);\n setIsFlowInitialized(true);\n setFlowError(new Error(extractErrorMessage(response, t)));\n return true;\n }\n // Terminal: backend invalidated the session — clear all state.\n await clearFlowState();\n setError(new Error(extractErrorMessage(response, t)));\n cleanupFlowUrlParams();\n return true;\n }\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // Get redirectUrl from response (from /oauth2/auth/callback) or fall back to afterSignInUrl\n const redirectUrl: any = (response as any)?.redirectUrl || (response as any)?.redirect_uri;\n const finalRedirectUrl: any = redirectUrl || afterSignInUrl;\n\n // Clear submitting state before redirect\n setIsSubmitting(false);\n\n // Clear all OAuth-related storage on successful completion\n setExecutionId(null);\n await setChallengeToken(null);\n setIsFlowInitialized(false);\n sessionStorage.removeItem(`${vendor}_execution_id`);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage after completion.');\n }\n\n // Clean up OAuth URL params before redirect\n cleanupOAuthUrlParams(true);\n\n if (onSuccess) {\n onSuccess({\n redirectUrl: finalRedirectUrl,\n ...(response.data || {}),\n });\n }\n\n if (finalRedirectUrl && window?.location) {\n window.location.href = finalRedirectUrl;\n }\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Initialize the authentication flow.\n * Priority: executionId > applicationId (from context) > applicationId (from URL)\n */\n const initializeFlow = async (): Promise<void> => {\n const urlParams: any = getUrlParams();\n\n // Reset OAuth code processed ref when starting a new flow\n oauthCodeProcessedRef.current = false;\n // Clear stale serverFieldErrors so the new flow doesn't inherit them via render-prop.\n setServerFieldErrors(null);\n\n await handleAuthId(urlParams.authId);\n\n const effectiveApplicationId: any = applicationId || urlParams.applicationId;\n\n // On a page refresh the executionId is no longer in the URL (it is scrubbed by\n // cleanupFlowUrlParams after the first load). Fall back to the executionId persisted in\n // sessionStorage so the in-progress flow can be resumed instead of starting a new flow.\n // This is required for authorization_code apps where direct new-flow initiation is blocked\n // server-side and the flow must be initiated through the OAuth /authorize endpoint.\n const storedExecutionId: any = !urlParams.executionId ? sessionStorage.getItem(`${vendor}_execution_id`) : null;\n const resumeExecutionId: any = urlParams.executionId || storedExecutionId;\n\n if (!resumeExecutionId && !effectiveApplicationId) {\n const error: any = new ThunderIDRuntimeError(\n 'Either executionId or applicationId is required for authentication',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(error);\n throw error;\n }\n\n try {\n setFlowError(null);\n\n let response: EmbeddedSignInFlowResponse;\n\n if (resumeExecutionId) {\n try {\n response = (await signIn({\n executionId: resumeExecutionId,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n } catch (resumeError) {\n // Only treat a stale/expired session (HTTP 400 from the server, meaning the stored\n // executionId is no longer valid) as a recoverable condition. Transient failures\n // such as 5xx server errors or network errors are rethrown so they surface correctly.\n const isStaleSession: boolean =\n storedExecutionId &&\n resumeExecutionId === storedExecutionId &&\n resumeError instanceof ThunderIDAPIError &&\n resumeError.statusCode === 400;\n\n if (isStaleSession) {\n setExecutionId(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n if (!effectiveApplicationId) {\n const expiredError: any = new ThunderIDRuntimeError(\n t('errors.signin.session.expired') ||\n 'Your session has expired. Please return to the application and sign in again.',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(expiredError);\n return;\n }\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n } else {\n throw resumeError;\n }\n }\n } else {\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n }\n\n if (await handleRedirection(response)) {\n return;\n }\n\n // Handle a flow that completes (or errors) on the very first step — e.g. a reused SSO\n // session lets the backend return COMPLETE immediately with no UI components. Without\n // this the UI would fall through with no components and spin forever.\n if (await handleTerminalResponse(response)) {\n // Only reset the init gate for unrecoverable Error responses so the user can retry;\n // Complete-without-redirect would otherwise kick off a fresh flow unintentionally.\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error && !response.executionId) {\n initializationAttemptedRef.current = false;\n }\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsFlowInitialized(true);\n setIsTimeoutDisabled(false);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n initializationAttemptedRef.current = false;\n }\n };\n\n /**\n * Initialize the flow and handle cleanup of stale flow state.\n */\n useEffect(() => {\n const urlParams: any = getUrlParams();\n\n // Check for OAuth error in URL\n if (urlParams.error) {\n handleOAuthError(urlParams.error, urlParams.errorDescription);\n return;\n }\n\n handleAuthId(urlParams.authId);\n\n // Skip OAuth code processing - let the dedicated OAuth useEffect handle it\n // No action needed here as the dedicated useEffect will handle it\n }, []);\n\n useEffect(() => {\n // Only initialize if we're not processing an OAuth callback or submission.\n // Wait for isStorageReady so the challenge token is restored from storage before\n // we attempt to resume a persisted executionId — the server requires it.\n const currentUrlParams: any = getUrlParams();\n if (\n isInitialized &&\n isStorageReady &&\n !isLoading &&\n !isFlowInitialized &&\n !initializationAttemptedRef.current &&\n !currentExecutionId &&\n !currentUrlParams.code &&\n !currentUrlParams.state &&\n !isSubmitting &&\n !oauthCodeProcessedRef.current\n ) {\n initializationAttemptedRef.current = true;\n initializeFlow();\n }\n }, [isInitialized, isStorageReady, isLoading, isFlowInitialized, currentExecutionId]);\n\n /**\n * Handle form submission from BaseSignIn or render props.\n */\n const handleSubmit = async (payload: EmbeddedSignInFlowRequest): Promise<void> => {\n // Use executionId from payload if available, otherwise fall back to currentExecutionId\n const effectiveExecutionId: any = payload.executionId || currentExecutionId;\n\n if (!effectiveExecutionId) {\n throw new Error('No active flow ID');\n }\n\n const processedInputs: Record<string, any> = {...payload.inputs};\n\n // Read and strip the sentinel up front so it can never reach the wire as an input\n const consentReason: string | undefined = processedInputs[CONSENT_REASON_KEY];\n delete processedInputs[CONSENT_REASON_KEY];\n\n // Auto-compile consent decisions if we are currently on a consent prompt step\n if (additionalData?.['consentPrompt']) {\n try {\n const consentPromptRawData: any = additionalData['consentPrompt'];\n const purposes: any[] =\n typeof consentPromptRawData === 'string'\n ? JSON.parse(consentPromptRawData)\n : consentPromptRawData.purposes || consentPromptRawData;\n\n // Find the action component to determine if it was a deny action\n let isDeny = false;\n if (payload.action) {\n // Flatten components to find the action\n const findAction = (comps: any[]): any => {\n if (!comps || comps.length === 0) return null;\n\n const found: any = comps.find((c: any) => c.id === payload.action);\n if (found) return found;\n\n return comps.reduce((acc: any, c: any) => {\n if (acc) return acc;\n if (c.components) return findAction(c.components);\n return null;\n }, null);\n };\n\n const submitAction: any = findAction(components);\n\n if (submitAction && submitAction.variant?.toLowerCase() !== 'primary') {\n isDeny = true;\n }\n }\n\n // An expired prompt is never an approval, whichever action carried the submission\n if (consentReason === ConsentConstants.REASON_TIMEOUT) {\n isDeny = true;\n }\n\n // An explicit denial carries a reason too, so the server never has to infer one\n const reason: string | undefined = consentReason ?? (isDeny ? ConsentConstants.REASON_USER_DENIED : undefined);\n\n const decisions: any = {\n approved: !isDeny,\n ...(reason ? {reason} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n elements: [\n ...(p.essential || []).map((e: any) => ({\n approved: !isDeny,\n name: e.name,\n })),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n return {\n approved: !isDeny && processedInputs[key] === 'true',\n name: e.name,\n };\n }),\n ],\n purposeName: p.purposeName,\n })),\n };\n processedInputs['consent_decisions'] = JSON.stringify(decisions);\n\n // Cleanup temporary consent tracking fields from inputs\n Object.keys(processedInputs).forEach((key: string) => {\n if (key.startsWith('__consent_opt__')) {\n delete processedInputs[key];\n }\n });\n } catch (e) {\n // Failed to construct consent_decisions payload automatically\n }\n }\n\n try {\n setIsSubmitting(true);\n setFlowError(null);\n // Clear any field errors from the previous response before the new round-trip.\n setServerFieldErrors(null);\n\n const response: EmbeddedSignInFlowResponse = (await signIn({\n executionId: effectiveExecutionId,\n ...payload,\n inputs: processedInputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n\n if (await handleRedirection(response)) {\n return;\n }\n if (\n response.data?.additionalData?.['passkeyChallenge'] ||\n response.data?.additionalData?.['passkeyCreationOptions']\n ) {\n const {passkeyChallenge, passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId || effectiveExecutionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: 'submit',\n challenge: passkeyChallenge,\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsSubmitting(false);\n\n return;\n }\n\n // Handle terminal flow statuses before normalization.\n if (await handleTerminalResponse(response)) {\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n // Always update challenge token on any INCOMPLETE response — token rotates every step.\n await setChallengeToken(response.challengeToken ?? null);\n\n // Update executionId if response contains a new one\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsTimeoutDisabled(false);\n // Ensure flow is marked as initialized when we have components\n setIsFlowInitialized(true);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n\n // Surface server-side validation failures so BaseSignIn can inject them into\n // the form-level fieldErrors state used by the render-prop / default UI.\n const responseFieldErrors: FieldError[] | undefined = (response.data as any)?.fieldErrors;\n if (responseFieldErrors && responseFieldErrors.length > 0) {\n setServerFieldErrors(responseFieldErrors);\n }\n\n // Display error from INCOMPLETE response\n if ((response as any)?.error) {\n setFlowError(new Error(extractErrorMessage(response, t)));\n }\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n return;\n } finally {\n setIsSubmitting(false);\n }\n };\n\n /**\n * Handle step timeout if configured in additionalData.\n *\n * An expired consent prompt is auto-submitted as a denial carrying the timeout reason, because its\n * actions no longer lead anywhere and the user would otherwise be stranded on the prompt. The\n * server discards those decisions and records nothing. Every other kind of step surfaces the\n * expiry error instead.\n */\n timeoutContextRef.current = {\n components,\n hasConsentPrompt: Boolean(additionalData?.['consentPrompt']),\n submit: handleSubmit,\n };\n\n useEffect(() => {\n const timeoutMs: number = Number(additionalData?.['stepTimeout']) || 0;\n if (timeoutMs <= 0 || !isFlowInitialized) {\n setIsTimeoutDisabled(false);\n return undefined;\n }\n\n const handleTimeout = (): void => {\n setIsTimeoutDisabled(true);\n\n const expiredError = (): Error =>\n new Error(t('errors.signin.timeout') || 'Time allowed to complete the step has expired.');\n\n // Read through the ref so the timer always sees the step that is on screen when it fires\n const context = timeoutContextRef.current;\n const actionId: string | undefined = context?.hasConsentPrompt\n ? findConsentSubmitActionId(context.components)\n : undefined;\n\n // Without an action the prompt node cannot be routed, so there is nothing to submit\n if (actionId && context && timeoutSubmittedForRef.current !== timeoutMs) {\n timeoutSubmittedForRef.current = timeoutMs;\n context\n .submit({action: actionId, inputs: {[CONSENT_REASON_KEY]: ConsentConstants.REASON_TIMEOUT}})\n .catch(() => setError(expiredError()));\n return;\n }\n\n setError(expiredError());\n };\n\n const timerId: ReturnType<typeof setTimeout> = setTimeout(handleTimeout, Math.max(0, timeoutMs - Date.now()));\n\n return () => clearTimeout(timerId);\n }, [additionalData?.['stepTimeout'], isFlowInitialized, t]);\n\n /**\n * Handle authentication errors.\n */\n const handleError = (error: Error): void => {\n setError(error);\n };\n\n useOAuthCallback({\n currentExecutionId,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isInitialized && !isLoading && isStorageReady,\n isSubmitting,\n onError: (err: any) => {\n clearFlowState();\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n onSubmit: async (payload: any) => handleSubmit({executionId: payload.executionId, inputs: payload.inputs}),\n processedRef: oauthCodeProcessedRef,\n setExecutionId,\n });\n\n /**\n * Handle passkey authentication/registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (\n !passkeyState.isActive ||\n (!passkeyState.challenge && !passkeyState.creationOptions) ||\n !passkeyState.executionId\n ) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyProcess = async (): Promise<void> => {\n let inputs: Record<string, string>;\n\n if (passkeyState.challenge) {\n const passkeyResponse: any = await handlePasskeyAuthentication(passkeyState.challenge);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n authenticatorData: passkeyResponseObj.response.authenticatorData,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n signature: passkeyResponseObj.response.signature,\n userHandle: passkeyResponseObj.response.userHandle,\n };\n } else if (passkeyState.creationOptions) {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n } else {\n throw new Error('No passkey challenge or creation options available');\n }\n\n await handleSubmit({\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n });\n };\n\n performPasskeyProcess()\n .then(() => {\n setPasskeyState({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n setFlowError(error as Error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.executionId]);\n\n if (children) {\n // Collapse the server FieldError[] array to a single message per field map for\n // render-prop consumers. First error per field wins. Multi-error cases per\n // field are rare in practice (server typically returns one rule failure per\n // field in current flows) and consumers needing the full array can still read\n // it from the raw flow response.\n const renderPropFieldErrors: Record<string, string> = {};\n if (serverFieldErrors) {\n for (const fe of serverFieldErrors) {\n if (!(fe.identifier in renderPropFieldErrors)) {\n renderPropFieldErrors[fe.identifier] = fe.message;\n }\n }\n }\n\n const renderProps: SignInRenderProps = {\n additionalData,\n components,\n error: flowError,\n fieldErrors: renderPropFieldErrors,\n initialize: initializeFlow,\n isInitialized: isFlowInitialized,\n isLoading: isLoading || isSubmitting || !isInitialized,\n isTimeoutDisabled,\n meta,\n onSubmit: handleSubmit,\n };\n\n return <>{children(renderProps)}</>;\n }\n // Otherwise, render the default BaseSignIn component\n return (\n <BaseSignIn\n additionalData={additionalData}\n components={components}\n isLoading={isLoading || !isInitialized || !isFlowInitialized}\n isTimeoutDisabled={isTimeoutDisabled}\n onSubmit={handleSubmit}\n onError={handleError}\n error={flowError}\n className={className}\n size={size}\n variant={variant}\n preferences={preferences}\n revalidateOnChangeAfterBlur={revalidateOnChangeAfterBlur}\n serverFieldErrors={serverFieldErrors}\n />\n );\n};\n\nexport default SignIn;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6JA,MAAM,qBAAqB;;AAG3B,MAAM,qBAAqB,WACxB,SAAS,EAAE,EAAE,SAAS,SAAgC,CAAC,MAAM,GAAG,kBAAkB,KAAK,WAAW,CAAC,CAAC;;;;;;AAOvG,MAAM,6BAA6B,UAAmE;CACpG,MAAMA,gBAAyC,kBAAkB,MAAM,CAAC,QACrE,SAAgC,KAAK,MAAM,KAAK,WAAW,aAAa,KAAK,SAC/E;AAKD,SAJsD,cAAc,MACjE,SAAgC,KAAK,SAAS,aAAa,KAAK,UAClE,IAEqB,cAAc,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgE3C,MAAMC,UAA2B,EAC/B,WACA,aACA,OAAO,UACP,WACA,SACA,SACA,UACA,kCAC+B;CAC/B,MAAM,EAAC,eAAe,gBAAgB,QAAQ,eAAe,WAAW,MAAM,mBAAmB,QAAQ,WACvGC,8BAAc;CAChB,MAAM,EAAC,MAAKC,+BAAe,aAAa,KAAK;CAG7C,MAAM,CAAC,YAAY,qCAAmD,EAAE,CAAC;CACzE,MAAM,CAAC,gBAAgB,yCAAmD,EAAE,CAAC;CAG7E,MAAM,CAAC,mBAAmB,4CAAsD,KAAK;CACrF,MAAM,CAAC,oBAAoB,6CAAiD,KAAK;CACjF,MAAMC,sCAA+C,KAAK;CAC1D,MAAM,CAAC,gBAAgB,yCAA8B,MAAM;CAC3D,MAAM,CAAC,mBAAmB,4CAAiC,MAAM;CACjE,MAAM,CAAC,WAAW,oCAAuC,KAAK;CAC9D,MAAM,CAAC,cAAc,uCAA4B,MAAM;CACvD,MAAM,CAAC,mBAAmB,4CAA0C,MAAM;CAC1E,MAAM,CAAC,cAAc,uCAA0C;EAC7D,UAAU;EACV,WAAW;EACX,iBAAiB;EACjB,OAAO;EACP,aAAa;EACb,UAAU;EACX,CAAC;CACF,MAAMC,+CAAyC,MAAM;CACrD,MAAMC,0CAAoC,MAAM;CAChD,MAAMC,wCAAkC,MAAM;CAG9C,MAAM,2CAA+C,KAAK;CAG1D,MAAM,sCAII,KAAK;;;;;CAKf,MAAM,kBAAkB,gBAAqC;AAC3D,wBAAsB,YAAY;AAClC,MAAI,YACF,gBAAe,QAAQ,GAAG,OAAO,gBAAgB,YAAY;MAE7D,gBAAe,WAAW,GAAG,OAAO,eAAe;;;;;;AAQvD,4BAAgB;AACd,MAAI,CAAC,cAAe;AAEpB,GAAC,YAA2B;AAC1B,OAAI;IAEF,MAAMC,WAAgB,OADM,MAAM,mBAAmB,GACT,kBAAkB;AAC9D,QAAI,UAAU,eACZ,mBAAkB,UAAU,SAAS;aAE/B;AACR,sBAAkB,KAAK;;MAEvB;IACH,CAAC,cAAc,CAAC;;;;;CAMnB,MAAM,oBAAoB,OAAO,mBAAiD;AAChF,oBAAkB,UAAU;AAC5B,MAAI;GACF,MAAMC,iBAAsB,MAAM,mBAAmB;AACrD,OAAI,eACF,KAAI,eACF,OAAM,eAAe,0BAA0B,kBAAkB,eAAe;OAEhF,OAAM,eAAe,6BAA6B,iBAAiB;UAGjE;AACN,8BAAO,KAAK,gDAAgD;;;;;;CAOhE,MAAM,iBAAiB,YAA2B;AAIhD,iBAAe,KAAK;AACpB,gBAAc,EAAE,CAAC;AACjB,oBAAkB,EAAE,CAAC;AACrB,uBAAqB,MAAM;AAC3B,QAAM,kBAAkB,KAAK;AAC7B,MAAI;AAEF,UAD4B,MAAM,mBAAmB,GAC/B,4BAA4B,SAAS;UACrD;AACN,8BAAO,KAAK,8CAA8C;;AAE5D,uBAAqB,MAAM;AAE3B,wBAAsB,UAAU;;;;;CAMlC,MAAM,qBAA0B;EAC9B,MAAMC,YAAiB,IAAI,IAAI,QAAQ,UAAU,QAAQ,GAAG,CAAC;AAE7D,SAAO;GACL,eAAe,UAAU,IAAI,gBAAgB;GAC7C,QAAQ,UAAU,IAAI,SAAS;GAC/B,MAAM,UAAU,IAAI,OAAO;GAC3B,OAAO,UAAU,IAAI,QAAQ;GAC7B,kBAAkB,UAAU,IAAI,oBAAoB;GACpD,aAAa,UAAU,IAAI,cAAc;GACzC,OAAO,UAAU,IAAI,QAAQ;GAC7B,OAAO,UAAU,IAAI,QAAQ;GAC9B;;;;;;;CAQH,MAAM,eAAe,OAAO,WAAyC;AACnE,MAAI,OACF,KAAI;AAEF,UAD4B,MAAM,mBAAmB,GAC/B,yBAAyB,UAAU,OAAO;UAC1D;AACN,8BAAO,KAAK,4CAA4C;;;;;;CAQ9D,MAAM,yBAAyB,eAAe,UAAgB;AAC5D,MAAI,CAAC,QAAQ,UAAU,KAAM;EAC7B,MAAMC,MAAW,IAAI,IAAI,OAAO,SAAS,KAAK;AAC9C,MAAI,aAAa,OAAO,QAAQ;AAChC,MAAI,aAAa,OAAO,oBAAoB;AAC5C,MAAI,aAAa,OAAO,OAAO;AAC/B,MAAI,aAAa,OAAO,QAAQ;AAChC,MAAI,aACF,KAAI,aAAa,OAAO,QAAQ;AAElC,UAAQ,SAAS,aAAa,EAAE,EAAE,IAAI,IAAI,UAAU,CAAC;;;;;;CAOvD,MAAM,6BAAmC;AACvC,MAAI,CAAC,QAAQ,UAAU,KAAM;EAC7B,MAAMA,MAAW,IAAI,IAAI,OAAO,SAAS,KAAK;AAC9C,MAAI,aAAa,OAAO,cAAc;AACtC,MAAI,aAAa,OAAO,SAAS;AACjC,MAAI,aAAa,OAAO,gBAAgB;AACxC,UAAQ,SAAS,aAAa,EAAE,EAAE,IAAI,IAAI,UAAU,CAAC;;;;;;CAOvD,MAAM,YAAY,UAAuB;AACvC,eAAa,MAAM;AACnB,uBAAqB,KAAK;AAC1B,YAAU,MAAM;;;;;;CAOlB,MAAM,oBAAoB,OAAe,qBAA0C;AACjF,kBAAgB;AAGhB,WADiB,IAAIC,0CADK,oBAAoB,gBAAgB,SACL,iBAAiB,QAAQ,CACrE;AACb,wBAAsB,KAAK;;;;;CAM7B,MAAM,oBAAoB,OAAO,aAA2D;AAC1F,MAAI,SAAS,SAASC,2CAAuB,aAAa;GACxD,MAAMC,cAAoB,SAAS,MAAc,eAAgB,UAAkB;AAEnF,OAAI,eAAe,QAAQ,UAAU;AACnC,QAAI,SAAS,YACX,gBAAe,SAAS,YAAY;AAEtC,UAAM,kBAAkB,SAAS,kBAAkB,KAAK;AAGxD,UAAM,aADiB,cAAc,CACR,OAAO;AAEpC,wCAAsB,aAAa,OAAO;AAC1C,WAAO;;;AAGX,SAAO;;;;;;;CAQT,MAAM,yBAAyB,OAAO,aAA2D;AAC/F,MAAI,SAAS,eAAeC,6CAAyB,OAAO;AAE1D,OAAI,SAAS,eAAe,QAAQ,UAAU;AAC5C,oBAAgB,MAAM;AACtB,UAAM,gBAAgB;AACtB,0BAAsB,KAAK;AAC3B,cAAU,IAAI,MAAMC,4CAAoB,UAAU,EAAE,CAAC,CAAC;AACtD,WAAO,SAAS,OAAO,SAAS;AAEhC,WAAO;;AAGT,OAAI,SAAS,aAAa;AAExB,mBAAe,SAAS,YAAY;AACpC,UAAM,kBAAkB,SAAS,kBAAkB,KAAK;AACxD,yBAAqB,KAAK;AAC1B,iBAAa,IAAI,MAAMA,4CAAoB,UAAU,EAAE,CAAC,CAAC;AACzD,WAAO;;AAGT,SAAM,gBAAgB;AACtB,YAAS,IAAI,MAAMA,4CAAoB,UAAU,EAAE,CAAC,CAAC;AACrD,yBAAsB;AACtB,UAAO;;AAGT,MAAI,SAAS,eAAeD,6CAAyB,UAAU;GAG7D,MAAME,mBADoB,UAAkB,eAAgB,UAAkB,gBACjC;AAG7C,mBAAgB,MAAM;AAGtB,kBAAe,KAAK;AACpB,SAAM,kBAAkB,KAAK;AAC7B,wBAAqB,MAAM;AAC3B,kBAAe,WAAW,GAAG,OAAO,eAAe;AACnD,OAAI;AAEF,WAD4B,MAAM,mBAAmB,GAC/B,4BAA4B,SAAS;WACrD;AACN,+BAAO,KAAK,+DAA+D;;AAI7E,yBAAsB,KAAK;AAE3B,OAAI,UACF,WAAU;IACR,aAAa;IACb,GAAI,SAAS,QAAQ,EAAE;IACxB,CAAC;AAGJ,OAAI,oBAAoB,QAAQ,SAC9B,QAAO,SAAS,OAAO;AAGzB,UAAO;;AAGT,SAAO;;;;;;CAOT,MAAM,iBAAiB,YAA2B;EAChD,MAAMP,YAAiB,cAAc;AAGrC,wBAAsB,UAAU;AAEhC,uBAAqB,KAAK;AAE1B,QAAM,aAAa,UAAU,OAAO;EAEpC,MAAMQ,yBAA8B,iBAAiB,UAAU;EAO/D,MAAMC,oBAAyB,CAAC,UAAU,cAAc,eAAe,QAAQ,GAAG,OAAO,eAAe,GAAG;EAC3G,MAAMC,oBAAyB,UAAU,eAAe;AAExD,MAAI,CAAC,qBAAqB,CAAC,wBAAwB;GACjD,MAAMC,QAAa,IAAIT,0CACrB,sEACA,iBACA,QACD;AACD,YAAS,MAAM;AACf,SAAM;;AAGR,MAAI;AACF,gBAAa,KAAK;GAElB,IAAIU;AAEJ,OAAI,kBACF,KAAI;AACF,eAAY,MAAM,OAAO;KACvB,aAAa;KACb,GAAI,kBAAkB,UAAU,EAAC,gBAAgB,kBAAkB,SAAQ,GAAG,EAAE;KACjF,CAAC;YACK,aAAa;AAUpB,QALE,qBACA,sBAAsB,qBACtB,uBAAuBC,yCACvB,YAAY,eAAe,KAET;AAClB,oBAAe,KAAK;AACpB,SAAI;AAEF,aAD4B,MAAM,mBAAmB,GAC/B,4BAA4B,SAAS;aACrD;AACN,iCAAO,KAAK,8CAA8C;;AAE5D,SAAI,CAAC,wBAAwB;AAO3B,eAN0B,IAAIX,0CAC5B,EAAE,gCAAgC,IAChC,iFACF,iBACA,QACD,CACqB;AACtB;;AAEF,gBAAY,MAAM,OAAO;MACvB,eAAe;MACf,UAAUY,qCAAiB;MAC3B,GAAI,UAAU,EAAC,QAAO;MACvB,CAAC;UAEF,OAAM;;OAIV,YAAY,MAAM,OAAO;IACvB,eAAe;IACf,UAAUA,qCAAiB;IAC3B,GAAI,UAAU,EAAC,QAAO;IACvB,CAAC;AAGJ,OAAI,MAAM,kBAAkB,SAAS,CACnC;AAMF,OAAI,MAAM,uBAAuB,SAAS,EAAE;AAG1C,QAAI,SAAS,eAAeT,6CAAyB,SAAS,CAAC,SAAS,YACtE,4BAA2B,UAAU;AAEvC;;GAGF,MAAM,EACJ,aAAa,uBACb,YAAY,sBACZ,gBAAgB,6BACdU,8CACF,UACA,GACA,EACE,qBAAqB,OACtB,EACD,KACD;AAED,SAAM,kBAAkB,SAAS,kBAAkB,KAAK;AAExD,OAAI,yBAAyB,sBAAsB;AACjD,mBAAe,sBAAsB;AACrC,kBAAc,qBAAqB;AACnC,sBAAkB,4BAA4B,EAAE,CAAC;AACjD,yBAAqB,KAAK;AAC1B,yBAAqB,MAAM;AAE3B,0BAAsB;;WAEjB,OAAO;GACd,MAAMC,MAAW;AACjB,SAAM,gBAAgB;AAEtB,YAAS,eAAed,4CAAwB,MAAM,IAAI,MAAMI,4CAAoB,KAAK,EAAE,CAAC,CAAC;AAC7F,8BAA2B,UAAU;;;;;;AAOzC,4BAAgB;EACd,MAAMN,YAAiB,cAAc;AAGrC,MAAI,UAAU,OAAO;AACnB,oBAAiB,UAAU,OAAO,UAAU,iBAAiB;AAC7D;;AAGF,eAAa,UAAU,OAAO;IAI7B,EAAE,CAAC;AAEN,4BAAgB;EAId,MAAMiB,mBAAwB,cAAc;AAC5C,MACE,iBACA,kBACA,CAAC,aACD,CAAC,qBACD,CAAC,2BAA2B,WAC5B,CAAC,sBACD,CAAC,iBAAiB,QAClB,CAAC,iBAAiB,SAClB,CAAC,gBACD,CAAC,sBAAsB,SACvB;AACA,8BAA2B,UAAU;AACrC,mBAAgB;;IAEjB;EAAC;EAAe;EAAgB;EAAW;EAAmB;EAAmB,CAAC;;;;CAKrF,MAAM,eAAe,OAAO,YAAsD;EAEhF,MAAMC,uBAA4B,QAAQ,eAAe;AAEzD,MAAI,CAAC,qBACH,OAAM,IAAI,MAAM,oBAAoB;EAGtC,MAAMC,kBAAuC,EAAC,GAAG,QAAQ,QAAO;EAGhE,MAAMC,gBAAoC,gBAAgB;AAC1D,SAAO,gBAAgB;AAGvB,MAAI,iBAAiB,iBACnB,KAAI;GACF,MAAMC,uBAA4B,eAAe;GACjD,MAAMC,WACJ,OAAO,yBAAyB,WAC5B,KAAK,MAAM,qBAAqB,GAChC,qBAAqB,YAAY;GAGvC,IAAI,SAAS;AACb,OAAI,QAAQ,QAAQ;IAElB,MAAM,cAAc,UAAsB;AACxC,SAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;KAEzC,MAAMC,QAAa,MAAM,MAAM,MAAW,EAAE,OAAO,QAAQ,OAAO;AAClE,SAAI,MAAO,QAAO;AAElB,YAAO,MAAM,QAAQ,KAAU,MAAW;AACxC,UAAI,IAAK,QAAO;AAChB,UAAI,EAAE,WAAY,QAAO,WAAW,EAAE,WAAW;AACjD,aAAO;QACN,KAAK;;IAGV,MAAMC,eAAoB,WAAW,WAAW;AAEhD,QAAI,gBAAgB,aAAa,SAAS,aAAa,KAAK,UAC1D,UAAS;;AAKb,OAAI,kBAAkBC,qCAAiB,eACrC,UAAS;GAIX,MAAMC,SAA6B,kBAAkB,SAASD,qCAAiB,qBAAqB;GAEpG,MAAME,YAAiB;IACrB,UAAU,CAAC;IACX,GAAI,SAAS,EAAC,QAAO,GAAG,EAAE;IAC1B,UAAU,SAAS,KAAK,OAAY;KAClC,UAAU,CAAC;KACX,UAAU,CACR,IAAI,EAAE,aAAa,EAAE,EAAE,KAAK,OAAY;MACtC,UAAU,CAAC;MACX,MAAM,EAAE;MACT,EAAE,EACH,IAAI,EAAE,YAAY,EAAE,EAAE,KAAK,MAAW;MACpC,MAAM,MAAM,kBAAkB,EAAE,UAAU,IAAI,EAAE;AAChD,aAAO;OACL,UAAU,CAAC,UAAU,gBAAgB,SAAS;OAC9C,MAAM,EAAE;OACT;OACD,CACH;KACD,aAAa,EAAE;KAChB,EAAE;IACJ;AACD,mBAAgB,uBAAuB,KAAK,UAAU,UAAU;AAGhE,UAAO,KAAK,gBAAgB,CAAC,SAAS,QAAgB;AACpD,QAAI,IAAI,WAAW,kBAAkB,CACnC,QAAO,gBAAgB;KAEzB;WACK,GAAG;AAKd,MAAI;AACF,mBAAgB,KAAK;AACrB,gBAAa,KAAK;AAElB,wBAAqB,KAAK;GAE1B,MAAMf,WAAwC,MAAM,OAAO;IACzD,aAAa;IACb,GAAG;IACH,QAAQ;IACR,GAAI,kBAAkB,UAAU,EAAC,gBAAgB,kBAAkB,SAAQ,GAAG,EAAE;IACjF,CAAC;AAEF,OAAI,MAAM,kBAAkB,SAAS,CACnC;AAEF,OACE,SAAS,MAAM,iBAAiB,uBAChC,SAAS,MAAM,iBAAiB,2BAChC;IACA,MAAM,EAAC,kBAAkB,2BAA+B,SAAS,KAAK;IACtE,MAAMgB,iCAAsC,SAAS,eAAe;AAGpE,wBAAoB,UAAU;AAE9B,UAAM,kBAAkB,SAAS,kBAAkB,KAAK;AAGxD,oBAAgB;KACd,UAAU;KACV,WAAW;KACX,iBAAiB;KACjB,OAAO;KACP,aAAa;KACb,UAAU;KACX,CAAC;AACF,oBAAgB,MAAM;AAEtB;;AAIF,OAAI,MAAM,uBAAuB,SAAS,CACxC;GAGF,MAAM,EACJ,aAAa,uBACb,YAAY,sBACZ,gBAAgB,6BACdb,8CACF,UACA,GACA,EACE,qBAAqB,OACtB,EACD,KACD;AAGD,SAAM,kBAAkB,SAAS,kBAAkB,KAAK;AAGxD,OAAI,yBAAyB,sBAAsB;AACjD,mBAAe,sBAAsB;AACrC,kBAAc,qBAAqB;AACnC,sBAAkB,4BAA4B,EAAE,CAAC;AACjD,yBAAqB,MAAM;AAE3B,yBAAqB,KAAK;AAE1B,0BAAsB;IAItB,MAAMc,sBAAiD,SAAS,MAAc;AAC9E,QAAI,uBAAuB,oBAAoB,SAAS,EACtD,sBAAqB,oBAAoB;AAI3C,QAAK,UAAkB,MACrB,cAAa,IAAI,MAAMvB,4CAAoB,UAAU,EAAE,CAAC,CAAC;;WAGtD,OAAO;GACd,MAAMU,MAAW;AACjB,SAAM,gBAAgB;AAEtB,YAAS,eAAed,4CAAwB,MAAM,IAAI,MAAMI,4CAAoB,KAAK,EAAE,CAAC,CAAC;AAC7F;YACQ;AACR,mBAAgB,MAAM;;;;;;;;;;;AAY1B,mBAAkB,UAAU;EAC1B;EACA,kBAAkB,QAAQ,iBAAiB,iBAAiB;EAC5D,QAAQ;EACT;AAED,4BAAgB;EACd,MAAMwB,YAAoB,OAAO,iBAAiB,eAAe,IAAI;AACrE,MAAI,aAAa,KAAK,CAAC,mBAAmB;AACxC,wBAAqB,MAAM;AAC3B;;EAGF,MAAM,sBAA4B;AAChC,wBAAqB,KAAK;GAE1B,MAAM,qBACJ,IAAI,MAAM,EAAE,wBAAwB,IAAI,iDAAiD;GAG3F,MAAM,UAAU,kBAAkB;GAClC,MAAMC,WAA+B,SAAS,mBAC1C,0BAA0B,QAAQ,WAAW,GAC7C;AAGJ,OAAI,YAAY,WAAW,uBAAuB,YAAY,WAAW;AACvE,2BAAuB,UAAU;AACjC,YACG,OAAO;KAAC,QAAQ;KAAU,QAAQ,GAAE,qBAAqBN,qCAAiB,gBAAe;KAAC,CAAC,CAC3F,YAAY,SAAS,cAAc,CAAC,CAAC;AACxC;;AAGF,YAAS,cAAc,CAAC;;EAG1B,MAAMO,UAAyC,WAAW,eAAe,KAAK,IAAI,GAAG,YAAY,KAAK,KAAK,CAAC,CAAC;AAE7G,eAAa,aAAa,QAAQ;IACjC;EAAC,iBAAiB;EAAgB;EAAmB;EAAE,CAAC;;;;CAK3D,MAAM,eAAe,UAAuB;AAC1C,WAAS,MAAM;;AAGjB,2CAAiB;EACf;EACA,uBAAuB,GAAG,OAAO;EACjC,eAAe,iBAAiB,CAAC,aAAa;EAC9C;EACA,UAAU,QAAa;AACrB,mBAAgB;AAChB,YAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;;EAE/D,UAAU,OAAO,YAAiB,aAAa;GAAC,aAAa,QAAQ;GAAa,QAAQ,QAAQ;GAAO,CAAC;EAC1G,cAAc;EACd;EACD,CAAC;;;;;AAMF,4BAAgB;AACd,MACE,CAAC,aAAa,YACb,CAAC,aAAa,aAAa,CAAC,aAAa,mBAC1C,CAAC,aAAa,YAEd;AAIF,MAAI,oBAAoB,QACtB;AAEF,sBAAoB,UAAU;EAE9B,MAAM,wBAAwB,YAA2B;GACvD,IAAIC;AAEJ,OAAI,aAAa,WAAW;IAC1B,MAAMC,kBAAuB,MAAMC,4CAA4B,aAAa,UAAU;IACtF,MAAMC,qBAA0B,KAAK,MAAM,gBAAgB;AAE3D,aAAS;KACP,mBAAmB,mBAAmB,SAAS;KAC/C,gBAAgB,mBAAmB,SAAS;KAC5C,cAAc,mBAAmB;KACjC,WAAW,mBAAmB,SAAS;KACvC,YAAY,mBAAmB,SAAS;KACzC;cACQ,aAAa,iBAAiB;IACvC,MAAMF,kBAAuB,MAAMG,0CAA0B,aAAa,gBAAgB;IAC1F,MAAMD,qBAA0B,KAAK,MAAM,gBAAgB;AAE3D,aAAS;KACP,mBAAmB,mBAAmB,SAAS;KAC/C,gBAAgB,mBAAmB,SAAS;KAC5C,cAAc,mBAAmB;KAClC;SAED,OAAM,IAAI,MAAM,qDAAqD;AAGvE,SAAM,aAAa;IACjB,aAAa,aAAa,eAAe;IACzC;IACD,CAAC;;AAGJ,yBAAuB,CACpB,WAAW;AACV,mBAAgB;IACd,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,OAAO;IACP,aAAa;IACb,UAAU;IACX,CAAC;IACF,CACD,OAAO,UAAe;AACrB,oBAAiB,UAAe;IAAC,GAAG;IAAa;IAAgB,UAAU;IAAM,EAAE;AACnF,gBAAa,MAAe;AAC5B,aAAU,MAAe;IACzB;IACH;EAAC,aAAa;EAAU,aAAa;EAAW,aAAa;EAAiB,aAAa;EAAY,CAAC;AAE3G,KAAI,UAAU;EAMZ,MAAME,wBAAgD,EAAE;AACxD,MAAI,mBACF;QAAK,MAAM,MAAM,kBACf,KAAI,EAAE,GAAG,cAAc,uBACrB,uBAAsB,GAAG,cAAc,GAAG;;AAkBhD,SAAO,mFAAG,SAb6B;GACrC;GACA;GACA,OAAO;GACP,aAAa;GACb,YAAY;GACZ,eAAe;GACf,WAAW,aAAa,gBAAgB,CAAC;GACzC;GACA;GACA,UAAU;GACX,CAE8B,GAAI;;AAGrC,QACE,2CAACC;EACiB;EACJ;EACZ,WAAW,aAAa,CAAC,iBAAiB,CAAC;EACxB;EACnB,UAAU;EACV,SAAS;EACT,OAAO;EACI;EACL;EACG;EACI;EACgB;EACV;GACnB;;AAIN,qBAAe"}
|
|
1
|
+
{"version":3,"file":"SignIn.cjs","names":["submitActions: EmbeddedFlowComponent[]","SignIn: FC<SignInProps>","useThunderID","useTranslation","challengeTokenRef: any","initializationAttemptedRef: any","oauthCodeProcessedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","urlParams: any","url: any","ThunderIDRuntimeError","EmbeddedSignInFlowType","redirectURL: any","EmbeddedSignInFlowStatus","extractErrorMessage","finalRedirectUrl: any","effectiveApplicationId: any","storedExecutionId: any","resumeExecutionId: any","response: EmbeddedSignInFlowResponse","ThunderIDAPIError","EmbeddedFlowType","normalizeFlowResponse","err: any","currentUrlParams: any","effectiveExecutionId: any","processedInputs: Record<string, any>","consentReason: string | undefined","consentPromptRawData: any","purposes: any[]","found: any","submitAction: any","ConsentConstants","reason: string | undefined","decisions: any","effectiveExecutionIdForPasskey: any","responseFieldErrors: FieldError[] | undefined","timeoutMs: number","actionId: string | undefined","timerId: ReturnType<typeof setTimeout>","inputs: Record<string, string>","passkeyResponse: any","handlePasskeyAuthentication","passkeyResponseObj: any","handlePasskeyRegistration","renderPropFieldErrors: Record<string, string>","BaseSignIn"],"sources":["../../../../../../src/components/presentation/auth/SignIn/SignIn.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ThunderIDRuntimeError,\n ThunderIDAPIError,\n ConsentConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowType,\n EmbeddedSignInFlowResponse,\n EmbeddedSignInFlowRequest,\n EmbeddedSignInFlowStatus,\n EmbeddedSignInFlowType,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n logger,\n} from '@thunderid/browser';\nimport {FC, ReactElement, useState, useEffect, useRef, ReactNode} from 'react';\n// eslint-disable-next-line import/no-named-as-default\nimport BaseSignIn, {BaseSignInProps} from './BaseSignIn';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../../hooks/useOAuthCallback';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../../utils/flowTransformer';\nimport {initiateOAuthRedirect} from '../../../../utils/oauth';\nimport {handlePasskeyAuthentication, handlePasskeyRegistration} from '../../../../utils/passkey';\n\n/**\n * Render props function parameters\n */\nexport interface SignInRenderProps {\n /**\n * Additional data from the flow response containing contextual information\n * like consent prompt details and session timeouts.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Current flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * Current error if any\n */\n error: Error | null;\n\n /**\n * Server-side field-level validation errors from the most recent flow response,\n * collapsed to one message per field (first error wins). Empty when no validation\n * failures are active. Render-prop consumers should display these alongside their\n * own client-side validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to manually initialize the flow\n */\n initialize: () => Promise<void>;\n\n /**\n * Whether the flow has been initialized\n */\n isInitialized: boolean;\n\n /**\n * Loading state indicator\n */\n isLoading: boolean;\n\n /**\n * Flag indicating whether the flow step timeout has expired.\n * Consuming components can use this to disable submit buttons.\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Function to submit authentication data (primary)\n */\n onSubmit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n}\n\n/**\n * Props for the SignIn component.\n * Matches the interface from the main SignIn component for consistency.\n */\nexport interface SignInProps {\n /**\n * Render props function for custom UI\n */\n children?: (props: SignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: BaseSignInProps['variant'];\n}\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n challenge: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Sentinel input key carrying the reason a consent prompt was submitted. It is folded into the\n * compiled `consent_decisions` payload and stripped from the inputs, like `__consent_opt__` keys.\n */\nconst CONSENT_REASON_KEY = '__consent_reason__';\n\n/** Flattens a component tree into a single list, parents before their children. */\nconst flattenComponents = (comps: EmbeddedFlowComponent[] | undefined): EmbeddedFlowComponent[] =>\n (comps ?? []).flatMap((comp: EmbeddedFlowComponent) => [comp, ...flattenComponents(comp.components)]);\n\n/**\n * Finds the action to submit an expired consent prompt with. A non-primary submit action is\n * preferred so the payload reads as a denial, falling back to any submit action because the server\n * needs an action to route the prompt node. Returns undefined when the view has neither.\n */\nconst findConsentSubmitActionId = (comps: EmbeddedFlowComponent[] | undefined): string | undefined => {\n const submitActions: EmbeddedFlowComponent[] = flattenComponents(comps).filter(\n (comp: EmbeddedFlowComponent) => comp.id && comp.eventType?.toUpperCase() === 'SUBMIT',\n );\n const denyAction: EmbeddedFlowComponent | undefined = submitActions.find(\n (comp: EmbeddedFlowComponent) => comp.variant?.toLowerCase() !== 'primary',\n );\n\n return (denyAction ?? submitActions[0])?.id;\n};\n\n/**\n * A component-driven SignIn component that provides authentication flow with pre-built styling.\n * This component handles the flow API calls for authentication and delegates UI logic to BaseSignIn.\n * It automatically transforms simple input-based responses into component-driven UI format.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => {\n * console.log('Authentication successful:', authData);\n * }}\n * onError={(error) => {\n * console.error('Authentication failed:', error);\n * }}\n * size=\"medium\"\n * variant=\"outlined\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => console.log('Success:', authData)}\n * onError={(error) => console.error('Error:', error)}\n * >\n * {({signIn, isLoading, components, error, isInitialized}) => (\n * <div className=\"custom-signin\">\n * <h1>Custom Sign In</h1>\n * {!isInitialized ? (\n * <p>Initializing...</p>\n * ) : error ? (\n * <div className=\"error\">{error.message}</div>\n * ) : (\n * <form onSubmit={(e) => {\n * e.preventDefault();\n * signIn({inputs: {username: 'user', password: 'pass'}});\n * }}>\n * <button type=\"submit\" disabled={isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign In'}\n * </button>\n * </form>\n * )}\n * </div>\n * )}\n * </SignIn>\n * );\n * };\n * ```\n */\nconst SignIn: FC<SignInProps> = ({\n className,\n preferences,\n size = 'medium',\n onSuccess,\n onError,\n variant,\n children,\n revalidateOnChangeAfterBlur,\n}: SignInProps): ReactElement => {\n const {applicationId, afterSignInUrl, signIn, isInitialized, isLoading, meta, getStorageManager, scopes, vendor} =\n useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n\n // State management for the flow\n const [components, setComponents] = useState<EmbeddedFlowComponent[]>([]);\n const [additionalData, setAdditionalData] = useState<Record<string, any>>({});\n // Server-side validation errors from the most recent flow response. Updated on every\n // submission; cleared when the next submission begins so stale errors don't linger.\n const [serverFieldErrors, setServerFieldErrors] = useState<FieldError[] | null>(null);\n const [currentExecutionId, setCurrentExecutionId] = useState<string | null>(null);\n const challengeTokenRef: any = useRef<string | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [flowError, setFlowError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isTimeoutDisabled, setIsTimeoutDisabled] = useState<boolean>(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const initializationAttemptedRef: any = useRef(false);\n const oauthCodeProcessedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // Deadline this component has already auto-submitted for, so a re-run of the timeout effect\n // cannot submit the same expired step twice.\n const timeoutSubmittedForRef = useRef<number | null>(null);\n // The timeout effect is keyed on the deadline alone, so a step that arrives carrying the same\n // deadline would otherwise leave the pending timer holding the previous step's context.\n const timeoutContextRef = useRef<{\n components: EmbeddedFlowComponent[];\n hasConsentPrompt: boolean;\n submit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n } | null>(null);\n /**\n * Sets executionId between sessionStorage and state.\n * This ensures both are always in sync.\n */\n const setExecutionId = (executionId: string | null): void => {\n setCurrentExecutionId(executionId);\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n } else {\n sessionStorage.removeItem(`${vendor}_execution_id`);\n }\n };\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Clear all flow-related storage and state.\n */\n const clearFlowState = async (): Promise<void> => {\n // Clear the expired flow state to prevent rendering a stale form with a null executionId.\n // Kept before the first await so callers that do not await this function still apply the\n // reset in one batch, ahead of the setError that follows.\n setExecutionId(null);\n setComponents([]);\n setAdditionalData({});\n setIsFlowInitialized(false);\n await setChallengeToken(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n setIsTimeoutDisabled(false);\n // Reset refs to allow new flows to start properly\n oauthCodeProcessedRef.current = false;\n };\n\n /**\n * Parse URL parameters used in flows.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n\n return {\n applicationId: urlParams.get('applicationId'),\n authId: urlParams.get('authId'),\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n errorDescription: urlParams.get('error_description'),\n executionId: urlParams.get('executionId'),\n nonce: urlParams.get('nonce'),\n state: urlParams.get('state'),\n };\n };\n\n /**\n * Handle authId from URL and persist it via the storage manager so it survives URL cleanup.\n * ThunderIDReactClient.signIn() reads authId from storageManager.getHybridDataParameter('authId'),\n * not from raw sessionStorage, so we must use the same storage path here.\n */\n const handleAuthId = async (authId: string | null): Promise<void> => {\n if (authId) {\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.setHybridDataParameter?.('authId', authId);\n } catch {\n logger.warn('Failed to store authId in hybrid storage.');\n }\n }\n };\n\n /**\n * Clean up OAuth-related URL parameters from the browser URL.\n */\n const cleanupOAuthUrlParams = (includeNonce = false): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('error');\n url.searchParams.delete('error_description');\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n if (includeNonce) {\n url.searchParams.delete('nonce');\n }\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Clean up flow-related URL parameters (executionId, authId) from the browser URL.\n * Used after executionId is set in state to prevent using invalidated executionId from URL.\n */\n const cleanupFlowUrlParams = (): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('authId');\n url.searchParams.delete('applicationId');\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Set error state and call onError callback.\n * Ensures isFlowInitialized is true so errors can be displayed in the UI.\n */\n const setError = (error: Error): void => {\n setFlowError(error);\n setIsFlowInitialized(true);\n onError?.(error);\n };\n\n /**\n * Handle OAuth error from URL parameters.\n * Clears flow state, creates error, and cleans up URL.\n */\n const handleOAuthError = (error: string, errorDescription: string | null): void => {\n clearFlowState();\n const errorMessage: any = errorDescription || `OAuth error: ${error}`;\n const err: any = new ThunderIDRuntimeError(errorMessage, 'SIGN_IN_ERROR', 'react');\n setError(err);\n cleanupOAuthUrlParams(true);\n };\n\n /**\n * Handle REDIRECTION response by storing flow state and redirecting to OAuth provider.\n */\n const handleRedirection = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.type === EmbeddedSignInFlowType.Redirection) {\n const redirectURL: any = (response.data as any)?.redirectURL || (response as any)?.redirectURL;\n\n if (redirectURL && window?.location) {\n if (response.executionId) {\n setExecutionId(response.executionId);\n }\n await setChallengeToken(response.challengeToken ?? null);\n\n const urlParams: any = getUrlParams();\n await handleAuthId(urlParams.authId);\n\n initiateOAuthRedirect(redirectURL, vendor);\n return true;\n }\n }\n return false;\n };\n\n /**\n * Handle ERROR and COMPLETE responses. Returns true if fully handled.\n * ERROR + executionId: recoverable — session preserved for retry.\n * ERROR + no executionId: terminal — clear state and surface the error.\n */\n const handleTerminalResponse = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error) {\n // Propagate OAuth error to the client\n if (response.redirectUrl && window?.location) {\n setIsSubmitting(false);\n await clearFlowState();\n cleanupOAuthUrlParams(true);\n onError?.(new Error(extractErrorMessage(response, t)));\n window.location.href = response.redirectUrl;\n\n return true;\n }\n\n if (response.executionId) {\n // Recoverable: session still alive. Show inline error without firing onError.\n setExecutionId(response.executionId);\n await setChallengeToken(response.challengeToken ?? null);\n setIsFlowInitialized(true);\n setFlowError(new Error(extractErrorMessage(response, t)));\n return true;\n }\n // Terminal: backend invalidated the session — clear all state.\n await clearFlowState();\n setError(new Error(extractErrorMessage(response, t)));\n cleanupFlowUrlParams();\n return true;\n }\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // Get redirectUrl from response (from /oauth2/auth/callback) or fall back to afterSignInUrl\n const redirectUrl: any = (response as any)?.redirectUrl || (response as any)?.redirect_uri;\n const finalRedirectUrl: any = redirectUrl || afterSignInUrl;\n\n // Clear submitting state before redirect\n setIsSubmitting(false);\n\n // Clear all OAuth-related storage on successful completion\n setExecutionId(null);\n await setChallengeToken(null);\n setIsFlowInitialized(false);\n sessionStorage.removeItem(`${vendor}_execution_id`);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage after completion.');\n }\n\n // Clean up OAuth URL params before redirect\n cleanupOAuthUrlParams(true);\n\n if (onSuccess) {\n onSuccess({\n redirectUrl: finalRedirectUrl,\n ...(response.data || {}),\n });\n }\n\n if (finalRedirectUrl && window?.location) {\n window.location.href = finalRedirectUrl;\n }\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Initialize the authentication flow.\n * Priority: executionId > applicationId (from context) > applicationId (from URL)\n */\n const initializeFlow = async (): Promise<void> => {\n const urlParams: any = getUrlParams();\n\n // Reset OAuth code processed ref when starting a new flow\n oauthCodeProcessedRef.current = false;\n // Clear stale serverFieldErrors so the new flow doesn't inherit them via render-prop.\n setServerFieldErrors(null);\n\n await handleAuthId(urlParams.authId);\n\n const effectiveApplicationId: any = applicationId || urlParams.applicationId;\n\n // On a page refresh the executionId is no longer in the URL (it is scrubbed by\n // cleanupFlowUrlParams after the first load). Fall back to the executionId persisted in\n // sessionStorage so the in-progress flow can be resumed instead of starting a new flow.\n // This is required for authorization_code apps where direct new-flow initiation is blocked\n // server-side and the flow must be initiated through the OAuth /authorize endpoint.\n const storedExecutionId: any = !urlParams.executionId ? sessionStorage.getItem(`${vendor}_execution_id`) : null;\n const resumeExecutionId: any = urlParams.executionId || storedExecutionId;\n\n if (!resumeExecutionId && !effectiveApplicationId) {\n const error: any = new ThunderIDRuntimeError(\n 'Either executionId or applicationId is required for authentication',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(error);\n\n return;\n }\n\n try {\n setFlowError(null);\n\n let response: EmbeddedSignInFlowResponse;\n\n if (resumeExecutionId) {\n try {\n response = (await signIn({\n executionId: resumeExecutionId,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n } catch (resumeError) {\n // Only treat a stale/expired session (HTTP 400 from the server, meaning the stored\n // executionId is no longer valid) as a recoverable condition. Transient failures\n // such as 5xx server errors or network errors are rethrown so they surface correctly.\n const isStaleSession: boolean =\n storedExecutionId &&\n resumeExecutionId === storedExecutionId &&\n resumeError instanceof ThunderIDAPIError &&\n resumeError.statusCode === 400;\n\n if (isStaleSession) {\n setExecutionId(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n if (!effectiveApplicationId) {\n const expiredError: any = new ThunderIDRuntimeError(\n t('errors.signin.session.expired') ||\n 'Your session has expired. Please return to the application and sign in again.',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(expiredError);\n return;\n }\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n } else {\n throw resumeError;\n }\n }\n } else {\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n }\n\n if (await handleRedirection(response)) {\n return;\n }\n\n // Handle a flow that completes (or errors) on the very first step — e.g. a reused SSO\n // session lets the backend return COMPLETE immediately with no UI components. Without\n // this the UI would fall through with no components and spin forever.\n if (await handleTerminalResponse(response)) {\n // Only reset the init gate for unrecoverable Error responses so the user can retry;\n // Complete-without-redirect would otherwise kick off a fresh flow unintentionally.\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error && !response.executionId) {\n initializationAttemptedRef.current = false;\n }\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsFlowInitialized(true);\n setIsTimeoutDisabled(false);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n initializationAttemptedRef.current = false;\n }\n };\n\n /**\n * Initialize the flow and handle cleanup of stale flow state.\n */\n useEffect(() => {\n const urlParams: any = getUrlParams();\n\n // Check for OAuth error in URL\n if (urlParams.error) {\n handleOAuthError(urlParams.error, urlParams.errorDescription);\n return;\n }\n\n handleAuthId(urlParams.authId);\n\n // Skip OAuth code processing - let the dedicated OAuth useEffect handle it\n // No action needed here as the dedicated useEffect will handle it\n }, []);\n\n useEffect(() => {\n // Only initialize if we're not processing an OAuth callback or submission.\n // Wait for isStorageReady so the challenge token is restored from storage before\n // we attempt to resume a persisted executionId — the server requires it.\n const currentUrlParams: any = getUrlParams();\n if (\n isInitialized &&\n isStorageReady &&\n !isLoading &&\n !isFlowInitialized &&\n !initializationAttemptedRef.current &&\n !currentExecutionId &&\n !currentUrlParams.code &&\n !currentUrlParams.state &&\n !isSubmitting &&\n !oauthCodeProcessedRef.current\n ) {\n initializationAttemptedRef.current = true;\n initializeFlow();\n }\n }, [isInitialized, isStorageReady, isLoading, isFlowInitialized, currentExecutionId]);\n\n /**\n * Handle form submission from BaseSignIn or render props.\n */\n const handleSubmit = async (payload: EmbeddedSignInFlowRequest): Promise<void> => {\n // Use executionId from payload if available, otherwise fall back to currentExecutionId\n const effectiveExecutionId: any = payload.executionId || currentExecutionId;\n\n if (!effectiveExecutionId) {\n throw new Error('No active flow ID');\n }\n\n const processedInputs: Record<string, any> = {...payload.inputs};\n\n // Read and strip the sentinel up front so it can never reach the wire as an input\n const consentReason: string | undefined = processedInputs[CONSENT_REASON_KEY];\n delete processedInputs[CONSENT_REASON_KEY];\n\n // Auto-compile consent decisions if we are currently on a consent prompt step\n if (additionalData?.['consentPrompt']) {\n try {\n const consentPromptRawData: any = additionalData['consentPrompt'];\n const purposes: any[] =\n typeof consentPromptRawData === 'string'\n ? JSON.parse(consentPromptRawData)\n : consentPromptRawData.purposes || consentPromptRawData;\n\n // Find the action component to determine if it was a deny action\n let isDeny = false;\n if (payload.action) {\n // Flatten components to find the action\n const findAction = (comps: any[]): any => {\n if (!comps || comps.length === 0) return null;\n\n const found: any = comps.find((c: any) => c.id === payload.action);\n if (found) return found;\n\n return comps.reduce((acc: any, c: any) => {\n if (acc) return acc;\n if (c.components) return findAction(c.components);\n return null;\n }, null);\n };\n\n const submitAction: any = findAction(components);\n\n if (submitAction && submitAction.variant?.toLowerCase() !== 'primary') {\n isDeny = true;\n }\n }\n\n // An expired prompt is never an approval, whichever action carried the submission\n if (consentReason === ConsentConstants.REASON_TIMEOUT) {\n isDeny = true;\n }\n\n // An explicit denial carries a reason too, so the server never has to infer one\n const reason: string | undefined = consentReason ?? (isDeny ? ConsentConstants.REASON_USER_DENIED : undefined);\n\n const decisions: any = {\n approved: !isDeny,\n ...(reason ? {reason} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n elements: [\n ...(p.essential || []).map((e: any) => ({\n approved: !isDeny,\n name: e.name,\n })),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n return {\n approved: !isDeny && processedInputs[key] === 'true',\n name: e.name,\n };\n }),\n ],\n purposeName: p.purposeName,\n })),\n };\n processedInputs['consent_decisions'] = JSON.stringify(decisions);\n\n // Cleanup temporary consent tracking fields from inputs\n Object.keys(processedInputs).forEach((key: string) => {\n if (key.startsWith('__consent_opt__')) {\n delete processedInputs[key];\n }\n });\n } catch (e) {\n // Failed to construct consent_decisions payload automatically\n }\n }\n\n try {\n setIsSubmitting(true);\n setFlowError(null);\n // Clear any field errors from the previous response before the new round-trip.\n setServerFieldErrors(null);\n\n const response: EmbeddedSignInFlowResponse = (await signIn({\n executionId: effectiveExecutionId,\n ...payload,\n inputs: processedInputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n\n if (await handleRedirection(response)) {\n return;\n }\n if (\n response.data?.additionalData?.['passkeyChallenge'] ||\n response.data?.additionalData?.['passkeyCreationOptions']\n ) {\n const {passkeyChallenge, passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId || effectiveExecutionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: 'submit',\n challenge: passkeyChallenge,\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsSubmitting(false);\n\n return;\n }\n\n // Handle terminal flow statuses before normalization.\n if (await handleTerminalResponse(response)) {\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n // Always update challenge token on any INCOMPLETE response — token rotates every step.\n await setChallengeToken(response.challengeToken ?? null);\n\n // Update executionId if response contains a new one\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsTimeoutDisabled(false);\n // Ensure flow is marked as initialized when we have components\n setIsFlowInitialized(true);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n\n // Surface server-side validation failures so BaseSignIn can inject them into\n // the form-level fieldErrors state used by the render-prop / default UI.\n const responseFieldErrors: FieldError[] | undefined = (response.data as any)?.fieldErrors;\n if (responseFieldErrors && responseFieldErrors.length > 0) {\n setServerFieldErrors(responseFieldErrors);\n }\n\n // Display error from INCOMPLETE response\n if ((response as any)?.error) {\n setFlowError(new Error(extractErrorMessage(response, t)));\n }\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n return;\n } finally {\n setIsSubmitting(false);\n }\n };\n\n /**\n * Handle step timeout if configured in additionalData.\n *\n * An expired consent prompt is auto-submitted as a denial carrying the timeout reason, because its\n * actions no longer lead anywhere and the user would otherwise be stranded on the prompt. The\n * server discards those decisions and records nothing. Every other kind of step surfaces the\n * expiry error instead.\n */\n timeoutContextRef.current = {\n components,\n hasConsentPrompt: Boolean(additionalData?.['consentPrompt']),\n submit: handleSubmit,\n };\n\n useEffect(() => {\n const timeoutMs: number = Number(additionalData?.['stepTimeout']) || 0;\n if (timeoutMs <= 0 || !isFlowInitialized) {\n setIsTimeoutDisabled(false);\n return undefined;\n }\n\n const handleTimeout = (): void => {\n setIsTimeoutDisabled(true);\n\n const expiredError = (): Error =>\n new Error(t('errors.signin.timeout') || 'Time allowed to complete the step has expired.');\n\n // Read through the ref so the timer always sees the step that is on screen when it fires\n const context = timeoutContextRef.current;\n const actionId: string | undefined = context?.hasConsentPrompt\n ? findConsentSubmitActionId(context.components)\n : undefined;\n\n // Without an action the prompt node cannot be routed, so there is nothing to submit\n if (actionId && context && timeoutSubmittedForRef.current !== timeoutMs) {\n timeoutSubmittedForRef.current = timeoutMs;\n context\n .submit({action: actionId, inputs: {[CONSENT_REASON_KEY]: ConsentConstants.REASON_TIMEOUT}})\n .catch(() => setError(expiredError()));\n return;\n }\n\n setError(expiredError());\n };\n\n const timerId: ReturnType<typeof setTimeout> = setTimeout(handleTimeout, Math.max(0, timeoutMs - Date.now()));\n\n return () => clearTimeout(timerId);\n }, [additionalData?.['stepTimeout'], isFlowInitialized, t]);\n\n /**\n * Handle authentication errors.\n */\n const handleError = (error: Error): void => {\n setError(error);\n };\n\n useOAuthCallback({\n currentExecutionId,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isInitialized && !isLoading && isStorageReady,\n isSubmitting,\n onError: (err: any) => {\n clearFlowState();\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n onSubmit: async (payload: any) => handleSubmit({executionId: payload.executionId, inputs: payload.inputs}),\n processedRef: oauthCodeProcessedRef,\n setExecutionId,\n });\n\n /**\n * Handle passkey authentication/registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (\n !passkeyState.isActive ||\n (!passkeyState.challenge && !passkeyState.creationOptions) ||\n !passkeyState.executionId\n ) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyProcess = async (): Promise<void> => {\n let inputs: Record<string, string>;\n\n if (passkeyState.challenge) {\n const passkeyResponse: any = await handlePasskeyAuthentication(passkeyState.challenge);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n authenticatorData: passkeyResponseObj.response.authenticatorData,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n signature: passkeyResponseObj.response.signature,\n userHandle: passkeyResponseObj.response.userHandle,\n };\n } else if (passkeyState.creationOptions) {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n } else {\n throw new Error('No passkey challenge or creation options available');\n }\n\n await handleSubmit({\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n });\n };\n\n performPasskeyProcess()\n .then(() => {\n setPasskeyState({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n setFlowError(error as Error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.executionId]);\n\n if (children) {\n // Collapse the server FieldError[] array to a single message per field map for\n // render-prop consumers. First error per field wins. Multi-error cases per\n // field are rare in practice (server typically returns one rule failure per\n // field in current flows) and consumers needing the full array can still read\n // it from the raw flow response.\n const renderPropFieldErrors: Record<string, string> = {};\n if (serverFieldErrors) {\n for (const fe of serverFieldErrors) {\n if (!(fe.identifier in renderPropFieldErrors)) {\n renderPropFieldErrors[fe.identifier] = fe.message;\n }\n }\n }\n\n const renderProps: SignInRenderProps = {\n additionalData,\n components,\n error: flowError,\n fieldErrors: renderPropFieldErrors,\n initialize: initializeFlow,\n isInitialized: isFlowInitialized,\n isLoading: isLoading || isSubmitting || !isInitialized,\n isTimeoutDisabled,\n meta,\n onSubmit: handleSubmit,\n };\n\n return <>{children(renderProps)}</>;\n }\n // Otherwise, render the default BaseSignIn component\n return (\n <BaseSignIn\n additionalData={additionalData}\n components={components}\n isLoading={isLoading || !isInitialized || !isFlowInitialized}\n isTimeoutDisabled={isTimeoutDisabled}\n onSubmit={handleSubmit}\n onError={handleError}\n error={flowError}\n className={className}\n size={size}\n variant={variant}\n preferences={preferences}\n revalidateOnChangeAfterBlur={revalidateOnChangeAfterBlur}\n serverFieldErrors={serverFieldErrors}\n />\n );\n};\n\nexport default SignIn;\n"],"mappings":"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"}
|
|
@@ -603,6 +603,7 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
603
603
|
id,
|
|
604
604
|
className: containerClasses,
|
|
605
605
|
children: children({
|
|
606
|
+
additionalData: currentFlow?.data?.additionalData ?? {},
|
|
606
607
|
components: (currentFlow?.data)?.components || [],
|
|
607
608
|
error: apiError,
|
|
608
609
|
fieldErrors: formErrors,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSignUp.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","BaseSignUpContent: FC<BaseSignUpProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","challengeTokenRef: any","initializationAttemptedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","extractFormFields: any","fields: FormField[]","EmbeddedFlowComponentType","fieldName: any","useForm","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","setupFormFields: any","fields: any","initialValues: Record<string, string>","data: any","components: unknown[] | undefined","EmbeddedSignUpFlowStatus","normalized: any","EmbeddedSignUpFlowType","redirectUrl: any","expectedState: string | null","reusablePopup: Window | null","popup: Window | null","hasProcessedCallback: any","popupMonitor: ReturnType<typeof setInterval> | null","messageHandler: ((event: MessageEvent) => Promise<void>) | null","payload: EmbeddedSignUpFlowRequest","continueResponse: any","normalizedContinueResponse: any","popupError: Error","expectedOrigin: any","popupUrl: any","url: any","code: any","state: any","error: any","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","response: any","effectiveExecutionIdForPasskey: any","passkeyResponse: any","handlePasskeyRegistration","passkeyResponseObj: any","inputs: any","processedResponse: any","containerClasses: any","cx","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderSignUpComponents","urlParams: any","payload: any","url: URL","result: any","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseSignUp: FC<BaseSignUpProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/SignUp/BaseSignUp.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedSignUpFlowRequest,\n EmbeddedSignUpFlowResponse,\n EmbeddedSignUpFlowStatus,\n EmbeddedSignUpFlowType,\n withVendorCSSClassPrefix,\n EmbeddedFlowComponentType,\n FieldError,\n createPackageComponentLogger,\n buildValidatorFromRules,\n Preferences,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport useStyles from './BaseSignUp.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useForm, FormField} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {cx} from '../../../../styles/emotion';\nimport composeAffixedInputs from '../../../../utils/composeAffixedInputs';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../../utils/getAuthComponentHeadings';\nimport {handlePasskeyRegistration} from '../../../../utils/passkey';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Logo from '../../../primitives/Logo/Logo';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderSignUpComponents} from '../AuthOptionFactory';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'BaseSignUp',\n);\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Render props for custom UI rendering\n */\nexport interface BaseSignUpRenderProps {\n /**\n * Flow components\n */\n components: any[];\n\n /**\n * API error (if any)\n */\n error?: Error | null;\n\n /**\n * Field validation errors\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to handle input changes\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state\n */\n isLoading: boolean;\n\n /**\n * Whether the form is valid\n */\n isValid: boolean;\n\n /**\n * Flow messages\n */\n messages: {message: string; type: string}[];\n\n /**\n * Flow subtitle\n */\n subtitle: string;\n\n /**\n * Flow title\n */\n title: string;\n\n /**\n * Touched fields\n */\n touched: Record<string, boolean>;\n\n /**\n * Function to validate the form\n */\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n\n /**\n * Form values\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseSignUp component.\n */\nexport interface BaseSignUpProps {\n /**\n * URL to redirect after successful sign-up.\n */\n afterSignUpUrl?: string;\n\n /**\n * Custom CSS class name for the submit button.\n */\n buttonClassName?: string;\n\n /**\n * Render props function for custom UI\n */\n children?: (props: BaseSignUpRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Error object to display\n */\n error?: Error | null;\n\n /**\n * Custom CSS class name for error messages.\n */\n errorClassName?: string;\n\n /**\n * HTML id attribute for the form container.\n */\n id?: string;\n\n /**\n * Custom CSS class name for form inputs.\n */\n inputClassName?: string;\n\n isInitialized?: boolean;\n\n /**\n * Custom CSS class name for info messages.\n */\n messageClassName?: string;\n\n /**\n * Callback function called when the sign-up flow completes and requires redirection.\n * This allows platform-specific handling of redirects (e.g., Next.js router.push).\n * @param response - The response from the sign-up flow containing the redirect URL, etc.\n */\n onComplete?: (response: EmbeddedSignUpFlowResponse) => void;\n\n /**\n * Callback function called when sign-up fails.\n * @param error - The error that occurred during sign-up.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when sign-up flow status changes.\n * @param response - The current sign-up response.\n */\n onFlowChange?: (response: EmbeddedSignUpFlowResponse) => void;\n\n /**\n * Function to initialize sign-up flow.\n * @returns Promise resolving to the initial sign-up response.\n */\n onInitialize?: (payload?: EmbeddedSignUpFlowRequest) => Promise<EmbeddedSignUpFlowResponse>;\n\n /**\n * Function to handle sign-up steps.\n * @param payload - The sign-up payload.\n * @returns Promise resolving to the sign-up response.\n */\n onSubmit?: (payload: EmbeddedSignUpFlowRequest) => Promise<EmbeddedSignUpFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Whether to redirect after sign-up.\n */\n shouldRedirectAfterSignUp?: boolean;\n\n /**\n * Whether to show the logo.\n */\n showLogo?: boolean;\n\n /**\n * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that consumes FlowContext and renders the sign-up UI.\n */\nconst BaseSignUpContent: FC<BaseSignUpProps> = ({\n afterSignUpUrl,\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\n id,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n errorClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isInitialized,\n children,\n showTitle = true,\n showSubtitle = true,\n revalidateOnChangeAfterBlur = false,\n}: BaseSignUpProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const {meta, isInitialized: isSdkInitialized, getStorageManager, vendor} = useThunderID();\n const styles: any = useStyles(theme, colorScheme);\n\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedSignUpFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // A completed flow leaves its last step rendered while the consumer navigates away, and the\n // redirect is not instantaneous. Latch the completion so the still-visible submit actions cannot\n // fire again: the executionId is spent, and re-submitting would start a whole new sign-up flow.\n const isFlowCompletedRef = useRef(false);\n // Tears down the active popup's listener and poll, so neither outlives the component.\n const cleanupActivePopupRef = useRef<(() => void) | null>(null);\n\n useEffect(() => () => cleanupActivePopupRef.current?.(), []);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n */\n useEffect(() => {\n if (!isSdkInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } catch {\n // StorageManager unavailable — continue without persisted token\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isSdkInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages\n * Uses the transformer's extractErrorMessage function.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear existing messages and add the error message\n clearMessages();\n addMessage({\n message: errorMessage,\n type: 'error',\n });\n },\n [t, addMessage, clearMessages],\n );\n\n /**\n * Normalize flow response to ensure component-driven format\n * Uses normalizeFlowResponse for modern API format responses\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedSignUpFlowResponse): EmbeddedSignUpFlowResponse => {\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.signUp.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...(response.data as any),\n components,\n },\n } as EmbeddedSignUpFlowResponse;\n }\n\n return response;\n },\n [t, meta],\n );\n\n /**\n * Extract form fields from flow components\n */\n const extractFormFields: any = useCallback(\n (components: any[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: any[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === EmbeddedFlowComponentType.TextInput ||\n component.type === EmbeddedFlowComponentType.PasswordInput ||\n component.type === EmbeddedFlowComponentType.EmailInput ||\n component.type === EmbeddedFlowComponentType.Select ||\n component.type === EmbeddedFlowComponentType.DateInput\n ) {\n // Use component.ref (mapped identifier) as the field name instead of component.id\n // This ensures form field names match what the input components use\n const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\n\n fields.push({\n initialValue: '',\n name: fieldName,\n required: component.required || false,\n validator: (value: string) => {\n if (component.required && (!value || value.trim() === '')) {\n return t('validations.required.field.error');\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n // Add email validation if it's an email field\n if (\n (component.type === EmbeddedFlowComponentType.EmailInput || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n\n return null;\n },\n });\n }\n\n if (component.components && Array.isArray(component.components)) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(components);\n return fields;\n },\n [t],\n );\n\n const formFields: any = useMemo(\n () => ((currentFlow?.data as any)?.components ? extractFormFields((currentFlow!.data as any).components) : []),\n [currentFlow, extractFormFields],\n );\n\n const form: any = useForm<Record<string, string>>({\n fields: formFields,\n initialValues: {},\n requiredMessage: t('validations.required.field.error'),\n revalidateOnChangeAfterBlur,\n validateOnBlur: true,\n validateOnChange: false,\n });\n\n const {\n values: formValues,\n touched: touchedFields,\n errors: formErrors,\n isValid: isFormValid,\n setValue: setFormValue,\n setTouched: setFormTouched,\n setTouchedFields,\n setErrors: setFormErrors,\n clearErrors: clearFormErrors,\n validateForm,\n touchAllFields,\n reset: resetForm,\n } = form;\n\n // Project server-side fieldErrors from the flow response into form state.\n // `setTouchedFields` avoids re-running client-side validation that would wipe\n // server errors when the client rules happen to pass.\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setTouchedFields(touched);\n setFormErrors(errors);\n }, [currentFlow, setFormErrors, setTouchedFields, clearFormErrors]);\n\n /**\n * Setup form fields based on the current flow.\n */\n const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedSignUpFlowResponse) => {\n const fields: any = extractFormFields((flowResponse.data as any)?.components || []);\n const initialValues: Record<string, string> = {};\n\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n\n resetForm();\n\n Object.keys(initialValues).forEach((key: any) => {\n setFormValue(key, initialValues[key]);\n });\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n /**\n * Determine whether a completed flow finished on a display-only screen.\n * Such a completion must be rendered, not redirected past.\n */\n const isDisplayOnlyCompletion = (response: EmbeddedSignUpFlowResponse): boolean => {\n const data: any = response?.data;\n const components: unknown[] | undefined = data?.components ?? data?.meta?.components;\n\n return (\n response?.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n Array.isArray(components) &&\n components.length > 0 &&\n !(response as {assertion?: string})?.assertion &&\n !data?.redirectURL &&\n !(response as any)?.redirectUrl\n );\n };\n\n /**\n * Handle a completed flow. A flow can complete on a display-only screen; in\n * that case render the screen and skip onComplete so the wrapper does not\n * immediately redirect away from it. Otherwise hand off to onComplete.\n */\n const handleFlowCompletion = (response: EmbeddedSignUpFlowResponse): void => {\n if (isDisplayOnlyCompletion(response)) {\n const normalized: any = normalizeFlowResponseLocal(response);\n setCurrentFlow(normalized);\n setupFormFields(normalized);\n return;\n }\n\n isFlowCompletedRef.current = true;\n onComplete?.(response);\n };\n\n /**\n * Handle input value changes.\n * Only updates the value without marking as touched.\n * Touched state is set on blur to avoid premature validation.\n */\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n /**\n * Handle input blur event.\n * Marks the field as touched, which triggers validation.\n */\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n /**\n * Check if the response contains a redirection URL and perform the redirect if necessary.\n * @param response - The sign-up response\n * @param existingPopup - A popup still open from the previous redirect, navigated instead of opening a new one\n * @returns true if a redirect was performed, false otherwise\n */\n const handleRedirectionIfNeeded = (response: EmbeddedSignUpFlowResponse, existingPopup?: Window): boolean => {\n if (response?.type === EmbeddedSignUpFlowType.Redirection && (response?.data as any)?.redirectURL) {\n /**\n * Open a popup window to handle redirection prompts for social sign-up\n */\n const redirectUrl: any = (response.data as any).redirectURL;\n // The reused popup can still deliver the previous round's callback (a late postMessage, or the old callback URL\n // until the new navigation commits), so only a callback carrying this round's state is accepted.\n const expectedState: string | null = new URL(redirectUrl as string).searchParams.get('state');\n const isThisRound = (state: unknown): boolean => !expectedState || state === expectedState;\n // A chained redirect arrives after an async round trip, with no user activation to open a new popup, so the\n // popup from the previous redirect is navigated instead.\n const reusablePopup: Window | null = existingPopup && !existingPopup.closed ? existingPopup : null;\n\n if (reusablePopup) {\n reusablePopup.location.href = redirectUrl;\n }\n\n const popup: Window | null =\n reusablePopup ?? window.open(redirectUrl, 'oauth_popup', 'width=500,height=600,scrollbars=yes,resizable=yes');\n\n if (!popup) {\n logger.error('Failed to open popup window');\n return false;\n }\n\n let hasProcessedCallback: any = false; // Prevent multiple processing\n let popupMonitor: ReturnType<typeof setInterval> | null = null;\n let messageHandler: ((event: MessageEvent) => Promise<void>) | null = null;\n\n /**\n * Clean up event listener and popup monitor\n */\n const cleanup = (): void => {\n if (messageHandler) {\n window.removeEventListener('message', messageHandler);\n }\n if (popupMonitor) {\n clearInterval(popupMonitor);\n }\n };\n cleanupActivePopupRef.current = cleanup;\n\n /**\n * Continue the flow with the provider's callback, then close the popup, unless a chained REDIRECTION\n * (e.g. the account-linking re-authentication) takes it over.\n */\n const continueWithCode = async (code: string, state: string): Promise<void> => {\n const payload: EmbeddedSignUpFlowRequest = {\n ...(currentFlow?.executionId && {executionId: currentFlow.executionId}),\n inputs: {\n code,\n state,\n },\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n try {\n const continueResponse: any = await onSubmit!(payload);\n cleanup();\n await setChallengeToken(continueResponse.challengeToken ?? null);\n onFlowChange?.(continueResponse);\n\n if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(continueResponse);\n onError?.(continueResponse);\n } else if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(continueResponse as EmbeddedSignUpFlowResponse);\n } else if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n const normalizedContinueResponse: any = normalizeFlowResponseLocal(continueResponse);\n\n // The provider callback can lead straight into another redirect, so follow it in the same popup.\n if (normalizedContinueResponse?.type === EmbeddedSignUpFlowType.Redirection) {\n if (!handleRedirectionIfNeeded(normalizedContinueResponse, popup)) {\n // Keep the current step rather than showing the redirect as a step of its own.\n popup.close();\n const popupError: Error = new Error(t('errors.signup.popup.failure'));\n handleError(popupError);\n onError?.(popupError);\n }\n return;\n }\n\n setCurrentFlow(normalizedContinueResponse);\n setupFormFields(normalizedContinueResponse);\n\n // Display error from INCOMPLETE response\n if (normalizedContinueResponse?.error) {\n handleError(normalizedContinueResponse);\n }\n }\n popup.close();\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n popup.close();\n cleanup();\n }\n };\n\n /**\n * Add an event listener to the window to capture the message from the popup\n */\n messageHandler = async function messageEventHandler(event: MessageEvent): Promise<void> {\n /**\n * Check if the message is from our popup window\n */\n if (event.source !== popup) {\n return;\n }\n\n /**\n * Check the origin of the message to ensure it's from a trusted source\n */\n const expectedOrigin: any = afterSignUpUrl ? new URL(afterSignUpUrl).origin : window.location.origin;\n if (event.origin !== expectedOrigin && event.origin !== window.location.origin) {\n return;\n }\n\n const {code, state} = event.data;\n\n // The poll may already have picked up this callback.\n if (code && state && isThisRound(state) && !hasProcessedCallback) {\n hasProcessedCallback = true;\n await continueWithCode(code, state);\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n /**\n * Monitor popup for closure and URL changes\n */\n popupMonitor = setInterval(async () => {\n try {\n if (popup.closed) {\n cleanup();\n return;\n }\n\n // Skip if we've already processed a callback\n if (hasProcessedCallback) {\n return;\n }\n\n // Try to access popup URL to check for callback\n try {\n const popupUrl: any = popup.location.href;\n\n // Check if we've been redirected to the callback URL\n if (popupUrl && (popupUrl.includes('code=') || popupUrl.includes('error='))) {\n // Parse the URL for OAuth parameters\n const url: any = new URL(popupUrl);\n const code: any = url.searchParams.get('code');\n const state: any = url.searchParams.get('state');\n const error: any = url.searchParams.get('error');\n\n // Still the previous round's callback page.\n if (!isThisRound(state)) {\n return;\n }\n\n hasProcessedCallback = true; // Set flag to prevent multiple processing\n\n if (error) {\n logger.error('OAuth error:');\n popup.close();\n cleanup();\n return;\n }\n\n if (code && state) {\n await continueWithCode(code, state);\n }\n }\n } catch (e) {\n // Cross-origin error is expected when popup navigates to OAuth provider\n // This is normal and we can ignore it\n }\n } catch (e) {\n logger.error('Error monitoring popup:');\n }\n }, 1000);\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Handle component submission (for buttons outside forms).\n */\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow || isFlowCompletedRef.current) {\n return;\n }\n\n // Only validate for form submit actions, skip for social/trigger actions\n if (!skipValidation) {\n // Mark all fields as touched before validation\n touchAllFields();\n\n const validation: ReturnType<typeof validateForm> = validateForm();\n\n if (!validation.isValid) {\n return;\n }\n }\n\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const composedData: Record<string, any> | undefined = data\n ? composeAffixedInputs(data as Record<string, string>, vendor)\n : undefined;\n\n // Filter out empty or undefined input values\n const filteredInputs: Record<string, any> = {};\n if (composedData) {\n Object.entries(composedData).forEach(([key, value]: [string, any]) => {\n if (value !== null && value !== undefined && value !== '') {\n filteredInputs[key] = value;\n }\n });\n }\n\n const payload: EmbeddedSignUpFlowRequest = {\n ...(currentFlow.executionId && {executionId: currentFlow.executionId}),\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs: filteredInputs,\n };\n\n const rawResponse: any = await onSubmit!(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(response as EmbeddedSignUpFlowResponse);\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n if (handleRedirectionIfNeeded(response)) {\n return;\n }\n\n if (response.data?.additionalData?.passkeyCreationOptions) {\n const {passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId ?? currentFlow?.executionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: component.id || 'submit',\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsLoading(false);\n return;\n }\n setCurrentFlow(response);\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n /**\n * Handle passkey registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (!passkeyState.isActive || !passkeyState.creationOptions || !passkeyState.executionId) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyRegistration = async (): Promise<void> => {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions!);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n const inputs: any = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n\n // After successful registration, submit the result to the server\n const payload: EmbeddedSignUpFlowRequest = {\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n } as any;\n\n const nextResponse: any = await onSubmit!(payload);\n const processedResponse: any = normalizeFlowResponseLocal(nextResponse);\n onFlowChange?.(processedResponse);\n\n if (processedResponse.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(processedResponse as EmbeddedSignUpFlowResponse);\n } else {\n setCurrentFlow(processedResponse);\n setupFormFields(processedResponse);\n }\n };\n\n performPasskeyRegistration()\n .then(() => {\n setPasskeyState({actionId: null, creationOptions: null, error: null, executionId: null, isActive: false});\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n handleError(error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.creationOptions, passkeyState.executionId]);\n\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup'),\n withVendorCSSClassPrefix(`signup--${size}`),\n withVendorCSSClassPrefix(`signup--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup__input'),\n size === 'small' && withVendorCSSClassPrefix('signup__input--small'),\n size === 'large' && withVendorCSSClassPrefix('signup__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup__button'),\n size === 'small' && withVendorCSSClassPrefix('signup__button--small'),\n size === 'large' && withVendorCSSClassPrefix('signup__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('signup__error')], errorClassName);\n\n const messageClasses: any = cx([withVendorCSSClassPrefix('signup__messages')], messageClassName);\n\n /**\n * Render form components based on flow data using the factory\n */\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderSignUpComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData: currentFlow?.data?.additionalData,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n t,\n variant,\n vendor,\n },\n ),\n [\n currentFlow,\n customRenderers,\n meta,\n t,\n formValues,\n touchedFields,\n formErrors,\n isFormValid,\n isLoading,\n size,\n theme,\n variant,\n vendor,\n inputClasses,\n buttonClasses,\n handleSubmit,\n handleInputBlur,\n ],\n );\n\n /**\n * Parse URL parameters to check for OAuth redirect state.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n return {\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n state: urlParams.get('state'),\n };\n };\n\n // Initialize the flow on component mount\n useEffect(() => {\n // Skip initialization if we're in an OAuth redirect state.\n const urlParams: any = getUrlParams();\n if (urlParams.code || urlParams.state) {\n return;\n }\n\n if (isInitialized && isStorageReady && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const payload: any = challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : undefined;\n const rawResponse: any = await onInitialize?.(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n await setChallengeToken(response.challengeToken ?? null);\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n // Clean up executionId and applicationId from URL after storing in state\n if (window?.location?.href) {\n const url: URL = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('applicationId');\n window.history.replaceState({}, '', url.toString());\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(response as EmbeddedSignUpFlowResponse);\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [\n isInitialized,\n isStorageReady,\n isFlowInitialized,\n onInitialize,\n onComplete,\n onError,\n onFlowChange,\n setupFormFields,\n normalizeFlowResponseLocal,\n afterSignUpUrl,\n t,\n ]);\n\n // If render props are provided, use them\n if (children) {\n const renderProps: BaseSignUpRenderProps = {\n components: (currentFlow?.data as any)?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n subtitle: flowSubtitle || t('signup.subheading'),\n title: flowTitle || t('signup.heading'),\n touched: touchedFields,\n validateForm: () => {\n const result: any = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return (\n <div id={id} className={containerClasses}>\n {children(renderProps)}\n </div>\n );\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={styles.loadingContainer}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!currentFlow) {\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\" className={errorClasses}>\n <AlertPrimitive.Title>{t('errors.heading')}</AlertPrimitive.Title>\n <AlertPrimitive.Description>{t('errors.signup.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Extract heading and subheading components and filter them from the main components\n const componentsToRender: any = (currentFlow.data as any)?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('signup.heading'),\n t('signup.subheading'),\n );\n\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {externalError && (\n <div className={styles.flowMessagesContainer}>\n <AlertPrimitive variant=\"error\" className={cx(styles.flowMessageItem, messageClasses)}>\n <AlertPrimitive.Description>{externalError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n {flowMessages && flowMessages.length > 0 && (\n <div className={styles.flowMessagesContainer}>\n {flowMessages.map((message: any, index: number) => (\n <AlertPrimitive\n key={message.id || index}\n variant={message.type?.toLowerCase() === 'error' ? 'error' : 'info'}\n className={cx(styles.flowMessageItem, messageClasses)}\n >\n <AlertPrimitive.Description>{message.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n ))}\n </div>\n )}\n <div className={styles.contentContainer}>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0 ? (\n renderComponents(componentsWithoutHeadings)\n ) : (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.signup.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseSignUp component that provides embedded sign-up flow for ThunderIDV2.\n * This component handles both the presentation layer and sign-up flow logic.\n * It accepts API functions as props to maintain framework independence.\n */\nconst BaseSignUp: FC<BaseSignUpProps> = ({preferences, showLogo = true, ...rest}: BaseSignUpProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const styles: any = useStyles(theme, colorScheme);\n\n const content: ReactElement = (\n <div>\n {showLogo && (\n <div className={styles.logoContainer}>\n <Logo size=\"large\" />\n </div>\n )}\n <FlowProvider>\n <BaseSignUpContent showLogo={showLogo} {...rest} />\n </FlowProvider>\n </div>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseSignUp;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseSignUp.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","BaseSignUpContent: FC<BaseSignUpProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","challengeTokenRef: any","initializationAttemptedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","extractFormFields: any","fields: FormField[]","EmbeddedFlowComponentType","fieldName: any","useForm","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","setupFormFields: any","fields: any","initialValues: Record<string, string>","data: any","components: unknown[] | undefined","EmbeddedSignUpFlowStatus","normalized: any","EmbeddedSignUpFlowType","redirectUrl: any","expectedState: string | null","reusablePopup: Window | null","popup: Window | null","hasProcessedCallback: any","popupMonitor: ReturnType<typeof setInterval> | null","messageHandler: ((event: MessageEvent) => Promise<void>) | null","payload: EmbeddedSignUpFlowRequest","continueResponse: any","normalizedContinueResponse: any","popupError: Error","expectedOrigin: any","popupUrl: any","url: any","code: any","state: any","error: any","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","response: any","effectiveExecutionIdForPasskey: any","passkeyResponse: any","handlePasskeyRegistration","passkeyResponseObj: any","inputs: any","processedResponse: any","containerClasses: any","cx","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderSignUpComponents","urlParams: any","payload: any","url: URL","result: any","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseSignUp: FC<BaseSignUpProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/SignUp/BaseSignUp.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedSignUpFlowRequest,\n EmbeddedSignUpFlowResponse,\n EmbeddedSignUpFlowStatus,\n EmbeddedSignUpFlowType,\n withVendorCSSClassPrefix,\n EmbeddedFlowComponentType,\n FieldError,\n createPackageComponentLogger,\n buildValidatorFromRules,\n Preferences,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport useStyles from './BaseSignUp.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useForm, FormField} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {cx} from '../../../../styles/emotion';\nimport composeAffixedInputs from '../../../../utils/composeAffixedInputs';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../../utils/getAuthComponentHeadings';\nimport {handlePasskeyRegistration} from '../../../../utils/passkey';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Logo from '../../../primitives/Logo/Logo';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderSignUpComponents} from '../AuthOptionFactory';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'BaseSignUp',\n);\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Render props for custom UI rendering\n */\nexport interface BaseSignUpRenderProps {\n /**\n * Additional data from the current flow step (e.g. `source` lookups for `KEY_VALUE_LIST`)\n */\n additionalData: Record<string, unknown>;\n\n /**\n * Flow components\n */\n components: any[];\n\n /**\n * API error (if any)\n */\n error?: Error | null;\n\n /**\n * Field validation errors\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to handle input changes\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state\n */\n isLoading: boolean;\n\n /**\n * Whether the form is valid\n */\n isValid: boolean;\n\n /**\n * Flow messages\n */\n messages: {message: string; type: string}[];\n\n /**\n * Flow subtitle\n */\n subtitle: string;\n\n /**\n * Flow title\n */\n title: string;\n\n /**\n * Touched fields\n */\n touched: Record<string, boolean>;\n\n /**\n * Function to validate the form\n */\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n\n /**\n * Form values\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseSignUp component.\n */\nexport interface BaseSignUpProps {\n /**\n * URL to redirect after successful sign-up.\n */\n afterSignUpUrl?: string;\n\n /**\n * Custom CSS class name for the submit button.\n */\n buttonClassName?: string;\n\n /**\n * Render props function for custom UI\n */\n children?: (props: BaseSignUpRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Error object to display\n */\n error?: Error | null;\n\n /**\n * Custom CSS class name for error messages.\n */\n errorClassName?: string;\n\n /**\n * HTML id attribute for the form container.\n */\n id?: string;\n\n /**\n * Custom CSS class name for form inputs.\n */\n inputClassName?: string;\n\n isInitialized?: boolean;\n\n /**\n * Custom CSS class name for info messages.\n */\n messageClassName?: string;\n\n /**\n * Callback function called when the sign-up flow completes and requires redirection.\n * This allows platform-specific handling of redirects (e.g., Next.js router.push).\n * @param response - The response from the sign-up flow containing the redirect URL, etc.\n */\n onComplete?: (response: EmbeddedSignUpFlowResponse) => void;\n\n /**\n * Callback function called when sign-up fails.\n * @param error - The error that occurred during sign-up.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when sign-up flow status changes.\n * @param response - The current sign-up response.\n */\n onFlowChange?: (response: EmbeddedSignUpFlowResponse) => void;\n\n /**\n * Function to initialize sign-up flow.\n * @returns Promise resolving to the initial sign-up response.\n */\n onInitialize?: (payload?: EmbeddedSignUpFlowRequest) => Promise<EmbeddedSignUpFlowResponse>;\n\n /**\n * Function to handle sign-up steps.\n * @param payload - The sign-up payload.\n * @returns Promise resolving to the sign-up response.\n */\n onSubmit?: (payload: EmbeddedSignUpFlowRequest) => Promise<EmbeddedSignUpFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Whether to redirect after sign-up.\n */\n shouldRedirectAfterSignUp?: boolean;\n\n /**\n * Whether to show the logo.\n */\n showLogo?: boolean;\n\n /**\n * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that consumes FlowContext and renders the sign-up UI.\n */\nconst BaseSignUpContent: FC<BaseSignUpProps> = ({\n afterSignUpUrl,\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\n id,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n errorClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isInitialized,\n children,\n showTitle = true,\n showSubtitle = true,\n revalidateOnChangeAfterBlur = false,\n}: BaseSignUpProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const {meta, isInitialized: isSdkInitialized, getStorageManager, vendor} = useThunderID();\n const styles: any = useStyles(theme, colorScheme);\n\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedSignUpFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // A completed flow leaves its last step rendered while the consumer navigates away, and the\n // redirect is not instantaneous. Latch the completion so the still-visible submit actions cannot\n // fire again: the executionId is spent, and re-submitting would start a whole new sign-up flow.\n const isFlowCompletedRef = useRef(false);\n // Tears down the active popup's listener and poll, so neither outlives the component.\n const cleanupActivePopupRef = useRef<(() => void) | null>(null);\n\n useEffect(() => () => cleanupActivePopupRef.current?.(), []);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n */\n useEffect(() => {\n if (!isSdkInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } catch {\n // StorageManager unavailable — continue without persisted token\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isSdkInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages\n * Uses the transformer's extractErrorMessage function.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear existing messages and add the error message\n clearMessages();\n addMessage({\n message: errorMessage,\n type: 'error',\n });\n },\n [t, addMessage, clearMessages],\n );\n\n /**\n * Normalize flow response to ensure component-driven format\n * Uses normalizeFlowResponse for modern API format responses\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedSignUpFlowResponse): EmbeddedSignUpFlowResponse => {\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.signUp.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...(response.data as any),\n components,\n },\n } as EmbeddedSignUpFlowResponse;\n }\n\n return response;\n },\n [t, meta],\n );\n\n /**\n * Extract form fields from flow components\n */\n const extractFormFields: any = useCallback(\n (components: any[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: any[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === EmbeddedFlowComponentType.TextInput ||\n component.type === EmbeddedFlowComponentType.PasswordInput ||\n component.type === EmbeddedFlowComponentType.EmailInput ||\n component.type === EmbeddedFlowComponentType.Select ||\n component.type === EmbeddedFlowComponentType.DateInput\n ) {\n // Use component.ref (mapped identifier) as the field name instead of component.id\n // This ensures form field names match what the input components use\n const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\n\n fields.push({\n initialValue: '',\n name: fieldName,\n required: component.required || false,\n validator: (value: string) => {\n if (component.required && (!value || value.trim() === '')) {\n return t('validations.required.field.error');\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n // Add email validation if it's an email field\n if (\n (component.type === EmbeddedFlowComponentType.EmailInput || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n\n return null;\n },\n });\n }\n\n if (component.components && Array.isArray(component.components)) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(components);\n return fields;\n },\n [t],\n );\n\n const formFields: any = useMemo(\n () => ((currentFlow?.data as any)?.components ? extractFormFields((currentFlow!.data as any).components) : []),\n [currentFlow, extractFormFields],\n );\n\n const form: any = useForm<Record<string, string>>({\n fields: formFields,\n initialValues: {},\n requiredMessage: t('validations.required.field.error'),\n revalidateOnChangeAfterBlur,\n validateOnBlur: true,\n validateOnChange: false,\n });\n\n const {\n values: formValues,\n touched: touchedFields,\n errors: formErrors,\n isValid: isFormValid,\n setValue: setFormValue,\n setTouched: setFormTouched,\n setTouchedFields,\n setErrors: setFormErrors,\n clearErrors: clearFormErrors,\n validateForm,\n touchAllFields,\n reset: resetForm,\n } = form;\n\n // Project server-side fieldErrors from the flow response into form state.\n // `setTouchedFields` avoids re-running client-side validation that would wipe\n // server errors when the client rules happen to pass.\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setTouchedFields(touched);\n setFormErrors(errors);\n }, [currentFlow, setFormErrors, setTouchedFields, clearFormErrors]);\n\n /**\n * Setup form fields based on the current flow.\n */\n const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedSignUpFlowResponse) => {\n const fields: any = extractFormFields((flowResponse.data as any)?.components || []);\n const initialValues: Record<string, string> = {};\n\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n\n resetForm();\n\n Object.keys(initialValues).forEach((key: any) => {\n setFormValue(key, initialValues[key]);\n });\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n /**\n * Determine whether a completed flow finished on a display-only screen.\n * Such a completion must be rendered, not redirected past.\n */\n const isDisplayOnlyCompletion = (response: EmbeddedSignUpFlowResponse): boolean => {\n const data: any = response?.data;\n const components: unknown[] | undefined = data?.components ?? data?.meta?.components;\n\n return (\n response?.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n Array.isArray(components) &&\n components.length > 0 &&\n !(response as {assertion?: string})?.assertion &&\n !data?.redirectURL &&\n !(response as any)?.redirectUrl\n );\n };\n\n /**\n * Handle a completed flow. A flow can complete on a display-only screen; in\n * that case render the screen and skip onComplete so the wrapper does not\n * immediately redirect away from it. Otherwise hand off to onComplete.\n */\n const handleFlowCompletion = (response: EmbeddedSignUpFlowResponse): void => {\n if (isDisplayOnlyCompletion(response)) {\n const normalized: any = normalizeFlowResponseLocal(response);\n setCurrentFlow(normalized);\n setupFormFields(normalized);\n return;\n }\n\n isFlowCompletedRef.current = true;\n onComplete?.(response);\n };\n\n /**\n * Handle input value changes.\n * Only updates the value without marking as touched.\n * Touched state is set on blur to avoid premature validation.\n */\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n /**\n * Handle input blur event.\n * Marks the field as touched, which triggers validation.\n */\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n /**\n * Check if the response contains a redirection URL and perform the redirect if necessary.\n * @param response - The sign-up response\n * @param existingPopup - A popup still open from the previous redirect, navigated instead of opening a new one\n * @returns true if a redirect was performed, false otherwise\n */\n const handleRedirectionIfNeeded = (response: EmbeddedSignUpFlowResponse, existingPopup?: Window): boolean => {\n if (response?.type === EmbeddedSignUpFlowType.Redirection && (response?.data as any)?.redirectURL) {\n /**\n * Open a popup window to handle redirection prompts for social sign-up\n */\n const redirectUrl: any = (response.data as any).redirectURL;\n // The reused popup can still deliver the previous round's callback (a late postMessage, or the old callback URL\n // until the new navigation commits), so only a callback carrying this round's state is accepted.\n const expectedState: string | null = new URL(redirectUrl as string).searchParams.get('state');\n const isThisRound = (state: unknown): boolean => !expectedState || state === expectedState;\n // A chained redirect arrives after an async round trip, with no user activation to open a new popup, so the\n // popup from the previous redirect is navigated instead.\n const reusablePopup: Window | null = existingPopup && !existingPopup.closed ? existingPopup : null;\n\n if (reusablePopup) {\n reusablePopup.location.href = redirectUrl;\n }\n\n const popup: Window | null =\n reusablePopup ?? window.open(redirectUrl, 'oauth_popup', 'width=500,height=600,scrollbars=yes,resizable=yes');\n\n if (!popup) {\n logger.error('Failed to open popup window');\n return false;\n }\n\n let hasProcessedCallback: any = false; // Prevent multiple processing\n let popupMonitor: ReturnType<typeof setInterval> | null = null;\n let messageHandler: ((event: MessageEvent) => Promise<void>) | null = null;\n\n /**\n * Clean up event listener and popup monitor\n */\n const cleanup = (): void => {\n if (messageHandler) {\n window.removeEventListener('message', messageHandler);\n }\n if (popupMonitor) {\n clearInterval(popupMonitor);\n }\n };\n cleanupActivePopupRef.current = cleanup;\n\n /**\n * Continue the flow with the provider's callback, then close the popup, unless a chained REDIRECTION\n * (e.g. the account-linking re-authentication) takes it over.\n */\n const continueWithCode = async (code: string, state: string): Promise<void> => {\n const payload: EmbeddedSignUpFlowRequest = {\n ...(currentFlow?.executionId && {executionId: currentFlow.executionId}),\n inputs: {\n code,\n state,\n },\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n try {\n const continueResponse: any = await onSubmit!(payload);\n cleanup();\n await setChallengeToken(continueResponse.challengeToken ?? null);\n onFlowChange?.(continueResponse);\n\n if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(continueResponse);\n onError?.(continueResponse);\n } else if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(continueResponse as EmbeddedSignUpFlowResponse);\n } else if (continueResponse.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n const normalizedContinueResponse: any = normalizeFlowResponseLocal(continueResponse);\n\n // The provider callback can lead straight into another redirect, so follow it in the same popup.\n if (normalizedContinueResponse?.type === EmbeddedSignUpFlowType.Redirection) {\n if (!handleRedirectionIfNeeded(normalizedContinueResponse, popup)) {\n // Keep the current step rather than showing the redirect as a step of its own.\n popup.close();\n const popupError: Error = new Error(t('errors.signup.popup.failure'));\n handleError(popupError);\n onError?.(popupError);\n }\n return;\n }\n\n setCurrentFlow(normalizedContinueResponse);\n setupFormFields(normalizedContinueResponse);\n\n // Display error from INCOMPLETE response\n if (normalizedContinueResponse?.error) {\n handleError(normalizedContinueResponse);\n }\n }\n popup.close();\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n popup.close();\n cleanup();\n }\n };\n\n /**\n * Add an event listener to the window to capture the message from the popup\n */\n messageHandler = async function messageEventHandler(event: MessageEvent): Promise<void> {\n /**\n * Check if the message is from our popup window\n */\n if (event.source !== popup) {\n return;\n }\n\n /**\n * Check the origin of the message to ensure it's from a trusted source\n */\n const expectedOrigin: any = afterSignUpUrl ? new URL(afterSignUpUrl).origin : window.location.origin;\n if (event.origin !== expectedOrigin && event.origin !== window.location.origin) {\n return;\n }\n\n const {code, state} = event.data;\n\n // The poll may already have picked up this callback.\n if (code && state && isThisRound(state) && !hasProcessedCallback) {\n hasProcessedCallback = true;\n await continueWithCode(code, state);\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n /**\n * Monitor popup for closure and URL changes\n */\n popupMonitor = setInterval(async () => {\n try {\n if (popup.closed) {\n cleanup();\n return;\n }\n\n // Skip if we've already processed a callback\n if (hasProcessedCallback) {\n return;\n }\n\n // Try to access popup URL to check for callback\n try {\n const popupUrl: any = popup.location.href;\n\n // Check if we've been redirected to the callback URL\n if (popupUrl && (popupUrl.includes('code=') || popupUrl.includes('error='))) {\n // Parse the URL for OAuth parameters\n const url: any = new URL(popupUrl);\n const code: any = url.searchParams.get('code');\n const state: any = url.searchParams.get('state');\n const error: any = url.searchParams.get('error');\n\n // Still the previous round's callback page.\n if (!isThisRound(state)) {\n return;\n }\n\n hasProcessedCallback = true; // Set flag to prevent multiple processing\n\n if (error) {\n logger.error('OAuth error:');\n popup.close();\n cleanup();\n return;\n }\n\n if (code && state) {\n await continueWithCode(code, state);\n }\n }\n } catch (e) {\n // Cross-origin error is expected when popup navigates to OAuth provider\n // This is normal and we can ignore it\n }\n } catch (e) {\n logger.error('Error monitoring popup:');\n }\n }, 1000);\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Handle component submission (for buttons outside forms).\n */\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow || isFlowCompletedRef.current) {\n return;\n }\n\n // Only validate for form submit actions, skip for social/trigger actions\n if (!skipValidation) {\n // Mark all fields as touched before validation\n touchAllFields();\n\n const validation: ReturnType<typeof validateForm> = validateForm();\n\n if (!validation.isValid) {\n return;\n }\n }\n\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const composedData: Record<string, any> | undefined = data\n ? composeAffixedInputs(data as Record<string, string>, vendor)\n : undefined;\n\n // Filter out empty or undefined input values\n const filteredInputs: Record<string, any> = {};\n if (composedData) {\n Object.entries(composedData).forEach(([key, value]: [string, any]) => {\n if (value !== null && value !== undefined && value !== '') {\n filteredInputs[key] = value;\n }\n });\n }\n\n const payload: EmbeddedSignUpFlowRequest = {\n ...(currentFlow.executionId && {executionId: currentFlow.executionId}),\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs: filteredInputs,\n };\n\n const rawResponse: any = await onSubmit!(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(response as EmbeddedSignUpFlowResponse);\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n if (handleRedirectionIfNeeded(response)) {\n return;\n }\n\n if (response.data?.additionalData?.passkeyCreationOptions) {\n const {passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId ?? currentFlow?.executionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: component.id || 'submit',\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsLoading(false);\n return;\n }\n setCurrentFlow(response);\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n /**\n * Handle passkey registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (!passkeyState.isActive || !passkeyState.creationOptions || !passkeyState.executionId) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyRegistration = async (): Promise<void> => {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions!);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n const inputs: any = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n\n // After successful registration, submit the result to the server\n const payload: EmbeddedSignUpFlowRequest = {\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n } as any;\n\n const nextResponse: any = await onSubmit!(payload);\n const processedResponse: any = normalizeFlowResponseLocal(nextResponse);\n onFlowChange?.(processedResponse);\n\n if (processedResponse.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(processedResponse as EmbeddedSignUpFlowResponse);\n } else {\n setCurrentFlow(processedResponse);\n setupFormFields(processedResponse);\n }\n };\n\n performPasskeyRegistration()\n .then(() => {\n setPasskeyState({actionId: null, creationOptions: null, error: null, executionId: null, isActive: false});\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n handleError(error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.creationOptions, passkeyState.executionId]);\n\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup'),\n withVendorCSSClassPrefix(`signup--${size}`),\n withVendorCSSClassPrefix(`signup--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup__input'),\n size === 'small' && withVendorCSSClassPrefix('signup__input--small'),\n size === 'large' && withVendorCSSClassPrefix('signup__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('signup__button'),\n size === 'small' && withVendorCSSClassPrefix('signup__button--small'),\n size === 'large' && withVendorCSSClassPrefix('signup__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('signup__error')], errorClassName);\n\n const messageClasses: any = cx([withVendorCSSClassPrefix('signup__messages')], messageClassName);\n\n /**\n * Render form components based on flow data using the factory\n */\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderSignUpComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData: currentFlow?.data?.additionalData,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n t,\n variant,\n vendor,\n },\n ),\n [\n currentFlow,\n customRenderers,\n meta,\n t,\n formValues,\n touchedFields,\n formErrors,\n isFormValid,\n isLoading,\n size,\n theme,\n variant,\n vendor,\n inputClasses,\n buttonClasses,\n handleSubmit,\n handleInputBlur,\n ],\n );\n\n /**\n * Parse URL parameters to check for OAuth redirect state.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n return {\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n state: urlParams.get('state'),\n };\n };\n\n // Initialize the flow on component mount\n useEffect(() => {\n // Skip initialization if we're in an OAuth redirect state.\n const urlParams: any = getUrlParams();\n if (urlParams.code || urlParams.state) {\n return;\n }\n\n if (isInitialized && isStorageReady && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const payload: any = challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : undefined;\n const rawResponse: any = await onInitialize?.(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n await setChallengeToken(response.challengeToken ?? null);\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n // Clean up executionId and applicationId from URL after storing in state\n if (window?.location?.href) {\n const url: URL = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('applicationId');\n window.history.replaceState({}, '', url.toString());\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Complete) {\n handleFlowCompletion(response as EmbeddedSignUpFlowResponse);\n return;\n }\n\n if (response.flowStatus === EmbeddedSignUpFlowStatus.Incomplete) {\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [\n isInitialized,\n isStorageReady,\n isFlowInitialized,\n onInitialize,\n onComplete,\n onError,\n onFlowChange,\n setupFormFields,\n normalizeFlowResponseLocal,\n afterSignUpUrl,\n t,\n ]);\n\n // If render props are provided, use them\n if (children) {\n const renderProps: BaseSignUpRenderProps = {\n additionalData: currentFlow?.data?.additionalData ?? {},\n components: (currentFlow?.data as any)?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n subtitle: flowSubtitle || t('signup.subheading'),\n title: flowTitle || t('signup.heading'),\n touched: touchedFields,\n validateForm: () => {\n const result: any = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return (\n <div id={id} className={containerClasses}>\n {children(renderProps)}\n </div>\n );\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={styles.loadingContainer}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!currentFlow) {\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\" className={errorClasses}>\n <AlertPrimitive.Title>{t('errors.heading')}</AlertPrimitive.Title>\n <AlertPrimitive.Description>{t('errors.signup.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Extract heading and subheading components and filter them from the main components\n const componentsToRender: any = (currentFlow.data as any)?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('signup.heading'),\n t('signup.subheading'),\n );\n\n return (\n <CardPrimitive id={id} className={cx(containerClasses, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {externalError && (\n <div className={styles.flowMessagesContainer}>\n <AlertPrimitive variant=\"error\" className={cx(styles.flowMessageItem, messageClasses)}>\n <AlertPrimitive.Description>{externalError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n {flowMessages && flowMessages.length > 0 && (\n <div className={styles.flowMessagesContainer}>\n {flowMessages.map((message: any, index: number) => (\n <AlertPrimitive\n key={message.id || index}\n variant={message.type?.toLowerCase() === 'error' ? 'error' : 'info'}\n className={cx(styles.flowMessageItem, messageClasses)}\n >\n <AlertPrimitive.Description>{message.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n ))}\n </div>\n )}\n <div className={styles.contentContainer}>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0 ? (\n renderComponents(componentsWithoutHeadings)\n ) : (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.signup.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseSignUp component that provides embedded sign-up flow for ThunderIDV2.\n * This component handles both the presentation layer and sign-up flow logic.\n * It accepts API functions as props to maintain framework independence.\n */\nconst BaseSignUp: FC<BaseSignUpProps> = ({preferences, showLogo = true, ...rest}: BaseSignUpProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const styles: any = useStyles(theme, colorScheme);\n\n const content: ReactElement = (\n <div>\n {showLogo && (\n <div className={styles.logoContainer}>\n <Logo size=\"large\" />\n </div>\n )}\n <FlowProvider>\n <BaseSignUpContent showLogo={showLogo} {...rest} />\n </FlowProvider>\n </div>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseSignUp;\n"],"mappings":"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"}
|
|
@@ -31,6 +31,9 @@ const AffixedField = ({ label, error, required, className, disabled, helperText,
|
|
|
31
31
|
const hasFixedPrefix = prefixList.length === 1;
|
|
32
32
|
const styles = require_AffixedField_styles.default(theme, colorScheme, disabled ?? false, hasError, hasPrefix);
|
|
33
33
|
const prefixDescriptionId = `${(0, react.useId)()}-prefix`;
|
|
34
|
+
const generatedId = (0, react.useId)();
|
|
35
|
+
const inputId = rest.id ?? generatedId;
|
|
36
|
+
const helperTextId = error || helperText ? `${inputId}-helper-text` : void 0;
|
|
34
37
|
const containerClassName = require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("affixed-field", "container")), styles["inputContainer"]);
|
|
35
38
|
const inputClassName = require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("affixed-field", "input")), styles["input"]);
|
|
36
39
|
const renderPrefix = () => {
|
|
@@ -60,9 +63,11 @@ const AffixedField = ({ label, error, required, className, disabled, helperText,
|
|
|
60
63
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_FormControl.default, {
|
|
61
64
|
error,
|
|
62
65
|
helperText,
|
|
66
|
+
helperTextId,
|
|
63
67
|
className: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("affixed-field")), className),
|
|
64
68
|
style,
|
|
65
69
|
children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_InputLabel.default, {
|
|
70
|
+
htmlFor: inputId,
|
|
66
71
|
required,
|
|
67
72
|
error: hasError,
|
|
68
73
|
children: label
|
|
@@ -75,7 +80,12 @@ const AffixedField = ({ label, error, required, className, disabled, helperText,
|
|
|
75
80
|
"aria-invalid": hasError,
|
|
76
81
|
"aria-required": required,
|
|
77
82
|
...rest,
|
|
78
|
-
|
|
83
|
+
id: inputId,
|
|
84
|
+
"aria-describedby": [
|
|
85
|
+
rest["aria-describedby"],
|
|
86
|
+
hasFixedPrefix ? prefixDescriptionId : void 0,
|
|
87
|
+
helperTextId
|
|
88
|
+
].filter(Boolean).join(" ") || void 0
|
|
79
89
|
})]
|
|
80
90
|
})]
|
|
81
91
|
});
|