{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "delete-user",
  "title": "Delete User",
  "description": "Delete-user plugin: danger zone with DeleteAccount card and confirmation dialog. Registers a DangerZone security card in account settings when the plugin is registered.",
  "dependencies": [
    "@better-auth-ui/react@latest",
    "@better-auth-ui/core@latest",
    "better-auth",
    "lucide-react"
  ],
  "registryDependencies": [
    "alert-dialog",
    "button",
    "card",
    "field",
    "input",
    "input-group",
    "sonner",
    "spinner"
  ],
  "files": [
    {
      "path": "src/lib/auth/auth-plugin.ts",
      "content": "import type {\n  AuthPluginComponents,\n  AuthPlugin as AuthPluginPrimitive\n} from \"@better-auth-ui/react\"\n\ndeclare module \"@better-auth-ui/core\" {\n  /** Widens `useAuth().plugins` to the shadcn-typed `AuthPlugin`. */\n  interface AuthPluginRegister {\n    shadcn: AuthPlugin\n  }\n}\n\n/** Props the shadcn `<Auth>` router spreads onto plugin-contributed auth views. */\nexport type AuthViewProps = {\n  className?: string\n  socialLayout?: \"auto\" | \"horizontal\" | \"vertical\" | \"grid\"\n  socialPosition?: \"top\" | \"bottom\"\n}\n\n/** Props the shadcn `<Settings>` router spreads onto plugin-contributed settings views. */\nexport type SettingsViewProps = {\n  className?: string\n}\n\n/** Shadcn plugin type. Plugin authors import this from `@/lib/auth/auth-plugin`. */\nexport type AuthPlugin = AuthPluginPrimitive<\n  AuthPluginComponents,\n  AuthViewProps,\n  SettingsViewProps\n>\n",
      "type": "registry:lib",
      "target": "@lib/auth/auth-plugin.ts"
    },
    {
      "path": "src/lib/auth/delete-user-plugin.ts",
      "content": "import { createAuthPlugin } from \"@better-auth-ui/core\"\nimport {\n  deleteUserPlugin as coreDeleteUserPlugin,\n  type DeleteUserPluginOptions\n} from \"@better-auth-ui/core/plugins\"\n\nimport { DangerZone } from \"@/components/auth/delete-user/danger-zone\"\n\nexport const deleteUserPlugin = createAuthPlugin(\n  coreDeleteUserPlugin.id,\n  (options: DeleteUserPluginOptions = {}) => ({\n    ...coreDeleteUserPlugin(options),\n    securityCards: [DangerZone]\n  })\n)\n",
      "type": "registry:lib",
      "target": "@lib/auth/delete-user-plugin.ts"
    },
    {
      "path": "src/components/auth/delete-user/danger-zone.tsx",
      "content": "\"use client\"\n\nimport { useAuth } from \"@better-auth-ui/react\"\nimport type { ComponentProps } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { DeleteAccount } from \"./delete-account\"\n\nexport type DangerZoneProps = {\n  className?: string\n}\n\n/**\n * Renders the danger zone heading and {@link DeleteAccount}.\n * Registered as a `securityCard` by `deleteUserPlugin()`; gate by registering the plugin.\n */\nexport function DangerZone({\n  className,\n  ...props\n}: DangerZoneProps & Omit<ComponentProps<\"div\">, \"children\" | \"className\">) {\n  const { localization } = useAuth()\n\n  return (\n    <div className={cn(\"flex w-full flex-col\", className)} {...props}>\n      <h2 className=\"text-sm font-semibold mb-3 text-destructive\">\n        {localization.settings.dangerZone}\n      </h2>\n\n      <DeleteAccount />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/delete-user/danger-zone.tsx"
    },
    {
      "path": "src/components/auth/delete-user/delete-account.tsx",
      "content": "\"use client\"\n\nimport { authQueryKeys } from \"@better-auth-ui/core\"\nimport {\n  useAuth,\n  useAuthPlugin,\n  useDeleteUser,\n  useListAccounts\n} from \"@better-auth-ui/react\"\nimport { useQueryClient } from \"@tanstack/react-query\"\nimport { Eye, EyeOff, TriangleAlert } from \"lucide-react\"\nimport { type SyntheticEvent, useState } from \"react\"\nimport { toast } from \"sonner\"\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogMedia,\n  AlertDialogTitle,\n  AlertDialogTrigger\n} from \"@/components/ui/alert-dialog\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { Field, FieldError, FieldLabel } from \"@/components/ui/field\"\nimport {\n  InputGroup,\n  InputGroupAddon,\n  InputGroupButton,\n  InputGroupInput\n} from \"@/components/ui/input-group\"\nimport { Spinner } from \"@/components/ui/spinner\"\nimport { deleteUserPlugin } from \"@/lib/auth/delete-user-plugin\"\nimport { cn } from \"@/lib/utils\"\n\nexport type DeleteAccountProps = {\n  className?: string\n}\n\n/**\n * Danger-zone card to delete the authenticated account, with a confirmation dialog and toasts.\n */\nexport function DeleteAccount({ className }: DeleteAccountProps) {\n  const { authClient, basePaths, localization, viewPaths, navigate } = useAuth()\n\n  const {\n    localization: deleteUserLocalization,\n    sendDeleteAccountVerification\n  } = useAuthPlugin(deleteUserPlugin)\n\n  const { data: accounts } = useListAccounts(authClient)\n\n  const queryClient = useQueryClient()\n\n  const [confirmOpen, setConfirmOpen] = useState(false)\n  const [password, setPassword] = useState(\"\")\n  const [isPasswordVisible, setIsPasswordVisible] = useState(false)\n\n  const hasCredentialAccount = accounts?.some(\n    (account) => account.providerId === \"credential\"\n  )\n  const needsPassword = !sendDeleteAccountVerification && hasCredentialAccount\n\n  const { mutate: deleteUser, isPending } = useDeleteUser(authClient)\n\n  const handleDialogOpenChange = (open: boolean) => {\n    setConfirmOpen(open)\n    setPassword(\"\")\n    setIsPasswordVisible(false)\n  }\n\n  const handleSubmit = async (e: SyntheticEvent<HTMLFormElement>) => {\n    e.preventDefault()\n\n    const params = {\n      ...(needsPassword ? { password } : {})\n    }\n\n    deleteUser(params, {\n      onSuccess: () => {\n        setConfirmOpen(false)\n        setPassword(\"\")\n\n        if (sendDeleteAccountVerification) {\n          toast.success(deleteUserLocalization.deleteUserVerificationSent)\n        } else {\n          toast.success(deleteUserLocalization.deleteUserSuccess)\n          queryClient.removeQueries({ queryKey: authQueryKeys.all })\n          navigate({\n            to: `${basePaths.auth}/${viewPaths.auth.signIn}`,\n            replace: true\n          })\n        }\n      }\n    })\n  }\n\n  return (\n    <Card className={cn(\"border-destructive\", className)}>\n      <CardContent className=\"flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <p className=\"text-sm font-medium leading-tight\">\n            {deleteUserLocalization.deleteAccount}\n          </p>\n\n          <p className=\"text-muted-foreground text-xs mt-0.5\">\n            {deleteUserLocalization.deleteAccountDescription}\n          </p>\n        </div>\n\n        <AlertDialog open={confirmOpen} onOpenChange={handleDialogOpenChange}>\n          <AlertDialogTrigger\n            className={cn(\n              buttonVariants({ variant: \"destructive\", size: \"sm\" })\n            )}\n            disabled={!accounts}\n          >\n            {deleteUserLocalization.deleteAccount}\n          </AlertDialogTrigger>\n\n          <AlertDialogContent>\n            <form onSubmit={handleSubmit} className=\"flex flex-col gap-6\">\n              <AlertDialogHeader>\n                <AlertDialogMedia className=\"bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive\">\n                  <TriangleAlert />\n                </AlertDialogMedia>\n\n                <AlertDialogTitle>\n                  {deleteUserLocalization.deleteAccount}\n                </AlertDialogTitle>\n\n                <AlertDialogDescription>\n                  {deleteUserLocalization.deleteAccountDescription}\n                </AlertDialogDescription>\n              </AlertDialogHeader>\n\n              {needsPassword && (\n                <Field>\n                  <FieldLabel htmlFor=\"delete-password\">\n                    {localization.auth.password}\n                  </FieldLabel>\n\n                  <InputGroup>\n                    <InputGroupInput\n                      id=\"delete-password\"\n                      name=\"password\"\n                      type={isPasswordVisible ? \"text\" : \"password\"}\n                      autoComplete=\"current-password\"\n                      placeholder={localization.auth.passwordPlaceholder}\n                      value={password}\n                      onChange={(e) => setPassword(e.target.value)}\n                      disabled={isPending}\n                      required\n                    />\n\n                    <InputGroupAddon align=\"inline-end\">\n                      <InputGroupButton\n                        size=\"icon-xs\"\n                        aria-label={\n                          isPasswordVisible\n                            ? localization.auth.hidePassword\n                            : localization.auth.showPassword\n                        }\n                        title={\n                          isPasswordVisible\n                            ? localization.auth.hidePassword\n                            : localization.auth.showPassword\n                        }\n                        onClick={() => {\n                          setIsPasswordVisible((visible) => !visible)\n                        }}\n                      >\n                        {isPasswordVisible ? <EyeOff /> : <Eye />}\n                      </InputGroupButton>\n                    </InputGroupAddon>\n                  </InputGroup>\n\n                  <FieldError />\n                </Field>\n              )}\n\n              <AlertDialogFooter>\n                <AlertDialogCancel disabled={isPending}>\n                  {localization.settings.cancel}\n                </AlertDialogCancel>\n\n                <Button\n                  type=\"submit\"\n                  variant=\"destructive\"\n                  disabled={isPending}\n                >\n                  {isPending && <Spinner />}\n\n                  {deleteUserLocalization.deleteAccount}\n                </Button>\n              </AlertDialogFooter>\n            </form>\n          </AlertDialogContent>\n        </AlertDialog>\n      </CardContent>\n    </Card>\n  )\n}\n",
      "type": "registry:component",
      "target": "@components/auth/delete-user/delete-account.tsx"
    }
  ],
  "type": "registry:component"
}