@ackplus/react-tanstack-data-table
Version:
A powerful React data table component built with MUI and TanStack Table
246 lines (245 loc) • 9.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SelectionFeature = void 0;
/**
* Custom Selection Feature for TanStack Table
*
* This feature adds custom selection capabilities to TanStack Table
* following the official custom features pattern (same as CustomColumnFilterFeature)
*/
const react_table_1 = require("@tanstack/react-table");
// The custom selection feature implementation (same pattern as CustomColumnFilterFeature)
exports.SelectionFeature = {
// Define the feature's initial state
getInitialState: (state) => {
return {
selectionState: {
ids: [],
type: 'include',
selectMode: 'page',
},
...state,
};
},
// Define the feature's default options
getDefaultOptions: (table) => {
return {
enableAdvanceSelection: true,
selectMode: 'page',
onSelectionStateChange: (0, react_table_1.makeStateUpdater)('selectionState', table),
};
},
// Define the feature's table instance methods
createTable: (table) => {
table.setSelectionState = (updater) => {
var _a, _b;
if (!table.options.enableAdvanceSelection)
return;
const safeUpdater = (old) => {
const newState = (0, react_table_1.functionalUpdate)(updater, old);
return newState;
};
return (_b = (_a = table.options).onSelectionStateChange) === null || _b === void 0 ? void 0 : _b.call(_a, safeUpdater);
};
// === BASIC SELECTION METHODS ===
table.selectRow = (rowId) => {
if (!table.options.enableAdvanceSelection)
return;
if (!table.canSelectRow(rowId))
return;
table.setSelectionState((old) => {
if (old.type === 'exclude') {
// In exclude mode, selecting means removing from exclude list
return {
...old,
ids: old.ids.filter(id => id !== rowId),
};
}
else {
// In include mode, selecting means adding to include list
const newIds = old.ids.includes(rowId) ? old.ids : [...old.ids, rowId];
return {
...old,
ids: newIds,
};
}
});
};
table.deselectRow = (rowId) => {
if (!table.options.enableAdvanceSelection)
return;
table.setSelectionState((old) => {
if (old.type === 'exclude') {
// In exclude mode, deselecting means adding to exclude list
const newIds = old.ids.includes(rowId) ? old.ids : [...old.ids, rowId];
return {
...old,
ids: newIds,
};
}
else {
// In include mode, deselecting means removing from include list
return {
...old,
ids: old.ids.filter(id => id !== rowId),
};
}
});
};
table.toggleRowSelected = (rowId) => {
if (!table.options.enableAdvanceSelection)
return;
if (table.getIsRowSelected(rowId)) {
table.deselectRow(rowId);
}
else {
table.selectRow(rowId);
}
};
table.selectAll = () => {
var _a, _b;
if (!table.options.enableAdvanceSelection)
return;
const selectMode = table.options.selectMode || 'page';
const currentRows = ((_b = (_a = table.getPaginationRowModel) === null || _a === void 0 ? void 0 : _a.call(table)) === null || _b === void 0 ? void 0 : _b.rows) ||
table.getRowModel().rows;
if (selectMode === 'all') {
// In 'all' mode, use exclude type with empty list (select all)
table.setSelectionState((old) => ({
...old,
ids: [],
type: 'exclude',
}));
}
else {
// In 'page' mode, select current page rows
const selectableRowIds = currentRows
.filter(row => table.canSelectRow(row.id))
.map(row => row.id);
table.setSelectionState((old) => ({
...old,
ids: selectableRowIds,
type: 'include',
}));
}
};
table.deselectAll = () => {
if (!table.options.enableAdvanceSelection)
return;
table.setSelectionState((old) => ({
...old,
ids: [],
type: 'include',
}));
};
table.toggleAllRowsSelected = () => {
if (!table.options.enableAdvanceSelection)
return;
if (table.getIsAllRowsSelected()) {
table.deselectAll();
}
else {
table.selectAll();
}
};
// === STATE CHECKERS ===
table.getIsRowSelected = (rowId) => {
const state = table.getSelectionState();
if (state.type === 'exclude') {
// In exclude mode, selected if NOT in exclude list
return !state.ids.includes(rowId);
}
else {
// In include mode, selected if in include list
return state.ids.includes(rowId);
}
};
table.getIsAllRowsSelected = () => {
var _a, _b;
const state = table.getSelectionState();
const selectMode = table.options.selectMode || 'page';
if (selectMode === 'all') {
const totalCount = table.getRowCount();
if (totalCount === 0)
return false;
if (state.type === 'exclude') {
return state.ids.length === 0;
}
else {
return state.ids.length === totalCount;
}
}
else {
// Page mode - check if all selectable rows on current page are selected
const currentPageRows = ((_b = (_a = table.getPaginationRowModel) === null || _a === void 0 ? void 0 : _a.call(table)) === null || _b === void 0 ? void 0 : _b.rows) || table.getRowModel().rows;
const selectableRows = currentPageRows.filter(row => table.canSelectRow(row.id));
if (selectableRows.length === 0)
return false;
return selectableRows.every(row => table.getIsRowSelected(row.id));
}
};
table.getIsSomeRowsSelected = () => {
const state = table.getSelectionState();
const selectMode = table.options.selectMode || 'page';
if (selectMode === 'all' && state.type === 'exclude') {
// In exclude mode, we have some selected if not all are excluded
const totalCount = table.getRowCount();
return totalCount > 0 && state.ids.length < totalCount;
}
else {
// In include mode, we have some selected if list has items
return state.ids.length > 0;
}
};
// === GETTERS ===
table.getSelectionState = () => {
return table.getState().selectionState || {
ids: [],
type: 'include',
selectMode: 'page',
};
};
table.getSelectedCount = () => {
const state = table.getSelectionState();
const selectMode = table.options.selectMode || 'page';
if (selectMode === 'all' && state.type === 'exclude') {
// For server-side data, use rowCount which includes total from server
// For client-side data, this will be the same as getRowModel().rows.length
const totalCount = table.getRowCount();
return Math.max(0, totalCount - state.ids.length);
}
else {
return state.ids.length;
}
};
table.getSelectedRowIds = () => {
const state = table.getSelectionState();
if (state.type === 'exclude') {
console.warn('[SelectionFeature] getSelectedRowIds() is not accurate in exclude mode. Use getSelectionState() to interpret selection properly.');
return []; // Return empty to avoid misleading API
}
return state.ids;
};
table.getSelectedRows = () => {
const state = table.getSelectionState();
const allRows = table.getRowModel().rows;
if (state.type === 'exclude') {
// Return all rows except excluded ones
return allRows.filter(row => !state.ids.includes(row.id));
}
else {
// Return only included rows
return allRows.filter(row => state.ids.includes(row.id));
}
};
// === HELPER METHODS ===
table.canSelectRow = (rowId) => {
if (!table.options.isRowSelectable)
return true;
const row = table.getRowModel().rows.find(r => r.id === rowId);
if (!row)
return false;
return table.options.isRowSelectable({ row: row.original, id: rowId });
};
},
};