@coreui/react-pro 4.8.0 → 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 (67) 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 +0 -4
  7. package/dist/components/element-cover/index.d.ts +2 -0
  8. package/dist/components/index.d.ts +1 -0
  9. package/dist/components/offcanvas/COffcanvas.d.ts +7 -1
  10. package/dist/components/smart-table/CSmartTableBody.d.ts +6 -5
  11. package/dist/components/smart-table/CSmartTableHead.d.ts +6 -3
  12. package/dist/components/smart-table/CSmartTableInterface.d.ts +30 -59
  13. package/dist/components/smart-table/types.d.ts +53 -0
  14. package/dist/components/smart-table/utils.d.ts +16 -0
  15. package/dist/components/time-picker/types.d.ts +15 -0
  16. package/dist/components/time-picker/utils.d.ts +23 -0
  17. package/dist/hooks/index.d.ts +3 -0
  18. package/dist/hooks/useForkedRef.d.ts +7 -0
  19. package/dist/hooks/useStateWithCallback.d.ts +2 -0
  20. package/dist/index.es.js +1076 -1005
  21. package/dist/index.es.js.map +1 -1
  22. package/dist/index.js +1076 -1004
  23. package/dist/index.js.map +1 -1
  24. package/dist/utils/index.d.ts +2 -1
  25. package/dist/utils/isObjectInArray.d.ts +2 -0
  26. package/package.json +11 -11
  27. package/src/components/alert/CAlert.tsx +1 -1
  28. package/src/components/backdrop/CBackdrop.tsx +1 -1
  29. package/src/components/calendar/CCalendar.tsx +351 -240
  30. package/src/components/calendar/index.ts +3 -0
  31. package/src/{utils/calendar.ts → components/calendar/utils.ts} +1 -1
  32. package/src/components/carousel/CCarousel.tsx +1 -1
  33. package/src/components/carousel/CCarouselItem.tsx +1 -1
  34. package/src/components/collapse/CCollapse.tsx +1 -1
  35. package/src/components/date-picker/CDatePicker.tsx +1 -1
  36. package/src/components/date-range-picker/CDateRangePicker.tsx +3 -3
  37. package/src/components/dropdown/CDropdown.tsx +1 -1
  38. package/src/components/dropdown/CDropdownToggle.tsx +1 -1
  39. package/src/components/element-cover/CElementCover.tsx +16 -22
  40. package/src/components/element-cover/index.ts +3 -0
  41. package/src/components/form/CFormCheck.tsx +1 -1
  42. package/src/components/index.ts +1 -0
  43. package/src/components/modal/CModal.tsx +1 -1
  44. package/src/components/nav/CNavLink.tsx +2 -1
  45. package/src/components/offcanvas/COffcanvas.tsx +35 -17
  46. package/src/components/sidebar/CSidebar.tsx +1 -1
  47. package/src/components/smart-table/CSmartTable.tsx +262 -256
  48. package/src/components/smart-table/CSmartTableBody.tsx +31 -41
  49. package/src/components/smart-table/CSmartTableCleaner.tsx +1 -1
  50. package/src/components/smart-table/CSmartTableFilter.tsx +1 -3
  51. package/src/components/smart-table/CSmartTableHead.tsx +53 -103
  52. package/src/components/smart-table/CSmartTableInterface.tsx +41 -71
  53. package/src/components/smart-table/CSmartTableItemsPerPageSelector.tsx +1 -2
  54. package/src/components/smart-table/types.tsx +65 -0
  55. package/src/components/smart-table/utils.tsx +199 -0
  56. package/src/components/tabs/CTabPane.tsx +1 -1
  57. package/src/components/time-picker/CTimePicker.tsx +50 -23
  58. package/src/components/time-picker/CTimePickerRollCol.tsx +1 -1
  59. package/src/components/time-picker/types.ts +15 -0
  60. package/src/{utils/time.ts → components/time-picker/utils.ts} +43 -2
  61. package/src/components/toast/CToast.tsx +1 -1
  62. package/src/components/virtual-scroller/CVirtualScroller.tsx +1 -1
  63. package/src/{utils/hooks → hooks}/index.ts +0 -0
  64. package/src/{utils/hooks → hooks}/useForkedRef.ts +0 -0
  65. package/src/{utils/hooks → hooks}/useStateWithCallback.ts +0 -0
  66. package/src/utils/index.ts +2 -1
  67. package/src/utils/isObjectInArray.ts +14 -0
