import classnames from 'classnames'; import React from 'react'; import type { IIconProps } from '@spinnaker/presentation'; import { Icon } from '@spinnaker/presentation'; import { CollapsibleSectionStateCache } from '../../cache/collapsibleSectionStateCache'; export interface ICollapsibleSectionProps { outerDivClassName?: string; toggleClassName?: string; headingClassName?: string; bodyClassName?: string; cacheKey?: string; enableCaching?: boolean; defaultExpanded?: boolean; expandIconPosition?: 'left' | 'right'; expandIconType?: 'arrow' | 'plus' | 'arrowCross'; expandIconSize?: string; heading: ((props: { chevron: JSX.Element }) => JSX.Element) | string; onToggle?: (isExpanded: boolean) => void; } export interface ICollapsibleSectionState { cacheKey: string; expanded: boolean; } const rotationByPosition = { left: { expanded: 'rotate-0', collapsed: 'rotate-m90', }, right: { expanded: 'rotate-p180', collapsed: 'rotate-p270', }, }; export const CollapsibleSection: React.FC = ({ outerDivClassName = 'collapsible-section', toggleClassName = 'section-heading', headingClassName = 'collapsible-heading', bodyClassName = 'content-body', enableCaching = true, cacheKey: cacheKeyInternal, defaultExpanded, heading, expandIconPosition = 'left', expandIconType = 'arrow', expandIconSize, onToggle, children, }) => { const cacheKey = React.useMemo( () => cacheKeyInternal || (typeof heading === 'string' ? (heading as string) : undefined), [cacheKeyInternal, heading], ); const [isExpanded, setIsExpanded] = React.useState( enableCaching && CollapsibleSectionStateCache.isSet(cacheKey) ? CollapsibleSectionStateCache.isExpanded(cacheKey) : defaultExpanded, ); const toggle = () => { setIsExpanded(!isExpanded); if (enableCaching) { CollapsibleSectionStateCache.setExpanded(cacheKey, !isExpanded); } onToggle?.(!isExpanded); }; const expandIconProps: Partial = { size: expandIconSize || '16px', color: 'concrete', }; const expandIcon = children ? ( {expandIconType === 'arrow' ? ( ) : expandIconType === 'plus' ? ( ) : ( )} ) : undefined; const Heading = typeof heading === 'string' ? (

{expandIconPosition === 'left' ? ( <> {expandIcon} {heading} ) : ( <> {heading} {expandIcon} )}

) : ( <>{heading({ chevron: expandIcon })} ); return (
{children ? (
{Heading}
) : ( Heading )} {isExpanded && children &&
{children}
}
); };