import { Card, useTheme } from '@mui/material'; import { useAtomValue } from 'jotai'; import { equals, isNil, omit, type } from 'ramda'; import { type CSSProperties, type MouseEvent, type ReactElement, RefObject, useEffect, useMemo } from 'react'; import ExpandableContainer from '../components/ExpandableContainer'; import type { Parameters } from '../components/ExpandableContainer/models'; import { useMemoComponent, useViewportIntersection } from '../utils'; import { isResizingItemAtom } from './atoms'; import { useDashboardItemStyles } from './Dashboard.styles'; interface DashboardItemProps { additionalMemoProps?: Array; canMove?: boolean; children: Array< | ReactElement | (({ isInViewport }: { isInViewport: boolean }) => ReactElement) >; className?: string; disablePadding?: boolean; header?: ReactElement | ((params: Parameters) => ReactElement); id: string; onMouseDown?: (e: MouseEvent) => void; onMouseUp?: (e: MouseEvent) => void; onTouchEnd?: (e: React.TouchEvent) => void; style?: CSSProperties; ref?: RefObject; } const Item = ({ children, style, className, header, onMouseDown, onMouseUp, onTouchEnd, id, disablePadding = false, canMove = false, additionalMemoProps = [], ref }: DashboardItemProps): ReactElement => { const { isInViewport, setElement } = useViewportIntersection({ rootMargin: '140px 0px 140px 0px' }); const hasHeader = !isNil(header); const { classes, cx } = useDashboardItemStyles({ hasHeader }); const theme = useTheme(); const isResizingItem = useAtomValue(isResizingItemAtom); const isResizing = useMemo( () => equals(id, isResizingItem), [isResizingItem, id] ); const sanitizedReactGridLayoutClassName = useMemo( () => (isResizing ? className : className?.replace(' resizing ', '')), [className, isResizing] ); const listeners = { onMouseDown, onMouseUp, onTouchEnd }; const cardContainerListeners = !hasHeader ? listeners : {}; useEffect(() => { if (isNil(ref?.current)) { return; } setElement(ref.current); }, [ref, setElement]); const newTransform = style?.transform && `translate3d(${style.transform.match(/translate\(([a-z0-9 ,-]+)\)/)?.[1]}, 0px)`; return useMemoComponent({ Component: (
{({ isExpanded, label, key, ...rest }) => { const canControl = isExpanded ? false : canMove; const childrenHeader = equals(type(header), 'Function') ? (header as (params: Parameters) => ReactElement)({ isExpanded, key, label, ref: ref as RefObject, ...rest }) : (header as ReactElement); return (
{childrenHeader && (
{canControl && (
)} {childrenHeader}
)}
{children.map((child) => typeof child === 'function' ? child({ isInViewport }) : child )}
); }}
), memoProps: isInViewport ? [ style, className, header, theme.palette.mode, canMove, isInViewport, ...additionalMemoProps ] : [isInViewport, theme.palette.mode, style] }); }; export default Item;