vxe-pc-ui 4.19.8 → 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 (100) hide show
  1. package/dist/all.esm.js +878 -115
  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 +364 -21
  10. package/es/list/style.css +43 -0
  11. package/es/list/style.min.css +1 -1
  12. package/es/scrollbar/src/scrollbar.js +59 -17
  13. package/es/scrollbar/style.css +1 -0
  14. package/es/style.css +1 -1
  15. package/es/style.min.css +1 -1
  16. package/es/tabs/src/tabs.js +19 -4
  17. package/es/tree/src/tree.js +393 -55
  18. package/es/tree/style.css +43 -0
  19. package/es/tree/style.min.css +1 -1
  20. package/es/ui/index.js +1 -1
  21. package/es/ui/src/log.js +1 -1
  22. package/es/ui/src/utils.js +12 -0
  23. package/es/vxe-list/style.css +43 -0
  24. package/es/vxe-list/style.min.css +1 -1
  25. package/es/vxe-scrollbar/style.css +1 -0
  26. package/es/vxe-tree/style.css +43 -0
  27. package/es/vxe-tree/style.min.css +1 -1
  28. package/lib/card/src/card.js +17 -3
  29. package/lib/card/src/card.min.js +1 -1
  30. package/lib/icon/style/style.css +1 -1
  31. package/lib/icon/style/style.min.css +1 -1
  32. package/lib/index.umd.js +914 -126
  33. package/lib/index.umd.min.js +1 -1
  34. package/lib/language/fr-FR.js +29 -29
  35. package/lib/language/fr-FR.min.js +1 -1
  36. package/lib/language/fr-FR.umd.js +29 -29
  37. package/lib/layout-aside/src/layout-aside.js +7 -7
  38. package/lib/layout-aside/src/layout-aside.min.js +1 -1
  39. package/lib/layout-body/src/layout-body.js +27 -21
  40. package/lib/layout-body/src/layout-body.min.js +1 -1
  41. package/lib/list/src/list.js +368 -21
  42. package/lib/list/src/list.min.js +1 -1
  43. package/lib/list/style/style.css +43 -0
  44. package/lib/list/style/style.min.css +1 -1
  45. package/lib/scrollbar/src/scrollbar.js +67 -15
  46. package/lib/scrollbar/src/scrollbar.min.js +1 -1
  47. package/lib/scrollbar/style/style.css +1 -0
  48. package/lib/style.css +1 -1
  49. package/lib/style.min.css +1 -1
  50. package/lib/tabs/src/tabs.js +22 -10
  51. package/lib/tabs/src/tabs.min.js +1 -1
  52. package/lib/tree/src/tree.js +397 -53
  53. package/lib/tree/src/tree.min.js +1 -1
  54. package/lib/tree/style/style.css +43 -0
  55. package/lib/tree/style/style.min.css +1 -1
  56. package/lib/ui/index.js +1 -1
  57. package/lib/ui/index.min.js +1 -1
  58. package/lib/ui/src/log.js +1 -1
  59. package/lib/ui/src/log.min.js +1 -1
  60. package/lib/ui/src/utils.js +14 -0
  61. package/lib/ui/src/utils.min.js +1 -1
  62. package/lib/vxe-list/style/style.css +43 -0
  63. package/lib/vxe-list/style/style.min.css +1 -1
  64. package/lib/vxe-scrollbar/style/style.css +1 -0
  65. package/lib/vxe-tree/style/style.css +43 -0
  66. package/lib/vxe-tree/style/style.min.css +1 -1
  67. package/package.json +1 -1
  68. package/packages/card/src/card.ts +18 -3
  69. package/packages/language/fr-FR.ts +903 -903
  70. package/packages/layout-aside/src/layout-aside.ts +8 -5
  71. package/packages/layout-body/src/layout-body.ts +23 -14
  72. package/packages/list/src/list.ts +397 -24
  73. package/packages/scrollbar/src/scrollbar.ts +63 -16
  74. package/packages/tabs/src/tabs.ts +19 -5
  75. package/packages/tree/src/tree.ts +432 -64
  76. package/packages/ui/src/utils.ts +14 -0
  77. package/styles/components/list.scss +76 -0
  78. package/styles/components/scrollbar.scss +3 -0
  79. package/styles/components/tree.scss +76 -0
  80. package/types/components/card.d.ts +10 -1
  81. package/types/components/layout-aside.d.ts +10 -1
  82. package/types/components/layout-body.d.ts +10 -1
  83. package/types/components/list.d.ts +33 -2
  84. package/types/components/scrollbar.d.ts +17 -2
  85. package/types/components/table-plugins/extend-cell-area.d.ts +1 -1
  86. package/types/components/table.d.ts +71 -4
  87. package/types/components/tabs.d.ts +10 -1
  88. package/types/components/tree.d.ts +33 -2
  89. /package/es/icon/{iconfont.1791862962954.ttf → iconfont.1791950625324.ttf} +0 -0
  90. /package/es/icon/{iconfont.1791862962954.woff → iconfont.1791950625324.woff} +0 -0
  91. /package/es/icon/{iconfont.1791862962954.woff2 → iconfont.1791950625324.woff2} +0 -0
  92. /package/es/{iconfont.1791862962954.ttf → iconfont.1791950625324.ttf} +0 -0
  93. /package/es/{iconfont.1791862962954.woff → iconfont.1791950625324.woff} +0 -0
  94. /package/es/{iconfont.1791862962954.woff2 → iconfont.1791950625324.woff2} +0 -0
  95. /package/lib/icon/style/{iconfont.1791862962954.ttf → iconfont.1791950625324.ttf} +0 -0
  96. /package/lib/icon/style/{iconfont.1791862962954.woff → iconfont.1791950625324.woff} +0 -0
  97. /package/lib/icon/style/{iconfont.1791862962954.woff2 → iconfont.1791950625324.woff2} +0 -0
  98. /package/lib/{iconfont.1791862962954.ttf → iconfont.1791950625324.ttf} +0 -0
  99. /package/lib/{iconfont.1791862962954.woff → iconfont.1791950625324.woff} +0 -0
  100. /package/lib/{iconfont.1791862962954.woff2 → iconfont.1791950625324.woff2} +0 -0
