strapi-plugin-parent-child-relationships
Version:
Strapi plugin to create and manage parent-child relationships between content types using custom fields
107 lines (91 loc) • 2.16 kB
JavaScript
import { useState } from 'react';
/**
* @typedef UseKeyboardDragAndDropCallbacks
*
* @type {{
* onCancel?: (index: number) => void,
* onDropItem?: (index: number) => void,
* onGrabItem?: (index: number) => void,
* onMoveItem: (newIndex: number, currentIndex: number) => void,
* }}
*/
/**
* Utility hook designed to implement keyboard accessibile drag and drop by
* returning an onKeyDown handler to be passed to the drag icon button.
*
* @internal - You should use `useDragAndDrop` instead.
*
* @type {(active: boolean, index: number, callbacks: UseKeyboardDragAndDropCallbacks) => (event: React.KeyboardEvent<HTMLButtonElement>) => void}
*/
export const useKeyboardDragAndDrop = (
active,
index,
{ onCancel, onDropItem, onGrabItem, onMoveItem }
) => {
const [isSelected, setIsSelected] = useState(false);
/**
* @type {(movement: 'UP' | 'DOWN') => void})}
*/
const handleMove = (movement) => {
if (!isSelected) {
return;
}
if (movement === 'UP') {
onMoveItem(index - 1, index);
} else if (movement === 'DOWN') {
onMoveItem(index + 1, index);
}
};
const handleDragClick = () => {
if (isSelected) {
if (onDropItem) {
onDropItem(index);
}
setIsSelected(false);
} else {
if (onGrabItem) {
onGrabItem(index);
}
setIsSelected(true);
}
};
const handleCancel = () => {
if (isSelected) {
setIsSelected(false);
if (onCancel) {
onCancel(index);
}
}
};
/**
* @type {React.KeyboardEventHandler<HTMLButtonElement>}
*/
const handleKeyDown = (e) => {
if (!active) {
return;
}
if (e.key === 'Tab' && !isSelected) {
return;
}
e.preventDefault();
switch (e.key) {
case ' ':
case 'Enter':
handleDragClick();
break;
case 'Escape':
handleCancel();
break;
case 'ArrowDown':
case 'ArrowRight':
handleMove('DOWN');
break;
case 'ArrowUp':
case 'ArrowLeft':
handleMove('UP');
break;
default:
}
};
return handleKeyDown;
};