@wordpress/components
Version:
UI components for WordPress.
103 lines (89 loc) • 2.66 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@wordpress/element";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useRef, useEffect, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import Popover from '../popover';
function useObservableState(initialState, onStateChange) {
const [state, setState] = useState(initialState);
return [state, value => {
setState(value);
if (onStateChange) {
onStateChange(value);
}
}];
}
export default function Dropdown({
renderContent,
renderToggle,
position = 'bottom right',
className,
contentClassName,
expandOnMobile,
headerTitle,
focusOnMount,
popoverProps,
onClose,
onToggle
}) {
var _popoverProps$anchorR;
const containerRef = useRef();
const [isOpen, setIsOpen] = useObservableState(false, onToggle);
useEffect(() => () => {
if (onToggle) {
onToggle(false);
}
}, []);
function toggle() {
setIsOpen(!isOpen);
}
/**
* Closes the dropdown if a focus leaves the dropdown wrapper. This is
* intentionally distinct from `onClose` since focus loss from the popover
* is expected to occur when using the Dropdown's toggle button, in which
* case the correct behavior is to keep the dropdown closed. The same applies
* in case when focus is moved to the modal dialog.
*/
function closeIfFocusOutside() {
const {
ownerDocument
} = containerRef.current;
if (!containerRef.current.contains(ownerDocument.activeElement) && !ownerDocument.activeElement.closest('[role="dialog"]')) {
close();
}
}
function close() {
if (onClose) {
onClose();
}
setIsOpen(false);
}
const args = {
isOpen,
onToggle: toggle,
onClose: close
};
return createElement("div", {
className: classnames('components-dropdown', className),
ref: containerRef
}, renderToggle(args), isOpen && createElement(Popover, _extends({
position: position,
onClose: close,
onFocusOutside: closeIfFocusOutside,
expandOnMobile: expandOnMobile,
headerTitle: headerTitle,
focusOnMount: focusOnMount
}, popoverProps, {
anchorRef: (_popoverProps$anchorR = popoverProps === null || popoverProps === void 0 ? void 0 : popoverProps.anchorRef) !== null && _popoverProps$anchorR !== void 0 ? _popoverProps$anchorR : containerRef.current,
className: classnames('components-dropdown__content', popoverProps ? popoverProps.className : undefined, contentClassName)
}), renderContent(args)));
}
//# sourceMappingURL=index.js.map