preact-arco-design
Version:
Arco Design React UI Library.
210 lines (175 loc) • 5.78 kB
JavaScript
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;
};