@gechiui/components
Version:
UI components for GeChiUI.
120 lines (100 loc) • 3.27 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Dropdown;
var _element = require("@gechiui/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _classnames = _interopRequireDefault(require("classnames"));
var _popover = _interopRequireDefault(require("../popover"));
// @ts-nocheck
/**
* External dependencies
*/
/**
* GeChiUI dependencies
*/
/**
* Internal dependencies
*/
function useObservableState(initialState, onStateChange) {
const [state, setState] = (0, _element.useState)(initialState);
return [state, value => {
setState(value);
if (onStateChange) {
onStateChange(value);
}
}];
}
function Dropdown(_ref) {
var _popoverProps$anchorR;
let {
renderContent,
renderToggle,
position = 'bottom right',
className,
contentClassName,
expandOnMobile,
headerTitle,
focusOnMount,
popoverProps,
onClose,
onToggle
} = _ref;
const containerRef = (0, _element.useRef)();
const [isOpen, setIsOpen] = useObservableState(false, onToggle);
(0, _element.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 (0, _element.createElement)("div", {
className: (0, _classnames.default)('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 && (0, _element.createElement)(_popover.default, (0, _extends2.default)({
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: (0, _classnames.default)('components-dropdown__content', popoverProps ? popoverProps.className : undefined, contentClassName)
}), renderContent(args)));
}
//# sourceMappingURL=index.js.map