{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./components/ui/accordion.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { ChevronDown } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport React, { type ReactNode, useCallback } from 'react';\n\n/**\n * Interface for AccordionContext values\n */\ninterface AccordionContextType {\n  /**\n   * Whether the accordion item is active\n   */\n  isActive?: boolean;\n  /**\n   * The value of the accordion item\n   */\n  value?: string;\n  /**\n   * Function to change the active index\n   */\n  onChangeIndex?: (value: string) => void;\n}\n\n/**\n * Context for accordion components\n */\nconst AccordionContext = React.createContext<AccordionContextType>({});\n/**\n * Hook to use the accordion context\n */\nconst useAccordion = () => React.useContext(AccordionContext);\n\n/**\n * Container component for accordion items\n */\nexport function AccordionContainer({\n  children,\n  className,\n}: {\n  children: ReactNode;\n  className?: string;\n}) {\n  return <div className={cn('grid grid-cols-2 gap-1', className)}>{children}</div>;\n}\n\n/**\n * Wrapper component for accordion items\n */\nexport function AccordionWrapper({ children }: { children: ReactNode }) {\n  return <div>{children}</div>;\n}\n\n/**\n * Interface for Accordion props\n */\ninterface AccordionProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Whether multiple items can be active at the same time\n   */\n  multiple?: boolean;\n  /**\n   * Default active index\n   */\n  defaultValue?: string | string[];\n}\n\n/**\n * Accordion component\n */\nexport function Accordion({ children, multiple, defaultValue }: AccordionProps) {\n  /**\n   * State for active index\n   */\n  const [activeIndex, setActiveIndex] = React.useState<string | string[] | null>(\n    multiple ? (Array.isArray(defaultValue) ? defaultValue : []) : defaultValue || null\n  );\n\n  /**\n   * Function to change the active index\n   */\n  const onChangeIndex = useCallback(\n    (value: string) => {\n      setActiveIndex((currentActiveIndex) => {\n        if (!multiple) {\n          return value === currentActiveIndex ? null : value;\n        }\n\n        if (Array.isArray(currentActiveIndex)) {\n          if (currentActiveIndex.includes(value)) {\n            return currentActiveIndex.filter((i) => i !== value);\n          }\n          return [...currentActiveIndex, value];\n        }\n\n        return [value];\n      });\n    },\n    [multiple]\n  );\n\n  return React.Children.map(children, (child) => {\n    if (!React.isValidElement(child)) return null;\n\n    const childProps = child.props as { value: string };\n    const value = childProps.value;\n    const isActive = multiple\n      ? Array.isArray(activeIndex) && activeIndex.includes(value)\n      : activeIndex === value;\n\n    return (\n      <AccordionContext.Provider value={{ isActive, value, onChangeIndex }}>\n        {child}\n      </AccordionContext.Provider>\n    );\n  });\n}\n\n/**\n * Interface for AccordionItem props\n */\ninterface AccordionItemProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Value of the accordion item\n   */\n  value: string;\n  className?: string;\n}\n\n/**\n * Accordion item component\n */\nexport function AccordionItem({ children, value, className }: AccordionItemProps) {\n  const { isActive } = useAccordion();\n\n  return (\n    <div\n      data-active={isActive || undefined}\n      className={cn(\n        'rounded-lg overflow-hidden mb-2 group border border-neutral-200 dark:border-neutral-800',\n        className\n      )}\n    >\n      {children}\n    </div>\n  );\n}\n\n/**\n * Interface for AccordionHeader props\n */\ninterface AccordionHeaderProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Icon component\n   */\n  customIcon?: boolean;\n  className?: string;\n}\n\n/**\n * Accordion header component\n */\nexport function AccordionHeader({ children, customIcon, className }: AccordionHeaderProps) {\n  const { isActive, value, onChangeIndex } = useAccordion();\n\n  const handleClick = useCallback(() => {\n    if (value && onChangeIndex) {\n      onChangeIndex(value);\n    }\n  }, [onChangeIndex, value]);\n\n  return (\n    <motion.button\n      type='button'\n      data-active={isActive || undefined}\n      aria-expanded={isActive}\n      className={cn(\n        'p-4 cursor-pointer w-full transition-all font-semibold text-neutral-500 dark:data-active:text-neutral-200 data-active:text-neutral-800 dark:data-active:bg-neutral-800 data-active:bg-neutral-200 hover:bg-neutral-100 hover:text-black flex justify-between gap-2 items-center text-left',\n        className\n      )}\n      onClick={handleClick}\n    >\n      {children}\n      {!customIcon && (\n        <ChevronDown\n          className={cn(\n            'transition-transform shrink-0 text-neutral-500 dark:text-neutral-400',\n            isActive ? 'rotate-180' : 'rotate-0'\n          )}\n          aria-hidden='true'\n        />\n      )}\n    </motion.button>\n  );\n}\n/**\n * Interface for AccordionPanel props\n */\ninterface AccordionPanelProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * className\n   */\n  className?: string;\n  /**\n   * article className\n   */\n  articleClassName?: string;\n}\n\n/**\n * Accordion panel component\n */\nexport function AccordionPanel({ children, className, articleClassName }: AccordionPanelProps) {\n  const { isActive, value } = useAccordion();\n\n  return (\n    <AnimatePresence initial={true}>\n      {isActive && (\n        <motion.div\n          data-active={isActive || undefined}\n          role='region'\n          id={`accordion-panel-${value}`}\n          aria-labelledby={`accordion-header-${value}`}\n          initial={{ height: 0, overflow: 'hidden' }}\n          animate={{ height: 'auto', overflow: 'hidden' }}\n          exit={{ height: 0 }}\n          transition={{ type: 'spring', duration: 0.3, bounce: 0 }}\n          className={cn(\n            'bg-neutral-100 dark:bg-neutral-900 px-2 data-active:bg-neutral-200 dark:data-active:bg-neutral-800 text-black dark:text-white',\n            className\n          )}\n        >\n          <motion.div\n            initial={{ clipPath: 'polygon(0 0, 100% 0, 100% 0, 0 0)' }}\n            animate={{ clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0% 100%)' }}\n            exit={{\n              clipPath: 'polygon(0 0, 100% 0, 100% 0, 0 0)',\n            }}\n            transition={{\n              type: 'spring',\n              duration: 0.4,\n              bounce: 0,\n            }}\n            className={cn('px-3 bg-transparent pb-4 space-y-2', articleClassName)}\n          >\n            {children}\n          </motion.div>\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}