@coreui/react-pro 4.11.0-next.0 → 4.11.0
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/accordion/index.d.ts +1 -2
- package/dist/components/calendar/CCalendar.d.ts +2 -2
- package/dist/components/dropdown/CDropdown.d.ts +7 -0
- package/dist/components/multi-select/CMultiSelect.d.ts +3 -3
- package/dist/components/smart-table/CSmartTableHead.d.ts +1 -0
- package/dist/components/smart-table/types.d.ts +12 -0
- package/dist/components/smart-table/utils.d.ts +12 -1
- package/dist/index.es.js +198 -82
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +197 -82
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/accordion/index.ts +0 -2
- package/src/components/calendar/CCalendar.tsx +54 -18
- package/src/components/dropdown/CDropdown.tsx +13 -8
- package/src/components/dropdown/CDropdownMenu.tsx +45 -41
- package/src/components/multi-select/CMultiSelect.tsx +5 -3
- package/src/components/offcanvas/COffcanvas.tsx +3 -5
- package/src/components/smart-table/CSmartTable.tsx +3 -4
- package/src/components/smart-table/CSmartTableBody.tsx +4 -3
- package/src/components/smart-table/CSmartTableHead.tsx +42 -10
- package/src/components/smart-table/types.ts +13 -0
- package/src/components/smart-table/utils.ts +124 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreui/react-pro",
|
|
3
|
-
"version": "4.11.0
|
|
3
|
+
"version": "4.11.0",
|
|
4
4
|
"description": "UI Components Library for React.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"typescript": "^4.9.5"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@coreui/coreui-pro": ">=4.
|
|
67
|
+
"@coreui/coreui-pro": ">=4.5.0",
|
|
68
68
|
"react": ">=17",
|
|
69
69
|
"react-dom": ">=17"
|
|
70
70
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CAccordion } from './CAccordion'
|
|
2
2
|
import { CAccordionBody } from './CAccordionBody'
|
|
3
3
|
import { CAccordionButton } from './CAccordionButton'
|
|
4
|
-
import { CAccordionCollapse } from './CAccordionCollapse'
|
|
5
4
|
import { CAccordionHeader } from './CAccordionHeader'
|
|
6
5
|
import { CAccordionItem } from './CAccordionItem'
|
|
7
6
|
|
|
@@ -9,7 +8,6 @@ export {
|
|
|
9
8
|
CAccordion,
|
|
10
9
|
CAccordionBody,
|
|
11
10
|
CAccordionButton,
|
|
12
|
-
CAccordionCollapse,
|
|
13
11
|
CAccordionHeader,
|
|
14
12
|
CAccordionItem,
|
|
15
13
|
}
|
|
@@ -106,13 +106,13 @@ export interface CCalendarProps {
|
|
|
106
106
|
/**
|
|
107
107
|
* Set whether days in adjacent months shown before or after the current month are selectable. This only applies if the `showAdjacementDays` option is set to true.
|
|
108
108
|
*
|
|
109
|
-
* @since 4.11.0
|
|
109
|
+
* @since 4.11.0
|
|
110
110
|
*/
|
|
111
111
|
selectAdjacementDays?: boolean
|
|
112
112
|
/**
|
|
113
113
|
* Set whether to display dates in adjacent months (non-selectable) at the start and end of the current month.
|
|
114
114
|
*
|
|
115
|
-
* @since 4.11.0
|
|
115
|
+
* @since 4.11.0
|
|
116
116
|
*/
|
|
117
117
|
showAdjacementDays?: boolean
|
|
118
118
|
/**
|
|
@@ -174,8 +174,10 @@ const Calendar = (props: {
|
|
|
174
174
|
onCellKeyDown: (event: KeyboardEvent<HTMLDivElement>, date: Date) => void
|
|
175
175
|
onCellMouseEnter: (date: Date) => void
|
|
176
176
|
onCellMouseLeave: () => void
|
|
177
|
-
onMonthClick: (month: number
|
|
178
|
-
|
|
177
|
+
onMonthClick: (month: number) => void
|
|
178
|
+
onMonthKeyDown: (event: KeyboardEvent<HTMLDivElement>, month: number) => void
|
|
179
|
+
onYearClick: (date: Date) => void
|
|
180
|
+
onYearKeyDown: (event: KeyboardEvent<HTMLDivElement>, date: Date) => void
|
|
179
181
|
selectAdjacementDays: boolean
|
|
180
182
|
selectEndDate: boolean | undefined
|
|
181
183
|
showAdjacementDays: boolean
|
|
@@ -199,7 +201,9 @@ const Calendar = (props: {
|
|
|
199
201
|
onCellMouseEnter,
|
|
200
202
|
onCellMouseLeave,
|
|
201
203
|
onMonthClick,
|
|
204
|
+
onMonthKeyDown,
|
|
202
205
|
onYearClick,
|
|
206
|
+
onYearKeyDown,
|
|
203
207
|
selectAdjacementDays,
|
|
204
208
|
selectEndDate,
|
|
205
209
|
showAdjacementDays,
|
|
@@ -258,6 +262,7 @@ const Calendar = (props: {
|
|
|
258
262
|
today: month === 'current' && isToday(date),
|
|
259
263
|
disabled: isDateDisabled(date, minDate, maxDate, disabledDates),
|
|
260
264
|
[month]: true,
|
|
265
|
+
clickable: month !== 'current' && selectAdjacementDays,
|
|
261
266
|
last: isLastDayOfMonth(date),
|
|
262
267
|
'range-hover':
|
|
263
268
|
month === 'current' &&
|
|
@@ -270,7 +275,12 @@ const Calendar = (props: {
|
|
|
270
275
|
end: isEndDate(date, startDate, endDate),
|
|
271
276
|
})}
|
|
272
277
|
key={idx}
|
|
273
|
-
tabIndex={
|
|
278
|
+
tabIndex={
|
|
279
|
+
(month === 'current' || selectAdjacementDays) &&
|
|
280
|
+
!isDateDisabled(date, minDate, maxDate, disabledDates)
|
|
281
|
+
? 0
|
|
282
|
+
: -1
|
|
283
|
+
}
|
|
274
284
|
title={date.toLocaleDateString(locale)}
|
|
275
285
|
{...((month === 'current' || selectAdjacementDays) && {
|
|
276
286
|
onBlur: () => onCellMouseLeave(),
|
|
@@ -305,9 +315,11 @@ const Calendar = (props: {
|
|
|
305
315
|
{row.map((month, idx) => {
|
|
306
316
|
return (
|
|
307
317
|
<td
|
|
308
|
-
key={idx}
|
|
309
318
|
className="calendar-cell month"
|
|
310
|
-
|
|
319
|
+
key={idx}
|
|
320
|
+
onClick={() => onMonthClick(index * 3 + idx - addMonths)}
|
|
321
|
+
onKeyDown={(event) => onMonthKeyDown(event, index * 3 + idx - addMonths)}
|
|
322
|
+
tabIndex={0}
|
|
311
323
|
>
|
|
312
324
|
<div className="calendar-cell-inner">{month}</div>
|
|
313
325
|
</td>
|
|
@@ -323,14 +335,18 @@ const Calendar = (props: {
|
|
|
323
335
|
{row.map((year, idx) => {
|
|
324
336
|
return (
|
|
325
337
|
<td
|
|
326
|
-
key={idx}
|
|
327
338
|
className="calendar-cell year"
|
|
339
|
+
key={idx}
|
|
328
340
|
onClick={() =>
|
|
329
|
-
onYearClick(
|
|
341
|
+
onYearClick(new Date(year, date.getMonth() - addMonths, date.getDate()))
|
|
342
|
+
}
|
|
343
|
+
onKeyDown={(event) =>
|
|
344
|
+
onYearKeyDown(
|
|
345
|
+
event,
|
|
330
346
|
new Date(year, date.getMonth() - addMonths, date.getDate()),
|
|
331
|
-
'months',
|
|
332
347
|
)
|
|
333
348
|
}
|
|
349
|
+
tabIndex={0}
|
|
334
350
|
>
|
|
335
351
|
<div className="calendar-cell-inner">
|
|
336
352
|
{new Date(year, 0, 1).toLocaleDateString(locale, { year: 'numeric' })}
|
|
@@ -648,6 +664,18 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
648
664
|
}
|
|
649
665
|
}
|
|
650
666
|
|
|
667
|
+
const handleMonthClick = (month: number) => {
|
|
668
|
+
setCalendarPage(0, 0, month)
|
|
669
|
+
setView('days')
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const handleMonthKeyDown = (event: React.KeyboardEvent<HTMLDivElement>, month: number) => {
|
|
673
|
+
if (event.code === 'Space' || event.key === 'Enter') {
|
|
674
|
+
setCalendarPage(0, 0, month)
|
|
675
|
+
setView('days')
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
651
679
|
const handleNavigationOnClick = (direction: string, double = false) => {
|
|
652
680
|
if (direction === 'prev') {
|
|
653
681
|
if (double) {
|
|
@@ -679,6 +707,18 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
679
707
|
}
|
|
680
708
|
}
|
|
681
709
|
|
|
710
|
+
const handleYearClick = (date: Date) => {
|
|
711
|
+
setCalendarDate(date)
|
|
712
|
+
setView('months')
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const handleYearKeyDown = (event: React.KeyboardEvent<HTMLDivElement>, date: Date) => {
|
|
716
|
+
if (event.code === 'Space' || event.key === 'Enter') {
|
|
717
|
+
setCalendarDate(date)
|
|
718
|
+
setView('months')
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
682
722
|
return (
|
|
683
723
|
<div className={classNames('calendars', className)}>
|
|
684
724
|
{_calendarDate &&
|
|
@@ -714,14 +754,10 @@ export const CCalendar = forwardRef<HTMLDivElement, CCalendarProps>(
|
|
|
714
754
|
onCellKeyDown={(event, date) => handleCellKeyDown(event, date, index)}
|
|
715
755
|
onCellMouseEnter={handleCellMouseEnter}
|
|
716
756
|
onCellMouseLeave={handleCellMouseLeave}
|
|
717
|
-
onMonthClick={
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
}
|
|
721
|
-
onYearClick={(date, view) => {
|
|
722
|
-
setCalendarDate(date)
|
|
723
|
-
setView(view)
|
|
724
|
-
}}
|
|
757
|
+
onMonthClick={handleMonthClick}
|
|
758
|
+
onMonthKeyDown={handleMonthKeyDown}
|
|
759
|
+
onYearClick={handleYearClick}
|
|
760
|
+
onYearKeyDown={handleYearKeyDown}
|
|
725
761
|
selectEndDate={_selectEndDate}
|
|
726
762
|
selectAdjacementDays={selectAdjacementDays}
|
|
727
763
|
showAdjacementDays={showAdjacementDays}
|
|
@@ -78,6 +78,12 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
|
|
|
78
78
|
* If you want to disable dynamic positioning set this property to `true`.
|
|
79
79
|
*/
|
|
80
80
|
popper?: boolean
|
|
81
|
+
/**
|
|
82
|
+
* Generates dropdown menu using createPortal.
|
|
83
|
+
*
|
|
84
|
+
* @since 4.8.0
|
|
85
|
+
*/
|
|
86
|
+
portal?: boolean
|
|
81
87
|
/**
|
|
82
88
|
* Set the dropdown variant to an btn-group, dropdown, input-group, and nav-item.
|
|
83
89
|
*/
|
|
@@ -88,13 +94,7 @@ export interface CDropdownProps extends HTMLAttributes<HTMLDivElement | HTMLLIEl
|
|
|
88
94
|
visible?: boolean
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
const PopperManagerWrapper = ({
|
|
92
|
-
children,
|
|
93
|
-
popper,
|
|
94
|
-
}: {
|
|
95
|
-
children: ReactNode
|
|
96
|
-
popper: boolean
|
|
97
|
-
}) => {
|
|
97
|
+
const PopperManagerWrapper = ({ children, popper }: { children: ReactNode; popper: boolean }) => {
|
|
98
98
|
return popper ? <Manager>{children}</Manager> : <>{children}</>
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -102,6 +102,7 @@ interface ContextProps extends CDropdownProps {
|
|
|
102
102
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
103
|
dropdownToggleRef: RefObject<any> | undefined
|
|
104
104
|
setVisible: React.Dispatch<React.SetStateAction<boolean | undefined>>
|
|
105
|
+
portal: boolean
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
export const CDropdownContext = createContext({} as ContextProps)
|
|
@@ -119,6 +120,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
119
120
|
onShow,
|
|
120
121
|
placement = 'bottom-start',
|
|
121
122
|
popper = true,
|
|
123
|
+
portal = false,
|
|
122
124
|
variant = 'btn-group',
|
|
123
125
|
component = 'div',
|
|
124
126
|
visible = false,
|
|
@@ -146,6 +148,7 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
146
148
|
dropdownToggleRef,
|
|
147
149
|
placement: placement,
|
|
148
150
|
popper,
|
|
151
|
+
portal: portal,
|
|
149
152
|
variant,
|
|
150
153
|
visible: _visible,
|
|
151
154
|
setVisible,
|
|
@@ -172,7 +175,8 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
172
175
|
{
|
|
173
176
|
'dropdown-center': direction === 'center',
|
|
174
177
|
'dropup dropup-center': direction === 'dropup-center',
|
|
175
|
-
direction:
|
|
178
|
+
[`${direction}`]:
|
|
179
|
+
direction && direction !== 'center' && direction !== 'dropup-center',
|
|
176
180
|
show: _visible,
|
|
177
181
|
},
|
|
178
182
|
className,
|
|
@@ -215,6 +219,7 @@ CDropdown.propTypes = {
|
|
|
215
219
|
onShow: PropTypes.func,
|
|
216
220
|
placement: placementPropType,
|
|
217
221
|
popper: PropTypes.bool,
|
|
222
|
+
portal: PropTypes.bool,
|
|
218
223
|
variant: PropTypes.oneOf(['btn-group', 'dropdown', 'input-group', 'nav-item']),
|
|
219
224
|
visible: PropTypes.bool,
|
|
220
225
|
}
|
|
@@ -4,6 +4,7 @@ import classNames from 'classnames'
|
|
|
4
4
|
import { Popper, PopperChildrenProps } from 'react-popper'
|
|
5
5
|
|
|
6
6
|
import { Alignments, CDropdownContext } from './CDropdown'
|
|
7
|
+
import { CConditionalPortal } from '../conditional-portal'
|
|
7
8
|
|
|
8
9
|
import type { Placements } from '../../types'
|
|
9
10
|
|
|
@@ -30,6 +31,21 @@ export interface CDropdownMenuProps
|
|
|
30
31
|
component?: string | ElementType
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
const alignmentClassNames = (alignment: Alignments) => {
|
|
35
|
+
const classNames: string[] = []
|
|
36
|
+
if (typeof alignment === 'object') {
|
|
37
|
+
Object.keys(alignment).map((key) => {
|
|
38
|
+
classNames.push(`dropdown-menu${key === 'xs' ? '' : `-${key}`}-${alignment[key]}`)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (typeof alignment === 'string') {
|
|
43
|
+
classNames.push(`dropdown-menu-${alignment}`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return classNames
|
|
47
|
+
}
|
|
48
|
+
|
|
33
49
|
export const CDropdownMenu: FC<CDropdownMenuProps> = ({
|
|
34
50
|
children,
|
|
35
51
|
className,
|
|
@@ -44,6 +60,7 @@ export const CDropdownMenu: FC<CDropdownMenuProps> = ({
|
|
|
44
60
|
dropdownToggleRef,
|
|
45
61
|
placement,
|
|
46
62
|
popper,
|
|
63
|
+
portal,
|
|
47
64
|
visible,
|
|
48
65
|
setVisible,
|
|
49
66
|
} = useContext(CDropdownContext)
|
|
@@ -111,48 +128,35 @@ export const CDropdownMenu: FC<CDropdownMenuProps> = ({
|
|
|
111
128
|
_placement = 'bottom-end'
|
|
112
129
|
}
|
|
113
130
|
|
|
114
|
-
const alignmentClassNames = (alignment: Alignments) => {
|
|
115
|
-
const classNames: string[] = []
|
|
116
|
-
if (typeof alignment === 'object') {
|
|
117
|
-
Object.keys(alignment).map((key) => {
|
|
118
|
-
classNames.push(`dropdown-menu${key === 'xs' ? '' : `-${key}`}-${alignment[key]}`)
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (typeof alignment === 'string') {
|
|
123
|
-
classNames.push(`dropdown-menu-${alignment}`)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return classNames
|
|
127
|
-
}
|
|
128
|
-
|
|
129
131
|
const dropdownMenuComponent = (style?: React.CSSProperties, ref?: React.Ref<HTMLDivElement>) => (
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
132
|
+
<CConditionalPortal portal={portal ?? false}>
|
|
133
|
+
<Component
|
|
134
|
+
className={classNames(
|
|
135
|
+
'dropdown-menu',
|
|
136
|
+
{
|
|
137
|
+
'dropdown-menu-dark': dark,
|
|
138
|
+
show: visible,
|
|
139
|
+
},
|
|
140
|
+
alignment && alignmentClassNames(alignment),
|
|
141
|
+
className,
|
|
142
|
+
)}
|
|
143
|
+
ref={ref}
|
|
144
|
+
style={style}
|
|
145
|
+
role="menu"
|
|
146
|
+
aria-hidden={!visible}
|
|
147
|
+
{...(!popper && { 'data-coreui-popper': 'static' })}
|
|
148
|
+
{...rest}
|
|
149
|
+
>
|
|
150
|
+
{Component === 'ul'
|
|
151
|
+
? React.Children.map(children, (child, index) => {
|
|
152
|
+
if (React.isValidElement(child)) {
|
|
153
|
+
return <li key={index}>{React.cloneElement(child)}</li>
|
|
154
|
+
}
|
|
155
|
+
return
|
|
156
|
+
})
|
|
157
|
+
: children}
|
|
158
|
+
</Component>
|
|
159
|
+
</CConditionalPortal>
|
|
156
160
|
)
|
|
157
161
|
|
|
158
162
|
return popper && visible ? (
|
|
@@ -29,7 +29,7 @@ export interface CMultiSelectProps
|
|
|
29
29
|
/**
|
|
30
30
|
* Allow users to create options if they are not in the list of options.
|
|
31
31
|
*
|
|
32
|
-
* @since 4.11.0
|
|
32
|
+
* @since 4.11.0
|
|
33
33
|
*/
|
|
34
34
|
allowCreateOptions?: boolean
|
|
35
35
|
/**
|
|
@@ -43,7 +43,7 @@ export interface CMultiSelectProps
|
|
|
43
43
|
/**
|
|
44
44
|
* Clear current search on selecting an item.
|
|
45
45
|
*
|
|
46
|
-
* @since 4.11.0
|
|
46
|
+
* @since 4.11.0
|
|
47
47
|
*/
|
|
48
48
|
clearSearchOnSelect?: boolean
|
|
49
49
|
/**
|
|
@@ -53,7 +53,7 @@ export interface CMultiSelectProps
|
|
|
53
53
|
/**
|
|
54
54
|
* When set, the options list will have a loading style: loading spinner and reduced opacity.
|
|
55
55
|
*
|
|
56
|
-
* @since 4.11.0
|
|
56
|
+
* @since 4.11.0
|
|
57
57
|
*/
|
|
58
58
|
loading?: boolean
|
|
59
59
|
/**
|
|
@@ -249,6 +249,8 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
249
249
|
|
|
250
250
|
const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
|
251
251
|
if (event.key === 'Enter' && searchValue && allowCreateOptions) {
|
|
252
|
+
event.preventDefault()
|
|
253
|
+
|
|
252
254
|
if (userOption) {
|
|
253
255
|
setSelected([...selected, ...userOption])
|
|
254
256
|
setUserOptions([...userOptions, ...userOption])
|
|
@@ -80,11 +80,9 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
80
80
|
}, [visible])
|
|
81
81
|
|
|
82
82
|
useEffect(() => {
|
|
83
|
-
if (_visible) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
document.body.style.paddingRight = '0px'
|
|
87
|
-
}
|
|
83
|
+
if (_visible && !scroll) {
|
|
84
|
+
document.body.style.overflow = 'hidden'
|
|
85
|
+
document.body.style.paddingRight = '0px'
|
|
88
86
|
return
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -88,9 +88,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
88
88
|
const [columnFilterState, setColumnFilterState] = useState<ColumnFilterValue>({})
|
|
89
89
|
const [selectedAll, setSelectedAll] = useState<boolean | string>()
|
|
90
90
|
const [sorterState, setSorterState] = useState<SorterValue>({})
|
|
91
|
-
const [tableFilterState, setTableFilterState] = useState<string>(
|
|
92
|
-
tableFilterValue ? tableFilterValue : '',
|
|
93
|
-
)
|
|
91
|
+
const [tableFilterState, setTableFilterState] = useState<string>(tableFilterValue ?? '')
|
|
94
92
|
|
|
95
93
|
useEffect(() => {
|
|
96
94
|
setActivePage(activePage)
|
|
@@ -170,7 +168,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
170
168
|
return
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
if (_selected.length
|
|
171
|
+
if (_selected.length > 0 && _selected.length !== _itemsNumber) {
|
|
174
172
|
setSelectedAll('indeterminate')
|
|
175
173
|
}
|
|
176
174
|
}
|
|
@@ -420,6 +418,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
|
|
|
420
418
|
selectable={selectable}
|
|
421
419
|
selectAll={selectAll}
|
|
422
420
|
selectedAll={selectedAll}
|
|
421
|
+
showGroups={false}
|
|
423
422
|
/>
|
|
424
423
|
)}
|
|
425
424
|
{Array.isArray(footer) && (
|
|
@@ -51,7 +51,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
51
51
|
{...rest}
|
|
52
52
|
ref={ref}
|
|
53
53
|
>
|
|
54
|
-
{currentItems.length ? (
|
|
54
|
+
{currentItems.length > 0 ? (
|
|
55
55
|
currentItems.map((item: Item, trIndex) => {
|
|
56
56
|
return (
|
|
57
57
|
<React.Fragment key={trIndex}>
|
|
@@ -94,11 +94,12 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
|
|
|
94
94
|
{
|
|
95
95
|
key: index,
|
|
96
96
|
},
|
|
97
|
-
)) ||
|
|
97
|
+
)) ||
|
|
98
|
+
(item[colName] && (
|
|
98
99
|
<CTableDataCell {...getTableDataCellProps(item, colName)} key={index}>
|
|
99
100
|
{String(item[colName])}
|
|
100
101
|
</CTableDataCell>
|
|
101
|
-
)
|
|
102
|
+
))
|
|
102
103
|
)
|
|
103
104
|
})}
|
|
104
105
|
</CTableRow>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
ElementType,
|
|
3
|
+
forwardRef,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react'
|
|
2
10
|
import PropTypes from 'prop-types'
|
|
3
11
|
|
|
4
12
|
import { CFormCheck, CFormInput } from '../form'
|
|
@@ -8,6 +16,8 @@ import { CTableHead, CTableHeadProps } from '../table/CTableHead'
|
|
|
8
16
|
import {
|
|
9
17
|
getColumnKey,
|
|
10
18
|
getColumnLabel,
|
|
19
|
+
getColumnGroups,
|
|
20
|
+
getColumns,
|
|
11
21
|
getColumnSorterState,
|
|
12
22
|
getColumnValues,
|
|
13
23
|
getTableHeaderCellProps,
|
|
@@ -31,6 +41,7 @@ export interface CSmartTableHeadProps extends CTableHeadProps {
|
|
|
31
41
|
selectable?: boolean
|
|
32
42
|
selectAll?: boolean | { external?: boolean }
|
|
33
43
|
selectedAll?: boolean | string
|
|
44
|
+
showGroups?: boolean
|
|
34
45
|
sorterState?: SorterValue
|
|
35
46
|
sortingIcon?: ReactNode
|
|
36
47
|
sortingIconAscending?: ReactNode
|
|
@@ -54,6 +65,7 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
54
65
|
selectable,
|
|
55
66
|
selectAll,
|
|
56
67
|
selectedAll,
|
|
68
|
+
showGroups = true,
|
|
57
69
|
sorterState,
|
|
58
70
|
sortingIcon,
|
|
59
71
|
sortingIconAscending,
|
|
@@ -65,6 +77,9 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
65
77
|
const selectAllcheckboxRef = useRef<HTMLInputElement>(null)
|
|
66
78
|
const [refresh, setRefresh] = useState(false)
|
|
67
79
|
|
|
80
|
+
const _columns = useMemo(() => getColumns(columns), [columns])
|
|
81
|
+
const groups = useMemo(() => getColumnGroups(columns), [columns])
|
|
82
|
+
|
|
68
83
|
useEffect(() => {
|
|
69
84
|
if (selectedAll === 'indeterminate') {
|
|
70
85
|
if (selectAllcheckboxRef.current) selectAllcheckboxRef.current.indeterminate = true
|
|
@@ -107,6 +122,23 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
107
122
|
|
|
108
123
|
return (
|
|
109
124
|
<Component {...rest} ref={ref}>
|
|
125
|
+
{showGroups &&
|
|
126
|
+
groups &&
|
|
127
|
+
groups.length > 0 &&
|
|
128
|
+
groups.map((row, index) => (
|
|
129
|
+
<CTableRow key={index}>
|
|
130
|
+
{selectable && <CTableHeaderCell></CTableHeaderCell>}
|
|
131
|
+
{row.map((cell, index) => (
|
|
132
|
+
<CTableHeaderCell
|
|
133
|
+
colSpan={cell.colspan}
|
|
134
|
+
{...getTableHeaderCellProps(cell)}
|
|
135
|
+
key={index}
|
|
136
|
+
>
|
|
137
|
+
{cell.label}
|
|
138
|
+
</CTableHeaderCell>
|
|
139
|
+
))}
|
|
140
|
+
</CTableRow>
|
|
141
|
+
))}
|
|
110
142
|
<CTableRow>
|
|
111
143
|
{selectable && (
|
|
112
144
|
<CTableHeaderCell>
|
|
@@ -119,7 +151,7 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
119
151
|
)}
|
|
120
152
|
</CTableHeaderCell>
|
|
121
153
|
)}
|
|
122
|
-
{
|
|
154
|
+
{_columns.map((column: Column | string, index: number) => {
|
|
123
155
|
return (
|
|
124
156
|
<CTableHeaderCell
|
|
125
157
|
{...getTableHeaderCellProps(column)}
|
|
@@ -129,11 +161,11 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
129
161
|
>
|
|
130
162
|
<div className="d-inline">{getColumnLabel(column)}</div>
|
|
131
163
|
{columnSorter &&
|
|
132
|
-
(typeof column
|
|
164
|
+
(typeof column === 'object'
|
|
165
|
+
? typeof column.sorter === 'undefined'
|
|
133
166
|
? true
|
|
134
|
-
:
|
|
135
|
-
|
|
136
|
-
: column.sorter) &&
|
|
167
|
+
: column.sorter
|
|
168
|
+
: true) &&
|
|
137
169
|
columnSorterIcon(column)}
|
|
138
170
|
</CTableHeaderCell>
|
|
139
171
|
)
|
|
@@ -142,15 +174,15 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
|
|
|
142
174
|
{columnFilter && (
|
|
143
175
|
<CTableRow>
|
|
144
176
|
{selectable && <CTableHeaderCell></CTableHeaderCell>}
|
|
145
|
-
{
|
|
177
|
+
{_columns.map((column: Column | string, index: number) => {
|
|
146
178
|
return (
|
|
147
179
|
<CTableHeaderCell {...getTableHeaderCellProps(column)} key={index}>
|
|
148
180
|
{(
|
|
149
|
-
typeof column
|
|
150
|
-
?
|
|
151
|
-
: typeof column.filter === 'undefined'
|
|
181
|
+
typeof column === 'object'
|
|
182
|
+
? column.filter === undefined
|
|
152
183
|
? true
|
|
153
184
|
: column.filter
|
|
185
|
+
: true
|
|
154
186
|
) ? (
|
|
155
187
|
typeof column !== 'string' && typeof column.filter === 'function' ? (
|
|
156
188
|
!refresh &&
|
|
@@ -5,7 +5,9 @@ import { CTableHeaderCellProps } from '../table/CTableHeaderCell'
|
|
|
5
5
|
import { CTableRowProps } from '../table/CTableRow'
|
|
6
6
|
|
|
7
7
|
export type Column = {
|
|
8
|
+
children?: Column[]
|
|
8
9
|
filter?: boolean | ((values: any[], onChange: (value: any) => void) => ReactNode)
|
|
10
|
+
group?: string
|
|
9
11
|
key: string
|
|
10
12
|
label?: string
|
|
11
13
|
sorter?: boolean
|
|
@@ -27,6 +29,17 @@ export type FooterItem = {
|
|
|
27
29
|
_props?: CTableDataCellProps
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
export type Group = {
|
|
33
|
+
children?: Group[] | Column[]
|
|
34
|
+
colspan?: number
|
|
35
|
+
deep?: number
|
|
36
|
+
group?: string
|
|
37
|
+
key: string
|
|
38
|
+
label?: string
|
|
39
|
+
_style?: any
|
|
40
|
+
_props?: CTableHeaderCellProps
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
export type Item = {
|
|
31
44
|
[key: string]: number | string | any
|
|
32
45
|
_cellProps?: any
|