{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dialog-01",
  "description": "Complex user management UI with nested dialogs.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@lumi-ui/dialog",
    "@lumi-ui/alert-dialog",
    "@lumi-ui/dropdown-menu",
    "@lumi-ui/button",
    "@lumi-ui/select",
    "@lumi-ui/toast",
    "@lumi-ui/separator"
  ],
  "files": [
    {
      "path": "registry/blocks/dialog-01/page.tsx",
      "content": "import { TeamManagement } from \"./components/team-management\";\n\nexport default function Page() {\n  return (\n    <div className=\"h-screen flex justify-center items-center w-screen\">\n      <TeamManagement />\n    </div>\n  );\n}\n",
      "type": "registry:page",
      "target": "app/dashboard/page.tsx"
    },
    {
      "path": "registry/blocks/dialog-01/components/team-management.tsx",
      "content": "\"use client\";\n\nimport type { DialogRootChangeEventDetails } from \"@base-ui/react\";\nimport {\n  ChevronsUpDownIcon,\n  Eye,\n  Loader2,\n  MoreHorizontal,\n  ShieldAlert,\n  ShieldCheck,\n  Trash2,\n  User,\n} from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  AlertDialog,\n  AlertDialogClose,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n  createAlertDialogHandle,\n} from \"@/registry/ui/alert-dialog\";\nimport { Badge } from \"@/registry/ui/badge\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  createDialogHandle,\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from \"@/registry/ui/dialog\";\nimport {\n  createDropdownMenuHandle,\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"@/registry/ui/dropdown-menu\";\nimport { Label } from \"@/registry/ui/label\";\nimport {\n  Select,\n  SelectContent,\n  SelectItemContent,\n  SelectTriggerGroup,\n} from \"@/registry/ui/select\";\nimport { Separator } from \"@/registry/ui/separator\";\nimport { toast } from \"@/registry/ui/toast\";\nimport { MemberCard } from \"./member-card\";\n\nexport type TeamMember = {\n  id: string;\n  name: string;\n  email: string;\n  role: \"Admin\" | \"Member\" | \"Viewer\";\n  initials: string;\n};\n\nconst menuHandle = createDropdownMenuHandle<TeamMember>();\nconst editMemberDialogHandle = createDialogHandle<TeamMember>();\nconst removeMemberDialogHandle = createDialogHandle<TeamMember>();\nconst confirmDeleteDialogHandle = createAlertDialogHandle<TeamMember>();\nconst closeConfirmDialogHandle = createAlertDialogHandle();\n\nexport function TeamManagement() {\n  const [members, setMembers] =\n    React.useState<TeamMember[]>(INITIAL_TEAM_MEMBERS);\n  const [selectedRole, setSelectedRole] = React.useState<\n    TeamMember[\"role\"] | null\n  >(null);\n  const [editingMember, setEditingMember] = React.useState<TeamMember | null>(\n    null,\n  );\n  const [editOpen, setEditOpen] = React.useState(false);\n  const [editTriggerId, setEditTriggerId] = React.useState<string | null>(null);\n\n  const [removeOpen, setRemoveOpen] = React.useState(false);\n  const [removeTriggerId, setRemoveTriggerId] = React.useState<string | null>(\n    null,\n  );\n\n  const [confirmDeleteOpen, setConfirmDeleteOpen] = React.useState(false);\n  const [confirmDeleteTriggerId, setConfirmDeleteTriggerId] = React.useState<\n    string | null\n  >(null);\n\n  const [isUpdating, setIsUpdating] = React.useState(false);\n  const [isDeleting, setIsDeleting] = React.useState(false);\n\n  const handleReset = () => {\n    setMembers(INITIAL_TEAM_MEMBERS);\n    setSelectedRole(null);\n  };\n\n  const handleDeleteMember = async (memberId: string) => {\n    setIsDeleting(true);\n\n    toast.promise(\n      new Promise<void>((resolve, reject) => {\n        setTimeout(() => {\n          const shouldSucceed = Math.random() > 0.1;\n          if (shouldSucceed) {\n            setMembers((prev) => prev.filter((m) => m.id !== memberId));\n            resolve();\n          } else {\n            reject(new Error(\"Failed to delete member.\"));\n          }\n        }, 1500);\n      }),\n      {\n        error: (err: Error) => {\n          setIsDeleting(false);\n          return { description: err.message, title: \"Error\" };\n        },\n        loading: { title: \"Deleting member...\" },\n        success: () => {\n          setConfirmDeleteOpen(false);\n          setRemoveOpen(false);\n          setIsDeleting(false);\n          return {\n            description: \"Member deleted successfully\",\n            title: \"Success\",\n          };\n        },\n      },\n    );\n  };\n\n  const handleUpdateRole = async (\n    memberId: string,\n    newRole: TeamMember[\"role\"],\n  ) => {\n    setIsUpdating(true);\n\n    toast.promise(\n      new Promise<void>((resolve, reject) => {\n        setTimeout(() => {\n          const shouldSucceed = Math.random() > 0.1;\n          if (shouldSucceed) {\n            setMembers((prev) =>\n              prev.map((m) =>\n                m.id === memberId ? { ...m, role: newRole } : m,\n              ),\n            );\n            resolve();\n          } else {\n            reject(new Error(\"Failed to update role.\"));\n          }\n        }, 1500);\n      }),\n      {\n        error: (err: Error) => {\n          setIsUpdating(false);\n          return { description: err.message, title: \"Error\" };\n        },\n        loading: { title: \"Updating role...\" },\n        success: () => {\n          setEditOpen(false);\n          setSelectedRole(null);\n          setIsUpdating(false);\n          return { description: \"Role updated successfully\", title: \"Success\" };\n        },\n      },\n    );\n  };\n\n  const handleConfirmDiscard = () => {\n    closeConfirmDialogHandle.close();\n    setEditOpen(false);\n    setSelectedRole(null);\n  };\n\n  const handleEditDialogChange = (\n    isOpen: boolean,\n    eventDetails: DialogRootChangeEventDetails,\n  ) => {\n    if (!isOpen && selectedRole !== null && editingMember) {\n      if (selectedRole !== editingMember.role) {\n        closeConfirmDialogHandle.open(null);\n        return; // Prevents the dialog from closing\n      }\n    }\n\n    setEditOpen(isOpen);\n\n    if (isOpen) {\n      setEditTriggerId(eventDetails.trigger?.id ?? null);\n    } else {\n      setSelectedRole(null);\n      setEditingMember(null);\n    }\n  };\n\n  return (\n    <div className=\"w-full max-w-2xl mx-auto border rounded-md\">\n      <div className=\"flex justify-between p-6\">\n        <div className=\"space-y-2\">\n          <div className=\"text-lg font-semibold\">Team Members</div>\n          <div className=\"text-sm text-muted-foreground\">\n            Manage your team members and their account permissions.\n          </div>\n        </div>\n        <Button onClick={handleReset} size=\"sm\" variant=\"outline\">\n          Reset\n        </Button>\n      </div>\n      <Separator />\n\n      <div className=\"flex flex-col gap-6 p-6 min-h-140\">\n        {members.map((member) => (\n          <div\n            className=\"flex items-center justify-between space-x-4\"\n            key={member.id}\n          >\n            <MemberCard member={member} />\n            <div className=\"flex items-center gap-3\">\n              <Badge\n                variant={member.role === \"Admin\" ? \"default\" : \"secondary\"}\n              >\n                {member.role}\n              </Badge>\n\n              {/* Detached Trigger */}\n              <DropdownMenuTrigger\n                handle={menuHandle}\n                payload={member}\n                render={(props, state) => {\n                  return (\n                    <Button\n                      className={cn(state.open && \"bg-accent hover:bg-accent!\")}\n                      size=\"icon-xs\"\n                      variant={\"ghost\"}\n                      {...props}\n                    >\n                      <MoreHorizontal className=\"size-4\" />\n                      <span className=\"sr-only\">\n                        Open menu for {member.name}\n                      </span>\n                    </Button>\n                  );\n                }}\n              />\n            </div>\n          </div>\n        ))}\n      </div>\n\n      <DropdownMenu handle={menuHandle}>\n        {({ payload: member }) => (\n          <DropdownMenuContent\n            align=\"center\"\n            className=\"w-40\"\n            matchAnchorWidth={false}\n          >\n            <DropdownMenuItem\n              onClick={() => {\n                setEditingMember(member as TeamMember);\n                editMemberDialogHandle.openWithPayload(member as TeamMember);\n              }}\n            >\n              <Eye className=\"size-4\" />\n              <span>View member</span>\n            </DropdownMenuItem>\n            <DropdownMenuItem\n              onClick={() =>\n                removeMemberDialogHandle.openWithPayload(member as TeamMember)\n              }\n              variant=\"destructive\"\n            >\n              <Trash2 className=\"size-4\" />\n              <span>Delete member</span>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        )}\n      </DropdownMenu>\n\n      {/* Edit Dialog */}\n      <Dialog\n        handle={editMemberDialogHandle}\n        onOpenChange={handleEditDialogChange}\n        open={editOpen}\n        triggerId={editTriggerId}\n      >\n        {({ payload }) => {\n          const currentRole = selectedRole || payload?.role;\n          const isDirty = currentRole !== payload?.role;\n          const isSaveDisabled = isUpdating || !isDirty;\n          return (\n            <DialogContent layout=\"stacked\" showCloseButton>\n              <DialogHeader>\n                <DialogTitle>Edit Permissions</DialogTitle>\n                {payload && (\n                  <DialogDescription>\n                    Change the access level for{\" \"}\n                    <span className=\"font-medium text-foreground\">\n                      {payload.name}\n                    </span>\n                  </DialogDescription>\n                )}\n              </DialogHeader>\n              {payload && (\n                <div className=\"grid gap-6 py-4\">\n                  <MemberCard member={payload} />\n\n                  <div className=\"space-y-2\">\n                    <Label>Role</Label>\n                    <Select\n                      disabled={isUpdating}\n                      onValueChange={(value) =>\n                        setSelectedRole(value as TeamMember[\"role\"])\n                      }\n                      value={currentRole}\n                    >\n                      <SelectTriggerGroup\n                        indicatorIcon={<ChevronsUpDownIcon />}\n                      />\n                      <SelectContent alignItemWithTrigger>\n                        <SelectItemContent value=\"Admin\">\n                          <ShieldAlert className=\"size-4 opacity-50\" />\n                          <span>Admin</span>\n                        </SelectItemContent>\n                        <SelectItemContent value=\"Member\">\n                          <ShieldCheck className=\"size-4 opacity-50\" />\n                          <span>Member</span>\n                        </SelectItemContent>\n                        <SelectItemContent value=\"Viewer\">\n                          <User className=\"size-4 opacity-50\" />\n                          <span>Viewer</span>\n                        </SelectItemContent>\n                      </SelectContent>\n                    </Select>\n                  </div>\n                </div>\n              )}\n\n              <DialogFooter>\n                <DialogClose\n                  disabled={isUpdating}\n                  render={<Button variant=\"outline\" />}\n                >\n                  Cancel\n                </DialogClose>\n                <Button\n                  disabled={isSaveDisabled}\n                  onClick={() => {\n                    if (payload && currentRole) {\n                      handleUpdateRole(payload.id, currentRole);\n                    }\n                  }}\n                >\n                  {isUpdating ? (\n                    <>\n                      <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n                      Saving...\n                    </>\n                  ) : (\n                    \"Save Changes\"\n                  )}\n                </Button>\n              </DialogFooter>\n              {/* Discard Confirmation */}\n              <AlertDialog handle={closeConfirmDialogHandle}>\n                <AlertDialogContent layout=\"stacked\">\n                  <AlertDialogHeader>\n                    <AlertDialogTitle>Discard changes?</AlertDialogTitle>\n                    <AlertDialogDescription>\n                      You have unsaved changes. Are you sure you want to close?\n                      The changes you made will be lost.\n                    </AlertDialogDescription>\n                  </AlertDialogHeader>\n                  <AlertDialogFooter>\n                    <AlertDialogClose render={<Button variant=\"outline\" />}>\n                      No, Keep Editing\n                    </AlertDialogClose>\n                    <Button\n                      onClick={handleConfirmDiscard}\n                      variant=\"destructive\"\n                    >\n                      Yes, Discard\n                    </Button>\n                  </AlertDialogFooter>\n                </AlertDialogContent>\n              </AlertDialog>\n            </DialogContent>\n          );\n        }}\n      </Dialog>\n\n      {/* Remove Dialog */}\n      <Dialog\n        handle={removeMemberDialogHandle}\n        onOpenChange={(open, event) => {\n          setRemoveOpen(open);\n          if (open) setRemoveTriggerId(event.trigger?.id ?? null);\n        }}\n        open={removeOpen}\n        triggerId={removeTriggerId}\n      >\n        {({ payload }) => (\n          <DialogContent layout=\"stacked\">\n            <DialogHeader>\n              <DialogTitle>Remove Member</DialogTitle>\n              <DialogDescription>\n                Review the member details before removing.\n              </DialogDescription>\n            </DialogHeader>\n            {payload && <MemberCard member={payload} />}\n            <DialogFooter>\n              <DialogClose\n                render={\n                  <Button disabled={isDeleting} variant=\"outline\">\n                    Cancel\n                  </Button>\n                }\n              />\n              <AlertDialogTrigger\n                handle={confirmDeleteDialogHandle}\n                id={`confirm-delete-trigger-${payload?.id}`}\n                payload={payload}\n                render={\n                  <Button disabled={isDeleting} variant=\"destructive\">\n                    Delete Member\n                  </Button>\n                }\n              />\n            </DialogFooter>\n\n            {/* Confirm Delete Dialog */}\n            <AlertDialog\n              handle={confirmDeleteDialogHandle}\n              onOpenChange={(open, event) => {\n                setConfirmDeleteOpen(open);\n                if (open) setConfirmDeleteTriggerId(event.trigger?.id ?? null);\n              }}\n              open={confirmDeleteOpen}\n              triggerId={confirmDeleteTriggerId}\n            >\n              {({ payload: confirmPayload }) => (\n                <AlertDialogContent layout=\"stacked\">\n                  <AlertDialogHeader>\n                    <AlertDialogTitle>\n                      Are you absolutely sure?\n                    </AlertDialogTitle>\n                    <AlertDialogDescription>\n                      This action cannot be undone. This will permanently remove{\" \"}\n                      <span className=\"font-medium text-foreground\">\n                        {confirmPayload?.name}\n                      </span>{\" \"}\n                      from the team.\n                    </AlertDialogDescription>\n                  </AlertDialogHeader>\n                  <AlertDialogFooter>\n                    <AlertDialogClose\n                      disabled={isDeleting}\n                      onClick={() => {\n                        setConfirmDeleteOpen(false);\n                      }}\n                      render={<Button variant=\"outline\" />}\n                    >\n                      Cancel\n                    </AlertDialogClose>\n                    <Button\n                      disabled={isDeleting}\n                      onClick={() => {\n                        if (confirmPayload) {\n                          handleDeleteMember(confirmPayload.id);\n                        }\n                      }}\n                      variant=\"destructive\"\n                    >\n                      {isDeleting ? (\n                        <>\n                          <Loader2 className=\"animate-spin\" />\n                          Deleting...\n                        </>\n                      ) : (\n                        \"Confirm Deletion\"\n                      )}\n                    </Button>\n                  </AlertDialogFooter>\n                </AlertDialogContent>\n              )}\n            </AlertDialog>\n          </DialogContent>\n        )}\n      </Dialog>\n    </div>\n  );\n}\n\nconst INITIAL_TEAM_MEMBERS: TeamMember[] = [\n  {\n    email: \"sofia@example.com\",\n    id: \"1\",\n    initials: \"SD\",\n    name: \"Sofia Davis\",\n    role: \"Admin\",\n  },\n  {\n    email: \"jackson@example.com\",\n    id: \"2\",\n    initials: \"JL\",\n    name: \"Jackson Lee\",\n    role: \"Member\",\n  },\n  {\n    email: \"isabella@example.com\",\n    id: \"3\",\n    initials: \"IN\",\n    name: \"Isabella Nguyen\",\n    role: \"Viewer\",\n  },\n  {\n    email: \"lucy@example.com\",\n    id: \"4\",\n    initials: \"LU\",\n    name: \"Lucy Wang\",\n    role: \"Member\",\n  },\n  {\n    email: \"matt@example.com\",\n    id: \"5\",\n    initials: \"MA\",\n    name: \"Matthew Brown\",\n    role: \"Viewer\",\n  },\n  {\n    email: \"alex@example.com\",\n    id: \"6\",\n    initials: \"AL\",\n    name: \"Alexander Johnson\",\n    role: \"Admin\",\n  },\n  {\n    email: \"allen@example.com\",\n    id: \"7\",\n    initials: \"AL\",\n    name: \"Allen Lee\",\n    role: \"Member\",\n  },\n];\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-01/components/member-card.tsx",
      "content": "import { cn } from \"@/lib/utils\";\nimport { Avatar, AvatarFallback } from \"@/registry/ui/avatar\";\nimport type { TeamMember } from \"./team-management\";\n\nexport const MemberCard = ({\n  member,\n  className,\n}: {\n  member: TeamMember;\n  className?: string;\n}) => {\n  return (\n    <div\n      className={cn(\n        \"flex items-center justify-between space-x-4 p-2\",\n        className,\n      )}\n    >\n      <div className=\"flex items-center space-x-4\">\n        <Avatar>\n          <AvatarFallback>{member.initials}</AvatarFallback>\n        </Avatar>\n        <div>\n          <p className=\"text-sm font-medium leading-none\">{member.name}</p>\n          <p className=\"text-sm text-muted-foreground\">{member.email}</p>\n        </div>\n      </div>\n    </div>\n  );\n};\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "dialog",
    "dashboard"
  ],
  "type": "registry:block"
}