import React from 'react'; import { MenuTrigger, Popover, SubmenuTrigger } from 'react-aria-components'; import type { SafeExtract, Variant } from '../../types'; import type { IconName } from '../Icon/IconName'; import { DropdownButtonList } from './DropdownButtonList/DropdownButtonList'; import { DropdownButtonListContext } from './DropdownButtonList/DropdownButtonListContext'; import { DropdownButtonListItem } from './DropdownButtonList/DropdownButtonListItem'; import { DropdownButtonModalMenu } from './DropdownButtonModalMenu/DropdownButtonModalMenu'; import { DropdownButtonModalSubmenu } from './DropdownButtonModalMenu/DropdownButtonModalSubmenu'; import { useDropdownContext } from './DropdownButtonContext'; import { DropdownButtonTrigger, type DropdownButtonTriggerProps } from './DropdownButtonTrigger'; // Max. possible setTimeout delay in ms const PRACTICAL_INFINITY = 2_147_483_647; const noop = () => { // do nothing }; /** @inheritdoc */ export interface DropdownButtonProps extends React.PropsWithChildren< Pick< DropdownButtonTriggerProps, | 'disabled' | 'id' | 'onBlur' | 'onClick' | 'onFocus' | 'size' | 'label' | 'labelOpen' | 'iconPosition' | 'indicateOpen' | 'trigger' > > { /** * Variant of the button. * @default 'primary' * */ variant?: SafeExtract; /** * Close the dropdown on action. * Applied to standalone dropdown buttons and all its nested dropdowns. * @default true */ closeOnAction?: boolean; /** * Description of a nested dropdown. * Applied to nested dropdown only. */ description?: string; /** * Icon of a nested dropdown. * Applied to nested dropdown only. */ icon?: IconName; /** * Items of the dropdown. * Only valid children are `DropdownButton.Item`, `DropdownButton` and `Fragment` components. * You can wrap these components into a custom component but it must return only components listed above. */ children?: React.ReactNode; } type DropdownButtonComponent = React.FC & { Item: typeof DropdownButtonListItem; }; /** * Dropdown button component. * It can be used as a standalone dropdown button or as a submenu of another dropdown button. * All the props are applied to standalone dropdown buttons only unless stated otherwise. */ export const DropdownButton: DropdownButtonComponent = ({ iconPosition = 'left', closeOnAction = true, children, label, description, icon, ...buttonProps }) => { const listContext = React.useContext(DropdownButtonListContext); const { mobileView } = useDropdownContext(); if (listContext) { return ( {mobileView ? ( {children} ) : ( {children} )} ); } return ( {mobileView ? ( {children} ) : ( {children} )} ); }; DropdownButton.Item = DropdownButtonListItem;