vxe-pc-ui 4.19.8 → 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 (60) hide show
  1. package/dist/all.esm.js +318 -19
  2. package/dist/style.css +1 -1
  3. package/dist/style.min.css +1 -1
  4. package/es/icon/style.css +1 -1
  5. package/es/list/src/list.js +317 -17
  6. package/es/list/style.css +26 -0
  7. package/es/list/style.min.css +1 -1
  8. package/es/scrollbar/style.css +1 -0
  9. package/es/style.css +1 -1
  10. package/es/style.min.css +1 -1
  11. package/es/ui/index.js +1 -1
  12. package/es/ui/src/log.js +1 -1
  13. package/es/ui/src/utils.js +9 -0
  14. package/es/vxe-list/style.css +26 -0
  15. package/es/vxe-list/style.min.css +1 -1
  16. package/es/vxe-scrollbar/style.css +1 -0
  17. package/lib/icon/style/style.css +1 -1
  18. package/lib/icon/style/style.min.css +1 -1
  19. package/lib/index.umd.js +336 -18
  20. package/lib/index.umd.min.js +1 -1
  21. package/lib/list/src/list.js +328 -19
  22. package/lib/list/src/list.min.js +1 -1
  23. package/lib/list/style/style.css +26 -0
  24. package/lib/list/style/style.min.css +1 -1
  25. package/lib/scrollbar/style/style.css +1 -0
  26. package/lib/style.css +1 -1
  27. package/lib/style.min.css +1 -1
  28. package/lib/ui/index.js +1 -1
  29. package/lib/ui/index.min.js +1 -1
  30. package/lib/ui/src/log.js +1 -1
  31. package/lib/ui/src/log.min.js +1 -1
  32. package/lib/ui/src/utils.js +10 -0
  33. package/lib/ui/src/utils.min.js +1 -1
  34. package/lib/vxe-list/style/style.css +26 -0
  35. package/lib/vxe-list/style/style.min.css +1 -1
  36. package/lib/vxe-scrollbar/style/style.css +1 -0
  37. package/package.json +1 -1
  38. package/packages/list/src/list.ts +345 -17
  39. package/packages/ui/src/utils.ts +10 -0
  40. package/styles/components/list.scss +51 -0
  41. package/styles/components/scrollbar.scss +3 -0
  42. package/types/components/card.d.ts +1 -1
  43. package/types/components/layout-aside.d.ts +1 -1
  44. package/types/components/layout-body.d.ts +1 -1
  45. package/types/components/list.d.ts +24 -2
  46. package/types/components/table-plugins/extend-cell-area.d.ts +1 -1
  47. package/types/components/table.d.ts +24 -0
  48. package/types/components/tabs.d.ts +1 -1
  49. /package/es/icon/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
  50. /package/es/icon/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
  51. /package/es/icon/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
  52. /package/es/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
  53. /package/es/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
  54. /package/es/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
  55. /package/lib/icon/style/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
  56. /package/lib/icon/style/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
  57. /package/lib/icon/style/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
  58. /package/lib/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
  59. /package/lib/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
  60. /package/lib/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
@@ -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
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,6 +493,11 @@ export default defineVxeComponent({
413
493
  })
414
494
  }
415
495
 
496
+ const updateScrollbar = () => {
497
+ updateThumbSize()
498
+ updateThumbOffset()
499
+ }
500
+
416
501
  /**
417
502
  * 重新计算列表
418
503
  */
