Merge pull request #32685 from grantila/grantila/bui-allow-data-to-be-passed-inplace

[BUI] Allow a 'data' prop to be passed inplace to the useTable hook
This commit is contained in:
Patrik Oldsberg
2026-02-05 19:47:20 +01:00
committed by GitHub
6 changed files with 65 additions and 29 deletions
+16 -12
View File
@@ -2121,21 +2121,25 @@ export function useTable<T extends TableItem, TFilter = unknown>(
): UseTableResult<T, TFilter>;
// @public (undocumented)
export interface UseTableCompleteOptions<T extends TableItem, TFilter = unknown>
extends QueryOptions<TFilter> {
// (undocumented)
filterFn?: (data: T[], filter: TFilter) => T[];
// (undocumented)
getData: () => T[] | Promise<T[]>;
// (undocumented)
export type UseTableCompleteOptions<
T extends TableItem,
TFilter = unknown,
> = QueryOptions<TFilter> & {
mode: 'complete';
// (undocumented)
paginationOptions?: PaginationOptions;
// (undocumented)
searchFn?: (data: T[], search: string) => T[];
// (undocumented)
sortFn?: (data: T[], sort: SortDescriptor) => T[];
}
filterFn?: (data: T[], filter: TFilter) => T[];
searchFn?: (data: T[], search: string) => T[];
} & (
| {
data: T[] | undefined;
getData?: never;
}
| {
data?: never;
getData: () => T[] | Promise<T[]>;
}
);
// @public (undocumented)
export interface UseTableCursorOptions<T extends TableItem, TFilter = unknown>
@@ -96,15 +96,25 @@ export interface CursorResponse<T> {
}
/** @public */
export interface UseTableCompleteOptions<T extends TableItem, TFilter = unknown>
extends QueryOptions<TFilter> {
export type UseTableCompleteOptions<
T extends TableItem,
TFilter = unknown,
> = QueryOptions<TFilter> & {
mode: 'complete';
getData: () => T[] | Promise<T[]>;
paginationOptions?: PaginationOptions;
sortFn?: (data: T[], sort: SortDescriptor) => T[];
filterFn?: (data: T[], filter: TFilter) => T[];
searchFn?: (data: T[], search: string) => T[];
}
} & (
| {
data: T[] | undefined;
getData?: never;
}
| {
data?: never;
getData: () => T[] | Promise<T[]>;
}
);
/** @public */
export interface UseTableOffsetOptions<T extends TableItem, TFilter = unknown>
@@ -30,7 +30,8 @@ export function useCompletePagination<T extends TableItem, TFilter>(
query: QueryState<TFilter>,
): PaginationResult<T> & { reload: () => void } {
const {
getData: getDataProp,
data,
getData: getDataProp = () => [],
paginationOptions = {},
sortFn,
filterFn,
@@ -43,7 +44,7 @@ export function useCompletePagination<T extends TableItem, TFilter>(
const { sort, filter, search } = query;
const [items, setItems] = useState<T[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(!data);
const [error, setError] = useState<Error | undefined>(undefined);
const [loadCount, setLoadCount] = useState(0);
@@ -52,6 +53,10 @@ export function useCompletePagination<T extends TableItem, TFilter>(
// Load data on mount and when loadCount changes (reload trigger)
useEffect(() => {
if (data) {
return;
}
let cancelled = false;
setIsLoading(true);
setError(undefined);
@@ -75,7 +80,7 @@ export function useCompletePagination<T extends TableItem, TFilter>(
return () => {
cancelled = true;
};
}, [getData, loadCount]);
}, [data, getData, loadCount]);
// Reset offset when query changes (query object is memoized)
const prevQueryRef = useRef(query);
@@ -86,9 +91,11 @@ export function useCompletePagination<T extends TableItem, TFilter>(
}
}, [query]);
const resolvedItems = useMemo(() => data ?? items, [data, items]);
// Process data client-side (filter, search, sort)
const processedData = useMemo(() => {
let result = [...items];
let result = [...resolvedItems];
if (filter !== undefined && filterFn) {
result = filterFn(result, filter);
}
@@ -99,7 +106,7 @@ export function useCompletePagination<T extends TableItem, TFilter>(
result = sortFn(result, sort);
}
return result;
}, [items, sort, filter, search, filterFn, searchFn, sortFn]);
}, [resolvedItems, sort, filter, search, filterFn, searchFn, sortFn]);
const totalCount = processedData.length;