@thunderid/react 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/cjs/components/adapters/Consent.cjs +21 -26
  2. package/dist/cjs/components/adapters/Consent.cjs.map +1 -1
  3. package/dist/cjs/components/adapters/ConsentCheckboxList.cjs +9 -3
  4. package/dist/cjs/components/adapters/ConsentCheckboxList.cjs.map +1 -1
  5. package/dist/cjs/components/presentation/LanguageSwitcher/LanguageSwitcher.cjs +10 -2
  6. package/dist/cjs/components/presentation/LanguageSwitcher/LanguageSwitcher.cjs.map +1 -1
  7. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs +1 -2
  8. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs.map +1 -1
  9. package/dist/cjs/components/presentation/auth/Recovery/BaseRecovery.cjs +1 -1
  10. package/dist/cjs/components/presentation/auth/Recovery/BaseRecovery.cjs.map +1 -1
  11. package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs +6 -3
  12. package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs.map +1 -1
  13. package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs +1 -1
  14. package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs.map +1 -1
  15. package/dist/cjs/contexts/FlowMeta/FlowMetaProvider.cjs +21 -9
  16. package/dist/cjs/contexts/FlowMeta/FlowMetaProvider.cjs.map +1 -1
  17. package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +2 -1
  18. package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
  19. package/dist/cjs/hooks/useForm.cjs +42 -5
  20. package/dist/cjs/hooks/useForm.cjs.map +1 -1
  21. package/dist/cjs/utils/resolveTranslationsInObject.cjs +3 -1
  22. package/dist/cjs/utils/resolveTranslationsInObject.cjs.map +1 -1
  23. package/dist/components/adapters/Consent.d.ts +1 -18
  24. package/dist/components/adapters/Consent.d.ts.map +1 -1
  25. package/dist/components/adapters/Consent.js +21 -25
  26. package/dist/components/adapters/Consent.js.map +1 -1
  27. package/dist/components/adapters/ConsentCheckboxList.d.ts +5 -0
  28. package/dist/components/adapters/ConsentCheckboxList.d.ts.map +1 -1
  29. package/dist/components/adapters/ConsentCheckboxList.js +9 -3
  30. package/dist/components/adapters/ConsentCheckboxList.js.map +1 -1
  31. package/dist/components/presentation/LanguageSwitcher/LanguageSwitcher.d.ts.map +1 -1
  32. package/dist/components/presentation/LanguageSwitcher/LanguageSwitcher.js +11 -3
  33. package/dist/components/presentation/LanguageSwitcher/LanguageSwitcher.js.map +1 -1
  34. package/dist/components/presentation/auth/AuthOptionFactory.d.ts.map +1 -1
  35. package/dist/components/presentation/auth/AuthOptionFactory.js +1 -2
  36. package/dist/components/presentation/auth/AuthOptionFactory.js.map +1 -1
  37. package/dist/components/presentation/auth/Recovery/BaseRecovery.d.ts.map +1 -1
  38. package/dist/components/presentation/auth/Recovery/BaseRecovery.js +1 -1
  39. package/dist/components/presentation/auth/Recovery/BaseRecovery.js.map +1 -1
  40. package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts.map +1 -1
  41. package/dist/components/presentation/auth/SignIn/BaseSignIn.js +6 -3
  42. package/dist/components/presentation/auth/SignIn/BaseSignIn.js.map +1 -1
  43. package/dist/components/presentation/auth/SignUp/BaseSignUp.js +1 -1
  44. package/dist/components/presentation/auth/SignUp/BaseSignUp.js.map +1 -1
  45. package/dist/contexts/FlowMeta/FlowMetaProvider.d.ts +15 -0
  46. package/dist/contexts/FlowMeta/FlowMetaProvider.d.ts.map +1 -1
  47. package/dist/contexts/FlowMeta/FlowMetaProvider.js +21 -9
  48. package/dist/contexts/FlowMeta/FlowMetaProvider.js.map +1 -1
  49. package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
  50. package/dist/contexts/ThunderID/ThunderIDProvider.js +2 -1
  51. package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
  52. package/dist/hooks/useForm.d.ts +5 -0
  53. package/dist/hooks/useForm.d.ts.map +1 -1
  54. package/dist/hooks/useForm.js +43 -6
  55. package/dist/hooks/useForm.js.map +1 -1
  56. package/dist/models/config.d.ts +2 -0
  57. package/dist/models/config.d.ts.map +1 -1
  58. package/dist/utils/resolveTranslationsInObject.d.ts.map +1 -1
  59. package/dist/utils/resolveTranslationsInObject.js +3 -1
  60. package/dist/utils/resolveTranslationsInObject.js.map +1 -1
  61. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"AuthOptionFactory.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClassCache: string | undefined","authOptionIconClassCache: string | undefined","css","EmbeddedFlowComponentType","FieldType","providerId: any","providerMatches: any","theme: any","customRenderers: ComponentRendererMap","key: string | number","customRenderer: ComponentRenderer | undefined","identifier: string","value: string","error: string","fieldType: string","hasPrefixes: boolean","hasPostfix: boolean","prefixStateKey: string","affixPrefixKey","postfixStateKey: string","affixPostfixKey","defaultPrefixValue: string","selectedPrefix: string","AffixedField","cx","createField","reportedLength: number","otpLength: number | undefined","numericOnly: boolean","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","EmbeddedFlowEventType","buttonType: HTMLButtonElement['type']","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","ConsentConstants","getConsentOptionalKey","socialButtonClassName: string","GoogleButton","GitHubButton","FacebookButton","MicrosoftButton","LinkedInButton","SignInWithEthereumButton","SmsOtpButton","startIconEl: ReactElement | null","endIconEl: ReactElement | null","Button","variant: any","textAlignClass: string","Typography","Divider","selectOptions: any","Select","DatePicker","formClass: string","blockComponents: any","richTextAction: EmbeddedFlowComponentAction | undefined","syntheticAction: EmbeddedFlowComponent","formData: Record<string, string>","handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined","anchor: HTMLAnchorElement | null","handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined","DOMPurify","explicitHeight: string","explicitWidth: string","ImageComponent","iconName: string","IconComponent: any","flowIconRegistry","direction: string","gap: number","align: string","justify: string","rawItems: string | number | undefined","parsedItems: number","items: number | null","isColumn: boolean","gridJustify: string","track: string","stackClass: string","stackChildren: (ReactElement | null)[]","consentPromptRawData: ConsentPromptData | string | undefined","Consent","textTemplate: string","timeoutMs: number","FlowTimer","sourceKey: string | undefined","CopyableText"],"sources":["../../../../../src/components/presentation/auth/AuthOptionFactory.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {CSSInterpolation} from '@emotion/css/create-instance';\nimport {\n ConsentConstants,\n FieldType,\n FlowMetadataResponse,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentAction,\n EmbeddedFlowComponentType,\n EmbeddedFlowTextVariant,\n EmbeddedFlowEventType,\n createPackageComponentLogger,\n resolveFlowTemplateLiterals,\n resolveEmojiUrisInHtml,\n ConsentPurposeData,\n ConsentPromptData,\n ConsentDecisions,\n ConsentPurposeDecision,\n ConsentAttributeElement,\n OrganizationUnitListResponse,\n PrefixOption,\n} from '@thunderid/browser';\nimport DOMPurify from 'dompurify';\nimport {ChangeEvent, cloneElement, CSSProperties, ReactElement} from 'react';\nimport {\n ComponentRenderer,\n ComponentRenderContext,\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport {UseTranslation} from '../../../hooks/useTranslation';\nimport {css, cx} from '../../../styles/emotion';\nimport Consent from '../../adapters/Consent';\nimport {getConsentOptionalKey} from '../../adapters/ConsentCheckboxList';\nimport FacebookButton from '../../adapters/FacebookButton';\nimport FlowTimer from '../../adapters/FlowTimer';\nimport GitHubButton from '../../adapters/GitHubButton';\nimport GoogleButton from '../../adapters/GoogleButton';\nimport ImageComponent from '../../adapters/ImageComponent';\nimport LinkedInButton from '../../adapters/LinkedInButton';\nimport MicrosoftButton from '../../adapters/MicrosoftButton';\nimport SignInWithEthereumButton from '../../adapters/SignInWithEthereumButton';\nimport SmsOtpButton from '../../adapters/SmsOtpButton';\nimport {createField} from '../../factories/FieldFactory';\nimport Button from '../../primitives/Button/Button';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport DatePicker from '../../primitives/DatePicker/DatePicker';\nimport Divider from '../../primitives/Divider/Divider';\nimport flowIconRegistry from '../../primitives/Icons/flowIconRegistry';\nimport AffixedField from '../../primitives/AffixedField/AffixedField';\nimport Select from '../../primitives/Select/Select';\nimport {affixPostfixKey, affixPrefixKey} from '../../../utils/composeAffixedInputs';\nimport Typography from '../../primitives/Typography/Typography';\nimport {TypographyVariant} from '../../primitives/Typography/Typography.styles';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'AuthOptionFactory',\n);\n\n/**\n * Replaces `emoji:` URIs embedded in HTML before DOMPurify sanitization.\n *\n * DOMPurify strips unknown URI schemes from attributes (e.g. `src=\"emoji:🦊\"` → `src=\"\"`).\n * This function converts:\n * - `<img src=\"emoji:X\" alt=\"Y\">` → `<span role=\"img\" aria-label=\"Y\">X</span>`\n * - Any remaining `emoji:X` text occurrences → `X`\n */\n\n// This module's functions (renderSignInComponents, etc.) are called imperatively from a\n// component's render, not React components/hooks themselves — so these classes can't be computed\n// at module scope: that runs at import time, before <ThunderIDProvider> has had a chance to\n// configure Emotion's CSP nonce, which would insert them into an un-nonced <style> tag. Instead\n// they're computed lazily, on first actual use (still just once — Emotion's own cache dedupes any\n// further calls to a no-op after that).\nlet richTextClassCache: string | undefined;\n\n/** Ensures rich-text content (including all inner elements from the server) always word-wraps. */\nfunction getRichTextClass(): string {\n richTextClassCache ??= css`\n overflow-wrap: anywhere;\n & * {\n overflow-wrap: anywhere;\n word-break: break-word;\n }\n & .rich-text-align-left {\n text-align: left;\n }\n & .rich-text-align-center {\n text-align: center;\n }\n & .rich-text-align-right {\n text-align: right;\n }\n & .rich-text-align-justify {\n text-align: justify;\n }\n & a,\n & .rich-text-link {\n text-decoration: underline;\n }\n & span[role='img'] {\n display: inline-block;\n }\n `;\n return richTextClassCache;\n}\n\nlet authOptionIconClassCache: string | undefined;\n\nfunction getAuthOptionIconClass(): string {\n authOptionIconClassCache ??= css({height: '1.25em', objectFit: 'contain', width: '1.25em'});\n return authOptionIconClassCache;\n}\n\nexport type AuthType = 'signin' | 'signup' | 'recovery';\n\n/**\n * Get the appropriate FieldType for an input component.\n */\n/** Upper bound on STACK grid slots, so a mistyped `items` cannot render thousands of cells. */\nconst MAX_STACK_ITEMS = 12;\n\nconst getFieldType = (variant: EmbeddedFlowComponentType): FieldType => {\n switch (variant) {\n case EmbeddedFlowComponentType.EmailInput:\n return FieldType.Email;\n case EmbeddedFlowComponentType.PhoneInput:\n return FieldType.Tel;\n case EmbeddedFlowComponentType.PasswordInput:\n return FieldType.Password;\n case EmbeddedFlowComponentType.TextInput:\n default:\n return FieldType.Text;\n }\n};\n\n/**\n * Get typography variant from component variant.\n */\nconst getTypographyVariant = (variant: string): any => {\n const variantMap: Record<EmbeddedFlowTextVariant, TypographyVariant> = {\n BODY_1: 'body1',\n BODY_2: 'body2',\n BUTTON_TEXT: 'button',\n CAPTION: 'caption',\n HEADING_1: 'h1',\n HEADING_2: 'h2',\n HEADING_3: 'h3',\n HEADING_4: 'h4',\n HEADING_5: 'h5',\n HEADING_6: 'h6',\n OVERLINE: 'overline',\n SUBTITLE_1: 'subtitle1',\n SUBTITLE_2: 'subtitle2',\n };\n\n return variantMap[variant] || 'h3';\n};\n\n/**\n * Check if a button text or action matches a social provider.\n */\nconst matchesSocialProvider = (\n actionId: string,\n eventType: string,\n buttonText: string,\n provider: string,\n authType: AuthType,\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n _componentVariant?: string,\n): boolean => {\n const providerId: any = `${provider}_auth`;\n const providerMatches: any = actionId === providerId || eventType === providerId;\n\n // Social buttons usually have \"Sign in with X\" or \"Continue with X\" text,\n // so also check button text for the provider name to increase chances of correct detection (especially for signup flows where action IDs are less standardized)\n if (buttonText.toLowerCase().includes(provider)) {\n return true;\n }\n\n // For signup, also check button text\n if (authType === 'signup') {\n return providerMatches || buttonText.toLowerCase().includes(provider);\n }\n\n return providerMatches;\n};\n\n/**\n * Create an auth component from flow component configuration.\n */\nconst createAuthComponentFromFlow = (\n component: EmbeddedFlowComponent,\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n authType: AuthType,\n options: {\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _customRenderers?: ComponentRendererMap;\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _theme?: any;\n /** Additional data from the flow response, used for different dynamic data */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Current consent purpose being rendered. Set by CONSENT_PURPOSE block iteration. */\n currentConsentPurpose?: ConsentPurposeData;\n inStack?: boolean;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n key?: string | number;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n } = {},\n): ReactElement | null => {\n const theme: any = options._theme;\n const customRenderers: ComponentRendererMap = options._customRenderers ?? {};\n\n const key: string | number = options.key || component.id;\n\n const customRenderer: ComponentRenderer | undefined =\n customRenderers[component.id] ?? customRenderers[component.type];\n if (customRenderer) {\n const renderCtx: ComponentRenderContext = {\n additionalData: options.additionalData,\n authType,\n formErrors,\n formValues,\n isFormValid,\n isLoading,\n meta: options.meta,\n resetForm,\n onInputBlur: options.onInputBlur,\n onInputChange,\n onSubmit: options.onSubmit,\n touchedFields,\n };\n return customRenderer(component, renderCtx);\n }\n\n /** Resolve any remaining {{t()}} or {{meta()}} template expressions in a string at render time. */\n const resolve = (text: string | undefined): string => {\n if (!text || (!options.t && !options.meta)) {\n return text || '';\n }\n return resolveFlowTemplateLiterals(text, {meta: options.meta, t: options.t || ((k: string): string => k)});\n };\n\n switch (component.type) {\n case EmbeddedFlowComponentType.TextInput:\n case EmbeddedFlowComponentType.PasswordInput:\n case EmbeddedFlowComponentType.EmailInput:\n case EmbeddedFlowComponentType.PhoneInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n const fieldType: string = getFieldType(component.type);\n\n // Prefix/postfix are accepted on any text-family input. When either is present,\n // route to AffixedField so the leading affix renders and submit-time composition\n // is picked up by composeAffixedInputs via the sentinel keys.\n // Both string.length and Array.length are defined, so a single truthy+length\n // check covers `prefixes?: string | PrefixOption[]`.\n const hasPrefixes: boolean = !!component.prefixes && component.prefixes.length > 0;\n const hasPostfix: boolean = typeof component.postfix === 'string' && component.postfix.length > 0;\n\n if (hasPrefixes || hasPostfix) {\n const prefixStateKey: string = affixPrefixKey(identifier, options.vendor);\n const postfixStateKey: string = affixPostfixKey(identifier, options.vendor);\n const defaultPrefixValue: string = hasPrefixes\n ? typeof component.prefixes === 'string'\n ? component.prefixes\n : (component.prefixes as PrefixOption[])[0].value\n : '';\n const selectedPrefix: string = formValues[prefixStateKey] ?? defaultPrefixValue;\n\n return (\n <AffixedField\n key={key}\n className={cx(options.inputClassName, component.classes)}\n id={component.id}\n label={resolve(component.label) || ''}\n name={identifier}\n placeholder={resolve(component.placeholder) || ''}\n required={component.required || false}\n error={error}\n value={value}\n type={fieldType}\n prefixes={component.prefixes}\n prefixValue={selectedPrefix}\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onInputChange(identifier, e.target.value)}\n onBlur={(): void => options.onInputBlur?.(identifier)}\n onPrefixChange={(newPrefix: string): void => onInputChange(prefixStateKey, newPrefix)}\n onFocus={(): void => {\n if (hasPrefixes && formValues[prefixStateKey] === undefined) {\n onInputChange(prefixStateKey, defaultPrefixValue);\n }\n if (hasPostfix && formValues[postfixStateKey] === undefined) {\n onInputChange(postfixStateKey, component.postfix!);\n }\n }}\n />\n );\n }\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: fieldType as FieldType,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.OtpInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // The server reports the length and character set of the code it generated, so the field\n // matches the OTP the user received. An older server omits both and the defaults apply.\n const reportedLength: number = Number(options.additionalData?.['otpLength']);\n const otpLength: number | undefined =\n Number.isInteger(reportedLength) && reportedLength > 0 ? reportedLength : undefined;\n const numericOnly: boolean = options.additionalData?.['otpNumericOnly'] !== 'false';\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n length: otpLength,\n name: identifier,\n numericOnly,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: FieldType.Otp,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.Action: {\n const actionId: string = component.id;\n const eventType: string = component.eventType || '';\n const buttonText: string = resolve(component.label);\n const componentVariant: string = component.variant || '';\n\n // Only validate on submit type events.\n const shouldSkipValidation: boolean = eventType.toUpperCase() !== EmbeddedFlowEventType.Submit;\n\n // Determine the button type based on the event type. Default to 'submit' if not recognized.\n const buttonTypeEnum = {\n [EmbeddedFlowEventType.Submit]: 'submit',\n [EmbeddedFlowEventType.Reset]: 'reset',\n [EmbeddedFlowEventType.Cancel]: 'button',\n [EmbeddedFlowEventType.Trigger]: 'button',\n [EmbeddedFlowEventType.Back]: 'button',\n };\n const buttonType: HTMLButtonElement['type'] = buttonTypeEnum[eventType.toUpperCase()] ?? 'submit';\n\n const handleClick = (): any => {\n if (options.onSubmit) {\n const formData: Record<string, any> = {};\n Object.keys(formValues).forEach((field: any) => {\n // Include all values, even empty strings, to ensure proper submission\n formData[field] = formValues[field];\n });\n\n // For consent actions, build the consent_decisions JSON from the form values.\n // The allow action captures per-attribute choices; the deny action sends\n // all purposes as rejected so the backend ConsentExecutor can fail the flow.\n const consentPrompt: ConsentPromptData | undefined = options.additionalData?.['consentPrompt'] as\n | ConsentPromptData\n | undefined;\n if (consentPrompt && eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n const isDeny: boolean = componentVariant.toLowerCase() !== 'primary';\n const decisions: ConsentDecisions = {\n approved: !isDeny,\n ...(isDeny ? {reason: ConsentConstants.REASON_USER_DENIED} : {}),\n purposes: consentPrompt.purposes.map(\n (p: ConsentPurposeData): ConsentPurposeDecision => ({\n approved: !isDeny,\n elements: [\n // Permission purposes carry no essential elements, so the server sends null here\n ...(p.essential ?? []).map((e): ConsentAttributeElement => ({approved: !isDeny, name: e.name})),\n ...(p.optional ?? []).map(\n (e): ConsentAttributeElement => ({\n approved: !isDeny && formValues[getConsentOptionalKey(p.purposeId, e.name)] === 'true',\n name: e.name,\n }),\n ),\n ],\n purposeName: p.purposeName!,\n }),\n ),\n };\n formData['consent_decisions'] = JSON.stringify(decisions);\n }\n\n // For submit events, pass the form data to the onSubmit callback. For other event types, reset the form and call onSubmit with an empty data object.\n if (eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n options.onSubmit(component, formData, shouldSkipValidation);\n } else {\n resetForm();\n options.onSubmit(component, {}, shouldSkipValidation);\n }\n }\n };\n\n // Render branded social login buttons for known action IDs\n\n const socialButtonClassName: string = cx(options.buttonClassName, component.classes);\n\n if (matchesSocialProvider(actionId, eventType, buttonText, 'google', authType, componentVariant)) {\n return <GoogleButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'github', authType, componentVariant)) {\n return <GitHubButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'facebook', authType, componentVariant)) {\n return <FacebookButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'microsoft', authType, componentVariant)) {\n return <MicrosoftButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'linkedin', authType, componentVariant)) {\n return <LinkedInButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'ethereum', authType, componentVariant)) {\n return (\n <SignInWithEthereumButton\n key={key}\n id={component.id}\n onClick={handleClick}\n className={socialButtonClassName}\n />\n );\n }\n if (actionId === 'prompt_mobile' || eventType === 'prompt_mobile') {\n return <SmsOtpButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n\n const startIconEl: ReactElement | null = component.startIcon ? (\n <img src={component.startIcon} alt=\"\" aria-hidden=\"true\" className={getAuthOptionIconClass()} />\n ) : null;\n\n const endIconEl: ReactElement | null = component.endIcon ? (\n <img src={component.endIcon} alt=\"\" aria-hidden=\"true\" className={getAuthOptionIconClass()} />\n ) : null;\n\n return (\n <Button\n fullWidth\n key={key}\n id={component.id}\n onClick={handleClick}\n disabled={\n isLoading ||\n (!isFormValid && !shouldSkipValidation) ||\n options.isTimeoutDisabled ||\n (component as any).config?.disabled\n }\n className={cx(options.buttonClassName, component.classes)}\n data-testid=\"thunderid-signin-submit\"\n variant={component.variant?.toLowerCase() === 'primary' ? 'solid' : 'outline'}\n color={component.variant?.toLowerCase() === 'primary' ? 'primary' : 'secondary'}\n startIcon={startIconEl}\n endIcon={endIconEl}\n type={buttonType}\n >\n {buttonText || 'Submit'}\n </Button>\n );\n }\n\n case EmbeddedFlowComponentType.Text: {\n const variant: any = getTypographyVariant(component.variant!);\n const textAlignClass: string = css({\n marginBottom: 2,\n textAlign:\n typeof component?.align === 'string' ? (component.align as React.CSSProperties['textAlign']) : 'left',\n });\n return (\n <Typography key={key} id={component.id} className={cx(component.classes, textAlignClass)} variant={variant}>\n {resolve(component.label)}\n </Typography>\n );\n }\n\n case EmbeddedFlowComponentType.Divider: {\n return <Divider key={key}>{resolve(component.label) || ''}</Divider>;\n }\n\n case EmbeddedFlowComponentType.Select: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // Options are pre-sanitized by flowTransformer to {value: string, label: string} format\n const selectOptions: any = (component.options || []).map((opt: any) => ({\n label: typeof opt === 'string' ? opt : String(opt.label ?? opt.value ?? ''),\n value: typeof opt === 'string' ? opt : String(opt.value ?? ''),\n }));\n\n return (\n <Select\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n options={selectOptions}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.DateInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n return (\n <DatePicker\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n dateFormat={component.dateFormat}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.OuSelect: {\n logger.warn('OU_SELECT component type is not supported. Skipping render.');\n return null;\n }\n\n case EmbeddedFlowComponentType.Block: {\n if (component.components && component.components.length > 0) {\n const formClass: string = css({\n display: 'flex',\n flexDirection: 'column',\n gap: `calc(${theme?.vars?.spacing?.unit ?? '4px'} * 2)`,\n });\n\n const blockComponents: any = component.components\n .map((childComponent: any, index: any) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n authType,\n {\n ...options,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n .filter(Boolean);\n\n return (\n <form id={component.id} key={key} className={cx(component.classes, formClass)}>\n {blockComponents}\n </form>\n );\n }\n return null;\n }\n\n case EmbeddedFlowComponentType.RichText: {\n const richTextAction: EmbeddedFlowComponentAction | undefined = component.action;\n\n const dispatchRichTextAction = (): void => {\n if (!richTextAction || !options.onSubmit) {\n return;\n }\n const eventTypeValue = String(richTextAction.eventType ?? EmbeddedFlowEventType.Submit);\n const shouldSkipValidation: boolean = eventTypeValue.toUpperCase() === String(EmbeddedFlowEventType.Trigger);\n const syntheticAction: EmbeddedFlowComponent = {\n eventType: eventTypeValue,\n id: `${component.id}_action`,\n ref: richTextAction.ref,\n type: EmbeddedFlowComponentType.Action,\n };\n const formData: Record<string, string> = {};\n Object.keys(formValues).forEach((field: string) => {\n formData[field] = formValues[field];\n });\n options.onSubmit(syntheticAction, formData, shouldSkipValidation);\n };\n\n // Sentinel-anchor contract: only anchors carrying `data-action-ref` equal to\n // richTextAction.ref dispatch the action. Anchors without the sentinel (or with\n // a non-matching one) are treated as ordinary links and are ignored here.\n const isMatchingSentinelAnchor = (anchor: HTMLAnchorElement): boolean =>\n anchor.getAttribute('data-action-ref') === richTextAction?.ref;\n\n const handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.MouseEvent<HTMLDivElement>): void => {\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n const handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return;\n }\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n return (\n // Sentinel anchors are made keyboard-operable via the container's onKeyDown\n // (Enter/Space activate the matching anchor). Authors should ensure the anchor\n // is focusable (`href` or `tabIndex`); the click+keydown delegation covers both\n // pointer and keyboard activation once focus lands on the anchor.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n key={key}\n className={getRichTextClass()}\n onClick={handleRichTextClick}\n onKeyDown={handleRichTextKeyDown}\n // Manually sanitizes with `DOMPurify`.\n // IMPORTANT: DO NOT REMOVE OR MODIFY THIS SANITIZATION STEP.\n dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(resolveEmojiUrisInHtml(resolve(component.label)))}}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Image: {\n const explicitHeight: string = resolve(component.height?.toString());\n const explicitWidth: string = resolve(component.width?.toString());\n return (\n <ImageComponent\n key={key}\n component={\n {\n config: {\n alt: resolve(component.alt) || resolve(component.label) || 'Image',\n height: explicitHeight || (options.inStack ? '50' : 'auto'),\n src: resolve(component.src),\n width: explicitWidth || (options.inStack ? '50' : '100%'),\n },\n } as any\n }\n formErrors={undefined!}\n formValues={undefined!}\n isFormValid={false}\n isLoading={false}\n onInputChange={(): void => {\n throw new Error('Function not implemented.');\n }}\n touchedFields={undefined!}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Icon: {\n const iconName: string = component.name || '';\n const IconComponent: any = flowIconRegistry[iconName];\n if (!IconComponent) {\n logger.warn(`Unknown icon name: \"${iconName}\". Skipping render.`);\n return null;\n }\n return <IconComponent key={key} size={component.size || 24} color={component.color || 'currentColor'} />;\n }\n\n case EmbeddedFlowComponentType.Stack: {\n const direction: string = (component as any).direction || 'row';\n const gap: number = (component as any).gap ?? 2;\n const align: string = (component as any).align || 'center';\n const justify: string = (component as any).justify || 'flex-start';\n\n // `items` is the number of slots across the main axis and `direction` picks\n // that axis: with `row` it is the column count (items: 2 with four buttons\n // renders a 2 x 2 grid), and with `column` it is the row count and children\n // flow into further columns. Fewer than two slots keeps the flex layout, so\n // stacks authored before grid support are unaffected.\n const rawItems: string | number | undefined = component.items;\n const parsedItems: number =\n typeof rawItems === 'string' ? Number(rawItems) : typeof rawItems === 'number' ? rawItems : NaN;\n const items: number | null =\n Number.isFinite(parsedItems) && Math.floor(parsedItems) >= 2\n ? Math.min(Math.floor(parsedItems), MAX_STACK_ITEMS)\n : null;\n // CSS Grid has no reverse auto-flow, so the reverse variants fall back to\n // their base axis rather than silently becoming a row.\n const isColumn: boolean = direction.startsWith('column');\n const gridJustify: string = component.justify ?? 'stretch';\n // Equal `1fr` tracks fill the container, leaving `justify-content` no free\n // space to distribute. Content-sized tracks restore it, so every justify\n // value has a visible effect while the default stays an even split.\n const track: string = gridJustify === 'stretch' ? '1fr' : 'auto';\n\n const stackStyle: CSSProperties =\n items !== null\n ? {\n alignItems: component.align ?? 'stretch',\n display: 'grid',\n gap: `${gap * 0.5}rem`,\n gridAutoFlow: isColumn ? 'column' : 'row',\n justifyContent: gridJustify,\n width: '100%',\n ...(isColumn\n ? {gridTemplateRows: `repeat(${items}, ${track})`}\n : {gridTemplateColumns: `repeat(${items}, ${track})`}),\n }\n : {\n alignItems: align,\n display: 'flex',\n flexDirection: direction as CSSProperties['flexDirection'],\n flexWrap: 'wrap',\n gap: `${gap * 0.5}rem`,\n justifyContent: justify,\n };\n\n const stackClass: string = css(stackStyle as CSSInterpolation);\n\n const stackChildren: (ReactElement | null)[] = component.components\n ? component.components.map((childComponent: any, index: number) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n authType,\n {\n ...options,\n inStack: true,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n : [];\n\n return (\n <div key={key} id={component.id} className={cx(component.classes, stackClass)}>\n {stackChildren}\n </div>\n );\n }\n\n case EmbeddedFlowComponentType.Consent: {\n const consentPromptRawData: ConsentPromptData | string | undefined = options.additionalData?.['consentPrompt'];\n\n return (\n <Consent\n key={key}\n consentData={consentPromptRawData as any}\n formValues={formValues}\n onInputChange={onInputChange}\n config={component.config}\n meta={options.meta}\n t={options.t}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Timer: {\n const textTemplate: string = resolve((component as any).label) || 'Time remaining: {time}';\n const timeoutMs: number = Number(options.additionalData?.['stepTimeout']) || 0;\n const expiresIn: number = timeoutMs > 0 ? Math.max(0, Math.floor((timeoutMs - Date.now()) / 1000)) : 0;\n\n return <FlowTimer key={key} expiresIn={expiresIn} textTemplate={textTemplate} />;\n }\n\n case EmbeddedFlowComponentType.CopyableText: {\n const sourceKey: string | undefined = (component as any).source;\n const value: string = sourceKey && options.additionalData ? String(options.additionalData[sourceKey] ?? '') : '';\n const labelText: string | undefined = resolve((component as any).label) || undefined;\n\n return <CopyableText key={key} label={labelText} value={value} />;\n }\n\n default:\n // Gracefully handle unsupported component types by returning null\n logger.warn(`Unsupported component type: ${component.type}. Skipping render.`);\n return null;\n }\n};\n\n/**\n * Processes an array of components and renders them as React elements for sign-in.\n */\nexport const renderSignInComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signin',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for sign-up.\n */\nexport const renderSignUpComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for recovery flow.\n */\nexport const renderRecoveryComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'recovery',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for invite user.\n * This is used by both InviteUser and AcceptInvite components.\n */\nexport const renderInviteUserComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Function to fetch child organization units for OU_SELECT components. */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n"],"mappings":"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ACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,0BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YAqBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,4BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YAuBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;;AAMjD,MAAa,8BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YA2BA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK"}
