vxe-pc-ui 3.18.21 → 3.18.23

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 (77) hide show
  1. package/es/components.js +3 -0
  2. package/es/icon/style.css +1 -1
  3. package/es/scrollbar/index.js +12 -0
  4. package/es/scrollbar/src/scrollbar.js +576 -0
  5. package/es/scrollbar/src/util.js +54 -0
  6. package/es/scrollbar/style.css +102 -0
  7. package/es/scrollbar/style.min.css +1 -0
  8. package/es/style.css +1 -1
  9. package/es/style.min.css +1 -1
  10. package/es/ui/index.js +10 -1
  11. package/es/ui/src/log.js +1 -1
  12. package/es/upload/style.css +5 -3
  13. package/es/upload/style.min.css +1 -1
  14. package/es/vxe-scrollbar/index.js +3 -0
  15. package/es/vxe-scrollbar/style.css +102 -0
  16. package/es/vxe-scrollbar/style.min.css +1 -0
  17. package/es/vxe-upload/style.css +5 -3
  18. package/es/vxe-upload/style.min.css +1 -1
  19. package/lib/components.js +13 -1
  20. package/lib/components.min.js +1 -1
  21. package/lib/icon/style/style.css +1 -1
  22. package/lib/icon/style/style.min.css +1 -1
  23. package/lib/index.umd.js +727 -7
  24. package/lib/index.umd.min.js +1 -1
  25. package/lib/scrollbar/index.js +19 -0
  26. package/lib/scrollbar/index.min.js +1 -0
  27. package/lib/scrollbar/src/scrollbar.js +584 -0
  28. package/lib/scrollbar/src/scrollbar.min.js +1 -0
  29. package/lib/scrollbar/src/util.js +63 -0
  30. package/lib/scrollbar/src/util.min.js +1 -0
  31. package/lib/scrollbar/style/index.js +1 -0
  32. package/lib/scrollbar/style/style.css +102 -0
  33. package/lib/scrollbar/style/style.min.css +1 -0
  34. package/lib/style.css +1 -1
  35. package/lib/style.min.css +1 -1
  36. package/lib/ui/index.js +10 -1
  37. package/lib/ui/index.min.js +1 -1
  38. package/lib/ui/src/log.js +1 -1
  39. package/lib/ui/src/log.min.js +1 -1
  40. package/lib/upload/style/style.css +5 -3
  41. package/lib/upload/style/style.min.css +1 -1
  42. package/lib/vxe-scrollbar/index.js +22 -0
  43. package/lib/vxe-scrollbar/index.min.js +1 -0
  44. package/lib/vxe-scrollbar/style/index.js +1 -0
  45. package/lib/vxe-scrollbar/style/style.css +102 -0
  46. package/lib/vxe-scrollbar/style/style.min.css +1 -0
  47. package/lib/vxe-upload/style/style.css +5 -3
  48. package/lib/vxe-upload/style/style.min.css +1 -1
  49. package/package.json +2 -2
  50. package/packages/components.ts +3 -0
  51. package/packages/scrollbar/index.ts +16 -0
  52. package/packages/scrollbar/src/scrollbar.ts +626 -0
  53. package/packages/scrollbar/src/util.ts +57 -0
  54. package/packages/ui/index.ts +9 -0
  55. package/styles/all.scss +1 -0
  56. package/styles/components/scrollbar.scss +114 -0
  57. package/styles/components/upload.scss +5 -3
  58. package/styles/theme/base.scss +5 -0
  59. package/styles/theme/dark.scss +5 -0
  60. package/styles/theme/light.scss +5 -0
  61. package/styles/variable.scss +5 -0
  62. package/types/all.d.ts +3 -0
  63. package/types/components/gantt.d.ts +3 -3
  64. package/types/components/scrollbar.d.ts +209 -0
  65. package/types/ui/global-config.d.ts +2 -0
  66. /package/es/icon/{iconfont.1790757609697.ttf → iconfont.1791517840480.ttf} +0 -0
  67. /package/es/icon/{iconfont.1790757609697.woff → iconfont.1791517840480.woff} +0 -0
  68. /package/es/icon/{iconfont.1790757609697.woff2 → iconfont.1791517840480.woff2} +0 -0
  69. /package/es/{iconfont.1790757609697.ttf → iconfont.1791517840480.ttf} +0 -0
  70. /package/es/{iconfont.1790757609697.woff → iconfont.1791517840480.woff} +0 -0
  71. /package/es/{iconfont.1790757609697.woff2 → iconfont.1791517840480.woff2} +0 -0
  72. /package/lib/icon/style/{iconfont.1790757609697.ttf → iconfont.1791517840480.ttf} +0 -0
  73. /package/lib/icon/style/{iconfont.1790757609697.woff → iconfont.1791517840480.woff} +0 -0
  74. /package/lib/icon/style/{iconfont.1790757609697.woff2 → iconfont.1791517840480.woff2} +0 -0
  75. /package/lib/{iconfont.1790757609697.ttf → iconfont.1791517840480.ttf} +0 -0
  76. /package/lib/{iconfont.1790757609697.woff → iconfont.1791517840480.woff} +0 -0
  77. /package/lib/{iconfont.1790757609697.woff2 → iconfont.1791517840480.woff2} +0 -0
