@coreui/react-pro
Version:
UI Components Library for React.js
352 lines (348 loc) • 22 kB
JavaScript
'use strict';
var tslib_es6 = require('../../node_modules/tslib/tslib.es6.js');
var React = require('react');
var PropTypes = require('prop-types');
var index_esm = require('../../node_modules/@coreui/icons-react/dist/index.esm.js');
var CElementCover = require('../element-cover/CElementCover.js');
require('../form/CForm.js');
require('../form/CFormCheck.js');
require('../form/CFormControlValidation.js');
require('../form/CFormControlWrapper.js');
require('../form/CFormFeedback.js');
require('../form/CFormFloating.js');
var CFormInput = require('../form/CFormInput.js');
var CFormLabel = require('../form/CFormLabel.js');
require('../form/CFormRange.js');
var CFormSelect = require('../form/CFormSelect.js');
require('../form/CFormSwitch.js');
require('../form/CFormText.js');
require('../form/CFormTextarea.js');
require('../form/CInputGroup.js');
require('../form/CInputGroupText.js');
var CSmartPagination = require('../smart-pagination/CSmartPagination.js');
var CTable = require('../table/CTable.js');
require('../table/CTableBody.js');
require('../table/CTableCaption.js');
var CTableDataCell = require('../table/CTableDataCell.js');
var CTableFoot = require('../table/CTableFoot.js');
require('../table/CTableHead.js');
require('../table/CTableHeaderCell.js');
var CTableRow = require('../table/CTableRow.js');
var CSmartTableBody = require('./CSmartTableBody.js');
var CSmartTableHead = require('./CSmartTableHead.js');
var isObjectInArray = require('../../utils/isObjectInArray.js');
var consts = require('./consts.js');
var utils = require('./utils.js');
var cilSwapVertical = require('../../node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js');
var cilArrowTop = require('../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js');
var cilArrowBottom = require('../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js');
var cilFilterX = require('../../node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js');
const CSmartTable = React.forwardRef((_a, ref) => {
var { activePage = 1, cleaner, clickableRows, columnFilter, columnFilterValue, // TODO: consider to use only columnFilter prop
columns, columnSorter, elementCover, footer, header = true, items = [], itemsNumber, itemsPerPage = 10, itemsPerPageLabel = 'Items per page:', itemsPerPageOptions = [5, 10, 20, 50], itemsPerPageSelect, loading, noItemsLabel = 'No items found', onActivePageChange, onColumnFilterChange, onFilteredItemsChange, onItemsPerPageChange, onRowChecked, onRowClick, onSelectAll, onSelectedItemsChange, onSorterChange, onTableFilterChange, pagination, paginationProps, scopedColumns, selected, selectable, selectAll = true, sorterValue, sortingIcon = React.createElement(index_esm.CIcon, { width: 18, icon: cilSwapVertical.cilSwapVertical, key: "csv" }), sortingIconAscending = React.createElement(index_esm.CIcon, { width: 18, icon: cilArrowTop.cilArrowTop, key: "cat" }), sortingIconDescending = React.createElement(index_esm.CIcon, { width: 18, icon: cilArrowBottom.cilArrowBottom, key: "cab" }), tableBodyProps, tableFootProps, tableFilter, tableFilterLabel = 'Filter:', tableFilterPlaceholder = 'type string...', tableFilterValue, tableHeadProps, tableProps } = _a, rest = tslib_es6.__rest(_a, ["activePage", "cleaner", "clickableRows", "columnFilter", "columnFilterValue", "columns", "columnSorter", "elementCover", "footer", "header", "items", "itemsNumber", "itemsPerPage", "itemsPerPageLabel", "itemsPerPageOptions", "itemsPerPageSelect", "loading", "noItemsLabel", "onActivePageChange", "onColumnFilterChange", "onFilteredItemsChange", "onItemsPerPageChange", "onRowChecked", "onRowClick", "onSelectAll", "onSelectedItemsChange", "onSorterChange", "onTableFilterChange", "pagination", "paginationProps", "scopedColumns", "selected", "selectable", "selectAll", "sorterValue", "sortingIcon", "sortingIconAscending", "sortingIconDescending", "tableBodyProps", "tableFootProps", "tableFilter", "tableFilterLabel", "tableFilterPlaceholder", "tableFilterValue", "tableHeadProps", "tableProps"]);
const mountedRef = React.useRef(false);
const [_activePage, setActivePage] = React.useState(activePage);
const [_items, setItems] = React.useState([]);
const [_itemsPerPage, setItemsPerPage] = React.useState(itemsPerPage);
const [_selected, setSelected] = React.useState([]);
const [columnFilterState, setColumnFilterState] = React.useState({});
const [selectedAll, setSelectedAll] = React.useState();
const [sorterState, setSorterState] = React.useState([]);
const [tableFilterState, setTableFilterState] = React.useState(tableFilterValue !== null && tableFilterValue !== void 0 ? tableFilterValue : '');
const _itemsNumber = React.useMemo(() => itemsNumber !== null && itemsNumber !== void 0 ? itemsNumber : items.length, [itemsNumber, items.length]);
React.useEffect(() => {
setActivePage(activePage);
}, [activePage]);
React.useEffect(() => {
if (items.length < _itemsPerPage * _activePage - _itemsPerPage) {
setActivePage(1);
}
const selected = [];
for (const item of items) {
if (item._selected) {
const _item = Object.assign({}, item);
for (const key of consts.ITEM_INTERNAL_KEYS) {
delete _item[key]; // Remove internal keys
}
selected.push(_item); // Add cleaned item to selected array
}
}
if (selected.length > 0) {
setSelected([..._selected, ...selected]);
}
if (Array.isArray(items)) {
setItems([...items]);
}
}, [JSON.stringify(items)]);
React.useEffect(() => {
Array.isArray(selected) && setSelected(selected);
}, [JSON.stringify(selected)]);
React.useEffect(() => {
columnFilterValue && setColumnFilterState(columnFilterValue);
}, [JSON.stringify(columnFilterValue)]);
React.useEffect(() => {
sorterValue && setSorterState(Array.isArray(sorterValue) ? sorterValue : [sorterValue]);
}, [JSON.stringify(sorterValue)]);
React.useEffect(() => setItemsPerPage(itemsPerPage), [itemsPerPage]);
React.useEffect(() => {
mountedRef.current && onActivePageChange && onActivePageChange(_activePage);
}, [_activePage]);
React.useEffect(() => {
mountedRef.current && onItemsPerPageChange && onItemsPerPageChange(_itemsPerPage);
itemsPerPage !== _itemsPerPage && setActivePage(1); // TODO: set proper page after _itemsPerPage update
}, [_itemsPerPage]);
React.useEffect(() => {
const multiple = typeof columnSorter === 'object' && columnSorter.multiple;
mountedRef.current &&
sorterState &&
onSorterChange &&
onSorterChange(multiple ? sorterState : sorterState[0]);
}, [sorterState]);
React.useEffect(() => {
mountedRef.current && onColumnFilterChange && onColumnFilterChange(columnFilterState);
}, [columnFilterState]);
React.useEffect(() => {
mountedRef.current && onTableFilterChange && onTableFilterChange(tableFilterState);
}, [tableFilterState]);
React.useEffect(() => {
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]);
const columnNames = React.useMemo(() => utils.getColumnNames(columns, _items), [columns, _items]);
const itemsDataColumns = React.useMemo(() => columnNames.filter((name) => utils.getColumnNamesFromItems(_items).includes(name)), [columnNames, _items]);
const filteredColumns = React.useMemo(() => utils.filterColumns(_items, columnFilter, columnFilterState, itemsDataColumns), [columnFilterState, _items]);
const filteredTable = React.useMemo(() => utils.filterTable(filteredColumns, tableFilter, tableFilterState, itemsDataColumns), [tableFilterState, tableFilterValue, filteredColumns]);
const sortedItems = React.useMemo(() => utils.sortItems(columns, columnSorter, filteredTable, itemsDataColumns, sorterState), [columnSorter, sorterState, filteredTable]);
const numberOfPages = _itemsPerPage ? Math.ceil(sortedItems.length / _itemsPerPage) : 1;
const firstItemOnActivePageIndex = _activePage ? (_activePage - 1) * _itemsPerPage : 0;
const currentItems = _activePage
? sortedItems.slice(firstItemOnActivePageIndex, firstItemOnActivePageIndex + _itemsPerPage)
: sortedItems;
React.useEffect(() => {
mountedRef.current && onFilteredItemsChange && onFilteredItemsChange(sortedItems);
}, [JSON.stringify(sortedItems)]);
const handleClean = () => {
setTableFilterState('');
setColumnFilterState({});
setSorterState([]);
};
const handleColumnFilterChange = (colName, value, type) => {
const isLazy = columnFilter && typeof columnFilter === 'object' && columnFilter.lazy === true;
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
return;
}
setActivePage(1);
setColumnFilterState((prevState) => {
const newState = Object.assign({}, prevState);
if (value === '') {
delete newState[colName];
}
else {
newState[colName] = value;
}
return newState;
});
};
const handleItemsPerPageChange = (event) => {
if (typeof itemsPerPageSelect !== 'object' ||
(typeof itemsPerPageSelect === 'object' && !itemsPerPageSelect.external)) {
setItemsPerPage(Number(event.target.value));
}
};
const handleRowChecked = (item, value) => {
onRowChecked === null || onRowChecked === void 0 ? void 0 : onRowChecked(item, value);
if (value && !isObjectInArray.default(_selected, item, consts.ITEM_INTERNAL_KEYS)) {
setSelected((prevSelected) => [...prevSelected, item]);
return;
}
setSelected((prevSelected) => prevSelected.filter((_item) => !isObjectInArray.default([_item], item, consts.ITEM_INTERNAL_KEYS)));
};
const handleSelectAllChecked = () => {
onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll();
if (selectedAll === true) {
setSelected(_items.filter((item) => item._selectable === false));
return;
}
if (selectAll && typeof selectAll === 'object' && selectAll.external) {
return;
}
const selectable = _items.filter((item) => item._selectable !== false || item._selected === true);
if (selectable.length === _selected.length) {
setSelected(_items.filter((item) => item._selectable === false && item._selected === true));
return;
}
const selected = selectable.map((item) => {
return Object.assign({}, item);
});
setSelected(selected.map((item) => {
for (const key of consts.ITEM_INTERNAL_KEYS) {
delete item[key];
}
return item;
}));
};
const handleSorterChange = (column, index, order) => {
if (!utils.isSortable(index, columns, columnSorter, itemsDataColumns, columnNames)) {
return;
}
const existingColumnState = sorterState.find((x) => x.column === column);
const 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((x) => x.column !== column) : []);
}
else {
// Toggle between ascending and descending
const newState = {
column,
state: order || (existingColumnState.state === 'asc' ? 'desc' : 'asc'),
};
setSorterState(multiple
? sorterState.map((item) => (item.column === column ? newState : item))
: [newState]);
}
}
else {
// If the column is not yet sorted, add it with the default or provided order
const newSorter = { column, state: order || 'asc' };
setSorterState(multiple ? [...sorterState, newSorter] : [newSorter]);
}
};
const handleTableFilterChange = (value, type) => {
const isLazy = tableFilter && typeof tableFilter === 'object' && tableFilter.lazy === true;
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
return;
}
setActivePage(1);
setTableFilterState(value);
};
React.useEffect(() => {
mountedRef.current = true;
}, []);
return (React.createElement(React.Fragment, null,
React.createElement("div", Object.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.CFormLabel, { className: "col-sm-auto col-form-label" }, tableFilterLabel),
React.createElement("div", { className: "col-sm-auto" },
React.createElement(CFormInput.CFormInput, { onInput: (e) => {
handleTableFilterChange(e.target.value, 'input');
}, onChange: (e) => {
handleTableFilterChange(e.target.value, 'change');
}, placeholder: tableFilterPlaceholder, value: tableFilterState || '' }))))),
React.createElement("div", { className: "col-auto p-0" }, cleaner && (React.createElement("button", Object.assign({ type: "button", className: "btn btn-transparent" }, (!(tableFilterState ||
sorterState.length > 0 ||
Object.values(columnFilterState).join('')) && {
disabled: true,
tabIndex: -1,
}), { onClick: () => handleClean(), onKeyDown: (event) => {
if (event.key === 'Enter')
handleClean();
} }),
React.createElement(index_esm.CIcon, { width: 18, icon: cilFilterX.cilFilterX }))))))))),
React.createElement("div", { className: "position-relative" },
React.createElement(CTable.CTable, Object.assign({}, tableProps),
header && (React.createElement(CSmartTableHead.CSmartTableHead, Object.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: (key, event) => handleColumnFilterChange(key, event, 'change'), handleFilterOnInput: (key, event) => handleColumnFilterChange(key, event, 'input'), handleOnCustomFilterChange: (key, event) => handleColumnFilterChange(key, event), handleSelectAllChecked: () => handleSelectAllChecked(), handleSort: (key, index, order) => handleSorterChange(key, index, order) }))),
React.createElement(CSmartTableBody.CSmartTableBody, Object.assign({ clickableRows: clickableRows, columnNames: columnNames, columns: columns !== null && columns !== void 0 ? columns : columnNames, currentItems: currentItems, firstItemOnActivePageIndex: firstItemOnActivePageIndex, noItemsLabel: noItemsLabel, onRowClick: (item, index, columnName, event) => clickableRows && onRowClick && onRowClick(item, index, columnName, event), onRowChecked: (item, value) => handleRowChecked(item, value), scopedColumns: scopedColumns, selectable: selectable, selected: _selected }, tableBodyProps)),
typeof footer === 'boolean' && footer && (React.createElement(CSmartTableHead.CSmartTableHead, Object.assign({ as: CTableFoot.CTableFoot }, tableFootProps, { columnFilter: false, columnSorter: false, columns: columns !== null && columns !== void 0 ? columns : columnNames, items: _items, handleSelectAllChecked: () => handleSelectAllChecked(), selectable: selectable, selectAll: selectAll, selectedAll: selectedAll, showGroups: false }))),
Array.isArray(footer) && (React.createElement(CTableFoot.CTableFoot, Object.assign({}, tableFootProps),
React.createElement(CTableRow.CTableRow, null, footer.map((item, index) => (React.createElement(CTableDataCell.CTableDataCell, Object.assign({}, (typeof item === 'object' && item._props && Object.assign({}, item._props)), { key: index }), typeof item === 'object' ? item.label : item))))))),
loading && (React.createElement(CElementCover.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.CSmartPagination, Object.assign({ activePage: _activePage, onActivePageChange: (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.CFormLabel, { className: "col-auto col-form-label" }, itemsPerPageLabel),
React.createElement("div", { className: "col-auto" },
React.createElement(CFormSelect.CFormSelect, { defaultValue: _itemsPerPage, onChange: (event) => handleItemsPerPageChange(event) }, itemsPerPageOptions &&
itemsPerPageOptions.map((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,
onRowChecked: 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';
exports.CSmartTable = CSmartTable;
//# sourceMappingURL=CSmartTable.js.map