@coreui/react 4.2.1 → 4.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreui/react",
3
- "version": "4.2.1",
3
+ "version": "4.3.0",
4
4
  "description": "UI Components Library for React.js",
5
5
  "keywords": [
6
6
  "react",
@@ -36,27 +36,27 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@popperjs/core": "^2.11.5",
39
- "@rollup/plugin-commonjs": "^21.0.3",
40
- "@rollup/plugin-node-resolve": "^13.1.3",
41
- "@rollup/plugin-typescript": "^8.3.1",
39
+ "@rollup/plugin-commonjs": "^22.0.1",
40
+ "@rollup/plugin-node-resolve": "^13.3.0",
41
+ "@rollup/plugin-typescript": "^8.3.3",
42
42
  "@testing-library/jest-dom": "^5.16.4",
43
- "@testing-library/react": "^12.1.4",
44
- "@types/react": "17.0.39",
45
- "@types/react-dom": "^17.0.15",
46
- "@types/react-transition-group": "^4.4.4",
43
+ "@testing-library/react": "^13.3.0",
44
+ "@types/react": "18.0.15",
45
+ "@types/react-dom": "^18.0.6",
46
+ "@types/react-transition-group": "^4.4.5",
47
47
  "classnames": "^2.3.1",
48
48
  "prop-types": "^15.8.1",
49
- "react": "^17.0.2",
50
- "react-dom": "^17.0.2",
49
+ "react": "^18.2.0",
50
+ "react-dom": "^18.2.0",
51
51
  "react-popper": "^2.2.5",
52
52
  "react-transition-group": "^4.4.2",
53
- "rollup": "^2.70.1",
53
+ "rollup": "^2.75.7",
54
54
  "rollup-plugin-peer-deps-external": "^2.2.4",
55
55
  "tslib": "^2.4.0",
56
- "typescript": "^4.6.3"
56
+ "typescript": "^4.7.4"
57
57
  },
58
58
  "peerDependencies": {
59
- "react": "^17",
60
- "react-dom": "^17"
59
+ "react": ">=17",
60
+ "react-dom": ">=17"
61
61
  }
62
62
  }
@@ -29,7 +29,14 @@ export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
29
29
  className,
30
30
  )
31
31
  return (
32
- <button className={_className} aria-label="Close" disabled={disabled} {...rest} ref={ref} />
32
+ <button
33
+ type="button"
34
+ className={_className}
35
+ aria-label="Close"
36
+ disabled={disabled}
37
+ {...rest}
38
+ ref={ref}
39
+ />
33
40
  )
34
41
  },
35
42
  )
@@ -1,4 +1,4 @@
1
- import React, { ChangeEventHandler, forwardRef, InputHTMLAttributes } from 'react'
1
+ import React, { ChangeEventHandler, forwardRef, TextareaHTMLAttributes } from 'react'
2
2
 
3
3
  import classNames from 'classnames'
4
4
  import PropTypes from 'prop-types'
@@ -7,7 +7,7 @@ import { CFormControlWrapper, CFormControlWrapperProps } from './CFormControlWra
7
7
 
8
8
  export interface CFormTextareaProps
9
9
  extends CFormControlWrapperProps,
