{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "status-updates",
  "title": "Status Updates",
  "description": "Popover with copy-link primitives for RSS, Atom, JSON, Slack, and SSH subscription channels. Flat exports — caller composes layout (tabs, sections, etc.)",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://openstatus.dev/r/status-i18n.json",
    "https://openstatus.dev/r/use-copy-to-clipboard.json",
    "button",
    "input",
    "popover",
    "separator"
  ],
  "files": [
    {
      "path": "src/components/blocks/status-updates.tsx",
      "content": "\"use client\";\n\nimport { useStatusBlocksLabels } from \"@/components/blocks/status-i18n\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { useCopyToClipboard } from \"@/hooks/use-copy-to-clipboard\";\nimport { cn } from \"@/lib/utils\";\nimport { Check, Copy } from \"lucide-react\";\n\n/**\n * StatusUpdates — popover root for \"Get updates\" controls.\n *\n * Flat exports. Compose `StatusUpdatesTrigger` + `StatusUpdatesContent` and\n * pick whichever channel children apply (`StatusUpdatesRss`,\n * `StatusUpdatesJson`, `StatusUpdatesSlack`, `StatusUpdatesSsh`, or your own\n * email form). The block does not enforce a tab structure — callers wrap\n * children with `Tabs` themselves if needed.\n */\nexport function StatusUpdates({\n  children,\n  ...props\n}: React.ComponentProps<typeof Popover>) {\n  return <Popover {...props}>{children}</Popover>;\n}\n\nexport function StatusUpdatesTrigger({\n  children,\n  className,\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <PopoverTrigger asChild>\n      <Button\n        data-slot=\"status-updates-trigger\"\n        size=\"sm\"\n        variant=\"outline\"\n        className={cn(className)}\n        {...props}\n      >\n        {children ?? labels.subscribe}\n      </Button>\n    </PopoverTrigger>\n  );\n}\n\nexport function StatusUpdatesContent({\n  className,\n  ...props\n}: React.ComponentProps<typeof PopoverContent>) {\n  return (\n    <PopoverContent\n      data-slot=\"status-updates-content\"\n      align=\"end\"\n      className={cn(\"w-80 overflow-hidden p-0\", className)}\n      {...props}\n    />\n  );\n}\n\n/**\n * StatusUpdatesSection — single channel description + content slot.\n * Use to compose custom channels; the built-in `StatusUpdatesRss`/`Json`/\n * `Slack`/`Ssh` children render this internally.\n */\nexport function StatusUpdatesSection({\n  description,\n  children,\n  className,\n  ...props\n}: React.ComponentProps<\"div\"> & {\n  description?: React.ReactNode;\n}) {\n  return (\n    <div\n      data-slot=\"status-updates-section\"\n      className={cn(\"flex flex-col gap-2 px-2 py-2\", className)}\n      {...props}\n    >\n      {description ? <div className=\"text-sm\">{description}</div> : null}\n      {children}\n    </div>\n  );\n}\n\nexport function StatusUpdatesCopyInput({\n  value,\n  className,\n  onClick,\n  ...props\n}: Omit<React.ComponentProps<typeof Input>, \"value\"> & { value: string }) {\n  const labels = useStatusBlocksLabels();\n  const { copy, isCopied } = useCopyToClipboard();\n  return (\n    <div\n      data-slot=\"status-updates-copy-input\"\n      className={cn(\"relative w-full\", className)}\n    >\n      <Input\n        data-slot=\"status-updates-copy-input-field\"\n        value={value}\n        readOnly\n        onClick={(e) => {\n          copy(value, {\n            successMessage: labels.linkCopiedToClipboard,\n            withToast: true,\n          });\n          onClick?.(e);\n        }}\n        {...props}\n      />\n      <Button\n        data-slot=\"status-updates-copy-input-button\"\n        type=\"button\"\n        variant=\"outline\"\n        size=\"icon\"\n        onClick={() =>\n          copy(value, {\n            successMessage: labels.linkCopiedToClipboard,\n            withToast: true,\n          })\n        }\n        className=\"absolute top-1/2 right-2 size-6 -translate-y-1/2 backdrop-blur-xs\"\n      >\n        {isCopied ? <Check /> : <Copy />}\n        <span className=\"sr-only\">{labels.ariaCopyLink}</span>\n      </Button>\n    </div>\n  );\n}\n\nexport function StatusUpdatesRss({\n  rssUrl,\n  atomUrl,\n}: {\n  rssUrl: string;\n  atomUrl?: string;\n}) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <>\n      <StatusUpdatesSection description={labels.subscribeRssDescription}>\n        <StatusUpdatesCopyInput value={rssUrl} />\n      </StatusUpdatesSection>\n      {atomUrl ? (\n        <>\n          <Separator />\n          <StatusUpdatesSection description={labels.subscribeAtomDescription}>\n            <StatusUpdatesCopyInput value={atomUrl} />\n          </StatusUpdatesSection>\n        </>\n      ) : null}\n    </>\n  );\n}\n\nexport function StatusUpdatesJson({ url }: { url: string }) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <StatusUpdatesSection description={labels.subscribeJsonDescription}>\n      <StatusUpdatesCopyInput value={url} />\n    </StatusUpdatesSection>\n  );\n}\n\nexport function StatusUpdatesSlack({ rssUrl }: { rssUrl: string }) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <StatusUpdatesSection description={labels.subscribeSlackDescription}>\n      <StatusUpdatesCopyInput value={`/feed subscribe ${rssUrl}`} />\n    </StatusUpdatesSection>\n  );\n}\n\nexport function StatusUpdatesSsh({ command }: { command: string }) {\n  const labels = useStatusBlocksLabels();\n  return (\n    <StatusUpdatesSection description={labels.subscribeSshDescription}>\n      <StatusUpdatesCopyInput value={command} />\n    </StatusUpdatesSection>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/blocks/status-updates.tsx"
    }
  ],
  "type": "registry:block"
}