{ "name": "accordion", "type": "registry:ui", "registryDependencies": [], "dependencies": [ "motion" ], "devDependencies": [], "tailwind": {}, "cssVars": { "light": {}, "dark": {} }, "files": [ { "path": "accordion.tsx", "content": "'use client';\nimport {\n motion,\n AnimatePresence,\n Transition,\n Variants,\n Variant,\n MotionConfig,\n} from 'motion/react';\nimport { cn } from '@/lib/utils';\nimport React, { createContext, useContext, useState, ReactNode } from 'react';\n\nexport type AccordionContextType = {\n expandedValue: React.Key | null;\n toggleItem: (value: React.Key) => void;\n variants?: { expanded: Variant; collapsed: Variant };\n};\n\nconst AccordionContext = createContext(\n undefined\n);\n\nfunction useAccordion() {\n const context = useContext(AccordionContext);\n if (!context) {\n throw new Error('useAccordion must be used within an AccordionProvider');\n }\n return context;\n}\n\nexport type AccordionProviderProps = {\n children: ReactNode;\n variants?: { expanded: Variant; collapsed: Variant };\n expandedValue?: React.Key | null;\n onValueChange?: (value: React.Key | null) => void;\n};\n\nfunction AccordionProvider({\n children,\n variants,\n expandedValue: externalExpandedValue,\n onValueChange,\n}: AccordionProviderProps) {\n const [internalExpandedValue, setInternalExpandedValue] =\n useState(null);\n\n const expandedValue =\n externalExpandedValue !== undefined\n ? externalExpandedValue\n : internalExpandedValue;\n\n const toggleItem = (value: React.Key) => {\n const newValue = expandedValue === value ? null : value;\n if (onValueChange) {\n onValueChange(newValue);\n } else {\n setInternalExpandedValue(newValue);\n }\n };\n\n return (\n \n {children}\n \n );\n}\n\nexport type AccordionProps = {\n children: ReactNode;\n className?: string;\n transition?: Transition;\n variants?: { expanded: Variant; collapsed: Variant };\n expandedValue?: React.Key | null;\n onValueChange?: (value: React.Key | null) => void;\n};\n\nfunction Accordion({\n children,\n className,\n transition,\n variants,\n expandedValue,\n onValueChange,\n}: AccordionProps) {\n return (\n \n
\n \n {children}\n \n
\n
\n );\n}\n\nexport type AccordionItemProps = {\n value: React.Key;\n children: ReactNode;\n className?: string;\n};\n\nfunction AccordionItem({ value, children, className }: AccordionItemProps) {\n const { expandedValue } = useAccordion();\n const isExpanded = value === expandedValue;\n\n return (\n \n {React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n ...child.props,\n value,\n expanded: isExpanded,\n });\n }\n return child;\n })}\n \n );\n}\n\nexport type AccordionTriggerProps = {\n children: ReactNode;\n className?: string;\n};\n\nfunction AccordionTrigger({\n children,\n className,\n ...props\n}: AccordionTriggerProps) {\n const { toggleItem, expandedValue } = useAccordion();\n const value = (props as { value?: React.Key }).value;\n const isExpanded = value === expandedValue;\n\n return (\n value !== undefined && toggleItem(value)}\n aria-expanded={isExpanded}\n type='button'\n className={cn('group', className)}\n {...(isExpanded ? { 'data-expanded': '' } : {'data-closed': ''})}\n >\n {children}\n \n );\n}\n\nexport type AccordionContentProps = {\n children: ReactNode;\n className?: string;\n};\n\nfunction AccordionContent({\n children,\n className,\n ...props\n}: AccordionContentProps) {\n const { expandedValue, variants } = useAccordion();\n const value = (props as { value?: React.Key }).value;\n const isExpanded = value === expandedValue;\n\n const BASE_VARIANTS: Variants = {\n expanded: { height: 'auto', opacity: 1 },\n collapsed: { height: 0, opacity: 0 },\n };\n\n const combinedVariants = {\n expanded: { ...BASE_VARIANTS.expanded, ...variants?.expanded },\n collapsed: { ...BASE_VARIANTS.collapsed, ...variants?.collapsed },\n };\n\n return (\n \n {isExpanded && (\n \n {children}\n \n )}\n \n );\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n", "type": "registry:ui" } ] }