@thunderid/react 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +16 -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/utils/composeAffixedInputs.cjs +74 -0
- package/dist/cjs/utils/composeAffixedInputs.cjs.map +1 -0
- 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 +16 -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/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 +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseRecovery.cjs","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","extractFormFields: any","fields: FormField[]","EmbeddedFlowComponentType","fieldName: any","useForm","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","setupFormFields: any","fields: any","initialValues: Record<string, string>","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","EmbeddedRecoveryFlowStatus","containerClasses: any","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderRecoveryComponents","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["/**\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.cjs","names":["BaseRecoveryContent: FC<BaseRecoveryProps>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","useThunderID","styles: any","useStyles","initializationAttemptedRef: any","challengeTokenRef: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","extractFormFields: any","fields: FormField[]","EmbeddedFlowComponentType","fieldName: any","useForm","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","setupFormFields: any","fields: any","initialValues: Record<string, string>","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","payload: EmbeddedRecoveryFlowRequest","rawResponse: any","response: any","EmbeddedRecoveryFlowStatus","containerClasses: any","inputClasses: any","buttonClasses: any","errorClasses: any","messageClasses: any","renderComponents: any","renderRecoveryComponents","result: ReturnType<typeof validateForm>","CardPrimitive","Spinner","AlertPrimitive","getAuthComponentHeadings","Typography","BaseRecovery: FC<BaseRecoveryProps>","content: ReactElement","Logo","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/Recovery/BaseRecovery.tsx"],"sourcesContent":["/**\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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"}
|
|
@@ -10,6 +10,7 @@ const require_flowTransformer = require('../../../../utils/flowTransformer.cjs')
|
|
|
10
10
|
const require_useForm = require('../../../../hooks/useForm.cjs');
|
|
11
11
|
const require_Spinner = require('../../../primitives/Spinner/Spinner.cjs');
|
|
12
12
|
const require_BaseSignIn_styles = require('./BaseSignIn.styles.cjs');
|
|
13
|
+
const require_composeAffixedInputs = require('../../../../utils/composeAffixedInputs.cjs');
|
|
13
14
|
const require_Typography = require('../../../primitives/Typography/Typography.cjs');
|
|
14
15
|
const require_Alert = require('../../../primitives/Alert/Alert.cjs');
|
|
15
16
|
const require_Card = require('../../../primitives/Card/Card.cjs');
|
|
@@ -27,8 +28,8 @@ __emotion_css = require_rolldown_runtime.__toESM(__emotion_css);
|
|
|
27
28
|
/**
|
|
28
29
|
* Internal component that consumes FlowContext and renders the sign-in UI.
|
|
29
30
|
*/
|
|
30
|
-
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, id, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false }) => {
|
|
31
|
-
const { meta } = require_useThunderID.default();
|
|
31
|
+
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, id, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false, serverFieldErrors = null }) => {
|
|
32
|
+
const { meta, vendor } = require_useThunderID.default();
|
|
32
33
|
const { theme } = require_useTheme.default();
|
|
33
34
|
const customRenderers = (0, react.useContext)(require_ComponentRendererContext.default);
|
|
34
35
|
const { t } = require_useTranslation.default();
|
|
@@ -61,8 +62,9 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
61
62
|
const fields = [];
|
|
62
63
|
const processComponents = (comps) => {
|
|
63
64
|
comps.forEach((component) => {
|
|
64
|
-
if (component.type === "TEXT_INPUT" || component.type === "PASSWORD_INPUT" || component.type === "EMAIL_INPUT" || component.type === "PHONE_INPUT" || component.type === "OTP_INPUT") {
|
|
65
|
+
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") {
|
|
65
66
|
const identifier = component.ref;
|
|
67
|
+
const ruleValidator = (0, __thunderid_browser.buildValidatorFromRules)(component.validation);
|
|
66
68
|
fields.push({
|
|
67
69
|
initialValue: "",
|
|
68
70
|
name: identifier,
|
|
@@ -70,6 +72,10 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
70
72
|
validator: (value) => {
|
|
71
73
|
if (component.required && (!value || value.trim() === "")) return t("validations.required.field.error");
|
|
72
74
|
if ((component.type === "EMAIL_INPUT" || component.variant === "EMAIL") && value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return t("field.email.invalid");
|
|
75
|
+
if (ruleValidator && value) {
|
|
76
|
+
const ruleMessage = ruleValidator(value);
|
|
77
|
+
if (ruleMessage) return t(ruleMessage);
|
|
78
|
+
}
|
|
73
79
|
return null;
|
|
74
80
|
}
|
|
75
81
|
});
|
|
@@ -80,13 +86,30 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
80
86
|
processComponents(flowComponents);
|
|
81
87
|
return fields;
|
|
82
88
|
}, [t]);
|
|
83
|
-
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, validateForm, touchAllFields } = require_useForm.useForm({
|
|
84
|
-
fields: components ? extractFormFields(components) : [],
|
|
89
|
+
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = require_useForm.useForm({
|
|
90
|
+
fields: (0, react.useMemo)(() => components ? extractFormFields(components) : [], [components, extractFormFields]),
|
|
85
91
|
initialValues: {},
|
|
86
92
|
requiredMessage: t("validations.required.field.error"),
|
|
87
93
|
validateOnBlur: true,
|
|
88
94
|
validateOnChange: false
|
|
89
95
|
});
|
|
96
|
+
(0, react.useEffect)(() => {
|
|
97
|
+
clearFormErrors();
|
|
98
|
+
if (!serverFieldErrors || serverFieldErrors.length === 0) return;
|
|
99
|
+
const errors = {};
|
|
100
|
+
const touched = {};
|
|
101
|
+
for (const fe of serverFieldErrors) if (!(fe.identifier in errors)) {
|
|
102
|
+
errors[fe.identifier] = fe.message;
|
|
103
|
+
touched[fe.identifier] = true;
|
|
104
|
+
}
|
|
105
|
+
setTouchedFields(touched);
|
|
106
|
+
setFormErrors(errors);
|
|
107
|
+
}, [
|
|
108
|
+
serverFieldErrors,
|
|
109
|
+
setFormErrors,
|
|
110
|
+
setTouchedFields,
|
|
111
|
+
clearFormErrors
|
|
112
|
+
]);
|
|
90
113
|
/**
|
|
91
114
|
* Handle input value changes.
|
|
92
115
|
* Only updates the value without marking as touched.
|
|
@@ -114,9 +137,10 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
114
137
|
setApiError(null);
|
|
115
138
|
clearMessages();
|
|
116
139
|
try {
|
|
140
|
+
const composedData = data ? require_composeAffixedInputs.default(data, vendor) : void 0;
|
|
117
141
|
const filteredInputs = {};
|
|
118
|
-
if (
|
|
119
|
-
if (
|
|
142
|
+
if (composedData) Object.keys(composedData).forEach((key) => {
|
|
143
|
+
if (composedData[key] !== void 0 && composedData[key] !== null && composedData[key] !== "") filteredInputs[key] = composedData[key];
|
|
120
144
|
});
|
|
121
145
|
let payload = {};
|
|
122
146
|
payload = {
|
|
@@ -151,7 +175,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
151
175
|
/**
|
|
152
176
|
* Render components based on flow data using the factory
|
|
153
177
|
*/
|
|
154
|
-
const renderComponents = (0, react.useCallback)((flowComponents) => require_AuthOptionFactory.renderSignInComponents(flowComponents, formValues, touchedFields, formErrors, isLoading, isFormValid, handleInputChange, {
|
|
178
|
+
const renderComponents = (0, react.useCallback)((flowComponents) => require_AuthOptionFactory.renderSignInComponents(flowComponents, formValues, touchedFields, formErrors, isLoading, isFormValid, resetForm, handleInputChange, {
|
|
155
179
|
_customRenderers: customRenderers,
|
|
156
180
|
_theme: theme,
|
|
157
181
|
additionalData,
|
|
@@ -163,7 +187,8 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
163
187
|
onSubmit: handleSubmit,
|
|
164
188
|
size,
|
|
165
189
|
t,
|
|
166
|
-
variant
|
|
190
|
+
variant,
|
|
191
|
+
vendor
|
|
167
192
|
}), [
|
|
168
193
|
additionalData,
|
|
169
194
|
customRenderers,
|
|
@@ -177,6 +202,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
177
202
|
isLoading,
|
|
178
203
|
size,
|
|
179
204
|
variant,
|
|
205
|
+
vendor,
|
|
180
206
|
inputClasses,
|
|
181
207
|
buttonClasses,
|
|
182
208
|
handleInputBlur,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSignIn.cjs","names":["BaseSignInContent: FC<BaseSignInProps>","useThunderID","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","styles: any","useStyles","isLoading: boolean","handleError: any","errorMessage: string","extractErrorMessage","extractFormFields: (components: EmbeddedFlowComponent[]) => FormField[]","fields: FormField[]","identifier: string","useForm","filteredInputs: Record<string, any>","payload: EmbeddedSignInFlowRequest","containerClasses: any","inputClasses: any","buttonClasses: any","messageClasses: any","renderComponents: any","renderSignInComponents","renderProps: BaseSignInRenderProps","result: any","CardPrimitive","Spinner","AlertPrimitive","Typography","BaseSignIn: FC<BaseSignInProps>","content: ReactElement","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/SignIn/BaseSignIn.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 withVendorCSSClassPrefix,\n EmbeddedSignInFlowRequest,\n EmbeddedFlowComponent,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n} from '@thunderid/browser';\nimport {FC, useState, useCallback, useContext, ReactElement, ReactNode} from 'react';\nimport useStyles from './BaseSignIn.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {FormField, useForm} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport {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 {renderSignInComponents} from '../AuthOptionFactory';\n\n/**\n * Render props for custom UI rendering\n */\nexport interface BaseSignInRenderProps {\n /**\n * Flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * API error (if any)\n */\n error?: Error | null;\n\n /**\n * Field validation errors\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to handle input changes\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission\n */\n handleSubmit: (component: EmbeddedFlowComponent, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state\n */\n isLoading: boolean;\n\n /**\n * Flag indicating if the step timer has reached zero\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Whether the form is valid\n */\n isValid: boolean;\n\n /**\n * Flow messages\n */\n messages: {message: string; type: string}[];\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Flow subtitle\n */\n subtitle: string;\n\n /**\n * Flow title\n */\n title: string;\n\n /**\n * Touched fields\n */\n touched: Record<string, boolean>;\n\n /**\n * Function to validate the form\n */\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n\n /**\n * Form values\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseSignIn component.\n */\nexport interface BaseSignInProps {\n /**\n * Additional data from the flow response.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Custom CSS class name for the submit button.\n */\n buttonClassName?: string;\n\n /**\n * Render props function for custom UI\n */\n children?: (props: BaseSignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Array of flow components to render.\n */\n components?: EmbeddedFlowComponent[];\n\n /**\n * Error object to display\n */\n error?: Error | null;\n\n /**\n * Custom CSS class name for error messages.\n */\n errorClassName?: string;\n\n /**\n * Custom CSS class name for form inputs.\n */\n inputClassName?: string;\n\n /**\n * Flag to determine if the component is ready to be rendered.\n */\n isLoading?: boolean;\n\n /**\n * Timer flag disabling actions\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Custom CSS class name for info messages.\n */\n messageClassName?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Function to handle form submission.\n * @param payload - The form data to submit.\n * @param component - The component that triggered the submission.\n */\n onSubmit?: (payload: EmbeddedSignInFlowRequest, component: EmbeddedFlowComponent) => Promise<void>;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * HTML id attribute for the form container.\n */\n id?: string;\n\n /**\n * Field-level validation errors returned by the server in `data.fieldErrors` on the\n * most recent flow response. The component collapses these into the form's\n * `fieldErrors` state (first error per field wins), surfacing them through the same\n * render-prop / UI path as client-side validation errors. The full array is preserved\n * here for advanced consumers that want every failing rule per field.\n */\n serverFieldErrors?: FieldError[] | null;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that consumes FlowContext and renders the sign-in UI.\n */\nconst BaseSignInContent: FC<BaseSignInProps> = ({\n components = [],\n onSubmit,\n onError,\n error: externalError,\n id,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isLoading: externalIsLoading,\n children,\n additionalData = {},\n isTimeoutDisabled = false,\n}: BaseSignInProps): ReactElement => {\n const {meta} = useThunderID();\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const isLoading: boolean = externalIsLoading || isSubmitting;\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);\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear existing messages and add the error message\n clearMessages();\n addMessage({\n message: errorMessage,\n type: 'error',\n });\n },\n [t, addMessage, clearMessages],\n );\n\n /**\n * Extract form fields from flow components\n */\n const extractFormFields: (components: EmbeddedFlowComponent[]) => FormField[] = useCallback(\n (flowComponents: EmbeddedFlowComponent[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: EmbeddedFlowComponent[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === 'TEXT_INPUT' ||\n component.type === 'PASSWORD_INPUT' ||\n component.type === 'EMAIL_INPUT' ||\n component.type === 'PHONE_INPUT' ||\n component.type === 'OTP_INPUT'\n ) {\n const identifier: string = component.ref;\n fields.push({\n initialValue: '',\n name: identifier,\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 // Add email validation if it's an email field\n if (\n (component.type === 'EMAIL_INPUT' || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n\n return null;\n },\n });\n }\n if (component.components) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(flowComponents);\n return fields;\n },\n [t],\n );\n\n const formFields: FormField[] = components ? extractFormFields(components) : [];\n\n const form: ReturnType<typeof useForm> = 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 validateForm,\n touchAllFields,\n } = form;\n\n /**\n * Handle input value changes.\n * Only updates the value without marking as touched.\n * Touched state is set on blur to avoid premature validation.\n */\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n /**\n * Handle input blur event.\n * Marks the field as touched, which triggers validation.\n */\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n /**\n * Handle component submission (for buttons and actions).\n */\n const handleSubmit = async (\n component: EmbeddedFlowComponent,\n data?: Record<string, any>,\n skipValidation?: boolean,\n ): Promise<void> => {\n // Only validate for form submit actions, skip for social/trigger actions\n if (!skipValidation) {\n // Mark all fields as touched before validation\n touchAllFields();\n\n const validation: ReturnType<typeof validateForm> = validateForm();\n\n if (!validation.isValid) {\n return;\n }\n }\n\n setIsSubmitting(true);\n setApiError(null);\n clearMessages();\n\n try {\n // Filter out empty or undefined input values\n const filteredInputs: Record<string, any> = {};\n if (data) {\n Object.keys(data).forEach((key: any) => {\n if (data[key] !== undefined && data[key] !== null && data[key] !== '') {\n filteredInputs[key] = data[key];\n }\n });\n }\n\n let payload: EmbeddedSignInFlowRequest = {};\n\n // For V2, we always send inputs and action\n payload = {\n ...payload,\n ...(component.id && {action: component.id}),\n inputs: filteredInputs,\n };\n\n await onSubmit?.(payload, component);\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n // Generate CSS classes\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin'),\n withVendorCSSClassPrefix(`signin--${size}`),\n withVendorCSSClassPrefix(`signin--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin__input'),\n size === 'small' && withVendorCSSClassPrefix('signin__input--small'),\n size === 'large' && withVendorCSSClassPrefix('signin__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin__button'),\n size === 'small' && withVendorCSSClassPrefix('signin__button--small'),\n size === 'large' && withVendorCSSClassPrefix('signin__button--large'),\n ],\n buttonClassName,\n );\n\n const messageClasses: any = cx([withVendorCSSClassPrefix('signin__messages')], messageClassName);\n\n /**\n * Render components based on flow data using the factory\n */\n const renderComponents: any = useCallback(\n (flowComponents: EmbeddedFlowComponent[]): ReactElement[] =>\n renderSignInComponents(\n flowComponents,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n isTimeoutDisabled,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n t,\n variant,\n },\n ),\n [\n additionalData,\n customRenderers,\n formValues,\n touchedFields,\n formErrors,\n isFormValid,\n meta,\n t,\n theme,\n isLoading,\n size,\n variant,\n inputClasses,\n buttonClasses,\n handleInputBlur,\n handleSubmit,\n isTimeoutDisabled,\n ],\n );\n\n // If render props are provided, use them\n if (children) {\n const renderProps: BaseSignInRenderProps = {\n components,\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isTimeoutDisabled,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle ?? '',\n title: flowTitle || t('signin.heading'),\n touched: touchedFields,\n validateForm: () => {\n const result: any = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return (\n <div id={id} className={containerClasses} data-testid=\"thunderid-signin\">\n {children(renderProps)}\n </div>\n );\n }\n\n // Default UI rendering\n if (isLoading) {\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\n >\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!components || components.length === 0) {\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\n >\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.signin.components.not.available')}</Typography>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\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: any) => (\n <AlertPrimitive\n key={index}\n variant={message.type === '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}>{renderComponents(components)}</div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * Base SignIn component that provides generic authentication flow.\n * This component handles component-driven UI rendering and can transform input\n * structure to component-driven format automatically.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { BaseSignIn } from '@thunderid/react';\n *\n * const MySignIn = () => {\n * return (\n * <BaseSignIn\n * components={components}\n * onSubmit={async (payload) => {\n * return await handleAuth(payload);\n * }}\n * onSuccess={(authData) => {\n * console.log('Success:', authData);\n * }}\n * className=\"max-w-md mx-auto\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * <BaseSignIn components={components} onSubmit={handleSubmit}>\n * {({values, errors, handleInputChange, handleSubmit, isLoading, components}) => (\n * <div className=\"custom-form\">\n * <input\n * name=\"username\"\n * value={values.username || ''}\n * onChange={(e) => handleInputChange('username', e.target.value)}\n * />\n * {errors.username && <span>{errors.username}</span>}\n * <button\n * onClick={() => handleSubmit(components[0], values)}\n * disabled={isLoading}\n * >\n * Sign In\n * </button>\n * </div>\n * )}\n * </BaseSignIn>\n * ```\n */\nconst BaseSignIn: FC<BaseSignInProps> = ({preferences, ...rest}: BaseSignInProps): ReactElement => {\n const content: ReactElement = (\n <FlowProvider>\n <BaseSignInContent {...rest} />\n </FlowProvider>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseSignIn;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseSignIn.cjs","names":["BaseSignInContent: FC<BaseSignInProps>","useThunderID","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useFlow","styles: any","useStyles","isLoading: boolean","handleError: any","errorMessage: string","extractErrorMessage","extractFormFields: (components: EmbeddedFlowComponent[]) => FormField[]","fields: FormField[]","identifier: string","useForm","errors: Record<string, string>","touched: Record<string, boolean>","composedData: Record<string, any> | undefined","composeAffixedInputs","filteredInputs: Record<string, any>","payload: EmbeddedSignInFlowRequest","containerClasses: any","inputClasses: any","buttonClasses: any","messageClasses: any","renderComponents: any","renderSignInComponents","renderProps: BaseSignInRenderProps","result: any","CardPrimitive","Spinner","AlertPrimitive","Typography","BaseSignIn: FC<BaseSignInProps>","content: ReactElement","FlowProvider","ComponentPreferencesContext"],"sources":["../../../../../../src/components/presentation/auth/SignIn/BaseSignIn.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 withVendorCSSClassPrefix,\n EmbeddedSignInFlowRequest,\n EmbeddedFlowComponent,\n FieldError,\n FlowMetadataResponse,\n Preferences,\n buildValidatorFromRules,\n} from '@thunderid/browser';\nimport {FC, useEffect, useMemo, useState, useCallback, useContext, ReactElement, ReactNode} from 'react';\nimport useStyles from './BaseSignIn.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport FlowProvider from '../../../../contexts/Flow/FlowProvider';\nimport useFlow from '../../../../contexts/Flow/useFlow';\nimport ComponentPreferencesContext from '../../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\nimport {FormField, useForm} from '../../../../hooks/useForm';\nimport useTranslation from '../../../../hooks/useTranslation';\nimport composeAffixedInputs from '../../../../utils/composeAffixedInputs';\nimport {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 {renderSignInComponents} from '../AuthOptionFactory';\n\n/**\n * Render props for custom UI rendering\n */\nexport interface BaseSignInRenderProps {\n /**\n * Flow components\n */\n components: EmbeddedFlowComponent[];\n\n /**\n * API error (if any)\n */\n error?: Error | null;\n\n /**\n * Field validation errors\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Function to handle input changes\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission\n */\n handleSubmit: (component: EmbeddedFlowComponent, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Loading state\n */\n isLoading: boolean;\n\n /**\n * Flag indicating if the step timer has reached zero\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Whether the form is valid\n */\n isValid: boolean;\n\n /**\n * Flow messages\n */\n messages: {message: string; type: string}[];\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Flow subtitle\n */\n subtitle: string;\n\n /**\n * Flow title\n */\n title: string;\n\n /**\n * Touched fields\n */\n touched: Record<string, boolean>;\n\n /**\n * Function to validate the form\n */\n validateForm: () => {fieldErrors: Record<string, string>; isValid: boolean};\n\n /**\n * Form values\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseSignIn component.\n */\nexport interface BaseSignInProps {\n /**\n * Additional data from the flow response.\n */\n additionalData?: Record<string, any>;\n\n /**\n * Custom CSS class name for the submit button.\n */\n buttonClassName?: string;\n\n /**\n * Render props function for custom UI\n */\n children?: (props: BaseSignInRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name for the form container.\n */\n className?: string;\n\n /**\n * Array of flow components to render.\n */\n components?: EmbeddedFlowComponent[];\n\n /**\n * Error object to display\n */\n error?: Error | null;\n\n /**\n * Custom CSS class name for error messages.\n */\n errorClassName?: string;\n\n /**\n * Custom CSS class name for form inputs.\n */\n inputClassName?: string;\n\n /**\n * Flag to determine if the component is ready to be rendered.\n */\n isLoading?: boolean;\n\n /**\n * Timer flag disabling actions\n */\n isTimeoutDisabled?: boolean;\n\n /**\n * Custom CSS class name for info messages.\n */\n messageClassName?: string;\n\n /**\n * Callback function called when authentication fails.\n * @param error - The error that occurred during authentication.\n */\n onError?: (error: Error) => void;\n\n /**\n * Function to handle form submission.\n * @param payload - The form data to submit.\n * @param component - The component that triggered the submission.\n */\n onSubmit?: (payload: EmbeddedSignInFlowRequest, component: EmbeddedFlowComponent) => Promise<void>;\n\n /**\n * Callback function called when authentication is successful.\n * @param authData - The authentication data returned upon successful completion.\n */\n onSuccess?: (authData: Record<string, any>) => void;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * HTML id attribute for the form container.\n */\n id?: string;\n\n /**\n * Field-level validation errors returned by the server in `data.fieldErrors` on the\n * most recent flow response. The component collapses these into the form's\n * `fieldErrors` state (first error per field wins), surfacing them through the same\n * render-prop / UI path as client-side validation errors. The full array is preserved\n * here for advanced consumers that want every failing rule per field.\n */\n serverFieldErrors?: FieldError[] | null;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Internal component that consumes FlowContext and renders the sign-in UI.\n */\nconst BaseSignInContent: FC<BaseSignInProps> = ({\n components = [],\n onSubmit,\n onError,\n error: externalError,\n id,\n className = '',\n inputClassName = '',\n buttonClassName = '',\n messageClassName = '',\n size = 'medium',\n variant = 'outlined',\n isLoading: externalIsLoading,\n children,\n additionalData = {},\n isTimeoutDisabled = false,\n serverFieldErrors = null,\n}: BaseSignInProps): ReactElement => {\n const {meta, vendor} = useThunderID();\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages} = useFlow();\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [apiError, setApiError] = useState<Error | null>(null);\n\n const isLoading: boolean = externalIsLoading || isSubmitting;\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);\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Clear existing messages and add the error message\n clearMessages();\n addMessage({\n message: errorMessage,\n type: 'error',\n });\n },\n [t, addMessage, clearMessages],\n );\n\n /**\n * Extract form fields from flow components\n */\n const extractFormFields: (components: EmbeddedFlowComponent[]) => FormField[] = useCallback(\n (flowComponents: EmbeddedFlowComponent[]): FormField[] => {\n const fields: FormField[] = [];\n\n const processComponents = (comps: EmbeddedFlowComponent[]): any => {\n comps.forEach((component: any) => {\n if (\n component.type === 'TEXT_INPUT' ||\n component.type === 'PASSWORD_INPUT' ||\n component.type === 'EMAIL_INPUT' ||\n component.type === 'PHONE_INPUT' ||\n component.type === 'OTP_INPUT' ||\n component.type === 'SELECT' ||\n component.type === 'DATE_INPUT'\n ) {\n const identifier: string = component.ref;\n const ruleValidator = buildValidatorFromRules(component.validation);\n fields.push({\n initialValue: '',\n name: identifier,\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 // Add email validation if it's an email field\n if (\n (component.type === 'EMAIL_INPUT' || component.variant === 'EMAIL') &&\n value &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n ) {\n return t('field.email.invalid');\n }\n // Run declarative rules from meta.components[].validation.\n if (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n\n return null;\n },\n });\n }\n if (component.components) {\n processComponents(component.components);\n }\n });\n };\n\n processComponents(flowComponents);\n return fields;\n },\n [t],\n );\n\n const formFields: FormField[] = useMemo(\n () => (components ? extractFormFields(components) : []),\n [components, extractFormFields],\n );\n\n const form: ReturnType<typeof useForm> = 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 into form state. `setTouchedFields` is used instead\n // of `setTouched` so client-side `validateField` doesn't wipe server errors when the\n // client rules happen to pass.\n useEffect(() => {\n clearFormErrors();\n if (!serverFieldErrors || serverFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of serverFieldErrors) {\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 }, [serverFieldErrors, setFormErrors, setTouchedFields, clearFormErrors]);\n\n /**\n * Handle input value changes.\n * Only updates the value without marking as touched.\n * Touched state is set on blur to avoid premature validation.\n */\n const handleInputChange = (name: string, value: string): void => {\n setFormValue(name, value);\n };\n\n /**\n * Handle input blur event.\n * Marks the field as touched, which triggers validation.\n */\n const handleInputBlur = (name: string): void => {\n setFormTouched(name, true);\n };\n\n /**\n * Handle component submission (for buttons and actions).\n */\n const handleSubmit = async (\n component: EmbeddedFlowComponent,\n data?: Record<string, any>,\n skipValidation?: boolean,\n ): Promise<void> => {\n // Only validate for form submit actions, skip for social/trigger actions\n if (!skipValidation) {\n // Mark all fields as touched before validation\n touchAllFields();\n\n const validation: ReturnType<typeof validateForm> = validateForm();\n\n if (!validation.isValid) {\n return;\n }\n }\n\n setIsSubmitting(true);\n setApiError(null);\n clearMessages();\n\n try {\n const composedData: Record<string, any> | undefined = data\n ? composeAffixedInputs(data as Record<string, string>, vendor)\n : undefined;\n\n // Filter out empty or undefined input values\n const filteredInputs: Record<string, any> = {};\n if (composedData) {\n Object.keys(composedData).forEach((key: any) => {\n if (composedData[key] !== undefined && composedData[key] !== null && composedData[key] !== '') {\n filteredInputs[key] = composedData[key];\n }\n });\n }\n\n let payload: EmbeddedSignInFlowRequest = {};\n\n // For V2, we always send inputs and action\n payload = {\n ...payload,\n ...(component.id && {action: component.id}),\n inputs: filteredInputs,\n };\n\n await onSubmit?.(payload, component);\n } catch (err) {\n handleError(err);\n onError?.(err as Error);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n // Generate CSS classes\n const containerClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin'),\n withVendorCSSClassPrefix(`signin--${size}`),\n withVendorCSSClassPrefix(`signin--${variant}`),\n ],\n className,\n );\n\n const inputClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin__input'),\n size === 'small' && withVendorCSSClassPrefix('signin__input--small'),\n size === 'large' && withVendorCSSClassPrefix('signin__input--large'),\n ],\n inputClassName,\n );\n\n const buttonClasses: any = cx(\n [\n withVendorCSSClassPrefix('signin__button'),\n size === 'small' && withVendorCSSClassPrefix('signin__button--small'),\n size === 'large' && withVendorCSSClassPrefix('signin__button--large'),\n ],\n buttonClassName,\n );\n\n const messageClasses: any = cx([withVendorCSSClassPrefix('signin__messages')], messageClassName);\n\n /**\n * Render components based on flow data using the factory\n */\n const renderComponents: any = useCallback(\n (flowComponents: EmbeddedFlowComponent[]): ReactElement[] =>\n renderSignInComponents(\n flowComponents,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n additionalData,\n buttonClassName: buttonClasses,\n inputClassName: inputClasses,\n isTimeoutDisabled,\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n t,\n variant,\n vendor,\n },\n ),\n [\n additionalData,\n customRenderers,\n formValues,\n touchedFields,\n formErrors,\n isFormValid,\n meta,\n t,\n theme,\n isLoading,\n size,\n variant,\n vendor,\n inputClasses,\n buttonClasses,\n handleInputBlur,\n handleSubmit,\n isTimeoutDisabled,\n ],\n );\n\n // If render props are provided, use them\n if (children) {\n const renderProps: BaseSignInRenderProps = {\n components,\n error: apiError,\n fieldErrors: formErrors,\n handleInputChange,\n handleSubmit,\n isLoading,\n isTimeoutDisabled,\n isValid: isFormValid,\n messages: flowMessages || [],\n meta,\n subtitle: flowSubtitle ?? '',\n title: flowTitle || t('signin.heading'),\n touched: touchedFields,\n validateForm: () => {\n const result: any = validateForm();\n return {fieldErrors: result.errors, isValid: result.isValid};\n },\n values: formValues,\n };\n\n return (\n <div id={id} className={containerClasses} data-testid=\"thunderid-signin\">\n {children(renderProps)}\n </div>\n );\n }\n\n // Default UI rendering\n if (isLoading) {\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\n >\n <CardPrimitive.Content>\n <div style={{display: 'flex', justifyContent: 'center', padding: '2rem'}}>\n <Spinner />\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n if (!components || components.length === 0) {\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\n >\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">{t('errors.signin.components.not.available')}</Typography>\n </AlertPrimitive>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n return (\n <CardPrimitive\n id={id}\n className={cx(containerClasses, styles.card)}\n data-testid=\"thunderid-signin\"\n variant={variant}\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: any) => (\n <AlertPrimitive\n key={index}\n variant={message.type === '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}>{renderComponents(components)}</div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\n/**\n * Base SignIn component that provides generic authentication flow.\n * This component handles component-driven UI rendering and can transform input\n * structure to component-driven format automatically.\n *\n * @example\n * // Default UI\n * ```tsx\n * import { BaseSignIn } from '@thunderid/react';\n *\n * const MySignIn = () => {\n * return (\n * <BaseSignIn\n * components={components}\n * onSubmit={async (payload) => {\n * return await handleAuth(payload);\n * }}\n * onSuccess={(authData) => {\n * console.log('Success:', authData);\n * }}\n * className=\"max-w-md mx-auto\"\n * />\n * );\n * };\n * ```\n *\n * @example\n * // Custom UI with render props\n * ```tsx\n * <BaseSignIn components={components} onSubmit={handleSubmit}>\n * {({values, errors, handleInputChange, handleSubmit, isLoading, components}) => (\n * <div className=\"custom-form\">\n * <input\n * name=\"username\"\n * value={values.username || ''}\n * onChange={(e) => handleInputChange('username', e.target.value)}\n * />\n * {errors.username && <span>{errors.username}</span>}\n * <button\n * onClick={() => handleSubmit(components[0], values)}\n * disabled={isLoading}\n * >\n * Sign In\n * </button>\n * </div>\n * )}\n * </BaseSignIn>\n * ```\n */\nconst BaseSignIn: FC<BaseSignInProps> = ({preferences, ...rest}: BaseSignInProps): ReactElement => {\n const content: ReactElement = (\n <FlowProvider>\n <BaseSignInContent {...rest} />\n </FlowProvider>\n );\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseSignIn;\n"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ const require_useTranslation = require('../../../../hooks/useTranslation.cjs');
|
|
|
9
9
|
const require_flowTransformer = require('../../../../utils/flowTransformer.cjs');
|
|
10
10
|
const require_useForm = require('../../../../hooks/useForm.cjs');
|
|
11
11
|
const require_Spinner = require('../../../primitives/Spinner/Spinner.cjs');
|
|
12
|
+
const require_composeAffixedInputs = require('../../../../utils/composeAffixedInputs.cjs');
|
|
12
13
|
const require_Typography = require('../../../primitives/Typography/Typography.cjs');
|
|
13
14
|
const require_Alert = require('../../../primitives/Alert/Alert.cjs');
|
|
14
15
|
const require_Card = require('../../../primitives/Card/Card.cjs');
|
|
@@ -36,7 +37,7 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
36
37
|
const customRenderers = (0, react.useContext)(require_ComponentRendererContext.default);
|
|
37
38
|
const { t } = require_useTranslation.default();
|
|
38
39
|
const { subtitle: flowSubtitle, title: flowTitle, messages: flowMessages, addMessage, clearMessages } = require_useFlow.default();
|
|
39
|
-
const { meta, isInitialized: isSdkInitialized, getStorageManager } = require_useThunderID.default();
|
|
40
|
+
const { meta, isInitialized: isSdkInitialized, getStorageManager, vendor } = require_useThunderID.default();
|
|
40
41
|
const styles = require_BaseSignUp_styles.default(theme, colorScheme);
|
|
41
42
|
const [isLoading, setIsLoading] = (0, react.useState)(false);
|
|
42
43
|
const [isFlowInitialized, setIsFlowInitialized] = (0, react.useState)(false);
|
|
@@ -149,30 +150,29 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
149
150
|
processComponents(components);
|
|
150
151
|
return fields;
|
|
151
152
|
}, [t]);
|
|
152
|
-
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = require_useForm.useForm({
|
|
153
|
+
const { values: formValues, touched: touchedFields, errors: formErrors, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = require_useForm.useForm({
|
|
153
154
|
fields: (0, react.useMemo)(() => (currentFlow?.data)?.components ? extractFormFields(currentFlow.data.components) : [], [currentFlow, extractFormFields]),
|
|
154
155
|
initialValues: {},
|
|
155
156
|
requiredMessage: t("validations.required.field.error"),
|
|
156
157
|
validateOnBlur: true,
|
|
157
158
|
validateOnChange: false
|
|
158
159
|
});
|
|
159
|
-
/**
|
|
160
|
-
* Project server-side validation errors from the most recent flow response into the
|
|
161
|
-
* form's `errors` state. See BaseSignIn for the same pattern: first error per field
|
|
162
|
-
* wins, and the affected fields are marked touched so the error renders immediately.
|
|
163
|
-
*/
|
|
164
160
|
(0, react.useEffect)(() => {
|
|
165
161
|
clearFormErrors();
|
|
166
162
|
const responseFieldErrors = (currentFlow?.data)?.fieldErrors;
|
|
167
163
|
if (!responseFieldErrors || responseFieldErrors.length === 0) return;
|
|
168
164
|
const errors = {};
|
|
169
|
-
|
|
165
|
+
const touched = {};
|
|
166
|
+
for (const fe of responseFieldErrors) if (!(fe.identifier in errors)) {
|
|
167
|
+
errors[fe.identifier] = fe.message;
|
|
168
|
+
touched[fe.identifier] = true;
|
|
169
|
+
}
|
|
170
|
+
setTouchedFields(touched);
|
|
170
171
|
setFormErrors(errors);
|
|
171
|
-
Object.keys(errors).forEach((field) => setFormTouched(field, true));
|
|
172
172
|
}, [
|
|
173
173
|
currentFlow,
|
|
174
174
|
setFormErrors,
|
|
175
|
-
|
|
175
|
+
setTouchedFields,
|
|
176
176
|
clearFormErrors
|
|
177
177
|
]);
|
|
178
178
|
/**
|
|
@@ -380,8 +380,9 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
380
380
|
setApiError(null);
|
|
381
381
|
clearMessages();
|
|
382
382
|
try {
|
|
383
|
+
const composedData = data ? require_composeAffixedInputs.default(data, vendor) : void 0;
|
|
383
384
|
const filteredInputs = {};
|
|
384
|
-
if (
|
|
385
|
+
if (composedData) Object.entries(composedData).forEach(([key, value]) => {
|
|
385
386
|
if (value !== null && value !== void 0 && value !== "") filteredInputs[key] = value;
|
|
386
387
|
});
|
|
387
388
|
const response = normalizeFlowResponseLocal(await onSubmit({
|
|
@@ -498,7 +499,7 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
498
499
|
/**
|
|
499
500
|
* Render form components based on flow data using the factory
|
|
500
501
|
*/
|
|
501
|
-
const renderComponents = (0, react.useCallback)((components) => require_AuthOptionFactory.renderSignUpComponents(components, formValues, touchedFields, formErrors, isLoading, isFormValid, handleInputChange, {
|
|
502
|
+
const renderComponents = (0, react.useCallback)((components) => require_AuthOptionFactory.renderSignUpComponents(components, formValues, touchedFields, formErrors, isLoading, isFormValid, resetForm, handleInputChange, {
|
|
502
503
|
_customRenderers: customRenderers,
|
|
503
504
|
_theme: theme,
|
|
504
505
|
buttonClassName: buttonClasses,
|
|
@@ -506,7 +507,8 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
506
507
|
onInputBlur: handleInputBlur,
|
|
507
508
|
onSubmit: handleSubmit,
|
|
508
509
|
size,
|
|
509
|
-
variant
|
|
510
|
+
variant,
|
|
511
|
+
vendor
|
|
510
512
|
}), [
|
|
511
513
|
customRenderers,
|
|
512
514
|
formValues,
|
|
@@ -517,6 +519,7 @@ const BaseSignUpContent = ({ afterSignUpUrl, onInitialize, onSubmit, onError, on
|
|
|
517
519
|
size,
|
|
518
520
|
theme,
|
|
519
521
|
variant,
|
|
522
|
+
vendor,
|
|
520
523
|
inputClasses,
|
|
521
524
|
buttonClasses,
|
|
522
525
|
handleSubmit,
|