1
+ {"version":3,"file":"AuthOptionFactory.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClassCache: string | undefined","authOptionIconClassCache: string | undefined","css","EmbeddedFlowComponentType","FieldType","providerId: any","providerMatches: any","theme: any","customRenderers: ComponentRendererMap","key: string | number","customRenderer: ComponentRenderer | undefined","identifier: string","value: string","error: string","fieldType: string","hasPrefixes: boolean","hasPostfix: boolean","prefixStateKey: string","affixPrefixKey","postfixStateKey: string","affixPostfixKey","defaultPrefixValue: string","selectedPrefix: string","AffixedField","cx","createField","reportedLength: number","otpLength: number | undefined","numericOnly: boolean","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","EmbeddedFlowEventType","buttonType: HTMLButtonElement['type']","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","ConsentConstants","getConsentOptionalKey","socialButtonClassName: string","GoogleButton","GitHubButton","FacebookButton","MicrosoftButton","LinkedInButton","SignInWithEthereumButton","SmsOtpButton","startIconEl: ReactElement | null","endIconEl: ReactElement | null","Button","variant: any","textAlignClass: string","Typography","Divider","selectOptions: any","Select","DatePicker","formClass: string","blockComponents: any","richTextAction: EmbeddedFlowComponentAction | undefined","syntheticAction: EmbeddedFlowComponent","formData: Record<string, string>","handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined","anchor: HTMLAnchorElement | null","handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined","DOMPurify","explicitHeight: string","explicitWidth: string","ImageComponent","iconName: string","IconComponent: any","flowIconRegistry","direction: string","gap: number","align: string","justify: string","rawItems: string | number | undefined","parsedItems: number","items: number | null","isColumn: boolean","gridJustify: string","track: string","stackClass: string","stackChildren: (ReactElement | null)[]","consentPromptRawData: ConsentPromptData | string | undefined","Consent","textTemplate: string","timeoutMs: number","FlowTimer","sourceKey: string | undefined","CopyableText"],"sources":["../../../../../src/components/presentation/auth/AuthOptionFactory.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {CSSInterpolation} from '@emotion/css/create-instance';\nimport {\n ConsentConstants,\n FieldType,\n FlowMetadataResponse,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentAction,\n EmbeddedFlowComponentType,\n EmbeddedFlowTextVariant,\n EmbeddedFlowEventType,\n createPackageComponentLogger,\n resolveFlowTemplateLiterals,\n resolveEmojiUrisInHtml,\n ConsentPurposeData,\n ConsentPromptData,\n ConsentDecisions,\n ConsentPurposeDecision,\n ConsentAttributeElement,\n OrganizationUnitListResponse,\n PrefixOption,\n} from '@thunderid/browser';\nimport DOMPurify from 'dompurify';\nimport {ChangeEvent, cloneElement, CSSProperties, FormEvent, ReactElement} from 'react';\nimport {\n ComponentRenderer,\n ComponentRenderContext,\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport {UseTranslation} from '../../../hooks/useTranslation';\nimport {css, cx} from '../../../styles/emotion';\nimport Consent from '../../adapters/Consent';\nimport {getConsentOptionalKey} from '../../adapters/ConsentCheckboxList';\nimport FacebookButton from '../../adapters/FacebookButton';\nimport FlowTimer from '../../adapters/FlowTimer';\nimport GitHubButton from '../../adapters/GitHubButton';\nimport GoogleButton from '../../adapters/GoogleButton';\nimport ImageComponent from '../../adapters/ImageComponent';\nimport LinkedInButton from '../../adapters/LinkedInButton';\nimport MicrosoftButton from '../../adapters/MicrosoftButton';\nimport SignInWithEthereumButton from '../../adapters/SignInWithEthereumButton';\nimport SmsOtpButton from '../../adapters/SmsOtpButton';\nimport {createField} from '../../factories/FieldFactory';\nimport Button from '../../primitives/Button/Button';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport DatePicker from '../../primitives/DatePicker/DatePicker';\nimport Divider from '../../primitives/Divider/Divider';\nimport flowIconRegistry from '../../primitives/Icons/flowIconRegistry';\nimport AffixedField from '../../primitives/AffixedField/AffixedField';\nimport Select from '../../primitives/Select/Select';\nimport {affixPostfixKey, affixPrefixKey} from '../../../utils/composeAffixedInputs';\nimport Typography from '../../primitives/Typography/Typography';\nimport {TypographyVariant} from '../../primitives/Typography/Typography.styles';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'AuthOptionFactory',\n);\n\n/**\n * Replaces `emoji:` URIs embedded in HTML before DOMPurify sanitization.\n *\n * DOMPurify strips unknown URI schemes from attributes (e.g. `src=\"emoji:🦊\"` → `src=\"\"`).\n * This function converts:\n * - `<img src=\"emoji:X\" alt=\"Y\">` → `<span role=\"img\" aria-label=\"Y\">X</span>`\n * - Any remaining `emoji:X` text occurrences → `X`\n */\n\n// This module's functions (renderSignInComponents, etc.) are called imperatively from a\n// component's render, not React components/hooks themselves — so these classes can't be computed\n// at module scope: that runs at import time, before <ThunderIDProvider> has had a chance to\n// configure Emotion's CSP nonce, which would insert them into an un-nonced <style> tag. Instead\n// they're computed lazily, on first actual use (still just once — Emotion's own cache dedupes any\n// further calls to a no-op after that).\nlet richTextClassCache: string | undefined;\n\n/** Ensures rich-text content (including all inner elements from the server) always word-wraps. */\nfunction getRichTextClass(): string {\n richTextClassCache ??= css`\n overflow-wrap: anywhere;\n & * {\n overflow-wrap: anywhere;\n word-break: break-word;\n }\n & .rich-text-align-left {\n text-align: left;\n }\n & .rich-text-align-center {\n text-align: center;\n }\n & .rich-text-align-right {\n text-align: right;\n }\n & .rich-text-align-justify {\n text-align: justify;\n }\n & a,\n & .rich-text-link {\n text-decoration: underline;\n }\n & span[role='img'] {\n display: inline-block;\n }\n `;\n return richTextClassCache;\n}\n\nlet authOptionIconClassCache: string | undefined;\n\nfunction getAuthOptionIconClass(): string {\n authOptionIconClassCache ??= css({height: '1.25em', objectFit: 'contain', width: '1.25em'});\n return authOptionIconClassCache;\n}\n\nexport type AuthType = 'signin' | 'signup' | 'recovery';\n\n/**\n * Get the appropriate FieldType for an input component.\n */\n/** Upper bound on STACK grid slots, so a mistyped `items` cannot render thousands of cells. */\nconst MAX_STACK_ITEMS = 12;\n\nconst getFieldType = (variant: EmbeddedFlowComponentType): FieldType => {\n switch (variant) {\n case EmbeddedFlowComponentType.EmailInput:\n return FieldType.Email;\n case EmbeddedFlowComponentType.PhoneInput:\n return FieldType.Tel;\n case EmbeddedFlowComponentType.PasswordInput:\n return FieldType.Password;\n case EmbeddedFlowComponentType.TextInput:\n default:\n return FieldType.Text;\n }\n};\n\n/**\n * Get typography variant from component variant.\n */\nconst getTypographyVariant = (variant: string): any => {\n const variantMap: Record<EmbeddedFlowTextVariant, TypographyVariant> = {\n BODY_1: 'body1',\n BODY_2: 'body2',\n BUTTON_TEXT: 'button',\n CAPTION: 'caption',\n HEADING_1: 'h1',\n HEADING_2: 'h2',\n HEADING_3: 'h3',\n HEADING_4: 'h4',\n HEADING_5: 'h5',\n HEADING_6: 'h6',\n OVERLINE: 'overline',\n SUBTITLE_1: 'subtitle1',\n SUBTITLE_2: 'subtitle2',\n };\n\n return variantMap[variant] || 'h3';\n};\n\n/**\n * Check if a button text or action matches a social provider.\n */\nconst matchesSocialProvider = (\n actionId: string,\n eventType: string,\n buttonText: string,\n provider: string,\n authType: AuthType,\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n _componentVariant?: string,\n): boolean => {\n const providerId: any = `${provider}_auth`;\n const providerMatches: any = actionId === providerId || eventType === providerId;\n\n // Social buttons usually have \"Sign in with X\" or \"Continue with X\" text,\n // so also check button text for the provider name to increase chances of correct detection (especially for signup flows where action IDs are less standardized)\n if (buttonText.toLowerCase().includes(provider)) {\n return true;\n }\n\n // For signup, also check button text\n if (authType === 'signup') {\n return providerMatches || buttonText.toLowerCase().includes(provider);\n }\n\n return providerMatches;\n};\n\n/**\n * Create an auth component from flow component configuration.\n */\nconst createAuthComponentFromFlow = (\n component: EmbeddedFlowComponent,\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n authType: AuthType,\n options: {\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _customRenderers?: ComponentRendererMap;\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _theme?: any;\n /** Additional data from the flow response, used for different dynamic data */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Current consent purpose being rendered. Set by CONSENT_PURPOSE block iteration. */\n currentConsentPurpose?: ConsentPurposeData;\n inStack?: boolean;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n key?: string | number;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n } = {},\n): ReactElement | null => {\n const theme: any = options._theme;\n const customRenderers: ComponentRendererMap = options._customRenderers ?? {};\n\n const key: string | number = options.key || component.id;\n\n const customRenderer: ComponentRenderer | undefined =\n customRenderers[component.id] ?? customRenderers[component.type];\n if (customRenderer) {\n const renderCtx: ComponentRenderContext = {\n additionalData: options.additionalData,\n authType,\n formErrors,\n formValues,\n isFormValid,\n isLoading,\n meta: options.meta,\n resetForm,\n onInputBlur: options.onInputBlur,\n onInputChange,\n onSubmit: options.onSubmit,\n touchedFields,\n };\n return customRenderer(component, renderCtx);\n }\n\n /** Resolve any remaining {{t()}} or {{meta()}} template expressions in a string at render time. */\n const resolve = (text: string | undefined): string => {\n if (!text || (!options.t && !options.meta)) {\n return text || '';\n }\n return resolveFlowTemplateLiterals(text, {meta: options.meta, t: options.t || ((k: string): string => k)});\n };\n\n switch (component.type) {\n case EmbeddedFlowComponentType.TextInput:\n case EmbeddedFlowComponentType.PasswordInput:\n case EmbeddedFlowComponentType.EmailInput:\n case EmbeddedFlowComponentType.PhoneInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n const fieldType: string = getFieldType(component.type);\n\n // Prefix/postfix are accepted on any text-family input. When either is present,\n // route to AffixedField so the leading affix renders and submit-time composition\n // is picked up by composeAffixedInputs via the sentinel keys.\n // Both string.length and Array.length are defined, so a single truthy+length\n // check covers `prefixes?: string | PrefixOption[]`.\n const hasPrefixes: boolean = !!component.prefixes && component.prefixes.length > 0;\n const hasPostfix: boolean = typeof component.postfix === 'string' && component.postfix.length > 0;\n\n if (hasPrefixes || hasPostfix) {\n const prefixStateKey: string = affixPrefixKey(identifier, options.vendor);\n const postfixStateKey: string = affixPostfixKey(identifier, options.vendor);\n const defaultPrefixValue: string = hasPrefixes\n ? typeof component.prefixes === 'string'\n ? component.prefixes\n : (component.prefixes as PrefixOption[])[0].value\n : '';\n const selectedPrefix: string = formValues[prefixStateKey] ?? defaultPrefixValue;\n\n return (\n <AffixedField\n key={key}\n className={cx(options.inputClassName, component.classes)}\n id={component.id}\n label={resolve(component.label) || ''}\n name={identifier}\n placeholder={resolve(component.placeholder) || ''}\n required={component.required || false}\n error={error}\n value={value}\n type={fieldType}\n prefixes={component.prefixes}\n prefixValue={selectedPrefix}\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onInputChange(identifier, e.target.value)}\n onBlur={(): void => options.onInputBlur?.(identifier)}\n onPrefixChange={(newPrefix: string): void => onInputChange(prefixStateKey, newPrefix)}\n onFocus={(): void => {\n if (hasPrefixes && formValues[prefixStateKey] === undefined) {\n onInputChange(prefixStateKey, defaultPrefixValue);\n }\n if (hasPostfix && formValues[postfixStateKey] === undefined) {\n onInputChange(postfixStateKey, component.postfix!);\n }\n }}\n />\n );\n }\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: fieldType as FieldType,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.OtpInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // The server reports the length and character set of the code it generated, so the field\n // matches the OTP the user received. An older server omits both and the defaults apply.\n const reportedLength: number = Number(options.additionalData?.['otpLength']);\n const otpLength: number | undefined =\n Number.isInteger(reportedLength) && reportedLength > 0 ? reportedLength : undefined;\n const numericOnly: boolean = options.additionalData?.['otpNumericOnly'] !== 'false';\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n length: otpLength,\n name: identifier,\n numericOnly,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: FieldType.Otp,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.Action: {\n const actionId: string = component.id;\n const eventType: string = component.eventType || '';\n const buttonText: string = resolve(component.label);\n const componentVariant: string = component.variant || '';\n\n // Only validate on submit type events.\n const shouldSkipValidation: boolean = eventType.toUpperCase() !== EmbeddedFlowEventType.Submit;\n\n // Determine the button type based on the event type. Default to 'submit' if not recognized.\n const buttonTypeEnum = {\n [EmbeddedFlowEventType.Submit]: 'submit',\n [EmbeddedFlowEventType.Reset]: 'reset',\n [EmbeddedFlowEventType.Cancel]: 'button',\n [EmbeddedFlowEventType.Trigger]: 'button',\n [EmbeddedFlowEventType.Back]: 'button',\n };\n const buttonType: HTMLButtonElement['type'] = buttonTypeEnum[eventType.toUpperCase()] ?? 'submit';\n\n const handleClick = (): any => {\n if (options.onSubmit) {\n const formData: Record<string, any> = {};\n Object.keys(formValues).forEach((field: any) => {\n // Include all values, even empty strings, to ensure proper submission\n formData[field] = formValues[field];\n });\n\n // For consent actions, build the consent_decisions JSON from the form values.\n // The allow action captures per-attribute choices; the deny action sends\n // all purposes as rejected so the backend ConsentExecutor can fail the flow.\n const consentPrompt: ConsentPromptData | undefined = options.additionalData?.['consentPrompt'] as\n | ConsentPromptData\n | undefined;\n if (consentPrompt && eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n const isDeny: boolean = componentVariant.toLowerCase() !== 'primary';\n const decisions: ConsentDecisions = {\n approved: !isDeny,\n ...(isDeny ? {reason: ConsentConstants.REASON_USER_DENIED} : {}),\n purposes: consentPrompt.purposes.map(\n (p: ConsentPurposeData): ConsentPurposeDecision => ({\n approved: !isDeny,\n elements: [\n // Permission purposes carry no essential elements, so the server sends null here\n ...(p.essential ?? []).map((e): ConsentAttributeElement => ({approved: !isDeny, name: e.name})),\n ...(p.optional ?? []).map(\n (e): ConsentAttributeElement => ({\n approved: !isDeny && formValues[getConsentOptionalKey(p.purposeId, e.name)] === 'true',\n name: e.name,\n }),\n ),\n ],\n purposeName: p.purposeName!,\n }),\n ),\n };\n formData['consent_decisions'] = JSON.stringify(decisions);\n }\n\n // For submit events, pass the form data to the onSubmit callback. For other event types, reset the form and call onSubmit with an empty data object.\n if (eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n options.onSubmit(component, formData, shouldSkipValidation);\n } else {\n resetForm();\n options.onSubmit(component, {}, shouldSkipValidation);\n }\n }\n };\n\n // Render branded social login buttons for known action IDs\n\n const socialButtonClassName: string = cx(options.buttonClassName, component.classes);\n\n if (matchesSocialProvider(actionId, eventType, buttonText, 'google', authType, componentVariant)) {\n return <GoogleButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'github', authType, componentVariant)) {\n return <GitHubButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'facebook', authType, componentVariant)) {\n return <FacebookButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'microsoft', authType, componentVariant)) {\n return <MicrosoftButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'linkedin', authType, componentVariant)) {\n return <LinkedInButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'ethereum', authType, componentVariant)) {\n return (\n <SignInWithEthereumButton\n key={key}\n id={component.id}\n onClick={handleClick}\n className={socialButtonClassName}\n />\n );\n }\n if (actionId === 'prompt_mobile' || eventType === 'prompt_mobile') {\n return <SmsOtpButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n\n const startIconEl: ReactElement | null = component.startIcon ? (\n <img src={component.startIcon} alt=\"\" aria-hidden=\"true\" className={getAuthOptionIconClass()} />\n ) : null;\n\n const endIconEl: ReactElement | null = component.endIcon ? (\n <img src={component.endIcon} alt=\"\" aria-hidden=\"true\" className={getAuthOptionIconClass()} />\n ) : null;\n\n return (\n <Button\n fullWidth\n key={key}\n id={component.id}\n onClick={handleClick}\n disabled={\n isLoading ||\n (!isFormValid && !shouldSkipValidation) ||\n options.isTimeoutDisabled ||\n (component as any).config?.disabled\n }\n className={cx(options.buttonClassName, component.classes)}\n data-testid=\"thunderid-signin-submit\"\n variant={component.variant?.toLowerCase() === 'primary' ? 'solid' : 'outline'}\n color={component.variant?.toLowerCase() === 'primary' ? 'primary' : 'secondary'}\n startIcon={startIconEl}\n endIcon={endIconEl}\n type={buttonType}\n >\n {buttonText || 'Submit'}\n </Button>\n );\n }\n\n case EmbeddedFlowComponentType.Text: {\n const variant: any = getTypographyVariant(component.variant!);\n const textAlignClass: string = css({\n marginBottom: 2,\n textAlign:\n typeof component?.align === 'string' ? (component.align as React.CSSProperties['textAlign']) : 'left',\n });\n return (\n <Typography key={key} id={component.id} className={cx(component.classes, textAlignClass)} variant={variant}>\n {resolve(component.label)}\n </Typography>\n );\n }\n\n case EmbeddedFlowComponentType.Divider: {\n return <Divider key={key}>{resolve(component.label) || ''}</Divider>;\n }\n\n case EmbeddedFlowComponentType.Select: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // Options are pre-sanitized by flowTransformer to {value: string, label: string} format\n const selectOptions: any = (component.options || []).map((opt: any) => ({\n label: typeof opt === 'string' ? opt : String(opt.label ?? opt.value ?? ''),\n value: typeof opt === 'string' ? opt : String(opt.value ?? ''),\n }));\n\n return (\n <Select\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n options={selectOptions}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.DateInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n return (\n <DatePicker\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n dateFormat={component.dateFormat}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.OuSelect: {\n logger.warn('OU_SELECT component type is not supported. Skipping render.');\n return null;\n }\n\n case EmbeddedFlowComponentType.Block: {\n if (component.components && component.components.length > 0) {\n const formClass: string = css({\n display: 'flex',\n flexDirection: 'column',\n gap: `calc(${theme?.vars?.spacing?.unit ?? '4px'} * 2)`,\n });\n\n const blockComponents: any = component.components\n .map((childComponent: any, index: any) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n authType,\n {\n ...options,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n .filter(Boolean);\n\n // The submit button's `type=\"submit\"` (and pressing Enter in a field) would\n // otherwise trigger the browser's native form submission — a GET request to\n // the current URL with all field values (including passwords) as query params.\n // Actual submission is handled entirely via `onClick`/`onSubmit` above.\n return (\n <form\n id={component.id}\n key={key}\n className={cx(component.classes, formClass)}\n onSubmit={(event: FormEvent<HTMLFormElement>): void => event.preventDefault()}\n >\n {blockComponents}\n </form>\n );\n }\n return null;\n }\n\n case EmbeddedFlowComponentType.RichText: {\n const richTextAction: EmbeddedFlowComponentAction | undefined = component.action;\n\n const dispatchRichTextAction = (): void => {\n if (!richTextAction || !options.onSubmit) {\n return;\n }\n const eventTypeValue = String(richTextAction.eventType ?? EmbeddedFlowEventType.Submit);\n const shouldSkipValidation: boolean = eventTypeValue.toUpperCase() === String(EmbeddedFlowEventType.Trigger);\n const syntheticAction: EmbeddedFlowComponent = {\n eventType: eventTypeValue,\n id: `${component.id}_action`,\n ref: richTextAction.ref,\n type: EmbeddedFlowComponentType.Action,\n };\n const formData: Record<string, string> = {};\n Object.keys(formValues).forEach((field: string) => {\n formData[field] = formValues[field];\n });\n options.onSubmit(syntheticAction, formData, shouldSkipValidation);\n };\n\n // Sentinel-anchor contract: only anchors carrying `data-action-ref` equal to\n // richTextAction.ref dispatch the action. Anchors without the sentinel (or with\n // a non-matching one) are treated as ordinary links and are ignored here.\n const isMatchingSentinelAnchor = (anchor: HTMLAnchorElement): boolean =>\n anchor.getAttribute('data-action-ref') === richTextAction?.ref;\n\n const handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.MouseEvent<HTMLDivElement>): void => {\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n const handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return;\n }\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n return (\n // Sentinel anchors are made keyboard-operable via the container's onKeyDown\n // (Enter/Space activate the matching anchor). Authors should ensure the anchor\n // is focusable (`href` or `tabIndex`); the click+keydown delegation covers both\n // pointer and keyboard activation once focus lands on the anchor.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n key={key}\n className={getRichTextClass()}\n onClick={handleRichTextClick}\n onKeyDown={handleRichTextKeyDown}\n // Manually sanitizes with `DOMPurify`.\n // IMPORTANT: DO NOT REMOVE OR MODIFY THIS SANITIZATION STEP.\n dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(resolveEmojiUrisInHtml(resolve(component.label)))}}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Image: {\n const explicitHeight: string = resolve(component.height?.toString());\n const explicitWidth: string = resolve(component.width?.toString());\n return (\n <ImageComponent\n key={key}\n component={\n {\n config: {\n alt: resolve(component.alt) || resolve(component.label) || 'Image',\n height: explicitHeight || (options.inStack ? '50' : 'auto'),\n src: resolve(component.src),\n width: explicitWidth || (options.inStack ? '50' : '100%'),\n },\n } as any\n }\n formErrors={undefined!}\n formValues={undefined!}\n isFormValid={false}\n isLoading={false}\n onInputChange={(): void => {\n throw new Error('Function not implemented.');\n }}\n touchedFields={undefined!}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Icon: {\n const iconName: string = component.name || '';\n const IconComponent: any = flowIconRegistry[iconName];\n if (!IconComponent) {\n logger.warn(`Unknown icon name: \"${iconName}\". Skipping render.`);\n return null;\n }\n return <IconComponent key={key} size={component.size || 24} color={component.color || 'currentColor'} />;\n }\n\n case EmbeddedFlowComponentType.Stack: {\n const direction: string = (component as any).direction || 'row';\n const gap: number = (component as any).gap ?? 2;\n const align: string = (component as any).align || 'center';\n const justify: string = (component as any).justify || 'flex-start';\n\n // `items` is the number of slots across the main axis and `direction` picks\n // that axis: with `row` it is the column count (items: 2 with four buttons\n // renders a 2 x 2 grid), and with `column` it is the row count and children\n // flow into further columns. Fewer than two slots keeps the flex layout, so\n // stacks authored before grid support are unaffected.\n const rawItems: string | number | undefined = component.items;\n const parsedItems: number =\n typeof rawItems === 'string' ? Number(rawItems) : typeof rawItems === 'number' ? rawItems : NaN;\n const items: number | null =\n Number.isFinite(parsedItems) && Math.floor(parsedItems) >= 2\n ? Math.min(Math.floor(parsedItems), MAX_STACK_ITEMS)\n : null;\n // CSS Grid has no reverse auto-flow, so the reverse variants fall back to\n // their base axis rather than silently becoming a row.\n const isColumn: boolean = direction.startsWith('column');\n const gridJustify: string = component.justify ?? 'stretch';\n // Equal `1fr` tracks fill the container, leaving `justify-content` no free\n // space to distribute. Content-sized tracks restore it, so every justify\n // value has a visible effect while the default stays an even split.\n const track: string = gridJustify === 'stretch' ? '1fr' : 'auto';\n\n const stackStyle: CSSProperties =\n items !== null\n ? {\n alignItems: component.align ?? 'stretch',\n display: 'grid',\n gap: `${gap * 0.5}rem`,\n gridAutoFlow: isColumn ? 'column' : 'row',\n justifyContent: gridJustify,\n width: '100%',\n ...(isColumn\n ? {gridTemplateRows: `repeat(${items}, ${track})`}\n : {gridTemplateColumns: `repeat(${items}, ${track})`}),\n }\n : {\n alignItems: align,\n display: 'flex',\n flexDirection: direction as CSSProperties['flexDirection'],\n flexWrap: 'wrap',\n gap: `${gap * 0.5}rem`,\n justifyContent: justify,\n };\n\n const stackClass: string = css(stackStyle as CSSInterpolation);\n\n const stackChildren: (ReactElement | null)[] = component.components\n ? component.components.map((childComponent: any, index: number) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n authType,\n {\n ...options,\n inStack: true,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n : [];\n\n return (\n <div key={key} id={component.id} className={cx(component.classes, stackClass)}>\n {stackChildren}\n </div>\n );\n }\n\n case EmbeddedFlowComponentType.Consent: {\n const consentPromptRawData: ConsentPromptData | string | undefined = options.additionalData?.['consentPrompt'];\n\n return (\n <Consent\n key={key}\n consentData={consentPromptRawData as any}\n formValues={formValues}\n onInputChange={onInputChange}\n t={options.t}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Timer: {\n const textTemplate: string = resolve((component as any).label) || 'Time remaining: {time}';\n const timeoutMs: number = Number(options.additionalData?.['stepTimeout']) || 0;\n const expiresIn: number = timeoutMs > 0 ? Math.max(0, Math.floor((timeoutMs - Date.now()) / 1000)) : 0;\n\n return <FlowTimer key={key} expiresIn={expiresIn} textTemplate={textTemplate} />;\n }\n\n case EmbeddedFlowComponentType.CopyableText: {\n const sourceKey: string | undefined = (component as any).source;\n const value: string = sourceKey && options.additionalData ? String(options.additionalData[sourceKey] ?? '') : '';\n const labelText: string | undefined = resolve((component as any).label) || undefined;\n\n return <CopyableText key={key} label={labelText} value={value} />;\n }\n\n default:\n // Gracefully handle unsupported component types by returning null\n logger.warn(`Unsupported component type: ${component.type}. Skipping render.`);\n return null;\n }\n};\n\n/**\n * Processes an array of components and renders them as React elements for sign-in.\n */\nexport const renderSignInComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signin',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for sign-up.\n */\nexport const renderSignUpComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for recovery flow.\n */\nexport const renderRecoveryComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'recovery',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for invite user.\n * This is used by both InviteUser and AcceptInvite components.\n */\nexport const renderInviteUserComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n resetForm: () => void,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Function to fetch child organization units for OU_SELECT components. */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n /** Vendor namespace used to derive affix sentinel keys for prefix/postfix-bearing inputs. */\n vendor?: string;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,MAAMA,+DACJ,oBACA,oBACD;;;;;;;;;AAiBD,IAAIC;;AAGJ,SAAS,mBAA2B;AAClC,wBAAuB,mBAAG;;;;;;;;;;;;;;;;;;;;;;;;;;AA0B1B,QAAO;;AAGT,IAAIC;AAEJ,SAAS,yBAAiC;AACxC,8BAA6BC,oBAAI;EAAC,QAAQ;EAAU,WAAW;EAAW,OAAO;EAAS,CAAC;AAC3F,QAAO;;;;;;AAST,MAAM,kBAAkB;AAExB,MAAM,gBAAgB,YAAkD;AACtE,SAAQ,SAAR;EACE,KAAKC,8CAA0B,WAC7B,QAAOC,8BAAU;EACnB,KAAKD,8CAA0B,WAC7B,QAAOC,8BAAU;EACnB,KAAKD,8CAA0B,cAC7B,QAAOC,8BAAU;EACnB,KAAKD,8CAA0B;EAC/B,QACE,QAAOC,8BAAU;;;;;;AAOvB,MAAM,wBAAwB,YAAyB;AAiBrD,QAhBuE;EACrE,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,SAAS;EACT,WAAW;EACX,WAAW;EACX,WAAW;EACX,WAAW;EACX,WAAW;EACX,WAAW;EACX,UAAU;EACV,YAAY;EACZ,YAAY;EACb,CAEiB,YAAY;;;;;AAMhC,MAAM,yBACJ,UACA,WACA,YACA,UACA,UAEA,sBACY;CACZ,MAAMC,aAAkB,GAAG,SAAS;CACpC,MAAMC,kBAAuB,aAAa,cAAc,cAAc;AAItE,KAAI,WAAW,aAAa,CAAC,SAAS,SAAS,CAC7C,QAAO;AAIT,KAAI,aAAa,SACf,QAAO,mBAAmB,WAAW,aAAa,CAAC,SAAS,SAAS;AAGvE,QAAO;;;;;AAMT,MAAM,+BACJ,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA,UAyBI,EAAE,KACkB;CACxB,MAAMC,QAAa,QAAQ;CAC3B,MAAMC,kBAAwC,QAAQ,oBAAoB,EAAE;CAE5E,MAAMC,MAAuB,QAAQ,OAAO,UAAU;CAEtD,MAAMC,iBACJ,gBAAgB,UAAU,OAAO,gBAAgB,UAAU;AAC7D,KAAI,eAeF,QAAO,eAAe,WAdoB;EACxC,gBAAgB,QAAQ;EACxB;EACA;EACA;EACA;EACA;EACA,MAAM,QAAQ;EACd;EACA,aAAa,QAAQ;EACrB;EACA,UAAU,QAAQ;EAClB;EACD,CAC0C;;CAI7C,MAAM,WAAW,SAAqC;AACpD,MAAI,CAAC,QAAS,CAAC,QAAQ,KAAK,CAAC,QAAQ,KACnC,QAAO,QAAQ;AAEjB,8DAAmC,MAAM;GAAC,MAAM,QAAQ;GAAM,GAAG,QAAQ,OAAO,MAAsB;GAAG,CAAC;;AAG5G,SAAQ,UAAU,MAAlB;EACE,KAAKP,8CAA0B;EAC/B,KAAKA,8CAA0B;EAC/B,KAAKA,8CAA0B;EAC/B,KAAKA,8CAA0B,YAAY;GACzC,MAAMQ,aAAqB,UAAU;GACrC,MAAMC,QAAgB,WAAW,eAAe;GAEhD,MAAMC,QADqB,cAAc,eAAe,QACtB,WAAW,cAAc;GAC3D,MAAMC,YAAoB,aAAa,UAAU,KAAK;GAOtD,MAAMC,cAAuB,CAAC,CAAC,UAAU,YAAY,UAAU,SAAS,SAAS;GACjF,MAAMC,aAAsB,OAAO,UAAU,YAAY,YAAY,UAAU,QAAQ,SAAS;AAEhG,OAAI,eAAe,YAAY;IAC7B,MAAMC,iBAAyBC,4CAAe,YAAY,QAAQ,OAAO;IACzE,MAAMC,kBAA0BC,6CAAgB,YAAY,QAAQ,OAAO;IAC3E,MAAMC,qBAA6B,cAC/B,OAAO,UAAU,aAAa,WAC5B,UAAU,WACT,UAAU,SAA4B,GAAG,QAC5C;IACJ,MAAMC,iBAAyB,WAAW,mBAAmB;AAE7D,WACE,2CAACC;KAEC,WAAWC,mBAAG,QAAQ,gBAAgB,UAAU,QAAQ;KACxD,IAAI,UAAU;KACd,OAAO,QAAQ,UAAU,MAAM,IAAI;KACnC,MAAM;KACN,aAAa,QAAQ,UAAU,YAAY,IAAI;KAC/C,UAAU,UAAU,YAAY;KACzB;KACA;KACP,MAAM;KACN,UAAU,UAAU;KACpB,aAAa;KACb,WAAW,MAA2C,cAAc,YAAY,EAAE,OAAO,MAAM;KAC/F,cAAoB,QAAQ,cAAc,WAAW;KACrD,iBAAiB,cAA4B,cAAc,gBAAgB,UAAU;KACrF,eAAqB;AACnB,UAAI,eAAe,WAAW,oBAAoB,OAChD,eAAc,gBAAgB,mBAAmB;AAEnD,UAAI,cAAc,WAAW,qBAAqB,OAChD,eAAc,iBAAiB,UAAU,QAAS;;OApBjD,IAuBL;;AAkBN,kCAdmBC,iCAAY;IAC7B,WAAWD,mBAAG,QAAQ,gBAAgB,UAAU,QAAQ;IACxD;IACA,IAAI,UAAU;IACd,OAAO,QAAQ,UAAU,MAAM,IAAI;IACnC,MAAM;IACN,cAAc,QAAQ,cAAc,WAAW;IAC/C,WAAW,aAAqB,cAAc,YAAY,SAAS;IACnE,aAAa,QAAQ,UAAU,YAAY,IAAI;IAC/C,UAAU,UAAU,YAAY;IAChC,MAAM;IACN;IACD,CAAC,EAEyB,EAAC,KAAI,CAAC;;EAGnC,KAAKrB,8CAA0B,UAAU;GACvC,MAAMQ,aAAqB,UAAU;GACrC,MAAMC,QAAgB,WAAW,eAAe;GAEhD,MAAMC,QADqB,cAAc,eAAe,QACtB,WAAW,cAAc;GAI3D,MAAMa,iBAAyB,OAAO,QAAQ,iBAAiB,aAAa;GAC5E,MAAMC,YACJ,OAAO,UAAU,eAAe,IAAI,iBAAiB,IAAI,iBAAiB;GAC5E,MAAMC,cAAuB,QAAQ,iBAAiB,sBAAsB;AAkB5E,kCAhBmBH,iCAAY;IAC7B,WAAWD,mBAAG,QAAQ,gBAAgB,UAAU,QAAQ;IACxD;IACA,IAAI,UAAU;IACd,OAAO,QAAQ,UAAU,MAAM,IAAI;IACnC,QAAQ;IACR,MAAM;IACN;IACA,cAAc,QAAQ,cAAc,WAAW;IAC/C,WAAW,aAAqB,cAAc,YAAY,SAAS;IACnE,aAAa,QAAQ,UAAU,YAAY,IAAI;IAC/C,UAAU,UAAU,YAAY;IAChC,MAAMpB,8BAAU;IAChB;IACD,CAAC,EAEyB,EAAC,KAAI,CAAC;;EAGnC,KAAKD,8CAA0B,QAAQ;GACrC,MAAM0B,WAAmB,UAAU;GACnC,MAAMC,YAAoB,UAAU,aAAa;GACjD,MAAMC,aAAqB,QAAQ,UAAU,MAAM;GACnD,MAAMC,mBAA2B,UAAU,WAAW;GAGtD,MAAMC,uBAAgC,UAAU,aAAa,KAAKC,0CAAsB;GAUxF,MAAMC,aAPiB;KACpBD,0CAAsB,SAAS;KAC/BA,0CAAsB,QAAQ;KAC9BA,0CAAsB,SAAS;KAC/BA,0CAAsB,UAAU;KAChCA,0CAAsB,OAAO;IAC/B,CAC4D,UAAU,aAAa,KAAK;GAEzF,MAAM,oBAAyB;AAC7B,QAAI,QAAQ,UAAU;KACpB,MAAME,WAAgC,EAAE;AACxC,YAAO,KAAK,WAAW,CAAC,SAAS,UAAe;AAE9C,eAAS,SAAS,WAAW;OAC7B;KAKF,MAAMC,gBAA+C,QAAQ,iBAAiB;AAG9E,SAAI,iBAAiB,UAAU,aAAa,KAAKH,0CAAsB,QAAQ;MAC7E,MAAMI,SAAkB,iBAAiB,aAAa,KAAK;MAC3D,MAAMC,YAA8B;OAClC,UAAU,CAAC;OACX,GAAI,SAAS,EAAC,QAAQC,qCAAiB,oBAAmB,GAAG,EAAE;OAC/D,UAAU,cAAc,SAAS,KAC9B,OAAmD;QAClD,UAAU,CAAC;QACX,UAAU,CAER,IAAI,EAAE,aAAa,EAAE,EAAE,KAAK,OAAgC;SAAC,UAAU,CAAC;SAAQ,MAAM,EAAE;SAAK,EAAE,EAC/F,IAAI,EAAE,YAAY,EAAE,EAAE,KACnB,OAAgC;SAC/B,UAAU,CAAC,UAAU,WAAWC,kDAAsB,EAAE,WAAW,EAAE,KAAK,MAAM;SAChF,MAAM,EAAE;SACT,EACF,CACF;QACD,aAAa,EAAE;QAChB,EACF;OACF;AACD,eAAS,uBAAuB,KAAK,UAAU,UAAU;;AAI3D,SAAI,UAAU,aAAa,KAAKP,0CAAsB,OACpD,SAAQ,SAAS,WAAW,UAAU,qBAAqB;UACtD;AACL,iBAAW;AACX,cAAQ,SAAS,WAAW,EAAE,EAAE,qBAAqB;;;;GAO3D,MAAMQ,wBAAgClB,mBAAG,QAAQ,iBAAiB,UAAU,QAAQ;AAEpF,OAAI,sBAAsB,UAAU,WAAW,YAAY,UAAU,UAAU,iBAAiB,CAC9F,QAAO,2CAACmB;IAAuB,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;AAE7G,OAAI,sBAAsB,UAAU,WAAW,YAAY,UAAU,UAAU,iBAAiB,CAC9F,QAAO,2CAACC;IAAuB,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;AAE7G,OAAI,sBAAsB,UAAU,WAAW,YAAY,YAAY,UAAU,iBAAiB,CAChG,QAAO,2CAACC;IAAyB,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;AAE/G,OAAI,sBAAsB,UAAU,WAAW,YAAY,aAAa,UAAU,iBAAiB,CACjG,QAAO,2CAACC;IAA0B,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;AAEhH,OAAI,sBAAsB,UAAU,WAAW,YAAY,YAAY,UAAU,iBAAiB,CAChG,QAAO,2CAACC;IAAyB,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;AAE/G,OAAI,sBAAsB,UAAU,WAAW,YAAY,YAAY,UAAU,iBAAiB,CAChG,QACE,2CAACC;IAEC,IAAI,UAAU;IACd,SAAS;IACT,WAAW;MAHN,IAIL;AAGN,OAAI,aAAa,mBAAmB,cAAc,gBAChD,QAAO,2CAACC;IAAuB,IAAI,UAAU;IAAI,SAAS;IAAa,WAAW;MAAxD,IAAiF;GAG7G,MAAMC,cAAmC,UAAU,YACjD,2CAAC;IAAI,KAAK,UAAU;IAAW,KAAI;IAAG,eAAY;IAAO,WAAW,wBAAwB;KAAI,GAC9F;GAEJ,MAAMC,YAAiC,UAAU,UAC/C,2CAAC;IAAI,KAAK,UAAU;IAAS,KAAI;IAAG,eAAY;IAAO,WAAW,wBAAwB;KAAI,GAC5F;AAEJ,UACE,2CAACC;IACC;IAEA,IAAI,UAAU;IACd,SAAS;IACT,UACE,aACC,CAAC,eAAe,CAAC,wBAClB,QAAQ,qBACP,UAAkB,QAAQ;IAE7B,WAAW5B,mBAAG,QAAQ,iBAAiB,UAAU,QAAQ;IACzD,eAAY;IACZ,SAAS,UAAU,SAAS,aAAa,KAAK,YAAY,UAAU;IACpE,OAAO,UAAU,SAAS,aAAa,KAAK,YAAY,YAAY;IACpE,WAAW;IACX,SAAS;IACT,MAAM;cAEL,cAAc;MAjBV,IAkBE;;EAIb,KAAKrB,8CAA0B,MAAM;GACnC,MAAMkD,UAAe,qBAAqB,UAAU,QAAS;GAC7D,MAAMC,iBAAyBpD,oBAAI;IACjC,cAAc;IACd,WACE,OAAO,WAAW,UAAU,WAAY,UAAU,QAA6C;IAClG,CAAC;AACF,UACE,2CAACqD;IAAqB,IAAI,UAAU;IAAI,WAAW/B,mBAAG,UAAU,SAAS,eAAe;IAAW;cAChG,QAAQ,UAAU,MAAM;MADV,IAEJ;;EAIjB,KAAKrB,8CAA0B,QAC7B,QAAO,2CAACqD,qCAAmB,QAAQ,UAAU,MAAM,IAAI,MAAlC,IAA+C;EAGtE,KAAKrD,8CAA0B,QAAQ;GACrC,MAAMQ,aAAqB,UAAU;GACrC,MAAMC,QAAgB,WAAW,eAAe;GAEhD,MAAMC,QADqB,cAAc,eAAe,QACtB,WAAW,cAAc;GAG3D,MAAM4C,iBAAsB,UAAU,WAAW,EAAE,EAAE,KAAK,SAAc;IACtE,OAAO,OAAO,QAAQ,WAAW,MAAM,OAAO,IAAI,SAAS,IAAI,SAAS,GAAG;IAC3E,OAAO,OAAO,QAAQ,WAAW,MAAM,OAAO,IAAI,SAAS,GAAG;IAC/D,EAAE;AAEH,UACE,2CAACC;IAEC,IAAI,UAAU;IACd,MAAM;IACN,OAAO,QAAQ,UAAU,MAAM,IAAI;IACnC,aAAa,QAAQ,UAAU,YAAY;IAC3C,UAAU,UAAU;IACpB,SAAS;IACF;IACA;IACP,WAAW,MAAiB,cAAc,YAAY,EAAE,OAAO,MAAM;IACrE,cAAmB,QAAQ,cAAc,WAAW;IACpD,WAAWlC,mBAAG,QAAQ,gBAAgB,UAAU,QAAQ;MAXnD,IAYL;;EAIN,KAAKrB,8CAA0B,WAAW;GACxC,MAAMQ,aAAqB,UAAU;GACrC,MAAMC,QAAgB,WAAW,eAAe;GAEhD,MAAMC,QADqB,cAAc,eAAe,QACtB,WAAW,cAAc;AAE3D,UACE,2CAAC8C;IAEC,IAAI,UAAU;IACd,MAAM;IACN,OAAO,QAAQ,UAAU,MAAM,IAAI;IACnC,aAAa,QAAQ,UAAU,YAAY;IAC3C,UAAU,UAAU;IACpB,YAAY,UAAU;IACf;IACA;IACP,WAAW,MAAiB,cAAc,YAAY,EAAE,OAAO,MAAM;IACrE,cAAmB,QAAQ,cAAc,WAAW;IACpD,WAAWnC,mBAAG,QAAQ,gBAAgB,UAAU,QAAQ;MAXnD,IAYL;;EAIN,KAAKrB,8CAA0B;AAC7B,UAAO,KAAK,8DAA8D;AAC1E,UAAO;EAGT,KAAKA,8CAA0B;AAC7B,OAAI,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;IAC3D,MAAMyD,YAAoB1D,oBAAI;KAC5B,SAAS;KACT,eAAe;KACf,KAAK,QAAQ,OAAO,MAAM,SAAS,QAAQ,MAAM;KAClD,CAAC;IAEF,MAAM2D,kBAAuB,UAAU,WACpC,KAAK,gBAAqB,UACzB,4BACE,gBACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;KACE,GAAG;KACH,KAAK,eAAe,MAAM,GAAG,UAAU,GAAG,GAAG;KAC9C,CACF,CACF,CACA,OAAO,QAAQ;AAMlB,WACE,2CAAC;KACC,IAAI,UAAU;KAEd,WAAWrC,mBAAG,UAAU,SAAS,UAAU;KAC3C,WAAW,UAA4C,MAAM,gBAAgB;eAE5E;OAJI,IAKA;;AAGX,UAAO;EAGT,KAAKrB,8CAA0B,UAAU;GACvC,MAAM2D,iBAA0D,UAAU;GAE1E,MAAM,+BAAqC;AACzC,QAAI,CAAC,kBAAkB,CAAC,QAAQ,SAC9B;IAEF,MAAM,iBAAiB,OAAO,eAAe,aAAa5B,0CAAsB,OAAO;IACvF,MAAMD,uBAAgC,eAAe,aAAa,KAAK,OAAOC,0CAAsB,QAAQ;IAC5G,MAAM6B,kBAAyC;KAC7C,WAAW;KACX,IAAI,GAAG,UAAU,GAAG;KACpB,KAAK,eAAe;KACpB,MAAM5D,8CAA0B;KACjC;IACD,MAAM6D,WAAmC,EAAE;AAC3C,WAAO,KAAK,WAAW,CAAC,SAAS,UAAkB;AACjD,cAAS,SAAS,WAAW;MAC7B;AACF,YAAQ,SAAS,iBAAiB,UAAU,qBAAqB;;GAMnE,MAAM,4BAA4B,WAChC,OAAO,aAAa,kBAAkB,KAAK,gBAAgB;GAE7D,MAAMC,sBAA2E,kBAC5E,UAAkD;IACjD,MAAMC,SAAoC,MAAM,OAAuB,QAAQ,IAAI;AACnF,QAAI,CAAC,UAAU,CAAC,yBAAyB,OAAO,CAC9C;AAEF,UAAM,gBAAgB;AACtB,4BAAwB;OAE1B;GAEJ,MAAMC,wBAAgF,kBACjF,UAAqD;AACpD,QAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,IACzC;IAEF,MAAMD,SAAoC,MAAM,OAAuB,QAAQ,IAAI;AACnF,QAAI,CAAC,UAAU,CAAC,yBAAyB,OAAO,CAC9C;AAEF,UAAM,gBAAgB;AACtB,4BAAwB;OAE1B;AAEJ,UAME,2CAAC;IAEC,WAAW,kBAAkB;IAC7B,SAAS;IACT,WAAW;IAGX,yBAAyB,EAAC,QAAQE,kBAAU,yDAAgC,QAAQ,UAAU,MAAM,CAAC,CAAC,EAAC;MANlG,IAOL;;EAIN,KAAKjE,8CAA0B,OAAO;GACpC,MAAMkE,iBAAyB,QAAQ,UAAU,QAAQ,UAAU,CAAC;GACpE,MAAMC,gBAAwB,QAAQ,UAAU,OAAO,UAAU,CAAC;AAClE,UACE,2CAACC;IAEC,WACE,EACE,QAAQ;KACN,KAAK,QAAQ,UAAU,IAAI,IAAI,QAAQ,UAAU,MAAM,IAAI;KAC3D,QAAQ,mBAAmB,QAAQ,UAAU,OAAO;KACpD,KAAK,QAAQ,UAAU,IAAI;KAC3B,OAAO,kBAAkB,QAAQ,UAAU,OAAO;KACnD,EACF;IAEH,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,WAAW;IACX,qBAA2B;AACzB,WAAM,IAAI,MAAM,4BAA4B;;IAE9C,eAAe;MAlBV,IAmBL;;EAIN,KAAKpE,8CAA0B,MAAM;GACnC,MAAMqE,WAAmB,UAAU,QAAQ;GAC3C,MAAMC,gBAAqBC,iCAAiB;AAC5C,OAAI,CAAC,eAAe;AAClB,WAAO,KAAK,uBAAuB,SAAS,qBAAqB;AACjE,WAAO;;AAET,UAAO,2CAAC;IAAwB,MAAM,UAAU,QAAQ;IAAI,OAAO,UAAU,SAAS;MAA3D,IAA6E;;EAG1G,KAAKvE,8CAA0B,OAAO;GACpC,MAAMwE,YAAqB,UAAkB,aAAa;GAC1D,MAAMC,MAAe,UAAkB,OAAO;GAC9C,MAAMC,QAAiB,UAAkB,SAAS;GAClD,MAAMC,UAAmB,UAAkB,WAAW;GAOtD,MAAMC,WAAwC,UAAU;GACxD,MAAMC,cACJ,OAAO,aAAa,WAAW,OAAO,SAAS,GAAG,OAAO,aAAa,WAAW,WAAW;GAC9F,MAAMC,QACJ,OAAO,SAAS,YAAY,IAAI,KAAK,MAAM,YAAY,IAAI,IACvD,KAAK,IAAI,KAAK,MAAM,YAAY,EAAE,gBAAgB,GAClD;GAGN,MAAMC,WAAoB,UAAU,WAAW,SAAS;GACxD,MAAMC,cAAsB,UAAU,WAAW;GAIjD,MAAMC,QAAgB,gBAAgB,YAAY,QAAQ;GAwB1D,MAAMC,aAAqBnF,oBArBzB,UAAU,OACN;IACE,YAAY,UAAU,SAAS;IAC/B,SAAS;IACT,KAAK,GAAG,MAAM,GAAI;IAClB,cAAc,WAAW,WAAW;IACpC,gBAAgB;IAChB,OAAO;IACP,GAAI,WACA,EAAC,kBAAkB,UAAU,MAAM,IAAI,MAAM,IAAG,GAChD,EAAC,qBAAqB,UAAU,MAAM,IAAI,MAAM,IAAG;IACxD,GACD;IACE,YAAY;IACZ,SAAS;IACT,eAAe;IACf,UAAU;IACV,KAAK,GAAG,MAAM,GAAI;IAClB,gBAAgB;IACjB,CAEuD;GAE9D,MAAMoF,gBAAyC,UAAU,aACrD,UAAU,WAAW,KAAK,gBAAqB,UAC7C,4BACE,gBACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;IACE,GAAG;IACH,SAAS;IACT,KAAK,eAAe,MAAM,GAAG,UAAU,GAAG,GAAG;IAC9C,CACF,CACF,GACD,EAAE;AAEN,UACE,2CAAC;IAAc,IAAI,UAAU;IAAI,WAAW9D,mBAAG,UAAU,SAAS,WAAW;cAC1E;MADO,IAEJ;;EAIV,KAAKrB,8CAA0B,SAAS;GACtC,MAAMoF,uBAA+D,QAAQ,iBAAiB;AAE9F,UACE,2CAACC;IAEC,aAAa;IACD;IACG;IACf,GAAG,QAAQ;MAJN,IAKL;;EAIN,KAAKrF,8CAA0B,OAAO;GACpC,MAAMsF,eAAuB,QAAS,UAAkB,MAAM,IAAI;GAClE,MAAMC,YAAoB,OAAO,QAAQ,iBAAiB,eAAe,IAAI;AAG7E,UAAO,2CAACC;IAAoB,WAFF,YAAY,IAAI,KAAK,IAAI,GAAG,KAAK,OAAO,YAAY,KAAK,KAAK,IAAI,IAAK,CAAC,GAAG;IAErC;MAAzC,IAAyD;;EAGlF,KAAKxF,8CAA0B,cAAc;GAC3C,MAAMyF,YAAiC,UAAkB;GACzD,MAAMhF,QAAgB,aAAa,QAAQ,iBAAiB,OAAO,QAAQ,eAAe,cAAc,GAAG,GAAG;AAG9G,UAAO,2CAACiF;IAAuB,OAFO,QAAS,UAAkB,MAAM,IAAI;IAEnB;MAA9B,IAAuC;;EAGnE;AAEE,UAAO,KAAK,+BAA+B,UAAU,KAAK,oBAAoB;AAC9E,UAAO;;;;;;AAOb,MAAa,0BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YAuBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,0BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YAqBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,4BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YAuBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;;AAMjD,MAAa,8BACX,YACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,YA2BA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,WACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK"}
@@ -87,11 +87,11 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
87
87
  required: component.required || false,