@@ -0,0 +1,626 @@
1
+ import { CreateElement, VNode, PropType } from 'vue'
2
+ import { defineVxeComponent } from '../../ui/src/comp'
3
+ import XEUtils from 'xe-utils'
4
+ import { VxeUI } from '../../ui'
5
+ import { toCssUnit } from '../../ui/src/dom'
6
+ import { getThumbOffsetSize, getThumbSize, getScrollFromClick, getScrollFromDrag } from './util'
7
+ import VxeLoadingComponent from '../../loading'
8
+
9
+ import type { ScrollbarReactData, ScrollbarInternalData, VxeScrollbarEmits, ValueOf, VxeScrollbarPropTypes, VxeComponentStyleType } from '../../../types'
10
+
11
+ const { getConfig, createEvent, domUtils, globalResize, renderEmptyElement } = VxeUI
12
+
13
+ function createReactData (): ScrollbarReactData {
14
+ return {
15
+ yThumbHeight: 0,
16
+ xThumbWidth: 0
17
+ }
18
+ }
19
+
20
+ function createInternalData (): ScrollbarInternalData {
21
+ return {
22
+ // resizeObserver: undefined,
23
+ // isThumbDrag: false,
24
+ thumbDragOffset: 0,
25
+ yThumbTop: 0,
26
+ xThumbLeft: 0,
27
+ lastScrollTop: 0,
28
+ lastScrollLeft: 0
29
+ }
30
+ }
31
+
32
+ export default /* define-vxe-component start */ defineVxeComponent({
33
+ name: 'VxeScrollbar',
34
+ props: {
35
+ width: [String, Number] as PropType<VxeScrollbarPropTypes.Width>,
36
+ height: [String, Number] as PropType<VxeScrollbarPropTypes.Height>,
37
+ minWidth: [String, Number] as PropType<VxeScrollbarPropTypes.MinWidth>,
38
+ minHeight: [String, Number] as PropType<VxeScrollbarPropTypes.MinHeight>,
39
+ maxWidth: [String, Number] as PropType<VxeScrollbarPropTypes.MaxWidth>,
40
+ maxHeight: [String, Number] as PropType<VxeScrollbarPropTypes.MaxHeight>,
41
+ loading: Boolean as PropType<VxeScrollbarPropTypes.Loading>,
42
+ native: {
43
+ type: Boolean as PropType<VxeScrollbarPropTypes.Native>,
44
+ default: () => getConfig().scrollbar.native
45
+ },
46
+ xConfig: Object as PropType<VxeScrollbarPropTypes.XConfig>,
47
+ yConfig: Object as PropType<VxeScrollbarPropTypes.YConfig>,
48
+ className: String as PropType<VxeScrollbarPropTypes.ClassName>,
49
+ viewClassName: String as PropType<VxeScrollbarPropTypes.ViewClassName>,
50
+ autoResize: {
51
+ type: Boolean as PropType<VxeScrollbarPropTypes.AutoResize>,
52
+ default: () => getConfig().scrollbar.autoResize
53
+ },
54
+ syncResize: [Boolean, String, Number] as PropType<VxeScrollbarPropTypes.SyncResize>
55
+ },
56
+ data () {
57
+ const xID = XEUtils.uniqueId()
58
+ const reactData = createReactData()
59
+
60
+ return {
61
+ ...({} as {
62
+ internalData: ScrollbarInternalData
63
+ }),
64
+ xID,
65
+ reactData,
66
+
67
+ reFlag: 0
68
+ }
69
+ },
70
+ computed: {
71
+ computeWrapperStyle () {
72
+ const $xeScrollbar = this
73
+ const props = $xeScrollbar
74
+
75
+ const { width, height, minWidth, minHeight, maxWidth, maxHeight } = props
76
+ const xOpts = $xeScrollbar.computeXOpts
77
+ const yOpts = $xeScrollbar.computeYOpts
78
+ const stys: VxeComponentStyleType = {}
79
+ if (width) {
80
+ stys.width = toCssUnit(width)
81
+ }
82
+ if (height) {
83
+ stys.height = toCssUnit(height)
84
+ }
85
+ if (minWidth) {
86
+ stys.minWidth = toCssUnit(minWidth)
87
+ }
88
+ if (minHeight) {
89
+ stys.minHeight = toCssUnit(minHeight)
90
+ }
91
+ if (maxWidth) {
92
+ stys.maxWidth = toCssUnit(maxWidth)
93
+ }
94
+ if (maxHeight) {
95
+ stys.maxHeight = toCssUnit(maxHeight)
96
+ }
97
+ if (yOpts.width) {
98
+ stys['--vxe-ui-scrollbar-y-width'] = toCssUnit(yOpts.width)
99
+ }
100
+ if (xOpts.height) {
101
+ stys['--vxe-ui-scrollbar-x-height'] = toCssUnit(xOpts.height)
102
+ }
103
+ return stys
104
+ },
105
+ computeWrapperClss () {
106
+ const $xeScrollbar = this
107
+ const props = $xeScrollbar
108
+
109
+ const { native, className } = props
110
+ const xOpts = ($xeScrollbar as any).computeXOpts as VxeScrollbarPropTypes.XConfig
111
+ const yOpts = ($xeScrollbar as any).computeYOpts as VxeScrollbarPropTypes.YConfig
112
+ return domUtils.buildClass([
113
+ 'vxe-scrollbar',
114
+ `ov-x--${xOpts.visible || 'visible'}`,
115
+ `ov-y--${yOpts.visible || 'visible'}`,
116
+ native ? 'is--native' : 'is--virtual',
117
+ className
118
+ ], {
119
+ 'ov-x--auto-hide': xOpts.autoHide,
120
+ 'ov-y--auto-hide': yOpts.autoHide
121
+ })
122
+ },
123
+ computeViewClss () {
124
+ const $xeScrollbar = this
125
+ const props = $xeScrollbar
126
+
127
+ const { viewClassName } = props
128
+ return domUtils.buildClass([
129
+ 'vxe-scrollbar--view',
130
+ viewClassName
131
+ ])
132
+ },
133
+ computeXOpts () {
134
+ const $xeScrollbar = this
135
+ const props = $xeScrollbar
136
+
137
+ return Object.assign({}, getConfig().scrollbar.xConfig, props.xConfig)
138
+ },
139
+ computeYOpts () {
140
+ const $xeScrollbar = this
141
+ const props = $xeScrollbar
142
+
143
+ return Object.assign({}, getConfig().scrollbar.yConfig, props.yConfig)
144
+ }
145
+ },
146
+ methods: {
147
+ //
148
+ // Method
149
+ //
150
+ dispatchEvent (type: ValueOf<VxeScrollbarEmits>, params: Record<string, any>, evnt: Event | null) {
151
+ const $xeScrollbar = this
152
+ $xeScrollbar.$emit(type, createEvent(evnt, { $scrollbar: $xeScrollbar }, params))
153
+ },
154
+ scrollTo (left: ScrollToOptions | number, top?: number) {
155
+ const $xeScrollbar = this
156
+
157
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
158
+ if (viewEl) {
159
+ if (XEUtils.isNumber(left)) {
160
+ viewEl.scrollTo(left, top || 0)
161
+ } else {
162
+ viewEl.scrollTo(left)
163
+ }
164
+ }
165
+ },
166
+ scrollIntoView () {
167
+ const $xeScrollbar = this
168
+
169
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
170
+ if (viewEl) {
171
+ viewEl.scrollIntoView()
172
+ }
173
+ },
174
+ recalculate () {
175
+ const $xeScrollbar = this
176
+
177
+ $xeScrollbar.updateThumbSize()
178
+ $xeScrollbar.updateThumbOffset()
179
+ return $xeScrollbar.$nextTick()
180
+ },
181
+ updateThumbSize () {
182
+ const $xeScrollbar = this
183
+ const reactData = $xeScrollbar.reactData
184
+
185
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
186
+ if (!viewEl) {
187
+ return
188
+ }
189
+ const trackXEl = $xeScrollbar.$refs.refTrackXElem as HTMLDivElement
190
+ const xThumbWidth = trackXEl ? getThumbSize(viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth) : 0
191
+ const thumbXElem = $xeScrollbar.$refs.refThumbXElem as HTMLDivElement
192
+ if (thumbXElem) {
193
+ thumbXElem.style.width = xThumbWidth + 'px'
194
+ }
195
+ reactData.xThumbWidth = xThumbWidth
196
+
197
+ const trackYEl = $xeScrollbar.$refs.refTrackYElem as HTMLDivElement
198
+ const yThumbHeight = trackYEl ? getThumbSize(viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight) : 0
199
+ const thumbYElem = $xeScrollbar.$refs.refThumbYElem as HTMLDivElement
200
+ if (thumbYElem) {
201
+ thumbYElem.style.height = yThumbHeight + 'px'
202
+ }
203
+ reactData.yThumbHeight = yThumbHeight
204
+ },
205
+ updateThumbOffset () {
206
+ const $xeScrollbar = this
207
+ const reactData = $xeScrollbar.reactData
208
+ const internalData = $xeScrollbar.internalData
209
+
210
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
211
+ if (!viewEl) {
212
+ return
213
+ }
214
+ const { xThumbWidth, yThumbHeight } = reactData
215
+ const trackXEl = $xeScrollbar.$refs.refTrackXElem as HTMLDivElement
216
+ const thumbXElem = $xeScrollbar.$refs.refThumbXElem as HTMLDivElement
217
+ const xThumbLeft = trackXEl && xThumbWidth ? getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackXEl.clientWidth, xThumbWidth) : 0
218
+ internalData.xThumbLeft = xThumbLeft
219
+ if (thumbXElem && xThumbWidth) {
220
+ thumbXElem.style.width = xThumbWidth + 'px'
221
+ thumbXElem.style.transform = `translateX(${xThumbLeft}px)`
222
+ }
223
+
224
+ const trackYEl = $xeScrollbar.$refs.refTrackYElem as HTMLDivElement
225
+ const thumbYElem = $xeScrollbar.$refs.refThumbYElem as HTMLDivElement
226
+ const yThumbTop = trackYEl && yThumbHeight ? getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackYEl.clientHeight, yThumbHeight) : 0
227
+ internalData.yThumbTop = yThumbTop
228
+ if (thumbYElem && yThumbHeight) {
229
+ thumbYElem.style.height = yThumbHeight + 'px'
230
+ thumbYElem.style.transform = `translateY(${yThumbTop}px)`
231
+ }
232
+ },
233
+ scrollEvent (evnt: Event) {
234
+ const $xeScrollbar = this
235
+ const reactData = $xeScrollbar.reactData
236
+ const internalData = $xeScrollbar.internalData
237
+
238
+ const { xThumbWidth, yThumbHeight } = reactData
239
+ const { lastScrollTop, lastScrollLeft } = internalData
240
+ const xOpts = $xeScrollbar.computeXOpts
241
+ const yOpts = $xeScrollbar.computeYOpts
242
+ const viewEl = evnt.currentTarget as HTMLDivElement
243
+ const { scrollTop, scrollLeft, clientWidth, clientHeight, scrollHeight, scrollWidth } = viewEl
244
+ let direction = ''
245
+ let isTopBoundary = false
246
+ let isBottomBoundary = false
247
+ let isLeftBoundary = false
248
+ let isRightBoundary = false
249
+ if (lastScrollTop !== scrollTop) {
250
+ const yThreshold = XEUtils.toNumber(yOpts.threshold) || 1
251
+ if (lastScrollTop < scrollTop) {
252
+ direction = 'bottom'
253
+ if (yThumbHeight > 0 && scrollTop + clientHeight >= scrollHeight - yThreshold) {
254
+ isBottomBoundary = true
255
+ }
256
+ } else {
257
+ direction = 'top'
258
+ if (yThumbHeight > 0 && scrollTop <= yThreshold) {
259
+ isTopBoundary = true
260
+ }
261
+ }
262
+ }
263
+ if (lastScrollLeft !== scrollLeft) {
264
+ const xThreshold = XEUtils.toNumber(xOpts.threshold) || 1
265
+ if (lastScrollLeft < scrollLeft) {
266
+ direction = 'right'
267
+ if (xThumbWidth > 0 && scrollLeft + clientWidth >= scrollWidth - xThreshold) {
268
+ isRightBoundary = true
269
+ }
270
+ } else {
271
+ direction = 'left'
272
+ if (xThumbWidth > 0 && scrollLeft <= xThreshold) {
273
+ isLeftBoundary = true
274
+ }
275
+ }
276
+ }
277
+ $xeScrollbar.updateThumbOffset()
278
+ internalData.lastScrollTop = scrollTop
279
+ internalData.lastScrollLeft = scrollLeft
280
+ if (isBottomBoundary || isTopBoundary || isRightBoundary || isLeftBoundary) {
281
+ $xeScrollbar.dispatchEvent('scroll-boundary', {
282
+ direction: direction,
283
+ isTop: isTopBoundary,
284
+ isBottom: isBottomBoundary,
285
+ isLeft: isLeftBoundary,
286
+ isRight: isRightBoundary,
287
+ scrollTop: scrollTop,
288
+ scrollLeft: scrollLeft,
289
+ clientWidth: clientWidth,
290
+ clientHeight: clientHeight,
291
+ scrollHeight: scrollHeight,
292
+ scrollWidth: scrollWidth
293
+ }, evnt)
294
+ }
295
+ $xeScrollbar.dispatchEvent('scroll', {
296
+ direction: direction,
297
+ isTop: yThumbHeight > 0 && scrollTop <= 0,
298
+ isBottom: yThumbHeight > 0 && scrollTop + clientHeight >= scrollHeight,
299
+ isLeft: xThumbWidth > 0 && scrollLeft <= 0,
300
+ isRight: xThumbWidth > 0 && scrollLeft + clientWidth >= scrollWidth,
301
+ scrollTop: scrollTop,
302
+ scrollLeft: scrollLeft,
303
+ clientWidth: clientWidth,
304
+ clientHeight: clientHeight,
305
+ scrollHeight: scrollHeight,
306
+ scrollWidth: scrollWidth
307
+ }, evnt)
308
+ },
309
+ clickTrackXEvent (evnt: MouseEvent) {
310
+ const $xeScrollbar = this
311
+ const reactData = $xeScrollbar.reactData
312
+
313
+ const trackEl = evnt.currentTarget as HTMLDivElement
314
+ if (trackEl !== evnt.target) {
315
+ return
316
+ }
317
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
318
+ if (!viewEl) {
319
+ return
320
+ }
321
+ const { xThumbWidth } = reactData
322
+ const trackRect = trackEl.getBoundingClientRect()
323
+ viewEl.scrollTo({
324
+ left: getScrollFromClick(evnt.clientX - trackRect.left, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth),
325
+ behavior: 'auto'
326
+ })
327
+ },
328
+ clickTrackYEvent (evnt: MouseEvent) {
329
+ const $xeScrollbar = this
330
+ const reactData = $xeScrollbar.reactData
331
+
332
+ const trackEl = evnt.currentTarget as HTMLDivElement
333
+ if (trackEl !== evnt.target) {
334
+ return
335
+ }
336
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
337
+ if (!viewEl) {
338
+ return
339
+ }
340
+ const { yThumbHeight } = reactData
341
+ const trackRect = trackEl.getBoundingClientRect()
342
+ viewEl.scrollTo({
343
+ top: getScrollFromClick(evnt.clientY - trackRect.top, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight),
344
+ behavior: 'auto'
345
+ })
346
+ },
347
+ pointerdownThumbXEvent (evnt: PointerEvent) {
348
+ const $xeScrollbar = this
349
+ const reactData = $xeScrollbar.reactData
350
+ const internalData = $xeScrollbar.internalData
351
+
352
+ const thumbEl = evnt.currentTarget as HTMLDivElement
353
+ internalData.isThumbDrag = true
354
+ thumbEl.setPointerCapture(evnt.pointerId)
355
+
356
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
357
+ if (!viewEl) {
358
+ return
359
+ }
360
+ const { xThumbWidth } = reactData
361
+ const trackEl = thumbEl.parentElement as HTMLDivElement
362
+ const trackRect = trackEl.getBoundingClientRect()
363
+ const pointerPosition = evnt.clientX - trackRect.left
364
+ // 记录 thumb 的偏移
365
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollLeft, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
366
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
367
+ },
368
+ pointermoveThumbXEvent (evnt: PointerEvent) {
369
+ const $xeScrollbar = this
370
+ const reactData = $xeScrollbar.reactData
371
+ const internalData = $xeScrollbar.internalData
372
+
373
+ const { isThumbDrag, thumbDragOffset } = internalData
374
+ if (isThumbDrag) {
375
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
376
+ if (!viewEl) {
377
+ return
378
+ }
379
+ const { xThumbWidth } = reactData
380
+ const thumbEl = evnt.currentTarget as HTMLDivElement
381
+ const trackEl = thumbEl.parentElement as HTMLDivElement
382
+ const trackRect = trackEl.getBoundingClientRect()
383
+ // 更新偏移
384
+ viewEl.scrollLeft = getScrollFromDrag(evnt.clientX - trackRect.left, thumbDragOffset, viewEl.clientWidth, viewEl.scrollWidth, trackEl.clientWidth, xThumbWidth)
385
+ }
386
+ },
387
+ cleatPointerThumbEvent (evnt: PointerEvent) {
388
+ const $xeScrollbar = this
389
+ const internalData = $xeScrollbar.internalData
390
+
391
+ const thumbEl = evnt.currentTarget as HTMLDivElement
392
+ thumbEl.releasePointerCapture(evnt.pointerId)
393
+ internalData.isThumbDrag = false
394
+ },
395
+ pointerdownThumbYEvent (evnt: PointerEvent) {
396
+ const $xeScrollbar = this
397
+ const reactData = $xeScrollbar.reactData
398
+ const internalData = $xeScrollbar.internalData
399
+
400
+ const thumbEl = evnt.currentTarget as HTMLDivElement
401
+ internalData.isThumbDrag = true
402
+ thumbEl.setPointerCapture(evnt.pointerId)
403
+
404
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
405
+ if (!viewEl) {
406
+ return
407
+ }
408
+ const { yThumbHeight } = reactData
409
+ const trackEl = thumbEl.parentElement as HTMLDivElement
410
+ const trackRect = trackEl.getBoundingClientRect()
411
+ const pointerPosition = evnt.clientY - trackRect.top
412
+ // 记录 thumb 的偏移
413
+ const thumbOffset = getThumbOffsetSize(viewEl.scrollTop, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
414
+ internalData.thumbDragOffset = pointerPosition - thumbOffset
415
+ },
416
+ pointermoveThumbYEvent (evnt: PointerEvent) {
417
+ const $xeScrollbar = this
418
+ const reactData = $xeScrollbar.reactData
419
+ const internalData = $xeScrollbar.internalData
420
+
421
+ const { isThumbDrag, thumbDragOffset } = internalData
422
+ if (isThumbDrag) {
423
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
424
+ if (!viewEl) {
425
+ return
426
+ }
427
+ const { yThumbHeight } = reactData
428
+ const thumbEl = evnt.currentTarget as HTMLDivElement
429
+ const trackEl = thumbEl.parentElement as HTMLDivElement
430
+ const trackRect = trackEl.getBoundingClientRect()
431
+ // 更新偏移
432
+ viewEl.scrollTop = getScrollFromDrag(evnt.clientY - trackRect.top, thumbDragOffset, viewEl.clientHeight, viewEl.scrollHeight, trackEl.clientHeight, yThumbHeight)
433
+ }
434
+ },
435
+
436
+ //
437
+ // Render
438
+ //
439
+ renderVN (h: CreateElement): VNode {
440
+ const $xeScrollbar = this
441
+ const props = $xeScrollbar
442
+ const slots = $xeScrollbar.$scopedSlots
443
+
444
+ const { native, loading, autoResize } = props
445
+ const wrapperStyle = $xeScrollbar.computeWrapperStyle
446
+ const wrapperClss = $xeScrollbar.computeWrapperClss
447
+ const viewClss = $xeScrollbar.computeViewClss
448
+ const xOpts = $xeScrollbar.computeXOpts
449
+ const yOpts = $xeScrollbar.computeYOpts
450
+ const defaultSlot = slots.default
451
+ return h('div', {
452
+ ref: 'refElem',
453
+ class: wrapperClss,
454
+ style: wrapperStyle
455
+ }, [
456
+ h('div', {
457
+ ref: 'refViewElem',
458
+ class: viewClss,
459
+ on: {
460
+ scroll: $xeScrollbar.scrollEvent
461
+ }
462
+ }, [
463
+ h('div', {
464
+ ref: 'refViewInnerElem',
465
+ class: 'vxe-scrollbar--view-inner'
466
+ }, autoResize
467
+ ? [
468
+ h('div', {
469
+ key: 'vi',
470
+ ref: 'refViewInnerElem',
471
+ class: 'vxe-scrollbar--view-inner'
472
+ }, defaultSlot ? defaultSlot({}) : [])
473
+ ]
474
+ : defaultSlot ? defaultSlot({}) : [])
475
+ ]),
476
+ native || xOpts.visible === 'hidden'
477
+ ? renderEmptyElement($xeScrollbar)
478
+ : h('div', {
479
+ ref: 'refTrackXElem',
480
+ class: 'vxe-scrollbar--track-x',
481
+ on: {
482
+ click: $xeScrollbar.clickTrackXEvent
483
+ }
484
+ }, [
485
+ h('div', {
486
+ ref: 'refThumbXElem',
487
+ class: 'vxe-scrollbar--thumb-x',
488
+ on: {
489
+ pointerdown: $xeScrollbar.pointerdownThumbXEvent,
490
+ pointermove: $xeScrollbar.pointermoveThumbXEvent,
491
+ pointerup: $xeScrollbar.cleatPointerThumbEvent,
492
+ pointercancel: $xeScrollbar.cleatPointerThumbEvent,
493
+ lostpointercapture: $xeScrollbar.cleatPointerThumbEvent
494
+ }
495
+ })
496
+ ]),
497
+ native || yOpts.visible === 'hidden'
498
+ ? renderEmptyElement($xeScrollbar)
499
+ : h('div', {
500
+ ref: 'refTrackYElem',
501
+ class: 'vxe-scrollbar--track-y',
502
+ on: {
503
+ click: $xeScrollbar.clickTrackYEvent
504
+ }
505
+ }, [
506
+ h('div', {
507
+ ref: 'refThumbYElem',
508
+ class: 'vxe-scrollbar--thumb-y',
509
+ on: {
510
+ pointerdown: $xeScrollbar.pointerdownThumbYEvent,
511
+ pointermove: $xeScrollbar.pointermoveThumbYEvent,
512
+ pointerup: $xeScrollbar.cleatPointerThumbEvent,
513
+ pointercancel: $xeScrollbar.cleatPointerThumbEvent,
514
+ lostpointercapture: $xeScrollbar.cleatPointerThumbEvent
515
+ }
516
+ })
517
+ ]),
518
+ h(VxeLoadingComponent, {
519
+ class: 'vxe-scrollbar--loading',
520
+ props: {
521
+ value: loading
522
+ }
523
+ })
524
+ ])
525
+ }
526
+ },
527
+ watch: {
528
+ height () {
529
+ const $xeScrollbar = this
530
+
531
+ $xeScrollbar.reFlag++
532
+ },
533
+ width () {
534
+ const $xeScrollbar = this
535
+
536
+ $xeScrollbar.reFlag++
537
+ },
538
+ minHeight () {
539
+ const $xeScrollbar = this
540
+
541
+ $xeScrollbar.reFlag++
542
+ },
543
+ minWidth () {
544
+ const $xeScrollbar = this
545
+
546
+ $xeScrollbar.reFlag++
547
+ },
548
+ maxHeight () {
549
+ const $xeScrollbar = this
550
+
551
+ $xeScrollbar.reFlag++
552
+ },
553
+ maxWidth () {
554
+ const $xeScrollbar = this
555
+
556
+ $xeScrollbar.reFlag++
557
+ },
558
+ native () {
559
+ const $xeScrollbar = this
560
+
561
+ $xeScrollbar.reFlag++
562
+ },
563
+ syncResize () {
564
+ const $xeScrollbar = this
565
+
566
+ $xeScrollbar.reFlag++
567
+ },
568
+ reFlag () {
569
+ const $xeScrollbar = this
570
+
571
+ $xeScrollbar.recalculate().then(() => {
572
+ $xeScrollbar.recalculate()
573
+ })
574
+ }
575
+ },
576
+ created () {
577
+ const $xeScrollbar = this
578
+
579
+ $xeScrollbar.internalData = createInternalData()
580
+ },
581
+ mounted () {
582
+ const $xeScrollbar = this
583
+ const props = $xeScrollbar
584
+ const internalData = $xeScrollbar.internalData
585
+
586
+ const { autoResize } = props
587
+ const viewEl = $xeScrollbar.$refs.refViewElem as HTMLDivElement
588
+ const viewInnerEl = $xeScrollbar.$refs.refViewInnerElem as HTMLDivElement
589
+ if (autoResize) {
590
+ const resizeObserver = globalResize.create(() => {
591
+ if (props.autoResize) {
592
+ $xeScrollbar.reFlag++
593
+ }
594
+ })
595
+ if (viewEl) {
596
+ resizeObserver.observe(viewEl)
597
+ }
598
+ if (viewInnerEl) {
599
+ resizeObserver.observe(viewInnerEl)
600
+ }
601
+ internalData.resizeObserver = resizeObserver
602
+ }
603
+
604
+ $xeScrollbar.reFlag++
605
+ },
606
+ beforeDestroy () {
607
+ const $xeScrollbar = this
608
+ const internalData = $xeScrollbar.internalData
609
+
610
+ const { resizeObserver } = internalData
611
+ if (resizeObserver) {
612
+ resizeObserver.disconnect()
613
+ }
614
+ },
615
+ destroyed () {
616
+ const $xeScrollbar = this
617
+ const reactData = $xeScrollbar.reactData
618
+ const internalData = $xeScrollbar.internalData
619
+
620
+ XEUtils.assign(reactData, createReactData())
621
+ XEUtils.assign(internalData, createInternalData())
622
+ },
623
+ render (this: any, h) {
624
+ return this.renderVN(h)
625
+ }
626
+ }) /* define-vxe-component end */
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 计算滚动条滑块的长度
3
+ */
4
+ export function getThumbSize (viewportSize: number, contentSize: number, trackSize: number) {
5
+ if (contentSize <= viewportSize) {
6
+ return 0
7
+ }
8
+ const ratio = viewportSize / contentSize
9
+ const ideal = trackSize * ratio
10
+ return Math.max(20, Math.min(ideal, trackSize))
11
+ }
12
+
13
+ /**
14
+ * 计算滚动条滑块的偏移位置
15
+ */
16
+ export function getThumbOffsetSize (offsetSize: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number) {
17
+ const maxScroll = contentSize - viewportSize
18
+ if (maxScroll <= 0) {
19
+ return 0
20
+ }
21
+ const maxThumbOffset = trackSize - thumbSize
22
+ if (maxThumbOffset <= 0) {
23
+ return 0
24
+ }
25
+ const clamped = Math.min(Math.max(offsetSize, 0), maxScroll)
26
+ const ratio = clamped / maxScroll
27
+ return ratio * maxThumbOffset
28
+ }
29
+
30
+ /**
31
+ * 根据点击轨道的位置,计算滑块的偏移位置
32
+ */
33
+ export function getScrollFromClick (clickPosition: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number) {
34
+ const maxThumbOffset = trackSize - thumbSize
35
+ const maxScroll = contentSize - viewportSize
36
+ if (maxScroll <= 0 || maxThumbOffset <= 0) {
37
+ return 0
38
+ }
39
+ let thumbOffset = clickPosition - thumbSize / 2
40
+ thumbOffset = Math.min(Math.max(thumbOffset, 0), maxThumbOffset)
41
+ const scrollOffset = (thumbOffset / maxThumbOffset) * maxScroll
42
+ return scrollOffset
43
+ }
44
+
45
+ /**
46
+ * 拖拽 thumb 时,根据鼠标位置计算滑块的偏移位置
47
+ */
48
+ export function getScrollFromDrag (pointerPosition: number, dragOffset: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number) {
49
+ const maxScroll = contentSize - viewportSize
50
+ const maxThumbOffset = trackSize - thumbSize
51
+ if (maxScroll <= 0 || maxThumbOffset <= 0) {
52
+ return 0
53
+ }
54
+ let thumbOffset = pointerPosition - dragOffset
55
+ thumbOffset = Math.min(Math.max(thumbOffset, 0), maxThumbOffset)
56
+ return (thumbOffset / maxThumbOffset) * maxScroll
57
+ }
@@ -352,6 +352,15 @@ setConfig({
352
352
  rate: {},
353
353
  result: {},
354
354
  row: {},
355
+ scrollbar: {
356
+ autoResize: true,
357
+ xConfig: {
358
+ // visible: 'visible'
359
+ },
360
+ yConfig: {
361
+ // visible: 'visible'
362
+ }
363
+ },
355
364
  segmented: {},
356
365
  select: {
357
366
  emptyValue: null,
package/styles/all.scss CHANGED
@@ -66,6 +66,7 @@
66
66
  @use './components/rate.scss';
67
67
  @use './components/result.scss';
68
68
  @use './components/row.scss';
69
+ @use './components/scrollbar.scss';
69
70
  @use './components/segmented.scss';
70
71
  @use './components/select.scss';
71
72
  @use './components/split.scss';