@octopusdeploy/design-system-components
Version:
The design systems component library.
75 lines (74 loc) • 3.14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useDropdownButton = useDropdownButton;
exports.useOpenControlledDropdownButton = useOpenControlledDropdownButton;
const react_1 = __importDefault(require("react"));
const useFocusTrap_1 = require("../../hooks/useFocusTrap");
const isHTMLElement_1 = require("../../utils/isHTMLElement");
function useDropdownButton(options) {
const [isOpen, setIsOpen] = react_1.default.useState(false);
return useOpenControlledDropdownButton({ ...options, isOpen, setIsOpen });
}
function useOpenControlledDropdownButton({ trapFocus, dropdownAriaRole, setIsOpen, isOpen }) {
const baseId = react_1.default.useId();
const dropdownId = `dropdown-${baseId}`;
const [buttonElement, setButtonElement] = react_1.default.useState(null);
const [dropdownElement, setDropdownElement] = react_1.default.useState(null);
(0, useFocusTrap_1.useFocusTrap)(dropdownElement, trapFocus);
const closeDropdown = react_1.default.useCallback((options) => {
setIsOpen(false);
if (options?.moveFocusToButton) {
buttonElement?.focus();
}
}, [setIsOpen, buttonElement]);
const toggleDropdown = react_1.default.useCallback(() => {
setIsOpen((prev) => !prev);
}, [setIsOpen]);
react_1.default.useEffect(() => {
if (!isOpen || buttonElement === null || dropdownElement === null)
return;
const onKeyDown = (event) => {
if (event.key === "Escape") {
closeDropdown({ moveFocusToButton: true });
event.preventDefault();
}
};
const onFocusInOrPointerDown = (event) => {
if ((0, isHTMLElement_1.isHTMLElement)(event.target) && !buttonElement.contains(event.target) && !dropdownElement.contains(event.target)) {
closeDropdown();
}
};
window.addEventListener("keydown", onKeyDown);
window.addEventListener("focusin", onFocusInOrPointerDown);
window.addEventListener("pointerdown", onFocusInOrPointerDown);
return () => {
window.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,
};
}