vxe-pc-ui 4.19.7 → 4.20.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 (100) hide show
  1. package/dist/all.esm.js +2206 -1851
  2. package/dist/style.css +1 -1
  3. package/dist/style.min.css +1 -1
  4. package/es/card/src/card.js +35 -12
  5. package/es/card/style.css +42 -44
  6. package/es/card/style.min.css +1 -1
  7. package/es/icon/style.css +1 -1
  8. package/es/list/src/list.js +323 -19
  9. package/es/list/style.css +26 -0
  10. package/es/list/style.min.css +1 -1
  11. package/es/scrollbar/src/scrollbar.js +9 -1
  12. package/es/scrollbar/style.css +6 -5
  13. package/es/scrollbar/style.min.css +1 -1
  14. package/es/style.css +1 -1
  15. package/es/style.min.css +1 -1
  16. package/es/tabs/src/tabs.js +27 -8
  17. package/es/tabs/style.css +4 -2
  18. package/es/tabs/style.min.css +1 -1
  19. package/es/tree/src/tree.js +6 -2
  20. package/es/ui/index.js +1 -1
  21. package/es/ui/src/log.js +1 -1
  22. package/es/ui/src/utils.js +9 -0
  23. package/es/vxe-card/style.css +42 -44
  24. package/es/vxe-card/style.min.css +1 -1
  25. package/es/vxe-list/style.css +26 -0
  26. package/es/vxe-list/style.min.css +1 -1
  27. package/es/vxe-scrollbar/style.css +6 -5
  28. package/es/vxe-scrollbar/style.min.css +1 -1
  29. package/es/vxe-tabs/style.css +4 -2
  30. package/es/vxe-tabs/style.min.css +1 -1
  31. package/lib/card/src/card.js +42 -6
  32. package/lib/card/src/card.min.js +1 -1
  33. package/lib/card/style/style.css +42 -44
  34. package/lib/card/style/style.min.css +1 -1
  35. package/lib/icon/style/style.css +1 -1
  36. package/lib/icon/style/style.min.css +1 -1
  37. package/lib/index.umd.js +2785 -2383
  38. package/lib/index.umd.min.js +1 -1
  39. package/lib/list/src/list.js +333 -20
  40. package/lib/list/src/list.min.js +1 -1
  41. package/lib/list/style/style.css +26 -0
  42. package/lib/list/style/style.min.css +1 -1
  43. package/lib/scrollbar/src/scrollbar.js +9 -1
  44. package/lib/scrollbar/src/scrollbar.min.js +1 -1
  45. package/lib/scrollbar/style/style.css +6 -5
  46. package/lib/scrollbar/style/style.min.css +1 -1
  47. package/lib/style.css +1 -1
  48. package/lib/style.min.css +1 -1
  49. package/lib/tabs/src/tabs.js +40 -8
  50. package/lib/tabs/src/tabs.min.js +1 -1
  51. package/lib/tabs/style/style.css +4 -2
  52. package/lib/tabs/style/style.min.css +1 -1
  53. package/lib/tree/src/tree.js +5 -1
  54. package/lib/tree/src/tree.min.js +1 -1
  55. package/lib/ui/index.js +1 -1
  56. package/lib/ui/index.min.js +1 -1
  57. package/lib/ui/src/log.js +1 -1
  58. package/lib/ui/src/log.min.js +1 -1
  59. package/lib/ui/src/utils.js +10 -0
  60. package/lib/ui/src/utils.min.js +1 -1
  61. package/lib/vxe-card/style/style.css +42 -44
  62. package/lib/vxe-card/style/style.min.css +1 -1
  63. package/lib/vxe-list/style/style.css +26 -0
  64. package/lib/vxe-list/style/style.min.css +1 -1
  65. package/lib/vxe-scrollbar/style/style.css +6 -5
  66. package/lib/vxe-scrollbar/style/style.min.css +1 -1
  67. package/lib/vxe-tabs/style/style.css +4 -2
  68. package/lib/vxe-tabs/style/style.min.css +1 -1
  69. package/package.json +1 -1
  70. package/packages/card/src/card.ts +55 -12
  71. package/packages/list/src/list.ts +351 -19
  72. package/packages/scrollbar/src/scrollbar.ts +10 -1
  73. package/packages/tabs/src/tabs.ts +34 -8
  74. package/packages/tree/src/tree.ts +6 -2
  75. package/packages/ui/src/utils.ts +10 -0
  76. package/styles/components/card.scss +44 -58
  77. package/styles/components/list.scss +51 -0
  78. package/styles/components/scrollbar.scss +18 -11
  79. package/styles/components/tabs.scss +2 -1
  80. package/types/components/card.d.ts +11 -0
  81. package/types/components/grid.d.ts +37 -0
  82. package/types/components/layout-aside.d.ts +7 -1
  83. package/types/components/layout-body.d.ts +7 -1
  84. package/types/components/list.d.ts +24 -2
  85. package/types/components/menu.d.ts +6 -0
  86. package/types/components/table-plugins/extend-cell-area.d.ts +1 -1
  87. package/types/components/table.d.ts +25 -2
  88. package/types/components/tabs.d.ts +11 -0
  89. /package/es/icon/{iconfont.1791794447472.ttf → iconfont.1791880413927.ttf} +0 -0
  90. /package/es/icon/{iconfont.1791794447472.woff → iconfont.1791880413927.woff} +0 -0
  91. /package/es/icon/{iconfont.1791794447472.woff2 → iconfont.1791880413927.woff2} +0 -0
  92. /package/es/{iconfont.1791794447472.ttf → iconfont.1791880413927.ttf} +0 -0
  93. /package/es/{iconfont.1791794447472.woff → iconfont.1791880413927.woff} +0 -0
  94. /package/es/{iconfont.1791794447472.woff2 → iconfont.1791880413927.woff2} +0 -0
  95. /package/lib/icon/style/{iconfont.1791794447472.ttf → iconfont.1791880413927.ttf} +0 -0
  96. /package/lib/icon/style/{iconfont.1791794447472.woff → iconfont.1791880413927.woff} +0 -0
  97. /package/lib/icon/style/{iconfont.1791794447472.woff2 → iconfont.1791880413927.woff2} +0 -0
  98. /package/lib/{iconfont.1791794447472.ttf → iconfont.1791880413927.ttf} +0 -0
  99. /package/lib/{iconfont.1791794447472.woff → iconfont.1791880413927.woff} +0 -0
  100. /package/lib/{iconfont.1791794447472.woff2 → iconfont.1791880413927.woff2} +0 -0
