use-table-tools
Version:
react hook for building powerful table components
355 lines • 15.2 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
import { useReducer, useLayoutEffect, useCallback } from 'react';
import { useWindowSize } from './use-window-size';
import { getObjectValueByString, getOffsetColumns } from './utils';
export var actionTypes = {
updateState: 'updateState',
switchColumns: 'switchColumns',
switchCurrentLayout: 'switchCurrentLayout',
deselectAll: 'deselectAll',
selectAll: 'selectAll',
checkboxToggle: 'checkboxToggle',
checkboxShiftToggle: 'checkboxShiftToggle',
changeSortDirection: 'changeSortDirection',
toggleSortDirection: 'toggleSortDirection',
toggleSortByKey: 'toggleSortByKey',
sortData: 'sortData',
};
export var tableToolsReducer = function (state, action) {
switch (action.type) {
case actionTypes.updateState: {
return __assign(__assign({}, state), action.payload);
}
case actionTypes.switchColumns: {
var _a = action.payload, to_1 = _a.to, from_1 = _a.from;
var columns = state.visibleColumns;
var index = columns.findIndex(function (x) { return x.sortKey === from_1; });
var visibleColumns = columns.filter(function (col) { return col.sortKey !== from_1; });
var replacement = getOffsetColumns(state.visibleColumns, state.columns).find(function (_a) {
var sortKey = _a.sortKey;
return sortKey === to_1;
});
if (replacement) {
visibleColumns.splice(index, 0, replacement);
}
return __assign(__assign({}, state), { visibleColumns: visibleColumns });
}
case actionTypes.switchCurrentLayout: {
var currentLayout = action.payload.currentLayout;
var visibleSortFields_1 = state.visibleColumns
.map(function (_a) {
var sortField = _a.sortField;
return sortField;
})
.reverse();
return __assign(__assign({}, state), { currentLayout: currentLayout, visibleColumns: state.columns
.sort(function (a, b) {
return (visibleSortFields_1.indexOf(b.sortKey) -
visibleSortFields_1.indexOf(a.sortKey));
})
.slice(0, currentLayout.length) });
}
case actionTypes.deselectAll: {
return __assign(__assign({}, state), { selectAllCheckboxState: 'none', checkedItems: [] });
}
case actionTypes.selectAll: {
var items = action.payload.items;
return __assign(__assign({}, state), { checkedItems: items, selectAllCheckboxState: state.totalItems === items.length ? 'all' : 'some' });
}
case actionTypes.checkboxToggle: {
var _b = action.payload, id = _b.id, rowId_1 = _b.value;
var checkedItems = state.checkedItems;
if (!checkedItems.includes(rowId_1)) {
var allCheckedItems = __spreadArrays(state.checkedItems, [rowId_1]);
return __assign(__assign({}, state), { lastChecked: { id: id, value: rowId_1 }, checkedItems: allCheckedItems, selectAllCheckboxState: state.totalItems === allCheckedItems.length ? 'all' : 'some' });
}
else {
var allCheckedItems = checkedItems.filter(function (id) { return id !== rowId_1; });
return __assign(__assign({}, state), { lastChecked: { id: id, value: rowId_1 }, checkedItems: allCheckedItems, selectAllCheckboxState: allCheckedItems.length ? 'some' : 'none' });
}
}
case actionTypes.checkboxShiftToggle: {
var checkedItems = state.checkedItems, lastChecked = state.lastChecked;
var _c = action.payload, id = _c.id, value = _c.value, refs = _c.refs;
if (lastChecked) {
var rows = Array.from(refs);
var lastCheckedId = parseInt(lastChecked.id);
var currentCheckedId = parseInt(id);
var slicedInputs = void 0;
var checked = [];
if (lastCheckedId < currentCheckedId) {
slicedInputs = rows.slice(lastCheckedId, currentCheckedId + 1);
}
else {
slicedInputs = rows.slice(currentCheckedId, lastCheckedId + 1);
}
var rangeIds_1 = slicedInputs.map(function (ref) { return ref.value; });
if (checkedItems.includes(lastChecked.value) &&
!checkedItems.includes(value)) {
checked = checkedItems.concat(rangeIds_1);
}
else if (!checkedItems.includes(lastChecked.value) &&
!checkedItems.includes(value)) {
checked = checkedItems.concat(rangeIds_1);
}
else {
checked = checkedItems.filter(function (id) {
return rangeIds_1.includes(id) ? false : true;
});
}
return __assign(__assign({}, state), { lastChecked: { id: id, value: value }, checkedItems: checked, selectAllCheckboxState: checked.length
? state.totalItems === checked.length
? 'all'
: 'some'
: 'none' });
}
else {
return __assign(__assign({}, state), { lastChecked: { id: id, value: value } });
}
}
case actionTypes.changeSortDirection: {
return __assign(__assign({}, state), { currentSort: {
fieldKey: state.currentSort.fieldKey,
direction: action.payload.direction,
} });
}
case actionTypes.toggleSortDirection: {
var currentSort = state.currentSort;
return __assign(__assign({}, state), { currentSort: {
direction: currentSort.direction === 'asc' ? 'dsc' : 'asc',
fieldKey: currentSort.fieldKey,
} });
}
case actionTypes.toggleSortByKey: {
var currentSort = state.currentSort;
var fieldKey = action.payload.fieldKey;
return __assign(__assign({}, state), { currentSort: {
fieldKey: fieldKey,
direction: currentSort.direction === 'asc' ? 'desc' : 'asc',
} });
}
case actionTypes.sortData: {
var _d = action.payload, fieldKey = _d.fieldKey, direction = _d.direction;
return __assign(__assign({}, state), { currentSort: { fieldKey: fieldKey, direction: direction } });
}
default: {
throw new Error("Unhandled type: " + action.type);
}
}
};
export var useTableTools = function (_a, reducer) {
var _b = _a.layout, layout = _b === void 0 ? ['0 0 25%', '1 1 35%', '0 0 20%', '0 0 20%'] : _b, _c = _a.totalItems, totalItems = _c === void 0 ? 0 : _c, _d = _a.clientSortBy, clientSortBy = _d === void 0 ? { direction: 'asc', fieldKey: '' } : _d, _e = _a.columns, columns = _e === void 0 ? [] : _e, _f = _a.checkedItems, checkedItems = _f === void 0 ? [] : _f;
if (reducer === void 0) { reducer = tableToolsReducer; }
var checkboxRefs = new Set();
var width = useWindowSize(Array.isArray(layout) ? 'no' : 'yes').width;
var _g = useReducer(reducer, {
currentLayout: [],
visibleColumns: [],
columns: columns,
totalItems: totalItems,
currentSort: clientSortBy,
checkedItems: checkedItems,
selectAllCheckboxState: 'none',
lastChecked: null,
}), state = _g[0], send = _g[1];
useLayoutEffect(function () {
if (Array.isArray(layout)) {
return send({
type: actionTypes.updateState,
payload: {
currentLayout: layout,
visibleColumns: columns.slice(0, layout.length),
},
});
}
Object.keys(layout).map(function (breakpoint) {
if (breakpoint < width) {
switchCurrentLayout(layout[breakpoint]);
}
return undefined;
});
}, [width]);
var switchColumns = function (from, to) {
send({ type: actionTypes.switchColumns, payload: { to: to, from: from } });
};
var switchCurrentLayout = function (nextLayout) {
send({
type: actionTypes.switchCurrentLayout,
payload: { currentLayout: nextLayout },
});
};
var offsetColumns = useCallback(function (_a) {
var includeVisible = (_a === void 0 ? {} : _a).includeVisible;
return getOffsetColumns(state.visibleColumns, state.columns, includeVisible);
}, [state.visibleColumns, state.columns]);
var onSelection = function (items) {
switch (state.selectAllCheckboxState) {
case 'all':
return deselectAll();
case 'some':
return deselectAll();
case 'none':
return selectAll(items);
default:
return deselectAll();
}
};
var deselectAll = function () {
send({ type: actionTypes.deselectAll });
};
var selectAll = function (items) {
send({
type: actionTypes.selectAll,
payload: { items: items.map(function (item) { return String(item); }) },
});
};
var checkboxToggle = function (evt) {
send({
type: actionTypes.checkboxToggle,
payload: { id: String(evt.target.id), value: String(evt.target.value) },
});
};
var checkboxShiftToggle = function (evt) {
if (evt.shiftKey && state.lastChecked) {
send({
type: actionTypes.checkboxShiftToggle,
payload: {
id: String(evt.target.id),
value: String(evt.target.value),
refs: checkboxRefs,
},
});
return;
}
send({
type: actionTypes.checkboxToggle,
payload: { id: String(evt.target.id), value: String(evt.target.value) },
});
};
var checkboxState = function (itemId) {
if (!state.checkedItems || state.checkedItems.length < 1) {
return false;
}
return state.checkedItems.includes(String(itemId));
};
var clientSortMethod = function (a, b) {
var _a = state.currentSort, fieldKey = _a.fieldKey, direction = _a.direction;
if (fieldKey && direction) {
var valueA = getObjectValueByString(a, fieldKey);
var valueB = getObjectValueByString(b, fieldKey);
valueA = valueA === null || valueA === undefined ? '' : valueA;
valueB = valueB === null || valueB === undefined ? '' : valueB;
valueA = typeof valueA === 'string' ? valueA.toLowerCase() : valueA;
valueB = typeof valueB === 'string' ? valueB.toLowerCase() : valueB;
if (direction.toLowerCase() === 'asc') {
if (valueA < valueB) {
return -1;
}
else if (valueA > valueB) {
return 1;
}
else {
return 0;
}
}
if (direction.toLowerCase() === 'desc') {
if (valueA > valueB) {
return -1;
}
else if (valueA < valueB) {
return 1;
}
else {
return 0;
}
}
return 0;
}
return 0;
};
var changeSortDirection = function (direction) {
send({ type: actionTypes.changeSortDirection, payload: { direction: direction } });
};
var toggleSortDirection = function () {
send({
type: actionTypes.toggleSortDirection,
});
};
var toggleSortByKey = function (fieldKey) {
send({
type: actionTypes.toggleSortByKey,
payload: { fieldKey: fieldKey },
});
};
var sortData = function (_a) {
var direction = _a.direction, fieldKey = _a.fieldKey;
send({ type: actionTypes.sortData, payload: { direction: direction, fieldKey: fieldKey } });
};
var activeSort = function (_a) {
var direction = _a.direction, fieldKey = _a.fieldKey;
var currentSort = state.currentSort;
var isActive = currentSort.fieldKey === fieldKey;
var isCurrentSortDir = currentSort.direction === direction;
return isActive && isCurrentSortDir;
};
var activeSortKey = function (fieldKey) {
var currentSort = state.currentSort;
return currentSort.fieldKey === fieldKey;
};
var getCheckboxProps = function (_a) {
if (_a === void 0) { _a = {}; }
var _b = _a.master, master = _b === void 0 ? false : _b, rest = __rest(_a, ["master"]);
if (master) {
return __assign({}, rest);
}
return __assign({ ref: function (ref) { return ref && checkboxRefs.add(ref); } }, rest);
};
return Object.assign(state, {
switchColumns: switchColumns,
switchCurrentLayout: switchCurrentLayout,
onSelection: onSelection,
deselectAll: deselectAll,
selectAll: selectAll,
offsetColumns: offsetColumns,
checkboxToggle: checkboxToggle,
checkboxShiftToggle: checkboxShiftToggle,
checkboxState: checkboxState,
clientSortMethod: clientSortMethod,
changeSortDirection: changeSortDirection,
toggleSortDirection: toggleSortDirection,
toggleSortByKey: toggleSortByKey,
sortData: sortData,
activeSort: activeSort,
activeSortKey: activeSortKey,
getCheckboxProps: getCheckboxProps,
});
};
//# sourceMappingURL=tableTools.js.map