@thunderid/react 1.0.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/dist/api/updateMeCredentials.d.ts +33 -0
  2. package/dist/api/updateMeCredentials.d.ts.map +1 -0
  3. package/dist/api/updateMeCredentials.js +29 -0
  4. package/dist/api/updateMeCredentials.js.map +1 -0
  5. package/dist/cjs/api/updateMeCredentials.cjs +31 -0
  6. package/dist/cjs/api/updateMeCredentials.cjs.map +1 -0
  7. package/dist/cjs/components/presentation/ChangeCredential/BaseChangeCredential.cjs +187 -0
  8. package/dist/cjs/components/presentation/ChangeCredential/BaseChangeCredential.cjs.map +1 -0
  9. package/dist/cjs/components/presentation/ChangeCredential/BaseChangeCredential.styles.cjs +108 -0
  10. package/dist/cjs/components/presentation/ChangeCredential/BaseChangeCredential.styles.cjs.map +1 -0
  11. package/dist/cjs/components/presentation/ChangeCredential/ChangeCredential.cjs +123 -0
  12. package/dist/cjs/components/presentation/ChangeCredential/ChangeCredential.cjs.map +1 -0
  13. package/dist/cjs/components/presentation/LanguageSwitcher/BaseLanguageSwitcher.cjs +1 -1
  14. package/dist/cjs/components/presentation/UserDropdown/BaseUserDropdown.cjs +2 -2
  15. package/dist/cjs/components/presentation/UserDropdown/BaseUserDropdown.cjs.map +1 -1
  16. package/dist/cjs/components/presentation/UserDropdown/UserDropdown.cjs +8 -4
  17. package/dist/cjs/components/presentation/UserDropdown/UserDropdown.cjs.map +1 -1
  18. package/dist/cjs/components/presentation/UserProfile/BaseUserProfile.styles.cjs +2 -0
  19. package/dist/cjs/components/presentation/UserProfile/BaseUserProfile.styles.cjs.map +1 -1
  20. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs +13 -0
  21. package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs.map +1 -1
  22. package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs +69 -66
  23. package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs.map +1 -1
  24. package/dist/cjs/components/primitives/KeyValueList/KeyValueList.cjs +41 -0
  25. package/dist/cjs/components/primitives/KeyValueList/KeyValueList.cjs.map +1 -0
  26. package/dist/cjs/components/primitives/KeyValueList/KeyValueList.styles.cjs +46 -0
  27. package/dist/cjs/components/primitives/KeyValueList/KeyValueList.styles.cjs.map +1 -0
  28. package/dist/cjs/components/primitives/PasswordField/PasswordField.cjs +2 -2
  29. package/dist/cjs/components/primitives/PasswordField/PasswordField.cjs.map +1 -1
  30. package/dist/cjs/contexts/Theme/ThemeProvider.cjs +26 -4
  31. package/dist/cjs/contexts/Theme/ThemeProvider.cjs.map +1 -1
  32. package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs +2 -0
  33. package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs.map +1 -1
  34. package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +7 -1
  35. package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
  36. package/dist/cjs/hooks/agents/useCreateAgent.cjs +26 -0
  37. package/dist/cjs/hooks/agents/useCreateAgent.cjs.map +1 -0
  38. package/dist/cjs/hooks/agents/useDeleteAgent.cjs +26 -0
  39. package/dist/cjs/hooks/agents/useDeleteAgent.cjs.map +1 -0
  40. package/dist/cjs/hooks/agents/useGetAgent.cjs +30 -0
  41. package/dist/cjs/hooks/agents/useGetAgent.cjs.map +1 -0
  42. package/dist/cjs/hooks/agents/useGetAgents.cjs +31 -0
  43. package/dist/cjs/hooks/agents/useGetAgents.cjs.map +1 -0
  44. package/dist/cjs/hooks/agents/useUpdateAgent.cjs +27 -0
  45. package/dist/cjs/hooks/agents/useUpdateAgent.cjs.map +1 -0
  46. package/dist/cjs/hooks/applications/useCreateApplication.cjs +31 -0
  47. package/dist/cjs/hooks/applications/useCreateApplication.cjs.map +1 -0
  48. package/dist/cjs/hooks/applications/useDeleteApplication.cjs +26 -0
  49. package/dist/cjs/hooks/applications/useDeleteApplication.cjs.map +1 -0
  50. package/dist/cjs/hooks/applications/useGetApplication.cjs +35 -0
  51. package/dist/cjs/hooks/applications/useGetApplication.cjs.map +1 -0
  52. package/dist/cjs/hooks/applications/useGetApplications.cjs +36 -0
  53. package/dist/cjs/hooks/applications/useGetApplications.cjs.map +1 -0
  54. package/dist/cjs/hooks/applications/useUpdateApplication.cjs +27 -0
  55. package/dist/cjs/hooks/applications/useUpdateApplication.cjs.map +1 -0
  56. package/dist/cjs/hooks/useManagementEndpoint.cjs +25 -0
  57. package/dist/cjs/hooks/useManagementEndpoint.cjs.map +1 -0
  58. package/dist/cjs/hooks/useResourceMutation.cjs +72 -0
  59. package/dist/cjs/hooks/useResourceMutation.cjs.map +1 -0
  60. package/dist/cjs/hooks/useResourceQuery.cjs +86 -0
  61. package/dist/cjs/hooks/useResourceQuery.cjs.map +1 -0
  62. package/dist/cjs/hooks/users/useCreateUser.cjs +26 -0
  63. package/dist/cjs/hooks/users/useCreateUser.cjs.map +1 -0
  64. package/dist/cjs/hooks/users/useDeleteUser.cjs +26 -0
  65. package/dist/cjs/hooks/users/useDeleteUser.cjs.map +1 -0
  66. package/dist/cjs/hooks/users/useGetUser.cjs +30 -0
  67. package/dist/cjs/hooks/users/useGetUser.cjs.map +1 -0
  68. package/dist/cjs/hooks/users/useGetUsers.cjs +38 -0
  69. package/dist/cjs/hooks/users/useGetUsers.cjs.map +1 -0
  70. package/dist/cjs/hooks/users/useUpdateUser.cjs +27 -0
  71. package/dist/cjs/hooks/users/useUpdateUser.cjs.map +1 -0
  72. package/dist/cjs/index.cjs +152 -0
  73. package/dist/cjs/utils/createAuthenticatedFetcher.cjs +43 -0
  74. package/dist/cjs/utils/createAuthenticatedFetcher.cjs.map +1 -0
  75. package/dist/cjs/utils/createResourceInvalidator.cjs +38 -0
  76. package/dist/cjs/utils/createResourceInvalidator.cjs.map +1 -0
  77. package/dist/components/actions/SignInButton/BaseSignInButton.js +2 -2
  78. package/dist/components/actions/SignInButton/BaseSignInButton.js.map +1 -1
  79. package/dist/components/actions/SignOutButton/BaseSignOutButton.js +2 -2
  80. package/dist/components/actions/SignOutButton/BaseSignOutButton.js.map +1 -1
  81. package/dist/components/actions/SignUpButton/BaseSignUpButton.js +2 -2
  82. package/dist/components/actions/SignUpButton/BaseSignUpButton.js.map +1 -1
  83. package/dist/components/adapters/FlowTimer.js +2 -2
  84. package/dist/components/adapters/FlowTimer.js.map +1 -1
  85. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.d.ts +100 -0
  86. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.d.ts.map +1 -0
  87. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.js +183 -0
  88. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.js.map +1 -0
  89. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.styles.d.ts +10 -0
  90. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.styles.d.ts.map +1 -0
  91. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.styles.js +108 -0
  92. package/dist/components/presentation/ChangeCredential/BaseChangeCredential.styles.js.map +1 -0
  93. package/dist/components/presentation/ChangeCredential/ChangeCredential.d.ts +55 -0
  94. package/dist/components/presentation/ChangeCredential/ChangeCredential.d.ts.map +1 -0
  95. package/dist/components/presentation/ChangeCredential/ChangeCredential.js +119 -0
  96. package/dist/components/presentation/ChangeCredential/ChangeCredential.js.map +1 -0
  97. package/dist/components/presentation/LanguageSwitcher/BaseLanguageSwitcher.js +3 -3
  98. package/dist/components/presentation/LanguageSwitcher/BaseLanguageSwitcher.js.map +1 -1
  99. package/dist/components/presentation/UserDropdown/BaseUserDropdown.d.ts +5 -0
  100. package/dist/components/presentation/UserDropdown/BaseUserDropdown.d.ts.map +1 -1
  101. package/dist/components/presentation/UserDropdown/BaseUserDropdown.js +2 -2
  102. package/dist/components/presentation/UserDropdown/BaseUserDropdown.js.map +1 -1
  103. package/dist/components/presentation/UserDropdown/UserDropdown.d.ts +12 -0
  104. package/dist/components/presentation/UserDropdown/UserDropdown.d.ts.map +1 -1
  105. package/dist/components/presentation/UserDropdown/UserDropdown.js +11 -7
  106. package/dist/components/presentation/UserDropdown/UserDropdown.js.map +1 -1
  107. package/dist/components/presentation/UserProfile/BaseUserProfile.js +8 -8
  108. package/dist/components/presentation/UserProfile/BaseUserProfile.js.map +1 -1
  109. package/dist/components/presentation/UserProfile/BaseUserProfile.styles.d.ts.map +1 -1
  110. package/dist/components/presentation/UserProfile/BaseUserProfile.styles.js +2 -0
  111. package/dist/components/presentation/UserProfile/BaseUserProfile.styles.js.map +1 -1
  112. package/dist/components/presentation/auth/AuthOptionFactory.d.ts.map +1 -1
  113. package/dist/components/presentation/auth/AuthOptionFactory.js +14 -1
  114. package/dist/components/presentation/auth/AuthOptionFactory.js.map +1 -1
  115. package/dist/components/presentation/auth/SignIn/SignIn.js +2 -2
  116. package/dist/components/presentation/auth/SignIn/SignIn.js.map +1 -1
  117. package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts.map +1 -1
  118. package/dist/components/presentation/auth/SignUp/BaseSignUp.js +69 -66
  119. package/dist/components/presentation/auth/SignUp/BaseSignUp.js.map +1 -1
  120. package/dist/components/primitives/AffixedField/AffixedField.js +2 -2
  121. package/dist/components/primitives/AffixedField/AffixedField.js.map +1 -1
  122. package/dist/components/primitives/KeyValueList/KeyValueList.d.ts +19 -0
  123. package/dist/components/primitives/KeyValueList/KeyValueList.d.ts.map +1 -0
  124. package/dist/components/primitives/KeyValueList/KeyValueList.js +38 -0
  125. package/dist/components/primitives/KeyValueList/KeyValueList.js.map +1 -0
  126. package/dist/components/primitives/KeyValueList/KeyValueList.styles.d.ts +4 -0
  127. package/dist/components/primitives/KeyValueList/KeyValueList.styles.d.ts.map +1 -0
  128. package/dist/components/primitives/KeyValueList/KeyValueList.styles.js +44 -0
  129. package/dist/components/primitives/KeyValueList/KeyValueList.styles.js.map +1 -0
  130. package/dist/components/primitives/PasswordField/PasswordField.d.ts +6 -0
  131. package/dist/components/primitives/PasswordField/PasswordField.d.ts.map +1 -1
  132. package/dist/components/primitives/PasswordField/PasswordField.js +2 -2
  133. package/dist/components/primitives/PasswordField/PasswordField.js.map +1 -1
  134. package/dist/contexts/Theme/ThemeProvider.d.ts +1 -1
  135. package/dist/contexts/Theme/ThemeProvider.d.ts.map +1 -1
  136. package/dist/contexts/Theme/ThemeProvider.js +27 -5
  137. package/dist/contexts/Theme/ThemeProvider.js.map +1 -1
  138. package/dist/contexts/ThunderID/ThunderIDContext.d.ts +12 -1
  139. package/dist/contexts/ThunderID/ThunderIDContext.d.ts.map +1 -1
  140. package/dist/contexts/ThunderID/ThunderIDContext.js +2 -0
  141. package/dist/contexts/ThunderID/ThunderIDContext.js.map +1 -1
  142. package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
  143. package/dist/contexts/ThunderID/ThunderIDProvider.js +7 -1
  144. package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
  145. package/dist/hooks/agents/useCreateAgent.d.ts +11 -0
  146. package/dist/hooks/agents/useCreateAgent.d.ts.map +1 -0
  147. package/dist/hooks/agents/useCreateAgent.js +24 -0
  148. package/dist/hooks/agents/useCreateAgent.js.map +1 -0
  149. package/dist/hooks/agents/useDeleteAgent.d.ts +10 -0
  150. package/dist/hooks/agents/useDeleteAgent.d.ts.map +1 -0
  151. package/dist/hooks/agents/useDeleteAgent.js +24 -0
  152. package/dist/hooks/agents/useDeleteAgent.js.map +1 -0
  153. package/dist/hooks/agents/useGetAgent.d.ts +12 -0
  154. package/dist/hooks/agents/useGetAgent.d.ts.map +1 -0
  155. package/dist/hooks/agents/useGetAgent.js +28 -0
  156. package/dist/hooks/agents/useGetAgent.js.map +1 -0
  157. package/dist/hooks/agents/useGetAgents.d.ts +19 -0
  158. package/dist/hooks/agents/useGetAgents.d.ts.map +1 -0
  159. package/dist/hooks/agents/useGetAgents.js +29 -0
  160. package/dist/hooks/agents/useGetAgents.js.map +1 -0
  161. package/dist/hooks/agents/useUpdateAgent.d.ts +18 -0
  162. package/dist/hooks/agents/useUpdateAgent.d.ts.map +1 -0
  163. package/dist/hooks/agents/useUpdateAgent.js +25 -0
  164. package/dist/hooks/agents/useUpdateAgent.js.map +1 -0
  165. package/dist/hooks/applications/useCreateApplication.d.ts +16 -0
  166. package/dist/hooks/applications/useCreateApplication.d.ts.map +1 -0
  167. package/dist/hooks/applications/useCreateApplication.js +29 -0
  168. package/dist/hooks/applications/useCreateApplication.js.map +1 -0
  169. package/dist/hooks/applications/useDeleteApplication.d.ts +10 -0
  170. package/dist/hooks/applications/useDeleteApplication.d.ts.map +1 -0
  171. package/dist/hooks/applications/useDeleteApplication.js +24 -0
  172. package/dist/hooks/applications/useDeleteApplication.js.map +1 -0
  173. package/dist/hooks/applications/useGetApplication.d.ts +17 -0
  174. package/dist/hooks/applications/useGetApplication.d.ts.map +1 -0
  175. package/dist/hooks/applications/useGetApplication.js +33 -0
  176. package/dist/hooks/applications/useGetApplication.js.map +1 -0
  177. package/dist/hooks/applications/useGetApplications.d.ts +24 -0
  178. package/dist/hooks/applications/useGetApplications.d.ts.map +1 -0
  179. package/dist/hooks/applications/useGetApplications.js +34 -0
  180. package/dist/hooks/applications/useGetApplications.js.map +1 -0
  181. package/dist/hooks/applications/useUpdateApplication.d.ts +18 -0
  182. package/dist/hooks/applications/useUpdateApplication.d.ts.map +1 -0
  183. package/dist/hooks/applications/useUpdateApplication.js +25 -0
  184. package/dist/hooks/applications/useUpdateApplication.js.map +1 -0
  185. package/dist/hooks/useManagementEndpoint.d.ts +22 -0
  186. package/dist/hooks/useManagementEndpoint.d.ts.map +1 -0
  187. package/dist/hooks/useManagementEndpoint.js +23 -0
  188. package/dist/hooks/useManagementEndpoint.js.map +1 -0
  189. package/dist/hooks/useResourceMutation.d.ts +51 -0
  190. package/dist/hooks/useResourceMutation.d.ts.map +1 -0
  191. package/dist/hooks/useResourceMutation.js +70 -0
  192. package/dist/hooks/useResourceMutation.js.map +1 -0
  193. package/dist/hooks/useResourceQuery.d.ts +45 -0
  194. package/dist/hooks/useResourceQuery.d.ts.map +1 -0
  195. package/dist/hooks/useResourceQuery.js +83 -0
  196. package/dist/hooks/useResourceQuery.js.map +1 -0
  197. package/dist/hooks/users/useCreateUser.d.ts +11 -0
  198. package/dist/hooks/users/useCreateUser.d.ts.map +1 -0
  199. package/dist/hooks/users/useCreateUser.js +24 -0
  200. package/dist/hooks/users/useCreateUser.js.map +1 -0
  201. package/dist/hooks/users/useDeleteUser.d.ts +10 -0
  202. package/dist/hooks/users/useDeleteUser.d.ts.map +1 -0
  203. package/dist/hooks/users/useDeleteUser.js +24 -0
  204. package/dist/hooks/users/useDeleteUser.js.map +1 -0
  205. package/dist/hooks/users/useGetUser.d.ts +12 -0
  206. package/dist/hooks/users/useGetUser.d.ts.map +1 -0
  207. package/dist/hooks/users/useGetUser.js +28 -0
  208. package/dist/hooks/users/useGetUser.js.map +1 -0
  209. package/dist/hooks/users/useGetUsers.d.ts +17 -0
  210. package/dist/hooks/users/useGetUsers.d.ts.map +1 -0
  211. package/dist/hooks/users/useGetUsers.js +36 -0
  212. package/dist/hooks/users/useGetUsers.js.map +1 -0
  213. package/dist/hooks/users/useUpdateUser.d.ts +18 -0
  214. package/dist/hooks/users/useUpdateUser.d.ts.map +1 -0
  215. package/dist/hooks/users/useUpdateUser.js +25 -0
  216. package/dist/hooks/users/useUpdateUser.js.map +1 -0
  217. package/dist/index.d.ts +32 -1
  218. package/dist/index.d.ts.map +1 -1
  219. package/dist/index.js +21 -2
  220. package/dist/models/config.d.ts +13 -1
  221. package/dist/models/config.d.ts.map +1 -1
  222. package/dist/utils/createAuthenticatedFetcher.d.ts +14 -0
  223. package/dist/utils/createAuthenticatedFetcher.d.ts.map +1 -0
  224. package/dist/utils/createAuthenticatedFetcher.js +41 -0
  225. package/dist/utils/createAuthenticatedFetcher.js.map +1 -0
  226. package/dist/utils/createResourceInvalidator.d.ts +29 -0
  227. package/dist/utils/createResourceInvalidator.d.ts.map +1 -0
  228. package/dist/utils/createResourceInvalidator.js +36 -0
  229. package/dist/utils/createResourceInvalidator.js.map +1 -0
  230. package/package.json +4 -4
