import { CloseOutlined } from '@mui/icons-material' import { Box, Divider, Grow, IconButton, Paper } from '@mui/material' import { isValidElement, useState, type JSX, type MouseEvent } from 'react' import { Tooltip } from '../../components/tooltip/tooltip' import { styles } from './styles' import type { ToolbarActionsProps } from './types' import { WidgetOptions } from '@carto/meridian-ds/custom-icons' const DEFAULT_LABELS = { trigger: 'More actions', close: 'Close', } /** * A floating toolbar component that displays action buttons. * Shows a trigger button when there are more visible actions than the visibleCount, * which expands to reveal all actions with a close button. * When visibleCount is undefined, all actions are shown without overflow. * * Children with the `data-toolbar-hidden` attribute are ignored when counting * visible actions but are included in the preview. This is useful for elements * like Dividers that should appear between actions but not count toward the limit. * * Example: With visibleCount=2 and children [Action1, Divider, Action2, Divider, Action3]: * - Preview shows: Action1, Divider, Action2 (2 visible actions + divider) * - Hidden: Divider, Action3 */ export function ToolbarActions({ children: _children, visibleCount, direction, labels, sx, IconButtonProps, TooltipProps, }: ToolbarActionsProps): JSX.Element | null { const [anchorEl, setAnchorEl] = useState(null) const triggerLabel = labels?.trigger ?? DEFAULT_LABELS.trigger const closeLabel = labels?.close ?? DEFAULT_LABELS.close const children = (Array.isArray(_children) ? _children : [_children]).filter( Boolean, ) // Don't render if no actions if (children.length === 0) { return null } // Filter out children with data-toolbar-hidden attribute for counting const visibleChildren = children.filter( (child) => !( isValidElement<{ 'data-toolbar-hidden'?: boolean }>(child) && child.props['data-toolbar-hidden'] ), ) // Show trigger only when visibleCount is defined and there are more visible actions const showTrigger = visibleCount !== undefined && visibleChildren.length > visibleCount const handleToggle = (e: MouseEvent) => { setAnchorEl((prev) => (prev ? null : e.currentTarget)) } // Build preview by including hidden elements but only counting visible ones const childrenPreview = visibleCount === undefined ? children : children.reduce<{ result: React.ReactNode[]; count: number }>( (acc, child) => { // Stop if we've already collected enough visible actions if (acc.count >= visibleCount) { return acc } const isHidden = isValidElement<{ 'data-toolbar-hidden'?: boolean }>(child) && child.props['data-toolbar-hidden'] return { result: [...acc.result, child], count: acc.count + (isHidden ? 0 : 1), } }, { result: [], count: 0 }, ).result const width = anchorEl?.getBoundingClientRect().width return ( {/* Trigger button - only shown when 3+ actions */} {showTrigger && ( <> {anchorEl ? : } )} {childrenPreview} {/* Actions container - shown only when expanded (trigger is active) */} direction === 'left' ? 0 : spacing(0.25), marginRight: ({ spacing }) => direction === 'left' ? spacing(0.25) : 0, }} > {children} ) }