UNPKG

preact-arco-design

Version:

Arco Design React UI Library.

210 lines (175 loc) 5.78 kB
var __assign = this && this.__assign || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } } return t; }; return __assign.apply(this, arguments); }; var __read = this && this.__read || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) { ar.push(r.value); } } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; import { useContext, useEffect, useState } from "preact/compat"; import MenuContext from "./context"; import useIsFirstRender from "../_util/hooks/useIsFirstRender"; import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Enter, Esc } from "../_util/keycode"; var INITIAL_HOTKEY_INFO = { type: null, update: false, activeKeyPath: [] }; export var useHotkeyListener = function useHotkeyListener(_a) { var menuInfoMap = _a.menuInfoMap, openKeys = _a.openKeys, selectedKeys = _a.selectedKeys, needPause = _a.needPause; var _b = __read(useState(INITIAL_HOTKEY_INFO), 2), hotkeyInfo = _b[0], setHokeyInfo = _b[1]; return { clear: function clear() { return setHokeyInfo(INITIAL_HOTKEY_INFO); }, hotkeyInfo: hotkeyInfo, listener: function listener(event) { if (typeof needPause === 'function' && needPause()) { return; } var keyCode = event.keyCode || event.which; var activeKey = hotkeyInfo.activeKeyPath[0] || selectedKeys && selectedKeys[0]; // 快捷键操作时,阻止页面滚动 if (keyCode === ArrowUp.code || keyCode === ArrowDown.code) { event.preventDefault(); } // 没有 active 状态的菜单项时返回 if (!menuInfoMap[activeKey]) { if ([ArrowUp.code, ArrowDown.code, ArrowLeft.code, ArrowRight.code].indexOf(keyCode) > -1) { var activeKey_1 = Object.keys(menuInfoMap)[0]; setHokeyInfo(__assign(__assign({}, hotkeyInfo), { update: false, activeKeyPath: menuInfoMap[activeKey_1].keyPath })); } return; } var walkSiblings = function walkSiblings(reverse) { var getKeyNext = function getKeyNext(base) { var _a = menuInfoMap[base], firstChild = _a.firstChild, next = _a.next, keyPath = _a.keyPath; var getParentNext = function getParentNext(keyPath) { var parent = keyPath[1] && menuInfoMap[keyPath[1]]; if (parent) { return parent.next || getParentNext(parent.keyPath); } }; return firstChild && openKeys.indexOf(base) > -1 ? firstChild : next || getParentNext(keyPath); }; var getKeyPrev = function getKeyPrev(base) { var result = null; var _a = menuInfoMap[base], prev = _a.prev, keyPath = _a.keyPath; if (prev) { result = prev; var info = menuInfoMap[prev]; while (info.lastChild && openKeys.indexOf(result) > -1) { result = info.lastChild; info = menuInfoMap[info.lastChild]; } } else { result = keyPath[1]; } return result; }; var getNewActiveKey = reverse ? getKeyPrev : getKeyNext; var newActiveKey = getNewActiveKey(activeKey); var newActiveItemInfo = menuInfoMap[newActiveKey]; while (newActiveItemInfo && newActiveItemInfo.disabled) { newActiveKey = getNewActiveKey(newActiveKey); newActiveItemInfo = menuInfoMap[newActiveKey]; } if (newActiveItemInfo) { setHokeyInfo({ type: 'sibling', update: false, activeKeyPath: newActiveItemInfo.keyPath }); } }; var walkGenerations = function walkGenerations(reverse) { var activeItemInfo = menuInfoMap[activeKey]; if (activeItemInfo) { var newActiveKey = reverse ? activeItemInfo.keyPath[1] : activeItemInfo.firstChild; var newActiveItemInfo = menuInfoMap[newActiveKey]; if (newActiveItemInfo) { setHokeyInfo({ type: 'generation', update: true, activeKeyPath: newActiveItemInfo.keyPath }); } } }; switch (keyCode) { case ArrowUp.code: walkSiblings(true); break; case ArrowDown.code: walkSiblings(); break; case ArrowLeft.code: walkGenerations(true); break; case ArrowRight.code: walkGenerations(); break; case Enter.code: setHokeyInfo(__assign(__assign({}, hotkeyInfo), { type: 'enter', update: true })); break; case Esc.code: setHokeyInfo(INITIAL_HOTKEY_INFO); break; default: } } }; }; export var useHotkeyHandler = function useHotkeyHandler(key, handler) { var hotkeyInfo = useContext(MenuContext).hotkeyInfo; var isFirstRender = useIsFirstRender(); var isActive = key && key === hotkeyInfo.activeKeyPath[0]; useEffect(function () { if (!isFirstRender && hotkeyInfo.update) { handler(isActive, hotkeyInfo.type); } }, [hotkeyInfo]); return isActive; };