@auth0/auth0-acul-react 1.0.0-alpha.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 (279) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/dist/export/getting-started.d.ts +336 -0
  4. package/dist/export/hooks.d.ts +1 -0
  5. package/dist/export/index.d.ts +6 -0
  6. package/dist/export/screens.d.ts +76 -0
  7. package/dist/hooks/common/auth0-themes.d.ts +48 -0
  8. package/dist/hooks/common/auth0-themes.js +2 -0
  9. package/dist/hooks/common/auth0-themes.js.map +1 -0
  10. package/dist/hooks/common/current-screen.d.ts +75 -0
  11. package/dist/hooks/common/current-screen.js +2 -0
  12. package/dist/hooks/common/current-screen.js.map +1 -0
  13. package/dist/hooks/common/errors.d.ts +103 -0
  14. package/dist/hooks/common/errors.js +2 -0
  15. package/dist/hooks/common/errors.js.map +1 -0
  16. package/dist/hooks/context/index.d.ts +120 -0
  17. package/dist/hooks/context/index.js +2 -0
  18. package/dist/hooks/context/index.js.map +1 -0
  19. package/dist/hooks/index.d.ts +10 -0
  20. package/dist/hooks/utility/login-identifiers.d.ts +26 -0
  21. package/dist/hooks/utility/login-identifiers.js +2 -0
  22. package/dist/hooks/utility/login-identifiers.js.map +1 -0
  23. package/dist/hooks/utility/polling-manager.d.ts +93 -0
  24. package/dist/hooks/utility/polling-manager.js +2 -0
  25. package/dist/hooks/utility/polling-manager.js.map +1 -0
  26. package/dist/hooks/utility/resend-manager.d.ts +74 -0
  27. package/dist/hooks/utility/resend-manager.js +2 -0
  28. package/dist/hooks/utility/resend-manager.js.map +1 -0
  29. package/dist/hooks/utility/signup-identifiers.d.ts +34 -0
  30. package/dist/hooks/utility/signup-identifiers.js +2 -0
  31. package/dist/hooks/utility/signup-identifiers.js.map +1 -0
  32. package/dist/hooks/utility/validate-password.d.ts +36 -0
  33. package/dist/hooks/utility/validate-password.js +2 -0
  34. package/dist/hooks/utility/validate-password.js.map +1 -0
  35. package/dist/hooks/utility/validate-username.d.ts +58 -0
  36. package/dist/hooks/utility/validate-username.js +2 -0
  37. package/dist/hooks/utility/validate-username.js.map +1 -0
  38. package/dist/index.d.ts +78 -0
  39. package/dist/index.js +2 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/screens/accept-invitation.d.ts +5 -0
  42. package/dist/screens/accept-invitation.js +2 -0
  43. package/dist/screens/accept-invitation.js.map +1 -0
  44. package/dist/screens/consent.d.ts +6 -0
  45. package/dist/screens/consent.js +2 -0
  46. package/dist/screens/consent.js.map +1 -0
  47. package/dist/screens/customized-consent.d.ts +6 -0
  48. package/dist/screens/customized-consent.js +2 -0
  49. package/dist/screens/customized-consent.js.map +1 -0
  50. package/dist/screens/device-code-activation-allowed.d.ts +4 -0
  51. package/dist/screens/device-code-activation-allowed.js +2 -0
  52. package/dist/screens/device-code-activation-allowed.js.map +1 -0
  53. package/dist/screens/device-code-activation-denied.d.ts +4 -0
  54. package/dist/screens/device-code-activation-denied.js +2 -0
  55. package/dist/screens/device-code-activation-denied.js.map +1 -0
  56. package/dist/screens/device-code-activation.d.ts +5 -0
  57. package/dist/screens/device-code-activation.js +2 -0
  58. package/dist/screens/device-code-activation.js.map +1 -0
  59. package/dist/screens/device-code-confirmation.d.ts +6 -0
  60. package/dist/screens/device-code-confirmation.js +2 -0
  61. package/dist/screens/device-code-confirmation.js.map +1 -0
  62. package/dist/screens/email-identifier-challenge.d.ts +8 -0
  63. package/dist/screens/email-identifier-challenge.js +2 -0
  64. package/dist/screens/email-identifier-challenge.js.map +1 -0
  65. package/dist/screens/email-otp-challenge.d.ts +7 -0
  66. package/dist/screens/email-otp-challenge.js +2 -0
  67. package/dist/screens/email-otp-challenge.js.map +1 -0
  68. package/dist/screens/email-verification-result.d.ts +4 -0
  69. package/dist/screens/email-verification-result.js +2 -0
  70. package/dist/screens/email-verification-result.js.map +1 -0
  71. package/dist/screens/interstitial-captcha.d.ts +4 -0
  72. package/dist/screens/interstitial-captcha.js +2 -0
  73. package/dist/screens/interstitial-captcha.js.map +1 -0
  74. package/dist/screens/login-email-verification.d.ts +7 -0
  75. package/dist/screens/login-email-verification.js +2 -0
  76. package/dist/screens/login-email-verification.js.map +1 -0
  77. package/dist/screens/login-id.d.ts +9 -0
  78. package/dist/screens/login-id.js +2 -0
  79. package/dist/screens/login-id.js.map +1 -0
  80. package/dist/screens/login-password.d.ts +6 -0
  81. package/dist/screens/login-password.js +2 -0
  82. package/dist/screens/login-password.js.map +1 -0
  83. package/dist/screens/login-passwordless-email-code.d.ts +7 -0
  84. package/dist/screens/login-passwordless-email-code.js +2 -0
  85. package/dist/screens/login-passwordless-email-code.js.map +1 -0
  86. package/dist/screens/login-passwordless-sms-otp.d.ts +7 -0
  87. package/dist/screens/login-passwordless-sms-otp.js +2 -0
  88. package/dist/screens/login-passwordless-sms-otp.js.map +1 -0
  89. package/dist/screens/login.d.ts +8 -0
  90. package/dist/screens/login.js +2 -0
  91. package/dist/screens/login.js.map +1 -0
  92. package/dist/screens/logout-aborted.d.ts +4 -0
  93. package/dist/screens/logout-aborted.js +2 -0
  94. package/dist/screens/logout-aborted.js.map +1 -0
  95. package/dist/screens/logout-complete.d.ts +4 -0
  96. package/dist/screens/logout-complete.js +2 -0
  97. package/dist/screens/logout-complete.js.map +1 -0
  98. package/dist/screens/logout.d.ts +5 -0
  99. package/dist/screens/logout.js +2 -0
  100. package/dist/screens/logout.js.map +1 -0
  101. package/dist/screens/mfa-begin-enroll-options.d.ts +5 -0
  102. package/dist/screens/mfa-begin-enroll-options.js +2 -0
  103. package/dist/screens/mfa-begin-enroll-options.js.map +1 -0
  104. package/dist/screens/mfa-country-codes.d.ts +6 -0
  105. package/dist/screens/mfa-country-codes.js +2 -0
  106. package/dist/screens/mfa-country-codes.js.map +1 -0
  107. package/dist/screens/mfa-detect-browser-capabilities.d.ts +5 -0
  108. package/dist/screens/mfa-detect-browser-capabilities.js +2 -0
  109. package/dist/screens/mfa-detect-browser-capabilities.js.map +1 -0
  110. package/dist/screens/mfa-email-challenge.d.ts +8 -0
  111. package/dist/screens/mfa-email-challenge.js +2 -0
  112. package/dist/screens/mfa-email-challenge.js.map +1 -0
  113. package/dist/screens/mfa-email-list.d.ts +6 -0
  114. package/dist/screens/mfa-email-list.js +2 -0
  115. package/dist/screens/mfa-email-list.js.map +1 -0
  116. package/dist/screens/mfa-enroll-result.d.ts +4 -0
  117. package/dist/screens/mfa-enroll-result.js +2 -0
  118. package/dist/screens/mfa-enroll-result.js.map +1 -0
  119. package/dist/screens/mfa-login-options.d.ts +5 -0
  120. package/dist/screens/mfa-login-options.js +2 -0
  121. package/dist/screens/mfa-login-options.js.map +1 -0
  122. package/dist/screens/mfa-otp-challenge.d.ts +6 -0
  123. package/dist/screens/mfa-otp-challenge.js +2 -0
  124. package/dist/screens/mfa-otp-challenge.js.map +1 -0
  125. package/dist/screens/mfa-otp-enrollment-code.d.ts +6 -0
  126. package/dist/screens/mfa-otp-enrollment-code.js +2 -0
  127. package/dist/screens/mfa-otp-enrollment-code.js.map +1 -0
  128. package/dist/screens/mfa-otp-enrollment-qr.d.ts +7 -0
  129. package/dist/screens/mfa-otp-enrollment-qr.js +2 -0
  130. package/dist/screens/mfa-otp-enrollment-qr.js.map +1 -0
  131. package/dist/screens/mfa-phone-challenge.d.ts +7 -0
  132. package/dist/screens/mfa-phone-challenge.js +2 -0
  133. package/dist/screens/mfa-phone-challenge.js.map +1 -0
  134. package/dist/screens/mfa-phone-enrollment.d.ts +7 -0
  135. package/dist/screens/mfa-phone-enrollment.js +2 -0
  136. package/dist/screens/mfa-phone-enrollment.js.map +1 -0
  137. package/dist/screens/mfa-push-challenge-push.d.ts +9 -0
  138. package/dist/screens/mfa-push-challenge-push.js +2 -0
  139. package/dist/screens/mfa-push-challenge-push.js.map +1 -0
  140. package/dist/screens/mfa-push-enrollment-qr.d.ts +5 -0
  141. package/dist/screens/mfa-push-enrollment-qr.js +2 -0
  142. package/dist/screens/mfa-push-enrollment-qr.js.map +1 -0
  143. package/dist/screens/mfa-push-list.d.ts +6 -0
  144. package/dist/screens/mfa-push-list.js +2 -0
  145. package/dist/screens/mfa-push-list.js.map +1 -0
  146. package/dist/screens/mfa-push-welcome.d.ts +6 -0
  147. package/dist/screens/mfa-push-welcome.js +2 -0
  148. package/dist/screens/mfa-push-welcome.js.map +1 -0
  149. package/dist/screens/mfa-recovery-code-challenge-new-code.d.ts +5 -0
  150. package/dist/screens/mfa-recovery-code-challenge-new-code.js +2 -0
  151. package/dist/screens/mfa-recovery-code-challenge-new-code.js.map +1 -0
  152. package/dist/screens/mfa-recovery-code-challenge.d.ts +6 -0
  153. package/dist/screens/mfa-recovery-code-challenge.js +2 -0
  154. package/dist/screens/mfa-recovery-code-challenge.js.map +1 -0
  155. package/dist/screens/mfa-recovery-code-enrollment.d.ts +5 -0
  156. package/dist/screens/mfa-recovery-code-enrollment.js +2 -0
  157. package/dist/screens/mfa-recovery-code-enrollment.js.map +1 -0
  158. package/dist/screens/mfa-sms-challenge.d.ts +10 -0
  159. package/dist/screens/mfa-sms-challenge.js +2 -0
  160. package/dist/screens/mfa-sms-challenge.js.map +1 -0
  161. package/dist/screens/mfa-sms-enrollment.d.ts +10 -0
  162. package/dist/screens/mfa-sms-enrollment.js +2 -0
  163. package/dist/screens/mfa-sms-enrollment.js.map +1 -0
  164. package/dist/screens/mfa-sms-list.d.ts +6 -0
  165. package/dist/screens/mfa-sms-list.js +2 -0
  166. package/dist/screens/mfa-sms-list.js.map +1 -0
  167. package/dist/screens/mfa-voice-challenge.d.ts +10 -0
  168. package/dist/screens/mfa-voice-challenge.js +2 -0
  169. package/dist/screens/mfa-voice-challenge.js.map +1 -0
  170. package/dist/screens/mfa-voice-enrollment.d.ts +7 -0
  171. package/dist/screens/mfa-voice-enrollment.js +2 -0
  172. package/dist/screens/mfa-voice-enrollment.js.map +1 -0
  173. package/dist/screens/mfa-webauthn-change-key-nickname.d.ts +5 -0
  174. package/dist/screens/mfa-webauthn-change-key-nickname.js +2 -0
  175. package/dist/screens/mfa-webauthn-change-key-nickname.js.map +1 -0
  176. package/dist/screens/mfa-webauthn-enrollment-success.d.ts +5 -0
  177. package/dist/screens/mfa-webauthn-enrollment-success.js +2 -0
  178. package/dist/screens/mfa-webauthn-enrollment-success.js.map +1 -0
  179. package/dist/screens/mfa-webauthn-error.d.ts +8 -0
  180. package/dist/screens/mfa-webauthn-error.js +2 -0
  181. package/dist/screens/mfa-webauthn-error.js.map +1 -0
  182. package/dist/screens/mfa-webauthn-not-available-error.d.ts +5 -0
  183. package/dist/screens/mfa-webauthn-not-available-error.js +2 -0
  184. package/dist/screens/mfa-webauthn-not-available-error.js.map +1 -0
  185. package/dist/screens/mfa-webauthn-platform-challenge.d.ts +7 -0
  186. package/dist/screens/mfa-webauthn-platform-challenge.js +2 -0
  187. package/dist/screens/mfa-webauthn-platform-challenge.js.map +1 -0
  188. package/dist/screens/mfa-webauthn-platform-enrollment.d.ts +8 -0
  189. package/dist/screens/mfa-webauthn-platform-enrollment.js +2 -0
  190. package/dist/screens/mfa-webauthn-platform-enrollment.js.map +1 -0
  191. package/dist/screens/mfa-webauthn-roaming-challenge.d.ts +7 -0
  192. package/dist/screens/mfa-webauthn-roaming-challenge.js +2 -0
  193. package/dist/screens/mfa-webauthn-roaming-challenge.js.map +1 -0
  194. package/dist/screens/mfa-webauthn-roaming-enrollment.d.ts +7 -0
  195. package/dist/screens/mfa-webauthn-roaming-enrollment.js +2 -0
  196. package/dist/screens/mfa-webauthn-roaming-enrollment.js.map +1 -0
  197. package/dist/screens/organization-picker.d.ts +9 -0
  198. package/dist/screens/organization-picker.js +2 -0
  199. package/dist/screens/organization-picker.js.map +1 -0
  200. package/dist/screens/organization-selection.d.ts +5 -0
  201. package/dist/screens/organization-selection.js +2 -0
  202. package/dist/screens/organization-selection.js.map +1 -0
  203. package/dist/screens/passkey-enrollment-local.d.ts +6 -0
  204. package/dist/screens/passkey-enrollment-local.js +2 -0
  205. package/dist/screens/passkey-enrollment-local.js.map +1 -0
  206. package/dist/screens/passkey-enrollment.d.ts +6 -0
  207. package/dist/screens/passkey-enrollment.js +2 -0
  208. package/dist/screens/passkey-enrollment.js.map +1 -0
  209. package/dist/screens/phone-identifier-challenge.d.ts +8 -0
  210. package/dist/screens/phone-identifier-challenge.js +2 -0
  211. package/dist/screens/phone-identifier-challenge.js.map +1 -0
  212. package/dist/screens/phone-identifier-enrollment.d.ts +6 -0
  213. package/dist/screens/phone-identifier-enrollment.js +2 -0
  214. package/dist/screens/phone-identifier-enrollment.js.map +1 -0
  215. package/dist/screens/redeem-ticket.d.ts +5 -0
  216. package/dist/screens/redeem-ticket.js +2 -0
  217. package/dist/screens/redeem-ticket.js.map +1 -0
  218. package/dist/screens/reset-password-email.d.ts +5 -0
  219. package/dist/screens/reset-password-email.js +2 -0
  220. package/dist/screens/reset-password-email.js.map +1 -0
  221. package/dist/screens/reset-password-error.d.ts +4 -0
  222. package/dist/screens/reset-password-error.js +2 -0
  223. package/dist/screens/reset-password-error.js.map +1 -0
  224. package/dist/screens/reset-password-mfa-email-challenge.d.ts +8 -0
  225. package/dist/screens/reset-password-mfa-email-challenge.js +2 -0
  226. package/dist/screens/reset-password-mfa-email-challenge.js.map +1 -0
  227. package/dist/screens/reset-password-mfa-otp-challenge.d.ts +6 -0
  228. package/dist/screens/reset-password-mfa-otp-challenge.js +2 -0
  229. package/dist/screens/reset-password-mfa-otp-challenge.js.map +1 -0
  230. package/dist/screens/reset-password-mfa-phone-challenge.d.ts +6 -0
  231. package/dist/screens/reset-password-mfa-phone-challenge.js +2 -0
  232. package/dist/screens/reset-password-mfa-phone-challenge.js.map +1 -0
  233. package/dist/screens/reset-password-mfa-push-challenge-push.d.ts +9 -0
  234. package/dist/screens/reset-password-mfa-push-challenge-push.js +2 -0
  235. package/dist/screens/reset-password-mfa-push-challenge-push.js.map +1 -0
  236. package/dist/screens/reset-password-mfa-recovery-code-challenge.d.ts +6 -0
  237. package/dist/screens/reset-password-mfa-recovery-code-challenge.js +2 -0
  238. package/dist/screens/reset-password-mfa-recovery-code-challenge.js.map +1 -0
  239. package/dist/screens/reset-password-mfa-sms-challenge.d.ts +9 -0
  240. package/dist/screens/reset-password-mfa-sms-challenge.js +2 -0
  241. package/dist/screens/reset-password-mfa-sms-challenge.js.map +1 -0
  242. package/dist/screens/reset-password-mfa-voice-challenge.d.ts +9 -0
  243. package/dist/screens/reset-password-mfa-voice-challenge.js +2 -0
  244. package/dist/screens/reset-password-mfa-voice-challenge.js.map +1 -0
  245. package/dist/screens/reset-password-mfa-webauthn-platform-challenge.d.ts +7 -0
  246. package/dist/screens/reset-password-mfa-webauthn-platform-challenge.js +2 -0
  247. package/dist/screens/reset-password-mfa-webauthn-platform-challenge.js.map +1 -0
  248. package/dist/screens/reset-password-mfa-webauthn-roaming-challenge.d.ts +7 -0
  249. package/dist/screens/reset-password-mfa-webauthn-roaming-challenge.js +2 -0
  250. package/dist/screens/reset-password-mfa-webauthn-roaming-challenge.js.map +1 -0
  251. package/dist/screens/reset-password-request.d.ts +7 -0
  252. package/dist/screens/reset-password-request.js +2 -0
  253. package/dist/screens/reset-password-request.js.map +1 -0
  254. package/dist/screens/reset-password-success.d.ts +4 -0
  255. package/dist/screens/reset-password-success.js +2 -0
  256. package/dist/screens/reset-password-success.js.map +1 -0
  257. package/dist/screens/reset-password.d.ts +6 -0
  258. package/dist/screens/reset-password.js +2 -0
  259. package/dist/screens/reset-password.js.map +1 -0
  260. package/dist/screens/signup-id.d.ts +9 -0
  261. package/dist/screens/signup-id.js +2 -0
  262. package/dist/screens/signup-id.js.map +1 -0
  263. package/dist/screens/signup-password.d.ts +7 -0
  264. package/dist/screens/signup-password.js +2 -0
  265. package/dist/screens/signup-password.js.map +1 -0
  266. package/dist/screens/signup.d.ts +10 -0
  267. package/dist/screens/signup.js +2 -0
  268. package/dist/screens/signup.js.map +1 -0
  269. package/dist/state/error-store.d.ts +47 -0
  270. package/dist/state/error-store.js +2 -0
  271. package/dist/state/error-store.js.map +1 -0
  272. package/dist/state/instance-store.d.ts +19 -0
  273. package/dist/state/instance-store.js +2 -0
  274. package/dist/state/instance-store.js.map +1 -0
  275. package/dist/telemetry.d.ts +8 -0
  276. package/dist/telemetry.js +2 -0
  277. package/dist/telemetry.js.map +1 -0
  278. package/dist/types/index.d.ts +2 -0
  279. package/package.json +61 -0
