{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"list-01","type":"registry:component","title":"Team Member List","description":"Comprehensive team member list with status indicators, role badges, star functionality, and action dropdowns. Features responsive design with mobile-friendly actions, customizable display options, and interactive elements for team management.","dependencies":["lucide-react"],"registryDependencies":["avatar","badge","button","card","dropdown-menu"],"files":[{"path":"src/registry/blocks/application/data-display/lists/list-01.tsx","content":"\"use client\";\n\nimport {\n  Crown,\n  type LucideIcon,\n  Mail,\n  MessageCircle,\n  MoreHorizontal,\n  Phone,\n  Shield,\n  Star,\n  Users,\n  Video,\n} from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/lib/utils\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/registry/ui/avatar\";\nimport { Button } from \"@/registry/ui/button\";\nimport { Card, CardContent } from \"@/registry/ui/card\";\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from \"@/registry/ui/dropdown-menu\";\n\ninterface TeamMember {\n  id: number;\n  name: string;\n  role: string;\n  email: string;\n  avatar: string;\n  status: \"online\" | \"away\" | \"busy\" | \"offline\";\n  lastSeen: string;\n  department: string;\n  level: \"junior\" | \"mid\" | \"senior\" | \"lead\";\n  isStarred: boolean;\n}\n\nexport interface List01Props {\n  className?: string;\n}\n\nconst content: {\n  teamMembers: TeamMember[];\n  emptyState: { message: string; icon: LucideIcon };\n} = {\n  teamMembers: [\n    {\n      id: 1,\n      name: \"Sarah Johnson\",\n      role: \"Product Manager\",\n      email: \"sarah.johnson@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/women/1.jpg\",\n      status: \"online\" as const,\n      lastSeen: \"Active now\",\n      department: \"Product\",\n      level: \"senior\" as const,\n      isStarred: true,\n    },\n    {\n      id: 2,\n      name: \"Michael Chen\",\n      role: \"Senior Developer\",\n      email: \"michael.chen@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/men/2.jpg\",\n      status: \"away\" as const,\n      lastSeen: \"5 minutes ago\",\n      department: \"Engineering\",\n      level: \"senior\" as const,\n      isStarred: false,\n    },\n    {\n      id: 3,\n      name: \"Emily Rodriguez\",\n      role: \"UX Designer\",\n      email: \"emily.rodriguez@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/women/3.jpg\",\n      status: \"busy\" as const,\n      lastSeen: \"In a meeting\",\n      department: \"Design\",\n      level: \"mid\" as const,\n      isStarred: true,\n    },\n    {\n      id: 4,\n      name: \"David Park\",\n      role: \"DevOps Engineer\",\n      email: \"david.park@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/men/4.jpg\",\n      status: \"offline\" as const,\n      lastSeen: \"2 hours ago\",\n      department: \"Engineering\",\n      level: \"senior\" as const,\n      isStarred: false,\n    },\n    {\n      id: 5,\n      name: \"Lisa Thompson\",\n      role: \"Marketing Specialist\",\n      email: \"lisa.thompson@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/women/5.jpg\",\n      status: \"online\" as const,\n      lastSeen: \"Active now\",\n      department: \"Marketing\",\n      level: \"junior\" as const,\n      isStarred: false,\n    },\n    {\n      id: 6,\n      name: \"James Wilson\",\n      role: \"Team Lead\",\n      email: \"james.wilson@company.com\",\n      avatar: \"https://randomuser.me/api/portraits/men/6.jpg\",\n      status: \"online\" as const,\n      lastSeen: \"Active now\",\n      department: \"Engineering\",\n      level: \"lead\" as const,\n      isStarred: true,\n    },\n  ],\n  emptyState: {\n    message: \"No team members found\",\n    icon: Users,\n  },\n};\n\nfunction getStatusColor(status: TeamMember[\"status\"]): string {\n  switch (status) {\n    case \"online\":\n      return \"bg-green-500\";\n    case \"away\":\n      return \"bg-yellow-500\";\n    case \"busy\":\n      return \"bg-red-500\";\n    default:\n      return \"bg-gray-400\";\n  }\n}\n\nfunction getLevelIcon(level: TeamMember[\"level\"]): LucideIcon | null {\n  switch (level) {\n    case \"lead\":\n      return Crown;\n    case \"senior\":\n      return Shield;\n    default:\n      return null;\n  }\n}\n\nexport function List01({ className }: List01Props) {\n  const [starredMembers, setStarredMembers] = useState(\n    new Set(\n      content.teamMembers\n        .filter((member) => member.isStarred)\n        .map((member) => member.id),\n    ),\n  );\n\n  const handleStarToggle = (memberId: number) => {\n    const newStarred = new Set(starredMembers);\n    const isStarred = newStarred.has(memberId);\n\n    if (isStarred) {\n      newStarred.delete(memberId);\n    } else {\n      newStarred.add(memberId);\n    }\n    setStarredMembers(newStarred);\n    console.log(\"Star toggled:\", { memberId, isStarred: !isStarred });\n  };\n\n  const handleActionClick = (action: string, member: TeamMember) => {\n    console.log(`${action} clicked:`, member);\n  };\n\n  return (\n    <Card className={cn(\"w-full max-w-4xl mx-auto\", className)}>\n      <CardContent className=\"p-0\">\n        <div className=\"divide-y divide-border/50\">\n          {content.teamMembers.map((member) => {\n            const LevelIcon = getLevelIcon(member.level);\n            const isStarred = starredMembers.has(member.id);\n\n            return (\n              <div\n                key={member.id}\n                className=\"block p-4 hover:bg-muted/50 transition-colors\"\n                data-testid={`team-member-${member.id}`}\n              >\n                <div className=\"flex items-center space-x-4\">\n                  <div className=\"relative flex-shrink-0\">\n                    <Avatar className=\"h-12 w-12\">\n                      <AvatarImage src={member.avatar} alt={member.name} />\n                      <AvatarFallback>\n                        {member.name\n                          .split(\" \")\n                          .map((n) => n[0])\n                          .join(\"\")}\n                      </AvatarFallback>\n                    </Avatar>\n                    <div\n                      className={cn(\n                        \"absolute -bottom-1 -right-1 h-4 w-4 rounded-full border-2 border-background\",\n                        getStatusColor(member.status),\n                      )}\n                      data-testid={`status-indicator-${member.id}`}\n                    />\n                  </div>\n\n                  <div className=\"flex-1 min-w-0\">\n                    <div className=\"flex items-center space-x-2 mb-1\">\n                      <h3 className=\"text-sm font-semibold text-foreground truncate\">\n                        {member.name}\n                      </h3>\n                      {LevelIcon && (\n                        <LevelIcon className=\"h-4 w-4 text-primary flex-shrink-0\" />\n                      )}\n                      <Button\n                        variant=\"ghost\"\n                        size=\"icon\"\n                        className=\"h-6 w-6 flex-shrink-0\"\n                        onClick={() => {\n                          handleStarToggle(member.id);\n                        }}\n                        data-testid={`star-button-${member.id}`}\n                      >\n                        <Star\n                          className={cn(\n                            \"h-3 w-3\",\n                            isStarred\n                              ? \"fill-yellow-400 text-yellow-400\"\n                              : \"text-muted-foreground\",\n                          )}\n                        />\n                      </Button>\n                    </div>\n                    <p className=\"text-sm text-muted-foreground truncate mb-1\">\n                      {member.role} • {member.department}\n                    </p>\n                    <p className=\"text-xs text-muted-foreground truncate\">\n                      {member.email}\n                    </p>\n                    <p className=\"text-xs text-muted-foreground mt-1\">\n                      {member.lastSeen}\n                    </p>\n                  </div>\n\n                  <div className=\"flex items-center space-x-1 flex-shrink-0\">\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      className=\"h-8 w-8 hidden sm:flex\"\n                      onClick={() => {\n                        handleActionClick(\"message\", member);\n                      }}\n                      data-testid={`message-button-${member.id}`}\n                    >\n                      <MessageCircle className=\"h-4 w-4\" />\n                    </Button>\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      className=\"h-8 w-8 hidden sm:flex\"\n                      onClick={() => {\n                        handleActionClick(\"email\", member);\n                      }}\n                      data-testid={`email-button-${member.id}`}\n                    >\n                      <Mail className=\"h-4 w-4\" />\n                    </Button>\n                    <Button\n                      variant=\"ghost\"\n                      size=\"icon\"\n                      className=\"h-8 w-8 hidden sm:flex\"\n                      onClick={() => {\n                        handleActionClick(\"phone\", member);\n                      }}\n                      data-testid={`phone-button-${member.id}`}\n                    >\n                      <Phone className=\"h-4 w-4\" />\n                    </Button>\n\n                    <DropdownMenu>\n                      <DropdownMenuTrigger asChild>\n                        <Button\n                          variant=\"ghost\"\n                          size=\"icon\"\n                          className=\"h-8 w-8\"\n                          data-testid={`more-actions-${member.id}`}\n                        >\n                          <MoreHorizontal className=\"h-4 w-4\" />\n                        </Button>\n                      </DropdownMenuTrigger>\n                      <DropdownMenuContent\n                        align=\"end\"\n                        data-testid={`dropdown-menu-${member.id}`}\n                      >\n                        <DropdownMenuItem\n                          className=\"sm:hidden\"\n                          onClick={() => {\n                            handleActionClick(\"message\", member);\n                          }}\n                        >\n                          <MessageCircle className=\"h-4 w-4 mr-2\" />\n                          Message\n                        </DropdownMenuItem>\n                        <DropdownMenuItem\n                          className=\"sm:hidden\"\n                          onClick={() => {\n                            handleActionClick(\"email\", member);\n                          }}\n                        >\n                          <Mail className=\"h-4 w-4 mr-2\" />\n                          Email\n                        </DropdownMenuItem>\n                        <DropdownMenuItem\n                          className=\"sm:hidden\"\n                          onClick={() => {\n                            handleActionClick(\"phone\", member);\n                          }}\n                        >\n                          <Phone className=\"h-4 w-4 mr-2\" />\n                          Call\n                        </DropdownMenuItem>\n                        <DropdownMenuItem\n                          className=\"sm:hidden\"\n                          onClick={() => {\n                            handleActionClick(\"video\", member);\n                          }}\n                        >\n                          <Video className=\"h-4 w-4 mr-2\" />\n                          Video Call\n                        </DropdownMenuItem>\n                        <DropdownMenuSeparator className=\"sm:hidden\" />\n                        <DropdownMenuItem\n                          onClick={() => {\n                            handleActionClick(\"view-profile\", member);\n                          }}\n                        >\n                          View Profile\n                        </DropdownMenuItem>\n                        <DropdownMenuItem\n                          onClick={() => {\n                            handleActionClick(\"edit\", member);\n                          }}\n                        >\n                          Edit Member\n                        </DropdownMenuItem>\n                        <DropdownMenuSeparator />\n                        <DropdownMenuItem\n                          className=\"text-destructive\"\n                          onClick={() => {\n                            handleActionClick(\"remove\", member);\n                          }}\n                        >\n                          Remove from Team\n                        </DropdownMenuItem>\n                      </DropdownMenuContent>\n                    </DropdownMenu>\n                  </div>\n                </div>\n              </div>\n            );\n          })}\n        </div>\n\n        {content.teamMembers.length === 0 && (\n          <div className=\"p-8 text-center\" data-testid=\"empty-state\">\n            <content.emptyState.icon className=\"h-12 w-12 text-muted-foreground mx-auto mb-4\" />\n            <p className=\"text-muted-foreground\">\n              {content.emptyState.message}\n            </p>\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  );\n}\n","type":"registry:component"},{"path":"src/registry/lib/utils.ts","content":"import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n","type":"registry:lib"}]}