UNPKG

@1771technologies/lytenyte-pro

Version:

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

193 lines (192 loc) 8.66 kB
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; }