vxe-pc-ui 4.20.0 → 4.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/all.esm.js +594 -130
  2. package/dist/style.css +1 -1
  3. package/dist/style.min.css +1 -1
  4. package/es/card/src/card.js +17 -3
  5. package/es/icon/style.css +1 -1
  6. package/es/language/fr-FR.js +29 -29
  7. package/es/layout-aside/src/layout-aside.js +8 -5
  8. package/es/layout-body/src/layout-body.js +19 -11
  9. package/es/list/src/list.js +79 -36
  10. package/es/list/style.css +25 -8
  11. package/es/list/style.min.css +1 -1
  12. package/es/scrollbar/src/scrollbar.js +59 -17
  13. package/es/style.css +1 -1
  14. package/es/style.min.css +1 -1
  15. package/es/tabs/src/tabs.js +19 -4
  16. package/es/tree/src/tree.js +393 -55
  17. package/es/tree/style.css +43 -0
  18. package/es/tree/style.min.css +1 -1
  19. package/es/ui/index.js +1 -1
  20. package/es/ui/src/log.js +1 -1
  21. package/es/ui/src/utils.js +3 -0
  22. package/es/vxe-list/style.css +25 -8
  23. package/es/vxe-list/style.min.css +1 -1
  24. package/es/vxe-tree/style.css +43 -0
  25. package/es/vxe-tree/style.min.css +1 -1
  26. package/lib/card/src/card.js +17 -3
  27. package/lib/card/src/card.min.js +1 -1
  28. package/lib/icon/style/style.css +1 -1
  29. package/lib/icon/style/style.min.css +1 -1
  30. package/lib/index.umd.js +610 -140
  31. package/lib/index.umd.min.js +1 -1
  32. package/lib/language/fr-FR.js +29 -29
  33. package/lib/language/fr-FR.min.js +1 -1
  34. package/lib/language/fr-FR.umd.js +29 -29
  35. package/lib/layout-aside/src/layout-aside.js +7 -7
  36. package/lib/layout-aside/src/layout-aside.min.js +1 -1
  37. package/lib/layout-body/src/layout-body.js +27 -21
  38. package/lib/layout-body/src/layout-body.min.js +1 -1
  39. package/lib/list/src/list.js +70 -32
  40. package/lib/list/src/list.min.js +1 -1
  41. package/lib/list/style/style.css +25 -8
  42. package/lib/list/style/style.min.css +1 -1
  43. package/lib/scrollbar/src/scrollbar.js +67 -15
  44. package/lib/scrollbar/src/scrollbar.min.js +1 -1
  45. package/lib/style.css +1 -1
  46. package/lib/style.min.css +1 -1
  47. package/lib/tabs/src/tabs.js +22 -10
  48. package/lib/tabs/src/tabs.min.js +1 -1
  49. package/lib/tree/src/tree.js +397 -53
  50. package/lib/tree/src/tree.min.js +1 -1
  51. package/lib/tree/style/style.css +43 -0
  52. package/lib/tree/style/style.min.css +1 -1
  53. package/lib/ui/index.js +1 -1
  54. package/lib/ui/index.min.js +1 -1
  55. package/lib/ui/src/log.js +1 -1
  56. package/lib/ui/src/log.min.js +1 -1
  57. package/lib/ui/src/utils.js +4 -0
  58. package/lib/ui/src/utils.min.js +1 -1
  59. package/lib/vxe-list/style/style.css +25 -8
  60. package/lib/vxe-list/style/style.min.css +1 -1
  61. package/lib/vxe-tree/style/style.css +43 -0
  62. package/lib/vxe-tree/style/style.min.css +1 -1
  63. package/package.json +1 -1
  64. package/packages/card/src/card.ts +18 -3
  65. package/packages/language/fr-FR.ts +903 -903
  66. package/packages/layout-aside/src/layout-aside.ts +8 -5
  67. package/packages/layout-body/src/layout-body.ts +23 -14
  68. package/packages/list/src/list.ts +87 -42
  69. package/packages/scrollbar/src/scrollbar.ts +63 -16
  70. package/packages/tabs/src/tabs.ts +19 -5
  71. package/packages/tree/src/tree.ts +432 -64
  72. package/packages/ui/src/utils.ts +4 -0
  73. package/styles/components/list.scss +35 -10
  74. package/styles/components/tree.scss +76 -0
  75. package/types/components/card.d.ts +10 -1
  76. package/types/components/layout-aside.d.ts +10 -1
  77. package/types/components/layout-body.d.ts +10 -1
  78. package/types/components/list.d.ts +10 -1
  79. package/types/components/scrollbar.d.ts +17 -2
  80. package/types/components/table.d.ts +47 -4
  81. package/types/components/tabs.d.ts +10 -1
  82. package/types/components/tree.d.ts +33 -2
  83. /package/es/icon/{iconfont.1791880413927.ttf → iconfont.1791950625324.ttf} +0 -0
  84. /package/es/icon/{iconfont.1791880413927.woff → iconfont.1791950625324.woff} +0 -0
  85. /package/es/icon/{iconfont.1791880413927.woff2 → iconfont.1791950625324.woff2} +0 -0
  86. /package/es/{iconfont.1791880413927.ttf → iconfont.1791950625324.ttf} +0 -0
  87. /package/es/{iconfont.1791880413927.woff → iconfont.1791950625324.woff} +0 -0
  88. /package/es/{iconfont.1791880413927.woff2 → iconfont.1791950625324.woff2} +0 -0
  89. /package/lib/icon/style/{iconfont.1791880413927.ttf → iconfont.1791950625324.ttf} +0 -0
  90. /package/lib/icon/style/{iconfont.1791880413927.woff → iconfont.1791950625324.woff} +0 -0
  91. /package/lib/icon/style/{iconfont.1791880413927.woff2 → iconfont.1791950625324.woff2} +0 -0
  92. /package/lib/{iconfont.1791880413927.ttf → iconfont.1791950625324.ttf} +0 -0
  93. /package/lib/{iconfont.1791880413927.woff → iconfont.1791950625324.woff} +0 -0
  94. /package/lib/{iconfont.1791880413927.woff2 → iconfont.1791950625324.woff2} +0 -0
