@coreui/vue-pro 4.7.0 → 4.8.0-next.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 (55) hide show
  1. package/dist/components/calendar/utils.d.ts +23 -0
  2. package/dist/components/index.d.ts +1 -0
  3. package/dist/components/modal/CModal.d.ts +4 -20
  4. package/dist/components/multi-select/CMultiSelect.d.ts +35 -44
  5. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +1 -1
  6. package/dist/components/multi-select/CMultiSelectOptions.d.ts +13 -11
  7. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -1
  8. package/dist/components/multi-select/types.d.ts +14 -0
  9. package/dist/components/multi-select/utils.d.ts +6 -0
  10. package/dist/components/offcanvas/COffcanvas.d.ts +35 -18
  11. package/dist/components/smart-table/CSmartTable.d.ts +65 -87
  12. package/dist/components/smart-table/CSmartTableBody.d.ts +16 -40
  13. package/dist/components/smart-table/CSmartTableHead.d.ts +17 -58
  14. package/dist/components/smart-table/CSmartTableInterface.d.ts +1 -1
  15. package/dist/components/smart-table/types.d.ts +50 -0
  16. package/dist/components/smart-table/utils.d.ts +17 -0
  17. package/dist/components/table/CTable.d.ts +1 -1
  18. package/dist/components/time-picker/types.d.ts +15 -0
  19. package/dist/components/time-picker/utils.d.ts +23 -0
  20. package/dist/components/virtual-scroller/CVirtualScroller.d.ts +23 -0
  21. package/dist/components/virtual-scroller/index.d.ts +6 -0
  22. package/dist/index.es.js +943 -885
  23. package/dist/index.es.js.map +1 -1
  24. package/dist/index.js +943 -883
  25. package/dist/index.js.map +1 -1
  26. package/dist/utils/index.d.ts +1 -3
  27. package/dist/utils/isObjectInArray.d.ts +2 -0
  28. package/package.json +6 -6
  29. package/src/components/calendar/CCalendar.ts +1 -1
  30. package/src/{utils/calendar.ts → components/calendar/utils.ts} +1 -1
  31. package/src/components/date-range-picker/CDateRangePicker.ts +1 -1
  32. package/src/components/element-cover/CElementCover.ts +14 -14
  33. package/src/components/index.ts +1 -0
  34. package/src/components/modal/CModal.ts +10 -10
  35. package/src/components/multi-select/CMultiSelect.ts +33 -99
  36. package/src/components/multi-select/CMultiSelectNativeSelect.ts +2 -1
  37. package/src/components/multi-select/CMultiSelectOptions.ts +31 -17
  38. package/src/components/multi-select/CMultiSelectSelection.ts +2 -1
  39. package/src/components/multi-select/types.ts +15 -0
  40. package/src/components/multi-select/utils.ts +92 -0
  41. package/src/components/offcanvas/COffcanvas.ts +50 -28
  42. package/src/components/smart-table/CSmartTable.ts +365 -268
  43. package/src/components/smart-table/CSmartTableBody.ts +126 -137
  44. package/src/components/smart-table/CSmartTableHead.ts +53 -138
  45. package/src/components/smart-table/CSmartTableInterface.ts +1 -1
  46. package/src/components/smart-table/types.ts +61 -0
  47. package/src/components/smart-table/utils.ts +212 -0
  48. package/src/components/time-picker/CTimePicker.ts +49 -27
  49. package/src/components/time-picker/types.ts +15 -0
  50. package/src/{utils/time.ts → components/time-picker/utils.ts} +43 -2
  51. package/src/components/virtual-scroller/CVirtualScroller.ts +109 -0
  52. package/src/components/virtual-scroller/index.ts +10 -0
  53. package/src/utils/index.ts +1 -3
  54. package/src/utils/getNextSibling.ts +0 -18
  55. package/src/utils/getPreviousSibling.ts +0 -18