@@ -1,10 +1,11 @@
1
1
  import { ref, h, reactive, PropType, computed } from 'vue'
2
2
  import { defineVxeComponent } from '../../ui/src/comp'
3
+ import XEUtils from 'xe-utils'
3
4
  import { getSlotVNs } from '../../ui/src/vn'
4
5
  import { getConfig, createEvent, useSize, renderEmptyElement } from '../../ui'
5
6
  import { toCssUnit } from '../../ui/src/dom'
6
7
  import VxeLoadingComponent from '../../loading'
7
- import XEUtils from 'xe-utils'
8
+ import VxeScrollbarComponent from '../../scrollbar'
8
9
 
9
10
  import type { CardReactData, VxeCardEmits, VxeCardPropTypes, CardPrivateRef, ValueOf, CardMethods, CardPrivateMethods, VxeCardPrivateComputed, VxeCardConstructor, VxeCardPrivateMethods } from '../../../types'
10
11
 
@@ -34,7 +35,12 @@ export default defineVxeComponent({
34
35
  size: {
35
36
  type: String as PropType<VxeCardPropTypes.Size>,
36
37
  default: () => getConfig().card.size || getConfig().size
37
- }
38
+ },
39
+ useScrollbar: {
40
+ type: Boolean as PropType<VxeCardPropTypes.UseScrollbar>,
41
+ default: () => getConfig().card.useScrollbar
42
+ },
43
+ scrollbarConfig: Object as PropType<VxeCardPropTypes.ScrollbarConfig>
38
44
  },
39
45
  emits: [
40
46
  ] as VxeCardEmits,
@@ -66,6 +72,10 @@ export default defineVxeComponent({
66
72
  return stys
67
73
  })
68
74
 
75
+ const computeScrollbarOpts = computed(() => {
76
+ return Object.assign({}, getConfig().card.scrollbarConfig, props.scrollbarConfig)
77
+ })
78
+
69
79
  const computeMaps: VxeCardPrivateComputed = {
70
80
  computeSize
71
81
  }