@@ -430,6 +515,7 @@ export default defineVxeComponent({
430
515
  parentHeight = parentEl.clientHeight - Math.ceil(XEUtils.toNumber(parentStyle.paddingLeft) + XEUtils.toNumber(parentStyle.paddingRight))
431
516
  }
432
517
  reactData.parentHeight = parentHeight
518
+ updateScrollbar()
433
519
  updateHeight()
434
520
  if (el.clientWidth && el.clientHeight) {
435
521
  return computeScrollLoad()
@@ -461,6 +547,7 @@ export default defineVxeComponent({
461
547
  const scrollLeft = scrollBodyElem.scrollLeft
462
548
  const isX = scrollLeft !== internalData.lastScrollLeft
463
549
  const isY = scrollTop !== internalData.lastScrollTop
550
+ updateThumbOffset()
464
551
  internalData.lastScrollTop = scrollTop
465
552
  internalData.lastScrollLeft = scrollLeft
466
553
  if (reactData.scrollYLoad) {
@@ -1815,6 +1902,176 @@ export default defineVxeComponent({
1815
1902
  }
1816
1903
  }
1817
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
+
1818
2075
  Object.assign($xeList, listMethods, listPrivateMethods)
1819
2076
 
1820
2077
  const renderDragTip = () => {
@@ -2053,7 +2310,7 @@ export default defineVxeComponent({
2053
2310
  }
2054
2311
 
2055
2312
  const renderVN = () => {
2056
- const { showCheckbox, className, loading } = props
2313
+ const { showCheckbox, className, loading, useScrollbar } = props
2057
2314
  const { bodyHeight, topSpaceHeight, rowList, isAllChecked, isAllIndeterminate } = reactData
2058
2315
  const defaultSlot = slots.default
2059
2316
  const headerSlot = slots.header
@@ -2069,6 +2326,9 @@ export default defineVxeComponent({
2069
2326
  const rowOpts = computeRowOpts.value
2070
2327
  const { isHover, padding } = rowOpts
2071
2328
  const isDrag = computeIsDrag.value
2329
+ const scrollbarXOpts = computeScrollbarXOpts.value
2330
+ const scrollbarYOpts = computeScrollbarYOpts.value
2331
+ const scrollbarWrapperClss = computeScrollbarWrapperClss.value
2072
2332
  const showDefChekboxHead = showCheckbox && showHeader !== false
2073
2333
 
2074
2334
  const leOns: {
@@ -2081,6 +2341,9 @@ export default defineVxeComponent({
2081
2341
  ref: refElem,
2082
2342
  class: ['vxe-list', className ? (XEUtils.isFunction(className) ? className({ $list: $xeList }) : className) : '', {
2083
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,
2084
2347
  'is--drag': isDrag,
2085
2348
  'is--loading': loading
2086
2349
  }],
@@ -2143,7 +2406,17 @@ export default defineVxeComponent({
2143
2406
  style: {
2144
2407
  marginTop: topSpaceHeight ? `${topSpaceHeight}px` : ''
2145
2408
  }
2146
- }, 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
+ ])
2147
2420
  ]),
2148
2421
  footerSlot
2149
2422
  ? h('div', {
@@ -2151,6 +2424,49 @@ export default defineVxeComponent({
2151
2424
  class: 'vxe-list--footer-wrapper'
2152
2425
  }, footerSlot({ items: rowList, $list: $xeList }))
2153
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),
2154
2470
  /**
2155
2471
  * 拖拽提示
2156
2472
  */
@@ -2211,7 +2527,9 @@ export default defineVxeComponent({
2211
2527
  })
2212
2528
 
2213
2529
  onActivated(() => {
2214
- recalculate().then(() => refreshScroll())
2530
+ recalculate().then(() => {
2531
+ refreshScroll()
2532
+ })
2215
2533
  })
2216
2534
 
2217
2535
  nextTick(() => {
@@ -2219,7 +2537,7 @@ export default defineVxeComponent({
2219
2537
  })
2220
2538
 
2221
2539
  onMounted(() => {
2222
- const { showSeq, showRadio, showCheckbox } = props
2540
+ const { showSeq, showRadio, showCheckbox, autoResize, useScrollbar } = props
2223
2541
  const rowOpts = computeRowOpts.value
2224
2542
  const { useKey } = rowOpts
2225
2543
 
@@ -2242,17 +2560,27 @@ export default defineVxeComponent({
2242
2560
  if (useKey && !keyField) {
2243
2561
  errLog('vxe.error.reqSupportProp', ['row-config.useKey', 'row-config.keyField'])
2244
2562
  }
2245
- if (props.autoResize) {
2563
+ if (useScrollbar || autoResize) {
2246
2564
  const el = refElem.value
2247
- const resizeObserver = globalResize.create(() => recalculate())
2565
+ const viewInnerEl = refViewInnerElem.value
2566
+ const resizeObserver = globalResize.create(() => {
2567
+ reFlag.value++
2568
+ })
2248
2569
  resizeObserver.observe(el)
2249
- if (el) {
2250
- 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)
2251
2577
  }
2252
2578
  internalData.resizeObserver = resizeObserver
2253
2579
  }
2254
- recalculate()
2255
- globalEvents.on($xeList, 'resize', recalculate)
2580
+ reFlag.value++
2581
+ globalEvents.on($xeList, 'resize', () => {
2582
+ reFlag.value++
2583
+ })
2256
2584
  })
2257
2585
 
2258
2586
  onBeforeUnmount(() => {
@@ -6,6 +6,16 @@ export function isEnableConf (conf: any): boolean {
6
6
  return conf && conf.enabled !== false
7
7
  }
8
8
 
9
+ /**
10
+ * 用于开关类型的配置项
11
+ * 局部启用规则:conf={}
12
+ * 局部禁用规则:conf={enabled:false}
13
+ * 全局默认启用规则:conf.enabled=true
14
+ */
15
+ export function hasEnableConf (conf: any, opts: any): boolean {
16
+ return opts && (conf ? opts.enabled !== false : opts.enabled)
17
+ }
18
+
9
19
  export function nextZIndex () {
10
20
  return DomZIndex.getNext()
11
21
  }
@@ -287,3 +287,54 @@
287
287
  padding-right: var(--vxe-ui-list-current-padding);
288
288
  @include baseMixin.createRadioIcon();
289
289
  }
290
+
291
+ // 滚动条
292
+ .vxe-list {
293
+ & > .vxe-scrollbar {
294
+ position: unset;
295
+ }
296
+ &.is--virtual-scrollbar {
297
+ & > .vxe-list--virtual-wrapper {
298
+ scrollbar-width: none;
299
+ -ms-overflow-style: none;
300
+ }
301
+ & > .vxe-list--virtual-wrapper::-webkit-scrollbar {
302
+ display: none;
303
+ }
304
+ }
305
+ }
306
+
307
+ .vxe-list {
308
+ &.is--virtual-scrollbar {
309
+ &.ov-x--auto-hide {
310
+ &:hover {
311
+ & > .vxe-scrollbar {
312
+ & > .vxe-scrollbar--track-x {
313
+ opacity: 1;
314
+ }
315
+ }
316
+ }
317
+ & > .vxe-scrollbar {
318
+ & > .vxe-scrollbar--track-x {
319
+ opacity: 0;
320
+ @include baseMixin.createAnimationTransition(opacity, 0.8s);
321
+ }
322
+ }
323
+ }
324
+ &.ov-y--auto-hide {
325
+ &:hover {
326
+ & > .vxe-scrollbar {
327
+ & > .vxe-scrollbar--track-y {
328
+ opacity: 1;
329
+ }
330
+ }
331
+ }
332
+ & > .vxe-scrollbar {
333
+ & > .vxe-scrollbar--track-y {
334
+ opacity: 0;
335
+ @include baseMixin.createAnimationTransition(opacity, 0.8s);
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
@@ -49,6 +49,9 @@
49
49
  background-color: var(--vxe-ui-scrollbar-thumb-active-background-color);
50
50
  }
51
51
  }
52
+ }
53
+
54
+ .vxe-scrollbar {
52
55
  &.ov-x--hidden {
53
56
  & > .vxe-scrollbar--view {
54
57
  overflow-x: hidden;
@@ -34,7 +34,7 @@ export namespace VxeCardPropTypes {
34
34
  export type Padding = boolean
35
35
  export type Size = VxeComponentSizeType
36
36
  export type UseScrollbar = boolean
37
- export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'yConfig' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
37
+ export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'xConfig' | 'yConfig' | 'padding' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
38
38
  }
39
39
 
40
40
  export type VxeCardProps = {
@@ -37,7 +37,7 @@ export namespace VxeLayoutAsidePropTypes {
37
37
  animation?: boolean
38
38
  }
39
39
  export type UseScrollbar = boolean
40
- export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'yConfig' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
40
+ export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'yConfig' | 'padding' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
41
41
  }
42
42
 
43
43
  export interface VxeLayoutAsideProps {
@@ -32,7 +32,7 @@ export namespace VxeLayoutBodyPropTypes {
32
32
  export type ShowBacktop = boolean
33
33
  export interface BacktopConfig extends Omit<VxeBacktopProps, 'target'> {}
34
34
  export type UseScrollbar = boolean
35
- export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'xConfig' | 'yConfig' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
35
+ export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'native' | 'xConfig' | 'yConfig' | 'padding' | 'className' | 'viewAttrs' | 'viewClassName' | 'viewInnerClassName'> {}
36
36
  }
37
37
  export interface VxeLayoutBodyProps {
38
38
  size?: VxeLayoutBodyPropTypes.Size
@@ -1,6 +1,7 @@
1
1
  import { RenderFunction, SetupContext, Ref } from 'vue'
2
2
  import { DefineVxeComponentApp, DefineVxeComponentOptions, DefineVxeComponentInstance, VxeComponentBaseOptions, VxeComponentEventParams, VxeComponentSizeType, ValueOf } from '@vxe-ui/core'
3
3
  import { VxeContextMenuPropTypes, VxeContextMenuDefines } from './context-menu'
4
+ import { VxeScrollbarProps } from './scrollbar'
4
5
 
5
6
  /* eslint-disable no-use-before-define,@typescript-eslint/ban-types */
6
7
 
@@ -226,6 +227,8 @@ export namespace VxeListPropTypes {
226
227
  */
227
228
  enabled?: boolean
228
229
  }
230
+ export type UseScrollbar = boolean
231
+ export interface ScrollbarConfig extends Pick<VxeScrollbarProps, 'xConfig' | 'yConfig' | 'padding'> {}
229
232
  }
230
233
 
231
234
  export interface VxeListProps<D = any> {
@@ -248,6 +251,14 @@ export interface VxeListProps<D = any> {
248
251
  dragConfig?: VxeListPropTypes.DragConfig
249
252
  menuConfig?: VxeListPropTypes.MenuConfig
250
253
  virtualYConfig?: VxeListPropTypes.VirtualYConfig
254
+ /**
255
+ * 使用虚拟滚动条
256
+ */
257
+ useScrollbar?: VxeListPropTypes.UseScrollbar
258
+ /**
259
+ * 滚动条配置项
260
+ */
261
+ scrollbarConfig?: VxeListPropTypes.ScrollbarConfig
251
262
 
252
263
  /**
253
264
  * 已废弃,被 virtual-y-config 替换
@@ -276,6 +287,10 @@ export interface ListReactData {
276
287
  isAllChecked: boolean
277
288
  isAllIndeterminate: boolean
278
289
 
290
+ // 滚动条
291
+ yThumbHeight: number
292
+ xThumbWidth: number
293
+
279
294
  insertRowFlag: number
280
295
  removeRowFlag: number
281
296
 
@@ -285,13 +300,20 @@ export interface ListReactData {
285
300
  }
286
301
 
287
302
  export interface ListInternalData {
288
- resizeObserver: ResizeObserver | undefined
289
303
  fullData: any[]
290
304
  afterList: any[]
291
305
  fullKeyMaps: Record<string, any>
292
306
  rowMaps: Record<string, VxeListDefines.RowCacheItem>
293
- lastScrollLeft: number
307
+
308
+ // 滚动条
309
+ resizeObserver?: ResizeObserver
310
+ isThumbDrag?: boolean
311
+ thumbDragOffset: number
312
+ yThumbTop: number
313
+ xThumbLeft: number
294
314
  lastScrollTop: number
315
+ lastScrollLeft: number
316
+
295
317
  scrollYStore: {
296
318
  startIndex: number
297
319
  endIndex: number