@1771technologies/lytenyte-pro
Version:
Blazingly fast headless React data grid with 100s of features.
102 lines (101 loc) • 3.58 kB
JavaScript
import { useEffect, useMemo, useState } from "react";
import { useVirtualizedTree } from "../../tree-view/virtualized/use-virtualized-tree.js";
import { useEvent } from "@1771technologies/lytenyte-core/yinternal";
export function useFilterTree({ grid, column, treeItemHeight = 24, pivotMode, applyChangesImmediately = false, query, }) {
const [items, setItems] = useState([]);
const [expansions, onExpansionChange] = useState({});
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
const rds = grid.state.rowDataSource.useValue();
const filterModel = grid.state.filterInModel.useValue();
const pivotModel = grid.state.columnPivotModel.useValue().filtersIn;
const currentPivotMode = grid.state.columnPivotMode.useValue();
const model = (pivotMode ?? currentPivotMode) ? pivotModel : filterModel;
const existingFilter = useMemo(() => {
const filter = model[column.id];
return filter ?? { kind: "in", operator: "not_in", value: new Set() };
}, [column.id, model]);
const [changes, setChanges] = useState(() => existingFilter);
// Keep in sync with any external changes.
useEffect(() => {
setChanges(existingFilter);
}, [existingFilter]);
const fetchItems = useEvent(() => {
const items = rds.inFilterItems(column);
if ("then" in items) {
setLoading(true);
items
.then((res) => {
setItems(res);
setError(null);
})
.catch((error) => setError(error))
.finally(() => setLoading(false));
}
else {
setItems(items);
setError(null);
setLoading(false);
}
});
useEffect(() => {
fetchItems();
}, [column, fetchItems, rds]);
const filteredItems = useMemo(() => {
if (!query)
return items;
return items.filter((c) => c.label.toLowerCase().includes(query.toLowerCase()));
}, [items, query]);
const itemsWithSelectAll = useMemo(() => {
return [{ id: "__LNG__SELECT_ALL", label: "(Select All)", value: "" }, ...filteredItems];
}, [filteredItems]);
const virt = useVirtualizedTree({
itemHeight: treeItemHeight,
paths: itemsWithSelectAll,
expansions,
expansionDefault: true,
nonAdjacentPathTrees: false,
});
const apply = useEvent(() => {
if (applyChangesImmediately)
return;
if (pivotMode) {
grid.state.columnPivotModel.set((prev) => {
return {
...prev,
filtersIn: { ...prev.filtersIn, [column.id]: changes },
};
});
}
else {
grid.state.filterInModel.set((prev) => ({ ...prev, [column.id]: changes }));
}
});
const reset = useEvent(() => {
if (applyChangesImmediately)
return;
setChanges(existingFilter);
});
return {
rootProps: {
fetchItems,
items,
grid,
columnId: column.id,
expansions,
pivotMode: pivotMode ?? currentPivotMode,
onExpansionChange,
treeRef: virt.ref,
loading,
error,
filterIn: changes,
filterInChange: setChanges,
applyChangesImmediately,
...virt.rootProps,
},
spacer: virt.spacer,
tree: virt.virtualTree,
apply,
reset,
};
}