@octopusdeploy/design-system-components
Version:
The design systems component library.
75 lines (74 loc) • 3.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useDropdownButton = useDropdownButton;
exports.useOpenControlledDropdownButton = useOpenControlledDropdownButton;
const react_1 = require("react");
const useFocusTrap_1 = require("../../hooks/useFocusTrap");
const isHTMLElement_1 = require("../../utils/isHTMLElement");
function useDropdownButton(options) {
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
return useOpenControlledDropdownButton({ ...options, isOpen, setIsOpen });
}
function useOpenControlledDropdownButton({ trapFocus, dropdownAriaRole, setIsOpen, isOpen }) {
const baseId = (0, react_1.useId)();
const dropdownId = `dropdown-${baseId}`;
const [buttonElement, setButtonElement] = (0, react_1.useState)(null);
const [dropdownElement, setDropdownElement] = (0, react_1.useState)(null);
(0, useFocusTrap_1.useFocusTrap)(dropdownElement, trapFocus);
const closeDropdown = (0, react_1.useCallback)((options) => {
setIsOpen(false);
if (options?.moveFocusToButton) {
buttonElement?.focus();
}
}, [setIsOpen, buttonElement]);
const toggleDropdown = (0, react_1.useCallback)(() => {
setIsOpen((prev) => !prev);
}, [setIsOpen]);
(0, react_1.useEffect)(() => {
if (!isOpen || buttonElement === null || dropdownElement === null)
return;
const onKeyDown = (event) => {
if (event.key === "Escape") {
closeDropdown({ moveFocusToButton: true });
event.preventDefault();
event.stopPropagation();
}
};
const onFocusInOrPointerDown = (event) => {
if ((0, isHTMLElement_1.isHTMLElement)(event.target) && !buttonElement.contains(event.target) && !dropdownElement.contains(event.target)) {
closeDropdown();
}
};
buttonElement.addEventListener("keydown", onKeyDown);
dropdownElement.addEventListener("keydown", onKeyDown);
window.addEventListener("focusin", onFocusInOrPointerDown);
window.addEventListener("pointerdown", onFocusInOrPointerDown);
return () => {
buttonElement.removeEventListener("keydown", onKeyDown);
dropdownElement.removeEventListener("keydown", onKeyDown);
window.removeEventListener("focusin", onFocusInOrPointerDown);
window.removeEventListener("pointerdown", onFocusInOrPointerDown);
};
}, [isOpen, buttonElement, dropdownElement, closeDropdown]);
const buttonAriaAttributes = {
"aria-expanded": isOpen ? "true" : "false",
"aria-haspopup": dropdownAriaRole,
"aria-controls": isOpen ? dropdownId : undefined,
};
const dropdownAttributes = {
dropdownId,
dropdownAriaAttributes: {
role: dropdownAriaRole,
},
};
return {
isOpen,
closeDropdown,
toggleDropdown,
buttonElement,
setButtonRef: setButtonElement,
buttonAriaAttributes,
setDropdownRef: setDropdownElement,
dropdownAttributes,
};
}