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.
- package/dist/all.esm.js +318 -19
- package/dist/style.css +1 -1
- package/dist/style.min.css +1 -1
- package/es/icon/style.css +1 -1
- package/es/list/src/list.js +317 -17
- package/es/list/style.css +26 -0
- package/es/list/style.min.css +1 -1
- package/es/scrollbar/style.css +1 -0
- package/es/style.css +1 -1
- package/es/style.min.css +1 -1
- package/es/ui/index.js +1 -1
- package/es/ui/src/log.js +1 -1
- package/es/ui/src/utils.js +9 -0
- package/es/vxe-list/style.css +26 -0
- package/es/vxe-list/style.min.css +1 -1
- package/es/vxe-scrollbar/style.css +1 -0
- package/lib/icon/style/style.css +1 -1
- package/lib/icon/style/style.min.css +1 -1
- package/lib/index.umd.js +336 -18
- package/lib/index.umd.min.js +1 -1
- package/lib/list/src/list.js +328 -19
- package/lib/list/src/list.min.js +1 -1
- package/lib/list/style/style.css +26 -0
- package/lib/list/style/style.min.css +1 -1
- package/lib/scrollbar/style/style.css +1 -0
- package/lib/style.css +1 -1
- package/lib/style.min.css +1 -1
- package/lib/ui/index.js +1 -1
- package/lib/ui/index.min.js +1 -1
- package/lib/ui/src/log.js +1 -1
- package/lib/ui/src/log.min.js +1 -1
- package/lib/ui/src/utils.js +10 -0
- package/lib/ui/src/utils.min.js +1 -1
- package/lib/vxe-list/style/style.css +26 -0
- package/lib/vxe-list/style/style.min.css +1 -1
- package/lib/vxe-scrollbar/style/style.css +1 -0
- package/package.json +1 -1
- package/packages/list/src/list.ts +345 -17
- package/packages/ui/src/utils.ts +10 -0
- package/styles/components/list.scss +51 -0
- package/styles/components/scrollbar.scss +3 -0
- package/types/components/card.d.ts +1 -1
- package/types/components/layout-aside.d.ts +1 -1
- package/types/components/layout-body.d.ts +1 -1
- package/types/components/list.d.ts +24 -2
- package/types/components/table-plugins/extend-cell-area.d.ts +1 -1
- package/types/components/table.d.ts +24 -0
- package/types/components/tabs.d.ts +1 -1
- /package/es/icon/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
- /package/es/icon/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
- /package/es/icon/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
- /package/es/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
- /package/es/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
- /package/es/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
- /package/lib/icon/style/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
- /package/lib/icon/style/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
- /package/lib/icon/style/{iconfont.1791862962954.woff2 → iconfont.1791880413927.woff2} +0 -0
- /package/lib/{iconfont.1791862962954.ttf → iconfont.1791880413927.ttf} +0 -0
- /package/lib/{iconfont.1791862962954.woff → iconfont.1791880413927.woff} +0 -0
- /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,
|
|
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
|
-
|
|
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
|
|
245
|
+
const scrollbarXOpts = computeScrollbarXOpts.value
|
|
246
|
+
const scrollbarYOpts = computeScrollbarYOpts.value
|
|
247
|
+
const stys: VxeComponentStyleType = {}
|
|
222
248
|
if (rowHeight) {
|
|
223
|
-
|
|
249
|
+
stys['--vxe-ui-list-row-height'] = toCssUnit(rowHeight)
|
|
224
250
|
}
|
|
225
|
-
|
|
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
|
-
},
|
|
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(() =>
|
|
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 (
|
|
2563
|
+
if (useScrollbar || autoResize) {
|
|
2246
2564
|
const el = refElem.value
|
|
2247
|
-
const
|
|
2565
|
+
const viewInnerEl = refViewInnerElem.value
|
|
2566
|
+
const resizeObserver = globalResize.create(() => {
|
|
2567
|
+
reFlag.value++
|
|
2568
|
+
})
|
|
2248
2569
|
resizeObserver.observe(el)
|
|
2249
|
-
if (
|
|
2250
|
-
|
|
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
|
-
|
|
2255
|
-
globalEvents.on($xeList, 'resize',
|
|
2580
|
+
reFlag.value++
|
|
2581
|
+
globalEvents.on($xeList, 'resize', () => {
|
|
2582
|
+
reFlag.value++
|
|
2583
|
+
})
|
|
2256
2584
|
})
|
|
2257
2585
|
|
|
2258
2586
|
onBeforeUnmount(() => {
|
package/packages/ui/src/utils.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -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
|
-
|
|
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
|