UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 34.5 kB
{"version":3,"file":"profile-form.cjs","sources":["../../../../../src/components/auth/user-profile/profile-form.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Profile Form Component\n *\n * User profile editing form with image upload, field validation,\n * and real-time updates for personal information management.\n */\n\n\"use client\";\n\nimport {\n\tAvatar,\n\tButton,\n\tCard,\n\tCardBody,\n\tCardHeader,\n\tDivider,\n\tInput,\n\tSelect,\n\tSelectItem,\n\tSpinner,\n\tSwitch,\n\tTextarea,\n} from \"@heroui/react\";\nimport React from \"react\";\nimport { useAuth } from \"../../../hooks/use-auth\";\nimport { useConfig } from \"../../../hooks/use-config\";\nimport { useUser } from \"../../../hooks/use-user\";\nimport { EmailField } from \"../../forms/email-field\";\nimport { PhoneField } from \"../../forms/phone-field\";\n\n// ============================================================================\n// Profile Form Interface\n// ============================================================================\n\nexport interface ProfileFormProps {\n\t/**\n\t * Form submission handler\n\t */\n\tonSubmit?: (data: ProfileFormData) => void;\n\n\t/**\n\t * Profile update handler\n\t */\n\tonUpdate?: (data: ProfileFormData) => void;\n\n\t/**\n\t * Success callback\n\t */\n\tonSuccess?: (message: string) => void;\n\n\t/**\n\t * Error callback\n\t */\n\tonError?: (error: string) => void;\n\n\t/**\n\t * Show save button\n\t */\n\tshowSaveButton?: boolean;\n\n\t/**\n\t * Auto-save changes\n\t */\n\tautoSave?: boolean;\n\n\t/**\n\t * Auto-save delay (ms)\n\t */\n\tautoSaveDelay?: number;\n\n\t/**\n\t * Show profile image upload\n\t */\n\tshowImageUpload?: boolean;\n\n\t/**\n\t * Show email field\n\t */\n\tshowEmail?: boolean;\n\n\t/**\n\t * Show phone field\n\t */\n\tshowPhone?: boolean;\n\n\t/**\n\t * Show username field\n\t */\n\tshowUsername?: boolean;\n\n\t/**\n\t * Show metadata fields\n\t */\n\tshowMetadata?: boolean;\n\n\t/**\n\t * Custom fields to display\n\t */\n\tcustomFields?: ProfileFormField[];\n\n\t/**\n\t * Hide specific fields\n\t */\n\thideFields?: string[];\n\n\t/**\n\t * Field layout (columns)\n\t */\n\tfieldLayout?: \"single\" | \"double\";\n\n\t/**\n\t * Form variant\n\t */\n\tvariant?: \"flat\" | \"bordered\" | \"faded\";\n\n\t/**\n\t * Form size\n\t */\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\n\t/**\n\t * Whether form is disabled\n\t */\n\tisDisabled?: boolean;\n\n\t/**\n\t * Whether form is loading\n\t */\n\tisLoading?: boolean;\n\n\t/**\n\t * Custom className\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Show verification status\n\t */\n\tshowVerificationStatus?: boolean;\n\n\t/**\n\t * Allow profile image removal\n\t */\n\tallowImageRemoval?: boolean;\n\n\t/**\n\t * Image upload handler\n\t */\n\tonImageUpload?: (file: File) => Promise<string>;\n\n\t/**\n\t * Image removal handler\n\t */\n\tonImageRemove?: () => Promise<void>;\n\n\t/**\n\t * Maximum file size for images (bytes)\n\t */\n\tmaxImageSize?: number;\n\n\t/**\n\t * Allowed image types\n\t */\n\tallowedImageTypes?: string[];\n}\n\nexport interface ProfileFormData {\n\tfirstName?: string;\n\tlastName?: string;\n\temail?: string;\n\tphone?: string;\n\tusername?: string;\n\tprofileImageUrl?: string;\n\tmetadata?: Record<string, any>;\n\tcustomFields?: Record<string, any>;\n}\n\nexport interface ProfileFormField {\n\tkey: string;\n\tlabel: string;\n\ttype: \"text\" | \"email\" | \"phone\" | \"textarea\" | \"select\" | \"switch\";\n\tplaceholder?: string;\n\tdescription?: string;\n\trequired?: boolean;\n\toptions?: { value: string; label: string }[];\n\tvalidation?: (value: any) => string | null;\n}\n\n// ============================================================================\n// Profile Form Component\n// ============================================================================\n\nexport function ProfileForm({\n\tonSubmit,\n\tonUpdate,\n\tonSuccess,\n\tonError,\n\tshowSaveButton = true,\n\tautoSave = false,\n\tautoSaveDelay = 1000,\n\tshowImageUpload = true,\n\tshowEmail = true,\n\tshowPhone = true,\n\tshowUsername = true,\n\tshowMetadata = false,\n\tcustomFields = [],\n\thideFields = [],\n\tfieldLayout = \"single\",\n\tvariant = \"bordered\",\n\tsize = \"md\",\n\tisDisabled = false,\n\tisLoading: externalLoading = false,\n\tclassName = \"\",\n\tshowVerificationStatus = true,\n\tallowImageRemoval = true,\n\tonImageUpload,\n\tonImageRemove,\n\tmaxImageSize = 5 * 1024 * 1024, // 5MB\n\tallowedImageTypes = [\"image/jpeg\", \"image/png\", \"image/webp\"],\n}: ProfileFormProps) {\n\tconst { user } = useAuth();\n\tconst {\n\t\tupdateProfile,\n\t\tupdateProfileImage,\n\t\tremoveProfileImage,\n\t\tisLoading: userLoading,\n\t\tisEmailVerified,\n\t\tisPhoneVerified,\n\t} = useUser();\n\tconst { components } = useConfig();\n\n\t// Custom component override\n\tconst CustomProfileForm = components.ProfileForm;\n\tif (CustomProfileForm) {\n\t\treturn (\n\t\t\t<CustomProfileForm\n\t\t\t\t{...{\n\t\t\t\t\tonSubmit,\n\t\t\t\t\tonUpdate,\n\t\t\t\t\tonSuccess,\n\t\t\t\t\tonError,\n\t\t\t\t\tshowSaveButton,\n\t\t\t\t\tautoSave,\n\t\t\t\t\tautoSaveDelay,\n\t\t\t\t\tshowImageUpload,\n\t\t\t\t\tshowEmail,\n\t\t\t\t\tshowPhone,\n\t\t\t\t\tshowUsername,\n\t\t\t\t\tshowMetadata,\n\t\t\t\t\tcustomFields,\n\t\t\t\t\thideFields,\n\t\t\t\t\tfieldLayout,\n\t\t\t\t\tvariant,\n\t\t\t\t\tsize,\n\t\t\t\t\tisDisabled,\n\t\t\t\t\tisLoading: externalLoading,\n\t\t\t\t\tclassName,\n\t\t\t\t\tshowVerificationStatus,\n\t\t\t\t\tallowImageRemoval,\n\t\t\t\t\tonImageUpload,\n\t\t\t\t\tonImageRemove,\n\t\t\t\t\tmaxImageSize,\n\t\t\t\t\tallowedImageTypes,\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Form state\n\tconst [formData, setFormData] = React.useState<ProfileFormData>({\n\t\tfirstName: user?.firstName || \"\",\n\t\tlastName: user?.lastName || \"\",\n\t\temail: user?.primaryEmailAddress || \"\",\n\t\tphone: user?.primaryPhoneNumber || \"\",\n\t\tusername: user?.username || \"\",\n\t\tprofileImageUrl: user?.profileImageUrl || \"\",\n\t\tmetadata: user?.unsafeMetadata || {},\n\t\tcustomFields: {},\n\t});\n\n\tconst [isDirty, setIsDirty] = React.useState(false);\n\tconst [isSaving, setIsSaving] = React.useState(false);\n\tconst [imageUploading, setImageUploading] = React.useState(false);\n\tconst [errors, setErrors] = React.useState<Record<string, string>>({});\n\n\t// Loading state\n\tconst isLoading = externalLoading || userLoading || isSaving;\n\n\t// Auto-save timer\n\tconst autoSaveTimer = React.useRef<NodeJS.Timeout>();\n\n\t// Update form data when user changes\n\tReact.useEffect(() => {\n\t\tif (user) {\n\t\t\tsetFormData({\n\t\t\t\tfirstName: user.firstName || \"\",\n\t\t\t\tlastName: user.lastName || \"\",\n\t\t\t\temail: user.primaryEmailAddress || \"\",\n\t\t\t\tphone: user.primaryPhoneNumber || \"\",\n\t\t\t\tusername: user.username || \"\",\n\t\t\t\tprofileImageUrl: user.profileImageUrl || \"\",\n\t\t\t\tmetadata: user.unsafeMetadata || {},\n\t\t\t\tcustomFields: {},\n\t\t\t});\n\t\t}\n\t}, [user]);\n\n\t// Auto-save functionality\n\tReact.useEffect(() => {\n\t\tif (autoSave && isDirty && !isDisabled) {\n\t\t\tif (autoSaveTimer.current) {\n\t\t\t\tclearTimeout(autoSaveTimer.current);\n\t\t\t}\n\n\t\t\tautoSaveTimer.current = setTimeout(() => {\n\t\t\t\thandleSave();\n\t\t\t}, autoSaveDelay);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (autoSaveTimer.current) {\n\t\t\t\tclearTimeout(autoSaveTimer.current);\n\t\t\t}\n\t\t};\n\t}, [formData, isDirty, autoSave, autoSaveDelay, isDisabled]);\n\n\t// Handle field change\n\tconst handleFieldChange = React.useCallback(\n\t\t(field: string, value: any) => {\n\t\t\tsetFormData((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\t[field]: value,\n\t\t\t}));\n\t\t\tsetIsDirty(true);\n\n\t\t\t// Clear field error\n\t\t\tif (errors[field]) {\n\t\t\t\tsetErrors((prev) => {\n\t\t\t\t\tconst newErrors = { ...prev };\n\t\t\t\t\tdelete newErrors[field];\n\t\t\t\t\treturn newErrors;\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[errors],\n\t);\n\n\t// Handle custom field change\n\tconst handleCustomFieldChange = React.useCallback(\n\t\t(field: string, value: any) => {\n\t\t\tsetFormData((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tcustomFields: {\n\t\t\t\t\t...prev.customFields,\n\t\t\t\t\t[field]: value,\n\t\t\t\t},\n\t\t\t}));\n\t\t\tsetIsDirty(true);\n\t\t},\n\t\t[],\n\t);\n\n\t// Validate form\n\tconst validateForm = React.useCallback(() => {\n\t\tconst newErrors: Record<string, string> = {};\n\n\t\t// Validate email\n\t\tif (showEmail && formData.email) {\n\t\t\tconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\t\t\tif (!emailRegex.test(formData.email)) {\n\t\t\t\tnewErrors.email = \"Please enter a valid email address\";\n\t\t\t}\n\t\t}\n\n\t\t// Validate custom fields\n\t\tcustomFields.forEach((field) => {\n\t\t\tif (field.required && !formData.customFields?.[field.key]) {\n\t\t\t\tnewErrors[field.key] = `${field.label} is required`;\n\t\t\t}\n\n\t\t\tif (field.validation && formData.customFields?.[field.key]) {\n\t\t\t\tconst validationError = field.validation(\n\t\t\t\t\tformData.customFields[field.key],\n\t\t\t\t);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tnewErrors[field.key] = validationError;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tsetErrors(newErrors);\n\t\treturn Object.keys(newErrors).length === 0;\n\t}, [formData, showEmail, customFields]);\n\n\t// Handle save\n\tconst handleSave = React.useCallback(async () => {\n\t\tif (!validateForm()) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tsetIsSaving(true);\n\n\t\t\tconst updateData = {\n\t\t\t\tfirstName: formData.firstName,\n\t\t\t\tlastName: formData.lastName,\n\t\t\t\tprimaryEmailAddress: formData.email,\n\t\t\t\tprimaryPhoneNumber: formData.phone,\n\t\t\t\tusername: formData.username,\n\t\t\t\tunsafeMetadata: {\n\t\t\t\t\t...formData.metadata,\n\t\t\t\t\t...formData.customFields,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tawait updateProfile(updateData);\n\t\t\tsetIsDirty(false);\n\n\t\t\tonUpdate?.(formData);\n\t\t\tonSuccess?.(\"Profile updated successfully\");\n\t\t} catch (error) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Failed to update profile\";\n\t\t\tonError?.(message);\n\t\t} finally {\n\t\t\tsetIsSaving(false);\n\t\t}\n\t}, [formData, validateForm, updateProfile, onUpdate, onSuccess, onError]);\n\n\t// Handle submit\n\tconst handleSubmit = React.useCallback(\n\t\t(e: React.FormEvent) => {\n\t\t\te.preventDefault();\n\n\t\t\tif (onSubmit) {\n\t\t\t\tonSubmit(formData);\n\t\t\t} else {\n\t\t\t\thandleSave();\n\t\t\t}\n\t\t},\n\t\t[formData, onSubmit, handleSave],\n\t);\n\n\t// Handle image upload\n\tconst handleImageUpload = React.useCallback(\n\t\tasync (file: File) => {\n\t\t\t// Validate file\n\t\t\tif (!allowedImageTypes.includes(file.type)) {\n\t\t\t\tonError?.(\"Please select a valid image file (JPEG, PNG, or WebP)\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (file.size > maxImageSize) {\n\t\t\t\tonError?.(\n\t\t\t\t\t`Image size must be less than ${Math.round(maxImageSize / 1024 / 1024)}MB`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsetImageUploading(true);\n\n\t\t\t\tlet imageUrl: string;\n\n\t\t\t\tif (onImageUpload) {\n\t\t\t\t\timageUrl = await onImageUpload(file);\n\t\t\t\t} else {\n\t\t\t\t\t// Convert to base64 or upload via default method\n\t\t\t\t\timageUrl = await updateProfileImage(URL.createObjectURL(file));\n\t\t\t\t}\n\n\t\t\t\thandleFieldChange(\"profileImageUrl\", imageUrl);\n\t\t\t\tonSuccess?.(\"Profile image updated successfully\");\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : \"Failed to upload image\";\n\t\t\t\tonError?.(message);\n\t\t\t} finally {\n\t\t\t\tsetImageUploading(false);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tallowedImageTypes,\n\t\t\tmaxImageSize,\n\t\t\tonImageUpload,\n\t\t\tupdateProfileImage,\n\t\t\thandleFieldChange,\n\t\t\tonSuccess,\n\t\t\tonError,\n\t\t],\n\t);\n\n\t// Handle image removal\n\tconst handleImageRemoval = React.useCallback(async () => {\n\t\ttry {\n\t\t\tsetImageUploading(true);\n\n\t\t\tif (onImageRemove) {\n\t\t\t\tawait onImageRemove();\n\t\t\t} else {\n\t\t\t\tawait removeProfileImage();\n\t\t\t}\n\n\t\t\thandleFieldChange(\"profileImageUrl\", \"\");\n\t\t\tonSuccess?.(\"Profile image removed successfully\");\n\t\t} catch (error) {\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : \"Failed to remove image\";\n\t\t\tonError?.(message);\n\t\t} finally {\n\t\t\tsetImageUploading(false);\n\t\t}\n\t}, [\n\t\tonImageRemove,\n\t\tremoveProfileImage,\n\t\thandleFieldChange,\n\t\tonSuccess,\n\t\tonError,\n\t]);\n\n\t// File input ref\n\tconst fileInputRef = React.useRef<HTMLInputElement>(null);\n\n\t// Don't render if no user\n\tif (!user) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} className={`space-y-6 ${className}`}>\n\t\t\t{/* Profile Image Section */}\n\t\t\t{showImageUpload && !hideFields.includes(\"profileImage\") && (\n\t\t\t\t<Card variant={variant}>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">Profile Picture</h4>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<Divider />\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<div className=\"flex items-center gap-4\">\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tsrc={formData.profileImageUrl}\n\t\t\t\t\t\t\t\tname={`${formData.firstName} ${formData.lastName}`}\n\t\t\t\t\t\t\t\tsize=\"xl\"\n\t\t\t\t\t\t\t\tisBordered\n\t\t\t\t\t\t\t\tfallback={imageUploading ? <Spinner size=\"sm\" /> : undefined}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t\t\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tvariant=\"bordered\"\n\t\t\t\t\t\t\t\t\t\tonPress={() => fileInputRef.current?.click()}\n\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled || imageUploading}\n\t\t\t\t\t\t\t\t\t\tisLoading={imageUploading}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tUpload Photo\n\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t{allowImageRemoval && formData.profileImageUrl && (\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"light\"\n\t\t\t\t\t\t\t\t\t\t\tcolor=\"danger\"\n\t\t\t\t\t\t\t\t\t\t\tonPress={handleImageRemoval}\n\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled || imageUploading}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500\">\n\t\t\t\t\t\t\t\t\tJPG, PNG or WebP. Max size{\" \"}\n\t\t\t\t\t\t\t\t\t{Math.round(maxImageSize / 1024 / 1024)}MB.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\taccept={allowedImageTypes.join(\",\")}\n\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\tconst file = e.target.files?.[0];\n\t\t\t\t\t\t\t\tif (file) {\n\t\t\t\t\t\t\t\t\thandleImageUpload(file);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\te.target.value = \"\";\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Personal Information */}\n\t\t\t<Card variant={variant}>\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<h4 className=\"text-md font-semibold\">Personal Information</h4>\n\t\t\t\t</CardHeader>\n\t\t\t\t<Divider />\n\t\t\t\t<CardBody>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={`grid gap-4 ${fieldLayout === \"double\" ? \"md:grid-cols-2\" : \"grid-cols-1\"}`}\n\t\t\t\t\t>\n\t\t\t\t\t\t{/* First Name */}\n\t\t\t\t\t\t{!hideFields.includes(\"firstName\") && (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tlabel=\"First Name\"\n\t\t\t\t\t\t\t\tplaceholder=\"Enter your first name\"\n\t\t\t\t\t\t\t\tvalue={formData.firstName}\n\t\t\t\t\t\t\t\tonValueChange={(value) => handleFieldChange(\"firstName\", value)}\n\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\tisInvalid={!!errors.firstName}\n\t\t\t\t\t\t\t\terrorMessage={errors.firstName}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Last Name */}\n\t\t\t\t\t\t{!hideFields.includes(\"lastName\") && (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tlabel=\"Last Name\"\n\t\t\t\t\t\t\t\tplaceholder=\"Enter your last name\"\n\t\t\t\t\t\t\t\tvalue={formData.lastName}\n\t\t\t\t\t\t\t\tonValueChange={(value) => handleFieldChange(\"lastName\", value)}\n\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\tisInvalid={!!errors.lastName}\n\t\t\t\t\t\t\t\terrorMessage={errors.lastName}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Username */}\n\t\t\t\t\t\t{showUsername && !hideFields.includes(\"username\") && (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tlabel=\"Username\"\n\t\t\t\t\t\t\t\tplaceholder=\"Enter your username\"\n\t\t\t\t\t\t\t\tvalue={formData.username}\n\t\t\t\t\t\t\t\tonValueChange={(value) => handleFieldChange(\"username\", value)}\n\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\tisInvalid={!!errors.username}\n\t\t\t\t\t\t\t\terrorMessage={errors.username}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Email */}\n\t\t\t\t\t\t{showEmail && !hideFields.includes(\"email\") && (\n\t\t\t\t\t\t\t<EmailField\n\t\t\t\t\t\t\t\tlabel=\"Email Address\"\n\t\t\t\t\t\t\t\tvalue={formData.email}\n\t\t\t\t\t\t\t\tonChange={(value) => handleFieldChange(\"email\", value)}\n\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t\t\t\terror={errors.email}\n\t\t\t\t\t\t\t\tshowVerificationStatus={showVerificationStatus}\n\t\t\t\t\t\t\t\tisVerified={isEmailVerified}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Phone */}\n\t\t\t\t\t\t{showPhone && !hideFields.includes(\"phone\") && (\n\t\t\t\t\t\t\t<PhoneField\n\t\t\t\t\t\t\t\tlabel=\"Phone Number\"\n\t\t\t\t\t\t\t\tvalue={formData.phone}\n\t\t\t\t\t\t\t\tonChange={(value) => handleFieldChange(\"phone\", value)}\n\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t\t\t\terror={errors.phone}\n\t\t\t\t\t\t\t\tshowVerificationStatus={showVerificationStatus}\n\t\t\t\t\t\t\t\tisVerified={isPhoneVerified}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</CardBody>\n\t\t\t</Card>\n\n\t\t\t{/* Custom Fields */}\n\t\t\t{customFields.length > 0 && (\n\t\t\t\t<Card variant={variant}>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<h4 className=\"text-md font-semibold\">Additional Information</h4>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<Divider />\n\t\t\t\t\t<CardBody>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={`grid gap-4 ${fieldLayout === \"double\" ? \"md:grid-cols-2\" : \"grid-cols-1\"}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{customFields.map((field) => {\n\t\t\t\t\t\t\t\tconst value = formData.customFields?.[field.key] || \"\";\n\n\t\t\t\t\t\t\t\tswitch (field.type) {\n\t\t\t\t\t\t\t\t\tcase \"textarea\":\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\t\t\t\t\t\t\tlabel={field.label}\n\t\t\t\t\t\t\t\t\t\t\t\tplaceholder={field.placeholder}\n\t\t\t\t\t\t\t\t\t\t\t\tdescription={field.description}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\t\t\t\t\t\tonValueChange={(val) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleCustomFieldChange(field.key, val)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\tisRequired={field.required}\n\t\t\t\t\t\t\t\t\t\t\t\tisInvalid={!!errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t\terrorMessage={errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tcase \"select\":\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\t\t\t\t\t\t\tlabel={field.label}\n\t\t\t\t\t\t\t\t\t\t\t\tplaceholder={field.placeholder}\n\t\t\t\t\t\t\t\t\t\t\t\tdescription={field.description}\n\t\t\t\t\t\t\t\t\t\t\t\tselectedKeys={value ? [value] : []}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelectionChange={(keys) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst selectedValue = Array.from(keys)[0] as string;\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleCustomFieldChange(field.key, selectedValue);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\tisRequired={field.required}\n\t\t\t\t\t\t\t\t\t\t\t\tisInvalid={!!errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t\terrorMessage={errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{field.options?.map((option) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SelectItem key={option.value} value={option.value}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t\t\t\t)) || []}\n\t\t\t\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tcase \"switch\":\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-between\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<label className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{field.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{field.required && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-danger ml-1\">*</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{field.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-default-500 mt-1\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{field.description}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\t\t\t\t\tisSelected={!!value}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonValueChange={(checked) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleCustomFieldChange(field.key, checked)\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\t\t\t\t\t\t\tlabel={field.label}\n\t\t\t\t\t\t\t\t\t\t\t\tplaceholder={field.placeholder}\n\t\t\t\t\t\t\t\t\t\t\t\tdescription={field.description}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\t\t\t\t\t\tonValueChange={(val) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleCustomFieldChange(field.key, val)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\ttype={field.type}\n\t\t\t\t\t\t\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t\t\t\t\t\tisDisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\tisRequired={field.required}\n\t\t\t\t\t\t\t\t\t\t\t\tisInvalid={!!errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t\terrorMessage={errors[field.key]}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardBody>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Save Button */}\n\t\t\t{showSaveButton && !autoSave && (\n\t\t\t\t<div className=\"flex justify-end gap-3\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\t\tisDisabled={isDisabled || !isDirty}\n\t\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave Changes\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Auto-save indicator */}\n\t\t\t{autoSave && isDirty && (\n\t\t\t\t<div className=\"flex items-center gap-2 text-sm text-default-500\">\n\t\t\t\t\t<Spinner size=\"sm\" />\n\t\t\t\t\t<span>Auto-saving...</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</form>\n\t);\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default ProfileForm;\n"],"names":["ProfileForm","onSubmit","onUpdate","onSuccess","onError","showSaveButton","autoSave","autoSaveDelay","showImageUpload","showEmail","showPhone","showUsername","showMetadata","customFields","hideFields","fieldLayout","variant","size","isDisabled","externalLoading","className","showVerificationStatus","allowImageRemoval","onImageUpload","onImageRemove","maxImageSize","allowedImageTypes","user","useAuth","updateProfile","updateProfileImage","removeProfileImage","userLoading","isEmailVerified","isPhoneVerified","useUser","components","useConfig","CustomProfileForm","jsx","formData","setFormData","React","isDirty","setIsDirty","isSaving","setIsSaving","imageUploading","setImageUploading","errors","setErrors","isLoading","autoSaveTimer","handleSave","handleFieldChange","field","value","prev","newErrors","handleCustomFieldChange","validateForm","validationError","updateData","error","message","handleSubmit","handleImageUpload","file","imageUrl","handleImageRemoval","fileInputRef","jsxs","Card","CardHeader","Divider","CardBody","Avatar","Spinner","Button","Input","EmailField","PhoneField","Textarea","val","Select","keys","selectedValue","option","SelectItem","Switch","checked"],"mappings":"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"}