@ackplus/react-tanstack-data-table
Version:
A powerful React data table component built with MUI and TanStack Table
617 lines (616 loc) • 27.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useDataTableApi = useDataTableApi;
const tslib_1 = require("tslib");
const react_1 = require("react");
const export_utils_1 = require("../utils/export-utils");
function useDataTableApi(props, ref) {
const { table, data, idKey, globalFilter, customColumnsFilter, sorting, pagination, columnOrder, columnPinning, enhancedColumns, enablePagination, enableColumnPinning, initialPageIndex, initialPageSize, pageSize, selectMode = 'page', onSelectionChange, handleColumnFilterStateChange, onDataStateChange, onFetchData, onDataChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, exportController, setExportController, isExporting, dataMode = 'client', } = props;
(0, react_1.useImperativeHandle)(ref, () => ({
table: {
getTable: () => table,
},
columnVisibility: {
showColumn: (columnId) => {
var _a;
(_a = table.getColumn(columnId)) === null || _a === void 0 ? void 0 : _a.toggleVisibility(true);
},
hideColumn: (columnId) => {
var _a;
(_a = table.getColumn(columnId)) === null || _a === void 0 ? void 0 : _a.toggleVisibility(false);
},
toggleColumn: (columnId) => {
var _a;
(_a = table.getColumn(columnId)) === null || _a === void 0 ? void 0 : _a.toggleVisibility();
},
showAllColumns: () => {
table.toggleAllColumnsVisible(true);
},
hideAllColumns: () => {
table.toggleAllColumnsVisible(false);
},
resetColumnVisibility: () => {
table.resetColumnVisibility();
},
},
columnOrdering: {
setColumnOrder: (columnOrder) => {
table.setColumnOrder(columnOrder);
},
moveColumn: (columnId, toIndex) => {
const currentOrder = table.getState().columnOrder || [];
const currentIndex = currentOrder.indexOf(columnId);
if (currentIndex === -1)
return;
const newOrder = [...currentOrder];
newOrder.splice(currentIndex, 1);
newOrder.splice(toIndex, 0, columnId);
table.setColumnOrder(newOrder);
},
resetColumnOrder: () => {
const initialOrder = enhancedColumns.map((col, index) => {
if (col.id)
return col.id;
const anyCol = col;
if (anyCol.accessorKey && typeof anyCol.accessorKey === 'string') {
return anyCol.accessorKey;
}
return `column_${index}`;
});
table.setColumnOrder(initialOrder);
},
},
columnPinning: {
pinColumnLeft: (columnId) => {
const currentPinning = table.getState().columnPinning;
const newPinning = Object.assign({}, currentPinning);
newPinning.right = (newPinning.right || []).filter(id => id !== columnId);
newPinning.left = [...(newPinning.left || []).filter(id => id !== columnId), columnId];
table.setColumnPinning(newPinning);
},
pinColumnRight: (columnId) => {
const currentPinning = table.getState().columnPinning;
const newPinning = Object.assign({}, currentPinning);
newPinning.left = (newPinning.left || []).filter(id => id !== columnId);
newPinning.right = [...(newPinning.right || []).filter(id => id !== columnId), columnId];
table.setColumnPinning(newPinning);
},
unpinColumn: (columnId) => {
const currentPinning = table.getState().columnPinning;
const newPinning = {
left: (currentPinning.left || []).filter(id => id !== columnId),
right: (currentPinning.right || []).filter(id => id !== columnId),
};
table.setColumnPinning(newPinning);
},
setPinning: (pinning) => {
table.setColumnPinning(pinning);
},
resetColumnPinning: () => {
table.setColumnPinning(table.initialState.columnPinning);
},
},
columnResizing: {
resizeColumn: (columnId, width) => {
const currentSizing = table.getState().columnSizing;
table.setColumnSizing(Object.assign(Object.assign({}, currentSizing), { [columnId]: width }));
},
autoSizeColumn: (columnId) => {
var _a;
(_a = table.getColumn(columnId)) === null || _a === void 0 ? void 0 : _a.resetSize();
},
autoSizeAllColumns: () => {
table.resetColumnSizing();
},
resetColumnSizing: () => {
table.resetColumnSizing();
},
},
filtering: {
setGlobalFilter: (filter) => {
table.setGlobalFilter(filter);
},
clearGlobalFilter: () => {
table.setGlobalFilter('');
},
setCustomColumnFilters: (filters) => {
handleColumnFilterStateChange(filters);
},
addColumnFilter: (columnId, operator, value) => {
const newFilter = {
id: `filter_${Date.now()}`,
columnId,
operator,
value,
};
const currentFilters = customColumnsFilter.filters || [];
const newFilters = [...currentFilters, newFilter];
handleColumnFilterStateChange({
filters: newFilters,
logic: customColumnsFilter.logic,
pendingFilters: customColumnsFilter.pendingFilters || [],
pendingLogic: customColumnsFilter.pendingLogic || 'AND',
});
},
removeColumnFilter: (filterId) => {
const currentFilters = customColumnsFilter.filters || [];
const newFilters = currentFilters.filter((f) => f.id !== filterId);
handleColumnFilterStateChange({
filters: newFilters,
logic: customColumnsFilter.logic,
pendingFilters: customColumnsFilter.pendingFilters || [],
pendingLogic: customColumnsFilter.pendingLogic || 'AND',
});
},
clearAllFilters: () => {
table.setGlobalFilter('');
handleColumnFilterStateChange({
filters: [],
logic: 'AND',
pendingFilters: [],
pendingLogic: 'AND',
});
},
resetFilters: () => {
table.resetGlobalFilter();
handleColumnFilterStateChange({
filters: [],
logic: 'AND',
pendingFilters: [],
pendingLogic: 'AND',
});
},
},
sorting: {
setSorting: (sortingState) => {
table.setSorting(sortingState);
},
sortColumn: (columnId, direction) => {
const column = table.getColumn(columnId);
if (!column)
return;
if (direction === false) {
column.clearSorting();
}
else {
column.toggleSorting(direction === 'desc');
}
},
clearSorting: () => {
table.resetSorting();
},
resetSorting: () => {
table.resetSorting();
},
},
pagination: {
goToPage: (pageIndex) => {
table.setPageIndex(pageIndex);
},
nextPage: () => {
table.nextPage();
},
previousPage: () => {
table.previousPage();
},
setPageSize: (pageSize) => {
table.setPageSize(pageSize);
},
goToFirstPage: () => {
table.setPageIndex(0);
},
goToLastPage: () => {
const pageCount = table.getPageCount();
if (pageCount > 0) {
table.setPageIndex(pageCount - 1);
}
},
},
selection: {
selectRow: (rowId) => { var _a; return (_a = table.selectRow) === null || _a === void 0 ? void 0 : _a.call(table, rowId); },
deselectRow: (rowId) => { var _a; return (_a = table.deselectRow) === null || _a === void 0 ? void 0 : _a.call(table, rowId); },
toggleRowSelection: (rowId) => { var _a; return (_a = table.toggleRowSelected) === null || _a === void 0 ? void 0 : _a.call(table, rowId); },
selectAll: () => { var _a; return (_a = table.selectAll) === null || _a === void 0 ? void 0 : _a.call(table); },
deselectAll: () => { var _a; return (_a = table.deselectAll) === null || _a === void 0 ? void 0 : _a.call(table); },
toggleSelectAll: () => { var _a; return (_a = table.toggleAllRowsSelected) === null || _a === void 0 ? void 0 : _a.call(table); },
getSelectionState: () => { var _a; return ((_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table)) || { ids: [], type: 'include' }; },
getSelectedRows: () => table.getSelectedRows(),
getSelectedCount: () => table.getSelectedCount(),
isRowSelected: (rowId) => table.getIsRowSelected(rowId) || false,
},
data: {
refresh: () => {
const currentFilters = {
globalFilter,
customColumnsFilter: customColumnsFilter,
sorting,
pagination,
};
if (onDataStateChange) {
const currentState = Object.assign(Object.assign({}, currentFilters), { columnOrder,
columnPinning });
onDataStateChange(currentState);
}
if (onFetchData) {
onFetchData(currentFilters);
}
},
reload: () => {
const currentFilters = {
globalFilter,
customColumnsFilter: customColumnsFilter,
sorting,
pagination,
};
if (onDataStateChange) {
const currentState = Object.assign(Object.assign({}, currentFilters), { columnOrder,
columnPinning });
onDataStateChange(Object.assign({}, currentState));
}
if (onFetchData) {
onFetchData(Object.assign({}, currentFilters));
}
},
getAllData: () => {
return [...data];
},
getRowData: (rowId) => {
return data.find(row => String(row[idKey]) === rowId);
},
getRowByIndex: (index) => {
return data[index];
},
updateRow: (rowId, updates) => {
const newData = data.map(row => String(row[idKey]) === rowId
? Object.assign(Object.assign({}, row), updates) : row);
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
updateRowByIndex: (index, updates) => {
const newData = [...data];
if (newData[index]) {
newData[index] = Object.assign(Object.assign({}, newData[index]), updates);
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
}
},
insertRow: (newRow, index) => {
const newData = [...data];
if (index !== undefined) {
newData.splice(index, 0, newRow);
}
else {
newData.push(newRow);
}
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
deleteRow: (rowId) => {
const newData = data.filter(row => String(row[idKey]) !== rowId);
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
deleteRowByIndex: (index) => {
const newData = [...data];
newData.splice(index, 1);
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
deleteSelectedRows: () => {
const selectedRowIds = Object.keys(table.getState().rowSelection)
.filter(key => table.getState().rowSelection[key]);
const newData = data.filter(row => !selectedRowIds.includes(String(row[idKey])));
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
table.resetRowSelection();
},
replaceAllData: (newData) => {
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
updateMultipleRows: (updates) => {
const updateMap = new Map(updates.map(u => [u.rowId, u.data]));
const newData = data.map(row => {
const rowId = String(row[idKey]);
const updateData = updateMap.get(rowId);
return updateData ? Object.assign(Object.assign({}, row), updateData) : row;
});
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
insertMultipleRows: (newRows, startIndex) => {
const newData = [...data];
if (startIndex !== undefined) {
newData.splice(startIndex, 0, ...newRows);
}
else {
newData.push(...newRows);
}
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
deleteMultipleRows: (rowIds) => {
const idsToDelete = new Set(rowIds);
const newData = data.filter(row => !idsToDelete.has(String(row[idKey])));
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
updateField: (rowId, fieldName, value) => {
const newData = data.map(row => String(row[idKey]) === rowId
? Object.assign(Object.assign({}, row), { [fieldName]: value }) : row);
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
},
updateFieldByIndex: (index, fieldName, value) => {
const newData = [...data];
if (newData[index]) {
newData[index] = Object.assign(Object.assign({}, newData[index]), { [fieldName]: value });
onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
}
},
findRows: (predicate) => {
return data.filter(predicate);
},
findRowIndex: (predicate) => {
return data.findIndex(predicate);
},
getDataCount: () => {
return data.length;
},
getFilteredDataCount: () => {
return table.getFilteredRowModel().rows.length;
},
},
layout: {
resetLayout: () => {
table.resetColumnSizing();
table.resetColumnVisibility();
table.resetSorting();
table.resetGlobalFilter();
},
resetAll: () => {
table.resetColumnSizing();
table.resetColumnVisibility();
table.resetSorting();
table.resetGlobalFilter();
table.resetColumnOrder();
table.resetExpanded();
table.resetRowSelection();
table.resetColumnPinning();
handleColumnFilterStateChange({
filters: [],
logic: 'AND',
pendingFilters: [],
pendingLogic: 'AND',
});
if (enablePagination) {
table.setPageIndex(initialPageIndex);
table.setPageSize(initialPageSize || pageSize);
}
if (enableColumnPinning) {
table.setColumnPinning({
left: [],
right: [],
});
}
},
saveLayout: () => {
return {
columnVisibility: table.getState().columnVisibility,
columnSizing: table.getState().columnSizing,
columnOrder: table.getState().columnOrder,
columnPinning: table.getState().columnPinning,
sorting: table.getState().sorting,
pagination: table.getState().pagination,
globalFilter: table.getState().globalFilter,
customColumnsFilter: customColumnsFilter,
};
},
restoreLayout: (layout) => {
if (layout.columnVisibility) {
table.setColumnVisibility(layout.columnVisibility);
}
if (layout.columnSizing) {
table.setColumnSizing(layout.columnSizing);
}
if (layout.columnOrder) {
table.setColumnOrder(layout.columnOrder);
}
if (layout.columnPinning) {
table.setColumnPinning(layout.columnPinning);
}
if (layout.sorting) {
table.setSorting(layout.sorting);
}
if (layout.pagination && enablePagination) {
table.setPagination(layout.pagination);
}
if (layout.globalFilter !== undefined) {
table.setGlobalFilter(layout.globalFilter);
}
if (layout.customColumnsFilter) {
handleColumnFilterStateChange(layout.customColumnsFilter);
}
},
},
state: {
getTableState: () => {
return table.getState();
},
getCurrentFilters: () => {
return customColumnsFilter;
},
getCurrentSorting: () => {
return table.getState().sorting;
},
getCurrentPagination: () => {
return table.getState().pagination;
},
getCurrentSelection: () => {
return Object.keys(table.getState().rowSelection)
.filter(key => table.getState().rowSelection[key]);
},
},
export: {
exportCSV: (...args_1) => tslib_1.__awaiter(this, [...args_1], void 0, function* (options = {}) {
var _a;
const { filename = exportFilename, } = options;
try {
const controller = new AbortController();
setExportController === null || setExportController === void 0 ? void 0 : setExportController(controller);
if (dataMode === 'server' && onServerExport) {
const currentFilters = {
globalFilter,
customColumnsFilter,
sorting,
pagination,
columnOrder,
columnPinning,
};
yield (0, export_utils_1.exportServerData)(table, {
format: 'csv',
filename,
fetchData: (filters, selection) => onServerExport(filters, selection),
currentFilters,
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
onProgress: onExportProgress,
onComplete: onExportComplete,
onError: onExportError,
});
}
else {
yield (0, export_utils_1.exportClientData)(table, {
format: 'csv',
filename,
onProgress: onExportProgress,
onComplete: onExportComplete,
onError: onExportError,
});
}
}
catch (error) {
onExportError === null || onExportError === void 0 ? void 0 : onExportError({
message: error.message || 'Export failed',
code: 'EXPORT_ERROR',
});
}
finally {
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
}
}),
exportExcel: (...args_1) => tslib_1.__awaiter(this, [...args_1], void 0, function* (options = {}) {
var _a;
const { filename = exportFilename } = options;
try {
const controller = new AbortController();
setExportController === null || setExportController === void 0 ? void 0 : setExportController(controller);
if (dataMode === 'server' && onServerExport) {
const currentFilters = {
globalFilter,
customColumnsFilter,
sorting,
pagination,
columnOrder,
columnPinning,
};
yield (0, export_utils_1.exportServerData)(table, {
format: 'excel',
filename,
fetchData: (filters, selection) => onServerExport(filters, selection),
currentFilters,
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
onProgress: onExportProgress,
onComplete: onExportComplete,
onError: onExportError,
});
}
else {
yield (0, export_utils_1.exportClientData)(table, {
format: 'excel',
filename,
onProgress: onExportProgress,
onComplete: onExportComplete,
onError: onExportError,
});
}
}
catch (error) {
onExportError === null || onExportError === void 0 ? void 0 : onExportError({
message: error.message || 'Export failed',
code: 'EXPORT_ERROR',
});
}
finally {
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
}
}),
exportServerData: (options) => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
const { format, filename = exportFilename, fetchData = onServerExport, } = options;
if (!fetchData) {
onExportError === null || onExportError === void 0 ? void 0 : onExportError({
message: 'No server export function provided',
code: 'NO_SERVER_EXPORT',
});
return;
}
try {
const controller = new AbortController();
setExportController === null || setExportController === void 0 ? void 0 : setExportController(controller);
const currentFilters = {
globalFilter,
customColumnsFilter,
sorting,
pagination,
columnOrder,
columnPinning,
};
yield (0, export_utils_1.exportServerData)(table, {
format,
filename,
fetchData: (filters, selection) => fetchData(filters, selection),
currentFilters,
selection: (_a = table.getSelectionState) === null || _a === void 0 ? void 0 : _a.call(table),
onProgress: onExportProgress,
onComplete: onExportComplete,
onError: onExportError,
});
}
catch (error) {
onExportError === null || onExportError === void 0 ? void 0 : onExportError({
message: error.message || 'Export failed',
code: 'EXPORT_ERROR',
});
}
finally {
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
}
}),
isExporting: () => isExporting || false,
cancelExport: () => {
exportController === null || exportController === void 0 ? void 0 : exportController.abort();
setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
},
},
}), [
table,
enhancedColumns,
handleColumnFilterStateChange,
customColumnsFilter,
data,
idKey,
onDataStateChange,
onFetchData,
globalFilter,
sorting,
pagination,
columnOrder,
columnPinning,
onDataChange,
enableColumnPinning,
enablePagination,
initialPageIndex,
initialPageSize,
pageSize,
exportFilename,
onExportProgress,
onExportComplete,
onExportError,
onServerExport,
exportController,
setExportController,
isExporting,
dataMode,
selectMode,
onSelectionChange,
]);
}