@thunderid/react 1.17.1 → 1.19.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/account/VerifyAttribute/BaseVerifyAttribute.cjs +6 -1
- package/dist/cjs/components/account/VerifyAttribute/BaseVerifyAttribute.cjs.map +1 -1
- package/dist/cjs/components/auth/AcceptInvite/BaseAcceptInvite.cjs +5 -0
- package/dist/cjs/components/auth/AcceptInvite/BaseAcceptInvite.cjs.map +1 -1
- package/dist/cjs/components/auth/InviteUser/BaseInviteUser.cjs +8 -0
- package/dist/cjs/components/auth/InviteUser/BaseInviteUser.cjs.map +1 -1
- package/dist/cjs/components/auth/Recovery/BaseRecovery.cjs +9 -1
- package/dist/cjs/components/auth/Recovery/BaseRecovery.cjs.map +1 -1
- package/dist/cjs/components/auth/SignIn/BaseSignIn.cjs +11 -4
- package/dist/cjs/components/auth/SignIn/BaseSignIn.cjs.map +1 -1
- package/dist/cjs/components/auth/SignUp/BaseSignUp.cjs +9 -1
- package/dist/cjs/components/auth/SignUp/BaseSignUp.cjs.map +1 -1
- package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs +3 -1
- package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs.map +1 -1
- package/dist/cjs/contexts/ComponentRenderer/ComponentRendererContext.cjs.map +1 -1
- package/dist/cjs/hooks/auth/useStepExpiry.cjs +25 -0
- package/dist/cjs/hooks/auth/useStepExpiry.cjs.map +1 -0
- package/dist/cjs/hooks/useForm.cjs +2 -0
- package/dist/cjs/hooks/useForm.cjs.map +1 -1
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.d.ts.map +1 -1
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.js +6 -1
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.js.map +1 -1
- package/dist/components/auth/AcceptInvite/BaseAcceptInvite.d.ts.map +1 -1
- package/dist/components/auth/AcceptInvite/BaseAcceptInvite.js +5 -0
- package/dist/components/auth/AcceptInvite/BaseAcceptInvite.js.map +1 -1
- package/dist/components/auth/InviteUser/BaseInviteUser.d.ts.map +1 -1
- package/dist/components/auth/InviteUser/BaseInviteUser.js +8 -0
- package/dist/components/auth/InviteUser/BaseInviteUser.js.map +1 -1
- package/dist/components/auth/Recovery/BaseRecovery.d.ts.map +1 -1
- package/dist/components/auth/Recovery/BaseRecovery.js +9 -1
- package/dist/components/auth/Recovery/BaseRecovery.js.map +1 -1
- package/dist/components/auth/SignIn/BaseSignIn.d.ts.map +1 -1
- package/dist/components/auth/SignIn/BaseSignIn.js +11 -4
- package/dist/components/auth/SignIn/BaseSignIn.js.map +1 -1
- package/dist/components/auth/SignUp/BaseSignUp.d.ts.map +1 -1
- package/dist/components/auth/SignUp/BaseSignUp.js +9 -1
- package/dist/components/auth/SignUp/BaseSignUp.js.map +1 -1
- package/dist/components/auth/flow/AuthOptionFactory.d.ts +20 -0
- package/dist/components/auth/flow/AuthOptionFactory.d.ts.map +1 -1
- package/dist/components/auth/flow/AuthOptionFactory.js +3 -1
- package/dist/components/auth/flow/AuthOptionFactory.js.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts +2 -15
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.js.map +1 -1
- package/dist/hooks/auth/useStepExpiry.d.ts +17 -0
- package/dist/hooks/auth/useStepExpiry.d.ts.map +1 -0
- package/dist/hooks/auth/useStepExpiry.js +23 -0
- package/dist/hooks/auth/useStepExpiry.js.map +1 -0
- package/dist/hooks/useForm.d.ts +6 -0
- package/dist/hooks/useForm.d.ts.map +1 -1
- package/dist/hooks/useForm.js +3 -1
- package/dist/hooks/useForm.js.map +1 -1
- package/package.json +2 -2
|
@@ -10,6 +10,7 @@ const require_useForm = require('../../../hooks/useForm.cjs');
|
|
|
10
10
|
const require_Spinner = require('../../primitives/Spinner/Spinner.cjs');
|
|
11
11
|
const require_Button = require('../../primitives/Button/Button.cjs');
|
|
12
12
|
const require_Typography = require('../../primitives/Typography/Typography.cjs');
|
|
13
|
+
const require_useStepExpiry = require('../../../hooks/auth/useStepExpiry.cjs');
|
|
13
14
|
const require_composeAffixedInputs = require('../../../utils/composeAffixedInputs.cjs');
|
|
14
15
|
const require_Alert = require('../../primitives/Alert/Alert.cjs');
|
|
15
16
|
const require_AuthOptionFactory = require('../../auth/flow/AuthOptionFactory.cjs');
|
|
@@ -98,13 +99,14 @@ const BaseVerifyAttributeContent = ({ attributeDisplayName = "", buttonClassName
|
|
|
98
99
|
};
|
|
99
100
|
}), [t]);
|
|
100
101
|
const formFields = (0, react.useMemo)(() => extractFormFields(currentFlow?.data?.components ?? []), [currentFlow, extractFormFields]);
|
|
101
|
-
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({
|
|
102
|
+
const { values: formValues, touched: touchedFields, errors: formErrors, isComplete: isFormComplete, isValid: isFormValid, setValue: setFormValue, setTouched: setFormTouched, setTouchedFields, setErrors: setFormErrors, clearErrors: clearFormErrors, validateForm, touchAllFields, reset: resetForm } = require_useForm.useForm({
|
|
102
103
|
fields: formFields,
|
|
103
104
|
initialValues: {},
|
|
104
105
|
requiredMessage: t("validations.required.field.error"),
|
|
105
106
|
validateOnBlur: true,
|
|
106
107
|
validateOnChange: false
|
|
107
108
|
});
|
|
109
|
+
const { expireStep, isStepExpired } = require_useStepExpiry.default(currentFlow);
|
|
108
110
|
(0, react.useEffect)(() => {
|
|
109
111
|
clearFormErrors();
|
|
110
112
|
const responseFieldErrors = currentFlow?.data?.fieldErrors;
|
|
@@ -306,8 +308,11 @@ const BaseVerifyAttributeContent = ({ attributeDisplayName = "", buttonClassName
|
|
|
306
308
|
additionalData,
|
|
307
309
|
buttonClassName: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("verify-attribute", "button")), buttonClassName),
|
|
308
310
|
inputClassName: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("verify-attribute", "input")), inputClassName),
|
|
311
|
+
isFormComplete,
|
|
312
|
+
isTimeoutDisabled: isStepExpired,
|
|
309
313
|
meta,
|
|
310
314
|
onInputBlur: handleInputBlur,
|
|
315
|
+
onStepExpire: expireStep,
|
|
311
316
|
onSubmit: (component, data, skip) => {
|
|
312
317
|
handleSubmit(component, data, skip);
|
|
313
318
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseVerifyAttribute.cjs","names":["props: {children?: ReactNode; name?: unknown}","testId","EmbeddedFlowComponentType","testId: string | undefined","children: ReactNode","BaseVerifyAttributeContent: FC<Omit<BaseVerifyAttributeProps, 'preferences'>>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useThunderID","styles: Record<string, string>","useStyles","isSubmittingRef: MutableRefObject<boolean>","initializationAttemptedRef: MutableRefObject<boolean>","challengeTokenRef: MutableRefObject<string | null>","labelParams: Record<string, string>","normalizeFlowResponse","formFields: FormField[]","useForm","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","response: EmbeddedSelfFlowResponse","EmbeddedSelfFlowStatus","message: string","extractErrorMessage","response: EmbeddedSelfFlowResponse | undefined","composedData: Record<string, string>","composeAffixedInputs","inputs: Record<string, string>","additionalData: Record<string, unknown>","maskedDestination: unknown","AttributeVerificationConstants","destination: string | null","headings: ReturnType<typeof getAuthComponentHeadings>","getAuthComponentHeadings","step: FlowStepComponents","isAwaitingLink: boolean","title: string","subtitle: string","destinationText: string | null","isLoading: boolean","containerClasses: string","cx","resend: EmbeddedFlowComponent | undefined","alertClasses: string","Typography","Spinner","AlertPrimitive","renderVerificationComponents","Button","BaseVerifyAttribute: FC<BaseVerifyAttributeProps>","content: ReactElement","ComponentPreferencesContext"],"sources":["../../../../../src/components/account/VerifyAttribute/BaseVerifyAttribute.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n AttributeVerificationConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentType,\n EmbeddedSelfFlowRequest,\n EmbeddedSelfFlowResponse,\n EmbeddedSelfFlowStatus,\n FieldError,\n FlowStepComponents,\n Preferences,\n bem,\n buildValidatorFromRules,\n getFlowStepComponents,\n resolveFlowTemplateLiterals,\n withVendorCSSClassPrefix,\n} from '@thunderid/browser';\nimport {\n FC,\n MutableRefObject,\n ReactElement,\n ReactNode,\n cloneElement,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport useStyles from './BaseVerifyAttribute.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\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 {cx} from '../../../styles/emotion';\nimport composeAffixedInputs from '../../../utils/composeAffixedInputs';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../utils/getAuthComponentHeadings';\nimport {renderVerificationComponents} from '../../auth/flow/AuthOptionFactory';\nimport AlertPrimitive from '../../primitives/Alert/Alert';\nimport Button from '../../primitives/Button/Button';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport Typography from '../../primitives/Typography/Typography';\n\ntype VerificationState = 'loading' | 'active' | 'complete' | 'failed';\n\ninterface FlowIds {\n actions: Set<string>;\n // Input name (`ref`, else `id`) to component type.\n fields: Map<string, string>;\n}\n\n// Flow identifiers of the step's inputs and actions.\nconst collectFlowIds = ({actions, inputs}: FlowStepComponents): FlowIds => ({\n actions: new Set(actions.map((component: EmbeddedFlowComponent) => component.id)),\n fields: new Map(inputs.map((component: EmbeddedFlowComponent) => [component.ref ?? component.id, component.type])),\n});\n\n// Tags the elements rendered from the flow with `thunderid-field-<ref>` and `thunderid-action-<id>`.\n// The shared factory keys an element by its component id and names an input by its ref.\nconst withFlowTestIds = (node: ReactNode, ids: FlowIds): ReactNode => {\n if (Array.isArray(node)) return node.map((child: ReactNode) => withFlowTestIds(child, ids));\n if (!isValidElement(node)) return node;\n\n const props: {children?: ReactNode; name?: unknown} = node.props as {children?: ReactNode; name?: unknown};\n if (typeof props.name === 'string' && ids.fields.has(props.name)) {\n const testId = `thunderid-field-${props.name}`;\n\n // The OTP field renders one input per character and takes no test identifier, so wrap it.\n if (ids.fields.get(props.name) === EmbeddedFlowComponentType.OtpInput) {\n return (\n <div key={node.key} data-testid={testId}>\n {node}\n </div>\n );\n }\n\n return cloneElement(node as ReactElement<Record<string, unknown>>, {'data-testid': testId});\n }\n\n const testId: string | undefined =\n node.key !== null && ids.actions.has(String(node.key)) ? `thunderid-action-${String(node.key)}` : undefined;\n const children: ReactNode = props.children === undefined ? undefined : withFlowTestIds(props.children, ids);\n if (!testId && children === props.children) return node;\n\n return cloneElement(node as ReactElement<Record<string, unknown>>, {\n ...(testId && {'data-testid': testId}),\n ...(props.children !== undefined && {children}),\n });\n};\n\n/**\n * What {@link BaseVerifyAttribute} hands its `children` render function, so the steps can be drawn\n * with any UI.\n */\nexport interface BaseVerifyAttributeRenderProps {\n additionalData: Record<string, unknown>;\n /**\n * The step's components, without its headings.\n */\n components: EmbeddedFlowComponent[];\n /**\n * Masked destination the code or link was sent to, when the flow reports it.\n */\n destination: string | null;\n /**\n * Translated \"Sent to …\" line, set when the flow has its own prompt in `subtitle`.\n */\n destinationText: string | null;\n /**\n * Translated error of the last request, or the refusal.\n */\n error: string | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n /**\n * Sends a new code. Set only while the step has a resend action.\n */\n handleResend?: () => Promise<void>;\n /**\n * Submits a step. Pass `skipValidation` for an action, such as a resend, that sends no inputs.\n */\n handleSubmit: (\n component: EmbeddedFlowComponent,\n data?: Record<string, string>,\n skipValidation?: boolean,\n ) => Promise<void>;\n isAwaitingLink: boolean;\n isComplete: boolean;\n /**\n * Whether the server refused the verification or the request failed; the flow cannot continue.\n */\n isFailed: boolean;\n isLoading: boolean;\n isValid: boolean;\n /**\n * Closes the panel. Set only when the app passes `onCancel`.\n */\n onCancel?: () => void;\n /**\n * Confirms a link the user opened outside the app. Set only while the step waits for a link and\n * the app passes `onDone`.\n */\n onDone?: () => void;\n subtitle: string;\n /**\n * Translated message for a recorded verification.\n */\n successMessage: string;\n title: string;\n touched: Record<string, boolean>;\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseVerifyAttribute component.\n */\nexport interface BaseVerifyAttributeProps {\n /**\n * Label of the attribute being verified, used in the default heading and success message.\n */\n attributeDisplayName?: string;\n buttonClassName?: string;\n /**\n * Renders custom UI in place of the default steps. Receives the step, the values and their setters,\n * submit, resend, cancel, the destination, and the loading, error and completed state.\n */\n children?: (props: BaseVerifyAttributeRenderProps) => ReactNode;\n className?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n /**\n * Called when the user closes the panel. The close action is shown only when this is set.\n */\n onCancel?: () => void;\n /**\n * Called once the server has recorded the verification.\n */\n onComplete?: (response: EmbeddedSelfFlowResponse) => void;\n /**\n * Called when the user selects Done after the flow sent a link, which they confirm outside the app.\n * The Done action is shown only when this is set.\n */\n onDone?: () => void;\n /**\n * Called when the server refuses the verification or the request fails.\n */\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedSelfFlowResponse) => void;\n onInitialize?: () => Promise<EmbeddedSelfFlowResponse>;\n onSubmit?: (payload: EmbeddedSelfFlowRequest) => Promise<EmbeddedSelfFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: 'outlined' | 'flat';\n}\n\n/**\n * Internal component that renders the verification steps and manages flow state.\n *\n * @internal\n */\nconst BaseVerifyAttributeContent: FC<Omit<BaseVerifyAttributeProps, 'preferences'>> = ({\n attributeDisplayName = '',\n buttonClassName = '',\n children = undefined,\n className = '',\n inputClassName = '',\n isInitialized = true,\n onCancel = undefined,\n onComplete = undefined,\n onDone = undefined,\n onError = undefined,\n onFlowChange = undefined,\n onInitialize = undefined,\n onSubmit = undefined,\n showSubtitle = true,\n showTitle = true,\n size = 'medium',\n variant = 'outlined',\n}: Omit<BaseVerifyAttributeProps, 'preferences'>): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {meta, vendor} = useThunderID();\n const styles: Record<string, string> = useStyles(theme, colorScheme);\n\n const [state, setState] = useState<VerificationState>('loading');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedSelfFlowResponse | null>(null);\n const [error, setError] = useState<string | null>(null);\n // Set before the first await, so a second call from a custom render cannot send a second code.\n const isSubmittingRef: MutableRefObject<boolean> = useRef(false);\n\n // Guards against a second initiation, which would send a second code.\n const initializationAttemptedRef: MutableRefObject<boolean> = useRef(false);\n const challengeTokenRef: MutableRefObject<string | null> = useRef<string | null>(null);\n\n const labelParams: Record<string, string> = {attribute: attributeDisplayName};\n\n const normalize = useCallback(\n (response: EmbeddedSelfFlowResponse): EmbeddedSelfFlowResponse => {\n if (!response?.data || Array.isArray(response.data.components)) {\n return response;\n }\n\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'user.verification.error', resolveTranslations: false, throwOnError: false},\n meta,\n );\n\n return {...response, data: {...response.data, components}};\n },\n [t, meta],\n );\n\n const extractFormFields = useCallback(\n (components: EmbeddedFlowComponent[]): FormField[] =>\n getFlowStepComponents(components).inputs.map((component: EmbeddedFlowComponent) => {\n const ruleValidator = buildValidatorFromRules(component.validation);\n return {\n initialValue: '',\n name: component.ref ?? component.id,\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 (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n return null;\n },\n };\n }),\n [t],\n );\n\n const formFields: FormField[] = useMemo(\n () => extractFormFields(currentFlow?.data?.components ?? []),\n [currentFlow, extractFormFields],\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 } = 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 // Project server-side field errors into form state.\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = currentFlow?.data?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n responseFieldErrors.forEach((fe: FieldError) => {\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 handleResponse = useCallback(\n (rawResponse: EmbeddedSelfFlowResponse): void => {\n const response: EmbeddedSelfFlowResponse = normalize(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedSelfFlowStatus.Error) {\n const message: string = extractErrorMessage(response, t, 'user.verification.error');\n setError(message);\n setState('failed');\n onError?.(new Error(message));\n return;\n }\n\n if (response.flowStatus === EmbeddedSelfFlowStatus.Complete) {\n setError(null);\n setState('complete');\n onComplete?.(response);\n return;\n }\n\n // INCOMPLETE: render the step; a rejected code comes back with an error and without\n // additionalData, so keep the destination and code length of the step that sent the code.\n setCurrentFlow(\n (previous: EmbeddedSelfFlowResponse | null): EmbeddedSelfFlowResponse =>\n response.data?.additionalData || !previous?.data?.additionalData\n ? response\n : {...response, data: {...response.data, additionalData: previous.data.additionalData}},\n );\n resetForm();\n setError(response.error ? extractErrorMessage(response, t, 'user.verification.error') : null);\n setState('active');\n },\n [normalize, onFlowChange, onError, onComplete, resetForm, t],\n );\n\n const handleFailure = useCallback(\n (caughtError: unknown): void => {\n // Show a generic message; an API error body is not meant for the user.\n setError(t('user.verification.error'));\n setState('failed');\n onError?.(caughtError instanceof Error ? caughtError : new Error(String(caughtError)));\n },\n [onError, t],\n );\n\n useEffect(() => {\n if (!isInitialized || initializationAttemptedRef.current) {\n return;\n }\n initializationAttemptedRef.current = true;\n\n void (async (): Promise<void> => {\n try {\n const response: EmbeddedSelfFlowResponse | undefined = await onInitialize?.();\n if (response) {\n handleResponse(response);\n }\n } catch (caughtError) {\n handleFailure(caughtError);\n }\n })();\n }, [isInitialized, onInitialize, handleResponse, handleFailure]);\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 (\n component: EmbeddedFlowComponent,\n data?: Record<string, string>,\n skipValidation?: boolean,\n ): Promise<void> => {\n if (!currentFlow || isSubmittingRef.current) return;\n\n if (!skipValidation) {\n touchAllFields();\n if (!validateForm().isValid) return;\n }\n\n isSubmittingRef.current = true;\n setIsSubmitting(true);\n setError(null);\n\n try {\n const composedData: Record<string, string> = data ? composeAffixedInputs(data, vendor) : {};\n const inputs: Record<string, string> = Object.fromEntries(\n Object.entries(composedData).filter(\n ([, value]: [string, string]) => value !== null && value !== undefined && value !== '',\n ),\n );\n\n const response: EmbeddedSelfFlowResponse | undefined = await onSubmit?.({\n executionId: currentFlow.executionId,\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs,\n });\n\n if (response) {\n handleResponse(response);\n }\n } catch (caughtError) {\n handleFailure(caughtError);\n } finally {\n isSubmittingRef.current = false;\n setIsSubmitting(false);\n }\n };\n\n const additionalData: Record<string, unknown> = currentFlow?.data?.additionalData ?? {};\n const maskedDestination: unknown = additionalData[AttributeVerificationConstants.MASKED_DESTINATION_KEY];\n const destination: string | null =\n typeof maskedDestination === 'string' && maskedDestination ? maskedDestination : null;\n const headings: ReturnType<typeof getAuthComponentHeadings> = getAuthComponentHeadings(\n currentFlow?.data?.components ?? [],\n undefined,\n undefined,\n t('user.verification.heading', labelParams),\n t('user.verification.subheading.generic'),\n );\n const {componentsWithoutHeadings} = headings;\n const step: FlowStepComponents = getFlowStepComponents(componentsWithoutHeadings ?? []);\n // A step with nothing to enter or submit waits for the user to open a link sent to them.\n const isAwaitingLink: boolean = state === 'active' && formFields.length === 0 && step.actions.length === 0;\n const title: string = resolveFlowTemplateLiterals(headings.title, {meta, t});\n // The flow's own prompt wins; the destination is added beside it, or fills in when the flow has none.\n const hasFlowSubtitle = !!headings.headingComponents.subheading;\n let subtitle: string = resolveFlowTemplateLiterals(headings.subtitle, {meta, t});\n let destinationText: string | null = null;\n if (destination && hasFlowSubtitle) {\n destinationText = t('user.verification.destination', {destination});\n } else if (destination) {\n subtitle = t(isAwaitingLink ? 'user.verification.subheading.link' : 'user.verification.subheading', {destination});\n }\n\n const isLoading: boolean = state === 'loading' || isSubmitting;\n\n const containerClasses: string = cx(\n withVendorCSSClassPrefix('verify-attribute'),\n withVendorCSSClassPrefix(`verify-attribute--${size}`),\n withVendorCSSClassPrefix(`verify-attribute--${variant}`),\n styles['root'],\n variant === 'outlined' ? styles['card'] : '',\n className,\n );\n\n if (children) {\n const resend: EmbeddedFlowComponent | undefined = state === 'active' ? step.resend : undefined;\n\n return (\n <div className={containerClasses}>\n {children({\n additionalData,\n components: componentsWithoutHeadings ?? [],\n destination,\n destinationText,\n error,\n fieldErrors: formErrors,\n handleInputChange,\n handleResend: resend ? (): Promise<void> => handleSubmit(resend, undefined, true) : undefined,\n handleSubmit,\n isAwaitingLink,\n isComplete: state === 'complete',\n isFailed: state === 'failed',\n isLoading,\n isValid: isFormValid,\n onCancel,\n onDone: isAwaitingLink ? onDone : undefined,\n subtitle,\n successMessage: t('user.verification.success', labelParams),\n title,\n touched: touchedFields,\n values: formValues,\n })}\n </div>\n );\n }\n\n const alertClasses: string = cx(withVendorCSSClassPrefix(bem('verify-attribute', 'alert')), styles['alert']);\n\n return (\n <div className={containerClasses} aria-busy={isLoading}>\n {state === 'active' && (showTitle || showSubtitle) && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'header')), styles['header'])}>\n {showTitle && (\n <Typography\n variant=\"h5\"\n className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'heading')), styles['heading'])}\n >\n {title}\n </Typography>\n )}\n {showSubtitle && (\n <Typography\n variant=\"body2\"\n className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'subheading')), styles['subheading'])}\n >\n {subtitle}\n {destinationText && (\n <span className={withVendorCSSClassPrefix(bem('verify-attribute', 'destination'))}>\n {` ${destinationText}`}\n </span>\n )}\n </Typography>\n )}\n </div>\n )}\n\n {state === 'loading' && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'loading')), styles['loading'])}>\n <Spinner size=\"medium\" />\n </div>\n )}\n\n {error && (\n <AlertPrimitive variant=\"error\" className={alertClasses}>\n <AlertPrimitive.Description>{error}</AlertPrimitive.Description>\n </AlertPrimitive>\n )}\n\n {state === 'complete' && (\n <AlertPrimitive variant=\"success\" className={alertClasses}>\n <AlertPrimitive.Description>{t('user.verification.success', labelParams)}</AlertPrimitive.Description>\n </AlertPrimitive>\n )}\n\n {state === 'active' && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'content')), styles['content'])}>\n {withFlowTestIds(\n renderVerificationComponents(\n componentsWithoutHeadings ?? [],\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: cx(withVendorCSSClassPrefix(bem('verify-attribute', 'button')), buttonClassName),\n inputClassName: cx(withVendorCSSClassPrefix(bem('verify-attribute', 'input')), inputClassName),\n meta,\n onInputBlur: handleInputBlur,\n onSubmit: (component: EmbeddedFlowComponent, data?: Record<string, string>, skip?: boolean): void => {\n void handleSubmit(component, data, skip);\n },\n size,\n t,\n variant,\n vendor,\n },\n ),\n collectFlowIds(step),\n )}\n </div>\n )}\n\n {(!!onCancel || (isAwaitingLink && !!onDone)) && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'actions')), styles['actions'])}>\n {isAwaitingLink && onDone && (\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"solid\"\n onClick={onDone}\n data-testid=\"thunderid-action-verificationDone\"\n >\n {t('user.verification.buttons.done.text')}\n </Button>\n )}\n {onCancel && (\n <Button\n size=\"small\"\n color=\"secondary\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={isSubmitting}\n data-testid=\"thunderid-action-verificationCancel\"\n >\n {state === 'active' || state === 'loading'\n ? t('user.verification.buttons.cancel.text')\n : t('user.verification.buttons.close.text')}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * BaseVerifyAttribute renders the server-described steps of a self attribute verification flow.\n * Accepts API functions as props to stay framework independent.\n */\nconst BaseVerifyAttribute: FC<BaseVerifyAttributeProps> = ({\n preferences = undefined,\n ...rest\n}: BaseVerifyAttributeProps): ReactElement => {\n const content: ReactElement = <BaseVerifyAttributeContent {...rest} />;\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseVerifyAttribute;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,MAAM,kBAAkB,EAAC,SAAS,cAA0C;CAC1E,SAAS,IAAI,IAAI,QAAQ,KAAK,cAAqC,UAAU,GAAG,CAAC;CACjF,QAAQ,IAAI,IAAI,OAAO,KAAK,cAAqC,CAAC,UAAU,OAAO,UAAU,IAAI,UAAU,KAAK,CAAC,CAAC;CACnH;AAID,MAAM,mBAAmB,MAAiB,QAA4B;AACpE,KAAI,MAAM,QAAQ,KAAK,CAAE,QAAO,KAAK,KAAK,UAAqB,gBAAgB,OAAO,IAAI,CAAC;AAC3F,KAAI,2BAAgB,KAAK,CAAE,QAAO;CAElC,MAAMA,QAAgD,KAAK;AAC3D,KAAI,OAAO,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,MAAM,KAAK,EAAE;EAChE,MAAMC,WAAS,mBAAmB,MAAM;AAGxC,MAAI,IAAI,OAAO,IAAI,MAAM,KAAK,KAAKC,8CAA0B,SAC3D,QACE,2CAAC;GAAmB,eAAaD;aAC9B;KADO,KAAK,IAET;AAIV,iCAAoB,MAA+C,EAAC,eAAeA,UAAO,CAAC;;CAG7F,MAAME,SACJ,KAAK,QAAQ,QAAQ,IAAI,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,GAAG,oBAAoB,OAAO,KAAK,IAAI,KAAK;CACpG,MAAMC,WAAsB,MAAM,aAAa,SAAY,SAAY,gBAAgB,MAAM,UAAU,IAAI;AAC3G,KAAI,CAAC,UAAU,aAAa,MAAM,SAAU,QAAO;AAEnD,gCAAoB,MAA+C;EACjE,GAAI,UAAU,EAAC,eAAe,QAAO;EACrC,GAAI,MAAM,aAAa,UAAa,EAAC,UAAS;EAC/C,CAAC;;;;;;;AAsHJ,MAAMC,8BAAiF,EACrF,uBAAuB,IACvB,kBAAkB,IAClB,WAAW,QACX,YAAY,IACZ,iBAAiB,IACjB,gBAAgB,MAChB,WAAW,QACX,aAAa,QACb,SAAS,QACT,UAAU,QACV,eAAe,QACf,eAAe,QACf,WAAW,QACX,eAAe,MACf,YAAY,MACZ,OAAO,UACP,UAAU,iBACuD;CACjE,MAAM,EAAC,OAAO,gBAAeC,0BAAU;CACvC,MAAMC,wCAAmDC,yCAAyB;CAClF,MAAM,EAAC,MAAKC,gCAAgB;CAC5B,MAAM,EAAC,MAAM,WAAUC,8BAAc;CACrC,MAAMC,SAAiCC,2CAAU,OAAO,YAAY;CAEpE,MAAM,CAAC,OAAO,gCAAwC,UAAU;CAChE,MAAM,CAAC,cAAc,uCAA4B,MAAM;CACvD,MAAM,CAAC,aAAa,sCAA4D,KAAK;CACrF,MAAM,CAAC,OAAO,gCAAoC,KAAK;CAEvD,MAAMC,oCAAoD,MAAM;CAGhE,MAAMC,+CAA+D,MAAM;CAC3E,MAAMC,sCAA2E,KAAK;CAEtF,MAAMC,cAAsC,EAAC,WAAW,sBAAqB;CAE7E,MAAM,oCACH,aAAiE;AAChE,MAAI,CAAC,UAAU,QAAQ,MAAM,QAAQ,SAAS,KAAK,WAAW,CAC5D,QAAO;EAGT,MAAM,EAAC,eAAcC,8CACnB,UACA,GACA;GAAC,iBAAiB;GAA2B,qBAAqB;GAAO,cAAc;GAAM,EAC7F,KACD;AAED,SAAO;GAAC,GAAG;GAAU,MAAM;IAAC,GAAG,SAAS;IAAM;IAAW;GAAC;IAE5D,CAAC,GAAG,KAAK,CACV;CAED,MAAM,4CACH,8DACuB,WAAW,CAAC,OAAO,KAAK,cAAqC;EACjF,MAAM,iEAAwC,UAAU,WAAW;AACnE,SAAO;GACL,cAAc;GACd,MAAM,UAAU,OAAO,UAAU;GACjC,UAAU,UAAU,YAAY;GAChC,YAAY,UAAkB;AAC5B,QAAI,UAAU,aAAa,CAAC,SAAS,MAAM,MAAM,KAAK,IACpD,QAAO,EAAE,mCAAmC;AAE9C,QAAI,iBAAiB,OAAO;KAC1B,MAAM,cAAc,cAAc,MAAM;AACxC,SAAI,YACF,QAAO,EAAE,YAAY;;AAGzB,WAAO;;GAEV;GACD,EACJ,CAAC,EAAE,CACJ;CAED,MAAMC,sCACE,kBAAkB,aAAa,MAAM,cAAc,EAAE,CAAC,EAC5D,CAAC,aAAa,kBAAkB,CACjC;CAED,MAAM,EACJ,QAAQ,YACR,SAAS,eACT,QAAQ,YACR,SAAS,aACT,UAAU,cACV,YAAY,gBACZ,kBACA,WAAW,eACX,aAAa,iBACb,cACA,gBACA,OAAO,cACLC,wBAAgC;EAClC,QAAQ;EACR,eAAe,EAAE;EACjB,iBAAiB,EAAE,mCAAmC;EACtD,gBAAgB;EAChB,kBAAkB;EACnB,CAAC;AAGF,4BAAgB;AACd,mBAAiB;EACjB,MAAMC,sBAAgD,aAAa,MAAM;AACzE,MAAI,CAAC,uBAAuB,oBAAoB,WAAW,EACzD;EAEF,MAAMC,SAAiC,EAAE;EACzC,MAAMC,UAAmC,EAAE;AAC3C,sBAAoB,SAAS,OAAmB;AAC9C,OAAI,EAAE,GAAG,cAAc,SAAS;AAC9B,WAAO,GAAG,cAAc,GAAG;AAC3B,YAAQ,GAAG,cAAc;;IAE3B;AACF,mBAAiB,QAAQ;AACzB,gBAAc,OAAO;IACpB;EAAC;EAAa;EAAe;EAAkB;EAAgB,CAAC;CAEnE,MAAM,yCACH,gBAAgD;EAC/C,MAAMC,WAAqC,UAAU,YAAY;AACjE,iBAAe,SAAS;AAExB,MAAI,SAAS,mBAAmB,OAC9B,mBAAkB,UAAU,SAAS,kBAAkB;AAGzD,MAAI,SAAS,eAAeC,2CAAuB,OAAO;GACxD,MAAMC,UAAkBC,4CAAoB,UAAU,GAAG,0BAA0B;AACnF,YAAS,QAAQ;AACjB,YAAS,SAAS;AAClB,aAAU,IAAI,MAAM,QAAQ,CAAC;AAC7B;;AAGF,MAAI,SAAS,eAAeF,2CAAuB,UAAU;AAC3D,YAAS,KAAK;AACd,YAAS,WAAW;AACpB,gBAAa,SAAS;AACtB;;AAKF,kBACG,aACC,SAAS,MAAM,kBAAkB,CAAC,UAAU,MAAM,iBAC9C,WACA;GAAC,GAAG;GAAU,MAAM;IAAC,GAAG,SAAS;IAAM,gBAAgB,SAAS,KAAK;IAAe;GAAC,CAC5F;AACD,aAAW;AACX,WAAS,SAAS,QAAQE,4CAAoB,UAAU,GAAG,0BAA0B,GAAG,KAAK;AAC7F,WAAS,SAAS;IAEpB;EAAC;EAAW;EAAc;EAAS;EAAY;EAAW;EAAE,CAC7D;CAED,MAAM,wCACH,gBAA+B;AAE9B,WAAS,EAAE,0BAA0B,CAAC;AACtC,WAAS,SAAS;AAClB,YAAU,uBAAuB,QAAQ,cAAc,IAAI,MAAM,OAAO,YAAY,CAAC,CAAC;IAExF,CAAC,SAAS,EAAE,CACb;AAED,4BAAgB;AACd,MAAI,CAAC,iBAAiB,2BAA2B,QAC/C;AAEF,6BAA2B,UAAU;AAErC,GAAM,YAA2B;AAC/B,OAAI;IACF,MAAMC,WAAiD,MAAM,gBAAgB;AAC7E,QAAI,SACF,gBAAe,SAAS;YAEnB,aAAa;AACpB,kBAAc,YAAY;;MAE1B;IACH;EAAC;EAAe;EAAc;EAAgB;EAAc,CAAC;CAEhE,MAAM,qBAAqB,MAAc,UAAwB;AAC/D,eAAa,MAAM,MAAM;;CAG3B,MAAM,mBAAmB,SAAuB;AAC9C,iBAAe,MAAM,KAAK;;CAG5B,MAAM,eAAe,OACnB,WACA,MACA,mBACkB;AAClB,MAAI,CAAC,eAAe,gBAAgB,QAAS;AAE7C,MAAI,CAAC,gBAAgB;AACnB,mBAAgB;AAChB,OAAI,CAAC,cAAc,CAAC,QAAS;;AAG/B,kBAAgB,UAAU;AAC1B,kBAAgB,KAAK;AACrB,WAAS,KAAK;AAEd,MAAI;GACF,MAAMC,eAAuC,OAAOC,qCAAqB,MAAM,OAAO,GAAG,EAAE;GAC3F,MAAMC,SAAiC,OAAO,YAC5C,OAAO,QAAQ,aAAa,CAAC,QAC1B,GAAG,WAA6B,UAAU,QAAQ,UAAU,UAAa,UAAU,GACrF,CACF;GAED,MAAMH,WAAiD,MAAM,WAAW;IACtE,aAAa,YAAY;IACzB,GAAI,UAAU,MAAM,EAAC,QAAQ,UAAU,IAAG;IAC1C,GAAI,kBAAkB,UAAU,EAAC,gBAAgB,kBAAkB,SAAQ,GAAG,EAAE;IAChF;IACD,CAAC;AAEF,OAAI,SACF,gBAAe,SAAS;WAEnB,aAAa;AACpB,iBAAc,YAAY;YAClB;AACR,mBAAgB,UAAU;AAC1B,mBAAgB,MAAM;;;CAI1B,MAAMI,iBAA0C,aAAa,MAAM,kBAAkB,EAAE;CACvF,MAAMC,oBAA6B,eAAeC,mDAA+B;CACjF,MAAMC,cACJ,OAAO,sBAAsB,YAAY,oBAAoB,oBAAoB;CACnF,MAAMC,WAAwDC,yCAC5D,aAAa,MAAM,cAAc,EAAE,EACnC,QACA,QACA,EAAE,6BAA6B,YAAY,EAC3C,EAAE,uCAAuC,CAC1C;CACD,MAAM,EAAC,8BAA6B;CACpC,MAAMC,sDAAiD,6BAA6B,EAAE,CAAC;CAEvF,MAAMC,iBAA0B,UAAU,YAAY,WAAW,WAAW,KAAK,KAAK,QAAQ,WAAW;CACzG,MAAMC,6DAA4C,SAAS,OAAO;EAAC;EAAM;EAAE,CAAC;CAE5E,MAAM,kBAAkB,CAAC,CAAC,SAAS,kBAAkB;CACrD,IAAIC,gEAA+C,SAAS,UAAU;EAAC;EAAM;EAAE,CAAC;CAChF,IAAIC,kBAAiC;AACrC,KAAI,eAAe,gBACjB,mBAAkB,EAAE,iCAAiC,EAAC,aAAY,CAAC;UAC1D,YACT,YAAW,EAAE,iBAAiB,sCAAsC,gCAAgC,EAAC,aAAY,CAAC;CAGpH,MAAMC,YAAqB,UAAU,aAAa;CAElD,MAAMC,mBAA2BC,qEACN,mBAAmB,oDACnB,qBAAqB,OAAO,oDAC5B,qBAAqB,UAAU,EACxD,OAAO,SACP,YAAY,aAAa,OAAO,UAAU,IAC1C,UACD;AAED,KAAI,UAAU;EACZ,MAAMC,SAA4C,UAAU,WAAW,KAAK,SAAS;AAErF,SACE,2CAAC;GAAI,WAAW;aACb,SAAS;IACR;IACA,YAAY,6BAA6B,EAAE;IAC3C;IACA;IACA;IACA,aAAa;IACb;IACA,cAAc,eAA8B,aAAa,QAAQ,QAAW,KAAK,GAAG;IACpF;IACA;IACA,YAAY,UAAU;IACtB,UAAU,UAAU;IACpB;IACA,SAAS;IACT;IACA,QAAQ,iBAAiB,SAAS;IAClC;IACA,gBAAgB,EAAE,6BAA6B,YAAY;IAC3D;IACA,SAAS;IACT,QAAQ;IACT,CAAC;IACE;;CAIV,MAAMC,eAAuBF,kGAAgC,oBAAoB,QAAQ,CAAC,EAAE,OAAO,SAAS;AAE5G,QACE,4CAAC;EAAI,WAAW;EAAkB,aAAW;;GAC1C,UAAU,aAAa,aAAa,iBACnC,4CAAC;IAAI,WAAWA,kGAAgC,oBAAoB,SAAS,CAAC,EAAE,OAAO,UAAU;eAC9F,aACC,2CAACG;KACC,SAAQ;KACR,WAAWH,kGAAgC,oBAAoB,UAAU,CAAC,EAAE,OAAO,WAAW;eAE7F;MACU,EAEd,gBACC,4CAACG;KACC,SAAQ;KACR,WAAWH,kGAAgC,oBAAoB,aAAa,CAAC,EAAE,OAAO,cAAc;gBAEnG,UACA,mBACC,2CAAC;MAAK,0FAAwC,oBAAoB,cAAc,CAAC;gBAC9E,IAAI;OACA;MAEE;KAEX;GAGP,UAAU,aACT,2CAAC;IAAI,WAAWA,kGAAgC,oBAAoB,UAAU,CAAC,EAAE,OAAO,WAAW;cACjG,2CAACI,2BAAQ,MAAK,WAAW;KACrB;GAGP,SACC,2CAACC;IAAe,SAAQ;IAAQ,WAAW;cACzC,2CAACA,sBAAe,yBAAa,QAAmC;KACjD;GAGlB,UAAU,cACT,2CAACA;IAAe,SAAQ;IAAU,WAAW;cAC3C,2CAACA,sBAAe,yBAAa,EAAE,6BAA6B,YAAY,GAA8B;KACvF;GAGlB,UAAU,YACT,2CAAC;IAAI,WAAWL,kGAAgC,oBAAoB,UAAU,CAAC,EAAE,OAAO,WAAW;cAChG,gBACCM,uDACE,6BAA6B,EAAE,EAC/B,YACA,eACA,YACA,WACA,aACA,WACA,mBACA;KACE,kBAAkB;KAClB,QAAQ;KACR;KACA,iBAAiBN,kGAAgC,oBAAoB,SAAS,CAAC,EAAE,gBAAgB;KACjG,gBAAgBA,kGAAgC,oBAAoB,QAAQ,CAAC,EAAE,eAAe;KAC9F;KACA,aAAa;KACb,WAAW,WAAkC,MAA+B,SAAyB;AACnG,MAAK,aAAa,WAAW,MAAM,KAAK;;KAE1C;KACA;KACA;KACA;KACD,CACF,EACD,eAAe,KAAK,CACrB;KACG;IAGN,CAAC,CAAC,YAAa,kBAAkB,CAAC,CAAC,WACnC,4CAAC;IAAI,WAAWA,kGAAgC,oBAAoB,UAAU,CAAC,EAAE,OAAO,WAAW;eAChG,kBAAkB,UACjB,2CAACO;KACC,MAAK;KACL,OAAM;KACN,SAAQ;KACR,SAAS;KACT,eAAY;eAEX,EAAE,sCAAsC;MAClC,EAEV,YACC,2CAACA;KACC,MAAK;KACL,OAAM;KACN,SAAQ;KACR,SAAS;KACT,UAAU;KACV,eAAY;eAEX,UAAU,YAAY,UAAU,YAC7B,EAAE,wCAAwC,GAC1C,EAAE,uCAAuC;MACtC;KAEP;;GAEJ;;;;;;AAQV,MAAMC,uBAAqD,EACzD,cAAc,OACd,GAAG,WACyC;CAC5C,MAAMC,UAAwB,2CAAC,8BAA2B,GAAI,OAAQ;AAEtE,KAAI,CAAC,YAAa,QAAO;AAEzB,QAAO,2CAACC,4CAA4B;EAAS,OAAO;YAAc;GAA+C;;AAGnH,kCAAe"}
|
|
1
|
+
{"version":3,"file":"BaseVerifyAttribute.cjs","names":["props: {children?: ReactNode; name?: unknown}","testId","EmbeddedFlowComponentType","testId: string | undefined","children: ReactNode","BaseVerifyAttributeContent: FC<Omit<BaseVerifyAttributeProps, 'preferences'>>","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","useTranslation","useThunderID","styles: Record<string, string>","useStyles","isSubmittingRef: MutableRefObject<boolean>","initializationAttemptedRef: MutableRefObject<boolean>","challengeTokenRef: MutableRefObject<string | null>","labelParams: Record<string, string>","normalizeFlowResponse","formFields: FormField[]","useForm","useStepExpiry","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","response: EmbeddedSelfFlowResponse","EmbeddedSelfFlowStatus","message: string","extractErrorMessage","response: EmbeddedSelfFlowResponse | undefined","composedData: Record<string, string>","composeAffixedInputs","inputs: Record<string, string>","additionalData: Record<string, unknown>","maskedDestination: unknown","AttributeVerificationConstants","destination: string | null","headings: ReturnType<typeof getAuthComponentHeadings>","getAuthComponentHeadings","step: FlowStepComponents","isAwaitingLink: boolean","title: string","subtitle: string","destinationText: string | null","isLoading: boolean","containerClasses: string","cx","resend: EmbeddedFlowComponent | undefined","alertClasses: string","Typography","Spinner","AlertPrimitive","renderVerificationComponents","Button","BaseVerifyAttribute: FC<BaseVerifyAttributeProps>","content: ReactElement","ComponentPreferencesContext"],"sources":["../../../../../src/components/account/VerifyAttribute/BaseVerifyAttribute.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n AttributeVerificationConstants,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentType,\n EmbeddedSelfFlowRequest,\n EmbeddedSelfFlowResponse,\n EmbeddedSelfFlowStatus,\n FieldError,\n FlowStepComponents,\n Preferences,\n bem,\n buildValidatorFromRules,\n getFlowStepComponents,\n resolveFlowTemplateLiterals,\n withVendorCSSClassPrefix,\n} from '@thunderid/browser';\nimport {\n FC,\n MutableRefObject,\n ReactElement,\n ReactNode,\n cloneElement,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport useStyles from './BaseVerifyAttribute.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport ComponentPreferencesContext from '../../../contexts/I18n/ComponentPreferencesContext';\nimport useTheme from '../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../contexts/ThunderID/useThunderID';\nimport useStepExpiry from '../../../hooks/auth/useStepExpiry';\nimport {FormField, useForm} from '../../../hooks/useForm';\nimport useTranslation from '../../../hooks/useTranslation';\nimport {cx} from '../../../styles/emotion';\nimport composeAffixedInputs from '../../../utils/composeAffixedInputs';\nimport {extractErrorMessage, normalizeFlowResponse} from '../../../utils/flowTransformer';\nimport getAuthComponentHeadings from '../../../utils/getAuthComponentHeadings';\nimport {renderVerificationComponents} from '../../auth/flow/AuthOptionFactory';\nimport AlertPrimitive from '../../primitives/Alert/Alert';\nimport Button from '../../primitives/Button/Button';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport Typography from '../../primitives/Typography/Typography';\n\ntype VerificationState = 'loading' | 'active' | 'complete' | 'failed';\n\ninterface FlowIds {\n actions: Set<string>;\n // Input name (`ref`, else `id`) to component type.\n fields: Map<string, string>;\n}\n\n// Flow identifiers of the step's inputs and actions.\nconst collectFlowIds = ({actions, inputs}: FlowStepComponents): FlowIds => ({\n actions: new Set(actions.map((component: EmbeddedFlowComponent) => component.id)),\n fields: new Map(inputs.map((component: EmbeddedFlowComponent) => [component.ref ?? component.id, component.type])),\n});\n\n// Tags the elements rendered from the flow with `thunderid-field-<ref>` and `thunderid-action-<id>`.\n// The shared factory keys an element by its component id and names an input by its ref.\nconst withFlowTestIds = (node: ReactNode, ids: FlowIds): ReactNode => {\n if (Array.isArray(node)) return node.map((child: ReactNode) => withFlowTestIds(child, ids));\n if (!isValidElement(node)) return node;\n\n const props: {children?: ReactNode; name?: unknown} = node.props as {children?: ReactNode; name?: unknown};\n if (typeof props.name === 'string' && ids.fields.has(props.name)) {\n const testId = `thunderid-field-${props.name}`;\n\n // The OTP field renders one input per character and takes no test identifier, so wrap it.\n if (ids.fields.get(props.name) === EmbeddedFlowComponentType.OtpInput) {\n return (\n <div key={node.key} data-testid={testId}>\n {node}\n </div>\n );\n }\n\n return cloneElement(node as ReactElement<Record<string, unknown>>, {'data-testid': testId});\n }\n\n const testId: string | undefined =\n node.key !== null && ids.actions.has(String(node.key)) ? `thunderid-action-${String(node.key)}` : undefined;\n const children: ReactNode = props.children === undefined ? undefined : withFlowTestIds(props.children, ids);\n if (!testId && children === props.children) return node;\n\n return cloneElement(node as ReactElement<Record<string, unknown>>, {\n ...(testId && {'data-testid': testId}),\n ...(props.children !== undefined && {children}),\n });\n};\n\n/**\n * What {@link BaseVerifyAttribute} hands its `children` render function, so the steps can be drawn\n * with any UI.\n */\nexport interface BaseVerifyAttributeRenderProps {\n additionalData: Record<string, unknown>;\n /**\n * The step's components, without its headings.\n */\n components: EmbeddedFlowComponent[];\n /**\n * Masked destination the code or link was sent to, when the flow reports it.\n */\n destination: string | null;\n /**\n * Translated \"Sent to …\" line, set when the flow has its own prompt in `subtitle`.\n */\n destinationText: string | null;\n /**\n * Translated error of the last request, or the refusal.\n */\n error: string | null;\n fieldErrors: Record<string, string>;\n handleInputChange: (name: string, value: string) => void;\n /**\n * Sends a new code. Set only while the step has a resend action.\n */\n handleResend?: () => Promise<void>;\n /**\n * Submits a step. Pass `skipValidation` for an action, such as a resend, that sends no inputs.\n */\n handleSubmit: (\n component: EmbeddedFlowComponent,\n data?: Record<string, string>,\n skipValidation?: boolean,\n ) => Promise<void>;\n isAwaitingLink: boolean;\n isComplete: boolean;\n /**\n * Whether the server refused the verification or the request failed; the flow cannot continue.\n */\n isFailed: boolean;\n isLoading: boolean;\n isValid: boolean;\n /**\n * Closes the panel. Set only when the app passes `onCancel`.\n */\n onCancel?: () => void;\n /**\n * Confirms a link the user opened outside the app. Set only while the step waits for a link and\n * the app passes `onDone`.\n */\n onDone?: () => void;\n subtitle: string;\n /**\n * Translated message for a recorded verification.\n */\n successMessage: string;\n title: string;\n touched: Record<string, boolean>;\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseVerifyAttribute component.\n */\nexport interface BaseVerifyAttributeProps {\n /**\n * Label of the attribute being verified, used in the default heading and success message.\n */\n attributeDisplayName?: string;\n buttonClassName?: string;\n /**\n * Renders custom UI in place of the default steps. Receives the step, the values and their setters,\n * submit, resend, cancel, the destination, and the loading, error and completed state.\n */\n children?: (props: BaseVerifyAttributeRenderProps) => ReactNode;\n className?: string;\n inputClassName?: string;\n isInitialized?: boolean;\n /**\n * Called when the user closes the panel. The close action is shown only when this is set.\n */\n onCancel?: () => void;\n /**\n * Called once the server has recorded the verification.\n */\n onComplete?: (response: EmbeddedSelfFlowResponse) => void;\n /**\n * Called when the user selects Done after the flow sent a link, which they confirm outside the app.\n * The Done action is shown only when this is set.\n */\n onDone?: () => void;\n /**\n * Called when the server refuses the verification or the request fails.\n */\n onError?: (error: Error) => void;\n onFlowChange?: (response: EmbeddedSelfFlowResponse) => void;\n onInitialize?: () => Promise<EmbeddedSelfFlowResponse>;\n onSubmit?: (payload: EmbeddedSelfFlowRequest) => Promise<EmbeddedSelfFlowResponse>;\n /**\n * Component-level preferences to override global i18n and theme settings.\n */\n preferences?: Preferences;\n showSubtitle?: boolean;\n showTitle?: boolean;\n size?: 'small' | 'medium' | 'large';\n variant?: 'outlined' | 'flat';\n}\n\n/**\n * Internal component that renders the verification steps and manages flow state.\n *\n * @internal\n */\nconst BaseVerifyAttributeContent: FC<Omit<BaseVerifyAttributeProps, 'preferences'>> = ({\n attributeDisplayName = '',\n buttonClassName = '',\n children = undefined,\n className = '',\n inputClassName = '',\n isInitialized = true,\n onCancel = undefined,\n onComplete = undefined,\n onDone = undefined,\n onError = undefined,\n onFlowChange = undefined,\n onInitialize = undefined,\n onSubmit = undefined,\n showSubtitle = true,\n showTitle = true,\n size = 'medium',\n variant = 'outlined',\n}: Omit<BaseVerifyAttributeProps, 'preferences'>): ReactElement => {\n const {theme, colorScheme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const {t} = useTranslation();\n const {meta, vendor} = useThunderID();\n const styles: Record<string, string> = useStyles(theme, colorScheme);\n\n const [state, setState] = useState<VerificationState>('loading');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<EmbeddedSelfFlowResponse | null>(null);\n const [error, setError] = useState<string | null>(null);\n // Set before the first await, so a second call from a custom render cannot send a second code.\n const isSubmittingRef: MutableRefObject<boolean> = useRef(false);\n\n // Guards against a second initiation, which would send a second code.\n const initializationAttemptedRef: MutableRefObject<boolean> = useRef(false);\n const challengeTokenRef: MutableRefObject<string | null> = useRef<string | null>(null);\n\n const labelParams: Record<string, string> = {attribute: attributeDisplayName};\n\n const normalize = useCallback(\n (response: EmbeddedSelfFlowResponse): EmbeddedSelfFlowResponse => {\n if (!response?.data || Array.isArray(response.data.components)) {\n return response;\n }\n\n const {components} = normalizeFlowResponse(\n response,\n t,\n {defaultErrorKey: 'user.verification.error', resolveTranslations: false, throwOnError: false},\n meta,\n );\n\n return {...response, data: {...response.data, components}};\n },\n [t, meta],\n );\n\n const extractFormFields = useCallback(\n (components: EmbeddedFlowComponent[]): FormField[] =>\n getFlowStepComponents(components).inputs.map((component: EmbeddedFlowComponent) => {\n const ruleValidator = buildValidatorFromRules(component.validation);\n return {\n initialValue: '',\n name: component.ref ?? component.id,\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 (ruleValidator && value) {\n const ruleMessage = ruleValidator(value);\n if (ruleMessage) {\n return t(ruleMessage);\n }\n }\n return null;\n },\n };\n }),\n [t],\n );\n\n const formFields: FormField[] = useMemo(\n () => extractFormFields(currentFlow?.data?.components ?? []),\n [currentFlow, extractFormFields],\n );\n\n const {\n values: formValues,\n touched: touchedFields,\n errors: formErrors,\n isComplete: isFormComplete,\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 } = 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 // A custom renderer can expire the step from the client; it holds until the next step response.\n const {expireStep, isStepExpired} = useStepExpiry(currentFlow);\n\n // Project server-side field errors into form state.\n useEffect(() => {\n clearFormErrors();\n const responseFieldErrors: FieldError[] | undefined = currentFlow?.data?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n responseFieldErrors.forEach((fe: FieldError) => {\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 handleResponse = useCallback(\n (rawResponse: EmbeddedSelfFlowResponse): void => {\n const response: EmbeddedSelfFlowResponse = normalize(rawResponse);\n onFlowChange?.(response);\n\n if (response.challengeToken !== undefined) {\n challengeTokenRef.current = response.challengeToken ?? null;\n }\n\n if (response.flowStatus === EmbeddedSelfFlowStatus.Error) {\n const message: string = extractErrorMessage(response, t, 'user.verification.error');\n setError(message);\n setState('failed');\n onError?.(new Error(message));\n return;\n }\n\n if (response.flowStatus === EmbeddedSelfFlowStatus.Complete) {\n setError(null);\n setState('complete');\n onComplete?.(response);\n return;\n }\n\n // INCOMPLETE: render the step; a rejected code comes back with an error and without\n // additionalData, so keep the destination and code length of the step that sent the code.\n setCurrentFlow(\n (previous: EmbeddedSelfFlowResponse | null): EmbeddedSelfFlowResponse =>\n response.data?.additionalData || !previous?.data?.additionalData\n ? response\n : {...response, data: {...response.data, additionalData: previous.data.additionalData}},\n );\n resetForm();\n setError(response.error ? extractErrorMessage(response, t, 'user.verification.error') : null);\n setState('active');\n },\n [normalize, onFlowChange, onError, onComplete, resetForm, t],\n );\n\n const handleFailure = useCallback(\n (caughtError: unknown): void => {\n // Show a generic message; an API error body is not meant for the user.\n setError(t('user.verification.error'));\n setState('failed');\n onError?.(caughtError instanceof Error ? caughtError : new Error(String(caughtError)));\n },\n [onError, t],\n );\n\n useEffect(() => {\n if (!isInitialized || initializationAttemptedRef.current) {\n return;\n }\n initializationAttemptedRef.current = true;\n\n void (async (): Promise<void> => {\n try {\n const response: EmbeddedSelfFlowResponse | undefined = await onInitialize?.();\n if (response) {\n handleResponse(response);\n }\n } catch (caughtError) {\n handleFailure(caughtError);\n }\n })();\n }, [isInitialized, onInitialize, handleResponse, handleFailure]);\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 (\n component: EmbeddedFlowComponent,\n data?: Record<string, string>,\n skipValidation?: boolean,\n ): Promise<void> => {\n if (!currentFlow || isSubmittingRef.current) return;\n\n if (!skipValidation) {\n touchAllFields();\n if (!validateForm().isValid) return;\n }\n\n isSubmittingRef.current = true;\n setIsSubmitting(true);\n setError(null);\n\n try {\n const composedData: Record<string, string> = data ? composeAffixedInputs(data, vendor) : {};\n const inputs: Record<string, string> = Object.fromEntries(\n Object.entries(composedData).filter(\n ([, value]: [string, string]) => value !== null && value !== undefined && value !== '',\n ),\n );\n\n const response: EmbeddedSelfFlowResponse | undefined = await onSubmit?.({\n executionId: currentFlow.executionId,\n ...(component.id && {action: component.id}),\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n inputs,\n });\n\n if (response) {\n handleResponse(response);\n }\n } catch (caughtError) {\n handleFailure(caughtError);\n } finally {\n isSubmittingRef.current = false;\n setIsSubmitting(false);\n }\n };\n\n const additionalData: Record<string, unknown> = currentFlow?.data?.additionalData ?? {};\n const maskedDestination: unknown = additionalData[AttributeVerificationConstants.MASKED_DESTINATION_KEY];\n const destination: string | null =\n typeof maskedDestination === 'string' && maskedDestination ? maskedDestination : null;\n const headings: ReturnType<typeof getAuthComponentHeadings> = getAuthComponentHeadings(\n currentFlow?.data?.components ?? [],\n undefined,\n undefined,\n t('user.verification.heading', labelParams),\n t('user.verification.subheading.generic'),\n );\n const {componentsWithoutHeadings} = headings;\n const step: FlowStepComponents = getFlowStepComponents(componentsWithoutHeadings ?? []);\n // A step with nothing to enter or submit waits for the user to open a link sent to them.\n const isAwaitingLink: boolean = state === 'active' && formFields.length === 0 && step.actions.length === 0;\n const title: string = resolveFlowTemplateLiterals(headings.title, {meta, t});\n // The flow's own prompt wins; the destination is added beside it, or fills in when the flow has none.\n const hasFlowSubtitle = !!headings.headingComponents.subheading;\n let subtitle: string = resolveFlowTemplateLiterals(headings.subtitle, {meta, t});\n let destinationText: string | null = null;\n if (destination && hasFlowSubtitle) {\n destinationText = t('user.verification.destination', {destination});\n } else if (destination) {\n subtitle = t(isAwaitingLink ? 'user.verification.subheading.link' : 'user.verification.subheading', {destination});\n }\n\n const isLoading: boolean = state === 'loading' || isSubmitting;\n\n const containerClasses: string = cx(\n withVendorCSSClassPrefix('verify-attribute'),\n withVendorCSSClassPrefix(`verify-attribute--${size}`),\n withVendorCSSClassPrefix(`verify-attribute--${variant}`),\n styles['root'],\n variant === 'outlined' ? styles['card'] : '',\n className,\n );\n\n if (children) {\n const resend: EmbeddedFlowComponent | undefined = state === 'active' ? step.resend : undefined;\n\n return (\n <div className={containerClasses}>\n {children({\n additionalData,\n components: componentsWithoutHeadings ?? [],\n destination,\n destinationText,\n error,\n fieldErrors: formErrors,\n handleInputChange,\n handleResend: resend ? (): Promise<void> => handleSubmit(resend, undefined, true) : undefined,\n handleSubmit,\n isAwaitingLink,\n isComplete: state === 'complete',\n isFailed: state === 'failed',\n isLoading,\n isValid: isFormValid,\n onCancel,\n onDone: isAwaitingLink ? onDone : undefined,\n subtitle,\n successMessage: t('user.verification.success', labelParams),\n title,\n touched: touchedFields,\n values: formValues,\n })}\n </div>\n );\n }\n\n const alertClasses: string = cx(withVendorCSSClassPrefix(bem('verify-attribute', 'alert')), styles['alert']);\n\n return (\n <div className={containerClasses} aria-busy={isLoading}>\n {state === 'active' && (showTitle || showSubtitle) && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'header')), styles['header'])}>\n {showTitle && (\n <Typography\n variant=\"h5\"\n className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'heading')), styles['heading'])}\n >\n {title}\n </Typography>\n )}\n {showSubtitle && (\n <Typography\n variant=\"body2\"\n className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'subheading')), styles['subheading'])}\n >\n {subtitle}\n {destinationText && (\n <span className={withVendorCSSClassPrefix(bem('verify-attribute', 'destination'))}>\n {` ${destinationText}`}\n </span>\n )}\n </Typography>\n )}\n </div>\n )}\n\n {state === 'loading' && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'loading')), styles['loading'])}>\n <Spinner size=\"medium\" />\n </div>\n )}\n\n {error && (\n <AlertPrimitive variant=\"error\" className={alertClasses}>\n <AlertPrimitive.Description>{error}</AlertPrimitive.Description>\n </AlertPrimitive>\n )}\n\n {state === 'complete' && (\n <AlertPrimitive variant=\"success\" className={alertClasses}>\n <AlertPrimitive.Description>{t('user.verification.success', labelParams)}</AlertPrimitive.Description>\n </AlertPrimitive>\n )}\n\n {state === 'active' && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'content')), styles['content'])}>\n {withFlowTestIds(\n renderVerificationComponents(\n componentsWithoutHeadings ?? [],\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: cx(withVendorCSSClassPrefix(bem('verify-attribute', 'button')), buttonClassName),\n inputClassName: cx(withVendorCSSClassPrefix(bem('verify-attribute', 'input')), inputClassName),\n isFormComplete,\n isTimeoutDisabled: isStepExpired,\n meta,\n onInputBlur: handleInputBlur,\n onStepExpire: expireStep,\n onSubmit: (component: EmbeddedFlowComponent, data?: Record<string, string>, skip?: boolean): void => {\n void handleSubmit(component, data, skip);\n },\n size,\n t,\n variant,\n vendor,\n },\n ),\n collectFlowIds(step),\n )}\n </div>\n )}\n\n {(!!onCancel || (isAwaitingLink && !!onDone)) && (\n <div className={cx(withVendorCSSClassPrefix(bem('verify-attribute', 'actions')), styles['actions'])}>\n {isAwaitingLink && onDone && (\n <Button\n size=\"small\"\n color=\"primary\"\n variant=\"solid\"\n onClick={onDone}\n data-testid=\"thunderid-action-verificationDone\"\n >\n {t('user.verification.buttons.done.text')}\n </Button>\n )}\n {onCancel && (\n <Button\n size=\"small\"\n color=\"secondary\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={isSubmitting}\n data-testid=\"thunderid-action-verificationCancel\"\n >\n {state === 'active' || state === 'loading'\n ? t('user.verification.buttons.cancel.text')\n : t('user.verification.buttons.close.text')}\n </Button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * BaseVerifyAttribute renders the server-described steps of a self attribute verification flow.\n * Accepts API functions as props to stay framework independent.\n */\nconst BaseVerifyAttribute: FC<BaseVerifyAttributeProps> = ({\n preferences = undefined,\n ...rest\n}: BaseVerifyAttributeProps): ReactElement => {\n const content: ReactElement = <BaseVerifyAttributeContent {...rest} />;\n\n if (!preferences) return content;\n\n return <ComponentPreferencesContext.Provider value={preferences}>{content}</ComponentPreferencesContext.Provider>;\n};\n\nexport default BaseVerifyAttribute;\n"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ const require_Spinner = require('../../primitives/Spinner/Spinner.cjs');
|
|
|
9
9
|
const require_Button = require('../../primitives/Button/Button.cjs');
|
|
10
10
|
const require_Typography = require('../../primitives/Typography/Typography.cjs');
|
|
11
11
|
const require_Card = require('../../primitives/Card/Card.cjs');
|
|
12
|
+
const require_useStepExpiry = require('../../../hooks/auth/useStepExpiry.cjs');
|
|
12
13
|
const require_Alert = require('../../primitives/Alert/Alert.cjs');
|
|
13
14
|
const require_isConsentApprovalBlocked = require('../../../utils/isConsentApprovalBlocked.cjs');
|
|
14
15
|
const require_AuthOptionFactory = require('../flow/AuthOptionFactory.cjs');
|
|
@@ -54,6 +55,7 @@ const BaseAcceptInvite = ({ executionId, inviteToken, onSubmit, onComplete, onEr
|
|
|
54
55
|
const [formErrors, setFormErrors] = (0, react.useState)({});
|
|
55
56
|
const [touchedFields, setTouchedFields] = (0, react.useState)({});
|
|
56
57
|
const [isFormValid, setIsFormValid] = (0, react.useState)(true);
|
|
58
|
+
const { expireStep, isStepExpired } = require_useStepExpiry.default(currentFlow);
|
|
57
59
|
const [isStorageReady, setIsStorageReady] = (0, react.useState)(false);
|
|
58
60
|
const challengeTokenRef = (0, react.useRef)(null);
|
|
59
61
|
/**
|
|
@@ -484,7 +486,10 @@ const BaseAcceptInvite = ({ executionId, inviteToken, onSubmit, onComplete, onEr
|
|
|
484
486
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [componentsWithoutHeadings && componentsWithoutHeadings.length > 0 ? require_AuthOptionFactory.renderInviteUserComponents(componentsWithoutHeadings, formValues, touchedFields, formErrors, isLoading, isFormValid, resetForm, handleInputChange, {
|
|
485
487
|
_customRenderers: customRenderers,
|
|
486
488
|
_theme: theme,
|
|
489
|
+
isFormComplete: validateForm(componentsWithoutHeadings).isValid,
|
|
490
|
+
isTimeoutDisabled: isStepExpired,
|
|
487
491
|
onInputBlur: handleInputBlur,
|
|
492
|
+
onStepExpire: expireStep,
|
|
488
493
|
onSubmit: handleSubmit,
|
|
489
494
|
size,
|
|
490
495
|
variant
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseAcceptInvite.cjs","names":["BaseAcceptInvite: FC<BaseAcceptInviteProps>","useThunderID","useTranslation","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","styles: any","useStyles","challengeTokenRef: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","tokenValidationAttemptedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","components","response: any","handleInputChange: any","newErrors: any","handleInputBlur: any","validateForm: any","value: any","handleSubmit: any","validation: any","inputs: any","raw: any","purposes: any[]","isConsentApprovalBlocked","ConsentConstants","CONSENT_MODIFIED_KEY_PREFIX","CONSENT_INVALID_KEY_PREFIX","payload: Record<string, any>","redirectURL: any","extractHeadings: any","title: string | undefined","subtitle: string | undefined","title","subtitle","filterHeadings: any","components: any","componentsWithoutHeadings: any","renderProps: BaseAcceptInviteRenderProps","CardPrimitive","cx","Spinner","Typography","AlertPrimitive","Button","renderInviteUserComponents"],"sources":["../../../../../src/components/auth/AcceptInvite/BaseAcceptInvite.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ConsentConstants,\n FieldError,\n FlowExecutionError,\n FlowMetadataResponse,\n Preferences,\n buildValidatorFromRules,\n CONSENT_INVALID_KEY_PREFIX,\n CONSENT_MODIFIED_KEY_PREFIX,\n getConsentElementDecision,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport useStyles from './BaseAcceptInvite.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport useTheme from '../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../hooks/auth/useOAuthCallback';\nimport useTranslation from '../../../hooks/useTranslation';\nimport {cx} from '../../../styles/emotion';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../utils/flowTransformer';\nimport isConsentApprovalBlocked from '../../../utils/isConsentApprovalBlocked';\nimport {initiateOAuthRedirect} from '../../../utils/oauth';\nimport AlertPrimitive from '../../primitives/Alert/Alert';\nimport Button from '../../primitives/Button/Button';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../primitives/Card/Card';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport Typography from '../../primitives/Typography/Typography';\nimport {renderInviteUserComponents} from '../flow/AuthOptionFactory';\n\n/**\n * Flow response structure from the backend.\n */\nexport interface AcceptInviteFlowResponse {\n challengeToken?: string;\n data?: {\n additionalData?: Record<string, string>;\n components?: any[];\n fieldErrors?: FieldError[];\n meta?: {\n components?: any[];\n };\n redirectURL?: string;\n };\n error?: FlowExecutionError;\n executionId: string;\n flowStatus: 'INCOMPLETE' | 'COMPLETE' | 'ERROR';\n type?: 'VIEW' | 'REDIRECTION';\n}\n\n/**\n * Render props for custom UI rendering of AcceptInvite.\n */\nexport interface BaseAcceptInviteRenderProps {\n /**\n * Additional data from the current flow step (e.g. consentPrompt for consent nodes).\n */\n additionalData: Record<string, any>;\n\n /**\n * Flow components from the current step.\n */\n components: any[];\n\n /**\n * API error (if any).\n */\n error?: Error | null;\n\n /**\n * Current flow ID from URL.\n */\n executionId?: string;\n\n /**\n * Field validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Navigate to sign in page.\n */\n goToSignIn?: () => void;\n\n /**\n * Function to handle input blur.\n */\n handleInputBlur: (name: string) => void;\n\n /**\n * Function to handle input changes.\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission.\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Invite token from URL.\n */\n inviteToken?: string;\n\n /**\n * Whether the flow has completed successfully.\n */\n isComplete: boolean;\n\n /**\n * Loading state.\n */\n isLoading: boolean;\n\n /**\n * Whether the token validation failed.\n */\n isTokenInvalid: boolean;\n\n /**\n * Whether the form is valid.\n */\n isValid: boolean;\n\n /**\n * Whether the invite token is being validated.\n */\n isValidatingToken: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Subtitle for the current step.\n */\n subtitle?: string;\n\n /**\n * Title for the current step.\n */\n title?: string;\n\n /**\n * Touched fields.\n */\n touched: Record<string, boolean>;\n\n /**\n * Form values for the current step.\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseAcceptInvite component.\n */\nexport interface BaseAcceptInviteProps {\n /**\n * Render props function for custom UI.\n * If not provided, default UI will be rendered.\n */\n children?: (props: BaseAcceptInviteRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name.\n */\n className?: string;\n\n /**\n * Flow ID from the invite link URL.\n */\n executionId?: string;\n\n /**\n * Invite token from the invite link URL.\n */\n inviteToken?: string;\n\n /**\n * Callback when the flow completes successfully.\n */\n onComplete?: () => void;\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when the flow state changes.\n */\n onFlowChange?: (response: AcceptInviteFlowResponse) => void;\n\n /**\n * Callback to navigate to sign in page.\n */\n onGoToSignIn?: () => void;\n\n /**\n * Function to submit flow step data.\n * This makes a request to the flow/execute endpoint.\n */\n onSubmit: (payload: Record<string, any>) => Promise<AcceptInviteFlowResponse>;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Base component for accept invite flow (end-user).\n * Handles the flow logic for validating an invite token and setting a password.\n *\n * When no children are provided, renders a default UI with:\n * - Loading spinner during token validation\n * - Error alerts for invalid/expired tokens\n * - Password form with validation\n * - Success state with sign-in redirect\n *\n * Flow steps handled:\n * 1. Validate invite token (automatic on mount)\n * 2. Password input\n * 3. Flow completion\n */\nconst BaseAcceptInvite: FC<BaseAcceptInviteProps> = ({\n executionId,\n inviteToken,\n onSubmit,\n onComplete,\n onError,\n onFlowChange,\n onGoToSignIn,\n className = '',\n children,\n preferences,\n size = 'medium',\n variant = 'outlined',\n showTitle = true,\n showSubtitle = true,\n}: BaseAcceptInviteProps): ReactElement => {\n const {meta, isInitialized, getStorageManager, vendor} = useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n const [isLoading, setIsLoading] = useState(false);\n const [isValidatingToken, setIsValidatingToken] = useState(true);\n const [isTokenInvalid, setIsTokenInvalid] = useState(false);\n const [isComplete, setIsComplete] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<AcceptInviteFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [formValues, setFormValues] = useState<Record<string, string>>({});\n const [formErrors, setFormErrors] = useState<Record<string, string>>({});\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({});\n const [isFormValid, setIsFormValid] = useState(true);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n /**\n * Project server-side validation errors from the most recent flow response into\n * the local formErrors state. First error per field wins; affected fields are\n * marked touched so errors render immediately.\n */\n useEffect(() => {\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setFormErrors(errors);\n setTouchedFields((prev: Record<string, boolean>) => ({...prev, ...touched}));\n }, [currentFlow]);\n\n const tokenValidationAttemptedRef: any = useRef(false);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages.\n * Uses the transformer's extractErrorMessage function for consistency.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t, 'components.acceptInvite.errors.generic');\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Call the onError callback if provided\n onError?.(error instanceof Error ? error : new Error(errorMessage));\n },\n [t, onError],\n );\n\n /**\n * Normalize flow response to ensure component-driven format.\n * Transforms data.meta.components to data.components.\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: AcceptInviteFlowResponse): AcceptInviteFlowResponse => {\n if (!response?.data?.meta?.components) {\n return response;\n }\n\n try {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.acceptInvite.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...response.data,\n components: components as any,\n },\n };\n } catch {\n // If transformer throws (e.g., error response), return as-is\n return response;\n }\n },\n [t, children],\n );\n\n /**\n * Handle OAuth callback when returning from OAuth provider.\n * This hook processes the authorization code and continues the flow.\n */\n useOAuthCallback({\n currentExecutionId: executionId ?? null,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isStorageReady,\n onComplete: () => {\n setIsValidatingToken(false);\n onComplete?.();\n },\n onError: (error: any) => {\n if (!error?.flowStatus) {\n setIsTokenInvalid(true);\n }\n setIsValidatingToken(false);\n handleError(error);\n },\n onFlowChange: (response: any) => {\n onFlowChange?.(response);\n if (response.flowStatus === 'COMPLETE') {\n setIsComplete(true);\n const completionComponents: any[] = response.data?.components || response.data?.meta?.components || [];\n if (completionComponents.length > 0) {\n setCurrentFlow(response);\n }\n } else {\n // Initialize currentFlow for next steps if not complete\n setCurrentFlow(response);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n }\n },\n onProcessingStart: () => {\n setIsValidatingToken(true);\n },\n onSubmit: async (payload: any) => {\n const rawResponse: any = await onSubmit({\n ...payload,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n });\n const response: any = normalizeFlowResponseLocal(rawResponse);\n await setChallengeToken(response.challengeToken ?? null);\n return response;\n },\n tokenValidationAttemptedRef,\n });\n\n /**\n * Handle input value changes.\n */\n const handleInputChange: any = useCallback((name: string, value: string) => {\n setFormValues((prev: any) => ({...prev, [name]: value}));\n // Clear error when user starts typing\n setFormErrors((prev: any) => {\n const newErrors: any = {...prev};\n delete newErrors[name];\n return newErrors;\n });\n setIsFormValid(true);\n }, []);\n\n /**\n * Handle input blur.\n */\n const handleInputBlur: any = useCallback((name: string) => {\n setTouchedFields((prev: any) => ({...prev, [name]: true}));\n }, []);\n\n /**\n * Validate required fields based on components.\n */\n const validateForm: any = useCallback(\n (components: any[]): {errors: Record<string, string>; isValid: boolean} => {\n const errors: Record<string, string> = {};\n\n const validateComponents = (comps: any[]): any => {\n comps.forEach((comp: any) => {\n if (\n (comp.type === 'PASSWORD_INPUT' ||\n comp.type === 'TEXT_INPUT' ||\n comp.type === 'EMAIL_INPUT' ||\n comp.type === 'PHONE_INPUT' ||\n comp.type === 'OTP_INPUT' ||\n comp.type === 'DATE_INPUT' ||\n comp.type === 'SELECT') &&\n comp.ref\n ) {\n const value: any = formValues[comp.ref];\n if (comp.required && (!value || value.trim() === '')) {\n errors[comp.ref] = t('validations.required.field.error');\n } else if (value) {\n // Evaluate declarative validation rules from meta.components[].validation.\n const ruleValidator = buildValidatorFromRules(comp.validation);\n if (ruleValidator) {\n const message = ruleValidator(value);\n if (message) {\n errors[comp.ref] = t(message);\n }\n }\n }\n }\n if (comp.components && Array.isArray(comp.components)) {\n validateComponents(comp.components);\n }\n });\n };\n\n validateComponents(components);\n\n return {errors, isValid: Object.keys(errors).length === 0};\n },\n [formValues, t],\n );\n\n /**\n * Handle form submission.\n */\n const handleSubmit: any = useCallback(\n async (component: any, data?: Record<string, any>) => {\n if (!currentFlow) {\n return;\n }\n\n // Validate form before submission\n const components: any = currentFlow.data?.components || [];\n const validation: any = validateForm(components);\n\n if (!validation.isValid) {\n setIsFormValid(false);\n setFormErrors(validation.errors);\n // Mark all fields as touched\n const touched: Record<string, boolean> = {};\n Object.keys(validation.errors).forEach((key: any) => {\n touched[key] = true;\n });\n setTouchedFields((prev: any) => ({...prev, ...touched}));\n return;\n }\n\n setIsLoading(true);\n setApiError(null);\n\n try {\n // Build payload with form values\n const inputs: any = {...(data || formValues)};\n\n // Auto-compile consent_decisions if we are on a consent prompt step.\n // Mirrors the same logic in SignIn to ensure the server receives a\n // properly structured JSON payload rather than individual checkbox keys.\n const currentAdditionalData = (currentFlow?.data?.additionalData as Record<string, any>) ?? {};\n if (currentAdditionalData['consentPrompt']) {\n try {\n const raw: any = currentAdditionalData['consentPrompt'];\n const purposes: any[] = typeof raw === 'string' ? JSON.parse(raw) : raw.purposes || raw;\n const isDeny = component?.variant?.toLowerCase() !== 'primary';\n // Approval waits while an approved authorization detail shows a value that cannot be submitted\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n if (!isDeny && isConsentApprovalBlocked(purposes, inputs)) {\n return;\n }\n const decisions = {\n approved: !isDeny,\n ...(isDeny ? {reason: ConsentConstants.REASON_USER_DENIED} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n purposeName: p.purposeName,\n elements: [\n ...(p.essential || []).map((e: any) => ({approved: !isDeny, name: e.name})),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access\n return getConsentElementDecision(p.purposeId, e, !isDeny && inputs[key] === 'true', inputs);\n }),\n ],\n })),\n };\n inputs.consent_decisions = JSON.stringify(decisions);\n Object.keys(inputs).forEach((k: string) => {\n if (\n k.startsWith('__consent_opt__') ||\n k.startsWith(CONSENT_MODIFIED_KEY_PREFIX) ||\n k.startsWith(CONSENT_INVALID_KEY_PREFIX)\n ) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n delete inputs[k];\n }\n });\n } catch {\n // Leave inputs as-is if consent building fails\n }\n }\n\n const payload: Record<string, any> = {\n executionId: currentFlow.executionId,\n inputs,\n verbose: true,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n // Add action ID if component has one\n if (component?.id) {\n payload['action'] = component.id;\n }\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Handle OAuth redirect response\n if (response.type === 'REDIRECTION') {\n const redirectURL: any = response.data?.redirectURL || response?.redirectURL;\n if (redirectURL && typeof window !== 'undefined') {\n // Initiate OAuth redirect with secure state management\n initiateOAuthRedirect(redirectURL, vendor);\n return;\n }\n }\n\n // Check for completion\n if (response.flowStatus === 'COMPLETE') {\n setIsComplete(true);\n const completionComponents: any[] = response.data?.components || response.data?.meta?.components || [];\n if (completionComponents.length > 0) {\n setCurrentFlow(response);\n } else {\n onComplete?.();\n }\n return;\n }\n\n // Check for error status\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n return;\n }\n\n // Update current flow and reset form state for next step, preserving input values\n setCurrentFlow(response);\n setFormErrors({});\n setTouchedFields({});\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n },\n [\n currentFlow,\n formValues,\n validateForm,\n onSubmit,\n onFlowChange,\n onComplete,\n handleError,\n normalizeFlowResponseLocal,\n ],\n );\n\n /**\n * reset form values, errors, and touched fields to initial state\n */\n const resetForm = useCallback(() => {\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n }, []);\n\n /**\n * Validate invite token on component mount.\n */\n useEffect(() => {\n // Skip validation if already validated\n if (tokenValidationAttemptedRef.current) {\n return;\n }\n\n // If an OAuth code is present, this is a return from an OAuth redirect.\n // useOAuthCallback will handle the code — skip the initial invite validation.\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n if (urlParams.get('code')) {\n return;\n }\n\n // Validate required params for initial invite link\n if (!executionId || !inviteToken) {\n setIsValidatingToken(false);\n setIsTokenInvalid(true);\n handleError(new Error('Invalid invite link. Missing executionId or inviteToken.'));\n return;\n }\n\n tokenValidationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsValidatingToken(true);\n setApiError(null);\n\n try {\n // Store executionId in sessionStorage for OAuth callback\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n }\n\n // Send the invite token to validate and continue the flow\n const payload: any = {\n executionId,\n inputs: {\n inviteToken,\n },\n verbose: true,\n };\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Check for error (invalid token)\n if (response.flowStatus === 'ERROR') {\n setIsTokenInvalid(true);\n handleError(response);\n return;\n }\n\n // Token is valid, show the password form\n setCurrentFlow(response);\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n setIsTokenInvalid(true);\n handleError(err);\n } finally {\n setIsValidatingToken(false);\n }\n })();\n }, [executionId, inviteToken, onSubmit, onFlowChange, handleError, normalizeFlowResponseLocal]);\n\n /**\n * Extract title and subtitle from components.\n */\n const extractHeadings: any = useCallback((components: any[]): {subtitle?: string; title?: string} => {\n let title: string | undefined;\n let subtitle: string | undefined;\n\n components.forEach((comp: any) => {\n if (comp.type === 'TEXT') {\n if (comp.variant === 'HEADING_1' && !title) {\n title = comp.label;\n } else if ((comp.variant === 'HEADING_2' || comp.variant === 'SUBTITLE_1') && !subtitle) {\n subtitle = comp.label;\n }\n }\n });\n\n return {subtitle, title};\n }, []);\n\n /**\n * Filter out heading components for default rendering.\n */\n const filterHeadings: any = useCallback(\n (components: any[]): any[] =>\n components.filter(\n (comp: any) => !(comp.type === 'TEXT' && (comp.variant === 'HEADING_1' || comp.variant === 'HEADING_2')),\n ),\n [],\n );\n\n // Get components from normalized response, with fallback to meta.components\n const components: any = currentFlow?.data?.components || currentFlow?.data?.meta?.components || [];\n const {title, subtitle} = extractHeadings(components);\n const componentsWithoutHeadings: any = filterHeadings(components);\n const additionalData: Record<string, any> = (currentFlow?.data?.additionalData as Record<string, any>) ?? {};\n\n // Render props\n const renderProps: BaseAcceptInviteRenderProps = {\n additionalData,\n components,\n error: apiError,\n executionId,\n fieldErrors: formErrors,\n goToSignIn: onGoToSignIn,\n handleInputBlur,\n handleInputChange,\n handleSubmit,\n inviteToken,\n isComplete,\n isLoading,\n isTokenInvalid,\n isValid: isFormValid,\n isValidatingToken,\n meta,\n subtitle,\n title,\n touched: touchedFields,\n values: formValues,\n };\n\n // If children render prop is provided, use it for custom UI\n if (children) {\n return <div className={className}>{children(renderProps)}</div>;\n }\n\n // Default rendering\n\n // Loading state during token validation\n if (isValidatingToken) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={(styles as Record<string, string>)['tokenValidationContainer']}>\n <Spinner size=\"medium\" />\n <Typography variant=\"body1\">Validating your invite link...</Typography>\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Invalid token state\n if (isTokenInvalid) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Header className={styles.header}>\n <CardPrimitive.Title level={2} className={styles.title}>\n Invalid Invite Link\n </CardPrimitive.Title>\n </CardPrimitive.Header>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Title>Unable to verify invite</AlertPrimitive.Title>\n <AlertPrimitive.Description>\n {apiError?.message ||\n 'This invite link is invalid or has expired. Please contact your administrator for a new invite.'}\n </AlertPrimitive.Description>\n </AlertPrimitive>\n {onGoToSignIn && (\n <div className={(styles as Record<string, string>)['goToSignInContainer']}>\n <Button variant=\"outline\" onClick={onGoToSignIn}>\n Go to Sign In\n </Button>\n </div>\n )}\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Flow components (password form)\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (title || subtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && title && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && subtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {apiError && (\n <div className={(styles as Record<string, string>)['errorContainer']}>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n <div>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0\n ? renderInviteUserComponents(\n componentsWithoutHeadings,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n onInputBlur: handleInputBlur,\n onSubmit: handleSubmit,\n size,\n variant,\n },\n )\n : !isLoading && (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">No form components available</Typography>\n </AlertPrimitive>\n )}\n {isLoading && (\n <div className={(styles as Record<string, string>)['centeredSpinnerContainerSmall']}>\n <Spinner size=\"small\" />\n </div>\n )}\n </div>\n {onGoToSignIn && (\n <div className={(styles as Record<string, string>)['alreadyHaveAccountContainer']}>\n <Typography variant=\"body2\">\n Already have an account?{' '}\n <Button\n variant=\"text\"\n onClick={onGoToSignIn}\n className={(styles as Record<string, string>)['signInInlineButton']}\n >\n Sign In\n </Button>\n </Typography>\n </div>\n )}\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\nexport default BaseAcceptInvite;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseAcceptInvite.cjs","names":["BaseAcceptInvite: FC<BaseAcceptInviteProps>","useThunderID","useTranslation","useTheme","customRenderers: ComponentRendererMap","ComponentRendererContext","styles: any","useStyles","useStepExpiry","challengeTokenRef: any","responseFieldErrors: FieldError[] | undefined","errors: Record<string, string>","touched: Record<string, boolean>","tokenValidationAttemptedRef: any","tempData: any","storageManager: any","handleError: any","errorMessage: string","extractErrorMessage","normalizeFlowResponseLocal: any","normalizeFlowResponse","components","response: any","handleInputChange: any","newErrors: any","handleInputBlur: any","validateForm: any","value: any","handleSubmit: any","validation: any","inputs: any","raw: any","purposes: any[]","isConsentApprovalBlocked","ConsentConstants","CONSENT_MODIFIED_KEY_PREFIX","CONSENT_INVALID_KEY_PREFIX","payload: Record<string, any>","redirectURL: any","extractHeadings: any","title: string | undefined","subtitle: string | undefined","title","subtitle","filterHeadings: any","components: any","componentsWithoutHeadings: any","renderProps: BaseAcceptInviteRenderProps","CardPrimitive","cx","Spinner","Typography","AlertPrimitive","Button","renderInviteUserComponents"],"sources":["../../../../../src/components/auth/AcceptInvite/BaseAcceptInvite.tsx"],"sourcesContent":["// Copyright 2025-2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n ConsentConstants,\n FieldError,\n FlowExecutionError,\n FlowMetadataResponse,\n Preferences,\n buildValidatorFromRules,\n CONSENT_INVALID_KEY_PREFIX,\n CONSENT_MODIFIED_KEY_PREFIX,\n getConsentElementDecision,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport useStyles from './BaseAcceptInvite.styles';\nimport ComponentRendererContext, {\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport useTheme from '../../../contexts/Theme/useTheme';\nimport useThunderID from '../../../contexts/ThunderID/useThunderID';\nimport {useOAuthCallback} from '../../../hooks/auth/useOAuthCallback';\nimport useStepExpiry from '../../../hooks/auth/useStepExpiry';\nimport useTranslation from '../../../hooks/useTranslation';\nimport {cx} from '../../../styles/emotion';\nimport {normalizeFlowResponse, extractErrorMessage} from '../../../utils/flowTransformer';\nimport isConsentApprovalBlocked from '../../../utils/isConsentApprovalBlocked';\nimport {initiateOAuthRedirect} from '../../../utils/oauth';\nimport AlertPrimitive from '../../primitives/Alert/Alert';\nimport Button from '../../primitives/Button/Button';\n// eslint-disable-next-line import/no-named-as-default\nimport CardPrimitive, {CardProps} from '../../primitives/Card/Card';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport Typography from '../../primitives/Typography/Typography';\nimport {renderInviteUserComponents} from '../flow/AuthOptionFactory';\n\n/**\n * Flow response structure from the backend.\n */\nexport interface AcceptInviteFlowResponse {\n challengeToken?: string;\n data?: {\n additionalData?: Record<string, string>;\n components?: any[];\n fieldErrors?: FieldError[];\n meta?: {\n components?: any[];\n };\n redirectURL?: string;\n };\n error?: FlowExecutionError;\n executionId: string;\n flowStatus: 'INCOMPLETE' | 'COMPLETE' | 'ERROR';\n type?: 'VIEW' | 'REDIRECTION';\n}\n\n/**\n * Render props for custom UI rendering of AcceptInvite.\n */\nexport interface BaseAcceptInviteRenderProps {\n /**\n * Additional data from the current flow step (e.g. consentPrompt for consent nodes).\n */\n additionalData: Record<string, any>;\n\n /**\n * Flow components from the current step.\n */\n components: any[];\n\n /**\n * API error (if any).\n */\n error?: Error | null;\n\n /**\n * Current flow ID from URL.\n */\n executionId?: string;\n\n /**\n * Field validation errors.\n */\n fieldErrors: Record<string, string>;\n\n /**\n * Navigate to sign in page.\n */\n goToSignIn?: () => void;\n\n /**\n * Function to handle input blur.\n */\n handleInputBlur: (name: string) => void;\n\n /**\n * Function to handle input changes.\n */\n handleInputChange: (name: string, value: string) => void;\n\n /**\n * Function to handle form submission.\n */\n handleSubmit: (component: any, data?: Record<string, any>) => Promise<void>;\n\n /**\n * Invite token from URL.\n */\n inviteToken?: string;\n\n /**\n * Whether the flow has completed successfully.\n */\n isComplete: boolean;\n\n /**\n * Loading state.\n */\n isLoading: boolean;\n\n /**\n * Whether the token validation failed.\n */\n isTokenInvalid: boolean;\n\n /**\n * Whether the form is valid.\n */\n isValid: boolean;\n\n /**\n * Whether the invite token is being validated.\n */\n isValidatingToken: boolean;\n\n /**\n * Flow metadata returned by the platform (v2 only). `null` while loading or unavailable.\n */\n meta: FlowMetadataResponse | null;\n\n /**\n * Subtitle for the current step.\n */\n subtitle?: string;\n\n /**\n * Title for the current step.\n */\n title?: string;\n\n /**\n * Touched fields.\n */\n touched: Record<string, boolean>;\n\n /**\n * Form values for the current step.\n */\n values: Record<string, string>;\n}\n\n/**\n * Props for the BaseAcceptInvite component.\n */\nexport interface BaseAcceptInviteProps {\n /**\n * Render props function for custom UI.\n * If not provided, default UI will be rendered.\n */\n children?: (props: BaseAcceptInviteRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name.\n */\n className?: string;\n\n /**\n * Flow ID from the invite link URL.\n */\n executionId?: string;\n\n /**\n * Invite token from the invite link URL.\n */\n inviteToken?: string;\n\n /**\n * Callback when the flow completes successfully.\n */\n onComplete?: () => void;\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when the flow state changes.\n */\n onFlowChange?: (response: AcceptInviteFlowResponse) => void;\n\n /**\n * Callback to navigate to sign in page.\n */\n onGoToSignIn?: () => void;\n\n /**\n * Function to submit flow step data.\n * This makes a request to the flow/execute endpoint.\n */\n onSubmit: (payload: Record<string, any>) => Promise<AcceptInviteFlowResponse>;\n\n /**\n * Component-level preferences to override global i18n and theme settings.\n * Preferences are deep-merged with global ones, with component preferences\n * taking precedence. Affects this component and all its descendants.\n */\n preferences?: Preferences;\n\n /**\n * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component.\n */\n variant?: CardProps['variant'];\n}\n\n/**\n * Base component for accept invite flow (end-user).\n * Handles the flow logic for validating an invite token and setting a password.\n *\n * When no children are provided, renders a default UI with:\n * - Loading spinner during token validation\n * - Error alerts for invalid/expired tokens\n * - Password form with validation\n * - Success state with sign-in redirect\n *\n * Flow steps handled:\n * 1. Validate invite token (automatic on mount)\n * 2. Password input\n * 3. Flow completion\n */\nconst BaseAcceptInvite: FC<BaseAcceptInviteProps> = ({\n executionId,\n inviteToken,\n onSubmit,\n onComplete,\n onError,\n onFlowChange,\n onGoToSignIn,\n className = '',\n children,\n preferences,\n size = 'medium',\n variant = 'outlined',\n showTitle = true,\n showSubtitle = true,\n}: BaseAcceptInviteProps): ReactElement => {\n const {meta, isInitialized, getStorageManager, vendor} = useThunderID();\n const {t} = useTranslation(preferences?.i18n);\n const {theme} = useTheme();\n const customRenderers: ComponentRendererMap = useContext(ComponentRendererContext);\n const styles: any = useStyles(theme, theme.vars.colors.text.primary);\n const [isLoading, setIsLoading] = useState(false);\n const [isValidatingToken, setIsValidatingToken] = useState(true);\n const [isTokenInvalid, setIsTokenInvalid] = useState(false);\n const [isComplete, setIsComplete] = useState(false);\n const [currentFlow, setCurrentFlow] = useState<AcceptInviteFlowResponse | null>(null);\n const [apiError, setApiError] = useState<Error | null>(null);\n const [formValues, setFormValues] = useState<Record<string, string>>({});\n const [formErrors, setFormErrors] = useState<Record<string, string>>({});\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({});\n const [isFormValid, setIsFormValid] = useState(true);\n // A custom renderer can expire the step from the client; it holds until the next step response.\n const {expireStep, isStepExpired} = useStepExpiry(currentFlow);\n const [isStorageReady, setIsStorageReady] = useState(false);\n const challengeTokenRef: any = useRef<string | null>(null);\n\n /**\n * Project server-side validation errors from the most recent flow response into\n * the local formErrors state. First error per field wins; affected fields are\n * marked touched so errors render immediately.\n */\n useEffect(() => {\n const responseFieldErrors: FieldError[] | undefined = (currentFlow?.data as any)?.fieldErrors;\n if (!responseFieldErrors || responseFieldErrors.length === 0) {\n return;\n }\n const errors: Record<string, string> = {};\n const touched: Record<string, boolean> = {};\n for (const fe of responseFieldErrors) {\n if (!(fe.identifier in errors)) {\n errors[fe.identifier] = fe.message;\n touched[fe.identifier] = true;\n }\n }\n setFormErrors(errors);\n setTouchedFields((prev: Record<string, boolean>) => ({...prev, ...touched}));\n }, [currentFlow]);\n\n const tokenValidationAttemptedRef: any = useRef(false);\n\n /**\n * Restore any challenge token persisted before an OAuth redirect.\n * Waits for SDK initialization before reading from storage.\n */\n useEffect(() => {\n if (!isInitialized) return;\n\n (async (): Promise<void> => {\n try {\n const storageManager: any = await getStorageManager();\n const tempData: any = await storageManager?.getTemporaryData();\n if (tempData?.challengeToken) {\n challengeTokenRef.current = tempData.challengeToken as string;\n }\n } finally {\n setIsStorageReady(true);\n }\n })();\n }, [isInitialized]);\n\n /**\n * Updates challengeTokenRef immediately (stale-closure safe) and persists via\n * the provider's StorageManager so the token survives OAuth redirects.\n */\n const setChallengeToken = async (challengeToken: string | null): Promise<void> => {\n challengeTokenRef.current = challengeToken;\n const storageManager: any = await getStorageManager();\n if (storageManager) {\n if (challengeToken) {\n await storageManager.setTemporaryDataParameter('challengeToken', challengeToken);\n } else {\n await storageManager.removeTemporaryDataParameter('challengeToken');\n }\n }\n };\n\n /**\n * Handle error responses and extract meaningful error messages.\n * Uses the transformer's extractErrorMessage function for consistency.\n */\n const handleError: any = useCallback(\n (error: any) => {\n const errorMessage: string = extractErrorMessage(error, t, 'components.acceptInvite.errors.generic');\n\n // Set the API error state\n setApiError(error instanceof Error ? error : new Error(errorMessage));\n\n // Call the onError callback if provided\n onError?.(error instanceof Error ? error : new Error(errorMessage));\n },\n [t, onError],\n );\n\n /**\n * Normalize flow response to ensure component-driven format.\n * Transforms data.meta.components to data.components.\n */\n const normalizeFlowResponseLocal: any = useCallback(\n (response: AcceptInviteFlowResponse): AcceptInviteFlowResponse => {\n if (!response?.data?.meta?.components) {\n return response;\n }\n\n try {\n const {components} = normalizeFlowResponse(\n response,\n t,\n {\n defaultErrorKey: 'components.acceptInvite.errors.generic',\n resolveTranslations: false,\n },\n meta,\n );\n\n return {\n ...response,\n data: {\n ...response.data,\n components: components as any,\n },\n };\n } catch {\n // If transformer throws (e.g., error response), return as-is\n return response;\n }\n },\n [t, children],\n );\n\n /**\n * Handle OAuth callback when returning from OAuth provider.\n * This hook processes the authorization code and continues the flow.\n */\n useOAuthCallback({\n currentExecutionId: executionId ?? null,\n executionIdStorageKey: `${vendor}_execution_id`,\n isInitialized: isStorageReady,\n onComplete: () => {\n setIsValidatingToken(false);\n onComplete?.();\n },\n onError: (error: any) => {\n if (!error?.flowStatus) {\n setIsTokenInvalid(true);\n }\n setIsValidatingToken(false);\n handleError(error);\n },\n onFlowChange: (response: any) => {\n onFlowChange?.(response);\n if (response.flowStatus === 'COMPLETE') {\n setIsComplete(true);\n const completionComponents: any[] = response.data?.components || response.data?.meta?.components || [];\n if (completionComponents.length > 0) {\n setCurrentFlow(response);\n }\n } else {\n // Initialize currentFlow for next steps if not complete\n setCurrentFlow(response);\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n }\n },\n onProcessingStart: () => {\n setIsValidatingToken(true);\n },\n onSubmit: async (payload: any) => {\n const rawResponse: any = await onSubmit({\n ...payload,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n });\n const response: any = normalizeFlowResponseLocal(rawResponse);\n await setChallengeToken(response.challengeToken ?? null);\n return response;\n },\n tokenValidationAttemptedRef,\n });\n\n /**\n * Handle input value changes.\n */\n const handleInputChange: any = useCallback((name: string, value: string) => {\n setFormValues((prev: any) => ({...prev, [name]: value}));\n // Clear error when user starts typing\n setFormErrors((prev: any) => {\n const newErrors: any = {...prev};\n delete newErrors[name];\n return newErrors;\n });\n setIsFormValid(true);\n }, []);\n\n /**\n * Handle input blur.\n */\n const handleInputBlur: any = useCallback((name: string) => {\n setTouchedFields((prev: any) => ({...prev, [name]: true}));\n }, []);\n\n /**\n * Validate required fields based on components.\n */\n const validateForm: any = useCallback(\n (components: any[]): {errors: Record<string, string>; isValid: boolean} => {\n const errors: Record<string, string> = {};\n\n const validateComponents = (comps: any[]): any => {\n comps.forEach((comp: any) => {\n if (\n (comp.type === 'PASSWORD_INPUT' ||\n comp.type === 'TEXT_INPUT' ||\n comp.type === 'EMAIL_INPUT' ||\n comp.type === 'PHONE_INPUT' ||\n comp.type === 'OTP_INPUT' ||\n comp.type === 'DATE_INPUT' ||\n comp.type === 'SELECT') &&\n comp.ref\n ) {\n const value: any = formValues[comp.ref];\n if (comp.required && (!value || value.trim() === '')) {\n errors[comp.ref] = t('validations.required.field.error');\n } else if (value) {\n // Evaluate declarative validation rules from meta.components[].validation.\n const ruleValidator = buildValidatorFromRules(comp.validation);\n if (ruleValidator) {\n const message = ruleValidator(value);\n if (message) {\n errors[comp.ref] = t(message);\n }\n }\n }\n }\n if (comp.components && Array.isArray(comp.components)) {\n validateComponents(comp.components);\n }\n });\n };\n\n validateComponents(components);\n\n return {errors, isValid: Object.keys(errors).length === 0};\n },\n [formValues, t],\n );\n\n /**\n * Handle form submission.\n */\n const handleSubmit: any = useCallback(\n async (component: any, data?: Record<string, any>) => {\n if (!currentFlow) {\n return;\n }\n\n // Validate form before submission\n const components: any = currentFlow.data?.components || [];\n const validation: any = validateForm(components);\n\n if (!validation.isValid) {\n setIsFormValid(false);\n setFormErrors(validation.errors);\n // Mark all fields as touched\n const touched: Record<string, boolean> = {};\n Object.keys(validation.errors).forEach((key: any) => {\n touched[key] = true;\n });\n setTouchedFields((prev: any) => ({...prev, ...touched}));\n return;\n }\n\n setIsLoading(true);\n setApiError(null);\n\n try {\n // Build payload with form values\n const inputs: any = {...(data || formValues)};\n\n // Auto-compile consent_decisions if we are on a consent prompt step.\n // Mirrors the same logic in SignIn to ensure the server receives a\n // properly structured JSON payload rather than individual checkbox keys.\n const currentAdditionalData = (currentFlow?.data?.additionalData as Record<string, any>) ?? {};\n if (currentAdditionalData['consentPrompt']) {\n try {\n const raw: any = currentAdditionalData['consentPrompt'];\n const purposes: any[] = typeof raw === 'string' ? JSON.parse(raw) : raw.purposes || raw;\n const isDeny = component?.variant?.toLowerCase() !== 'primary';\n // Approval waits while an approved authorization detail shows a value that cannot be submitted\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n if (!isDeny && isConsentApprovalBlocked(purposes, inputs)) {\n return;\n }\n const decisions = {\n approved: !isDeny,\n ...(isDeny ? {reason: ConsentConstants.REASON_USER_DENIED} : {}),\n purposes: purposes.map((p: any) => ({\n approved: !isDeny,\n purposeName: p.purposeName,\n elements: [\n ...(p.essential || []).map((e: any) => ({approved: !isDeny, name: e.name})),\n ...(p.optional || []).map((e: any) => {\n const key = `__consent_opt__${p.purposeId}__${e.name}`;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access\n return getConsentElementDecision(p.purposeId, e, !isDeny && inputs[key] === 'true', inputs);\n }),\n ],\n })),\n };\n inputs.consent_decisions = JSON.stringify(decisions);\n Object.keys(inputs).forEach((k: string) => {\n if (\n k.startsWith('__consent_opt__') ||\n k.startsWith(CONSENT_MODIFIED_KEY_PREFIX) ||\n k.startsWith(CONSENT_INVALID_KEY_PREFIX)\n ) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n delete inputs[k];\n }\n });\n } catch {\n // Leave inputs as-is if consent building fails\n }\n }\n\n const payload: Record<string, any> = {\n executionId: currentFlow.executionId,\n inputs,\n verbose: true,\n ...(challengeTokenRef.current ? {challengeToken: challengeTokenRef.current} : {}),\n };\n\n // Add action ID if component has one\n if (component?.id) {\n payload['action'] = component.id;\n }\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Handle OAuth redirect response\n if (response.type === 'REDIRECTION') {\n const redirectURL: any = response.data?.redirectURL || response?.redirectURL;\n if (redirectURL && typeof window !== 'undefined') {\n // Initiate OAuth redirect with secure state management\n initiateOAuthRedirect(redirectURL, vendor);\n return;\n }\n }\n\n // Check for completion\n if (response.flowStatus === 'COMPLETE') {\n setIsComplete(true);\n const completionComponents: any[] = response.data?.components || response.data?.meta?.components || [];\n if (completionComponents.length > 0) {\n setCurrentFlow(response);\n } else {\n onComplete?.();\n }\n return;\n }\n\n // Check for error status\n if (response.flowStatus === 'ERROR') {\n handleError(response);\n return;\n }\n\n // Update current flow and reset form state for next step, preserving input values\n setCurrentFlow(response);\n setFormErrors({});\n setTouchedFields({});\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n handleError(err);\n } finally {\n setIsLoading(false);\n }\n },\n [\n currentFlow,\n formValues,\n validateForm,\n onSubmit,\n onFlowChange,\n onComplete,\n handleError,\n normalizeFlowResponseLocal,\n ],\n );\n\n /**\n * reset form values, errors, and touched fields to initial state\n */\n const resetForm = useCallback(() => {\n setFormValues({});\n setFormErrors({});\n setTouchedFields({});\n }, []);\n\n /**\n * Validate invite token on component mount.\n */\n useEffect(() => {\n // Skip validation if already validated\n if (tokenValidationAttemptedRef.current) {\n return;\n }\n\n // If an OAuth code is present, this is a return from an OAuth redirect.\n // useOAuthCallback will handle the code — skip the initial invite validation.\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n if (urlParams.get('code')) {\n return;\n }\n\n // Validate required params for initial invite link\n if (!executionId || !inviteToken) {\n setIsValidatingToken(false);\n setIsTokenInvalid(true);\n handleError(new Error('Invalid invite link. Missing executionId or inviteToken.'));\n return;\n }\n\n tokenValidationAttemptedRef.current = true;\n\n (async (): Promise<void> => {\n setIsValidatingToken(true);\n setApiError(null);\n\n try {\n // Store executionId in sessionStorage for OAuth callback\n if (executionId) {\n sessionStorage.setItem(`${vendor}_execution_id`, executionId);\n }\n\n // Send the invite token to validate and continue the flow\n const payload: any = {\n executionId,\n inputs: {\n inviteToken,\n },\n verbose: true,\n };\n\n const rawResponse: any = await onSubmit(payload);\n const response: any = normalizeFlowResponseLocal(rawResponse);\n onFlowChange?.(response);\n\n await setChallengeToken(response.challengeToken ?? null);\n\n // Check for error (invalid token)\n if (response.flowStatus === 'ERROR') {\n setIsTokenInvalid(true);\n handleError(response);\n return;\n }\n\n // Token is valid, show the password form\n setCurrentFlow(response);\n\n // Display error from INCOMPLETE response\n if (response?.error) {\n handleError(response);\n }\n } catch (err) {\n setIsTokenInvalid(true);\n handleError(err);\n } finally {\n setIsValidatingToken(false);\n }\n })();\n }, [executionId, inviteToken, onSubmit, onFlowChange, handleError, normalizeFlowResponseLocal]);\n\n /**\n * Extract title and subtitle from components.\n */\n const extractHeadings: any = useCallback((components: any[]): {subtitle?: string; title?: string} => {\n let title: string | undefined;\n let subtitle: string | undefined;\n\n components.forEach((comp: any) => {\n if (comp.type === 'TEXT') {\n if (comp.variant === 'HEADING_1' && !title) {\n title = comp.label;\n } else if ((comp.variant === 'HEADING_2' || comp.variant === 'SUBTITLE_1') && !subtitle) {\n subtitle = comp.label;\n }\n }\n });\n\n return {subtitle, title};\n }, []);\n\n /**\n * Filter out heading components for default rendering.\n */\n const filterHeadings: any = useCallback(\n (components: any[]): any[] =>\n components.filter(\n (comp: any) => !(comp.type === 'TEXT' && (comp.variant === 'HEADING_1' || comp.variant === 'HEADING_2')),\n ),\n [],\n );\n\n // Get components from normalized response, with fallback to meta.components\n const components: any = currentFlow?.data?.components || currentFlow?.data?.meta?.components || [];\n const {title, subtitle} = extractHeadings(components);\n const componentsWithoutHeadings: any = filterHeadings(components);\n const additionalData: Record<string, any> = (currentFlow?.data?.additionalData as Record<string, any>) ?? {};\n\n // Render props\n const renderProps: BaseAcceptInviteRenderProps = {\n additionalData,\n components,\n error: apiError,\n executionId,\n fieldErrors: formErrors,\n goToSignIn: onGoToSignIn,\n handleInputBlur,\n handleInputChange,\n handleSubmit,\n inviteToken,\n isComplete,\n isLoading,\n isTokenInvalid,\n isValid: isFormValid,\n isValidatingToken,\n meta,\n subtitle,\n title,\n touched: touchedFields,\n values: formValues,\n };\n\n // If children render prop is provided, use it for custom UI\n if (children) {\n return <div className={className}>{children(renderProps)}</div>;\n }\n\n // Default rendering\n\n // Loading state during token validation\n if (isValidatingToken) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Content>\n <div className={(styles as Record<string, string>)['tokenValidationContainer']}>\n <Spinner size=\"medium\" />\n <Typography variant=\"body1\">Validating your invite link...</Typography>\n </div>\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Invalid token state\n if (isTokenInvalid) {\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n <CardPrimitive.Header className={styles.header}>\n <CardPrimitive.Title level={2} className={styles.title}>\n Invalid Invite Link\n </CardPrimitive.Title>\n </CardPrimitive.Header>\n <CardPrimitive.Content>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Title>Unable to verify invite</AlertPrimitive.Title>\n <AlertPrimitive.Description>\n {apiError?.message ||\n 'This invite link is invalid or has expired. Please contact your administrator for a new invite.'}\n </AlertPrimitive.Description>\n </AlertPrimitive>\n {onGoToSignIn && (\n <div className={(styles as Record<string, string>)['goToSignInContainer']}>\n <Button variant=\"outline\" onClick={onGoToSignIn}>\n Go to Sign In\n </Button>\n </div>\n )}\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n }\n\n // Flow components (password form)\n return (\n <CardPrimitive className={cx(className, styles.card)} variant={variant}>\n {(showTitle || showSubtitle) && (title || subtitle) && (\n <CardPrimitive.Header className={styles.header}>\n {showTitle && title && (\n <CardPrimitive.Title level={2} className={styles.title}>\n {title}\n </CardPrimitive.Title>\n )}\n {showSubtitle && subtitle && (\n <Typography variant=\"body1\" className={styles.subtitle}>\n {subtitle}\n </Typography>\n )}\n </CardPrimitive.Header>\n )}\n <CardPrimitive.Content>\n {apiError && (\n <div className={(styles as Record<string, string>)['errorContainer']}>\n <AlertPrimitive variant=\"error\">\n <AlertPrimitive.Description>{apiError.message}</AlertPrimitive.Description>\n </AlertPrimitive>\n </div>\n )}\n <div>\n {componentsWithoutHeadings && componentsWithoutHeadings.length > 0\n ? renderInviteUserComponents(\n componentsWithoutHeadings,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n resetForm,\n handleInputChange,\n {\n _customRenderers: customRenderers,\n _theme: theme,\n isFormComplete: validateForm(componentsWithoutHeadings).isValid,\n isTimeoutDisabled: isStepExpired,\n onInputBlur: handleInputBlur,\n onStepExpire: expireStep,\n onSubmit: handleSubmit,\n size,\n variant,\n },\n )\n : !isLoading && (\n <AlertPrimitive variant=\"warning\">\n <Typography variant=\"body1\">No form components available</Typography>\n </AlertPrimitive>\n )}\n {isLoading && (\n <div className={(styles as Record<string, string>)['centeredSpinnerContainerSmall']}>\n <Spinner size=\"small\" />\n </div>\n )}\n </div>\n {onGoToSignIn && (\n <div className={(styles as Record<string, string>)['alreadyHaveAccountContainer']}>\n <Typography variant=\"body2\">\n Already have an account?{' '}\n <Button\n variant=\"text\"\n onClick={onGoToSignIn}\n className={(styles as Record<string, string>)['signInInlineButton']}\n >\n Sign In\n </Button>\n </Typography>\n </div>\n )}\n </CardPrimitive.Content>\n </CardPrimitive>\n );\n};\n\nexport default BaseAcceptInvite;\n"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ const require_flowTransformer = require('../../../utils/flowTransformer.cjs');
|
|
|
8
8
|
const require_Spinner = require('../../primitives/Spinner/Spinner.cjs');
|
|
9
9
|
const require_Typography = require('../../primitives/Typography/Typography.cjs');
|
|
10
10
|
const require_Card = require('../../primitives/Card/Card.cjs');
|
|
11
|
+
const require_useStepExpiry = require('../../../hooks/auth/useStepExpiry.cjs');
|
|
11
12
|
const require_Alert = require('../../primitives/Alert/Alert.cjs');
|
|
12
13
|
const require_AuthOptionFactory = require('../flow/AuthOptionFactory.cjs');
|
|
13
14
|
const require_BaseInviteUser_styles = require('./BaseInviteUser.styles.cjs');
|
|
@@ -48,6 +49,7 @@ const BaseInviteUser = ({ onInitialize, onSubmit, onError, onFlowChange, classNa
|
|
|
48
49
|
const [formErrors, setFormErrors] = (0, react.useState)({});
|
|
49
50
|
const [touchedFields, setTouchedFields] = (0, react.useState)({});
|
|
50
51
|
const [isFormValid, setIsFormValid] = (0, react.useState)(true);
|
|
52
|
+
const { expireStep, isStepExpired } = require_useStepExpiry.default(currentFlow);
|
|
51
53
|
const challengeTokenRef = (0, react.useRef)(null);
|
|
52
54
|
/**
|
|
53
55
|
* Project server-side validation errors from the most recent flow response into the
|
|
@@ -344,9 +346,12 @@ const BaseInviteUser = ({ onInitialize, onSubmit, onError, onFlowChange, classNa
|
|
|
344
346
|
fetchOrganizationUnitChildren,
|
|
345
347
|
fetchUsers,
|
|
346
348
|
fetchUserTypes,
|
|
349
|
+
isFormComplete: validateForm(components$1).isValid,
|
|
350
|
+
isTimeoutDisabled: isStepExpired,
|
|
347
351
|
meta,
|
|
348
352
|
onInputBlur: handleInputBlur,
|
|
349
353
|
onPickerError: onError,
|
|
354
|
+
onStepExpire: expireStep,
|
|
350
355
|
onSubmit: handleSubmit,
|
|
351
356
|
size,
|
|
352
357
|
t,
|
|
@@ -366,6 +371,9 @@ const BaseInviteUser = ({ onInitialize, onSubmit, onError, onFlowChange, classNa
|
|
|
366
371
|
formErrors,
|
|
367
372
|
isLoading,
|
|
368
373
|
isFormValid,
|
|
374
|
+
validateForm,
|
|
375
|
+
isStepExpired,
|
|
376
|
+
expireStep,
|
|
369
377
|
handleInputChange,
|
|
370
378
|
handleInputBlur,
|
|
371
379
|
handleSubmit,
|