{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "my-account/user-mfa-management",
  "type": "registry:block",
  "title": "Multi-factor authentication management component.",
  "description": "Complete MFA management interface for enrolling, viewing, and deleting authentication factors. Supports TOTP authenticators, SMS, Email, Push notifications, and recovery codes.",
  "dependencies": [
    "@auth0/universal-components-core@2.1.0",
    "@auth0/auth0-react@^2.15.1",
    "@hookform/resolvers@^5.1.0",
    "@radix-ui/react-dialog@^1.1.14",
    "@radix-ui/react-label@^2.1.7",
    "@radix-ui/react-popover@^1.1.14",
    "@radix-ui/react-slot@^1.2.3",
    "@radix-ui/react-tooltip@^1.2.7",
    "@tanstack/react-query@^5.56.2",
    "class-variance-authority@^0.7.1",
    "clsx@^2.1.1",
    "lucide-react@^1.16.0",
    "qrcode@^1.5.4",
    "react-hook-form@^7.57.0",
    "sonner@^2.0.5",
    "tailwind-merge@^3.3.0"
  ],
  "files": [
    {
      "path": "src/components/auth0/my-account/user-mfa-management.tsx",
      "content": "/** @module user-mfa-management */\n\nimport { getComponentStyles } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { DeleteFactorConfirmation } from '@/components/auth0/my-account/shared/mfa/delete-factor-confirmation';\nimport { MFAEmptyState } from '@/components/auth0/my-account/shared/mfa/empty-state';\nimport { MFAErrorState } from '@/components/auth0/my-account/shared/mfa/error-state';\nimport { FactorsList } from '@/components/auth0/my-account/shared/mfa/factors-list';\nimport { UserMFASetupForm } from '@/components/auth0/my-account/shared/mfa/user-mfa-setup-form';\nimport { GateKeeper } from '@/components/auth0/shared/gate-keeper/gate-keeper';\nimport { StyledScope } from '@/components/auth0/shared/styled-scope';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardDescription, CardTitle } from '@/components/ui/card';\nimport { List, ListItem } from '@/components/ui/list';\nimport { useUserMFA } from '@/hooks/my-account/use-user-mfa';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { cn } from '@/lib/utils';\nimport type { UserMFAMgmtProps, UserMFAMgmtViewProps } from '@/types/my-account/mfa/mfa-types';\n\n/**\n * Multi-factor authentication management component.\n *\n * Complete MFA management interface for enrolling, viewing, and deleting authentication\n * factors. Supports TOTP authenticators, SMS, Email, Push notifications, and recovery codes.\n *\n * @param props - {@link UserMFAMgmtProps}\n * @param props.customMessages - Custom i18n message overrides\n * @param props.styling - CSS variables and class overrides\n * @param props.hideHeader - Hide the header section\n * @param props.showActiveOnly - Show only enrolled factors\n * @param props.disableEnroll - Disable enroll actions\n * @param props.disableDelete - Disable delete actions\n * @param props.readOnly - Render in read-only mode\n * @param props.factorConfig - Per-factor visibility/enabled configuration\n * @param props.onEnroll - Callback after successful enrollment\n * @param props.onDelete - Callback after successful deletion\n * @param props.onFetch - Callback after factors are loaded\n * @param props.onErrorAction - Callback when actions error\n * @param props.onBeforeAction - Callback before actions; return false to cancel\n * @param props.schema - Validation schema overrides\n * @returns MFA management component\n *\n * @see {@link UserMFAMgmtProps} for full props documentation\n *\n * @example\n * ```tsx\n * <UserMFAMgmt\n *   onEnroll={(factor) => console.log('Enrolled:', factor)}\n *   onDelete={(factor) => console.log('Deleted:', factor)}\n *   factorConfig={{\n *     otp: { enabled: true },\n *     sms: { enabled: true },\n *     email: { enabled: false },\n *   }}\n * />\n * ```\n */\nfunction UserMFAMgmt({\n  customMessages = {},\n  styling = { variables: { common: {}, light: {}, dark: {} }, classes: {} },\n  hideHeader = false,\n  showActiveOnly = false,\n  disableEnroll = false,\n  disableDelete = false,\n  readOnly = false,\n  factorConfig = {},\n  onEnroll,\n  onDelete,\n  onFetch,\n  onErrorAction,\n  onBeforeAction,\n  schema,\n}: UserMFAMgmtProps) {\n  const {\n    factorsByType,\n    isLoadingFactors,\n    isEnrolling,\n    isDeleting,\n    isConfirming,\n    error,\n    isEnrollDialogOpen,\n    enrollFactor,\n    enrollmentPhase,\n    contact,\n    otpData,\n    recoveryCode,\n    isDeleteDialogOpen,\n    factorToDelete,\n    visibleFactorTypes,\n    hasNoActiveFactors,\n    handleEnroll,\n    handleCloseEnrollDialog,\n    handleDeleteFactor,\n    handleConfirmDelete,\n    handleCancelDelete,\n    handleSendCode,\n    handleConfirmOtp,\n    handleConfirmPush,\n    handleConfirmRecoveryCode,\n    handleEnterQRPhase,\n  } = useUserMFA({\n    showActiveOnly,\n    readOnly,\n    disableDelete,\n    factorConfig,\n    customMessages,\n    onFetch,\n    onEnroll,\n    onDelete,\n    onErrorAction,\n    onBeforeAction,\n  });\n\n  return (\n    <GateKeeper styling={styling} isLoading={isLoadingFactors}>\n      <UserMFAMgmtView\n        error={error}\n        schema={schema}\n        isEnrolling={isEnrolling}\n        isDeleting={isDeleting}\n        isConfirming={isConfirming}\n        styling={styling}\n        customMessages={customMessages}\n        hideHeader={hideHeader}\n        showActiveOnly={showActiveOnly}\n        disableEnroll={disableEnroll}\n        disableDelete={disableDelete}\n        readOnly={readOnly}\n        factorConfig={factorConfig}\n        isEnrollDialogOpen={isEnrollDialogOpen}\n        enrollFactor={enrollFactor}\n        enrollmentPhase={enrollmentPhase}\n        contact={contact}\n        otpData={otpData}\n        recoveryCode={recoveryCode}\n        isDeleteDialogOpen={isDeleteDialogOpen}\n        factorToDelete={factorToDelete}\n        factorsByType={factorsByType}\n        visibleFactorTypes={visibleFactorTypes}\n        hasNoActiveFactors={hasNoActiveFactors}\n        onEnrollFactor={handleEnroll}\n        onDeleteFactor={handleDeleteFactor}\n        onCloseEnrollDialog={handleCloseEnrollDialog}\n        onConfirmDelete={handleConfirmDelete}\n        onCancelDelete={handleCancelDelete}\n        onSubmitContact={handleSendCode}\n        onConfirmOtp={handleConfirmOtp}\n        onContinueQR={handleConfirmPush}\n        onConfirmRecoveryCode={handleConfirmRecoveryCode}\n        onAdvanceToQR={handleEnterQRPhase}\n      />\n    </GateKeeper>\n  );\n}\n\n/**\n * UserMFAMgmtView — Presentational component.\n * @param props - All state and handlers passed directly.\n * @returns User Management View element\n * @internal\n */\nfunction UserMFAMgmtView({\n  error,\n  schema,\n  isEnrolling,\n  isDeleting,\n  isConfirming,\n  styling,\n  customMessages,\n  hideHeader,\n  showActiveOnly,\n  disableEnroll,\n  disableDelete,\n  readOnly,\n  factorConfig,\n  isEnrollDialogOpen,\n  enrollFactor,\n  enrollmentPhase,\n  contact,\n  otpData,\n  recoveryCode,\n  isDeleteDialogOpen,\n  factorToDelete,\n  factorsByType,\n  visibleFactorTypes,\n  hasNoActiveFactors,\n  onEnrollFactor,\n  onDeleteFactor,\n  onCloseEnrollDialog,\n  onConfirmDelete,\n  onCancelDelete,\n  onSubmitContact,\n  onConfirmOtp,\n  onContinueQR,\n  onConfirmRecoveryCode,\n  onAdvanceToQR,\n}: UserMFAMgmtViewProps) {\n  const { isDarkMode } = useTheme();\n  const { t } = useTranslator('mfa', customMessages);\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  return (\n    <StyledScope style={currentStyles.variables}>\n      <Card className={cn('p-6', currentStyles.classes?.['UserMFAMgmt-card'])}>\n        {error ? (\n          <MFAErrorState\n            title={t('component_error_title')}\n            description={t('component_error_description')}\n          />\n        ) : (\n          <>\n            {!hideHeader && (\n              <>\n                <CardTitle\n                  id=\"mfa-management-title\"\n                  className=\"text-2xl text-(length:--font-size-heading) font-medium text-left\"\n                >\n                  {t('title')}\n                </CardTitle>\n                <CardDescription\n                  id=\"mfa-management-desc\"\n                  className=\"text-sm text-(length:--font-size-paragraph) text-muted-foreground text-left\"\n                >\n                  {t('description')}\n                </CardDescription>\n              </>\n            )}\n            {showActiveOnly && hasNoActiveFactors ? (\n              <MFAEmptyState message={t('no_active_mfa')} />\n            ) : (\n              <List\n                className=\"flex flex-col gap-0 w-full\"\n                aria-labelledby=\"mfa-management-title\"\n                aria-describedby=\"mfa-management-desc\"\n              >\n                {visibleFactorTypes.map((factorType) => {\n                  const factors = factorsByType[factorType] || [];\n                  const activeFactors = factors.filter((f) => f.enrolled);\n                  const isEnabledFactor = factorConfig?.[factorType]?.enabled !== false;\n                  const hasActiveFactors = activeFactors.length > 0;\n\n                  return (\n                    <ListItem\n                      key={factorType}\n                      className={cn(\n                        'w-full p-0 m-0 py-6 gap-3',\n                        !isEnabledFactor && 'opacity-50 pointer-events-none',\n                      )}\n                      aria-disabled={!isEnabledFactor}\n                      tabIndex={0}\n                      aria-label={t(`${factorType}.title`)}\n                    >\n                      <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-3\">\n                        <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n                          <span\n                            className={cn(\n                              'break-words text-card-foreground whitespace-normal text-base text-(length:--font-size-body) font-medium',\n                            )}\n                            id={`factor-title-${factorType}`}\n                          >\n                            {t(`${factorType}.title`)}\n                          </span>\n\n                          {hasActiveFactors && (\n                            <Badge\n                              variant=\"success\"\n                              size=\"sm\"\n                              className=\"shrink-0\"\n                              aria-label={t('enabled')}\n                            >\n                              {t('enabled')}\n                            </Badge>\n                          )}\n                        </div>\n\n                        {!readOnly && (\n                          <Button\n                            size=\"default\"\n                            variant=\"outline\"\n                            className=\"text-sm w-full sm:w-auto shrink-0\"\n                            onClick={() => onEnrollFactor(factorType)}\n                            disabled={disableEnroll || !isEnabledFactor}\n                            aria-label={t(`${factorType}.button-text`)}\n                            aria-describedby={`factor-title-${factorType}`}\n                          >\n                            {t(`${factorType}.button-text`)}\n                          </Button>\n                        )}\n                      </div>\n\n                      {!hasActiveFactors && (\n                        <p\n                          className={cn(\n                            'font-normal text-sm text-(length:--font-size-paragraph) text-muted-foreground text-left break-words',\n                          )}\n                          id={`factor-desc-${factorType}`}\n                        >\n                          {t(`${factorType}.description`)}\n                        </p>\n                      )}\n\n                      {hasActiveFactors && (\n                        <FactorsList\n                          factors={activeFactors}\n                          factorType={factorType}\n                          readOnly={readOnly}\n                          isEnabledFactor={isEnabledFactor}\n                          onDeleteFactor={onDeleteFactor}\n                          isDeletingFactor={isDeleting}\n                          disableDelete={disableDelete}\n                          styling={styling}\n                          customMessages={customMessages}\n                        />\n                      )}\n                    </ListItem>\n                  );\n                })}\n              </List>\n            )}\n          </>\n        )}\n      </Card>\n      {enrollFactor && (\n        <UserMFASetupForm\n          open={isEnrollDialogOpen}\n          onClose={onCloseEnrollDialog}\n          factorType={enrollFactor}\n          enrollmentPhase={enrollmentPhase}\n          contact={contact}\n          otpData={otpData}\n          recoveryCode={recoveryCode}\n          isEnrolling={isEnrolling}\n          isConfirming={isConfirming}\n          onSubmitContact={onSubmitContact}\n          onConfirmOtp={onConfirmOtp}\n          onContinueQR={onContinueQR}\n          onConfirmRecoveryCode={onConfirmRecoveryCode}\n          onAdvanceToQR={onAdvanceToQR}\n          schema={schema}\n          styling={styling}\n          customMessages={customMessages}\n        />\n      )}\n      <DeleteFactorConfirmation\n        open={isDeleteDialogOpen}\n        onOpenChange={(open) => !open && !isDeleting && onCancelDelete()}\n        factorToDelete={factorToDelete}\n        isDeletingFactor={isDeleting}\n        onConfirm={onConfirmDelete}\n        onCancel={onCancelDelete}\n        styling={styling}\n        customMessages={customMessages}\n      />\n    </StyledScope>\n  );\n}\n\nexport { UserMFAMgmt, UserMFAMgmtView };\n",
      "type": "registry:block",
      "target": "components/auth0/my-account/user-mfa-management.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/contact-input-form.tsx",
      "content": "/**\n * MFA contact input form for email/SMS enrollment.\n * @module contact-input-form\n * @internal\n */\n\nimport {\n  FACTOR_TYPE_EMAIL,\n  createEmailContactSchema,\n  createSmsContactSchema,\n  type EmailContactForm,\n  type SmsContactForm,\n  getComponentStyles,\n} from '@auth0/universal-components-core';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { MailIcon, SmartphoneIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { useForm } from 'react-hook-form';\n\nimport { OTPVerificationForm } from '@/components/auth0/my-account/shared/mfa/otp-verification-form';\nimport { Button } from '@/components/ui/button';\nimport {\n  Form,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormMessage,\n} from '@/components/ui/form';\nimport { Spinner } from '@/components/ui/spinner';\nimport { TextField } from '@/components/ui/text-field';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { FORM_REVALIDATE_MODE, FORM_VALIDATION_MODE } from '@/lib/constants/form-constants';\nimport { ENTER_CONTACT, ENTER_OTP } from '@/lib/constants/my-account/mfa/mfa-constants';\nimport type { ContactInputFormProps } from '@/types/my-account/mfa/mfa-types';\n\ntype ContactForm = EmailContactForm | SmsContactForm;\n\ntype Phase = typeof ENTER_CONTACT | typeof ENTER_OTP;\n\n/**\n *\n * @param props - Component props.\n * @param props.factorType - The MFA factor type\n * @param props.contact - Current contact value (email or phone) from hook state\n * @param props.isEnrolling - Whether enrollment is in progress\n * @param props.isConfirming - Whether OTP confirmation is in progress\n * @param props.onSubmitContact - Called with contact options; returns true on success\n * @param props.onConfirmOtp - Called with the 6-digit OTP code\n * @param props.onClose - Callback fired when the component should close\n * @param props.schema - Zod validation schema\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function ContactInputForm({\n  factorType,\n  contact,\n  isEnrolling,\n  isConfirming,\n  onSubmitContact,\n  onConfirmOtp,\n  onClose,\n  schema,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: ContactInputFormProps) {\n  const [phase, setPhase] = React.useState<Phase>(ENTER_CONTACT);\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  const ContactSchema = React.useMemo(() => {\n    return factorType === FACTOR_TYPE_EMAIL\n      ? createEmailContactSchema(t('errors.invalid_email'), schema?.email)\n      : createSmsContactSchema(t('errors.invalid_phone_number'), schema?.phone);\n  }, [factorType, t, schema]);\n\n  const form = useForm<ContactForm>({\n    resolver: zodResolver(ContactSchema),\n    mode: FORM_VALIDATION_MODE,\n    reValidateMode: FORM_REVALIDATE_MODE,\n    defaultValues: { contact: contact || '' },\n  });\n\n  const handleCancel = () => {\n    form.reset();\n    onClose?.();\n  };\n\n  const handleBack = () => setPhase(ENTER_CONTACT);\n\n  const handleSubmit = async (data: ContactForm) => {\n    const options: Record<string, string> =\n      factorType === FACTOR_TYPE_EMAIL ? { email: data.contact } : { phone_number: data.contact };\n    const success = await onSubmitContact(options);\n    if (success) setPhase(ENTER_OTP);\n  };\n\n  const renderContactScreen = () => (\n    <div style={currentStyles.variables} className=\"w-full max-w-sm mx-auto\">\n      <div className=\"flex flex-col items-center justify-center flex-1 space-y-10\">\n        {isEnrolling ? (\n          <div\n            className=\"absolute inset-0 flex items-center justify-center\"\n            role=\"status\"\n            aria-live=\"polite\"\n          >\n            <Spinner aria-label={t('loading')} />\n          </div>\n        ) : (\n          <>\n            <p\n              className=\"text-center text-primary text-sm text-(length:--font-size-paragraph) font-normal\"\n              id=\"contact-description\"\n            >\n              {factorType === FACTOR_TYPE_EMAIL\n                ? t('enrollment_form.enroll_email_description')\n                : t('enrollment_form.enroll_sms_description')}\n            </p>\n\n            <div className=\"w-full\">\n              <Form {...form}>\n                <form\n                  onSubmit={form.handleSubmit(handleSubmit)}\n                  className=\"space-y-6\"\n                  aria-describedby=\"contact-description\"\n                >\n                  <FormField\n                    control={form.control}\n                    name=\"contact\"\n                    render={({ field }) => (\n                      <FormItem>\n                        <FormLabel\n                          className=\"text-left text-sm text-(length:--font-size-paragraph) font-medium\"\n                          htmlFor=\"contact-input\"\n                        >\n                          {factorType === FACTOR_TYPE_EMAIL\n                            ? t('enrollment_form.email_address')\n                            : t('enrollment_form.phone_number')}\n                        </FormLabel>\n                        <FormControl>\n                          <TextField\n                            id=\"contact-input\"\n                            type={factorType === FACTOR_TYPE_EMAIL ? 'email' : 'tel'}\n                            autoComplete={factorType === FACTOR_TYPE_EMAIL ? 'email' : 'tel'}\n                            startAdornment={\n                              <div className=\"p-1.5\" aria-hidden=\"true\">\n                                {factorType === FACTOR_TYPE_EMAIL ? (\n                                  <MailIcon />\n                                ) : (\n                                  <SmartphoneIcon />\n                                )}\n                              </div>\n                            }\n                            placeholder={\n                              factorType === FACTOR_TYPE_EMAIL\n                                ? t('enrollment_form.enroll_email_placeholder')\n                                : t('enrollment_form.enroll_sms_placeholder')\n                            }\n                            error={Boolean(form.formState.errors.contact)}\n                            aria-invalid={Boolean(form.formState.errors.contact)}\n                            {...field}\n                          />\n                        </FormControl>\n                        <FormMessage\n                          className=\"text-left text-sm text-(length:--font-size-paragraph)\"\n                          id=\"contact-error\"\n                          role=\"alert\"\n                        />\n                      </FormItem>\n                    )}\n                  />\n                  <div className=\"flex flex-row justify-end gap-3 mt-6 mb-6\">\n                    <Button\n                      type=\"button\"\n                      className=\"text-sm\"\n                      variant=\"outline\"\n                      size=\"default\"\n                      onClick={handleCancel}\n                      aria-label={t('cancel')}\n                    >\n                      {t('cancel')}\n                    </Button>\n                    <Button\n                      type=\"submit\"\n                      size=\"default\"\n                      className=\"text-sm\"\n                      disabled={!form.formState.isValid || isEnrolling}\n                      aria-label={t('submit')}\n                    >\n                      {t('submit')}\n                    </Button>\n                  </div>\n                </form>\n              </Form>\n            </div>\n          </>\n        )}\n      </div>\n    </div>\n  );\n\n  const renderOtpScreen = () => (\n    <OTPVerificationForm\n      factorType={factorType}\n      contact={contact}\n      isConfirming={isConfirming}\n      onConfirmOtp={onConfirmOtp}\n      onBack={handleBack}\n      styling={styling}\n      customMessages={customMessages}\n    />\n  );\n\n  return phase === ENTER_CONTACT ? renderContactScreen() : renderOtpScreen();\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/contact-input-form.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/delete-factor-confirmation.tsx",
      "content": "/**\n * MFA factor deletion confirmation dialog.\n * @module delete-factor-confirmation\n * @internal\n */\n\nimport { getComponentStyles } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Separator } from '@/components/ui/separator';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { cn } from '@/lib/utils';\nimport type { DeleteFactorConfirmationProps } from '@/types/my-account/mfa/mfa-types';\n\n/**\n *\n * @param props - Component props.\n * @param props.open - Whether the component is open/visible\n * @param props.onOpenChange - Callback fired when open state changes\n * @param props.factorToDelete - The factor selected for deletion\n * @param props.isDeletingFactor - Whether a factor deletion is in progress\n * @param props.onConfirm - Callback fired when the action is confirmed\n * @param props.onCancel - Callback fired when the operation is cancelled\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function DeleteFactorConfirmation({\n  open,\n  onOpenChange,\n  factorToDelete,\n  isDeletingFactor,\n  onConfirm,\n  onCancel,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: DeleteFactorConfirmationProps) {\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  return (\n    <Dialog open={open} onOpenChange={onOpenChange}>\n      <DialogContent\n        style={currentStyles?.variables}\n        className={cn(\n          'w-[600px] max-h-[90vh]',\n          currentStyles.classes?.['DeleteFactorConfirmation-dialogContent'],\n        )}\n      >\n        <DialogHeader>\n          <DialogTitle className=\"text-center text-(length:--font-size-title) font-medium\">\n            {t('delete_mfa_title')}\n          </DialogTitle>\n          <Separator className=\"my-2\" />\n        </DialogHeader>\n\n        <div className=\"flex flex-col items-center mt-6\">\n          <p\n            className={cn(\n              'text-center text-(length:--font-size-paragraph) font-normal mb-10 text-primary',\n            )}\n          >\n            {t(`delete_mfa_${factorToDelete?.type}_consent`)}\n          </p>\n\n          <div className=\"flex flex-row justify-end gap-3 w-full mt-6 mb-6\">\n            <Button\n              variant=\"outline\"\n              size=\"default\"\n              className=\"text-sm\"\n              onClick={onCancel}\n              disabled={isDeletingFactor}\n              aria-label={t('cancel')}\n            >\n              {t('cancel')}\n            </Button>\n            <Button\n              variant=\"destructive\"\n              size=\"default\"\n              className=\"text-sm\"\n              onClick={() => onConfirm()}\n              disabled={isDeletingFactor}\n              aria-label={t('confirm')}\n            >\n              {isDeletingFactor ? t('deleting') : t('confirm')}\n            </Button>\n          </div>\n        </div>\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/delete-factor-confirmation.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/empty-state.tsx",
      "content": "/**\n * MFA empty state display.\n * @module empty-state\n * @internal\n */\n\nimport { cn } from '@/lib/utils';\n\ninterface MFAEmptyStateProps {\n  message: string;\n  className?: string;\n}\n\n/**\n *\n * @param props - Component props.\n * @param props.message - The message to display\n * @param props.className - Optional CSS class name for styling\n * @returns JSX element\n */\nexport function MFAEmptyState({ message, className }: MFAEmptyStateProps) {\n  return (\n    <p\n      className={cn(\n        'text-sm text-(length:--font-size-paragraph) text-center text-muted-foreground',\n        className,\n      )}\n    >\n      {message}\n    </p>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/empty-state.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/error-state.tsx",
      "content": "/**\n * MFA error state display.\n * @module error-state\n * @internal\n */\n\nimport { cn } from '@/lib/utils';\n\ninterface ErrorStateProps {\n  title: string;\n  description: string;\n  className?: string;\n}\n\n/**\n * Displays an error state for MFA operations.\n *\n * @param props - Component props.\n * @param props.title - Error title text.\n * @param props.description - Error description text.\n * @param props.className - Additional CSS class names.\n * @returns Error state component.\n * @internal\n */\nexport function MFAErrorState({ title, description, className }: ErrorStateProps) {\n  return (\n    <div\n      className={cn('flex flex-col items-center justify-center p-4 space-y-2', className)}\n      role=\"alert\"\n      aria-live=\"assertive\"\n    >\n      <h1\n        className=\"text-base font-medium text-center text-destructive-foreground\"\n        id=\"mfa-error-title\"\n      >\n        {title}\n      </h1>\n      <p className=\"text-sm text-center text-destructive-foreground whitespace-pre-line\">\n        {description}\n      </p>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/error-state.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/factors-list.tsx",
      "content": "/**\n * MFA enrolled factors list display.\n * @module factors-list\n * @internal\n */\n\nimport { FACTOR_TYPE_PHONE, FACTOR_TYPE_EMAIL } from '@auth0/universal-components-core';\nimport { getComponentStyles } from '@auth0/universal-components-core';\nimport { MoreVertical, Trash2, Mail, Smartphone } from 'lucide-react';\nimport * as React from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { cn } from '@/lib/utils';\nimport type { FactorsListProps } from '@/types/my-account/mfa/mfa-types';\n\nconst FACTOR_ICONS = {\n  [FACTOR_TYPE_PHONE]: Smartphone,\n  [FACTOR_TYPE_EMAIL]: Mail,\n} as const;\n\n/**\n *\n * @param props - Component props.\n * @param props.factors - Array of MFA factors\n * @param props.factorType - The MFA factor type\n * @param props.readOnly - Whether the component is in read-only mode\n * @param props.isEnabledFactor - Whether the factor is enabled\n * @param props.onDeleteFactor - Callback to delete a factor\n * @param props.isDeletingFactor - Whether a factor deletion is in progress\n * @param props.disableDelete - Whether delete action is disabled\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function FactorsList({\n  factors,\n  factorType,\n  readOnly,\n  isEnabledFactor,\n  onDeleteFactor,\n  isDeletingFactor,\n  disableDelete,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: FactorsListProps) {\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const IconComponent = FACTOR_ICONS[factorType as keyof typeof FACTOR_ICONS];\n\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  return (\n    <div className=\"space-y-2 mt-2\" style={currentStyles?.variables}>\n      {factors.map((factor) => (\n        <Card\n          key={factor.id}\n          className=\"border border-[color:var(--color-border)] rounded-lg shadow-none bg-transparent p-0 w-full\"\n          aria-label={t(`${factorType}.title`)}\n        >\n          <CardContent className=\"flex flex-row items-center justify-between gap-3 p-3\">\n            <div className=\"flex items-center gap-3 min-w-0 flex-grow\">\n              {IconComponent && (\n                <IconComponent\n                  className=\"w-5 h-5 text-muted-foreground shrink-0\"\n                  aria-hidden=\"true\"\n                />\n              )}\n              <span\n                className={cn(\n                  'font-medium text-base text-(length:--font-size-body) text-foreground truncate',\n                )}\n                title={factor.name || factor.id}\n              >\n                {factor.name || factor.id}\n              </span>\n            </div>\n            {!readOnly && (\n              <div className=\"shrink-0\">\n                <Popover>\n                  <PopoverTrigger asChild>\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      aria-label={t('actions')}\n                      className=\"p-2\"\n                      tabIndex={0}\n                    >\n                      <MoreVertical className=\"w-5 h-5\" aria-hidden=\"true\" />\n                    </Button>\n                  </PopoverTrigger>\n                  <PopoverContent className=\"w-30 p-2\" role=\"menu\">\n                    <Button\n                      size=\"sm\"\n                      variant=\"ghost\"\n                      className=\"flex items-center justify-center px-4 py-2 gap-2 text-red-600 font-normal text-sm w-full\"\n                      onClick={() => onDeleteFactor(factor.id, factorType)}\n                      disabled={disableDelete || isDeletingFactor || !isEnabledFactor}\n                      aria-label={t('remove')}\n                      role=\"menuitem\"\n                    >\n                      <Trash2 className=\"w-4 h-4 color-red-10\" aria-hidden=\"true\" />\n                      <span className=\"color-red-10\">{t('remove')}</span>\n                    </Button>\n                  </PopoverContent>\n                </Popover>\n              </div>\n            )}\n          </CardContent>\n        </Card>\n      ))}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/factors-list.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/otp-verification-form.tsx",
      "content": "/**\n * OTP verification input form.\n * @module otp-verification-form\n * @internal\n */\n\nimport {\n  type MFAType,\n  FACTOR_TYPE_EMAIL,\n  FACTOR_TYPE_TOTP,\n  FACTOR_TYPE_PUSH_NOTIFICATION,\n  getComponentStyles,\n} from '@auth0/universal-components-core';\nimport * as React from 'react';\nimport { useForm } from 'react-hook-form';\n\nimport { Button } from '@/components/ui/button';\nimport {\n  Form,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormMessage,\n} from '@/components/ui/form';\nimport { OTPField } from '@/components/ui/otp-field';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { FORM_VALIDATION_MODE } from '@/lib/constants/form-constants';\nimport type { OTPVerificationFormProps } from '@/types/my-account/mfa/mfa-types';\n\ntype OtpForm = {\n  userOtp: string;\n};\n\nconst maskContact = (contact: string, factorType: MFAType): string => {\n  if (!contact) return '';\n\n  if (factorType === FACTOR_TYPE_EMAIL) {\n    const [local, domain] = contact.split('@');\n    if (!domain || !local || local.length <= 2) return contact;\n    return `${local.slice(0, 2)}${'*'.repeat(local.length - 2)}@${domain}`;\n  }\n\n  return contact.length > 6\n    ? `${contact.slice(0, 3)}${'*'.repeat(contact.length - 6)}${contact.slice(-3)}`\n    : contact;\n};\n\n/**\n * OTP verification form for MFA enrollment confirmation.\n * @param props - Component props.\n * @param props.factorType - The MFA factor type\n * @param props.contact - Contact information (email/phone)\n * @param props.isConfirming - Whether confirmation is in progress\n * @param props.onConfirmOtp - Called with the 6-digit OTP code on submit\n * @param props.onBack - Callback fired when back navigation is triggered\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function OTPVerificationForm({\n  factorType,\n  contact,\n  isConfirming,\n  onConfirmOtp,\n  onBack,\n  styling = {\n    variables: { common: {}, light: {}, dark: {} },\n    classes: {},\n  },\n  customMessages = {},\n}: OTPVerificationFormProps) {\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  const form = useForm<OtpForm>({ mode: FORM_VALIDATION_MODE });\n  const userOtp = form.watch('userOtp');\n\n  const otpInputRef = React.useRef<HTMLInputElement>(null);\n\n  React.useEffect(() => {\n    otpInputRef.current?.focus();\n  }, []);\n\n  const maskedContact = contact ? maskContact(contact, factorType) : '';\n\n  return (\n    <div style={currentStyles.variables} className=\"w-full max-w-sm mx-auto text-center\">\n      <Form {...form}>\n        <form\n          onSubmit={form.handleSubmit((data) => onConfirmOtp(data.userOtp))}\n          autoComplete=\"off\"\n          className=\"space-y-6\"\n          aria-describedby=\"otp-description\"\n        >\n          <p\n            id=\"otp-description\"\n            className=\"text-sm text-primary font-normal text-center text-(length:--font-size-paragraph)\"\n          >\n            {[FACTOR_TYPE_PUSH_NOTIFICATION, FACTOR_TYPE_TOTP].includes(factorType)\n              ? t('enrollment_form.show_otp.enter_opt_code')\n              : t('enrollment_form.show_otp.enter_verify_code', { verifier: maskedContact })}\n          </p>\n\n          <FormField\n            control={form.control}\n            name=\"userOtp\"\n            render={({ field }) => (\n              <FormItem>\n                <FormLabel\n                  className=\"text-sm font-medium text-(length:--font-size-label)\"\n                  htmlFor=\"otp-input\"\n                >\n                  {t('enrollment_form.show_otp.one_time_passcode')}\n                </FormLabel>\n                <FormControl>\n                  <OTPField\n                    id=\"otp-input\"\n                    length={6}\n                    separator={{ character: '-', afterEvery: 3 }}\n                    onChange={field.onChange}\n                    inputRef={otpInputRef}\n                    aria-invalid={!!form.formState.errors.userOtp}\n                    value={field.value || ''}\n                  />\n                </FormControl>\n                <FormMessage\n                  className=\"text-sm text-left text-(length:--font-size-paragraph)\"\n                  id=\"otp-error\"\n                  role=\"alert\"\n                />\n              </FormItem>\n            )}\n          />\n\n          <div className=\"flex flex-row justify-end gap-3 mt-6 mb-6\">\n            <Button\n              type=\"button\"\n              className=\"text-sm\"\n              variant=\"outline\"\n              size=\"default\"\n              onClick={onBack}\n              aria-label={t('back')}\n            >\n              {t('back')}\n            </Button>\n\n            <Button\n              type=\"submit\"\n              className=\"text-sm\"\n              size=\"default\"\n              disabled={userOtp?.length !== 6 || isConfirming}\n              aria-label={isConfirming ? t('enrollment_form.show_otp.verifying') : t('submit')}\n            >\n              {isConfirming ? t('enrollment_form.show_otp.verifying') : t('submit')}\n            </Button>\n          </div>\n        </form>\n      </Form>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/otp-verification-form.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/qr-code-enrollment-form.tsx",
      "content": "/**\n * QR code MFA enrollment form.\n * @module qr-code-enrollment-form\n * @internal\n */\n\nimport {\n  getComponentStyles,\n  FACTOR_TYPE_TOTP,\n  FACTOR_TYPE_PUSH_NOTIFICATION,\n} from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { OTPVerificationForm } from '@/components/auth0/my-account/shared/mfa/otp-verification-form';\nimport { CopyableTextField } from '@/components/auth0/shared/copyable-text-field';\nimport { Button } from '@/components/ui/button';\nimport { QRCodeDisplayer } from '@/components/ui/qr-code';\nimport { Spinner } from '@/components/ui/spinner';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { QR_PHASE_ENTER_OTP, QR_PHASE_SCAN } from '@/lib/constants/my-account/mfa/mfa-constants';\nimport type { QRCodeEnrollmentFormProps } from '@/types/my-account/mfa/mfa-types';\n\ntype Phase = typeof QR_PHASE_SCAN | typeof QR_PHASE_ENTER_OTP;\n\n/**\n *\n * @param props - Component props.\n * @param props.factorType - The MFA factor type\n * @param props.barcodeUri - QR code URI to display\n * @param props.manualInputCode - Manual input code fallback\n * @param props.isEnrolling - Whether enrollment data is loading\n * @param props.isConfirming - Whether OTP confirmation is in progress\n * @param props.onContinueQR - Called when continuing past QR scan (push notification confirm)\n * @param props.onConfirmOtp - Called with the 6-digit OTP code (TOTP)\n * @param props.onClose - Callback fired when the component should close\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function QRCodeEnrollmentForm({\n  factorType,\n  barcodeUri,\n  manualInputCode,\n  isEnrolling,\n  isConfirming,\n  onContinueQR,\n  onConfirmOtp,\n  onClose,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: QRCodeEnrollmentFormProps) {\n  const [phase, setPhase] = React.useState<Phase>(QR_PHASE_SCAN);\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  const handleContinue = React.useCallback(async () => {\n    if (factorType === FACTOR_TYPE_PUSH_NOTIFICATION) {\n      await onContinueQR();\n    } else {\n      setPhase(QR_PHASE_ENTER_OTP);\n    }\n  }, [factorType, onContinueQR]);\n\n  const handleBack = React.useCallback(() => {\n    setPhase(QR_PHASE_SCAN);\n  }, []);\n\n  const renderQrScreen = () => (\n    <div style={currentStyles.variables} className=\"w-full\">\n      {isEnrolling ? (\n        <div\n          className=\"absolute inset-0 flex items-center justify-center\"\n          role=\"status\"\n          aria-live=\"polite\"\n        >\n          <Spinner aria-label={t('loading')} />\n        </div>\n      ) : (\n        <div className=\"w-full max-w-sm mx-auto text-center\">\n          <div className=\"mb-6\">\n            <div className=\"flex justify-center items-center mb-6\">\n              <QRCodeDisplayer\n                size={150}\n                value={barcodeUri}\n                alt={t('enrollment_form.show_otp.qr_code_description')}\n              />\n            </div>\n            <p\n              id=\"qr-description\"\n              className=\"font-normal block text-sm text-center text-(length:--font-size-paragraph) text-primary\"\n            >\n              {factorType === FACTOR_TYPE_TOTP\n                ? t('enrollment_form.show_otp.title')\n                : t('enrollment_form.show_auth0_guardian_title')}\n            </p>\n          </div>\n\n          <div aria-describedby=\"qr-description\">\n            <CopyableTextField value={manualInputCode || barcodeUri} />\n\n            <div className=\"flex flex-row justify-end gap-3 mt-6 mb-6\">\n              <Button\n                type=\"button\"\n                className=\"text-sm\"\n                variant=\"outline\"\n                size=\"default\"\n                onClick={onClose}\n                aria-label={t('cancel')}\n              >\n                {t('cancel')}\n              </Button>\n              <Button\n                type=\"button\"\n                className=\"text-sm\"\n                size=\"default\"\n                onClick={handleContinue}\n                disabled={isConfirming}\n                aria-label={t('continue')}\n              >\n                {t('continue')}\n              </Button>\n            </div>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n\n  const renderOtpScreen = () => (\n    <OTPVerificationForm\n      factorType={factorType}\n      isConfirming={isConfirming}\n      onConfirmOtp={onConfirmOtp}\n      onBack={handleBack}\n      styling={styling}\n      customMessages={customMessages}\n    />\n  );\n\n  return phase === QR_PHASE_SCAN ? renderQrScreen() : renderOtpScreen();\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/qr-code-enrollment-form.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/show-recovery-code.tsx",
      "content": "/**\n * Recovery code display component.\n * @module show-recovery-code\n * @internal\n */\n\nimport { getComponentStyles } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { CopyableTextField } from '@/components/auth0/shared/copyable-text-field';\nimport { Button } from '@/components/ui/button';\nimport { Spinner } from '@/components/ui/spinner';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport type { ShowRecoveryCodeProps } from '@/types/my-account/mfa/mfa-types';\n\n/**\n *\n * @param props - Component props.\n * @param props.recoveryCode - Recovery code to display\n * @param props.isEnrolling - Whether enrollment (code fetch) is in progress\n * @param props.isConfirming - Whether confirmation is in progress\n * @param props.onConfirmRecoveryCode - Called when the user confirms they've saved the code\n * @param props.onClose - Callback fired when the component should close\n * @param props.styling - Custom styling configuration with variables and classes\n * @param props.customMessages - Custom translation messages to override defaults\n * @returns JSX element\n */\nexport function ShowRecoveryCode({\n  recoveryCode,\n  isEnrolling,\n  isConfirming,\n  onConfirmRecoveryCode,\n  onClose,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: ShowRecoveryCodeProps) {\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  return (\n    <div style={currentStyles.variables} className=\"w-full max-w-sm mx-auto text-center\">\n      {isEnrolling || isConfirming ? (\n        <div className=\"flex items-center justify-center py-16\">\n          <Spinner />\n        </div>\n      ) : (\n        <div className=\"space-y-6\">\n          <div>\n            <p className=\"font-normal block text-sm text-center mb-4 text-primary\">\n              {t('enrollment_form.recovery_code_description')}\n            </p>\n            <CopyableTextField value={recoveryCode} />\n          </div>\n\n          <div className=\"flex flex-row justify-end gap-3 mt-6 mb-6\">\n            <Button\n              type=\"button\"\n              className=\"text-sm\"\n              variant=\"outline\"\n              size=\"default\"\n              onClick={onClose}\n              aria-label={t('back')}\n            >\n              {t('back')}\n            </Button>\n\n            <Button\n              type=\"button\"\n              className=\"text-sm\"\n              size=\"default\"\n              onClick={onConfirmRecoveryCode}\n              aria-label={t('submit')}\n            >\n              {t('submit')}\n            </Button>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/show-recovery-code.tsx"
    },
    {
      "path": "src/components/auth0/my-account/shared/mfa/user-mfa-setup-form.tsx",
      "content": "/**\n * MFA setup form with factor selection.\n * @module user-mfa-setup-form\n * @internal\n */\n\nimport { getComponentStyles } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport AppleLogo from '@/assets/icons/apple-logo';\nimport GoogleLogo from '@/assets/icons/google-logo';\nimport { ContactInputForm } from '@/components/auth0/my-account/shared/mfa/contact-input-form';\nimport { QRCodeEnrollmentForm } from '@/components/auth0/my-account/shared/mfa/qr-code-enrollment-form';\nimport { ShowRecoveryCode } from '@/components/auth0/my-account/shared/mfa/show-recovery-code';\nimport { Button } from '@/components/ui/button';\nimport { Card } from '@/components/ui/card';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';\nimport { Separator } from '@/components/ui/separator';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport {\n  ENTER_QR,\n  ENTER_CONTACT,\n  QR_PHASE_INSTALLATION,\n  SHOW_RECOVERY_CODE,\n} from '@/lib/constants/my-account/mfa/mfa-constants';\nimport { cn } from '@/lib/utils';\nimport type { UserMFASetupFormProps } from '@/types/my-account/mfa/mfa-types';\n\n/**\n *\n * @param props - Component props.\n * @param props.open - Whether the dialog is open\n * @param props.onClose - Callback fired when the dialog should close\n * @param props.factorType - The MFA factor type being enrolled\n * @param props.enrollmentPhase - Current enrollment phase from useUserMFA\n * @param props.contact - Current enrolled contact (email/phone) from hook state\n * @param props.otpData - QR code data from hook state\n * @param props.recoveryCode - Recovery code from hook state\n * @param props.isEnrolling - Whether enrollment mutation is pending\n * @param props.isConfirming - Whether confirmation mutation is pending\n * @param props.onSubmitContact - Called with contact options on submit\n * @param props.onConfirmOtp - Called with OTP code on verification\n * @param props.onContinueQR - Called when continuing past QR scan (push notification)\n * @param props.onConfirmRecoveryCode - Called when confirming recovery code\n * @param props.onAdvanceToQR - Called to move from installation to QR scan phase\n * @param props.styling - Custom styling configuration\n * @param props.customMessages - Custom translation messages\n * @returns JSX element\n */\nexport function UserMFASetupForm({\n  open,\n  onClose,\n  factorType,\n  enrollmentPhase,\n  contact,\n  otpData,\n  recoveryCode,\n  isEnrolling,\n  isConfirming,\n  onSubmitContact,\n  onConfirmOtp,\n  onContinueQR,\n  onConfirmRecoveryCode,\n  onAdvanceToQR,\n  schema,\n  styling = {\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n    classes: {},\n  },\n  customMessages = {},\n}: UserMFASetupFormProps) {\n  const { t } = useTranslator('mfa', customMessages);\n  const { isDarkMode } = useTheme();\n  const currentStyles = React.useMemo(\n    () => getComponentStyles(styling, isDarkMode),\n    [styling, isDarkMode],\n  );\n\n  const renderInstallationPhase = () => (\n    <div style={currentStyles.variables} className=\"w-full max-w-sm mx-auto\">\n      <div className=\"flex flex-col items-center justify-center flex-1 space-y-10\">\n        <p className=\"text-center text-primary text-sm text-(length:--font-size-paragraph) font-normal\">\n          {t('enrollment_form.show_otp.install_guardian_description')}\n        </p>\n        <div className=\"flex gap-4 w-full\">\n          <a\n            href=\"https://apps.apple.com/us/app/auth0-guardian/id1093447833\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            className=\"flex-1\"\n          >\n            <Card className=\"flex flex-col items-center gap-1 min-w-24 p-6 h-full\">\n              <AppleLogo className=\"w-8 h-8\" />\n              <span className=\"text-sm text-(length:--font-size-paragraph) text-center\">\n                {t('app-store')}\n              </span>\n            </Card>\n          </a>\n          <a\n            href=\"https://play.google.com/store/apps/details?id=com.auth0.guardian\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            className=\"flex-1\"\n          >\n            <Card className=\"flex flex-col items-center gap-1 min-w-24 p-6 h-full\">\n              <GoogleLogo className=\"w-8 h-8\" />\n              <span className=\"text-sm text-(length:--font-size-paragraph) text-center\">\n                {t('google-play')}\n              </span>\n            </Card>\n          </a>\n        </div>\n        <div className=\"flex flex-row justify-end gap-3 w-full mt-6 mb-6\">\n          <Button\n            type=\"button\"\n            className=\"text-sm\"\n            variant=\"outline\"\n            size=\"default\"\n            onClick={onClose}\n          >\n            {t('cancel')}\n          </Button>\n          <Button type=\"button\" className=\"text-sm\" size=\"default\" onClick={onAdvanceToQR}>\n            {t('continue')}\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n\n  const renderForm = () => {\n    switch (enrollmentPhase) {\n      case QR_PHASE_INSTALLATION:\n        return renderInstallationPhase();\n      case ENTER_CONTACT:\n        return (\n          <ContactInputForm\n            factorType={factorType}\n            contact={contact}\n            isEnrolling={isEnrolling}\n            isConfirming={isConfirming}\n            onSubmitContact={onSubmitContact}\n            onConfirmOtp={onConfirmOtp}\n            onClose={onClose}\n            schema={schema}\n            styling={styling}\n            customMessages={customMessages}\n          />\n        );\n      case ENTER_QR:\n        return (\n          <QRCodeEnrollmentForm\n            factorType={factorType}\n            barcodeUri={otpData.barcodeUri}\n            manualInputCode={otpData.manualInputCode}\n            isEnrolling={isEnrolling}\n            isConfirming={isConfirming}\n            onContinueQR={onContinueQR}\n            onConfirmOtp={onConfirmOtp}\n            onClose={onClose}\n            styling={styling}\n            customMessages={customMessages}\n          />\n        );\n      case SHOW_RECOVERY_CODE:\n        return (\n          <ShowRecoveryCode\n            recoveryCode={recoveryCode}\n            isEnrolling={isEnrolling}\n            isConfirming={isConfirming}\n            onConfirmRecoveryCode={onConfirmRecoveryCode}\n            onClose={onClose}\n            styling={styling}\n            customMessages={customMessages}\n          />\n        );\n      default:\n        return null;\n    }\n  };\n\n  return (\n    <Dialog open={open && Boolean(enrollmentPhase)} onOpenChange={onClose}>\n      <DialogContent\n        style={currentStyles.variables}\n        aria-describedby=\"mfa-setup-form\"\n        className={cn(\n          'w-[600px] max-h-[90vh]',\n          currentStyles.classes?.['UserMFASetupForm-dialogContent'],\n        )}\n      >\n        <DialogHeader>\n          <DialogTitle className=\"text-left font-medium text-xl text-(length:--font-size-title)\">\n            {t('enrollment_form.enroll_title')}\n          </DialogTitle>\n          <Separator className=\"my-2\" />\n        </DialogHeader>\n        {renderForm()}\n      </DialogContent>\n    </Dialog>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/auth0/my-account/shared/mfa/user-mfa-setup-form.tsx"
    },
    {
      "path": "src/components/auth0/shared/copyable-text-field.tsx",
      "content": "/**\n * Text field with copy-to-clipboard button.\n * @module copyable-text-field\n * @internal\n */\n\nimport { Copy } from 'lucide-react';\nimport * as React from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { TextField, type TextFieldProps } from '@/components/ui/text-field';\nimport { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { cn } from '@/lib/utils';\n\nexport interface CopyableTextFieldProps extends TextFieldProps {\n  onCopy?: () => void;\n  copyButtonClassName?: string;\n  tooltipSide?: 'top' | 'bottom' | 'left' | 'right';\n  tooltipAlign?: 'start' | 'center' | 'end';\n  showCopyButton?: boolean;\n}\n\nconst CopyableTextField = React.forwardRef<HTMLInputElement, CopyableTextFieldProps>(\n  (\n    {\n      onCopy,\n      copyButtonClassName,\n      tooltipSide = 'top',\n      tooltipAlign = 'end',\n      readOnly = true,\n      endAdornment,\n      showCopyButton = true,\n      ...props\n    },\n    ref,\n  ) => {\n    const { t } = useTranslator('common');\n    const [tooltipText, setTooltipText] = React.useState(t('copy'));\n    const [tooltipOpen, setTooltipOpen] = React.useState(false);\n\n    const handleCopy = async () => {\n      if (props.value) {\n        await navigator.clipboard.writeText(String(props.value));\n        setTooltipText(t('copied'));\n        setTooltipOpen(true);\n        setTimeout(() => {\n          setTooltipText(t('copy'));\n          setTooltipOpen(false);\n        }, 1000);\n        onCopy?.();\n      }\n    };\n\n    const copyButton = (\n      <Tooltip open={tooltipOpen} onOpenChange={setTooltipOpen}>\n        <TooltipTrigger asChild>\n          <Button\n            type=\"button\"\n            variant=\"ghost\"\n            size=\"icon\"\n            className={cn('h-8 w-8', copyButtonClassName)}\n            onClick={handleCopy}\n            aria-label={t('copy')}\n          >\n            <Copy className=\"h-4 w-4\" aria-hidden=\"true\" />\n          </Button>\n        </TooltipTrigger>\n        <TooltipContent side={tooltipSide} align={tooltipAlign} sideOffset={5} className=\"z-[1000]\">\n          {tooltipText}\n        </TooltipContent>\n      </Tooltip>\n    );\n\n    return (\n      <TextField\n        ref={ref}\n        readOnly={readOnly}\n        {...props}\n        endAdornment={\n          showCopyButton ? (\n            endAdornment ? (\n              <div className=\"flex items-center gap-1\">\n                {endAdornment}\n                {copyButton}\n              </div>\n            ) : (\n              copyButton\n            )\n          ) : (\n            endAdornment\n          )\n        }\n      />\n    );\n  },\n);\n\nCopyableTextField.displayName = 'CopyableTextField';\n\nexport { CopyableTextField };\n",
      "type": "registry:component",
      "target": "components/auth0/shared/copyable-text-field.tsx"
    },
    {
      "path": "src/components/auth0/shared/gate-keeper/gate-keeper.tsx",
      "content": "/**\n * GateKeeper component for guarding content during loading, MFA step-up, and 5xx error states.\n * @module gate-keeper\n * @internal\n */\n\nimport {\n  type ComponentStyling,\n  getComponentStyles,\n  getStatusCode,\n  isMfaRequiredError,\n} from '@auth0/universal-components-core';\nimport { RefreshCcw } from 'lucide-react';\nimport React, { useCallback, useMemo, useState, useEffect } from 'react';\n\nimport { StyledScope } from '@/components/auth0/shared/styled-scope';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent, CardDescription, CardFooter, CardTitle } from '@/components/ui/card';\nimport { Spinner } from '@/components/ui/spinner';\nimport { useCoreClient } from '@/hooks/shared/use-core-client';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport { useGateKeeperContext } from '@/providers/gate-keeper-context';\n\ninterface GateKeeperProps {\n  styling?: ComponentStyling<Record<string, string>>;\n  isLoading?: boolean;\n  children: React.ReactNode;\n}\n\n/**\n * Blocking error fallback with retry button.\n * Shown for 5xx errors and dismissed MFA errors.\n *\n * @param props - Component props.\n * @param props.onRetry - Retry handler.\n * @returns Error fallback element.\n * @internal\n */\nfunction ErrorFallback({ onRetry, isMfa }: { onRetry: () => void; isMfa?: boolean }) {\n  const { t } = useTranslator('gate_keeper');\n  const key = isMfa ? 'mfa_error' : 'fallback';\n\n  return (\n    <Card className=\"text-center\">\n      <CardContent className=\"flex flex-col items-center gap-2\">\n        <CardTitle>{t(`${key}.title`)}</CardTitle>\n        <CardDescription>{t(`${key}.description`)}</CardDescription>\n      </CardContent>\n      {!isMfa && (\n        <CardFooter className=\"justify-center\">\n          <Button variant=\"primary\" size=\"default\" onClick={onRetry}>\n            <RefreshCcw className=\"size-4\" />\n            {t('fallback.retry')}\n          </Button>\n        </CardFooter>\n      )}\n    </Card>\n  );\n}\n\n/**\n * Guards children from rendering during loading/error states. MFA step-up overlays\n * children without unmounting them, preserving any in-progress form state.\n * - Loading → spinner (blocks children)\n * - MFA required error → MFA step-up dialog overlaid on children\n * - 5xx error or dismissed MFA → blocking error fallback with retry\n * - No error → children\n *\n * @param props - Component props.\n * @param props.styling - Styling configuration forwarded to the styled scope.\n * @param props.isLoading - Whether content is loading.\n * @param props.children - Child elements to render on success.\n * @returns GateKeeper element.\n */\nexport function GateKeeper({ styling, isLoading, children }: GateKeeperProps) {\n  const { error, onRetry } = useGateKeeperContext();\n  const { coreClient } = useCoreClient();\n  const { isDarkMode } = useTheme();\n  const [isRetrying, setIsRetrying] = useState(false);\n\n  const styles = useMemo(() => getComponentStyles(styling, isDarkMode), [styling, isDarkMode]);\n\n  const handleRetry = useCallback(async () => {\n    setIsRetrying(true);\n    try {\n      await onRetry?.();\n    } finally {\n      setIsRetrying(false);\n    }\n  }, [onRetry]);\n\n  const isMfaStepUp = isMfaRequiredError(error);\n  const statusCode = getStatusCode(error);\n  const isSystemError = !!error && !!statusCode && statusCode >= 500;\n\n  useEffect(() => {\n    if (isMfaStepUp && coreClient && !coreClient.isProxyMode()) {\n      console.warn(\n        `🚨 [Auth0 Components Warning]: A step-up authentication (MFA) was triggered, but the interactiveErrorHandler is not configured.\\n\\nTo enable Universal Login redirects for MFA step-up, login required, or consent errors, please update your configuration:\\n\\n<Auth0Provider\\n  ...\\n  interactiveErrorHandler=\"popup\"\\n>\\n\\nFor more details, refer to the Auth0 Documentation.`,\n      );\n    }\n  }, [isMfaStepUp, coreClient]);\n\n  if (isLoading || isRetrying) {\n    return (\n      <StyledScope style={styles.variables}>\n        <div className=\"flex items-center justify-center p-8\">\n          <Spinner />\n        </div>\n      </StyledScope>\n    );\n  }\n\n  if (isSystemError || isMfaStepUp) {\n    return (\n      <StyledScope style={styles.variables}>\n        <ErrorFallback onRetry={handleRetry} isMfa={isMfaStepUp} />\n      </StyledScope>\n    );\n  }\n\n  return <StyledScope style={styles.variables}>{children}</StyledScope>;\n}\n",
      "type": "registry:component",
      "target": "components/auth0/shared/gate-keeper/gate-keeper.tsx"
    },
    {
      "path": "src/components/auth0/shared/sonner.tsx",
      "content": "/**\n * Sonner toast provider wrapper.\n * @module sonner\n * @internal\n */\n\n'use client';\n\nimport type { ToasterProps } from 'sonner';\nimport { Toaster as Sonner } from 'sonner';\n\nimport { useTheme } from '@/hooks/shared/use-theme';\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n  const { isDarkMode } = useTheme();\n  const theme = isDarkMode ? 'dark' : 'light';\n\n  return (\n    <Sonner\n      theme={theme as ToasterProps['theme']}\n      className=\"toaster group\"\n      toastOptions={{\n        style: {\n          width: 'fit-content',\n          maxWidth: '22.25rem',\n        },\n      }}\n      {...props}\n    />\n  );\n};\n\nexport { Toaster };\n",
      "type": "registry:component",
      "target": "components/auth0/shared/sonner.tsx"
    },
    {
      "path": "src/components/auth0/shared/styled-scope.tsx",
      "content": "/**\n * Auth0Scope component — CSS scope root and portal container for lib components.\n * @module auth0-scope\n * @internal\n */\n\n'use client';\n\nimport { getCoreStyles } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { ThemeContext } from '@/providers/theme-provider';\n\nexport interface StyledScopeProps {\n  children: React.ReactNode;\n  style?: React.CSSProperties;\n}\n\n/**\n * CSS scope root for lib components. Handles dark-mode class and theme attribute.\n *\n * @param props - Component props.\n * @param props.children - Content to render inside the scope root.\n * @param props.style - Optional inline CSS styles\n * @returns A scoped wrapper div with dark-mode and theme attributes applied.\n * @internal\n */\nexport const StyledScope: React.FC<StyledScopeProps> = ({ children, style }) => {\n  const { theme = 'default', isDarkMode, variables } = React.useContext(ThemeContext);\n\n  const mergedStyle = React.useMemo(() => {\n    const providerVars = getCoreStyles(variables, isDarkMode).variables;\n    return { ...providerVars, ...style };\n  }, [variables, isDarkMode, style]);\n\n  return (\n    <div\n      className={cn('auth0-universal', isDarkMode && 'dark')}\n      data-theme={theme}\n      style={mergedStyle}\n    >\n      {children}\n    </div>\n  );\n};\n",
      "type": "registry:component",
      "target": "components/auth0/shared/styled-scope.tsx"
    },
    {
      "path": "src/components/auth0/shared/toast.tsx",
      "content": "/**\n * Toast notification utilities.\n * @module toast\n * @internal\n */\n\nimport { Flag } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { toast, type ExternalToast } from 'sonner';\n\nimport { DEFAULT_TOAST_SETTINGS } from '@/types/toast-types';\nimport type { ToastOptions, ToastSettings, ToastType } from '@/types/toast-types';\n\nconst TOAST_COLOR_CLASSES: Record<ToastType, string> = {\n  success: 'text-success-foreground',\n  error: 'text-destructive-foreground',\n  warning: 'text-warning-foreground',\n  info: 'text-info-foreground',\n} as const;\n\nconst VALID_TOAST_TYPES: ToastType[] = ['success', 'error', 'warning', 'info'] as const;\n\nconst BASE_TOAST_Z_INDEX = 1000;\nlet toastZIndexCounter = 0;\nconst MAX_Z_INDEX_COUNTER = 1000;\nconst activeToastIds = new Set<string | number | unknown>();\n\n/**\n * Resets the z-index counter if no active toasts remain\n */\nconst resetCounterIfEmpty = (): void => {\n  if (activeToastIds.size === 0) {\n    toastZIndexCounter = 0;\n  }\n};\n\n/**\n * Removes a toast from tracking and resets counter if needed\n * @param toastId - The toast ID to remove, or undefined to clear all\n */\nconst removeToastFromTracking = (toastId?: string | number | unknown): void => {\n  if (toastId !== undefined && toastId !== null) {\n    activeToastIds.delete(toastId);\n  } else {\n    activeToastIds.clear();\n  }\n  resetCounterIfEmpty();\n};\n\nlet globalToastSettings: ToastSettings = {\n  ...DEFAULT_TOAST_SETTINGS,\n};\n\n/**\n * Sets global toast configuration. Called by Auth0ComponentProvider.\n * @param settings - Settings configuration\n * @internal\n */\nexport const setGlobalToastSettings = (settings?: ToastSettings): void => {\n  if (!settings) {\n    globalToastSettings = {\n      ...DEFAULT_TOAST_SETTINGS,\n    };\n    return;\n  }\n\n  globalToastSettings = {\n    ...settings,\n  };\n\n  if (settings.provider === 'custom') {\n    const { methods } = settings;\n    const availableMethods = Object.keys(methods);\n\n    if (availableMethods.length === 0) {\n      console.warn(\n        'Auth0ComponentProvider: Custom toast provider specified but no custom methods provided',\n      );\n    }\n\n    availableMethods.forEach((method) => {\n      if (typeof methods[method as keyof typeof methods] !== 'function') {\n        console.warn(`Auth0ComponentProvider: Custom toast method '${method}' is not a function`);\n      }\n    });\n  }\n};\n\n/**\n * Gets the current global toast configuration.\n * @returns The current toast settings\n */\nexport const getGlobalToastSettings = (): ToastSettings => globalToastSettings;\n\n/**\n * Creates a styled message element with appropriate color classes.\n * @param type - The toast type for styling\n * @param message - The message text to style\n * @returns A React element with styled text\n */\nconst createStyledMessage = (type: ToastType, message: string): ReactNode => {\n  const colorClass = TOAST_COLOR_CLASSES[type];\n  return <span className={colorClass}>{message}</span>;\n};\n\n/**\n * Creates a default icon for the toast based on its type.\n * @param type - The toast type to create an icon for\n * @returns A React element with a styled Flag icon\n */\nconst createDefaultIcon = (type: ToastType): ReactNode => {\n  const colorClass = TOAST_COLOR_CLASSES[type];\n  return <Flag className={`h-4 w-4 ${colorClass}`} aria-hidden=\"true\" />;\n};\n\n/**\n * Shows a toast notification using the configured provider.\n *\n * @param options - The toast configuration options\n * @param options.type - The type of toast ('success', 'error', 'info', 'warning', 'loading')\n * @param options.message - The message to display in the toast\n * @param options.className - Optional CSS class name for custom styling\n * @param options.icon - Optional custom icon to display\n * @param options.data - Additional options passed to the toast provider\n * @returns The toast instance ID or result from custom method\n */\nexport const showToast = ({\n  type,\n  message,\n  className,\n  icon,\n  data = {},\n}: ToastOptions): string | number | void => {\n  if (!message?.trim()) {\n    console.warn('showToast: Empty message provided');\n    return;\n  }\n\n  if (!VALID_TOAST_TYPES.includes(type)) {\n    console.error(\n      `showToast: Invalid toast type '${type}'. Must be one of: ${VALID_TOAST_TYPES.join(', ')}`,\n    );\n    return;\n  }\n\n  if (globalToastSettings.provider === 'custom' && globalToastSettings.methods[type]) {\n    try {\n      // Custom methods only receive the message - they handle their own configuration\n      return globalToastSettings.methods[type]!(message);\n    } catch (error) {\n      console.error(`showToast: Error in custom ${type} method:`, error);\n    }\n  }\n\n  const styledMessage = createStyledMessage(type, message);\n  const defaultIcon = icon || createDefaultIcon(type);\n\n  const currentZIndex = BASE_TOAST_Z_INDEX + toastZIndexCounter;\n  toastZIndexCounter += 1;\n\n  if (toastZIndexCounter >= MAX_Z_INDEX_COUNTER) {\n    toastZIndexCounter = 0;\n  }\n\n  const toastOptions: ExternalToast = {\n    className,\n    icon: defaultIcon,\n    style: {\n      zIndex: currentZIndex,\n    },\n    onDismiss: (toastId) => {\n      removeToastFromTracking(toastId);\n    },\n    ...data,\n  };\n\n  try {\n    const toastId = toast[type](styledMessage, toastOptions);\n    if (toastId) {\n      activeToastIds.add(toastId);\n    }\n    return toastId;\n  } catch (error) {\n    console.error(`showToast: Error showing ${type} toast:`, error);\n    return toast(message);\n  }\n};\n\n/**\n * Dismisses a toast notification by ID, or dismisses all toasts if no ID is provided.\n *\n * @param toastId - Optional toast ID to dismiss. If not provided, dismisses all toasts.\n */\nexport const dismissToast = (toastId?: string | number): void => {\n  if (globalToastSettings.provider === 'custom' && globalToastSettings.methods.dismiss) {\n    try {\n      globalToastSettings.methods.dismiss(toastId?.toString());\n    } catch (error) {\n      console.error('dismissToast: Error in custom dismiss method:', error);\n    }\n    return;\n  }\n\n  toast.dismiss(toastId);\n\n  removeToastFromTracking(toastId);\n};\n",
      "type": "registry:component",
      "target": "components/auth0/shared/toast.tsx"
    },
    {
      "path": "src/components/ui/badge.tsx",
      "content": "/**\n * Badge component with variants.\n * @module badge\n * @internal\n */\n\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst badgeVariants = cva(\n  'theme-default:shadow-xs box-border inline-flex items-center overflow-clip rounded-2xl border border-transparent font-medium',\n  {\n    variants: {\n      variant: {\n        default: 'bg-primary text-primary-foreground theme-default:border-primary',\n        secondary: 'bg-muted text-muted-foreground theme-default:border-muted-foreground/25',\n        outline: 'border-border',\n        info: 'bg-info text-info-foreground theme-default:border-info-foreground/25',\n        success: 'bg-success theme-default:border-success-foreground/25 text-success-foreground',\n        warning: 'bg-warning theme-default:border-warning-foreground/25 text-warning-foreground',\n        destructive:\n          'bg-destructive theme-default:border-destructive-foreground/25 text-destructive-foreground',\n      },\n      size: {\n        sm: 'px-1.5 py-0.5 text-xs',\n        md: 'px-2 py-1 text-sm',\n        lg: 'px-2.5 py-1.5 text-sm',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'md',\n    },\n  },\n);\n\nfunction Badge({\n  className,\n  variant,\n  size,\n  asChild = false,\n  ...props\n}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot : 'span';\n\n  return (\n    <Comp\n      data-slot=\"badge\"\n      className={cn(badgeVariants({ variant, size }), className)}\n      {...props}\n    />\n  );\n}\n\nexport { Badge, badgeVariants };\n",
      "type": "registry:component",
      "target": "components/ui/badge.tsx"
    },
    {
      "path": "src/components/ui/button.tsx",
      "content": "/**\n * Button component with variants.\n * @module button\n * @internal\n */\n\n'use client';\n\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n  \"focus-visible:ring-ring aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive theme-default:active:scale-[0.99] relative box-border inline-flex shrink-0 items-center justify-center gap-2 overflow-hidden text-sm font-medium whitespace-nowrap transition-all duration-150 ease-in-out outline-none focus-visible:ring-4 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      variant: {\n        primary:\n          \"shadow-button-resting hover:shadow-button-hover hover:border-primary/50 border-primary bg-primary text-primary-foreground hover:bg-primary/90 theme-default:before:from-primary-foreground/0 theme-default:before:to-primary-foreground/15 theme-default:before:absolute theme-default:before:top-0 theme-default:before:left-0 theme-default:before:block theme-default:before:h-full theme-default:before:w-full theme-default:before:bg-gradient-to-t theme-default:before:content-[''] border\",\n        outline:\n          \"dark:bg-muted/50 hover:text-accent-foreground shadow-button-outlined-resting hover:shadow-button-outlined-hover hover:border-accent bg-background hover:bg-muted text-primary border-primary/35 theme-default:before:from-primary/5 theme-default:before:to-primary/0 theme-default:before:absolute theme-default:before:top-0 theme-default:before:left-0 theme-default:before:block theme-default:before:h-full theme-default:before:w-full theme-default:before:bg-gradient-to-t theme-default:before:content-[''] border\",\n        ghost: 'hover:bg-muted text-primary bg-transparent',\n        destructive:\n          \"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-button-destructive-resting hover:shadow-button-destructive-hover border-destructive-border/25 hover:border-destructive-border/50 theme-default:before:to-primary-foreground/50 theme-default:before:absolute theme-default:before:top-0 theme-default:before:left-0 theme-default:before:block theme-default:before:h-full theme-default:before:w-full theme-default:before:bg-gradient-to-t theme-default:before:content-[''] theme-default:border\",\n        link: 'text-foreground underline-offset-4 hover:underline',\n      },\n      size: {\n        default: 'h-10 rounded-2xl px-4 py-2.5 has-[>svg]:px-3',\n        xs: 'h-7 rounded-md px-2 py-1.5 text-xs has-[>svg]:px-2',\n        sm: 'h-8 gap-1.5 rounded-xl px-3 py-2 text-xs has-[>svg]:px-2.5',\n        lg: 'h-12 rounded-3xl px-6 py-3 text-base has-[>svg]:px-4',\n        icon: 'size-7 rounded-xl',\n      },\n    },\n    defaultVariants: {\n      variant: 'primary',\n      size: 'default',\n    },\n  },\n);\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof buttonVariants> {\n  as?: boolean;\n}\n\nfunction Button({\n  className,\n  variant,\n  size,\n  as,\n  ...props\n}: React.ComponentProps<'button'> & ButtonProps) {\n  const Comp = as ? Slot : 'button';\n\n  return <Comp className={cn(buttonVariants({ variant, size }), className)} {...props} />;\n}\n\nexport { Button, buttonVariants };\n",
      "type": "registry:component",
      "target": "components/ui/button.tsx"
    },
    {
      "path": "src/components/ui/card.tsx",
      "content": "/**\n * Card layout component.\n * @module card\n * @internal\n */\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nfunction Card({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card\"\n      className={cn(\n        'bg-card text-card-foreground shadow-bevel-2xl flex flex-col gap-6 rounded-4xl py-6',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card-header\"\n      className={cn(\n        '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card-title\"\n      className={cn('leading-none font-semibold', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card-description\"\n      className={cn('text-muted-foreground text-sm', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card-action\"\n      className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}\n      {...props}\n    />\n  );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>) {\n  return <div data-slot=\"card-content\" className={cn('px-6', className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"card-footer\"\n      className={cn('flex items-center px-6 [.border-t]:pt-6', className)}\n      {...props}\n    />\n  );\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };\n",
      "type": "registry:component",
      "target": "components/ui/card.tsx"
    },
    {
      "path": "src/components/ui/dialog.tsx",
      "content": "/**\n * Dialog component using Radix primitives.\n * @module dialog\n * @internal\n */\n\n'use client';\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { XIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/providers/portal-context';\n\nfunction Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {\n  return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n  const { children, asChild = false, ...elementProps } = props;\n\n  if (asChild && React.isValidElement(children)) {\n    return React.cloneElement(children, {\n      ...(typeof children.props === 'object' ? children.props : {}),\n      ...elementProps,\n    });\n  }\n\n  return (\n    <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" asChild {...props}>\n      <Button {...elementProps} data-slot=\"dialog-trigger\">\n        {children}\n      </Button>\n    </DialogPrimitive.Trigger>\n  );\n}\n\nfunction DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n  const portalContainer = usePortalContainer();\n  return (\n    <DialogPrimitive.Portal container={portalContainer} data-slot=\"dialog-portal\" {...props} />\n  );\n}\n\nfunction DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {\n  const { children } = props;\n\n  return (\n    <DialogPrimitive.Close data-slot=\"dialog-close\" asChild>\n      <Button variant=\"outline\" data-slot=\"dialog-close\">\n        {children}\n      </Button>\n    </DialogPrimitive.Close>\n  );\n}\n\nfunction DialogOverlay({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n  return (\n    <DialogPrimitive.Overlay\n      data-slot=\"dialog-overlay\"\n      className={cn(\n        'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 duration-200 ease-in-out',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction DialogContent({\n  className,\n  children,\n  showCloseButton = true,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n  showCloseButton?: boolean;\n}) {\n  return (\n    <DialogPortal data-slot=\"dialog-portal\">\n      <DialogOverlay />\n      <DialogPrimitive.Content\n        data-slot=\"dialog-content\"\n        className={cn(\n          'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 shadow-bevel-2xl rounded-5xl fixed top-[50%] left-[50%] z-[999] grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 p-6 duration-200 ease-in-out sm:max-w-lg',\n          className,\n        )}\n        {...props}\n      >\n        {children}\n        {showCloseButton && (\n          <DialogPrimitive.Close\n            asChild\n            data-slot=\"dialog-close\"\n            className=\"ring-offset-background absolute top-4 right-4\"\n          >\n            <Button variant=\"ghost\" size=\"icon\">\n              <XIcon />\n              <span className=\"sr-only\">Close</span>\n            </Button>\n          </DialogPrimitive.Close>\n        )}\n      </DialogPrimitive.Content>\n    </DialogPortal>\n  );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"dialog-header\"\n      className={cn('flex flex-col gap-2 text-center sm:text-left', className)}\n      {...props}\n    />\n  );\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot=\"dialog-footer\"\n      className={cn('flex flex-row gap-2 justify-end', className)}\n      {...props}\n    />\n  );\n}\n\nfunction DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n  return (\n    <DialogPrimitive.Title\n      data-slot=\"dialog-title\"\n      className={cn('text-lg text-primary leading-none font-semibold', className)}\n      {...props}\n    />\n  );\n}\n\nfunction DialogDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n  return (\n    <DialogPrimitive.Description\n      data-slot=\"dialog-description\"\n      className={cn('text-muted-foreground text-sm', className)}\n      {...props}\n    />\n  );\n}\n\nexport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogOverlay,\n  DialogPortal,\n  DialogTitle,\n  DialogTrigger,\n};\n",
      "type": "registry:component",
      "target": "components/ui/dialog.tsx"
    },
    {
      "path": "src/components/ui/form.tsx",
      "content": "/**\n * Form components with react-hook-form integration.\n * @module form\n * @internal\n */\n\n'use client';\n\nimport type * as LabelPrimitive from '@radix-ui/react-label';\nimport { Slot } from '@radix-ui/react-slot';\nimport * as React from 'react';\nimport {\n  Controller,\n  FormProvider,\n  useFormContext,\n  useFormState,\n  type ControllerProps,\n  type FieldPath,\n  type FieldValues,\n} from 'react-hook-form';\n\nimport { Label } from '@/components/ui/label';\nimport { cn } from '@/lib/utils';\n\nconst Form: typeof FormProvider = FormProvider;\n\ntype FormFieldContextValue<\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n  name: TName;\n};\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n  ...props\n}: ControllerProps<TFieldValues, TName>) => {\n  return (\n    <FormFieldContext.Provider value={{ name: props.name }}>\n      <Controller\n        {...props}\n        render={({ field, fieldState, formState }) => {\n          const { onChange, onBlur, ...rest } = field;\n          return props.render({\n            field: {\n              ...rest,\n              onChange: (...args: unknown[]) => {\n                onChange(...(args as Parameters<typeof onChange>));\n              },\n              onBlur: (...args: unknown[]) => {\n                onBlur(...(args as Parameters<typeof onBlur>));\n              },\n            },\n            fieldState,\n            formState,\n          });\n        }}\n      />\n    </FormFieldContext.Provider>\n  );\n};\n\nconst useFormField = () => {\n  const fieldContext = React.useContext(FormFieldContext);\n  const itemContext = React.useContext(FormItemContext);\n  const { getFieldState } = useFormContext();\n  const formState = useFormState({ name: fieldContext.name });\n  const fieldState = getFieldState(fieldContext.name, formState);\n\n  if (!fieldContext) {\n    throw new Error('useFormField should be used within <FormField>');\n  }\n\n  const { id } = itemContext;\n\n  return {\n    id,\n    name: fieldContext.name,\n    formItemId: `${id}-form-item`,\n    formDescriptionId: `${id}-form-item-description`,\n    formMessageId: `${id}-form-item-message`,\n    ...fieldState,\n  };\n};\n\ntype FormItemContextValue = {\n  id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\nfunction FormItem({ className, ...props }: React.ComponentProps<'div'>) {\n  const id = React.useId();\n\n  return (\n    <FormItemContext.Provider value={{ id }}>\n      <div data-slot=\"form-item\" className={cn('grid gap-2', className)} {...props} />\n    </FormItemContext.Provider>\n  );\n}\n\nfunction FormLabel({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {\n  const { error, formItemId } = useFormField();\n\n  return (\n    <Label\n      data-slot=\"form-label\"\n      data-error={!!error}\n      className={cn('data-[error=true]:text-destructive-foreground', className)}\n      htmlFor={formItemId}\n      {...props}\n    />\n  );\n}\n\nfunction FormControl({ ...props }: React.ComponentProps<typeof Slot>) {\n  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n  return (\n    <Slot\n      data-slot=\"form-control\"\n      id={formItemId}\n      aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n      aria-invalid={!!error}\n      {...props}\n    />\n  );\n}\n\nfunction FormDescription({ className, ...props }: React.ComponentProps<'p'>) {\n  const { formDescriptionId } = useFormField();\n\n  return (\n    <p\n      data-slot=\"form-description\"\n      id={formDescriptionId}\n      className={cn('text-muted-foreground text-sm', className)}\n      {...props}\n    />\n  );\n}\n\nfunction FormMessage({ className, ...props }: React.ComponentProps<'p'>) {\n  const { error, formMessageId } = useFormField();\n  const body = error ? String(error?.message ?? '') : props.children;\n\n  if (!body) {\n    return null;\n  }\n\n  return (\n    <p\n      data-slot=\"form-message\"\n      id={formMessageId}\n      className={cn('text-destructive-foreground text-sm', className)}\n      {...props}\n    >\n      {body}\n    </p>\n  );\n}\n\nexport {\n  useFormField,\n  Form,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormDescription,\n  FormMessage,\n  FormField,\n};\n",
      "type": "registry:component",
      "target": "components/ui/form.tsx"
    },
    {
      "path": "src/components/ui/label.tsx",
      "content": "/**\n * Form label component.\n * @module label\n * @internal\n */\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport function Label({ children, className, ...props }: React.ComponentPropsWithoutRef<'label'>) {\n  return (\n    <label\n      className={cn(\n        'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </label>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/ui/label.tsx"
    },
    {
      "path": "src/components/ui/list.tsx",
      "content": "/**\n * List component with variants.\n * @module list\n * @internal\n */\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface ListProps extends React.HTMLAttributes<HTMLUListElement> {\n  variant?: 'bullet' | 'number' | 'icon' | 'plain';\n  spacing?: 'tight' | 'default' | 'relaxed';\n  iconPosition?: 'start' | 'end';\n}\n\nexport interface ListItemProps extends React.LiHTMLAttributes<HTMLLIElement> {\n  icon?: React.ReactNode;\n  description?: string;\n  info?: React.ReactNode;\n}\n\nconst ListItem = React.forwardRef<HTMLLIElement, ListItemProps>(\n  ({ className, children, icon, description, info, ...props }, ref) => {\n    return (\n      <li ref={ref} className={cn('flex items-start gap-2', className)} {...props}>\n        <div className=\"flex min-w-0 gap-2 flex-1\">\n          {icon && <div className=\"text-muted-foreground mt-1 shrink-0\">{icon}</div>}\n          <div className=\"min-w-0 flex-1\">\n            <div className=\"text-primary text-sm\">{children}</div>\n            {description && <p className=\"text-muted-foreground text-sm\">{description}</p>}\n          </div>\n        </div>\n        {info && <div className=\"shrink-0\">{info}</div>}\n      </li>\n    );\n  },\n);\nListItem.displayName = 'ListItem';\n\nconst List = React.forwardRef<HTMLUListElement, ListProps>(\n  ({ className, children, variant = 'plain', spacing = 'default', ...props }, ref) => {\n    return (\n      <ul\n        ref={ref}\n        className={cn(\n          'text-sm',\n\n          spacing === 'tight' && 'space-y-2',\n          spacing === 'default' && 'space-y-3',\n          spacing === 'relaxed' && 'space-y-4',\n\n          variant === 'bullet' && 'list-inside list-disc',\n          variant === 'number' && 'list-inside list-decimal',\n          variant === 'plain' && 'divide-border list-none divide-y',\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </ul>\n    );\n  },\n);\nList.displayName = 'List';\n\nexport { List, ListItem };\n",
      "type": "registry:component",
      "target": "components/ui/list.tsx"
    },
    {
      "path": "src/components/ui/otp-field.tsx",
      "content": "/**\n * One-time password input field.\n * @module otp-field\n * @internal\n */\n\n'use client';\n\nimport type { ClipboardEvent, KeyboardEvent } from 'react';\nimport React, { useRef, useState } from 'react';\n\nimport { TextField } from '@/components/ui/text-field';\nimport { cn } from '@/lib/utils';\n\nexport interface OTPFieldProps {\n  length?: number;\n  className?: string;\n  placeholder?: string;\n  disabled?: boolean;\n  onChange?: (value: string) => void;\n  autoSubmit?: (value: string) => void;\n  separator?: {\n    character?: string;\n    afterEvery?: number;\n  };\n  id?: string;\n  value?: string;\n  name?: string;\n  inputRef?: React.Ref<HTMLInputElement>;\n}\n\nfunction OTPField({\n  length = 6,\n  placeholder,\n  disabled,\n  className,\n  onChange,\n  autoSubmit,\n  separator,\n  id,\n  value,\n  name,\n  inputRef,\n}: OTPFieldProps) {\n  const [internalOtp, setInternalOtp] = useState<string[]>(new Array(length).fill(''));\n  const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n\n  // Controlled vs uncontrolled logic\n  const isControlled = value !== undefined;\n  const otpValue = value || '';\n  const otp = isControlled ? Array.from({ length }, (_, i) => otpValue[i] || '') : internalOtp;\n\n  const setOtp = (newOtp: string[]) => {\n    if (!isControlled) {\n      setInternalOtp(newOtp);\n    }\n  };\n\n  const handleChange = (element: HTMLInputElement, index: number) => {\n    const value = element.value;\n    if (isNaN(Number(value))) return;\n\n    const newOtp = [...otp];\n    newOtp[index] = value.substring(value.length - 1);\n    setOtp(newOtp);\n\n    const otpValue = newOtp.join('');\n    onChange?.(otpValue);\n\n    if (otpValue.length === length && autoSubmit) {\n      autoSubmit(otpValue);\n    }\n\n    if (value && index < length - 1) {\n      inputRefs.current[index + 1]?.focus();\n    }\n  };\n\n  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>, index: number) => {\n    if ((e.key === 'Delete' || e.key === 'Backspace') && (e.ctrlKey || e.metaKey)) {\n      e.preventDefault();\n      const newOtp = new Array(length).fill('');\n      setOtp(newOtp);\n      onChange?.('');\n      inputRefs.current[0]?.focus();\n      return;\n    }\n\n    if (e.key === 'ArrowLeft') {\n      e.preventDefault();\n      if (index > 0) {\n        inputRefs.current[index - 1]?.focus();\n      }\n      return;\n    }\n\n    if (e.key === 'ArrowRight') {\n      e.preventDefault();\n      if (index < length - 1) {\n        inputRefs.current[index + 1]?.focus();\n      }\n      return;\n    }\n\n    if (e.key === 'Home') {\n      e.preventDefault();\n      inputRefs.current[0]?.focus();\n      return;\n    }\n\n    if (e.key === 'End') {\n      e.preventDefault();\n      inputRefs.current[length - 1]?.focus();\n      return;\n    }\n\n    if (e.key === 'Backspace') {\n      if (!otp[index] && index > 0) {\n        const newOtp = [...otp];\n        newOtp[index - 1] = '';\n        setOtp(newOtp);\n        onChange?.(newOtp.join(''));\n        inputRefs.current[index - 1]?.focus();\n      }\n      return;\n    }\n\n    if (e.key === 'Delete') {\n      if (otp[index]) {\n        const newOtp = [...otp];\n        newOtp[index] = '';\n        setOtp(newOtp);\n        onChange?.(newOtp.join(''));\n      } else if (index < length - 1) {\n        const newOtp = [...otp];\n        newOtp[index + 1] = '';\n        setOtp(newOtp);\n        onChange?.(newOtp.join(''));\n      }\n      return;\n    }\n\n    if (e.key === ' ') {\n      e.preventDefault();\n      const nextEmptyIndex = otp.findIndex((digit, i) => i > index && !digit);\n      if (nextEmptyIndex !== -1) {\n        inputRefs.current[nextEmptyIndex]?.focus();\n      } else if (index < length - 1) {\n        inputRefs.current[index + 1]?.focus();\n      }\n      return;\n    }\n  };\n\n  const handlePaste = (e: ClipboardEvent<HTMLInputElement>, startIndex: number) => {\n    e.preventDefault();\n    const pasteData = e.clipboardData.getData('text').replace(/[^0-9]/g, '');\n\n    if (!pasteData) return;\n\n    const newOtp = [...otp];\n    const availableSlots = length - startIndex;\n    const digitsToPaste = pasteData.slice(0, availableSlots);\n\n    for (let i = startIndex; i < Math.min(startIndex + digitsToPaste.length, length); i++) {\n      newOtp[i] = '';\n    }\n\n    for (let i = 0; i < digitsToPaste.length && startIndex + i < length; i++) {\n      newOtp[startIndex + i] = digitsToPaste[i] ?? '';\n    }\n\n    setOtp(newOtp);\n    const otpValue = newOtp.join('');\n    onChange?.(otpValue);\n\n    if (otpValue.length === length && autoSubmit) {\n      autoSubmit(otpValue);\n    }\n\n    const nextFocusIndex = Math.min(startIndex + digitsToPaste.length, length - 1);\n    setTimeout(() => {\n      inputRefs.current[nextFocusIndex]?.focus();\n    }, 0);\n  };\n\n  return (\n    <div className={cn('flex w-full items-center gap-2', className)}>\n      {otp.map((digit, index) => (\n        <React.Fragment key={index}>\n          <TextField\n            ref={(el) => {\n              inputRefs.current[index] = el as HTMLInputElement;\n              if (index === 0 && inputRef) {\n                if (typeof inputRef === 'function') {\n                  inputRef(el as HTMLInputElement);\n                } else {\n                  inputRef.current = el as HTMLInputElement;\n                }\n              }\n            }}\n            type=\"text\"\n            inputMode=\"numeric\"\n            maxLength={1}\n            value={digit}\n            placeholder={placeholder}\n            disabled={disabled}\n            className=\"flex-1 text-xl font-semibold *:text-center has-[input]:text-center\"\n            onChange={(e) => handleChange(e.target, index)}\n            onKeyDown={(e) => handleKeyDown(e, index)}\n            onPaste={(e) => handlePaste(e, index)}\n            // Apply the id and name only to the first input for label association and form submission\n            id={index === 0 ? id : undefined}\n            name={index === 0 ? name : undefined}\n          />\n          {separator?.afterEvery &&\n            (index + 1) % separator.afterEvery === 0 &&\n            index < length - 1 && (\n              <span className=\"text-muted-foreground text-2xl font-semibold\">\n                {separator.character || '-'}\n              </span>\n            )}\n        </React.Fragment>\n      ))}\n    </div>\n  );\n}\n\nexport { OTPField };\n",
      "type": "registry:component",
      "target": "components/ui/otp-field.tsx"
    },
    {
      "path": "src/components/ui/popover.tsx",
      "content": "/**\n * Popover component using Radix primitives.\n * @module popover\n * @internal\n */\n\n'use client';\n\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/providers/portal-context';\n\nfunction Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n  return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\nfunction PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n  return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} asChild />;\n}\nfunction PopoverContent({\n  className,\n  align = 'center',\n  sideOffset = 4,\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n  const portalContainer = usePortalContainer();\n  return (\n    <PopoverPrimitive.Portal container={portalContainer}>\n      <PopoverPrimitive.Content\n        data-slot=\"popover-content\"\n        align={align}\n        sideOffset={sideOffset}\n        className={cn(\n          'bg-popover text-popover-foreground animate-in fade-in-0 zoom-in-95 shadow-bevel-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) overflow-hidden rounded-3xl ring-0 outline-hidden duration-150 ease-in-out outline-none focus:outline-none',\n          className,\n        )}\n        {...props}\n      />\n    </PopoverPrimitive.Portal>\n  );\n}\nfunction PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n  return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };\n",
      "type": "registry:component",
      "target": "components/ui/popover.tsx"
    },
    {
      "path": "src/components/ui/qr-code.tsx",
      "content": "/**\n * QR code display component.\n * @module qr-code\n * @internal\n */\n\nimport * as React from 'react';\n\nimport { Spinner } from '@/components/ui/spinner';\nimport { useTheme } from '@/hooks/shared/use-theme';\nimport { cn } from '@/lib/utils';\n\nexport interface QRCodeDisplayerProps {\n  value: string;\n  size?: number;\n  className?: string;\n  alt?: string;\n  loadingMessage?: string;\n  errorMessage?: string;\n}\n\nexport function QRCodeDisplayer({\n  value,\n  size = 150,\n  className,\n  alt = 'QR Code',\n  loadingMessage = 'Loading QR code',\n  errorMessage = 'Failed to load QR code',\n}: QRCodeDisplayerProps) {\n  const [qrUrl, setQrUrl] = React.useState<string | null>(null);\n  const [hasError, setHasError] = React.useState(false);\n  const [isLoading, setIsLoading] = React.useState(true);\n\n  const { isDarkMode } = useTheme();\n\n  const qrCodeColorScheme = React.useMemo(\n    () => ({\n      dark: isDarkMode ? '#FFFFFF' : '#000000',\n      light: isDarkMode ? '#000000' : '#FFFFFF',\n    }),\n    [isDarkMode],\n  );\n\n  React.useEffect(() => {\n    if (!value) {\n      setQrUrl(null);\n      setHasError(true);\n      setIsLoading(false);\n      return;\n    }\n\n    const generateQRCode = async () => {\n      try {\n        // Lazy load qrcode only in browser\n        const { toDataURL } = await import('qrcode');\n        const dataURL = await toDataURL(value, {\n          width: size,\n          margin: 1,\n          color: qrCodeColorScheme,\n        });\n        setQrUrl(dataURL);\n        setHasError(false);\n      } catch (err) {\n        setQrUrl(null);\n        setHasError(true);\n      } finally {\n        setIsLoading(false);\n      }\n    };\n\n    setIsLoading(true);\n    generateQRCode();\n  }, [value, size, qrCodeColorScheme]);\n\n  const wrapperProps = {\n    className: cn(\n      'flex items-center justify-center rounded p-2',\n      'bg-gray-100 dark:bg-gray-800',\n      hasError && 'text-gray-500 dark:text-gray-400 text-sm',\n      className,\n    ),\n    style: { width: size, height: size },\n  };\n\n  if (isLoading) {\n    return (\n      <div {...wrapperProps} aria-label={loadingMessage}>\n        <Spinner aria-label={loadingMessage} />\n      </div>\n    );\n  }\n\n  if (hasError || !qrUrl) {\n    return (\n      <div {...wrapperProps} role=\"alert\" aria-live=\"assertive\" aria-label={errorMessage}>\n        <span>{errorMessage}</span>\n      </div>\n    );\n  }\n\n  return (\n    <img\n      src={qrUrl}\n      alt={alt}\n      width={size}\n      height={size}\n      className={cn('block rounded', className)}\n      style={{ imageRendering: 'pixelated' }}\n    />\n  );\n}\n",
      "type": "registry:component",
      "target": "components/ui/qr-code.tsx"
    },
    {
      "path": "src/components/ui/separator.tsx",
      "content": "/**\n * Visual separator component.\n * @module separator\n * @internal\n */\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nfunction Separator({\n  className,\n  orientation = 'horizontal',\n  decorative = true,\n  ...props\n}: React.ComponentProps<'hr'> & { orientation?: 'horizontal' | 'vertical'; decorative?: boolean }) {\n  return (\n    <div\n      data-slot=\"separator\"\n      data-orientation={orientation}\n      role={decorative ? 'none' : 'separator'}\n      className={cn(\n        'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport { Separator };\n",
      "type": "registry:component",
      "target": "components/ui/separator.tsx"
    },
    {
      "path": "src/components/ui/spinner.tsx",
      "content": "/**\n * Loading spinner component.\n * @module spinner\n * @internal\n */\n\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst spinnerVariants = cva(\n  'inline-block h-8 w-8 animate-spin rounded-full border-2 border-transparent',\n  {\n    variants: {\n      variant: {\n        solid: '!border-t-current',\n        dots: 'animate-[spin_5s_linear_infinite] border-6 border-dotted border-current',\n        pulse: 'animate-pulse bg-current',\n      },\n      size: {\n        sm: 'size-4',\n        md: 'size-8',\n        lg: 'size-12',\n      },\n      colorScheme: {\n        primary: 'text-primary',\n        foreground: 'text-primary-foreground',\n        muted: 'text-muted-foreground',\n      },\n    },\n    defaultVariants: {\n      variant: 'solid',\n      size: 'md',\n      colorScheme: 'primary',\n    },\n  },\n);\n\nexport interface SpinnerProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof spinnerVariants> {}\n\nexport function Spinner({ variant, size, colorScheme, className, ...props }: SpinnerProps) {\n  return (\n    <div className={cn(spinnerVariants({ variant, size, colorScheme }), className)} {...props}>\n      <span className=\"sr-only\">Loading...</span>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/ui/spinner.tsx"
    },
    {
      "path": "src/components/ui/text-field.tsx",
      "content": "/**\n * Text input field with variants.\n * @module text-field\n * @internal\n */\n\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst textFieldVariants = cva(\n  \"bg-input aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive relative box-border inline-flex w-full shrink-0 cursor-text items-center justify-center gap-2 overflow-hidden rounded-2xl text-sm transition-[color,box-shadow] duration-150 ease-in-out outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      variant: {\n        default:\n          'border-border/50 text-input-foreground shadow-input-resting hover:shadow-input-hover hover:border-primary/25 focus-within:border-border focus-within:ring-primary/15 focus-within:ring-4',\n        error:\n          'border-destructive-border/50 text-destructive-foreground shadow-input-destructive-resting hover:shadow-input-destructive-hover hover:border-destructive-border/25 focus-within:ring-destructive-border/15 focus-within:ring-4',\n      },\n      size: {\n        default: 'h-10',\n        sm: 'h-9',\n        lg: 'h-11',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n);\n\nexport interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\n  error?: boolean;\n  helperText?: string;\n  size?: VariantProps<typeof textFieldVariants>['size'];\n  variant?: VariantProps<typeof textFieldVariants>['variant'];\n  startAdornment?: React.ReactNode;\n  endAdornment?: React.ReactNode;\n}\n\nconst TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(\n  (\n    { className, variant, size, error, helperText, startAdornment, endAdornment, ...props },\n    ref,\n  ) => {\n    const isDisabled = props.disabled;\n\n    const WrapperComponent = props.id ? 'div' : 'label';\n\n    return (\n      <div className=\"flex w-full flex-col\">\n        <WrapperComponent\n          className={cn(\n            textFieldVariants({ variant: error ? 'error' : variant, size }),\n            'group items-center gap-0.5',\n            isDisabled &&\n              'bg-input-muted text-input-muted-foreground cursor-not-allowed opacity-50',\n            isDisabled && variant === 'default' && 'bg-input-muted',\n            startAdornment && 'pl-[5px]',\n            endAdornment && 'pr-[5px]',\n            className,\n          )}\n        >\n          {startAdornment && (\n            <div className=\"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\">\n              {startAdornment}\n            </div>\n          )}\n          <input\n            className={cn(\n              'w-full flex-1 bg-transparent px-3 py-2 outline-none file:border-0 file:bg-transparent file:text-sm file:font-medium',\n              isDisabled &&\n                'bg-input-muted text-input-muted-foreground cursor-not-allowed opacity-50',\n              startAdornment && 'pl-0',\n              endAdornment && 'pr-0',\n              size === 'default' && 'h-10',\n              size === 'sm' && 'h-9',\n              size === 'lg' && 'h-11',\n            )}\n            ref={ref}\n            {...props}\n          />\n          {endAdornment && (\n            <div className=\"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\">\n              {endAdornment}\n            </div>\n          )}\n        </WrapperComponent>\n        {helperText && (\n          <p\n            className={cn(\n              'mt-1.5 px-2 text-xs',\n              error ? 'text-destructive-foreground' : 'text-muted-foreground',\n            )}\n          >\n            {helperText}\n          </p>\n        )}\n      </div>\n    );\n  },\n);\n\nTextField.displayName = 'TextField';\n\nexport { TextField, textFieldVariants };\n",
      "type": "registry:component",
      "target": "components/ui/text-field.tsx"
    },
    {
      "path": "src/components/ui/tooltip.tsx",
      "content": "/**\n * Tooltip using Radix primitives.\n * @module tooltip\n * @internal\n */\n\n'use client';\n\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/providers/portal-context';\n\nconst tooltipVariants = cva(\n  'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 shadow-bevel-lg z-50 w-fit rounded-xl px-2 py-1 text-sm text-balance',\n  {\n    variants: {\n      position: {\n        top: 'origin-bottom',\n        bottom: 'origin-top',\n        left: 'origin-left',\n        right: 'origin-right',\n      },\n    },\n    defaultVariants: {\n      position: 'top',\n    },\n  },\n);\n\nfunction Tooltip({ children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n  return (\n    <TooltipPrimitive.Provider>\n      <TooltipPrimitive.Root {...props}>{children}</TooltipPrimitive.Root>\n    </TooltipPrimitive.Provider>\n  );\n}\n\nfunction TooltipTrigger({\n  asChild = true,\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n  return <TooltipPrimitive.Trigger asChild={asChild} {...props} />;\n}\n\ninterface TooltipContentProps\n  extends React.ComponentProps<typeof TooltipPrimitive.Content>,\n    VariantProps<typeof tooltipVariants> {}\n\nconst TooltipContent = React.forwardRef<\n  React.ElementRef<typeof TooltipPrimitive.Content>,\n  TooltipContentProps\n>(({ className, side = 'top', position, sideOffset = 8, children, ...props }, ref) => {\n  const portalContainer = usePortalContainer();\n  return (\n    <TooltipPrimitive.Portal container={portalContainer}>\n      <TooltipPrimitive.Content\n        ref={ref}\n        side={side}\n        sideOffset={sideOffset}\n        className={cn(tooltipVariants({ position: position || side }), className)}\n        {...props}\n      >\n        {children}\n        <TooltipPrimitive.Arrow className=\"fill-popover\" />\n      </TooltipPrimitive.Content>\n    </TooltipPrimitive.Portal>\n  );\n});\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipTrigger, TooltipContent, tooltipVariants };\n",
      "type": "registry:component",
      "target": "components/ui/tooltip.tsx"
    },
    {
      "path": "src/hooks/my-account/shared/services/use-user-mfa-service.ts",
      "content": "/**\n * MFA service hook with TanStack Query.\n * @module use-user-mfa-service\n * @internal\n */\n\nimport {\n  MFAMappers,\n  mfaQueryKeys,\n  type Authenticator,\n  type MFAType,\n  type EnrollOptions,\n  type ConfirmEnrollmentOptions,\n} from '@auth0/universal-components-core';\nimport { useQuery, useMutation } from '@tanstack/react-query';\n\nimport { useCoreClient } from '@/hooks/shared/use-core-client';\nimport type { UseUserMFAServiceReturn } from '@/types/my-account/mfa/mfa-types';\n\n/**\n * Internal service hook for MFA operations backed by TanStack Query.\n * Provides queries and mutations; use `useUserMFA` for the public API.\n * @param onlyActive - Whether to return only active factors.\n * @returns MFA query and mutation handlers for factor listing and enrollment lifecycle operations.\n * @internal\n */\nexport function useUserMFAService(onlyActive: boolean): UseUserMFAServiceReturn {\n  const { coreClient } = useCoreClient();\n\n  const factorsQuery = useQuery<Record<MFAType, Authenticator[]>>({\n    queryKey: mfaQueryKeys.factors(onlyActive),\n    queryFn: async () => {\n      const client = coreClient!.getMyAccountApiClient();\n      const [availableFactors, enrolledFactors] = await Promise.all([\n        client.factors.list(),\n        client.authenticationMethods.list(),\n      ]);\n      return MFAMappers.fromAPI(availableFactors, enrolledFactors, onlyActive) as Record<\n        MFAType,\n        Authenticator[]\n      >;\n    },\n    enabled: !!coreClient,\n  });\n\n  const enrollMutation = useMutation({\n    mutationFn: ({\n      factorType,\n      options = {},\n    }: {\n      factorType: MFAType;\n      options?: EnrollOptions;\n    }) => {\n      const client = coreClient!.getMyAccountApiClient();\n      const params = MFAMappers.buildEnrollParams(factorType, options);\n      return client.authenticationMethods.create(params);\n    },\n  });\n\n  const deleteMutation = useMutation({\n    mutationFn: (authenticatorId: string) =>\n      coreClient!.getMyAccountApiClient().authenticationMethods.delete(authenticatorId),\n  });\n\n  const verifyMutation = useMutation({\n    mutationFn: ({\n      factorType,\n      authSession,\n      authenticationMethodId,\n      options,\n    }: {\n      factorType: MFAType;\n      authSession: string;\n      authenticationMethodId: string;\n      options: ConfirmEnrollmentOptions;\n    }) => {\n      const client = coreClient!.getMyAccountApiClient();\n      const params = MFAMappers.buildConfirmEnrollmentParams(factorType, authSession, options);\n      return client.authenticationMethods.verify(authenticationMethodId, params);\n    },\n  });\n\n  return {\n    factorsQuery,\n    enrollMutation,\n    deleteMutation,\n    verifyMutation,\n  };\n}\n",
      "type": "registry:component",
      "target": "hooks/my-account/shared/services/use-user-mfa-service.ts"
    },
    {
      "path": "src/hooks/my-account/use-user-mfa.ts",
      "content": "/**\n * User MFA management hook.\n * @module use-user-mfa\n */\n\nimport {\n  FACTOR_TYPE_EMAIL,\n  FACTOR_TYPE_PHONE,\n  FACTOR_TYPE_PUSH_NOTIFICATION,\n  FACTOR_TYPE_RECOVERY_CODE,\n  isNotifiableError,\n  normalizeError,\n  type Authenticator,\n  type CreateAuthenticationMethodResponseContent,\n  type MFAType,\n} from '@auth0/universal-components-core';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { toast } from 'sonner';\n\nimport { useUserMFAService } from '@/hooks/my-account/shared/services/use-user-mfa-service';\nimport { useErrorHandler } from '@/hooks/shared/use-error-handler';\nimport { useTranslator } from '@/hooks/shared/use-translator';\nimport {\n  CONFIRM,\n  ENTER_CONTACT,\n  ENTER_QR,\n  ENROLL,\n  QR_PHASE_INSTALLATION,\n  SHOW_RECOVERY_CODE,\n} from '@/lib/constants/my-account/mfa/mfa-constants';\nimport type {\n  EnrollmentPhase,\n  UserMFAOptions,\n  UseUserMFAReturn,\n} from '@/types/my-account/mfa/mfa-types';\n\nconst EMPTY_SESSION = { authSession: '', authenticationMethodId: '' };\n\nconst extractSession = (res: CreateAuthenticationMethodResponseContent) => ({\n  authSession: res.auth_session,\n  authenticationMethodId: 'id' in res ? res.id : '',\n});\n\nconst extractOtpData = (res: CreateAuthenticationMethodResponseContent) => ({\n  barcodeUri: 'barcode_uri' in res ? res.barcode_uri : '',\n  manualInputCode: 'manual_input_code' in res ? (res.manual_input_code ?? '') : '',\n});\n\n/**\n * Hook for user MFA management — fetch, enroll, delete, confirm, and all UI state.\n * @param options - Hook options.\n * @returns MFA state, UI handlers, and API methods.\n */\nexport function useUserMFA({\n  showActiveOnly = false,\n  readOnly = false,\n  disableDelete = false,\n  factorConfig,\n  customMessages = {},\n  onFetch,\n  onEnroll,\n  onDelete,\n  onErrorAction,\n  onBeforeAction,\n}: UserMFAOptions = {}): UseUserMFAReturn {\n  const { t } = useTranslator('mfa', customMessages);\n  const handleError = useErrorHandler();\n  const { factorsQuery, enrollMutation, deleteMutation, verifyMutation } =\n    useUserMFAService(showActiveOnly);\n\n  const [isEnrollDialogOpen, setIsEnrollDialogOpen] = useState(false);\n  const [enrollFactor, setEnrollFactor] = useState<MFAType | null>(null);\n  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n  const [factorToDelete, setFactorToDelete] = useState<{ id: string; type: MFAType } | null>(null);\n\n  const [enrollmentPhase, setEnrollmentPhase] = useState<EnrollmentPhase>(null);\n  const [enrollmentSession, setEnrollmentSession] = useState(EMPTY_SESSION);\n  const [contact, setContact] = useState('');\n  const [otpData, setOtpData] = useState({ barcodeUri: '', manualInputCode: '' });\n  const [recoveryCode, setRecoveryCode] = useState('');\n\n  const factorsByType = factorsQuery.data ?? ({} as Record<MFAType, Authenticator[]>);\n\n  useEffect(() => {\n    if (factorsQuery.isSuccess) onFetch?.();\n  }, [factorsQuery.isSuccess, onFetch]);\n\n  useEffect(() => {\n    if (factorsQuery.isError) {\n      handleError(factorsQuery.error, { fallbackMessage: t('errors.factors_loading_error') });\n    }\n  }, [factorsQuery.isError, factorsQuery.error, handleError, t]);\n\n  const visibleFactorTypes = useMemo(\n    () =>\n      (Object.keys(factorsByType) as MFAType[]).filter(\n        (factorType) => factorConfig?.[factorType]?.visible !== false,\n      ),\n    [factorsByType, factorConfig],\n  );\n\n  const hasNoActiveFactors = useMemo(\n    () => visibleFactorTypes.every((type) => !factorsByType[type]?.some((f) => f.enrolled)),\n    [visibleFactorTypes, factorsByType],\n  );\n\n  const handleEnrollError = useCallback(\n    (err: unknown, stage: typeof ENROLL | typeof CONFIRM, factor: MFAType | null) => {\n      if (!isNotifiableError(err)) {\n        handleError(err);\n        return;\n      }\n      const label = stage === ENROLL ? t('enrollment') : t('confirmation');\n      const error = normalizeError(err, {\n        resolver: (code) => t(`errors.${factor}.${code}`, {}, t('errors.unexpected')),\n      });\n      toast.error(`${label} ${t('errors.failed', { message: error.message })}`);\n      onErrorAction?.(error, stage);\n    },\n    [handleError, onErrorAction, t],\n  );\n\n  const handleEnrollSuccess = useCallback(async () => {\n    toast.success(t('enroll_factor'), {\n      duration: 2000,\n      onAutoClose: () => onEnroll?.(),\n    });\n    setIsEnrollDialogOpen(false);\n    setEnrollFactor(null);\n    setEnrollmentPhase(null);\n    setEnrollmentSession(EMPTY_SESSION);\n    setContact('');\n    setOtpData({ barcodeUri: '', manualInputCode: '' });\n    setRecoveryCode('');\n    await factorsQuery.refetch();\n  }, [factorsQuery, onEnroll, t]);\n\n  const verifyAndComplete = useCallback(\n    async (params: Parameters<typeof verifyMutation.mutateAsync>[0]) => {\n      try {\n        await verifyMutation.mutateAsync(params);\n        await handleEnrollSuccess();\n      } catch (err) {\n        handleEnrollError(err, CONFIRM, params.factorType);\n      }\n    },\n    [verifyMutation, handleEnrollSuccess, handleEnrollError],\n  );\n\n  const handleEnroll = useCallback(\n    async (factor: MFAType) => {\n      setEnrollFactor(factor);\n      setIsEnrollDialogOpen(true);\n\n      if (factor === FACTOR_TYPE_EMAIL || factor === FACTOR_TYPE_PHONE) {\n        setEnrollmentPhase(ENTER_CONTACT);\n        return;\n      }\n\n      if (factor === FACTOR_TYPE_PUSH_NOTIFICATION) {\n        setEnrollmentPhase(QR_PHASE_INSTALLATION);\n        return;\n      }\n\n      try {\n        const enrollment = await enrollMutation.mutateAsync({ factorType: factor, options: {} });\n        setEnrollmentSession(extractSession(enrollment));\n        if (factor === FACTOR_TYPE_RECOVERY_CODE) {\n          setRecoveryCode('recovery_code' in enrollment ? enrollment.recovery_code : '');\n          setEnrollmentPhase(SHOW_RECOVERY_CODE);\n        } else {\n          setOtpData(extractOtpData(enrollment));\n          setEnrollmentPhase(ENTER_QR);\n        }\n      } catch (err) {\n        handleEnrollError(err, ENROLL, factor);\n        setIsEnrollDialogOpen(false);\n        setEnrollFactor(null);\n      }\n    },\n    [enrollMutation, handleEnrollError],\n  );\n\n  const handleCancelDelete = useCallback(() => {\n    if (deleteMutation.isPending) return;\n    setIsDeleteDialogOpen(false);\n    setFactorToDelete(null);\n  }, [deleteMutation.isPending]);\n\n  const handleCloseEnrollDialog = useCallback(async () => {\n    setIsEnrollDialogOpen(false);\n    setEnrollmentPhase(null);\n    setEnrollmentSession(EMPTY_SESSION);\n    setContact('');\n    setOtpData({ barcodeUri: '', manualInputCode: '' });\n    setRecoveryCode('');\n    if (enrollFactor === FACTOR_TYPE_PUSH_NOTIFICATION && enrollmentSession.authSession) {\n      await factorsQuery.refetch();\n    }\n    setEnrollFactor(null);\n  }, [enrollFactor, enrollmentSession.authSession, factorsQuery]);\n\n  const executeDelete = useCallback(\n    async (factorId: string) => {\n      try {\n        await deleteMutation.mutateAsync(factorId);\n        await factorsQuery.refetch();\n        toast.success(t('remove_factor'), {\n          duration: 2000,\n          onAutoClose: () => onDelete?.(),\n        });\n      } catch (err) {\n        if (isNotifiableError(err)) {\n          onErrorAction?.(\n            err instanceof Error ? err : new Error(t('errors.delete_factor')),\n            'delete',\n          );\n        }\n        handleError(err, { fallbackMessage: t('errors.delete_factor') });\n      } finally {\n        setIsDeleteDialogOpen(false);\n        setFactorToDelete(null);\n      }\n    },\n    [deleteMutation, factorsQuery, handleError, onDelete, onErrorAction, t],\n  );\n\n  const handleConfirmDelete = useCallback(async () => {\n    if (!factorToDelete) return;\n    await executeDelete(factorToDelete.id);\n  }, [factorToDelete, executeDelete]);\n\n  const handleDeleteFactor = useCallback(\n    async (factorId: string, factorType: MFAType) => {\n      if (readOnly || disableDelete) return;\n      if (onBeforeAction) {\n        const canProceed = await onBeforeAction('delete', factorType);\n        if (!canProceed) return;\n        await executeDelete(factorId);\n      } else {\n        setFactorToDelete({ id: factorId, type: factorType });\n        setIsDeleteDialogOpen(true);\n      }\n    },\n    [readOnly, disableDelete, onBeforeAction, executeDelete],\n  );\n\n  const handleSendCode = useCallback(\n    async (options: Record<string, string>): Promise<boolean> => {\n      try {\n        const enrollment = await enrollMutation.mutateAsync({ factorType: enrollFactor!, options });\n        setContact(options.email ?? options.phone_number ?? '');\n        setEnrollmentSession(extractSession(enrollment));\n        return true;\n      } catch (err) {\n        handleEnrollError(err, ENROLL, enrollFactor);\n        return false;\n      }\n    },\n    [enrollFactor, enrollMutation, handleEnrollError],\n  );\n\n  const handleConfirmOtp = useCallback(\n    (otpCode: string) =>\n      verifyAndComplete({\n        factorType: enrollFactor!,\n        authSession: enrollmentSession.authSession,\n        authenticationMethodId: enrollmentSession.authenticationMethodId,\n        options: { userOtpCode: otpCode },\n      }),\n    [enrollFactor, enrollmentSession, verifyAndComplete],\n  );\n\n  const handleEnterQRPhase = useCallback(async () => {\n    if (!enrollFactor) return;\n    try {\n      const enrollment = await enrollMutation.mutateAsync({\n        factorType: enrollFactor,\n        options: {},\n      });\n      setEnrollmentSession(extractSession(enrollment));\n      setOtpData(extractOtpData(enrollment));\n      setEnrollmentPhase(ENTER_QR);\n    } catch (err) {\n      handleEnrollError(err, ENROLL, enrollFactor);\n      setIsEnrollDialogOpen(false);\n      setEnrollFactor(null);\n    }\n  }, [enrollFactor, enrollMutation, handleEnrollError]);\n\n  const handleConfirmPush = useCallback(async () => {\n    if (enrollFactor !== FACTOR_TYPE_PUSH_NOTIFICATION) return;\n    await verifyAndComplete({\n      factorType: enrollFactor,\n      authSession: enrollmentSession.authSession,\n      authenticationMethodId: enrollmentSession.authenticationMethodId,\n      options: {},\n    });\n  }, [enrollFactor, enrollmentSession, verifyAndComplete]);\n\n  const handleConfirmRecoveryCode = useCallback(\n    () =>\n      verifyAndComplete({\n        factorType: enrollFactor!,\n        authSession: enrollmentSession.authSession,\n        authenticationMethodId: enrollmentSession.authenticationMethodId,\n        options: {},\n      }),\n    [enrollFactor, enrollmentSession, verifyAndComplete],\n  );\n\n  return {\n    factorsByType,\n    isLoadingFactors: factorsQuery.isLoading,\n    isEnrolling: enrollMutation.isPending,\n    isDeleting: deleteMutation.isPending,\n    isConfirming: verifyMutation.isPending,\n    error: factorsQuery.isError ? t('errors.factors_loading_error') : null,\n    isEnrollDialogOpen,\n    enrollFactor,\n    enrollmentPhase,\n    isDeleteDialogOpen,\n    factorToDelete,\n    visibleFactorTypes,\n    hasNoActiveFactors,\n    contact,\n    otpData,\n    recoveryCode,\n    handleCancelDelete,\n    handleConfirmDelete,\n    handleEnroll,\n    handleCloseEnrollDialog,\n    handleDeleteFactor,\n    handleSendCode,\n    handleConfirmOtp,\n    handleConfirmPush,\n    handleConfirmRecoveryCode,\n    handleEnterQRPhase,\n  };\n}\n",
      "type": "registry:component",
      "target": "hooks/my-account/use-user-mfa.ts"
    },
    {
      "path": "src/hooks/shared/use-core-client-initialization.ts",
      "content": "/**\n * CoreClient initialization hook.\n * @module use-core-client-initialization\n * @internal\n */\n\nimport type {\n  CoreClientInterface,\n  AuthDetails,\n  I18nInitOptions,\n} from '@auth0/universal-components-core';\nimport { createCoreClient } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\ninterface UseCoreClientInitializationProps {\n  authDetails: AuthDetails;\n  i18nOptions?: I18nInitOptions;\n}\n\n/**\n * @internal\n * @param props - Initialization props.\n * @returns The initialized CoreClient instance, or null while initializing.\n */\nexport const useCoreClientInitialization = ({\n  authDetails,\n  i18nOptions,\n}: UseCoreClientInitializationProps): CoreClientInterface | null => {\n  const { authProxyUrl } = authDetails;\n  const [coreClient, setCoreClient] = React.useState<CoreClientInterface | null>(null);\n\n  React.useEffect(() => {\n    const initializeCoreClient = async () => {\n      try {\n        const initializedCoreClient = await createCoreClient(authDetails, i18nOptions);\n        setCoreClient(initializedCoreClient);\n      } catch (error) {\n        console.error(error);\n      }\n    };\n    initializeCoreClient();\n  }, [authProxyUrl, i18nOptions]);\n\n  return coreClient;\n};\n",
      "type": "registry:component",
      "target": "hooks/shared/use-core-client-initialization.ts"
    },
    {
      "path": "src/hooks/shared/use-core-client.ts",
      "content": "/**\n * CoreClient context and hook.\n * @module use-core-client\n */\n\nimport type { CoreClientInterface } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\n/** @internal */\nconst CoreClientContext = React.createContext<{\n  coreClient: CoreClientInterface | null;\n}>({\n  coreClient: null,\n});\n\n/**\n * Hook to access CoreClient from context.\n * @returns CoreClient instance or null.\n * @throws If used outside Auth0ComponentProvider.\n */\nexport const useCoreClient = () => {\n  const context = React.useContext(CoreClientContext);\n  if (!context) {\n    throw new Error('useCoreClient must be used within Auth0ComponentProvider');\n  }\n  return context;\n};\n\nexport { CoreClientContext };\n",
      "type": "registry:component",
      "target": "hooks/shared/use-core-client.ts"
    },
    {
      "path": "src/hooks/shared/use-error-handler.ts",
      "content": "/**\n * Error handling hook with toast error.\n * @module use-error-handler\n */\n\nimport {\n  isNetworkError,\n  isNotifiableError,\n  resolveErrorMessage,\n  getStatusCode,\n  hasApiErrorBody,\n  ERROR_CODES,\n} from '@auth0/universal-components-core';\nimport { useCallback } from 'react';\n\nimport { showToast } from '@/components/auth0/shared/toast';\nimport { useTranslator } from '@/hooks/shared/use-translator';\n\ninterface ErrorHandlerCallOptions {\n  fallbackMessage?: string;\n}\n\n/**\n * Hook for consistent error handling across the app.\n *\n * @returns Error handler function.\n *\n * @example\n * const handleError = useErrorHandler();\n *\n * // With custom message\n * onError: (error) => handleError(error, {\n *   fallbackMessage: t('my_error')\n * });\n *\n * // With defaults\n * onError: handleError;\n */\nexport function useErrorHandler() {\n  const { t } = useTranslator('common');\n\n  return useCallback(\n    (error: unknown, options: ErrorHandlerCallOptions = {}): void => {\n      if (!isNotifiableError(error)) return;\n\n      const getCustomErrorMessage = (err: unknown): string | undefined => {\n        if (isNetworkError(err)) return t('error.network');\n        const status = getStatusCode(err);\n        switch (status) {\n          case 400:\n            return t('error.bad_request');\n          case 401:\n            return t('error.missing_token');\n          case 403:\n            return hasApiErrorBody(err) && err.body?.type?.includes(ERROR_CODES.INSUFFICIENT_SCOPE)\n              ? t('error.insufficient_scope')\n              : t('error.forbidden');\n          case 404:\n            return t('error.not_found');\n          case 429:\n            return t('error.rate_limit');\n          default:\n            return undefined;\n        }\n      };\n\n      showToast({\n        type: 'error',\n        message:\n          getCustomErrorMessage(error) ??\n          resolveErrorMessage(error, options.fallbackMessage ?? t('error.generic')),\n      });\n    },\n    [t],\n  );\n}\n",
      "type": "registry:component",
      "target": "hooks/shared/use-error-handler.ts"
    },
    {
      "path": "src/hooks/shared/use-theme.ts",
      "content": "/**\n * Theme context hook.\n * @module use-theme\n */\n\n'use client';\n\nimport { useContext } from 'react';\n\nimport { ThemeContext } from '@/providers/theme-provider';\n\n/**\n * Hook to access theme context (mode, variables, loader).\n * @returns Theme context value.\n * @throws If used outside ThemeProvider.\n */\nexport function useTheme() {\n  const context = useContext(ThemeContext);\n  if (!context) {\n    throw new Error('useTheme must be used within a ThemeProvider');\n  }\n  return context;\n}\n",
      "type": "registry:component",
      "target": "hooks/shared/use-theme.ts"
    },
    {
      "path": "src/hooks/shared/use-toast-provider.ts",
      "content": "/**\n * Toast settings management hook.\n * @module use-toast-provider\n * @internal\n */\n\nimport { useEffect, useMemo } from 'react';\n\nimport { setGlobalToastSettings } from '@/components/auth0/shared/toast';\nimport { DEFAULT_TOAST_SETTINGS, type ToastSettings } from '@/types/toast-types';\n\n/**\n * Hook to merge and apply toast settings.\n * @param toastSettings - Optional toast settings.\n * @returns Merged toast settings.\n * @internal\n */\nexport const useToastProvider = (toastSettings?: ToastSettings) => {\n  const mergedToastSettings = useMemo(() => {\n    if (!toastSettings) {\n      return DEFAULT_TOAST_SETTINGS;\n    }\n\n    if (toastSettings.provider === 'custom') {\n      return toastSettings;\n    }\n\n    const defaultSonnerSettings =\n      DEFAULT_TOAST_SETTINGS.provider === 'sonner' ? DEFAULT_TOAST_SETTINGS.settings || {} : {};\n\n    return {\n      provider: 'sonner' as const,\n      settings: {\n        ...defaultSonnerSettings,\n        ...(toastSettings.provider === 'sonner' ? toastSettings.settings : {}),\n      },\n    } satisfies ToastSettings;\n  }, [toastSettings]);\n\n  useEffect(() => {\n    setGlobalToastSettings(mergedToastSettings);\n  }, [mergedToastSettings]);\n\n  return mergedToastSettings;\n};\n",
      "type": "registry:component",
      "target": "hooks/shared/use-toast-provider.ts"
    },
    {
      "path": "src/hooks/shared/use-translator.ts",
      "content": "/**\n * i18n translator hook.\n * @module use-translator\n */\n\nimport { type EnhancedTranslationFunction } from '@auth0/universal-components-core';\nimport { useMemo, useCallback } from 'react';\n\nimport { useCoreClient } from '@/hooks/shared/use-core-client';\n\n/**\n * Hook to access i18n translations.\n * @param namespace - Translation namespace.\n * @param overrides - Optional translation overrides.\n * @returns Translator function and language utilities.\n */\nexport function useTranslator(\n  namespace: string,\n  overrides?: Record<string, unknown>,\n): {\n  t: EnhancedTranslationFunction;\n  changeLanguage: (language: string, fallbackLanguage?: string) => Promise<void>;\n  currentLanguage: string;\n  fallbackLanguage: string | undefined;\n} {\n  const { coreClient } = useCoreClient();\n\n  if (!coreClient) {\n    throw new Error(\n      'useTranslator must be used within Auth0ComponentProvider with initialized CoreClient',\n    );\n  }\n\n  const translator = useMemo(() => {\n    return coreClient.i18nService.translator(namespace, overrides);\n  }, [coreClient, namespace, overrides]);\n\n  const changeLanguage = useCallback(\n    async (language: string, fallbackLanguage?: string) => {\n      await coreClient.i18nService.changeLanguage(language, fallbackLanguage);\n    },\n    [coreClient],\n  );\n\n  return {\n    t: translator,\n    changeLanguage,\n    currentLanguage: coreClient.i18nService.currentLanguage,\n    fallbackLanguage: coreClient.i18nService.fallbackLanguage,\n  };\n}\n",
      "type": "registry:component",
      "target": "hooks/shared/use-translator.ts"
    },
    {
      "path": "src/providers/gate-keeper-context.tsx",
      "content": "'use client';\n\nimport { createContext, useContext } from 'react';\n\nexport interface GateKeeperContextValue {\n  error: Error | null;\n  /** Defined only when an error is active. */\n  onRetry?: () => Promise<boolean>;\n}\n\nexport const GateKeeperContext = createContext<GateKeeperContextValue | null>(null);\n\n/**\n * @internal\n * @returns Current GateKeeper context value\n * @throws Error if used outside of the GateKeeperProvider\n */\nexport function useGateKeeperContext(): GateKeeperContextValue {\n  const context = useContext(GateKeeperContext);\n\n  if (!context) {\n    throw new Error('useGateKeeperContext must be used within a GateKeeperProvider');\n  }\n\n  return context;\n}\n",
      "type": "registry:component",
      "target": "providers/gate-keeper-context.tsx"
    },
    {
      "path": "src/providers/portal-context.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\n\n/**\n * React context that stores the target HTML element used as a portal container\n * for overlay-based UI (for example, dialogs, popovers, and tooltips).\n *\n */\nexport const PortalContext = React.createContext<HTMLElement | null>(null);\n\n/**\n * Returns the current portal container element from `PortalContext`.\n *\n * @returns The configured portal host element, or `null` when not provided.\n */\nexport function usePortalContainer() {\n  return React.useContext(PortalContext);\n}\n",
      "type": "registry:component",
      "target": "providers/portal-context.tsx"
    },
    {
      "path": "src/providers/proxy-provider.tsx",
      "content": "/**\n * RWA proxy provider for server-side auth.\n * @module proxy-provider\n */\n\n'use client';\n\nimport type { AuthDetails } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { Toaster } from '@/components/auth0/shared/sonner';\nimport { StyledScope } from '@/components/auth0/shared/styled-scope';\nimport { Spinner } from '@/components/ui/spinner';\nimport { CoreClientContext } from '@/hooks/shared/use-core-client';\nimport { useCoreClientInitialization } from '@/hooks/shared/use-core-client-initialization';\nimport { useToastProvider } from '@/hooks/shared/use-toast-provider';\nimport { QueryProvider } from '@/providers/query-provider';\nimport { ThemeProvider } from '@/providers/theme-provider';\nimport type { Auth0ComponentProviderProps } from '@/types/auth-types';\n\n/**\n * Auth0 provider for RWAs using backend proxy auth.\n * @param props - Provider configuration including domain, proxyConfig, i18n, themeSettings, toastSettings, cacheConfig, loader, and children.\n * @returns Provider component tree\n */\nexport const Auth0ComponentProvider = ({\n  i18n,\n  domain,\n  proxyConfig,\n  previewMode,\n  themeSettings = {\n    theme: 'default',\n    mode: 'light',\n    variables: {\n      common: {},\n      light: {},\n      dark: {},\n    },\n  },\n  toastSettings,\n  cacheConfig,\n  loader,\n  children,\n}: Extract<Auth0ComponentProviderProps, { mode: 'proxy' }> & { children: React.ReactNode }) => {\n  const mergedToastSettings = useToastProvider(toastSettings);\n  const { baseUrl, fetcher } = proxyConfig;\n\n  const memoizedAuthDetails = React.useMemo<AuthDetails>(\n    () => ({\n      domain,\n      authProxyUrl: baseUrl,\n      fetcher,\n      previewMode,\n    }),\n    [domain, baseUrl, fetcher, previewMode],\n  );\n\n  const coreClient = useCoreClientInitialization({\n    authDetails: memoizedAuthDetails,\n    i18nOptions: i18n,\n  });\n\n  const coreClientValue = React.useMemo(\n    () => ({\n      coreClient,\n    }),\n    [coreClient],\n  );\n\n  const fallback = loader || (\n    <StyledScope>\n      <div className=\"flex items-center justify-center min-h-[200px]\">\n        <Spinner />\n      </div>\n    </StyledScope>\n  );\n\n  return (\n    <ThemeProvider\n      themeSettings={{\n        mode: themeSettings.mode,\n        variables: themeSettings.variables,\n        loader,\n        theme: themeSettings.theme,\n      }}\n    >\n      {mergedToastSettings.provider === 'sonner' && (\n        <Toaster\n          position={mergedToastSettings.settings?.position || 'top-right'}\n          closeButton={mergedToastSettings.settings?.closeButton ?? true}\n          className=\"auth0-universal\"\n        />\n      )}\n      {coreClient ? (\n        <CoreClientContext.Provider value={coreClientValue}>\n          <QueryProvider cacheConfig={cacheConfig}>{children}</QueryProvider>\n        </CoreClientContext.Provider>\n      ) : (\n        fallback\n      )}\n    </ThemeProvider>\n  );\n};\n\nexport default Auth0ComponentProvider;\n",
      "type": "registry:component",
      "target": "providers/proxy-provider.tsx"
    },
    {
      "path": "src/providers/query-provider.tsx",
      "content": "'use client';\n\n/**\n * TanStack Query provider wrapper.\n * @module query-provider\n * @internal\n */\n\nimport { isMfaRequiredError, isNotifiableError } from '@auth0/universal-components-core';\nimport {\n  MutationCache,\n  type Query,\n  QueryCache,\n  QueryClient,\n  QueryClientProvider as TanStackQueryClientProvider,\n} from '@tanstack/react-query';\nimport { useMemo, useState, type ReactElement, type ReactNode } from 'react';\n\nimport { GateKeeperContext } from '@/providers/gate-keeper-context';\n\n/** Query cache configuration. */\nexport interface QueryCacheConfig {\n  enabled?: boolean;\n  staleTime?: number;\n  gcTime?: number;\n  refetchOnWindowFocus?: boolean | 'always';\n}\n\n/** Default cache configuration. */\nexport const DEFAULT_CACHE_CONFIG: Readonly<Required<QueryCacheConfig>> = {\n  enabled: true,\n  staleTime: 2 * 60 * 1000,\n  gcTime: 5 * 60 * 1000,\n  refetchOnWindowFocus: false,\n};\n\nconst QUERY_RETRY_CONFIG = {\n  maxRetries: 3,\n  maxRetryDelay: 30_000,\n  backoffMultiplier: 2,\n} as const;\n\nconst MUTATION_RETRY_CONFIG = {\n  maxRetries: 1,\n} as const;\n\nconst DISABLED_CACHE_GC_TIME = 5 * 1000;\n\n/**\n * Merges user config with defaults.\n * @param userConfig - User-provided cache config.\n * @returns The resolved cache configuration\n * @internal\n */\nexport function resolveCacheConfig(userConfig?: QueryCacheConfig): Required<QueryCacheConfig> {\n  const merged: Required<QueryCacheConfig> = {\n    ...DEFAULT_CACHE_CONFIG,\n    ...userConfig,\n  };\n\n  if (!merged.enabled) {\n    return {\n      ...merged,\n      staleTime: 0,\n      gcTime: DISABLED_CACHE_GC_TIME,\n    };\n  }\n\n  return merged;\n}\n\n/**\n * Returns true if a cached query has an error that GateKeeper should handle.\n * @param query - The cached query to check.\n * @returns Whether the query error should be intercepted by GateKeeper.\n */\nfunction isGateKeeperError(query: Query): boolean {\n  return !!query.state.error && !isNotifiableError(query.state.error);\n}\n\n/**\n * Creates a QueryClient with config and global GateKeeper error interception.\n * @param cacheConfig - Cache configuration.\n * @param setGateKeeperState - Setter for GateKeeper context state.\n * @returns The configured QueryClient instance\n * @internal\n */\nfunction createQueryClient(\n  cacheConfig: Required<QueryCacheConfig>,\n  setGateKeeperState: (state: { error: Error; onRetry: () => Promise<boolean> } | null) => void,\n): QueryClient {\n  const queryClient = new QueryClient({\n    queryCache: new QueryCache({\n      onError: (error) => {\n        if (!isNotifiableError(error)) {\n          setGateKeeperState({\n            error,\n            onRetry: async () => {\n              await queryClient.refetchQueries({ predicate: isGateKeeperError });\n              const stillFailing = queryClient.getQueryCache().getAll().some(isGateKeeperError);\n              if (!stillFailing) setGateKeeperState(null);\n              return !stillFailing;\n            },\n          });\n        }\n      },\n    }),\n    mutationCache: new MutationCache({\n      onError: (error, variables, _context, mutation) => {\n        if (isMfaRequiredError(error)) {\n          setGateKeeperState({\n            error,\n            onRetry: async () => {\n              try {\n                await mutation.execute(variables);\n                setGateKeeperState(null);\n                return true;\n              } catch {\n                return false;\n              }\n            },\n          });\n        }\n      },\n    }),\n    defaultOptions: {\n      queries: {\n        staleTime: cacheConfig.staleTime,\n        gcTime: cacheConfig.gcTime,\n        refetchOnWindowFocus: cacheConfig.refetchOnWindowFocus,\n        retry: (failureCount, error) =>\n          !isMfaRequiredError(error) && failureCount < QUERY_RETRY_CONFIG.maxRetries,\n        retryDelay: (attemptIndex: number) =>\n          Math.min(\n            1000 * QUERY_RETRY_CONFIG.backoffMultiplier ** attemptIndex,\n            QUERY_RETRY_CONFIG.maxRetryDelay,\n          ),\n        refetchOnReconnect: true,\n      },\n      mutations: {\n        retry: (failureCount, error) =>\n          !isMfaRequiredError(error) && failureCount < MUTATION_RETRY_CONFIG.maxRetries,\n      },\n    },\n  });\n\n  return queryClient;\n}\n\n/** Props for QueryProvider. */\nexport interface QueryProviderProps {\n  children: ReactNode;\n  /** Cache config, only read on mount. */\n  cacheConfig?: QueryCacheConfig;\n}\n\n/**\n * Internal TanStack Query provider wrapper.\n * @param props - Component props.\n * @param props.children - Child components.\n * @param props.cacheConfig - Cache configuration.\n * @returns The context provider component\n * @internal\n */\nexport function QueryProvider({ children, cacheConfig }: QueryProviderProps): ReactElement {\n  const [gateKeeperState, setGateKeeperState] = useState<{\n    error: Error;\n    onRetry: () => Promise<boolean>;\n  } | null>(null);\n  const [queryClient] = useState(() =>\n    createQueryClient(resolveCacheConfig(cacheConfig), setGateKeeperState),\n  );\n\n  const contextValue = useMemo(() => gateKeeperState ?? { error: null }, [gateKeeperState]);\n\n  return (\n    <GateKeeperContext.Provider value={contextValue}>\n      <TanStackQueryClientProvider client={queryClient}>{children}</TanStackQueryClientProvider>\n    </GateKeeperContext.Provider>\n  );\n}\n",
      "type": "registry:component",
      "target": "providers/query-provider.tsx"
    },
    {
      "path": "src/providers/spa-provider.tsx",
      "content": "/**\n * SPA provider using @auth0/auth0-react.\n * @module spa-provider\n */\n\n'use client';\n\nimport { useAuth0 } from '@auth0/auth0-react';\nimport type { AuthDetails, BasicAuth0ContextInterface } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { Toaster } from '@/components/auth0/shared/sonner';\nimport { StyledScope } from '@/components/auth0/shared/styled-scope';\nimport { Spinner } from '@/components/ui/spinner';\nimport { CoreClientContext } from '@/hooks/shared/use-core-client';\nimport { useCoreClientInitialization } from '@/hooks/shared/use-core-client-initialization';\nimport { useToastProvider } from '@/hooks/shared/use-toast-provider';\nimport { QueryProvider } from '@/providers/query-provider';\nimport { ThemeProvider } from '@/providers/theme-provider';\nimport type { Auth0ComponentProviderProps } from '@/types/auth-types';\n\n/**\n * Auth0 provider for SPAs. Wraps components with required contexts.\n * @param props - Provider configuration including domain, mode, authContext, i18n, themeSettings, toastSettings, cacheConfig, loader, and children.\n * @returns Provider component tree\n */\nexport const Auth0ComponentProvider = (\n  props: Extract<Auth0ComponentProviderProps, { mode?: 'direct' }> & { children: React.ReactNode },\n) => {\n  const {\n    i18n,\n    previewMode,\n    themeSettings = {\n      theme: 'default',\n      mode: 'light',\n      variables: {\n        common: {},\n        light: {},\n        dark: {},\n      },\n    },\n    toastSettings,\n    cacheConfig,\n    loader,\n    children,\n    authContext,\n  } = props;\n  const mergedToastSettings = useToastProvider(toastSettings);\n\n  const auth0ReactContext = useAuth0();\n\n  const resolvedAuthContext = React.useMemo(() => {\n    if (authContext) {\n      return authContext;\n    }\n    if (auth0ReactContext && 'isAuthenticated' in auth0ReactContext) {\n      return auth0ReactContext as BasicAuth0ContextInterface;\n    }\n\n    throw new Error(\n      'Auth0ContextInterface is not available. Make sure you wrap your app with Auth0Provider from @auth0/auth0-react, or pass authContext.',\n    );\n  }, [auth0ReactContext, authContext]);\n\n  const memoizedAuthDetails = React.useMemo<AuthDetails>(\n    () => ({\n      contextInterface: resolvedAuthContext,\n      previewMode,\n    }),\n    [resolvedAuthContext, previewMode],\n  );\n\n  const coreClient = useCoreClientInitialization({\n    authDetails: memoizedAuthDetails,\n    i18nOptions: i18n,\n  });\n\n  const coreClientValue = React.useMemo(\n    () => ({\n      coreClient,\n    }),\n    [coreClient],\n  );\n\n  const fallback = loader || (\n    <StyledScope>\n      <div className=\"flex items-center justify-center min-h-[200px]\">\n        <Spinner />\n      </div>\n    </StyledScope>\n  );\n\n  return (\n    <ThemeProvider\n      themeSettings={{\n        mode: themeSettings.mode,\n        variables: themeSettings.variables,\n        loader,\n        theme: themeSettings.theme,\n      }}\n    >\n      {mergedToastSettings.provider === 'sonner' && (\n        <Toaster\n          position={mergedToastSettings.settings?.position || 'top-right'}\n          closeButton={mergedToastSettings.settings?.closeButton ?? true}\n          className=\"auth0-universal\"\n        />\n      )}\n      {coreClient ? (\n        <CoreClientContext.Provider value={coreClientValue}>\n          <QueryProvider cacheConfig={cacheConfig}>{children}</QueryProvider>\n        </CoreClientContext.Provider>\n      ) : (\n        fallback\n      )}\n    </ThemeProvider>\n  );\n};\n\nexport default Auth0ComponentProvider;\n",
      "type": "registry:component",
      "target": "providers/spa-provider.tsx"
    },
    {
      "path": "src/providers/theme-provider.tsx",
      "content": "/**\n * Theme provider for styling configuration.\n * @module theme-provider\n * @internal\n */\n\n'use client';\n\nimport { applyStyleOverrides, type StylingVariables } from '@auth0/universal-components-core';\nimport * as React from 'react';\n\nimport { PortalContext } from '@/providers/portal-context';\nimport type { ThemeContextValue, ThemeInput } from '@/types/theme-types';\n\n/** Default empty style overrides. */\nconst defaultStyleOverrides: StylingVariables = { common: {}, light: {}, dark: {} };\n\n/**\n * Theme context for accessing theme settings.\n * @internal\n * @returns The context provider component\n */\nexport const ThemeContext = React.createContext<ThemeContextValue>({\n  isDarkMode: false,\n  variables: defaultStyleOverrides,\n  loader: null,\n});\n\n/**\n * Provides theme configuration to the component tree.\n * @param props - Component props.\n * @param props.themeSettings - Theme settings with mode, variables, and loader.\n * @param props.children - Child components.\n * @returns Theme provider.\n * @internal\n */\nexport const ThemeProvider: React.FC<{\n  themeSettings?: ThemeInput;\n  children: React.ReactNode;\n}> = ({ themeSettings, children }) => {\n  const { variables, loader, mode, theme } = React.useMemo(\n    () => ({\n      variables: themeSettings?.variables ?? defaultStyleOverrides,\n      loader: themeSettings?.loader ?? null,\n      mode: themeSettings?.mode,\n      theme: themeSettings?.theme ?? 'default',\n    }),\n    [themeSettings],\n  );\n\n  const [portalContainer, setPortalContainer] = React.useState<HTMLElement | null>(null);\n\n  React.useEffect(() => {\n    applyStyleOverrides(variables, mode, theme);\n  }, [variables, mode, theme]);\n\n  return (\n    <ThemeContext.Provider value={{ isDarkMode: mode === 'dark', theme, variables, loader }}>\n      <PortalContext.Provider value={portalContainer}>\n        {children}\n        <div className=\"auth0-universal\" data-theme={theme} ref={setPortalContainer} />\n      </PortalContext.Provider>\n    </ThemeContext.Provider>\n  );\n};\n",
      "type": "registry:component",
      "target": "providers/theme-provider.tsx"
    },
    {
      "path": "src/types/auth-types.ts",
      "content": "/**\n * Auth provider configuration types.\n * @module auth-types\n */\n\nimport type { AuthDetails, FetcherAuthParams } from '@auth0/universal-components-core';\nimport type * as React from 'react';\n\nimport type { QueryCacheConfig } from '@/types/cache-types';\nimport type { I18nOptions } from '@/types/i18n-types';\nimport type { ThemeSettings } from '@/types/theme-types';\nimport type { ToastSettings } from '@/types/toast-types';\n\n/** Props for Auth0ComponentProvider. */\nexport type Auth0ComponentProviderProps = (\n  | {\n      mode?: 'direct';\n      authContext?: AuthDetails['contextInterface'];\n      proxyConfig?: never;\n    }\n  | {\n      mode: 'proxy';\n      domain: string;\n      proxyConfig: {\n        baseUrl: string;\n        fetcher?: (\n          url: string,\n          init?: RequestInit,\n          authParams?: FetcherAuthParams,\n        ) => Promise<Response>;\n      };\n    }\n) & {\n  i18n?: I18nOptions;\n  themeSettings?: ThemeSettings;\n  loader?: React.ReactNode;\n  toastSettings?: ToastSettings;\n  /** TanStack Query cache config. Use `{ enabled: false }` to disable. */\n  cacheConfig?: QueryCacheConfig;\n  previewMode?: boolean;\n};\n",
      "type": "registry:component",
      "target": "types/auth-types.ts"
    },
    {
      "path": "src/types/cache-types.ts",
      "content": "/**\n * TanStack Query cache configuration types.\n * @module cache-types\n */\n\n/** Cache configuration options. */\nexport interface QueryCacheConfig {\n  enabled?: boolean;\n  staleTime?: number;\n  gcTime?: number;\n  refetchOnWindowFocus?: boolean | 'always';\n}\n",
      "type": "registry:component",
      "target": "types/cache-types.ts"
    },
    {
      "path": "src/types/i18n-types.ts",
      "content": "/**\n * Internationalization configuration types.\n * @module i18n-types\n */\n\n/** i18n configuration for Auth0 components. */\nexport interface I18nOptions {\n  currentLanguage: string;\n  fallbackLanguage?: string;\n}\n",
      "type": "registry:component",
      "target": "types/i18n-types.ts"
    },
    {
      "path": "src/types/my-account/mfa/mfa-types.ts",
      "content": "/**\n * MFA management types.\n * @module mfa-types\n */\n\nimport type {\n  CreateAuthenticationMethodResponseContent,\n  VerifyAuthenticationMethodResponseContent,\n  Authenticator,\n  MFAType,\n  EnrollOptions,\n  ConfirmEnrollmentOptions,\n  MFAMessages,\n  SharedComponentProps,\n} from '@auth0/universal-components-core';\nimport type { UseMutationResult, UseQueryResult } from '@tanstack/react-query';\n\nimport type {\n  ENTER_CONTACT,\n  ENTER_QR,\n  SHOW_RECOVERY_CODE,\n  QR_PHASE_INSTALLATION,\n  QR_PHASE_SCAN,\n  QR_PHASE_ENTER_OTP,\n} from '@/lib/constants/my-account/mfa/mfa-constants';\n\nexport type EnrollmentPhase =\n  | typeof ENTER_CONTACT\n  | typeof ENTER_QR\n  | typeof SHOW_RECOVERY_CODE\n  | typeof QR_PHASE_INSTALLATION\n  | typeof QR_PHASE_SCAN\n  | typeof QR_PHASE_ENTER_OTP\n  | null;\n\nexport interface UserMFAOptions {\n  showActiveOnly?: boolean;\n  readOnly?: boolean;\n  disableDelete?: boolean;\n  factorConfig?: FactorConfig;\n  customMessages?: UserMFAMgmtProps['customMessages'];\n  onFetch?: () => void;\n  onEnroll?: () => void;\n  onDelete?: () => void;\n  onErrorAction?: (error: Error, action: 'enroll' | 'delete' | 'confirm') => void;\n  onBeforeAction?: (\n    action: 'enroll' | 'delete' | 'confirm',\n    factorType: MFAType,\n  ) => boolean | Promise<boolean>;\n}\n\nexport interface UseUserMFAReturn {\n  factorsByType: Record<MFAType, Authenticator[]>;\n  isLoadingFactors: boolean;\n  isEnrolling: boolean;\n  isDeleting: boolean;\n  isConfirming: boolean;\n  error: string | null;\n  isEnrollDialogOpen: boolean;\n  enrollFactor: MFAType | null;\n  enrollmentPhase: EnrollmentPhase;\n  isDeleteDialogOpen: boolean;\n  factorToDelete: { id: string; type: MFAType } | null;\n  visibleFactorTypes: MFAType[];\n  hasNoActiveFactors: boolean;\n  contact: string;\n  otpData: { barcodeUri: string; manualInputCode: string };\n  recoveryCode: string;\n  handleCancelDelete: () => void;\n  handleConfirmDelete: () => Promise<void>;\n  handleEnroll: (factor: MFAType) => Promise<void>;\n  handleCloseEnrollDialog: () => Promise<void>;\n  handleDeleteFactor: (factorId: string, factorType: MFAType) => Promise<void>;\n  handleSendCode: (options: Record<string, string>) => Promise<boolean>;\n  handleConfirmOtp: (otpCode: string) => Promise<void>;\n  handleConfirmPush: () => Promise<void>;\n  handleConfirmRecoveryCode: () => Promise<void>;\n  handleEnterQRPhase: () => Promise<void>;\n}\n\nexport interface UseUserMFAServiceReturn {\n  factorsQuery: UseQueryResult<Record<MFAType, Authenticator[]>>;\n  enrollMutation: UseMutationResult<\n    CreateAuthenticationMethodResponseContent,\n    Error,\n    { factorType: MFAType; options?: EnrollOptions }\n  >;\n  deleteMutation: UseMutationResult<void, Error, string>;\n  verifyMutation: UseMutationResult<\n    VerifyAuthenticationMethodResponseContent,\n    Error,\n    {\n      factorType: MFAType;\n      authSession: string;\n      authenticationMethodId: string;\n      options: ConfirmEnrollmentOptions;\n    }\n  >;\n}\n\n/** Configuration for an individual MFA factor type. */\nexport interface FactorConfigOptions {\n  visible?: boolean;\n  enabled?: boolean;\n}\n\n/** MFA factor type configuration map. */\nexport type FactorConfig = Partial<Record<MFAType, FactorConfigOptions>>;\n\n/** CSS classes for UserMFAMgmt component. */\nexport interface UserMFAMgmtClasses {\n  'UserMFAMgmt-card'?: string;\n  'UserMFASetupForm-dialogContent'?: string;\n  'DeleteFactorConfirmation-dialogContent'?: string;\n}\n\n/** Props for UserMFAMgmt component. */\nexport interface UserMFAMgmtProps\n  extends SharedComponentProps<\n    MFAMessages,\n    UserMFAMgmtClasses,\n    { email?: RegExp; phone?: RegExp }\n  > {\n  /** Hide component header. */\n  hideHeader?: boolean;\n\n  /** Show only active (enrolled) factors. */\n  showActiveOnly?: boolean;\n\n  /** Disable enrolling new factors. */\n  disableEnroll?: boolean;\n\n  /**\n   * Whether to disable the ability to delete existing MFA factors.\n   * @defaultValue `false`\n   */\n  disableDelete?: boolean;\n\n  /**\n   * Whether the component should be in read-only mode.\n   * When `true`, users cannot enroll or delete factors.\n   * @defaultValue `false`\n   */\n  readOnly?: boolean;\n\n  /**\n   * Configuration for individual MFA factor types.\n   * Allows hiding or disabling specific factor types.\n   *\n   * @example\n   * ```tsx\n   * factorConfig={{\n   *   sms: { visible: true, enabled: true },\n   *   email: { visible: true, enabled: false },\n   *   otp: { visible: false },\n   * }}\n   * ```\n   *\n   * @see {@link FactorConfig} for the type definition\n   * @see {@link FactorConfigOptions} for available options per factor\n   */\n  factorConfig?: FactorConfig;\n\n  /**\n   * Callback invoked after a factor is successfully enrolled.\n   */\n  onEnroll?: () => void;\n\n  /**\n   * Callback invoked after a factor is successfully deleted.\n   */\n  onDelete?: () => void;\n\n  /**\n   * Callback invoked after factors are successfully fetched.\n   */\n  onFetch?: () => void;\n\n  /**\n   * Callback invoked when an error occurs during an MFA action.\n   * @param error - The error that occurred\n   * @param action - The action that failed ('enroll', 'delete', or 'confirm')\n   */\n  onErrorAction?: (error: Error, action: 'enroll' | 'delete' | 'confirm') => void;\n\n  /**\n   * Callback invoked before an MFA action is performed.\n   * Return `false` or a Promise resolving to `false` to cancel the action.\n   *\n   * @param action - The action about to be performed ('enroll', 'delete', or 'confirm')\n   * @param factorType - The MFA factor type involved in the action\n   * @returns `true` to proceed, `false` to cancel\n   *\n   * @example\n   * ```tsx\n   * onBeforeAction={async (action, factorType) => {\n   *   if (action === 'delete') {\n   *     return await confirmDeletion();\n   *   }\n   *   return true;\n   * }}\n   * ```\n   */\n  onBeforeAction?: (\n    action: 'enroll' | 'delete' | 'confirm',\n    factorType: MFAType,\n  ) => boolean | Promise<boolean>;\n}\n\nexport interface ContactInputFormProps\n  extends SharedComponentProps<\n    MFAMessages,\n    UserMFAMgmtClasses,\n    { email?: RegExp; phone?: RegExp }\n  > {\n  factorType: MFAType;\n  contact: string;\n  isEnrolling: boolean;\n  isConfirming: boolean;\n  onSubmitContact: (options: Record<string, string>) => Promise<boolean>;\n  onConfirmOtp: (otpCode: string) => Promise<void>;\n  onClose: () => void;\n}\n\nexport interface DeleteFactorConfirmationProps\n  extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  factorToDelete: {\n    id: string;\n    type: MFAType;\n  } | null;\n  isDeletingFactor: boolean;\n  onConfirm: () => void;\n  onCancel: () => void;\n}\n\nexport interface OTPVerificationFormProps\n  extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  factorType: MFAType;\n  contact?: string;\n  isConfirming: boolean;\n  onConfirmOtp: (otpCode: string) => Promise<void>;\n  onBack?: () => void;\n}\n\nexport interface QRCodeEnrollmentFormProps\n  extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  factorType: MFAType;\n  barcodeUri: string;\n  manualInputCode: string;\n  isEnrolling: boolean;\n  isConfirming: boolean;\n  onContinueQR: () => Promise<void>;\n  onConfirmOtp: (otpCode: string) => Promise<void>;\n  onClose: () => void;\n}\n\nexport interface UserMFASetupFormProps\n  extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  open: boolean;\n  onClose: () => void;\n  factorType: MFAType;\n  enrollmentPhase: EnrollmentPhase;\n  contact: string;\n  otpData: { barcodeUri: string; manualInputCode: string };\n  recoveryCode: string;\n  isEnrolling: boolean;\n  isConfirming: boolean;\n  onSubmitContact: (options: Record<string, string>) => Promise<boolean>;\n  onConfirmOtp: (otpCode: string) => Promise<void>;\n  onContinueQR: () => Promise<void>;\n  onConfirmRecoveryCode: () => Promise<void>;\n  onAdvanceToQR: () => void;\n}\n\nexport interface ShowRecoveryCodeProps\n  extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  recoveryCode: string;\n  isEnrolling: boolean;\n  isConfirming: boolean;\n  onConfirmRecoveryCode: () => Promise<void>;\n  onClose: () => void;\n}\n\nexport interface FactorsListProps extends SharedComponentProps<MFAMessages, UserMFAMgmtClasses> {\n  factors: Authenticator[];\n  factorType: MFAType;\n  readOnly: boolean;\n  isEnabledFactor: boolean;\n  onDeleteFactor: (factorId: string, factorType: MFAType) => void;\n  isDeletingFactor: boolean;\n  disableDelete: boolean;\n}\n\nexport interface UserMFAMgmtViewProps {\n  error: string | null;\n  schema: UserMFAMgmtProps['schema'];\n  isEnrolling: boolean;\n  isDeleting: boolean;\n  isConfirming: boolean;\n  styling: UserMFAMgmtProps['styling'];\n  customMessages: UserMFAMgmtProps['customMessages'];\n  hideHeader: boolean;\n  showActiveOnly: boolean;\n  disableEnroll: boolean;\n  disableDelete: boolean;\n  readOnly: boolean;\n  factorConfig?: FactorConfig;\n  isEnrollDialogOpen: boolean;\n  enrollFactor: MFAType | null;\n  enrollmentPhase: EnrollmentPhase;\n  contact: string;\n  otpData: { barcodeUri: string; manualInputCode: string };\n  recoveryCode: string;\n  isDeleteDialogOpen: boolean;\n  factorToDelete: { id: string; type: MFAType } | null;\n  factorsByType: Record<MFAType, Authenticator[]>;\n  visibleFactorTypes: MFAType[];\n  hasNoActiveFactors: boolean;\n  onEnrollFactor: (factor: MFAType) => void;\n  onDeleteFactor: (factorId: string, factorType: MFAType) => Promise<void>;\n  onCloseEnrollDialog: () => void;\n  onConfirmDelete: () => Promise<void>;\n  onCancelDelete: () => void;\n  onSubmitContact: (options: Record<string, string>) => Promise<boolean>;\n  onConfirmOtp: (otpCode: string) => Promise<void>;\n  onContinueQR: () => Promise<void>;\n  onConfirmRecoveryCode: () => Promise<void>;\n  onAdvanceToQR: () => void;\n}\n",
      "type": "registry:component",
      "target": "types/my-account/mfa/mfa-types.ts"
    },
    {
      "path": "src/types/theme-types.ts",
      "content": "/**\n * Theme configuration types.\n * @module theme-types\n */\n\nimport type { StylingVariables } from '@auth0/universal-components-core';\nimport type React from 'react';\n\n/** Theme settings for provider. */\nexport interface ThemeSettings {\n  theme?: 'default' | 'minimal' | 'rounded';\n  mode?: 'light' | 'dark';\n  variables?: StylingVariables;\n}\n\n/** Theme input for ThemeProvider. */\nexport type ThemeInput = {\n  theme?: 'default' | 'minimal' | 'rounded';\n  mode?: 'light' | 'dark';\n  variables?: StylingVariables;\n  loader?: React.ReactNode;\n};\n\n/** Theme context value. */\nexport type ThemeContextValue = {\n  theme?: 'default' | 'minimal' | 'rounded';\n  isDarkMode?: boolean;\n  variables: StylingVariables;\n  loader: React.ReactNode | null;\n};\n",
      "type": "registry:component",
      "target": "types/theme-types.ts"
    },
    {
      "path": "src/types/toast-types.ts",
      "content": "/**\n * Toast notification types.\n * @module toast-types\n */\n\nimport type { ReactNode } from 'react';\nimport type { ExternalToast } from 'sonner';\n\n/** Toast notification type. */\nexport type ToastType = 'success' | 'info' | 'warning' | 'error';\n\n/** Toast position options. */\nexport type ToastPosition =\n  | 'top-left'\n  | 'top-right'\n  | 'bottom-left'\n  | 'bottom-right'\n  | 'top-center'\n  | 'bottom-center';\n\n/** Custom toast method signature. */\nexport interface CustomToastMethod {\n  (message: string): void;\n}\n\n/** Custom toast methods for overriding default behavior. */\nexport interface CustomToastMethods {\n  success?: CustomToastMethod;\n  error?: CustomToastMethod;\n  warning?: CustomToastMethod;\n  info?: CustomToastMethod;\n  dismiss?: (toastId?: string) => void;\n}\n\n/** Sonner toast settings. */\nexport interface SonnerSettings {\n  position?: ToastPosition;\n  maxToasts?: number;\n  duration?: number;\n  dismissible?: boolean;\n  closeButton?: boolean;\n}\n\n/** Toast provider configuration. */\nexport type ToastSettings =\n  | { provider?: 'sonner'; settings?: SonnerSettings }\n  | { provider: 'custom'; methods: CustomToastMethods };\n\n/** Toast options for showToast. */\nexport interface ToastOptions {\n  type: ToastType;\n  message: string;\n  className?: string;\n  icon?: ReactNode;\n  data?: ExternalToast;\n}\n\n/** Default toast settings. */\nexport const DEFAULT_TOAST_SETTINGS: ToastSettings = {\n  provider: 'sonner',\n  settings: {\n    position: 'top-right',\n    closeButton: true,\n  },\n} as const;\n",
      "type": "registry:component",
      "target": "types/toast-types.ts"
    },
    {
      "path": "src/lib/constants/form-constants.ts",
      "content": "/**\n * Form constants used across the components.\n * @internal\n */\n\nexport const FORM_VALIDATION_MODE = 'onTouched';\nexport const FORM_REVALIDATE_MODE = 'onChange';\n",
      "type": "registry:component",
      "target": "lib/constants/form-constants.ts"
    },
    {
      "path": "src/lib/constants/my-account/mfa/mfa-constants.ts",
      "content": "/**\n * MFA enrollment flow constants.\n * @module mfa-constants\n * @internal\n */\n\nexport const ENTER_OTP = 'enterOtp';\nexport const ENTER_QR = 'showQr';\nexport const ENTER_CONTACT = 'enterContact';\n\nexport const ENROLL = 'enroll';\nexport const CONFIRM = 'confirm';\n\nexport const QR_PHASE_INSTALLATION = 'installation';\nexport const QR_PHASE_SCAN = 'scan';\nexport const QR_PHASE_ENTER_OTP = 'enter-otp';\nexport const SHOW_RECOVERY_CODE = 'show_recovery';\n",
      "type": "registry:component",
      "target": "lib/constants/my-account/mfa/mfa-constants.ts"
    },
    {
      "path": "src/lib/utils.ts",
      "content": "/**\n * Tailwind CSS utility functions.\n * @module utils\n * @internal\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merges class names with Tailwind CSS conflict resolution.\n * @param inputs - Input values to process\n * @returns The merged class name string\n * @internal\n */\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n",
      "type": "registry:component",
      "target": "lib/utils.ts"
    },
    {
      "path": "src/assets/icons/apple-logo.tsx",
      "content": "/**\n * Apple logo icon component.\n * @module apple-logo\n * @internal\n */\n\nimport { AppleLogoSvg } from '@auth0/universal-components-core';\nimport React from 'react';\n\nexport interface AppleLogoProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n  width?: number | string;\n  height?: number | string;\n  title?: string;\n}\n\n/**\n * AppleLogo component renders the Apple SVG logo.\n *\n * @param props - Props including width, height, title, and standard SVG attributes.\n * @returns A JSX element with the Apple logo image.\n */\nconst AppleLogo: React.FC<AppleLogoProps> = ({\n  width = 30,\n  height = 30,\n  title = 'Apple logo',\n  className,\n  ...props\n}) => {\n  return (\n    <img\n      src={AppleLogoSvg}\n      alt={title}\n      width={width}\n      height={height}\n      className={className}\n      {...props}\n    />\n  );\n};\n\nexport default React.memo(AppleLogo);\n",
      "type": "registry:component",
      "target": "assets/icons/apple-logo.tsx"
    },
    {
      "path": "src/assets/icons/google-logo.tsx",
      "content": "/**\n * Google logo icon component.\n * @module google-logo\n * @internal\n */\n\nimport { GoogleLogoSvg } from '@auth0/universal-components-core';\nimport React from 'react';\n\nexport interface GoogleLogoProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n  width?: number | string;\n  height?: number | string;\n  title?: string;\n}\n\n/**\n * GoogleLogo component renders the Google \"G\" logo SVG.\n *\n * @param props - Props including width, height, title, and standard SVG attributes.\n * @returns A JSX SVG element of the Google logo.\n */\nconst GoogleLogo: React.FC<GoogleLogoProps> = ({\n  width = 48,\n  height = 48,\n  title = 'Google logo',\n  className,\n  ...props\n}) => {\n  return (\n    <img\n      src={GoogleLogoSvg}\n      alt={title}\n      width={width}\n      height={height}\n      className={className}\n      {...props}\n    />\n  );\n};\n\nexport default React.memo(GoogleLogo);\n",
      "type": "registry:component",
      "target": "assets/icons/google-logo.tsx"
    },
    {
      "path": "src/styles/globals.css",
      "content": "@import 'tailwindcss' important;\n@import '@auth0/universal-components-core/styles/globals.css';\n",
      "type": "registry:component",
      "target": "styles/globals.css"
    },
    {
      "path": "src/styles/tailwind.css",
      "content": "/* Scan component library for class names */\n@source \"./**/*.js\";\n",
      "type": "registry:component",
      "target": "styles/tailwind.css"
    }
  ],
  "meta": {
    "coreVersion": "2.1.0"
  }
}
