diff --git a/.changeset/chatty-bugs-agree.md b/.changeset/chatty-bugs-agree.md new file mode 100644 index 00000000..a5e69c1b --- /dev/null +++ b/.changeset/chatty-bugs-agree.md @@ -0,0 +1,5 @@ +--- +'@asgardeo/react': patch +--- + +Clear input fields for error in invite flow diff --git a/packages/react/src/components/presentation/auth/AcceptInvite/v2/BaseAcceptInvite.tsx b/packages/react/src/components/presentation/auth/AcceptInvite/v2/BaseAcceptInvite.tsx index a7908b84..0069e932 100644 --- a/packages/react/src/components/presentation/auth/AcceptInvite/v2/BaseAcceptInvite.tsx +++ b/packages/react/src/components/presentation/auth/AcceptInvite/v2/BaseAcceptInvite.tsx @@ -34,6 +34,22 @@ import Spinner from '../../../../primitives/Spinner/Spinner'; import Typography from '../../../../primitives/Typography/Typography'; import {renderInviteUserComponents} from '../../AuthOptionFactory'; +/** + * Build a map of empty strings for all form field refs in the given components. + * Used to clear controlled inputs on step transitions without making them uncontrolled. + */ +const buildClearedFormValues = (components: any[]): Record => { + const result: Record = {}; + const collect = (comps: any[]): void => + comps.forEach((c: any) => { + if ((c.type === 'TEXT_INPUT' || c.type === 'EMAIL_INPUT' || c.type === 'SELECT') && c.ref) + result[c.ref as string] = ''; + if (c.components) collect(c.components); + }); + collect(components); + return result; +}; + /** * Flow response structure from the backend. */ @@ -361,8 +377,9 @@ const BaseAcceptInvite: FC = ({ onFlowChange?.(response); // Initialize currentFlow for next steps if not complete if (response.flowStatus !== 'COMPLETE') { + const nextComponents: any[] = response.data?.components || response.data?.meta?.components || []; setCurrentFlow(response); - setFormValues({}); + setFormValues(buildClearedFormValues(nextComponents)); setFormErrors({}); setTouchedFields({}); } @@ -512,9 +529,10 @@ const BaseAcceptInvite: FC = ({ return; } - // Update current flow and reset form for next step + // Update current flow and clear form values. + const nextComponents: any[] = response.data?.components || response.data?.meta?.components || []; setCurrentFlow(response); - setFormValues({}); + setFormValues(buildClearedFormValues(nextComponents)); setFormErrors({}); setTouchedFields({}); } catch (err) { diff --git a/packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx b/packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx index dc59d2e5..f8a59a60 100644 --- a/packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx +++ b/packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx @@ -229,6 +229,22 @@ export interface BaseInviteUserProps { variant?: CardProps['variant']; } +/** + * Build a map of empty strings for all form field refs in the given components. + * Used to clear controlled inputs on step transitions without making them uncontrolled. + */ +const buildClearedFormValues = (components: any[]): Record => { + const result: Record = {}; + const collect = (comps: any[]): void => + comps.forEach((c: any) => { + if ((c.type === 'TEXT_INPUT' || c.type === 'EMAIL_INPUT' || c.type === 'SELECT') && c.ref) + result[c.ref as string] = ''; + if (c.components) collect(c.components); + }); + collect(components); + return result; +}; + /** * Base component for invite user flow. * Handles the flow logic for creating a user and generating an invite link. @@ -454,9 +470,10 @@ const BaseInviteUser: FC = ({ return; } - // Update current flow and reset form for next step + // Update current flow and clear form values. + const nextComponents: any[] = response.data?.components || response.data?.meta?.components || []; setCurrentFlow(response); - setFormValues({}); + setFormValues(buildClearedFormValues(nextComponents)); setFormErrors({}); setTouchedFields({}); } catch (err) {