@@ -151,6 +151,22 @@ export default defineVxeComponent({
151
151
  const computeScrollbarOpts = computed(() => {
152
152
  return Object.assign({}, getConfig().tabs.scrollbarConfig, props.scrollbarConfig);
153
153
  });
154
+ const computeScrollbarProps = computed(() => {
155
+ const scrollbarOpts = computeScrollbarOpts.value;
156
+ const { viewClassName, viewInnerClassName } = scrollbarOpts;
157
+ return {
158
+ width: scrollbarOpts.width,
159
+ height: scrollbarOpts.height,
160
+ autoHide: scrollbarOpts.autoHide,
161
+ visible: scrollbarOpts.visible,
162
+ xConfig: scrollbarOpts.xConfig,
163
+ yConfig: scrollbarOpts.yConfig,
164
+ className: scrollbarOpts.className,
165
+ viewAttrs: scrollbarOpts.viewAttrs,
166
+ viewClassName: 'vxe-tabs-pane--scrollbar-item-view' + (viewClassName ? (' ' + viewClassName) : ''),
167
+ viewInnerClassName: 'vxe-tabs-pane--scrollbar-item-inner' + (viewClassName ? (' ' + viewInnerClassName) : '')
168
+ };
169
+ });
154
170
  const computeMaps = {};
155
171
  const $xeTabs = {
156
172
  xID,
@@ -730,13 +746,12 @@ export default defineVxeComponent({
730
746
  const { initNames, activeName } = reactData;
731
747
  const { name, slots } = item;
732
748
  const defaultSlot = slots ? slots.default : null;
733
- const scrollbarOpts = computeScrollbarOpts.value;
734
- const { viewClassName, viewInnerClassName } = scrollbarOpts;
749
+ const scrollbarProps = computeScrollbarProps.value;
735
750
  if (name && initNames.includes(name)) {
736
751
  return useScrollbar
737
- ? h(VxeScrollbarComponent, Object.assign(Object.assign({ key: `${name}`, class: ['vxe-tabs-pane--scrollbar-item', {
752
+ ? h(VxeScrollbarComponent, Object.assign({ key: `${name}`, class: ['vxe-tabs-pane--scrollbar-item', {
738
753
  'is--visible': activeName === name
739
- }] }, scrollbarOpts), { viewClassName: 'vxe-tabs-pane--scrollbar-item-view' + (viewClassName ? (' ' + viewClassName) : ''), viewInnerClassName: 'vxe-tabs-pane--scrollbar-item-inner' + (viewClassName ? (' ' + viewInnerClassName) : '') }), {
754
+ }] }, scrollbarProps), {
740
755
  default: () => defaultSlot ? callSlot(defaultSlot, { name }) : []
741
756
  })
742
757
  : h('div', {
@@ -1,14 +1,15 @@
1
1
  import { ref, h, reactive, computed, 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
  const { warnLog, errLog } = createComponentLog('tree');
@@ -19,6 +20,34 @@ const { menus, getConfig, getI18n, getIcon } = VxeUI;
19
20
  function getNodeUniqueId() {
20
21
  return XEUtils.uniqueId('node_');
21
22
  }
23
+ function createReactData() {
24
+ return {
25
+ parentHeight: 0,
26
+ customHeight: 0,
27
+ customMinHeight: 0,
28
+ customMaxHeight: 0,
29
+ currentNode: null,
30
+ scrollYLoad: false,
31
+ bodyHeight: 0,
32
+ topSpaceHeight: 0,
33
+ selectRadioKey: null,
34
+ treeList: [],
35
+ updateExpandedFlag: 1,
36
+ updateCheckboxFlag: 1,
37
+ // 滚动条
38
+ yThumbHeight: 0,
39
+ xThumbWidth: 0,
40
+ insertNodeFlag: 1,
41
+ removeNodeFlag: 1,
42
+ dragNode: null,
43
+ dragTipText: '',
44
+ isCrossDragNode: false,
45
+ tooltipStore: {
46
+ visible: false,
47
+ node: null
48
+ }
49
+ };
50
+ }
22
51
  function createInternalData() {
23
52
  return {
24
53
  // initialized: false,
@@ -31,8 +60,14 @@ function createInternalData() {
31
60
  indeterminateNodeMaps: {},
32
61
  treeExpandedMaps: {},
33
62
  treeExpandLazyLoadedMaps: {},
34
- lastScrollLeft: 0,
63
+ // 滚动条
64
+ // resizeObserver: undefined,
65
+ // isThumbDrag: false,
66
+ thumbDragOffset: 0,
67
+ yThumbTop: 0,
68
+ xThumbLeft: 0,
35
69
  lastScrollTop: 0,
70
+ lastScrollLeft: 0,
36
71
  scrollYStore: {
37
72
  startIndex: 0,
38
73
  endIndex: 0,
@@ -49,31 +84,6 @@ function createInternalData() {
49
84
  // hpTimeout: undefined
50
85
  };
51
86
  }
52
- function createReactData() {
53
- return {
54
- parentHeight: 0,
55
- customHeight: 0,
56
- customMinHeight: 0,
57
- customMaxHeight: 0,
58
- currentNode: null,
59
- scrollYLoad: false,
60
- bodyHeight: 0,
61
- topSpaceHeight: 0,
62
- selectRadioKey: null,
63
- treeList: [],
64
- updateExpandedFlag: 1,
65
- updateCheckboxFlag: 1,
66
- insertNodeFlag: 1,
67
- removeNodeFlag: 1,
68
- dragNode: null,
69
- dragTipText: '',
70
- isCrossDragNode: false,
71
- tooltipStore: {
72
- visible: false,
73
- node: null
74
- }
75
- };
76
- }
77
87
  let crossTreeDragNodeObj = null;
78
88
  export default defineVxeComponent({
79
89
  name: 'VxeTree',
@@ -204,7 +214,12 @@ export default defineVxeComponent({
204
214
  type: String,
205
215
  default: () => getConfig().tree.size || getConfig().size
206
216
  },
207
- virtualYConfig: Object
217
+ virtualYConfig: Object,
218
+ useScrollbar: {
219
+ type: Boolean,
220
+ default: () => getConfig().tree.useScrollbar
221
+ },
222
+ scrollbarConfig: Object
208
223
  },
209
224
  emits: [
210
225
  'update:modelValue',
@@ -236,6 +251,10 @@ export default defineVxeComponent({
236
251
  const refFooterWrapperElem = ref();
237
252
  const refVirtualWrapper = ref();
238
253
  const refVirtualBody = ref();
254
+ const refTrackXElem = ref();
255
+ const refTrackYElem = ref();
256
+ const refThumbXElem = ref();
257
+ const refThumbYElem = ref();
239
258
  const refDragNodeLineElem = ref();
240
259
  const refDragTipElem = ref();
241
260
  const refTooltip = ref();
@@ -307,6 +326,19 @@ export default defineVxeComponent({
307
326
  const computeMenuOpts = computed(() => {
308
327
  return Object.assign({}, getConfig().tree.menuConfig, props.menuConfig);
309
328
  });
329
+ const computeWrapperStyles = computed(() => {
330
+ const scrollbarOpts = computeScrollbarOpts.value;
331
+ const scrollbarXOpts = computeScrollbarXOpts.value;
332
+ const scrollbarYOpts = computeScrollbarYOpts.value;
333
+ const barWidth = getDefaultConfig(getDefaultConfig(scrollbarYOpts.width, scrollbarOpts.width), getConfig().scrollbar.width);
334
+ const barHeight = getDefaultConfig(getDefaultConfig(scrollbarXOpts.height, scrollbarOpts.height), getConfig().scrollbar.height);
335
+ const stys = {};
336
+ if (barWidth || barHeight) {
337
+ stys['--vxe-ui-scrollbar-y-width'] = toCssUnit(barWidth || barHeight);
338
+ stys['--vxe-ui-scrollbar-x-height'] = toCssUnit(barHeight || barWidth);
339
+ }
340
+ return stys;
341
+ });
310
342
  const computeTreeStyle = computed(() => {
311
343
  const { indent } = props;
312
344
  const { customHeight, customMinHeight, customMaxHeight } = reactData;
@@ -339,6 +371,71 @@ export default defineVxeComponent({
339
371
  const computeFilterOpts = computed(() => {
340
372
  return Object.assign({}, getConfig().tree.filterConfig, props.filterConfig);
341
373
  });
374
+ const computeScrollbarOpts = computed(() => {
375
+ return Object.assign({}, getConfig().tree.scrollbarConfig, props.scrollbarConfig);
376
+ });
377
+ const computeScrollbarXOpts = computed(() => {
378
+ const scrollbarOpts = computeScrollbarOpts.value;
379
+ return Object.assign({}, getConfig().scrollbar.xConfig, scrollbarOpts.xConfig, {
380
+ visible: false
381
+ });
382
+ });
383
+ const computeScrollbarYOpts = computed(() => {
384
+ const scrollbarOpts = computeScrollbarOpts.value;
385
+ return Object.assign({}, getConfig().scrollbar.yConfig, scrollbarOpts.yConfig);
386
+ });
387
+ const computeScrollXVisible = computed(() => {
388
+ const scrollbarOpts = computeScrollbarOpts.value;
389
+ const scrollbarXOpts = computeScrollbarXOpts.value;
390
+ return getDefaultConfig(scrollbarXOpts.visible, scrollbarOpts.visible);
391
+ });
392
+ const computeScrollYVisible = computed(() => {
393
+ const scrollbarOpts = computeScrollbarOpts.value;
394
+ const scrollbarYOpts = computeScrollbarYOpts.value;
395
+ return getDefaultConfig(scrollbarYOpts.visible, scrollbarOpts.visible);
396
+ });
397
+ const computeScrollXAutoHide = computed(() => {
398
+ const scrollbarOpts = computeScrollbarOpts.value;
399
+ const scrollbarXOpts = computeScrollbarXOpts.value;
400
+ return getDefaultConfig(getDefaultConfig(scrollbarXOpts.autoHide, scrollbarOpts.autoHide), getConfig().scrollbar.autoHide);
401
+ });
402
+ const computeScrollYAutoHide = computed(() => {
403
+ const scrollbarOpts = computeScrollbarOpts.value;
404
+ const scrollbarYOpts = computeScrollbarYOpts.value;
405
+ return getDefaultConfig(getDefaultConfig(scrollbarYOpts.autoHide, scrollbarOpts.autoHide), getConfig().scrollbar.autoHide);
406
+ });
407
+ const computeScrollbarWrapperClss = computed(() => {
408
+ const scrollbarOpts = computeScrollbarOpts.value;
409
+ const { padding } = scrollbarOpts;
410
+ const { yThumbHeight, xThumbWidth } = reactData;
411
+ const scrollbarXToTop = computeScrollbarXToTop.value;
412
+ const scrollbarYToLeft = computeScrollbarYToLeft.value;
413
+ const scrollXVisible = computeScrollXVisible.value;
414
+ const scrollYVisible = computeScrollYVisible.value;
415
+ const scrollXAutoHide = computeScrollXAutoHide.value;
416
+ const scrollYAutoHide = computeScrollYAutoHide.value;
417
+ return domUtils.buildClass([
418
+ 'vxe-scrollbar is--virtual',
419
+ `ov-x--${scrollXVisible === false ? 'hidden' : 'visible'}`,
420
+ `ov-y--${scrollYVisible === false ? 'hidden' : 'visible'}`,
421
+ `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}`,
422
+ `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}`
423
+ ], {
424
+ 'is--padding': padding,
425
+ 'ov-x--auto-hide': scrollXAutoHide,
426
+ 'ov-y--auto-hide': scrollYAutoHide,
427
+ 'overflow-y': yThumbHeight,
428
+ 'overflow-x': xThumbWidth
429
+ });
430
+ });
431
+ const computeScrollbarXToTop = computed(() => {
432
+ const scrollbarXOpts = computeScrollbarXOpts.value;
433
+ return scrollbarXOpts.position === 'top';
434
+ });
435
+ const computeScrollbarYToLeft = computed(() => {
436
+ const scrollbarYOpts = computeScrollbarYOpts.value;
437
+ return scrollbarYOpts.position === 'left';
438
+ });
342
439
  const computeMaps = {
343
440
  computeKeyField,
344
441
  computeParentField,
@@ -856,6 +953,10 @@ export default defineVxeComponent({
856
953
  }
857
954
  });
858
955
  };
956
+ const updateScrollbar = () => {
957
+ updateThumbSize();
958
+ updateThumbOffset();
959
+ };
859
960
  /**
860
961
  * 重新计算列表
861
962
  */
@@ -877,6 +978,7 @@ export default defineVxeComponent({
877
978
  const parentPaddingSize = getPaddingTopBottomSize(parentEl);
878
979
  reactData.parentHeight = Math.max(headHeight + footHeight + rowHeight, parentEl.clientHeight - parentPaddingSize - headHeight - footHeight);
879
980
  }
981
+ updateScrollbar();
880
982
  updateHeight();
881
983
  return computeScrollLoad().then(() => {
882
984
  updateHeight();
@@ -910,6 +1012,7 @@ export default defineVxeComponent({
910
1012
  const scrollLeft = scrollBodyElem.scrollLeft;
911
1013
  const isX = scrollLeft !== internalData.lastScrollLeft;
912
1014
  const isY = scrollTop !== internalData.lastScrollTop;
1015
+ updateThumbOffset();
913
1016
  internalData.lastScrollTop = scrollTop;
914
1017
  internalData.lastScrollLeft = scrollLeft;
915
1018
  if (reactData.scrollYLoad) {
@@ -1457,13 +1560,6 @@ export default defineVxeComponent({
1457
1560
  emitRadioMode(value);
1458
1561
  dispatchEvent('radio-change', { node, value, checked: isChecked }, evnt);
1459
1562
  };
1460
- const handleGlobalResizeEvent = () => {
1461
- const el = refElem.value;
1462
- if (!el || !el.clientWidth) {
1463
- return;
1464
- }
1465
- recalculate();
1466
- };
1467
1563
  const insertTreeNode = (newRecords, isAppend) => {
1468
1564
  const { treeFullData, nodeMaps } = internalData;
1469
1565
  const keyField = computeKeyField.value;
@@ -2899,6 +2995,162 @@ export default defineVxeComponent({
2899
2995
  hideDropTip();
2900
2996
  }
2901
2997
  };
2998
+ const updateThumbSize = () => {
2999
+ const viewEl = refVirtualWrapper.value;
3000
+ if (!viewEl) {
3001
+ return;
3002
+ }
3003
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
3004
+ return;
3005
+ }
3006
+ const trackXEl = refTrackXElem.value;
3007
+ const xThumbWidth = trackXEl ? getThumbSize(viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth) : 0;
3008
+ const thumbXElem = refThumbXElem.value;
3009
+ if (thumbXElem) {
3010
+ thumbXElem.style.width = xThumbWidth + 'px';
3011
+ }
3012
+ reactData.xThumbWidth = xThumbWidth;
3013
+ const trackYEl = refTrackYElem.value;
3014
+ const yThumbHeight = trackYEl ? getThumbSize(viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight) : 0;
3015
+ const thumbYElem = refThumbYElem.value;
3016
+ if (thumbYElem) {
3017
+ thumbYElem.style.height = yThumbHeight + 'px';
3018
+ }
3019
+ reactData.yThumbHeight = yThumbHeight;
3020
+ };
3021
+ const updateThumbOffset = () => {
3022
+ const viewEl = refVirtualWrapper.value;
3023
+ if (!viewEl) {
3024
+ return;
3025
+ }
3026
+ if (!viewEl.clientHeight || !viewEl.clientHeight) {
3027
+ return;
3028
+ }
3029
+ const { xThumbWidth, yThumbHeight } = reactData;
3030
+ const trackXEl = refTrackXElem.value;
3031
+ const thumbXElem = refThumbXElem.value;
3032
+ const xThumbLeft = trackXEl && xThumbWidth ? getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth, xThumbWidth) : 0;
3033
+ internalData.xThumbLeft = xThumbLeft;
3034
+ if (thumbXElem && xThumbWidth) {
3035
+ thumbXElem.style.width = xThumbWidth + 'px';
3036
+ thumbXElem.style.transform = `translateX(${xThumbLeft}px)`;
3037
+ }
3038
+ const trackYEl = refTrackYElem.value;
3039
+ const thumbYElem = refThumbYElem.value;
3040
+ const yThumbTop = trackYEl && yThumbHeight ? getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight, yThumbHeight) : 0;
3041
+ internalData.yThumbTop = yThumbTop;
3042
+ if (thumbYElem && yThumbHeight) {
3043
+ thumbYElem.style.height = yThumbHeight + 'px';
3044
+ thumbYElem.style.transform = `translateY(${yThumbTop}px)`;
3045
+ }
3046
+ };
3047
+ const clickTrackXEvent = (evnt) => {
3048
+ const trackEl = evnt.currentTarget;
3049
+ if (trackEl !== evnt.target) {
3050
+ return;
3051
+ }
3052
+ const viewEl = refVirtualWrapper.value;
3053
+ if (!viewEl) {
3054
+ return;
3055
+ }
3056
+ const { xThumbWidth } = reactData;
3057
+ const trackRect = trackEl.getBoundingClientRect();
3058
+ viewEl.scrollTo({
3059
+ left: getScrollFromClick(evnt.clientX - trackRect.left, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth),
3060
+ behavior: 'auto'
3061
+ });
3062
+ };
3063
+ const clickTrackYEvent = (evnt) => {
3064
+ const trackEl = evnt.currentTarget;
3065
+ if (trackEl !== evnt.target) {
3066
+ return;
3067
+ }
3068
+ const viewEl = refVirtualWrapper.value;
3069
+ if (!viewEl) {
3070
+ return;
3071
+ }
3072
+ const { yThumbHeight } = reactData;
3073
+ const trackRect = trackEl.getBoundingClientRect();
3074
+ viewEl.scrollTo({
3075
+ top: getScrollFromClick(evnt.clientY - trackRect.top, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight),
3076
+ behavior: 'auto'
3077
+ });
3078
+ };
3079
+ const pointerdownThumbXEvent = (evnt) => {
3080
+ const thumbEl = evnt.currentTarget;
3081
+ internalData.isThumbDrag = true;
3082
+ thumbEl.setPointerCapture(evnt.pointerId);
3083
+ const viewEl = refVirtualWrapper.value;
3084
+ if (!viewEl) {
3085
+ return;
3086
+ }
3087
+ const { xThumbWidth } = reactData;
3088
+ const trackEl = thumbEl.parentElement;
3089
+ const trackRect = trackEl.getBoundingClientRect();
3090
+ const pointerPosition = evnt.clientX - trackRect.left;
3091
+ // 记录 thumb 的偏移
3092
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth);
3093
+ internalData.thumbDragOffset = pointerPosition - thumbOffset;
3094
+ };
3095
+ const pointermoveThumbXEvent = (evnt) => {
3096
+ const thumbEl = evnt.currentTarget;
3097
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
3098
+ return;
3099
+ }
3100
+ const { isThumbDrag, thumbDragOffset } = internalData;
3101
+ if (isThumbDrag) {
3102
+ const viewEl = refVirtualWrapper.value;
3103
+ if (!viewEl) {
3104
+ return;
3105
+ }
3106
+ const { xThumbWidth } = reactData;
3107
+ const thumbEl = evnt.currentTarget;
3108
+ const trackEl = thumbEl.parentElement;
3109
+ const trackRect = trackEl.getBoundingClientRect();
3110
+ // 更新偏移
3111
+ viewEl.scrollLeft = getScrollFromDrag(evnt.clientX - trackRect.left, thumbDragOffset, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth);
3112
+ }
3113
+ };
3114
+ const cleatPointerThumbEvent = (evnt) => {
3115
+ const thumbEl = evnt.currentTarget;
3116
+ thumbEl.releasePointerCapture(evnt.pointerId);
3117
+ internalData.isThumbDrag = false;
3118
+ };
3119
+ const pointerdownThumbYEvent = (evnt) => {
3120
+ const thumbEl = evnt.currentTarget;
3121
+ internalData.isThumbDrag = true;
3122
+ thumbEl.setPointerCapture(evnt.pointerId);
3123
+ const viewEl = refVirtualWrapper.value;
3124
+ if (!viewEl) {
3125
+ return;
3126
+ }
3127
+ const { yThumbHeight } = reactData;
3128
+ const trackEl = thumbEl.parentElement;
3129
+ const trackRect = trackEl.getBoundingClientRect();
3130
+ const pointerPosition = evnt.clientY - trackRect.top;
3131
+ // 记录 thumb 的偏移
3132
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight);
3133
+ internalData.thumbDragOffset = pointerPosition - thumbOffset;
3134
+ };
3135
+ const pointermoveThumbYEvent = (evnt) => {
3136
+ const thumbEl = evnt.currentTarget;
3137
+ if (!thumbEl.hasPointerCapture(evnt.pointerId)) {
3138
+ return;
3139
+ }
3140
+ const { isThumbDrag, thumbDragOffset } = internalData;
3141
+ if (isThumbDrag) {
3142
+ const viewEl = refVirtualWrapper.value;
3143
+ if (!viewEl) {
3144
+ return;
3145
+ }
3146
+ const { yThumbHeight } = reactData;
3147
+ const thumbEl = evnt.currentTarget;
3148
+ const trackEl = thumbEl.parentElement;
3149
+ const trackRect = trackEl.getBoundingClientRect();
3150
+ // 更新偏移
3151
+ viewEl.scrollTop = getScrollFromDrag(evnt.clientY - trackRect.top, thumbDragOffset, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight);
3152
+ }
3153
+ };
2902
3154
  Object.assign($xeTree, treeMethods, treePrivateMethods);
2903
3155
  const renderDragIcon = (node, nodeid) => {
2904
3156
  const { drag, transform } = props;
@@ -3208,13 +3460,14 @@ export default defineVxeComponent({
3208
3460
  return renderEmptyElement($xeTree);
3209
3461
  };
3210
3462
  const renderVN = () => {
3211
- const { loading, trigger, showLine } = props;
3212
- const { bodyHeight, topSpaceHeight, treeList, tooltipStore } = reactData;
3463
+ const { loading, trigger, showLine, useScrollbar } = props;
3464
+ const { bodyHeight, topSpaceHeight, treeList, tooltipStore, xThumbWidth, yThumbHeight } = reactData;
3213
3465
  const vSize = computeSize.value;
3214
3466
  const radioOpts = computeRadioOpts.value;
3215
3467
  const checkboxOpts = computeCheckboxOpts.value;
3216
3468
  const loadingOpts = computeLoadingOpts.value;
3217
3469
  const isNodeHover = computeIsNodeHover.value;
3470
+ const wrapperStyles = computeWrapperStyles.value;
3218
3471
  const treeStyle = computeTreeStyle.value;
3219
3472
  const dragOpts = computeDragOpts.value;
3220
3473
  const tooltipOpts = computeTooltipOpts.value;
@@ -3222,19 +3475,40 @@ export default defineVxeComponent({
3222
3475
  const headerSlot = slots.header;
3223
3476
  const footerSlot = slots.footer;
3224
3477
  const tooltipSlot = slots.tooltip;
3478
+ const scrollbarOpts = computeScrollbarOpts.value;
3479
+ const scrollXVisible = computeScrollXVisible.value;
3480
+ const scrollYVisible = computeScrollYVisible.value;
3481
+ const scrollbarXToTop = computeScrollbarXToTop.value;
3482
+ const scrollbarYToLeft = computeScrollbarYToLeft.value;
3483
+ const scrollXAutoHide = computeScrollXAutoHide.value;
3484
+ const scrollYAutoHide = computeScrollYAutoHide.value;
3485
+ const scrollbarWrapperClss = computeScrollbarWrapperClss.value;
3225
3486
  const teOns = {};
3226
3487
  if (dragOpts.isCrossTreeDrag && !treeList.length) {
3227
3488
  teOns.onDragover = $xeTree.handleCrossTreeNodeDragoverEmptyEvent;
3228
3489
  }
3229
- return h('div', Object.assign({ ref: refElem, class: ['vxe-tree', {
3490
+ return h('div', Object.assign({ ref: refElem, class: [
3491
+ 'vxe-tree',
3492
+ useScrollbar ? `ov-x--${scrollXVisible === false ? 'hidden' : 'visible'}` : '',
3493
+ useScrollbar ? `ov-y--${scrollYVisible === false ? 'hidden' : 'visible'}` : '',
3494
+ useScrollbar ? `sx-pos--${scrollbarXToTop ? 'top' : 'bottom'}` : '',
3495
+ useScrollbar ? `sy-pos--${scrollbarYToLeft ? 'left' : 'right'}` : '',
3496
+ {
3230
3497
  [`size--${vSize}`]: vSize,
3231
3498
  'show--line': showLine,
3499
+ 'is--virtual-scrollbar': useScrollbar,
3500
+ 'ov-padding': useScrollbar && scrollbarOpts.padding,
3501
+ 'ov-x--auto-hide': useScrollbar && scrollXAutoHide,
3502
+ 'ov-y--auto-hide': useScrollbar && scrollYAutoHide,
3503
+ 'overflow-y': yThumbHeight,
3504
+ 'overflow-x': xThumbWidth,
3232
3505
  'checkbox--highlight': checkboxOpts.highlight,
3233
3506
  'radio--highlight': radioOpts.highlight,
3234
3507
  'node--hover': isNodeHover,
3235
3508
  'node--trigger': trigger === 'node',
3236
3509
  'is--loading': loading
3237
- }] }, teOns), [
3510
+ }
3511
+ ], style: wrapperStyles }, teOns), [
3238
3512
  headerSlot
3239
3513
  ? h('div', {
3240
3514
  ref: refHeaderWrapperElem,
@@ -3267,6 +3541,49 @@ export default defineVxeComponent({
3267
3541
  class: 'vxe-tree--footer-wrapper'
3268
3542
  }, footerSlot({ $tree: $xeTree }))
3269
3543
  : renderEmptyElement($xeTree),
3544
+ /**
3545
+ * 滚动条
3546
+ */
3547
+ useScrollbar
3548
+ ? h('div', {
3549
+ class: scrollbarWrapperClss
3550
+ }, [
3551
+ scrollXVisible === false
3552
+ ? renderEmptyElement($xeTree)
3553
+ : h('div', {
3554
+ ref: refTrackXElem,
3555
+ class: 'vxe-scrollbar--track-x',
3556
+ onClick: clickTrackXEvent
3557
+ }, [
3558
+ h('div', {
3559
+ ref: refThumbXElem,
3560
+ class: 'vxe-scrollbar--thumb-x',
3561
+ onPointerdown: pointerdownThumbXEvent,
3562
+ onPointermove: pointermoveThumbXEvent,
3563
+ onPointerup: cleatPointerThumbEvent,
3564
+ onPointercancel: cleatPointerThumbEvent,
3565
+ onLostpointercapture: cleatPointerThumbEvent
3566
+ })
3567
+ ]),
3568
+ scrollYVisible === false
3569
+ ? renderEmptyElement($xeTree)
3570
+ : h('div', {
3571
+ ref: refTrackYElem,
3572
+ class: 'vxe-scrollbar--track-y',
3573
+ onClick: clickTrackYEvent
3574
+ }, [
3575
+ h('div', {
3576
+ ref: refThumbYElem,
3577
+ class: 'vxe-scrollbar--thumb-y',
3578
+ onPointerdown: pointerdownThumbYEvent,
3579
+ onPointermove: pointermoveThumbYEvent,
3580
+ onPointerup: cleatPointerThumbEvent,
3581
+ onPointercancel: cleatPointerThumbEvent,
3582
+ onLostpointercapture: cleatPointerThumbEvent
3583
+ })
3584
+ ])
3585
+ ])
3586
+ : renderEmptyElement($xeTree),
3270
3587
  /**
3271
3588
  * 拖拽提示
3272
3589
  */
@@ -3350,21 +3667,36 @@ export default defineVxeComponent({
3350
3667
  watch(() => props.filterValue, () => {
3351
3668
  triggerSearchEvent(new Event('filter'));
3352
3669
  });
3353
- const hFlag = ref(0);
3670
+ const reFlag = ref(0);
3354
3671
  watch(() => props.height, () => {
3355
- hFlag.value++;
3672
+ reFlag.value++;
3356
3673
  });
3357
3674
  watch(() => props.minHeight, () => {
3358
- hFlag.value++;
3675
+ reFlag.value++;
3359
3676
  });
3360
3677
  watch(() => props.maxHeight, () => {
3361
- hFlag.value++;
3678
+ reFlag.value++;
3362
3679
  });
3363
- watch(hFlag, () => {
3364
- recalculate();
3680
+ watch(() => props.useScrollbar, () => {
3681
+ reFlag.value++;
3682
+ });
3683
+ watch(computeScrollXVisible, () => {
3684
+ nextTick(() => {
3685
+ reFlag.value++;
3686
+ });
3687
+ });
3688
+ watch(computeScrollYVisible, () => {
3689
+ nextTick(() => {
3690
+ reFlag.value++;
3691
+ });
3692
+ });
3693
+ watch(reFlag, () => {
3694
+ recalculate().then(() => {
3695
+ recalculate();
3696
+ });
3365
3697
  });
3366
3698
  onMounted(() => {
3367
- const { transform, drag, menuConfig, showOverflow, lazy, loadMethod } = props;
3699
+ const { transform, drag, menuConfig, showOverflow, lazy, loadMethod, autoResize, useScrollbar } = props;
3368
3700
  const dragOpts = computeDragOpts.value;
3369
3701
  if (!showOverflow) {
3370
3702
  errLog('vxe.error.errProp', ['show-overflow=false', 'show-overflow=true']);
@@ -3385,24 +3717,30 @@ export default defineVxeComponent({
3385
3717
  if (menuConfig && !VxeUIContextMenu) {
3386
3718
  errLog('vxe.error.reqComp', ['vxe-context-menu']);
3387
3719
  }
3388
- if (props.autoResize) {
3720
+ if (useScrollbar || autoResize) {
3389
3721
  const el = refElem.value;
3722
+ const viewInnerEl = refVirtualBody.value;
3390
3723
  const parentEl = getParentElem();
3391
3724
  const resizeObserver = globalResize.create(() => {
3392
- if (props.autoResize) {
3393
- recalculate();
3394
- }
3725
+ reFlag.value++;
3395
3726
  });
3396
3727
  if (el) {
3397
3728
  resizeObserver.observe(el);
3729
+ if (autoResize) {
3730
+ if (parentEl) {
3731
+ resizeObserver.observe(parentEl);
3732
+ }
3733
+ }
3398
3734
  }
3399
- if (parentEl) {
3400
- resizeObserver.observe(parentEl);
3735
+ if (viewInnerEl) {
3736
+ resizeObserver.observe(viewInnerEl);
3401
3737
  }
3402
3738
  internalData.resizeObserver = resizeObserver;
3403
3739
  }
3404
- recalculate();
3405
- globalEvents.on($xeTree, 'resize', handleGlobalResizeEvent);
3740
+ reFlag.value++;
3741
+ globalEvents.on($xeTree, 'resize', () => {
3742
+ reFlag.value++;
3743
+ });
3406
3744
  });
3407
3745
  onBeforeUnmount(() => {
3408
3746
  const { resizeObserver } = internalData;