@@ -19,8 +19,9 @@ import { createField } from "../../factories/FieldFactory.js";
19
19
  import CopyableText_default from "../../primitives/CopyableText/CopyableText.js";
20
20
  import Divider_default from "../../primitives/Divider/Divider.js";
21
21
  import flowIconRegistry_default from "../../primitives/Icons/flowIconRegistry.js";
22
+ import KeyValueList_default from "../../primitives/KeyValueList/KeyValueList.js";
22
23
  import AffixedField_default from "../../primitives/AffixedField/AffixedField.js";
23
- import { ConsentConstants, EmbeddedFlowComponentType, EmbeddedFlowEventType, FieldType, createPackageComponentLogger, resolveEmojiUrisInHtml, resolveFlowTemplateLiterals } from "@thunderid/browser";
24
+ import { ConsentConstants, EmbeddedFlowComponentType, EmbeddedFlowEventType, FieldType, createPackageComponentLogger, parseKeyValuePairs, resolveEmojiUrisInHtml, resolveFlowTemplateLiterals } from "@thunderid/browser";
24
25
  import { cloneElement } from "react";
25
26
  import { jsx } from "react/jsx-runtime";
26
27
  import DOMPurify from "dompurify";
@@ -542,6 +543,18 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
542
543
  value
543
544
  }, key);
544
545
  }
