{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"grid-01","type":"registry:component","title":"App Store Grid","description":"Responsive card grid component for displaying applications, tools, or content items with images, metadata, and interactive actions. Features star toggles, dropdown menus, status badges, download counts, ratings, and install buttons. Perfect for app stores, galleries, plugin marketplaces, or any content showcase with customizable event handlers and empty states.","dependencies":["lucide-react"],"registryDependencies":["badge","button","card","dropdown-menu"],"files":[{"path":"src/registry/blocks/application/data-display/grids/grid-01.tsx","content":"\"use client\";\n\nimport {\n  Download,\n  ExternalLink,\n  MoreHorizontal,\n  Star,\n  Trash2,\n} from \"lucide-react\";\nimport NextImage from \"next/image\";\n\nimport { cn } from \"@/registry/lib/utils\";\nimport { Badge } from \"@/registry/ui/badge\";\nimport { Button } from \"@/registry/ui/button\";\nimport { Card, CardContent } from \"@/registry/ui/card\";\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"@/registry/ui/dropdown-menu\";\n\nexport interface Grid01Props {\n  className?: string;\n}\n\nconst content = {\n  items: [\n    {\n      id: 1,\n      name: \"Analytics Dashboard\",\n      description: \"Real-time analytics and reporting platform\",\n      image:\n        \"https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=300&h=200&fit=crop&crop=center\",\n      category: \"Analytics\",\n      status: \"Active\" as const,\n      downloads: \"2.4k\",\n      rating: 4.8,\n      isStarred: true,\n    },\n    {\n      id: 2,\n      name: \"Task Manager Pro\",\n      description: \"Advanced project management and collaboration tool\",\n      image:\n        \"https://images.unsplash.com/photo-1611224923853-80b023f02d71?w=300&h=200&fit=crop&crop=center\",\n      category: \"Productivity\",\n      status: \"Active\" as const,\n      downloads: \"1.8k\",\n      rating: 4.6,\n      isStarred: false,\n    },\n    {\n      id: 3,\n      name: \"Design System\",\n      description: \"Comprehensive UI component library\",\n      image:\n        \"https://images.unsplash.com/photo-1558655146-9f40138edfeb?w=300&h=200&fit=crop&crop=center\",\n      category: \"Design\",\n      status: \"Beta\" as const,\n      downloads: \"956\",\n      rating: 4.9,\n      isStarred: true,\n    },\n    {\n      id: 4,\n      name: \"API Gateway\",\n      description: \"Secure API management and monitoring\",\n      image:\n        \"https://images.unsplash.com/photo-1629654297299-c8506221ca97?w=300&h=200&fit=crop&crop=center\",\n      category: \"Development\",\n      status: \"Active\" as const,\n      downloads: \"3.2k\",\n      rating: 4.7,\n      isStarred: false,\n    },\n    {\n      id: 5,\n      name: \"Chat Widget\",\n      description: \"Embeddable customer support chat\",\n      image:\n        \"https://images.unsplash.com/photo-1577563908411-5077b6dc7624?w=300&h=200&fit=crop&crop=center\",\n      category: \"Support\",\n      status: \"Active\" as const,\n      downloads: \"1.2k\",\n      rating: 4.5,\n      isStarred: false,\n    },\n    {\n      id: 6,\n      name: \"Email Templates\",\n      description: \"Beautiful responsive email templates\",\n      image:\n        \"https://images.unsplash.com/photo-1596526131083-e8c633c948d2?w=300&h=200&fit=crop&crop=center\",\n      category: \"Marketing\",\n      status: \"New\" as const,\n      downloads: \"687\",\n      rating: 4.8,\n      isStarred: true,\n    },\n  ],\n  emptyState: {\n    message: \"No items found\",\n    icon: {\n      viewBox: \"0 0 24 24\",\n      path: \"M3 7V17C3 18.1046 3.89543 19 5 19H19C20.1046 19 21 18.1046 21 17V7M3 7L12 14L21 7M3 7L5 5H19L21 7\",\n      title: \"No items found\",\n    },\n  },\n};\n\nexport function Grid01({ className }: Grid01Props) {\n  const getStatusVariant = (status: string) => {\n    switch (status) {\n      case \"Active\":\n        return \"default\";\n      case \"Beta\":\n        return \"secondary\";\n      case \"New\":\n        return \"outline\";\n      case \"Inactive\":\n        return \"destructive\";\n      default:\n        return \"outline\";\n    }\n  };\n\n  const handleToggleStar = (item: (typeof content.items)[0]) => {\n    console.log(\"Toggle star for:\", item.name);\n  };\n\n  const handleInstall = (item: (typeof content.items)[0]) => {\n    console.log(\"Install:\", item.name);\n  };\n\n  const handleDropdownAction = (\n    action: string,\n    item: (typeof content.items)[0],\n  ) => {\n    console.log(`${action} action for:`, item.name);\n  };\n\n  if (content.items.length === 0) {\n    return (\n      <Card\n        className={cn(\"w-full max-w-6xl mx-auto\", className)}\n        data-testid=\"grid-empty-state\"\n      >\n        <CardContent className=\"p-8 text-center\">\n          <div className=\"h-12 w-12 text-muted-foreground mx-auto mb-4\">\n            <svg\n              viewBox={content.emptyState.icon.viewBox}\n              fill=\"none\"\n              xmlns=\"http://www.w3.org/2000/svg\"\n              className=\"h-full w-full\"\n              role=\"img\"\n              aria-label={content.emptyState.icon.title}\n            >\n              <title>{content.emptyState.icon.title}</title>\n              <path\n                d={content.emptyState.icon.path}\n                stroke=\"currentColor\"\n                strokeWidth=\"2\"\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n              />\n            </svg>\n          </div>\n          <p className=\"text-muted-foreground\">{content.emptyState.message}</p>\n        </CardContent>\n      </Card>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        \"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\",\n        className,\n      )}\n      data-testid=\"grid-container\"\n    >\n      {content.items.map((item) => (\n        <Card\n          key={item.id}\n          className=\"group hover:shadow-lg transition-shadow py-0 rounded-t-lg\"\n          data-testid={`grid-item-${item.id}`}\n        >\n          <CardContent className=\"p-0\">\n            <div className=\"relative\">\n              <NextImage\n                src={item.image || \"/placeholder.svg\"}\n                alt={item.name}\n                width={300}\n                height={200}\n                className=\"w-full h-48 object-cover rounded-t-lg\"\n                data-testid={`item-image-${item.id}`}\n              />\n              <div className=\"absolute top-3 right-3 flex gap-2\">\n                <Button\n                  size=\"sm\"\n                  variant={item.isStarred ? \"default\" : \"secondary\"}\n                  className=\"h-8 w-8 p-0\"\n                  onClick={(e) => {\n                    e.stopPropagation();\n                    handleToggleStar(item);\n                  }}\n                  data-testid={`star-button-${item.id}`}\n                >\n                  <Star\n                    className={cn(\n                      \"h-4 w-4\",\n                      item.isStarred ? \"fill-current\" : \"\",\n                    )}\n                  />\n                </Button>\n                <DropdownMenu>\n                  <DropdownMenuTrigger asChild>\n                    <Button\n                      size=\"sm\"\n                      variant=\"secondary\"\n                      className=\"h-8 w-8 p-0\"\n                      data-testid={`dropdown-trigger-${item.id}`}\n                    >\n                      <MoreHorizontal className=\"h-4 w-4\" />\n                    </Button>\n                  </DropdownMenuTrigger>\n                  <DropdownMenuContent\n                    align=\"end\"\n                    data-testid={`dropdown-content-${item.id}`}\n                  >\n                    <DropdownMenuItem\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        handleDropdownAction(\"view-details\", item);\n                      }}\n                      data-testid={`view-details-${item.id}`}\n                    >\n                      <ExternalLink className=\"mr-2 h-4 w-4\" />\n                      View Details\n                    </DropdownMenuItem>\n                    <DropdownMenuItem\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        handleDropdownAction(\"download\", item);\n                      }}\n                      data-testid={`download-${item.id}`}\n                    >\n                      <Download className=\"mr-2 h-4 w-4\" />\n                      Download\n                    </DropdownMenuItem>\n                    <DropdownMenuItem\n                      className=\"text-destructive\"\n                      onClick={(e) => {\n                        e.stopPropagation();\n                        handleDropdownAction(\"delete\", item);\n                      }}\n                      data-testid={`delete-${item.id}`}\n                    >\n                      <Trash2 className=\"mr-2 h-4 w-4\" />\n                      Delete\n                    </DropdownMenuItem>\n                  </DropdownMenuContent>\n                </DropdownMenu>\n              </div>\n              <Badge\n                variant={getStatusVariant(item.status)}\n                className=\"absolute bottom-3 left-3\"\n                data-testid={`status-badge-${item.id}`}\n              >\n                {item.status}\n              </Badge>\n            </div>\n            <div className=\"p-4\">\n              <div className=\"flex items-start justify-between mb-2\">\n                <h3\n                  className=\"font-semibold text-lg leading-tight\"\n                  data-testid={`item-title-${item.id}`}\n                >\n                  {item.name}\n                </h3>\n                <Badge\n                  variant=\"outline\"\n                  className=\"text-xs\"\n                  data-testid={`category-badge-${item.id}`}\n                >\n                  {item.category}\n                </Badge>\n              </div>\n              <p\n                className=\"text-sm text-muted-foreground mb-4 line-clamp-2\"\n                data-testid={`item-description-${item.id}`}\n              >\n                {item.description}\n              </p>\n              <div className=\"flex items-center justify-between\">\n                <div className=\"flex items-center gap-4 text-sm text-muted-foreground\">\n                  <span data-testid={`downloads-${item.id}`}>\n                    {item.downloads} downloads\n                  </span>\n                  <div className=\"flex items-center gap-1\">\n                    <Star className=\"h-3 w-3 fill-current text-yellow-500\" />\n                    <span data-testid={`rating-${item.id}`}>{item.rating}</span>\n                  </div>\n                </div>\n                <Button\n                  size=\"sm\"\n                  onClick={(e) => {\n                    e.stopPropagation();\n                    handleInstall(item);\n                  }}\n                  data-testid={`install-button-${item.id}`}\n                >\n                  Install\n                </Button>\n              </div>\n            </div>\n          </CardContent>\n        </Card>\n      ))}\n    </div>\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"}]}