@@ -0,0 +1,212 @@
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 | string) => {
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 isObjectInArray = <T>(array: T[], item: T, ignore: string[] = []) =>
147
+ array.some((_item: T) => {
148
+ let result = true
149
+ for (const key in item) {
150
+ if (!ignore.includes(key) && item[key] !== _item[key]) {
151
+ result = false
152
+ break
153
+ }
154
+ }
155
+
156
+ return result
157
+ })
158
+
159
+ export const isSortable = (
160
+ i: number,
161
+ columns: (string | Column)[] | undefined,
162
+ columnSorter: Sorter | boolean | undefined,
163
+ itemsDataColumns: string[],
164
+ columnNames: string[],
165
+ ): boolean | undefined => {
166
+ const isDataColumn = itemsDataColumns.includes(columnNames[i])
167
+ let column
168
+ if (columns) column = columns[i]
169
+ return (
170
+ columnSorter &&
171
+ (!columns ||
172
+ typeof column !== 'object' ||
173
+ (typeof column === 'object' && (typeof column.sorter === 'undefined' || column.sorter))) &&
174
+ isDataColumn
175
+ )
176
+ }
177
+
178
+ export const pretifyName = (name: string) => {
179
+ return name
180
+ .replace(/[-_.]/g, ' ')
181
+ .replace(/ +/g, ' ')
182
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
183
+ .split(' ')
184
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
185
+ .join(' ')
186
+ }
187
+
188
+ export const sortItems = (
189
+ columnSorter: boolean | Sorter | undefined,
190
+ items: Item[],
191
+ itemsDataColumns: string[],
192
+ sorterState: SorterValue,
193
+ ) => {
194
+ const column = sorterState.column
195
+ if (
196
+ !column ||
197
+ !itemsDataColumns.includes(column) ||
198
+ (columnSorter && typeof columnSorter === 'object' && columnSorter.external)
199
+ ) {
200
+ return items
201
+ }
202
+
203
+ const flip = sorterState.state === 'asc' ? 1 : sorterState.state === 'desc' ? -1 : 0
204
+ const sorted = items.slice().sort((item, item2) => {
205
+ const value = item[column]
206
+ const value2 = item2[column]
207
+ const a = typeof value === 'number' ? value : String(value).toLowerCase()
208
+ const b = typeof value2 === 'number' ? value2 : String(value2).toLowerCase()
209
+ return a > b ? 1 * flip : b > a ? -1 * flip : 0
210
+ })
211
+ return sorted
212
+ }
@@ -1,25 +1,24 @@
1
1
  import { defineComponent, h, ref, watch } from 'vue'
2
2
 
3
3
  import { CFormInput, CFormSelect, CInputGroup, CInputGroupText } from '../form/'
4
- import { CFormControlWrapper } from './../form/CFormControlWrapper'
4
+ import { CFormControlWrapper } from '../form/CFormControlWrapper'
5
5
  import { CPicker } from '../picker'
6
+
6
7
  import { CTimePickerRollCol } from './CTimePickerRollCol'
7
8
 
8
9
  import {
9
10
  convert12hTo24h,
10
11
  convertTimeToDate,
11
12
  getAmPm,
12
- getListOfHours,
13
- getListOfMinutes,
14
- getListOfSeconds,
13
+ getLocalizedTimePartials,
15
14
  getSelectedHour,
16
15
  getSelectedMinutes,
17
16
  getSelectedSeconds,
18
- isAmPm,
19
17
  isValidTime,
20
- } from '../../utils/time'
18
+ } from './utils'
21
19
 
22
20
  import { Color } from '../props'
21
+ import type { LocalizedTimePartials } from './types'
23
22
 
