import * as React from 'react' import type { ButtonProps, DropdownMenuCloseReason, DropdownMenuProps, DropdownTriggerProps, MenuProps, } from '@planview/pv-uikit' import { ButtonEmpty, DropdownMenu, Menu } from '@planview/pv-uikit' import { useGridApi } from '../context/grid-context' import styled from 'styled-components' const CCell = styled.div` height: 100%; width: 100%; ` const StyledButtonEmpty = styled(ButtonEmpty)` height: 100%; ` type CellDropdownMenuTriggerConfig = Omit< ButtonProps, | 'aria-haspopup' | 'aria-controls' | 'aria-expanded' | 'aria-disabled' | 'children' | 'size' > & { /** Label of trigger */ label?: string | number } export type GridCellDropdownMenuProps = { /** * Accessible tab index. You should generally pass through the tabIndex * provided to the Renderer component. */ tabIndex: number /** * Trigger configuration for dropdown menu. This is similar to DropdownMenu * except that you cannot provide a custom function and you can supply a tooltip. * * When omitted, it will default to showing the label and a caret */ trigger?: CellDropdownMenuTriggerConfig } & Omit type BaseMenu = Omit type GridCellDropdownMenuBaseProps< TMenuProps extends Partial = MenuProps, > = Pick< GridCellDropdownMenuProps, 'trigger' | 'tabIndex' | 'onOpen' | 'onClose' > & { MenuComponent: React.ComponentType menuProps: TMenuProps } /* Prevent the grid from selecting the row */ const stopPropagation: React.MouseEventHandler = (ev) => ev.stopPropagation() const GridCellDropdownMenuBase = ({ tabIndex, trigger, onClose, onOpen, MenuComponent, menuProps, }: GridCellDropdownMenuBaseProps) => { const api = useGridApi() const [open, setOpen] = React.useState(false) const handleOpen = React.useCallback(() => { setOpen(true) onOpen?.() }, [onOpen]) const handleClose = React.useCallback( (reason: DropdownMenuCloseReason) => { setOpen(false) onClose?.(reason) }, [onClose] ) const renderTrigger = React.useCallback< (trigger: DropdownTriggerProps) => React.JSX.Element >( (triggerProps) => { const { label: triggerLabel, ...triggerConfig } = trigger || { label: menuProps.label, withCaret: true, } return ( { if (e.key === 'Enter' || e.key === ' ') { return triggerProps.onKeyDown(e) } }} onClick={stopPropagation} > {triggerLabel} ) }, [menuProps.label, tabIndex, trigger] ) React.useEffect(() => { if (open) { api.navigation.disable() return () => { api.navigation.enable() } } }, [api.navigation, open]) return ( ) } const GridCellDropdownMenuImpl = ({ tabIndex, trigger, onClose, onOpen, ...menuProps }: GridCellDropdownMenuProps) => ( ) const GridCellDropdownMenuMemo = React.memo(GridCellDropdownMenuImpl) as any GridCellDropdownMenuMemo.displayName = 'GridCellDropdownMenu' GridCellDropdownMenuMemo.Base = GridCellDropdownMenuBase type GridCellDropdownMenuComposite = typeof GridCellDropdownMenuImpl & { Base: typeof GridCellDropdownMenuBase } export const GridCellDropdownMenu = GridCellDropdownMenuMemo as GridCellDropdownMenuComposite