vxe-pc-ui 3.18.21 → 3.18.22
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/es/components.js +3 -0
- package/es/icon/style.css +1 -1
- package/es/scrollbar/index.js +12 -0
- package/es/scrollbar/src/scrollbar.js +540 -0
- package/es/scrollbar/src/util.js +54 -0
- package/es/scrollbar/style.css +102 -0
- package/es/scrollbar/style.min.css +1 -0
- package/es/style.css +1 -1
- package/es/style.min.css +1 -1
- package/es/ui/index.js +10 -1
- package/es/ui/src/log.js +1 -1
- package/es/vxe-scrollbar/index.js +3 -0
- package/es/vxe-scrollbar/style.css +102 -0
- package/es/vxe-scrollbar/style.min.css +1 -0
- package/lib/components.js +13 -1
- package/lib/components.min.js +1 -1
- package/lib/icon/style/style.css +1 -1
- package/lib/icon/style/style.min.css +1 -1
- package/lib/index.umd.js +694 -7
- package/lib/index.umd.min.js +1 -1
- package/lib/scrollbar/index.js +19 -0
- package/lib/scrollbar/index.min.js +1 -0
- package/lib/scrollbar/src/scrollbar.js +551 -0
- package/lib/scrollbar/src/scrollbar.min.js +1 -0
- package/lib/scrollbar/src/util.js +63 -0
- package/lib/scrollbar/src/util.min.js +1 -0
- package/lib/scrollbar/style/index.js +1 -0
- package/lib/scrollbar/style/style.css +102 -0
- package/lib/scrollbar/style/style.min.css +1 -0
- package/lib/style.css +1 -1
- package/lib/style.min.css +1 -1
- package/lib/ui/index.js +10 -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/vxe-scrollbar/index.js +22 -0
- package/lib/vxe-scrollbar/index.min.js +1 -0
- package/lib/vxe-scrollbar/style/index.js +1 -0
- package/lib/vxe-scrollbar/style/style.css +102 -0
- package/lib/vxe-scrollbar/style/style.min.css +1 -0
- package/package.json +2 -2
- package/packages/components.ts +3 -0
- package/packages/scrollbar/index.ts +16 -0
- package/packages/scrollbar/src/scrollbar.ts +583 -0
- package/packages/scrollbar/src/util.ts +57 -0
- package/packages/ui/index.ts +9 -0
- package/styles/all.scss +1 -0
- package/styles/components/scrollbar.scss +114 -0
- package/styles/theme/base.scss +5 -0
- package/styles/theme/dark.scss +5 -0
- package/styles/theme/light.scss +5 -0
- package/styles/variable.scss +5 -0
- package/types/all.d.ts +3 -0
- package/types/components/gantt.d.ts +3 -3
- package/types/components/scrollbar.d.ts +209 -0
- package/types/ui/global-config.d.ts +2 -0
- /package/es/icon/{iconfont.1790757609697.ttf → iconfont.1791471260167.ttf} +0 -0
- /package/es/icon/{iconfont.1790757609697.woff → iconfont.1791471260167.woff} +0 -0
- /package/es/icon/{iconfont.1790757609697.woff2 → iconfont.1791471260167.woff2} +0 -0
- /package/es/{iconfont.1790757609697.ttf → iconfont.1791471260167.ttf} +0 -0
- /package/es/{iconfont.1790757609697.woff → iconfont.1791471260167.woff} +0 -0
- /package/es/{iconfont.1790757609697.woff2 → iconfont.1791471260167.woff2} +0 -0
- /package/lib/icon/style/{iconfont.1790757609697.ttf → iconfont.1791471260167.ttf} +0 -0
- /package/lib/icon/style/{iconfont.1790757609697.woff → iconfont.1791471260167.woff} +0 -0
- /package/lib/icon/style/{iconfont.1790757609697.woff2 → iconfont.1791471260167.woff2} +0 -0
- /package/lib/{iconfont.1790757609697.ttf → iconfont.1791471260167.ttf} +0 -0
- /package/lib/{iconfont.1790757609697.woff → iconfont.1791471260167.woff} +0 -0
- /package/lib/{iconfont.1790757609697.woff2 → iconfont.1791471260167.woff2} +0 -0
|
@@ -0,0 +1,583 @@
|
|
|
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 } = 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
|
+
}, defaultSlot ? defaultSlot({}) : [])
|
|
467
|
+
]),
|
|
468
|
+
native || xOpts.visible === 'hidden'
|
|
469
|
+
? renderEmptyElement($xeScrollbar)
|
|
470
|
+
: h('div', {
|
|
471
|
+
ref: 'refTrackXElem',
|
|
472
|
+
class: 'vxe-scrollbar--track-x',
|
|
473
|
+
on: {
|
|
474
|
+
click: $xeScrollbar.clickTrackXEvent
|
|
475
|
+
}
|
|
476
|
+
}, [
|
|
477
|
+
h('div', {
|
|
478
|
+
ref: 'refThumbXElem',
|
|
479
|
+
class: 'vxe-scrollbar--thumb-x',
|
|
480
|
+
on: {
|
|
481
|
+
pointerdown: $xeScrollbar.pointerdownThumbXEvent,
|
|
482
|
+
pointermove: $xeScrollbar.pointermoveThumbXEvent,
|
|
483
|
+
pointerup: $xeScrollbar.cleatPointerThumbEvent,
|
|
484
|
+
pointercancel: $xeScrollbar.cleatPointerThumbEvent,
|
|
485
|
+
lostpointercapture: $xeScrollbar.cleatPointerThumbEvent
|
|
486
|
+
}
|
|
487
|
+
})
|
|
488
|
+
]),
|
|
489
|
+
native || yOpts.visible === 'hidden'
|
|
490
|
+
? renderEmptyElement($xeScrollbar)
|
|
491
|
+
: h('div', {
|
|
492
|
+
ref: 'refTrackYElem',
|
|
493
|
+
class: 'vxe-scrollbar--track-y',
|
|
494
|
+
on: {
|
|
495
|
+
click: $xeScrollbar.clickTrackYEvent
|
|
496
|
+
}
|
|
497
|
+
}, [
|
|
498
|
+
h('div', {
|
|
499
|
+
ref: 'refThumbYElem',
|
|
500
|
+
class: 'vxe-scrollbar--thumb-y',
|
|
501
|
+
on: {
|
|
502
|
+
pointerdown: $xeScrollbar.pointerdownThumbYEvent,
|
|
503
|
+
pointermove: $xeScrollbar.pointermoveThumbYEvent,
|
|
504
|
+
pointerup: $xeScrollbar.cleatPointerThumbEvent,
|
|
505
|
+
pointercancel: $xeScrollbar.cleatPointerThumbEvent,
|
|
506
|
+
lostpointercapture: $xeScrollbar.cleatPointerThumbEvent
|
|
507
|
+
}
|
|
508
|
+
})
|
|
509
|
+
]),
|
|
510
|
+
h(VxeLoadingComponent, {
|
|
511
|
+
class: 'vxe-scrollbar--loading',
|
|
512
|
+
props: {
|
|
513
|
+
value: loading
|
|
514
|
+
}
|
|
515
|
+
})
|
|
516
|
+
])
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
watch: {
|
|
520
|
+
native () {
|
|
521
|
+
const $xeScrollbar = this
|
|
522
|
+
|
|
523
|
+
$xeScrollbar.reFlag++
|
|
524
|
+
},
|
|
525
|
+
syncResize () {
|
|
526
|
+
const $xeScrollbar = this
|
|
527
|
+
|
|
528
|
+
$xeScrollbar.reFlag++
|
|
529
|
+
},
|
|
530
|
+
reFlag () {
|
|
531
|
+
const $xeScrollbar = this
|
|
532
|
+
|
|
533
|
+
$xeScrollbar.recalculate().then(() => {
|
|
534
|
+
$xeScrollbar.recalculate()
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
created () {
|
|
539
|
+
const $xeScrollbar = this
|
|
540
|
+
|
|
541
|
+
$xeScrollbar.internalData = createInternalData()
|
|
542
|
+
},
|
|
543
|
+
mounted () {
|
|
544
|
+
const $xeScrollbar = this
|
|
545
|
+
const props = $xeScrollbar
|
|
546
|
+
const internalData = $xeScrollbar.internalData
|
|
547
|
+
|
|
548
|
+
const { autoResize } = props
|
|
549
|
+
const viewInnerEl = $xeScrollbar.$refs.refViewInnerElem as HTMLDivElement
|
|
550
|
+
if (autoResize && viewInnerEl) {
|
|
551
|
+
const resizeObserver = globalResize.create(() => {
|
|
552
|
+
if (props.autoResize) {
|
|
553
|
+
$xeScrollbar.reFlag++
|
|
554
|
+
}
|
|
555
|
+
})
|
|
556
|
+
resizeObserver.observe(viewInnerEl)
|
|
557
|
+
internalData.resizeObserver = resizeObserver
|
|
558
|
+
}
|
|
559
|
+
$xeScrollbar.$nextTick(() => {
|
|
560
|
+
$xeScrollbar.recalculate()
|
|
561
|
+
})
|
|
562
|
+
},
|
|
563
|
+
beforeDestroy () {
|
|
564
|
+
const $xeScrollbar = this
|
|
565
|
+
const internalData = $xeScrollbar.internalData
|
|
566
|
+
|
|
567
|
+
const { resizeObserver } = internalData
|
|
568
|
+
if (resizeObserver) {
|
|
569
|
+
resizeObserver.disconnect()
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
destroyed () {
|
|
573
|
+
const $xeScrollbar = this
|
|
574
|
+
const reactData = $xeScrollbar.reactData
|
|
575
|
+
const internalData = $xeScrollbar.internalData
|
|
576
|
+
|
|
577
|
+
XEUtils.assign(reactData, createReactData())
|
|
578
|
+
XEUtils.assign(internalData, createInternalData())
|
|
579
|
+
},
|
|
580
|
+
render (this: any, h) {
|
|
581
|
+
return this.renderVN(h)
|
|
582
|
+
}
|
|
583
|
+
}) /* 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
|
+
}
|
package/packages/ui/index.ts
CHANGED
|
@@ -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