Skip to content

Commit

Permalink
Disable Drop Works
Browse files Browse the repository at this point in the history
  • Loading branch information
jameskerr committed Mar 19, 2024
1 parent 55279a0 commit 8ba482f
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 10 deletions.
11 changes: 10 additions & 1 deletion modules/react-arborist/src/controllers/node-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class NodeController<T> {
return this.object.parent?.id || null;
}

get parent() {
get parent(): NodeController<T> | null {
if (this.parentId) {
return this.tree.get(this.parentId);
} else {
Expand Down Expand Up @@ -94,6 +94,15 @@ export class NodeController<T> {
} as Record<string, boolean>;
}

isDescendantOf(node: NodeController<T>) {
let cursor: NodeController<any> | null = this;
while (cursor) {
if (cursor.id === node.id) return true;
cursor = cursor.parent;
}
return false;
}

/* Open State */
get isOpen() {
return this.isInternal && this.tree.isOpen(this.id);
Expand Down
32 changes: 27 additions & 5 deletions modules/react-arborist/src/controllers/tree-controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CursorState } from "../cursor/types";
import { safeToDrop } from "../dnd/safe-to-drop";
import { TreeViewProps } from "../types/tree-view-props";
import { NodeController } from "./node-controller";

Expand Down Expand Up @@ -58,15 +59,38 @@ export class TreeController<T> {
return len === 0 ? null : this.rows[len - 1];
}

get(id: string) {
get dragNodes() {
return this.getAll(this.props.dnd.value.dragItems);
}

get dragSourceNode() {
return this.get(this.props.dnd.value.dragSourceId);
}

get dropTargetParentNode() {
return this.get(this.props.dnd.value.targetParentId);
}

get dropTargetIndex() {
return this.props.dnd.value.targetIndex;
}

get(id: string | null): NodeController<T> | null {
if (id === null) return null;
const index = this.indexOf(id);
if (index) {
this.rows[index] || null;
return this.rows[index] || null;
} else {
return null;
}
}

getAll(ids: string[]) {
return ids
.map((id) => this.get(id))
.filter((n) => !!n) as NodeController<T>[];
}

nodeBefore(node: NodeController<T>) {
return this.rows[node.rowIndex - 1] || null;
}
Expand Down Expand Up @@ -211,9 +235,7 @@ export class TreeController<T> {
}

canDrop() {
// todo
// mmove this into a default prop or something
return true;
return safeToDrop(this);
}

drop() {
Expand Down
31 changes: 31 additions & 0 deletions modules/react-arborist/src/dnd/safe-to-drop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { TreeController } from "../controllers/tree-controller";

export function safeToDrop(tree: TreeController<any>) {
const targetParentNode = tree.dropTargetParentNode;
const targetIndex = tree.dropTargetIndex;
const dragNodes = tree.dragNodes;

/* Basic Defaul Check */
if (targetParentNode === null && targetIndex === null) return false;

for (const draggingNode of tree.dragNodes) {
if (
draggingNode.isInternal &&
targetParentNode?.isDescendantOf(draggingNode)
) {
return false;
}
}

/* User Provided Check */
const disableCheck = tree.props.disableDrop;
if (typeof disableCheck == "function") {
return !disableCheck({ dragNodes, targetParentNode, targetIndex });
} else if (typeof disableCheck == "string" && targetParentNode) {
return !targetParentNode.data[disableCheck];
} else if (typeof disableCheck === "boolean") {
return !disableCheck;
} else {
return true;
}
}
7 changes: 7 additions & 0 deletions modules/react-arborist/src/dnd/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { NodeController } from "../controllers/node-controller";
import { PartialController } from "../types/utils";

export type DndState = {
Expand Down Expand Up @@ -26,3 +27,9 @@ export type DndPartialController = PartialController<
DndState,
DndOnChangeEvent
>;

export type DisableDropCheck<T> = (args: {
dragNodes: NodeController<T>[];
targetParentNode: NodeController<T> | null;
targetIndex: number | null;
}) => boolean;
2 changes: 1 addition & 1 deletion modules/react-arborist/src/dnd/use-node-drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function useNodeDrop<T>(node: NodeController<T>, ref: any) {
});
if (drop) node.tree.draggingOver(drop.parentId, drop.index!);

if (true /* canDrop? */) {
if (node.tree.canDrop()) {
if (cursor) node.tree.showCursor(cursor);
} else {
node.tree.hideCursor();
Expand Down
4 changes: 2 additions & 2 deletions modules/react-arborist/src/nodes/default-node-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ export const defaultNodeObjects: DefaultNodeObject[] = [
name: "Mastodon",
},
{
id: "10",
id: "12",
name: "GitHub Profile",
},
{
id: "11",
id: "13",
name: "Email",
},
],
Expand Down
3 changes: 2 additions & 1 deletion modules/react-arborist/src/types/tree-view-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { OpensPartialController } from "../opens/types";
import { PartialController } from "./utils";
import { EditOnChangeEvent, EditPartialController } from "../edit/types";
import { SelectionPartialController } from "../selection/types";
import { DndPartialController } from "../dnd/types";
import { DisableDropCheck, DndPartialController } from "../dnd/types";
import { CursorPartialController } from "../cursor/types";
import { FocusPartialController } from "../focus/types";

Expand Down Expand Up @@ -33,4 +33,5 @@ export type TreeViewProps<T> = {

/* Configurations */
openByDefault: boolean;
disableDrop?: string | boolean | DisableDropCheck<T>;
};

0 comments on commit 8ba482f

Please sign in to comment.