@@ -94,7 +104,7 @@ export default defineVxeComponent({
94
104
  Object.assign($xeCard, cardMethods, cardPrivateMethods)
95
105
 
96
106
  const renderVN = () => {
97
- const { title, border, shadow, padding, loading, showTitleOverflow } = props
107
+ const { title, border, shadow, padding, loading, showTitleOverflow, useScrollbar } = props
98
108
  const defaultSlot = slots.default
99
109
  const headerSlot = slots.header
100
110
  const titleSlot = slots.title
@@ -104,6 +114,8 @@ export default defineVxeComponent({
104
114
  const rightSlot = slots.right
105
115
  const vSize = computeSize.value
106
116
  const cardStyle = computeCardStyle.value
117
+ const scrollbarOpts = computeScrollbarOpts.value
118
+ const { viewClassName, viewInnerClassName } = scrollbarOpts
107
119
 
108
120
  return h('div', {
109
121
  ref: refElem,
@@ -137,17 +149,48 @@ export default defineVxeComponent({
137
149
  class: 'vxe-card--body'
138
150
  }, [
139
151
  leftSlot
140
- ? h('div', {
141
- class: 'vxe-card--body-left'
142
- }, getSlotVNs(leftSlot({})))
152
+ ? (
153
+ useScrollbar
154
+ ? h(VxeScrollbarComponent, {
155
+ class: 'vxe-card--body-scrollbar-left',
156
+ ...scrollbarOpts,
157
+ viewClassName: 'vxe-card--body-scrollbar-left-view',
158
+ viewInnerClassName: 'vxe-card--body-scrollbar-left-inner'
159
+ }, {
160
+ default: () => getSlotVNs(leftSlot({}))
161
+ })
162
+ : h('div', {
163
+ class: 'vxe-card--body-left'
164
+ }, getSlotVNs(leftSlot({})))
165
+ )
143
166
  : renderEmptyElement($xeCard),
144
- h('div', {
145
- class: 'vxe-card--body-content'
146
- }, defaultSlot ? getSlotVNs(defaultSlot({})) : []),
167
+ useScrollbar
168
+ ? h(VxeScrollbarComponent, {
169
+ class: 'vxe-card--body-scrollbar-content',
170
+ ...scrollbarOpts,
171
+ viewClassName: 'vxe-card--body-scrollbar-content-view' + (viewClassName ? (' ' + viewClassName) : ''),
172
+ viewInnerClassName: 'vxe-card--body-scrollbar-content-inner' + (viewClassName ? (' ' + viewInnerClassName) : '')
173
+ }, {
174
+ default: () => defaultSlot ? getSlotVNs(defaultSlot({})) : []
175
+ })
176
+ : h('div', {
177
+ class: 'vxe-card--body-content'
178
+ }, defaultSlot ? getSlotVNs(defaultSlot({})) : []),
147
179
  rightSlot
148
- ? h('div', {
149
- class: 'vxe-card--body-right'
150
- }, getSlotVNs(rightSlot({})))
180
+ ? (
181
+ useScrollbar
182
+ ? h(VxeScrollbarComponent, {
183
+ class: 'vxe-card--body-scrollbar-right',
184
+ ...scrollbarOpts,
185
+ viewClassName: 'vxe-card--body-scrollbar-right-view',
186
+ viewInnerClassName: 'vxe-card--body-scrollbar-right-inner'
187
+ }, {
188
+ default: () => getSlotVNs(rightSlot({}))
189
+ })
190
+ : h('div', {
191
+ class: 'vxe-card--body-right'
192
+ }, getSlotVNs(rightSlot({})))
193
+ )
151
194
  : renderEmptyElement($xeCard)
152
195
  ]),
153
196
  footerSlot
@@ -1,12 +1,13 @@
1
1
  import { h, PropType, ref, Ref, computed, onBeforeUnmount, watch, reactive, nextTick, onActivated, onMounted, VNode } from 'vue'
2
2
  import { defineVxeComponent } from '../../ui/src/comp'
3
3
  import XEUtils from 'xe-utils'
4
- import { VxeUI, getConfig, getIcon, getI18n, menus, globalEvents, globalResize, createEvent, useSize, renderEmptyElement } from '../../ui'
4
+ import { VxeUI, getConfig, getIcon, getI18n, domUtils, menus, globalEvents, globalResize, useSize, createEvent, renderEmptyElement } from '../../ui'
5
5
  import { getCrossListDragRowInfo } from './store'
6
- import { isScale, removeClass, addClass, getTpImg, toCssUnit } from '../../ui/src/dom'
6
+ import { isScale, removeClass, addClass, getTpImg, toCssUnit, hasClass } from '../../ui/src/dom'
7
7
  import { isEnableConf, getText, enModelValue, deModelValue } from '../../ui/src/utils'
8
8
  import { createComponentLog } from '../../ui/src/log'
9
9
  import { moveRowAnimateToTb, clearRowAnimate } from '../../ui/src/anime'
10
+ import { getThumbOffsetSize, getThumbSize, getScrollFromClick, getScrollFromDrag } from '../../scrollbar/src/util'
10
11
  import { getItemCacheObj } from './util'
11
12
  import VxeLoadingComponent from '../../loading'
12
13
 
@@ -42,6 +43,11 @@ function createReactData (): ListReactData {
42
43
  updateCheckboxFlag: 1,
43
44
  isAllChecked: false,
44
45
  isAllIndeterminate: false,
46
+
47
+ // 滚动条
48
+ yThumbHeight: 0,
49
+ xThumbWidth: 0,
50
+
45
51
  insertRowFlag: 1,
46
52
  removeRowFlag: 1,
47
53
  dragRow: null,
@@ -52,13 +58,20 @@ function createReactData (): ListReactData {
52
58
 
53
59
  function createInternalData (): ListInternalData {
54
60
  return {
55
- resizeObserver: undefined,
56
61
  fullData: [],
57
62
  afterList: [],
58
63
  fullKeyMaps: {},
59
64
  rowMaps: {},
60
- lastScrollLeft: 0,
65
+
66
+ // 滚动条
67
+ // resizeObserver: undefined,
68
+ // isThumbDrag: false,
69
+ thumbDragOffset: 0,
70
+ yThumbTop: 0,
71
+ xThumbLeft: 0,
61
72
  lastScrollTop: 0,
73
+ lastScrollLeft: 0,
74
+
62
75
  scrollYStore: {
63
76
  startIndex: 0,
64
77
  endIndex: 0,
@@ -117,7 +130,12 @@ export default defineVxeComponent({
117
130
  dragConfig: Object as PropType<VxeListPropTypes.DragConfig>,
118
131
  menuConfig: Object as PropType<VxeListPropTypes.MenuConfig>,
119
132
  virtualYConfig: Object as PropType<VxeListPropTypes.VirtualYConfig>,
120
- scrollY: Object as PropType<VxeListPropTypes.ScrollY>
133
+ scrollY: Object as PropType<VxeListPropTypes.ScrollY>,
134
+ useScrollbar: {
135
+ type: Boolean as PropType<VxeListPropTypes.UseScrollbar>,
136
+ default: () => getConfig().list.useScrollbar
137
+ },
138
+ scrollbarConfig: Object as PropType<VxeListPropTypes.ScrollbarConfig>
121
139
  },
122
140
  emits: [
123
141
  'update:checkRowKey',
@@ -158,6 +176,12 @@ export default defineVxeComponent({
158
176
  const refVirtualWrapper = ref() as Ref<HTMLDivElement>
159
177
  const refVirtualBody = ref() as Ref<HTMLDivElement>
160
178
 
179
+ const refViewInnerElem = ref<HTMLDivElement>()
180
+ const refTrackXElem = ref<HTMLDivElement>()
181
+ const refTrackYElem = ref<HTMLDivElement>()
182
+ const refThumbXElem = ref<HTMLDivElement>()
183
+ const refThumbYElem = ref<HTMLDivElement>()
184
+
161
185
  const refDragRowLineElem = ref<HTMLDivElement>()
162
186
  const refDragTipElem = ref<HTMLDivElement>()
163
187
 
@@ -218,11 +242,19 @@ export default defineVxeComponent({
218
242
 
219
243
  const computeWrapperStyles = computed(() => {
220
244
  const rowHeight = computeRowHeight.value
221
- const style: VxeComponentStyleType = {}
245
+ const scrollbarXOpts = computeScrollbarXOpts.value
246
+ const scrollbarYOpts = computeScrollbarYOpts.value
247
+ const stys: VxeComponentStyleType = {}
222
248
  if (rowHeight) {
223
- style['--vxe-ui-list-row-height'] = toCssUnit(rowHeight)
249
+ stys['--vxe-ui-list-row-height'] = toCssUnit(rowHeight)
224
250
  }
225
- return style
251
+ if (scrollbarYOpts.width) {
252
+ stys['--vxe-ui-scrollbar-y-width'] = toCssUnit(scrollbarYOpts.width)
253
+ }
254
+ if (scrollbarXOpts.height) {
255
+ stys['--vxe-ui-scrollbar-x-height'] = toCssUnit(scrollbarXOpts.height)
256
+ }
257
+ return stys
226
258
  })
227
259
 
228
260
  const computeVirtualStyles = computed(() => {
@@ -238,6 +270,53 @@ export default defineVxeComponent({
238
270
  return style
239
271
  })
240
272
 
273
+ const computeScrollbarOpts = computed(() => {
274
+ return Object.assign({}, getConfig().list.scrollbarConfig, props.scrollbarConfig)
275
+ })
276
+
277
+ const computeScrollbarXOpts = computed(() => {
278
+ const scrollbarOpts = computeScrollbarOpts.value
279
+ return Object.assign({}, getConfig().scrollbar.xConfig, scrollbarOpts.xConfig)
280
+ })
281
+
282
+ const computeScrollbarYOpts = computed(() => {
283
+ const scrollbarOpts = computeScrollbarOpts.value
284
+ return Object.assign({}, getConfig().scrollbar.yConfig, scrollbarOpts.yConfig)
285
+ })
286
+
287
+ const computeScrollbarWrapperClss = computed(() => {
288
+ const scrollbarOpts = computeScrollbarOpts.value
289
+ const { padding } = scrollbarOpts
290
+ const { yThumbHeight, xThumbWidth } = reactData
291
+ const scrollbarXOpts = computeScrollbarXOpts.value
292
+ const scrollbarYOpts = computeScrollbarYOpts.value
293
+ const scrollbarXToTop = computeScrollbarXToTop.value
294
+ const scrollbarYToLeft = computeScrollbarYToLeft.value
295
+ return domUtils.buildClass([
296
+ 'vxe-scrollbar is--virtual',
297
+ `ov-x--${scrollbarXOpts.visible || 'visible'}`,
298
+ `ov-y--${scrollbarYOpts.visible || 'visible'}`,
299
+ `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}`,
300
+ `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}`
301
+ ], {
302
+ 'is--padding': padding,
303
+ 'ov-x--auto-hide': scrollbarXOpts.autoHide,
304
+ 'ov-y--auto-hide': scrollbarYOpts.autoHide,
305
+ 'overflow-y': yThumbHeight,
306
+ 'overflow-x': xThumbWidth
307
+ })
308
+ })
309
+
310
+ const computeScrollbarXToTop = computed(() => {
311
+ const scrollbarXOpts = computeScrollbarXOpts.value
312
+ return scrollbarXOpts.position === 'top'
313
+ })
314
+
315
+ const computeScrollbarYToLeft = computed(() => {
316
+ const scrollbarYOpts = computeScrollbarYOpts.value
317
+ return scrollbarYOpts.position === 'left'
318
+ })
319
+
241
320
  const dispatchEvent = (type: ValueOf<VxeListEmits>, params: Record<string, any>, evnt: Event | null) => {
242
321
  emit(type, createEvent(evnt, { $list: $xeList }, params))
243
322
  }
@@ -404,6 +483,7 @@ export default defineVxeComponent({
404
483
  */
405
484
  const refreshScroll = () => {
406
485
  const { lastScrollLeft, lastScrollTop } = internalData
486
+ updateScrollbar()
407
487
  return clearScroll().then(() => {
408
488
  if (lastScrollLeft || lastScrollTop) {
409
489
  internalData.lastScrollLeft = 0
@@ -413,19 +493,29 @@ export default defineVxeComponent({
413
493
  })
414
494
  }
415
495
 
496
+ const updateScrollbar = () => {
497
+ updateThumbSize()
498
+ updateThumbOffset()
499
+ }
500
+
416
501
  /**
417
502
  * 重新计算列表
418
503
  */
419
504
  const recalculate = () => {
420
505
  const el = refElem.value
421
506
  if (el) {
422
- const parentEl = el.parentElement
507
+ let parentEl = el.parentElement
423
508
  let parentHeight = 0
509
+ // 如果是虚拟滚动条
510
+ if (parentEl && hasClass(parentEl, 'vxe-scrollbar--view-inner')) {
511
+ parentEl = parentEl.parentElement
512
+ }
424
513
  if (parentEl) {
425
514
  const parentStyle = getComputedStyle(parentEl)
426
515
  parentHeight = parentEl.clientHeight - Math.ceil(XEUtils.toNumber(parentStyle.paddingLeft) + XEUtils.toNumber(parentStyle.paddingRight))
427
516
  }
428
517
  reactData.parentHeight = parentHeight
518
+ updateScrollbar()
429
519
  updateHeight()
430
520
  if (el.clientWidth && el.clientHeight) {
431
521
  return computeScrollLoad()
@@ -457,6 +547,7 @@ export default defineVxeComponent({
457
547
  const scrollLeft = scrollBodyElem.scrollLeft
458
548
  const isX = scrollLeft !== internalData.lastScrollLeft
459
549
  const isY = scrollTop !== internalData.lastScrollTop
550
+ updateThumbOffset()
460
551
  internalData.lastScrollTop = scrollTop
461
552
  internalData.lastScrollLeft = scrollLeft
462
553
  if (reactData.scrollYLoad) {
@@ -1811,6 +1902,176 @@ export default defineVxeComponent({
1811
1902
  }
1812
1903
  }
1813
1904
 
1905
+ const updateThumbSize = () => {
1906
+ const viewEl = refVirtualWrapper.value
1907
+ if (!viewEl) {
1908
+ return
1909
+ }
1910
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
1911
+ return
1912
+ }
1913
+ const trackXEl = refTrackXElem.value
1914
+ const xThumbWidth = trackXEl ? getThumbSize(viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth) : 0
1915
+ const thumbXElem = refThumbXElem.value
1916
+ if (thumbXElem) {
1917
+ thumbXElem.style.width = xThumbWidth + 'px'
1918
+ }
1919
+ reactData.xThumbWidth = xThumbWidth
1920
+
1921
+ const trackYEl = refTrackYElem.value
1922
+
1923
+ const yThumbHeight = trackYEl ? getThumbSize(viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight) : 0
1924
+ const thumbYElem = refThumbYElem.value
1925
+ if (thumbYElem) {
1926
+ thumbYElem.style.height = yThumbHeight + 'px'
1927
+ }
1928
+ reactData.yThumbHeight = yThumbHeight
1929
+ }
1930
+
1931
+ const updateThumbOffset = () => {
1932
+ const viewEl = refVirtualWrapper.value
1933
+ if (!viewEl) {
1934
+ return
1935
+ }
1936
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
1937
+ return
1938
+ }
1939
+ const { xThumbWidth, yThumbHeight } = reactData
1940
+ const trackXEl = refTrackXElem.value
1941
+ const thumbXElem = refThumbXElem.value
1942
+ const xThumbLeft = trackXEl && xThumbWidth ? getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth, xThumbWidth) : 0
1943
+ internalData.xThumbLeft = xThumbLeft
1944
+ if (thumbXElem && xThumbWidth) {
1945
+ thumbXElem.style.width = xThumbWidth + 'px'
1946
+ thumbXElem.style.transform = `translateX(${xThumbLeft}px)`
1947
+ }
1948
+
1949
+ const trackYEl = refTrackYElem.value
1950
+ const thumbYElem = refThumbYElem.value
1951
+ const yThumbTop = trackYEl && yThumbHeight ? getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight, yThumbHeight) : 0
1952
+ internalData.yThumbTop = yThumbTop
1953
+ if (thumbYElem && yThumbHeight) {
1954
+ thumbYElem.style.height = yThumbHeight + 'px'
1955
+ thumbYElem.style.transform = `translateY(${yThumbTop}px)`
1956
+ }
1957
+ }
1958
+
1959
+ const clickTrackXEvent = (evnt: MouseEvent) => {
1960
+ const trackEl = evnt.currentTarget as HTMLDivElement
1961
+ if (trackEl !== evnt.target) {
1962
+ return
1963
+ }
1964
+ const viewEl = refVirtualWrapper.value
1965
+ if (!viewEl) {
1966
+ return
1967
+ }
1968
+ const { xThumbWidth } = reactData
1969
+ const trackRect = trackEl.getBoundingClientRect()
1970
+ viewEl.scrollTo({
1971
+ left: getScrollFromClick(evnt.clientX - trackRect.left, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth),
1972
+ behavior: 'auto'
1973
+ })
1974
+ }
1975
+
1976
+ const clickTrackYEvent = (evnt: MouseEvent) => {
1977
+ const trackEl = evnt.currentTarget as HTMLDivElement
1978
+ if (trackEl !== evnt.target) {
1979
+ return
1980
+ }
1981
+ const viewEl = refVirtualWrapper.value
1982
+ if (!viewEl) {
1983
+ return
1984
+ }
1985
+ const { yThumbHeight } = reactData
1986
+ const trackRect = trackEl.getBoundingClientRect()
1987
+ viewEl.scrollTo({
1988
+ top: getScrollFromClick(evnt.clientY - trackRect.top, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight),
1989
+ behavior: 'auto'
1990
+ })
1991
+ }
1992
+
1993
+ const pointerdownThumbXEvent = (evnt: PointerEvent) => {
1994
+ const thumbEl = evnt.currentTarget as HTMLDivElement
1995
+ internalData.isThumbDrag = true
1996
+ thumbEl.setPointerCapture(evnt.pointerId)
1997
+
1998
+ const viewEl = refVirtualWrapper.value
1999
+ if (!viewEl) {
2000
+ return
2001
+ }
2002
+ const { xThumbWidth } = reactData
2003
+ const trackEl = thumbEl.parentElement as HTMLDivElement
2004
+ const trackRect = trackEl.getBoundingClientRect()
2005
+ const pointerPosition = evnt.clientX - trackRect.left
2006
+ // 记录 thumb 的偏移
2007
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
2008
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
2009
+ }
2010
+
2011
+ const pointermoveThumbXEvent = (evnt: PointerEvent) => {
2012
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2013
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
2014
+ return
2015
+ }
2016
+ const { isThumbDrag, thumbDragOffset } = internalData
2017
+ if (isThumbDrag) {
2018
+ const viewEl = refVirtualWrapper.value
2019
+ if (!viewEl) {
2020
+ return
2021
+ }
2022
+ const { xThumbWidth } = reactData
2023
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2024
+ const trackEl = thumbEl.parentElement as HTMLDivElement
2025
+ const trackRect = trackEl.getBoundingClientRect()
2026
+ // 更新偏移
2027
+ viewEl.scrollLeft = getScrollFromDrag(evnt.clientX - trackRect.left, thumbDragOffset, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
2028
+ }
2029
+ }
2030
+
2031
+ const cleatPointerThumbEvent = (evnt: PointerEvent) => {
2032
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2033
+ thumbEl.releasePointerCapture(evnt.pointerId)
2034
+ internalData.isThumbDrag = false
2035
+ }
2036
+
2037
+ const pointerdownThumbYEvent = (evnt: PointerEvent) => {
2038
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2039
+ internalData.isThumbDrag = true
2040
+ thumbEl.setPointerCapture(evnt.pointerId)
2041
+
2042
+ const viewEl = refVirtualWrapper.value
2043
+ if (!viewEl) {
2044
+ return
2045
+ }
2046
+ const { yThumbHeight } = reactData
2047
+ const trackEl = thumbEl.parentElement as HTMLDivElement
2048
+ const trackRect = trackEl.getBoundingClientRect()
2049
+ const pointerPosition = evnt.clientY - trackRect.top
2050
+ // 记录 thumb 的偏移
2051
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
2052
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
2053
+ }
2054
+
2055
+ const pointermoveThumbYEvent = (evnt: PointerEvent) => {
2056
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2057
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
2058
+ return
2059
+ }
2060
+ const { isThumbDrag, thumbDragOffset } = internalData
2061
+ if (isThumbDrag) {
2062
+ const viewEl = refVirtualWrapper.value
2063
+ if (!viewEl) {
2064
+ return
2065
+ }
2066
+ const { yThumbHeight } = reactData
2067
+ const thumbEl = evnt.currentTarget as HTMLDivElement
2068
+ const trackEl = thumbEl.parentElement as HTMLDivElement
2069
+ const trackRect = trackEl.getBoundingClientRect()
2070
+ // 更新偏移
2071
+ viewEl.scrollTop = getScrollFromDrag(evnt.clientY - trackRect.top, thumbDragOffset, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
2072
+ }
2073
+ }
2074
+
1814
2075
  Object.assign($xeList, listMethods, listPrivateMethods)
1815
2076
 
1816
2077
  const renderDragTip = () => {
@@ -2049,7 +2310,7 @@ export default defineVxeComponent({
2049
2310
  }
2050
2311
 
2051
2312
  const renderVN = () => {
2052
- const { showCheckbox, className, loading } = props
2313
+ const { showCheckbox, className, loading, useScrollbar } = props
2053
2314
  const { bodyHeight, topSpaceHeight, rowList, isAllChecked, isAllIndeterminate } = reactData
2054
2315
  const defaultSlot = slots.default
2055
2316
  const headerSlot = slots.header
@@ -2065,6 +2326,9 @@ export default defineVxeComponent({
2065
2326
  const rowOpts = computeRowOpts.value
2066
2327
  const { isHover, padding } = rowOpts
2067
2328
  const isDrag = computeIsDrag.value
2329
+ const scrollbarXOpts = computeScrollbarXOpts.value
2330
+ const scrollbarYOpts = computeScrollbarYOpts.value
2331
+ const scrollbarWrapperClss = computeScrollbarWrapperClss.value
2068
2332
  const showDefChekboxHead = showCheckbox && showHeader !== false
2069
2333
 
2070
2334
  const leOns: {
@@ -2077,6 +2341,9 @@ export default defineVxeComponent({
2077
2341
  ref: refElem,
2078
2342
  class: ['vxe-list', className ? (XEUtils.isFunction(className) ? className({ $list: $xeList }) : className) : '', {
2079
2343
  [`size--${vSize}`]: vSize,
2344
+ 'is--virtual-scrollbar': useScrollbar,
2345
+ 'ov-x--auto-hide': useScrollbar && scrollbarXOpts.autoHide,
2346
+ 'ov-y--auto-hide': useScrollbar && scrollbarYOpts.autoHide,
2080
2347
  'is--drag': isDrag,
2081
2348
  'is--loading': loading
2082
2349
  }],
@@ -2139,7 +2406,17 @@ export default defineVxeComponent({
2139
2406
  style: {
2140
2407
  marginTop: topSpaceHeight ? `${topSpaceHeight}px` : ''
2141
2408
  }
2142
- }, defaultSlot ? defaultSlot({ items: rowList, $list: $xeList }) : rowList.map((row, i) => renderRow(row, i)))
2409
+ }, useScrollbar
2410
+ ? (
2411
+ defaultSlot ? defaultSlot({ items: rowList, $list: $xeList }) : rowList.map((row, i) => renderRow(row, i))
2412
+ )
2413
+ : [
2414
+ h('div', {
2415
+ key: 'vi',
2416
+ ref: refViewInnerElem,
2417
+ class: 'vxe-scrollbar--view-inner'
2418
+ }, defaultSlot ? defaultSlot({ items: rowList, $list: $xeList }) : rowList.map((row, i) => renderRow(row, i)))
2419
+ ])
2143
2420
  ]),
2144
2421
  footerSlot
2145
2422
  ? h('div', {
@@ -2147,6 +2424,49 @@ export default defineVxeComponent({
2147
2424
  class: 'vxe-list--footer-wrapper'
2148
2425
  }, footerSlot({ items: rowList, $list: $xeList }))
2149
2426
  : renderEmptyElement($xeList),
2427
+ /**
2428
+ * 滚动条
2429
+ */
2430
+ useScrollbar
2431
+ ? h('div', {
2432
+ class: scrollbarWrapperClss
2433
+ }, [
2434
+ scrollbarXOpts.visible === 'hidden'
2435
+ ? renderEmptyElement($xeList)
2436
+ : h('div', {
2437
+ ref: refTrackXElem,
2438
+ class: 'vxe-scrollbar--track-x',
2439
+ onClick: clickTrackXEvent
2440
+ }, [
2441
+ h('div', {
2442
+ ref: refThumbXElem,
2443
+ class: 'vxe-scrollbar--thumb-x',
2444
+ onPointerdown: pointerdownThumbXEvent,
2445
+ onPointermove: pointermoveThumbXEvent,
2446
+ onPointerup: cleatPointerThumbEvent,
2447
+ onPointercancel: cleatPointerThumbEvent,
2448
+ onLostpointercapture: cleatPointerThumbEvent
2449
+ })
2450
+ ]),
2451
+ scrollbarYOpts.visible === 'hidden'
2452
+ ? renderEmptyElement($xeList)
2453
+ : h('div', {
2454
+ ref: refTrackYElem,
2455
+ class: 'vxe-scrollbar--track-y',
2456
+ onClick: clickTrackYEvent
2457
+ }, [
2458
+ h('div', {
2459
+ ref: refThumbYElem,
2460
+ class: 'vxe-scrollbar--thumb-y',
2461
+ onPointerdown: pointerdownThumbYEvent,
2462
+ onPointermove: pointermoveThumbYEvent,
2463
+ onPointerup: cleatPointerThumbEvent,
2464
+ onPointercancel: cleatPointerThumbEvent,
2465
+ onLostpointercapture: cleatPointerThumbEvent
2466
+ })
2467
+ ])
2468
+ ])
2469
+ : renderEmptyElement($xeList),
2150
2470
  /**
2151
2471
  * 拖拽提示
2152
2472
  */
@@ -2207,7 +2527,9 @@ export default defineVxeComponent({
2207
2527
  })
2208
2528
 
2209
2529
  onActivated(() => {
2210
- recalculate().then(() => refreshScroll())
2530
+ recalculate().then(() => {
2531
+ refreshScroll()
2532
+ })
2211
2533
  })
2212
2534
 
2213
2535
  nextTick(() => {
@@ -2215,7 +2537,7 @@ export default defineVxeComponent({
2215
2537
  })
2216
2538
 
2217
2539
  onMounted(() => {
2218
- const { showSeq, showRadio, showCheckbox } = props
2540
+ const { showSeq, showRadio, showCheckbox, autoResize, useScrollbar } = props
2219
2541
  const rowOpts = computeRowOpts.value
2220
2542
  const { useKey } = rowOpts
2221
2543
 
@@ -2238,17 +2560,27 @@ export default defineVxeComponent({
2238
2560
  if (useKey && !keyField) {
2239
2561
  errLog('vxe.error.reqSupportProp', ['row-config.useKey', 'row-config.keyField'])
2240
2562
  }
2241
- if (props.autoResize) {
2563
+ if (useScrollbar || autoResize) {
2242
2564
  const el = refElem.value
2243
- const resizeObserver = globalResize.create(() => recalculate())
2565
+ const viewInnerEl = refViewInnerElem.value
2566
+ const resizeObserver = globalResize.create(() => {
2567
+ reFlag.value++
2568
+ })
2244
2569
  resizeObserver.observe(el)
2245
- if (el) {
2246
- resizeObserver.observe(el.parentElement as HTMLDivElement)
2570
+ if (autoResize) {
2571
+ if (el) {
2572
+ resizeObserver.observe(el.parentElement as HTMLDivElement)
2573
+ }
2574
+ }
2575
+ if (viewInnerEl) {
2576
+ resizeObserver.observe(viewInnerEl)
2247
2577
  }
2248
2578
  internalData.resizeObserver = resizeObserver
2249
2579
  }
2250
- recalculate()
2251
- globalEvents.on($xeList, 'resize', recalculate)
2580
+ reFlag.value++
2581
+ globalEvents.on($xeList, 'resize', () => {
2582
+ reFlag.value++
2583
+ })
2252
2584
  })
2253
2585
 
2254
2586
  onBeforeUnmount(() => {
@@ -268,6 +268,9 @@ export default defineVxeComponent({
268
268
  if (!viewEl) {
269
269
  return
270
270
  }
271
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
272
+ return
273
+ }
271
274
  const trackXEl = refTrackXElem.value
272
275
  const xThumbWidth = trackXEl ? getThumbSize(viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth) : 0
273
276
  const thumbXElem = refThumbXElem.value
@@ -277,6 +280,7 @@ export default defineVxeComponent({
277
280
  reactData.xThumbWidth = xThumbWidth
278
281
 
279
282
  const trackYEl = refTrackYElem.value
283
+
280
284
  const yThumbHeight = trackYEl ? getThumbSize(viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight) : 0
281
285
  const thumbYElem = refThumbYElem.value
282
286
  if (thumbYElem) {
@@ -290,6 +294,9 @@ export default defineVxeComponent({
290
294
  if (!viewEl) {
291
295
  return
292
296
  }
297
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
298
+ return
299
+ }
293
300
  const { xThumbWidth, yThumbHeight } = reactData
294
301
  const trackXEl = refTrackXElem.value
295
302
  const thumbXElem = refThumbXElem.value
@@ -599,7 +606,9 @@ export default defineVxeComponent({
599
606
  reFlag.value++
600
607
  })
601
608
  watch(reFlag, () => {
602
- $xeScrollbar.recalculate()
609
+ $xeScrollbar.recalculate().then(() => {
610
+ $xeScrollbar.recalculate()
611
+ })
603
612
  })
604
613
 
605
614
  onMounted(() => {