@ackplus/react-tanstack-data-table
Version:
A powerful React data table component built with MUI and TanStack Table
248 lines (247 loc) • 11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCombinedFilteredRowModel = exports.CustomColumnFilterFeature = void 0;
exports.matchesCustomColumnFilters = matchesCustomColumnFilters;
const tslib_1 = require("tslib");
const react_table_1 = require("@tanstack/react-table");
const moment_1 = tslib_1.__importDefault(require("moment"));
exports.CustomColumnFilterFeature = {
getInitialState: (state) => {
return Object.assign({ customColumnFilter: {
filters: [],
logic: 'AND',
pendingFilters: [],
pendingLogic: 'AND',
} }, state);
},
getDefaultOptions: (table) => {
return {
enableCustomColumnFilter: true,
onCustomColumnFilterChange: (0, react_table_1.makeStateUpdater)('customColumnFilter', table),
onCustomColumnFilterApply: (state) => {
},
};
},
createTable: (table) => {
table.setCustomColumnFilter = (updater) => {
var _a, _b;
const safeUpdater = (old) => {
const newState = (0, react_table_1.functionalUpdate)(updater, old);
return newState;
};
return (_b = (_a = table.options).onCustomColumnFilterChange) === null || _b === void 0 ? void 0 : _b.call(_a, safeUpdater);
};
table.addPendingColumnFilter = (columnId, operator, value) => {
table.setCustomColumnFilter((old) => {
const newFilter = {
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
columnId,
operator,
value,
};
return Object.assign(Object.assign({}, old), { pendingFilters: [...old.pendingFilters, newFilter] });
});
};
table.updatePendingColumnFilter = (filterId, updates) => {
table.setCustomColumnFilter((old) => {
const updatedFilters = old.pendingFilters.map((filter) => filter.id === filterId ? Object.assign(Object.assign({}, filter), updates) : filter);
return Object.assign(Object.assign({}, old), { pendingFilters: updatedFilters });
});
};
table.removePendingColumnFilter = (filterId) => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { pendingFilters: old.pendingFilters.filter((filter) => filter.id !== filterId) })));
};
table.clearAllPendingColumnFilters = () => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { pendingFilters: [] })));
};
table.setPendingFilterLogic = (logic) => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { pendingLogic: logic })));
};
table.applyPendingColumnFilters = () => {
table.setCustomColumnFilter((old) => {
const newState = Object.assign(Object.assign({}, old), { filters: [...old.pendingFilters], logic: old.pendingLogic });
setTimeout(() => {
var _a, _b;
(_b = (_a = table.options).onCustomColumnFilterApply) === null || _b === void 0 ? void 0 : _b.call(_a, newState);
}, 0);
return newState;
});
};
table.addColumnFilter = (columnId, operator, value) => {
table.setCustomColumnFilter((old) => {
const newFilter = {
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
columnId,
operator,
value,
};
return Object.assign(Object.assign({}, old), { filters: [...old.filters, newFilter] });
});
};
table.updateColumnFilter = (filterId, updates) => {
table.setCustomColumnFilter((old) => {
const updatedFilters = old.filters.map((filter) => filter.id === filterId ? Object.assign(Object.assign({}, filter), updates) : filter);
return Object.assign(Object.assign({}, old), { filters: updatedFilters });
});
};
table.removeColumnFilter = (filterId) => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { filters: old.filters.filter((filter) => filter.id !== filterId) })));
};
table.clearAllColumnFilters = () => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { filters: [] })));
};
table.setFilterLogic = (logic) => {
table.setCustomColumnFilter((old) => (Object.assign(Object.assign({}, old), { logic })));
};
table.getActiveColumnFilters = () => {
const state = table.getState().customColumnFilter;
return state.filters.filter((f) => f.columnId && f.operator);
};
table.getPendingColumnFilters = () => {
const state = table.getState().customColumnFilter;
return state.pendingFilters.filter((f) => f.columnId && f.operator);
};
table.getCustomColumnFilterState = () => {
return table.getState().customColumnFilter;
};
},
};
function matchesCustomColumnFilters(row, filters, logic = 'AND') {
if (filters.length === 0)
return true;
const activeFilters = filters.filter((f) => f.columnId && f.operator);
if (activeFilters.length === 0)
return true;
const results = activeFilters.map((filter) => {
var _a;
let columnValue;
let columnType = filter.columnType || 'text';
try {
const column = row.getAllCells().find((cell) => cell.column.id === filter.columnId);
if (column) {
columnValue = column.getValue();
if (!filter.columnType && column.column.columnDef && column.column.columnDef.type) {
columnType = column.column.columnDef.type;
}
}
}
catch (error) {
console.warn(`Error getting value for column ${filter.columnId}:`, error);
columnValue = ((_a = row.original) === null || _a === void 0 ? void 0 : _a[filter.columnId]) || '';
}
return evaluateFilterCondition(columnValue, filter.operator, filter.value, columnType);
});
return logic === 'AND' ? results.every(Boolean) : results.some(Boolean);
}
const getCombinedFilteredRowModel = () => {
return (table) => () => {
var _a;
const baseFilteredModel = (0, react_table_1.getFilteredRowModel)()(table)();
const { filters, logic } = (_a = table.getState().customColumnFilter) !== null && _a !== void 0 ? _a : {
filters: [],
logic: 'AND',
};
if (!filters.length)
return baseFilteredModel;
const filteredRows = baseFilteredModel.rows.filter(row => matchesCustomColumnFilters(row, filters, logic));
const flatRows = [];
const rowsById = {};
const addRow = (row) => {
var _a;
flatRows.push(row);
rowsById[row.id] = row;
(_a = row.subRows) === null || _a === void 0 ? void 0 : _a.forEach(addRow);
};
filteredRows.forEach(addRow);
return {
rows: filteredRows,
flatRows,
rowsById,
};
};
};
exports.getCombinedFilteredRowModel = getCombinedFilteredRowModel;
function evaluateFilterCondition(columnValue, operator, filterValue, type = 'text') {
function toMoment(val) {
if (!val)
return null;
const m = (0, moment_1.default)(val);
return m.isValid() ? m : null;
}
if (type === 'date') {
const mCol = toMoment(columnValue);
const mFilter = toMoment(filterValue);
if (!mCol || !mFilter)
return false;
switch (operator) {
case 'equals':
return mCol.isSame(mFilter, 'day');
case 'notEquals':
return !mCol.isSame(mFilter, 'day');
case 'after':
return mCol.isAfter(mFilter, 'day');
case 'before':
return mCol.isBefore(mFilter, 'day');
case 'isEmpty':
return !columnValue;
case 'isNotEmpty':
return !!columnValue;
default:
return true;
}
}
if (type === 'boolean') {
switch (operator) {
case 'is':
if (filterValue === 'any')
return true;
if (filterValue === 'true')
return (columnValue === true || columnValue === 'true' || columnValue === 1 || columnValue === '1' || columnValue === 'Yes' || columnValue === 'yes');
if (filterValue === 'false')
return (columnValue === false || columnValue === 'false' || columnValue === 0 || columnValue === '0' || columnValue === 'No' || columnValue === 'no');
return false;
default:
return true;
}
}
if (type === 'select') {
if (operator === 'in' || operator === 'notIn') {
if (Array.isArray(filterValue)) {
if (operator === 'in')
return filterValue.includes(columnValue);
if (operator === 'notIn')
return !filterValue.includes(columnValue);
}
return false;
}
if (operator === 'equals' || operator === 'notEquals') {
return operator === 'equals'
? columnValue === filterValue
: columnValue !== filterValue;
}
}
switch (operator) {
case 'contains':
return String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
case 'notContains':
return !String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
case 'startsWith':
return String(columnValue).toLowerCase().startsWith(String(filterValue).toLowerCase());
case 'endsWith':
return String(columnValue).toLowerCase().endsWith(String(filterValue).toLowerCase());
case 'isEmpty':
return columnValue === null || columnValue === undefined || columnValue === '';
case 'isNotEmpty':
return columnValue !== null && columnValue !== undefined && columnValue !== '';
case 'greaterThan':
return Number(columnValue) > Number(filterValue);
case 'greaterThanOrEqual':
return Number(columnValue) >= Number(filterValue);
case 'lessThan':
return Number(columnValue) < Number(filterValue);
case 'lessThanOrEqual':
return Number(columnValue) <= Number(filterValue);
default:
return true;
}
}