24
23
  const CTimePicker = defineComponent({
25
24
  name: 'CTimePicker',
@@ -281,10 +280,16 @@ const CTimePicker = defineComponent({
281
280
  'update:time',
282
281
  ],
283
282
  setup(props, { emit, attrs, slots }) {
284
- const visible = ref(props.visible)
285
283
  const date = ref<Date | null>(convertTimeToDate(props.time))
286
- const initialDate = ref<Date | null>(null)
287
284
  const ampm = ref<'am' | 'pm'>(date.value ? getAmPm(new Date(date.value), props.locale) : 'am')
285
+ const initialDate = ref<Date | null>(null)
286
+ const visible = ref(props.visible)
287
+ const localizedTimePartials = ref<LocalizedTimePartials>({
288
+ listOfHours: [],
289
+ listOfMinutes: [],
290
+ listOfSeconds: [],
291
+ hour12: false,
292
+ })
288
293
 
289
294
  watch(
290
295
  () => props.time,
@@ -294,6 +299,8 @@ const CTimePicker = defineComponent({
294
299
  )
295
300
 
296
301
  watch(date, () => {
302
+ localizedTimePartials.value = getLocalizedTimePartials(props.locale, props.ampm)
303
+
297
304
  if (date.value) {
298
305
  ampm.value = getAmPm(new Date(date.value), props.locale)
299
306
  }
@@ -313,13 +320,14 @@ const CTimePicker = defineComponent({
313
320
  if (value === 'am') {
314
321
  _date.setHours(_date.getHours() - 12)
315
322
  }
323
+
316
324
  if (value === 'pm') {
317
325
  _date.setHours(_date.getHours() + 12)
318
326
  }
319
327
  }
320
328
 
321
329
  if (set === 'hours') {
322
- if ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm === true) {
330
+ if (localizedTimePartials.value && localizedTimePartials.value.hour12) {
323
331
  _date.setHours(convert12hTo24h(ampm.value, parseInt(value)))
324
332
  } else {
325
333
  _date.setHours(parseInt(value))
@@ -353,9 +361,7 @@ const CTimePicker = defineComponent({
353
361
  readonly: props.inputReadOnly,
354
362
  value: date.value
355
363
  ? date.value.toLocaleTimeString(props.locale, {
356
- hour12:
357
- (props.ampm === 'auto' && isAmPm(props.locale)) ||
358
- (props.ampm === 'boolean' && props.ampm),
364
+ hour12: localizedTimePartials.value && localizedTimePartials.value.hour12,
359
365
  ...(!props.seconds && { timeStyle: 'short' }),
360
366
  })
361
367
  : '',
@@ -391,35 +397,50 @@ const CTimePicker = defineComponent({
391
397
  h('span', { class: 'time-picker-inline-icon' }),
392
398
  h(CFormSelect, {
393
399
  disabled: props.disabled,
394
- options: getListOfHours(props.locale).map((option) => {
395
- return {
396
- value: option.value.toString(),
397
- label: option.label,
398
- }
399
- }),
400
+ options:
401
+ localizedTimePartials.value &&
402
+ localizedTimePartials.value.listOfHours?.map((option) => {
403
+ return {
404
+ value: option.value.toString(),
405
+ label: option.label,
406
+ }
407
+ }),
400
408
  onChange: (event) => handleTimeChange('hours', event.target.value),
401
409
  ...(date.value && { value: getSelectedHour(date.value, props.locale) }),
402
410
  }),
403
411
  ':',
404
- // @ts-expect-error the getListOfMinutes function returns corect type
405
412
  h(CFormSelect, {
406
413
  disabled: props.disabled,
407
- options: getListOfMinutes(props.locale, true),
414
+ options:
415
+ localizedTimePartials.value &&
416
+ localizedTimePartials.value.listOfMinutes.map((option) => {
417
+ return {
418
+ value: option.value.toString(),
419
+ label: option.label,
420
+ }
421
+ }),
408
422
  onChange: (event: Event) =>
409
423
  handleTimeChange('minutes', (event.target as HTMLSelectElement).value),
410
424
  ...(date.value && { value: getSelectedMinutes(date.value) }),
411
425
  }),
412
426
  props.seconds && ':',
413
427
  props.seconds &&
414
- // @ts-expect-error the getListOfMinutes function returns corect type
415
428
  h(CFormSelect, {
416
429
  disabled: props.disabled,
417
- options: getListOfSeconds(props.locale, true),
430
+ options:
431
+ localizedTimePartials.value &&
432
+ localizedTimePartials.value.listOfSeconds.map((option) => {
433
+ return {
434
+ value: option.value.toString(),
435
+ label: option.label,
436
+ }
437
+ }),
418
438
  onChange: (event: Event) =>
419
439
  handleTimeChange('seconds', (event.target as HTMLSelectElement).value),
420
440
  ...(date.value && { value: getSelectedSeconds(date.value) }),
421
441
  }),
422
- isAmPm(props.locale) &&
442
+ localizedTimePartials.value &&
443
+ localizedTimePartials.value.hour12 &&
423
444
  h(CFormSelect, {
424
445
  disabled: props.disabled,
425
446
  options: [
@@ -433,22 +454,23 @@ const CTimePicker = defineComponent({
433
454
 
434
455
  const TimePickerRoll = () => [
435
456
  h(CTimePickerRollCol, {
436
- elements: getListOfHours(props.locale, props.ampm),
457
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfHours,
437
458
  onClick: (index: number) => handleTimeChange('hours', index.toString()),
438
459
  selected: getSelectedHour(date.value, props.locale, props.ampm),
439
460
  }),
440
461
  h(CTimePickerRollCol, {
441
- elements: getListOfMinutes(props.locale),
462
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfMinutes,
442
463
  onClick: (index: number) => handleTimeChange('minutes', index.toString()),
443
464
  selected: getSelectedMinutes(date.value),
444
465
  }),
445
466
  props.seconds &&
446
467
  h(CTimePickerRollCol, {
447
- elements: getListOfSeconds(props.locale),
468
+ elements: localizedTimePartials.value && localizedTimePartials.value.listOfSeconds,
448
469
  onClick: (index: number) => handleTimeChange('seconds', index.toString()),
449
470
  selected: getSelectedSeconds(date.value),
450
471
  }),
451
- ((props.ampm === 'auto' && isAmPm(props.locale)) || props.ampm === true) &&
472
+ localizedTimePartials.value &&
473
+ localizedTimePartials.value.hour12 &&
452
474
  h(CTimePickerRollCol, {
453
475
  elements: [
454
476
  { value: 'am', label: 'AM' },
@@ -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,
@@ -0,0 +1,109 @@
1
+ import { cloneVNode, computed, defineComponent, h, onMounted, ref, VNode } from 'vue'
2
+
3
+ const CVirtualScroller = defineComponent({
4
+ name: 'CVirtualScroller',
5
+ props: {
6
+ /**
7
+ * Amount of visible items
8
+ */
9
+ visibleItems: {
10
+ type: Number,
11
+ default: 10,
12
+ },
13
+ },
14
+ setup(props, { slots }) {
15
+ const virtualScrollRef = ref<HTMLDivElement>()
16
+ const virtualScrollContentRef = ref<HTMLDivElement>()
17
+
18
+ const currentItemIndex = ref(1)
19
+ const itemHeight = ref<number>(0)
20
+ const itemsNumber = ref<number>(0)
21
+ const viewportPadding = ref(0)
22
+
23
+ const buffer = computed(() => Math.floor(props.visibleItems / 2))
24
+
25
+ const maxHeight = computed(
26
+ () => itemsNumber.value * itemHeight.value + 2 * viewportPadding.value,
27
+ )
28
+
29
+ const viewportHeight = computed(
30
+ () => props.visibleItems * itemHeight.value + 2 * viewportPadding.value,
31
+ )
32
+
33
+ onMounted(() => {
34
+ if (virtualScrollRef.value) {
35
+ viewportPadding.value = parseFloat(getComputedStyle(virtualScrollRef.value).paddingTop)
36
+ // It's necessary to calculate heights of items
37
+ virtualScrollRef.value.dispatchEvent(new CustomEvent('scroll'))
38
+ }
39
+ })
40
+
41
+ const handleScroll = (scrollTop: number) => {
42
+ currentItemIndex.value =
43
+ itemHeight.value && Math.max(Math.ceil(scrollTop / itemHeight.value), 1)
44
+ }
45
+
46
+ return () => {
47
+ const children: any = slots.default
48
+ ? Array.isArray(slots.default()[0].children)
49
+ ? slots.default()[0].children
50
+ : slots.default()
51
+ : []
52
+ itemsNumber.value = children && children.length ? children.length : 0
53
+ return h(
54
+ 'div',
55
+ {
56
+ class: ['virtual-scroller'],
57
+ onScroll: (event: any) => handleScroll((event.target as HTMLDivElement).scrollTop),
58
+ style: {
59
+ height: `${
60
+ maxHeight.value > viewportHeight.value ? viewportHeight.value : maxHeight.value
61
+ }px`,
62
+ overflowY: 'auto',
63
+ },
64
+ ref: virtualScrollRef,
65
+ },
66
+ h(
67
+ 'div',
68
+ {
69
+ class: 'virtual-scroller-content',
70
+ style: {
71
+ height: `${maxHeight.value}px`,
72
+ },
73
+ ref: virtualScrollContentRef,
74
+ },
75
+ children.map(
76
+ (slot: VNode, index: number) =>
77
+ index + 1 > Math.max(currentItemIndex.value - buffer.value, 0) &&
78
+ index + 1 <= currentItemIndex.value + props.visibleItems + buffer.value &&
79
+ cloneVNode(slot, {
80
+ class: [
81
+ {
82
+ 'virtual-scroller-item-preload':
83
+ index + 1 > currentItemIndex.value + props.visibleItems ||
84
+ index + 1 < currentItemIndex.value,
85
+ },
86
+ ],
87
+ style: {
88
+ ...(currentItemIndex.value > buffer.value && {
89
+ transform: `translateY(${
90
+ (currentItemIndex.value - buffer.value) * itemHeight.value
91
+ }px)`,
92
+ }),
93
+ },
94
+ ref: (node) => {
95
+ if (node && (node as HTMLElement).offsetHeight) {
96
+ itemHeight.value =
97
+ (node as HTMLElement).offsetHeight +
98
+ parseFloat(getComputedStyle(node as HTMLElement).marginTop) +
99
+ parseFloat(getComputedStyle(node as HTMLElement).marginBottom)
100
+ }
101
+ },
102
+ }),
103
+ ),
104
+ ),
105
+ )
106
+ }
107
+ },
108
+ })
109
+ export { CVirtualScroller }
@@ -0,0 +1,10 @@
1
+ import { App } from 'vue'
2
+ import { CVirtualScroller } from './CVirtualScroller'
3
+
4
+ const CVirtualScrollerPlugin = {
5
+ install: (app: App): void => {
6
+ app.component(CVirtualScroller.name, CVirtualScroller)
7
+ },
8
+ }
9
+
10
+ export { CVirtualScroller, CVirtualScrollerPlugin }
@@ -1,5 +1,3 @@
1
- import getNextSibling from './getNextSibling'
2
- import getPreviousSibling from './getPreviousSibling'
3
1
  import isInViewport from './isInViewport'
4
2
 
5
- export { getNextSibling, getPreviousSibling, isInViewport }
3
+ export { isInViewport }
@@ -1,18 +0,0 @@
1
- const getNextSibling = (elem: HTMLElement, selector?: string) => {
2
- // Get the next sibling element
3
- let sibling = elem.nextElementSibling
4
-
5
- // If there's no selector, return the first sibling
6
- if (!selector) return sibling
7
-
8
- // If the sibling matches our selector, use it
9
- // If not, jump to the next sibling and continue the loop
10
- while (sibling) {
11
- if (sibling.matches(selector)) return sibling
12
- sibling = sibling.nextElementSibling
13
- }
14
-
15
- return
16
- }
17
-
18
- export default getNextSibling
@@ -1,18 +0,0 @@
1
- const getPreviousSibling = (elem: HTMLElement, selector?: string) => {
2
- // Get the next sibling element
3
- let sibling = elem.previousElementSibling
4
-
5
- // If there's no selector, return the first sibling
6
- if (!selector) return sibling
7
-
8
- // If the sibling matches our selector, use it
9
- // If not, jump to the next sibling and continue the loop
10
- while (sibling) {
11
- if (sibling.matches(selector)) return sibling
12
- sibling = sibling.previousElementSibling
13
- }
14
-
15
- return
16
- }
17
-
18
- export default getPreviousSibling