@coreui/react-pro
Version:
UI Components Library for React.js
359 lines (356 loc) • 23.9 kB
JavaScript
import { __rest, __assign, __spreadArray } from '../../node_modules/tslib/tslib.es6.js';
import React, { forwardRef, useRef, useState, useMemo, useEffect } from 'react';
import PropTypes from 'prop-types';
import { CIcon } from '../../node_modules/@coreui/icons-react/dist/index.esm.js';
import { CElementCover } from '../element-cover/CElementCover.js';
import '../form/CForm.js';
import '../form/CFormCheck.js';
import '../form/CFormControlValidation.js';
import '../form/CFormControlWrapper.js';
import '../form/CFormFeedback.js';
import '../form/CFormFloating.js';
import { CFormInput } from '../form/CFormInput.js';
import { CFormLabel } from '../form/CFormLabel.js';
import '../form/CFormRange.js';
import { CFormSelect } from '../form/CFormSelect.js';
import '../form/CFormSwitch.js';
import '../form/CFormText.js';
import '../form/CFormTextarea.js';
import '../form/CInputGroup.js';
import '../form/CInputGroupText.js';
import { CSmartPagination } from '../smart-pagination/CSmartPagination.js';
import { CTable } from '../table/CTable.js';
import '../table/CTableBody.js';
import '../table/CTableCaption.js';
import { CTableDataCell } from '../table/CTableDataCell.js';
import { CTableFoot } from '../table/CTableFoot.js';
import '../table/CTableHead.js';
import '../table/CTableHeaderCell.js';
import { CTableRow } from '../table/CTableRow.js';
import { CSmartTableBody } from './CSmartTableBody.js';
import { CSmartTableHead } from './CSmartTableHead.js';
import isObjectInArray from '../../utils/isObjectInArray.js';
import { ITEM_INTERNAL_KEYS } from './consts.js';
import { getColumnNames, getColumnNamesFromItems, filterColumns, filterTable, sortItems, isSortable } from './utils.js';
import { cilSwapVertical } from '../../node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js';
import { cilArrowTop } from '../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js';
import { cilArrowBottom } from '../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js';
import { cilFilterX } from '../../node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js';
var CSmartTable = forwardRef(function (_a, ref) {
var _b = _a.activePage, activePage = _b === void 0 ? 1 : _b, cleaner = _a.cleaner, clickableRows = _a.clickableRows, columnFilter = _a.columnFilter, columnFilterValue = _a.columnFilterValue, // TODO: consider to use only columnFilter prop
columns = _a.columns, columnSorter = _a.columnSorter, elementCover = _a.elementCover, footer = _a.footer, _c = _a.header, header = _c === void 0 ? true : _c, _d = _a.items, items = _d === void 0 ? [] : _d, itemsNumber = _a.itemsNumber, _e = _a.itemsPerPage, itemsPerPage = _e === void 0 ? 10 : _e, _f = _a.itemsPerPageLabel, itemsPerPageLabel = _f === void 0 ? 'Items per page:' : _f, _g = _a.itemsPerPageOptions, itemsPerPageOptions = _g === void 0 ? [5, 10, 20, 50] : _g, itemsPerPageSelect = _a.itemsPerPageSelect, loading = _a.loading, _h = _a.noItemsLabel, noItemsLabel = _h === void 0 ? 'No items found' : _h, onActivePageChange = _a.onActivePageChange, onColumnFilterChange = _a.onColumnFilterChange, onFilteredItemsChange = _a.onFilteredItemsChange, onItemsPerPageChange = _a.onItemsPerPageChange, onRowClick = _a.onRowClick, onSelectAll = _a.onSelectAll, onSelectedItemsChange = _a.onSelectedItemsChange, onSorterChange = _a.onSorterChange, onTableFilterChange = _a.onTableFilterChange, pagination = _a.pagination, paginationProps = _a.paginationProps, scopedColumns = _a.scopedColumns, selected = _a.selected, selectable = _a.selectable, _j = _a.selectAll, selectAll = _j === void 0 ? true : _j, sorterValue = _a.sorterValue, _k = _a.sortingIcon, sortingIcon = _k === void 0 ? React.createElement(CIcon, { width: 18, icon: cilSwapVertical, key: "csv" }) : _k, _l = _a.sortingIconAscending, sortingIconAscending = _l === void 0 ? React.createElement(CIcon, { width: 18, icon: cilArrowTop, key: "cat" }) : _l, _m = _a.sortingIconDescending, sortingIconDescending = _m === void 0 ? React.createElement(CIcon, { width: 18, icon: cilArrowBottom, key: "cab" }) : _m, tableBodyProps = _a.tableBodyProps, tableFootProps = _a.tableFootProps, tableFilter = _a.tableFilter, _o = _a.tableFilterLabel, tableFilterLabel = _o === void 0 ? 'Filter:' : _o, _p = _a.tableFilterPlaceholder, tableFilterPlaceholder = _p === void 0 ? 'type string...' : _p, tableFilterValue = _a.tableFilterValue, tableHeadProps = _a.tableHeadProps, tableProps = _a.tableProps, rest = __rest(_a, ["activePage", "cleaner", "clickableRows", "columnFilter", "columnFilterValue", "columns", "columnSorter", "elementCover", "footer", "header", "items", "itemsNumber", "itemsPerPage", "itemsPerPageLabel", "itemsPerPageOptions", "itemsPerPageSelect", "loading", "noItemsLabel", "onActivePageChange", "onColumnFilterChange", "onFilteredItemsChange", "onItemsPerPageChange", "onRowClick", "onSelectAll", "onSelectedItemsChange", "onSorterChange", "onTableFilterChange", "pagination", "paginationProps", "scopedColumns", "selected", "selectable", "selectAll", "sorterValue", "sortingIcon", "sortingIconAscending", "sortingIconDescending", "tableBodyProps", "tableFootProps", "tableFilter", "tableFilterLabel", "tableFilterPlaceholder", "tableFilterValue", "tableHeadProps", "tableProps"]);
var mountedRef = useRef(false);
var _q = useState(activePage), _activePage = _q[0], setActivePage = _q[1];
var _r = useState([]), _items = _r[0], setItems = _r[1];
var _s = useState(itemsPerPage), _itemsPerPage = _s[0], setItemsPerPage = _s[1];
var _t = useState([]), _selected = _t[0], setSelected = _t[1];
var _u = useState({}), columnFilterState = _u[0], setColumnFilterState = _u[1];
var _v = useState(), selectedAll = _v[0], setSelectedAll = _v[1];
var _w = useState([]), sorterState = _w[0], setSorterState = _w[1];
var _x = useState(tableFilterValue !== null && tableFilterValue !== void 0 ? tableFilterValue : ''), tableFilterState = _x[0], setTableFilterState = _x[1];
var _itemsNumber = useMemo(function () { return itemsNumber !== null && itemsNumber !== void 0 ? itemsNumber : items.length; }, [itemsNumber, items.length]);
useEffect(function () {
setActivePage(activePage);
}, [activePage]);
useEffect(function () {
if (items.length < _itemsPerPage * _activePage - _itemsPerPage) {
setActivePage(1);
}
var selected = [];
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
var item = items_1[_i];
if (item._selected) {
var _item = __assign({}, item);
for (var _a = 0, ITEM_INTERNAL_KEYS_1 = ITEM_INTERNAL_KEYS; _a < ITEM_INTERNAL_KEYS_1.length; _a++) {
var key = ITEM_INTERNAL_KEYS_1[_a];
delete _item[key]; // Remove internal keys
}
selected.push(_item); // Add cleaned item to selected array
}
}
if (selected.length > 0) {
setSelected(__spreadArray(__spreadArray([], _selected, true), selected, true));
}
if (Array.isArray(items)) {
setItems(__spreadArray([], items, true));
}
}, [JSON.stringify(items)]);
useEffect(function () {
Array.isArray(selected) && setSelected(selected);
}, [JSON.stringify(selected)]);
useEffect(function () {
columnFilterValue && setColumnFilterState(columnFilterValue);
}, [JSON.stringify(columnFilterValue)]);
useEffect(function () {
sorterValue && setSorterState(Array.isArray(sorterValue) ? sorterValue : [sorterValue]);
}, [JSON.stringify(sorterValue)]);
useEffect(function () { return setItemsPerPage(itemsPerPage); }, [itemsPerPage]);
useEffect(function () {
mountedRef.current && onActivePageChange && onActivePageChange(_activePage);
}, [_activePage]);
useEffect(function () {
mountedRef.current && onItemsPerPageChange && onItemsPerPageChange(_itemsPerPage);
itemsPerPage !== _itemsPerPage && setActivePage(1); // TODO: set proper page after _itemsPerPage update
}, [_itemsPerPage]);
useEffect(function () {
var multiple = typeof columnSorter === 'object' && columnSorter.multiple;
mountedRef.current &&
sorterState &&
onSorterChange &&
onSorterChange(multiple ? sorterState : sorterState[0]);
}, [sorterState]);
useEffect(function () {
mountedRef.current && onColumnFilterChange && onColumnFilterChange(columnFilterState);
}, [columnFilterState]);
useEffect(function () {
mountedRef.current && onTableFilterChange && onTableFilterChange(tableFilterState);
}, [tableFilterState]);
useEffect(function () {
if (selectable) {
onSelectedItemsChange && onSelectedItemsChange(_selected);
if (_selected.length === _itemsNumber) {
setSelectedAll(true);
return;
}
if (_selected.length === 0) {
setSelectedAll(false);
return;
}
if (_selected.length > 0 && _selected.length !== _itemsNumber) {
setSelectedAll('indeterminate');
}
}
}, [JSON.stringify(_selected), _itemsNumber]);
var columnNames = useMemo(function () { return getColumnNames(columns, _items); }, [columns, _items]);
var itemsDataColumns = useMemo(function () { return columnNames.filter(function (name) { return getColumnNamesFromItems(_items).includes(name); }); }, [columnNames, _items]);
var filteredColumns = useMemo(function () { return filterColumns(_items, columnFilter, columnFilterState, itemsDataColumns); }, [columnFilterState, _items]);
var filteredTable = useMemo(function () { return filterTable(filteredColumns, tableFilter, tableFilterState, itemsDataColumns); }, [tableFilterState, tableFilterValue, filteredColumns]);
var sortedItems = useMemo(function () { return sortItems(columns, columnSorter, filteredTable, itemsDataColumns, sorterState); }, [columnSorter, sorterState, filteredTable]);
var numberOfPages = _itemsPerPage ? Math.ceil(sortedItems.length / _itemsPerPage) : 1;
var firstItemOnActivePageIndex = _activePage ? (_activePage - 1) * _itemsPerPage : 0;
var currentItems = _activePage
? sortedItems.slice(firstItemOnActivePageIndex, firstItemOnActivePageIndex + _itemsPerPage)
: sortedItems;
useEffect(function () {
mountedRef.current && onFilteredItemsChange && onFilteredItemsChange(sortedItems);
}, [JSON.stringify(sortedItems)]);
var handleClean = function () {
setTableFilterState('');
setColumnFilterState({});
setSorterState([]);
};
var handleColumnFilterChange = function (colName, value, type) {
var isLazy = columnFilter && typeof columnFilter === 'object' && columnFilter.lazy === true;
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
return;
}
setActivePage(1);
setColumnFilterState(function (prevState) {
var newState = __assign({}, prevState);
if (value === '') {
delete newState[colName];
}
else {
newState[colName] = value;
}
return newState;
});
};
var handleItemsPerPageChange = function (event) {
if (typeof itemsPerPageSelect !== 'object' ||
(typeof itemsPerPageSelect === 'object' && !itemsPerPageSelect.external)) {
setItemsPerPage(Number(event.target.value));
}
};
var handleRowChecked = function (item, value) {
if (value && !isObjectInArray(_selected, item, ITEM_INTERNAL_KEYS)) {
setSelected(function (prevSelected) { return __spreadArray(__spreadArray([], prevSelected, true), [item], false); });
return;
}
setSelected(function (prevSelected) {
return prevSelected.filter(function (_item) { return !isObjectInArray([_item], item, ITEM_INTERNAL_KEYS); });
});
};
var handleSelectAllChecked = function () {
if (selectedAll === true) {
setSelected(_items.filter(function (item) { return item._selectable === false; }));
return;
}
onSelectAll && onSelectAll();
if (selectAll && typeof selectAll === 'object' && selectAll.external) {
return;
}
var selectable = _items.filter(function (item) { return item._selectable !== false || item._selected === true; });
if (selectable.length === _selected.length) {
setSelected(_items.filter(function (item) { return item._selectable === false && item._selected === true; }));
return;
}
var selected = selectable.map(function (item) {
return __assign({}, item);
});
setSelected(selected.map(function (item) {
for (var _i = 0, ITEM_INTERNAL_KEYS_2 = ITEM_INTERNAL_KEYS; _i < ITEM_INTERNAL_KEYS_2.length; _i++) {
var key = ITEM_INTERNAL_KEYS_2[_i];
delete item[key];
}
return item;
}));
};
var handleSorterChange = function (column, index, order) {
if (!isSortable(index, columns, columnSorter, itemsDataColumns, columnNames)) {
return;
}
var existingColumnState = sorterState.find(function (x) { return x.column === column; });
var multiple = typeof columnSorter === 'object' && columnSorter.multiple;
// If the column already has a sort state
if (existingColumnState) {
// No need to update if the order is already the same
if (existingColumnState.state === order) {
return;
}
// Remove the column from sorting if resetable and descending
if (typeof columnSorter === 'object' &&
columnSorter.resetable &&
existingColumnState.state === 'desc' &&
order !== 'asc') {
setSorterState(multiple ? sorterState.filter(function (x) { return x.column !== column; }) : []);
}
else {
// Toggle between ascending and descending
var newState_1 = {
column: column,
state: order || (existingColumnState.state === 'asc' ? 'desc' : 'asc'),
};
setSorterState(multiple
? sorterState.map(function (item) { return (item.column === column ? newState_1 : item); })
: [newState_1]);
}
}
else {
// If the column is not yet sorted, add it with the default or provided order
var newSorter = { column: column, state: order || 'asc' };
setSorterState(multiple ? __spreadArray(__spreadArray([], sorterState, true), [newSorter], false) : [newSorter]);
}
};
var handleTableFilterChange = function (value, type) {
var isLazy = tableFilter && typeof tableFilter === 'object' && tableFilter.lazy === true;
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
return;
}
setActivePage(1);
setTableFilterState(value);
};
useEffect(function () {
mountedRef.current = true;
}, []);
return (React.createElement(React.Fragment, null,
React.createElement("div", __assign({}, rest, { ref: ref }), (itemsPerPageSelect || tableFilter || cleaner) && (React.createElement("div", { className: "row my-2 mx-0" }, (tableFilter || cleaner) && (React.createElement(React.Fragment, null,
React.createElement("div", { className: "col-auto p-0" }, tableFilter && (React.createElement("div", { className: "row mb-2" },
React.createElement(CFormLabel, { className: "col-sm-auto col-form-label" }, tableFilterLabel),
React.createElement("div", { className: "col-sm-auto" },
React.createElement(CFormInput, { onInput: function (e) {
handleTableFilterChange(e.target.value, 'input');
}, onChange: function (e) {
handleTableFilterChange(e.target.value, 'change');
}, placeholder: tableFilterPlaceholder, value: tableFilterState || '' }))))),
React.createElement("div", { className: "col-auto p-0" }, cleaner && (React.createElement("button", __assign({ type: "button", className: "btn btn-transparent" }, (!(tableFilterState ||
sorterState.length > 0 ||
Object.values(columnFilterState).join('')) && {
disabled: true,
tabIndex: -1,
}), { onClick: function () { return handleClean(); }, onKeyDown: function (event) {
if (event.key === 'Enter')
handleClean();
} }),
React.createElement(CIcon, { width: 18, icon: cilFilterX }))))))))),
React.createElement("div", { className: "position-relative" },
React.createElement(CTable, __assign({}, tableProps),
header && (React.createElement(CSmartTableHead, __assign({}, tableHeadProps, { columnFilter: columnFilter, columnFilterState: columnFilterState, columns: columns !== null && columns !== void 0 ? columns : columnNames, columnSorter: columnSorter, items: _items, selectable: selectable, selectAll: selectAll, selectedAll: selectedAll, sorterState: sorterState, sortingIcon: sortingIcon, sortingIconAscending: sortingIconAscending, sortingIconDescending: sortingIconDescending, handleFilterOnChange: function (key, event) {
return handleColumnFilterChange(key, event, 'change');
}, handleFilterOnInput: function (key, event) { return handleColumnFilterChange(key, event, 'input'); }, handleOnCustomFilterChange: function (key, event) { return handleColumnFilterChange(key, event); }, handleSelectAllChecked: function () { return handleSelectAllChecked(); }, handleSort: function (key, index, order) { return handleSorterChange(key, index, order); } }))),
React.createElement(CSmartTableBody, __assign({ clickableRows: clickableRows, columnNames: columnNames, columns: columns !== null && columns !== void 0 ? columns : columnNames, currentItems: currentItems, firstItemOnActivePageIndex: firstItemOnActivePageIndex, noItemsLabel: noItemsLabel, onRowClick: function (item, index, columnName, event) {
return clickableRows && onRowClick && onRowClick(item, index, columnName, event);
}, onRowChecked: function (item, value) { return handleRowChecked(item, value); }, scopedColumns: scopedColumns, selectable: selectable, selected: _selected }, tableBodyProps)),
typeof footer === 'boolean' && footer && (React.createElement(CSmartTableHead, __assign({ as: CTableFoot }, tableFootProps, { columnFilter: false, columnSorter: false, columns: columns !== null && columns !== void 0 ? columns : columnNames, items: _items, handleSelectAllChecked: function () { return handleSelectAllChecked(); }, selectable: selectable, selectAll: selectAll, selectedAll: selectedAll, showGroups: false }))),
Array.isArray(footer) && (React.createElement(CTableFoot, __assign({}, tableFootProps),
React.createElement(CTableRow, null, footer.map(function (item, index) { return (React.createElement(CTableDataCell, __assign({}, (typeof item === 'object' && item._props && __assign({}, item._props)), { key: index }), typeof item === 'object' ? item.label : item)); }))))),
loading && (React.createElement(CElementCover, { boundaries: [
{ sides: ['top'], query: 'tbody' },
{ sides: ['bottom'], query: 'tbody' },
] }, elementCover))),
(pagination || itemsPerPageSelect) && (React.createElement("div", { className: "row" },
React.createElement("div", { className: "col" }, ((pagination && numberOfPages > 1) ||
(paginationProps && paginationProps.pages > 1)) && (React.createElement(CSmartPagination, __assign({ activePage: _activePage, onActivePageChange: function (page) {
pagination && typeof pagination === 'object' && pagination.external
? onActivePageChange && onActivePageChange(page)
: setActivePage(page);
}, pages: numberOfPages }, paginationProps)))),
React.createElement("div", { className: "col-auto ms-auto" }, itemsPerPageSelect && (React.createElement("div", { className: "row" },
React.createElement(CFormLabel, { className: "col-auto col-form-label" }, itemsPerPageLabel),
React.createElement("div", { className: "col-auto" },
React.createElement(CFormSelect, { defaultValue: _itemsPerPage, onChange: function (event) {
return handleItemsPerPageChange(event);
} }, itemsPerPageOptions &&
itemsPerPageOptions.map(function (number, index) {
return (React.createElement("option", { value: number, key: index }, number));
}))))))))));
});
CSmartTable.propTypes = {
activePage: PropTypes.number,
cleaner: PropTypes.bool,
clickableRows: PropTypes.bool,
columnFilter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
columnFilterValue: PropTypes.object,
columns: PropTypes.array,
columnSorter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
elementCover: PropTypes.node,
footer: PropTypes.oneOfType([PropTypes.bool, PropTypes.array]),
header: PropTypes.bool,
items: PropTypes.array,
itemsNumber: PropTypes.number,
itemsPerPage: PropTypes.number,
itemsPerPageLabel: PropTypes.string,
itemsPerPageOptions: PropTypes.array,
itemsPerPageSelect: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
loading: PropTypes.bool,
noItemsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
onActivePageChange: PropTypes.func,
onColumnFilterChange: PropTypes.func,
onFilteredItemsChange: PropTypes.func,
onItemsPerPageChange: PropTypes.func,
onRowClick: PropTypes.func,
onSelectAll: PropTypes.func,
onSelectedItemsChange: PropTypes.func,
onSorterChange: PropTypes.func, // TODO: change to `onColumnSorterChange` in v6
onTableFilterChange: PropTypes.func,
pagination: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
paginationProps: PropTypes.any, // TODO: update
scopedColumns: PropTypes.object,
selectable: PropTypes.bool,
selectAll: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
selected: PropTypes.array,
sorterValue: PropTypes.oneOfType([
PropTypes.shape({
column: PropTypes.string.isRequired,
state: PropTypes.oneOf(['asc', 'desc', 0]).isRequired,
}),
PropTypes.arrayOf(PropTypes.shape({
column: PropTypes.string.isRequired,
state: PropTypes.oneOf(['asc', 'desc', 0]).isRequired,
}).isRequired),
]),
sortingIcon: PropTypes.node,
sortingIconAscending: PropTypes.node,
sortingIconDescending: PropTypes.node,
tableBodyProps: PropTypes.object,
tableFootProps: PropTypes.object,
tableFilter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
tableFilterLabel: PropTypes.string,
tableFilterPlaceholder: PropTypes.string,
tableFilterValue: PropTypes.string,
tableHeadProps: PropTypes.object,
tableProps: PropTypes.object,
};
CSmartTable.displayName = 'CSmartTable';
export { CSmartTable };
//# sourceMappingURL=CSmartTable.js.map