@@ -1,14 +1,15 @@
1
1
  import { ref, h, reactive, PropType, computed, VNode, watch, onBeforeUnmount, nextTick, onMounted, provide } from 'vue'
2
2
  import { defineVxeComponent } from '../../ui/src/comp'
3
- import { VxeUI, createEvent, useSize, globalEvents, globalResize, renderEmptyElement } from '../../ui'
3
+ import { VxeUI, domUtils, createEvent, useSize, globalEvents, globalResize, renderEmptyElement } from '../../ui'
4
4
  import { calcTreeLine, getItemCacheObj } from './util'
5
5
  import { createComponentLog } from '../../ui/src/log'
6
6
  import { getCrossTreeDragNodeInfo } from './store'
7
7
  import XEUtils from 'xe-utils'
8
8
  import { getSlotVNs } from '../../ui/src/vn'
9
9
  import { toCssUnit, isScale, getPaddingTopBottomSize, addClass, removeClass, getTpImg, hasControlKey, getEventTargetNode, hasClass } from '../../ui/src/dom'
10
- import { isEnableConf, enModelValue, deModelValue, getText } from '../../ui/src/utils'
10
+ import { isEnableConf, enModelValue, deModelValue, getText, getDefaultConfig } from '../../ui/src/utils'
11
11
  import { moveRowAnimateToTb, clearRowAnimate } from '../../ui/src/anime'
12
+ import { getThumbOffsetSize, getThumbSize, getScrollFromClick, getScrollFromDrag } from '../../scrollbar/src/util'
12
13
  import VxeLoadingComponent from '../../loading'
13
14
  import VxeTooltipComponent from '../../tooltip'
14
15
 
@@ -25,6 +26,37 @@ function getNodeUniqueId () {
25
26
  return XEUtils.uniqueId('node_')
26
27
  }
27
28
 
