{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radix-accordion",
  "type": "registry:ui",
  "title": "Radix Accordion",
  "description": "A vertically stacked set of interactive headings that each reveal an associated section of content.",
  "dependencies": [
    "motion",
    "radix-ui"
  ],
  "files": [
    {
      "path": "registry/radix/accordion/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { Accordion as AccordionPrimitive } from 'radix-ui';\nimport { ChevronDown } from 'lucide-react';\nimport {\n  motion,\n  AnimatePresence,\n  type Transition,\n  type HTMLMotionProps,\n} from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype AccordionItemContextType = {\n  isOpen: boolean;\n  setIsOpen: (open: boolean) => void;\n};\n\nconst AccordionItemContext = React.createContext<\n  AccordionItemContextType | undefined\n>(undefined);\n\nconst useAccordionItem = (): AccordionItemContextType => {\n  const context = React.useContext(AccordionItemContext);\n  if (!context) {\n    throw new Error('useAccordionItem must be used within an AccordionItem');\n  }\n  return context;\n};\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root>;\n\nfunction Accordion(props: AccordionProps) {\n  return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />;\n}\n\ntype AccordionItemProps = React.ComponentProps<\n  typeof AccordionPrimitive.Item\n> & {\n  children: React.ReactNode;\n};\n\nfunction AccordionItem({ className, children, ...props }: AccordionItemProps) {\n  const [isOpen, setIsOpen] = React.useState(false);\n\n  return (\n    <AccordionItemContext.Provider value={{ isOpen, setIsOpen }}>\n      <AccordionPrimitive.Item\n        data-slot=\"accordion-item\"\n        className={cn('border-b', className)}\n        {...props}\n      >\n        {children}\n      </AccordionPrimitive.Item>\n    </AccordionItemContext.Provider>\n  );\n}\n\ntype AccordionTriggerProps = React.ComponentProps<\n  typeof AccordionPrimitive.Trigger\n> & {\n  transition?: Transition;\n  chevron?: boolean;\n};\n\nfunction AccordionTrigger({\n  ref,\n  className,\n  children,\n  transition = { type: 'spring', stiffness: 150, damping: 22 },\n  chevron = true,\n  ...props\n}: AccordionTriggerProps) {\n  const triggerRef = React.useRef<HTMLButtonElement | null>(null);\n  React.useImperativeHandle(ref, () => triggerRef.current as HTMLButtonElement);\n  const { isOpen, setIsOpen } = useAccordionItem();\n\n  React.useEffect(() => {\n    const node = triggerRef.current;\n    if (!node) return;\n\n    const observer = new MutationObserver((mutationsList) => {\n      mutationsList.forEach((mutation) => {\n        if (mutation.attributeName === 'data-state') {\n          const currentState = node.getAttribute('data-state');\n          setIsOpen(currentState === 'open');\n        }\n      });\n    });\n    observer.observe(node, {\n      attributes: true,\n      attributeFilter: ['data-state'],\n    });\n    const initialState = node.getAttribute('data-state');\n    setIsOpen(initialState === 'open');\n    return () => {\n      observer.disconnect();\n    };\n  }, [setIsOpen]);\n\n  return (\n    <AccordionPrimitive.Header data-slot=\"accordion-header\" className=\"flex\">\n      <AccordionPrimitive.Trigger\n        ref={triggerRef}\n        data-slot=\"accordion-trigger\"\n        className={cn(\n          'flex flex-1 text-start items-center justify-between py-4 font-medium hover:underline',\n          className,\n        )}\n        {...props}\n      >\n        {children}\n\n        {chevron && (\n          <motion.div\n            data-slot=\"accordion-trigger-chevron\"\n            animate={{ rotate: isOpen ? 180 : 0 }}\n            transition={transition}\n          >\n            <ChevronDown className=\"size-5 shrink-0\" />\n          </motion.div>\n        )}\n      </AccordionPrimitive.Trigger>\n    </AccordionPrimitive.Header>\n  );\n}\n\ntype AccordionContentProps = React.ComponentProps<\n  typeof AccordionPrimitive.Content\n> &\n  HTMLMotionProps<'div'> & {\n    transition?: Transition;\n  };\n\nfunction AccordionContent({\n  className,\n  children,\n  transition = { type: 'spring', stiffness: 150, damping: 22 },\n  ...props\n}: AccordionContentProps) {\n  const { isOpen } = useAccordionItem();\n\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <AccordionPrimitive.Content forceMount {...props}>\n          <motion.div\n            key=\"accordion-content\"\n            data-slot=\"accordion-content\"\n            initial={{ height: 0, opacity: 0, '--mask-stop': '0%' }}\n            animate={{ height: 'auto', opacity: 1, '--mask-stop': '100%' }}\n            exit={{ height: 0, opacity: 0, '--mask-stop': '0%' }}\n            transition={transition}\n            style={{\n              maskImage:\n                'linear-gradient(black var(--mask-stop), transparent var(--mask-stop))',\n              WebkitMaskImage:\n                'linear-gradient(black var(--mask-stop), transparent var(--mask-stop))',\n            }}\n            className=\"overflow-hidden\"\n            {...props}\n          >\n            <div className={cn('pb-4 pt-0 text-sm', className)}>{children}</div>\n          </motion.div>\n        </AccordionPrimitive.Content>\n      )}\n    </AnimatePresence>\n  );\n}\n\nexport {\n  Accordion,\n  AccordionItem,\n  AccordionTrigger,\n  AccordionContent,\n  useAccordionItem,\n  type AccordionItemContextType,\n  type AccordionProps,\n  type AccordionItemProps,\n  type AccordionTriggerProps,\n  type AccordionContentProps,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/radix/accordion.tsx"
    }
  ]
}