546
+ case EmbeddedFlowComponentType.KeyValueList: {
547
+ const sourceKey = component.source;
548
+ const pairs = parseKeyValuePairs(sourceKey && options.additionalData ? options.additionalData[sourceKey] : void 0).map((pair) => ({
549
+ ...pair,
550
+ label: resolve(pair.label)
551
+ }));
552
+ if (pairs.length === 0) return null;
553
+ return /* @__PURE__ */ jsx(KeyValueList_default, {
554
+ label: resolve(component.label) || void 0,
555
+ pairs
556
+ }, key);
557
+ }
545
558
  default:
546
559
  logger$1.warn(`Unsupported component type: ${component.type}. Skipping render.`);
547
560
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthOptionFactory.js","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClassCache: string | undefined","authOptionIconClassCache: string | undefined","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","postfixStateKey: string","defaultPrefixValue: string","selectedPrefix: string","AffixedField","reportedLength: number","otpLength: number | undefined","numericOnly: boolean","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","buttonType: HTMLButtonElement['type']","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","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","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":"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A,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.js","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClassCache: string | undefined","authOptionIconClassCache: string | undefined","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","postfixStateKey: string","defaultPrefixValue: string","selectedPrefix: string","AffixedField","reportedLength: number","otpLength: number | undefined","numericOnly: boolean","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","buttonType: HTMLButtonElement['type']","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","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","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","pairs: KeyValuePair[]","KeyValueList"],"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 KeyValuePair,\n parseKeyValuePairs,\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 KeyValueList from '../../primitives/KeyValueList/KeyValueList';\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 case EmbeddedFlowComponentType.KeyValueList: {\n const sourceKey: string | undefined = component.source;\n const pairs: KeyValuePair[] = parseKeyValuePairs(\n sourceKey && options.additionalData ? options.additionalData[sourceKey] : undefined,\n ).map((pair: KeyValuePair) => ({...pair, label: resolve(pair.label)}));\n\n // An empty panel tells the user nothing, so a list with no pairs renders nothing at all.\n if (pairs.length === 0) {\n return null;\n }\n\n return <KeyValueList key={key} label={resolve(component.label) || undefined} pairs={pairs} />;\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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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"}
@@ -7,7 +7,7 @@ import { initiateOAuthRedirect } from "../../../../utils/oauth.js";
7
7
  import { handlePasskeyAuthentication, handlePasskeyRegistration } from "../../../../utils/passkey.js";
8
8
  import { ConsentConstants, EmbeddedFlowType, EmbeddedSignInFlowStatus, EmbeddedSignInFlowType, ThunderIDAPIError, ThunderIDRuntimeError, logger } from "@thunderid/browser";
9
9
  import { useEffect, useRef, useState } from "react";
10
- import { Fragment, jsx } from "react/jsx-runtime";
10
+ import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
11
11
 
12
12
  //#region src/components/presentation/auth/SignIn/SignIn.tsx
13
13
  /**
@@ -627,7 +627,7 @@ const SignIn = ({ className, preferences, size = "medium", onSuccess, onError, v
627
627
  if (serverFieldErrors) {
628
628
  for (const fe of serverFieldErrors) if (!(fe.identifier in renderPropFieldErrors)) renderPropFieldErrors[fe.identifier] = fe.message;
629
629
  }
630
- return /* @__PURE__ */ jsx(Fragment, { children: children({
630
+ return /* @__PURE__ */ jsx(Fragment$1, { children: children({
631
631
  additionalData,
632
632
  components,
633
633
  error: flowError,
@@ -1 +1 @@
1
- {"version":3,"file":"SignIn.js","names":["submitActions: EmbeddedFlowComponent[]","SignIn: FC<SignInProps>","useThunderID","useTranslation","challengeTokenRef: any","initializationAttemptedRef: any","oauthCodeProcessedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","urlParams: any","url: any","redirectURL: any","finalRedirectUrl: any","effectiveApplicationId: any","storedExecutionId: any","resumeExecutionId: any","error: any","response: EmbeddedSignInFlowResponse","err: any","currentUrlParams: any","effectiveExecutionId: any","processedInputs: Record<string, any>","consentReason: string | undefined","consentPromptRawData: any","purposes: any[]","found: any","submitAction: any","reason: string | undefined","decisions: any","effectiveExecutionIdForPasskey: any","responseFieldErrors: FieldError[] | undefined","timeoutMs: number","actionId: string | undefined","timerId: ReturnType<typeof setTimeout>","inputs: Record<string, string>","passkeyResponse: any","passkeyResponseObj: any","renderPropFieldErrors: Record<string, string>","BaseSignIn"],"sources":["../../../../../src/components/presentation/auth/SignIn/SignIn.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ThunderIDRuntimeError,\n ThunderIDAPIError,\n ConsentConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowType,\n EmbeddedSignInFlowResponse,\n EmbeddedSignInFlowRequest,\n EmbeddedSignInFlowStatus,\n EmbeddedSignInFlowType,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n logger,\n} from '@thunderid/browser';\nimport {FC, ReactElement, useState, useEffect, useRef, ReactNode} from 'react';\n// eslint-disable-next-line import/no-named-as-default\nimport BaseSignIn, {BaseSignInProps} from './BaseSignIn';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../../hooks/useOAuthCallback';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../../utils/flowTransformer';\nimport {initiateOAuthRedirect} from '../../../../utils/oauth';\nimport {handlePasskeyAuthentication, handlePasskeyRegistration} from '../../../../utils/passkey';\n\n/**\n * Render props function parameters\n */\nexport interface SignInRenderProps {\n /**\n * Additional data from the flow response containing contextual information\n * like consent prompt details and session timeouts.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Current flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * Current error if any\n */\n error: Error | null;\n\n /**\n * Server-side field-level validation errors from the most recent flow response,\n * collapsed to one message per field (first error wins). Empty when no validation\n * failures are active. Render-prop consumers should display these alongside their\n * own client-side validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to manually initialize the flow\n */\n initialize: () => Promise<void>;\n\n /**\n * Whether the flow has been initialized\n */\n isInitialized: boolean;\n\n /**\n * Loading state indicator\n */\n isLoading: boolean;\n\n /**\n * Flag indicating whether the flow step timeout has expired.\n * Consuming components can use this to disable submit buttons.\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Function to submit authentication data (primary)\n */\n onSubmit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n}\n\n/**\n * Props for the SignIn component.\n * Matches the interface from the main SignIn component for consistency.\n */\nexport interface SignInProps {\n /**\n * Render props function for custom UI\n */\n children?: (props: SignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: BaseSignInProps['variant'];\n}\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n challenge: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Sentinel input key carrying the reason a consent prompt was submitted. It is folded into the\n * compiled `consent_decisions` payload and stripped from the inputs, like `__consent_opt__` keys.\n */\nconst CONSENT_REASON_KEY = '__consent_reason__';\n\n/** Flattens a component tree into a single list, parents before their children. */\nconst flattenComponents = (comps: EmbeddedFlowComponent[] | undefined): EmbeddedFlowComponent[] =>\n (comps ?? []).flatMap((comp: EmbeddedFlowComponent) => [comp, ...flattenComponents(comp.components)]);\n\n/**\n * Finds the action to submit an expired consent prompt with. A non-primary submit action is\n * preferred so the payload reads as a denial, falling back to any submit action because the server\n * needs an action to route the prompt node. Returns undefined when the view has neither.\n */\nconst findConsentSubmitActionId = (comps: EmbeddedFlowComponent[] | undefined): string | undefined => {\n const submitActions: EmbeddedFlowComponent[] = flattenComponents(comps).filter(\n (comp: EmbeddedFlowComponent) => comp.id && comp.eventType?.toUpperCase() === 'SUBMIT',\n );\n const denyAction: EmbeddedFlowComponent | undefined = submitActions.find(\n (comp: EmbeddedFlowComponent) => comp.variant?.toLowerCase() !== 'primary',\n );\n\n return (denyAction ?? submitActions[0])?.id;\n};\n\n/**\n * A component-driven SignIn component that provides authentication flow with pre-built styling.\n * This component handles the flow API calls for authentication and delegates UI logic to BaseSignIn.\n * It automatically transforms simple input-based responses into component-driven UI format.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => {\n * console.log('Authentication successful:', authData);\n * }}\n * onError={(error) => {\n * console.error('Authentication failed:', error);\n * }}\n * size=\"medium\"\n * variant=\"outlined\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => console.log('Success:', authData)}\n * onError={(error) => console.error('Error:', error)}\n * >\n * {({signIn, isLoading, components, error, isInitialized}) => (\n * <div className=\"custom-signin\">\n * <h1>Custom Sign In</h1>\n * {!isInitialized ? (\n * <p>Initializing...</p>\n * ) : error ? (\n * <div className=\"error\">{error.message}</div>\n * ) : (\n * <form onSubmit={(e) => {\n * e.preventDefault();\n * signIn({inputs: {username: 'user', password: 'pass'}});\n * }}>\n * <button type=\"submit\" disabled={isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign In'}\n * </button>\n * </form>\n * )}\n * </div>\n * )}\n * </SignIn>\n * );\n * };\n * ```\n */\nconst SignIn: FC<SignInProps> = ({\n className,\n preferences,\n size = 'medium',\n onSuccess,\n onError,\n variant,\n children,\n revalidateOnChangeAfterBlur,\n}: SignInProps): ReactElement => {\n const {applicationId, afterSignInUrl, signIn, isInitialized, isLoading, meta, getStorageManager, scopes, vendor} =\n useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n\n // State management for the flow\n const [components, setComponents] = useState<EmbeddedFlowComponent[]>([]);\n const [additionalData, setAdditionalData] = useState<Record<string, any>>({});\n // Server-side validation errors from the most recent flow response. Updated on every\n // submission; cleared when the next submission begins so stale errors don't linger.\n const [serverFieldErrors, setServerFieldErrors] = useState<FieldError[] | null>(null);\n const [currentExecutionId, setCurrentExecutionId] = useState<string | null>(null);\n const challengeTokenRef: any = useRef<string | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [flowError, setFlowError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isTimeoutDisabled, setIsTimeoutDisabled] = useState<boolean>(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const initializationAttemptedRef: any = useRef(false);\n const oauthCodeProcessedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // Deadline this component has already auto-submitted for, so a re-run of the timeout effect\n // cannot submit the same expired step twice.\n const timeoutSubmittedForRef = useRef<number | null>(null);\n // The timeout effect is keyed on the deadline alone, so a step that arrives carrying the same\n // deadline would otherwise leave the pending timer holding the previous step's context.\n const timeoutContextRef = useRef<{\n components: EmbeddedFlowComponent[];\n hasConsentPrompt: boolean;\n submit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n } | null>(null);\n /**\n * Sets executionId between sessionStorage and state.\n * This ensures both are always in sync.\n */\n const setExecutionId = (executionId: string | null): void => {\n setCurrentExecutionId(executionId);\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n } else {\n sessionStorage.removeItem(`${vendor}_execution_id`);\n }\n };\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Clear all flow-related storage and state.\n */\n const clearFlowState = async (): Promise<void> => {\n // Clear the expired flow state to prevent rendering a stale form with a null executionId.\n // Kept before the first await so callers that do not await this function still apply the\n // reset in one batch, ahead of the setError that follows.\n setExecutionId(null);\n setComponents([]);\n setAdditionalData({});\n setIsFlowInitialized(false);\n await setChallengeToken(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n setIsTimeoutDisabled(false);\n // Reset refs to allow new flows to start properly\n oauthCodeProcessedRef.current = false;\n };\n\n /**\n * Parse URL parameters used in flows.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n\n return {\n applicationId: urlParams.get('applicationId'),\n authId: urlParams.get('authId'),\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n errorDescription: urlParams.get('error_description'),\n executionId: urlParams.get('executionId'),\n nonce: urlParams.get('nonce'),\n state: urlParams.get('state'),\n };\n };\n\n /**\n * Handle authId from URL and persist it via the storage manager so it survives URL cleanup.\n * ThunderIDReactClient.signIn() reads authId from storageManager.getHybridDataParameter('authId'),\n * not from raw sessionStorage, so we must use the same storage path here.\n */\n const handleAuthId = async (authId: string | null): Promise<void> => {\n if (authId) {\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.setHybridDataParameter?.('authId', authId);\n } catch {\n logger.warn('Failed to store authId in hybrid storage.');\n }\n }\n };\n\n /**\n * Clean up OAuth-related URL parameters from the browser URL.\n */\n const cleanupOAuthUrlParams = (includeNonce = false): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('error');\n url.searchParams.delete('error_description');\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n if (includeNonce) {\n url.searchParams.delete('nonce');\n }\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Clean up flow-related URL parameters (executionId, authId) from the browser URL.\n * Used after executionId is set in state to prevent using invalidated executionId from URL.\n */\n const cleanupFlowUrlParams = (): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('authId');\n url.searchParams.delete('applicationId');\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Set error state and call onError callback.\n * Ensures isFlowInitialized is true so errors can be displayed in the UI.\n */\n const setError = (error: Error): void => {\n setFlowError(error);\n setIsFlowInitialized(true);\n onError?.(error);\n };\n\n /**\n * Handle OAuth error from URL parameters.\n * Clears flow state, creates error, and cleans up URL.\n */\n const handleOAuthError = (error: string, errorDescription: string | null): void => {\n clearFlowState();\n const errorMessage: any = errorDescription || `OAuth error: ${error}`;\n const err: any = new ThunderIDRuntimeError(errorMessage, 'SIGN_IN_ERROR', 'react');\n setError(err);\n cleanupOAuthUrlParams(true);\n };\n\n /**\n * Handle REDIRECTION response by storing flow state and redirecting to OAuth provider.\n */\n const handleRedirection = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.type === EmbeddedSignInFlowType.Redirection) {\n const redirectURL: any = (response.data as any)?.redirectURL || (response as any)?.redirectURL;\n\n if (redirectURL && window?.location) {\n if (response.executionId) {\n setExecutionId(response.executionId);\n }\n await setChallengeToken(response.challengeToken ?? null);\n\n const urlParams: any = getUrlParams();\n await handleAuthId(urlParams.authId);\n\n initiateOAuthRedirect(redirectURL, vendor);\n return true;\n }\n }\n return false;\n };\n\n /**\n * Handle ERROR and COMPLETE responses. Returns true if fully handled.\n * ERROR + executionId: recoverable — session preserved for retry.\n * ERROR + no executionId: terminal — clear state and surface the error.\n */\n const handleTerminalResponse = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error) {\n // Propagate OAuth error to the client\n if (response.redirectUrl && window?.location) {\n setIsSubmitting(false);\n await clearFlowState();\n cleanupOAuthUrlParams(true);\n onError?.(new Error(extractErrorMessage(response, t)));\n window.location.href = response.redirectUrl;\n\n return true;\n }\n\n if (response.executionId) {\n // Recoverable: session still alive. Show inline error without firing onError.\n setExecutionId(response.executionId);\n await setChallengeToken(response.challengeToken ?? null);\n setIsFlowInitialized(true);\n setFlowError(new Error(extractErrorMessage(response, t)));\n return true;\n }\n // Terminal: backend invalidated the session — clear all state.\n await clearFlowState();\n setError(new Error(extractErrorMessage(response, t)));\n cleanupFlowUrlParams();\n return true;\n }\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // Get redirectUrl from response (from /oauth2/auth/callback) or fall back to afterSignInUrl\n const redirectUrl: any = (response as any)?.redirectUrl || (response as any)?.redirect_uri;\n const finalRedirectUrl: any = redirectUrl || afterSignInUrl;\n\n // Clear submitting state before redirect\n setIsSubmitting(false);\n\n // Clear all OAuth-related storage on successful completion\n setExecutionId(null);\n await setChallengeToken(null);\n setIsFlowInitialized(false);\n sessionStorage.removeItem(`${vendor}_execution_id`);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage after completion.');\n }\n\n // Clean up OAuth URL params before redirect\n cleanupOAuthUrlParams(true);\n\n if (onSuccess) {\n onSuccess({\n redirectUrl: finalRedirectUrl,\n ...(response.data || {}),\n });\n }\n\n if (finalRedirectUrl && window?.location) {\n window.location.href = finalRedirectUrl;\n }\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Initialize the authentication flow.\n * Priority: executionId > applicationId (from context) > applicationId (from URL)\n */\n const initializeFlow = async (): Promise<void> => {\n const urlParams: any = getUrlParams();\n\n // Reset OAuth code processed ref when starting a new flow\n oauthCodeProcessedRef.current = false;\n // Clear stale serverFieldErrors so the new flow doesn't inherit them via render-prop.\n setServerFieldErrors(null);\n\n await handleAuthId(urlParams.authId);\n\n const effectiveApplicationId: any = applicationId || urlParams.applicationId;\n\n // On a page refresh the executionId is no longer in the URL (it is scrubbed by\n // cleanupFlowUrlParams after the first load). Fall back to the executionId persisted in\n // sessionStorage so the in-progress flow can be resumed instead of starting a new flow.\n // This is required for authorization_code apps where direct new-flow initiation is blocked\n // server-side and the flow must be initiated through the OAuth /authorize endpoint.\n const storedExecutionId: any = !urlParams.executionId ? sessionStorage.getItem(`${vendor}_execution_id`) : null;\n const resumeExecutionId: any = urlParams.executionId || storedExecutionId;\n\n if (!resumeExecutionId && !effectiveApplicationId) {\n const error: any = new ThunderIDRuntimeError(\n 'Either executionId or applicationId is required for authentication',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(error);\n throw error;\n }\n\n try {\n setFlowError(null);\n\n let response: EmbeddedSignInFlowResponse;\n\n if (resumeExecutionId) {\n try {\n response = (await signIn({\n executionId: resumeExecutionId,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n } catch (resumeError) {\n // Only treat a stale/expired session (HTTP 400 from the server, meaning the stored\n // executionId is no longer valid) as a recoverable condition. Transient failures\n // such as 5xx server errors or network errors are rethrown so they surface correctly.\n const isStaleSession: boolean =\n storedExecutionId &&\n resumeExecutionId === storedExecutionId &&\n resumeError instanceof ThunderIDAPIError &&\n resumeError.statusCode === 400;\n\n if (isStaleSession) {\n setExecutionId(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n if (!effectiveApplicationId) {\n const expiredError: any = new ThunderIDRuntimeError(\n t('errors.signin.session.expired') ||\n 'Your session has expired. Please return to the application and sign in again.',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(expiredError);\n return;\n }\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n } else {\n throw resumeError;\n }\n }\n } else {\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n }\n\n if (await handleRedirection(response)) {\n return;\n }\n\n // Handle a flow that completes (or errors) on the very first step — e.g. a reused SSO\n // session lets the backend return COMPLETE immediately with no UI components. Without\n // this the UI would fall through with no components and spin forever.\n if (await handleTerminalResponse(response)) {\n // Only reset the init gate for unrecoverable Error responses so the user can retry;\n // Complete-without-redirect would otherwise kick off a fresh flow unintentionally.\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error && !response.executionId) {\n initializationAttemptedRef.current = false;\n }\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsFlowInitialized(true);\n setIsTimeoutDisabled(false);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n initializationAttemptedRef.current = false;\n }\n };\n\n /**\n * Initialize the flow and handle cleanup of stale flow state.\n */\n useEffect(() => {\n const urlParams: any = getUrlParams();\n\n // Check for OAuth error in URL\n if (urlParams.error) {\n handleOAuthError(urlParams.error, urlParams.errorDescription);\n return;\n }\n\n handleAuthId(urlParams.authId);\n\n // Skip OAuth code processing - let the dedicated OAuth useEffect handle it\n // No action needed here as the dedicated useEffect will handle it\n }, []);\n\n useEffect(() => {\n // Only initialize if we're not processing an OAuth callback or submission.\n // Wait for isStorageReady so the challenge token is restored from storage before\n // we attempt to resume a persisted executionId — the server requires it.\n const currentUrlParams: any = getUrlParams();\n if (\n isInitialized &&\n isStorageReady &&\n !isLoading &&\n !isFlowInitialized &&\n !initializationAttemptedRef.current &&\n !currentExecutionId &&\n !currentUrlParams.code &&\n !currentUrlParams.state &&\n !isSubmitting &&\n !oauthCodeProcessedRef.current\n ) {\n initializationAttemptedRef.current = true;\n initializeFlow();\n }\n }, [isInitialized, isStorageReady, isLoading, isFlowInitialized, currentExecutionId]);\n\n /**\n * Handle form submission from BaseSignIn or render props.\n */\n const handleSubmit = async (payload: EmbeddedSignInFlowRequest): Promise<void> => {\n // Use executionId from payload if available, otherwise fall back to currentExecutionId\n const effectiveExecutionId: any = payload.executionId || currentExecutionId;\n\n if (!effectiveExecutionId) {\n throw new Error('No active flow ID');\n }\n\n const processedInputs: Record<string, any> = {...payload.inputs};\n\n // Read and strip the sentinel up front so it can never reach the wire as an input\n const consentReason: string | undefined = processedInputs[CONSENT_REASON_KEY];\n delete processedInputs[CONSENT_REASON_KEY];\n\n // Auto-compile consent decisions if we are currently on a consent prompt step\n if (additionalData?.['consentPrompt']) {\n try {\n const consentPromptRawData: any = additionalData['consentPrompt'];\n const purposes: any[] =\n typeof consentPromptRawData === 'string'\n ? JSON.parse(consentPromptRawData)\n : consentPromptRawData.purposes || consentPromptRawData;\n\n // Find the action component to determine if it was a deny action\n let isDeny = false;\n if (payload.action) {\n // Flatten components to find the action\n const findAction = (comps: any[]): any => {\n if (!comps || comps.length === 0) return null;\n\n const found: any = comps.find((c: any) => c.id === payload.action);\n if (found) return found;\n\n return comps.reduce((acc: any, c: any) => {\n if (acc) return acc;\n if (c.components) return findAction(c.components);\n return null;\n }, null);\n };\n\n const submitAction: any = findAction(components);\n\n if (submitAction && submitAction.variant?.toLowerCase() !== 'primary') {\n isDeny = true;\n }\n }\n\n // An expired prompt is never an approval, whichever action carried the submission\n if (consentReason === ConsentConstants.REASON_TIMEOUT) {\n isDeny = true;\n }\n\n // An explicit denial carries a reason too, so the server never has to infer one\n const reason: string | undefined = consentReason ?? (isDeny ? ConsentConstants.REASON_USER_DENIED : undefined);\n\n const decisions: any = {\n approved: !isDeny,\n ...(reason ? {reason} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n elements: [\n ...(p.essential || []).map((e: any) => ({\n approved: !isDeny,\n name: e.name,\n })),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n return {\n approved: !isDeny && processedInputs[key] === 'true',\n name: e.name,\n };\n }),\n ],\n purposeName: p.purposeName,\n })),\n };\n processedInputs['consent_decisions'] = JSON.stringify(decisions);\n\n // Cleanup temporary consent tracking fields from inputs\n Object.keys(processedInputs).forEach((key: string) => {\n if (key.startsWith('__consent_opt__')) {\n delete processedInputs[key];\n }\n });\n } catch (e) {\n // Failed to construct consent_decisions payload automatically\n }\n }\n\n try {\n setIsSubmitting(true);\n setFlowError(null);\n // Clear any field errors from the previous response before the new round-trip.\n setServerFieldErrors(null);\n\n const response: EmbeddedSignInFlowResponse = (await signIn({\n executionId: effectiveExecutionId,\n ...payload,\n inputs: processedInputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n\n if (await handleRedirection(response)) {\n return;\n }\n if (\n response.data?.additionalData?.['passkeyChallenge'] ||\n response.data?.additionalData?.['passkeyCreationOptions']\n ) {\n const {passkeyChallenge, passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId || effectiveExecutionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: 'submit',\n challenge: passkeyChallenge,\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsSubmitting(false);\n\n return;\n }\n\n // Handle terminal flow statuses before normalization.\n if (await handleTerminalResponse(response)) {\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n // Always update challenge token on any INCOMPLETE response — token rotates every step.\n await setChallengeToken(response.challengeToken ?? null);\n\n // Update executionId if response contains a new one\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsTimeoutDisabled(false);\n // Ensure flow is marked as initialized when we have components\n setIsFlowInitialized(true);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n\n // Surface server-side validation failures so BaseSignIn can inject them into\n // the form-level fieldErrors state used by the render-prop / default UI.\n const responseFieldErrors: FieldError[] | undefined = (response.data as any)?.fieldErrors;\n if (responseFieldErrors && responseFieldErrors.length > 0) {\n setServerFieldErrors(responseFieldErrors);\n }\n\n // Display error from INCOMPLETE response\n if ((response as any)?.error) {\n setFlowError(new Error(extractErrorMessage(response, t)));\n }\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n return;\n } finally {\n setIsSubmitting(false);\n }\n };\n\n /**\n * Handle step timeout if configured in additionalData.\n *\n * An expired consent prompt is auto-submitted as a denial carrying the timeout reason, because its\n * actions no longer lead anywhere and the user would otherwise be stranded on the prompt. The\n * server discards those decisions and records nothing. Every other kind of step surfaces the\n * expiry error instead.\n */\n timeoutContextRef.current = {\n components,\n hasConsentPrompt: Boolean(additionalData?.['consentPrompt']),\n submit: handleSubmit,\n };\n\n useEffect(() => {\n const timeoutMs: number = Number(additionalData?.['stepTimeout']) || 0;\n if (timeoutMs <= 0 || !isFlowInitialized) {\n setIsTimeoutDisabled(false);\n return undefined;\n }\n\n const handleTimeout = (): void => {\n setIsTimeoutDisabled(true);\n\n const expiredError = (): Error =>\n new Error(t('errors.signin.timeout') || 'Time allowed to complete the step has expired.');\n\n // Read through the ref so the timer always sees the step that is on screen when it fires\n const context = timeoutContextRef.current;\n const actionId: string | undefined = context?.hasConsentPrompt\n ? findConsentSubmitActionId(context.components)\n : undefined;\n\n // Without an action the prompt node cannot be routed, so there is nothing to submit\n if (actionId && context && timeoutSubmittedForRef.current !== timeoutMs) {\n timeoutSubmittedForRef.current = timeoutMs;\n context\n .submit({action: actionId, inputs: {[CONSENT_REASON_KEY]: ConsentConstants.REASON_TIMEOUT}})\n .catch(() => setError(expiredError()));\n return;\n }\n\n setError(expiredError());\n };\n\n const timerId: ReturnType<typeof setTimeout> = setTimeout(handleTimeout, Math.max(0, timeoutMs - Date.now()));\n\n return () => clearTimeout(timerId);\n }, [additionalData?.['stepTimeout'], isFlowInitialized, t]);\n\n /**\n * Handle authentication errors.\n */\n const handleError = (error: Error): void => {\n setError(error);\n };\n\n useOAuthCallback({\n currentExecutionId,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isInitialized && !isLoading && isStorageReady,\n isSubmitting,\n onError: (err: any) => {\n clearFlowState();\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n onSubmit: async (payload: any) => handleSubmit({executionId: payload.executionId, inputs: payload.inputs}),\n processedRef: oauthCodeProcessedRef,\n setExecutionId,\n });\n\n /**\n * Handle passkey authentication/registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (\n !passkeyState.isActive ||\n (!passkeyState.challenge && !passkeyState.creationOptions) ||\n !passkeyState.executionId\n ) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyProcess = async (): Promise<void> => {\n let inputs: Record<string, string>;\n\n if (passkeyState.challenge) {\n const passkeyResponse: any = await handlePasskeyAuthentication(passkeyState.challenge);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n authenticatorData: passkeyResponseObj.response.authenticatorData,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n signature: passkeyResponseObj.response.signature,\n userHandle: passkeyResponseObj.response.userHandle,\n };\n } else if (passkeyState.creationOptions) {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n } else {\n throw new Error('No passkey challenge or creation options available');\n }\n\n await handleSubmit({\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n });\n };\n\n performPasskeyProcess()\n .then(() => {\n setPasskeyState({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n setFlowError(error as Error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.executionId]);\n\n if (children) {\n // Collapse the server FieldError[] array to a single message per field map for\n // render-prop consumers. First error per field wins. Multi-error cases per\n // field are rare in practice (server typically returns one rule failure per\n // field in current flows) and consumers needing the full array can still read\n // it from the raw flow response.\n const renderPropFieldErrors: Record<string, string> = {};\n if (serverFieldErrors) {\n for (const fe of serverFieldErrors) {\n if (!(fe.identifier in renderPropFieldErrors)) {\n renderPropFieldErrors[fe.identifier] = fe.message;\n }\n }\n }\n\n const renderProps: SignInRenderProps = {\n additionalData,\n components,\n error: flowError,\n fieldErrors: renderPropFieldErrors,\n initialize: initializeFlow,\n isInitialized: isFlowInitialized,\n isLoading: isLoading || isSubmitting || !isInitialized,\n isTimeoutDisabled,\n meta,\n onSubmit: handleSubmit,\n };\n\n return <>{children(renderProps)}</>;\n }\n // Otherwise, render the default BaseSignIn component\n return (\n <BaseSignIn\n additionalData={additionalData}\n components={components}\n isLoading={isLoading || !isInitialized || !isFlowInitialized}\n isTimeoutDisabled={isTimeoutDisabled}\n onSubmit={handleSubmit}\n onError={handleError}\n error={flowError}\n className={className}\n size={size}\n variant={variant}\n preferences={preferences}\n revalidateOnChangeAfterBlur={revalidateOnChangeAfterBlur}\n serverFieldErrors={serverFieldErrors}\n />\n );\n};\n\nexport default SignIn;\n"],"mappings":"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"}
1
+ {"version":3,"file":"SignIn.js","names":["submitActions: EmbeddedFlowComponent[]","SignIn: FC<SignInProps>","useThunderID","useTranslation","challengeTokenRef: any","initializationAttemptedRef: any","oauthCodeProcessedRef: any","passkeyProcessedRef: any","tempData: any","storageManager: any","urlParams: any","url: any","redirectURL: any","finalRedirectUrl: any","effectiveApplicationId: any","storedExecutionId: any","resumeExecutionId: any","error: any","response: EmbeddedSignInFlowResponse","err: any","currentUrlParams: any","effectiveExecutionId: any","processedInputs: Record<string, any>","consentReason: string | undefined","consentPromptRawData: any","purposes: any[]","found: any","submitAction: any","reason: string | undefined","decisions: any","effectiveExecutionIdForPasskey: any","responseFieldErrors: FieldError[] | undefined","timeoutMs: number","actionId: string | undefined","timerId: ReturnType<typeof setTimeout>","inputs: Record<string, string>","passkeyResponse: any","passkeyResponseObj: any","renderPropFieldErrors: Record<string, string>","BaseSignIn"],"sources":["../../../../../src/components/presentation/auth/SignIn/SignIn.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ThunderIDRuntimeError,\n ThunderIDAPIError,\n ConsentConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowType,\n EmbeddedSignInFlowResponse,\n EmbeddedSignInFlowRequest,\n EmbeddedSignInFlowStatus,\n EmbeddedSignInFlowType,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n logger,\n} from '@thunderid/browser';\nimport {FC, ReactElement, useState, useEffect, useRef, ReactNode} from 'react';\n// eslint-disable-next-line import/no-named-as-default\nimport BaseSignIn, {BaseSignInProps} from './BaseSignIn';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../../hooks/useOAuthCallback';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../../utils/flowTransformer';\nimport {initiateOAuthRedirect} from '../../../../utils/oauth';\nimport {handlePasskeyAuthentication, handlePasskeyRegistration} from '../../../../utils/passkey';\n\n/**\n * Render props function parameters\n */\nexport interface SignInRenderProps {\n /**\n * Additional data from the flow response containing contextual information\n * like consent prompt details and session timeouts.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Current flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * Current error if any\n */\n error: Error | null;\n\n /**\n * Server-side field-level validation errors from the most recent flow response,\n * collapsed to one message per field (first error wins). Empty when no validation\n * failures are active. Render-prop consumers should display these alongside their\n * own client-side validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to manually initialize the flow\n */\n initialize: () => Promise<void>;\n\n /**\n * Whether the flow has been initialized\n */\n isInitialized: boolean;\n\n /**\n * Loading state indicator\n */\n isLoading: boolean;\n\n /**\n * Flag indicating whether the flow step timeout has expired.\n * Consuming components can use this to disable submit buttons.\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Function to submit authentication data (primary)\n */\n onSubmit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n}\n\n/**\n * Props for the SignIn component.\n * Matches the interface from the main SignIn component for consistency.\n */\nexport interface SignInProps {\n /**\n * Render props function for custom UI\n */\n children?: (props: SignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * When a field has been blurred at least once, re-run validation on every subsequent\n * keystroke so a rendered error clears the moment the value becomes valid. Doesn't\n * affect fields that have never been blurred — the user isn't shown errors while\n * initially typing. Default `false` preserves prior behavior.\n */\n revalidateOnChangeAfterBlur?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: BaseSignInProps['variant'];\n}\n\n/**\n * State for tracking passkey registration\n */\ninterface PasskeyState {\n actionId: string | null;\n challenge: string | null;\n creationOptions: string | null;\n error: Error | null;\n executionId: string | null;\n isActive: boolean;\n}\n\n/**\n * Sentinel input key carrying the reason a consent prompt was submitted. It is folded into the\n * compiled `consent_decisions` payload and stripped from the inputs, like `__consent_opt__` keys.\n */\nconst CONSENT_REASON_KEY = '__consent_reason__';\n\n/** Flattens a component tree into a single list, parents before their children. */\nconst flattenComponents = (comps: EmbeddedFlowComponent[] | undefined): EmbeddedFlowComponent[] =>\n (comps ?? []).flatMap((comp: EmbeddedFlowComponent) => [comp, ...flattenComponents(comp.components)]);\n\n/**\n * Finds the action to submit an expired consent prompt with. A non-primary submit action is\n * preferred so the payload reads as a denial, falling back to any submit action because the server\n * needs an action to route the prompt node. Returns undefined when the view has neither.\n */\nconst findConsentSubmitActionId = (comps: EmbeddedFlowComponent[] | undefined): string | undefined => {\n const submitActions: EmbeddedFlowComponent[] = flattenComponents(comps).filter(\n (comp: EmbeddedFlowComponent) => comp.id && comp.eventType?.toUpperCase() === 'SUBMIT',\n );\n const denyAction: EmbeddedFlowComponent | undefined = submitActions.find(\n (comp: EmbeddedFlowComponent) => comp.variant?.toLowerCase() !== 'primary',\n );\n\n return (denyAction ?? submitActions[0])?.id;\n};\n\n/**\n * A component-driven SignIn component that provides authentication flow with pre-built styling.\n * This component handles the flow API calls for authentication and delegates UI logic to BaseSignIn.\n * It automatically transforms simple input-based responses into component-driven UI format.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => {\n * console.log('Authentication successful:', authData);\n * }}\n * onError={(error) => {\n * console.error('Authentication failed:', error);\n * }}\n * size=\"medium\"\n * variant=\"outlined\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * import { SignIn } from '@thunderid/react/component-driven';\n *\n * const App = () => {\n * return (\n * <SignIn\n * onSuccess={(authData) => console.log('Success:', authData)}\n * onError={(error) => console.error('Error:', error)}\n * >\n * {({signIn, isLoading, components, error, isInitialized}) => (\n * <div className=\"custom-signin\">\n * <h1>Custom Sign In</h1>\n * {!isInitialized ? (\n * <p>Initializing...</p>\n * ) : error ? (\n * <div className=\"error\">{error.message}</div>\n * ) : (\n * <form onSubmit={(e) => {\n * e.preventDefault();\n * signIn({inputs: {username: 'user', password: 'pass'}});\n * }}>\n * <button type=\"submit\" disabled={isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign In'}\n * </button>\n * </form>\n * )}\n * </div>\n * )}\n * </SignIn>\n * );\n * };\n * ```\n */\nconst SignIn: FC<SignInProps> = ({\n className,\n preferences,\n size = 'medium',\n onSuccess,\n onError,\n variant,\n children,\n revalidateOnChangeAfterBlur,\n}: SignInProps): ReactElement => {\n const {applicationId, afterSignInUrl, signIn, isInitialized, isLoading, meta, getStorageManager, scopes, vendor} =\n useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n\n // State management for the flow\n const [components, setComponents] = useState<EmbeddedFlowComponent[]>([]);\n const [additionalData, setAdditionalData] = useState<Record<string, any>>({});\n // Server-side validation errors from the most recent flow response. Updated on every\n // submission; cleared when the next submission begins so stale errors don't linger.\n const [serverFieldErrors, setServerFieldErrors] = useState<FieldError[] | null>(null);\n const [currentExecutionId, setCurrentExecutionId] = useState<string | null>(null);\n const challengeTokenRef: any = useRef<string | null>(null);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [flowError, setFlowError] = useState<Error | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isTimeoutDisabled, setIsTimeoutDisabled] = useState<boolean>(false);\n const [passkeyState, setPasskeyState] = useState<PasskeyState>({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n const initializationAttemptedRef: any = useRef(false);\n const oauthCodeProcessedRef: any = useRef(false);\n const passkeyProcessedRef: any = useRef(false);\n // Deadline this component has already auto-submitted for, so a re-run of the timeout effect\n // cannot submit the same expired step twice.\n const timeoutSubmittedForRef = useRef<number | null>(null);\n // The timeout effect is keyed on the deadline alone, so a step that arrives carrying the same\n // deadline would otherwise leave the pending timer holding the previous step's context.\n const timeoutContextRef = useRef<{\n components: EmbeddedFlowComponent[];\n hasConsentPrompt: boolean;\n submit: (payload: EmbeddedSignInFlowRequest) => Promise<void>;\n } | null>(null);\n /**\n * Sets executionId between sessionStorage and state.\n * This ensures both are always in sync.\n */\n const setExecutionId = (executionId: string | null): void => {\n setCurrentExecutionId(executionId);\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n } else {\n sessionStorage.removeItem(`${vendor}_execution_id`);\n }\n };\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Clear all flow-related storage and state.\n */\n const clearFlowState = async (): Promise<void> => {\n // Clear the expired flow state to prevent rendering a stale form with a null executionId.\n // Kept before the first await so callers that do not await this function still apply the\n // reset in one batch, ahead of the setError that follows.\n setExecutionId(null);\n setComponents([]);\n setAdditionalData({});\n setIsFlowInitialized(false);\n await setChallengeToken(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n setIsTimeoutDisabled(false);\n // Reset refs to allow new flows to start properly\n oauthCodeProcessedRef.current = false;\n };\n\n /**\n * Parse URL parameters used in flows.\n */\n const getUrlParams = (): any => {\n const urlParams: any = new URL(window?.location?.href ?? '').searchParams;\n\n return {\n applicationId: urlParams.get('applicationId'),\n authId: urlParams.get('authId'),\n code: urlParams.get('code'),\n error: urlParams.get('error'),\n errorDescription: urlParams.get('error_description'),\n executionId: urlParams.get('executionId'),\n nonce: urlParams.get('nonce'),\n state: urlParams.get('state'),\n };\n };\n\n /**\n * Handle authId from URL and persist it via the storage manager so it survives URL cleanup.\n * ThunderIDReactClient.signIn() reads authId from storageManager.getHybridDataParameter('authId'),\n * not from raw sessionStorage, so we must use the same storage path here.\n */\n const handleAuthId = async (authId: string | null): Promise<void> => {\n if (authId) {\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.setHybridDataParameter?.('authId', authId);\n } catch {\n logger.warn('Failed to store authId in hybrid storage.');\n }\n }\n };\n\n /**\n * Clean up OAuth-related URL parameters from the browser URL.\n */\n const cleanupOAuthUrlParams = (includeNonce = false): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('error');\n url.searchParams.delete('error_description');\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n if (includeNonce) {\n url.searchParams.delete('nonce');\n }\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Clean up flow-related URL parameters (executionId, authId) from the browser URL.\n * Used after executionId is set in state to prevent using invalidated executionId from URL.\n */\n const cleanupFlowUrlParams = (): void => {\n if (!window?.location?.href) return;\n const url: any = new URL(window.location.href);\n url.searchParams.delete('executionId');\n url.searchParams.delete('authId');\n url.searchParams.delete('applicationId');\n window?.history?.replaceState({}, '', url.toString());\n };\n\n /**\n * Set error state and call onError callback.\n * Ensures isFlowInitialized is true so errors can be displayed in the UI.\n */\n const setError = (error: Error): void => {\n setFlowError(error);\n setIsFlowInitialized(true);\n onError?.(error);\n };\n\n /**\n * Handle OAuth error from URL parameters.\n * Clears flow state, creates error, and cleans up URL.\n */\n const handleOAuthError = (error: string, errorDescription: string | null): void => {\n clearFlowState();\n const errorMessage: any = errorDescription || `OAuth error: ${error}`;\n const err: any = new ThunderIDRuntimeError(errorMessage, 'SIGN_IN_ERROR', 'react');\n setError(err);\n cleanupOAuthUrlParams(true);\n };\n\n /**\n * Handle REDIRECTION response by storing flow state and redirecting to OAuth provider.\n */\n const handleRedirection = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.type === EmbeddedSignInFlowType.Redirection) {\n const redirectURL: any = (response.data as any)?.redirectURL || (response as any)?.redirectURL;\n\n if (redirectURL && window?.location) {\n if (response.executionId) {\n setExecutionId(response.executionId);\n }\n await setChallengeToken(response.challengeToken ?? null);\n\n const urlParams: any = getUrlParams();\n await handleAuthId(urlParams.authId);\n\n initiateOAuthRedirect(redirectURL, vendor);\n return true;\n }\n }\n return false;\n };\n\n /**\n * Handle ERROR and COMPLETE responses. Returns true if fully handled.\n * ERROR + executionId: recoverable — session preserved for retry.\n * ERROR + no executionId: terminal — clear state and surface the error.\n */\n const handleTerminalResponse = async (response: EmbeddedSignInFlowResponse): Promise<boolean> => {\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error) {\n // Propagate OAuth error to the client\n if (response.redirectUrl && window?.location) {\n setIsSubmitting(false);\n await clearFlowState();\n cleanupOAuthUrlParams(true);\n onError?.(new Error(extractErrorMessage(response, t)));\n window.location.href = response.redirectUrl;\n\n return true;\n }\n\n if (response.executionId) {\n // Recoverable: session still alive. Show inline error without firing onError.\n setExecutionId(response.executionId);\n await setChallengeToken(response.challengeToken ?? null);\n setIsFlowInitialized(true);\n setFlowError(new Error(extractErrorMessage(response, t)));\n return true;\n }\n // Terminal: backend invalidated the session — clear all state.\n await clearFlowState();\n setError(new Error(extractErrorMessage(response, t)));\n cleanupFlowUrlParams();\n return true;\n }\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // Get redirectUrl from response (from /oauth2/auth/callback) or fall back to afterSignInUrl\n const redirectUrl: any = (response as any)?.redirectUrl || (response as any)?.redirect_uri;\n const finalRedirectUrl: any = redirectUrl || afterSignInUrl;\n\n // Clear submitting state before redirect\n setIsSubmitting(false);\n\n // Clear all OAuth-related storage on successful completion\n setExecutionId(null);\n await setChallengeToken(null);\n setIsFlowInitialized(false);\n sessionStorage.removeItem(`${vendor}_execution_id`);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage after completion.');\n }\n\n // Clean up OAuth URL params before redirect\n cleanupOAuthUrlParams(true);\n\n if (onSuccess) {\n onSuccess({\n redirectUrl: finalRedirectUrl,\n ...(response.data || {}),\n });\n }\n\n if (finalRedirectUrl && window?.location) {\n window.location.href = finalRedirectUrl;\n }\n\n return true;\n }\n\n return false;\n };\n\n /**\n * Initialize the authentication flow.\n * Priority: executionId > applicationId (from context) > applicationId (from URL)\n */\n const initializeFlow = async (): Promise<void> => {\n const urlParams: any = getUrlParams();\n\n // Reset OAuth code processed ref when starting a new flow\n oauthCodeProcessedRef.current = false;\n // Clear stale serverFieldErrors so the new flow doesn't inherit them via render-prop.\n setServerFieldErrors(null);\n\n await handleAuthId(urlParams.authId);\n\n const effectiveApplicationId: any = applicationId || urlParams.applicationId;\n\n // On a page refresh the executionId is no longer in the URL (it is scrubbed by\n // cleanupFlowUrlParams after the first load). Fall back to the executionId persisted in\n // sessionStorage so the in-progress flow can be resumed instead of starting a new flow.\n // This is required for authorization_code apps where direct new-flow initiation is blocked\n // server-side and the flow must be initiated through the OAuth /authorize endpoint.\n const storedExecutionId: any = !urlParams.executionId ? sessionStorage.getItem(`${vendor}_execution_id`) : null;\n const resumeExecutionId: any = urlParams.executionId || storedExecutionId;\n\n if (!resumeExecutionId && !effectiveApplicationId) {\n const error: any = new ThunderIDRuntimeError(\n 'Either executionId or applicationId is required for authentication',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(error);\n throw error;\n }\n\n try {\n setFlowError(null);\n\n let response: EmbeddedSignInFlowResponse;\n\n if (resumeExecutionId) {\n try {\n response = (await signIn({\n executionId: resumeExecutionId,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n } catch (resumeError) {\n // Only treat a stale/expired session (HTTP 400 from the server, meaning the stored\n // executionId is no longer valid) as a recoverable condition. Transient failures\n // such as 5xx server errors or network errors are rethrown so they surface correctly.\n const isStaleSession: boolean =\n storedExecutionId &&\n resumeExecutionId === storedExecutionId &&\n resumeError instanceof ThunderIDAPIError &&\n resumeError.statusCode === 400;\n\n if (isStaleSession) {\n setExecutionId(null);\n try {\n const storageManager: any = await getStorageManager();\n await storageManager?.removeHybridDataParameter?.('authId');\n } catch {\n logger.warn('Failed to clear authId from hybrid storage.');\n }\n if (!effectiveApplicationId) {\n const expiredError: any = new ThunderIDRuntimeError(\n t('errors.signin.session.expired') ||\n 'Your session has expired. Please return to the application and sign in again.',\n 'SIGN_IN_ERROR',\n 'react',\n );\n setError(expiredError);\n return;\n }\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n } else {\n throw resumeError;\n }\n }\n } else {\n response = (await signIn({\n applicationId: effectiveApplicationId,\n flowType: EmbeddedFlowType.Authentication,\n ...(scopes && {scopes}),\n })) as EmbeddedSignInFlowResponse;\n }\n\n if (await handleRedirection(response)) {\n return;\n }\n\n // Handle a flow that completes (or errors) on the very first step — e.g. a reused SSO\n // session lets the backend return COMPLETE immediately with no UI components. Without\n // this the UI would fall through with no components and spin forever.\n if (await handleTerminalResponse(response)) {\n // Only reset the init gate for unrecoverable Error responses so the user can retry;\n // Complete-without-redirect would otherwise kick off a fresh flow unintentionally.\n if (response.flowStatus === EmbeddedSignInFlowStatus.Error && !response.executionId) {\n initializationAttemptedRef.current = false;\n }\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n await setChallengeToken(response.challengeToken ?? null);\n\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsFlowInitialized(true);\n setIsTimeoutDisabled(false);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n initializationAttemptedRef.current = false;\n }\n };\n\n /**\n * Initialize the flow and handle cleanup of stale flow state.\n */\n useEffect(() => {\n const urlParams: any = getUrlParams();\n\n // Check for OAuth error in URL\n if (urlParams.error) {\n handleOAuthError(urlParams.error, urlParams.errorDescription);\n return;\n }\n\n handleAuthId(urlParams.authId);\n\n // Skip OAuth code processing - let the dedicated OAuth useEffect handle it\n // No action needed here as the dedicated useEffect will handle it\n }, []);\n\n useEffect(() => {\n // Only initialize if we're not processing an OAuth callback or submission.\n // Wait for isStorageReady so the challenge token is restored from storage before\n // we attempt to resume a persisted executionId — the server requires it.\n const currentUrlParams: any = getUrlParams();\n if (\n isInitialized &&\n isStorageReady &&\n !isLoading &&\n !isFlowInitialized &&\n !initializationAttemptedRef.current &&\n !currentExecutionId &&\n !currentUrlParams.code &&\n !currentUrlParams.state &&\n !isSubmitting &&\n !oauthCodeProcessedRef.current\n ) {\n initializationAttemptedRef.current = true;\n initializeFlow();\n }\n }, [isInitialized, isStorageReady, isLoading, isFlowInitialized, currentExecutionId]);\n\n /**\n * Handle form submission from BaseSignIn or render props.\n */\n const handleSubmit = async (payload: EmbeddedSignInFlowRequest): Promise<void> => {\n // Use executionId from payload if available, otherwise fall back to currentExecutionId\n const effectiveExecutionId: any = payload.executionId || currentExecutionId;\n\n if (!effectiveExecutionId) {\n throw new Error('No active flow ID');\n }\n\n const processedInputs: Record<string, any> = {...payload.inputs};\n\n // Read and strip the sentinel up front so it can never reach the wire as an input\n const consentReason: string | undefined = processedInputs[CONSENT_REASON_KEY];\n delete processedInputs[CONSENT_REASON_KEY];\n\n // Auto-compile consent decisions if we are currently on a consent prompt step\n if (additionalData?.['consentPrompt']) {\n try {\n const consentPromptRawData: any = additionalData['consentPrompt'];\n const purposes: any[] =\n typeof consentPromptRawData === 'string'\n ? JSON.parse(consentPromptRawData)\n : consentPromptRawData.purposes || consentPromptRawData;\n\n // Find the action component to determine if it was a deny action\n let isDeny = false;\n if (payload.action) {\n // Flatten components to find the action\n const findAction = (comps: any[]): any => {\n if (!comps || comps.length === 0) return null;\n\n const found: any = comps.find((c: any) => c.id === payload.action);\n if (found) return found;\n\n return comps.reduce((acc: any, c: any) => {\n if (acc) return acc;\n if (c.components) return findAction(c.components);\n return null;\n }, null);\n };\n\n const submitAction: any = findAction(components);\n\n if (submitAction && submitAction.variant?.toLowerCase() !== 'primary') {\n isDeny = true;\n }\n }\n\n // An expired prompt is never an approval, whichever action carried the submission\n if (consentReason === ConsentConstants.REASON_TIMEOUT) {\n isDeny = true;\n }\n\n // An explicit denial carries a reason too, so the server never has to infer one\n const reason: string | undefined = consentReason ?? (isDeny ? ConsentConstants.REASON_USER_DENIED : undefined);\n\n const decisions: any = {\n approved: !isDeny,\n ...(reason ? {reason} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n elements: [\n ...(p.essential || []).map((e: any) => ({\n approved: !isDeny,\n name: e.name,\n })),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n return {\n approved: !isDeny && processedInputs[key] === 'true',\n name: e.name,\n };\n }),\n ],\n purposeName: p.purposeName,\n })),\n };\n processedInputs['consent_decisions'] = JSON.stringify(decisions);\n\n // Cleanup temporary consent tracking fields from inputs\n Object.keys(processedInputs).forEach((key: string) => {\n if (key.startsWith('__consent_opt__')) {\n delete processedInputs[key];\n }\n });\n } catch (e) {\n // Failed to construct consent_decisions payload automatically\n }\n }\n\n try {\n setIsSubmitting(true);\n setFlowError(null);\n // Clear any field errors from the previous response before the new round-trip.\n setServerFieldErrors(null);\n\n const response: EmbeddedSignInFlowResponse = (await signIn({\n executionId: effectiveExecutionId,\n ...payload,\n inputs: processedInputs,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n })) as EmbeddedSignInFlowResponse;\n\n if (await handleRedirection(response)) {\n return;\n }\n if (\n response.data?.additionalData?.['passkeyChallenge'] ||\n response.data?.additionalData?.['passkeyCreationOptions']\n ) {\n const {passkeyChallenge, passkeyCreationOptions}: any = response.data.additionalData;\n const effectiveExecutionIdForPasskey: any = response.executionId || effectiveExecutionId;\n\n // Reset passkey processed ref to allow processing\n passkeyProcessedRef.current = false;\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Set passkey state to trigger the passkey\n setPasskeyState({\n actionId: 'submit',\n challenge: passkeyChallenge,\n creationOptions: passkeyCreationOptions,\n error: null,\n executionId: effectiveExecutionIdForPasskey,\n isActive: true,\n });\n setIsSubmitting(false);\n\n return;\n }\n\n // Handle terminal flow statuses before normalization.\n if (await handleTerminalResponse(response)) {\n return;\n }\n\n const {\n executionId: normalizedExecutionId,\n components: normalizedComponents,\n additionalData: normalizedAdditionalData,\n } = normalizeFlowResponse(\n response,\n t,\n {\n resolveTranslations: false,\n },\n meta,\n );\n\n // Always update challenge token on any INCOMPLETE response — token rotates every step.\n await setChallengeToken(response.challengeToken ?? null);\n\n // Update executionId if response contains a new one\n if (normalizedExecutionId && normalizedComponents) {\n setExecutionId(normalizedExecutionId);\n setComponents(normalizedComponents);\n setAdditionalData(normalizedAdditionalData ?? {});\n setIsTimeoutDisabled(false);\n // Ensure flow is marked as initialized when we have components\n setIsFlowInitialized(true);\n // Clean up executionId from URL after setting it in state\n cleanupFlowUrlParams();\n\n // Surface server-side validation failures so BaseSignIn can inject them into\n // the form-level fieldErrors state used by the render-prop / default UI.\n const responseFieldErrors: FieldError[] | undefined = (response.data as any)?.fieldErrors;\n if (responseFieldErrors && responseFieldErrors.length > 0) {\n setServerFieldErrors(responseFieldErrors);\n }\n\n // Display error from INCOMPLETE response\n if ((response as any)?.error) {\n setFlowError(new Error(extractErrorMessage(response, t)));\n }\n }\n } catch (error) {\n const err: any = error;\n await clearFlowState();\n\n setError(err instanceof ThunderIDRuntimeError ? err : new Error(extractErrorMessage(err, t)));\n return;\n } finally {\n setIsSubmitting(false);\n }\n };\n\n /**\n * Handle step timeout if configured in additionalData.\n *\n * An expired consent prompt is auto-submitted as a denial carrying the timeout reason, because its\n * actions no longer lead anywhere and the user would otherwise be stranded on the prompt. The\n * server discards those decisions and records nothing. Every other kind of step surfaces the\n * expiry error instead.\n */\n timeoutContextRef.current = {\n components,\n hasConsentPrompt: Boolean(additionalData?.['consentPrompt']),\n submit: handleSubmit,\n };\n\n useEffect(() => {\n const timeoutMs: number = Number(additionalData?.['stepTimeout']) || 0;\n if (timeoutMs <= 0 || !isFlowInitialized) {\n setIsTimeoutDisabled(false);\n return undefined;\n }\n\n const handleTimeout = (): void => {\n setIsTimeoutDisabled(true);\n\n const expiredError = (): Error =>\n new Error(t('errors.signin.timeout') || 'Time allowed to complete the step has expired.');\n\n // Read through the ref so the timer always sees the step that is on screen when it fires\n const context = timeoutContextRef.current;\n const actionId: string | undefined = context?.hasConsentPrompt\n ? findConsentSubmitActionId(context.components)\n : undefined;\n\n // Without an action the prompt node cannot be routed, so there is nothing to submit\n if (actionId && context && timeoutSubmittedForRef.current !== timeoutMs) {\n timeoutSubmittedForRef.current = timeoutMs;\n context\n .submit({action: actionId, inputs: {[CONSENT_REASON_KEY]: ConsentConstants.REASON_TIMEOUT}})\n .catch(() => setError(expiredError()));\n return;\n }\n\n setError(expiredError());\n };\n\n const timerId: ReturnType<typeof setTimeout> = setTimeout(handleTimeout, Math.max(0, timeoutMs - Date.now()));\n\n return () => clearTimeout(timerId);\n }, [additionalData?.['stepTimeout'], isFlowInitialized, t]);\n\n /**\n * Handle authentication errors.\n */\n const handleError = (error: Error): void => {\n setError(error);\n };\n\n useOAuthCallback({\n currentExecutionId,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isInitialized && !isLoading && isStorageReady,\n isSubmitting,\n onError: (err: any) => {\n clearFlowState();\n setError(err instanceof Error ? err : new Error(String(err)));\n },\n onSubmit: async (payload: any) => handleSubmit({executionId: payload.executionId, inputs: payload.inputs}),\n processedRef: oauthCodeProcessedRef,\n setExecutionId,\n });\n\n /**\n * Handle passkey authentication/registration when passkey state becomes active.\n * This effect auto-triggers the browser passkey popup and submits the result.\n */\n useEffect(() => {\n if (\n !passkeyState.isActive ||\n (!passkeyState.challenge && !passkeyState.creationOptions) ||\n !passkeyState.executionId\n ) {\n return;\n }\n\n // Prevent re-processing\n if (passkeyProcessedRef.current) {\n return;\n }\n passkeyProcessedRef.current = true;\n\n const performPasskeyProcess = async (): Promise<void> => {\n let inputs: Record<string, string>;\n\n if (passkeyState.challenge) {\n const passkeyResponse: any = await handlePasskeyAuthentication(passkeyState.challenge);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n authenticatorData: passkeyResponseObj.response.authenticatorData,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n signature: passkeyResponseObj.response.signature,\n userHandle: passkeyResponseObj.response.userHandle,\n };\n } else if (passkeyState.creationOptions) {\n const passkeyResponse: any = await handlePasskeyRegistration(passkeyState.creationOptions);\n const passkeyResponseObj: any = JSON.parse(passkeyResponse);\n\n inputs = {\n attestationObject: passkeyResponseObj.response.attestationObject,\n clientDataJSON: passkeyResponseObj.response.clientDataJSON,\n credentialId: passkeyResponseObj.id,\n };\n } else {\n throw new Error('No passkey challenge or creation options available');\n }\n\n await handleSubmit({\n executionId: passkeyState.executionId ?? undefined,\n inputs,\n });\n };\n\n performPasskeyProcess()\n .then(() => {\n setPasskeyState({\n actionId: null,\n challenge: null,\n creationOptions: null,\n error: null,\n executionId: null,\n isActive: false,\n });\n })\n .catch((error: any) => {\n setPasskeyState((prev: any) => ({...prev, error: error as Error, isActive: false}));\n setFlowError(error as Error);\n onError?.(error as Error);\n });\n }, [passkeyState.isActive, passkeyState.challenge, passkeyState.creationOptions, passkeyState.executionId]);\n\n if (children) {\n // Collapse the server FieldError[] array to a single message per field map for\n // render-prop consumers. First error per field wins. Multi-error cases per\n // field are rare in practice (server typically returns one rule failure per\n // field in current flows) and consumers needing the full array can still read\n // it from the raw flow response.\n const renderPropFieldErrors: Record<string, string> = {};\n if (serverFieldErrors) {\n for (const fe of serverFieldErrors) {\n if (!(fe.identifier in renderPropFieldErrors)) {\n renderPropFieldErrors[fe.identifier] = fe.message;\n }\n }\n }\n\n const renderProps: SignInRenderProps = {\n additionalData,\n components,\n error: flowError,\n fieldErrors: renderPropFieldErrors,\n initialize: initializeFlow,\n isInitialized: isFlowInitialized,\n isLoading: isLoading || isSubmitting || !isInitialized,\n isTimeoutDisabled,\n meta,\n onSubmit: handleSubmit,\n };\n\n return <>{children(renderProps)}</>;\n }\n // Otherwise, render the default BaseSignIn component\n return (\n <BaseSignIn\n additionalData={additionalData}\n components={components}\n isLoading={isLoading || !isInitialized || !isFlowInitialized}\n isTimeoutDisabled={isTimeoutDisabled}\n onSubmit={handleSubmit}\n onError={handleError}\n error={flowError}\n className={className}\n size={size}\n variant={variant}\n preferences={preferences}\n revalidateOnChangeAfterBlur={revalidateOnChangeAfterBlur}\n serverFieldErrors={serverFieldErrors}\n />\n );\n};\n\nexport default SignIn;\n"],"mappings":"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"}