@coreui/react-pro 4.0.0 → 4.1.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.
Files changed (42) hide show
  1. package/README.md +157 -0
  2. package/dist/components/accordion/CAccordionCollapse.d.ts +1 -1
  3. package/dist/components/collapse/CCollapse.d.ts +4 -0
  4. package/dist/components/form/CFormCheck.d.ts +4 -0
  5. package/dist/components/form/CFormLabel.d.ts +2 -2
  6. package/dist/components/form/CFormSelect.d.ts +13 -0
  7. package/dist/components/placeholder/CPlaceholder.d.ts +51 -0
  8. package/dist/components/popover/CPopover.d.ts +2 -2
  9. package/dist/components/smart-table/CSmartTableBody.d.ts +3 -3
  10. package/dist/components/smart-table/CSmartTableHead.d.ts +2 -1
  11. package/dist/components/smart-table/CSmartTableInterface.d.ts +9 -6
  12. package/dist/components/tooltip/CTooltip.d.ts +1 -1
  13. package/dist/index.d.ts +2 -1
  14. package/dist/index.es.js +371 -239
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/index.js +371 -238
  17. package/dist/index.js.map +1 -1
  18. package/package.json +11 -11
  19. package/src/components/accordion/CAccordionCollapse.tsx +1 -1
  20. package/src/components/collapse/CCollapse.tsx +36 -3
  21. package/src/components/form/CFormCheck.tsx +30 -3
  22. package/src/components/form/CFormLabel.tsx +2 -2
  23. package/src/components/form/CFormSelect.tsx +28 -2
  24. package/src/components/form/__tests__/CFormLabel.spec.tsx +8 -0
  25. package/src/components/form/__tests__/__snapshots__/CFormLabel.spec.tsx.snap +11 -0
  26. package/src/components/grid/CCol.tsx +8 -8
  27. package/src/components/grid/CContainer.tsx +3 -3
  28. package/src/components/grid/CRow.tsx +6 -6
  29. package/src/components/offcanvas/COffcanvas.tsx +15 -2
  30. package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -1
  31. package/src/components/offcanvas/__tests__/__snapshots__/COffcanvas.spec.tsx.snap +2 -2
  32. package/src/components/placeholder/CPlaceholder.tsx +114 -0
  33. package/src/components/placeholder/__tests__/CPlaceholder.spec.tsx +21 -0
  34. package/src/components/placeholder/__tests__/__snapshots__/CPlaceholder.spec.tsx.snap +17 -0
  35. package/src/components/popover/CPopover.tsx +4 -4
  36. package/src/components/smart-table/CSmartTable.tsx +41 -45
  37. package/src/components/smart-table/CSmartTableBody.tsx +9 -4
  38. package/src/components/smart-table/CSmartTableHead.tsx +16 -3
  39. package/src/components/smart-table/CSmartTableInterface.tsx +10 -6
  40. package/src/components/tooltip/CTooltip.tsx +2 -2
  41. package/src/index.ts +2 -0
  42. package/src/utils/hooks/useForkedRef.ts +5 -0
