{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "animated-tabs",
  "dependencies": [
    "motion"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/ui/tab.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { AnimatePresence, motion } from 'motion/react';\nimport React, {\n  createContext,\n  isValidElement,\n  type ReactNode,\n  useCallback,\n  useContext,\n  useMemo,\n  useState,\n} from 'react';\n\n// Improved TypeScript interfaces with more specific types\ninterface TabContextType {\n  activeTab: string;\n  setActiveTab: (value: string) => void;\n  wobbly: boolean;\n  hover: boolean;\n  defaultValue: string;\n  prevIndex: number;\n  setPrevIndex: (value: number) => void;\n  tabsOrder: string[];\n}\n\nconst TabContext = createContext<TabContextType | undefined>(undefined);\n\n// Custom hook with memoization\nexport const useTabs = () => {\n  const context = useContext(TabContext);\n  if (!context) {\n    throw new Error('useTabs must be used within a TabsProvider');\n  }\n  return context;\n};\n\n// Props interfaces with more specific types\ninterface TabsProviderProps {\n  children: ReactNode;\n  defaultValue: string;\n  wobbly?: boolean;\n  hover?: boolean;\n}\n\ninterface TabsBtnProps {\n  children: ReactNode;\n  className?: string;\n  value: string;\n}\n\ninterface TabsContentProps {\n  children: ReactNode;\n  className?: string;\n  value: string;\n  yValue?: boolean;\n}\n\nexport const TabsProvider: React.FC<TabsProviderProps> = React.memo(\n  ({ children, defaultValue, wobbly = true, hover = false }) => {\n    // Use useCallback to memoize state setters\n    const [activeTab, setActiveTab] = useState(defaultValue);\n    const [prevIndex, setPrevIndex] = useState(0);\n\n    // Memoize tabs order to prevent unnecessary recalculations\n    const tabsOrder = useMemo(() => {\n      return React.Children.toArray(children)\n        .filter((child) => isValidElement(child) && child.type === TabsContent)\n        .map((child) => (child as React.ReactElement<any>).props.value);\n    }, [children]);\n\n    // Memoize context value to prevent unnecessary re-renders\n    const contextValue = useMemo(\n      () => ({\n        activeTab,\n        setActiveTab,\n        wobbly,\n        hover,\n        defaultValue,\n        setPrevIndex,\n        prevIndex,\n        tabsOrder,\n      }),\n      [activeTab, setActiveTab, wobbly, hover, defaultValue, prevIndex, tabsOrder]\n    );\n\n    return <TabContext.Provider value={contextValue}>{children}</TabContext.Provider>;\n  }\n);\n\n// Memoized TabsBtn component\nexport const TabsBtn: React.FC<TabsBtnProps> = React.memo(({ children, className, value }) => {\n  const { activeTab, setPrevIndex, setActiveTab, defaultValue, hover, wobbly, tabsOrder } =\n    useTabs();\n\n  // Use useCallback to memoize the click handler\n  const handleClick = useCallback(() => {\n    setPrevIndex(tabsOrder.indexOf(activeTab));\n    setActiveTab(value);\n  }, [setPrevIndex, tabsOrder, activeTab, setActiveTab, value]);\n\n  return (\n    <motion.div\n      className={cn(`cursor-pointer 2xl:p-2 p-2 2xl:px-4 px-2 rounded-md relative`, className)}\n      onFocus={() => hover && handleClick()}\n      onMouseEnter={() => hover && handleClick()}\n      onClick={handleClick}\n    >\n      {children}\n\n      <AnimatePresence mode='wait'>\n        {activeTab === value && (\n          <>\n            <motion.div\n              transition={{\n                layout: {\n                  duration: 0.2,\n                  ease: 'easeInOut',\n                  delay: 0.2,\n                },\n              }}\n              layoutId={defaultValue}\n              className='absolute w-full h-full left-0 top-0 dark:bg-primary-base bg-white rounded-md z-1'\n            />\n\n            {wobbly && (\n              <>\n                <motion.div\n                  transition={{\n                    layout: {\n                      duration: 0.4,\n                      ease: 'easeInOut',\n                      delay: 0.04,\n                    },\n                  }}\n                  layoutId={defaultValue}\n                  className='absolute w-full h-full left-0 top-0 dark:bg-primary-base bg-white rounded-md z-1 tab-shadow'\n                />\n                <motion.div\n                  transition={{\n                    layout: {\n                      duration: 0.4,\n                      ease: 'easeOut',\n                      delay: 0.2,\n                    },\n                  }}\n                  layoutId={`${defaultValue}b`}\n                  className='absolute w-full h-full left-0 top-0 dark:bg-primary-base bg-white rounded-md z-1 tab-shadow'\n                />\n              </>\n            )}\n          </>\n        )}\n      </AnimatePresence>\n    </motion.div>\n  );\n});\n\n// Memoized TabsContent component\nexport const TabsContent: React.FC<TabsContentProps> = React.memo(\n  ({ children, className, value, yValue }) => {\n    const { activeTab, tabsOrder, prevIndex } = useTabs();\n\n    // Memoize direction calculation\n    const isForward = useMemo(\n      () => tabsOrder.indexOf(activeTab) > prevIndex,\n      [tabsOrder, activeTab, prevIndex]\n    );\n\n    return (\n      <AnimatePresence mode='popLayout'>\n        {activeTab === value && (\n          <motion.div\n            initial={{ opacity: 0, y: yValue ? (isForward ? 10 : -10) : 0 }}\n            animate={{ opacity: 1, y: 0 }}\n            exit={{ opacity: 0, y: yValue ? (isForward ? -50 : 50) : 0 }}\n            transition={{\n              duration: 0.3,\n              ease: 'easeInOut',\n              delay: 0.5,\n            }}\n            className={cn('p-2 px-4 rounded-md relative', className)}\n          >\n            {children}\n          </motion.div>\n        )}\n      </AnimatePresence>\n    );\n  }\n);\n\n// Add display names for better debugging\nTabsProvider.displayName = 'TabsProvider';\nTabsBtn.displayName = 'TabsBtn';\nTabsContent.displayName = 'TabsContent';\n",
      "type": "registry:component"
    },
    {
      "path": "./registry/components/tabs/preview-tab.tsx",
      "content": "'use client';\nimport { TabsBtn, TabsContent, TabsProvider } from '@/components/ui/tab';\nimport { AnimatePresence, motion } from 'motion/react';\nimport Image from 'next/image';\nimport React, { useState } from 'react';\n\nconst effectArr = [\n  {\n    id: 1,\n    name: 'basic',\n  },\n  {\n    id: 2,\n    name: 'hover',\n  },\n  {\n    id: 3,\n    name: 'wobbly',\n  },\n];\nfunction PreviewTab() {\n  const [checkEffect, setCheckEffect] = useState('basic');\n  return (\n    <>\n      <div className='flex bg-black dark:bg-neutral-900 w-fit ml-auto mb-4 gap-1 p-1 rounded-md text-white'>\n        {effectArr?.map((effect, index) => {\n          return (\n            <>\n              <motion.button\n                onClick={() => setCheckEffect(effect?.name)}\n                className={`py-1 px-3 rounded-md capitalize relative `}\n              >\n                <span className='z-10 relative'>{effect?.name}</span>\n                {checkEffect === effect.name && (\n                  <motion.div\n                    transition={{\n                      layout: {\n                        duration: 0.2,\n                        ease: 'easeInOut',\n                      },\n                    }}\n                    layoutId={'magnetic'}\n                    className='absolute w-full h-full left-0 top-0 bg-[conic-gradient(from_90deg_at_50%_50%,#8494ff_0%,#3749be_50%,#7d8efc_100%)] rounded-md  z-1 tab-shadow'\n                  />\n                )}\n              </motion.button>\n            </>\n          );\n        })}\n      </div>\n\n      <div className='border bg-white/10 dark:bg-black/40 backdrop-blur-xs rounded-md p-4  relative'>\n        <TabsProvider\n          defaultValue={'design'}\n          wobbly={checkEffect === 'wobbly' ? true : false}\n          hover={checkEffect === 'hover' ? true : false}\n        >\n          <div className='flex justify-center mt-2'>\n            <div className='flex items-center w-fit dark:bg-[#1d2025] bg-neutral-200 p-1 dark:text-white text-black rounded-md border'>\n              <TabsBtn value='design'>\n                <span className='relative z-2 uppercase sm:text-base text-xs'>design</span>\n              </TabsBtn>\n              <TabsBtn value='collaborate'>\n                <span className='relative z-2 uppercase sm:text-base text-xs'>collaborate</span>\n              </TabsBtn>\n              <TabsBtn value='share'>\n                <span className='relative z-2 uppercase sm:text-base text-xs'>share</span>\n              </TabsBtn>\n              <TabsBtn value='publish'>\n                <span className='relative z-2 uppercase sm:text-base text-xs'>publish</span>\n              </TabsBtn>\n            </div>\n          </div>\n          <TabsContent value='design'>\n            <div className='w-full'>\n              <Image\n                src={\n                  'https://images.unsplash.com/photo-1506097425191-7ad538b29cef?q=80&w=1000&auto=format&fit=crop'\n                }\n                width={1000}\n                height={1000}\n                alt='preview_img'\n                className='w-[850px] object-cover h-full mx-auto rounded-md'\n              />\n            </div>\n          </TabsContent>\n          <TabsContent value='collaborate'>\n            <div className='w-full'>\n              <Image\n                src={\n                  'https://images.unsplash.com/photo-1557804506-669a67965ba0?q=80&w=1000&auto=format&fit=crop'\n                }\n                width={1000}\n                height={1000}\n                alt='preview_img'\n                className='w-[850px] object-cover h-full mx-auto rounded-md'\n              />\n            </div>\n          </TabsContent>\n          <TabsContent value='share'>\n            <div className='w-full'>\n              <Image\n                src={\n                  'https://images.unsplash.com/photo-1665470909901-162912ec16f7?q=80&w=1000&auto=format&fit=crop'\n                }\n                width={1000}\n                height={1000}\n                alt='preview_img'\n                className='w-[850px] object-cover h-full mx-auto rounded-md'\n              />\n            </div>\n          </TabsContent>\n          <TabsContent value='publish'>\n            <div className='w-full'>\n              <Image\n                src={\n                  'https://images.unsplash.com/photo-1694022861804-840f61d1c452?q=80&w=1000&auto=format&fit=crop'\n                }\n                width={1000}\n                height={1000}\n                alt='preview_img'\n                className='w-[850px] object-cover h-full mx-auto rounded-md'\n              />\n            </div>\n          </TabsContent>\n        </TabsProvider>\n      </div>\n    </>\n  );\n}\n\nexport default PreviewTab;\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}