Headless UI for building powerful tables & datagrids for TS/JS
—
Pre-built sorting, filtering, and aggregation functions for common table operations. These functions provide robust, tested implementations for standard data operations.
Built-in sorting functions for different data types and sorting requirements.
/** Built-in sorting functions collection */
const sortingFns: {
alphanumeric: SortingFn<any>;
alphanumericCaseSensitive: SortingFn<any>;
text: SortingFn<any>;
textCaseSensitive: SortingFn<any>;
datetime: SortingFn<any>;
basic: SortingFn<any>;
};
/** Built-in sorting function names */
type BuiltInSortingFn = keyof typeof sortingFns;
/** Regular expression for splitting alphanumeric strings */
const reSplitAlphaNumeric: RegExp;Usage Examples:
import { sortingFns } from "@tanstack/table-core";
// Using built-in sorting functions in column definitions
const columns = [
columnHelper.accessor('name', {
header: 'Name',
sortingFn: 'alphanumeric', // Mixed letters and numbers
}),
columnHelper.accessor('code', {
header: 'Code',
sortingFn: 'alphanumericCaseSensitive', // Case-sensitive mixed sorting
}),
columnHelper.accessor('description', {
header: 'Description',
sortingFn: 'text', // Fast text sorting
}),
columnHelper.accessor('label', {
header: 'Label',
sortingFn: 'textCaseSensitive', // Case-sensitive text sorting
}),
columnHelper.accessor('createdAt', {
header: 'Created',
sortingFn: 'datetime', // Date/time sorting
}),
columnHelper.accessor('score', {
header: 'Score',
sortingFn: 'basic', // Basic value comparison
}),
];
// Access sorting functions directly
const result = sortingFns.alphanumeric(rowA, rowB, 'columnId');Detailed documentation for each built-in sorting function.
/**
* Alphanumeric sorting with mixed text and numbers
* Handles numeric sequences within strings properly
* Case-insensitive comparison
*/
function alphanumeric<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;
/**
* Case-sensitive alphanumeric sorting
* Same as alphanumeric but preserves case
*/
function alphanumericCaseSensitive<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;
/**
* Fast text sorting for string values
* Case-insensitive, optimized for speed
* Less numeric support than alphanumeric
*/
function text<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;
/**
* Case-sensitive text sorting
* Same as text but preserves case
*/
function textCaseSensitive<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;
/**
* Date and time sorting
* Handles Date objects and nullish values
* Uses comparison operators for performance
*/
function datetime<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;
/**
* Basic value comparison sorting
* Simple comparison using > and < operators
* Works with numbers, strings, and other comparable types
*/
function basic<TData extends RowData>(
rowA: Row<TData>,
rowB: Row<TData>,
columnId: string
): number;Usage Examples:
// Example data types that work well with each sorting function
// alphanumeric: "item1", "item2", "item10", "item20"
// Correctly sorts as: item1, item2, item10, item20 (not item1, item10, item2, item20)
// alphanumericCaseSensitive: "Item1", "item2", "Item10"
// Sorts with case sensitivity preserved
// text: Fast sorting for plain text fields
// Best for: names, descriptions, labels
// textCaseSensitive: "Apple", "banana", "Zebra"
// Maintains case-sensitive ordering
// datetime: Date objects, null, undefined
const dateColumn = columnHelper.accessor('createdAt', {
sortingFn: 'datetime',
cell: info => info.getValue()?.toLocaleDateString(),
});
// basic: numbers, booleans, simple comparisons
const numericColumn = columnHelper.accessor('count', {
sortingFn: 'basic', // Simple numeric comparison
});Built-in filter functions for various filtering patterns and data types.
/** Built-in filter functions collection */
const filterFns: {
includesString: FilterFn<any>;
includesStringSensitive: FilterFn<any>;
equalsString: FilterFn<any>;
arrIncludes: FilterFn<any>;
arrIncludesAll: FilterFn<any>;
arrIncludesSome: FilterFn<any>;
equals: FilterFn<any>;
weakEquals: FilterFn<any>;
inNumberRange: FilterFn<any>;
};
/** Built-in filter function names */
type BuiltInFilterFn = keyof typeof filterFns;Usage Examples:
import { filterFns } from "@tanstack/table-core";
// Using built-in filter functions in column definitions
const columns = [
columnHelper.accessor('name', {
header: 'Name',
filterFn: 'includesString', // Case-insensitive partial match
}),
columnHelper.accessor('code', {
header: 'Code',
filterFn: 'includesStringSensitive', // Case-sensitive partial match
}),
columnHelper.accessor('status', {
header: 'Status',
filterFn: 'equalsString', // Exact string match
}),
columnHelper.accessor('tags', {
header: 'Tags',
filterFn: 'arrIncludes', // Array contains value
}),
columnHelper.accessor('id', {
header: 'ID',
filterFn: 'equals', // Strict equality
}),
columnHelper.accessor('age', {
header: 'Age',
filterFn: 'inNumberRange', // Numeric range filter
}),
];Detailed documentation for each built-in filter function.
/**
* Case-insensitive string inclusion filter
* Checks if cell value contains the filter value
* Converts both to lowercase for comparison
*/
function includesString(
row: Row<any>,
columnId: string,
filterValue: string
): boolean;
/**
* Case-sensitive string inclusion filter
* Checks if cell value contains the filter value
* Preserves original case for comparison
*/
function includesStringSensitive(
row: Row<any>,
columnId: string,
filterValue: string
): boolean;
/**
* Case-insensitive string equality filter
* Checks if cell value exactly equals filter value
* Converts both to lowercase for comparison
*/
function equalsString(
row: Row<any>,
columnId: string,
filterValue: string
): boolean;
/**
* Array inclusion filter
* Checks if cell array contains the filter value
* Uses array.includes() method
*/
function arrIncludes(
row: Row<any>,
columnId: string,
filterValue: unknown
): boolean;
/**
* Array includes all filter
* Checks if cell array contains all values in filter array
* All filter values must be present in cell array
*/
function arrIncludesAll(
row: Row<any>,
columnId: string,
filterValue: unknown[]
): boolean;
/**
* Array includes some filter
* Checks if cell array contains any values in filter array
* At least one filter value must be present in cell array
*/
function arrIncludesSome(
row: Row<any>,
columnId: string,
filterValue: unknown[]
): boolean;
/**
* Strict equality filter
* Uses === comparison between cell value and filter value
* No type coercion performed
*/
function equals(
row: Row<any>,
columnId: string,
filterValue: unknown
): boolean;
/**
* Weak equality filter
* Uses == comparison between cell value and filter value
* Allows type coercion (e.g., "1" == 1)
*/
function weakEquals(
row: Row<any>,
columnId: string,
filterValue: unknown
): boolean;
/**
* Number range filter
* Checks if numeric cell value falls within min/max range
* Handles null values and invalid numbers gracefully
*/
function inNumberRange(
row: Row<any>,
columnId: string,
filterValue: [number, number]
): boolean;Built-in filter functions include additional properties for enhanced functionality.
/** Auto-removal function for includesString */
includesString.autoRemove = (val: any) => testFalsey(val);
/** Auto-removal function for equalsString */
equalsString.autoRemove = (val: any) => testFalsey(val);
/** Auto-removal function for equals */
equals.autoRemove = (val: any) => testFalsey(val);
/** Filter value resolver for inNumberRange */
inNumberRange.resolveFilterValue = (val: [any, any]) => [number, number];
/** Auto-removal function for inNumberRange */
inNumberRange.autoRemove = (val: any) =>
testFalsey(val) || (testFalsey(val[0]) && testFalsey(val[1]));Usage Examples:
// String filtering examples
const nameFilter = filterFns.includesString;
const isMatch = nameFilter(row, 'name', 'john'); // Matches "John", "johnny", etc.
// Array filtering examples
const tagsData = { tags: ['react', 'typescript', 'table'] };
const hasReact = filterFns.arrIncludes(row, 'tags', 'react'); // true
const hasAll = filterFns.arrIncludesAll(row, 'tags', ['react', 'vue']); // false
const hasSome = filterFns.arrIncludesSome(row, 'tags', ['react', 'vue']); // true
// Range filtering examples
const ageData = { age: 25 };
const inRange = filterFns.inNumberRange(row, 'age', [18, 65]); // true
// Equality filtering examples
const statusData = { status: 'active', count: 5 };
const exactMatch = filterFns.equals(row, 'status', 'active'); // true
const numericMatch = filterFns.weakEquals(row, 'count', '5'); // true (string coerced to number)Built-in aggregation functions for grouped data calculations.
/** Built-in aggregation functions collection */
const aggregationFns: {
sum: AggregationFn<any>;
min: AggregationFn<any>;
max: AggregationFn<any>;
extent: AggregationFn<any>;
mean: AggregationFn<any>;
median: AggregationFn<any>;
unique: AggregationFn<any>;
uniqueCount: AggregationFn<any>;
count: AggregationFn<any>;
};
/** Built-in aggregation function names */
type BuiltInAggregationFn = keyof typeof aggregationFns;Usage Examples:
import { aggregationFns } from "@tanstack/table-core";
// Using aggregation functions in column definitions
const columns = [
columnHelper.accessor('department', {
header: 'Department',
enableGrouping: true,
}),
columnHelper.accessor('salary', {
header: 'Salary',
aggregationFn: 'sum', // Sum all salaries in group
aggregatedCell: ({ getValue }) =>
`$${getValue().toLocaleString()}`,
}),
columnHelper.accessor('experience', {
header: 'Experience',
aggregationFn: 'mean', // Average experience in group
aggregatedCell: ({ getValue }) =>
`${Math.round(getValue())} years`,
}),
columnHelper.accessor('score', {
header: 'Score',
aggregationFn: 'extent', // Min and max scores
aggregatedCell: ({ getValue }) => {
const [min, max] = getValue();
return `${min} - ${max}`;
},
}),
];Detailed documentation for each built-in aggregation function.
/**
* Sum aggregation - adds numeric values
* Treats non-numeric values as 0
* Works with child row aggregated values
*/
function sum(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number;
/**
* Minimum aggregation - finds smallest numeric value
* Ignores null/undefined values
* Handles NaN values gracefully
*/
function min(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number | undefined;
/**
* Maximum aggregation - finds largest numeric value
* Ignores null/undefined values
* Handles NaN values gracefully
*/
function max(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number | undefined;
/**
* Extent aggregation - returns [min, max] array
* Combines min and max calculations
* Returns undefined if no valid values
*/
function extent(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): [number, number] | undefined;
/**
* Mean aggregation - calculates average of numeric values
* Excludes null/undefined/NaN values from calculation
* Returns undefined if no valid values
*/
function mean(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number | undefined;
/**
* Median aggregation - finds middle value when sorted
* Handles even/odd number of values appropriately
* Only works with numeric arrays
*/
function median(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number | undefined;
/**
* Unique aggregation - returns array of unique values
* Uses Set for deduplication
* Preserves all data types
*/
function unique(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): any[];
/**
* Unique count aggregation - counts distinct values
* Uses Set size for counting
* More memory efficient than unique for just counts
*/
function uniqueCount(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number;
/**
* Count aggregation - counts total rows
* Simply returns array length
* Useful for "Total Items" type aggregations
*/
function count(
columnId: string,
leafRows: Row<any>[],
childRows: Row<any>[]
): number;Usage Examples:
// Aggregation function examples with different data types
// Numeric aggregations
const salesData = [
{ region: 'North', sales: 1000 },
{ region: 'North', sales: 1500 },
{ region: 'South', sales: 800 },
];
// sum: North = 2500, South = 800
// mean: North = 1250, South = 800
// min: North = 1000, South = 800
// max: North = 1500, South = 800
// extent: North = [1000, 1500], South = [800, 800]
// Count aggregations
// count: North = 2, South = 1
// Text aggregations
const employeeData = [
{ dept: 'Engineering', skill: 'JavaScript' },
{ dept: 'Engineering', skill: 'TypeScript' },
{ dept: 'Engineering', skill: 'JavaScript' }, // duplicate
];
// unique: Engineering = ['JavaScript', 'TypeScript']
// uniqueCount: Engineering = 2
// Using aggregations with grouping
const table = createTable({
data: salesData,
columns: [
columnHelper.accessor('region', {
enableGrouping: true,
}),
columnHelper.accessor('sales', {
aggregationFn: 'sum',
aggregatedCell: ({ getValue }) => `$${getValue().toLocaleString()}`,
}),
],
getCoreRowModel: getCoreRowModel(),
getGroupedRowModel: getGroupedRowModel(),
state: {
grouping: ['region'],
},
});Type definitions for creating custom functions that match the built-in patterns.
/** Sorting function interface */
interface SortingFn<TData extends RowData> {
(rowA: Row<TData>, rowB: Row<TData>, columnId: string): number;
}
/** Filter function interface */
interface FilterFn<TData extends RowData> {
(
row: Row<TData>,
columnId: string,
filterValue: any,
addMeta?: (meta: FilterMeta) => void
): boolean;
autoRemove?: (filterValue: any, column?: Column<TData, unknown>) => boolean;
resolveFilterValue?: (filterValue: any) => any;
}
/** Aggregation function interface */
interface AggregationFn<TData extends RowData> {
(
columnId: string,
leafRows: Row<TData>[],
childRows: Row<TData>[]
): any;
}These built-in functions provide robust, tested implementations that handle edge cases like null values, type coercion, and performance optimization. They serve as both ready-to-use solutions and examples for creating custom functions.
Install with Tessl CLI
npx tessl i tessl/npm-tanstack--table-core