UNPKG

@1771technologies/lytenyte-pro

Version:

Blazingly fast headless React data grid with 100s of features.

60 lines (59 loc) 2.24 kB
import { useMemo } from "react"; import { isObject } from "../utils/is-object.js"; const defaultIdFn = (path) => path.join("-->"); const rowValueFnDefault = (x) => { if (!isObject(x)) return null; const entries = Object.entries(x).filter((v) => !isObject(v[1])); return Object.fromEntries(entries); }; const rowChildrenFnDefault = (x) => { if (!isObject(x)) return []; return Object.entries(x).filter((x) => isObject(x[1])); }; export function useTree({ data, filter, idFn = defaultIdFn, rowValueFn = rowValueFnDefault, rowChildrenFn = rowChildrenFnDefault, rowRootFn = Object.entries, }) { const rowTree = useMemo(() => { const root = { kind: "root", children: new Map(), rowIdToNode: new Map(), data, }; const groupKeys = (parent, path, row, parentObj) => { const value = rowValueFn(row, parentObj, path.at(-1)); const entries = rowChildrenFn(row, parentObj, path.at(-1)); if (filter && !filter(value)) return; const expandable = entries.some((x) => isObject(x[1])); const node = { kind: "parent", children: new Map(), parent, path, data: row, key: path.at(-1), row: { kind: "branch", depth: path.length - 1, expandable, expanded: false, key: path.at(-1), last: !expandable, id: idFn(path, value), data: value, parentId: parent.kind === "root" ? null : parent.row.id, }, }; parent.children.set(path.at(-1), node); root.rowIdToNode.set(node.row.id, node); entries.forEach((x) => groupKeys(node, [...path, x[0]], x[1], row)); }; const rootRows = rowRootFn(data); for (const [path, row] of rootRows) { groupKeys(root, [path], row, data); } return root; }, [data, filter, idFn, rowChildrenFn, rowRootFn, rowValueFn]); return rowTree; }