UNPKG

@1771technologies/lytenyte-pro

Version:

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

117 lines (116 loc) 4.22 kB
import { useCallback, useMemo } from "react"; import { useGrid } from "../../grid-provider/use-grid.js"; import { useTreeContext } from "../context.js"; function isSelectAll(item) { return item.kind === "leaf" && item.leaf.data.id === "__LNG__SELECT_ALL"; } export function useTreeItem(item) { const { filter, filterChange, pivotMode, columnId, items, applyChangesImmediately } = useTreeContext(); const grid = useGrid(); const itemValues = useMemo(() => { if (item.kind === "leaf") return [item.leaf.data.value]; const leafItems = []; const stack = [...item.children.values()]; while (stack.length) { const c = stack.pop(); if (c.kind === "leaf") leafItems.push(c.leaf.data.value); else stack.push(...c.children.values()); } return leafItems; }, [item]); const isChecked = useMemo(() => { if (filter.operator === "in") { if (isSelectAll(item)) { return items.every((c) => filter.value.has(c.value)); } return itemValues.every((c) => filter.value.has(c)); } else { if (isSelectAll(item)) { return filter.value.size === 0; } return itemValues.every((c) => !filter.value.has(c)); } }, [filter.operator, filter.value, item, itemValues, items]); const isIndeterminate = useMemo(() => { if (filter.operator === "in") { if (isSelectAll(item)) { return !isChecked && items.some((c) => filter.value.has(c)); } return !isChecked && itemValues.some((c) => filter.value.has(c)); } else { if (isSelectAll(item)) { return (!isChecked && filter.value.size > 0 && items.some((c) => !filter.value.has(c))); } return !isChecked && itemValues.some((c) => !filter.value.has(c)); } }, [item, isChecked, itemValues, filter, items]); const onCheckChange = useCallback((b) => { const checked = b ?? !isChecked; let nextValue; const operator = filter.operator; if (isSelectAll(item)) { if (operator === "in") { nextValue = checked ? new Set(items.map((c) => c.value)) : new Set(); } else { nextValue = checked ? new Set() : new Set(items.map((c) => c.value)); } } else { nextValue = new Set(filter.value); if (operator === "in") { if (checked) itemValues.forEach((c) => nextValue.add(c)); else itemValues.forEach((c) => nextValue.delete(c)); } else { if (checked) itemValues.forEach((c) => nextValue.delete(c)); else itemValues.forEach((c) => nextValue.add(c)); } } if (!applyChangesImmediately) { filterChange({ kind: "in", operator, value: nextValue }); } else { if (pivotMode) { grid.state.columnPivotModel.set((prev) => { return { ...prev, filtersIn: { ...prev.filtersIn, [columnId]: { kind: "in", operator, value: nextValue }, }, }; }); } else { grid.state.filterInModel.set((prev) => ({ ...prev, [columnId]: { kind: "in", operator, value: nextValue }, })); } } }, [ isChecked, item, itemValues, filter.operator, filter.value, applyChangesImmediately, items, filterChange, pivotMode, grid.state.columnPivotModel, grid.state.filterInModel, columnId, ]); return useMemo(() => ({ onCheckChange, isChecked, isIndeterminate, item }), [isChecked, isIndeterminate, item, onCheckChange]); }