@coreui/react-pro 4.8.0 → 4.9.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/alert/CAlert.d.ts +1 -1
- package/dist/components/avatar/CAvatar.d.ts +1 -1
- package/dist/components/badge/CBadge.d.ts +1 -1
- package/dist/components/button/CButton.d.ts +1 -1
- package/dist/components/calendar/index.d.ts +2 -0
- package/dist/components/calendar/utils.d.ts +22 -0
- package/dist/components/callout/CCallout.d.ts +1 -1
- package/dist/components/card/CCard.d.ts +1 -1
- package/dist/components/date-picker/CDatePicker.d.ts +1 -1
- package/dist/components/date-range-picker/CDateRangePicker.d.ts +3 -3
- package/dist/components/date-range-picker/utils.d.ts +1 -0
- package/dist/components/dropdown/CDropdown.d.ts +1 -1
- package/dist/components/dropdown/CDropdownToggle.d.ts +1 -1
- package/dist/components/element-cover/CElementCover.d.ts +0 -4
- package/dist/components/element-cover/index.d.ts +2 -0
- package/dist/components/form/CFormCheck.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/list-group/CListGroupItem.d.ts +4 -5
- package/dist/components/multi-select/CMultiSelect.d.ts +1 -13
- package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
- package/dist/components/multi-select/CMultiSelectOptions.d.ts +1 -1
- package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
- package/dist/components/multi-select/types.d.ts +14 -0
- package/dist/components/multi-select/utils.d.ts +6 -0
- package/dist/components/navbar/CNavbar.d.ts +1 -1
- package/dist/components/offcanvas/COffcanvas.d.ts +7 -1
- package/dist/components/picker/CPicker.d.ts +1 -1
- package/dist/components/placeholder/CPlaceholder.d.ts +1 -1
- package/dist/components/popover/CPopover.d.ts +1 -1
- package/dist/components/progress/CProgressBar.d.ts +1 -1
- package/dist/components/smart-table/CSmartTableBody.d.ts +6 -5
- package/dist/components/smart-table/CSmartTableHead.d.ts +6 -3
- package/dist/components/smart-table/CSmartTableInterface.d.ts +38 -59
- package/dist/components/smart-table/types.d.ts +53 -0
- package/dist/components/smart-table/utils.d.ts +16 -0
- package/dist/components/spinner/CSpinner.d.ts +1 -1
- package/dist/components/table/CTable.d.ts +2 -18
- package/dist/components/table/CTableBody.d.ts +1 -1
- package/dist/components/table/CTableDataCell.d.ts +1 -1
- package/dist/components/table/CTableFoot.d.ts +1 -1
- package/dist/components/table/CTableHead.d.ts +1 -1
- package/dist/components/table/CTableHeaderCell.d.ts +1 -1
- package/dist/components/table/CTableRow.d.ts +1 -1
- package/dist/components/table/types.d.ts +17 -0
- package/dist/components/table/utils.d.ts +5 -0
- package/dist/components/time-picker/types.d.ts +15 -0
- package/dist/components/time-picker/utils.d.ts +23 -0
- package/dist/components/toast/CToast.d.ts +1 -1
- package/dist/components/toast/CToastClose.d.ts +1 -1
- package/dist/components/tooltip/CTooltip.d.ts +1 -1
- package/dist/components/virtual-scroller/CVirtualScroller.d.ts +0 -8
- package/dist/components/widgets/CWidgetStatsA.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsB.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsC.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsD.d.ts +1 -1
- package/dist/components/widgets/CWidgetStatsF.d.ts +1 -1
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/useForkedRef.d.ts +7 -0
- package/dist/hooks/useStateWithCallback.d.ts +2 -0
- package/dist/index.es.js +1171 -1109
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1171 -1108
- package/dist/index.js.map +1 -1
- package/dist/props.d.ts +8 -0
- package/dist/types.d.ts +7 -0
- package/dist/utils/index.d.ts +2 -3
- package/dist/utils/isObjectInArray.d.ts +2 -0
- package/package.json +11 -11
- package/src/components/accordion/CAccordionBody.tsx +1 -0
- package/src/components/accordion/CAccordionCollapse.tsx +1 -0
- package/src/components/alert/CAlert.tsx +3 -2
- package/src/components/avatar/CAvatar.tsx +2 -8
- package/src/components/backdrop/CBackdrop.tsx +2 -2
- package/src/components/badge/CBadge.tsx +2 -10
- package/src/components/button/CButton.tsx +3 -1
- package/src/components/calendar/CCalendar.tsx +351 -240
- package/src/components/calendar/index.ts +3 -0
- package/src/{utils/calendar.ts → components/calendar/utils.ts} +1 -47
- package/src/components/callout/CCallout.tsx +2 -1
- package/src/components/card/CCard.tsx +2 -1
- package/src/components/carousel/CCarousel.tsx +1 -1
- package/src/components/carousel/CCarouselItem.tsx +1 -1
- package/src/components/collapse/CCollapse.tsx +1 -1
- package/src/components/date-picker/CDatePicker.tsx +1 -1
- package/src/components/date-range-picker/CDateRangePicker.tsx +4 -4
- package/src/components/date-range-picker/utils.ts +49 -0
- package/src/components/dropdown/CDropdown.tsx +3 -2
- package/src/components/dropdown/CDropdownItem.tsx +1 -2
- package/src/components/dropdown/CDropdownMenu.tsx +2 -1
- package/src/components/dropdown/CDropdownToggle.tsx +5 -4
- package/src/components/element-cover/CElementCover.tsx +16 -22
- package/src/components/element-cover/index.ts +3 -0
- package/src/components/form/CFormCheck.tsx +3 -3
- package/src/components/form/CFormControlValidation.tsx +0 -1
- package/src/components/form/CFormControlWrapper.tsx +0 -1
- package/src/components/form/CFormInput.tsx +8 -4
- package/src/components/form/CFormRange.tsx +1 -2
- package/src/components/form/CFormSelect.tsx +1 -2
- package/src/components/form/CFormTextarea.tsx +1 -2
- package/src/components/index.ts +1 -0
- package/src/components/list-group/CListGroupItem.tsx +8 -8
- package/src/components/list-group/CListGroupItem.tsx~HEAD +3 -1
- package/src/components/modal/CModal.tsx +2 -2
- package/src/components/modal/CModalHeader.tsx +3 -2
- package/src/components/multi-select/CMultiSelect.tsx +15 -74
- package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
- package/src/components/multi-select/CMultiSelectOptions.tsx +2 -2
- package/src/components/multi-select/CMultiSelectSelection.tsx +1 -1
- package/src/components/multi-select/types.ts +15 -0
- package/src/components/multi-select/utils.ts +92 -0
- package/src/components/nav/CNavItem.tsx +1 -0
- package/src/components/nav/CNavLink.tsx +4 -3
- package/src/components/navbar/CNavbar.tsx +2 -1
- package/src/components/offcanvas/COffcanvas.tsx +38 -19
- package/src/components/picker/CPicker.tsx +1 -1
- package/src/components/placeholder/CPlaceholder.tsx +2 -1
- package/src/components/popover/CPopover.tsx +2 -1
- package/src/components/progress/CProgress.tsx +1 -0
- package/src/components/progress/CProgressBar.tsx +2 -1
- package/src/components/sidebar/CSidebar.tsx +3 -2
- package/src/components/smart-table/CSmartTable.tsx +263 -257
- package/src/components/smart-table/CSmartTableBody.tsx +98 -107
- package/src/components/smart-table/CSmartTableCleaner.tsx +1 -1
- package/src/components/smart-table/CSmartTableFilter.tsx +1 -3
- package/src/components/smart-table/CSmartTableHead.tsx +56 -103
- package/src/components/smart-table/CSmartTableInterface.tsx +49 -71
- package/src/components/smart-table/CSmartTableItemsPerPageSelector.tsx +1 -2
- package/src/components/smart-table/types.ts +65 -0
- package/src/components/smart-table/utils.ts +199 -0
- package/src/components/spinner/CSpinner.tsx +2 -1
- package/src/components/table/CTable.tsx +25 -59
- package/src/components/table/CTableBody.tsx +2 -1
- package/src/components/table/CTableDataCell.tsx +2 -1
- package/src/components/table/CTableFoot.tsx +2 -1
- package/src/components/table/CTableHead.tsx +2 -1
- package/src/components/table/CTableHeaderCell.tsx +2 -1
- package/src/components/table/CTableRow.tsx +2 -1
- package/src/components/table/types.ts +20 -0
- package/src/components/table/utils.ts +29 -0
- package/src/components/tabs/CTabPane.tsx +2 -1
- package/src/components/time-picker/CTimePicker.tsx +48 -23
- package/src/components/time-picker/CTimePickerRollCol.tsx +1 -1
- package/src/components/time-picker/types.ts +15 -0
- package/src/{utils/time.ts → components/time-picker/utils.ts} +43 -2
- package/src/components/toast/CToast.tsx +4 -4
- package/src/components/toast/CToastClose.tsx +2 -2
- package/src/components/toast/CToaster.tsx +2 -1
- package/src/components/tooltip/CTooltip.tsx +3 -2
- package/src/components/virtual-scroller/CVirtualScroller.tsx +32 -55
- package/src/components/widgets/CWidgetStatsA.tsx +3 -3
- package/src/components/widgets/CWidgetStatsB.tsx +4 -4
- package/src/components/widgets/CWidgetStatsC.tsx +4 -4
- package/src/components/widgets/CWidgetStatsD.tsx +4 -5
- package/src/components/widgets/CWidgetStatsE.tsx +1 -2
- package/src/components/widgets/CWidgetStatsF.tsx +3 -4
- package/src/{components/Types.tsx → props.ts} +1 -68
- package/src/types.ts +68 -0
- package/src/utils/index.ts +2 -3
- package/src/utils/isObjectInArray.ts +14 -0
- package/src/components/multi-select/CMultiSelectCleaner.tsx +0 -18
- package/src/utils/getNextSibling.ts +0 -18
- package/src/utils/getPreviousSibling.ts +0 -18
- /package/src/{utils/hooks → hooks}/index.ts +0 -0
- /package/src/{utils/hooks → hooks}/useForkedRef.ts +0 -0
- /package/src/{utils/hooks → hooks}/useStateWithCallback.ts +0 -0
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import React, { ChangeEvent, forwardRef, useEffect, useMemo, useRef, useState } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
|
|
4
|
-
import { cilArrowBottom, cilArrowTop, cilSwapVertical } from '@coreui/icons
|
|
4
|
+
import { cilArrowBottom, cilArrowTop, cilSwapVertical } from '@coreui/icons'
|
|
5
|
+
import CIcon from '@coreui/icons-react'
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
FooterItem,
|
|
10
|
-
Item,
|
|
11
|
-
ItemInternal,
|
|
12
|
-
SorterValue,
|
|
13
|
-
} from './CSmartTableInterface'
|
|
14
|
-
|
|
15
|
-
import { CElementCover } from '../element-cover/CElementCover'
|
|
16
|
-
import { CSmartPagination } from '../smart-pagination/CSmartPagination'
|
|
7
|
+
import { CElementCover } from '../element-cover'
|
|
8
|
+
import { CFormInput, CFormLabel, CFormSelect } from '../form'
|
|
9
|
+
import { CSmartPagination } from '../smart-pagination'
|
|
17
10
|
import { CTable, CTableDataCell, CTableFoot, CTableRow } from '../table'
|
|
18
11
|
|
|
12
|
+
import { CSmartTableProps } from './CSmartTableInterface'
|
|
13
|
+
import type { ColumnFilterValue, FooterItem, Item, SorterValue } from './types'
|
|
14
|
+
|
|
19
15
|
import { CSmartTableBody } from './CSmartTableBody'
|
|
20
16
|
import { CSmartTableCleaner } from './CSmartTableCleaner'
|
|
21
|
-
import { CSmartTableFilter } from './CSmartTableFilter'
|
|
22
17
|
import { CSmartTableHead } from './CSmartTableHead'
|
|
23
|
-
import { CSmartTableItemsPerPageSelector } from './CSmartTableItemsPerPageSelector'
|
|
24
18
|
|
|
25
|
-
import
|
|
19
|
+
import { isObjectInArray } from '../../utils'
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
filterColumns,
|
|
23
|
+
filterTable,
|
|
24
|
+
getColumnNames,
|
|
25
|
+
getColumnNamesFromItems,
|
|
26
|
+
isSortable,
|
|
27
|
+
sortItems,
|
|
28
|
+
} from './utils'
|
|
26
29
|
|
|
27
30
|
export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
28
31
|
(
|
|
@@ -34,9 +37,11 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
34
37
|
columnFilterValue, // TODO: consider to use only columnFilter prop
|
|
35
38
|
columns,
|
|
36
39
|
columnSorter,
|
|
40
|
+
elementCover,
|
|
37
41
|
footer,
|
|
38
42
|
header = true,
|
|
39
43
|
items,
|
|
44
|
+
itemsNumber,
|
|
40
45
|
itemsPerPage = 10,
|
|
41
46
|
itemsPerPageLabel = 'Items per page:',
|
|
42
47
|
itemsPerPageOptions = [5, 10, 20, 50],
|
|
@@ -48,13 +53,16 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
48
53
|
onFilteredItemsChange,
|
|
49
54
|
onItemsPerPageChange,
|
|
50
55
|
onRowClick,
|
|
56
|
+
onSelectAll,
|
|
51
57
|
onSelectedItemsChange,
|
|
52
58
|
onSorterChange,
|
|
53
59
|
onTableFilterChange,
|
|
54
60
|
pagination,
|
|
55
61
|
paginationProps,
|
|
56
62
|
scopedColumns,
|
|
63
|
+
selected,
|
|
57
64
|
selectable,
|
|
65
|
+
selectAll = true,
|
|
58
66
|
sorterValue,
|
|
59
67
|
sortingIcon = <CIcon width={18} icon={cilSwapVertical} key="csv" />,
|
|
60
68
|
sortingIconAscending = <CIcon width={18} icon={cilArrowTop} key="cat" />,
|
|
@@ -71,12 +79,12 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
71
79
|
},
|
|
72
80
|
ref,
|
|
73
81
|
) => {
|
|
74
|
-
// instance data
|
|
75
82
|
const mountedRef = useRef(false)
|
|
76
|
-
|
|
77
|
-
const [
|
|
78
|
-
const [
|
|
83
|
+
const [_activePage, setActivePage] = useState(activePage)
|
|
84
|
+
const [_items, setItems] = useState<Item[]>([])
|
|
85
|
+
const [_itemsNumber, setItemsNumber] = useState(itemsNumber)
|
|
79
86
|
const [_itemsPerPage, setItemsPerPage] = useState(itemsPerPage)
|
|
87
|
+
const [_selected, setSelected] = useState<Item[]>([])
|
|
80
88
|
const [columnFilterState, setColumnFilterState] = useState<ColumnFilterValue>({})
|
|
81
89
|
const [selectedAll, setSelectedAll] = useState<boolean | string>()
|
|
82
90
|
const [sorterState, setSorterState] = useState<SorterValue>({})
|
|
@@ -88,266 +96,225 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
88
96
|
setActivePage(activePage)
|
|
89
97
|
}, [activePage])
|
|
90
98
|
|
|
91
|
-
|
|
92
|
-
useMemo(() => {
|
|
99
|
+
useEffect(() => {
|
|
93
100
|
if (items && items.length < _itemsPerPage * _activePage - _itemsPerPage) {
|
|
94
101
|
setActivePage(1)
|
|
95
102
|
}
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
items &&
|
|
105
|
+
items.forEach((item: Item) => {
|
|
106
|
+
if (item._selected) {
|
|
107
|
+
const _item = { ...item }
|
|
108
|
+
delete _item['_cellProps']
|
|
109
|
+
delete _item['_props']
|
|
110
|
+
delete _item['_selected']
|
|
111
|
+
setSelected([..._selected, _item])
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
if (Array.isArray(items)) {
|
|
116
|
+
setItems(items)
|
|
117
|
+
setItemsNumber(itemsNumber || items.length)
|
|
118
|
+
}
|
|
104
119
|
}, [JSON.stringify(items)])
|
|
105
120
|
|
|
106
|
-
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
Array.isArray(selected) && setSelected(selected)
|
|
123
|
+
}, [JSON.stringify(selected)])
|
|
124
|
+
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
itemsNumber && setItemsNumber(itemsNumber)
|
|
127
|
+
}, [itemsNumber])
|
|
128
|
+
|
|
129
|
+
useEffect(() => {
|
|
107
130
|
columnFilterValue && setColumnFilterState(columnFilterValue)
|
|
108
131
|
}, [JSON.stringify(columnFilterValue)])
|
|
109
132
|
|
|
110
|
-
|
|
133
|
+
useEffect(() => {
|
|
111
134
|
setSorterState({ ...sorterValue })
|
|
112
135
|
}, [JSON.stringify(sorterValue)])
|
|
113
136
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// functions
|
|
117
|
-
|
|
118
|
-
const isSortable = (i: number): boolean | undefined => {
|
|
119
|
-
const isDataColumn = itemsDataColumns.includes(rawColumnNames[i])
|
|
120
|
-
let column
|
|
121
|
-
if (columns) column = columns[i]
|
|
122
|
-
return (
|
|
123
|
-
columnSorter &&
|
|
124
|
-
(!columns ||
|
|
125
|
-
typeof column !== 'object' ||
|
|
126
|
-
(typeof column === 'object' &&
|
|
127
|
-
(typeof column.sorter === 'undefined' || column.sorter))) &&
|
|
128
|
-
isDataColumn
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const sorterChange = (column: string, index: number): void => {
|
|
133
|
-
if (!isSortable(index)) {
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
//if column changed or sort was descending change asc to true
|
|
137
|
-
const state = sorterState ? sorterState : { column: '', state: '' }
|
|
138
|
-
|
|
139
|
-
if (state.column === column) {
|
|
140
|
-
if (state.state === 0) {
|
|
141
|
-
state.state = 'asc'
|
|
142
|
-
} else if (state.state === 'asc') {
|
|
143
|
-
state.state = 'desc'
|
|
144
|
-
} else {
|
|
145
|
-
if (typeof columnSorter === 'object' && !columnSorter.resetable) {
|
|
146
|
-
state.state = 'asc'
|
|
147
|
-
} else {
|
|
148
|
-
state.state = 0
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
state.column = column
|
|
153
|
-
state.state = 'asc'
|
|
154
|
-
}
|
|
155
|
-
setSorterState({ ...state })
|
|
156
|
-
}
|
|
137
|
+
useEffect(() => setItemsPerPage(itemsPerPage), [itemsPerPage])
|
|
157
138
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
(typeof itemsPerPageSelect === 'object' && !itemsPerPageSelect.external)
|
|
162
|
-
)
|
|
163
|
-
setItemsPerPage(Number((event.target as HTMLSelectElement).value))
|
|
164
|
-
}
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
mountedRef.current && onActivePageChange && onActivePageChange(_activePage)
|
|
141
|
+
}, [_activePage])
|
|
165
142
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
const newState = { ...columnFilterState, [`${colName}`]: value }
|
|
172
|
-
setActivePage(1)
|
|
173
|
-
setColumnFilterState(newState)
|
|
174
|
-
}
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
mountedRef.current && onItemsPerPageChange && onItemsPerPageChange(_itemsPerPage)
|
|
145
|
+
itemsPerPage !== _itemsPerPage && setActivePage(1) // TODO: set proper page after _itemsPerPage update
|
|
146
|
+
}, [_itemsPerPage])
|
|
175
147
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
setActivePage(1)
|
|
182
|
-
setTableFilterState(value)
|
|
183
|
-
}
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
mountedRef.current && sorterState && onSorterChange && onSorterChange(sorterState)
|
|
150
|
+
}, [JSON.stringify(sorterState)])
|
|
184
151
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
setSorterState({})
|
|
189
|
-
}
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
mountedRef.current && onColumnFilterChange && onColumnFilterChange(columnFilterState)
|
|
154
|
+
}, [columnFilterState])
|
|
190
155
|
|
|
191
|
-
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
mountedRef.current && onTableFilterChange && onTableFilterChange(tableFilterState)
|
|
158
|
+
}, [tableFilterState])
|
|
192
159
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
})
|
|
199
|
-
: genCols //! || el
|
|
200
|
-
const itemsDataColumns = rawColumnNames.filter((name) => genCols.includes(name))
|
|
201
|
-
|
|
202
|
-
// variables
|
|
203
|
-
const filteredColumns: ItemInternal[] = useMemo(() => {
|
|
204
|
-
let items = _items
|
|
205
|
-
if (columnFilter && typeof columnFilter === 'object' && columnFilter.external) {
|
|
206
|
-
return items
|
|
207
|
-
}
|
|
208
|
-
Object.entries(columnFilterState).forEach(([key, value]) => {
|
|
209
|
-
if (value instanceof Function) {
|
|
210
|
-
items = items.filter((item) => value(item[key]))
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
if (selectable) {
|
|
162
|
+
onSelectedItemsChange && onSelectedItemsChange(_selected)
|
|
163
|
+
if (_selected.length === _itemsNumber) {
|
|
164
|
+
setSelectedAll(true)
|
|
211
165
|
return
|
|
212
166
|
}
|
|
213
167
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return String(item[key]).toLowerCase().includes(columnFilter)
|
|
218
|
-
})
|
|
168
|
+
if (_selected.length === 0) {
|
|
169
|
+
setSelectedAll(false)
|
|
170
|
+
return
|
|
219
171
|
}
|
|
220
|
-
})
|
|
221
|
-
return items
|
|
222
|
-
}, [columnFilterState, JSON.stringify(_items)])
|
|
223
172
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
!tableFilterState ||
|
|
228
|
-
(tableFilter && typeof tableFilter === 'object' && tableFilter.external)
|
|
229
|
-
) {
|
|
230
|
-
return items
|
|
231
|
-
}
|
|
232
|
-
const filter = tableFilterState.toLowerCase()
|
|
233
|
-
const valueContainFilter = (val: any) => String(val).toLowerCase().includes(filter)
|
|
234
|
-
items = items.filter((item) => {
|
|
235
|
-
return !!itemsDataColumns.find((key) => valueContainFilter(item[key]))
|
|
236
|
-
})
|
|
237
|
-
return items
|
|
238
|
-
}, [tableFilterState, JSON.stringify(tableFilterValue), JSON.stringify(filteredColumns)])
|
|
239
|
-
|
|
240
|
-
const sortedItems: ItemInternal[] = useMemo(() => {
|
|
241
|
-
const col = sorterState?.column
|
|
242
|
-
if (
|
|
243
|
-
!col ||
|
|
244
|
-
!itemsDataColumns.includes(col) ||
|
|
245
|
-
(columnSorter && typeof columnSorter === 'object' && columnSorter.external)
|
|
246
|
-
) {
|
|
247
|
-
return filteredTable
|
|
173
|
+
if (_selected.length !== 0 && _selected.length !== _itemsNumber) {
|
|
174
|
+
setSelectedAll('indeterminate')
|
|
175
|
+
}
|
|
248
176
|
}
|
|
177
|
+
}, [JSON.stringify(_selected), _itemsNumber])
|
|
249
178
|
|
|
250
|
-
|
|
251
|
-
const sorted = filteredTable.slice().sort((item, item2) => {
|
|
252
|
-
const value = item[col]
|
|
253
|
-
const value2 = item2[col]
|
|
254
|
-
const a = typeof value === 'number' ? value : String(value).toLowerCase()
|
|
255
|
-
const b = typeof value2 === 'number' ? value2 : String(value2).toLowerCase()
|
|
256
|
-
return a > b ? 1 * flip : b > a ? -1 * flip : 0
|
|
257
|
-
})
|
|
258
|
-
return sorted
|
|
259
|
-
}, [
|
|
260
|
-
JSON.stringify(filteredTable),
|
|
261
|
-
JSON.stringify(sorterState),
|
|
262
|
-
JSON.stringify(columnSorter),
|
|
263
|
-
JSON.stringify(filteredColumns),
|
|
264
|
-
JSON.stringify(_items),
|
|
265
|
-
])
|
|
179
|
+
const columnNames = useMemo(() => getColumnNames(columns, _items), [columns, _items])
|
|
266
180
|
|
|
267
|
-
const
|
|
181
|
+
const itemsDataColumns = useMemo(
|
|
182
|
+
() => columnNames.filter((name) => getColumnNamesFromItems(_items).includes(name)),
|
|
183
|
+
[columnNames, _items],
|
|
184
|
+
)
|
|
268
185
|
|
|
269
|
-
const
|
|
186
|
+
const filteredColumns: Item[] = useMemo(
|
|
187
|
+
() => filterColumns(_items, columnFilter, columnFilterState, itemsDataColumns),
|
|
188
|
+
[columnFilterState, JSON.stringify(_items)],
|
|
189
|
+
)
|
|
270
190
|
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
191
|
+
const filteredTable: Item[] = useMemo(
|
|
192
|
+
() => filterTable(filteredColumns, tableFilter, tableFilterState, itemsDataColumns),
|
|
193
|
+
[tableFilterState, JSON.stringify(tableFilterValue), JSON.stringify(filteredColumns)],
|
|
274
194
|
)
|
|
275
195
|
|
|
276
|
-
const
|
|
196
|
+
const sortedItems: Item[] = useMemo(
|
|
197
|
+
() => sortItems(columnSorter, filteredTable, itemsDataColumns, sorterState),
|
|
198
|
+
[
|
|
199
|
+
JSON.stringify(filteredTable),
|
|
200
|
+
JSON.stringify(sorterState),
|
|
201
|
+
JSON.stringify(columnSorter),
|
|
202
|
+
JSON.stringify(filteredColumns),
|
|
203
|
+
JSON.stringify(_items),
|
|
204
|
+
],
|
|
205
|
+
)
|
|
277
206
|
|
|
278
|
-
const
|
|
279
|
-
tableFilterState || sorterState?.column || Object.values(columnFilterState).join('')
|
|
207
|
+
const numberOfPages: number = _itemsPerPage ? Math.ceil(sortedItems.length / _itemsPerPage) : 1
|
|
280
208
|
|
|
281
|
-
|
|
209
|
+
const firstItemOnActivePageIndex: number = _activePage ? (_activePage - 1) * _itemsPerPage : 0
|
|
282
210
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
211
|
+
const currentItems: Item[] = _activePage
|
|
212
|
+
? sortedItems.slice(firstItemOnActivePageIndex, firstItemOnActivePageIndex + _itemsPerPage)
|
|
213
|
+
: sortedItems
|
|
286
214
|
|
|
287
215
|
useEffect(() => {
|
|
288
|
-
mountedRef.current &&
|
|
289
|
-
|
|
290
|
-
}, [_itemsPerPage])
|
|
216
|
+
mountedRef.current && onFilteredItemsChange && onFilteredItemsChange(sortedItems)
|
|
217
|
+
}, [JSON.stringify(sortedItems)])
|
|
291
218
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
219
|
+
const handleClean = (): void => {
|
|
220
|
+
setTableFilterState('')
|
|
221
|
+
setColumnFilterState({})
|
|
222
|
+
setSorterState({})
|
|
223
|
+
}
|
|
295
224
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
225
|
+
const handleColumnFilterChange = (colName: string, value: any, type?: string): void => {
|
|
226
|
+
const isLazy = columnFilter && typeof columnFilter === 'object' && columnFilter.lazy === true
|
|
227
|
+
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
|
|
228
|
+
return
|
|
229
|
+
}
|
|
299
230
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
231
|
+
const newState = { ...columnFilterState, [`${colName}`]: value }
|
|
232
|
+
setActivePage(1)
|
|
233
|
+
setColumnFilterState(newState)
|
|
234
|
+
}
|
|
303
235
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
236
|
+
const handleItemsPerPageChange = (event: ChangeEvent<HTMLSelectElement>): void => {
|
|
237
|
+
if (
|
|
238
|
+
typeof itemsPerPageSelect !== 'object' ||
|
|
239
|
+
(typeof itemsPerPageSelect === 'object' && !itemsPerPageSelect.external)
|
|
240
|
+
) {
|
|
241
|
+
setItemsPerPage(Number((event.target as HTMLSelectElement).value))
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const handleRowChecked = (item: Item, value: boolean) => {
|
|
246
|
+
if (value && !isObjectInArray(_selected, item, ['_cellProps', '_props', '_selected'])) {
|
|
247
|
+
setSelected([..._selected, item])
|
|
248
|
+
return
|
|
249
|
+
}
|
|
307
250
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
251
|
+
setSelected(
|
|
252
|
+
_selected.filter(
|
|
253
|
+
(_item: Item) => !isObjectInArray([_item], item, ['_cellProps', '_props', '_selected']),
|
|
254
|
+
),
|
|
255
|
+
)
|
|
312
256
|
}
|
|
313
257
|
|
|
314
258
|
const handleSelectAllChecked = () => {
|
|
315
259
|
if (selectedAll === true) {
|
|
316
|
-
|
|
317
|
-
_items.map((item: ItemInternal) => {
|
|
318
|
-
return { ...item, _selected: false }
|
|
319
|
-
}),
|
|
320
|
-
)
|
|
260
|
+
setSelected([])
|
|
321
261
|
return
|
|
322
262
|
}
|
|
323
263
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
264
|
+
onSelectAll && onSelectAll()
|
|
265
|
+
|
|
266
|
+
if (selectAll && typeof selectAll === 'object' && selectAll.external) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
setSelected(
|
|
271
|
+
_items.map((item) => {
|
|
272
|
+
delete item['_cellProps']
|
|
273
|
+
delete item['_props']
|
|
274
|
+
delete item['_selected']
|
|
275
|
+
|
|
276
|
+
return item
|
|
327
277
|
}),
|
|
328
278
|
)
|
|
329
279
|
}
|
|
330
280
|
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
281
|
+
const handleSorterChange = (column: string, index: number): void => {
|
|
282
|
+
if (!isSortable(index, columns, columnSorter, itemsDataColumns, columnNames)) {
|
|
283
|
+
return
|
|
284
|
+
}
|
|
335
285
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
return
|
|
339
|
-
}
|
|
286
|
+
//if column changed or sort was descending change asc to true
|
|
287
|
+
const state = sorterState ? sorterState : { column: '', state: '' }
|
|
340
288
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
289
|
+
if (state.column === column) {
|
|
290
|
+
if (state.state === 0) {
|
|
291
|
+
state.state = 'asc'
|
|
292
|
+
} else if (state.state === 'asc') {
|
|
293
|
+
state.state = 'desc'
|
|
294
|
+
} else {
|
|
295
|
+
if (typeof columnSorter === 'object' && !columnSorter.resetable) {
|
|
296
|
+
state.state = 'asc'
|
|
297
|
+
} else {
|
|
298
|
+
state.state = 0
|
|
299
|
+
}
|
|
344
300
|
}
|
|
301
|
+
} else {
|
|
302
|
+
state.column = column
|
|
303
|
+
state.state = 'asc'
|
|
304
|
+
}
|
|
345
305
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
306
|
+
setSorterState({ ...state })
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const handleTableFilterChange = (value: string, type: string): void => {
|
|
310
|
+
const isLazy = tableFilter && typeof tableFilter === 'object' && tableFilter.lazy === true
|
|
311
|
+
if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
|
|
312
|
+
return
|
|
349
313
|
}
|
|
350
|
-
|
|
314
|
+
|
|
315
|
+
setActivePage(1)
|
|
316
|
+
setTableFilterState(value)
|
|
317
|
+
}
|
|
351
318
|
|
|
352
319
|
useEffect(() => {
|
|
353
320
|
mountedRef.current = true
|
|
@@ -362,26 +329,39 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
362
329
|
<>
|
|
363
330
|
<div className="col-auto p-0">
|
|
364
331
|
{tableFilter && (
|
|
365
|
-
<
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
332
|
+
<div className="row mb-2">
|
|
333
|
+
<CFormLabel className="col-sm-auto col-form-label">
|
|
334
|
+
{tableFilterLabel}
|
|
335
|
+
</CFormLabel>
|
|
336
|
+
<div className="col-sm-auto">
|
|
337
|
+
<CFormInput
|
|
338
|
+
onInput={(e) => {
|
|
339
|
+
handleTableFilterChange((e.target as HTMLInputElement).value, 'input')
|
|
340
|
+
}}
|
|
341
|
+
onChange={(e) => {
|
|
342
|
+
handleTableFilterChange(
|
|
343
|
+
(e.target as HTMLInputElement).value,
|
|
344
|
+
'change',
|
|
345
|
+
)
|
|
346
|
+
}}
|
|
347
|
+
placeholder={tableFilterPlaceholder}
|
|
348
|
+
value={tableFilterState || ''}
|
|
349
|
+
/>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
376
352
|
)}
|
|
377
353
|
</div>
|
|
378
354
|
<div className="col-auto p-0">
|
|
379
355
|
{cleaner && (
|
|
380
356
|
<CSmartTableCleaner
|
|
381
|
-
isFiltered={
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
357
|
+
isFiltered={
|
|
358
|
+
tableFilterState ||
|
|
359
|
+
sorterState?.column ||
|
|
360
|
+
Object.values(columnFilterState).join('')
|
|
361
|
+
}
|
|
362
|
+
onClick={() => handleClean()}
|
|
363
|
+
onKeyDown={(event) => {
|
|
364
|
+
if (event.key === 'Enter') handleClean()
|
|
385
365
|
}}
|
|
386
366
|
/>
|
|
387
367
|
)}
|
|
@@ -398,20 +378,23 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
398
378
|
{...tableHeadProps}
|
|
399
379
|
columnFilter={columnFilter}
|
|
400
380
|
columnFilterState={columnFilterState}
|
|
401
|
-
columns={columns ? columns :
|
|
381
|
+
columns={columns ? columns : columnNames}
|
|
402
382
|
columnSorter={columnSorter}
|
|
403
383
|
items={_items}
|
|
404
384
|
selectable={selectable}
|
|
405
|
-
selectAll={
|
|
385
|
+
selectAll={selectAll}
|
|
386
|
+
selectedAll={selectedAll}
|
|
406
387
|
sorterState={sorterState}
|
|
407
388
|
sortingIcon={sortingIcon}
|
|
408
389
|
sortingIconAscending={sortingIconAscending}
|
|
409
390
|
sortingIconDescending={sortingIconDescending}
|
|
410
|
-
handleFilterOnChange={(key, event) =>
|
|
411
|
-
|
|
412
|
-
|
|
391
|
+
handleFilterOnChange={(key, event) =>
|
|
392
|
+
handleColumnFilterChange(key, event, 'change')
|
|
393
|
+
}
|
|
394
|
+
handleFilterOnInput={(key, event) => handleColumnFilterChange(key, event, 'input')}
|
|
395
|
+
handleOnCustomFilterChange={(key, event) => handleColumnFilterChange(key, event)}
|
|
413
396
|
handleSelectAllChecked={() => handleSelectAllChecked()}
|
|
414
|
-
handleSort={(key, index) =>
|
|
397
|
+
handleSort={(key, index) => handleSorterChange(key, index)}
|
|
415
398
|
/>
|
|
416
399
|
)}
|
|
417
400
|
<CSmartTableBody
|
|
@@ -422,10 +405,11 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
422
405
|
onRowClick={(item, index, columnName, event) =>
|
|
423
406
|
clickableRows && onRowClick && onRowClick(item, index, columnName, event)
|
|
424
407
|
}
|
|
425
|
-
onRowChecked={(
|
|
426
|
-
|
|
408
|
+
onRowChecked={(item, value) => handleRowChecked(item, value)}
|
|
409
|
+
columnNames={columnNames}
|
|
427
410
|
scopedColumns={scopedColumns}
|
|
428
411
|
selectable={selectable}
|
|
412
|
+
selected={_selected}
|
|
429
413
|
{...tableBodyProps}
|
|
430
414
|
/>
|
|
431
415
|
{typeof footer === 'boolean' && footer && (
|
|
@@ -434,11 +418,12 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
434
418
|
{...tableFootProps}
|
|
435
419
|
columnFilter={false}
|
|
436
420
|
columnSorter={false}
|
|
437
|
-
columns={columns ? columns :
|
|
421
|
+
columns={columns ? columns : columnNames}
|
|
438
422
|
items={_items}
|
|
439
423
|
handleSelectAllChecked={() => handleSelectAllChecked()}
|
|
440
424
|
selectable={selectable}
|
|
441
|
-
selectAll={
|
|
425
|
+
selectAll={selectAll}
|
|
426
|
+
selectedAll={selectedAll}
|
|
442
427
|
/>
|
|
443
428
|
)}
|
|
444
429
|
{Array.isArray(footer) && (
|
|
@@ -459,10 +444,12 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
459
444
|
{loading && (
|
|
460
445
|
<CElementCover
|
|
461
446
|
boundaries={[
|
|
462
|
-
{ sides: ['top'], query: '
|
|
447
|
+
{ sides: ['top'], query: 'tbody' },
|
|
463
448
|
{ sides: ['bottom'], query: 'tbody' },
|
|
464
449
|
]}
|
|
465
|
-
|
|
450
|
+
>
|
|
451
|
+
{elementCover}
|
|
452
|
+
</CElementCover>
|
|
466
453
|
)}
|
|
467
454
|
</div>
|
|
468
455
|
|
|
@@ -484,12 +471,26 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
484
471
|
</div>
|
|
485
472
|
<div className="col-auto ms-auto">
|
|
486
473
|
{itemsPerPageSelect && (
|
|
487
|
-
<
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
474
|
+
<div className="row">
|
|
475
|
+
<CFormLabel className="col-auto col-form-label">{itemsPerPageLabel}</CFormLabel>
|
|
476
|
+
<div className="col-auto">
|
|
477
|
+
<CFormSelect
|
|
478
|
+
defaultValue={_itemsPerPage}
|
|
479
|
+
onChange={(event: ChangeEvent<HTMLSelectElement>) =>
|
|
480
|
+
handleItemsPerPageChange(event)
|
|
481
|
+
}
|
|
482
|
+
>
|
|
483
|
+
{itemsPerPageOptions &&
|
|
484
|
+
itemsPerPageOptions.map((number, index) => {
|
|
485
|
+
return (
|
|
486
|
+
<option value={number} key={index}>
|
|
487
|
+
{number}
|
|
488
|
+
</option>
|
|
489
|
+
)
|
|
490
|
+
})}
|
|
491
|
+
</CFormSelect>
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
493
494
|
)}
|
|
494
495
|
</div>
|
|
495
496
|
</div>
|
|
@@ -507,9 +508,11 @@ CSmartTable.propTypes = {
|
|
|
507
508
|
columnFilterValue: PropTypes.object,
|
|
508
509
|
columns: PropTypes.array,
|
|
509
510
|
columnSorter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
|
511
|
+
elementCover: PropTypes.node,
|
|
510
512
|
footer: PropTypes.oneOfType([PropTypes.bool, PropTypes.array]),
|
|
511
513
|
header: PropTypes.bool,
|
|
512
514
|
items: PropTypes.array,
|
|
515
|
+
itemsNumber: PropTypes.number,
|
|
513
516
|
itemsPerPage: PropTypes.number,
|
|
514
517
|
itemsPerPageLabel: PropTypes.string,
|
|
515
518
|
itemsPerPageOptions: PropTypes.array,
|
|
@@ -521,13 +524,16 @@ CSmartTable.propTypes = {
|
|
|
521
524
|
onFilteredItemsChange: PropTypes.func,
|
|
522
525
|
onItemsPerPageChange: PropTypes.func,
|
|
523
526
|
onRowClick: PropTypes.func,
|
|
527
|
+
onSelectAll: PropTypes.func,
|
|
524
528
|
onSelectedItemsChange: PropTypes.func,
|
|
525
|
-
onSorterChange: PropTypes.func, // TODO: change to `
|
|
529
|
+
onSorterChange: PropTypes.func, // TODO: change to `onColumnSorterChange` in v5
|
|
526
530
|
onTableFilterChange: PropTypes.func,
|
|
527
531
|
pagination: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
|
528
532
|
paginationProps: PropTypes.any, // TODO: update
|
|
529
533
|
scopedColumns: PropTypes.object,
|
|
530
534
|
selectable: PropTypes.bool,
|
|
535
|
+
selectAll: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
|
536
|
+
selected: PropTypes.array,
|
|
531
537
|
sorterValue: PropTypes.object,
|
|
532
538
|
sortingIcon: PropTypes.node,
|
|
533
539
|
sortingIconAscending: PropTypes.node,
|