@coreui/react-pro 4.8.0-alpha.3 → 4.9.0-next.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.
Files changed (82) hide show
  1. package/README.md +1 -1
  2. package/dist/components/calendar/index.d.ts +2 -0
  3. package/dist/components/calendar/utils.d.ts +23 -0
  4. package/dist/components/date-picker/CDatePicker.d.ts +1 -1
  5. package/dist/components/date-range-picker/CDateRangePicker.d.ts +2 -2
  6. package/dist/components/element-cover/CElementCover.d.ts +3 -7
  7. package/dist/components/element-cover/index.d.ts +2 -0
  8. package/dist/components/form/CFormInput.d.ts +1 -1
  9. package/dist/components/form/CFormSwitch.d.ts +1 -1
  10. package/dist/components/index.d.ts +2 -0
  11. package/dist/components/nav/CNavGroup.d.ts +4 -4
  12. package/dist/components/offcanvas/COffcanvas.d.ts +8 -2
  13. package/dist/components/sidebar/CSidebar.d.ts +4 -4
  14. package/dist/components/smart-table/CSmartTableBody.d.ts +6 -5
  15. package/dist/components/smart-table/CSmartTableHead.d.ts +6 -3
  16. package/dist/components/smart-table/CSmartTableInterface.d.ts +46 -109
  17. package/dist/components/smart-table/types.d.ts +53 -0
  18. package/dist/components/smart-table/utils.d.ts +16 -0
  19. package/dist/components/table/CTable.d.ts +5 -5
  20. package/dist/components/time-picker/types.d.ts +15 -0
  21. package/dist/components/time-picker/utils.d.ts +23 -0
  22. package/dist/hooks/index.d.ts +3 -0
  23. package/dist/hooks/useForkedRef.d.ts +7 -0
  24. package/dist/hooks/useStateWithCallback.d.ts +2 -0
  25. package/dist/index.es.js +1246 -1865
  26. package/dist/index.es.js.map +1 -1
  27. package/dist/index.js +1246 -1863
  28. package/dist/index.js.map +1 -1
  29. package/dist/utils/index.d.ts +3 -2
  30. package/dist/utils/isInViewport.d.ts +2 -0
  31. package/dist/utils/isObjectInArray.d.ts +2 -0
  32. package/package.json +14 -14
  33. package/src/components/accordion/CAccordionBody.tsx +1 -1
  34. package/src/components/alert/CAlert.tsx +1 -1
  35. package/src/components/backdrop/CBackdrop.tsx +1 -1
  36. package/src/components/calendar/CCalendar.tsx +351 -240
  37. package/src/components/calendar/index.ts +3 -0
  38. package/src/{utils/calendar.ts → components/calendar/utils.ts} +1 -1
  39. package/src/components/carousel/CCarousel.tsx +4 -4
  40. package/src/components/carousel/CCarouselItem.tsx +1 -1
  41. package/src/components/collapse/CCollapse.tsx +1 -1
  42. package/src/components/date-picker/CDatePicker.tsx +1 -1
  43. package/src/components/date-range-picker/CDateRangePicker.tsx +3 -3
  44. package/src/components/dropdown/CDropdown.tsx +1 -1
  45. package/src/components/dropdown/CDropdownToggle.tsx +1 -1
  46. package/src/components/element-cover/CElementCover.tsx +19 -25
  47. package/src/components/element-cover/index.ts +3 -0
  48. package/src/components/form/CFormCheck.tsx +1 -1
  49. package/src/components/form/CFormControlWrapper.tsx +14 -20
  50. package/src/components/form/CFormInput.tsx +1 -1
  51. package/src/components/form/CFormSwitch.tsx +1 -1
  52. package/src/components/grid/CCol.tsx +4 -0
  53. package/src/components/index.ts +2 -0
  54. package/src/components/modal/CModal.tsx +1 -1
  55. package/src/components/nav/CNavGroup.tsx +4 -4
  56. package/src/components/nav/CNavLink.tsx +2 -1
  57. package/src/components/offcanvas/COffcanvas.tsx +36 -18
  58. package/src/components/sidebar/CSidebar.tsx +10 -10
  59. package/src/components/smart-table/CSmartTable.tsx +279 -259
  60. package/src/components/smart-table/CSmartTableBody.tsx +31 -41
  61. package/src/components/smart-table/CSmartTableCleaner.tsx +1 -1
  62. package/src/components/smart-table/CSmartTableFilter.tsx +1 -3
  63. package/src/components/smart-table/CSmartTableHead.tsx +53 -103
  64. package/src/components/smart-table/CSmartTableInterface.tsx +57 -120
  65. package/src/components/smart-table/CSmartTableItemsPerPageSelector.tsx +1 -2
  66. package/src/components/smart-table/types.tsx +65 -0
  67. package/src/components/smart-table/utils.tsx +199 -0
  68. package/src/components/table/CTable.tsx +12 -9
  69. package/src/components/tabs/CTabPane.tsx +1 -1
  70. package/src/components/time-picker/CTimePicker.tsx +50 -23
  71. package/src/components/time-picker/CTimePickerRollCol.tsx +1 -1
  72. package/src/components/time-picker/types.ts +15 -0
  73. package/src/{utils/time.ts → components/time-picker/utils.ts} +43 -2
  74. package/src/components/toast/CToast.tsx +1 -1
  75. package/src/components/virtual-scroller/CVirtualScroller.tsx +1 -1
  76. package/src/{utils/hooks → hooks}/index.ts +0 -0
  77. package/src/{utils/hooks → hooks}/useForkedRef.ts +0 -0
  78. package/src/{utils/hooks → hooks}/useStateWithCallback.ts +0 -0
  79. package/src/utils/index.ts +3 -2
  80. package/src/utils/isInViewport.ts +11 -0
  81. package/src/utils/isObjectInArray.ts +14 -0
  82. package/src/utils/isVisible.ts +0 -11
