import type { HTMLAttributes, MouseEventHandler, ReactElement, ReactNode, SyntheticEvent } from 'react'; import type { SortEndHandler } from 'react-sortable-hoc'; import type { VariableSizeListProps } from 'react-window'; import type { CheckboxProps as MuiCheckboxProps } from '@mui/material/Checkbox'; import type { IconButtonProps as MuiIconButtonProps } from '@mui/material/IconButton'; import type { MenuProps as MuiMenuProps } from '@mui/material/Menu'; import type { MenuItemProps as MuiMenuItemProps } from '@mui/material/MenuItem'; import type { PopperProps } from '@mui/material/Popper'; import type { ButtonProps } from '../button'; import type { CustomIconProps } from '../custom-icon'; import type { TooltipProps } from '../@popovers/tooltip'; import type { CreateClassesProps } from './styles'; import createClasses from './styles'; export interface DropDownMenuProps extends Omit { /** * A HTML element, or a function that returns it. * It's used to set the position of the menu. * @document */ anchorEl?: MuiMenuProps['anchorEl'] | PopperProps['anchorEl']; /** * Call back which will be fired on clicking a menu item. */ handleClick?: ( name: string | number, value?: DropdownMenuItem['value'] ) => MouseEventHandler; /** * The items which will be shown in the list. */ listItems: DropdownMenuItem[]; /** * Changes an existing menu item. This function is used to specify the content, appearance, and behavior of the menu item. * @param {MenuItemProps} props * @returns {MenuItemProps} */ modifyMenuItem?: (props: MenuItemProps) => Partial; /** * Will be placed just before the list. */ InsertBeforeList?: () => ReactNode; /** * Will be placed right after the list. */ InsertAfterList?: () => ReactNode; /** * Allow multiple selection. Notice your selection logic should also support multiple selection. */ multiple?: boolean; /** * Specify top addition to place the menu correctly relative to the anchor component. */ anchorElTopAddition?: number; /** * The width of the menu. */ width?: number; /** * Whether or not to show selected icon on single selection. */ showSelectedIcon?: boolean; /** * Whether or not to show the sort icon for menu items, notice you must pass `onSortEnd` to make it work. */ sortable?: boolean; /** * Callback which is fired on sort end. */ onSortEnd?: SortEndHandler; /** * Whether or not to allow searching items inside the menu, notice you must pass `handleSearchChangeCallback` to make it work. */ search?: boolean; /** * Callback which is fired on search text change. */ handleSearchChangeCallback?: (value: string) => void; /** * Highlighting emphasizes the search term(s) matches in the results. * @default false */ searchHighlight?: boolean; /** * Place holder for the search field. */ searchPlaceholder?: string; /** * List of fields to search by. * @default ['name'] */ searchBy?: Array; /** * Whether or not to show the delete icon for menu items, notice you must pass `handleDelete` to make it work. */ deletable?: boolean; /** * Call back which will be fired on click a delete icon. */ handleDelete?: ( name: string | number, value?: DropdownMenuItem['value'] ) => MouseEventHandler; /** * If passed, a button will appear in the bottom of the menu, pass `bottomButtonClickHandler` to make it work. */ bottomButtonText?: string; /** * Call back which will be fired on click the bottom button. */ bottomButtonClickHandler?: ButtonProps['onClick']; /** * On which side to show the menu arrow. */ arrowSide?: CreateClassesProps['arrowSide']; /** * Specify left addition to place the menu correctly relative to the anchor component. */ leftAddition?: number; /** * Defines a string value that labels the DropDownMenu element. */ ariaLabel?: HTMLAttributes['aria-label']; /** * Text to display when there are no items in the list. */ noOptionsText?: ReactNode; /** * Text to display when there are no search results. */ noResultsText?: ReactNode; /** * Text to display when there are items loading. */ loadingText?: ReactNode; /** * Virtualize large lists with react-window? */ variableSizeList?: boolean; variableSizeListProps?: Omit< VariableSizeListProps, 'children' | 'itemCount' | 'itemSize' | 'height' | 'width' > & { itemSize?: VariableSizeListProps['itemSize']; height?: VariableSizeListProps['height']; width?: VariableSizeListProps['width']; }; /** * Provide to override classes. */ classes?: Partial>; } export interface InfinityScrollProps { fetchFunction: () => void; allItemsCount: number; threshold?: number; } export interface ListItemProps { infinityScrollProps?: InfinityScrollProps; listItems: DropDownMenuProps['listItems']; modifyMenuItem?: DropDownMenuProps['modifyMenuItem']; InsertBeforeList?: DropDownMenuProps['InsertBeforeList']; InsertAfterList?: DropDownMenuProps['InsertAfterList']; multiple?: DropDownMenuProps['multiple']; handleClick?: DropDownMenuProps['handleClick']; styles: ReturnType; classes?: DropDownMenuProps['classes']; sortable?: DropDownMenuProps['sortable']; deletable?: DropDownMenuProps['deletable']; handleDelete?: DropDownMenuProps['handleDelete']; showSelectedIcon?: DropDownMenuProps['showSelectedIcon']; ariaLabel?: DropDownMenuProps['ariaLabel']; noOptionsText?: DropDownMenuProps['noOptionsText']; noResultsText?: DropDownMenuProps['noResultsText']; loadingText?: DropDownMenuProps['loadingText']; variableSizeList?: DropDownMenuProps['variableSizeList']; variableSizeListProps?: DropDownMenuProps['variableSizeListProps']; } export interface MenuContentProps { infinityScrollProps?: InfinityScrollProps; search?: DropDownMenuProps['search']; handleTextChange?: ( value: string | SyntheticEvent ) => void; /** * Number of milliseconds for which the calls to handleTextChange is to be delayed. */ searchDebounceTime?: number; searchHighlight?: DropDownMenuProps['searchHighlight']; searchPlaceholder?: DropDownMenuProps['searchPlaceholder']; searchBy?: DropDownMenuProps['searchBy']; styles?: ReturnType; classes?: DropDownMenuProps['classes']; sortable?: DropDownMenuProps['sortable']; handleClick?: DropDownMenuProps['handleClick']; listItems: DropDownMenuProps['listItems']; modifyMenuItem?: DropDownMenuProps['modifyMenuItem']; InsertBeforeList?: DropDownMenuProps['InsertBeforeList']; InsertAfterList?: DropDownMenuProps['InsertAfterList']; multiple?: DropDownMenuProps['multiple']; deletable?: DropDownMenuProps['deletable']; handleDelete?: DropDownMenuProps['handleDelete']; onSortEnd?: DropDownMenuProps['onSortEnd']; showSelectedIcon?: DropDownMenuProps['showSelectedIcon']; bottomButtonText?: DropDownMenuProps['bottomButtonText']; bottomButtonClickHandler?: DropDownMenuProps['bottomButtonClickHandler']; bottomButtonProps?: ButtonProps; showSort?: boolean; ariaLabel?: DropDownMenuProps['ariaLabel']; noOptionsText?: DropDownMenuProps['noOptionsText']; noResultsText?: DropDownMenuProps['noResultsText']; loadingText?: DropDownMenuProps['loadingText']; /** * Used only when `search` in menuContentProps is enabled. */ defaultListItems?: DropDownMenuProps['listItems']; clearSelectItems?: () => void; variableSizeList?: DropDownMenuProps['variableSizeList']; variableSizeListProps?: DropDownMenuProps['variableSizeListProps']; /** * Displays fixed content at the top of the menu. */ menuListHeader?: ReactNode; /** * Displays fixed content at the bottom of the menu. */ menuListFooter?: ReactNode; /** * If enabled, the menuListLoader is displayed. */ loading?: boolean; /** * Custom loader content. * @default 'Loading...' */ menuListLoader?: ReactNode; } export interface SortableProps { children: ReactElement; } /** * Supported props for the "action icon" of the menu item. */ export interface MenuItemActionIconProps extends Omit { 'data-testid'?: string; iconSrc: string; customIconProps?: CustomIconProps; handleClick?: ( name: MenuItemProps['name'], value: MenuItemProps['value'] ) => MouseEventHandler; tooltipText?: TooltipProps['title']; } export interface MenuItemProps extends Omit { handleClick?: DropDownMenuProps['handleClick']; multiple?: DropDownMenuProps['multiple']; styles?: ReturnType; classes?: DropDownMenuProps['classes']; sortable?: DropDownMenuProps['sortable']; deletable?: DropDownMenuProps['deletable']; handleDelete?: DropDownMenuProps['handleDelete']; index?: number; showSelectedIcon?: DropDownMenuProps['showSelectedIcon']; /** * Allows to render a grouping of options (HTML nested list). * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul#nesting_a_list */ nestedListItems?: ReactNode; autoFocus?: MuiMenuItemProps['autoFocus']; actionIcons?: MenuItemActionIconProps[]; modifyMenuItem?: DropDownMenuProps['modifyMenuItem']; style?: MuiMenuItemProps['style']; sx?: MuiMenuItemProps['sx']; } type Key = string | number; export interface DropdownMenuItem { /** * The unique identifier to be used as the key. */ id?: Key | null; /** * Text that will be displayed in case `textNode` is not supplied. * Also this name will be passed to the click handler. */ name: string | number; /** * Used to display instead of `name` to support partial text styling. */ textNode?: ReactNode; /** * If not passed, name should be used as value. If passed, this would be sent as the value/id. */ value?: string | ReadonlyArray | number; /** * Will render selected menu item. */ selected?: boolean; /** * Will render disabled menu item. */ disabled?: boolean; /** * Will render hidden menu item. */ hidden?: boolean; /** * If provider then the item will rendered with a checkbox. */ checkboxProps?: MuiCheckboxProps; /** * Creates a nested grouping of options, where `name` is used as a group label. */ options?: DropdownMenuItem[]; /** * Identifies the element (or elements) that labels the MenuItem element. */ ariaLabelledby?: HTMLAttributes['aria-labelledby']; style?: MuiMenuProps['style']; /** * The autocomplete input (to pass inside the rendered list item) */ searchQuery?: string; indeterminate?: MuiCheckboxProps['indeterminate']; /** * An array containing the "action icons" of the menu item. * @default [] */ actionIcons?: MenuItemActionIconProps[]; }