List Engine
ListEngine
Section titled “ListEngine”ListEngine is a generic, composable list-rendering primitive used for filterable, paginated list UIs where each item is custom-rendered.
It wraps useListEngineApi() and renders three sections:
- header
- list body
- footer (pagination, when applicable)
Exports
Section titled “Exports”From src/components/ListEngine/index.tsx:
ListEngine<T>()useListEngineApi<T>()ListEngineProps<T>ListEngineRenderArgs<T>ListEngineItemRenderArgs<T>ListEngineFilterGroup
Core Types
Section titled “Core Types”export type ListEngineFilterGroup = { id: string; label: string; description?: string; placement?: "header" | "panel"; order?: number;};export interface ListEngineItemRenderArgs<T> { item: T; index: number; globalIndex: number; page: number;}export interface ListEngineRenderArgs<T> { items: readonly T[]; filteredItems: readonly T[]; allItems: readonly T[]; loading: boolean; page: number; totalPages: number; pageSize: number; filterState: FilterStateMap<T>; rangeState: RangeStateMap<T>; dateRangeState: DateRangeMap<T>; setPage: Dispatch<SetStateAction<number>>; setFilter: (key: keyof T, value: string) => void; setRange: (key: keyof T, min: number | null, max: number | null) => void; setDateRange: (key: keyof T, range: DateRange) => void; clearFilters: () => void;}Props (ListEngineProps<T>)
Section titled “Props (ListEngineProps<T>)”interface ListEngineProps<T extends Record<string, any>> { title?: string; label?: string; data: readonly T[]; filters?: readonly Filter<T>[]; filterGroups?: readonly ListEngineFilterGroup[]; actions?: ReactNode; loading?: boolean; pageSize?: number; initialFilters?: FilterStateMap<T>; initialRangeState?: RangeStateMap<T>; initialDateRanges?: DateRangeMap<T>; listSize?: number | string; itemKey?: (item: T, index: number) => string | number; renderItem: (args: ListEngineItemRenderArgs<T>) => ReactNode; emptyState?: ReactNode;}Behavior Notes
Section titled “Behavior Notes”Filtering
Section titled “Filtering”Supports filter types from BusinessTable/filters.tsx:
textselectrangedateRange
placement controls where filters render:
"header"-> inline in header"panel"-> inside SidePanel opened byFiltersbutton
filterGroups allow grouped panel sections with label/description/order.
Pagination
Section titled “Pagination”- Pagination is enabled only when
pageSize > 0. - Footer is rendered only when there is more than one page.
- Page resets to
1when data or any filter state changes.
Loading and Empty States
Section titled “Loading and Empty States”loading=trueshows a short loader bar in list area.- If not loading and no page items remain,
emptyStateis shown. - Default empty state text:
No records found.
Actions
Section titled “Actions”actions are rendered in a DropdownButton (kebab menu) in the header.
Title Resolution
Section titled “Title Resolution”Header title resolves in this order:
titlelabel- fallback:
"List"
Basic Usage
Section titled “Basic Usage”import ListEngine, { type ListEngineProps } from "@/components/ListEngine";import type { Filter } from "@/components/BusinessTable/filters";
type UserRow = { id: number; name: string; role: string; createdAt: string;};
const filters: Filter<UserRow>[] = [ { type: "text", label: "Name", key: "name", placement: "header", placeholder: "Search users" }, { type: "select", label: "Role", key: "role", placement: "panel", options: [ { label: "Admin", value: "Admin" }, { label: "User", value: "User" }, ], }, { type: "dateRange", label: "Created", key: "createdAt", placement: "panel" },];
<ListEngine<UserRow> title="Users" data={rows} filters={filters} pageSize={20} itemKey={(row) => row.id} renderItem={({ item }) => ( <div> <strong>{item.name}</strong> - {item.role} </div> )}/>;Using useListEngineApi Directly
Section titled “Using useListEngineApi Directly”Use this when you need custom layout around generated sections.
import { useListEngineApi } from "@/components/ListEngine";
const { header, list, footer, state } = useListEngineApi<UserRow>({ title: "Users", data: rows, filters, pageSize: 20, renderItem: ({ item }) => <UserCard user={item} />,});
return ( <section> {header} <div style={{ marginTop: 12 }}>{list}</div> {footer} </section>);When To Use
Section titled “When To Use”Use ListEngine when:
- you need complex filter composition,
- each row/item has custom markup,
- you need pagination + filter state control.
Prefer DynamicTable for simpler table-like CRUD/read screens.
Source Files
Section titled “Source Files”src/components/ListEngine/index.tsxsrc/components/ListEngine/useListEngineApi.tsxsrc/components/ListEngine/useListEngine.tssrc/components/ListEngine/useListFilterRendering.tsxsrc/components/BusinessTable/filters.tsx