@@ -2,64 +2,46 @@ import React, { forwardRef, MouseEvent, ReactNode } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
4
  import { CTableBody, CTableBodyProps } from '../table/CTableBody'
5
- import { CTableRow } from '../table/CTableRow'
6
- import { CTableDataCell } from '../table/CTableDataCell'
5
+ import { CFormCheck } from '../form'
6
+ import { CTableDataCell, CTableRow } from '../table'
7
7
 
8
- import { CFormCheck } from '../form/CFormCheck'
8
+ import type { Item, ScopedColumns } from './types'
9
9
 
10
- import { Item, ItemInternal, ScopedColumns } from './CSmartTableInterface'
10
+ import { isObjectInArray } from '../../utils'
11
+
12
+ import { getClickedColumnName, getTableDataCellProps } from './utils'
11
13
 
12
14
  export interface CSmartTableBodyProps extends CTableBodyProps {
13
15
  clickableRows?: boolean
14
- currentItems: ItemInternal[]
16
+ columnNames: string[]
17
+ currentItems: Item[]
15
18
  firstItemOnActivePageIndex: number
16
19
  noItemsLabel?: string | ReactNode
17
- onRowChecked?: (id: number, value: boolean) => void
18
- onRowClick?: (
19
- item: ItemInternal,
20
- index: number,
21
- columnName: string,
22
- event: MouseEvent | boolean,
23
- ) => void
24
- rawColumnNames: string[]
20
+ onRowChecked?: (item: Item, value: boolean) => void
21
+ onRowClick?: (item: Item, index: number, columnName: string, event: MouseEvent | boolean) => void
25
22
  scopedColumns?: ScopedColumns
26
23
  selectable?: boolean
24
+ selected?: Item[]
27
25
  }
28
26
 