88
88
  validator: (value) => {
89
89
  if (component.required && (!value || value.trim() === "")) return t("validations.required.field.error");
90
- if ((component.type === __thunderid_browser.EmbeddedFlowComponentType.EmailInput || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
91
90
  if (ruleValidator && value) {
92
91
  const ruleMessage = ruleValidator(value);
93
92
  if (ruleMessage) return t(ruleMessage);
94
93
  }
94
+ if ((component.type === __thunderid_browser.EmbeddedFlowComponentType.EmailInput || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
95
95
  return null;
96
96
  }
97
97
  });
@@ -1 +1 @@
1
- {"version":3,"file":"BaseRecovery.cjs","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: 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>","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","EmbeddedRecoveryFlowStatus","containerClasses: any","cx","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderRecoveryComponents","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedRecoveryFlowRequest,\n EmbeddedRecoveryFlowResponse,\n EmbeddedRecoveryFlowStatus,\n EmbeddedFlowComponentType,\n FieldError,\n withVendorCSSClassPrefix,\n buildValidatorFromRules,\n Preferences,\n FlowMetadataResponse,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useContext, useEffect, useMemo, useState, useCallback, useRef} from 'react';\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 AlertPrimitive from '../../../primitives/Alert/Alert';\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 {renderRecoveryComponents} from '../AuthOptionFactory';\nimport useStyles from '../SignUp/BaseSignUp.styles';\n\n/**\n * Render props for custom UI rendering.\n */\nexport interface BaseRecoveryRenderProps {\n components: any[];\n error?: Error | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n isLoading: boolean;\n isValid: boolean;\n messages: {message: string; type: string}[];\n meta: FlowMetadataResponse | null;\n subtitle: string;\n title: string;\n touched: Record<string, boolean>;\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseRecovery component.\n */\nexport interface BaseRecoveryProps {\n afterRecoveryUrl?: string;\n buttonClassName?: string;\n /**\n * Render props function for custom UI or static content\n */\n children?: ((props: BaseRecoveryRenderProps) => ReactNode) | ReactNode;\n className?: string;\n error?: Error | null;\n errorClassName?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n messageClassName?: string;\n onComplete?: (response: EmbeddedRecoveryFlowResponse) => void;\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedRecoveryFlowResponse) => void;\n onInitialize?: (payload?: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n onSubmit?: (payload: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\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 showLogo?: boolean;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that renders the V2 recovery UI and manages flow state.\n *\n * @internal\n */\nconst BaseRecoveryContent: FC<BaseRecoveryProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\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}: BaseRecoveryProps): 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, 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<EmbeddedRecoveryFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n clearMessages();\n addMessage({message: errorMessage, type: 'error'});\n },\n [t, addMessage, clearMessages],\n );\n\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedRecoveryFlowResponse): EmbeddedRecoveryFlowResponse => {\n if (response?.data?.components && Array.isArray(response.data.components)) {\n return response;\n }\n\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'components.recovery.errors.generic', resolveTranslations: false},\n meta,\n );\n\n return {...response, data: {...response.data, components: components as any}};\n }\n\n return response;\n },\n [t, meta],\n );\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 const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\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 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 // 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 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?.components ? extractFormFields(currentFlow.data.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 const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedRecoveryFlowResponse) => {\n const fields: any = extractFormFields(flowResponse.data?.components || []);\n const initialValues: Record<string, string> = {};\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n resetForm();\n Object.keys(initialValues).forEach((key: any) => setFormValue(key, initialValues[key]));\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow) return;\n\n if (!skipValidation) {\n touchAllFields();\n const validation: ReturnType<typeof validateForm> = validateForm();\n if (!validation.isValid) return;\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 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: EmbeddedRecoveryFlowRequest = {\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 if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\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 const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery'),\n withVendorCSSClassPrefix(`recovery--${size}`),\n withVendorCSSClassPrefix(`recovery--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__input'),\n size === 'small' && withVendorCSSClassPrefix('recovery__input--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__button'),\n size === 'small' && withVendorCSSClassPrefix('recovery__button--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('recovery__error')], errorClassName);\n const messageClasses: any = cx([withVendorCSSClassPrefix('recovery__messages')], messageClassName);\n\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderRecoveryComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n vendor,\n },\n ),\n [\n customRenderers,\n buttonClasses,\n formErrors,\n formValues,\n handleInputBlur,\n handleSubmit,\n inputClasses,\n isFormValid,\n meta,\n isLoading,\n size,\n theme,\n touchedFields,\n variant,\n vendor,\n ],\n );\n\n useEffect(() => {\n if (isInitialized && !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 rawResponse: any = await onInitialize?.();\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n }\n\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.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 isFlowInitialized,\n isInitialized,\n normalizeFlowResponseLocal,\n onComplete,\n onError,\n onFlowChange,\n onInitialize,\n setupFormFields,\n t,\n ]);\n\n if (children) {\n if (typeof children === 'function') {\n const renderProps: BaseRecoveryRenderProps = {\n components: currentFlow?.data?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle || t('recovery.subheading'),\n title: flowTitle || t('recovery.heading'),\n touched: touchedFields,\n validateForm: (): {fieldErrors: Record<string, string>; isValid: boolean} => {\n const result: ReturnType<typeof validateForm> = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return <div className={containerClasses}>{(children as any)(renderProps)}</div>;\n }\n\n return <div className={containerClasses}>{children}</div>;\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive 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 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.recovery.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n const componentsToRender: any = currentFlow.data?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('recovery.heading'),\n t('recovery.subheading'),\n );\n\n return (\n <CardPrimitive 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.recovery.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseRecovery component for ThunderIDV2 that provides an embedded account/password recovery flow.\n * Accepts API functions as props to maintain framework independence.\n */\nconst BaseRecovery: FC<BaseRecoveryProps> = ({\n preferences,\n showLogo = true,\n ...rest\n}: BaseRecoveryProps): 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 <BaseRecoveryContent 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 BaseRecovery;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BaseRecovery.cjs","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: 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>","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","EmbeddedRecoveryFlowStatus","containerClasses: any","cx","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderRecoveryComponents","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedRecoveryFlowRequest,\n EmbeddedRecoveryFlowResponse,\n EmbeddedRecoveryFlowStatus,\n EmbeddedFlowComponentType,\n FieldError,\n withVendorCSSClassPrefix,\n buildValidatorFromRules,\n Preferences,\n FlowMetadataResponse,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useContext, useEffect, useMemo, useState, useCallback, useRef} from 'react';\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 AlertPrimitive from '../../../primitives/Alert/Alert';\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 {renderRecoveryComponents} from '../AuthOptionFactory';\nimport useStyles from '../SignUp/BaseSignUp.styles';\n\n/**\n * Render props for custom UI rendering.\n */\nexport interface BaseRecoveryRenderProps {\n components: any[];\n error?: Error | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n isLoading: boolean;\n isValid: boolean;\n messages: {message: string; type: string}[];\n meta: FlowMetadataResponse | null;\n subtitle: string;\n title: string;\n touched: Record<string, boolean>;\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseRecovery component.\n */\nexport interface BaseRecoveryProps {\n afterRecoveryUrl?: string;\n buttonClassName?: string;\n /**\n * Render props function for custom UI or static content\n */\n children?: ((props: BaseRecoveryRenderProps) => ReactNode) | ReactNode;\n className?: string;\n error?: Error | null;\n errorClassName?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n messageClassName?: string;\n onComplete?: (response: EmbeddedRecoveryFlowResponse) => void;\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedRecoveryFlowResponse) => void;\n onInitialize?: (payload?: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n onSubmit?: (payload: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\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 showLogo?: boolean;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that renders the V2 recovery UI and manages flow state.\n *\n * @internal\n */\nconst BaseRecoveryContent: FC<BaseRecoveryProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\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}: BaseRecoveryProps): 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, 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<EmbeddedRecoveryFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n clearMessages();\n addMessage({message: errorMessage, type: 'error'});\n },\n [t, addMessage, clearMessages],\n );\n\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedRecoveryFlowResponse): EmbeddedRecoveryFlowResponse => {\n if (response?.data?.components && Array.isArray(response.data.components)) {\n return response;\n }\n\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'components.recovery.errors.generic', resolveTranslations: false},\n meta,\n );\n\n return {...response, data: {...response.data, components: components as any}};\n }\n\n return response;\n },\n [t, meta],\n );\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 const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\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 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?.components ? extractFormFields(currentFlow.data.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 const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedRecoveryFlowResponse) => {\n const fields: any = extractFormFields(flowResponse.data?.components || []);\n const initialValues: Record<string, string> = {};\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n resetForm();\n Object.keys(initialValues).forEach((key: any) => setFormValue(key, initialValues[key]));\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow) return;\n\n if (!skipValidation) {\n touchAllFields();\n const validation: ReturnType<typeof validateForm> = validateForm();\n if (!validation.isValid) return;\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 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: EmbeddedRecoveryFlowRequest = {\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 if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\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 const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery'),\n withVendorCSSClassPrefix(`recovery--${size}`),\n withVendorCSSClassPrefix(`recovery--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__input'),\n size === 'small' && withVendorCSSClassPrefix('recovery__input--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__button'),\n size === 'small' && withVendorCSSClassPrefix('recovery__button--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('recovery__error')], errorClassName);\n const messageClasses: any = cx([withVendorCSSClassPrefix('recovery__messages')], messageClassName);\n\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderRecoveryComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n vendor,\n },\n ),\n [\n customRenderers,\n buttonClasses,\n formErrors,\n formValues,\n handleInputBlur,\n handleSubmit,\n inputClasses,\n isFormValid,\n meta,\n isLoading,\n size,\n theme,\n touchedFields,\n variant,\n vendor,\n ],\n );\n\n useEffect(() => {\n if (isInitialized && !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 rawResponse: any = await onInitialize?.();\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n }\n\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.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 isFlowInitialized,\n isInitialized,\n normalizeFlowResponseLocal,\n onComplete,\n onError,\n onFlowChange,\n onInitialize,\n setupFormFields,\n t,\n ]);\n\n if (children) {\n if (typeof children === 'function') {\n const renderProps: BaseRecoveryRenderProps = {\n components: currentFlow?.data?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle || t('recovery.subheading'),\n title: flowTitle || t('recovery.heading'),\n touched: touchedFields,\n validateForm: (): {fieldErrors: Record<string, string>; isValid: boolean} => {\n const result: ReturnType<typeof validateForm> = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return <div className={containerClasses}>{(children as any)(renderProps)}</div>;\n }\n\n return <div className={containerClasses}>{children}</div>;\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive 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 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.recovery.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n const componentsToRender: any = currentFlow.data?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('recovery.heading'),\n t('recovery.subheading'),\n );\n\n return (\n <CardPrimitive 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.recovery.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseRecovery component for ThunderIDV2 that provides an embedded account/password recovery flow.\n * Accepts API functions as props to maintain framework independence.\n */\nconst BaseRecovery: FC<BaseRecoveryProps> = ({\n preferences,\n showLogo = true,\n ...rest\n}: BaseRecoveryProps): 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 <BaseRecoveryContent 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 BaseRecovery;\n"],"mappings":"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"}
@@ -31,7 +31,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
31
31
  const { meta, vendor } = require_useThunderID.default();
32
32
  const { theme } = require_useTheme.default();
33
33
  const customRenderers = (0, react.useContext)(require_ComponentRendererContext.default);
34
- const { t } = require_useTranslation.default();
34
+ const { t, currentLanguage } = require_useTranslation.default();
35
35
  const { subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages } = require_useFlow.default();
36
36
  const styles = require_BaseSignIn_styles.default(theme, theme.vars.colors.text.primary);
37
37
  const [isSubmitting, setIsSubmitting] = (0, react.useState)(false);
@@ -83,11 +83,11 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
83
83
  required: component.required || false,
84
84
  validator: (value) => {
85
85
  if (component.required && (!value || value.trim() === "")) return t("validations.required.field.error");
86
- if ((component.type === "EMAIL_INPUT" || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
87
86
  if (ruleValidator && value) {
88
87
  const ruleMessage = ruleValidator(value);
89
88
  if (ruleMessage) return t(ruleMessage);
90
89
  }
90
+ if ((component.type === "EMAIL_INPUT" || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
91
91
  return null;
92
92
  }
93
93
  });
@@ -98,7 +98,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
98
98
  processComponents(flowComponents);
99
99
  return fields;
100
100
  }, [t]);
101
- const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = require_useForm.useForm({
101
+ const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm, revalidateTouchedFields } = require_useForm.useForm({
102
102
  fields: (0, react.useMemo)(() => components ? extractFormFields(components) : [], [components, extractFormFields]),
103
103
  initialValues: {},
104
104
  requiredMessage: t("validations.required.field.error"),
@@ -123,6 +123,9 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
123
123
  setTouchedFields,
124
124
  clearFormErrors
125
125
  ]);
126
+ (0, react.useEffect)(() => {
127
+ revalidateTouchedFields();
128
+ }, [currentLanguage, revalidateTouchedFields]);
126
129
  /**
127
130
  * Handle input value changes.
128
131
  * Only updates the value without marking as touched.