{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radix-tabs",
  "type": "registry:ui",
  "title": "Radix Tabs",
  "description": "A set of layered sections of content—known as tab panels—that are displayed one at a time.",
  "dependencies": [
    "motion",
    "radix-ui"
  ],
  "registryDependencies": [
    "https://animate-ui.com/r/motion-highlight"
  ],
  "files": [
    {
      "path": "registry/radix/tabs/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { Tabs as TabsPrimitive } from 'radix-ui';\nimport { type HTMLMotionProps, type Transition, motion } from 'motion/react';\n\nimport { cn } from '@/lib/utils';\nimport {\n  MotionHighlight,\n  MotionHighlightItem,\n} from '@/components/animate-ui/effects/motion-highlight';\n\ntype TabsProps = React.ComponentProps<typeof TabsPrimitive.Root>;\n\nfunction Tabs({ className, ...props }: TabsProps) {\n  return (\n    <TabsPrimitive.Root\n      data-slot=\"tabs\"\n      className={cn('flex flex-col gap-2', className)}\n      {...props}\n    />\n  );\n}\n\ntype TabsListProps = React.ComponentProps<typeof TabsPrimitive.List> & {\n  activeClassName?: string;\n  transition?: Transition;\n};\n\nfunction TabsList({\n  ref,\n  children,\n  className,\n  activeClassName,\n  transition = {\n    type: 'spring',\n    stiffness: 200,\n    damping: 25,\n  },\n  ...props\n}: TabsListProps) {\n  const localRef = React.useRef<HTMLDivElement | null>(null);\n  React.useImperativeHandle(ref, () => localRef.current as HTMLDivElement);\n\n  const [activeValue, setActiveValue] = React.useState<string | undefined>(\n    undefined,\n  );\n\n  const getActiveValue = React.useCallback(() => {\n    if (!localRef.current) return;\n    const activeTab = localRef.current.querySelector<HTMLElement>(\n      '[data-state=\"active\"]',\n    );\n    if (!activeTab) return;\n    setActiveValue(activeTab.getAttribute('data-value') ?? undefined);\n  }, []);\n\n  React.useEffect(() => {\n    getActiveValue();\n\n    const observer = new MutationObserver(getActiveValue);\n\n    if (localRef.current) {\n      observer.observe(localRef.current, {\n        attributes: true,\n        childList: true,\n        subtree: true,\n      });\n    }\n\n    return () => {\n      observer.disconnect();\n    };\n  }, [getActiveValue]);\n\n  return (\n    <MotionHighlight\n      controlledItems\n      className={cn('rounded-sm bg-background shadow-sm', activeClassName)}\n      value={activeValue}\n      transition={transition}\n    >\n      <TabsPrimitive.List\n        ref={localRef}\n        data-slot=\"tabs-list\"\n        className={cn(\n          'bg-muted text-muted-foreground inline-flex h-10 w-fit items-center justify-center rounded-lg p-[4px]',\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </TabsPrimitive.List>\n    </MotionHighlight>\n  );\n}\n\ntype TabsTriggerProps = React.ComponentProps<typeof TabsPrimitive.Trigger>;\n\nfunction TabsTrigger({ className, value, ...props }: TabsTriggerProps) {\n  return (\n    <MotionHighlightItem value={value} className=\"size-full\">\n      <TabsPrimitive.Trigger\n        data-slot=\"tabs-trigger\"\n        className={cn(\n          'inline-flex cursor-pointer items-center size-full justify-center whitespace-nowrap rounded-sm px-2 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground z-[1]',\n          className,\n        )}\n        value={value}\n        {...props}\n      />\n    </MotionHighlightItem>\n  );\n}\n\ntype TabsContentProps = React.ComponentProps<typeof TabsPrimitive.Content> &\n  HTMLMotionProps<'div'> & {\n    transition?: Transition;\n  };\n\nfunction TabsContent({\n  className,\n  children,\n  transition = {\n    duration: 0.5,\n    ease: 'easeInOut',\n  },\n  ...props\n}: TabsContentProps) {\n  return (\n    <TabsPrimitive.Content asChild {...props}>\n      <motion.div\n        data-slot=\"tabs-content\"\n        className={cn('flex-1 outline-none', className)}\n        layout\n        initial={{ opacity: 0, y: -10, filter: 'blur(4px)' }}\n        animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}\n        exit={{ opacity: 0, y: 10, filter: 'blur(4px)' }}\n        transition={transition}\n        {...props}\n      >\n        {children}\n      </motion.div>\n    </TabsPrimitive.Content>\n  );\n}\n\ntype TabsContentsProps = HTMLMotionProps<'div'> & {\n  children: React.ReactNode;\n  className?: string;\n  transition?: Transition;\n};\n\nfunction TabsContents({\n  children,\n  className,\n  transition = { type: 'spring', stiffness: 200, damping: 25 },\n  ...props\n}: TabsContentsProps) {\n  const containerRef = React.useRef<HTMLDivElement | null>(null);\n\n  const [height, setHeight] = React.useState(0);\n\n  React.useEffect(() => {\n    if (!containerRef.current) return;\n\n    const resizeObserver = new ResizeObserver((entries) => {\n      const newHeight = entries?.[0]?.contentRect.height;\n      if (!newHeight) return;\n      requestAnimationFrame(() => {\n        setHeight(newHeight);\n      });\n    });\n\n    resizeObserver.observe(containerRef.current);\n\n    return () => {\n      resizeObserver.disconnect();\n    };\n  }, [children]);\n\n  React.useLayoutEffect(() => {\n    if (containerRef.current) {\n      const initialHeight = containerRef.current.getBoundingClientRect().height;\n      setHeight(initialHeight);\n    }\n  }, [children]);\n\n  return (\n    <motion.div\n      data-slot=\"tabs-contents\"\n      layout\n      animate={{ height: height }}\n      transition={transition}\n      className={className}\n      {...props}\n    >\n      <div ref={containerRef}>{children}</div>\n    </motion.div>\n  );\n}\n\nexport {\n  Tabs,\n  TabsList,\n  TabsTrigger,\n  TabsContent,\n  TabsContents,\n  type TabsProps,\n  type TabsListProps,\n  type TabsTriggerProps,\n  type TabsContentProps,\n  type TabsContentsProps,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/radix/tabs.tsx"
    }
  ]
}