29
27
  export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBodyProps>(
30
28
  (
31
29
  {
32
30
  clickableRows,
31
+ columnNames,
33
32
  currentItems,
34
33
  firstItemOnActivePageIndex,
35
34
  noItemsLabel,
36
35
  onRowChecked,
37
36
  onRowClick,
38
- rawColumnNames,
39
37
  scopedColumns,
40
38
  selectable,
39
+ selected,
41
40
  ...rest
42
41
  },
43
42
  ref,
44
43
  ) => {
45
- const tableDataCellProps = (item: Item, colName: string) => {
46
- const props = item._cellProps && {
47
- ...(item._cellProps['all'] && { ...item._cellProps['all'] }),
48
- ...(item._cellProps[colName] && { ...item._cellProps[colName] }),
49
- }
50
-
51
- return props
52
- }
53
-
54
- const getColumnName = (event: MouseEvent): string => {
55
- const target = event.target as HTMLTextAreaElement
56
- const closest = target.closest('tr')
57
- const children = closest ? Array.from(closest.children) : []
58
- const clickedCell = children.filter((child) => child.contains(target))[0]
59
- return rawColumnNames[children.indexOf(clickedCell)]
60
- }
61
-
62
- const colspan: number = selectable ? rawColumnNames.length + 1 : rawColumnNames.length
44
+ const colspan: number = selectable ? columnNames.length + 1 : columnNames.length
63
45
 
64
46
  return (
65
47
  <CTableBody
@@ -69,7 +51,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
69
51
  {...rest}
70
52
  ref={ref}
71
53
  >
72
- {currentItems.map((item: ItemInternal, trIndex) => {
54
+ {currentItems.map((item: Item, trIndex) => {
73
55
  return (
74
56
  <React.Fragment key={trIndex}>
75
57
  <CTableRow
@@ -80,7 +62,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
80
62
  onRowClick(
81
63
  item,
82
64
  trIndex + firstItemOnActivePageIndex,
83
- getColumnName(event),
65
+ getClickedColumnName(event.target as HTMLTextAreaElement, columnNames),
84
66
  event,
85
67
  )
86
68
  }
@@ -88,14 +70,21 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
88
70
  {selectable && (
89
71
  <CTableDataCell>
90
72
  <CFormCheck
91
- checked={item._selected ? item._selected : false}
92
- onChange={(event) =>
93
- onRowChecked && onRowChecked(item._id, event.target.checked)
73
+ checked={
74
+ selected &&
75
+ isObjectInArray(selected, item, ['_cellProps', '_props', '_selected'])
94
76
  }
77
+ onChange={(event) => {
78
+ const _item = { ...item }
79
+ delete _item['_cellProps']
80
+ delete _item['_props']
81
+ delete _item['_selected']
82
+ onRowChecked && onRowChecked(_item, event.target.checked)
83
+ }}
95
84
  />
96
85
  </CTableDataCell>
97
86
  )}
98
- {rawColumnNames.map((colName, index) => {
87
+ {columnNames.map((colName, index) => {
99
88
  return (
100
89
  (scopedColumns &&
101
90
  scopedColumns[colName] &&
@@ -105,7 +94,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
105
94
  key: index,
106
95
  },
107
96
  )) || (
108
- <CTableDataCell {...tableDataCellProps(item, colName)} key={index}>
97
+ <CTableDataCell {...getTableDataCellProps(item, colName)} key={index}>
109
98
  {String(item[colName])}
110
99
  </CTableDataCell>
111
100
  )
@@ -128,7 +117,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
128
117
  onRowClick(
129
118
  item,
130
119
  trIndex + firstItemOnActivePageIndex,
131
- getColumnName(event),
120
+ getClickedColumnName(event.target as HTMLTextAreaElement, columnNames),
132
121
  true,
133
122
  )
134
123
  }
@@ -161,9 +150,10 @@ CSmartTableBody.propTypes = {
161
150
  noItemsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
162
151
  onRowChecked: PropTypes.func,
163
152
  onRowClick: PropTypes.func,
164
- rawColumnNames: PropTypes.array.isRequired,
153
+ columnNames: PropTypes.array.isRequired,
165
154
  scopedColumns: PropTypes.object,
166
155
  selectable: PropTypes.bool,
156
+ selected: PropTypes.array,
167
157
  }
168
158
 
169
159
  CSmartTableBody.displayName = 'CSmartTableBody'
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'
3
3
 
4
- import { cilFilterX } from '@coreui/icons-pro'
4
+ import { cilFilterX } from '@coreui/icons'
5
5
 
6
6
  import CIcon from '@coreui/icons-react'
7
7
 
@@ -1,11 +1,9 @@
1
1
  import React, { forwardRef, HTMLAttributes } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import { CFormLabel } from '../form/CFormLabel'
5
- import { CFormInput } from '../form/CFormInput'
4
+ import { CFormInput, CFormLabel } from '../form'
6
5
 
7
6
  interface CSmartTableFilterProps extends HTMLAttributes<HTMLInputElement> {
8
- // TODO: consider to simplify ex. filterLabel --> label
9
7
  filterLabel?: string
10
8
  filterPlaceholder?: string
11
9
  value?: string | number
@@ -1,20 +1,21 @@
1
1
  import React, { ElementType, forwardRef, ReactNode, useEffect, useRef, useState } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import {
5
- ColumnFilter,
6
- ColumnFilterValue,
7
- Column,
8
- ItemInternal,
9
- Sorter,
10
- SorterValue,
11
- } from './CSmartTableInterface'
4
+ import type { ColumnFilter, ColumnFilterValue, Column, Item, Sorter, SorterValue } from './types'
12
5
 
13
- import { CFormInput } from '../form/CFormInput'
14
- import { CFormCheck } from '../form/CFormCheck'
6
+ import { CFormCheck, CFormInput } from '../form'
7
+ import { CTableHeaderCell, CTableRow } from '../table'
15
8
  import { CTableHead, CTableHeadProps } from '../table/CTableHead'
16
- import { CTableHeaderCell } from '../table/CTableHeaderCell'
17
- import { CTableRow } from '../table/CTableRow'
9
+
10
+ import {
11
+ getColumnKey,
12
+ getColumnLabel,
13
+ getColumnSorterState,
14
+ getColumnValues,
15
+ getTableHeaderCellProps,
16
+ getTableHeaderCellStyles,
17
+ } from './utils'
18
+
18
19
  export interface CSmartTableHeadProps extends CTableHeadProps {
19
20
  columnFilter?: boolean | ColumnFilter
20
21
  columnFilterState?: ColumnFilterValue
@@ -26,9 +27,10 @@ export interface CSmartTableHeadProps extends CTableHeadProps {
26
27
  handleFilterOnInput?: (key: string, value: string) => void
27
28
  handleSelectAllChecked?: () => void
28
29
  handleSort?: (key: string, index: number) => void
29
- items: ItemInternal[]
30
+ items: Item[]
30
31
  selectable?: boolean
31
- selectAll?: boolean | string
32
+ selectAll?: boolean | { external?: boolean }
33
+ selectedAll?: boolean | string
32
34
  sorterState?: SorterValue
33
35
  sortingIcon?: ReactNode
34
36
  sortingIconAscending?: ReactNode
@@ -51,6 +53,7 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
51
53
  items,
52
54
  selectable,
53
55
  selectAll,
56
+ selectedAll,
54
57
  sorterState,
55
58
  sortingIcon,
56
59
  sortingIconAscending,
@@ -59,8 +62,17 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
59
62
  },
60
63
  ref,
61
64
  ) => {
65
+ const selectAllcheckboxRef = useRef<HTMLInputElement>(null)
62
66
  const [refresh, setRefresh] = useState(false)
63
67
 
68
+ useEffect(() => {
69
+ if (selectedAll === 'indeterminate') {
70
+ if (selectAllcheckboxRef.current) selectAllcheckboxRef.current.indeterminate = true
71
+ } else {
72
+ if (selectAllcheckboxRef.current) selectAllcheckboxRef.current.indeterminate = false
73
+ }
74
+ }, [selectedAll])
75
+
64
76
  useEffect(() => {
65
77
  if (columnFilterState && Object.keys(columnFilterState).length === 0) {
66
78
  setRefresh(true)
@@ -77,108 +89,42 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
77
89
  }
78
90
  }, [refresh])
79
91
 
80
- const tableHeaderCellProps = (column: Column | string) => {
81
- if (typeof column === 'object' && column._props) {
82
- return column._props
83
- }
84
- return {}
85
- }
86
-
87
- const tableHeaderCellStyles = (column: Column | string) => {
88
- const style = { verticalAlign: 'middle', overflow: 'hidden', cursor: '' }
89
-
90
- if (
91
- columnSorter &&
92
- (typeof column !== 'object' ||
93
- (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter)))
94
- ) {
95
- style.cursor = 'pointer'
96
- }
97
-
98
- if (typeof column === 'object' && column._style) {
99
- return { ...style, ...column._style }
100
- }
101
- return style
102
- }
103
-
104
- const pretifyName = (name: string) => {
105
- return name
106
- .replace(/[-_.]/g, ' ')
107
- .replace(/ +/g, ' ')
108
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
109
- .split(' ')
110
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
111
- .join(' ')
112
- }
113
-
114
- const label = (column: Column | string) =>
115
- typeof column === 'object'
116
- ? column.label !== undefined
117
- ? column.label
118
- : pretifyName(column.key)
119
- : pretifyName(column)
120
-
121
- const key = (column: Column | string) => (typeof column === 'object' ? column.key : column)
122
-
123
- const getColumnSorterState = (key: string): string | number => {
124
- if (sorterState && sorterState.column === key) {
125
- if (sorterState.state) {
126
- return sorterState.state
127
- }
128
- return 0
129
- }
130
-
131
- return 0
132
- }
133
-
134
- const getValues = (items: ItemInternal[], key: string) => {
135
- return items.map((a) => a[key])
136
- }
137
-
138
92
  const columnSorterIcon = (column: Column | string) => {
139
- if (getColumnSorterState(key(column)) === 0) {
93
+ if (getColumnSorterState(getColumnKey(column), sorterState) === 0) {
140
94
  return <span className="opacity-25 float-end me-1">{sortingIcon}</span>
141
95
  }
142
- if (getColumnSorterState(key(column)) === 'asc') {
96
+ if (getColumnSorterState(getColumnKey(column), sorterState) === 'asc') {
143
97
  return <span className="float-end me-1">{sortingIconAscending}</span>
144
98
  }
145
- if (getColumnSorterState(key(column)) === 'desc') {
99
+ if (getColumnSorterState(getColumnKey(column), sorterState) === 'desc') {
146
100
  return <span className="float-end me-1">{sortingIconDescending}</span>
147
101
  }
148
102
  return
149
103
  }
150
104
 
151
- const checkboxRef = useRef<HTMLInputElement>(null)
152
-
153
- useEffect(() => {
154
- if (selectAll === 'indeterminate') {
155
- if (checkboxRef.current) checkboxRef.current.indeterminate = true
156
- } else {
157
- if (checkboxRef.current) checkboxRef.current.indeterminate = false
158
- }
159
- }, [selectAll])
160
-
161
105
  return (
162
106
  <Component {...rest} ref={ref}>
163
107
  <CTableRow>
164
108
  {selectable && (
165
109
  <CTableHeaderCell>
166
- <CFormCheck
167
- checked={typeof selectAll === 'boolean' ? selectAll : false}
168
- onChange={() => handleSelectAllChecked && handleSelectAllChecked()}
169
- ref={checkboxRef}
170
- />
110
+ {selectAll && (
111
+ <CFormCheck
112
+ checked={typeof selectedAll === 'boolean' ? selectedAll : false}
113
+ onChange={() => handleSelectAllChecked && handleSelectAllChecked()}
114
+ ref={selectAllcheckboxRef}
115
+ />
116
+ )}
171
117
  </CTableHeaderCell>
172
118
  )}
173
119
  {columns.map((column: Column | string, index: number) => {
174
120
  return (
175
121
  <CTableHeaderCell
176
- {...tableHeaderCellProps(column)}
177
- onClick={() => handleSort && handleSort(key(column), index)}
178
- style={tableHeaderCellStyles(column)}
122
+ {...getTableHeaderCellProps(column)}
123
+ onClick={() => handleSort && handleSort(getColumnKey(column), index)}
124
+ style={getTableHeaderCellStyles(column, columnSorter)}
179
125
  key={index}
180
126
  >
181
- <div className="d-inline">{label(column)}</div>
127
+ <div className="d-inline">{getColumnLabel(column)}</div>
182
128
  {columnSorter &&
183
129
  (typeof column !== 'object'
184
130
  ? true
@@ -195,7 +141,7 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
195
141
  {selectable && <CTableHeaderCell></CTableHeaderCell>}
196
142
  {columns.map((column: Column | string, index: number) => {
197
143
  return (
198
- <CTableHeaderCell {...tableHeaderCellProps(column)} key={index}>
144
+ <CTableHeaderCell {...getTableHeaderCellProps(column)} key={index}>
199
145
  {(
200
146
  typeof column !== 'object'
201
147
  ? true
@@ -206,31 +152,34 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
206
152
  typeof column !== 'string' && typeof column.filter === 'function' ? (
207
153
  !refresh &&
208
154
  column.filter(
209
- getValues(items, key(column)),
155
+ getColumnValues(items, getColumnKey(column)),
210
156
  (value: any) =>
211
157
  handleOnCustomFilterChange &&
212
- handleOnCustomFilterChange(key(column), value),
158
+ handleOnCustomFilterChange(getColumnKey(column), value),
213
159
  )
214
160
  ) : (
215
161
  <CFormInput
216
162
  size="sm"
217
163
  onInput={(event) =>
218
164
  handleFilterOnInput &&
219
- handleFilterOnInput(key(column), (event.target as HTMLInputElement).value)
165
+ handleFilterOnInput(
166
+ getColumnKey(column),
167
+ (event.target as HTMLInputElement).value,
168
+ )
220
169
  }
221
170
  onChange={(event) =>
222
171
  handleFilterOnChange &&
223
172
  handleFilterOnChange(
224
- key(column),
173
+ getColumnKey(column),
225
174
  (event.target as HTMLInputElement).value,
226
175
  )
227
176
  }
228
177
  value={
229
- columnFilterState && columnFilterState[key(column)]
230
- ? columnFilterState[key(column)]
178
+ columnFilterState && columnFilterState[getColumnKey(column)]
179
+ ? columnFilterState[getColumnKey(column)]
231
180
  : ''
232
181
  }
233
- aria-label={`column name: '${label(column)}' filter input`}
182
+ aria-label={`column name: '${getColumnLabel(column)}' filter input`}
234
183
  />
235
184
  )
236
185
  ) : (
@@ -258,7 +207,8 @@ CSmartTableHead.propTypes = {
258
207
  handleSelectAllChecked: PropTypes.func,
259
208
  handleSort: PropTypes.func,
260
209
  selectable: PropTypes.bool,
261
- selectAll: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
210
+ selectAll: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
211
+ selectedAll: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
262
212
  sorterState: PropTypes.object,
263
213
  sortingIcon: PropTypes.node,
264
214
  sortingIconAscending: PropTypes.node,