UNPKG

@atlaskit/dropdown-menu

Version:

A dropdown menu displays a list of actions or options to a user.

118 lines (113 loc) 5.04 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = handleFocus; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _keycodes = require("@atlaskit/ds-lib/keycodes"); var _platformFeatureFlags = require("@atlaskit/platform-feature-flags"); var _useGeneratedId = require("./use-generated-id"); var actionMap = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, _keycodes.KEY_DOWN, 'next'), _keycodes.KEY_UP, 'prev'), _keycodes.KEY_HOME, 'first'), _keycodes.KEY_END, 'last'); /** * `currentFocusedIdx + 1` will not work if the next focusable element * is disabled. So, we need to iterate through the following menu items * to find one that isn't disabled. If all following elements are disabled, * return undefined. */ var getNextFocusableElement = function getNextFocusableElement(refs, currentFocusedIdx) { for (var i = 0; i < refs.length - 1; i++) { if (currentFocusedIdx + 1 === refs.length) { currentFocusedIdx = 0; } else { currentFocusedIdx++; } var element = refs[currentFocusedIdx].current; var isValid = !!element && !element.hasAttribute('disabled'); if (isValid) { return element; } } }; /** * `currentFocusedIdx - 1` will not work if the prev focusable element * is disabled. So, we need to iterate through the previous menu items * to find one that isn't disabled. If all previous elements are disabled, * return undefined. */ var getPrevFocusableElement = function getPrevFocusableElement(refs, currentFocusedIdx) { for (var i = 0; i < refs.length - 1; i++) { if (currentFocusedIdx === 0) { currentFocusedIdx = refs.length - 1; } else { currentFocusedIdx--; } var element = refs[currentFocusedIdx].current; var isValid = !!element && !element.hasAttribute('disabled'); if (isValid) { return element; } } }; function handleFocus(refs, isLayerDisabled, onClose) { return function (e) { var _refs$current; var currentRefs = (_refs$current = refs.current) !== null && _refs$current !== void 0 ? _refs$current : []; var currentFocusedIdx = currentRefs.findIndex(function (_ref) { var _document$activeEleme; var el = _ref.current; return el && ((_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 ? void 0 : _document$activeEleme.isSameNode(el)); }); if ((0, _platformFeatureFlags.fg)('platform_dst_popup-disable-focuslock')) { var _document$activeEleme2; // if we use a popup as a nested dropdown, we must prevent the dropdown from closing. var isNestedDropdown = !!((_document$activeEleme2 = document.activeElement) !== null && _document$activeEleme2 !== void 0 && _document$activeEleme2.closest("[id^=".concat(_useGeneratedId.PREFIX, "]"))); if (isLayerDisabled() && isNestedDropdown) { if (e.key === _keycodes.KEY_TAB && !e.shiftKey) { onClose(e); } // if it is a nested dropdown and the level of the given dropdown is not the current level, // we don't need to have focus on it return; } } else { if (isLayerDisabled()) { if (e.key === _keycodes.KEY_TAB && !e.shiftKey) { onClose(e); } // if it is a nested dropdown and the level of the given dropdown is not the current level, // we don't need to have focus on it return; } } var action = actionMap[e.key]; switch (action) { case 'next': // Always cancelling the event to prevent scrolling e.preventDefault(); var nextFocusableElement = getNextFocusableElement(currentRefs, currentFocusedIdx); nextFocusableElement === null || nextFocusableElement === void 0 || nextFocusableElement.focus(); break; case 'prev': // Always cancelling the event to prevent scrolling e.preventDefault(); var prevFocusableElement = getPrevFocusableElement(currentRefs, currentFocusedIdx); prevFocusableElement === null || prevFocusableElement === void 0 || prevFocusableElement.focus(); break; case 'first': e.preventDefault(); // Search for first non-disabled element if first element is disabled var firstFocusableElement = getNextFocusableElement(currentRefs, -1); firstFocusableElement === null || firstFocusableElement === void 0 || firstFocusableElement.focus(); break; case 'last': e.preventDefault(); // Search for last non-disabled element if last element is disabled var lastFocusableElement = getPrevFocusableElement(currentRefs, currentRefs.length); lastFocusableElement === null || lastFocusableElement === void 0 || lastFocusableElement.focus(); break; default: return; } }; }