Don't show the placeholder if the action will be a no-op (#58)

Update the computeMove function to only set pendingAction if the action
is not a no-op (i.e. it will not place the node adjacent to itself at
the same level). Also clears the pendingAction if the user hovers over
the node that is being dragged.
This commit is contained in:
Evan Simkowitz 2024-06-18 16:03:00 -07:00 committed by GitHub
parent 4ded6d94b6
commit a3a576bd6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 45 additions and 15 deletions

View File

@ -423,18 +423,24 @@ const OverlayNode = <T,>({ layoutNode, layoutTreeState, dispatch, setRef, delete
}
},
hover: (_, monitor) => {
if (monitor.isOver({ shallow: true }) && monitor.canDrop()) {
const dragItem = monitor.getItem<LayoutNode<T>>();
console.log("computing operation", layoutNode, dragItem, layoutTreeState.pendingAction);
dispatch({
type: LayoutTreeActionType.ComputeMove,
node: layoutNode,
nodeToMove: dragItem,
direction: determineDropDirection(
overlayRef.current?.getBoundingClientRect(),
monitor.getClientOffset()
),
} as LayoutTreeComputeMoveNodeAction<T>);
if (monitor.isOver({ shallow: true })) {
if (monitor.canDrop()) {
const dragItem = monitor.getItem<LayoutNode<T>>();
console.log("computing operation", layoutNode, dragItem, layoutTreeState.pendingAction);
dispatch({
type: LayoutTreeActionType.ComputeMove,
node: layoutNode,
nodeToMove: dragItem,
direction: determineDropDirection(
overlayRef.current?.getBoundingClientRect(),
monitor.getClientOffset()
),
} as LayoutTreeComputeMoveNodeAction<T>);
} else {
dispatch({
type: LayoutTreeActionType.ClearPendingAction,
});
}
}
},
}),

View File

@ -70,6 +70,9 @@ function layoutTreeStateReducerInner<T>(layoutTreeState: LayoutTreeState<T>, act
case LayoutTreeActionType.ComputeMove:
computeMoveNode(layoutTreeState, action as LayoutTreeComputeMoveNodeAction<T>);
break;
case LayoutTreeActionType.ClearPendingAction:
clearPendingAction(layoutTreeState);
break;
case LayoutTreeActionType.CommitPendingAction:
if (!layoutTreeState?.pendingAction) {
console.error("unable to commit pending action, does not exist");
@ -129,6 +132,10 @@ function computeMoveNode<T>(
const grandparent = lazy(() => findParent(rootNode, parent().id));
const indexInParent = lazy(() => parent()?.children.findIndex((child) => node.id === child.id));
const indexInGrandparent = lazy(() => grandparent()?.children.findIndex((child) => parent().id === child.id));
const nodeToMoveParent = lazy(() => findParent(rootNode, nodeToMove.id));
const nodeToMoveIndexInParent = lazy(() =>
nodeToMoveParent()?.children.findIndex((child) => nodeToMove.id === child.id)
);
const isRoot = rootNode.id === node.id;
switch (direction) {
@ -268,6 +275,7 @@ function computeMoveNode<T>(
};
console.log("swapAction", swapAction);
layoutTreeState.pendingAction = swapAction;
return;
} else {
console.warn("cannot swap");
}
@ -276,13 +284,21 @@ function computeMoveNode<T>(
throw new Error(`Invalid direction: ${direction}`);
}
if (newMoveOperation)
if (
newMoveOperation?.parentId !== nodeToMoveParent()?.id ||
(newMoveOperation.index !== nodeToMoveIndexInParent() &&
newMoveOperation.index !== nodeToMoveIndexInParent() + 1)
)
layoutTreeState.pendingAction = {
type: LayoutTreeActionType.Move,
...newMoveOperation,
} as LayoutTreeMoveNodeAction<T>;
}
function clearPendingAction(layoutTreeState: LayoutTreeState<any>) {
layoutTreeState.pendingAction = undefined;
}
function moveNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeMoveNodeAction<T>) {
const rootNode = layoutTreeState.rootNode;
console.log("moveNode", action, layoutTreeState.rootNode);
@ -305,7 +321,7 @@ function moveNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeMove
// If moving under the same parent, we need to make sure that we are removing the child from its old position, not its new one.
// If the new index is before the old index, we need to start our search for the node to delete after the new index position.
if (oldParent?.id === parent.id) {
if (oldParent && parent && oldParent.id === parent.id) {
const curIndexInParent = parent.children!.indexOf(node);
if (curIndexInParent >= action.index) {
startingIndex = action.index + 1;

View File

@ -33,10 +33,11 @@ export type MoveOperation<T> = {
* Types of actions that modify the layout tree.
*/
export enum LayoutTreeActionType {
ComputeMove = "computeMove",
ComputeMove = "compute",
Move = "move",
Swap = "swap",
CommitPendingAction = "commit",
ClearPendingAction = "clear",
ResizeNode = "resize",
InsertNode = "insert",
DeleteNode = "delete",
@ -116,6 +117,13 @@ export interface LayoutTreeDeleteNodeAction extends LayoutTreeAction {
nodeId: string;
}
/**
* Action for clearing the pendingAction field from the layout tree state.
*/
export interface LayoutTreeClearPendingAction extends LayoutTreeAction {
type: LayoutTreeActionType.ClearPendingAction;
}
/**
* Represents the state of a layout tree.
*