UNPKG

react-elegant-ui

Version:

Elegant UI components, made by BEM best practices for react

128 lines (127 loc) 4.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useKeyboardNavigation = exports.navigate = exports.defaultPredicate = void 0; var _react = require("react"); var _findIndexLoop = require("../../lib/findIndexLoop"); var _keyboard = require("../../lib/keyboard"); var _useImmutableCallback = require("../useImmutableCallback"); var defaultPredicate = function (item) { return !item.disabled; }; /** * Return index of new active item * * If new item can't be found - return `-1` * It's return `-1` in case when all items except current is not match */ exports.defaultPredicate = defaultPredicate; var navigate = function (items, cursor, direction, predicate, loop) { var actualPredicate = predicate !== null && predicate !== void 0 ? predicate : defaultPredicate; var lastIndex = items.length - 1; // Init cursor if (cursor === -1) { var findDownToUp = direction === 'prev' || direction === 'end'; var startIndex = findDownToUp ? lastIndex : 0; var searchDirection = findDownToUp ? -1 : 1; return (0, _findIndexLoop.findIndexLoop)(items, actualPredicate, startIndex, searchDirection); } var newCursor = -1; // Navigation if (direction === 'start') { newCursor = items.findIndex(actualPredicate); } else if (direction === 'end') { newCursor = (0, _findIndexLoop.findIndexLoop)(items, actualPredicate, lastIndex, -1); } else if (direction === 'prev') { if (loop) { newCursor = (0, _findIndexLoop.findIndexLoop)(items, // Skip first iteration, cuz it self object function (item, iteration) { return iteration > 0 && actualPredicate(item); }, cursor, -1); } else { var prevItemIndex = cursor - 1; // Skip while out of bounds if (prevItemIndex < 0) { return -1; } // Slice array from start to previous item and search from end to start var offsetFromEnd = items.slice(0, cursor).reverse().findIndex(actualPredicate); if (offsetFromEnd !== -1) { newCursor = prevItemIndex - offsetFromEnd; } } } else if (direction === 'next') { if (loop) { newCursor = (0, _findIndexLoop.findIndexLoop)(items, // Skip first iteration, cuz it self object function (item, iteration) { return iteration > 0 && actualPredicate(item); }, cursor, 1); } else { var nextItemIndex = cursor + 1; var foundIndex = items.slice(nextItemIndex).findIndex(actualPredicate); newCursor = foundIndex === -1 ? -1 : foundIndex + nextItemIndex; } } return newCursor; }; /** * Global hook which implement keyboard navigation * * It useful when u want navigate in items by keyboard arrows */ exports.navigate = navigate; var useKeyboardNavigation = function (_a) { var enabled = _a.enabled, items = _a.items, cursor = _a.cursor, setCursor = _a.setCursor, predicate = _a.predicate, direction = _a.direction, loop = _a.loop, enableJump = _a.enableJump, _b = _a.eventCapture, eventCapture = _b === void 0 ? true : _b; // Update global handler var onKeyDownGlobal = (0, _useImmutableCallback.useImmutableCallback)(function (evt) { if (direction === undefined) return; var cursorIndex = cursor !== null && cursor !== void 0 ? cursor : -1; var navDirection = null; // Set navigation direction if (enableJump && (0, _keyboard.isKeyCode)(evt.code, [_keyboard.Keys.HOME, _keyboard.Keys.END])) { navDirection = evt.code === _keyboard.Keys.HOME ? 'start' : 'end'; } else if (direction.indexOf('vertical') !== -1 && (0, _keyboard.isKeyCode)(evt.code, [_keyboard.Keys.UP, _keyboard.Keys.DOWN])) { navDirection = evt.code === _keyboard.Keys.UP ? 'prev' : 'next'; } else if (direction.indexOf('horizontal') !== -1 && (0, _keyboard.isKeyCode)(evt.code, [_keyboard.Keys.LEFT, _keyboard.Keys.RIGHT])) { navDirection = evt.code === _keyboard.Keys.LEFT ? 'prev' : 'next'; } // Skip handle a non navigation keys if (navDirection === null) return; evt.preventDefault(); var newCursor = navigate(items, cursorIndex, navDirection, predicate, loop); // Fix cursor when current cursor exist but next item is not found // Should not reset cursor due to this, but setter should be called if (cursorIndex !== -1 && newCursor === -1) { newCursor = cursorIndex; } // Set cursor if (setCursor !== undefined) { setCursor(newCursor); } }, [items, cursor, setCursor, predicate, direction, loop, enableJump]); // Global handler (0, _react.useEffect)(function () { if (!enabled) return; document.addEventListener('keydown', onKeyDownGlobal, { capture: eventCapture }); return function () { return document.removeEventListener('keydown', onKeyDownGlobal, { capture: eventCapture }); }; }, [enabled, onKeyDownGlobal, eventCapture]); }; exports.useKeyboardNavigation = useKeyboardNavigation;