10
- InputHTMLAttributes<HTMLTextAreaElement> {
10
+ TextareaHTMLAttributes<HTMLTextAreaElement> {
11
11
  /**
12
12
  * A string of all className you want applied to the component.
13
13
  */
@@ -19,6 +19,7 @@ test('CFormTextarea customize', async () => {
19
19
  readOnly={true}
20
20
  valid={true}
21
21
  defaultValue="Some value"
22
+ rows={2}
22
23
  />,
23
24
  )
24
25
  expect(container).toMatchSnapshot()
@@ -193,7 +193,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
193
193
  }
194
194
 
195
195
  const handleKeyDown = useCallback(
196
- (event) => {
196
+ (event: KeyboardEvent) => {
197
197
  if (event.key === 'Escape' && keyboard) {
198
198
  return handleDismiss()
199
199
  }
@@ -107,7 +107,7 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
107
107
  }
108
108
 
109
109
  const handleKeyDown = useCallback(
110
- (event) => {
110
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
111
111
  if (event.key === 'Escape' && keyboard) {
112
112
  return handleDismiss()
113
113
  }
@@ -7,6 +7,7 @@ import { usePopper } from 'react-popper'
7
7
  import { Transition } from 'react-transition-group'
8
8
 
9
9
  import { Triggers, triggerPropType } from '../Types'
10
+ import { useEffect } from 'react'
10
11
 
11
12
  export interface CPopoverProps {
12
13
  // TODO: find solution to not use any
@@ -78,6 +79,10 @@ export const CPopover: FC<CPopoverProps> = ({
78
79
  placement: placement,
79
80
  })
80
81
 
82
+ useEffect(() => {
83
+ setVisible(visible)
84
+ }, [visible])
85
+
81
86
  const getTransitionClass = (state: string) => {
82
87
  return state === 'entering'
83
88
  ? 'fade'
@@ -9,7 +9,7 @@ exports[`CPopover customize 1`] = `
9
9
  Test
10
10
  </button>
11
11
  <div
12
- class="popover bs-popover-end fade show"
12
+ class="popover bs-popover-end fade"
13
13
  role="tooltip"
14
14
  style="position: absolute; left: 0px; top: 0px;"
15
15
  >
@@ -3,8 +3,15 @@ import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
5
  import { Colors, colorPropType } from '../Types'
6
+ import { CTableHead, CTableHeadProps } from './CTableHead'
7
+ import { CTableHeaderCell, CTableHeaderCellProps } from './CTableHeaderCell'
8
+ import { CTableBody } from './CTableBody'
9
+ import { CTableDataCell, CTableDataCellProps } from './CTableDataCell'
10
+ import { CTableRow, CTableRowProps } from './CTableRow'
11
+ import { CTableFoot, CTableFootProps } from './CTableFoot'
12
+ import { CTableCaption } from './CTableCaption'
6
13
 
7
- export interface CTableProps extends TableHTMLAttributes<HTMLTableElement> {
14
+ export interface CTableProps extends Omit<TableHTMLAttributes<HTMLTableElement>, 'align'> {
8
15
  /**
9
16
  * Set the vertical aligment.
10
17
  */
@@ -24,23 +31,63 @@ export interface CTableProps extends TableHTMLAttributes<HTMLTableElement> {
24
31
  */
25
32
  borderless?: boolean
26
33
  /**
27
- * Put the `<caption>` on the top of the table.
34
+ * Put the caption on the top if you set `caption="top"` of the table or set the text of the table caption.
28
35
  */
29
- caption?: 'top'
36
+ caption?: 'top' | string
37
+ /**
38
+ * Set the text of the table caption and the caption on the top of the table.
39
+ *
40
+ * @since 4.3.0
41
+ */
42
+ captionTop?: string
30
43
  /**
31
44
  * A string of all className you want applied to the component.
32
45
  */
33
46
  className?: string
47
+ /**
48
+ * Prop for table columns configuration. If prop is not defined, table will display columns based on the first item keys, omitting keys that begins with underscore (e.g. '_props')
49
+ *
50
+ * In columns prop each array item represents one column. Item might be specified in two ways:
51
+ * String: each item define column name equal to item value.
52
+ * Object: item is object with following keys available as column configuration:
53
+ * - key (required)(String) - define column name equal to item key.
54
+ * - label (String) - define visible label of column. If not defined, label will be generated automatically based on column name, by converting kebab-case and snake_case to individual words and capitalization of each word.
55
+ * - _props (Object) - adds classes to all cels in column, ex. _props: { scope: 'col', className: 'custom-class' },
56
+ * - _style (Object) - adds styles to the column header (useful for defining widths)
57
+ *
58
+ * @since 4.3.0
59
+ */
60
+ columns?: (string | Column)[]
34
61
  /**
35
62
  * Sets the color context of the component to one of CoreUI’s themed colors.
36
63
  *
37
64
  * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
38
65
  */
39
66
  color?: Colors
67
+ /**
68
+ * Array of objects or strings, where each element represents one cell in the table footer.
69
+ *
70
+ * Example items:
71
+ * ['FooterCell', 'FooterCell', 'FooterCell']
72
+ * or
73
+ * [{ label: 'FooterCell', _props: { color: 'success' }, ...]
74
+ *
75
+ * @since 4.3.0
76
+ */
77
+ footer?: FooterItem[]
40
78
  /**
41
79
  * Enable a hover state on table rows within a `<CTableBody>`.
42
80
  */
43
81
  hover?: boolean
82
+ /**
83
+ * Array of objects, where each object represents one item - row in table. Additionally, you can add style classes to each row by passing them by '_props' key and to single cell by '_cellProps'.
84
+ *
85
+ * Example item:
86
+ * { name: 'John' , age: 12, _props: { color: 'success' }, _cellProps: { age: { className: 'fw-bold'}}}
87
+ *
88
+ * @since 4.3.0
89
+ */
90
+ items?: Item[]
44
91
  /**
45
92
  * Make any table responsive across all viewports or pick a maximum breakpoint with which to have a responsive table up to.
46
93
  */
@@ -53,6 +100,43 @@ export interface CTableProps extends TableHTMLAttributes<HTMLTableElement> {
53
100
  * Add zebra-striping to any table row within the `<CTableBody>`.
54
101
  */
55
102
  striped?: boolean
103
+ /**
104
+ * Add zebra-striping to any table column.
105
+ *
106
+ * @since 4.3.0
107
+ */
108
+ stripedColumns?: boolean
109
+ /**
110
+ * Properties that will be passed to the table footer component.
111
+ *
112
+ * @link https://coreui.io/react/docs/components/table/#ctablefoot
113
+ * @since 4.3.0
114
+ */
115
+ tableFootProps?: CTableFootProps
116
+ /**
117
+ * Properties that will be passed to the table head component.
118
+ *
119
+ * @link https://coreui.io/react/docs/components/table/#ctablehead
120
+ * @since 4.3.0
121
+ */
122
+ tableHeadProps?: CTableHeadProps
123
+ }
124
+
125
+ export interface Column {
126
+ label?: string
127
+ key: string
128
+ _style?: any
129
+ _props?: CTableHeaderCellProps
130
+ }
131
+
132
+ export interface Item {
133
+ [key: string]: number | string | any
134
+ _props?: CTableRowProps
135
+ }
136
+
137
+ export interface FooterItem {
138
+ label?: string
139
+ _props?: CTableDataCellProps
56
140
  }
57
141
 
58
142
  export const CTable = forwardRef<HTMLTableElement, CTableProps>(
@@ -64,12 +148,19 @@ export const CTable = forwardRef<HTMLTableElement, CTableProps>(
64
148
  bordered,
65
149
  borderless,
66
150
  caption,
151
+ captionTop,
67
152
  className,
68
153
  color,
154
+ columns,
155
+ footer,
69
156
  hover,
157
+ items = [],
70
158
  responsive,
71
159
  small,
72
160
  striped,
161
+ stripedColumns,
162
+ tableFootProps,
163
+ tableHeadProps,
73
164
  ...rest
74
165
  },
75
166
  ref,
@@ -78,32 +169,109 @@ export const CTable = forwardRef<HTMLTableElement, CTableProps>(
78
169
  'table',
79
170
  {
80
171
  [`align-${align}`]: align,
81
- [`caption-${caption}`]: caption,
82
172
  [`border-${borderColor}`]: borderColor,
173
+ [`caption-top`]: captionTop || caption === 'top',
83
174
  'table-bordered': bordered,
84
175
  'table-borderless': borderless,
85
176
  [`table-${color}`]: color,
86
177
  'table-hover': hover,
87
178
  'table-sm': small,
88
179
  'table-striped': striped,
180
+ 'table-striped-columns': stripedColumns,
89
181
  },
90
182
  className,
91
183
  )
92
184
 
185
+ const rawColumnNames = columns
186
+ ? columns.map((column: Column) => {
187
+ if (typeof column === 'object') return column.key
188
+ else return column
189
+ })
190
+ : Object.keys(items[0] || {}).filter((el) => el.charAt(0) !== '_')
191
+
192
+ const pretifyName = (name: string) => {
193
+ return name
194
+ .replace(/[-_.]/g, ' ')
195
+ .replace(/ +/g, ' ')
196
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
197
+ .split(' ')
198
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
199
+ .join(' ')
200
+ }
201
+
202
+ const label = (column: Column | string) =>
203
+ typeof column === 'object'
204
+ ? column.label !== undefined
205
+ ? column.label
206
+ : pretifyName(column.key)
207
+ : pretifyName(column)
208
+
209
+ const Table = () => (
210
+ <table className={_className} {...rest} ref={ref}>
211
+ {((caption && caption !== 'top') || captionTop) && (
212
+ <CTableCaption>{caption || captionTop}</CTableCaption>
213
+ )}
214
+ {columns && (
215
+ <CTableHead {...tableHeadProps}>
216
+ <CTableRow>
217
+ {columns.map((column: Column, index: number) => (
218
+ <CTableHeaderCell
219
+ {...(column._props && { ...column._props })}
220
+ {...(column._style && { style: { ...column._style } })}
221
+ key={index}
222
+ >
223
+ {label(column)}
224
+ </CTableHeaderCell>
225
+ ))}
226
+ </CTableRow>
227
+ </CTableHead>
228
+ )}
229
+ {items && (
230
+ <CTableBody>
231
+ {items.map((item: Item, index: number) => (
232
+ <CTableRow {...(item._props && { ...item._props })} key={index}>
233
+ {rawColumnNames.map((colName: string, index: number) => {
234
+ return item[colName] ? (
235
+ <CTableDataCell
236
+ {...(item._cellProps && {
237
+ ...(item._cellProps['all'] && { ...item._cellProps['all'] }),
238
+ ...(item._cellProps[colName] && { ...item._cellProps[colName] }),
239
+ })}
240
+ key={index}
241
+ >
242
+ {item[colName]}
243
+ </CTableDataCell>
244
+ ) : null
245
+ })}
246
+ </CTableRow>
247
+ ))}
248
+ </CTableBody>
249
+ )}
250
+ {children}
251
+ {footer && (
252
+ <CTableFoot {...tableFootProps}>
253
+ <CTableRow>
254
+ {footer.map((item: FooterItem, index: number) => (
255
+ <CTableDataCell {...(item._props && { ...item._props })} key={index}>
256
+ {typeof item === 'object' ? item.label : item}
257
+ </CTableDataCell>
258
+ ))}
259
+ </CTableRow>
260
+ </CTableFoot>
261
+ )}
262
+ </table>
263
+ )
264
+
93
265
  return responsive ? (
94
266
  <div
95
267
  className={
96
268
  typeof responsive === 'boolean' ? 'table-responsive' : `table-responsive-${responsive}`
97
269
  }
98
270
  >
99
- <table className={_className ? _className : undefined} {...rest} ref={ref}>
100
- {children}
101
- </table>
271
+ <Table />
102
272
  </div>
103
273
  ) : (
104
- <table className={_className ? _className : undefined} {...rest} ref={ref}>
105
- {children}
106
- </table>
274
+ <Table />
107
275
  )
108
276
  },
109
277
  )
@@ -113,17 +281,24 @@ CTable.propTypes = {
113
281
  borderColor: PropTypes.string,
114
282
  bordered: PropTypes.bool,
115
283
  borderless: PropTypes.bool,
116
- caption: PropTypes.oneOf(['top']),
284
+ caption: PropTypes.oneOfType([PropTypes.string, PropTypes.oneOf(['top'])]),
285
+ captionTop: PropTypes.string,
117
286
  children: PropTypes.node,
118
287
  className: PropTypes.string,
119
288
  color: colorPropType,
289
+ columns: PropTypes.array,
290
+ footer: PropTypes.array,
120
291
  hover: PropTypes.bool,
292
+ items: PropTypes.array,
121
293
  responsive: PropTypes.oneOfType([
122
294
  PropTypes.bool,
123
295
  PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']),
124
296
  ]),
125
297
  small: PropTypes.bool,
126
298
  striped: PropTypes.bool,
299
+ stripedColumns: PropTypes.bool,
300
+ tableFootProps: PropTypes.shape({ ...CTableFoot.propTypes }),
301
+ tableHeadProps: PropTypes.shape({ ...CTableHead.propTypes }),
127
302
  }
128
303
 
129
304
  CTable.displayName = 'CTable'
@@ -1,11 +1,12 @@
1
- import React, { forwardRef, TdHTMLAttributes } from 'react'
1
+ import React, { forwardRef, TdHTMLAttributes, ThHTMLAttributes } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
5
  import { Colors, colorPropType } from '../Types'
6
6
 
7
7
  export interface CTableDataCellProps
8
- extends Omit<TdHTMLAttributes<HTMLTableDataCellElement>, 'align'> {
8
+ extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'>,
9
+ Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'> {
9
10
  /**
10
11
  * Highlight a table row or cell.
11
12
  */
@@ -26,7 +27,7 @@ export interface CTableDataCellProps
26
27
  color?: Colors
27
28
  }
28
29
 
29
- export const CTableDataCell = forwardRef<HTMLTableDataCellElement, CTableDataCellProps>(
30
+ export const CTableDataCell = forwardRef<HTMLTableCellElement, CTableDataCellProps>(
30
31
  ({ children, active, align, className, color, ...rest }, ref) => {
31
32
  const _className = classNames(
32
33
  {
@@ -37,10 +38,12 @@ export const CTableDataCell = forwardRef<HTMLTableDataCellElement, CTableDataCel
37
38
  className,
38
39
  )
39
40
 
41
+ const Component = rest.scope ? 'th' : 'td'
42
+
40
43
  return (
41
- <td className={_className ? _className : undefined} {...rest} ref={ref}>
44
+ <Component className={_className ? _className : undefined} {...rest} ref={ref}>
42
45
  {children}
43
- </td>
46
+ </Component>
44
47
  )
45
48
  },
46
49
  )
@@ -4,7 +4,7 @@ import classNames from 'classnames'
4
4
 
5
5
  import { Colors, colorPropType } from '../Types'
6
6
 
7
- export interface CTableHeaderCellProps extends ThHTMLAttributes<HTMLTableHeaderCellElement> {
7
+ export interface CTableHeaderCellProps extends ThHTMLAttributes<HTMLTableCellElement> {
8
8
  /**
9
9
  * A string of all className you want applied to the component.
10
10
  */
@@ -17,7 +17,7 @@ export interface CTableHeaderCellProps extends ThHTMLAttributes<HTMLTableHeaderC
17
17
  color?: Colors
18
18
  }
19
19
 
20
- export const CTableHeaderCell = forwardRef<HTMLTableHeaderCellElement, CTableHeaderCellProps>(
20
+ export const CTableHeaderCell = forwardRef<HTMLTableCellElement, CTableHeaderCellProps>(
21
21
  ({ children, className, color, ...rest }, ref) => {
22
22
  const _className = classNames(
23
23
  {