Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop as Sibling of Empty, Open Folder #202

Merged
merged 5 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 46 additions & 29 deletions packages/react-arborist/src/dnd/compute-drop.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { XYCoord } from "react-dnd";
import { NodeApi } from "../interfaces/node-api";
import { bound, indexOf, isClosed, isItem } from "../utils";
import {
bound,
indexOf,
isClosed,
isItem,
isOpenWithEmptyChildren,
} from "../utils";
import { DropResult } from "./drop-hook";

function measureHover(el: HTMLElement, offset: XYCoord) {
Expand Down Expand Up @@ -56,28 +62,6 @@ type Args = {
nextNode: NodeApi | null;
};

function getDropLevel(
hovering: HoverData,
aboveCursor: NodeApi | null,
belowCursor: NodeApi | null,
indent: number
) {
const hoverLevel = Math.round(Math.max(0, hovering.x - indent) / indent);
let min, max;
if (!aboveCursor) {
max = 0;
min = 0;
} else if (!belowCursor) {
max = aboveCursor.level;
min = 0;
} else {
max = aboveCursor.level;
min = belowCursor.level;
}

return bound(hoverLevel, min, max);
}

export type ComputedDrop = {
drop: DropResult | null;
cursor: Cursor | null;
Expand Down Expand Up @@ -128,10 +112,11 @@ export type Cursor = LineCursor | NoCursor | HighlightCursor;

/**
* This is the most complex, tricky function in the whole repo.
* It could be simplified and made more understandable.
*/
export function computeDrop(args: Args): ComputedDrop {
const hover = measureHover(args.element, args.offset);
const indent = args.indent;
const hoverLevel = Math.round(Math.max(0, hover.x - indent) / indent);
const { node, nextNode, prevNode } = args;
const [above, below] = getNodesAroundCursor(node, prevNode, nextNode, hover);

Expand All @@ -143,24 +128,56 @@ export function computeDrop(args: Args): ComputedDrop {
};
}

/* At the top of the list */
/*
* Now we only need to care about the node above the cursor
* ----------- -------
*/

/* There is no node above the cursor line */
if (!above) {
return {
drop: dropAt(below?.parent?.id, 0),
cursor: lineCursor(0, 0),
};
}

/* The above node is an item or a closed folder */
if (isItem(above) || isClosed(above)) {
const level = getDropLevel(hover, above, below, args.indent);
/* The node above the cursor line is an item */
if (isItem(above)) {
const level = bound(hoverLevel, below?.level || 0, above.level);
return {
drop: walkUpFrom(above, level),
cursor: lineCursor(above.rowIndex! + 1, level),
};
}

/* The node above the cursor line is a closed folder */
if (isClosed(above)) {
const level = bound(hoverLevel, below?.level || 0, above.level);
return {
drop: walkUpFrom(above, level),
cursor: lineCursor(above.rowIndex! + 1, level),
};
}

/* The above node is an open folder */
/* The node above the cursor line is an open folder with no children */
if (isOpenWithEmptyChildren(above)) {
const level = bound(hoverLevel, 0, above.level + 1);
if (level > above.level) {
/* Will be the first child of the empty folder */
return {
drop: dropAt(above.id, 0),
cursor: lineCursor(above.rowIndex! + 1, level),
};
} else {
/* Will be a sibling or grandsibling of the empty folder */
return {
drop: walkUpFrom(above, level),
cursor: lineCursor(above.rowIndex! + 1, level),
};
}
}

/* The node above the cursor is a an open folder with children */
return {
drop: dropAt(above?.id, 0),
cursor: lineCursor(above.rowIndex! + 1, above.level + 1),
Expand Down
4 changes: 4 additions & 0 deletions packages/react-arborist/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export function isClosed(node: NodeApi<any> | null) {
return node && node.isInternal && !node.isOpen;
}

export function isOpenWithEmptyChildren(node: NodeApi<any> | null) {
return node && node.isOpen && !node.children?.length;
}

/**
* Is first param a descendant of the second param
*/
Expand Down
Loading