2024-06-21 19:49:13 +03:00

226 lines
8.1 KiB
JavaScript

import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import useEventCallback from '@mui/utils/useEventCallback';
import { getFirstNode, getLastNode, getNextNode, getPreviousNode, populateInstance } from '../../useTreeView/useTreeView.utils';
function isPrintableCharacter(string) {
return string && string.length === 1 && string.match(/\S/);
}
function findNextFirstChar(firstChars, startIndex, char) {
for (var i = startIndex; i < firstChars.length; i += 1) {
if (char === firstChars[i]) {
return i;
}
}
return -1;
}
export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigation(_ref) {
var instance = _ref.instance,
params = _ref.params,
state = _ref.state;
var theme = useTheme();
var isRtl = theme.direction === 'rtl';
var firstCharMap = React.useRef({});
var mapFirstChar = useEventCallback(function (nodeId, firstChar) {
firstCharMap.current[nodeId] = firstChar;
return function () {
var newMap = _extends({}, firstCharMap.current);
delete newMap[nodeId];
firstCharMap.current = newMap;
};
});
populateInstance(instance, {
mapFirstChar: mapFirstChar
});
var handleNextArrow = function handleNextArrow(event) {
if (state.focusedNodeId != null && instance.isNodeExpandable(state.focusedNodeId)) {
if (instance.isNodeExpanded(state.focusedNodeId)) {
instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
} else if (!instance.isNodeDisabled(state.focusedNodeId)) {
instance.toggleNodeExpansion(event, state.focusedNodeId);
}
}
return true;
};
var handlePreviousArrow = function handlePreviousArrow(event) {
if (state.focusedNodeId == null) {
return false;
}
if (instance.isNodeExpanded(state.focusedNodeId) && !instance.isNodeDisabled(state.focusedNodeId)) {
instance.toggleNodeExpansion(event, state.focusedNodeId);
return true;
}
var parent = instance.getNode(state.focusedNodeId).parentId;
if (parent) {
instance.focusNode(event, parent);
return true;
}
return false;
};
var focusByFirstCharacter = function focusByFirstCharacter(event, nodeId, firstChar) {
var start;
var index;
var lowercaseChar = firstChar.toLowerCase();
var firstCharIds = [];
var firstChars = [];
// This really only works since the ids are strings
Object.keys(firstCharMap.current).forEach(function (mapNodeId) {
var map = instance.getNode(mapNodeId);
var visible = map.parentId ? instance.isNodeExpanded(map.parentId) : true;
var shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isNodeDisabled(mapNodeId);
if (visible && !shouldBeSkipped) {
firstCharIds.push(mapNodeId);
firstChars.push(firstCharMap.current[mapNodeId]);
}
});
// Get start index for search based on position of currentItem
start = firstCharIds.indexOf(nodeId) + 1;
if (start >= firstCharIds.length) {
start = 0;
}
// Check remaining slots in the menu
index = findNextFirstChar(firstChars, start, lowercaseChar);
// If not found in remaining slots, check from beginning
if (index === -1) {
index = findNextFirstChar(firstChars, 0, lowercaseChar);
}
// If match was found...
if (index > -1) {
instance.focusNode(event, firstCharIds[index]);
}
};
var selectNextNode = function selectNextNode(event, id) {
if (!instance.isNodeDisabled(getNextNode(instance, id))) {
instance.selectRange(event, {
end: getNextNode(instance, id),
current: id
}, true);
}
};
var selectPreviousNode = function selectPreviousNode(event, nodeId) {
if (!instance.isNodeDisabled(getPreviousNode(instance, nodeId))) {
instance.selectRange(event, {
end: getPreviousNode(instance, nodeId),
current: nodeId
}, true);
}
};
var createHandleKeyDown = function createHandleKeyDown(otherHandlers) {
return function (event) {
var _otherHandlers$onKeyD;
(_otherHandlers$onKeyD = otherHandlers.onKeyDown) == null || _otherHandlers$onKeyD.call(otherHandlers, event);
var flag = false;
var key = event.key;
// If the tree is empty there will be no focused node
if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
return;
}
var ctrlPressed = event.ctrlKey || event.metaKey;
switch (key) {
case ' ':
if (!params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
flag = true;
if (params.multiSelect && event.shiftKey) {
instance.selectRange(event, {
end: state.focusedNodeId
});
} else if (params.multiSelect) {
instance.selectNode(event, state.focusedNodeId, true);
} else {
instance.selectNode(event, state.focusedNodeId);
}
}
event.stopPropagation();
break;
case 'Enter':
if (!instance.isNodeDisabled(state.focusedNodeId)) {
if (instance.isNodeExpandable(state.focusedNodeId)) {
instance.toggleNodeExpansion(event, state.focusedNodeId);
flag = true;
} else if (!params.disableSelection) {
flag = true;
if (params.multiSelect) {
instance.selectNode(event, state.focusedNodeId, true);
} else {
instance.selectNode(event, state.focusedNodeId);
}
}
}
event.stopPropagation();
break;
case 'ArrowDown':
if (params.multiSelect && event.shiftKey && !params.disableSelection) {
selectNextNode(event, state.focusedNodeId);
}
instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
flag = true;
break;
case 'ArrowUp':
if (params.multiSelect && event.shiftKey && !params.disableSelection) {
selectPreviousNode(event, state.focusedNodeId);
}
instance.focusNode(event, getPreviousNode(instance, state.focusedNodeId));
flag = true;
break;
case 'ArrowRight':
if (isRtl) {
flag = handlePreviousArrow(event);
} else {
flag = handleNextArrow(event);
}
break;
case 'ArrowLeft':
if (isRtl) {
flag = handleNextArrow(event);
} else {
flag = handlePreviousArrow(event);
}
break;
case 'Home':
if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
instance.rangeSelectToFirst(event, state.focusedNodeId);
}
instance.focusNode(event, getFirstNode(instance));
flag = true;
break;
case 'End':
if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
instance.rangeSelectToLast(event, state.focusedNodeId);
}
instance.focusNode(event, getLastNode(instance));
flag = true;
break;
default:
if (key === '*') {
instance.expandAllSiblings(event, state.focusedNodeId);
flag = true;
} else if (params.multiSelect && ctrlPressed && key.toLowerCase() === 'a' && !params.disableSelection) {
instance.selectRange(event, {
start: getFirstNode(instance),
end: getLastNode(instance)
});
flag = true;
} else if (!ctrlPressed && !event.shiftKey && isPrintableCharacter(key)) {
focusByFirstCharacter(event, state.focusedNodeId, key);
flag = true;
}
}
if (flag) {
event.preventDefault();
event.stopPropagation();
}
};
};
return {
getRootProps: function getRootProps(otherHandlers) {
return {
onKeyDown: createHandleKeyDown(otherHandlers)
};
}
};
};