@@ -13,7 +13,7 @@ export interface CPopoverProps {
13
13
  /**
14
14
  * Content node for your component.
15
15
  */
16
- content: ReactNode
16
+ content: ReactNode | string
17
17
  /**
18
18
  * Offset of the popover relative to its target.
19
19
  */
@@ -29,7 +29,7 @@ export interface CPopoverProps {
29
29
  /**
30
30
  * Title node for your component.
31
31
  */
32
- title?: ReactNode
32
+ title?: ReactNode | string
33
33
  /**
34
34
  * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
35
35
  *
@@ -147,12 +147,12 @@ export const CPopover: FC<CPopoverProps> = ({
147
147
 
148
148
  CPopover.propTypes = {
149
149
  children: PropTypes.any,
150
- content: PropTypes.node,
150
+ content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
151
151
  placement: PropTypes.oneOf(['auto', 'top', 'right', 'bottom', 'left']),
152
152
  offset: PropTypes.any, // TODO: find good proptype
153
153
  onHide: PropTypes.func,
154
154
  onShow: PropTypes.func,
155
- title: PropTypes.string,
155
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
156
156
  trigger: triggerPropType,
157
157
  visible: PropTypes.bool,
158
158
  }
@@ -1,7 +1,13 @@
1
1
  import React, { ChangeEvent, forwardRef, useEffect, useMemo, useRef, useState } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import { ColumnFilterValue, CSmartTableProps, Item, SorterValue } from './CSmartTableInterface'
4
+ import {
5
+ ColumnFilterValue,
6
+ CSmartTableProps,
7
+ Item,
8
+ ItemInternal,
9
+ SorterValue,
10
+ } from './CSmartTableInterface'
5
11
 
6
12
  import { CSmartPagination } from '../pagination/CSmartPagination'
7
13
  import { CElementCover } from '../element-cover/CElementCover'
@@ -95,19 +101,32 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
95
101
  const compData = useRef({ firstRun: true, columnFiltered: 0, changeItems: 0 }).current
96
102
 
97
103
  const previousSorterValue = useRef<SorterValue>()
104
+ const previousItemsValue = useRef<Item[]>()
105
+
106
+ const [_activePage, setActivePage] = useState<number>(activePage)
107
+ const [_items, setItems] = useState<ItemInternal[]>([])
108
+ const [_itemsPerPage, setItemsPerPage] = useState(itemsPerPage)
109
+ const [columnFilterState, setColumnFilterState] = useState<ColumnFilterValue>(
110
+ columnFilterValue ? columnFilterValue : {},
111
+ )
112
+ const [selectedAll, setSelectedAll] = useState<boolean | string>()
113
+ const [sorterState, setSorterState] = useState<SorterValue>(previousSorterValue.current || {})
114
+ const [tableFilterState, setTableFilterState] = useState<string>(
115
+ tableFilterValue ? tableFilterValue : '',
116
+ )
98
117
 
99
118
  useMemo(() => {
100
119
  if (JSON.stringify(previousSorterValue.current) !== JSON.stringify(sorterValue)) {
101
120
  previousSorterValue.current = sorterValue
121
+ setSorterState({ ...sorterValue })
102
122
  }
103
123
  }, [sorterValue])
104
124
 
105
- const previousItemsValue = useRef<Item[]>()
106
-
107
- const [_items, setItems] = useState<Item[]>([])
108
-
109
125
  useMemo(() => {
110
126
  if (JSON.stringify(previousItemsValue.current) !== JSON.stringify(items)) {
127
+ if (items && items.length < _itemsPerPage * _activePage - _itemsPerPage) {
128
+ setActivePage(1)
129
+ }
111
130
  previousItemsValue.current = items
112
131
 
113
132
  Array.isArray(items) &&
@@ -119,18 +138,6 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
119
138
  }
120
139
  }, [items])
121
140
 
122
- const [_itemsPerPage, setItemsPerPage] = useState(itemsPerPage)
123
- const [_activePage, setActivePage] = useState<number>(activePage)
124
- const [selectedAll, setSelectedAll] = useState<boolean | string>()
125
-
126
- const [sorterState, setSorterState] = useState<SorterValue>(previousSorterValue.current || {})
127
- const [tableFilterState, setTableFilterState] = useState<string>(
128
- tableFilterValue ? tableFilterValue : '',
129
- )
130
- const [columnFilterState, setColumnFilterState] = useState<ColumnFilterValue>(
131
- columnFilterValue ? columnFilterValue : {},
132
- )
133
-
134
141
  // functions
135
142
 
136
143
  const isSortable = (i: number): boolean | undefined => {
@@ -160,7 +167,11 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
160
167
  } else if (state.state === 'asc') {
161
168
  state.state = 'desc'
162
169
  } else {
163
- state.state = 0
170
+ if (typeof columnSorter === 'object' && !columnSorter.resetable) {
171
+ state.state = 'asc'
172
+ } else {
173
+ state.state = 0
174
+ }
164
175
  }
165
176
  } else {
166
177
  state.column = column
@@ -183,6 +194,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
183
194
  return
184
195
  }
185
196
  const newState = { ...columnFilterState, [`${colName}`]: value }
197
+ setActivePage(1)
186
198
  setColumnFilterState(newState)
187
199
  }
188
200
 
@@ -191,6 +203,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
191
203
  if ((isLazy && type === 'input') || (!isLazy && type === 'change')) {
192
204
  return
193
205
  }
206
+ setActivePage(1)
194
207
  setTableFilterState(value)
195
208
  }
196
209
 
@@ -222,7 +235,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
222
235
  compData.changeItems,
223
236
  ])
224
237
 
225
- const columnFiltered: Item[] = useMemo(() => {
238
+ const columnFiltered: ItemInternal[] = useMemo(() => {
226
239
  let items = _items
227
240
  if (columnFilter && typeof columnFilter === 'object' && columnFilter.external) {
228
241
  return items
@@ -238,7 +251,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
238
251
  return items
239
252
  }, [compData.columnFiltered, _items])
240
253
 
241
- const tableFiltered: Item[] = useMemo(() => {
254
+ const tableFiltered: ItemInternal[] = useMemo(() => {
242
255
  let items = columnFiltered
243
256
  if (
244
257
  !tableFilterState ||
@@ -259,7 +272,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
259
272
  JSON.stringify(columnFiltered),
260
273
  ])
261
274
 
262
- const sortedItems: Item[] = useMemo(() => {
275
+ const sortedItems: ItemInternal[] = useMemo(() => {
263
276
  const col = sorterState?.column
264
277
  if (
265
278
  !col ||
@@ -285,12 +298,12 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
285
298
 
286
299
  const firstItemOnActivePageIndex: number = _activePage ? (_activePage - 1) * _itemsPerPage : 0
287
300
 
288
- const itemsOnActivePage: Item[] = sortedItems.slice(
301
+ const itemsOnActivePage: ItemInternal[] = sortedItems.slice(
289
302
  firstItemOnActivePageIndex,
290
303
  firstItemOnActivePageIndex + _itemsPerPage,
291
304
  )
292
305
 
293
- const currentItems: Item[] = _activePage ? itemsOnActivePage : sortedItems
306
+ const currentItems: ItemInternal[] = _activePage ? itemsOnActivePage : sortedItems
294
307
 
295
308
  const isFiltered: string =
296
309
  tableFilterState || sorterState?.column || Object.values(columnFilterState).join('')
@@ -332,23 +345,6 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
332
345
  )
333
346
  useMemo(() => setColumnFilterState({ ...columnFilterValue }), [columnFilterValue])
334
347
 
335
- //items
336
- // useMemo(() => {
337
- // if (
338
- // items &&
339
- // !compData.firstRun &&
340
- // (items.length !== _items.length || JSON.stringify(items) !== JSON.stringify(_items))
341
- // ) {
342
- // setItems(
343
- // items?.map((item: Item, index: number) => {
344
- // return { ...item, _id: index }
345
- // }),
346
- // )
347
-
348
- // compData.changeItems++
349
- // }
350
- // }, [items])
351
-
352
348
  compData.firstRun = false
353
349
 
354
350
  const handleRowChecked = (id: number, value: boolean) => {
@@ -360,7 +356,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
360
356
  const handleSelectAllChecked = () => {
361
357
  if (selectedAll === true) {
362
358
  setItems(
363
- _items.map((item: Item) => {
359
+ _items.map((item: ItemInternal) => {
364
360
  return { ...item, _selected: false }
365
361
  }),
366
362
  )
@@ -368,7 +364,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
368
364
  }
369
365
 
370
366
  setItems(
371
- _items.map((item: Item) => {
367
+ _items.map((item: ItemInternal) => {
372
368
  return { ...item, _selected: true }
373
369
  }),
374
370
  )
@@ -377,6 +373,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
377
373
  useEffect(() => {
378
374
  if (selectable) {
379
375
  const selected = _items.filter((item) => item._selected === true)
376
+ onSelectedItemsChange && onSelectedItemsChange(selected)
380
377
 
381
378
  if (selected.length === _items.length) {
382
379
  setSelectedAll(true)
@@ -391,8 +388,6 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
391
388
  if (selected.length !== 0 && selected.length !== _items.length) {
392
389
  setSelectedAll('indeterminate')
393
390
  }
394
-
395
- onSelectedItemsChange && onSelectedItemsChange(selected)
396
391
  }
397
392
  }, [_items])
398
393
 
@@ -440,6 +435,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
440
435
  <CSmartTableHead
441
436
  {...tableHeadProps}
442
437
  columnFilter={columnFilter}
438
+ columnFilterState={columnFilterState}
443
439
  columns={columns ? columns : rawColumnNames}
444
440
  columnSorter={columnSorter}
445
441
  selectable={selectable}
@@ -492,7 +488,7 @@ export const CSmartTable = forwardRef<HTMLDivElement, CSmartTableProps>(
492
488
 
493
489
  {(pagination || itemsPerPageSelect) && (
494
490
  <div className="row">
495
- <div className="col-auto">
491
+ <div className="col">
496
492
  {pagination && numberOfPages > 1 && (
497
493
  <CSmartPagination
498
494
  {...paginationProps}
@@ -7,15 +7,20 @@ import { CTableDataCell } from '../table/CTableDataCell'
7
7
 
8
8
  import { CFormCheck } from '../form/CFormCheck'
9
9
 
10
- import { Item, ScopedColumns } from './CSmartTableInterface'
10
+ import { Item, ItemInternal, ScopedColumns } from './CSmartTableInterface'
11
11
 
12
12
  export interface CSmartTableBodyProps extends CTableBodyProps {
13
13
  clickableRows?: boolean
14
- currentItems: Item[]
14
+ currentItems: ItemInternal[]
15
15
  firstItemOnActivePageIndex: number
16
16
  noItemsLabel?: string | ReactNode
17
17
  onRowChecked?: (id: number, value: boolean) => void
18
- onRowClick?: (item: Item, index: number, columnName: string, event: MouseEvent | boolean) => void
18
+ onRowClick?: (
19
+ item: ItemInternal,
20
+ index: number,
21
+ columnName: string,
22
+ event: MouseEvent | boolean,
23
+ ) => void
19
24
  rawColumnNames: string[]
20
25
  scopedColumns?: ScopedColumns
21
26
  selectable?: boolean
@@ -64,7 +69,7 @@ export const CSmartTableBody = forwardRef<HTMLTableSectionElement, CSmartTableBo
64
69
  {...rest}
65
70
  ref={ref}
66
71
  >
67
- {currentItems.map((item: Item, trIndex) => {
72
+ {currentItems.map((item: ItemInternal, trIndex) => {
68
73
  return (
69
74
  <React.Fragment key={trIndex}>
70
75
  <CTableRow
@@ -1,7 +1,13 @@
1
1
  import React, { ElementType, forwardRef, ReactNode, useEffect, useRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import { ColumnFilter, Column, Sorter, SorterValue } from './CSmartTableInterface'
4
+ import {
5
+ ColumnFilter,
6
+ ColumnFilterValue,
7
+ Column,
8
+ Sorter,
9
+ SorterValue,
10
+ } from './CSmartTableInterface'
5
11
 
6
12
  import { CFormInput } from '../form/CFormInput'
7
13
  import { CFormCheck } from '../form/CFormCheck'
@@ -10,6 +16,7 @@ import { CTableHeaderCell } from '../table/CTableHeaderCell'
10
16
  import { CTableRow } from '../table/CTableRow'
11
17
  export interface CSmartTableHeadProps extends CTableHeadProps {
12
18
  columnFilter?: boolean | ColumnFilter
19
+ columnFilterState?: ColumnFilterValue
13
20
  columnSorter?: boolean | Sorter
14
21
  component?: string | ElementType
15
22
  columns: (Column | string)[]
@@ -29,6 +36,7 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
29
36
  (
30
37
  {
31
38
  columnFilter,
39
+ columnFilterState,
32
40
  columnSorter,
33
41
  component: Component = CTableHead,
34
42
  columns,
@@ -176,7 +184,11 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
176
184
  handleFilterOnChange &&
177
185
  handleFilterOnChange(key(column), (event.target as HTMLInputElement).value)
178
186
  }
179
- // value={columnFilterState[colName] || ''}
187
+ value={
188
+ columnFilterState && columnFilterState[key(column)]
189
+ ? columnFilterState[key(column)]
190
+ : ''
191
+ }
180
192
  aria-label={`column name: '${label(column)}' filter input`}
181
193
  />
182
194
  )}
@@ -192,7 +204,8 @@ export const CSmartTableHead = forwardRef<HTMLTableSectionElement, CSmartTableHe
192
204
 
193
205
  CSmartTableHead.propTypes = {
194
206
  columnFilter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
195
- columnSorter: PropTypes.bool,
207
+ columnFilterState: PropTypes.object,
208
+ columnSorter: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
196
209
  component: PropTypes.elementType,
197
210
  children: PropTypes.node,
198
211
  columns: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.any, PropTypes.string])).isRequired, // TODO: improve this Prop Type,
@@ -8,10 +8,10 @@ import { CTableRowProps } from '../table/CTableRow'
8
8
  import { CTableHeadProps } from '../table/CTableHead'
9
9
 
10
10
  export interface Column {
11
- sorter?: boolean
12
- key: string
13
- label?: string
14
11
  filter?: boolean
12
+ label?: string
13
+ key: string
14
+ sorter?: boolean
15
15
  _style?: any
16
16
  _props?: CTableHeaderCellProps
17
17
  }
@@ -27,9 +27,12 @@ export interface ColumnFilterValue {
27
27
 
28
28
  export interface Item {
29
29
  [key: string]: number | string | any
30
+ _props?: CTableRowProps
31
+ _selected?: boolean
32
+ }
33
+
34
+ export interface ItemInternal extends Item {
30
35
  _id: number
31
- _props: CTableRowProps
32
- _selected: boolean
33
36
  }
34
37
 
35
38
  export interface ItemsPerPageSelect {
@@ -44,6 +47,7 @@ export interface Sorter {
44
47
  }
45
48
 
46
49
  export interface ScopedColumns {
50
+ [key: string]: any
47
51
  details?: (a: Item, b: number) => ReactNode
48
52
  }
49
53
 
@@ -115,7 +119,7 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
115
119
  * - sorter (Boolean) - disables sorting of the column when set to false
116
120
  * - filter (Boolean) - removes filter from column when set to false.
117
121
  */
118
- columns?: Column[] | string[]
122
+ columns?: (string | Column)[]
119
123
  /**
120
124
  * Enables table sorting by column value. Sorting will be performed corectly only if values in column are of one type: string (case insensitive) or number.
121
125
  *
@@ -13,7 +13,7 @@ export interface CTooltipProps {
13
13
  /**
14
14
  * Content node for your component.
15
15
  */
16
- content: ReactNode
16
+ content: ReactNode | string
17
17
  /**
18
18
  * Callback fired when the component requests to be hidden.
19
19
  */
@@ -126,7 +126,7 @@ export const CTooltip: FC<CTooltipProps> = ({
126
126
 
127
127
  CTooltip.propTypes = {
128
128
  children: PropTypes.any,
129
- content: PropTypes.node,
129
+ content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
130
130
  placement: PropTypes.oneOf(['auto', 'top', 'right', 'bottom', 'left']),
131
131
  onHide: PropTypes.func,
132
132
  onShow: PropTypes.func,
package/src/index.ts CHANGED
@@ -89,6 +89,7 @@ import { CNavbarToggler } from './components/navbar/CNavbarToggler'
89
89
  import { CPagination } from './components/pagination/CPagination'
90
90
  import { CPaginationItem } from './components/pagination/CPaginationItem'
91
91
  import { CSmartPagination } from './components/pagination/CSmartPagination'
92
+ import { CPlaceholder } from './components/placeholder/CPlaceholder'
92
93
  import { CPopover } from './components/popover/CPopover'
93
94
  import { CProgress } from './components/progress/CProgress'
94
95
  import { CProgressBar } from './components/progress/CProgressBar'
@@ -212,6 +213,7 @@ export {
212
213
  CNavbarToggler,
213
214
  CPagination,
214
215
  CPaginationItem,
216
+ CPlaceholder,
215
217
  CPopover,
216
218
  CProgress,
217
219
  CProgressBar,
@@ -9,6 +9,7 @@ export type AssignableRef<ValueType> =
9
9
  }['bivarianceHack']
10
10
  | React.MutableRefObject<ValueType | null>
11
11
 
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
13
  export function useForkedRef<RefValueType = any>(
13
14
  ...refs: (AssignableRef<RefValueType> | null | undefined)[]
14
15
  ) {
@@ -16,6 +17,7 @@ export function useForkedRef<RefValueType = any>(
16
17
  if (refs.every((ref) => ref == null)) {
17
18
  return null
18
19
  }
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
21
  return (node: any) => {
20
22
  refs.forEach((ref) => {
21
23
  assignRef(ref, node)
@@ -24,8 +26,10 @@ export function useForkedRef<RefValueType = any>(
24
26
  }, refs)
25
27
  }
26
28
 
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
30
  export function assignRef<RefValueType = any>(
28
31
  ref: AssignableRef<RefValueType> | null | undefined,
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
33
  value: any,
30
34
  ) {
31
35
  if (ref == null) return
@@ -40,6 +44,7 @@ export function assignRef<RefValueType = any>(
40
44
  }
41
45
  }
42
46
 
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
43
48
  export function isFunction(value: any): value is Function {
44
49
  return !!(value && {}.toString.call(value) == '[object Function]')
45
50
  }