import React, { cloneElement, isValidElement, Key, ReactElement, ReactNode, useId, useRef, } from 'react'; import clsx from 'clsx'; import {AnimatePresence, m} from 'framer-motion'; import {useControlledState} from '@react-stately/utils'; import {FocusScope, useFocusManager} from '@react-aria/focus'; import {KeyboardArrowDownIcon} from '../../icons/material/KeyboardArrowDown'; import {AccordionAnimation} from '@common/ui/accordion/accordtion-animation'; type Props = { variant?: 'outline' | 'default' | 'minimal'; children?: ReactNode; mode?: 'single' | 'multiple'; expandedValues?: Key[]; defaultExpandedValues?: Key[]; onExpandedChange?: (key: Key[]) => void; className?: string; isLazy?: boolean; }; export const Accordion = React.forwardRef( ( { variant = 'default', mode = 'single', children, className, isLazy, ...other }, ref, ) => { const [expandedValues, setExpandedValues] = useControlledState( other.expandedValues, other.defaultExpandedValues || [], other.onExpandedChange, ); return (
{React.Children.map(children, (child, index) => { if (!isValidElement(child)) return null; return cloneElement(child, { key: child.key || index, value: child.props.value || index, mode, variant, expandedValues, setExpandedValues, isLazy, }); })}
); }, ); interface AccordionItemProps { children: ReactNode; disabled?: boolean; label: ReactNode; description?: ReactNode; value?: Key; bodyClassName?: string; labelClassName?: string; buttonPadding?: string; chevronPosition?: 'left' | 'right'; startIcon?: ReactElement; endAppend?: ReactElement; } interface ClonedItemProps extends AccordionItemProps { variant?: 'outline' | 'default' | 'minimal'; expandedValues: Key[]; setExpandedValues: (keys: Key[]) => void; mode: 'single' | 'multiple'; value: Key; isLazy?: boolean; } export function AccordionItem({ children, label, disabled, bodyClassName, labelClassName, buttonPadding = 'py-10 pl-14 pr-10', startIcon, description, endAppend, chevronPosition = 'right', ...other }: AccordionItemProps) { const {expandedValues, setExpandedValues, variant, value, mode, isLazy} = other as ClonedItemProps; const ref = useRef(null); const isExpanded = !disabled && expandedValues.includes(value); const wasExpandedOnce = useRef(false); if (isExpanded) { wasExpandedOnce.current = true; } const focusManager = useFocusManager(); const id = useId(); const buttonId = `${id}-button`; const panelId = `${id}-panel`; const onKeyDown = (e: React.KeyboardEvent) => { switch (e.key) { case 'ArrowDown': focusManager?.focusNext(); break; case 'ArrowUp': focusManager?.focusPrevious(); break; case 'Home': focusManager?.focusFirst(); break; case 'End': focusManager?.focusLast(); break; } }; const toggle = () => { const i = expandedValues.indexOf(value); if (i > -1) { const newKeys = [...expandedValues]; newKeys.splice(i, 1); setExpandedValues(newKeys); } else if (mode === 'single') { setExpandedValues([value]); } else { setExpandedValues([...expandedValues, value]); } }; const chevron = (
); return (

{endAppend && (
{endAppend}
)}

{!isLazy || wasExpandedOnce ? children : null}
); }