{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "activity-feed",
  "title": "Activity Feed",
  "description": "The nx-ui Activity Feed block.",
  "registryDependencies": [
    "@nx-ui/avatar",
    "@nx-ui/featured-icon",
    "@nx-ui/timeline"
  ],
  "files": [
    {
      "path": "components/blocks/activity-feed.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { FeaturedIcon } from \"@/components/blocks/featured-icon\"\nimport {\n  Timeline,\n  TimelineCard,\n  TimelineContent,\n  TimelineItem,\n  TimelineMeta,\n  TimelineNode,\n  TimelineTitle,\n} from \"@/components/ui/timeline\"\n\n/**\n * ActivityFeed — a data-driven vertical timeline of events (actor + action +\n * time), each with an avatar or a coloured FeaturedIcon node on the connector\n * rail, and an optional attached card (e.g. a comment body).\n *\n * Composes `timeline` + `avatar` + `featured-icon`.\n *\n * @example\n * <ActivityFeed\n *   items={[\n *     { id: \"1\", actor: { name: \"Ada Okonkwo\" }, action: \"approved batch #0412\", time: \"2h ago\" },\n *     { id: \"2\", icon: { component: CheckCircle, color: \"success\" }, title: \"Round RD-2231 delivered\", time: \"yesterday\" },\n *   ]}\n * />\n */\n\ninterface ActivityItem {\n  id: string\n  /** Actor whose avatar leads the row (mutually exclusive with `icon`). */\n  actor?: { name: string; src?: string; initials?: string }\n  /** A FeaturedIcon node instead of an avatar. */\n  icon?: {\n    component: React.ComponentType<{ className?: string }>\n    color?: React.ComponentProps<typeof FeaturedIcon>[\"color\"]\n  }\n  /** The headline. When `actor` is set, `action` is appended after their name. */\n  title?: React.ReactNode\n  action?: React.ReactNode\n  time: React.ReactNode\n  /** Optional card body attached under the headline. */\n  body?: React.ReactNode\n}\n\nfunction initialsOf(name: string): string {\n  return name\n    .split(/\\s+/)\n    .slice(0, 2)\n    .map((p) => p.charAt(0).toUpperCase())\n    .join(\"\")\n}\n\nfunction ActivityFeed({\n  items,\n  className,\n  ...props\n}: React.ComponentProps<\"ul\"> & { items: ActivityItem[] }) {\n  return (\n    <Timeline className={className} {...props}>\n      {items.map((item) => (\n        <TimelineItem key={item.id}>\n          {item.actor ? (\n            <Avatar size=\"default\" className=\"relative z-[1] ring-4 ring-bg-primary\">\n              {item.actor.src ? (\n                <AvatarImage src={item.actor.src} alt={item.actor.name} />\n              ) : null}\n              <AvatarFallback>\n                {item.actor.initials ?? initialsOf(item.actor.name)}\n              </AvatarFallback>\n            </Avatar>\n          ) : item.icon ? (\n            <FeaturedIcon\n              icon={item.icon.component}\n              color={item.icon.color ?? \"gray\"}\n              theme=\"light\"\n              size=\"sm\"\n              className=\"relative z-[1] ring-4 ring-bg-primary\"\n            />\n          ) : (\n            <TimelineNode />\n          )}\n\n          <TimelineContent>\n            <TimelineTitle>\n              {item.actor ? (\n                <>\n                  <span className=\"font-semibold text-text-primary\">\n                    {item.actor.name}\n                  </span>{\" \"}\n                  <span className=\"font-normal text-text-tertiary\">\n                    {item.action ?? item.title}\n                  </span>\n                </>\n              ) : (\n                item.title\n              )}\n            </TimelineTitle>\n            <TimelineMeta>{item.time}</TimelineMeta>\n            {item.body ? <TimelineCard>{item.body}</TimelineCard> : null}\n          </TimelineContent>\n        </TimelineItem>\n      ))}\n    </Timeline>\n  )\n}\n\nexport { ActivityFeed }\nexport type { ActivityItem }\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:block"
}