import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { DropdownMenu } from './DropdownMenu'; import { DropdownProps } from './Dropdown'; import { DropdownContext, DropdownDirection, DropdownPosition } from './dropdownConstants'; import { getOUIAProps, OUIAProps } from '../../../helpers'; import { PickOptional } from '../../../helpers/typeUtils'; import { Popper } from '../../../helpers/Popper/Popper'; class DropdownWithContext extends React.Component { static displayName = 'DropdownWithContext'; openedOnEnter = false; baseComponentRef = React.createRef(); menuComponentRef = React.createRef(); // seed for the aria-labelledby ID static currentId = 0; static defaultProps: PickOptional = { className: '', dropdownItems: [] as any[], isOpen: false, isPlain: false, isText: false, isGrouped: false, position: DropdownPosition.left, direction: DropdownDirection.down, onSelect: (): void => undefined, autoFocus: true, menuAppendTo: 'inline', isFlipEnabled: true }; constructor(props: DropdownProps & OUIAProps) { super(props); if (props.dropdownItems && props.dropdownItems.length > 0 && props.children) { // eslint-disable-next-line no-console console.error( 'Children and dropdownItems props have been provided. Only the dropdownItems prop items will be rendered' ); } } onEnter = () => { this.openedOnEnter = true; }; componentDidUpdate() { if (!this.props.isOpen) { this.openedOnEnter = false; } } setMenuComponentRef = (element: any) => { this.menuComponentRef = element; }; getMenuComponentRef = () => this.menuComponentRef; render() { const { children, className, direction, dropdownItems, isOpen, isPlain, isText, isGrouped, isFullHeight, // eslint-disable-next-line @typescript-eslint/no-unused-vars onSelect, position, toggle, autoFocus, minWidth, menuAppendTo, isFlipEnabled, zIndex, ...props } = this.props; const id = toggle.props.id || `pf-dropdown-toggle-id-${DropdownWithContext.currentId++}`; let component: string; let renderedContent: React.ReactNode[]; let ariaHasPopup = false; if (dropdownItems && dropdownItems.length > 0) { component = 'ul'; renderedContent = dropdownItems; ariaHasPopup = true; } else { component = 'div'; renderedContent = React.Children.toArray(children); } const popperRef = React.createRef(); const openedOnEnter = this.openedOnEnter; const isStatic = isFlipEnabled && menuAppendTo !== 'inline'; return ( {({ baseClass, baseComponent, id: contextId, ouiaId, ouiaComponentType, ouiaSafe, alignments }) => { const BaseComponent = baseComponent as any; const menuContainer = ( {renderedContent} ); const popperContainer = (
{isOpen && menuContainer}
); const mainContainer = ( {React.Children.map(toggle, (oneToggle) => React.cloneElement(oneToggle, { parentRef: this.baseComponentRef, getMenuRef: this.getMenuComponentRef, isOpen, id, isPlain, isText, 'aria-haspopup': ariaHasPopup, onEnter: () => { this.onEnter(); oneToggle.props.onEnter && oneToggle.props.onEnter(); } }) )} {menuAppendTo === 'inline' && isOpen && menuContainer} ); const getParentElement = () => { if (this.baseComponentRef && this.baseComponentRef.current) { return this.baseComponentRef.current.parentElement; } return null; }; return menuAppendTo === 'inline' ? ( mainContainer ) : ( ); }}
); } } export { DropdownWithContext };