@1771technologies/lytenyte-pro
Version:
Blazingly fast headless React data grid with 100s of features.
193 lines (192 loc) • 8.66 kB
JavaScript
import { useMemo } from "react";
import { usePiece, useOnRowsSelected, useRowIsSelected, useRowSelection, useRowsSelected, useEvent, useGlobalRefresh, useRowSelectionState, } from "@1771technologies/lytenyte-core/internal";
import {} from "@1771technologies/lytenyte-shared";
import { useRowByIndex } from "./source/use-row-by-index.js";
import { useRowIndexToRowId } from "./source/use-row-index-to-row-id.js";
import { useRowIdToRowIndex } from "./source/use-row-id-to-row-index.js";
import { useRowById } from "./source/use-row-by-id.js";
import { useOnViewChange } from "./source/use-on-view-change.js";
import { useSourceState } from "./source/use-source-state.js";
import { useSource } from "./source/use-source.js";
import { useRowParents } from "./source/use-row-parents.js";
import { useRowsBetween } from "./source/use-rows-between.js";
import { useRowChildren } from "./source/use-row-children.js";
import { useRowLeafs } from "./source/use-row-leafs.js";
import { useOnRowsUpdated } from "./source/use-on-rows-updated.js";
import { useRowDelete } from "./source/use-row-delete.js";
import { useRowAdd } from "./source/use-row-add.js";
import { useRowSiblings } from "./source/use-row-siblings.js";
export function useServerDataSource(props) {
const isolatedSelected = props.rowsIsolatedSelection ?? false;
const state = useSourceState(props);
const isLoading$ = usePiece(state.isLoading);
const loadError$ = usePiece(state.loadingError);
const requestsForView$ = usePiece(state.requestsForView, state.setRequestsForView);
const top$ = usePiece(state.topCount);
const bot$ = usePiece(state.botCount);
const maxDepth$ = usePiece(state.maxDepth);
const rowCount$ = usePiece(state.rowCount);
const globalSignal = useGlobalRefresh();
const source = useSource(props, state, globalSignal);
const rowById = useRowById(source);
const rowIdToRowIndex = useRowIdToRowIndex(source);
const rowIndexToRowId = useRowIndexToRowId(source);
const rowParents = useRowParents(source);
const rowsBetween = useRowsBetween(source);
const rowChildren = useRowChildren(source);
const onViewChange = useOnViewChange(source, state.requestsForView, state.setRequestsForView);
const idSpec = useEvent((id) => {
const node = source.tree.rowIdToNode.get(id);
if (!node || node.kind === "leaf")
return null;
return { size: node.size, children: node.byIndex };
});
const { rootIds, rootCount } = useMemo(() => {
const subset = props.rowSelectionIdUniverseSubtractions ?? new Set();
const rootIds = new Set([...source.tree.byIndex.values()].map((x) => x.row.id)).difference(subset);
const additions = new Set(props.rowSelectionIdUniverseAdditions?.filter((x) => x.root).map((x) => x.id) ?? []).difference(subset);
return { rootIds: rootIds.union(additions), rootCount: source.tree.size };
}, [
props.rowSelectionIdUniverseAdditions,
props.rowSelectionIdUniverseSubtractions,
source.tree.byIndex,
source.tree.size,
]);
// Handling row selection
const selectionState = useRowSelection(props.rowSelection, props.onRowSelectionChange, isolatedSelected, props.rowSelectKey ?? props.queryKey, useMemo(() => {
const subset = props.rowSelectionIdUniverseSubtractions ?? new Set();
if (!props.rowSelectionIdUniverseAdditions)
return state.idUniverse.difference(subset);
return state.idUniverse
.union(new Set(props.rowSelectionIdUniverseAdditions.map((x) => x.id)))
.difference(subset);
}, [props.rowSelectionIdUniverseAdditions, props.rowSelectionIdUniverseSubtractions, state.idUniverse]), rootIds, rootCount, globalSignal);
const onRowsSelected = useOnRowsSelected(selectionState, idSpec, rowParents, isolatedSelected, globalSignal);
const rowIsSelected = useRowIsSelected(selectionState, rowParents, rowById);
const rowsSelected = useRowsSelected(selectionState, source.tree.rowIdToNode, rowParents);
const rowSelectionState = useRowSelectionState(selectionState);
const rowLeafs = useRowLeafs(source);
const { rowByIndex, rowInvalidate } = useRowByIndex(source, selectionState, globalSignal, rowParents);
const setExpansions = state.onExpansionsChange;
const onRowsUpdated = useOnRowsUpdated(source, props.onRowDataChange, props.rowUpdateOptimistically, globalSignal);
const rowSiblings = useRowSiblings(source);
const rowDelete = useRowDelete(source, props.onRowsDeleted, props.rowUpdateOptimistically);
const rowAdd = useRowAdd(source, props.onRowsAdded, props.rowUpdateOptimistically);
const selection$ = usePiece(selectionState.rowSelectionsRaw);
const rowGroupsPresent$ = usePiece(props.hasRowBranches ?? "infer");
const rowSource = useMemo(() => {
const rowSource = {
rowById,
rowByIndex,
rowInvalidate,
rowIdToRowIndex,
rowIndexToRowId,
rowChildren,
rowsSelected,
rowIsSelected,
rowSelectionState,
rowDelete,
rowAdd,
rowUpdate: onRowsUpdated,
rowSiblings,
rowLeafs,
rowParents,
rowsBetween,
useTopCount: () => top$.useValue(),
useRowCount: () => rowCount$.useValue(),
useBottomCount: () => bot$.useValue(),
useRows: () => {
const rowCount = rowCount$.useValue();
const mappedMemo = useMemo(() => {
return {
get: (i) => {
const row = source.flat.rowIndexToRow.get(i);
if (!row && i >= 0 && i < rowCount) {
return {
kind: "leaf",
id: `__loading__placeholder__${i}`,
data: {},
depth: 0,
};
}
return row;
},
size: rowCount,
};
}, [rowCount]);
return mappedMemo;
},
useMaxRowGroupDepth: () => {
const maxDepth = maxDepth$.useValue();
const presence = rowGroupsPresent$.useValue();
if (presence === "infer")
return maxDepth;
return presence ? 1 : 0;
},
useSelectionState: selection$.useValue,
rowGroupExpansionChange: (deltaChanges) => {
setExpansions(deltaChanges);
},
onRowsSelected,
onViewChange,
onRowsUpdated,
// Specific to the server data source
isLoading: isLoading$,
loadingError: loadError$,
requestsForView: requestsForView$,
pushRequests: (requests) => source.handleRequests(requests),
pushResponses: source.handleResponses,
retry: () => {
source.retry();
rowSource.rowInvalidate();
},
refresh: (onSuccess, onError) => {
const requests = requestsForView$.get();
rowSource.pushRequests(requests, onSuccess, onError);
},
reset: () => source.reset(),
requestForGroup: (row) => {
const index = typeof row === "number" ? row : source.flat.rowIdToRowIndex.get(row.id);
if (index == null)
return null;
return source.requestForGroup(index);
},
requestForNextSlice: (req) => source.requestForNextSlice(req),
get seenRequests() {
return source.flat?.seenRequests ?? new Set();
},
};
return rowSource;
}, [
bot$,
isLoading$,
loadError$,
maxDepth$,
onRowsSelected,
onRowsUpdated,
onViewChange,
requestsForView$,
rowAdd,
rowById,
rowByIndex,
rowChildren,
rowCount$,
rowDelete,
rowGroupsPresent$,
rowIdToRowIndex,
rowIndexToRowId,
rowInvalidate,
rowIsSelected,
rowLeafs,
rowParents,
rowSelectionState,
rowSiblings,
rowsBetween,
rowsSelected,
selection$.useValue,
setExpansions,
source,
top$,
]);
return rowSource;
}