{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "branch",
  "dependencies": [
    "ai"
  ],
  "registryDependencies": [
    "https://taki-ui.com/r/button.json"
  ],
  "files": [
    {
      "path": "registry/new-york/ai-elements/branch.tsx",
      "content": "\"use client\"\n\nimport type { ComponentProps, HTMLAttributes, ReactElement } from \"react\"\nimport { createContext, useContext, useEffect, useState } from \"react\"\nimport type { UIMessage } from \"ai\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/new-york/ui/button\"\n\ntype BranchContextType = {\n  currentBranch: number\n  totalBranches: number\n  goToPrevious: () => void\n  goToNext: () => void\n  branches: ReactElement[]\n  setBranches: (branches: ReactElement[]) => void\n}\n\nconst BranchContext = createContext<BranchContextType | null>(null)\n\nconst useBranch = () => {\n  const context = useContext(BranchContext)\n\n  if (!context) {\n    throw new Error(\"Branch components must be used within Branch\")\n  }\n\n  return context\n}\n\nexport type BranchProps = HTMLAttributes<HTMLDivElement> & {\n  defaultBranch?: number\n  onBranchChange?: (branchIndex: number) => void\n}\n\nexport const Branch = ({\n  defaultBranch = 0,\n  onBranchChange,\n  className,\n  ...props\n}: BranchProps) => {\n  const [currentBranch, setCurrentBranch] = useState(defaultBranch)\n  const [branches, setBranches] = useState<ReactElement[]>([])\n\n  const handleBranchChange = (newBranch: number) => {\n    setCurrentBranch(newBranch)\n    onBranchChange?.(newBranch)\n  }\n\n  const goToPrevious = () => {\n    const newBranch =\n      currentBranch > 0 ? currentBranch - 1 : branches.length - 1\n    handleBranchChange(newBranch)\n  }\n\n  const goToNext = () => {\n    const newBranch =\n      currentBranch < branches.length - 1 ? currentBranch + 1 : 0\n    handleBranchChange(newBranch)\n  }\n\n  const contextValue: BranchContextType = {\n    currentBranch,\n    totalBranches: branches.length,\n    goToPrevious,\n    goToNext,\n    branches,\n    setBranches,\n  }\n\n  return (\n    <BranchContext.Provider value={contextValue}>\n      <div\n        className={cn(\"grid w-full gap-2 [&>div]:pb-0\", className)}\n        {...props}\n      />\n    </BranchContext.Provider>\n  )\n}\n\nexport type BranchMessagesProps = HTMLAttributes<HTMLDivElement>\n\nexport const BranchMessages = ({ children, ...props }: BranchMessagesProps) => {\n  const { currentBranch, setBranches, branches } = useBranch()\n  const childrenArray = Array.isArray(children) ? children : [children]\n\n  // Use useEffect to update branches when they change\n  useEffect(() => {\n    if (branches.length !== childrenArray.length) {\n      setBranches(childrenArray)\n    }\n  }, [childrenArray, branches, setBranches])\n\n  return childrenArray.map((branch, index) => (\n    <div\n      className={cn(\n        \"grid gap-2 overflow-hidden [&>div]:pb-0\",\n        index === currentBranch ? \"block\" : \"hidden\"\n      )}\n      key={branch.key}\n      {...props}\n    >\n      {branch}\n    </div>\n  ))\n}\n\nexport type BranchSelectorProps = HTMLAttributes<HTMLDivElement> & {\n  from: UIMessage[\"role\"]\n}\n\nexport const BranchSelector = ({\n  className,\n  from,\n  ...props\n}: BranchSelectorProps) => {\n  const { totalBranches } = useBranch()\n\n  // Don't render if there's only one branch\n  if (totalBranches <= 1) {\n    return null\n  }\n\n  return (\n    <div\n      className={cn(\n        \"flex items-center gap-2 self-end px-10\",\n        from === \"assistant\" ? \"justify-start\" : \"justify-end\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type BranchPreviousProps = ComponentProps<typeof Button>\n\nexport const BranchPrevious = ({\n  className,\n  children,\n  ...props\n}: BranchPreviousProps) => {\n  const { goToPrevious, totalBranches } = useBranch()\n\n  return (\n    <Button\n      aria-label=\"Previous branch\"\n      className={cn(\n        \"text-muted-foreground size-7 shrink-0 rounded-full transition-colors\",\n        \"hover:bg-accent hover:text-foreground\",\n        \"disabled:pointer-events-none disabled:opacity-50\",\n        className\n      )}\n      disabled={totalBranches <= 1}\n      onPress={goToPrevious}\n      size=\"icon\"\n      type=\"button\"\n      variant=\"ghost\"\n      {...props}\n    >\n      {children ?? <ChevronLeftIcon size={14} />}\n    </Button>\n  )\n}\n\nexport type BranchNextProps = ComponentProps<typeof Button>\n\nexport const BranchNext = ({\n  className,\n  children,\n  ...props\n}: BranchNextProps) => {\n  const { goToNext, totalBranches } = useBranch()\n\n  return (\n    <Button\n      aria-label=\"Next branch\"\n      className={cn(\n        \"text-muted-foreground size-7 shrink-0 rounded-full transition-colors\",\n        \"hover:bg-accent hover:text-foreground\",\n        \"disabled:pointer-events-none disabled:opacity-50\",\n        className\n      )}\n      disabled={totalBranches <= 1}\n      onPress={goToNext}\n      size=\"icon\"\n      type=\"button\"\n      variant=\"ghost\"\n      {...props}\n    >\n      {children ?? <ChevronRightIcon size={14} />}\n    </Button>\n  )\n}\n\nexport type BranchPageProps = HTMLAttributes<HTMLSpanElement>\n\nexport const BranchPage = ({ className, ...props }: BranchPageProps) => {\n  const { currentBranch, totalBranches } = useBranch()\n\n  return (\n    <span\n      className={cn(\n        \"text-muted-foreground text-xs font-medium tabular-nums\",\n        className\n      )}\n      {...props}\n    >\n      {currentBranch + 1} of {totalBranches}\n    </span>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}