@gechiui/components
Version:
UI components for GeChiUI.
109 lines (95 loc) • 2.96 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@gechiui/element";
// @ts-nocheck
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* GeChiUI dependencies
*/
import { useRef, useEffect, useState } from '@gechiui/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(_ref) {
var _popoverProps$anchorR;
let {
renderContent,
renderToggle,
position = 'bottom right',
className,
contentClassName,
expandOnMobile,
headerTitle,
focusOnMount,
popoverProps,
onClose,
onToggle
} = _ref;
const containerRef = useRef();
const [isOpen, setIsOpen] = useObservableState(false, onToggle);
useEffect(() => () => {
if (onToggle) {
onToggle(false);
}
}, []);
function toggle() {
setIsOpen(!isOpen);
}
/**
* Closes the popover when focus leaves it unless the toggle was pressed or
* focus has moved to a separate dialog. The former is to let the toggle
* handle closing the popover and the latter is to preserve presence in
* case a dialog has opened, allowing focus to return when it's dismissed.
*/
function closeIfFocusOutside() {
const {
ownerDocument
} = containerRef.current;
const dialog = ownerDocument.activeElement.closest('[role="dialog"]');
if (!containerRef.current.contains(ownerDocument.activeElement) && (!dialog || dialog.contains(containerRef.current))) {
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 // Some UAs focus the closest focusable parent when the toggle is
// clicked. Making this div focusable ensures such UAs will focus
// it and `closeIfFocusOutside` can tell if the toggle was clicked.
,
tabIndex: "-1"
}, 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