@thunderid/react 0.3.7 → 0.4.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/factories/FieldFactory.cjs +2 -1
- package/dist/cjs/components/factories/FieldFactory.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs +56 -33
- package/dist/cjs/components/presentation/auth/AuthOptionFactory.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs +5 -1
- package/dist/cjs/components/presentation/auth/SignIn/BaseSignIn.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs +5 -1
- package/dist/cjs/components/presentation/auth/SignUp/BaseSignUp.cjs.map +1 -1
- package/dist/cjs/components/primitives/FormControl/FormControl.cjs +2 -1
- package/dist/cjs/components/primitives/FormControl/FormControl.cjs.map +1 -1
- package/dist/cjs/components/primitives/Typography/Typography.cjs.map +1 -1
- package/dist/components/factories/FieldFactory.d.ts +4 -0
- package/dist/components/factories/FieldFactory.d.ts.map +1 -1
- package/dist/components/factories/FieldFactory.js +2 -1
- package/dist/components/factories/FieldFactory.js.map +1 -1
- package/dist/components/presentation/auth/AuthOptionFactory.d.ts.map +1 -1
- package/dist/components/presentation/auth/AuthOptionFactory.js +57 -34
- package/dist/components/presentation/auth/AuthOptionFactory.js.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts +4 -0
- package/dist/components/presentation/auth/SignIn/BaseSignIn.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js +5 -1
- package/dist/components/presentation/auth/SignIn/BaseSignIn.js.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts +4 -0
- package/dist/components/presentation/auth/SignUp/BaseSignUp.d.ts.map +1 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js +5 -1
- package/dist/components/presentation/auth/SignUp/BaseSignUp.js.map +1 -1
- package/dist/components/primitives/FormControl/FormControl.d.ts +4 -0
- package/dist/components/primitives/FormControl/FormControl.d.ts.map +1 -1
- package/dist/components/primitives/FormControl/FormControl.js +2 -1
- package/dist/components/primitives/FormControl/FormControl.js.map +1 -1
- package/dist/components/primitives/Typography/Typography.d.ts +4 -0
- package/dist/components/primitives/Typography/Typography.d.ts.map +1 -1
- package/dist/components/primitives/Typography/Typography.js.map +1 -1
- package/package.json +2 -2
|
@@ -47,13 +47,14 @@ const validateFieldValue = (value, type, required = false, touched = false) => {
|
|
|
47
47
|
* ```
|
|
48
48
|
*/
|
|
49
49
|
const createField = (config) => {
|
|
50
|
-
const { name, type, label, required, value, onChange, onBlur, disabled = false, error, className, options = [], touched = false, placeholder } = config;
|
|
50
|
+
const { name, type, label, required, value, onChange, onBlur, disabled = false, error, className, id, options = [], touched = false, placeholder } = config;
|
|
51
51
|
const validationError = error || validateFieldValue(value, type, required, touched);
|
|
52
52
|
const commonProps = {
|
|
53
53
|
className,
|
|
54
54
|
"data-testid": `thunderid-signin-${name}`,
|
|
55
55
|
disabled,
|
|
56
56
|
error: validationError,
|
|
57
|
+
id,
|
|
57
58
|
label,
|
|
58
59
|
name,
|
|
59
60
|
onBlur,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldFactory.cjs","names":["FieldType","numValue: number","validationError: string | null","commonProps: Record<string, any>","PasswordField","TextField","DatePicker","isChecked: boolean","Checkbox","OtpField","fieldOptions: SelectOption[]","Select","FieldFactory: FC<FieldConfig>"],"sources":["../../../../src/components/factories/FieldFactory.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {FieldType} from '@thunderid/browser';\nimport {ChangeEvent, FC, ReactElement} from 'react';\nimport Checkbox from '../primitives/Checkbox/Checkbox';\nimport DatePicker from '../primitives/DatePicker/DatePicker';\nimport OtpField from '../primitives/OtpField/OtpField';\nimport PasswordField from '../primitives/PasswordField/PasswordField';\nimport Select, {SelectOption} from '../primitives/Select/Select';\nimport TextField from '../primitives/TextField/TextField';\n\n/**\n * Interface for field configuration.\n */\nexport interface FieldConfig {\n /**\n * Additional CSS class name.\n */\n className?: string;\n /**\n * Whether the field is disabled.\n */\n disabled?: boolean;\n /**\n * Error message to display.\n */\n error?: string;\n /**\n * Display name for the field.\n */\n label: string;\n /**\n * The name of the field.\n */\n name: string;\n /**\n * Callback function when the field loses focus.\n */\n onBlur?: () => void;\n /**\n * Callback function when the field value changes.\n */\n onChange: (value: string) => void;\n /**\n * Additional options for multi-valued fields.\n */\n options?: SelectOption[];\n /**\n * Placeholder text for the field.\n */\n placeholder?: string;\n /**\n * Whether the field is required.\n */\n required: boolean;\n /**\n * Whether the field has been touched/interacted with by the user.\n */\n touched?: boolean;\n /**\n * The field type.\n */\n type: FieldType;\n /**\n * Current value of the field.\n */\n value: string;\n}\n\n/**\n * Utility function to validate field values based on type\n */\nexport const validateFieldValue = (\n value: string,\n type: FieldType,\n required = false,\n touched = false,\n): string | null => {\n if (required && touched && (!value || value.trim() === '')) {\n return 'This field is required';\n }\n\n if (!value || value.trim() === '') {\n return null;\n }\n\n switch (type) {\n case FieldType.Number: {\n const numValue: number = parseInt(value, 10);\n if (Number.isNaN(numValue)) {\n return 'Please enter a valid number';\n }\n break;\n }\n default:\n break;\n }\n\n return null;\n};\n\n/**\n * Factory function to create form fields based on field type.\n *\n * @param config - The field configuration\n * @returns The appropriate React component for the field type\n *\n * @example\n * ```tsx\n * const field = createField({\n * param: 'username',\n * type: FieldType.Text,\n * label: 'Username',\n * confidential: false,\n * required: true,\n * value: '',\n * onChange: (value) => console.log(value)\n * });\n * ```\n */\nexport const createField = (config: FieldConfig): ReactElement => {\n const {\n name,\n type,\n label,\n required,\n value,\n onChange,\n onBlur,\n disabled = false,\n error,\n className,\n options = [],\n touched = false,\n placeholder,\n } = config;\n\n const validationError: string | null = error || validateFieldValue(value, type, required, touched);\n\n const commonProps: Record<string, any> = {\n className,\n 'data-testid': `thunderid-signin-${name}`,\n disabled,\n error: validationError,\n label,\n name,\n onBlur,\n placeholder,\n required,\n value,\n };\n\n switch (type) {\n case FieldType.Password:\n return <PasswordField {...commonProps} onChange={onChange} />;\n case FieldType.Text:\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"off\"\n />\n );\n case FieldType.Email:\n return (\n <TextField\n {...commonProps}\n type=\"email\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"email\"\n />\n );\n case FieldType.Tel:\n return (\n <TextField\n {...commonProps}\n type=\"tel\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"tel\"\n />\n );\n case FieldType.Date:\n return (\n <DatePicker {...commonProps} onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)} />\n );\n case FieldType.Checkbox: {\n const isChecked: boolean = value === 'true' || (value as any) === true;\n return (\n <Checkbox\n {...commonProps}\n checked={isChecked}\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.checked.toString())}\n />\n );\n }\n case FieldType.Otp:\n return (\n <OtpField {...commonProps} onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)} />\n );\n case FieldType.Number:\n return (\n <TextField\n {...commonProps}\n type=\"number\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Enter a numeric value\"\n />\n );\n case FieldType.Select: {\n const fieldOptions: SelectOption[] = options.length > 0 ? options : [];\n\n if (fieldOptions.length > 0) {\n return (\n <Select\n {...commonProps}\n options={fieldOptions}\n onChange={(e: ChangeEvent<HTMLSelectElement>): void => onChange(e.target.value)}\n helperText=\"Select from available options\"\n />\n );\n }\n\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Enter multiple values separated by commas (e.g., value1, value2, value3)\"\n placeholder=\"value1, value2, value3\"\n />\n );\n }\n default:\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Unknown field type, treating as text\"\n />\n );\n }\n};\n\n/**\n * React component wrapper for the field factory.\n */\nexport const FieldFactory: FC<FieldConfig> = (props: FieldConfig): ReactElement => createField(props);\n\nexport default FieldFactory;\n"],"mappings":";;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"FieldFactory.cjs","names":["FieldType","numValue: number","validationError: string | null","commonProps: Record<string, any>","PasswordField","TextField","DatePicker","isChecked: boolean","Checkbox","OtpField","fieldOptions: SelectOption[]","Select","FieldFactory: FC<FieldConfig>"],"sources":["../../../../src/components/factories/FieldFactory.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {FieldType} from '@thunderid/browser';\nimport {ChangeEvent, FC, ReactElement} from 'react';\nimport Checkbox from '../primitives/Checkbox/Checkbox';\nimport DatePicker from '../primitives/DatePicker/DatePicker';\nimport OtpField from '../primitives/OtpField/OtpField';\nimport PasswordField from '../primitives/PasswordField/PasswordField';\nimport Select, {SelectOption} from '../primitives/Select/Select';\nimport TextField from '../primitives/TextField/TextField';\n\n/**\n * Interface for field configuration.\n */\nexport interface FieldConfig {\n /**\n * Additional CSS class name.\n */\n className?: string;\n /**\n * Whether the field is disabled.\n */\n disabled?: boolean;\n /**\n * Error message to display.\n */\n error?: string;\n /**\n * HTML id to apply to the rendered field.\n */\n id?: string;\n /**\n * Display name for the field.\n */\n label: string;\n /**\n * The name of the field.\n */\n name: string;\n /**\n * Callback function when the field loses focus.\n */\n onBlur?: () => void;\n /**\n * Callback function when the field value changes.\n */\n onChange: (value: string) => void;\n /**\n * Additional options for multi-valued fields.\n */\n options?: SelectOption[];\n /**\n * Placeholder text for the field.\n */\n placeholder?: string;\n /**\n * Whether the field is required.\n */\n required: boolean;\n /**\n * Whether the field has been touched/interacted with by the user.\n */\n touched?: boolean;\n /**\n * The field type.\n */\n type: FieldType;\n /**\n * Current value of the field.\n */\n value: string;\n}\n\n/**\n * Utility function to validate field values based on type\n */\nexport const validateFieldValue = (\n value: string,\n type: FieldType,\n required = false,\n touched = false,\n): string | null => {\n if (required && touched && (!value || value.trim() === '')) {\n return 'This field is required';\n }\n\n if (!value || value.trim() === '') {\n return null;\n }\n\n switch (type) {\n case FieldType.Number: {\n const numValue: number = parseInt(value, 10);\n if (Number.isNaN(numValue)) {\n return 'Please enter a valid number';\n }\n break;\n }\n default:\n break;\n }\n\n return null;\n};\n\n/**\n * Factory function to create form fields based on field type.\n *\n * @param config - The field configuration\n * @returns The appropriate React component for the field type\n *\n * @example\n * ```tsx\n * const field = createField({\n * param: 'username',\n * type: FieldType.Text,\n * label: 'Username',\n * confidential: false,\n * required: true,\n * value: '',\n * onChange: (value) => console.log(value)\n * });\n * ```\n */\nexport const createField = (config: FieldConfig): ReactElement => {\n const {\n name,\n type,\n label,\n required,\n value,\n onChange,\n onBlur,\n disabled = false,\n error,\n className,\n id,\n options = [],\n touched = false,\n placeholder,\n } = config;\n\n const validationError: string | null = error || validateFieldValue(value, type, required, touched);\n\n const commonProps: Record<string, any> = {\n className,\n 'data-testid': `thunderid-signin-${name}`,\n disabled,\n error: validationError,\n id,\n label,\n name,\n onBlur,\n placeholder,\n required,\n value,\n };\n\n switch (type) {\n case FieldType.Password:\n return <PasswordField {...commonProps} onChange={onChange} />;\n case FieldType.Text:\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"off\"\n />\n );\n case FieldType.Email:\n return (\n <TextField\n {...commonProps}\n type=\"email\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"email\"\n />\n );\n case FieldType.Tel:\n return (\n <TextField\n {...commonProps}\n type=\"tel\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n autoComplete=\"tel\"\n />\n );\n case FieldType.Date:\n return (\n <DatePicker {...commonProps} onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)} />\n );\n case FieldType.Checkbox: {\n const isChecked: boolean = value === 'true' || (value as any) === true;\n return (\n <Checkbox\n {...commonProps}\n checked={isChecked}\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.checked.toString())}\n />\n );\n }\n case FieldType.Otp:\n return (\n <OtpField {...commonProps} onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)} />\n );\n case FieldType.Number:\n return (\n <TextField\n {...commonProps}\n type=\"number\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Enter a numeric value\"\n />\n );\n case FieldType.Select: {\n const fieldOptions: SelectOption[] = options.length > 0 ? options : [];\n\n if (fieldOptions.length > 0) {\n return (\n <Select\n {...commonProps}\n options={fieldOptions}\n onChange={(e: ChangeEvent<HTMLSelectElement>): void => onChange(e.target.value)}\n helperText=\"Select from available options\"\n />\n );\n }\n\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Enter multiple values separated by commas (e.g., value1, value2, value3)\"\n placeholder=\"value1, value2, value3\"\n />\n );\n }\n default:\n return (\n <TextField\n {...commonProps}\n type=\"text\"\n onChange={(e: ChangeEvent<HTMLInputElement>): void => onChange(e.target.value)}\n helperText=\"Unknown field type, treating as text\"\n />\n );\n }\n};\n\n/**\n * React component wrapper for the field factory.\n */\nexport const FieldFactory: FC<FieldConfig> = (props: FieldConfig): ReactElement => createField(props);\n\nexport default FieldFactory;\n"],"mappings":";;;;;;;;;;;;;;;;AA4FA,MAAa,sBACX,OACA,MACA,WAAW,OACX,UAAU,UACQ;AAClB,KAAI,YAAY,YAAY,CAAC,SAAS,MAAM,MAAM,KAAK,IACrD,QAAO;AAGT,KAAI,CAAC,SAAS,MAAM,MAAM,KAAK,GAC7B,QAAO;AAGT,SAAQ,MAAR;EACE,KAAKA,8BAAU,QAAQ;GACrB,MAAMC,WAAmB,SAAS,OAAO,GAAG;AAC5C,OAAI,OAAO,MAAM,SAAS,CACxB,QAAO;AAET;;EAEF,QACE;;AAGJ,QAAO;;;;;;;;;;;;;;;;;;;;;AAsBT,MAAa,eAAe,WAAsC;CAChE,MAAM,EACJ,MACA,MACA,OACA,UACA,OACA,UACA,QACA,WAAW,OACX,OACA,WACA,IACA,UAAU,EAAE,EACZ,UAAU,OACV,gBACE;CAEJ,MAAMC,kBAAiC,SAAS,mBAAmB,OAAO,MAAM,UAAU,QAAQ;CAElG,MAAMC,cAAmC;EACvC;EACA,eAAe,oBAAoB;EACnC;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACD;AAED,SAAQ,MAAR;EACE,KAAKH,8BAAU,SACb,QAAO,2CAACI;GAAc,GAAI;GAAuB;IAAY;EAC/D,KAAKJ,8BAAU,KACb,QACE,2CAACK;GACC,GAAI;GACJ,MAAK;GACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;GAC9E,cAAa;IACb;EAEN,KAAKL,8BAAU,MACb,QACE,2CAACK;GACC,GAAI;GACJ,MAAK;GACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;GAC9E,cAAa;IACb;EAEN,KAAKL,8BAAU,IACb,QACE,2CAACK;GACC,GAAI;GACJ,MAAK;GACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;GAC9E,cAAa;IACb;EAEN,KAAKL,8BAAU,KACb,QACE,2CAACM;GAAW,GAAI;GAAa,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;IAAI;EAEnH,KAAKN,8BAAU,UAAU;GACvB,MAAMO,YAAqB,UAAU,UAAW,UAAkB;AAClE,UACE,2CAACC;IACC,GAAI;IACJ,SAAS;IACT,WAAW,MAA2C,SAAS,EAAE,OAAO,QAAQ,UAAU,CAAC;KAC3F;;EAGN,KAAKR,8BAAU,IACb,QACE,2CAACS;GAAS,GAAI;GAAa,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;IAAI;EAEjH,KAAKT,8BAAU,OACb,QACE,2CAACK;GACC,GAAI;GACJ,MAAK;GACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;GAC9E,YAAW;IACX;EAEN,KAAKL,8BAAU,QAAQ;GACrB,MAAMU,eAA+B,QAAQ,SAAS,IAAI,UAAU,EAAE;AAEtE,OAAI,aAAa,SAAS,EACxB,QACE,2CAACC;IACC,GAAI;IACJ,SAAS;IACT,WAAW,MAA4C,SAAS,EAAE,OAAO,MAAM;IAC/E,YAAW;KACX;AAIN,UACE,2CAACN;IACC,GAAI;IACJ,MAAK;IACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;IAC9E,YAAW;IACX,aAAY;KACZ;;EAGN,QACE,QACE,2CAACA;GACC,GAAI;GACJ,MAAK;GACL,WAAW,MAA2C,SAAS,EAAE,OAAO,MAAM;GAC9E,YAAW;IACX;;;;;;AAQV,MAAaO,gBAAiC,UAAqC,YAAY,MAAM"}
|
|
@@ -147,8 +147,9 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
147
147
|
const error = touchedFields[identifier] || false ? formErrors[identifier] : void 0;
|
|
148
148
|
const fieldType = getFieldType(component.type);
|
|
149
149
|
return (0, react.cloneElement)(require_FieldFactory.createField({
|
|
150
|
-
className: options.inputClassName,
|
|
150
|
+
className: (0, __emotion_css.cx)(options.inputClassName, component.classes),
|
|
151
151
|
error,
|
|
152
|
+
id: component.id,
|
|
152
153
|
label: resolve(component.label) || "",
|
|
153
154
|
name: identifier,
|
|
154
155
|
onBlur: () => options.onInputBlur?.(identifier),
|
|
@@ -164,8 +165,9 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
164
165
|
const value = formValues[identifier] || "";
|
|
165
166
|
const error = touchedFields[identifier] || false ? formErrors[identifier] : void 0;
|
|
166
167
|
return (0, react.cloneElement)(require_FieldFactory.createField({
|
|
167
|
-
className: options.inputClassName,
|
|
168
|
+
className: (0, __emotion_css.cx)(options.inputClassName, component.classes),
|
|
168
169
|
error,
|
|
170
|
+
id: component.id,
|
|
169
171
|
label: resolve(component.label) || "",
|
|
170
172
|
name: identifier,
|
|
171
173
|
onBlur: () => options.onInputBlur?.(identifier),
|
|
@@ -207,33 +209,41 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
207
209
|
options.onSubmit(component, formData, shouldSkipValidation);
|
|
208
210
|
}
|
|
209
211
|
};
|
|
212
|
+
const socialButtonClassName = (0, __emotion_css.cx)(options.buttonClassName, component.classes);
|
|
210
213
|
if (matchesSocialProvider(actionId, eventType, buttonText, "google", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_GoogleButton.default, {
|
|
214
|
+
id: component.id,
|
|
211
215
|
onClick: handleClick,
|
|
212
|
-
className:
|
|
216
|
+
className: socialButtonClassName
|
|
213
217
|
}, key);
|
|
214
218
|
if (matchesSocialProvider(actionId, eventType, buttonText, "github", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_GitHubButton.default, {
|
|
219
|
+
id: component.id,
|
|
215
220
|
onClick: handleClick,
|
|
216
|
-
className:
|
|
221
|
+
className: socialButtonClassName
|
|
217
222
|
}, key);
|
|
218
223
|
if (matchesSocialProvider(actionId, eventType, buttonText, "facebook", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_FacebookButton.default, {
|
|
224
|
+
id: component.id,
|
|
219
225
|
onClick: handleClick,
|
|
220
|
-
className:
|
|
226
|
+
className: socialButtonClassName
|
|
221
227
|
}, key);
|
|
222
228
|
if (matchesSocialProvider(actionId, eventType, buttonText, "microsoft", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MicrosoftButton.default, {
|
|
229
|
+
id: component.id,
|
|
223
230
|
onClick: handleClick,
|
|
224
|
-
className:
|
|
231
|
+
className: socialButtonClassName
|
|
225
232
|
}, key);
|
|
226
233
|
if (matchesSocialProvider(actionId, eventType, buttonText, "linkedin", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LinkedInButton.default, {
|
|
234
|
+
id: component.id,
|
|
227
235
|
onClick: handleClick,
|
|
228
|
-
className:
|
|
236
|
+
className: socialButtonClassName
|
|
229
237
|
}, key);
|
|
230
238
|
if (matchesSocialProvider(actionId, eventType, buttonText, "ethereum", authType, componentVariant)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SignInWithEthereumButton.default, {
|
|
239
|
+
id: component.id,
|
|
231
240
|
onClick: handleClick,
|
|
232
|
-
className:
|
|
241
|
+
className: socialButtonClassName
|
|
233
242
|
}, key);
|
|
234
243
|
if (actionId === "prompt_mobile" || eventType === "prompt_mobile") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SmsOtpButton.default, {
|
|
244
|
+
id: component.id,
|
|
235
245
|
onClick: handleClick,
|
|
236
|
-
className:
|
|
246
|
+
className: socialButtonClassName
|
|
237
247
|
}, key);
|
|
238
248
|
const startIconEl = component.startIcon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
239
249
|
src: component.startIcon,
|
|
@@ -257,9 +267,10 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
257
267
|
}) : null;
|
|
258
268
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.default, {
|
|
259
269
|
fullWidth: true,
|
|
270
|
+
id: component.id,
|
|
260
271
|
onClick: handleClick,
|
|
261
272
|
disabled: isLoading || !isFormValid && !shouldSkipValidation || options.isTimeoutDisabled || component.config?.disabled,
|
|
262
|
-
className: options.buttonClassName,
|
|
273
|
+
className: (0, __emotion_css.cx)(options.buttonClassName, component.classes),
|
|
263
274
|
"data-testid": "thunderid-signin-submit",
|
|
264
275
|
variant: component.variant?.toLowerCase() === "primary" ? "solid" : "outline",
|
|
265
276
|
color: component.variant?.toLowerCase() === "primary" ? "primary" : "secondary",
|
|
@@ -268,14 +279,19 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
268
279
|
children: buttonText || "Submit"
|
|
269
280
|
}, key);
|
|
270
281
|
}
|
|
271
|
-
case __thunderid_browser.EmbeddedFlowComponentType.Text:
|
|
272
|
-
variant
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
282
|
+
case __thunderid_browser.EmbeddedFlowComponentType.Text: {
|
|
283
|
+
const variant = getTypographyVariant(component.variant);
|
|
284
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Typography.default, {
|
|
285
|
+
id: component.id,
|
|
286
|
+
className: component.classes,
|
|
287
|
+
variant,
|
|
288
|
+
style: {
|
|
289
|
+
marginBottom: 2,
|
|
290
|
+
textAlign: typeof component?.align === "string" ? component.align : "left"
|
|
291
|
+
},
|
|
292
|
+
children: resolve(component.label)
|
|
293
|
+
}, key);
|
|
294
|
+
}
|
|
279
295
|
case __thunderid_browser.EmbeddedFlowComponentType.Divider: return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Divider.default, { children: resolve(component.label) || "" }, key);
|
|
280
296
|
case __thunderid_browser.EmbeddedFlowComponentType.Select: {
|
|
281
297
|
const identifier = component.ref;
|
|
@@ -286,6 +302,7 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
286
302
|
value: typeof opt === "string" ? opt : String(opt.value ?? "")
|
|
287
303
|
}));
|
|
288
304
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Select.default, {
|
|
305
|
+
id: component.id,
|
|
289
306
|
name: identifier,
|
|
290
307
|
label: resolve(component.label) || "",
|
|
291
308
|
placeholder: resolve(component.placeholder),
|
|
@@ -295,7 +312,7 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
295
312
|
error,
|
|
296
313
|
onChange: (e) => onInputChange(identifier, e.target.value),
|
|
297
314
|
onBlur: () => options.onInputBlur?.(identifier),
|
|
298
|
-
className: options.inputClassName
|
|
315
|
+
className: (0, __emotion_css.cx)(options.inputClassName, component.classes)
|
|
299
316
|
}, key);
|
|
300
317
|
}
|
|
301
318
|
case __thunderid_browser.EmbeddedFlowComponentType.DateInput: {
|
|
@@ -303,6 +320,7 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
303
320
|
const value = formValues[identifier] || "";
|
|
304
321
|
const error = touchedFields[identifier] || false ? formErrors[identifier] : void 0;
|
|
305
322
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_DatePicker.default, {
|
|
323
|
+
id: component.id,
|
|
306
324
|
name: identifier,
|
|
307
325
|
label: resolve(component.label) || "",
|
|
308
326
|
placeholder: resolve(component.placeholder),
|
|
@@ -312,7 +330,7 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
312
330
|
error,
|
|
313
331
|
onChange: (e) => onInputChange(identifier, e.target.value),
|
|
314
332
|
onBlur: () => options.onInputBlur?.(identifier),
|
|
315
|
-
className: options.inputClassName
|
|
333
|
+
className: (0, __emotion_css.cx)(options.inputClassName, component.classes)
|
|
316
334
|
}, key);
|
|
317
335
|
}
|
|
318
336
|
case __thunderid_browser.EmbeddedFlowComponentType.OuSelect:
|
|
@@ -331,6 +349,7 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
331
349
|
})).filter(Boolean);
|
|
332
350
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("form", {
|
|
333
351
|
id: component.id,
|
|
352
|
+
className: component.classes,
|
|
334
353
|
style: formStyles,
|
|
335
354
|
children: blockComponents
|
|
336
355
|
}, key);
|
|
@@ -410,20 +429,24 @@ const createAuthComponentFromFlow = (component, formValues, touchedFields, formE
|
|
|
410
429
|
const gap = component.gap ?? 2;
|
|
411
430
|
const align = component.align || "center";
|
|
412
431
|
const justify = component.justify || "flex-start";
|
|
432
|
+
const stackStyle = {
|
|
433
|
+
alignItems: align,
|
|
434
|
+
display: "flex",
|
|
435
|
+
flexDirection: direction,
|
|
436
|
+
flexWrap: "wrap",
|
|
437
|
+
gap: `${gap * .5}rem`,
|
|
438
|
+
justifyContent: justify
|
|
439
|
+
};
|
|
440
|
+
const stackChildren = component.components ? component.components.map((childComponent, index) => createAuthComponentFromFlow(childComponent, formValues, touchedFields, formErrors, isLoading, isFormValid, onInputChange, authType, {
|
|
441
|
+
...options,
|
|
442
|
+
inStack: true,
|
|
443
|
+
key: childComponent.id || `${component.id}_${index}`
|
|
444
|
+
})) : [];
|
|
413
445
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
flexWrap: "wrap",
|
|
419
|
-
gap: `${gap * .5}rem`,
|
|
420
|
-
justifyContent: justify
|
|
421
|
-
},
|
|
422
|
-
children: component.components ? component.components.map((childComponent, index) => createAuthComponentFromFlow(childComponent, formValues, touchedFields, formErrors, isLoading, isFormValid, onInputChange, authType, {
|
|
423
|
-
...options,
|
|
424
|
-
inStack: true,
|
|
425
|
-
key: childComponent.id || `${component.id}_${index}`
|
|
426
|
-
})) : []
|
|
446
|
+
id: component.id,
|
|
447
|
+
className: component.classes,
|
|
448
|
+
style: stackStyle,
|
|
449
|
+
children: stackChildren
|
|
427
450
|
}, key);
|
|
428
451
|
}
|
|
429
452
|
case __thunderid_browser.EmbeddedFlowComponentType.Consent: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthOptionFactory.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClass: string","EmbeddedFlowComponentType","FieldType","providerId: any","providerMatches: any","theme: any","customRenderers: ComponentRendererMap","key: string | number","customRenderer: ComponentRenderer | undefined","identifier: string","value: string","error: string","fieldType: string","createField","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","EmbeddedFlowEventType","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","getConsentOptionalKey","GoogleButton","GitHubButton","FacebookButton","MicrosoftButton","LinkedInButton","SignInWithEthereumButton","SmsOtpButton","startIconEl: ReactElement | null","endIconEl: ReactElement | null","Button","Typography","Divider","selectOptions: any","Select","DatePicker","formStyles: CSSProperties","blockComponents: any","richTextAction: EmbeddedFlowComponentAction | undefined","syntheticAction: EmbeddedFlowComponent","formData: Record<string, string>","anchor: HTMLAnchorElement | null","DOMPurify","explicitHeight: string","explicitWidth: string","ImageComponent","iconName: string","IconComponent: any","flowIconRegistry","direction: string","gap: number","align: string","justify: string","consentPromptRawData: ConsentPromptData | string | undefined","Consent","textTemplate: string","timeoutMs: number","FlowTimer","sourceKey: string | undefined","CopyableText"],"sources":["../../../../../src/components/presentation/auth/AuthOptionFactory.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {css} from '@emotion/css';\nimport {\n FieldType,\n FlowMetadataResponse,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentAction,\n EmbeddedFlowComponentType,\n EmbeddedFlowTextVariant,\n EmbeddedFlowEventType,\n createPackageComponentLogger,\n resolveFlowTemplateLiterals,\n resolveEmojiUrisInHtml,\n ConsentPurposeData,\n ConsentPromptData,\n ConsentDecisions,\n ConsentPurposeDecision,\n ConsentAttributeElement,\n OrganizationUnitListResponse,\n} from '@thunderid/browser';\nimport DOMPurify from 'dompurify';\nimport {cloneElement, CSSProperties, ReactElement} from 'react';\nimport {\n ComponentRenderer,\n ComponentRenderContext,\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport {UseTranslation} from '../../../hooks/useTranslation';\nimport Consent from '../../adapters/Consent';\nimport {getConsentOptionalKey} from '../../adapters/ConsentCheckboxList';\nimport FacebookButton from '../../adapters/FacebookButton';\nimport FlowTimer from '../../adapters/FlowTimer';\nimport GitHubButton from '../../adapters/GitHubButton';\nimport GoogleButton from '../../adapters/GoogleButton';\nimport ImageComponent from '../../adapters/ImageComponent';\nimport LinkedInButton from '../../adapters/LinkedInButton';\nimport MicrosoftButton from '../../adapters/MicrosoftButton';\nimport SignInWithEthereumButton from '../../adapters/SignInWithEthereumButton';\nimport SmsOtpButton from '../../adapters/SmsOtpButton';\nimport {createField} from '../../factories/FieldFactory';\nimport Button from '../../primitives/Button/Button';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport DatePicker from '../../primitives/DatePicker/DatePicker';\nimport Divider from '../../primitives/Divider/Divider';\nimport flowIconRegistry from '../../primitives/Icons/flowIconRegistry';\nimport Select from '../../primitives/Select/Select';\nimport Typography from '../../primitives/Typography/Typography';\nimport {TypographyVariant} from '../../primitives/Typography/Typography.styles';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'AuthOptionFactory',\n);\n\n/**\n * Replaces `emoji:` URIs embedded in HTML before DOMPurify sanitization.\n *\n * DOMPurify strips unknown URI schemes from attributes (e.g. `src=\"emoji:🦊\"` → `src=\"\"`).\n * This function converts:\n * - `<img src=\"emoji:X\" alt=\"Y\">` → `<span role=\"img\" aria-label=\"Y\">X</span>`\n * - Any remaining `emoji:X` text occurrences → `X`\n */\n\n/** Ensures rich-text content (including all inner elements from the server) always word-wraps. */\nconst richTextClass: string = css`\n overflow-wrap: anywhere;\n & * {\n overflow-wrap: anywhere;\n word-break: break-word;\n }\n & .rich-text-align-left {\n text-align: left;\n }\n & .rich-text-align-center {\n text-align: center;\n }\n & .rich-text-align-right {\n text-align: right;\n }\n & .rich-text-align-justify {\n text-align: justify;\n }\n & a,\n & .rich-text-link {\n text-decoration: underline;\n }\n & span[role='img'] {\n display: inline-block;\n }\n`;\n\nexport type AuthType = 'signin' | 'signup' | 'recovery';\n\n/**\n * Get the appropriate FieldType for an input component.\n */\nconst getFieldType = (variant: EmbeddedFlowComponentType): FieldType => {\n switch (variant) {\n case EmbeddedFlowComponentType.EmailInput:\n return FieldType.Email;\n case EmbeddedFlowComponentType.PhoneInput:\n return FieldType.Tel;\n case EmbeddedFlowComponentType.PasswordInput:\n return FieldType.Password;\n case EmbeddedFlowComponentType.TextInput:\n default:\n return FieldType.Text;\n }\n};\n\n/**\n * Get typography variant from component variant.\n */\nconst getTypographyVariant = (variant: string): any => {\n const variantMap: Record<EmbeddedFlowTextVariant, TypographyVariant> = {\n BODY_1: 'body1',\n BODY_2: 'body2',\n BUTTON_TEXT: 'button',\n CAPTION: 'caption',\n HEADING_1: 'h1',\n HEADING_2: 'h2',\n HEADING_3: 'h3',\n HEADING_4: 'h4',\n HEADING_5: 'h5',\n HEADING_6: 'h6',\n OVERLINE: 'overline',\n SUBTITLE_1: 'subtitle1',\n SUBTITLE_2: 'subtitle2',\n };\n\n return variantMap[variant] || 'h3';\n};\n\n/**\n * Check if a button text or action matches a social provider.\n */\nconst matchesSocialProvider = (\n actionId: string,\n eventType: string,\n buttonText: string,\n provider: string,\n authType: AuthType,\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n _componentVariant?: string,\n): boolean => {\n const providerId: any = `${provider}_auth`;\n const providerMatches: any = actionId === providerId || eventType === providerId;\n\n // Social buttons usually have \"Sign in with X\" or \"Continue with X\" text,\n // so also check button text for the provider name to increase chances of correct detection (especially for signup flows where action IDs are less standardized)\n if (buttonText.toLowerCase().includes(provider)) {\n return true;\n }\n\n // For signup, also check button text\n if (authType === 'signup') {\n return providerMatches || buttonText.toLowerCase().includes(provider);\n }\n\n return providerMatches;\n};\n\n/**\n * Create an auth component from flow component configuration.\n */\nconst createAuthComponentFromFlow = (\n component: EmbeddedFlowComponent,\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n authType: AuthType,\n options: {\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _customRenderers?: ComponentRendererMap;\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _theme?: any;\n /** Additional data from the flow response, used for different dynamic data */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Current consent purpose being rendered. Set by CONSENT_PURPOSE block iteration. */\n currentConsentPurpose?: ConsentPurposeData;\n inStack?: boolean;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n key?: string | number;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n } = {},\n): ReactElement | null => {\n const theme: any = options._theme;\n const customRenderers: ComponentRendererMap = options._customRenderers ?? {};\n\n const key: string | number = options.key || component.id;\n\n const customRenderer: ComponentRenderer | undefined =\n customRenderers[component.id] ?? customRenderers[component.type];\n if (customRenderer) {\n const renderCtx: ComponentRenderContext = {\n additionalData: options.additionalData,\n authType,\n formErrors,\n formValues,\n isFormValid,\n isLoading,\n meta: options.meta,\n onInputBlur: options.onInputBlur,\n onInputChange,\n onSubmit: options.onSubmit,\n touchedFields,\n };\n return customRenderer(component, renderCtx);\n }\n\n /** Resolve any remaining {{t()}} or {{meta()}} template expressions in a string at render time. */\n const resolve = (text: string | undefined): string => {\n if (!text || (!options.t && !options.meta)) {\n return text || '';\n }\n return resolveFlowTemplateLiterals(text, {meta: options.meta, t: options.t || ((k: string): string => k)});\n };\n\n switch (component.type) {\n case EmbeddedFlowComponentType.TextInput:\n case EmbeddedFlowComponentType.PasswordInput:\n case EmbeddedFlowComponentType.EmailInput:\n case EmbeddedFlowComponentType.PhoneInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n const fieldType: string = getFieldType(component.type);\n\n const field: any = createField({\n className: options.inputClassName,\n error,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: fieldType as FieldType,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.OtpInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n const field: any = createField({\n className: options.inputClassName,\n error,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: FieldType.Otp,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.Action: {\n const actionId: string = component.id;\n const eventType: string = component.eventType || '';\n const buttonText: string = resolve(component.label);\n const componentVariant: string = component.variant || '';\n\n // Only validate on submit type events.\n const shouldSkipValidation: boolean = eventType.toUpperCase() === EmbeddedFlowEventType.Trigger;\n\n const handleClick = (): any => {\n if (options.onSubmit) {\n const formData: Record<string, any> = {};\n Object.keys(formValues).forEach((field: any) => {\n // Include all values, even empty strings, to ensure proper submission\n formData[field] = formValues[field];\n });\n\n // For consent actions, build the consent_decisions JSON from the form values.\n // The allow action captures per-attribute choices; the deny action sends\n // all purposes as rejected so the backend ConsentExecutor can fail the flow.\n const consentPrompt: ConsentPromptData | undefined = options.additionalData?.['consentPrompt'] as\n | ConsentPromptData\n | undefined;\n if (consentPrompt && eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n const isDeny: boolean = componentVariant.toLowerCase() !== 'primary';\n const decisions: ConsentDecisions = {\n purposes: consentPrompt.purposes.map(\n (p: ConsentPurposeData): ConsentPurposeDecision => ({\n approved: !isDeny,\n elements: [\n ...p.essential.map((e): ConsentAttributeElement => ({approved: !isDeny, name: e.name})),\n ...p.optional.map(\n (e): ConsentAttributeElement => ({\n approved: isDeny ? false : formValues[getConsentOptionalKey(p.purposeId, e.name)] !== 'false',\n name: e.name,\n }),\n ),\n ],\n purposeName: p.purposeName!,\n }),\n ),\n };\n formData['consent_decisions'] = JSON.stringify(decisions);\n }\n\n options.onSubmit(component, formData, shouldSkipValidation);\n }\n };\n\n // Render branded social login buttons for known action IDs\n\n if (matchesSocialProvider(actionId, eventType, buttonText, 'google', authType, componentVariant)) {\n return <GoogleButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'github', authType, componentVariant)) {\n return <GitHubButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'facebook', authType, componentVariant)) {\n return <FacebookButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'microsoft', authType, componentVariant)) {\n return <MicrosoftButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'linkedin', authType, componentVariant)) {\n return <LinkedInButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'ethereum', authType, componentVariant)) {\n return <SignInWithEthereumButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n if (actionId === 'prompt_mobile' || eventType === 'prompt_mobile') {\n return <SmsOtpButton key={key} onClick={handleClick} className={options.buttonClassName} />;\n }\n\n const startIconEl: ReactElement | null = component.startIcon ? (\n <img\n src={component.startIcon}\n alt=\"\"\n aria-hidden=\"true\"\n style={{height: '1.25em', objectFit: 'contain', width: '1.25em'}}\n />\n ) : null;\n\n const endIconEl: ReactElement | null = component.endIcon ? (\n <img\n src={component.endIcon}\n alt=\"\"\n aria-hidden=\"true\"\n style={{height: '1.25em', objectFit: 'contain', width: '1.25em'}}\n />\n ) : null;\n\n return (\n <Button\n fullWidth\n key={key}\n onClick={handleClick}\n disabled={\n isLoading ||\n (!isFormValid && !shouldSkipValidation) ||\n options.isTimeoutDisabled ||\n (component as any).config?.disabled\n }\n className={options.buttonClassName}\n data-testid=\"thunderid-signin-submit\"\n variant={component.variant?.toLowerCase() === 'primary' ? 'solid' : 'outline'}\n color={component.variant?.toLowerCase() === 'primary' ? 'primary' : 'secondary'}\n startIcon={startIconEl}\n endIcon={endIconEl}\n >\n {buttonText || 'Submit'}\n </Button>\n );\n }\n\n case EmbeddedFlowComponentType.Text: {\n const variant: any = getTypographyVariant(component.variant!);\n return (\n <Typography\n key={key}\n variant={variant}\n style={{\n marginBottom: 2,\n textAlign:\n typeof component?.align === 'string' ? (component.align as React.CSSProperties['textAlign']) : 'left',\n }}\n >\n {resolve(component.label)}\n </Typography>\n );\n }\n\n case EmbeddedFlowComponentType.Divider: {\n return <Divider key={key}>{resolve(component.label) || ''}</Divider>;\n }\n\n case EmbeddedFlowComponentType.Select: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // Options are pre-sanitized by flowTransformer to {value: string, label: string} format\n const selectOptions: any = (component.options || []).map((opt: any) => ({\n label: typeof opt === 'string' ? opt : String(opt.label ?? opt.value ?? ''),\n value: typeof opt === 'string' ? opt : String(opt.value ?? ''),\n }));\n\n return (\n <Select\n key={key}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n options={selectOptions}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={options.inputClassName}\n />\n );\n }\n\n case EmbeddedFlowComponentType.DateInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n return (\n <DatePicker\n key={key}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n dateFormat={component.dateFormat}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={options.inputClassName}\n />\n );\n }\n\n case EmbeddedFlowComponentType.OuSelect: {\n logger.warn('OU_SELECT component type is not supported. Skipping render.');\n return null;\n }\n\n case EmbeddedFlowComponentType.Block: {\n if (component.components && component.components.length > 0) {\n const formStyles: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: `calc(${theme?.vars?.spacing?.unit ?? '4px'} * 2)`,\n };\n\n const blockComponents: any = component.components\n .map((childComponent: any, index: any) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n authType,\n {\n ...options,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n .filter(Boolean);\n\n return (\n <form id={component.id} key={key} style={formStyles}>\n {blockComponents}\n </form>\n );\n }\n return null;\n }\n\n case EmbeddedFlowComponentType.RichText: {\n const richTextAction: EmbeddedFlowComponentAction | undefined = component.action;\n\n const dispatchRichTextAction = (): void => {\n if (!richTextAction || !options.onSubmit) {\n return;\n }\n const eventTypeValue = String(richTextAction.eventType ?? EmbeddedFlowEventType.Submit);\n const shouldSkipValidation: boolean = eventTypeValue.toUpperCase() === String(EmbeddedFlowEventType.Trigger);\n const syntheticAction: EmbeddedFlowComponent = {\n eventType: eventTypeValue,\n id: `${component.id}_action`,\n ref: richTextAction.ref,\n type: EmbeddedFlowComponentType.Action,\n };\n const formData: Record<string, string> = {};\n Object.keys(formValues).forEach((field: string) => {\n formData[field] = formValues[field];\n });\n options.onSubmit(syntheticAction, formData, shouldSkipValidation);\n };\n\n // Sentinel-anchor contract: only anchors carrying `data-action-ref` equal to\n // richTextAction.ref dispatch the action. Anchors without the sentinel (or with\n // a non-matching one) are treated as ordinary links and are ignored here.\n const isMatchingSentinelAnchor = (anchor: HTMLAnchorElement): boolean =>\n anchor.getAttribute('data-action-ref') === richTextAction?.ref;\n\n const handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.MouseEvent<HTMLDivElement>): void => {\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n const handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return;\n }\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n return (\n // Sentinel anchors are made keyboard-operable via the container's onKeyDown\n // (Enter/Space activate the matching anchor). Authors should ensure the anchor\n // is focusable (`href` or `tabIndex`); the click+keydown delegation covers both\n // pointer and keyboard activation once focus lands on the anchor.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n key={key}\n className={richTextClass}\n onClick={handleRichTextClick}\n onKeyDown={handleRichTextKeyDown}\n // Manually sanitizes with `DOMPurify`.\n // IMPORTANT: DO NOT REMOVE OR MODIFY THIS SANITIZATION STEP.\n dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(resolveEmojiUrisInHtml(resolve(component.label)))}}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Image: {\n const explicitHeight: string = resolve(component.height?.toString());\n const explicitWidth: string = resolve(component.width?.toString());\n return (\n <ImageComponent\n key={key}\n component={\n {\n config: {\n alt: resolve(component.alt) || resolve(component.label) || 'Image',\n height: explicitHeight || (options.inStack ? '50' : 'auto'),\n src: resolve(component.src),\n width: explicitWidth || (options.inStack ? '50' : '100%'),\n },\n } as any\n }\n formErrors={undefined!}\n formValues={undefined!}\n isFormValid={false}\n isLoading={false}\n onInputChange={(): void => {\n throw new Error('Function not implemented.');\n }}\n touchedFields={undefined!}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Icon: {\n const iconName: string = component.name || '';\n const IconComponent: any = flowIconRegistry[iconName];\n if (!IconComponent) {\n logger.warn(`Unknown icon name: \"${iconName}\". Skipping render.`);\n return null;\n }\n return <IconComponent key={key} size={component.size || 24} color={component.color || 'currentColor'} />;\n }\n\n case EmbeddedFlowComponentType.Stack: {\n const direction: string = (component as any).direction || 'row';\n const gap: number = (component as any).gap ?? 2;\n const align: string = (component as any).align || 'center';\n const justify: string = (component as any).justify || 'flex-start';\n\n const stackStyle: CSSProperties = {\n alignItems: align,\n display: 'flex',\n flexDirection: direction as CSSProperties['flexDirection'],\n flexWrap: 'wrap',\n gap: `${gap * 0.5}rem`,\n justifyContent: justify,\n };\n\n const stackChildren: (ReactElement | null)[] = component.components\n ? component.components.map((childComponent: any, index: number) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n authType,\n {\n ...options,\n inStack: true,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n : [];\n\n return (\n <div key={key} style={stackStyle}>\n {stackChildren}\n </div>\n );\n }\n\n case EmbeddedFlowComponentType.Consent: {\n const consentPromptRawData: ConsentPromptData | string | undefined = options.additionalData?.['consentPrompt'];\n\n return (\n <Consent\n key={key}\n consentData={consentPromptRawData as any}\n formValues={formValues}\n onInputChange={onInputChange}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Timer: {\n const textTemplate: string = resolve((component as any).label) || 'Time remaining: {time}';\n const timeoutMs: number = Number(options.additionalData?.['stepTimeout']) || 0;\n const expiresIn: number = timeoutMs > 0 ? Math.max(0, Math.floor((timeoutMs - Date.now()) / 1000)) : 0;\n\n return <FlowTimer key={key} expiresIn={expiresIn} textTemplate={textTemplate} />;\n }\n\n case EmbeddedFlowComponentType.CopyableText: {\n const sourceKey: string | undefined = (component as any).source;\n const value: string = sourceKey && options.additionalData ? String(options.additionalData[sourceKey] ?? '') : '';\n const labelText: string | undefined = resolve((component as any).label) || undefined;\n\n return <CopyableText key={key} label={labelText} value={value} />;\n }\n\n default:\n // Gracefully handle unsupported component types by returning null\n logger.warn(`Unsupported component type: ${component.type}. Skipping render.`);\n return null;\n }\n};\n\n/**\n * Processes an array of components and renders them as React elements for sign-in.\n */\nexport const renderSignInComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signin',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for sign-up.\n */\nexport const renderSignUpComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for recovery flow.\n */\nexport const renderRecoveryComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'recovery',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for invite user.\n * This is used by both InviteUser and AcceptInvite components.\n */\nexport const renderInviteUserComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Function to fetch child organization units for OU_SELECT components. */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuthOptionFactory.cjs","names":["logger: ReturnType<typeof createPackageComponentLogger>","richTextClass: string","EmbeddedFlowComponentType","FieldType","providerId: any","providerMatches: any","theme: any","customRenderers: ComponentRendererMap","key: string | number","customRenderer: ComponentRenderer | undefined","identifier: string","value: string","error: string","fieldType: string","createField","actionId: string","eventType: string","buttonText: string","componentVariant: string","shouldSkipValidation: boolean","EmbeddedFlowEventType","formData: Record<string, any>","consentPrompt: ConsentPromptData | undefined","isDeny: boolean","decisions: ConsentDecisions","getConsentOptionalKey","socialButtonClassName: string","GoogleButton","GitHubButton","FacebookButton","MicrosoftButton","LinkedInButton","SignInWithEthereumButton","SmsOtpButton","startIconEl: ReactElement | null","endIconEl: ReactElement | null","Button","variant: any","Typography","Divider","selectOptions: any","Select","DatePicker","formStyles: CSSProperties","blockComponents: any","richTextAction: EmbeddedFlowComponentAction | undefined","syntheticAction: EmbeddedFlowComponent","formData: Record<string, string>","anchor: HTMLAnchorElement | null","DOMPurify","explicitHeight: string","explicitWidth: string","ImageComponent","iconName: string","IconComponent: any","flowIconRegistry","direction: string","gap: number","align: string","justify: string","stackStyle: CSSProperties","stackChildren: (ReactElement | null)[]","consentPromptRawData: ConsentPromptData | string | undefined","Consent","textTemplate: string","timeoutMs: number","FlowTimer","sourceKey: string | undefined","CopyableText"],"sources":["../../../../../src/components/presentation/auth/AuthOptionFactory.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {css, cx} from '@emotion/css';\nimport {\n FieldType,\n FlowMetadataResponse,\n EmbeddedFlowComponent,\n EmbeddedFlowComponentAction,\n EmbeddedFlowComponentType,\n EmbeddedFlowTextVariant,\n EmbeddedFlowEventType,\n createPackageComponentLogger,\n resolveFlowTemplateLiterals,\n resolveEmojiUrisInHtml,\n ConsentPurposeData,\n ConsentPromptData,\n ConsentDecisions,\n ConsentPurposeDecision,\n ConsentAttributeElement,\n OrganizationUnitListResponse,\n} from '@thunderid/browser';\nimport DOMPurify from 'dompurify';\nimport {cloneElement, CSSProperties, ReactElement} from 'react';\nimport {\n ComponentRenderer,\n ComponentRenderContext,\n ComponentRendererMap,\n} from '../../../contexts/ComponentRenderer/ComponentRendererContext';\nimport {UseTranslation} from '../../../hooks/useTranslation';\nimport Consent from '../../adapters/Consent';\nimport {getConsentOptionalKey} from '../../adapters/ConsentCheckboxList';\nimport FacebookButton from '../../adapters/FacebookButton';\nimport FlowTimer from '../../adapters/FlowTimer';\nimport GitHubButton from '../../adapters/GitHubButton';\nimport GoogleButton from '../../adapters/GoogleButton';\nimport ImageComponent from '../../adapters/ImageComponent';\nimport LinkedInButton from '../../adapters/LinkedInButton';\nimport MicrosoftButton from '../../adapters/MicrosoftButton';\nimport SignInWithEthereumButton from '../../adapters/SignInWithEthereumButton';\nimport SmsOtpButton from '../../adapters/SmsOtpButton';\nimport {createField} from '../../factories/FieldFactory';\nimport Button from '../../primitives/Button/Button';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport DatePicker from '../../primitives/DatePicker/DatePicker';\nimport Divider from '../../primitives/Divider/Divider';\nimport flowIconRegistry from '../../primitives/Icons/flowIconRegistry';\nimport Select from '../../primitives/Select/Select';\nimport Typography from '../../primitives/Typography/Typography';\nimport {TypographyVariant} from '../../primitives/Typography/Typography.styles';\n\nconst logger: ReturnType<typeof createPackageComponentLogger> = createPackageComponentLogger(\n '@thunderid/react',\n 'AuthOptionFactory',\n);\n\n/**\n * Replaces `emoji:` URIs embedded in HTML before DOMPurify sanitization.\n *\n * DOMPurify strips unknown URI schemes from attributes (e.g. `src=\"emoji:🦊\"` → `src=\"\"`).\n * This function converts:\n * - `<img src=\"emoji:X\" alt=\"Y\">` → `<span role=\"img\" aria-label=\"Y\">X</span>`\n * - Any remaining `emoji:X` text occurrences → `X`\n */\n\n/** Ensures rich-text content (including all inner elements from the server) always word-wraps. */\nconst richTextClass: string = css`\n overflow-wrap: anywhere;\n & * {\n overflow-wrap: anywhere;\n word-break: break-word;\n }\n & .rich-text-align-left {\n text-align: left;\n }\n & .rich-text-align-center {\n text-align: center;\n }\n & .rich-text-align-right {\n text-align: right;\n }\n & .rich-text-align-justify {\n text-align: justify;\n }\n & a,\n & .rich-text-link {\n text-decoration: underline;\n }\n & span[role='img'] {\n display: inline-block;\n }\n`;\n\nexport type AuthType = 'signin' | 'signup' | 'recovery';\n\n/**\n * Get the appropriate FieldType for an input component.\n */\nconst getFieldType = (variant: EmbeddedFlowComponentType): FieldType => {\n switch (variant) {\n case EmbeddedFlowComponentType.EmailInput:\n return FieldType.Email;\n case EmbeddedFlowComponentType.PhoneInput:\n return FieldType.Tel;\n case EmbeddedFlowComponentType.PasswordInput:\n return FieldType.Password;\n case EmbeddedFlowComponentType.TextInput:\n default:\n return FieldType.Text;\n }\n};\n\n/**\n * Get typography variant from component variant.\n */\nconst getTypographyVariant = (variant: string): any => {\n const variantMap: Record<EmbeddedFlowTextVariant, TypographyVariant> = {\n BODY_1: 'body1',\n BODY_2: 'body2',\n BUTTON_TEXT: 'button',\n CAPTION: 'caption',\n HEADING_1: 'h1',\n HEADING_2: 'h2',\n HEADING_3: 'h3',\n HEADING_4: 'h4',\n HEADING_5: 'h5',\n HEADING_6: 'h6',\n OVERLINE: 'overline',\n SUBTITLE_1: 'subtitle1',\n SUBTITLE_2: 'subtitle2',\n };\n\n return variantMap[variant] || 'h3';\n};\n\n/**\n * Check if a button text or action matches a social provider.\n */\nconst matchesSocialProvider = (\n actionId: string,\n eventType: string,\n buttonText: string,\n provider: string,\n authType: AuthType,\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n _componentVariant?: string,\n): boolean => {\n const providerId: any = `${provider}_auth`;\n const providerMatches: any = actionId === providerId || eventType === providerId;\n\n // Social buttons usually have \"Sign in with X\" or \"Continue with X\" text,\n // so also check button text for the provider name to increase chances of correct detection (especially for signup flows where action IDs are less standardized)\n if (buttonText.toLowerCase().includes(provider)) {\n return true;\n }\n\n // For signup, also check button text\n if (authType === 'signup') {\n return providerMatches || buttonText.toLowerCase().includes(provider);\n }\n\n return providerMatches;\n};\n\n/**\n * Create an auth component from flow component configuration.\n */\nconst createAuthComponentFromFlow = (\n component: EmbeddedFlowComponent,\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n authType: AuthType,\n options: {\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _customRenderers?: ComponentRendererMap;\n /** @internal Passed from the host React component so hooks aren't called inside a loop. */\n _theme?: any;\n /** Additional data from the flow response, used for different dynamic data */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Current consent purpose being rendered. Set by CONSENT_PURPOSE block iteration. */\n currentConsentPurpose?: ConsentPurposeData;\n inStack?: boolean;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n key?: string | number;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n } = {},\n): ReactElement | null => {\n const theme: any = options._theme;\n const customRenderers: ComponentRendererMap = options._customRenderers ?? {};\n\n const key: string | number = options.key || component.id;\n\n const customRenderer: ComponentRenderer | undefined =\n customRenderers[component.id] ?? customRenderers[component.type];\n if (customRenderer) {\n const renderCtx: ComponentRenderContext = {\n additionalData: options.additionalData,\n authType,\n formErrors,\n formValues,\n isFormValid,\n isLoading,\n meta: options.meta,\n onInputBlur: options.onInputBlur,\n onInputChange,\n onSubmit: options.onSubmit,\n touchedFields,\n };\n return customRenderer(component, renderCtx);\n }\n\n /** Resolve any remaining {{t()}} or {{meta()}} template expressions in a string at render time. */\n const resolve = (text: string | undefined): string => {\n if (!text || (!options.t && !options.meta)) {\n return text || '';\n }\n return resolveFlowTemplateLiterals(text, {meta: options.meta, t: options.t || ((k: string): string => k)});\n };\n\n switch (component.type) {\n case EmbeddedFlowComponentType.TextInput:\n case EmbeddedFlowComponentType.PasswordInput:\n case EmbeddedFlowComponentType.EmailInput:\n case EmbeddedFlowComponentType.PhoneInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n const fieldType: string = getFieldType(component.type);\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: fieldType as FieldType,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.OtpInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n const field: any = createField({\n className: cx(options.inputClassName, component.classes),\n error,\n id: component.id,\n label: resolve(component.label) || '',\n name: identifier,\n onBlur: () => options.onInputBlur?.(identifier),\n onChange: (newValue: string) => onInputChange(identifier, newValue),\n placeholder: resolve(component.placeholder) || '',\n required: component.required || false,\n type: FieldType.Otp,\n value,\n });\n\n return cloneElement(field, {key});\n }\n\n case EmbeddedFlowComponentType.Action: {\n const actionId: string = component.id;\n const eventType: string = component.eventType || '';\n const buttonText: string = resolve(component.label);\n const componentVariant: string = component.variant || '';\n\n // Only validate on submit type events.\n const shouldSkipValidation: boolean = eventType.toUpperCase() === EmbeddedFlowEventType.Trigger;\n\n const handleClick = (): any => {\n if (options.onSubmit) {\n const formData: Record<string, any> = {};\n Object.keys(formValues).forEach((field: any) => {\n // Include all values, even empty strings, to ensure proper submission\n formData[field] = formValues[field];\n });\n\n // For consent actions, build the consent_decisions JSON from the form values.\n // The allow action captures per-attribute choices; the deny action sends\n // all purposes as rejected so the backend ConsentExecutor can fail the flow.\n const consentPrompt: ConsentPromptData | undefined = options.additionalData?.['consentPrompt'] as\n | ConsentPromptData\n | undefined;\n if (consentPrompt && eventType.toUpperCase() === EmbeddedFlowEventType.Submit) {\n const isDeny: boolean = componentVariant.toLowerCase() !== 'primary';\n const decisions: ConsentDecisions = {\n purposes: consentPrompt.purposes.map(\n (p: ConsentPurposeData): ConsentPurposeDecision => ({\n approved: !isDeny,\n elements: [\n ...p.essential.map((e): ConsentAttributeElement => ({approved: !isDeny, name: e.name})),\n ...p.optional.map(\n (e): ConsentAttributeElement => ({\n approved: isDeny ? false : formValues[getConsentOptionalKey(p.purposeId, e.name)] !== 'false',\n name: e.name,\n }),\n ),\n ],\n purposeName: p.purposeName!,\n }),\n ),\n };\n formData['consent_decisions'] = JSON.stringify(decisions);\n }\n\n options.onSubmit(component, formData, shouldSkipValidation);\n }\n };\n\n // Render branded social login buttons for known action IDs\n\n const socialButtonClassName: string = cx(options.buttonClassName, component.classes);\n\n if (matchesSocialProvider(actionId, eventType, buttonText, 'google', authType, componentVariant)) {\n return <GoogleButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'github', authType, componentVariant)) {\n return <GitHubButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'facebook', authType, componentVariant)) {\n return <FacebookButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'microsoft', authType, componentVariant)) {\n return <MicrosoftButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'linkedin', authType, componentVariant)) {\n return <LinkedInButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n if (matchesSocialProvider(actionId, eventType, buttonText, 'ethereum', authType, componentVariant)) {\n return (\n <SignInWithEthereumButton\n key={key}\n id={component.id}\n onClick={handleClick}\n className={socialButtonClassName}\n />\n );\n }\n if (actionId === 'prompt_mobile' || eventType === 'prompt_mobile') {\n return <SmsOtpButton key={key} id={component.id} onClick={handleClick} className={socialButtonClassName} />;\n }\n\n const startIconEl: ReactElement | null = component.startIcon ? (\n <img\n src={component.startIcon}\n alt=\"\"\n aria-hidden=\"true\"\n style={{height: '1.25em', objectFit: 'contain', width: '1.25em'}}\n />\n ) : null;\n\n const endIconEl: ReactElement | null = component.endIcon ? (\n <img\n src={component.endIcon}\n alt=\"\"\n aria-hidden=\"true\"\n style={{height: '1.25em', objectFit: 'contain', width: '1.25em'}}\n />\n ) : null;\n\n return (\n <Button\n fullWidth\n key={key}\n id={component.id}\n onClick={handleClick}\n disabled={\n isLoading ||\n (!isFormValid && !shouldSkipValidation) ||\n options.isTimeoutDisabled ||\n (component as any).config?.disabled\n }\n className={cx(options.buttonClassName, component.classes)}\n data-testid=\"thunderid-signin-submit\"\n variant={component.variant?.toLowerCase() === 'primary' ? 'solid' : 'outline'}\n color={component.variant?.toLowerCase() === 'primary' ? 'primary' : 'secondary'}\n startIcon={startIconEl}\n endIcon={endIconEl}\n >\n {buttonText || 'Submit'}\n </Button>\n );\n }\n\n case EmbeddedFlowComponentType.Text: {\n const variant: any = getTypographyVariant(component.variant!);\n return (\n <Typography\n key={key}\n id={component.id}\n className={component.classes}\n variant={variant}\n style={{\n marginBottom: 2,\n textAlign:\n typeof component?.align === 'string' ? (component.align as React.CSSProperties['textAlign']) : 'left',\n }}\n >\n {resolve(component.label)}\n </Typography>\n );\n }\n\n case EmbeddedFlowComponentType.Divider: {\n return <Divider key={key}>{resolve(component.label) || ''}</Divider>;\n }\n\n case EmbeddedFlowComponentType.Select: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n // Options are pre-sanitized by flowTransformer to {value: string, label: string} format\n const selectOptions: any = (component.options || []).map((opt: any) => ({\n label: typeof opt === 'string' ? opt : String(opt.label ?? opt.value ?? ''),\n value: typeof opt === 'string' ? opt : String(opt.value ?? ''),\n }));\n\n return (\n <Select\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n options={selectOptions}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.DateInput: {\n const identifier: string = component.ref!;\n const value: string = formValues[identifier] || '';\n const isTouched: boolean = touchedFields[identifier] || false;\n const error: string = isTouched ? formErrors[identifier] : undefined!;\n\n return (\n <DatePicker\n key={key}\n id={component.id}\n name={identifier}\n label={resolve(component.label) || ''}\n placeholder={resolve(component.placeholder)}\n required={component.required}\n dateFormat={component.dateFormat}\n value={value}\n error={error}\n onChange={(e: any): void => onInputChange(identifier, e.target.value)}\n onBlur={(): any => options.onInputBlur?.(identifier)}\n className={cx(options.inputClassName, component.classes)}\n />\n );\n }\n\n case EmbeddedFlowComponentType.OuSelect: {\n logger.warn('OU_SELECT component type is not supported. Skipping render.');\n return null;\n }\n\n case EmbeddedFlowComponentType.Block: {\n if (component.components && component.components.length > 0) {\n const formStyles: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: `calc(${theme?.vars?.spacing?.unit ?? '4px'} * 2)`,\n };\n\n const blockComponents: any = component.components\n .map((childComponent: any, index: any) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n authType,\n {\n ...options,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n .filter(Boolean);\n\n return (\n <form id={component.id} key={key} className={component.classes} style={formStyles}>\n {blockComponents}\n </form>\n );\n }\n return null;\n }\n\n case EmbeddedFlowComponentType.RichText: {\n const richTextAction: EmbeddedFlowComponentAction | undefined = component.action;\n\n const dispatchRichTextAction = (): void => {\n if (!richTextAction || !options.onSubmit) {\n return;\n }\n const eventTypeValue = String(richTextAction.eventType ?? EmbeddedFlowEventType.Submit);\n const shouldSkipValidation: boolean = eventTypeValue.toUpperCase() === String(EmbeddedFlowEventType.Trigger);\n const syntheticAction: EmbeddedFlowComponent = {\n eventType: eventTypeValue,\n id: `${component.id}_action`,\n ref: richTextAction.ref,\n type: EmbeddedFlowComponentType.Action,\n };\n const formData: Record<string, string> = {};\n Object.keys(formValues).forEach((field: string) => {\n formData[field] = formValues[field];\n });\n options.onSubmit(syntheticAction, formData, shouldSkipValidation);\n };\n\n // Sentinel-anchor contract: only anchors carrying `data-action-ref` equal to\n // richTextAction.ref dispatch the action. Anchors without the sentinel (or with\n // a non-matching one) are treated as ordinary links and are ignored here.\n const isMatchingSentinelAnchor = (anchor: HTMLAnchorElement): boolean =>\n anchor.getAttribute('data-action-ref') === richTextAction?.ref;\n\n const handleRichTextClick: React.MouseEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.MouseEvent<HTMLDivElement>): void => {\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n const handleRichTextKeyDown: React.KeyboardEventHandler<HTMLDivElement> | undefined = richTextAction\n ? (event: React.KeyboardEvent<HTMLDivElement>): void => {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return;\n }\n const anchor: HTMLAnchorElement | null = (event.target as HTMLElement).closest('a');\n if (!anchor || !isMatchingSentinelAnchor(anchor)) {\n return;\n }\n event.preventDefault();\n dispatchRichTextAction();\n }\n : undefined;\n\n return (\n // Sentinel anchors are made keyboard-operable via the container's onKeyDown\n // (Enter/Space activate the matching anchor). Authors should ensure the anchor\n // is focusable (`href` or `tabIndex`); the click+keydown delegation covers both\n // pointer and keyboard activation once focus lands on the anchor.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n key={key}\n className={richTextClass}\n onClick={handleRichTextClick}\n onKeyDown={handleRichTextKeyDown}\n // Manually sanitizes with `DOMPurify`.\n // IMPORTANT: DO NOT REMOVE OR MODIFY THIS SANITIZATION STEP.\n dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(resolveEmojiUrisInHtml(resolve(component.label)))}}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Image: {\n const explicitHeight: string = resolve(component.height?.toString());\n const explicitWidth: string = resolve(component.width?.toString());\n return (\n <ImageComponent\n key={key}\n component={\n {\n config: {\n alt: resolve(component.alt) || resolve(component.label) || 'Image',\n height: explicitHeight || (options.inStack ? '50' : 'auto'),\n src: resolve(component.src),\n width: explicitWidth || (options.inStack ? '50' : '100%'),\n },\n } as any\n }\n formErrors={undefined!}\n formValues={undefined!}\n isFormValid={false}\n isLoading={false}\n onInputChange={(): void => {\n throw new Error('Function not implemented.');\n }}\n touchedFields={undefined!}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Icon: {\n const iconName: string = component.name || '';\n const IconComponent: any = flowIconRegistry[iconName];\n if (!IconComponent) {\n logger.warn(`Unknown icon name: \"${iconName}\". Skipping render.`);\n return null;\n }\n return <IconComponent key={key} size={component.size || 24} color={component.color || 'currentColor'} />;\n }\n\n case EmbeddedFlowComponentType.Stack: {\n const direction: string = (component as any).direction || 'row';\n const gap: number = (component as any).gap ?? 2;\n const align: string = (component as any).align || 'center';\n const justify: string = (component as any).justify || 'flex-start';\n\n const stackStyle: CSSProperties = {\n alignItems: align,\n display: 'flex',\n flexDirection: direction as CSSProperties['flexDirection'],\n flexWrap: 'wrap',\n gap: `${gap * 0.5}rem`,\n justifyContent: justify,\n };\n\n const stackChildren: (ReactElement | null)[] = component.components\n ? component.components.map((childComponent: any, index: number) =>\n createAuthComponentFromFlow(\n childComponent,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n authType,\n {\n ...options,\n inStack: true,\n key: childComponent.id || `${component.id}_${index}`,\n },\n ),\n )\n : [];\n\n return (\n <div key={key} id={component.id} className={component.classes} style={stackStyle}>\n {stackChildren}\n </div>\n );\n }\n\n case EmbeddedFlowComponentType.Consent: {\n const consentPromptRawData: ConsentPromptData | string | undefined = options.additionalData?.['consentPrompt'];\n\n return (\n <Consent\n key={key}\n consentData={consentPromptRawData as any}\n formValues={formValues}\n onInputChange={onInputChange}\n />\n );\n }\n\n case EmbeddedFlowComponentType.Timer: {\n const textTemplate: string = resolve((component as any).label) || 'Time remaining: {time}';\n const timeoutMs: number = Number(options.additionalData?.['stepTimeout']) || 0;\n const expiresIn: number = timeoutMs > 0 ? Math.max(0, Math.floor((timeoutMs - Date.now()) / 1000)) : 0;\n\n return <FlowTimer key={key} expiresIn={expiresIn} textTemplate={textTemplate} />;\n }\n\n case EmbeddedFlowComponentType.CopyableText: {\n const sourceKey: string | undefined = (component as any).source;\n const value: string = sourceKey && options.additionalData ? String(options.additionalData[sourceKey] ?? '') : '';\n const labelText: string | undefined = resolve((component as any).label) || undefined;\n\n return <CopyableText key={key} label={labelText} value={value} />;\n }\n\n default:\n // Gracefully handle unsupported component types by returning null\n logger.warn(`Unsupported component type: ${component.type}. Skipping render.`);\n return null;\n }\n};\n\n/**\n * Processes an array of components and renders them as React elements for sign-in.\n */\nexport const renderSignInComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signin',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for sign-up.\n */\nexport const renderSignUpComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for recovery flow.\n */\nexport const renderRecoveryComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n inputClassName?: string;\n /** Flag to determine if the step timeline has expired */\n isTimeoutDisabled?: boolean;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'recovery',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n\n/**\n * Processes an array of components and renders them as React elements for invite user.\n * This is used by both InviteUser and AcceptInvite components.\n */\nexport const renderInviteUserComponents = (\n components: EmbeddedFlowComponent[],\n formValues: Record<string, string>,\n touchedFields: Record<string, boolean>,\n formErrors: Record<string, string>,\n isLoading: boolean,\n isFormValid: boolean,\n onInputChange: (name: string, value: string) => void,\n options?: {\n /** @internal */\n _customRenderers?: ComponentRendererMap;\n /** @internal */\n _theme?: any;\n /** Additional data from the flow response */\n additionalData?: Record<string, any>;\n buttonClassName?: string;\n /** Function to fetch child organization units for OU_SELECT components. */\n fetchOrganizationUnitChildren?: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse>;\n inputClassName?: string;\n /** Flow metadata for resolving {{meta(...)}} expressions at render time */\n meta?: FlowMetadataResponse | null;\n onInputBlur?: (name: string) => void;\n onSubmit?: (component: EmbeddedFlowComponent, data?: Record<string, any>, skipValidation?: boolean) => void;\n size?: 'small' | 'medium' | 'large';\n /** Translation function for resolving {{t(...)}} expressions at render time */\n t?: UseTranslation['t'];\n variant?: any;\n },\n): ReactElement[] =>\n components\n .map((component: any, index: any) =>\n createAuthComponentFromFlow(\n component,\n formValues,\n touchedFields,\n formErrors,\n isLoading,\n isFormValid,\n onInputChange,\n 'signup',\n {\n ...options,\n key: component.id || index,\n },\n ),\n )\n .filter((x): x is ReactElement => x !== null);\n"],"mappings":"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AAgB,aAAa,QAAQ,iBAAiB,OAAO,QAAQ,eAAe,cAAc,GAAG,GAAG;AAG9G,UAAO,2CAACyD;IAAuB,OAFO,QAAS,UAAkB,MAAM,IAAI;IAEnB;MAA9B,IAAuC;;EAGnE;AAEE,UAAO,KAAK,+BAA+B,UAAU,KAAK,oBAAoB;AAC9E,UAAO;;;;;;AAOb,MAAa,0BACX,YACA,YACA,eACA,YACA,WACA,aACA,eACA,YAqBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,0BACX,YACA,YACA,eACA,YACA,WACA,aACA,eACA,YAmBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;AAKjD,MAAa,4BACX,YACA,YACA,eACA,YACA,WACA,aACA,eACA,YAqBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,eACA,YACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK;;;;;AAMjD,MAAa,8BACX,YACA,YACA,eACA,YACA,WACA,aACA,eACA,YAyBA,WACG,KAAK,WAAgB,UACpB,4BACE,WACA,YACA,eACA,YACA,WACA,aACA,eACA,UACA;CACE,GAAG;CACH,KAAK,UAAU,MAAM;CACtB,CACF,CACF,CACA,QAAQ,MAAyB,MAAM,KAAK"}
|
|
@@ -27,7 +27,7 @@ __emotion_css = require_rolldown_runtime.__toESM(__emotion_css);
|
|
|
27
27
|
/**
|
|
28
28
|
* Internal component that consumes FlowContext and renders the sign-in UI.
|
|
29
29
|
*/
|
|
30
|
-
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false }) => {
|
|
30
|
+
const BaseSignInContent = ({ components = [], onSubmit, onError, error: externalError, id, className = "", inputClassName = "", buttonClassName = "", messageClassName = "", size = "medium", variant = "outlined", isLoading: externalIsLoading, children, additionalData = {}, isTimeoutDisabled = false }) => {
|
|
31
31
|
const { meta } = require_useThunderID.default();
|
|
32
32
|
const { theme } = require_useTheme.default();
|
|
33
33
|
const customRenderers = (0, react.useContext)(require_ComponentRendererContext.default);
|
|
@@ -208,12 +208,14 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
208
208
|
values: formValues
|
|
209
209
|
};
|
|
210
210
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
211
|
+
id,
|
|
211
212
|
className: containerClasses,
|
|
212
213
|
"data-testid": "thunderid-signin",
|
|
213
214
|
children: children(renderProps)
|
|
214
215
|
});
|
|
215
216
|
}
|
|
216
217
|
if (isLoading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.default, {
|
|
218
|
+
id,
|
|
217
219
|
className: (0, __emotion_css.cx)(containerClasses, styles.card),
|
|
218
220
|
"data-testid": "thunderid-signin",
|
|
219
221
|
variant,
|
|
@@ -227,6 +229,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
227
229
|
}) })
|
|
228
230
|
});
|
|
229
231
|
if (!components || components.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.default, {
|
|
232
|
+
id,
|
|
230
233
|
className: (0, __emotion_css.cx)(containerClasses, styles.card),
|
|
231
234
|
"data-testid": "thunderid-signin",
|
|
232
235
|
variant,
|
|
@@ -239,6 +242,7 @@ const BaseSignInContent = ({ components = [], onSubmit, onError, error: external
|
|
|
239
242
|
}) })
|
|
240
243
|
});
|
|
241
244
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Card.default, {
|
|
245
|
+
id,
|
|
242
246
|
className: (0, __emotion_css.cx)(containerClasses, styles.card),
|
|
243
247
|
"data-testid": "thunderid-signin",
|
|
244
248
|
variant,
|