{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "socket-grid",
  "title": "Socket grid",
  "description": "The socket layout: perk sockets as side-by-side columns of circles, then mod sockets as a row of squares — the Destiny weapon perk/mod grid.",
  "dependencies": [
    "@engram/core"
  ],
  "registryDependencies": [
    "@engram/cn",
    "@engram/socket",
    "@engram/tokens"
  ],
  "files": [
    {
      "path": "src/components/socket-grid.tsx",
      "content": "import type {\n  SocketGridProps as GridData,\n  PlugAnnotation,\n  PlugProps as PlugData,\n} from \"@engram/core\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport { Socket } from \"./socket.js\";\n\nexport interface SocketGridProps extends GridData {\n  className?: string;\n  /** Typed curated-roll annotations keyed by plug hash (rendered as default badges). */\n  annotations?: Record<number, PlugAnnotation>;\n  /** Fully override the badge for a plug (takes precedence over `annotations`). */\n  renderBadge?: (plug: PlugData) => ReactNode;\n  /** Called when a plug is clicked. */\n  onPlugClick?: (plug: PlugData) => void;\n  /** A plug's inspect popup (e.g. a {@link ModPopup}), revealed on hover beside\n   *  the parent inspect panel. Return `null` for plugs with no inspect. */\n  plugPopup?: (plug: PlugData) => ReactNode;\n}\n\n/**\n * The socket layout: perk sockets as side-by-side columns of circles, then mod\n * sockets as a row of squares — the Destiny weapon perk/mod grid.\n */\nexport function SocketGrid({\n  sockets,\n  className,\n  annotations,\n  renderBadge,\n  onPlugClick,\n  plugPopup,\n}: SocketGridProps) {\n  const perks = sockets.filter((s) => s.kind === \"perk\");\n  const mods = sockets.filter((s) => s.kind === \"mod\");\n  return (\n    <div className={cn(\"flex flex-col gap-3\", className)}>\n      {perks.length > 0 ? (\n        <div className=\"flex gap-2.5\">\n          {perks.map((socket) => (\n            <Socket\n              key={socket.index}\n              {...socket}\n              annotations={annotations}\n              renderBadge={renderBadge}\n              onPlugClick={onPlugClick}\n              plugPopup={plugPopup}\n            />\n          ))}\n        </div>\n      ) : null}\n      {mods.length > 0 ? (\n        <div className=\"flex flex-wrap gap-2\">\n          {mods.map((socket) => (\n            <Socket\n              key={socket.index}\n              {...socket}\n              annotations={annotations}\n              renderBadge={renderBadge}\n              onPlugClick={onPlugClick}\n              plugPopup={plugPopup}\n            />\n          ))}\n        </div>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/engram/socket-grid.tsx"
    }
  ],
  "meta": {
    "level": "component"
  },
  "docs": "Extend without forking: edit the copied source, use `asChild` (Radix Slot) to change the rendered element, pass the typed `annotations` prop for curated data (verdict/tags/per-plug), or use slot / render-prop props for arbitrary content. Requires the @engram/tokens theme (--engram-* CSS variables).",
  "categories": [
    "socket"
  ],
  "type": "registry:component"
}