@@ -0,0 +1,75 @@
1
+ import { type CurrentScreenOptions } from '@auth0/auth0-acul-js';
2
+ /**
3
+ * React hook that gets the current screen context and state.
4
+ *
5
+ * This hook provides access to client configuration, organization details, screen identification,
6
+ * tenant settings, transaction state, and authorization parameters for building custom authentication UI.
7
+ *
8
+ * ## Return Value
9
+ *
10
+ * Returns `CurrentScreenOptions` object with the following properties, or `null` if unavailable:
11
+ *
12
+ * - **`client`** - Application identifier and metadata
13
+ * - **`organization`** - Organization ID and metadata (for Auth0 Organizations)
14
+ * - **`prompt`** - Current prompt name (e.g., "login", "consent", "mfa")
15
+ * - **`screen`** - Current screen name (e.g., "login-id", "login-password", "mfa-otp-challenge")
16
+ * - **`tenant`** - Tenant configuration including enabled locales
17
+ * - **`transaction`** - Transaction state, errors array, and current locale
18
+ * - **`untrustedData`** - Authorization parameters from the client (validate before use)
19
+ *
20
+ * ## Key Points
21
+ *
22
+ * - Use `screen.name` for conditional rendering of authentication screens
23
+ * - Always use optional chaining (`?.`) as nested properties can be `null`
24
+ * - Check `transaction.errors` for displaying validation errors
25
+ * - Access `organization.metadata` for organization-specific branding
26
+ *
27
+ * @returns {CurrentScreenOptions | null} Current screen context data, or `null` if not available
28
+ *
29
+ * @example
30
+ * Basic screen routing
31
+ * ```tsx
32
+ * import { useCurrentScreen } from '@auth0/auth0-acul-react';
33
+ *
34
+ * const AuthFlow = () => {
35
+ * const screenOptions = useCurrentScreen();
36
+ * const screen = screenOptions?.screen?.name || "login-id";
37
+ *
38
+ * switch (screen) {
39
+ * case "login-id":
40
+ * return <LoginIdScreen />;
41
+ * case "login-password":
42
+ * return <LoginPasswordScreen />;
43
+ * case "mfa-otp-challenge":
44
+ * return <MfaOtpChallengeScreen />;
45
+ * default:
46
+ * return null;
47
+ * }
48
+ * };
49
+ * ```
50
+ *
51
+ * @example
52
+ * Accessing multiple properties
53
+ * ```tsx
54
+ * import { useCurrentScreen } from '@auth0/auth0-acul-react';
55
+ *
56
+ * const CustomAuthScreen = () => {
57
+ * const screenOptions = useCurrentScreen();
58
+ * const organizationId = screenOptions?.organization?.id;
59
+ * const errors = screenOptions?.transaction?.errors || [];
60
+ * const locale = screenOptions?.transaction?.locale || 'en';
61
+ *
62
+ * return (
63
+ * <div>
64
+ * {organizationId && <p>Organization: {organizationId}</p>}
65
+ * {errors.map((error, i) => (
66
+ * <p key={i} className="error">{error.message}</p>
67
+ * ))}
68
+ * <p>Language: {locale}</p>
69
+ * </div>
70
+ * );
71
+ * };
72
+ * ```
73
+ *
74
+ */
75
+ export declare const useCurrentScreen: () => CurrentScreenOptions | null;
@@ -0,0 +1,2 @@
1
+ import{getCurrentScreenOptions as t}from"@auth0/auth0-acul-js";const o=()=>t();export{o as useCurrentScreen};
2
+ //# sourceMappingURL=current-screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"current-screen.js","sources":["../../../src/hooks/common/current-screen.ts"],"sourcesContent":["import { getCurrentScreenOptions, type CurrentScreenOptions } from '@auth0/auth0-acul-js';\n\n/**\n * React hook that gets the current screen context and state.\n *\n * This hook provides access to client configuration, organization details, screen identification,\n * tenant settings, transaction state, and authorization parameters for building custom authentication UI.\n *\n * ## Return Value\n *\n * Returns `CurrentScreenOptions` object with the following properties, or `null` if unavailable:\n *\n * - **`client`** - Application identifier and metadata\n * - **`organization`** - Organization ID and metadata (for Auth0 Organizations)\n * - **`prompt`** - Current prompt name (e.g., \"login\", \"consent\", \"mfa\")\n * - **`screen`** - Current screen name (e.g., \"login-id\", \"login-password\", \"mfa-otp-challenge\")\n * - **`tenant`** - Tenant configuration including enabled locales\n * - **`transaction`** - Transaction state, errors array, and current locale\n * - **`untrustedData`** - Authorization parameters from the client (validate before use)\n *\n * ## Key Points\n *\n * - Use `screen.name` for conditional rendering of authentication screens\n * - Always use optional chaining (`?.`) as nested properties can be `null`\n * - Check `transaction.errors` for displaying validation errors\n * - Access `organization.metadata` for organization-specific branding\n *\n * @returns {CurrentScreenOptions | null} Current screen context data, or `null` if not available\n *\n * @example\n * Basic screen routing\n * ```tsx\n * import { useCurrentScreen } from '@auth0/auth0-acul-react';\n *\n * const AuthFlow = () => {\n * const screenOptions = useCurrentScreen();\n * const screen = screenOptions?.screen?.name || \"login-id\";\n *\n * switch (screen) {\n * case \"login-id\":\n * return <LoginIdScreen />;\n * case \"login-password\":\n * return <LoginPasswordScreen />;\n * case \"mfa-otp-challenge\":\n * return <MfaOtpChallengeScreen />;\n * default:\n * return null;\n * }\n * };\n * ```\n *\n * @example\n * Accessing multiple properties\n * ```tsx\n * import { useCurrentScreen } from '@auth0/auth0-acul-react';\n *\n * const CustomAuthScreen = () => {\n * const screenOptions = useCurrentScreen();\n * const organizationId = screenOptions?.organization?.id;\n * const errors = screenOptions?.transaction?.errors || [];\n * const locale = screenOptions?.transaction?.locale || 'en';\n *\n * return (\n * <div>\n * {organizationId && <p>Organization: {organizationId}</p>}\n * {errors.map((error, i) => (\n * <p key={i} className=\"error\">{error.message}</p>\n * ))}\n * <p>Language: {locale}</p>\n * </div>\n * );\n * };\n * ```\n *\n */\nexport const useCurrentScreen = (): CurrentScreenOptions | null => {\n return getCurrentScreenOptions();\n};\n"],"names":["useCurrentScreen","getCurrentScreenOptions"],"mappings":"+DA2EO,MAAMA,EAAmB,IACvBC"}
@@ -0,0 +1,103 @@
1
+ import { type ErrorItem, type ErrorKind } from '../../state/error-store';
2
+ export interface ErrorsResult extends ReadonlyArray<ErrorItem> {
3
+ byKind(kind: ErrorKind, opts?: {
4
+ field?: string;
5
+ }): ReadonlyArray<ErrorItem>;
6
+ byField(field: string, opts?: {
7
+ kind?: ErrorKind;
8
+ }): ReadonlyArray<ErrorItem>;
9
+ }
10
+ export interface UseErrorOptions {
11
+ includeDevErrors?: boolean;
12
+ }
13
+ export interface UseErrorsResult {
14
+ errors: ErrorsResult;
15
+ hasError: boolean;
16
+ dismiss: (id: string) => void;
17
+ dismissAll: () => void;
18
+ }
19
+ /**
20
+ * React hook for reading and managing errors in ACUL (Advanced Customization of Universal Login).
21
+ * With all validation and server-side errors. It groups errors into three kinds:
22
+ * - `server` — errors returned by Auth0 or your own backend.
23
+ * - `client` — errors from client-side validation (e.g., invalid form input).
24
+ * - `developer` — errors caused by incorrect integration or SDK misuse.
25
+ *
26
+ * @supportedScreens
27
+ * - The `useErrors` hook is available on every ACUL screen.
28
+ *
29
+ * @param options.includeDevErrors - When `true`, developer errors are included in
30
+ * the returned list. Defaults to `false`.
31
+ *
32
+ * @returns An object of type {@link UseErrorsResult}, containing:
33
+ * - `errors` — the full error list of type {@link ErrorsResult}, with helpers:
34
+ * - `errors.byKind(kind, filter?)` — filter by error kind and optionally by field.
35
+ * - `errors.byField(field, filter?)` — filter by field and optionally by kind.
36
+ * - `hasError` — `true` if any error is currently present.
37
+ * - `dismiss(id)` — remove a specific error by its ID.
38
+ * - `dismissAll()` — clear all tracked errors.
39
+ *
40
+ * Typical usage is inside a form or screen component where you need to
41
+ * reactively display errors and provide ways to dismiss them:
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * import { useErrors } from "@auth0/auth0-acul-react";
46
+ *
47
+ * export function SignupForm() {
48
+ * const { errors, hasError, dismiss, dismissAll } = useErrors();
49
+ *
50
+ * return (
51
+ * <div>
52
+ * {hasError && (
53
+ * <div className="mb-4">
54
+ * {errors.byKind("server").map(err => (
55
+ * <div key={err.id} className="text-red-600">
56
+ * {err.message}
57
+ * <button onClick={() => dismiss(err.id)}>Dismiss</button>
58
+ * </div>
59
+ * ))}
60
+ * </div>
61
+ * )}
62
+ *
63
+ * <button onClick={dismissAll}>Clear All Errors</button>
64
+ * </div>
65
+ * );
66
+ * }
67
+ * ```
68
+ *
69
+ * In addition to rendering messages, you can filter by field or kind:
70
+ * ```ts
71
+ * console.log(errors.byKind('client')); // all client errors
72
+ * console.log(errors.byKind('client', { field: 'username' })); // client errors for field 'username'
73
+ * console.log(errors.byField('username')); // all errors for field 'username'
74
+ * console.log(errors.byField('username', { kind: 'server' })); // server errors for field 'username'
75
+ * ```
76
+ */
77
+ export declare function useErrors(options?: UseErrorOptions): UseErrorsResult;
78
+ declare function withError<T>(actionOrPromise: (() => T | Promise<T>) | Promise<T>): T | Promise<T>;
79
+ /**
80
+ * @hidden
81
+ * Internal error manager for use by SDK methods.
82
+ * Use the `useErrors` hook in React components instead.
83
+ */
84
+ export declare const errorManager: {
85
+ withError: typeof withError;
86
+ replaceClientErrors(list: Array<Omit<ErrorItem, "id">>, opts?: {
87
+ byField?: string;
88
+ }): void;
89
+ clearClientErrors(): void;
90
+ pushClientErrors(list: Omit<ErrorItem, "id"> | Array<Omit<ErrorItem, "id">>): void;
91
+ replaceDeveloperErrors(list: Array<Omit<ErrorItem, "id">>, opts?: {
92
+ byField?: string;
93
+ }): void;
94
+ clearDeveloperErrors(): void;
95
+ pushDeveloperErrors(list: Omit<ErrorItem, "id"> | Array<Omit<ErrorItem, "id">>): void;
96
+ replaceServerErrors(list: Array<Omit<ErrorItem, "id">>, opts?: {
97
+ byField?: string;
98
+ }): void;
99
+ clearServerErrors(): void;
100
+ pushServerErrors(list: Omit<ErrorItem, "id"> | Array<Omit<ErrorItem, "id">>): void;
101
+ syncServerErrors(): void;
102
+ };
103
+ export { ErrorItem, ErrorKind };
@@ -0,0 +1,2 @@
1
+ import{getErrors as e,UserInputError as r,SDKUsageError as t,Auth0ServerError as n}from"@auth0/auth0-acul-js";import{useSyncExternalStore as c,useRef as o,useEffect as l,useMemo as s,useCallback as i}from"react";import{errorStore as a,ERROR_KINDS as p}from"../../state/error-store.js";function d(e,r){return r?e.filter(e=>e.field===r):e}const u=new WeakMap,v=new WeakMap,f=new WeakMap,h=(e,r)=>{const t="server"===e?u:"client"===e?v:f,n=t.get(r);if(n)return n;const c=Object.freeze(r.map(r=>Object.freeze({...r,kind:e})));return t.set(r,c),c};function b(r={}){const{includeDevErrors:t=!1}=r,n=c(e=>a.subscribe(e),()=>a.snapshot()),u=o(!1);l(()=>{if(u.current)return;u.current=!0;const r=e?.()??[];a.replace("server",r)},[]);const v=s(()=>h("server",n.server),[n.server]),f=s(()=>h("client",n.client),[n.client]),b=s(()=>h("developer",n.developer),[n.developer]),E=s(()=>Object.freeze([...t?b:[],...f,...v]),[t,b,f,v]),y=s(()=>{const e=Object.assign([...E],{byKind(e,r){const t="client"===e?f:"developer"===e?b:v;return r?.field?Object.freeze(d(t,r.field)):t},byField:(r,t)=>t?.kind?e.byKind(t.kind,{field:r}):Object.freeze(d(E,r))});return Object.freeze(e)},[E,f,b,v]),m=E.length>0,k=i(e=>{a.remove(p,e)},[]),w=i(()=>{a.clear(p)},[]);return s(()=>({errors:y,hasError:m,dismiss:k,dismissAll:w}),[y,m,k,w])}const E={withError:function(e){const c=e=>{const c=function(e){return e instanceof r?"client":e instanceof t?"developer":e instanceof n?"server":null}(e),o=function(e){return{code:e?.code??(e instanceof Error?e.name:void 0)??"unknown_error",message:e?.message??"Unknown error",field:e?.field}}(e);switch(c){case"client":E.replaceClientErrors([o]);break;case"developer":E.replaceDeveloperErrors([o]);break;case"server":E.replaceServerErrors([o]);break;default:throw console.error("[auth0-acul-react] Unhandled error:",e),e}};if("function"==typeof e)try{const r=e();return"object"==typeof(o=r)&&null!==o&&"then"in o&&"function"==typeof o.then?r.catch(e=>{throw c(e),e}):r}catch(e){throw c(e),e}var o;return e.catch(e=>{throw c(e),e})},replaceClientErrors(e,r){r?.byField?a.replacePartial("client",e,r.byField):a.replace("client",e)},clearClientErrors(){a.clear(["client"])},pushClientErrors(e){a.push("client",e)},replaceDeveloperErrors(e,r){r?.byField?a.replacePartial("developer",e,r.byField):a.replace("developer",e)},clearDeveloperErrors(){a.clear(["developer"])},pushDeveloperErrors(e){a.push("developer",e)},replaceServerErrors(e,r){r?.byField?a.replacePartial("server",e,r.byField):a.replace("server",e)},clearServerErrors(){a.clear(["server"])},pushServerErrors(e){a.push("server",e)},syncServerErrors(){const r=e?.()??[];a.replace("server",r)}};export{E as errorManager,b as useErrors};
2
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sources":["../../../src/hooks/common/errors.ts"],"sourcesContent":["import {\n SDKUsageError,\n UserInputError,\n Auth0ServerError,\n getErrors as getServerErrors,\n type Error as Auth0Error,\n} from '@auth0/auth0-acul-js';\nimport { useEffect, useMemo, useRef, useSyncExternalStore, useCallback } from 'react';\n\nimport { errorStore, ERROR_KINDS, type ErrorItem, type ErrorKind } from '../../state/error-store';\n\nexport interface ErrorsResult extends ReadonlyArray<ErrorItem> {\n byKind(kind: ErrorKind, opts?: { field?: string }): ReadonlyArray<ErrorItem>;\n byField(field: string, opts?: { kind?: ErrorKind }): ReadonlyArray<ErrorItem>;\n}\n\nexport interface UseErrorOptions {\n includeDevErrors?: boolean;\n}\n\nexport interface UseErrorsResult {\n errors: ErrorsResult;\n hasError: boolean;\n dismiss: (id: string) => void;\n dismissAll: () => void;\n}\n\nfunction classifyKind(e: unknown): ErrorKind | null {\n if (e instanceof UserInputError) {\n return 'client';\n }\n if (e instanceof SDKUsageError) {\n return 'developer';\n }\n if (e instanceof Auth0ServerError) {\n return 'server';\n }\n return null;\n}\n\nfunction toErrorObject(e: unknown): Omit<ErrorItem, 'id'> {\n return {\n code: (e as Auth0Error)?.code ?? (e instanceof Error ? e.name : undefined) ?? 'unknown_error',\n message: (e as Auth0Error)?.message ?? 'Unknown error',\n field: (e as Auth0Error)?.field,\n };\n}\n\nfunction filterByField<T extends { field?: string }>(\n list: ReadonlyArray<T>,\n field?: string\n): ReadonlyArray<T> {\n if (!field) {\n return list;\n }\n return list.filter((e) => e.field === field);\n}\n\n// caches for tagging\nconst cacheServer = new WeakMap<ReadonlyArray<ErrorItem>, ReadonlyArray<ErrorItem>>();\nconst cacheClient = new WeakMap<ReadonlyArray<ErrorItem>, ReadonlyArray<ErrorItem>>();\nconst cacheDev = new WeakMap<ReadonlyArray<ErrorItem>, ReadonlyArray<ErrorItem>>();\n\nconst tag = (kind: ErrorKind, arr: ReadonlyArray<ErrorItem>): ReadonlyArray<ErrorItem> => {\n const cache = kind === 'server' ? cacheServer : kind === 'client' ? cacheClient : cacheDev;\n const hit = cache.get(arr);\n if (hit) {\n return hit;\n }\n const out = Object.freeze(arr.map((e) => Object.freeze({ ...e, kind })));\n cache.set(arr, out);\n return out;\n};\n\n/**\n * React hook for reading and managing errors in ACUL (Advanced Customization of Universal Login).\n * With all validation and server-side errors. It groups errors into three kinds:\n * - `server` — errors returned by Auth0 or your own backend.\n * - `client` — errors from client-side validation (e.g., invalid form input).\n * - `developer` — errors caused by incorrect integration or SDK misuse.\n *\n * @supportedScreens\n * - The `useErrors` hook is available on every ACUL screen.\n *\n * @param options.includeDevErrors - When `true`, developer errors are included in\n * the returned list. Defaults to `false`.\n *\n * @returns An object of type {@link UseErrorsResult}, containing:\n * - `errors` — the full error list of type {@link ErrorsResult}, with helpers:\n * - `errors.byKind(kind, filter?)` — filter by error kind and optionally by field.\n * - `errors.byField(field, filter?)` — filter by field and optionally by kind.\n * - `hasError` — `true` if any error is currently present.\n * - `dismiss(id)` — remove a specific error by its ID.\n * - `dismissAll()` — clear all tracked errors.\n *\n * Typical usage is inside a form or screen component where you need to\n * reactively display errors and provide ways to dismiss them:\n *\n * @example\n * ```tsx\n * import { useErrors } from \"@auth0/auth0-acul-react\";\n *\n * export function SignupForm() {\n * const { errors, hasError, dismiss, dismissAll } = useErrors();\n *\n * return (\n * <div>\n * {hasError && (\n * <div className=\"mb-4\">\n * {errors.byKind(\"server\").map(err => (\n * <div key={err.id} className=\"text-red-600\">\n * {err.message}\n * <button onClick={() => dismiss(err.id)}>Dismiss</button>\n * </div>\n * ))}\n * </div>\n * )}\n *\n * <button onClick={dismissAll}>Clear All Errors</button>\n * </div>\n * );\n * }\n * ```\n *\n * In addition to rendering messages, you can filter by field or kind:\n * ```ts\n * console.log(errors.byKind('client')); // all client errors\n * console.log(errors.byKind('client', { field: 'username' })); // client errors for field 'username'\n * console.log(errors.byField('username')); // all errors for field 'username'\n * console.log(errors.byField('username', { kind: 'server' })); // server errors for field 'username'\n * ```\n */\n\nexport function useErrors(options: UseErrorOptions = {}): UseErrorsResult {\n const { includeDevErrors = false } = options;\n\n const snap = useSyncExternalStore(\n (cb) => errorStore.subscribe(cb),\n () => errorStore.snapshot()\n );\n\n const didInit = useRef(false);\n useEffect(() => {\n if (didInit.current) {\n return;\n }\n didInit.current = true;\n\n // Get server errors directly from TS SDK on first render.\n const server = (getServerErrors?.() ?? []) as Array<Omit<ErrorItem, 'id'>>;\n errorStore.replace('server', server);\n }, []);\n\n const serverTagged = useMemo(() => tag('server', snap.server), [snap.server]);\n const clientTagged = useMemo(() => tag('client', snap.client), [snap.client]);\n const devTagged = useMemo(() => tag('developer', snap.developer), [snap.developer]);\n\n const all = useMemo<ReadonlyArray<ErrorItem>>(\n () => Object.freeze([...(includeDevErrors ? devTagged : []), ...clientTagged, ...serverTagged]),\n [includeDevErrors, devTagged, clientTagged, serverTagged]\n );\n\n const errors: ErrorsResult = useMemo(() => {\n const arr = Object.assign([...all], {\n byKind(kind: ErrorKind, opts?: { field?: string }): ReadonlyArray<ErrorItem> {\n const base =\n kind === 'client' ? clientTagged : kind === 'developer' ? devTagged : serverTagged;\n return opts?.field ? Object.freeze(filterByField(base, opts.field)) : base;\n },\n byField(field: string, opts?: { kind?: ErrorKind }): ReadonlyArray<ErrorItem> {\n if (opts?.kind) {\n return arr.byKind(opts.kind, { field });\n }\n return Object.freeze(filterByField(all, field));\n },\n });\n return Object.freeze(arr);\n }, [all, clientTagged, devTagged, serverTagged]);\n\n const hasError = all.length > 0;\n\n const dismiss = useCallback((id: string) => {\n errorStore.remove(ERROR_KINDS, id);\n }, []);\n\n const dismissAll = useCallback(() => {\n errorStore.clear(ERROR_KINDS);\n }, []);\n\n return useMemo(\n () => ({ errors, hasError, dismiss, dismissAll }),\n [errors, hasError, dismiss, dismissAll]\n );\n}\n\n// ---------------- INTERNAL (SDK-only) ----------------\nconst isPromise = (v: unknown): v is Promise<unknown> =>\n typeof v === 'object' &&\n v !== null &&\n 'then' in v &&\n typeof (v as { then: unknown }).then === 'function';\n\nfunction withError<T>(actionOrPromise: (() => T | Promise<T>) | Promise<T>): T | Promise<T> {\n const handle = (e: unknown) => {\n const kind = classifyKind(e);\n const normalized = toErrorObject(e);\n switch (kind) {\n case 'client':\n errorManager.replaceClientErrors([normalized]);\n break;\n case 'developer':\n errorManager.replaceDeveloperErrors([normalized]);\n break;\n case 'server':\n errorManager.replaceServerErrors([normalized]);\n break;\n default: {\n console.error('[auth0-acul-react] Unhandled error:', e);\n throw e;\n }\n }\n };\n\n if (typeof actionOrPromise === 'function') {\n try {\n const result = (actionOrPromise as () => T | Promise<T>)();\n return isPromise(result)\n ? result.catch((e) => {\n handle(e);\n throw e;\n })\n : result;\n } catch (e) {\n handle(e);\n throw e;\n }\n }\n\n return actionOrPromise.catch((e) => {\n handle(e);\n throw e;\n });\n}\n\n/**\n * @hidden\n * Internal error manager for use by SDK methods.\n * Use the `useErrors` hook in React components instead.\n */\nexport const errorManager = {\n withError,\n\n replaceClientErrors(list: Array<Omit<ErrorItem, 'id'>>, opts?: { byField?: string }) {\n if (opts?.byField) {\n errorStore.replacePartial('client', list, opts.byField);\n } else {\n errorStore.replace('client', list);\n }\n },\n clearClientErrors() {\n errorStore.clear(['client']);\n },\n pushClientErrors(list: Omit<ErrorItem, 'id'> | Array<Omit<ErrorItem, 'id'>>) {\n errorStore.push('client', list);\n },\n\n replaceDeveloperErrors(list: Array<Omit<ErrorItem, 'id'>>, opts?: { byField?: string }) {\n if (opts?.byField) {\n errorStore.replacePartial('developer', list, opts.byField);\n } else {\n errorStore.replace('developer', list);\n }\n },\n clearDeveloperErrors() {\n errorStore.clear(['developer']);\n },\n pushDeveloperErrors(list: Omit<ErrorItem, 'id'> | Array<Omit<ErrorItem, 'id'>>) {\n errorStore.push('developer', list);\n },\n\n replaceServerErrors(list: Array<Omit<ErrorItem, 'id'>>, opts?: { byField?: string }) {\n if (opts?.byField) {\n errorStore.replacePartial('server', list, opts.byField);\n } else {\n errorStore.replace('server', list);\n }\n },\n clearServerErrors() {\n errorStore.clear(['server']);\n },\n pushServerErrors(list: Omit<ErrorItem, 'id'> | Array<Omit<ErrorItem, 'id'>>) {\n errorStore.push('server', list);\n },\n\n syncServerErrors() {\n const server = (getServerErrors?.() ?? []) as Array<Omit<ErrorItem, 'id'>>;\n errorStore.replace('server', server);\n },\n};\n\nexport { ErrorItem, ErrorKind };\n"],"names":["filterByField","list","field","filter","e","cacheServer","WeakMap","cacheClient","cacheDev","tag","kind","arr","cache","hit","get","out","Object","freeze","map","set","useErrors","options","includeDevErrors","snap","useSyncExternalStore","cb","errorStore","subscribe","snapshot","didInit","useRef","useEffect","current","server","getServerErrors","replace","serverTagged","useMemo","clientTagged","client","devTagged","developer","all","errors","assign","byKind","opts","base","byField","hasError","length","dismiss","useCallback","id","remove","ERROR_KINDS","dismissAll","clear","errorManager","withError","actionOrPromise","handle","UserInputError","SDKUsageError","Auth0ServerError","classifyKind","normalized","code","Error","name","undefined","message","toErrorObject","replaceClientErrors","replaceDeveloperErrors","replaceServerErrors","console","error","result","v","then","catch","replacePartial","clearClientErrors","pushClientErrors","push","clearDeveloperErrors","pushDeveloperErrors","clearServerErrors","pushServerErrors","syncServerErrors"],"mappings":"6RAgDA,SAASA,EACPC,EACAC,GAEA,OAAKA,EAGED,EAAKE,OAAQC,GAAMA,EAAEF,QAAUA,GAF7BD,CAGX,CAGA,MAAMI,EAAc,IAAIC,QAClBC,EAAc,IAAID,QAClBE,EAAW,IAAIF,QAEfG,EAAM,CAACC,EAAiBC,KAC5B,MAAMC,EAAiB,WAATF,EAAoBL,EAAuB,WAATK,EAAoBH,EAAcC,EAC5EK,EAAMD,EAAME,IAAIH,GACtB,GAAIE,EACF,OAAOA,EAET,MAAME,EAAMC,OAAOC,OAAON,EAAIO,IAAKd,GAAMY,OAAOC,OAAO,IAAKb,EAAGM,WAE/D,OADAE,EAAMO,IAAIR,EAAKI,GACRA,GA8DH,SAAUK,EAAUC,EAA2B,IACnD,MAAMC,iBAAEA,GAAmB,GAAUD,EAE/BE,EAAOC,EACVC,GAAOC,EAAWC,UAAUF,GAC7B,IAAMC,EAAWE,YAGbC,EAAUC,GAAO,GACvBC,EAAU,KACR,GAAIF,EAAQG,QACV,OAEFH,EAAQG,SAAU,EAGlB,MAAMC,EAAUC,OAAuB,GACvCR,EAAWS,QAAQ,SAAUF,IAC5B,IAEH,MAAMG,EAAeC,EAAQ,IAAM5B,EAAI,SAAUc,EAAKU,QAAS,CAACV,EAAKU,SAC/DK,EAAeD,EAAQ,IAAM5B,EAAI,SAAUc,EAAKgB,QAAS,CAAChB,EAAKgB,SAC/DC,EAAYH,EAAQ,IAAM5B,EAAI,YAAac,EAAKkB,WAAY,CAAClB,EAAKkB,YAElEC,EAAML,EACV,IAAMrB,OAAOC,OAAO,IAAKK,EAAmBkB,EAAY,MAAQF,KAAiBF,IACjF,CAACd,EAAkBkB,EAAWF,EAAcF,IAGxCO,EAAuBN,EAAQ,KACnC,MAAM1B,EAAMK,OAAO4B,OAAO,IAAIF,GAAM,CAClC,MAAAG,CAAOnC,EAAiBoC,GACtB,MAAMC,EACK,WAATrC,EAAoB4B,EAAwB,cAAT5B,EAAuB8B,EAAYJ,EACxE,OAAOU,GAAM5C,MAAQc,OAAOC,OAAOjB,EAAc+C,EAAMD,EAAK5C,QAAU6C,CACxE,EACAC,QAAO,CAAC9C,EAAe4C,IACjBA,GAAMpC,KACDC,EAAIkC,OAAOC,EAAKpC,KAAM,CAAER,UAE1Bc,OAAOC,OAAOjB,EAAc0C,EAAKxC,MAG5C,OAAOc,OAAOC,OAAON,IACpB,CAAC+B,EAAKJ,EAAcE,EAAWJ,IAE5Ba,EAAWP,EAAIQ,OAAS,EAExBC,EAAUC,EAAaC,IAC3B3B,EAAW4B,OAAOC,EAAaF,IAC9B,IAEGG,EAAaJ,EAAY,KAC7B1B,EAAW+B,MAAMF,IAChB,IAEH,OAAOlB,EACL,KAAA,CAASM,SAAQM,WAAUE,UAASK,eACpC,CAACb,EAAQM,EAAUE,EAASK,GAEhC,CAwDO,MAAME,EAAe,CAC1BC,UAhDF,SAAsBC,GACpB,MAAMC,EAAUzD,IACd,MAAMM,EAjLV,SAAsBN,GACpB,OAAIA,aAAa0D,EACR,SAEL1D,aAAa2D,EACR,YAEL3D,aAAa4D,EACR,SAEF,IACT,CAsKiBC,CAAa7D,GACpB8D,EArKV,SAAuB9D,GACrB,MAAO,CACL+D,KAAO/D,GAAkB+D,OAAS/D,aAAagE,MAAQhE,EAAEiE,UAAOC,IAAc,gBAC9EC,QAAUnE,GAAkBmE,SAAW,gBACvCrE,MAAQE,GAAkBF,MAE9B,CA+JuBsE,CAAcpE,GACjC,OAAQM,GACN,IAAK,SACHgD,EAAae,oBAAoB,CAACP,IAClC,MACF,IAAK,YACHR,EAAagB,uBAAuB,CAACR,IACrC,MACF,IAAK,SACHR,EAAaiB,oBAAoB,CAACT,IAClC,MACF,QAEE,MADAU,QAAQC,MAAM,sCAAuCzE,GAC/CA,IAKZ,GAA+B,mBAApBwD,EACT,IACE,MAAMkB,EAAUlB,IAChB,MA7BS,iBADImB,EA8BID,IA5Bf,OAANC,GACA,SAAUA,GAC+B,mBAAjCA,EAAwBC,KA2BxBF,EAAOG,MAAO7E,IAEZ,MADAyD,EAAOzD,GACDA,IAER0E,CACN,CAAE,MAAO1E,GAEP,MADAyD,EAAOzD,GACDA,CACR,CAvCc,IAAC2E,EA0CjB,OAAOnB,EAAgBqB,MAAO7E,IAE5B,MADAyD,EAAOzD,GACDA,GAEV,EAUE,mBAAAqE,CAAoBxE,EAAoC6C,GAClDA,GAAME,QACRtB,EAAWwD,eAAe,SAAUjF,EAAM6C,EAAKE,SAE/CtB,EAAWS,QAAQ,SAAUlC,EAEjC,EACA,iBAAAkF,GACEzD,EAAW+B,MAAM,CAAC,UACpB,EACA,gBAAA2B,CAAiBnF,GACfyB,EAAW2D,KAAK,SAAUpF,EAC5B,EAEA,sBAAAyE,CAAuBzE,EAAoC6C,GACrDA,GAAME,QACRtB,EAAWwD,eAAe,YAAajF,EAAM6C,EAAKE,SAElDtB,EAAWS,QAAQ,YAAalC,EAEpC,EACA,oBAAAqF,GACE5D,EAAW+B,MAAM,CAAC,aACpB,EACA,mBAAA8B,CAAoBtF,GAClByB,EAAW2D,KAAK,YAAapF,EAC/B,EAEA,mBAAA0E,CAAoB1E,EAAoC6C,GAClDA,GAAME,QACRtB,EAAWwD,eAAe,SAAUjF,EAAM6C,EAAKE,SAE/CtB,EAAWS,QAAQ,SAAUlC,EAEjC,EACA,iBAAAuF,GACE9D,EAAW+B,MAAM,CAAC,UACpB,EACA,gBAAAgC,CAAiBxF,GACfyB,EAAW2D,KAAK,SAAUpF,EAC5B,EAEA,gBAAAyF,GACE,MAAMzD,EAAUC,OAAuB,GACvCR,EAAWS,QAAQ,SAAUF,EAC/B"}
@@ -0,0 +1,120 @@
1
+ import { type BaseMembers } from '@auth0/auth0-acul-js';
2
+ /**
3
+ * Factory class that creates context hooks for accessing Auth0 Universal Login data.
4
+ * These hooks provide access to various aspects of the authentication flow and tenant configuration.
5
+ */
6
+ export declare class ContextHooks<T extends BaseMembers> {
7
+ private instance;
8
+ constructor(instance: T);
9
+ /**
10
+ * Hook to access user information and profile data.
11
+ * @returns User object containing profile information, attributes, and user-specific data
12
+ * @example
13
+ * ```jsx
14
+ * import { useUser } from '@auth0/auth0-acul-react/login-id';
15
+ * function UserProfile() {
16
+ * const user = useUser();
17
+ * }
18
+ * ```
19
+ */
20
+ useUser: () => T["user"];
21
+ /**
22
+ * Hook to access tenant configuration and settings.
23
+ * @returns Tenant object containing domain, region, and tenant-specific configuration
24
+ * @example
25
+ * ```jsx
26
+ * import { useTenant } from '@auth0/auth0-acul-react/login-id';
27
+ * function TenantInfo() {
28
+ * const tenant = useTenant();
29
+ * }
30
+ * ```
31
+ */
32
+ useTenant: () => T["tenant"];
33
+ /**
34
+ * Hook to access branding and theme configuration.
35
+ * @returns Branding object containing colors, logos, fonts, and visual customization settings
36
+ * @example
37
+ * ```jsx
38
+ * import { useBranding } from '@auth0/auth0-acul-react/login-id';
39
+ * function CustomTheme() {
40
+ * const branding = useBranding();
41
+ * }
42
+ * ```
43
+ */
44
+ useBranding: () => T["branding"];
45
+ /**
46
+ * Hook to access Auth0 application (client) configuration.
47
+ * @returns Client object containing application settings, callbacks, and client-specific data
48
+ * @example
49
+ * ```jsx
50
+ * import { useClient } from '@auth0/auth0-acul-react/login-id';
51
+ * function AppInfo() {
52
+ * const client = useClient();
53
+ * }
54
+ * ```
55
+ */
56
+ useClient: () => T["client"];
57
+ /**
58
+ * Hook to access organization context and settings.
59
+ * @returns Organization object containing org-specific data, metadata, and configuration
60
+ * @example
61
+ * ```jsx
62
+ * import { useOrganization } from '@auth0/auth0-acul-react/login-id';
63
+ * function OrgSelector() {
64
+ * const organization = useOrganization();
65
+ * if (!organization) {
66
+ * return <p>No organization context</p>;
67
+ * }
68
+ * }
69
+ * ```
70
+ */
71
+ useOrganization: () => T["organization"];
72
+ /**
73
+ * Hook to access prompt configuration and flow settings.
74
+ * @returns Prompt object containing flow configuration, screen settings, and prompt-specific data
75
+ * @example
76
+ * ```jsx
77
+ * import { usePrompt } from '@auth0/auth0-acul-react/login-id';
78
+ * function FlowInfo() {
79
+ * const prompt = usePrompt();
80
+ * }
81
+ * ```
82
+ */
83
+ usePrompt: () => T["prompt"];
84
+ /**
85
+ * Hook to access untrusted data from URL parameters and form submissions.
86
+ * @returns Object containing untrusted user input that should be validated before use
87
+ * @example
88
+ * ```jsx
89
+ * import { useUntrustedData } from '@auth0/auth0-acul-react/login-id';
90
+ * function PrefilledForm() {
91
+ * const untrustedData = useUntrustedData();
92
+ * }
93
+ * ```
94
+ */
95
+ useUntrustedData: () => T["untrustedData"];
96
+ /**
97
+ * Hook to access current screen information and metadata.
98
+ * @returns Screen object containing current screen name, configuration, and screen-specific data
99
+ * @example
100
+ * ```jsx
101
+ * import { useScreen } from '@auth0/auth0-acul-react/login-id';
102
+ * function ScreenDebug() {
103
+ * const screen = useScreen();
104
+ * }
105
+ * ```
106
+ */
107
+ useScreen: () => T["screen"];
108
+ /**
109
+ * Hook to access transaction state and authentication flow data.
110
+ * @returns Transaction object containing flow state, session data, and transaction-specific information
111
+ * @example
112
+ * ```jsx
113
+ * import { useTransaction } from '@auth0/auth0-acul-react/login-id';
114
+ * function TransactionInfo() {
115
+ * const transaction = useTransaction();
116
+ * }
117
+ * ```
118
+ */
119
+ useTransaction: () => T["transaction"];
120
+ }
@@ -0,0 +1,2 @@
1
+ class t{constructor(t){this.instance=t,this.useUser=()=>this.instance.user,this.useTenant=()=>this.instance.tenant,this.useBranding=()=>this.instance.branding,this.useClient=()=>this.instance.client,this.useOrganization=()=>this.instance.organization,this.usePrompt=()=>this.instance.prompt,this.useUntrustedData=()=>this.instance.untrustedData,this.useScreen=()=>this.instance.screen,this.useTransaction=()=>this.instance.transaction}}export{t as ContextHooks};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/hooks/context/index.tsx"],"sourcesContent":["import { type BaseMembers } from '@auth0/auth0-acul-js';\n\n/**\n * Factory class that creates context hooks for accessing Auth0 Universal Login data.\n * These hooks provide access to various aspects of the authentication flow and tenant configuration.\n */\nexport class ContextHooks<T extends BaseMembers> {\n constructor(private instance: T) {}\n\n /**\n * Hook to access user information and profile data.\n * @returns User object containing profile information, attributes, and user-specific data\n * @example\n * ```jsx\n * import { useUser } from '@auth0/auth0-acul-react/login-id';\n * function UserProfile() {\n * const user = useUser();\n * }\n * ```\n */\n useUser = () => this.instance.user as T['user'];\n\n /**\n * Hook to access tenant configuration and settings.\n * @returns Tenant object containing domain, region, and tenant-specific configuration\n * @example\n * ```jsx\n * import { useTenant } from '@auth0/auth0-acul-react/login-id';\n * function TenantInfo() {\n * const tenant = useTenant();\n * }\n * ```\n */\n useTenant = () => this.instance.tenant as T['tenant'];\n\n /**\n * Hook to access branding and theme configuration.\n * @returns Branding object containing colors, logos, fonts, and visual customization settings\n * @example\n * ```jsx\n * import { useBranding } from '@auth0/auth0-acul-react/login-id';\n * function CustomTheme() {\n * const branding = useBranding();\n * }\n * ```\n */\n useBranding = () => this.instance.branding as T['branding'];\n\n /**\n * Hook to access Auth0 application (client) configuration.\n * @returns Client object containing application settings, callbacks, and client-specific data\n * @example\n * ```jsx\n * import { useClient } from '@auth0/auth0-acul-react/login-id';\n * function AppInfo() {\n * const client = useClient();\n * }\n * ```\n */\n useClient = () => this.instance.client as T['client'];\n\n /**\n * Hook to access organization context and settings.\n * @returns Organization object containing org-specific data, metadata, and configuration\n * @example\n * ```jsx\n * import { useOrganization } from '@auth0/auth0-acul-react/login-id';\n * function OrgSelector() {\n * const organization = useOrganization();\n * if (!organization) {\n * return <p>No organization context</p>;\n * }\n * }\n * ```\n */\n useOrganization = () => this.instance.organization as T['organization'];\n\n /**\n * Hook to access prompt configuration and flow settings.\n * @returns Prompt object containing flow configuration, screen settings, and prompt-specific data\n * @example\n * ```jsx\n * import { usePrompt } from '@auth0/auth0-acul-react/login-id';\n * function FlowInfo() {\n * const prompt = usePrompt();\n * }\n * ```\n */\n usePrompt = () => this.instance.prompt as T['prompt'];\n\n /**\n * Hook to access untrusted data from URL parameters and form submissions.\n * @returns Object containing untrusted user input that should be validated before use\n * @example\n * ```jsx\n * import { useUntrustedData } from '@auth0/auth0-acul-react/login-id';\n * function PrefilledForm() {\n * const untrustedData = useUntrustedData();\n * }\n * ```\n */\n useUntrustedData = () => this.instance.untrustedData as T['untrustedData'];\n\n /**\n * Hook to access current screen information and metadata.\n * @returns Screen object containing current screen name, configuration, and screen-specific data\n * @example\n * ```jsx\n * import { useScreen } from '@auth0/auth0-acul-react/login-id';\n * function ScreenDebug() {\n * const screen = useScreen();\n * }\n * ```\n */\n useScreen = () => this.instance.screen as T['screen'];\n\n /**\n * Hook to access transaction state and authentication flow data.\n * @returns Transaction object containing flow state, session data, and transaction-specific information\n * @example\n * ```jsx\n * import { useTransaction } from '@auth0/auth0-acul-react/login-id';\n * function TransactionInfo() {\n * const transaction = useTransaction();\n * }\n * ```\n */\n useTransaction = () => this.instance.transaction as T['transaction'];\n}\n"],"names":["ContextHooks","constructor","instance","this","useUser","user","useTenant","tenant","useBranding","branding","useClient","client","useOrganization","organization","usePrompt","prompt","useUntrustedData","untrustedData","useScreen","screen","useTransaction","transaction"],"mappings":"MAMaA,EACX,WAAAC,CAAoBC,GAAAC,KAAAD,SAAAA,EAapBC,KAAAC,QAAU,IAAMD,KAAKD,SAASG,KAa9BF,KAAAG,UAAY,IAAMH,KAAKD,SAASK,OAahCJ,KAAAK,YAAc,IAAML,KAAKD,SAASO,SAalCN,KAAAO,UAAY,IAAMP,KAAKD,SAASS,OAgBhCR,KAAAS,gBAAkB,IAAMT,KAAKD,SAASW,aAatCV,KAAAW,UAAY,IAAMX,KAAKD,SAASa,OAahCZ,KAAAa,iBAAmB,IAAMb,KAAKD,SAASe,cAavCd,KAAAe,UAAY,IAAMf,KAAKD,SAASiB,OAahChB,KAAAiB,eAAiB,IAAMjB,KAAKD,SAASmB,WAxHH"}
@@ -0,0 +1,10 @@
1
+ export { useAuth0Themes } from './common/auth0-themes';
2
+ export { useCurrentScreen } from './common/current-screen';
3
+ export { errorManager, useErrors, type UseErrorOptions, type UseErrorsResult, type ErrorsResult, type ErrorKind, type ErrorItem, } from './common/errors';
4
+ export { ContextHooks } from './context';
5
+ export { useLoginIdentifiers } from './utility/login-identifiers';
6
+ export { useSignupIdentifiers } from './utility/signup-identifiers';
7
+ export { useMfaPolling, type MfaPollingResult, type ULError } from './utility/polling-manager';
8
+ export { useResend, type UseResendReturn, type UseResendOptions } from './utility/resend-manager';
9
+ export { usePasswordValidation, type PasswordValidationResult, type PasswordComplexityRule, } from './utility/validate-password';
10
+ export { useUsernameValidation, type UsernameValidationResult, type UsernameValidationError, } from './utility/validate-username';
@@ -0,0 +1,26 @@
1
+ import { IdentifierType } from '@auth0/auth0-acul-js';
2
+ /**
3
+ * Returns a list of active identifier types (such as `'email'`, `'phone'`, or `'username'`)
4
+ * currently in use in the authentication flow or login process.
5
+ *
6
+ * @supportedScreens
7
+ * - `login`
8
+ * - `login-id`
9
+ * - `reset-password-request`
10
+ *
11
+ * @returns An array of {@link IdentifierType} representing active identifiers.
12
+ *
13
+ * @example This example shows how to use the hook in a functional component on "login" screen.
14
+ * ```tsx
15
+ * import { useLoginIdentifiers } from '@auth0/auth0-acul-react/login';
16
+ *
17
+ * const loginIdentifiers = useLoginIdentifiers();
18
+ * const hasEmail = loginIdentifiers.includes('email');
19
+ * const hasPhone = loginIdentifiers.includes('phone');
20
+ * const hasUsername = loginIdentifiers.includes('username');
21
+ *
22
+ * // loginIdentifiers could be:
23
+ * // ['email', 'username']
24
+ * ```
25
+ */
26
+ export declare const useLoginIdentifiers: () => IdentifierType[];
@@ -0,0 +1,2 @@
1
+ import{getScreen as t}from"../../state/instance-store.js";const e=()=>t().getLoginIdentifiers();export{e as useLoginIdentifiers};
2
+ //# sourceMappingURL=login-identifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-identifiers.js","sources":["../../../src/hooks/utility/login-identifiers.ts"],"sourcesContent":["import { IdentifierType } from '@auth0/auth0-acul-js';\n\nimport { getScreen } from '../../state/instance-store';\n\ninterface WithLoginIdentifiers {\n getLoginIdentifiers: () => IdentifierType[];\n}\n\n/**\n * Returns a list of active identifier types (such as `'email'`, `'phone'`, or `'username'`)\n * currently in use in the authentication flow or login process.\n *\n * @supportedScreens\n * - `login`\n * - `login-id`\n * - `reset-password-request`\n *\n * @returns An array of {@link IdentifierType} representing active identifiers.\n *\n * @example This example shows how to use the hook in a functional component on \"login\" screen.\n * ```tsx\n * import { useLoginIdentifiers } from '@auth0/auth0-acul-react/login';\n *\n * const loginIdentifiers = useLoginIdentifiers();\n * const hasEmail = loginIdentifiers.includes('email');\n * const hasPhone = loginIdentifiers.includes('phone');\n * const hasUsername = loginIdentifiers.includes('username');\n *\n * // loginIdentifiers could be:\n * // ['email', 'username']\n * ```\n */\n\nexport const useLoginIdentifiers = (): IdentifierType[] => {\n const instance = getScreen<WithLoginIdentifiers>();\n return instance.getLoginIdentifiers();\n};\n"],"names":["useLoginIdentifiers","getScreen","getLoginIdentifiers"],"mappings":"0DAiCO,MAAMA,EAAsB,IAChBC,IACDC"}
@@ -0,0 +1,93 @@
1
+ import type { MfaPollingOptions, Error as ULError } from '@auth0/auth0-acul-js';
2
+ /**
3
+ * Result object returned by {@link useMfaPolling}.
4
+ *
5
+ * @public
6
+ */
7
+ export interface MfaPollingResult {
8
+ /**
9
+ * Indicates whether the MFA push polling process is currently active.
10
+ *
11
+ * - `true` — Polling is running and awaiting completion.
12
+ * - `false` — Polling has stopped, either due to completion,
13
+ * manual cancellation, or component unmount.
14
+ */
15
+ isRunning: boolean;
16
+ /**
17
+ * Starts or resumes the polling process.
18
+ *
19
+ * - If polling is already active, this call has no effect.
20
+ * - If previously stopped, calling this restarts the polling loop.
21
+ */
22
+ startPolling: () => void;
23
+ /**
24
+ * Stops the polling process immediately.
25
+ *
26
+ * - Cancels any scheduled timers or in-flight requests.
27
+ * - Safe to call multiple times; subsequent calls have no effect.
28
+ */
29
+ stopPolling: () => void;
30
+ }
31
+ /**
32
+ * React hook to manage MFA push polling (e.g., waiting for a push notification approval)
33
+ * on an Auth0 Advanced Customization of Universal Login (ACUL) screen.
34
+ *
35
+ * This hook sets up and controls a long-running polling loop that repeatedly checks
36
+ * the MFA push challenge endpoint until one of the following occurs:
37
+ *
38
+ * - The challenge is **approved or denied** by the user, triggering `options.onCompleted`.
39
+ * - An **error** occurs (network error, non-200/429 response), triggering `options.onError`.
40
+ * - The **component unmounts** or `stopPolling()` is called, which cancels polling.
41
+ *
42
+ * ### Key Features
43
+ * - `isRunning` is **reactive** — it updates automatically if the polling loop
44
+ * stops internally or is canceled.
45
+ * - Uses a **stable single polling instance** (`useRef`) to prevent
46
+ * duplicate network calls and unintended restarts during React re-renders.
47
+ * - **Automatic cleanup** on unmount: no orphan timers or leaked XHR requests.
48
+ *
49
+ * @param options - {@link MfaPollingOptions} specifying the polling interval,
50
+ * success callback (`onCompleted`), and optional error handler (`onError`).
51
+ *
52
+ *@supportedScreens
53
+ * - `mfa-push-challenge-push`
54
+ * - `reset-password-mfa-push-challenge-push`
55
+ *
56
+ * @returns object {@link MfaPollingResult} containing:
57
+ * - `isRunning` — `true` while polling is active.
58
+ * - `startPolling()` — starts or resumes polling.
59
+ * - `stopPolling()` — stops polling immediately.
60
+ *
61
+ * @example
62
+ * ```tsx
63
+ * import { useMfaPolling } from '@auth0/auth0-acul-react/mfa-push-challenge-push';
64
+ *
65
+ * export function MfaPushStatus() {
66
+ * const { isRunning, startPolling, stopPolling } = useMfaPolling({
67
+ * intervalMs: 5000,
68
+ * onCompleted: () => console.log('Push approved!/denied'),
69
+ * onError: (error) => console.error('Polling error:', error)
70
+ * });
71
+ *
72
+ * return (
73
+ * <div>
74
+ * <button onClick={startPolling} disabled={isRunning}>
75
+ * {isRunning ? 'Waiting for approval…' : 'Start MFA Polling'}
76
+ * </button>
77
+ * {isRunning && <button onClick={stopPolling}>Cancel</button>}
78
+ * </div>
79
+ * );
80
+ * }
81
+ * ```
82
+ *
83
+ * @remarks
84
+ * - The `onError` callback receives an {@link ULError} object
85
+ * with `status` and `responseText` describing the server response.
86
+ * - Internal rate-limit responses (`429`) are automatically handled:
87
+ * polling waits for the reset window before retrying.
88
+ * - Calling `startPolling()` repeatedly while running is safe and idempotent.
89
+ *
90
+ * @public
91
+ */
92
+ export declare function useMfaPolling(options?: MfaPollingOptions): MfaPollingResult;
93
+ export type { MfaPollingOptions, ULError };
@@ -0,0 +1,2 @@
1
+ import{useState as r,useMemo as n,useRef as o,useCallback as t,useEffect as e}from"react";import{getScreen as s}from"../../state/instance-store.js";import{errorManager as l}from"../common/errors.js";function i(i){const[u,c]=r(!1),m=n(()=>{const r=i??{};return{...r,onCompleted:()=>{c(!1),r.onCompleted?.()},onError:n=>{c(!1),l.pushServerErrors([n]),r.onError?.(n)}}},[i]),p=n(()=>s(),[]),a=o(null);null===a.current&&(a.current=p.pollingManager(m));const g=a.current,f=t(()=>{g.startPolling(),c(!0)},[g]),P=t(()=>{g.stopPolling(),c(!1)},[g]);return e(()=>{let r=!0;const n=()=>{if(!r)return;const o=g.isRunning();c(o),o&&requestAnimationFrame(n)};return n(),()=>{r=!1,g.stopPolling()}},[g]),{isRunning:u,startPolling:f,stopPolling:P}}export{i as useMfaPolling};
2
+ //# sourceMappingURL=polling-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polling-manager.js","sources":["../../../src/hooks/utility/polling-manager.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { getScreen } from '../../state/instance-store';\nimport { errorManager } from '../common/errors';\n\nimport type {\n MfaPollingOptions,\n MfaPushPollingControl,\n Error as ULError,\n} from '@auth0/auth0-acul-js';\n\n/**\n * Result object returned by {@link useMfaPolling}.\n *\n * @public\n */\nexport interface MfaPollingResult {\n /**\n * Indicates whether the MFA push polling process is currently active.\n *\n * - `true` — Polling is running and awaiting completion.\n * - `false` — Polling has stopped, either due to completion,\n * manual cancellation, or component unmount.\n */\n isRunning: boolean;\n\n /**\n * Starts or resumes the polling process.\n *\n * - If polling is already active, this call has no effect.\n * - If previously stopped, calling this restarts the polling loop.\n */\n startPolling: () => void;\n\n /**\n * Stops the polling process immediately.\n *\n * - Cancels any scheduled timers or in-flight requests.\n * - Safe to call multiple times; subsequent calls have no effect.\n */\n stopPolling: () => void;\n}\n\n/**\n * React hook to manage MFA push polling (e.g., waiting for a push notification approval)\n * on an Auth0 Advanced Customization of Universal Login (ACUL) screen.\n *\n * This hook sets up and controls a long-running polling loop that repeatedly checks\n * the MFA push challenge endpoint until one of the following occurs:\n *\n * - The challenge is **approved or denied** by the user, triggering `options.onCompleted`.\n * - An **error** occurs (network error, non-200/429 response), triggering `options.onError`.\n * - The **component unmounts** or `stopPolling()` is called, which cancels polling.\n *\n * ### Key Features\n * - `isRunning` is **reactive** — it updates automatically if the polling loop\n * stops internally or is canceled.\n * - Uses a **stable single polling instance** (`useRef`) to prevent\n * duplicate network calls and unintended restarts during React re-renders.\n * - **Automatic cleanup** on unmount: no orphan timers or leaked XHR requests.\n *\n * @param options - {@link MfaPollingOptions} specifying the polling interval,\n * success callback (`onCompleted`), and optional error handler (`onError`).\n *\n *@supportedScreens\n * - `mfa-push-challenge-push`\n * - `reset-password-mfa-push-challenge-push`\n *\n * @returns object {@link MfaPollingResult} containing:\n * - `isRunning` — `true` while polling is active.\n * - `startPolling()` — starts or resumes polling.\n * - `stopPolling()` — stops polling immediately.\n *\n * @example\n * ```tsx\n * import { useMfaPolling } from '@auth0/auth0-acul-react/mfa-push-challenge-push';\n *\n * export function MfaPushStatus() {\n * const { isRunning, startPolling, stopPolling } = useMfaPolling({\n * intervalMs: 5000,\n * onCompleted: () => console.log('Push approved!/denied'),\n * onError: (error) => console.error('Polling error:', error)\n * });\n *\n * return (\n * <div>\n * <button onClick={startPolling} disabled={isRunning}>\n * {isRunning ? 'Waiting for approval…' : 'Start MFA Polling'}\n * </button>\n * {isRunning && <button onClick={stopPolling}>Cancel</button>}\n * </div>\n * );\n * }\n * ```\n *\n * @remarks\n * - The `onError` callback receives an {@link ULError} object\n * with `status` and `responseText` describing the server response.\n * - Internal rate-limit responses (`429`) are automatically handled:\n * polling waits for the reset window before retrying.\n * - Calling `startPolling()` repeatedly while running is safe and idempotent.\n *\n * @public\n */\nexport function useMfaPolling(options?: MfaPollingOptions): MfaPollingResult {\n const [isRunning, setIsRunning] = useState(false);\n\n // Wrap callbacks safely to immediately update `isRunning` on completion/error.\n const wrappedOptions: MfaPollingOptions = useMemo(() => {\n const safe = options ?? {};\n return {\n ...safe,\n onCompleted: () => {\n setIsRunning(false);\n safe.onCompleted?.();\n },\n onError: (error: ULError) => {\n setIsRunning(false);\n errorManager.pushServerErrors([error]);\n safe.onError?.(error);\n },\n };\n }, [options]);\n\n // Stable screen instance\n const screen = useMemo(\n () => getScreen<{ pollingManager: (o: MfaPollingOptions) => MfaPushPollingControl }>(),\n []\n );\n\n // Single polling control instance per component\n const pollingControlRef = useRef<MfaPushPollingControl | null>(null);\n if (pollingControlRef.current === null) {\n pollingControlRef.current = screen.pollingManager(wrappedOptions);\n }\n const pollingControl = pollingControlRef.current;\n\n const startPolling = useCallback(() => {\n pollingControl.startPolling();\n setIsRunning(true);\n }, [pollingControl]);\n\n const stopPolling = useCallback(() => {\n pollingControl.stopPolling();\n setIsRunning(false);\n }, [pollingControl]);\n\n // One effect handles cleanup and state sync\n useEffect(() => {\n let mounted = true;\n\n const tick = () => {\n if (!mounted) {\n return;\n }\n const running = pollingControl.isRunning();\n setIsRunning(running);\n if (running) {\n requestAnimationFrame(tick);\n }\n };\n tick();\n\n return () => {\n mounted = false;\n pollingControl.stopPolling();\n };\n }, [pollingControl]);\n\n return { isRunning, startPolling, stopPolling };\n}\n\nexport type { MfaPollingOptions, ULError };\n"],"names":["useMfaPolling","options","isRunning","setIsRunning","useState","wrappedOptions","useMemo","safe","onCompleted","onError","error","errorManager","pushServerErrors","screen","getScreen","pollingControlRef","useRef","current","pollingManager","pollingControl","startPolling","useCallback","stopPolling","useEffect","mounted","tick","running","requestAnimationFrame"],"mappings":"uMAwGM,SAAUA,EAAcC,GAC5B,MAAOC,EAAWC,GAAgBC,GAAS,GAGrCC,EAAoCC,EAAQ,KAChD,MAAMC,EAAON,GAAW,CAAA,EACxB,MAAO,IACFM,EACHC,YAAa,KACXL,GAAa,GACbI,EAAKC,iBAEPC,QAAUC,IACRP,GAAa,GACbQ,EAAaC,iBAAiB,CAACF,IAC/BH,EAAKE,UAAUC,MAGlB,CAACT,IAGEY,EAASP,EACb,IAAMQ,IACN,IAIIC,EAAoBC,EAAqC,MAC7B,OAA9BD,EAAkBE,UACpBF,EAAkBE,QAAUJ,EAAOK,eAAeb,IAEpD,MAAMc,EAAiBJ,EAAkBE,QAEnCG,EAAeC,EAAY,KAC/BF,EAAeC,eACfjB,GAAa,IACZ,CAACgB,IAEEG,EAAcD,EAAY,KAC9BF,EAAeG,cACfnB,GAAa,IACZ,CAACgB,IAwBJ,OArBAI,EAAU,KACR,IAAIC,GAAU,EAEd,MAAMC,EAAO,KACX,IAAKD,EACH,OAEF,MAAME,EAAUP,EAAejB,YAC/BC,EAAauB,GACTA,GACFC,sBAAsBF,IAK1B,OAFAA,IAEO,KACLD,GAAU,EACVL,EAAeG,gBAEhB,CAACH,IAEG,CAAEjB,YAAWkB,eAAcE,cACpC"}
@@ -0,0 +1,74 @@
1
+ /** Return type for {@link useResend}. */
2
+ export interface UseResendReturn {
3
+ /** Seconds remaining until the next resend attempt is allowed. */
4
+ remaining: number;
5
+ /** Whether the resend action is currently disabled. */
6
+ disabled: boolean;
7
+ /** Start a resend attempt immediately, if allowed. */
8
+ startResend: () => void;
9
+ }
10
+ /** Optional configuration for {@link useResend}. */
11
+ export interface UseResendOptions {
12
+ /**
13
+ * Countdown duration (in seconds) before another resend is allowed.
14
+ * Defaults to `10`.
15
+ */
16
+ timeoutSeconds?: number;
17
+ /**
18
+ * Callback fired when the countdown finishes and the resend
19
+ * action becomes available again.
20
+ */
21
+ onTimeout?: () => void;
22
+ }
23
+ /**
24
+ * This React hook manages "resend" actions (e.g., resending a verification code) on ACUL screens.
25
+ *
26
+ * This hook:
27
+ * - Tracks the remaining cooldown time.
28
+ * - Tells you whether the resend button should be disabled.
29
+ * - Provides a `startResend` function to trigger a resend immediately.
30
+ *
31
+ * @supportedScreens
32
+ * - `email-identifier-challenge`
33
+ * - `email-otp-challenge`
34
+ * - `login-email-verification`
35
+ * - `login-passwordless-email-code`
36
+ * - `login-passwordless-sms-otp`
37
+ * - `mfa-email-challenge`
38
+ * - `mfa-sms-challenge`
39
+ * - `mfa-voice-challenge`
40
+ * - `phone-identifier-challenge`
41
+ * - `reset-password-mfa-email-challenge`
42
+ * - `reset-password-mfa-sms-challenge`
43
+ * - `reset-password-mfa-voice-challenge`
44
+ *
45
+ * @param options - Optional configuration such as `timeoutSeconds` and `onTimeout`.
46
+ *
47
+ * @returns An object with:
48
+ * - `remaining` — seconds left until the next resend is permitted.
49
+ * - `disabled` — `true` if resending is currently blocked.
50
+ * - `startResend` — call to initiate a resend immediately (if allowed).
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * import { useResend } from '@auth0/auth0-acul-react/mfa-sms-challenge';
55
+ *
56
+ * export function ResendButton() {
57
+ * const { remaining, disabled, startResend } = useResend({
58
+ * timeoutSeconds: 30,
59
+ * onTimeout: () => console.log('You can resend again'),
60
+ * });
61
+ *
62
+ * return (
63
+ * <button onClick={startResend} disabled={disabled}>
64
+ * {disabled ? `Resend in ${remaining}s` : 'Resend Code'}
65
+ * </button>
66
+ * );
67
+ * }
68
+ * ```
69
+ *
70
+ * @remarks
71
+ * - The underlying `ResendControl` has no explicit teardown method; the hook does not require manual cleanup.
72
+ * - The hook re-initializes the resend manager if `timeoutSeconds` or `onTimeout` change.
73
+ */
74
+ export declare function useResend(options?: UseResendOptions): UseResendReturn;
@@ -0,0 +1,2 @@
1
+ import{useMemo as t,useState as e,useRef as n,useCallback as r,useEffect as o}from"react";import{getScreen as s}from"../../state/instance-store.js";function a(a){const{timeoutSeconds:i=10,onTimeout:u}=a??{},m=t(()=>s(),[]),[c,d]=e(0),[f,g]=e(!1),l=n(null),p=r((t,e)=>{d(t),g(e)},[]);o(()=>{l.current=m.resendManager({timeoutSeconds:i,onStatusChange:p,...u&&{onTimeout:u}})},[m,i,p,u]);return{remaining:c,disabled:f,startResend:r(()=>{l.current?.startResend()},[])}}export{a as useResend};
2
+ //# sourceMappingURL=resend-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resend-manager.js","sources":["../../../src/hooks/utility/resend-manager.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { getScreen } from '../../state/instance-store';\n\nimport type { StartResendOptions, ResendControl } from '@auth0/auth0-acul-js';\n\n/** Return type for {@link useResend}. */\nexport interface UseResendReturn {\n /** Seconds remaining until the next resend attempt is allowed. */\n remaining: number;\n /** Whether the resend action is currently disabled. */\n disabled: boolean;\n /** Start a resend attempt immediately, if allowed. */\n startResend: () => void;\n}\n\n/** Optional configuration for {@link useResend}. */\nexport interface UseResendOptions {\n /**\n * Countdown duration (in seconds) before another resend is allowed.\n * Defaults to `10`.\n */\n timeoutSeconds?: number;\n /**\n * Callback fired when the countdown finishes and the resend\n * action becomes available again.\n */\n onTimeout?: () => void;\n}\n\n/** Screens that support resend operations expose a `resendManager` method. */\ninterface WithResendManager {\n resendManager(options?: StartResendOptions): ResendControl;\n}\n\n/**\n * This React hook manages \"resend\" actions (e.g., resending a verification code) on ACUL screens.\n *\n * This hook:\n * - Tracks the remaining cooldown time.\n * - Tells you whether the resend button should be disabled.\n * - Provides a `startResend` function to trigger a resend immediately.\n *\n * @supportedScreens\n * - `email-identifier-challenge`\n * - `email-otp-challenge`\n * - `login-email-verification`\n * - `login-passwordless-email-code`\n * - `login-passwordless-sms-otp`\n * - `mfa-email-challenge`\n * - `mfa-sms-challenge`\n * - `mfa-voice-challenge`\n * - `phone-identifier-challenge`\n * - `reset-password-mfa-email-challenge`\n * - `reset-password-mfa-sms-challenge`\n * - `reset-password-mfa-voice-challenge`\n *\n * @param options - Optional configuration such as `timeoutSeconds` and `onTimeout`.\n *\n * @returns An object with:\n * - `remaining` — seconds left until the next resend is permitted.\n * - `disabled` — `true` if resending is currently blocked.\n * - `startResend` — call to initiate a resend immediately (if allowed).\n *\n * @example\n * ```tsx\n * import { useResend } from '@auth0/auth0-acul-react/mfa-sms-challenge';\n *\n * export function ResendButton() {\n * const { remaining, disabled, startResend } = useResend({\n * timeoutSeconds: 30,\n * onTimeout: () => console.log('You can resend again'),\n * });\n *\n * return (\n * <button onClick={startResend} disabled={disabled}>\n * {disabled ? `Resend in ${remaining}s` : 'Resend Code'}\n * </button>\n * );\n * }\n * ```\n *\n * @remarks\n * - The underlying `ResendControl` has no explicit teardown method; the hook does not require manual cleanup.\n * - The hook re-initializes the resend manager if `timeoutSeconds` or `onTimeout` change.\n */\nexport function useResend(options?: UseResendOptions): UseResendReturn {\n const { timeoutSeconds = 10, onTimeout } = options ?? {};\n const screen = useMemo(() => getScreen<WithResendManager>(), []);\n\n const [remaining, setRemaining] = useState(0);\n const [disabled, setDisabled] = useState(false);\n const controlRef = useRef<ResendControl | null>(null);\n\n // Update state whenever the manager reports a change\n const handleStatusChange = useCallback((secs: number, isDisabled: boolean) => {\n setRemaining(secs);\n setDisabled(isDisabled);\n }, []);\n\n // Initialize the resend manager; re-run if options that affect its behavior change\n useEffect(() => {\n controlRef.current = screen.resendManager({\n timeoutSeconds,\n onStatusChange: handleStatusChange,\n ...(onTimeout && { onTimeout }),\n });\n }, [screen, timeoutSeconds, handleStatusChange, onTimeout]);\n\n const startResend = useCallback(() => {\n controlRef.current?.startResend();\n }, []);\n\n return { remaining, disabled, startResend };\n}\n"],"names":["useResend","options","timeoutSeconds","onTimeout","screen","useMemo","getScreen","remaining","setRemaining","useState","disabled","setDisabled","controlRef","useRef","handleStatusChange","useCallback","secs","isDisabled","useEffect","current","resendManager","onStatusChange","startResend"],"mappings":"oJAsFM,SAAUA,EAAUC,GACxB,MAAMC,eAAEA,EAAiB,GAAEC,UAAEA,GAAcF,GAAW,CAAA,EAChDG,EAASC,EAAQ,IAAMC,IAAgC,KAEtDC,EAAWC,GAAgBC,EAAS,IACpCC,EAAUC,GAAeF,GAAS,GACnCG,EAAaC,EAA6B,MAG1CC,EAAqBC,EAAY,CAACC,EAAcC,KACpDT,EAAaQ,GACbL,EAAYM,IACX,IAGHC,EAAU,KACRN,EAAWO,QAAUf,EAAOgB,cAAc,CACxClB,iBACAmB,eAAgBP,KACZX,GAAa,CAAEA,gBAEpB,CAACC,EAAQF,EAAgBY,EAAoBX,IAMhD,MAAO,CAAEI,YAAWG,WAAUY,YAJVP,EAAY,KAC9BH,EAAWO,SAASG,eACnB,IAGL"}