@@ -0,0 +1,199 @@
1
+ import type {
2
+ Column,
3
+ ColumnFilter,
4
+ ColumnFilterValue,
5
+ Item,
6
+ Sorter,
7
+ SorterValue,
8
+ TableFilter,
9
+ } from './types'
10
+
11
+ export const filterColumns = (
12
+ items: Item[],
13
+ columnFilter: boolean | ColumnFilter | undefined,
14
+ columnFilterState: ColumnFilterValue,
15
+ itemsDataColumns: string[],
16
+ ) => {
17
+ if (columnFilter && typeof columnFilter === 'object' && columnFilter.external) {
18
+ return items
19
+ }
20
+
21
+ Object.entries(columnFilterState).forEach(([key, value]) => {
22
+ if (value instanceof Function) {
23
+ items = items.filter((item) => value(item[key]))
24
+ return
25
+ }
26
+
27
+ const columnFilter = String(value).toLowerCase()
28
+ if (columnFilter && itemsDataColumns.includes(key)) {
29
+ items = items.filter((item) => {
30
+ return String(item[key]).toLowerCase().includes(columnFilter)
31
+ })
32
+ }
33
+ })
34
+
35
+ return items
36
+ }
37
+
38
+ export const filterTable = (
39
+ items: Item[],
40
+ tableFilter: boolean | TableFilter | undefined,
41
+ tableFilterState: string,
42
+ itemsDataColumns: string[],
43
+ ) => {
44
+ if (
45
+ !tableFilterState ||
46
+ (tableFilter && typeof tableFilter === 'object' && tableFilter.external)
47
+ ) {
48
+ return items
49
+ }
50
+
51
+ const filter = tableFilterState.toLowerCase()
52
+ const valueContainFilter = (val: any) => String(val).toLowerCase().includes(filter)
53
+ items = items.filter((item) => {
54
+ return !!itemsDataColumns.find((key) => valueContainFilter(item[key]))
55
+ })
56
+
57
+ return items
58
+ }
59
+
60
+ export const getClickedColumnName = (
61
+ target: HTMLTextAreaElement,
62
+ columnNames: string[],
63
+ ): string => {
64
+ const closest = target.closest('tr')
65
+ const children = closest ? Array.from(closest.children) : []
66
+ const clickedCell = children.filter((child) => child.contains(target))[0]
67
+ return columnNames[children.indexOf(clickedCell)]
68
+ }
69
+
70
+ export const getColumnKey = (column: Column | string) =>
71
+ typeof column === 'object' ? column.key : column
72
+
73
+ export const getColumnLabel = (column: Column | string) =>
74
+ typeof column === 'object'
75
+ ? column.label !== undefined
76
+ ? column.label
77
+ : pretifyName(column.key)
78
+ : pretifyName(column)
79
+
80
+ export const getColumnNames = (columns: (string | Column)[] | undefined, items: Item[]) =>
81
+ columns
82
+ ? columns.map((column: Column) => {
83
+ if (typeof column === 'object') return column.key
84
+ else return column
85
+ })
86
+ : getColumnNamesFromItems(items)
87
+
88
+ export const getColumnNamesFromItems = (items: Item[]) =>
89
+ Object.keys(items[0] || {}).filter((el) => el.charAt(0) !== '_')
90
+
91
+ export const getColumnSorterState = (
92
+ key: string,
93
+ sorterState: SorterValue | undefined,
94
+ ): string | number => {
95
+ if (sorterState && sorterState.column === key) {
96
+ if (sorterState.state) {
97
+ return sorterState.state
98
+ }
99
+ return 0
100
+ }
101
+
102
+ return 0
103
+ }
104
+
105
+ export const getColumnValues = (items: Item[], key: string) => {
106
+ return items.map((item) => item[key])
107
+ }
108
+
109
+ export const getTableDataCellProps = (item: Item, colName: string) => {
110
+ const props = item._cellProps && {
111
+ ...(item._cellProps['all'] && { ...item._cellProps['all'] }),
112
+ ...(item._cellProps[colName] && { ...item._cellProps[colName] }),
113
+ }
114
+
115
+ return props
116
+ }
117
+
118
+ export const getTableHeaderCellProps = (column: Column | string) => {
119
+ if (typeof column === 'object' && column._props) {
120
+ return column._props
121
+ }
122
+
123
+ return {}
124
+ }
125
+
126
+ export const getTableHeaderCellStyles = (
127
+ column: Column | string,
128
+ columnSorter: boolean | Sorter | undefined,
129
+ ) => {
130
+ const style = {}
131
+
132
+ if (
133
+ columnSorter &&
134
+ (typeof column !== 'object' ||
135
+ (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter)))
136
+ ) {
137
+ style['cursor'] = 'pointer'
138
+ }
139
+
140
+ if (typeof column === 'object' && column._style) {
141
+ return { ...style, ...column._style }
142
+ }
143
+ return style
144
+ }
145
+
146
+ export const isSortable = (
147
+ i: number,
148
+ columns: (string | Column)[] | undefined,
149
+ columnSorter: Sorter | boolean | undefined,
150
+ itemsDataColumns: string[],
151
+ columnNames: string[],
152
+ ): boolean | undefined => {
153
+ const isDataColumn = itemsDataColumns.includes(columnNames[i])
154
+ let column
155
+ if (columns) column = columns[i]
156
+ return (
157
+ columnSorter &&
158
+ (!columns ||
159
+ typeof column !== 'object' ||
160
+ (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter))) &&
161
+ isDataColumn
162
+ )
163
+ }
164
+
165
+ export const pretifyName = (name: string) => {
166
+ return name
167
+ .replace(/[-_.]/g, ' ')
168
+ .replace(/ +/g, ' ')
169
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
170
+ .split(' ')
171
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
172
+ .join(' ')
173
+ }
174
+
175
+ export const sortItems = (
176
+ columnSorter: boolean | Sorter | undefined,
177
+ items: Item[],
178
+ itemsDataColumns: string[],
179
+ sorterState: SorterValue,
180
+ ) => {
181
+ const column = sorterState.column
182
+ if (
183
+ !column ||
184
+ !itemsDataColumns.includes(column) ||
185
+ (columnSorter && typeof columnSorter === 'object' && columnSorter.external)
186
+ ) {
187
+ return items
188
+ }
189
+
190
+ const flip = sorterState.state === 'asc' ? 1 : sorterState.state === 'desc' ? -1 : 0
191
+ const sorted = items.slice().sort((item, item2) => {
192
+ const value = item[column]
193
+ const value2 = item2[column]
194
+ const a = typeof value === 'number' ? value : String(value).toLowerCase()
195
+ const b = typeof value2 === 'number' ? value2 : String(value2).toLowerCase()
196
+ return a > b ? 1 * flip : b > a ? -1 * flip : 0
197
+ })
198
+ return sorted
199
+ }
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
  import { Transition } from 'react-transition-group'
