@thunderid/react 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/{getScim2Me.d.ts → getUsersMe.d.ts} +11 -11
- package/dist/api/{getScim2Me.d.ts.map → getUsersMe.d.ts.map} +1 -1
- package/dist/api/{getScim2Me.js → getUsersMe.js} +12 -12
- package/dist/api/{getScim2Me.js.map → getUsersMe.js.map} +1 -1
- package/dist/api/updateMeProfile.d.ts +5 -5
- package/dist/api/updateMeProfile.js +6 -6
- package/dist/api/updateMeProfile.js.map +1 -1
- package/dist/cjs/api/{getScim2Me.cjs → getUsersMe.cjs} +11 -11
- package/dist/cjs/api/{getScim2Me.cjs.map → getUsersMe.cjs.map} +1 -1
- package/dist/cjs/api/updateMeProfile.cjs +6 -6
- package/dist/cjs/api/updateMeProfile.cjs.map +1 -1
- package/dist/cjs/components/presentation/UserProfile/BaseUserProfile.cjs +48 -58
- package/dist/cjs/components/presentation/UserProfile/BaseUserProfile.cjs.map +1 -1
- package/dist/cjs/components/presentation/UserProfile/UserProfile.cjs +21 -8
- package/dist/cjs/components/presentation/UserProfile/UserProfile.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/AcceptInvite/BaseAcceptInvite.cjs +9 -1
- package/dist/cjs/components/presentation/auth/AcceptInvite/BaseAcceptInvite.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs +52 -9
- package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/InviteUser/BaseInviteUser.cjs +11 -1
- package/dist/cjs/components/presentation/auth/InviteUser/BaseInviteUser.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/Recovery/BaseRecovery.cjs +18 -14
- package/dist/cjs/components/presentation/auth/Recovery/BaseRecovery.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs +35 -9
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs +18 -13
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs.map +1 -1
- package/dist/cjs/components/primitives/AffixedField/AffixedField.cjs +88 -0
- package/dist/cjs/components/primitives/AffixedField/AffixedField.cjs.map +1 -0
- package/dist/cjs/components/primitives/AffixedField/AffixedField.styles.cjs +130 -0
- package/dist/cjs/components/primitives/AffixedField/AffixedField.styles.cjs.map +1 -0
- package/dist/cjs/contexts/ComponentRenderer/ComponentRendererContext.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs +1 -0
- package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +23 -7
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
- package/dist/cjs/contexts/User/UserContext.cjs +0 -1
- package/dist/cjs/contexts/User/UserContext.cjs.map +1 -1
- package/dist/cjs/contexts/User/UserProvider.cjs +0 -2
- package/dist/cjs/contexts/User/UserProvider.cjs.map +1 -1
- package/dist/cjs/contexts/User/useUser.cjs +0 -1
- package/dist/cjs/contexts/User/useUser.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -2
- package/dist/cjs/utils/composeAffixedInputs.cjs +74 -0
- package/dist/cjs/utils/composeAffixedInputs.cjs.map +1 -0
- package/dist/components/presentation/UserProfile/BaseUserProfile.d.ts +0 -20
- package/dist/components/presentation/UserProfile/BaseUserProfile.d.ts.map +1 -1
- package/dist/components/presentation/UserProfile/BaseUserProfile.js +50 -60
- package/dist/components/presentation/UserProfile/BaseUserProfile.js.map +1 -1
- package/dist/components/presentation/UserProfile/UserProfile.d.ts +1 -1
- package/dist/components/presentation/UserProfile/UserProfile.d.ts.map +1 -1
- package/dist/components/presentation/UserProfile/UserProfile.js +22 -9
- package/dist/components/presentation/UserProfile/UserProfile.js.map +1 -1
- package/dist/components/presentation/auth/AcceptInvite/BaseAcceptInvite.d.ts.map +1 -1
- package/dist/components/presentation/auth/AcceptInvite/BaseAcceptInvite.js +9 -1
- package/dist/components/presentation/auth/AcceptInvite/BaseAcceptInvite.js.map +1 -1
- package/dist/components/presentation/auth/AuthOptionFactory.d.ts +12 -4
- package/dist/components/presentation/auth/AuthOptionFactory.d.ts.map +1 -1
- package/dist/components/presentation/auth/AuthOptionFactory.js +52 -9
- package/dist/components/presentation/auth/AuthOptionFactory.js.map +1 -1
- package/dist/components/presentation/auth/InviteUser/BaseInviteUser.d.ts.map +1 -1
- package/dist/components/presentation/auth/InviteUser/BaseInviteUser.js +11 -1
- package/dist/components/presentation/auth/InviteUser/BaseInviteUser.js.map +1 -1
- package/dist/components/presentation/auth/Recovery/BaseRecovery.d.ts.map +1 -1
- package/dist/components/presentation/auth/Recovery/BaseRecovery.js +19 -15
- package/dist/components/presentation/auth/Recovery/BaseRecovery.js.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js +37 -11
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js +18 -13
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js.map +1 -1
- package/dist/components/primitives/AffixedField/AffixedField.d.ts +52 -0
- package/dist/components/primitives/AffixedField/AffixedField.d.ts.map +1 -0
- package/dist/components/primitives/AffixedField/AffixedField.js +83 -0
- package/dist/components/primitives/AffixedField/AffixedField.js.map +1 -0
- package/dist/components/primitives/AffixedField/AffixedField.styles.d.ts +25 -0
- package/dist/components/primitives/AffixedField/AffixedField.styles.d.ts.map +1 -0
- package/dist/components/primitives/AffixedField/AffixedField.styles.js +127 -0
- package/dist/components/primitives/AffixedField/AffixedField.styles.js.map +1 -0
- package/dist/components/primitives/AffixedField/index.d.ts +20 -0
- package/dist/components/primitives/AffixedField/index.d.ts.map +1 -0
- package/dist/components/primitives/Dialog/Dialog.js +3 -3
- package/dist/components/primitives/Dialog/Dialog.js.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts +1 -0
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts +1 -0
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.js +1 -0
- package/dist/contexts/ThunderID/ThunderIDContext.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.js +23 -7
- package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
- package/dist/contexts/User/UserContext.d.ts +1 -2
- package/dist/contexts/User/UserContext.d.ts.map +1 -1
- package/dist/contexts/User/UserContext.js +0 -1
- package/dist/contexts/User/UserContext.js.map +1 -1
- package/dist/contexts/User/UserProvider.d.ts +0 -1
- package/dist/contexts/User/UserProvider.d.ts.map +1 -1
- package/dist/contexts/User/UserProvider.js +0 -2
- package/dist/contexts/User/UserProvider.js.map +1 -1
- package/dist/contexts/User/useUser.d.ts +0 -1
- package/dist/contexts/User/useUser.d.ts.map +1 -1
- package/dist/contexts/User/useUser.js +0 -1
- package/dist/contexts/User/useUser.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/utils/composeAffixedInputs.d.ts +52 -0
- package/dist/utils/composeAffixedInputs.d.ts.map +1 -0
- package/dist/utils/composeAffixedInputs.js +70 -0
- package/dist/utils/composeAffixedInputs.js.map +1 -0
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseInviteUser.js","names":["BaseInviteUser: FC<BaseInviteUserProps>","useThunderID","useTranslation","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","styles: any","useStyles","challengeTokenRef: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","initializationAttemptedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","normalizeFlowResponseLocal: any","components","handleInputChange: any","newErrors: any","handleInputBlur: any","validateForm: any","value: any","handleSubmit: any","validation: any","inputs: any","payload: Record<string, any>","response: any","resetFlow: any","components: any","extractHeadings: any","title: string | undefined","subtitle: string | undefined","title","subtitle","filterHeadings: any","renderComponents: any","componentsWithoutHeadings: any","renderProps: BaseInviteUserRenderProps","CardPrimitive","Spinner","AlertPrimitive","Typography"],"sources":["../../../../../src/components/presentation/auth/InviteUser/BaseInviteUser.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {cx} from '@emotion/css';\nimport {\n EmbeddedFlowType,\n FieldError,\n FlowExecutionError,\n FlowMetadataResponse,\n buildValidatorFromRules,\n logger,\n OrganizationUnitListResponse,\n Preferences,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport useStyles from './BaseInviteUser.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderInviteUserComponents} from '../AuthOptionFactory';\n\n/**\n * Flow response structure from the backend.\n */\nexport interface InviteUserFlowResponse {\n challengeToken?: string;\n data?: {\n additionalData?: Record<string, any>;\n components?: any[];\n fieldErrors?: FieldError[];\n meta?: {\n components?: any[];\n };\n };\n error?: FlowExecutionError;\n executionId: string;\n flowStatus: 'INCOMPLETE' | 'COMPLETE' | 'ERROR';\n type?: 'VIEW' | 'REDIRECTION';\n}\n\n/**\n * Render props for custom UI rendering of InviteUser.\n */\nexport interface BaseInviteUserRenderProps {\n /**\n * Additional data from the current flow response (e.g. rootOuId, inviteLink).\n */\n additionalData?: Record<string, any>;\n\n /**\n * Flow components from the current step.\n */\n components: any[];\n\n /**\n * API error (if any).\n */\n error?: Error | null;\n\n /**\n * Current flow execution ID.\n */\n executionId?: string;\n\n /**\n * Field validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Current flow execution ID.\n */\n flowExecId?: string;\n\n /**\n * Function to handle input blur.\n */\n handleInputBlur: (name: string) => void;\n\n /**\n * Function to handle input changes.\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission.\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state.\n */\n isLoading: boolean;\n\n /**\n * Whether the form is valid.\n */\n isValid: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Reset the flow to invite another user.\n */\n resetFlow: () => void;\n\n /**\n * Subtitle for the current step.\n */\n subtitle?: string;\n\n /**\n * Title for the current step.\n */\n title?: string;\n\n /**\n * Touched fields.\n */\n touched: Record<string, boolean>;\n\n /**\n * Form values for the current step.\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseInviteUser component.\n */\nexport interface BaseInviteUserProps {\n /**\n * Render props function for custom UI.\n * If not provided, default UI will be rendered.\n */\n children?: (props: BaseInviteUserRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name.\n */\n className?: string;\n\n /**\n * Function to fetch child organization units.\n * When provided, enables the OU tree picker for OU_SELECT components.\n */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n\n /**\n * Whether the SDK is initialized.\n */\n isInitialized?: boolean;\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when the flow state changes.\n */\n onFlowChange?: (response: InviteUserFlowResponse) => void;\n\n /**\n * Function to initialize the invite user flow.\n * This should make an authenticated request to the flow/execute endpoint.\n */\n onInitialize: (payload: Record<string, any>) => Promise<InviteUserFlowResponse>;\n\n /**\n * Function to submit flow step data.\n * This should make an authenticated request to the flow/execute endpoint.\n */\n onSubmit: (payload: Record<string, any>) => Promise<InviteUserFlowResponse>;\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 * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Base component for invite user flow.\n * Handles the flow logic for creating a user and generating an invite link.\n *\n * When no children are provided, renders a default UI with:\n * - Loading spinner during initialization\n * - Error alerts for failures\n * - Flow components (user type selection, user details form)\n * - Invite link display with copy functionality\n *\n * Flow steps handled:\n * 1. User type selection (if multiple types available)\n * 2. User details input (username, email)\n * 3. Invite link generation\n */\nconst BaseInviteUser: FC<BaseInviteUserProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n className = '',\n children,\n fetchOrganizationUnitChildren,\n isInitialized = true,\n preferences,\n size = 'medium',\n variant = 'outlined',\n showTitle = true,\n showSubtitle = true,\n}: BaseInviteUserProps): ReactElement => {\n const {meta, isInitialized: isSdkInitialized, getStorageManager} = useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<InviteUserFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [formValues, setFormValues] = useState<Record<string, string>>({});\n const [formErrors, setFormErrors] = useState<Record<string, string>>({});\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({});\n const [isFormValid, setIsFormValid] = useState(true);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n /**\n * Project server-side validation errors from the most recent flow response into the\n * local formErrors state so they render alongside client-side errors. First error\n * per field wins, matching the SDK's single-string-per-field render-prop shape.\n */\n useEffect(() => {\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setFormErrors(errors);\n setTouchedFields((prev: Record<string, boolean>) => ({...prev, ...touched}));\n }, [currentFlow]);\n\n const initializationAttemptedRef: any = useRef(false);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n */\n useEffect(() => {\n if (!isSdkInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } catch {\n // StorageManager unavailable — continue without persisted token\n }\n })();\n }, [isSdkInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages.\n * Uses the transformer's extractErrorMessage function for consistency.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t, 'components.inviteUser.errors.generic');\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Call the onError callback if provided\n onError?.(error instanceof Error ? error : new Error(errorMessage));\n },\n [t, onError],\n );\n\n /**\n * Normalize flow response to ensure component-driven format.\n * Transforms data.meta.components to data.components.\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: InviteUserFlowResponse): InviteUserFlowResponse => {\n if (!response?.data?.meta?.components) {\n return response;\n }\n\n try {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.inviteUser.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...response.data,\n components: components as any,\n },\n };\n } catch {\n // If transformer throws (e.g., error response), return as-is\n return response;\n }\n },\n [t, children],\n );\n\n /**\n * Handle input value changes.\n */\n const handleInputChange: any = useCallback((name: string, value: string) => {\n setFormValues((prev: any) => ({...prev, [name]: value}));\n // Clear error when user starts typing\n setFormErrors((prev: any) => {\n const newErrors: any = {...prev};\n delete newErrors[name];\n return newErrors;\n });\n }, []);\n\n /**\n * Handle input blur.\n */\n const handleInputBlur: any = useCallback((name: string) => {\n setTouchedFields((prev: any) => ({...prev, [name]: true}));\n }, []);\n\n /**\n * Validate required fields based on components.\n */\n const validateForm: any = useCallback(\n (components: any[]): {errors: Record<string, string>; isValid: boolean} => {\n const errors: Record<string, string> = {};\n\n const validateComponents = (comps: any[]): any => {\n comps.forEach((comp: any) => {\n if (\n (comp.type === 'TEXT_INPUT' ||\n comp.type === 'EMAIL_INPUT' ||\n comp.type === 'SELECT' ||\n comp.type === 'PHONE_INPUT' ||\n comp.type === 'OTP_INPUT' ||\n comp.type === 'DATE_INPUT') &&\n comp.ref\n ) {\n const value: any = formValues[comp.ref];\n if (comp.required && (!value || value.trim() === '')) {\n errors[comp.ref] = `${comp.label || comp.ref} is required`;\n } else {\n // Email validation\n if (comp.type === 'EMAIL_INPUT' && value && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n errors[comp.ref] = 'Please enter a valid email address';\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (value && !errors[comp.ref]) {\n const ruleValidator = buildValidatorFromRules(comp.validation);\n if (ruleValidator) {\n const message = ruleValidator(value);\n if (message) {\n errors[comp.ref] = t(message);\n }\n }\n }\n }\n }\n if (comp.components && Array.isArray(comp.components)) {\n validateComponents(comp.components);\n }\n });\n };\n\n validateComponents(components);\n\n return {errors, isValid: Object.keys(errors).length === 0};\n },\n [formValues],\n );\n\n /**\n * Handle form submission.\n */\n const handleSubmit: any = useCallback(\n async (component: any, data?: Record<string, any>) => {\n if (!currentFlow) {\n return;\n }\n\n // Validate form before submission\n const components: any = currentFlow.data?.components || [];\n const validation: any = validateForm(components);\n\n if (!validation.isValid) {\n setFormErrors(validation.errors);\n setIsFormValid(false);\n // Mark all fields as touched\n const touched: Record<string, boolean> = {};\n Object.keys(validation.errors).forEach((key: any) => {\n touched[key] = true;\n });\n setTouchedFields((prev: any) => ({...prev, ...touched}));\n return;\n }\n\n setIsLoading(true);\n setApiError(null);\n setIsFormValid(true);\n\n try {\n // Build payload with form values\n const inputs: any = data || formValues;\n\n const payload: Record<string, any> = {\n executionId: currentFlow.executionId,\n inputs,\n verbose: true,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n // Add action ID if component has one\n if (component?.id) {\n payload['action'] = component.id;\n }\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Check for error status\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n return;\n }\n\n // Update current flow and reset form for next step\n setCurrentFlow(response);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n },\n [currentFlow, formValues, validateForm, onSubmit, onFlowChange, handleError, normalizeFlowResponseLocal],\n );\n\n /**\n * Reset the flow to invite another user.\n */\n const resetFlow: any = useCallback(() => {\n setIsFlowInitialized(false);\n setCurrentFlow(null);\n setApiError(null);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n initializationAttemptedRef.current = false;\n }, []);\n\n /**\n * Initialize the flow on component mount.\n */\n useEffect(() => {\n if (isInitialized && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n\n try {\n const payload: any = {\n flowType: EmbeddedFlowType.UserOnboarding,\n verbose: true,\n };\n\n const rawResponse: any = await onInitialize(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n await setChallengeToken(response.challengeToken ?? null);\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n // Check for immediate error\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [isInitialized, isFlowInitialized, onInitialize, onFlowChange, handleError, normalizeFlowResponseLocal]);\n\n /**\n * Recalculate form validity whenever form values or components change.\n * This ensures the submit button is enabled/disabled correctly as the user types.\n */\n useEffect(() => {\n if (currentFlow && isFlowInitialized) {\n const components: any = currentFlow.data?.components || [];\n if (components.length > 0) {\n const validation: any = validateForm(components);\n setIsFormValid(validation.isValid);\n }\n }\n }, [formValues, currentFlow, isFlowInitialized, validateForm]);\n\n /**\n * Extract title and subtitle from components.\n */\n const extractHeadings: any = useCallback((components: any[]): {subtitle?: string; title?: string} => {\n let title: string | undefined;\n let subtitle: string | undefined;\n\n components.forEach((comp: any) => {\n if (comp.type === 'TEXT') {\n if (comp.variant === 'HEADING_1' && !title) {\n title = comp.label;\n } else if ((comp.variant === 'HEADING_2' || comp.variant === 'SUBTITLE_1') && !subtitle) {\n subtitle = comp.label;\n }\n }\n });\n\n return {subtitle, title};\n }, []);\n\n /**\n * Filter out heading components for default rendering.\n */\n const filterHeadings: any = useCallback(\n (components: any[]): any[] =>\n components.filter(\n (comp: any) => !(comp.type === 'TEXT' && (comp.variant === 'HEADING_1' || comp.variant === 'HEADING_2')),\n ),\n [],\n );\n\n /**\n * Render form components using the factory.\n */\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderInviteUserComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData: currentFlow?.data?.additionalData,\n fetchOrganizationUnitChildren,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n },\n ),\n [\n customRenderers,\n currentFlow?.data?.additionalData,\n fetchOrganizationUnitChildren,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n handleInputChange,\n handleInputBlur,\n handleSubmit,\n size,\n theme,\n variant,\n ],\n );\n\n // Get components from normalized response, with fallback to meta.components\n const components: any = currentFlow?.data?.components || currentFlow?.data?.meta?.components || [];\n const {title, subtitle} = extractHeadings(components);\n const componentsWithoutHeadings: any = filterHeadings(components);\n\n // Render props\n const renderProps: BaseInviteUserRenderProps = {\n additionalData: currentFlow?.data?.additionalData,\n components,\n error: apiError,\n executionId: currentFlow?.executionId,\n fieldErrors: formErrors,\n handleInputBlur,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n meta,\n resetFlow,\n subtitle,\n title,\n touched: touchedFields,\n values: formValues,\n };\n\n // If children render prop is provided, use it for custom UI\n if (children) {\n return <div className={className}>{children(renderProps)}</div>;\n }\n\n // Default rendering\n\n // Waiting for SDK initialization\n if (!isInitialized) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Loading state during initialization\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Error state during initialization\n if (!currentFlow && apiError) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Title>Error</AlertPrimitive.Title>\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Flow components\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (title || subtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && title && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && subtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {apiError && (\n <div style={{marginBottom: '1rem'}}>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n <div>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0\n ? renderComponents(componentsWithoutHeadings)\n : !isLoading && (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">No form components available</Typography>\n </AlertPrimitive>\n )}\n {isLoading && (\n <div style={{display: 'flex', justifyContent: 'center', padding: '1rem'}}>\n <Spinner size=\"small\" />\n </div>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\nexport default BaseInviteUser;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseInviteUser.js","names":["BaseInviteUser: FC<BaseInviteUserProps>","useThunderID","useTranslation","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","styles: any","useStyles","challengeTokenRef: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","initializationAttemptedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","normalizeFlowResponseLocal: any","components","handleInputChange: any","newErrors: any","handleInputBlur: any","validateForm: any","value: any","handleSubmit: any","validation: any","inputs: any","payload: Record<string, any>","response: any","resetFlow: any","components: any","extractHeadings: any","title: string | undefined","subtitle: string | undefined","title","subtitle","filterHeadings: any","renderComponents: any","componentsWithoutHeadings: any","renderProps: BaseInviteUserRenderProps","CardPrimitive","Spinner","AlertPrimitive","Typography"],"sources":["../../../../../src/components/presentation/auth/InviteUser/BaseInviteUser.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {cx} from '@emotion/css';\nimport {\n EmbeddedFlowType,\n FieldError,\n FlowExecutionError,\n FlowMetadataResponse,\n buildValidatorFromRules,\n logger,\n OrganizationUnitListResponse,\n Preferences,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport useStyles from './BaseInviteUser.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderInviteUserComponents} from '../AuthOptionFactory';\n\n/**\n * Flow response structure from the backend.\n */\nexport interface InviteUserFlowResponse {\n challengeToken?: string;\n data?: {\n additionalData?: Record<string, any>;\n components?: any[];\n fieldErrors?: FieldError[];\n meta?: {\n components?: any[];\n };\n };\n error?: FlowExecutionError;\n executionId: string;\n flowStatus: 'INCOMPLETE' | 'COMPLETE' | 'ERROR';\n type?: 'VIEW' | 'REDIRECTION';\n}\n\n/**\n * Render props for custom UI rendering of InviteUser.\n */\nexport interface BaseInviteUserRenderProps {\n /**\n * Additional data from the current flow response (e.g. rootOuId, inviteLink).\n */\n additionalData?: Record<string, any>;\n\n /**\n * Flow components from the current step.\n */\n components: any[];\n\n /**\n * API error (if any).\n */\n error?: Error | null;\n\n /**\n * Current flow execution ID.\n */\n executionId?: string;\n\n /**\n * Field validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Current flow execution ID.\n */\n flowExecId?: string;\n\n /**\n * Function to handle input blur.\n */\n handleInputBlur: (name: string) => void;\n\n /**\n * Function to handle input changes.\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission.\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state.\n */\n isLoading: boolean;\n\n /**\n * Whether the form is valid.\n */\n isValid: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Reset the flow to invite another user.\n */\n resetFlow: () => void;\n\n /**\n * Subtitle for the current step.\n */\n subtitle?: string;\n\n /**\n * Title for the current step.\n */\n title?: string;\n\n /**\n * Touched fields.\n */\n touched: Record<string, boolean>;\n\n /**\n * Form values for the current step.\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseInviteUser component.\n */\nexport interface BaseInviteUserProps {\n /**\n * Render props function for custom UI.\n * If not provided, default UI will be rendered.\n */\n children?: (props: BaseInviteUserRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name.\n */\n className?: string;\n\n /**\n * Function to fetch child organization units.\n * When provided, enables the OU tree picker for OU_SELECT components.\n */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n\n /**\n * Whether the SDK is initialized.\n */\n isInitialized?: boolean;\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when the flow state changes.\n */\n onFlowChange?: (response: InviteUserFlowResponse) => void;\n\n /**\n * Function to initialize the invite user flow.\n * This should make an authenticated request to the flow/execute endpoint.\n */\n onInitialize: (payload: Record<string, any>) => Promise<InviteUserFlowResponse>;\n\n /**\n * Function to submit flow step data.\n * This should make an authenticated request to the flow/execute endpoint.\n */\n onSubmit: (payload: Record<string, any>) => Promise<InviteUserFlowResponse>;\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 * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Base component for invite user flow.\n * Handles the flow logic for creating a user and generating an invite link.\n *\n * When no children are provided, renders a default UI with:\n * - Loading spinner during initialization\n * - Error alerts for failures\n * - Flow components (user type selection, user details form)\n * - Invite link display with copy functionality\n *\n * Flow steps handled:\n * 1. User type selection (if multiple types available)\n * 2. User details input (username, email)\n * 3. Invite link generation\n */\nconst BaseInviteUser: FC<BaseInviteUserProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n className = '',\n children,\n fetchOrganizationUnitChildren,\n isInitialized = true,\n preferences,\n size = 'medium',\n variant = 'outlined',\n showTitle = true,\n showSubtitle = true,\n}: BaseInviteUserProps): ReactElement => {\n const {meta, isInitialized: isSdkInitialized, getStorageManager} = useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<InviteUserFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [formValues, setFormValues] = useState<Record<string, string>>({});\n const [formErrors, setFormErrors] = useState<Record<string, string>>({});\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({});\n const [isFormValid, setIsFormValid] = useState(true);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n /**\n * Project server-side validation errors from the most recent flow response into the\n * local formErrors state so they render alongside client-side errors. First error\n * per field wins, matching the SDK's single-string-per-field render-prop shape.\n */\n useEffect(() => {\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setFormErrors(errors);\n setTouchedFields((prev: Record<string, boolean>) => ({...prev, ...touched}));\n }, [currentFlow]);\n\n const initializationAttemptedRef: any = useRef(false);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n */\n useEffect(() => {\n if (!isSdkInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } catch {\n // StorageManager unavailable — continue without persisted token\n }\n })();\n }, [isSdkInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n try {\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n } catch {\n logger.warn('Failed to persist challenge token in storage.');\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages.\n * Uses the transformer's extractErrorMessage function for consistency.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t, 'components.inviteUser.errors.generic');\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Call the onError callback if provided\n onError?.(error instanceof Error ? error : new Error(errorMessage));\n },\n [t, onError],\n );\n\n /**\n * Normalize flow response to ensure component-driven format.\n * Transforms data.meta.components to data.components.\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: InviteUserFlowResponse): InviteUserFlowResponse => {\n if (!response?.data?.meta?.components) {\n return response;\n }\n\n try {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.inviteUser.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...response.data,\n components: components as any,\n },\n };\n } catch {\n // If transformer throws (e.g., error response), return as-is\n return response;\n }\n },\n [t, children],\n );\n\n /**\n * Handle input value changes.\n */\n const handleInputChange: any = useCallback((name: string, value: string) => {\n setFormValues((prev: any) => ({...prev, [name]: value}));\n // Clear error when user starts typing\n setFormErrors((prev: any) => {\n const newErrors: any = {...prev};\n delete newErrors[name];\n return newErrors;\n });\n }, []);\n\n /**\n * Handle input blur.\n */\n const handleInputBlur: any = useCallback((name: string) => {\n setTouchedFields((prev: any) => ({...prev, [name]: true}));\n }, []);\n\n /**\n * Validate required fields based on components.\n */\n const validateForm: any = useCallback(\n (components: any[]): {errors: Record<string, string>; isValid: boolean} => {\n const errors: Record<string, string> = {};\n\n const validateComponents = (comps: any[]): any => {\n comps.forEach((comp: any) => {\n if (\n (comp.type === 'TEXT_INPUT' ||\n comp.type === 'EMAIL_INPUT' ||\n comp.type === 'SELECT' ||\n comp.type === 'PHONE_INPUT' ||\n comp.type === 'OTP_INPUT' ||\n comp.type === 'DATE_INPUT') &&\n comp.ref\n ) {\n const value: any = formValues[comp.ref];\n if (comp.required && (!value || value.trim() === '')) {\n errors[comp.ref] = `${comp.label || comp.ref} is required`;\n } else {\n // Email validation\n if (comp.type === 'EMAIL_INPUT' && value && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n errors[comp.ref] = 'Please enter a valid email address';\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (value && !errors[comp.ref]) {\n const ruleValidator = buildValidatorFromRules(comp.validation);\n if (ruleValidator) {\n const message = ruleValidator(value);\n if (message) {\n errors[comp.ref] = t(message);\n }\n }\n }\n }\n }\n if (comp.components && Array.isArray(comp.components)) {\n validateComponents(comp.components);\n }\n });\n };\n\n validateComponents(components);\n\n return {errors, isValid: Object.keys(errors).length === 0};\n },\n [formValues],\n );\n\n /**\n * Handle form submission.\n */\n const handleSubmit: any = useCallback(\n async (component: any, data?: Record<string, any>) => {\n if (!currentFlow) {\n return;\n }\n\n // Validate form before submission\n const components: any = currentFlow.data?.components || [];\n const validation: any = validateForm(components);\n\n if (!validation.isValid) {\n setFormErrors(validation.errors);\n setIsFormValid(false);\n // Mark all fields as touched\n const touched: Record<string, boolean> = {};\n Object.keys(validation.errors).forEach((key: any) => {\n touched[key] = true;\n });\n setTouchedFields((prev: any) => ({...prev, ...touched}));\n return;\n }\n\n setIsLoading(true);\n setApiError(null);\n setIsFormValid(true);\n\n try {\n // Build payload with form values\n const inputs: any = data || formValues;\n\n const payload: Record<string, any> = {\n executionId: currentFlow.executionId,\n inputs,\n verbose: true,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n // Add action ID if component has one\n if (component?.id) {\n payload['action'] = component.id;\n }\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Check for error status\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n return;\n }\n\n // Update current flow and reset form for next step\n setCurrentFlow(response);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n },\n [currentFlow, formValues, validateForm, onSubmit, onFlowChange, handleError, normalizeFlowResponseLocal],\n );\n\n /**\n * Reset the flow to invite another user.\n */\n const resetFlow: any = useCallback(() => {\n setIsFlowInitialized(false);\n setCurrentFlow(null);\n setApiError(null);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n initializationAttemptedRef.current = false;\n }, []);\n\n /**\n * reset form values, errors, and touched fields to initial state\n */\n const resetForm = useCallback(() => {\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n setApiError(null);\n setIsFormValid(true);\n }, []);\n\n /**\n * Initialize the flow on component mount.\n */\n useEffect(() => {\n if (isInitialized && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n\n try {\n const payload: any = {\n flowType: EmbeddedFlowType.UserOnboarding,\n verbose: true,\n };\n\n const rawResponse: any = await onInitialize(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n await setChallengeToken(response.challengeToken ?? null);\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n // Check for immediate error\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [isInitialized, isFlowInitialized, onInitialize, onFlowChange, handleError, normalizeFlowResponseLocal]);\n\n /**\n * Recalculate form validity whenever form values or components change.\n * This ensures the submit button is enabled/disabled correctly as the user types.\n */\n useEffect(() => {\n if (currentFlow && isFlowInitialized) {\n const components: any = currentFlow.data?.components || [];\n if (components.length > 0) {\n const validation: any = validateForm(components);\n setIsFormValid(validation.isValid);\n }\n }\n }, [formValues, currentFlow, isFlowInitialized, validateForm]);\n\n /**\n * Extract title and subtitle from components.\n */\n const extractHeadings: any = useCallback((components: any[]): {subtitle?: string; title?: string} => {\n let title: string | undefined;\n let subtitle: string | undefined;\n\n components.forEach((comp: any) => {\n if (comp.type === 'TEXT') {\n if (comp.variant === 'HEADING_1' && !title) {\n title = comp.label;\n } else if ((comp.variant === 'HEADING_2' || comp.variant === 'SUBTITLE_1') && !subtitle) {\n subtitle = comp.label;\n }\n }\n });\n\n return {subtitle, title};\n }, []);\n\n /**\n * Filter out heading components for default rendering.\n */\n const filterHeadings: any = useCallback(\n (components: any[]): any[] =>\n components.filter(\n (comp: any) => !(comp.type === 'TEXT' && (comp.variant === 'HEADING_1' || comp.variant === 'HEADING_2')),\n ),\n [],\n );\n\n /**\n * Render form components using the factory.\n */\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderInviteUserComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData: currentFlow?.data?.additionalData,\n fetchOrganizationUnitChildren,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n },\n ),\n [\n customRenderers,\n currentFlow?.data?.additionalData,\n fetchOrganizationUnitChildren,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n handleInputChange,\n handleInputBlur,\n handleSubmit,\n size,\n theme,\n variant,\n ],\n );\n\n // Get components from normalized response, with fallback to meta.components\n const components: any = currentFlow?.data?.components || currentFlow?.data?.meta?.components || [];\n const {title, subtitle} = extractHeadings(components);\n const componentsWithoutHeadings: any = filterHeadings(components);\n\n // Render props\n const renderProps: BaseInviteUserRenderProps = {\n additionalData: currentFlow?.data?.additionalData,\n components,\n error: apiError,\n executionId: currentFlow?.executionId,\n fieldErrors: formErrors,\n handleInputBlur,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n meta,\n resetFlow,\n subtitle,\n title,\n touched: touchedFields,\n values: formValues,\n };\n\n // If children render prop is provided, use it for custom UI\n if (children) {\n return <div className={className}>{children(renderProps)}</div>;\n }\n\n // Default rendering\n\n // Waiting for SDK initialization\n if (!isInitialized) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Loading state during initialization\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Error state during initialization\n if (!currentFlow && apiError) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Title>Error</AlertPrimitive.Title>\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Flow components\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (title || subtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && title && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && subtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {apiError && (\n <div style={{marginBottom: '1rem'}}>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n <div>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0\n ? renderComponents(componentsWithoutHeadings)\n : !isLoading && (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">No form components available</Typography>\n </AlertPrimitive>\n )}\n {isLoading && (\n <div style={{display: 'flex', justifyContent: 'center', padding: '1rem'}}>\n <Spinner size=\"small\" />\n </div>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\nexport default BaseInviteUser;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAM5B,WAAW,EACX,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,EAAE,EAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"BaseRecovery.d.ts","sourceRoot":"","sources":["../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAM5B,WAAW,EACX,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,EAAE,EAAgB,SAAS,EAAgE,MAAM,OAAO,CAAC;AAejH,OAAsB,EAAC,SAAS,EAAC,MAAM,+BAA+B,CAAC;AAOvE;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC5C,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM;QAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC;IAC5E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,uBAAuB,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,4BAA4B,KAAK,IAAI,CAAC;IAC9D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,4BAA4B,KAAK,IAAI,CAAC;IAChE,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,2BAA2B,KAAK,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAChG,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC3F;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAChC;AAogBD;;;GAGG;AACH,QAAA,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAwBvC,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -8,6 +8,7 @@ import useTranslation_default from "../../../../hooks/useTranslation.js";
|
|
|
8
8
|
import { extractErrorMessage, normalizeFlowResponse } from "../../../../utils/flowTransformer.js";
|
|
9
9
|
import { useForm } from "../../../../hooks/useForm.js";
|
|
10
10
|
import Spinner_default from "../../../primitives/Spinner/Spinner.js";
|
|
11
|
+
import composeAffixedInputs_default from "../../../../utils/composeAffixedInputs.js";
|
|
11
12
|
import Typography_default from "../../../primitives/Typography/Typography.js";
|
|
12
13
|
import Alert_default from "../../../primitives/Alert/Alert.js";
|
|
13
14
|
import Card_default from "../../../primitives/Card/Card.js";
|
|
@@ -16,7 +17,7 @@ import BaseSignUp_styles_default from "../SignUp/BaseSignUp.styles.js";
|
|
|
16
17
|
import getAuthComponentHeadings_default from "../../../../utils/getAuthComponentHeadings.js";
|
|
17
18
|
import Logo_default from "../../../primitives/Logo/Logo.js";
|
|
18
19
|
import { EmbeddedFlowComponentType, EmbeddedRecoveryFlowStatus, buildValidatorFromRules, withVendorCSSClassPrefix } from "@thunderid/browser";
|
|
19
|
-
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
20
|
+
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
20
21
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
21
22
|
import { cx } from "@emotion/css";
|
|
22
23
|
|
|
@@ -31,7 +32,7 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
31
32
|
const customRenderers = useContext(ComponentRendererContext_default);
|
|
32
33
|
const { t } = useTranslation_default();
|
|
33
34
|
const { subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages } = useFlow_default();
|
|
34
|
-
const { meta } = useThunderID_default();
|
|
35
|
+
const { meta, vendor } = useThunderID_default();
|
|
35
36
|
const styles = BaseSignUp_styles_default(theme, colorScheme);
|
|
36
37
|
const [isLoading, setIsLoading] = useState(false);
|
|
37
38
|
const [isFlowInitialized, setIsFlowInitialized] = useState(false);
|
|
@@ -97,29 +98,29 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
97
98
|
processComponents(components);
|
|
98
99
|
return fields;
|
|
99
100
|
}, [t]);
|
|
100
|
-
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = useForm({
|
|
101
|
-
fields: currentFlow?.data?.components ? extractFormFields(currentFlow.data.components) : [],
|
|
101
|
+
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = useForm({
|
|
102
|
+
fields: useMemo(() => currentFlow?.data?.components ? extractFormFields(currentFlow.data.components) : [], [currentFlow, extractFormFields]),
|
|
102
103
|
initialValues: {},
|
|
103
104
|
requiredMessage: t("validations.required.field.error"),
|
|
104
105
|
validateOnBlur: true,
|
|
105
106
|
validateOnChange: false
|
|
106
107
|
});
|
|
107
|
-
/**
|
|
108
|
-
* Project server-side validation errors from the most recent flow response into the
|
|
109
|
-
* form's `errors` state. See BaseSignIn for the same pattern.
|
|
110
|
-
*/
|
|
111
108
|
useEffect(() => {
|
|
112
109
|
clearFormErrors();
|
|
113
110
|
const responseFieldErrors = (currentFlow?.data)?.fieldErrors;
|
|
114
111
|
if (!responseFieldErrors || responseFieldErrors.length === 0) return;
|
|
115
112
|
const errors = {};
|
|
116
|
-
|
|
113
|
+
const touched = {};
|
|
114
|
+
for (const fe of responseFieldErrors) if (!(fe.identifier in errors)) {
|
|
115
|
+
errors[fe.identifier] = fe.message;
|
|
116
|
+
touched[fe.identifier] = true;
|
|
117
|
+
}
|
|
118
|
+
setTouchedFields(touched);
|
|
117
119
|
setFormErrors(errors);
|
|
118
|
-
Object.keys(errors).forEach((field) => setFormTouched(field, true));
|
|
119
120
|
}, [
|
|
120
121
|
currentFlow,
|
|
121
122
|
setFormErrors,
|
|
122
|
-
|
|
123
|
+
setTouchedFields,
|
|
123
124
|
clearFormErrors
|
|
124
125
|
]);
|
|
125
126
|
const setupFormFields = useCallback((flowResponse) => {
|
|
@@ -151,8 +152,9 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
151
152
|
setApiError(null);
|
|
152
153
|
clearMessages();
|
|
153
154
|
try {
|
|
155
|
+
const composedData = data ? composeAffixedInputs_default(data, vendor) : void 0;
|
|
154
156
|
const filteredInputs = {};
|
|
155
|
-
if (
|
|
157
|
+
if (composedData) Object.entries(composedData).forEach(([key, value]) => {
|
|
156
158
|
if (value !== null && value !== void 0 && value !== "") filteredInputs[key] = value;
|
|
157
159
|
});
|
|
158
160
|
const payload = {
|
|
@@ -204,7 +206,7 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
204
206
|
], buttonClassName);
|
|
205
207
|
const errorClasses = cx([withVendorCSSClassPrefix("recovery__error")], errorClassName);
|
|
206
208
|
const messageClasses = cx([withVendorCSSClassPrefix("recovery__messages")], messageClassName);
|
|
207
|
-
const renderComponents = useCallback((components) => renderRecoveryComponents(components, formValues, touchedFields, formErrors, isLoading, isFormValid, handleInputChange, {
|
|
209
|
+
const renderComponents = useCallback((components) => renderRecoveryComponents(components, formValues, touchedFields, formErrors, isLoading, isFormValid, resetForm, handleInputChange, {
|
|
208
210
|
_customRenderers: customRenderers,
|
|
209
211
|
_theme: theme,
|
|
210
212
|
buttonClassName: buttonClasses,
|
|
@@ -213,7 +215,8 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
213
215
|
onInputBlur: handleInputBlur,
|
|
214
216
|
onSubmit: handleSubmit,
|
|
215
217
|
size,
|
|
216
|
-
variant
|
|
218
|
+
variant,
|
|
219
|
+
vendor
|
|
217
220
|
}), [
|
|
218
221
|
customRenderers,
|
|
219
222
|
buttonClasses,
|
|
@@ -228,7 +231,8 @@ const BaseRecoveryContent = ({ onInitialize, onSubmit, onError, onFlowChange, on
|
|
|
228
231
|
size,
|
|
229
232
|
theme,
|
|
230
233
|
touchedFields,
|
|
231
|
-
variant
|
|
234
|
+
variant,
|
|
235
|
+
vendor
|
|
232
236
|
]);
|
|
233
237
|
useEffect(() => {
|
|
234
238
|
if (isInitialized && !isFlowInitialized && !initializationAttemptedRef.current) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseRecovery.js","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: any","handleError: any","errorMessage: string","normalizeFlowResponseLocal: any","extractFormFields: any","fields: FormField[]","fieldName: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","setupFormFields: any","fields: any","initialValues: Record<string, string>","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","containerClasses: any","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {cx} from '@emotion/css';\nimport {\n EmbeddedRecoveryFlowRequest,\n EmbeddedRecoveryFlowResponse,\n EmbeddedRecoveryFlowStatus,\n EmbeddedFlowComponentType,\n FieldError,\n withVendorCSSClassPrefix,\n buildValidatorFromRules,\n Preferences,\n FlowMetadataResponse,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useContext, useEffect, useState, useCallback, useRef} from 'react';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useForm, FormField} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../../utils/getAuthComponentHeadings';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Logo from '../../../primitives/Logo/Logo';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderRecoveryComponents} from '../AuthOptionFactory';\nimport useStyles from '../SignUp/BaseSignUp.styles';\n\n/**\n * Render props for custom UI rendering.\n */\nexport interface BaseRecoveryRenderProps {\n components: any[];\n error?: Error | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n isLoading: boolean;\n isValid: boolean;\n messages: {message: string; type: string}[];\n meta: FlowMetadataResponse | null;\n subtitle: string;\n title: string;\n touched: Record<string, boolean>;\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseRecovery component.\n */\nexport interface BaseRecoveryProps {\n afterRecoveryUrl?: string;\n buttonClassName?: string;\n /**\n * Render props function for custom UI or static content\n */\n children?: ((props: BaseRecoveryRenderProps) => ReactNode) | ReactNode;\n className?: string;\n error?: Error | null;\n errorClassName?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n messageClassName?: string;\n onComplete?: (response: EmbeddedRecoveryFlowResponse) => void;\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedRecoveryFlowResponse) => void;\n onInitialize?: (payload?: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n onSubmit?: (payload: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\n showLogo?: boolean;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that renders the V2 recovery UI and manages flow state.\n *\n * @internal\n */\nconst BaseRecoveryContent: FC<BaseRecoveryProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n errorClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isInitialized,\n children,\n showTitle = true,\n showSubtitle = true,\n}: BaseRecoveryProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const {meta} = useThunderID();\n const styles: any = useStyles(theme, colorScheme);\n\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedRecoveryFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n clearMessages();\n addMessage({message: errorMessage, type: 'error'});\n },\n [t, addMessage, clearMessages],\n );\n\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedRecoveryFlowResponse): EmbeddedRecoveryFlowResponse => {\n if (response?.data?.components && Array.isArray(response.data.components)) {\n return response;\n }\n\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'components.recovery.errors.generic', resolveTranslations: false},\n meta,\n );\n\n return {...response, data: {...response.data, components: components as any}};\n }\n\n return response;\n },\n [t, meta],\n );\n\n const extractFormFields: any = useCallback(\n (components: any[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: any[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === EmbeddedFlowComponentType.TextInput ||\n component.type === EmbeddedFlowComponentType.PasswordInput ||\n component.type === EmbeddedFlowComponentType.EmailInput ||\n component.type === EmbeddedFlowComponentType.Select ||\n component.type === EmbeddedFlowComponentType.DateInput\n ) {\n const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\n fields.push({\n initialValue: '',\n name: fieldName,\n required: component.required || false,\n validator: (value: string) => {\n if (component.required && (!value || value.trim() === '')) {\n return t('validations.required.field.error');\n }\n if (\n (component.type === EmbeddedFlowComponentType.EmailInput || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n return null;\n },\n });\n }\n\n if (component.components && Array.isArray(component.components)) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(components);\n return fields;\n },\n [t],\n );\n\n const formFields: any = currentFlow?.data?.components ? extractFormFields(currentFlow.data.components) : [];\n\n const form: any = useForm<Record<string, string>>({\n fields: formFields,\n initialValues: {},\n requiredMessage: t('validations.required.field.error'),\n validateOnBlur: true,\n validateOnChange: false,\n });\n\n const {\n values: formValues,\n touched: touchedFields,\n errors: formErrors,\n isValid: isFormValid,\n setValue: setFormValue,\n setTouched: setFormTouched,\n setErrors: setFormErrors,\n clearErrors: clearFormErrors,\n validateForm,\n touchAllFields,\n reset: resetForm,\n } = form;\n\n /**\n * Project server-side validation errors from the most recent flow response into the\n * form's `errors` state. See BaseSignIn for the same pattern.\n */\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n }\n }\n setFormErrors(errors);\n Object.keys(errors).forEach((field: string) => setFormTouched(field, true));\n }, [currentFlow, setFormErrors, setFormTouched, clearFormErrors]);\n\n const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedRecoveryFlowResponse) => {\n const fields: any = extractFormFields(flowResponse.data?.components || []);\n const initialValues: Record<string, string> = {};\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n resetForm();\n Object.keys(initialValues).forEach((key: any) => setFormValue(key, initialValues[key]));\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow) return;\n\n if (!skipValidation) {\n touchAllFields();\n const validation: ReturnType<typeof validateForm> = validateForm();\n if (!validation.isValid) return;\n }\n\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const filteredInputs: Record<string, any> = {};\n if (data) {\n Object.entries(data).forEach(([key, value]: [string, any]) => {\n if (value !== null && value !== undefined && value !== '') {\n filteredInputs[key] = value;\n }\n });\n }\n\n const payload: EmbeddedRecoveryFlowRequest = {\n ...(currentFlow.executionId && {executionId: currentFlow.executionId}),\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs: filteredInputs,\n };\n\n const rawResponse: any = await onSubmit?.(payload);\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\n setCurrentFlow(response);\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery'),\n withVendorCSSClassPrefix(`recovery--${size}`),\n withVendorCSSClassPrefix(`recovery--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__input'),\n size === 'small' && withVendorCSSClassPrefix('recovery__input--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__button'),\n size === 'small' && withVendorCSSClassPrefix('recovery__button--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('recovery__error')], errorClassName);\n const messageClasses: any = cx([withVendorCSSClassPrefix('recovery__messages')], messageClassName);\n\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderRecoveryComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n },\n ),\n [\n customRenderers,\n buttonClasses,\n formErrors,\n formValues,\n handleInputBlur,\n handleSubmit,\n inputClasses,\n isFormValid,\n meta,\n isLoading,\n size,\n theme,\n touchedFields,\n variant,\n ],\n );\n\n useEffect(() => {\n if (isInitialized && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const rawResponse: any = await onInitialize?.();\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n }\n\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [\n isFlowInitialized,\n isInitialized,\n normalizeFlowResponseLocal,\n onComplete,\n onError,\n onFlowChange,\n onInitialize,\n setupFormFields,\n t,\n ]);\n\n if (children) {\n if (typeof children === 'function') {\n const renderProps: BaseRecoveryRenderProps = {\n components: currentFlow?.data?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle || t('recovery.subheading'),\n title: flowTitle || t('recovery.heading'),\n touched: touchedFields,\n validateForm: (): {fieldErrors: Record<string, string>; isValid: boolean} => {\n const result: ReturnType<typeof validateForm> = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return <div className={containerClasses}>{(children as any)(renderProps)}</div>;\n }\n\n return <div className={containerClasses}>{children}</div>;\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={styles.loadingContainer}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!currentFlow) {\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\" className={errorClasses}>\n <AlertPrimitive.Title>{t('errors.heading')}</AlertPrimitive.Title>\n <AlertPrimitive.Description>{t('errors.recovery.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n const componentsToRender: any = currentFlow.data?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('recovery.heading'),\n t('recovery.subheading'),\n );\n\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {externalError && (\n <div className={styles.flowMessagesContainer}>\n <AlertPrimitive variant=\"error\" className={cx(styles.flowMessageItem, messageClasses)}>\n <AlertPrimitive.Description>{externalError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n {flowMessages && flowMessages.length > 0 && (\n <div className={styles.flowMessagesContainer}>\n {flowMessages.map((message: any, index: number) => (\n <AlertPrimitive\n key={message.id || index}\n variant={message.type?.toLowerCase() === 'error' ? 'error' : 'info'}\n className={cx(styles.flowMessageItem, messageClasses)}\n >\n <AlertPrimitive.Description>{message.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n ))}\n </div>\n )}\n <div className={styles.contentContainer}>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0 ? (\n renderComponents(componentsWithoutHeadings)\n ) : (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.recovery.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseRecovery component for ThunderIDV2 that provides an embedded account/password recovery flow.\n * Accepts API functions as props to maintain framework independence.\n */\nconst BaseRecovery: FC<BaseRecoveryProps> = ({\n preferences,\n showLogo = true,\n ...rest\n}: BaseRecoveryProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const styles: any = useStyles(theme, colorScheme);\n\n const content: ReactElement = (\n <div>\n {showLogo && (\n <div className={styles.logoContainer}>\n <Logo size=\"large\" />\n </div>\n )}\n <FlowProvider>\n <BaseRecoveryContent showLogo={showLogo} {...rest} />\n </FlowProvider>\n </div>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseRecovery;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseRecovery.js","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: any","handleError: any","errorMessage: string","normalizeFlowResponseLocal: any","extractFormFields: any","fields: FormField[]","fieldName: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","setupFormFields: any","fields: any","initialValues: Record<string, string>","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","containerClasses: any","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {cx} from '@emotion/css';\nimport {\n EmbeddedRecoveryFlowRequest,\n EmbeddedRecoveryFlowResponse,\n EmbeddedRecoveryFlowStatus,\n EmbeddedFlowComponentType,\n FieldError,\n withVendorCSSClassPrefix,\n buildValidatorFromRules,\n Preferences,\n FlowMetadataResponse,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useContext, useEffect, useMemo, useState, useCallback, useRef} from 'react';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {useForm, FormField} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport composeAffixedInputs from '../../../../utils/composeAffixedInputs';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../../utils/getAuthComponentHeadings';\nimport AlertPrimitive from '../../../primitives/Alert/Alert';\nimport CardPrimitive, {CardProps} from '../../../primitives/Card/Card';\nimport Logo from '../../../primitives/Logo/Logo';\nimport Spinner from '../../../primitives/Spinner/Spinner';\nimport Typography from '../../../primitives/Typography/Typography';\nimport {renderRecoveryComponents} from '../AuthOptionFactory';\nimport useStyles from '../SignUp/BaseSignUp.styles';\n\n/**\n * Render props for custom UI rendering.\n */\nexport interface BaseRecoveryRenderProps {\n components: any[];\n error?: Error | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n isLoading: boolean;\n isValid: boolean;\n messages: {message: string; type: string}[];\n meta: FlowMetadataResponse | null;\n subtitle: string;\n title: string;\n touched: Record<string, boolean>;\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseRecovery component.\n */\nexport interface BaseRecoveryProps {\n afterRecoveryUrl?: string;\n buttonClassName?: string;\n /**\n * Render props function for custom UI or static content\n */\n children?: ((props: BaseRecoveryRenderProps) => ReactNode) | ReactNode;\n className?: string;\n error?: Error | null;\n errorClassName?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n messageClassName?: string;\n onComplete?: (response: EmbeddedRecoveryFlowResponse) => void;\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedRecoveryFlowResponse) => void;\n onInitialize?: (payload?: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n onSubmit?: (payload: EmbeddedRecoveryFlowRequest) => Promise<EmbeddedRecoveryFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\n showLogo?: boolean;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that renders the V2 recovery UI and manages flow state.\n *\n * @internal\n */\nconst BaseRecoveryContent: FC<BaseRecoveryProps> = ({\n onInitialize,\n onSubmit,\n onError,\n onFlowChange,\n onComplete,\n error: externalError,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n errorClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isInitialized,\n children,\n showTitle = true,\n showSubtitle = true,\n}: BaseRecoveryProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const {meta, vendor} = useThunderID();\n const styles: any = useStyles(theme, colorScheme);\n\n const [isLoading, setIsLoading] = useState(false);\n const [isFlowInitialized, setIsFlowInitialized] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedRecoveryFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const initializationAttemptedRef: any = useRef(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t);\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n clearMessages();\n addMessage({message: errorMessage, type: 'error'});\n },\n [t, addMessage, clearMessages],\n );\n\n const normalizeFlowResponseLocal: any = useCallback(\n (response: EmbeddedRecoveryFlowResponse): EmbeddedRecoveryFlowResponse => {\n if (response?.data?.components && Array.isArray(response.data.components)) {\n return response;\n }\n\n if (response?.data) {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'components.recovery.errors.generic', resolveTranslations: false},\n meta,\n );\n\n return {...response, data: {...response.data, components: components as any}};\n }\n\n return response;\n },\n [t, meta],\n );\n\n const extractFormFields: any = useCallback(\n (components: any[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: any[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === EmbeddedFlowComponentType.TextInput ||\n component.type === EmbeddedFlowComponentType.PasswordInput ||\n component.type === EmbeddedFlowComponentType.EmailInput ||\n component.type === EmbeddedFlowComponentType.Select ||\n component.type === EmbeddedFlowComponentType.DateInput\n ) {\n const fieldName: any = component.ref || component.id;\n const ruleValidator = buildValidatorFromRules(component.validation);\n fields.push({\n initialValue: '',\n name: fieldName,\n required: component.required || false,\n validator: (value: string) => {\n if (component.required && (!value || value.trim() === '')) {\n return t('validations.required.field.error');\n }\n if (\n (component.type === EmbeddedFlowComponentType.EmailInput || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n // Evaluate declarative validation rules from meta.components[].validation.\n if (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n return null;\n },\n });\n }\n\n if (component.components && Array.isArray(component.components)) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(components);\n return fields;\n },\n [t],\n );\n\n const formFields: any = useMemo(\n () => (currentFlow?.data?.components ? extractFormFields(currentFlow.data.components) : []),\n [currentFlow, extractFormFields],\n );\n\n const form: any = useForm<Record<string, string>>({\n fields: formFields,\n initialValues: {},\n requiredMessage: t('validations.required.field.error'),\n validateOnBlur: true,\n validateOnChange: false,\n });\n\n const {\n values: formValues,\n touched: touchedFields,\n errors: formErrors,\n isValid: isFormValid,\n setValue: setFormValue,\n setTouched: setFormTouched,\n setTouchedFields,\n setErrors: setFormErrors,\n clearErrors: clearFormErrors,\n validateForm,\n touchAllFields,\n reset: resetForm,\n } = form;\n\n // Project server-side fieldErrors from the flow response into form state.\n // `setTouchedFields` avoids re-running client-side validation that would wipe\n // server errors when the client rules happen to pass.\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setTouchedFields(touched);\n setFormErrors(errors);\n }, [currentFlow, setFormErrors, setTouchedFields, clearFormErrors]);\n\n const setupFormFields: any = useCallback(\n (flowResponse: EmbeddedRecoveryFlowResponse) => {\n const fields: any = extractFormFields(flowResponse.data?.components || []);\n const initialValues: Record<string, string> = {};\n fields.forEach((field: any) => {\n initialValues[field.name] = field.initialValue || '';\n });\n resetForm();\n Object.keys(initialValues).forEach((key: any) => setFormValue(key, initialValues[key]));\n },\n [extractFormFields, resetForm, setFormValue],\n );\n\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n const handleSubmit = async (component: any, data?: Record<string, any>, skipValidation?: boolean): Promise<void> => {\n if (!currentFlow) return;\n\n if (!skipValidation) {\n touchAllFields();\n const validation: ReturnType<typeof validateForm> = validateForm();\n if (!validation.isValid) return;\n }\n\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const composedData: Record<string, any> | undefined = data\n ? composeAffixedInputs(data as Record<string, string>, vendor)\n : undefined;\n\n const filteredInputs: Record<string, any> = {};\n if (composedData) {\n Object.entries(composedData).forEach(([key, value]: [string, any]) => {\n if (value !== null && value !== undefined && value !== '') {\n filteredInputs[key] = value;\n }\n });\n }\n\n const payload: EmbeddedRecoveryFlowRequest = {\n ...(currentFlow.executionId && {executionId: currentFlow.executionId}),\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs: filteredInputs,\n };\n\n const rawResponse: any = await onSubmit?.(payload);\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\n setCurrentFlow(response);\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n };\n\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery'),\n withVendorCSSClassPrefix(`recovery--${size}`),\n withVendorCSSClassPrefix(`recovery--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__input'),\n size === 'small' && withVendorCSSClassPrefix('recovery__input--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('recovery__button'),\n size === 'small' && withVendorCSSClassPrefix('recovery__button--small'),\n size === 'large' && withVendorCSSClassPrefix('recovery__button--large'),\n ],\n buttonClassName,\n );\n\n const errorClasses: any = cx([withVendorCSSClassPrefix('recovery__error')], errorClassName);\n const messageClasses: any = cx([withVendorCSSClassPrefix('recovery__messages')], messageClassName);\n\n const renderComponents: any = useCallback(\n (components: any[]): ReactElement[] =>\n renderRecoveryComponents(\n components,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n vendor,\n },\n ),\n [\n customRenderers,\n buttonClasses,\n formErrors,\n formValues,\n handleInputBlur,\n handleSubmit,\n inputClasses,\n isFormValid,\n meta,\n isLoading,\n size,\n theme,\n touchedFields,\n variant,\n vendor,\n ],\n );\n\n useEffect(() => {\n if (isInitialized && !isFlowInitialized && !initializationAttemptedRef.current) {\n initializationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsLoading(true);\n setApiError(null);\n clearMessages();\n\n try {\n const rawResponse: any = await onInitialize?.();\n if (!rawResponse) return;\n const response: any = normalizeFlowResponseLocal(rawResponse);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Error) {\n handleError(response);\n onError?.(new Error(extractErrorMessage(response, t)));\n }\n\n setCurrentFlow(response);\n setIsFlowInitialized(true);\n onFlowChange?.(response);\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Complete) {\n onComplete?.(response);\n return;\n }\n\n if (response.flowStatus === EmbeddedRecoveryFlowStatus.Incomplete) {\n setupFormFields(response);\n\n // Display error from INCOMPLETE response\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (response?.error) {\n handleError(response);\n }\n }\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }\n }, [\n isFlowInitialized,\n isInitialized,\n normalizeFlowResponseLocal,\n onComplete,\n onError,\n onFlowChange,\n onInitialize,\n setupFormFields,\n t,\n ]);\n\n if (children) {\n if (typeof children === 'function') {\n const renderProps: BaseRecoveryRenderProps = {\n components: currentFlow?.data?.components || [],\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle || t('recovery.subheading'),\n title: flowTitle || t('recovery.heading'),\n touched: touchedFields,\n validateForm: (): {fieldErrors: Record<string, string>; isValid: boolean} => {\n const result: ReturnType<typeof validateForm> = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return <div className={containerClasses}>{(children as any)(renderProps)}</div>;\n }\n\n return <div className={containerClasses}>{children}</div>;\n }\n\n if (!isFlowInitialized && isLoading) {\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={styles.loadingContainer}>\n <Spinner size=\"medium\" />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!currentFlow) {\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\" className={errorClasses}>\n <AlertPrimitive.Title>{t('errors.heading')}</AlertPrimitive.Title>\n <AlertPrimitive.Description>{t('errors.recovery.flow.initialization.failure')}</AlertPrimitive.Description>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n const componentsToRender: any = currentFlow.data?.components || [];\n const {title, subtitle, componentsWithoutHeadings} = getAuthComponentHeadings(\n componentsToRender,\n flowTitle,\n flowSubtitle,\n t('recovery.heading'),\n t('recovery.subheading'),\n );\n\n return (\n <CardPrimitive className={cx(containerClasses, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {externalError && (\n <div className={styles.flowMessagesContainer}>\n <AlertPrimitive variant=\"error\" className={cx(styles.flowMessageItem, messageClasses)}>\n <AlertPrimitive.Description>{externalError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n {flowMessages && flowMessages.length > 0 && (\n <div className={styles.flowMessagesContainer}>\n {flowMessages.map((message: any, index: number) => (\n <AlertPrimitive\n key={message.id || index}\n variant={message.type?.toLowerCase() === 'error' ? 'error' : 'info'}\n className={cx(styles.flowMessageItem, messageClasses)}\n >\n <AlertPrimitive.Description>{message.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n ))}\n </div>\n )}\n <div className={styles.contentContainer}>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0 ? (\n renderComponents(componentsWithoutHeadings)\n ) : (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.recovery.components.not.available')}</Typography>\n </AlertPrimitive>\n )}\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * BaseRecovery component for ThunderIDV2 that provides an embedded account/password recovery flow.\n * Accepts API functions as props to maintain framework independence.\n */\nconst BaseRecovery: FC<BaseRecoveryProps> = ({\n preferences,\n showLogo = true,\n ...rest\n}: BaseRecoveryProps): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const styles: any = useStyles(theme, colorScheme);\n\n const content: ReactElement = (\n <div>\n {showLogo && (\n <div className={styles.logoContainer}>\n <Logo size=\"large\" />\n </div>\n )}\n <FlowProvider>\n <BaseRecoveryContent showLogo={showLogo} {...rest} />\n </FlowProvider>\n </div>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseRecovery;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSignIn.d.ts","sourceRoot":"","sources":["../../../../../src/components/presentation/auth/SignIn/BaseSignIn.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAEL,yBAAyB,EACzB,qBAAqB,EACrB,UAAU,EACV,oBAAoB,EACpB,WAAW,
|
|
1
|
+
{"version":3,"file":"BaseSignIn.d.ts","sourceRoot":"","sources":["../../../../../src/components/presentation/auth/SignIn/BaseSignIn.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,12 +9,13 @@ import { extractErrorMessage } from "../../../../utils/flowTransformer.js";
|
|
|
9
9
|
import { useForm } from "../../../../hooks/useForm.js";
|
|
10
10
|
import Spinner_default from "../../../primitives/Spinner/Spinner.js";
|
|
11
11
|
import BaseSignIn_styles_default from "./BaseSignIn.styles.js";
|
|
12
|
+
import composeAffixedInputs_default from "../../../../utils/composeAffixedInputs.js";
|
|
12
13
|
import Typography_default from "../../../primitives/Typography/Typography.js";
|
|
13
14
|
import Alert_default from "../../../primitives/Alert/Alert.js";
|
|
14
15
|
import Card_default from "../../../primitives/Card/Card.js";
|
|
15
16
|
import { renderSignInComponents } from "../AuthOptionFactory.js";
|
|
16
|
-
import { withVendorCSSClassPrefix } from "@thunderid/browser";
|
|
17
|
-
import { useCallback, useContext, useState } from "react";
|
|
17
|
+
import { buildValidatorFromRules, withVendorCSSClassPrefix } from "@thunderid/browser";
|
|
18
|
+
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
|
18
19
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
20
|
import { cx } from "@emotion/css";
|
|
20
21
|
|
|
@@ -22,8 +23,8 @@ import { cx } from "@emotion/css";
|
|
|
22
23
|
/**
|
|
23
24
|
* Internal component that consumes FlowContext and renders the sign-in UI.
|
|
24
25
|
*/
|
|
25
|
-
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, id, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false }) => {
|
|
26
|
-
const { meta } = useThunderID_default();
|
|
26
|
+
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, id, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false, serverFieldErrors = null }) => {
|
|
27
|
+
const { meta, vendor } = useThunderID_default();
|
|
27
28
|
const { theme } = useTheme_default();
|
|
28
29
|
const customRenderers = useContext(ComponentRendererContext_default);
|
|
29
30
|
const { t } = useTranslation_default();
|
|
@@ -56,8 +57,9 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
56
57
|
const fields = [];
|
|
57
58
|
const processComponents = (comps) => {
|
|
58
59
|
comps.forEach((component) => {
|
|
59
|
-
if (component.type === "TEXT_INPUT" || component.type === "PASSWORD_INPUT" || component.type === "EMAIL_INPUT" || component.type === "PHONE_INPUT" || component.type === "OTP_INPUT") {
|
|
60
|
+
if (component.type === "TEXT_INPUT" || component.type === "PASSWORD_INPUT" || component.type === "EMAIL_INPUT" || component.type === "PHONE_INPUT" || component.type === "OTP_INPUT" || component.type === "SELECT" || component.type === "DATE_INPUT") {
|
|
60
61
|
const identifier = component.ref;
|
|
62
|
+
const ruleValidator = buildValidatorFromRules(component.validation);
|
|
61
63
|
fields.push({
|
|
62
64
|
initialValue: "",
|
|
63
65
|
name: identifier,
|
|
@@ -65,6 +67,10 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
65
67
|
validator: (value) => {
|
|
66
68
|
if (component.required && (!value || value.trim() === "")) return t("validations.required.field.error");
|
|
67
69
|
if ((component.type === "EMAIL_INPUT" || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
|
|
70
|
+
if (ruleValidator && value) {
|
|
71
|
+
const ruleMessage = ruleValidator(value);
|
|
72
|
+
if (ruleMessage) return t(ruleMessage);
|
|
73
|
+
}
|
|
68
74
|
return null;
|
|
69
75
|
}
|
|
70
76
|
});
|
|
@@ -75,13 +81,30 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
75
81
|
processComponents(flowComponents);
|
|
76
82
|
return fields;
|
|
77
83
|
}, [t]);
|
|
78
|
-
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, validateForm, touchAllFields } = useForm({
|
|
79
|
-
fields: components ? extractFormFields(components) : [],
|
|
84
|
+
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = useForm({
|
|
85
|
+
fields: useMemo(() => components ? extractFormFields(components) : [], [components, extractFormFields]),
|
|
80
86
|
initialValues: {},
|
|
81
87
|
requiredMessage: t("validations.required.field.error"),
|
|
82
88
|
validateOnBlur: true,
|
|
83
89
|
validateOnChange: false
|
|
84
90
|
});
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
clearFormErrors();
|
|
93
|
+
if (!serverFieldErrors || serverFieldErrors.length === 0) return;
|
|
94
|
+
const errors = {};
|
|
95
|
+
const touched = {};
|
|
96
|
+
for (const fe of serverFieldErrors) if (!(fe.identifier in errors)) {
|
|
97
|
+
errors[fe.identifier] = fe.message;
|
|
98
|
+
touched[fe.identifier] = true;
|
|
99
|
+
}
|
|
100
|
+
setTouchedFields(touched);
|
|
101
|
+
setFormErrors(errors);
|
|
102
|
+
}, [
|
|
103
|
+
serverFieldErrors,
|
|
104
|
+
setFormErrors,
|
|
105
|
+
setTouchedFields,
|
|
106
|
+
clearFormErrors
|
|
107
|
+
]);
|
|
85
108
|
/**
|
|
86
109
|
* Handle input value changes.
|
|
87
110
|
* Only updates the value without marking as touched.
|
|
@@ -109,9 +132,10 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
109
132
|
setApiError(null);
|
|
110
133
|
clearMessages();
|
|
111
134
|
try {
|
|
135
|
+
const composedData = data ? composeAffixedInputs_default(data, vendor) : void 0;
|
|
112
136
|
const filteredInputs = {};
|
|
113
|
-
if (
|
|
114
|
-
if (
|
|
137
|
+
if (composedData) Object.keys(composedData).forEach((key) => {
|
|
138
|
+
if (composedData[key] !== void 0 && composedData[key] !== null && composedData[key] !== "") filteredInputs[key] = composedData[key];
|
|
115
139
|
});
|
|
116
140
|
let payload = {};
|
|
117
141
|
payload = {
|
|
@@ -146,7 +170,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
146
170
|
/**
|
|
147
171
|
* Render components based on flow data using the factory
|
|
148
172
|
*/
|
|
149
|
-
const renderComponents = useCallback((flowComponents) => renderSignInComponents(flowComponents, formValues, touchedFields, formErrors, isLoading, isFormValid, handleInputChange, {
|
|
173
|
+
const renderComponents = useCallback((flowComponents) => renderSignInComponents(flowComponents, formValues, touchedFields, formErrors, isLoading, isFormValid, resetForm, handleInputChange, {
|
|
150
174
|
_customRenderers: customRenderers,
|
|
151
175
|
_theme: theme,
|
|
152
176
|
additionalData,
|
|
@@ -158,7 +182,8 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
158
182
|
onSubmit: handleSubmit,
|
|
159
183
|
size,
|
|
160
184
|
t,
|
|
161
|
-
variant
|
|
185
|
+
variant,
|
|
186
|
+
vendor
|
|
162
187
|
}), [
|
|
163
188
|
additionalData,
|
|
164
189
|
customRenderers,
|
|
@@ -172,6 +197,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
172
197
|
isLoading,
|
|
173
198
|
size,
|
|
174
199
|
variant,
|
|
200
|
+
vendor,
|
|
175
201
|
inputClasses,
|
|
176
202
|
buttonClasses,
|
|
177
203
|
handleInputBlur,
|