diff --git a/packages/react-arborist/src/hooks/use-dynamic-tree.ts b/packages/react-arborist/src/hooks/use-dynamic-tree.ts new file mode 100644 index 00000000..3461ca16 --- /dev/null +++ b/packages/react-arborist/src/hooks/use-dynamic-tree.ts @@ -0,0 +1,54 @@ +import { useMemo, useState } from "react"; +import { SimpleTree } from "../data/simple-tree"; +import { + CreateHandler, + DeleteHandler, + MoveHandler, + RenameHandler, +} from "../types/handlers"; +import { IdObj } from "../types/utils"; + +let nextId = 0; + +export function useDynamicTree() { + const [data, setData] = useState([]); + const tree = useMemo( + () => + new SimpleTree(data), + [data] + ); + + const onMove: MoveHandler = (args: { + dragIds: string[]; + parentId: null | string; + index: number; + }) => { + for (const id of args.dragIds) { + tree.move({ id, parentId: args.parentId, index: args.index }); + } + setData(tree.data); + }; + + const onRename: RenameHandler = ({ name, id }) => { + tree.update({ id, changes: { name } as any }); + setData(tree.data); + }; + + const onCreate: CreateHandler = ({ parentId, index, type }) => { + const data = { id: `simple-tree-id-${nextId++}`, name: "" } as any; + if (type === "internal") data.children = []; + tree.create({ parentId, index, data }); + setData(tree.data); + return data; + }; + + const onDelete: DeleteHandler = (args: { ids: string[] }) => { + args.ids.forEach((id) => tree.drop({ id })); + setData(tree.data); + }; + + const controllers = { onMove, onRename, onCreate, onDelete }; + + return { data, setData, controllers } as const; +} diff --git a/packages/react-arborist/src/index.ts b/packages/react-arborist/src/index.ts index 854860fb..c3cf822f 100644 --- a/packages/react-arborist/src/index.ts +++ b/packages/react-arborist/src/index.ts @@ -7,3 +7,4 @@ export * from "./interfaces/node-api"; export * from "./interfaces/tree-api"; export * from "./data/simple-tree"; export * from "./hooks/use-simple-tree"; +export * from "./hooks/use-dynamic-tree";