5
5
 
6
- import { useForkedRef } from '../../utils/hooks'
6
+ import { useForkedRef } from '../../hooks'
7
7
  export interface CTabPaneProps extends HTMLAttributes<HTMLDivElement> {
8
8
  /**
9
9
  * A string of all className you want applied to the base component.
@@ -4,22 +4,21 @@ import classNames from 'classnames'
4
4
 
5
5
  import { CFormInput, CFormSelect, CInputGroup, CInputGroupText } from '../form'
6
6
  import { CFormControlWrapper, CFormControlWrapperProps } from '../form/CFormControlWrapper'
7
+ import { CPicker, CPickerProps } from './../picker/CPicker'
7
8
 
8
9
  import { CTimePickerRollCol } from './CTimePickerRollCol'
9
- import { CPicker, CPickerProps } from './../picker/CPicker'
10
10
  import {
11
11
  convert12hTo24h,
12
12
  convertTimeToDate,
13
13
  getAmPm,
14
- getListOfHours,
15
- getListOfMinutes,
16
- getListOfSeconds,
14
+ getLocalizedTimePartials,
17
15
  getSelectedHour,
18
16
  getSelectedMinutes,
19
17
  getSelectedSeconds,
20
- isAmPm,
21
18
  isValidTime,
22
- } from '../../utils/time'
19
+ } from './utils'
20
+
21
+ import type { LocalizedTimePartials } from './types'
23
22
 
24
23
  export interface CTimePickerProps
25
24
  extends Omit<CFormControlWrapperProps, 'floatingLabel'>,
@@ -121,6 +120,17 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
121
120
  const [_ampm, setAmPm] = useState<'am' | 'pm'>(date ? getAmPm(new Date(date), locale) : 'am')
122
121
  const [_visible, setVisible] = useState(visible)
123
122
 
123
+ const [localizedTimePartials, setLocalizedTimePartials] = useState<LocalizedTimePartials>({
124
+ listOfHours: [],
125
+ listOfMinutes: [],
126
+ listOfSeconds: [],
127
+ hour12: false,
128
+ })
129
+
130
+ useEffect(() => {
131
+ setLocalizedTimePartials(getLocalizedTimePartials(locale, ampm))
132
+ }, [date])
133
+
124
134
  useEffect(() => {
125
135
  setDate(convertTimeToDate(time))
126
136
  }, [time])
@@ -129,7 +139,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
129
139
  if (inputRef.current) {
130
140
  inputRef.current.value = date
131
141
  ? date.toLocaleTimeString(locale, {
132
- hour12: (ampm === 'auto' && isAmPm(locale)) || (typeof ampm === 'boolean' && ampm),
142
+ hour12: localizedTimePartials && localizedTimePartials.hour12,
133
143
  ...(!seconds && { timeStyle: 'short' }),
134
144
  })
135
145
  : ''
@@ -157,7 +167,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
157
167
  }
158
168
 
159
169
  if (set === 'hours') {
160
- if ((ampm === 'auto' && isAmPm(locale)) || ampm === true) {
170
+ if (localizedTimePartials && localizedTimePartials.hour12) {
161
171
  _date.setHours(convert12hTo24h(_ampm, parseInt(value)))
162
172
  } else {
163
173
  _date.setHours(parseInt(value))
@@ -224,12 +234,15 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
224
234
  <span className="time-picker-inline-icon" />
225
235
  <CFormSelect
226
236
  disabled={disabled}
227
- options={getListOfHours(locale).map((option) => {
228
- return {
229
- value: option.value.toString(),
230
- label: option.label,
231
- }
232
- })}
237
+ options={
238
+ localizedTimePartials &&
239
+ localizedTimePartials.listOfHours?.map((option) => {
240
+ return {
241
+ value: option.value.toString(),
242
+ label: option.label,
243
+ }
244
+ })
245
+ }
233
246
  onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
234
247
  handleTimeChange('hours', event.target.value)
235
248
  }
@@ -238,8 +251,15 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
238
251
  <>:</>
239
252
  <CFormSelect
240
253
  disabled={disabled}
241
- // @ts-expect-error the getListOfMinutes function returns corect type
242
- options={getListOfMinutes(locale, true)}
254
+ options={
255
+ localizedTimePartials &&
256
+ localizedTimePartials.listOfMinutes.map((option) => {
257
+ return {
258
+ value: option.value.toString(),
259
+ label: option.label,
260
+ }
261
+ })
262
+ }
243
263
  onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
244
264
  handleTimeChange('minutes', event.target.value)
245
265
  }
@@ -250,8 +270,15 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
250
270
  <>:</>
251
271
  <CFormSelect
252
272
  disabled={disabled}
253
- // @ts-expect-error the getListOfSeconds function returns corect type
254
- options={getListOfSeconds(locale, true)}
273
+ options={
274
+ localizedTimePartials &&
275
+ localizedTimePartials.listOfSeconds.map((option) => {
276
+ return {
277
+ value: option.value.toString(),
278
+ label: option.label,
279
+ }
280
+ })
281
+ }
255
282
  onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
256
283
  handleTimeChange('seconds', event.target.value)
257
284
  }
@@ -259,7 +286,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
259
286
  />
260
287
  </>
261
288
  )}
262
- {isAmPm(locale) && (
289
+ {localizedTimePartials && localizedTimePartials.hour12 && (
263
290
  <CFormSelect
264
291
  disabled={disabled}
265
292
  options={[
@@ -279,23 +306,23 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
279
306
  const TimePickerRoll = () => (
280
307
  <>
281
308
  <CTimePickerRollCol
282
- elements={getListOfHours(locale, ampm)}
309
+ elements={localizedTimePartials && localizedTimePartials.listOfHours}
283
310
  onClick={(index: number) => handleTimeChange('hours', index.toString())}
284
311
  selected={getSelectedHour(date, locale, ampm)}
285
312
  />
286
313
  <CTimePickerRollCol
287
- elements={getListOfMinutes(locale)}
314
+ elements={localizedTimePartials && localizedTimePartials.listOfMinutes}
288
315
  onClick={(index: number) => handleTimeChange('minutes', index.toString())}
289
316
  selected={getSelectedMinutes(date)}
290
317
  />
291
318
  {seconds && (
292
319
  <CTimePickerRollCol
293
- elements={getListOfSeconds(locale)}
320
+ elements={localizedTimePartials && localizedTimePartials.listOfSeconds}
294
321
  onClick={(index: number) => handleTimeChange('seconds', index.toString())}
295
322
  selected={getSelectedSeconds(date)}
296
323
  />
297
324
  )}
298
- {((ampm === 'auto' && isAmPm(locale)) || ampm === true) && (
325
+ {localizedTimePartials && localizedTimePartials.hour12 && (
299
326
  <CTimePickerRollCol
300
327
  elements={[
301
328
  { value: 'am', label: 'AM' },
@@ -2,7 +2,7 @@ import React, { forwardRef, useEffect, useRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
- import { useForkedRef } from '../../utils/hooks'
5
+ import { useForkedRef } from '../../hooks'
6
6
 
7
7
  export interface Element {
8
8
  value: number | string
@@ -0,0 +1,15 @@
1
+ export type LocalizedTimePartials = {
2
+ listOfHours: {
3
+ value: number
4
+ label: string
5
+ }[]
6
+ listOfMinutes: {
7
+ value: number
8
+ label: string
9
+ }[]
10
+ listOfSeconds: {
11
+ value: number
12
+ label: string
13
+ }[]
14
+ hour12: boolean
15
+ }
@@ -1,3 +1,5 @@
1
+ import type { LocalizedTimePartials } from './types'
2
+
1
3
  export const convert12hTo24h = (abbr: 'am' | 'pm', hour: number) => {
2
4
  if (abbr === 'am' && hour === 12) {
3
5
  return 0
@@ -26,6 +28,7 @@ export const getAmPm = (date: Date, locale: string) => {
26
28
  return date.getHours() >= 12 ? 'pm' : 'am'
27
29
  }
28
30
 
31
+ // TODO: clean-up
29
32
  export const getListOfHours = (locale: string, ampm: 'auto' | boolean = 'auto') =>
30
33
  Array.from({ length: (ampm === 'auto' && isAmPm(locale)) || ampm === true ? 12 : 24 }, (_, i) => {
31
34
  return {
@@ -36,6 +39,7 @@ export const getListOfHours = (locale: string, ampm: 'auto' | boolean = 'auto')
36
39
  }
37
40
  })
38
41
 
42
+ // TODO: clean-up
39
43
  export const getListOfMinutes = (locale: string, valueAsString = false) =>
40
44
  Array.from({ length: 60 }, (_, i) => {
41
45
  const d = new Date()
@@ -47,10 +51,11 @@ export const getListOfMinutes = (locale: string, valueAsString = false) =>
47
51
  minute: '2-digit',
48
52
  second: '2-digit',
49
53
  })
50
- .split(/[^A-Za-z0-9]/)[0],
54
+ .split(/[^A-Za-z0-9\u06F0-\u06F90-9]/)[0],
51
55
  }
52
56
  })
53
57
 
58
+ // TODO: clean-up
54
59
  export const getListOfSeconds = (locale: string, valueAsString = false) =>
55
60
  Array.from({ length: 60 }, (_, i) => {
56
61
  const d = new Date()
@@ -62,10 +67,46 @@ export const getListOfSeconds = (locale: string, valueAsString = false) =>
62
67
  minute: '2-digit',
63
68
  second: '2-digit',
64
69
  })
65
- .split(/[^A-Za-z0-9]/)[1],
70
+ .split(/[^A-Za-z0-9\u06F0-\u06F90-9]/)[0],
71
+ }
72
+ })
73
+
74
+ export const getLocalizedTimePartials = (
75
+ locale: string,
76
+ ampm: 'auto' | boolean = 'auto',
77
+ ): LocalizedTimePartials => {
78
+ const date = new Date()
79
+ const hour12 = ['am', 'AM', 'pm', 'PM'].some((el) => date.toLocaleString(locale).includes(el))
80
+ const listOfHours = Array.from(
81
+ { length: (ampm === 'auto' && hour12) || ampm === true ? 12 : 24 },
82
+ (_, i) => {
83
+ return {
84
+ value: (ampm === 'auto' && hour12) || ampm === true ? i + 1 : i,
85
+ label: ((ampm === 'auto' && hour12) || ampm === true ? i + 1 : i).toLocaleString(locale),
86
+ }
87
+ },
88
+ )
89
+ const listOfMinutesSeconds = Array.from({ length: 60 }, (_, i) => {
90
+ date.setMinutes(i)
91
+ return {
92
+ value: i,
93
+ label: date
94
+ .toLocaleTimeString(locale, {
95
+ minute: '2-digit',
96
+ second: '2-digit',
97
+ })
98
+ .split(/[^A-Za-z0-9\u06F0-\u06F90-9]/)[0],
66
99
  }
67
100
  })
68
101
 
102
+ return {
103
+ listOfHours,
104
+ listOfMinutes: listOfMinutesSeconds,
105
+ listOfSeconds: listOfMinutesSeconds,
106
+ hour12,
107
+ }
108
+ }
109
+
69
110
  export const getSelectedHour = (
70
111
  date: Date | null,
71
112
  locale: string,
@@ -12,7 +12,7 @@ import classNames from 'classnames'
12
12
 
13
13
  import { Colors, colorPropType } from '../Types'
14
14
 
15
- import { useForkedRef } from '../../utils/hooks'
15
+ import { useForkedRef } from '../../hooks'
16
16
 
17
17
  export interface CToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
18
18
  /**
@@ -2,7 +2,7 @@ import React, { forwardRef, HTMLAttributes, UIEvent, useEffect, useRef, useState
2
2
  import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
 
5
- import { useForkedRef } from '../../utils/hooks'
5
+ import { useForkedRef } from '../../hooks'
6
6
 
7
7
  export interface CVirtualScrollerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onScroll'> {
8
8
  /**
File without changes
File without changes
@@ -1,5 +1,6 @@
1
1
  import getNextSibling from './getNextSibling'
2
2
  import getPreviousSibling from './getPreviousSibling'
3
3
  import isInViewport from './isInViewport'
4
+ import isObjectInArray from './isObjectInArray'
4
5
 
5
- export { getNextSibling, getPreviousSibling, isInViewport }
6
+ export { getNextSibling, getPreviousSibling, isInViewport, isObjectInArray }
@@ -0,0 +1,14 @@
1
+ const isObjectInArray = <T>(array: T[], item: T, ignore: string[] = []) =>
2
+ array.some((_item: T) => {
3
+ let result = true
4
+ for (const key in item) {
5
+ if (!ignore.includes(key) && item[key] !== _item[key]) {
6
+ result = false
7
+ break
8
+ }
9
+ }
10
+
11
+ return result
12
+ })
13
+
14
+ export default isObjectInArray