feat(nodes-edges): add nodesFocusable, edgesFocusable, cleanup keyboard controls

This commit is contained in:
moklick
2022-10-03 14:31:34 +02:00
parent d00faa6b3e
commit be6590a5d6
13 changed files with 73 additions and 26 deletions
@@ -51,7 +51,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
markerStart,
rfId,
ariaLabel,
disableKeyboardA11y,
isFocusable,
pathOptions,
interactionWidth,
}: WrapEdgeProps): JSX.Element | null => {
@@ -158,12 +158,12 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
onMouseEnter={onEdgeMouseEnter}
onMouseMove={onEdgeMouseMove}
onMouseLeave={onEdgeMouseLeave}
onKeyDown={disableKeyboardA11y ? undefined : onKeyDown}
tabIndex={disableKeyboardA11y ? undefined : 0}
role={disableKeyboardA11y ? undefined : 'button'}
onKeyDown={isFocusable ? onKeyDown : undefined}
tabIndex={isFocusable ? 0 : undefined}
role={isFocusable ? 'button' : undefined}
data-testid={`rf__edge-${id}`}
aria-label={ariaLabel === null ? undefined : ariaLabel ? ariaLabel : `Edge from ${source} to ${target}`}
aria-describedby={disableKeyboardA11y ? undefined : `${ARIA_EDGE_DESC_KEY}-${rfId}`}
aria-describedby={isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined}
ref={edgeRef}
>
{!updating && (
+26 -10
View File
@@ -11,10 +11,10 @@ import { NodeProps, WrapNodeProps, XYPosition } from '../../types';
import { elementSelectionKeys } from '../../utils';
export const arrowKeyDiffs: Record<string, XYPosition> = {
ArrowUp: { x: 0, y: -10 },
ArrowDown: { x: 0, y: 10 },
ArrowLeft: { x: -10, y: 0 },
ArrowRight: { x: 10, y: 0 },
ArrowUp: { x: 0, y: -1 },
ArrowDown: { x: 0, y: 1 },
ArrowLeft: { x: -1, y: 0 },
ArrowRight: { x: 1, y: 0 },
};
export default (NodeComponent: ComponentType<NodeProps>) => {
@@ -38,6 +38,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
isDraggable,
isSelectable,
isConnectable,
isFocusable,
selectNodesOnDrag,
sourcePosition,
targetPosition,
@@ -82,6 +83,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
};
const onKeyDown = (event: KeyboardEvent) => {
const { snapGrid, snapToGrid } = store.getState();
if (elementSelectionKeys.includes(event.key) && isSelectable) {
const unselect = event.key === 'Escape';
if (unselect) {
@@ -92,14 +94,28 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
store,
unselect,
});
} else if (selected && Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
} else if (
!disableKeyboardA11y &&
isDraggable &&
selected &&
Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)
) {
store.setState({
ariaLiveMessage: `Moved selected node ten pixels ${event.key
ariaLiveMessage: `Moved selected node ${event.key
.replace('Arrow', '')
.toLowerCase()}. New position, x: ${~~xPos}, y: ${~~yPos}`,
});
updatePositions(arrowKeyDiffs[event.key]);
// by default a node moves 5px on each key press, or 20px if shift is pressed
// if snap grid is enabled, we use that for the velocity.
const xVelo = snapToGrid ? snapGrid[0] : 5;
const yVelo = snapToGrid ? snapGrid[1] : 5;
const factor = event.shiftKey ? 4 : 1;
updatePositions({
x: arrowKeyDiffs[event.key].x * xVelo * factor,
y: arrowKeyDiffs[event.key].y * yVelo * factor,
});
}
};
@@ -179,9 +195,9 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
onContextMenu={onContextMenuHandler}
onClick={onSelectNodeHandler}
onDoubleClick={onDoubleClickHandler}
onKeyDown={disableKeyboardA11y ? undefined : onKeyDown}
tabIndex={disableKeyboardA11y ? undefined : 0}
role={disableKeyboardA11y ? undefined : 'button'}
onKeyDown={isFocusable ? onKeyDown : undefined}
tabIndex={isFocusable ? 0 : undefined}
role={isFocusable ? 'button' : undefined}
aria-describedby={disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`}
aria-label={ariaLabel}
>
@@ -18,6 +18,8 @@ type StoreUpdaterProps = Pick<
| 'onClickConnectEnd'
| 'nodesDraggable'
| 'nodesConnectable'
| 'nodesFocusable'
| 'edgesFocusable'
| 'minZoom'
| 'maxZoom'
| 'nodeExtent'
@@ -89,6 +91,8 @@ const StoreUpdater = ({
onClickConnectEnd,
nodesDraggable,
nodesConnectable,
nodesFocusable,
edgesFocusable,
minZoom,
maxZoom,
nodeExtent,
@@ -145,6 +149,8 @@ const StoreUpdater = ({
useDirectStoreUpdater('onClickConnectEnd', onClickConnectEnd, store.setState);
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState);
useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState);
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
useDirectStoreUpdater('snapGrid', snapGrid, store.setState);