Spaces:
Running
Running
'use client' | |
import type { FC } from 'react' | |
import React, { useEffect } from 'react' | |
import cn from 'classnames' | |
import { useBoolean } from 'ahooks' | |
import { ChevronRightIcon } from '@heroicons/react/24/outline' | |
export type IPanelProps = { | |
className?: string | |
headerIcon: React.ReactNode | |
title: React.ReactNode | |
headerRight?: React.ReactNode | |
bodyClassName?: string | |
children: React.ReactNode | |
keepUnFold?: boolean | |
foldDisabled?: boolean | |
onFoldChange?: (fold: boolean) => void | |
controlUnFold?: number | |
controlFold?: number | |
} | |
const Panel: FC<IPanelProps> = ({ | |
className, | |
headerIcon, | |
title, | |
headerRight, | |
bodyClassName, | |
children, | |
keepUnFold, | |
foldDisabled = false, | |
onFoldChange, | |
controlUnFold, | |
controlFold, | |
}) => { | |
const [fold, { setTrue: setFold, setFalse: setUnFold, toggle: toggleFold }] = useBoolean(!keepUnFold) | |
useEffect(() => { | |
onFoldChange?.(fold) | |
}, [fold]) | |
useEffect(() => { | |
if (controlUnFold) | |
setUnFold() | |
}, [controlUnFold]) | |
useEffect(() => { | |
if (controlFold) | |
setFold() | |
}, [controlFold]) | |
// overflow-hidden | |
return ( | |
<div className={cn(className, 'w-full rounded-xl border border-gray-100 overflow-hidden select-none')}> | |
{/* Header */} | |
<div | |
onClick={() => (!foldDisabled && !keepUnFold) && toggleFold()} | |
className={cn(!fold && 'border-b border-gray-100', 'flex justify-between items-center h-12 bg-gray-50 pl-4 pr-2')}> | |
<div className='flex items-center gap-2'> | |
{headerIcon} | |
<div className='text-gray-900 text-sm'>{title}</div> | |
</div> | |
{(fold && headerRight) ? headerRight : ''} | |
{!headerRight && !keepUnFold && ( | |
<ChevronRightIcon className={cn(!fold && 'rotate-90', 'mr-2 cursor-pointer')} width="16" height="16"> | |
</ChevronRightIcon> | |
)} | |
</div> | |
{/* Main Content */} | |
{!fold && !foldDisabled && ( | |
<div className={cn(bodyClassName)}> | |
{children} | |
</div> | |
)} | |
</div> | |
) | |
} | |
export default React.memo(Panel) | |