29
+ function createReactData ():TreeReactData {
30
+ return {
31
+ parentHeight: 0,
32
+ customHeight: 0,
33
+ customMinHeight: 0,
34
+ customMaxHeight: 0,
35
+ currentNode: null,
36
+ scrollYLoad: false,
37
+ bodyHeight: 0,
38
+ topSpaceHeight: 0,
39
+ selectRadioKey: null,
40
+ treeList: [],
41
+ updateExpandedFlag: 1,
42
+ updateCheckboxFlag: 1,
43
+
44
+ // 滚动条
45
+ yThumbHeight: 0,
46
+ xThumbWidth: 0,
47
+
48
+ insertNodeFlag: 1,
49
+ removeNodeFlag: 1,
50
+ dragNode: null,
51
+ dragTipText: '',
52
+ isCrossDragNode: false,
53
+ tooltipStore: {
54
+ visible: false,
55
+ node: null
56
+ }
57
+ }
58
+ }
59
+
28
60
  function createInternalData (): TreeInternalData {
29
61
  return {
30
62
  // initialized: false,
@@ -38,8 +70,15 @@ function createInternalData (): TreeInternalData {
38
70
  treeExpandedMaps: {},
39
71
  treeExpandLazyLoadedMaps: {},
40
72
 
41
- lastScrollLeft: 0,
73
+ // 滚动条
74
+ // resizeObserver: undefined,
75
+ // isThumbDrag: false,
76
+ thumbDragOffset: 0,
77
+ yThumbTop: 0,
78
+ xThumbLeft: 0,
42
79
  lastScrollTop: 0,
80
+ lastScrollLeft: 0,
81
+
43
82
  scrollYStore: {
44
83
  startIndex: 0,
45
84
  endIndex: 0,
@@ -60,32 +99,6 @@ function createInternalData (): TreeInternalData {
60
99
  }
61
100
  }
62
101
 
63
- function createReactData ():TreeReactData {
64
- return {
65
- parentHeight: 0,
66
- customHeight: 0,
67
- customMinHeight: 0,
68
- customMaxHeight: 0,
69
- currentNode: null,
70
- scrollYLoad: false,
71
- bodyHeight: 0,
72
- topSpaceHeight: 0,
73
- selectRadioKey: null,
74
- treeList: [],
75
- updateExpandedFlag: 1,
76
- updateCheckboxFlag: 1,
77
- insertNodeFlag: 1,
78
- removeNodeFlag: 1,
79
- dragNode: null,
80
- dragTipText: '',
81
- isCrossDragNode: false,
82
- tooltipStore: {
83
- visible: false,
84
- node: null
85
- }
86
- }
87
- }
88
-
89
102
  let crossTreeDragNodeObj: {
90
103
  $oldTree: VxeTreeConstructor & VxeTreePrivateMethods
91
104
  $newTree: (VxeTreeConstructor & VxeTreePrivateMethods) | null
@@ -220,7 +233,12 @@ export default defineVxeComponent({
220
233
  type: String as PropType<VxeTreePropTypes.Size>,
221
234
  default: () => getConfig().tree.size || getConfig().size
222
235
  },
223
- virtualYConfig: Object as PropType<VxeTreePropTypes.VirtualYConfig>
236
+ virtualYConfig: Object as PropType<VxeTreePropTypes.VirtualYConfig>,
237
+ useScrollbar: {
238
+ type: Boolean as PropType<VxeTreePropTypes.UseScrollbar>,
239
+ default: () => getConfig().tree.useScrollbar
240
+ },
241
+ scrollbarConfig: Object as PropType<VxeTreePropTypes.ScrollbarConfig>
224
242
  },
225
243
  emits: [
226
244
  'update:modelValue',
@@ -256,6 +274,11 @@ export default defineVxeComponent({
256
274
  const refVirtualWrapper = ref<HTMLDivElement>()
257
275
  const refVirtualBody = ref<HTMLDivElement>()
258
276
 
277
+ const refTrackXElem = ref<HTMLDivElement>()
278
+ const refTrackYElem = ref<HTMLDivElement>()
279
+ const refThumbXElem = ref<HTMLDivElement>()
280
+ const refThumbYElem = ref<HTMLDivElement>()
281
+
259
282
  const refDragNodeLineElem = ref<HTMLDivElement>()
260
283
  const refDragTipElem = ref<HTMLDivElement>()
261
284
 
@@ -349,6 +372,20 @@ export default defineVxeComponent({
349
372
  return Object.assign({}, getConfig().tree.menuConfig, props.menuConfig)
350
373
  })
351
374
 
375
+ const computeWrapperStyles = computed(() => {
376
+ const scrollbarOpts = computeScrollbarOpts.value
377
+ const scrollbarXOpts = computeScrollbarXOpts.value
378
+ const scrollbarYOpts = computeScrollbarYOpts.value
379
+ const barWidth = getDefaultConfig(getDefaultConfig(scrollbarYOpts.width, scrollbarOpts.width), getConfig().scrollbar.width)
380
+ const barHeight = getDefaultConfig(getDefaultConfig(scrollbarXOpts.height, scrollbarOpts.height), getConfig().scrollbar.height)
381
+ const stys: VxeComponentStyleType = {}
382
+ if (barWidth || barHeight) {
383
+ stys['--vxe-ui-scrollbar-y-width'] = toCssUnit(barWidth || barHeight)
384
+ stys['--vxe-ui-scrollbar-x-height'] = toCssUnit(barHeight || barWidth)
385
+ }
386
+ return stys
387
+ })
388
+
352
389
  const computeTreeStyle = computed(() => {
353
390
  const { indent } = props
354
391
  const { customHeight, customMinHeight, customMaxHeight } = reactData
@@ -383,6 +420,81 @@ export default defineVxeComponent({
383
420
  return Object.assign({}, getConfig().tree.filterConfig, props.filterConfig)
384
421
  })
385
422
 
423
+ const computeScrollbarOpts = computed(() => {
424
+ return Object.assign({}, getConfig().tree.scrollbarConfig, props.scrollbarConfig)
425
+ })
426
+
427
+ const computeScrollbarXOpts = computed(() => {
428
+ const scrollbarOpts = computeScrollbarOpts.value
429
+ return Object.assign({}, getConfig().scrollbar.xConfig, scrollbarOpts.xConfig, {
430
+ visible: false
431
+ })
432
+ })
433
+
434
+ const computeScrollbarYOpts = computed(() => {
435
+ const scrollbarOpts = computeScrollbarOpts.value
436
+ return Object.assign({}, getConfig().scrollbar.yConfig, scrollbarOpts.yConfig)
437
+ })
438
+
439
+ const computeScrollXVisible = computed(() => {
440
+ const scrollbarOpts = computeScrollbarOpts.value
441
+ const scrollbarXOpts = computeScrollbarXOpts.value
442
+ return getDefaultConfig(scrollbarXOpts.visible, scrollbarOpts.visible)
443
+ })
444
+
445
+ const computeScrollYVisible = computed(() => {
446
+ const scrollbarOpts = computeScrollbarOpts.value
447
+ const scrollbarYOpts = computeScrollbarYOpts.value
448
+ return getDefaultConfig(scrollbarYOpts.visible, scrollbarOpts.visible)
449
+ })
450
+
451
+ const computeScrollXAutoHide = computed(() => {
452
+ const scrollbarOpts = computeScrollbarOpts.value
453
+ const scrollbarXOpts = computeScrollbarXOpts.value
454
+ return getDefaultConfig(getDefaultConfig(scrollbarXOpts.autoHide, scrollbarOpts.autoHide), getConfig().scrollbar.autoHide)
455
+ })
456
+
457
+ const computeScrollYAutoHide = computed(() => {
458
+ const scrollbarOpts = computeScrollbarOpts.value
459
+ const scrollbarYOpts = computeScrollbarYOpts.value
460
+ return getDefaultConfig(getDefaultConfig(scrollbarYOpts.autoHide, scrollbarOpts.autoHide), getConfig().scrollbar.autoHide)
461
+ })
462
+
463
+ const computeScrollbarWrapperClss = computed(() => {
464
+ const scrollbarOpts = computeScrollbarOpts.value
465
+ const { padding } = scrollbarOpts
466
+ const { yThumbHeight, xThumbWidth } = reactData
467
+ const scrollbarXToTop = computeScrollbarXToTop.value
468
+ const scrollbarYToLeft = computeScrollbarYToLeft.value
469
+ const scrollXVisible = computeScrollXVisible.value
470
+ const scrollYVisible = computeScrollYVisible.value
471
+ const scrollXAutoHide = computeScrollXAutoHide.value
472
+ const scrollYAutoHide = computeScrollYAutoHide.value
473
+ return domUtils.buildClass([
474
+ 'vxe-scrollbar is--virtual',
475
+ `ov-x--${scrollXVisible === false ? 'hidden' : 'visible'}`,
476
+ `ov-y--${scrollYVisible === false ? 'hidden' : 'visible'}`,
477
+ `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}`,
478
+ `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}`
479
+ ], {
480
+ 'is--padding': padding,
481
+ 'ov-x--auto-hide': scrollXAutoHide,
482
+ 'ov-y--auto-hide': scrollYAutoHide,
483
+ 'overflow-y': yThumbHeight,
484
+ 'overflow-x': xThumbWidth
485
+ })
486
+ })
487
+
488
+ const computeScrollbarXToTop = computed(() => {
489
+ const scrollbarXOpts = computeScrollbarXOpts.value
490
+ return scrollbarXOpts.position === 'top'
491
+ })
492
+
493
+ const computeScrollbarYToLeft = computed(() => {
494
+ const scrollbarYOpts = computeScrollbarYOpts.value
495
+ return scrollbarYOpts.position === 'left'
496
+ })
497
+
386
498
  const computeMaps: VxeTreePrivateComputed = {
387
499
  computeKeyField,
388
500
  computeParentField,
@@ -928,6 +1040,11 @@ export default defineVxeComponent({
928
1040
  })
929
1041
  }
930
1042
 
1043
+ const updateScrollbar = () => {
1044
+ updateThumbSize()
1045
+ updateThumbOffset()
1046
+ }
1047
+
931
1048
  /**
932
1049
  * 重新计算列表
933
1050
  */
@@ -949,6 +1066,7 @@ export default defineVxeComponent({
949
1066
  const parentPaddingSize = getPaddingTopBottomSize(parentEl)
950
1067
  reactData.parentHeight = Math.max(headHeight + footHeight + rowHeight, parentEl.clientHeight - parentPaddingSize - headHeight - footHeight)
951
1068
  }
1069
+ updateScrollbar()
952
1070
  updateHeight()
953
1071
  return computeScrollLoad().then(() => {
954
1072
  updateHeight()
@@ -984,6 +1102,7 @@ export default defineVxeComponent({
984
1102
  const scrollLeft = scrollBodyElem.scrollLeft
985
1103
  const isX = scrollLeft !== internalData.lastScrollLeft
986
1104
  const isY = scrollTop !== internalData.lastScrollTop
1105
+ updateThumbOffset()
987
1106
  internalData.lastScrollTop = scrollTop
988
1107
  internalData.lastScrollLeft = scrollLeft
989
1108
  if (reactData.scrollYLoad) {
@@ -1531,14 +1650,6 @@ export default defineVxeComponent({
1531
1650
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt)
1532
1651
  }
1533
1652
 
1534
- const handleGlobalResizeEvent = () => {
1535
- const el = refElem.value
1536
- if (!el || !el.clientWidth) {
1537
- return
1538
- }
1539
- recalculate()
1540
- }
1541
-
1542
1653
  const insertTreeNode = (newRecords: any[], isAppend: boolean) => {
1543
1654
  const { treeFullData, nodeMaps } = internalData
1544
1655
  const keyField = computeKeyField.value
@@ -2997,6 +3108,176 @@ export default defineVxeComponent({
2997
3108
  }
2998
3109
  }
2999
3110
 
3111
+ const updateThumbSize = () => {
3112
+ const viewEl = refVirtualWrapper.value
3113
+ if (!viewEl) {
3114
+ return
3115
+ }
3116
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
3117
+ return
3118
+ }
3119
+ const trackXEl = refTrackXElem.value
3120
+ const xThumbWidth = trackXEl ? getThumbSize(viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth) : 0
3121
+ const thumbXElem = refThumbXElem.value
3122
+ if (thumbXElem) {
3123
+ thumbXElem.style.width = xThumbWidth + 'px'
3124
+ }
3125
+ reactData.xThumbWidth = xThumbWidth
3126
+
3127
+ const trackYEl = refTrackYElem.value
3128
+
3129
+ const yThumbHeight = trackYEl ? getThumbSize(viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight) : 0
3130
+ const thumbYElem = refThumbYElem.value
3131
+ if (thumbYElem) {
3132
+ thumbYElem.style.height = yThumbHeight + 'px'
3133
+ }
3134
+ reactData.yThumbHeight = yThumbHeight
3135
+ }
3136
+
3137
+ const updateThumbOffset = () => {
3138
+ const viewEl = refVirtualWrapper.value
3139
+ if (!viewEl) {
3140
+ return
3141
+ }
3142
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
3143
+ return
3144
+ }
3145
+ const { xThumbWidth, yThumbHeight } = reactData
3146
+ const trackXEl = refTrackXElem.value
3147
+ const thumbXElem = refThumbXElem.value
3148
+ const xThumbLeft = trackXEl && xThumbWidth ? getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth, xThumbWidth) : 0
3149
+ internalData.xThumbLeft = xThumbLeft
3150
+ if (thumbXElem && xThumbWidth) {
3151
+ thumbXElem.style.width = xThumbWidth + 'px'
3152
+ thumbXElem.style.transform = `translateX(${xThumbLeft}px)`
3153
+ }
3154
+
3155
+ const trackYEl = refTrackYElem.value
3156
+ const thumbYElem = refThumbYElem.value
3157
+ const yThumbTop = trackYEl && yThumbHeight ? getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight, yThumbHeight) : 0
3158
+ internalData.yThumbTop = yThumbTop
3159
+ if (thumbYElem && yThumbHeight) {
3160
+ thumbYElem.style.height = yThumbHeight + 'px'
3161
+ thumbYElem.style.transform = `translateY(${yThumbTop}px)`
3162
+ }
3163
+ }
3164
+
3165
+ const clickTrackXEvent = (evnt: MouseEvent) => {
3166
+ const trackEl = evnt.currentTarget as HTMLDivElement
3167
+ if (trackEl !== evnt.target) {
3168
+ return
3169
+ }
3170
+ const viewEl = refVirtualWrapper.value
3171
+ if (!viewEl) {
3172
+ return
3173
+ }
3174
+ const { xThumbWidth } = reactData
3175
+ const trackRect = trackEl.getBoundingClientRect()
3176
+ viewEl.scrollTo({
3177
+ left: getScrollFromClick(evnt.clientX - trackRect.left, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth),
3178
+ behavior: 'auto'
3179
+ })
3180
+ }
3181
+
3182
+ const clickTrackYEvent = (evnt: MouseEvent) => {
3183
+ const trackEl = evnt.currentTarget as HTMLDivElement
3184
+ if (trackEl !== evnt.target) {
3185
+ return
3186
+ }
3187
+ const viewEl = refVirtualWrapper.value
3188
+ if (!viewEl) {
3189
+ return
3190
+ }
3191
+ const { yThumbHeight } = reactData
3192
+ const trackRect = trackEl.getBoundingClientRect()
3193
+ viewEl.scrollTo({
3194
+ top: getScrollFromClick(evnt.clientY - trackRect.top, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight),
3195
+ behavior: 'auto'
3196
+ })
3197
+ }
3198
+
3199
+ const pointerdownThumbXEvent = (evnt: PointerEvent) => {
3200
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3201
+ internalData.isThumbDrag = true
3202
+ thumbEl.setPointerCapture(evnt.pointerId)
3203
+
3204
+ const viewEl = refVirtualWrapper.value
3205
+ if (!viewEl) {
3206
+ return
3207
+ }
3208
+ const { xThumbWidth } = reactData
3209
+ const trackEl = thumbEl.parentElement as HTMLDivElement
3210
+ const trackRect = trackEl.getBoundingClientRect()
3211
+ const pointerPosition = evnt.clientX - trackRect.left
3212
+ // 记录 thumb 的偏移
3213
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
3214
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
3215
+ }
3216
+
3217
+ const pointermoveThumbXEvent = (evnt: PointerEvent) => {
3218
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3219
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
3220
+ return
3221
+ }
3222
+ const { isThumbDrag, thumbDragOffset } = internalData
3223
+ if (isThumbDrag) {
3224
+ const viewEl = refVirtualWrapper.value
3225
+ if (!viewEl) {
3226
+ return
3227
+ }
3228
+ const { xThumbWidth } = reactData
3229
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3230
+ const trackEl = thumbEl.parentElement as HTMLDivElement
3231
+ const trackRect = trackEl.getBoundingClientRect()
3232
+ // 更新偏移
3233
+ viewEl.scrollLeft = getScrollFromDrag(evnt.clientX - trackRect.left, thumbDragOffset, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
3234
+ }
3235
+ }
3236
+
3237
+ const cleatPointerThumbEvent = (evnt: PointerEvent) => {
3238
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3239
+ thumbEl.releasePointerCapture(evnt.pointerId)
3240
+ internalData.isThumbDrag = false
3241
+ }
3242
+
3243
+ const pointerdownThumbYEvent = (evnt: PointerEvent) => {
3244
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3245
+ internalData.isThumbDrag = true
3246
+ thumbEl.setPointerCapture(evnt.pointerId)
3247
+
3248
+ const viewEl = refVirtualWrapper.value
3249
+ if (!viewEl) {
3250
+ return
3251
+ }
3252
+ const { yThumbHeight } = reactData
3253
+ const trackEl = thumbEl.parentElement as HTMLDivElement
3254
+ const trackRect = trackEl.getBoundingClientRect()
3255
+ const pointerPosition = evnt.clientY - trackRect.top
3256
+ // 记录 thumb 的偏移
3257
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
3258
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
3259
+ }
3260
+
3261
+ const pointermoveThumbYEvent = (evnt: PointerEvent) => {
3262
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3263
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
3264
+ return
3265
+ }
3266
+ const { isThumbDrag, thumbDragOffset } = internalData
3267
+ if (isThumbDrag) {
3268
+ const viewEl = refVirtualWrapper.value
3269
+ if (!viewEl) {
3270
+ return
3271
+ }
3272
+ const { yThumbHeight } = reactData
3273
+ const thumbEl = evnt.currentTarget as HTMLDivElement
3274
+ const trackEl = thumbEl.parentElement as HTMLDivElement
3275
+ const trackRect = trackEl.getBoundingClientRect()
3276
+ // 更新偏移
3277
+ viewEl.scrollTop = getScrollFromDrag(evnt.clientY - trackRect.top, thumbDragOffset, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
3278
+ }
3279
+ }
3280
+
3000
3281
  Object.assign($xeTree, treeMethods, treePrivateMethods)
3001
3282
 
3002
3283
  const renderDragIcon = (node: any, nodeid: string) => {
@@ -3341,13 +3622,14 @@ export default defineVxeComponent({
3341
3622
  }
3342
3623
 
3343
3624
  const renderVN = () => {
3344
- const { loading, trigger, showLine } = props
3345
- const { bodyHeight, topSpaceHeight, treeList, tooltipStore } = reactData
3625
+ const { loading, trigger, showLine, useScrollbar } = props
3626
+ const { bodyHeight, topSpaceHeight, treeList, tooltipStore, xThumbWidth, yThumbHeight } = reactData
3346
3627
  const vSize = computeSize.value
3347
3628
  const radioOpts = computeRadioOpts.value
3348
3629
  const checkboxOpts = computeCheckboxOpts.value
3349
3630
  const loadingOpts = computeLoadingOpts.value
3350
3631
  const isNodeHover = computeIsNodeHover.value
3632
+ const wrapperStyles = computeWrapperStyles.value
3351
3633
  const treeStyle = computeTreeStyle.value
3352
3634
  const dragOpts = computeDragOpts.value
3353
3635
  const tooltipOpts = computeTooltipOpts.value
@@ -3355,6 +3637,14 @@ export default defineVxeComponent({
3355
3637
  const headerSlot = slots.header
3356
3638
  const footerSlot = slots.footer
3357
3639
  const tooltipSlot = slots.tooltip
3640
+ const scrollbarOpts = computeScrollbarOpts.value
3641
+ const scrollXVisible = computeScrollXVisible.value
3642
+ const scrollYVisible = computeScrollYVisible.value
3643
+ const scrollbarXToTop = computeScrollbarXToTop.value
3644
+ const scrollbarYToLeft = computeScrollbarYToLeft.value
3645
+ const scrollXAutoHide = computeScrollXAutoHide.value
3646
+ const scrollYAutoHide = computeScrollYAutoHide.value
3647
+ const scrollbarWrapperClss = computeScrollbarWrapperClss.value
3358
3648
 
3359
3649
  const teOns: {
3360
3650
  onDragover?: (...args: any[]) => void
@@ -3364,15 +3654,29 @@ export default defineVxeComponent({
3364
3654
  }
3365
3655
  return h('div', {
3366
3656
  ref: refElem,
3367
- class: ['vxe-tree', {
3368
- [`size--${vSize}`]: vSize,
3369
- 'show--line': showLine,
3370
- 'checkbox--highlight': checkboxOpts.highlight,
3371
- 'radio--highlight': radioOpts.highlight,
3372
- 'node--hover': isNodeHover,
3373
- 'node--trigger': trigger === 'node',
3374
- 'is--loading': loading
3375
- }],
3657
+ class: [
3658
+ 'vxe-tree',
3659
+ useScrollbar ? `ov-x--${scrollXVisible === false ? 'hidden' : 'visible'}` : '',
3660
+ useScrollbar ? `ov-y--${scrollYVisible === false ? 'hidden' : 'visible'}` : '',
3661
+ useScrollbar ? `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}` : '',
3662
+ useScrollbar ? `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}` : '',
3663
+ {
3664
+ [`size--${vSize}`]: vSize,
3665
+ 'show--line': showLine,
3666
+ 'is--virtual-scrollbar': useScrollbar,
3667
+ 'ov-padding': useScrollbar && scrollbarOpts.padding,
3668
+ 'ov-x--auto-hide': useScrollbar && scrollXAutoHide,
3669
+ 'ov-y--auto-hide': useScrollbar && scrollYAutoHide,
3670
+ 'overflow-y': yThumbHeight,
3671
+ 'overflow-x': xThumbWidth,
3672
+ 'checkbox--highlight': checkboxOpts.highlight,
3673
+ 'radio--highlight': radioOpts.highlight,
3674
+ 'node--hover': isNodeHover,
3675
+ 'node--trigger': trigger === 'node',
3676
+ 'is--loading': loading
3677
+ }
3678
+ ],
3679
+ style: wrapperStyles,
3376
3680
  ...teOns
3377
3681
  }, [
3378
3682
  headerSlot
@@ -3407,6 +3711,49 @@ export default defineVxeComponent({
3407
3711
  class: 'vxe-tree--footer-wrapper'
3408
3712
  }, footerSlot({ $tree: $xeTree }))
3409
3713
  : renderEmptyElement($xeTree),
3714
+ /**
3715
+ * 滚动条
3716
+ */
3717
+ useScrollbar
3718
+ ? h('div', {
3719
+ class: scrollbarWrapperClss
3720
+ }, [
3721
+ scrollXVisible === false
3722
+ ? renderEmptyElement($xeTree)
3723
+ : h('div', {
3724
+ ref: refTrackXElem,
3725
+ class: 'vxe-scrollbar--track-x',
3726
+ onClick: clickTrackXEvent
3727
+ }, [
3728
+ h('div', {
3729
+ ref: refThumbXElem,
3730
+ class: 'vxe-scrollbar--thumb-x',
3731
+ onPointerdown: pointerdownThumbXEvent,
3732
+ onPointermove: pointermoveThumbXEvent,
3733
+ onPointerup: cleatPointerThumbEvent,
3734
+ onPointercancel: cleatPointerThumbEvent,
3735
+ onLostpointercapture: cleatPointerThumbEvent
3736
+ })
3737
+ ]),
3738
+ scrollYVisible === false
3739
+ ? renderEmptyElement($xeTree)
3740
+ : h('div', {
3741
+ ref: refTrackYElem,
3742
+ class: 'vxe-scrollbar--track-y',
3743
+ onClick: clickTrackYEvent
3744
+ }, [
3745
+ h('div', {
3746
+ ref: refThumbYElem,
3747
+ class: 'vxe-scrollbar--thumb-y',
3748
+ onPointerdown: pointerdownThumbYEvent,
3749
+ onPointermove: pointermoveThumbYEvent,
3750
+ onPointerup: cleatPointerThumbEvent,
3751
+ onPointercancel: cleatPointerThumbEvent,
3752
+ onLostpointercapture: cleatPointerThumbEvent
3753
+ })
3754
+ ])
3755
+ ])
3756
+ : renderEmptyElement($xeTree),
3410
3757
  /**
3411
3758
  * 拖拽提示
3412
3759
  */
@@ -3495,22 +3842,37 @@ export default defineVxeComponent({
3495
3842
  triggerSearchEvent(new Event('filter'))
3496
3843
  })
3497
3844
 
3498
- const hFlag = ref(0)
3845
+ const reFlag = ref(0)
3499
3846
  watch(() => props.height, () => {
3500
- hFlag.value++
3847
+ reFlag.value++
3501
3848
  })
3502
3849
  watch(() => props.minHeight, () => {
3503
- hFlag.value++
3850
+ reFlag.value++
3504
3851
  })
3505
3852
  watch(() => props.maxHeight, () => {
3506
- hFlag.value++
3853
+ reFlag.value++
3507
3854
  })
3508
- watch(hFlag, () => {
3509
- recalculate()
3855
+ watch(() => props.useScrollbar, () => {
3856
+ reFlag.value++
3857
+ })
3858
+ watch(computeScrollXVisible, () => {
3859
+ nextTick(() => {
3860
+ reFlag.value++
3861
+ })
3862
+ })
3863
+ watch(computeScrollYVisible, () => {
3864
+ nextTick(() => {
3865
+ reFlag.value++
3866
+ })
3867
+ })
3868
+ watch(reFlag, () => {
3869
+ recalculate().then(() => {
3870
+ recalculate()
3871
+ })
3510
3872
  })
3511
3873
 
3512
3874
  onMounted(() => {
3513
- const { transform, drag, menuConfig, showOverflow, lazy, loadMethod } = props
3875
+ const { transform, drag, menuConfig, showOverflow, lazy, loadMethod, autoResize, useScrollbar } = props
3514
3876
  const dragOpts = computeDragOpts.value
3515
3877
  if (!showOverflow) {
3516
3878
  errLog('vxe.error.errProp', ['show-overflow=false', 'show-overflow=true'])
@@ -3531,25 +3893,31 @@ export default defineVxeComponent({
3531
3893
  if (menuConfig && !VxeUIContextMenu) {
3532
3894
  errLog('vxe.error.reqComp', ['vxe-context-menu'])
3533
3895
  }
3534
- if (props.autoResize) {
3896
+ if (useScrollbar || autoResize) {
3535
3897
  const el = refElem.value
3898
+ const viewInnerEl = refVirtualBody.value
3536
3899
  const parentEl = getParentElem()
3537
3900
  const resizeObserver = globalResize.create(() => {
3538
- if (props.autoResize) {
3539
- recalculate()
3540
- }
3901
+ reFlag.value++
3541
3902
  })
3542
3903
  if (el) {
3543
3904
  resizeObserver.observe(el)
3905
+ if (autoResize) {
3906
+ if (parentEl) {
3907
+ resizeObserver.observe(parentEl)
3908
+ }
3909
+ }
3544
3910
  }
3545
- if (parentEl) {
3546
- resizeObserver.observe(parentEl)
3911
+ if (viewInnerEl) {
3912
+ resizeObserver.observe(viewInnerEl)
3547
3913
  }
3548
3914
  internalData.resizeObserver = resizeObserver
3549
3915
  }
3550
3916
 
3551
- recalculate()
3552
- globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent)
3917
+ reFlag.value++
3918
+ globalEvents.on($xeTree, 'resize', () => {
3919
+ reFlag.value++
3920
+ })
3553
3921
  })
3554
3922
 
3555
3923
  onBeforeUnmount(() => {
@@ -72,3 +72,7 @@ export function enModelValue (nodeid: string | number | null | undefined) {
72
72
  export function deModelValue (nodeid: string | number | null) {
73
73
  return nodeid ? decodeURIComponent(`${nodeid}`) : nodeid
74
74
  }
75
+
76
+ export function getDefaultConfig <T = any, D = any> (val1: T, def1: D): (T | D) {
77
+ return XEUtils.eqNull(val1) ? def1 : val1
78
+ }