@tanstack/table-core
Version:
Headless UI for building powerful tables & datagrids for TS/JS.
1,252 lines (1,198 loc) • 139 kB
JavaScript
/**
* table-core
*
* Copyright (c) TanStack
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
// type Person = {
// firstName: string
// lastName: string
// age: number
// visits: number
// status: string
// progress: number
// createdAt: Date
// nested: {
// foo: [
// {
// bar: 'bar'
// }
// ]
// bar: { subBar: boolean }[]
// baz: {
// foo: 'foo'
// bar: {
// baz: 'baz'
// }
// }
// }
// }
// const test: DeepKeys<Person> = 'nested.foo.0.bar'
// const test2: DeepKeys<Person> = 'nested.bar'
// const helper = createColumnHelper<Person>()
// helper.accessor('nested.foo', {
// cell: info => info.getValue(),
// })
// helper.accessor('nested.foo.0.bar', {
// cell: info => info.getValue(),
// })
// helper.accessor('nested.bar', {
// cell: info => info.getValue(),
// })
function createColumnHelper() {
return {
accessor: (accessor, column) => {
return typeof accessor === 'function' ? {
...column,
accessorFn: accessor
} : {
...column,
accessorKey: accessor
};
},
display: column => column,
group: column => column
};
}
// Is this type a tuple?
// If this type is a tuple, what indices are allowed?
///
function functionalUpdate(updater, input) {
return typeof updater === 'function' ? updater(input) : updater;
}
function noop() {
//
}
function makeStateUpdater(key, instance) {
return updater => {
instance.setState(old => {
return {
...old,
[key]: functionalUpdate(updater, old[key])
};
});
};
}
function isFunction(d) {
return d instanceof Function;
}
function isNumberArray(d) {
return Array.isArray(d) && d.every(val => typeof val === 'number');
}
function flattenBy(arr, getChildren) {
const flat = [];
const recurse = subArr => {
subArr.forEach(item => {
flat.push(item);
const children = getChildren(item);
if (children != null && children.length) {
recurse(children);
}
});
};
recurse(arr);
return flat;
}
function memo(getDeps, fn, opts) {
let deps = [];
let result;
return depArgs => {
let depTime;
if (opts.key && opts.debug) depTime = Date.now();
const newDeps = getDeps(depArgs);
const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
if (!depsChanged) {
return result;
}
deps = newDeps;
let resultTime;
if (opts.key && opts.debug) resultTime = Date.now();
result = fn(...newDeps);
opts == null || opts.onChange == null || opts.onChange(result);
if (opts.key && opts.debug) {
if (opts != null && opts.debug()) {
const depEndTime = Math.round((Date.now() - depTime) * 100) / 100;
const resultEndTime = Math.round((Date.now() - resultTime) * 100) / 100;
const resultFpsPercentage = resultEndTime / 16;
const pad = (str, num) => {
str = String(str);
while (str.length < num) {
str = ' ' + str;
}
return str;
};
console.info(`%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`, `
font-size: .6rem;
font-weight: bold;
color: hsl(${Math.max(0, Math.min(120 - 120 * resultFpsPercentage, 120))}deg 100% 31%);`, opts == null ? void 0 : opts.key);
}
}
return result;
};
}
function getMemoOptions(tableOptions, debugLevel, key, onChange) {
return {
debug: () => {
var _tableOptions$debugAl;
return (_tableOptions$debugAl = tableOptions == null ? void 0 : tableOptions.debugAll) != null ? _tableOptions$debugAl : tableOptions[debugLevel];
},
key: process.env.NODE_ENV === 'development' && key,
onChange
};
}
function createCell(table, row, column, columnId) {
const getRenderValue = () => {
var _cell$getValue;
return (_cell$getValue = cell.getValue()) != null ? _cell$getValue : table.options.renderFallbackValue;
};
const cell = {
id: `${row.id}_${column.id}`,
row,
column,
getValue: () => row.getValue(columnId),
renderValue: getRenderValue,
getContext: memo(() => [table, column, row, cell], (table, column, row, cell) => ({
table,
column,
row,
cell: cell,
getValue: cell.getValue,
renderValue: cell.renderValue
}), getMemoOptions(table.options, 'debugCells', 'cell.getContext'))
};
table._features.forEach(feature => {
feature.createCell == null || feature.createCell(cell, column, row, table);
}, {});
return cell;
}
function createColumn(table, columnDef, depth, parent) {
var _ref, _resolvedColumnDef$id;
const defaultColumn = table._getDefaultColumnDef();
const resolvedColumnDef = {
...defaultColumn,
...columnDef
};
const accessorKey = resolvedColumnDef.accessorKey;
let id = (_ref = (_resolvedColumnDef$id = resolvedColumnDef.id) != null ? _resolvedColumnDef$id : accessorKey ? typeof String.prototype.replaceAll === 'function' ? accessorKey.replaceAll('.', '_') : accessorKey.replace(/\./g, '_') : undefined) != null ? _ref : typeof resolvedColumnDef.header === 'string' ? resolvedColumnDef.header : undefined;
let accessorFn;
if (resolvedColumnDef.accessorFn) {
accessorFn = resolvedColumnDef.accessorFn;
} else if (accessorKey) {
// Support deep accessor keys
if (accessorKey.includes('.')) {
accessorFn = originalRow => {
let result = originalRow;
for (const key of accessorKey.split('.')) {
var _result;
result = (_result = result) == null ? void 0 : _result[key];
if (process.env.NODE_ENV !== 'production' && result === undefined) {
console.warn(`"${key}" in deeply nested key "${accessorKey}" returned undefined.`);
}
}
return result;
};
} else {
accessorFn = originalRow => originalRow[resolvedColumnDef.accessorKey];
}
}
if (!id) {
if (process.env.NODE_ENV !== 'production') {
throw new Error(resolvedColumnDef.accessorFn ? `Columns require an id when using an accessorFn` : `Columns require an id when using a non-string header`);
}
throw new Error();
}
let column = {
id: `${String(id)}`,
accessorFn,
parent: parent,
depth,
columnDef: resolvedColumnDef,
columns: [],
getFlatColumns: memo(() => [true], () => {
var _column$columns;
return [column, ...((_column$columns = column.columns) == null ? void 0 : _column$columns.flatMap(d => d.getFlatColumns()))];
}, getMemoOptions(table.options, 'debugColumns', 'column.getFlatColumns')),
getLeafColumns: memo(() => [table._getOrderColumnsFn()], orderColumns => {
var _column$columns2;
if ((_column$columns2 = column.columns) != null && _column$columns2.length) {
let leafColumns = column.columns.flatMap(column => column.getLeafColumns());
return orderColumns(leafColumns);
}
return [column];
}, getMemoOptions(table.options, 'debugColumns', 'column.getLeafColumns'))
};
for (const feature of table._features) {
feature.createColumn == null || feature.createColumn(column, table);
}
// Yes, we have to convert table to unknown, because we know more than the compiler here.
return column;
}
const debug = 'debugHeaders';
//
function createHeader(table, column, options) {
var _options$id;
const id = (_options$id = options.id) != null ? _options$id : column.id;
let header = {
id,
column,
index: options.index,
isPlaceholder: !!options.isPlaceholder,
placeholderId: options.placeholderId,
depth: options.depth,
subHeaders: [],
colSpan: 0,
rowSpan: 0,
headerGroup: null,
getLeafHeaders: () => {
const leafHeaders = [];
const recurseHeader = h => {
if (h.subHeaders && h.subHeaders.length) {
h.subHeaders.map(recurseHeader);
}
leafHeaders.push(h);
};
recurseHeader(header);
return leafHeaders;
},
getContext: () => ({
table,
header: header,
column
})
};
table._features.forEach(feature => {
feature.createHeader == null || feature.createHeader(header, table);
});
return header;
}
const Headers = {
createTable: table => {
// Header Groups
table.getHeaderGroups = memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allColumns, leafColumns, left, right) => {
var _left$map$filter, _right$map$filter;
const leftColumns = (_left$map$filter = left == null ? void 0 : left.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _left$map$filter : [];
const rightColumns = (_right$map$filter = right == null ? void 0 : right.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _right$map$filter : [];
const centerColumns = leafColumns.filter(column => !(left != null && left.includes(column.id)) && !(right != null && right.includes(column.id)));
const headerGroups = buildHeaderGroups(allColumns, [...leftColumns, ...centerColumns, ...rightColumns], table);
return headerGroups;
}, getMemoOptions(table.options, debug, 'getHeaderGroups'));
table.getCenterHeaderGroups = memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allColumns, leafColumns, left, right) => {
leafColumns = leafColumns.filter(column => !(left != null && left.includes(column.id)) && !(right != null && right.includes(column.id)));
return buildHeaderGroups(allColumns, leafColumns, table, 'center');
}, getMemoOptions(table.options, debug, 'getCenterHeaderGroups'));
table.getLeftHeaderGroups = memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.left], (allColumns, leafColumns, left) => {
var _left$map$filter2;
const orderedLeafColumns = (_left$map$filter2 = left == null ? void 0 : left.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _left$map$filter2 : [];
return buildHeaderGroups(allColumns, orderedLeafColumns, table, 'left');
}, getMemoOptions(table.options, debug, 'getLeftHeaderGroups'));
table.getRightHeaderGroups = memo(() => [table.getAllColumns(), table.getVisibleLeafColumns(), table.getState().columnPinning.right], (allColumns, leafColumns, right) => {
var _right$map$filter2;
const orderedLeafColumns = (_right$map$filter2 = right == null ? void 0 : right.map(columnId => leafColumns.find(d => d.id === columnId)).filter(Boolean)) != null ? _right$map$filter2 : [];
return buildHeaderGroups(allColumns, orderedLeafColumns, table, 'right');
}, getMemoOptions(table.options, debug, 'getRightHeaderGroups'));
// Footer Groups
table.getFooterGroups = memo(() => [table.getHeaderGroups()], headerGroups => {
return [...headerGroups].reverse();
}, getMemoOptions(table.options, debug, 'getFooterGroups'));
table.getLeftFooterGroups = memo(() => [table.getLeftHeaderGroups()], headerGroups => {
return [...headerGroups].reverse();
}, getMemoOptions(table.options, debug, 'getLeftFooterGroups'));
table.getCenterFooterGroups = memo(() => [table.getCenterHeaderGroups()], headerGroups => {
return [...headerGroups].reverse();
}, getMemoOptions(table.options, debug, 'getCenterFooterGroups'));
table.getRightFooterGroups = memo(() => [table.getRightHeaderGroups()], headerGroups => {
return [...headerGroups].reverse();
}, getMemoOptions(table.options, debug, 'getRightFooterGroups'));
// Flat Headers
table.getFlatHeaders = memo(() => [table.getHeaderGroups()], headerGroups => {
return headerGroups.map(headerGroup => {
return headerGroup.headers;
}).flat();
}, getMemoOptions(table.options, debug, 'getFlatHeaders'));
table.getLeftFlatHeaders = memo(() => [table.getLeftHeaderGroups()], left => {
return left.map(headerGroup => {
return headerGroup.headers;
}).flat();
}, getMemoOptions(table.options, debug, 'getLeftFlatHeaders'));
table.getCenterFlatHeaders = memo(() => [table.getCenterHeaderGroups()], left => {
return left.map(headerGroup => {
return headerGroup.headers;
}).flat();
}, getMemoOptions(table.options, debug, 'getCenterFlatHeaders'));
table.getRightFlatHeaders = memo(() => [table.getRightHeaderGroups()], left => {
return left.map(headerGroup => {
return headerGroup.headers;
}).flat();
}, getMemoOptions(table.options, debug, 'getRightFlatHeaders'));
// Leaf Headers
table.getCenterLeafHeaders = memo(() => [table.getCenterFlatHeaders()], flatHeaders => {
return flatHeaders.filter(header => {
var _header$subHeaders;
return !((_header$subHeaders = header.subHeaders) != null && _header$subHeaders.length);
});
}, getMemoOptions(table.options, debug, 'getCenterLeafHeaders'));
table.getLeftLeafHeaders = memo(() => [table.getLeftFlatHeaders()], flatHeaders => {
return flatHeaders.filter(header => {
var _header$subHeaders2;
return !((_header$subHeaders2 = header.subHeaders) != null && _header$subHeaders2.length);
});
}, getMemoOptions(table.options, debug, 'getLeftLeafHeaders'));
table.getRightLeafHeaders = memo(() => [table.getRightFlatHeaders()], flatHeaders => {
return flatHeaders.filter(header => {
var _header$subHeaders3;
return !((_header$subHeaders3 = header.subHeaders) != null && _header$subHeaders3.length);
});
}, getMemoOptions(table.options, debug, 'getRightLeafHeaders'));
table.getLeafHeaders = memo(() => [table.getLeftHeaderGroups(), table.getCenterHeaderGroups(), table.getRightHeaderGroups()], (left, center, right) => {
var _left$0$headers, _left$, _center$0$headers, _center$, _right$0$headers, _right$;
return [...((_left$0$headers = (_left$ = left[0]) == null ? void 0 : _left$.headers) != null ? _left$0$headers : []), ...((_center$0$headers = (_center$ = center[0]) == null ? void 0 : _center$.headers) != null ? _center$0$headers : []), ...((_right$0$headers = (_right$ = right[0]) == null ? void 0 : _right$.headers) != null ? _right$0$headers : [])].map(header => {
return header.getLeafHeaders();
}).flat();
}, getMemoOptions(table.options, debug, 'getLeafHeaders'));
}
};
function buildHeaderGroups(allColumns, columnsToGroup, table, headerFamily) {
var _headerGroups$0$heade, _headerGroups$;
// Find the max depth of the columns:
// build the leaf column row
// build each buffer row going up
// placeholder for non-existent level
// real column for existing level
let maxDepth = 0;
const findMaxDepth = function (columns, depth) {
if (depth === void 0) {
depth = 1;
}
maxDepth = Math.max(maxDepth, depth);
columns.filter(column => column.getIsVisible()).forEach(column => {
var _column$columns;
if ((_column$columns = column.columns) != null && _column$columns.length) {
findMaxDepth(column.columns, depth + 1);
}
}, 0);
};
findMaxDepth(allColumns);
let headerGroups = [];
const createHeaderGroup = (headersToGroup, depth) => {
// The header group we are creating
const headerGroup = {
depth,
id: [headerFamily, `${depth}`].filter(Boolean).join('_'),
headers: []
};
// The parent columns we're going to scan next
const pendingParentHeaders = [];
// Scan each column for parents
headersToGroup.forEach(headerToGroup => {
// What is the latest (last) parent column?
const latestPendingParentHeader = [...pendingParentHeaders].reverse()[0];
const isLeafHeader = headerToGroup.column.depth === headerGroup.depth;
let column;
let isPlaceholder = false;
if (isLeafHeader && headerToGroup.column.parent) {
// The parent header is new
column = headerToGroup.column.parent;
} else {
// The parent header is repeated
column = headerToGroup.column;
isPlaceholder = true;
}
if (latestPendingParentHeader && (latestPendingParentHeader == null ? void 0 : latestPendingParentHeader.column) === column) {
// This column is repeated. Add it as a sub header to the next batch
latestPendingParentHeader.subHeaders.push(headerToGroup);
} else {
// This is a new header. Let's create it
const header = createHeader(table, column, {
id: [headerFamily, depth, column.id, headerToGroup == null ? void 0 : headerToGroup.id].filter(Boolean).join('_'),
isPlaceholder,
placeholderId: isPlaceholder ? `${pendingParentHeaders.filter(d => d.column === column).length}` : undefined,
depth,
index: pendingParentHeaders.length
});
// Add the headerToGroup as a subHeader of the new header
header.subHeaders.push(headerToGroup);
// Add the new header to the pendingParentHeaders to get grouped
// in the next batch
pendingParentHeaders.push(header);
}
headerGroup.headers.push(headerToGroup);
headerToGroup.headerGroup = headerGroup;
});
headerGroups.push(headerGroup);
if (depth > 0) {
createHeaderGroup(pendingParentHeaders, depth - 1);
}
};
const bottomHeaders = columnsToGroup.map((column, index) => createHeader(table, column, {
depth: maxDepth,
index
}));
createHeaderGroup(bottomHeaders, maxDepth - 1);
headerGroups.reverse();
// headerGroups = headerGroups.filter(headerGroup => {
// return !headerGroup.headers.every(header => header.isPlaceholder)
// })
const recurseHeadersForSpans = headers => {
const filteredHeaders = headers.filter(header => header.column.getIsVisible());
return filteredHeaders.map(header => {
let colSpan = 0;
let rowSpan = 0;
let childRowSpans = [0];
if (header.subHeaders && header.subHeaders.length) {
childRowSpans = [];
recurseHeadersForSpans(header.subHeaders).forEach(_ref => {
let {
colSpan: childColSpan,
rowSpan: childRowSpan
} = _ref;
colSpan += childColSpan;
childRowSpans.push(childRowSpan);
});
} else {
colSpan = 1;
}
const minChildRowSpan = Math.min(...childRowSpans);
rowSpan = rowSpan + minChildRowSpan;
header.colSpan = colSpan;
header.rowSpan = rowSpan;
return {
colSpan,
rowSpan
};
});
};
recurseHeadersForSpans((_headerGroups$0$heade = (_headerGroups$ = headerGroups[0]) == null ? void 0 : _headerGroups$.headers) != null ? _headerGroups$0$heade : []);
return headerGroups;
}
const createRow = (table, id, original, rowIndex, depth, subRows, parentId) => {
let row = {
id,
index: rowIndex,
original,
depth,
parentId,
_valuesCache: {},
_uniqueValuesCache: {},
getValue: columnId => {
if (row._valuesCache.hasOwnProperty(columnId)) {
return row._valuesCache[columnId];
}
const column = table.getColumn(columnId);
if (!(column != null && column.accessorFn)) {
return undefined;
}
row._valuesCache[columnId] = column.accessorFn(row.original, rowIndex);
return row._valuesCache[columnId];
},
getUniqueValues: columnId => {
if (row._uniqueValuesCache.hasOwnProperty(columnId)) {
return row._uniqueValuesCache[columnId];
}
const column = table.getColumn(columnId);
if (!(column != null && column.accessorFn)) {
return undefined;
}
if (!column.columnDef.getUniqueValues) {
row._uniqueValuesCache[columnId] = [row.getValue(columnId)];
return row._uniqueValuesCache[columnId];
}
row._uniqueValuesCache[columnId] = column.columnDef.getUniqueValues(row.original, rowIndex);
return row._uniqueValuesCache[columnId];
},
renderValue: columnId => {
var _row$getValue;
return (_row$getValue = row.getValue(columnId)) != null ? _row$getValue : table.options.renderFallbackValue;
},
subRows: subRows != null ? subRows : [],
getLeafRows: () => flattenBy(row.subRows, d => d.subRows),
getParentRow: () => row.parentId ? table.getRow(row.parentId, true) : undefined,
getParentRows: () => {
let parentRows = [];
let currentRow = row;
while (true) {
const parentRow = currentRow.getParentRow();
if (!parentRow) break;
parentRows.push(parentRow);
currentRow = parentRow;
}
return parentRows.reverse();
},
getAllCells: memo(() => [table.getAllLeafColumns()], leafColumns => {
return leafColumns.map(column => {
return createCell(table, row, column, column.id);
});
}, getMemoOptions(table.options, 'debugRows', 'getAllCells')),
_getAllCellsByColumnId: memo(() => [row.getAllCells()], allCells => {
return allCells.reduce((acc, cell) => {
acc[cell.column.id] = cell;
return acc;
}, {});
}, getMemoOptions(table.options, 'debugRows', 'getAllCellsByColumnId'))
};
for (let i = 0; i < table._features.length; i++) {
const feature = table._features[i];
feature == null || feature.createRow == null || feature.createRow(row, table);
}
return row;
};
//
const ColumnFaceting = {
createColumn: (column, table) => {
column._getFacetedRowModel = table.options.getFacetedRowModel && table.options.getFacetedRowModel(table, column.id);
column.getFacetedRowModel = () => {
if (!column._getFacetedRowModel) {
return table.getPreFilteredRowModel();
}
return column._getFacetedRowModel();
};
column._getFacetedUniqueValues = table.options.getFacetedUniqueValues && table.options.getFacetedUniqueValues(table, column.id);
column.getFacetedUniqueValues = () => {
if (!column._getFacetedUniqueValues) {
return new Map();
}
return column._getFacetedUniqueValues();
};
column._getFacetedMinMaxValues = table.options.getFacetedMinMaxValues && table.options.getFacetedMinMaxValues(table, column.id);
column.getFacetedMinMaxValues = () => {
if (!column._getFacetedMinMaxValues) {
return undefined;
}
return column._getFacetedMinMaxValues();
};
}
};
const includesString = (row, columnId, filterValue) => {
var _filterValue$toString, _row$getValue;
const search = filterValue == null || (_filterValue$toString = filterValue.toString()) == null ? void 0 : _filterValue$toString.toLowerCase();
return Boolean((_row$getValue = row.getValue(columnId)) == null || (_row$getValue = _row$getValue.toString()) == null || (_row$getValue = _row$getValue.toLowerCase()) == null ? void 0 : _row$getValue.includes(search));
};
includesString.autoRemove = val => testFalsey(val);
const includesStringSensitive = (row, columnId, filterValue) => {
var _row$getValue2;
return Boolean((_row$getValue2 = row.getValue(columnId)) == null || (_row$getValue2 = _row$getValue2.toString()) == null ? void 0 : _row$getValue2.includes(filterValue));
};
includesStringSensitive.autoRemove = val => testFalsey(val);
const equalsString = (row, columnId, filterValue) => {
var _row$getValue3;
return ((_row$getValue3 = row.getValue(columnId)) == null || (_row$getValue3 = _row$getValue3.toString()) == null ? void 0 : _row$getValue3.toLowerCase()) === (filterValue == null ? void 0 : filterValue.toLowerCase());
};
equalsString.autoRemove = val => testFalsey(val);
const arrIncludes = (row, columnId, filterValue) => {
var _row$getValue4;
return (_row$getValue4 = row.getValue(columnId)) == null ? void 0 : _row$getValue4.includes(filterValue);
};
arrIncludes.autoRemove = val => testFalsey(val) || !(val != null && val.length);
const arrIncludesAll = (row, columnId, filterValue) => {
return !filterValue.some(val => {
var _row$getValue5;
return !((_row$getValue5 = row.getValue(columnId)) != null && _row$getValue5.includes(val));
});
};
arrIncludesAll.autoRemove = val => testFalsey(val) || !(val != null && val.length);
const arrIncludesSome = (row, columnId, filterValue) => {
return filterValue.some(val => {
var _row$getValue6;
return (_row$getValue6 = row.getValue(columnId)) == null ? void 0 : _row$getValue6.includes(val);
});
};
arrIncludesSome.autoRemove = val => testFalsey(val) || !(val != null && val.length);
const equals = (row, columnId, filterValue) => {
return row.getValue(columnId) === filterValue;
};
equals.autoRemove = val => testFalsey(val);
const weakEquals = (row, columnId, filterValue) => {
return row.getValue(columnId) == filterValue;
};
weakEquals.autoRemove = val => testFalsey(val);
const inNumberRange = (row, columnId, filterValue) => {
let [min, max] = filterValue;
const rowValue = row.getValue(columnId);
return rowValue >= min && rowValue <= max;
};
inNumberRange.resolveFilterValue = val => {
let [unsafeMin, unsafeMax] = val;
let parsedMin = typeof unsafeMin !== 'number' ? parseFloat(unsafeMin) : unsafeMin;
let parsedMax = typeof unsafeMax !== 'number' ? parseFloat(unsafeMax) : unsafeMax;
let min = unsafeMin === null || Number.isNaN(parsedMin) ? -Infinity : parsedMin;
let max = unsafeMax === null || Number.isNaN(parsedMax) ? Infinity : parsedMax;
if (min > max) {
const temp = min;
min = max;
max = temp;
}
return [min, max];
};
inNumberRange.autoRemove = val => testFalsey(val) || testFalsey(val[0]) && testFalsey(val[1]);
// Export
const filterFns = {
includesString,
includesStringSensitive,
equalsString,
arrIncludes,
arrIncludesAll,
arrIncludesSome,
equals,
weakEquals,
inNumberRange
};
// Utils
function testFalsey(val) {
return val === undefined || val === null || val === '';
}
//
const ColumnFiltering = {
getDefaultColumnDef: () => {
return {
filterFn: 'auto'
};
},
getInitialState: state => {
return {
columnFilters: [],
...state
};
},
getDefaultOptions: table => {
return {
onColumnFiltersChange: makeStateUpdater('columnFilters', table),
filterFromLeafRows: false,
maxLeafRowFilterDepth: 100
};
},
createColumn: (column, table) => {
column.getAutoFilterFn = () => {
const firstRow = table.getCoreRowModel().flatRows[0];
const value = firstRow == null ? void 0 : firstRow.getValue(column.id);
if (typeof value === 'string') {
return filterFns.includesString;
}
if (typeof value === 'number') {
return filterFns.inNumberRange;
}
if (typeof value === 'boolean') {
return filterFns.equals;
}
if (value !== null && typeof value === 'object') {
return filterFns.equals;
}
if (Array.isArray(value)) {
return filterFns.arrIncludes;
}
return filterFns.weakEquals;
};
column.getFilterFn = () => {
var _table$options$filter, _table$options$filter2;
return isFunction(column.columnDef.filterFn) ? column.columnDef.filterFn : column.columnDef.filterFn === 'auto' ? column.getAutoFilterFn() : // @ts-ignore
(_table$options$filter = (_table$options$filter2 = table.options.filterFns) == null ? void 0 : _table$options$filter2[column.columnDef.filterFn]) != null ? _table$options$filter : filterFns[column.columnDef.filterFn];
};
column.getCanFilter = () => {
var _column$columnDef$ena, _table$options$enable, _table$options$enable2;
return ((_column$columnDef$ena = column.columnDef.enableColumnFilter) != null ? _column$columnDef$ena : true) && ((_table$options$enable = table.options.enableColumnFilters) != null ? _table$options$enable : true) && ((_table$options$enable2 = table.options.enableFilters) != null ? _table$options$enable2 : true) && !!column.accessorFn;
};
column.getIsFiltered = () => column.getFilterIndex() > -1;
column.getFilterValue = () => {
var _table$getState$colum;
return (_table$getState$colum = table.getState().columnFilters) == null || (_table$getState$colum = _table$getState$colum.find(d => d.id === column.id)) == null ? void 0 : _table$getState$colum.value;
};
column.getFilterIndex = () => {
var _table$getState$colum2, _table$getState$colum3;
return (_table$getState$colum2 = (_table$getState$colum3 = table.getState().columnFilters) == null ? void 0 : _table$getState$colum3.findIndex(d => d.id === column.id)) != null ? _table$getState$colum2 : -1;
};
column.setFilterValue = value => {
table.setColumnFilters(old => {
const filterFn = column.getFilterFn();
const previousFilter = old == null ? void 0 : old.find(d => d.id === column.id);
const newFilter = functionalUpdate(value, previousFilter ? previousFilter.value : undefined);
//
if (shouldAutoRemoveFilter(filterFn, newFilter, column)) {
var _old$filter;
return (_old$filter = old == null ? void 0 : old.filter(d => d.id !== column.id)) != null ? _old$filter : [];
}
const newFilterObj = {
id: column.id,
value: newFilter
};
if (previousFilter) {
var _old$map;
return (_old$map = old == null ? void 0 : old.map(d => {
if (d.id === column.id) {
return newFilterObj;
}
return d;
})) != null ? _old$map : [];
}
if (old != null && old.length) {
return [...old, newFilterObj];
}
return [newFilterObj];
});
};
},
createRow: (row, _table) => {
row.columnFilters = {};
row.columnFiltersMeta = {};
},
createTable: table => {
table.setColumnFilters = updater => {
const leafColumns = table.getAllLeafColumns();
const updateFn = old => {
var _functionalUpdate;
return (_functionalUpdate = functionalUpdate(updater, old)) == null ? void 0 : _functionalUpdate.filter(filter => {
const column = leafColumns.find(d => d.id === filter.id);
if (column) {
const filterFn = column.getFilterFn();
if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {
return false;
}
}
return true;
});
};
table.options.onColumnFiltersChange == null || table.options.onColumnFiltersChange(updateFn);
};
table.resetColumnFilters = defaultState => {
var _table$initialState$c, _table$initialState;
table.setColumnFilters(defaultState ? [] : (_table$initialState$c = (_table$initialState = table.initialState) == null ? void 0 : _table$initialState.columnFilters) != null ? _table$initialState$c : []);
};
table.getPreFilteredRowModel = () => table.getCoreRowModel();
table.getFilteredRowModel = () => {
if (!table._getFilteredRowModel && table.options.getFilteredRowModel) {
table._getFilteredRowModel = table.options.getFilteredRowModel(table);
}
if (table.options.manualFiltering || !table._getFilteredRowModel) {
return table.getPreFilteredRowModel();
}
return table._getFilteredRowModel();
};
}
};
function shouldAutoRemoveFilter(filterFn, value, column) {
return (filterFn && filterFn.autoRemove ? filterFn.autoRemove(value, column) : false) || typeof value === 'undefined' || typeof value === 'string' && !value;
}
const sum = (columnId, _leafRows, childRows) => {
// It's faster to just add the aggregations together instead of
// process leaf nodes individually
return childRows.reduce((sum, next) => {
const nextValue = next.getValue(columnId);
return sum + (typeof nextValue === 'number' ? nextValue : 0);
}, 0);
};
const min = (columnId, _leafRows, childRows) => {
let min;
childRows.forEach(row => {
const value = row.getValue(columnId);
if (value != null && (min > value || min === undefined && value >= value)) {
min = value;
}
});
return min;
};
const max = (columnId, _leafRows, childRows) => {
let max;
childRows.forEach(row => {
const value = row.getValue(columnId);
if (value != null && (max < value || max === undefined && value >= value)) {
max = value;
}
});
return max;
};
const extent = (columnId, _leafRows, childRows) => {
let min;
let max;
childRows.forEach(row => {
const value = row.getValue(columnId);
if (value != null) {
if (min === undefined) {
if (value >= value) min = max = value;
} else {
if (min > value) min = value;
if (max < value) max = value;
}
}
});
return [min, max];
};
const mean = (columnId, leafRows) => {
let count = 0;
let sum = 0;
leafRows.forEach(row => {
let value = row.getValue(columnId);
if (value != null && (value = +value) >= value) {
++count, sum += value;
}
});
if (count) return sum / count;
return;
};
const median = (columnId, leafRows) => {
if (!leafRows.length) {
return;
}
const values = leafRows.map(row => row.getValue(columnId));
if (!isNumberArray(values)) {
return;
}
if (values.length === 1) {
return values[0];
}
const mid = Math.floor(values.length / 2);
const nums = values.sort((a, b) => a - b);
return values.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
};
const unique = (columnId, leafRows) => {
return Array.from(new Set(leafRows.map(d => d.getValue(columnId))).values());
};
const uniqueCount = (columnId, leafRows) => {
return new Set(leafRows.map(d => d.getValue(columnId))).size;
};
const count = (_columnId, leafRows) => {
return leafRows.length;
};
const aggregationFns = {
sum,
min,
max,
extent,
mean,
median,
unique,
uniqueCount,
count
};
//
const ColumnGrouping = {
getDefaultColumnDef: () => {
return {
aggregatedCell: props => {
var _toString, _props$getValue;
return (_toString = (_props$getValue = props.getValue()) == null || _props$getValue.toString == null ? void 0 : _props$getValue.toString()) != null ? _toString : null;
},
aggregationFn: 'auto'
};
},
getInitialState: state => {
return {
grouping: [],
...state
};
},
getDefaultOptions: table => {
return {
onGroupingChange: makeStateUpdater('grouping', table),
groupedColumnMode: 'reorder'
};
},
createColumn: (column, table) => {
column.toggleGrouping = () => {
table.setGrouping(old => {
// Find any existing grouping for this column
if (old != null && old.includes(column.id)) {
return old.filter(d => d !== column.id);
}
return [...(old != null ? old : []), column.id];
});
};
column.getCanGroup = () => {
var _column$columnDef$ena, _table$options$enable;
return ((_column$columnDef$ena = column.columnDef.enableGrouping) != null ? _column$columnDef$ena : true) && ((_table$options$enable = table.options.enableGrouping) != null ? _table$options$enable : true) && (!!column.accessorFn || !!column.columnDef.getGroupingValue);
};
column.getIsGrouped = () => {
var _table$getState$group;
return (_table$getState$group = table.getState().grouping) == null ? void 0 : _table$getState$group.includes(column.id);
};
column.getGroupedIndex = () => {
var _table$getState$group2;
return (_table$getState$group2 = table.getState().grouping) == null ? void 0 : _table$getState$group2.indexOf(column.id);
};
column.getToggleGroupingHandler = () => {
const canGroup = column.getCanGroup();
return () => {
if (!canGroup) return;
column.toggleGrouping();
};
};
column.getAutoAggregationFn = () => {
const firstRow = table.getCoreRowModel().flatRows[0];
const value = firstRow == null ? void 0 : firstRow.getValue(column.id);
if (typeof value === 'number') {
return aggregationFns.sum;
}
if (Object.prototype.toString.call(value) === '[object Date]') {
return aggregationFns.extent;
}
};
column.getAggregationFn = () => {
var _table$options$aggreg, _table$options$aggreg2;
if (!column) {
throw new Error();
}
return isFunction(column.columnDef.aggregationFn) ? column.columnDef.aggregationFn : column.columnDef.aggregationFn === 'auto' ? column.getAutoAggregationFn() : (_table$options$aggreg = (_table$options$aggreg2 = table.options.aggregationFns) == null ? void 0 : _table$options$aggreg2[column.columnDef.aggregationFn]) != null ? _table$options$aggreg : aggregationFns[column.columnDef.aggregationFn];
};
},
createTable: table => {
table.setGrouping = updater => table.options.onGroupingChange == null ? void 0 : table.options.onGroupingChange(updater);
table.resetGrouping = defaultState => {
var _table$initialState$g, _table$initialState;
table.setGrouping(defaultState ? [] : (_table$initialState$g = (_table$initialState = table.initialState) == null ? void 0 : _table$initialState.grouping) != null ? _table$initialState$g : []);
};
table.getPreGroupedRowModel = () => table.getFilteredRowModel();
table.getGroupedRowModel = () => {
if (!table._getGroupedRowModel && table.options.getGroupedRowModel) {
table._getGroupedRowModel = table.options.getGroupedRowModel(table);
}
if (table.options.manualGrouping || !table._getGroupedRowModel) {
return table.getPreGroupedRowModel();
}
return table._getGroupedRowModel();
};
},
createRow: (row, table) => {
row.getIsGrouped = () => !!row.groupingColumnId;
row.getGroupingValue = columnId => {
if (row._groupingValuesCache.hasOwnProperty(columnId)) {
return row._groupingValuesCache[columnId];
}
const column = table.getColumn(columnId);
if (!(column != null && column.columnDef.getGroupingValue)) {
return row.getValue(columnId);
}
row._groupingValuesCache[columnId] = column.columnDef.getGroupingValue(row.original);
return row._groupingValuesCache[columnId];
};
row._groupingValuesCache = {};
},
createCell: (cell, column, row, table) => {
cell.getIsGrouped = () => column.getIsGrouped() && column.id === row.groupingColumnId;
cell.getIsPlaceholder = () => !cell.getIsGrouped() && column.getIsGrouped();
cell.getIsAggregated = () => {
var _row$subRows;
return !cell.getIsGrouped() && !cell.getIsPlaceholder() && !!((_row$subRows = row.subRows) != null && _row$subRows.length);
};
}
};
function orderColumns(leafColumns, grouping, groupedColumnMode) {
if (!(grouping != null && grouping.length) || !groupedColumnMode) {
return leafColumns;
}
const nonGroupingColumns = leafColumns.filter(col => !grouping.includes(col.id));
if (groupedColumnMode === 'remove') {
return nonGroupingColumns;
}
const groupingColumns = grouping.map(g => leafColumns.find(col => col.id === g)).filter(Boolean);
return [...groupingColumns, ...nonGroupingColumns];
}
//
const ColumnOrdering = {
getInitialState: state => {
return {
columnOrder: [],
...state
};
},
getDefaultOptions: table => {
return {
onColumnOrderChange: makeStateUpdater('columnOrder', table)
};
},
createColumn: (column, table) => {
column.getIndex = memo(position => [_getVisibleLeafColumns(table, position)], columns => columns.findIndex(d => d.id === column.id), getMemoOptions(table.options, 'debugColumns', 'getIndex'));
column.getIsFirstColumn = position => {
var _columns$;
const columns = _getVisibleLeafColumns(table, position);
return ((_columns$ = columns[0]) == null ? void 0 : _columns$.id) === column.id;
};
column.getIsLastColumn = position => {
var _columns;
const columns = _getVisibleLeafColumns(table, position);
return ((_columns = columns[columns.length - 1]) == null ? void 0 : _columns.id) === column.id;
};
},
createTable: table => {
table.setColumnOrder = updater => table.options.onColumnOrderChange == null ? void 0 : table.options.onColumnOrderChange(updater);
table.resetColumnOrder = defaultState => {
var _table$initialState$c;
table.setColumnOrder(defaultState ? [] : (_table$initialState$c = table.initialState.columnOrder) != null ? _table$initialState$c : []);
};
table._getOrderColumnsFn = memo(() => [table.getState().columnOrder, table.getState().grouping, table.options.groupedColumnMode], (columnOrder, grouping, groupedColumnMode) => columns => {
// Sort grouped columns to the start of the column list
// before the headers are built
let orderedColumns = [];
// If there is no order, return the normal columns
if (!(columnOrder != null && columnOrder.length)) {
orderedColumns = columns;
} else {
const columnOrderCopy = [...columnOrder];
// If there is an order, make a copy of the columns
const columnsCopy = [...columns];
// And make a new ordered array of the columns
// Loop over the columns and place them in order into the new array
while (columnsCopy.length && columnOrderCopy.length) {
const targetColumnId = columnOrderCopy.shift();
const foundIndex = columnsCopy.findIndex(d => d.id === targetColumnId);
if (foundIndex > -1) {
orderedColumns.push(columnsCopy.splice(foundIndex, 1)[0]);
}
}
// If there are any columns left, add them to the end
orderedColumns = [...orderedColumns, ...columnsCopy];
}
return orderColumns(orderedColumns, grouping, groupedColumnMode);
}, getMemoOptions(table.options, 'debugTable', '_getOrderColumnsFn'));
}
};
//
const getDefaultColumnPinningState = () => ({
left: [],
right: []
});
const ColumnPinning = {
getInitialState: state => {
return {
columnPinning: getDefaultColumnPinningState(),
...state
};
},
getDefaultOptions: table => {
return {
onColumnPinningChange: makeStateUpdater('columnPinning', table)
};
},
createColumn: (column, table) => {
column.pin = position => {
const columnIds = column.getLeafColumns().map(d => d.id).filter(Boolean);
table.setColumnPinning(old => {
var _old$left3, _old$right3;
if (position === 'right') {
var _old$left, _old$right;
return {
left: ((_old$left = old == null ? void 0 : old.left) != null ? _old$left : []).filter(d => !(columnIds != null && columnIds.includes(d))),
right: [...((_old$right = old == null ? void 0 : old.right) != null ? _old$right : []).filter(d => !(columnIds != null && columnIds.includes(d))), ...columnIds]
};
}
if (position === 'left') {
var _old$left2, _old$right2;
return {
left: [...((_old$left2 = old == null ? void 0 : old.left) != null ? _old$left2 : []).filter(d => !(columnIds != null && columnIds.includes(d))), ...columnIds],
right: ((_old$right2 = old == null ? void 0 : old.right) != null ? _old$right2 : []).filter(d => !(columnIds != null && columnIds.includes(d)))
};
}
return {
left: ((_old$left3 = old == null ? void 0 : old.left) != null ? _old$left3 : []).filter(d => !(columnIds != null && columnIds.includes(d))),
right: ((_old$right3 = old == null ? void 0 : old.right) != null ? _old$right3 : []).filter(d => !(columnIds != null && columnIds.includes(d)))
};
});
};
column.getCanPin = () => {
const leafColumns = column.getLeafColumns();
return leafColumns.some(d => {
var _d$columnDef$enablePi, _ref, _table$options$enable;
return ((_d$columnDef$enablePi = d.columnDef.enablePinning) != null ? _d$columnDef$enablePi : true) && ((_ref = (_table$options$enable = table.options.enableColumnPinning) != null ? _table$options$enable : table.options.enablePinning) != null ? _ref : true);
});
};
column.getIsPinned = () => {
const leafColumnIds = column.getLeafColumns().map(d => d.id);
const {
left,
right
} = table.getState().columnPinning;
const isLeft = leafColumnIds.some(d => left == null ? void 0 : left.includes(d));
const isRight = leafColumnIds.some(d => right == null ? void 0 : right.includes(d));
return isLeft ? 'left' : isRight ? 'right' : false;
};
column.getPinnedIndex = () => {
var _table$getState$colum, _table$getState$colum2;
const position = column.getIsPinned();
return position ? (_table$getState$colum = (_table$getState$colum2 = table.getState().columnPinning) == null || (_table$getState$colum2 = _table$getState$colum2[position]) == null ? void 0 : _table$getState$colum2.indexOf(column.id)) != null ? _table$getState$colum : -1 : 0;
};
},
createRow: (row, table) => {
row.getCenterVisibleCells = memo(() => [row._getAllVisibleCells(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allCells, left, right) => {
const leftAndRight = [...(left != null ? left : []), ...(right != null ? right : [])];
return allCells.filter(d => !leftAndRight.includes(d.column.id));
}, getMemoOptions(table.options, 'debugRows', 'getCenterVisibleCells'));
row.getLeftVisibleCells = memo(() => [row._getAllVisibleCells(), table.getState().columnPinning.left], (allCells, left) => {
const cells = (left != null ? left : []).map(columnId => allCells.find(cell => cell.column.id === columnId)).filter(Boolean).map(d => ({
...d,
position: 'left'
}));
return cells;
}, getMemoOptions(table.options, 'debugRows', 'getLeftVisibleCells'));
row.getRightVisibleCells = memo(() => [row._getAllVisibleCells(), table.getState().columnPinning.right], (allCells, right) => {
const cells = (right != null ? right : []).map(columnId => allCells.find(cell => cell.column.id === columnId)).filter(Boolean).map(d => ({
...d,
position: 'right'
}));
return cells;
}, getMemoOptions(table.options, 'debugRows', 'getRightVisibleCells'));
},
createTable: table => {
table.setColumnPinning = updater => table.options.onColumnPinningChange == null ? void 0 : table.options.onColumnPinningChange(updater);
table.resetColumnPinning = defaultState => {
var _table$initialState$c, _table$initialState;
return table.setColumnPinning(defaultState ? getDefaultColumnPinningState() : (_table$initialState$c = (_table$initialState = table.initialState) == null ? void 0 : _table$initialState.columnPinning) != null ? _table$initialState$c : getDefaultColumnPinningState());
};
table.getIsSomeColumnsPinned = position => {
var _pinningState$positio;
const pinningState = table.getState().columnPinning;
if (!position) {
var _pinningState$left, _pinningState$right;
return Boolean(((_pinningState$left = pinningState.left) == null ? void 0 : _pinningState$left.length) || ((_pinningState$right = pinningState.right) == null ? void 0 : _pinningState$right.length));
}
return Boolean((_pinningState$positio = pinningState[position]) == null ? void 0 : _pinningState$positio.length);
};
table.getLeftLeafColumns = memo(() => [table.getAllLeafColumns(), table.getState().columnPinning.left], (allColumns, left) => {
return (left != null ? left : []).map(columnId => allColumns.find(column => column.id === columnId)).filter(Boolean);
}, getMemoOptions(table.options, 'debugColumns', 'getLeftLeafColumns'));
table.getRightLeafColumns = memo(() => [table.getAllLeafColumns(), table.getState().columnPinning.right], (allColumns, right) => {
return (right != null ? right : []).map(columnId => allColumns.find(column => column.id === columnId)).filter(Boolean);
}, getMemoOptions(table.options, 'debugColumns', 'getRightLeafColumns'));
table.getCenterLeafColumns = memo(() => [table.getAllLeafColumns(), table.getState().columnPinning.left, table.getState().columnPinning.right], (allColumns, left, right) => {
const leftAndRight = [...(left != null ? left : []), ...(right != null ? right : [])];
return allColumns.filter(d => !leftAndRight.includes(d.id));
}, getMemoOptions(table.options, 'debugColumns', 'getCenterLeafColumns'));
}
};
//
//
const defaultColumnSizing = {
size: 150,
minSize: 20,
maxSize: Number.MAX_SAFE_INTEGER
};
const getDefaultColumnSizingInfoState = () => ({
startOffset: null,
startSize: null,
deltaOffset: null,
deltaPercentage: null,
isResizingColumn: false,
columnSizingStart: []
});
const ColumnSizing = {
getDefaultColumnDef: () => {
return defaultColumnSizing;
},
getInitialState: state => {
return {
columnSizing: {},
columnSizingInfo: getDefaultColumnSizingInfoState(),
...state
};
},
getDefaultOptions: table => {
return {
columnResizeMode: 'onEnd',
columnResizeDirection: 'ltr',
onColumnSizingChange: makeStateUpdater('columnSizing', table),
onColumnSizingInfoChange: makeStateUpdater('columnSizingInfo', table)
};
},
createColumn: (column, table) => {
column.getSize = () => {
var _column$columnDef$min, _ref, _column$columnDef$max;
const columnSize = table.getState().columnSizing[column.id];
return Math.min(Math.max((_column$columnDef$min = column.columnDef.minSize) != null ? _column$columnDef$min : defaultColumnSizing.minSize, (_ref = columnSize != null ? columnSize : column.columnDef.size) != null ? _ref : defaultColumnSizing.size), (_column$columnDef$max