@vxe-ui/core 4.4.30 → 4.4.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all.esm.js +250 -3
- package/es/index.esm.js +6 -0
- package/es/src/core.js +1 -1
- package/es/src/log.js +1 -1
- package/es/src/popper-utils.js +188 -0
- package/es/src/scrollbar-utils.js +56 -0
- package/lib/index.common.js +26 -0
- package/lib/index.umd.js +259 -2
- package/lib/index.umd.min.js +1 -1
- package/lib/src/core.js +1 -1
- package/lib/src/core.min.js +1 -1
- package/lib/src/log.js +1 -1
- package/lib/src/log.min.js +1 -1
- package/lib/src/popper-utils.js +198 -0
- package/lib/src/popper-utils.min.js +1 -0
- package/lib/src/scrollbar-utils.js +62 -0
- package/lib/src/scrollbar-utils.min.js +1 -0
- package/package.json +1 -1
- package/packages/index.ts +6 -0
- package/packages/src/popper-utils.ts +194 -0
- package/packages/src/scrollbar-utils.ts +58 -0
- package/types/core/index.d.ts +14 -0
- package/types/core/popper-utils.d.ts +44 -0
- package/types/core/scrollbar-utils.d.ts +38 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.popperUtils = void 0;
|
|
7
|
+
var _xeUtils = _interopRequireDefault(require("xe-utils"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
/**
|
|
10
|
+
* 获取包裹容器的元素
|
|
11
|
+
*/
|
|
12
|
+
function getWrapperElement(panelElem) {
|
|
13
|
+
if (!panelElem) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const bodyEl = document.body;
|
|
17
|
+
const parentEl = panelElem.parentElement;
|
|
18
|
+
return (parentEl === bodyEl ? document.documentElement : parentEl) || null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 获取插入到指定容器的元素或字符串
|
|
22
|
+
*/
|
|
23
|
+
function getAppendSelector(appendTo) {
|
|
24
|
+
const selectElem = appendTo && _xeUtils.default.isFunction(appendTo) ? appendTo({}) : appendTo;
|
|
25
|
+
return selectElem || 'body';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 获取插入到指定容器的元素
|
|
29
|
+
*/
|
|
30
|
+
function getAppendElement(appendTo) {
|
|
31
|
+
const selectElem = getAppendSelector(appendTo);
|
|
32
|
+
if (_xeUtils.default.isString(selectElem)) {
|
|
33
|
+
return document.querySelector(selectElem) || document.body;
|
|
34
|
+
}
|
|
35
|
+
return selectElem;
|
|
36
|
+
}
|
|
37
|
+
const popperUtils = exports.popperUtils = {
|
|
38
|
+
/**
|
|
39
|
+
* 更新位置
|
|
40
|
+
*/
|
|
41
|
+
updatePlacement(targetElem, panelElem, options) {
|
|
42
|
+
const {
|
|
43
|
+
defaultTop,
|
|
44
|
+
defaultLeft,
|
|
45
|
+
placement,
|
|
46
|
+
defaultPlacement,
|
|
47
|
+
appendTo,
|
|
48
|
+
teleportTo,
|
|
49
|
+
marginSize,
|
|
50
|
+
isMinWidth
|
|
51
|
+
} = Object.assign({
|
|
52
|
+
appendTo: '',
|
|
53
|
+
teleportTo: false,
|
|
54
|
+
marginSize: 18,
|
|
55
|
+
isMinWidth: true
|
|
56
|
+
}, options);
|
|
57
|
+
let panelPlacement = 'bottom';
|
|
58
|
+
let top = '';
|
|
59
|
+
let bottom = '';
|
|
60
|
+
let left = 0;
|
|
61
|
+
let minWidth = '';
|
|
62
|
+
let arrowLeft = '';
|
|
63
|
+
const stys = {};
|
|
64
|
+
if (panelElem && targetElem) {
|
|
65
|
+
const bodyEl = document.body;
|
|
66
|
+
const parentWrapperEl = getWrapperElement(teleportTo ? getAppendElement(appendTo) : panelElem);
|
|
67
|
+
if (parentWrapperEl) {
|
|
68
|
+
const targetWidth = targetElem.offsetWidth;
|
|
69
|
+
const targetHeight = targetElem.offsetHeight;
|
|
70
|
+
const panelWidth = panelElem.offsetWidth;
|
|
71
|
+
const panelHeight = panelElem.offsetHeight;
|
|
72
|
+
const parentWrapperRect = parentWrapperEl.getBoundingClientRect();
|
|
73
|
+
const panelRect = panelElem.getBoundingClientRect();
|
|
74
|
+
const targetRect = targetElem.getBoundingClientRect();
|
|
75
|
+
const visibleHeight = bodyEl.clientHeight;
|
|
76
|
+
const visibleWidth = bodyEl.clientWidth;
|
|
77
|
+
const parentWrapperScrollLeft = parentWrapperEl.scrollLeft;
|
|
78
|
+
const parentWrapperScrollTop = parentWrapperEl.scrollTop;
|
|
79
|
+
const parentWrapperOffsetLeft = parentWrapperRect.left;
|
|
80
|
+
const parentWrapperOffsetTop = parentWrapperRect.top;
|
|
81
|
+
const targetLeft = targetRect.left;
|
|
82
|
+
const targetTop = targetRect.top;
|
|
83
|
+
minWidth = targetElem.offsetWidth;
|
|
84
|
+
if (teleportTo) {
|
|
85
|
+
left = (defaultLeft || targetLeft - (panelWidth - targetWidth) / 2) - parentWrapperScrollLeft;
|
|
86
|
+
top = (defaultTop || targetTop + targetHeight) - parentWrapperScrollTop;
|
|
87
|
+
if (placement === 'top') {
|
|
88
|
+
panelPlacement = 'top';
|
|
89
|
+
top = targetTop - panelHeight;
|
|
90
|
+
} else if (!placement) {
|
|
91
|
+
if (defaultPlacement === 'top') {
|
|
92
|
+
panelPlacement = 'top';
|
|
93
|
+
if (!defaultTop) {
|
|
94
|
+
top = targetTop - panelHeight;
|
|
95
|
+
}
|
|
96
|
+
// 如果上面不够放,则向下
|
|
97
|
+
if (top < marginSize) {
|
|
98
|
+
panelPlacement = 'bottom';
|
|
99
|
+
top = targetTop + targetHeight;
|
|
100
|
+
}
|
|
101
|
+
// 如果下面不够放,则向上(优先)
|
|
102
|
+
if (top + panelHeight + marginSize > visibleHeight) {
|
|
103
|
+
panelPlacement = 'top';
|
|
104
|
+
top = targetTop - panelHeight;
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
// 如果下面不够放,则向上
|
|
108
|
+
if (top + panelHeight + marginSize > visibleHeight) {
|
|
109
|
+
panelPlacement = 'top';
|
|
110
|
+
top = targetTop - panelHeight;
|
|
111
|
+
}
|
|
112
|
+
// 如果上面不够放,则向下(优先)
|
|
113
|
+
if (top < marginSize) {
|
|
114
|
+
panelPlacement = 'bottom';
|
|
115
|
+
top = targetTop + targetHeight;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 如果溢出右边
|
|
120
|
+
if (left + panelWidth + marginSize > visibleWidth) {
|
|
121
|
+
left -= left + panelWidth + marginSize - visibleWidth;
|
|
122
|
+
}
|
|
123
|
+
// 如果溢出左边
|
|
124
|
+
if (left < marginSize) {
|
|
125
|
+
left = marginSize;
|
|
126
|
+
}
|
|
127
|
+
// 偏移
|
|
128
|
+
top -= parentWrapperOffsetTop;
|
|
129
|
+
left -= parentWrapperOffsetLeft;
|
|
130
|
+
} else {
|
|
131
|
+
if (placement === 'top') {
|
|
132
|
+
panelPlacement = 'top';
|
|
133
|
+
bottom = targetHeight;
|
|
134
|
+
} else if (!placement) {
|
|
135
|
+
// 如果下面不够放,则向上
|
|
136
|
+
top = targetHeight;
|
|
137
|
+
if (targetTop + targetHeight + panelHeight + marginSize > visibleHeight) {
|
|
138
|
+
// 如果上面不够放,则向下(优先)
|
|
139
|
+
if (targetTop - targetHeight - panelHeight > marginSize) {
|
|
140
|
+
panelPlacement = 'top';
|
|
141
|
+
top = '';
|
|
142
|
+
bottom = targetHeight;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// 是否超出右侧
|
|
147
|
+
if (panelRect.left + panelRect.width + marginSize > visibleWidth) {
|
|
148
|
+
left = -(panelRect.left + panelRect.width + marginSize - visibleWidth);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (_xeUtils.default.isNumber(top)) {
|
|
152
|
+
stys.top = top + 'px';
|
|
153
|
+
}
|
|
154
|
+
if (_xeUtils.default.isNumber(bottom)) {
|
|
155
|
+
stys.bottom = bottom + 'px';
|
|
156
|
+
}
|
|
157
|
+
if (_xeUtils.default.isNumber(left)) {
|
|
158
|
+
stys.left = left + 'px';
|
|
159
|
+
}
|
|
160
|
+
if (isMinWidth && _xeUtils.default.isNumber(minWidth)) {
|
|
161
|
+
stys.minWidth = minWidth + 'px';
|
|
162
|
+
}
|
|
163
|
+
// 箭头
|
|
164
|
+
if (left === targetLeft) {
|
|
165
|
+
if (targetWidth <= panelWidth) {
|
|
166
|
+
arrowLeft = targetWidth / 2;
|
|
167
|
+
}
|
|
168
|
+
} else if (left < targetLeft) {
|
|
169
|
+
if (left + panelWidth > targetLeft + targetWidth) {
|
|
170
|
+
arrowLeft = targetLeft - left + targetWidth / 2;
|
|
171
|
+
} else {
|
|
172
|
+
arrowLeft = targetLeft - left + (panelWidth - (targetLeft - left)) / 2;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
top: top || 0,
|
|
179
|
+
bottom: bottom || 0,
|
|
180
|
+
left: left || 0,
|
|
181
|
+
arrowLeft: arrowLeft || 0,
|
|
182
|
+
style: stys,
|
|
183
|
+
placement: panelPlacement
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
/**
|
|
187
|
+
* 获取包裹容器的元素
|
|
188
|
+
*/
|
|
189
|
+
getWrapperElement,
|
|
190
|
+
/**
|
|
191
|
+
* 获取插入到指定容器的元素或字符串
|
|
192
|
+
*/
|
|
193
|
+
getAppendSelector,
|
|
194
|
+
/**
|
|
195
|
+
* 获取插入到指定容器的元素
|
|
196
|
+
*/
|
|
197
|
+
getAppendElement
|
|
198
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.popperUtils=void 0;var _xeUtils=_interopRequireDefault(require("xe-utils"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function getWrapperElement(e){var t;return e&&(t=document.body,(e=e.parentElement)===t?document.documentElement:e)||null}function getAppendSelector(e){return(e&&_xeUtils.default.isFunction(e)?e({}):e)||"body"}function getAppendElement(e){e=getAppendSelector(e);return _xeUtils.default.isString(e)?document.querySelector(e)||document.body:e}let popperUtils=exports.popperUtils={updatePlacement(e,t,o){var{defaultTop:o,defaultLeft:l,placement:n,defaultPlacement:p,appendTo:i,teleportTo:r,marginSize:d,isMinWidth:u}=Object.assign({appendTo:"",teleportTo:!1,marginSize:18,isMinWidth:!0},o);let f="bottom",a="",s="",m=0;var c="";let g="";var b,x,_,h,W,E,U,A,S,v,y,T={};return t&&e&&(E=document.body,i=getWrapperElement(r?getAppendElement(i):t))&&(b=e.offsetWidth,x=e.offsetHeight,_=t.offsetWidth,h=t.offsetHeight,S=i.getBoundingClientRect(),t=t.getBoundingClientRect(),y=e.getBoundingClientRect(),W=E.clientHeight,E=E.clientWidth,U=i.scrollLeft,i=i.scrollTop,A=S.left,S=S.top,v=y.left,y=y.top,c=e.offsetWidth,r?(m=(l||v-(_-b)/2)-U,a=(o||y+x)-i,"top"===n?(f="top",a=y-h):n||("top"===p?(f="top",(a=o?a:y-h)<d&&(f="bottom",a=y+x),a+h+d>W&&(f="top",a=y-h)):(a+h+d>W&&(f="top",a=y-h),a<d&&(f="bottom",a=y+x))),m+_+d>E&&(m-=m+_+d-E),m<d&&(m=d),a-=S,m-=A):("top"===n?(f="top",s=x):n||W<y+(a=x)+h+d&&d<y-x-h&&(f="top",a="",s=x),t.left+t.width+d>E&&(m=-(t.left+t.width+d-E))),_xeUtils.default.isNumber(a)&&(T.top=a+"px"),_xeUtils.default.isNumber(s)&&(T.bottom=s+"px"),_xeUtils.default.isNumber(m)&&(T.left=m+"px"),u&&_xeUtils.default.isNumber(c)&&(T.minWidth=c+"px"),m===v?b<=_&&(g=b/2):m<v&&(g=m+_>v+b?v-m+b/2:v-m+(_-(v-m))/2)),{top:a||0,bottom:s||0,left:m||0,arrowLeft:g||0,style:T,placement:f}},getWrapperElement:getWrapperElement,getAppendSelector:getAppendSelector,getAppendElement:getAppendElement};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.scrollbarUtils = void 0;
|
|
7
|
+
const scrollbarUtils = exports.scrollbarUtils = {
|
|
8
|
+
/**
|
|
9
|
+
* 计算滚动条滑块的长度
|
|
10
|
+
*/
|
|
11
|
+
getThumbSize(viewportSize, contentSize, trackSize) {
|
|
12
|
+
if (contentSize <= viewportSize) {
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
const ratio = viewportSize / contentSize;
|
|
16
|
+
const ideal = trackSize * ratio;
|
|
17
|
+
return Math.max(20, Math.min(ideal, trackSize));
|
|
18
|
+
},
|
|
19
|
+
/**
|
|
20
|
+
* 计算滚动条滑块的偏移位置
|
|
21
|
+
*/
|
|
22
|
+
getThumbOffsetSize(offsetSize, viewportSize, contentSize, trackSize, thumbSize) {
|
|
23
|
+
const maxScroll = contentSize - viewportSize;
|
|
24
|
+
if (maxScroll <= 0) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
28
|
+
if (maxThumbOffset <= 0) {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
const clamped = Math.min(Math.max(offsetSize, 0), maxScroll);
|
|
32
|
+
const ratio = clamped / maxScroll;
|
|
33
|
+
return ratio * maxThumbOffset;
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* 根据点击轨道的位置,计算滑块的偏移位置
|
|
37
|
+
*/
|
|
38
|
+
getScrollFromClick(clickPosition, viewportSize, contentSize, trackSize, thumbSize) {
|
|
39
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
40
|
+
const maxScroll = contentSize - viewportSize;
|
|
41
|
+
if (maxScroll <= 0 || maxThumbOffset <= 0) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
let thumbOffset = clickPosition - thumbSize / 2;
|
|
45
|
+
thumbOffset = Math.min(Math.max(thumbOffset, 0), maxThumbOffset);
|
|
46
|
+
const scrollOffset = thumbOffset / maxThumbOffset * maxScroll;
|
|
47
|
+
return scrollOffset;
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* 拖拽 thumb 时,根据鼠标位置计算滑块的偏移位置
|
|
51
|
+
*/
|
|
52
|
+
getScrollFromDrag(pointerPosition, dragOffset, viewportSize, contentSize, trackSize, thumbSize) {
|
|
53
|
+
const maxScroll = contentSize - viewportSize;
|
|
54
|
+
const maxThumbOffset = trackSize - thumbSize;
|
|
55
|
+
if (maxScroll <= 0 || maxThumbOffset <= 0) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
let thumbOffset = pointerPosition - dragOffset;
|
|
59
|
+
thumbOffset = Math.min(Math.max(thumbOffset, 0), maxThumbOffset);
|
|
60
|
+
return thumbOffset / maxThumbOffset * maxScroll;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.scrollbarUtils=void 0;let scrollbarUtils=exports.scrollbarUtils={getThumbSize(t,r,e){return r<=t?0:Math.max(20,Math.min(e*(t/r),e))},getThumbOffsetSize(t,r,e,a,l){e-=r;return e<=0||(r=a-l)<=0?0:Math.min(Math.max(t,0),e)/e*r},getScrollFromClick(t,r,e,a,l){a-=l,e-=r;return e<=0||a<=0?0:(r=t-l/2,(r=Math.min(Math.max(r,0),a))/a*e)},getScrollFromDrag(t,r,e,a,l,o){a-=e,e=l-o;return a<=0||e<=0?0:(l=t-r,(l=Math.min(Math.max(l,0),e))/e*a)}};
|
package/package.json
CHANGED
package/packages/index.ts
CHANGED
|
@@ -17,6 +17,8 @@ import { clipboard } from './src/clipboard'
|
|
|
17
17
|
import { permission } from './src/permission'
|
|
18
18
|
import { baseUtils } from './src/base-utils'
|
|
19
19
|
import { domUtils } from './src/dom-utils'
|
|
20
|
+
import { scrollbarUtils } from './src/scrollbar-utils'
|
|
21
|
+
import { popperUtils } from './src/popper-utils'
|
|
20
22
|
import { log } from './src/log'
|
|
21
23
|
import { hooks } from './src/hooks'
|
|
22
24
|
import { useFns } from './src/useFns'
|
|
@@ -109,6 +111,8 @@ export const VxeUI = Object.assign(VxeCore, {
|
|
|
109
111
|
|
|
110
112
|
baseUtils,
|
|
111
113
|
domUtils,
|
|
114
|
+
scrollbarUtils,
|
|
115
|
+
popperUtils,
|
|
112
116
|
|
|
113
117
|
globalStore,
|
|
114
118
|
|
|
@@ -146,6 +150,8 @@ export * from './src/permission'
|
|
|
146
150
|
|
|
147
151
|
export * from './src/base-utils'
|
|
148
152
|
export * from './src/dom-utils'
|
|
153
|
+
export * from './src/scrollbar-utils'
|
|
154
|
+
export * from './src/popper-utils'
|
|
149
155
|
|
|
150
156
|
export * from './src/dataStore'
|
|
151
157
|
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import XEUtils from 'xe-utils'
|
|
2
|
+
|
|
3
|
+
import type { VxePopperUtils, VxePopperOptions } from '../../types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 获取包裹容器的元素
|
|
7
|
+
*/
|
|
8
|
+
function getWrapperElement (panelElem: HTMLElement | null | undefined) {
|
|
9
|
+
if (!panelElem) {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
const bodyEl = document.body
|
|
13
|
+
const parentEl = panelElem.parentElement
|
|
14
|
+
return (parentEl === bodyEl ? document.documentElement : parentEl) || null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 获取插入到指定容器的元素或字符串
|
|
19
|
+
*/
|
|
20
|
+
function getAppendSelector (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
|
|
21
|
+
const selectElem = appendTo && XEUtils.isFunction(appendTo) ? appendTo({}) : appendTo
|
|
22
|
+
return selectElem || 'body'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 获取插入到指定容器的元素
|
|
27
|
+
*/
|
|
28
|
+
function getAppendElement (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
|
|
29
|
+
const selectElem = getAppendSelector(appendTo)
|
|
30
|
+
if (XEUtils.isString(selectElem)) {
|
|
31
|
+
return document.querySelector<HTMLElement>(selectElem) || document.body
|
|
32
|
+
}
|
|
33
|
+
return selectElem
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const popperUtils: VxePopperUtils = {
|
|
37
|
+
/**
|
|
38
|
+
* 更新位置
|
|
39
|
+
*/
|
|
40
|
+
updatePlacement (targetElem: HTMLElement | null | undefined, panelElem: HTMLElement | null | undefined, options: VxePopperOptions) {
|
|
41
|
+
const { defaultTop, defaultLeft, placement, defaultPlacement, appendTo, teleportTo, marginSize, isMinWidth } = Object.assign({
|
|
42
|
+
appendTo: '',
|
|
43
|
+
teleportTo: false,
|
|
44
|
+
marginSize: 18,
|
|
45
|
+
isMinWidth: true
|
|
46
|
+
}, options)
|
|
47
|
+
let panelPlacement: 'top' | 'bottom' = 'bottom'
|
|
48
|
+
let top: number | '' = ''
|
|
49
|
+
let bottom: number | '' = ''
|
|
50
|
+
let left = 0
|
|
51
|
+
let minWidth: number | '' = ''
|
|
52
|
+
let arrowLeft: number | '' = ''
|
|
53
|
+
const stys: Record<string, string> = {}
|
|
54
|
+
if (panelElem && targetElem) {
|
|
55
|
+
const bodyEl = document.body
|
|
56
|
+
const parentWrapperEl = getWrapperElement(teleportTo ? getAppendElement(appendTo) : panelElem)
|
|
57
|
+
if (parentWrapperEl) {
|
|
58
|
+
const targetWidth = targetElem.offsetWidth
|
|
59
|
+
const targetHeight = targetElem.offsetHeight
|
|
60
|
+
const panelWidth = panelElem.offsetWidth
|
|
61
|
+
const panelHeight = panelElem.offsetHeight
|
|
62
|
+
|
|
63
|
+
const parentWrapperRect = parentWrapperEl.getBoundingClientRect()
|
|
64
|
+
const panelRect = panelElem.getBoundingClientRect()
|
|
65
|
+
const targetRect = targetElem.getBoundingClientRect()
|
|
66
|
+
const visibleHeight = bodyEl.clientHeight
|
|
67
|
+
const visibleWidth = bodyEl.clientWidth
|
|
68
|
+
|
|
69
|
+
const parentWrapperScrollLeft = parentWrapperEl.scrollLeft
|
|
70
|
+
const parentWrapperScrollTop = parentWrapperEl.scrollTop
|
|
71
|
+
const parentWrapperOffsetLeft = parentWrapperRect.left
|
|
72
|
+
const parentWrapperOffsetTop = parentWrapperRect.top
|
|
73
|
+
const targetLeft = targetRect.left
|
|
74
|
+
const targetTop = targetRect.top
|
|
75
|
+
|
|
76
|
+
minWidth = targetElem.offsetWidth
|
|
77
|
+
|
|
78
|
+
if (teleportTo) {
|
|
79
|
+
left = (defaultLeft || (targetLeft - (panelWidth - targetWidth) / 2)) - parentWrapperScrollLeft
|
|
80
|
+
top = (defaultTop || (targetTop + targetHeight)) - parentWrapperScrollTop
|
|
81
|
+
if (placement === 'top') {
|
|
82
|
+
panelPlacement = 'top'
|
|
83
|
+
top = targetTop - panelHeight
|
|
84
|
+
} else if (!placement) {
|
|
85
|
+
if (defaultPlacement === 'top') {
|
|
86
|
+
panelPlacement = 'top'
|
|
87
|
+
if (!defaultTop) {
|
|
88
|
+
top = targetTop - panelHeight
|
|
89
|
+
}
|
|
90
|
+
// 如果上面不够放,则向下
|
|
91
|
+
if (top < marginSize) {
|
|
92
|
+
panelPlacement = 'bottom'
|
|
93
|
+
top = targetTop + targetHeight
|
|
94
|
+
}
|
|
95
|
+
// 如果下面不够放,则向上(优先)
|
|
96
|
+
if (top + panelHeight + marginSize > visibleHeight) {
|
|
97
|
+
panelPlacement = 'top'
|
|
98
|
+
top = targetTop - panelHeight
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// 如果下面不够放,则向上
|
|
102
|
+
if (top + panelHeight + marginSize > visibleHeight) {
|
|
103
|
+
panelPlacement = 'top'
|
|
104
|
+
top = targetTop - panelHeight
|
|
105
|
+
}
|
|
106
|
+
// 如果上面不够放,则向下(优先)
|
|
107
|
+
if (top < marginSize) {
|
|
108
|
+
panelPlacement = 'bottom'
|
|
109
|
+
top = targetTop + targetHeight
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// 如果溢出右边
|
|
114
|
+
if (left + panelWidth + marginSize > visibleWidth) {
|
|
115
|
+
left -= left + panelWidth + marginSize - visibleWidth
|
|
116
|
+
}
|
|
117
|
+
// 如果溢出左边
|
|
118
|
+
if (left < marginSize) {
|
|
119
|
+
left = marginSize
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 偏移
|
|
123
|
+
top -= parentWrapperOffsetTop
|
|
124
|
+
left -= parentWrapperOffsetLeft
|
|
125
|
+
} else {
|
|
126
|
+
if (placement === 'top') {
|
|
127
|
+
panelPlacement = 'top'
|
|
128
|
+
bottom = targetHeight
|
|
129
|
+
} else if (!placement) {
|
|
130
|
+
// 如果下面不够放,则向上
|
|
131
|
+
top = targetHeight
|
|
132
|
+
if (targetTop + targetHeight + panelHeight + marginSize > visibleHeight) {
|
|
133
|
+
// 如果上面不够放,则向下(优先)
|
|
134
|
+
if (targetTop - targetHeight - panelHeight > marginSize) {
|
|
135
|
+
panelPlacement = 'top'
|
|
136
|
+
top = ''
|
|
137
|
+
bottom = targetHeight
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// 是否超出右侧
|
|
142
|
+
if (panelRect.left + panelRect.width + marginSize > visibleWidth) {
|
|
143
|
+
left = -(panelRect.left + panelRect.width + marginSize - visibleWidth)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (XEUtils.isNumber(top)) {
|
|
147
|
+
stys.top = top + 'px'
|
|
148
|
+
}
|
|
149
|
+
if (XEUtils.isNumber(bottom)) {
|
|
150
|
+
stys.bottom = bottom + 'px'
|
|
151
|
+
}
|
|
152
|
+
if (XEUtils.isNumber(left)) {
|
|
153
|
+
stys.left = left + 'px'
|
|
154
|
+
}
|
|
155
|
+
if (isMinWidth && XEUtils.isNumber(minWidth)) {
|
|
156
|
+
stys.minWidth = minWidth + 'px'
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 箭头
|
|
160
|
+
if (left === targetLeft) {
|
|
161
|
+
if (targetWidth <= panelWidth) {
|
|
162
|
+
arrowLeft = targetWidth / 2
|
|
163
|
+
}
|
|
164
|
+
} else if (left < targetLeft) {
|
|
165
|
+
if (left + panelWidth > targetLeft + targetWidth) {
|
|
166
|
+
arrowLeft = (targetLeft - left) + targetWidth / 2
|
|
167
|
+
} else {
|
|
168
|
+
arrowLeft = (targetLeft - left) + (panelWidth - (targetLeft - left)) / 2
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
top: top || 0,
|
|
175
|
+
bottom: bottom || 0,
|
|
176
|
+
left: left || 0,
|
|
177
|
+
arrowLeft: arrowLeft || 0,
|
|
178
|
+
style: stys,
|
|
179
|
+
placement: panelPlacement
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
/**
|
|
183
|
+
* 获取包裹容器的元素
|
|
184
|
+
*/
|
|
185
|
+
getWrapperElement,
|
|
186
|
+
/**
|
|
187
|
+
* 获取插入到指定容器的元素或字符串
|
|
188
|
+
*/
|
|
189
|
+
getAppendSelector,
|
|
190
|
+
/**
|
|
191
|
+
* 获取插入到指定容器的元素
|
|
192
|
+
*/
|
|
193
|
+
getAppendElement
|
|
194
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { VxeScrollbarUtils } from '../../types'
|
|
2
|
+
|
|
3
|
+
export const scrollbarUtils: VxeScrollbarUtils = {
|
|
4
|
+
/**
|
|
5
|
+
* 计算滚动条滑块的长度
|
|
6
|
+
*/
|
|
7
|
+
getThumbSize (viewportSize: number, contentSize: number, trackSize: number) {
|
|
8
|
+
if (contentSize <= viewportSize) {
|
|
9
|
+
return 0
|
|
10
|
+
}
|
|
11
|
+
const ratio = viewportSize / contentSize
|
|
12
|
+
const ideal = trackSize * ratio
|
|
13
|
+
return Math.max(20, Math.min(ideal, trackSize))
|
|
14
|
+
},
|
|
15
|
+
/**
|
|
16
|
+
* 计算滚动条滑块的偏移位置
|
|
17
|
+
*/
|
|
18
|
+
getThumbOffsetSize (offsetSize: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number) {
|
|
19
|
+
const maxScroll = contentSize - viewportSize
|
|
20
|
+
if (maxScroll <= 0) {
|
|
21
|
+
return 0
|
|
22
|
+
}
|
|
23
|
+
const maxThumbOffset = trackSize - thumbSize
|
|
24
|
+
if (maxThumbOffset <= 0) {
|
|
25
|
+
return 0
|
|
26
|
+
}
|
|
27
|
+
const clamped = Math.min(Math.max(offsetSize, 0), maxScroll)
|
|
28
|
+
const ratio = clamped / maxScroll
|
|
29
|
+
return ratio * maxThumbOffset
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* 根据点击轨道的位置,计算滑块的偏移位置
|
|
33
|
+
*/
|
|
34
|
+
getScrollFromClick (clickPosition: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number) {
|
|
35
|
+
const maxThumbOffset = trackSize - thumbSize
|
|
36
|
+
const maxScroll = contentSize - viewportSize
|
|
37
|
+
if (maxScroll <= 0 || maxThumbOffset <= 0) {
|
|
38
|
+
return 0
|
|
39
|
+
}
|
|
40
|
+
let thumbOffset = clickPosition - thumbSize / 2
|
|
41
|
+
thumbOffset = Math.min(Math.max(thumbOffset, 0), maxThumbOffset)
|
|
42
|
+
const scrollOffset = (thumbOffset / maxThumbOffset) * maxScroll
|
|
43
|
+
return scrollOffset
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* 拖拽 thumb 时,根据鼠标位置计算滑块的偏移位置
|
|
47
|
+
*/
|
|
48
|
+
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
|
+
}
|
|
58
|
+
}
|
package/types/core/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ import { VxeGlobalClipboard } from './clipboard'
|
|
|
16
16
|
import { VxeGlobalPermission } from './permission'
|
|
17
17
|
import { VxeBaseUtils } from './base-utils'
|
|
18
18
|
import { VxeDomUtils } from './dom-utils'
|
|
19
|
+
import { VxeScrollbarUtils } from './scrollbar-utils'
|
|
20
|
+
import { VxePopperUtils } from './popper-utils'
|
|
19
21
|
import { VxeGlobalComponentMethod, VxeGlobalGetComponentMethod, VxeGlobalHasComponentMethod } from './components'
|
|
20
22
|
import { VxeGlobalUseFns } from './useFn'
|
|
21
23
|
import { VxeGlobalHooks } from './hooks'
|
|
@@ -74,6 +76,8 @@ export const permission: VxeGlobalPermission
|
|
|
74
76
|
|
|
75
77
|
export const baseUtils: VxeBaseUtils
|
|
76
78
|
export const domUtils: VxeDomUtils
|
|
79
|
+
export const scrollbarUtils: VxeScrollbarUtils
|
|
80
|
+
export const popperUtils: VxePopperUtils
|
|
77
81
|
|
|
78
82
|
export const globalEvents: VxeGlobalEvents
|
|
79
83
|
|
|
@@ -217,6 +221,14 @@ export interface VxeUIExport {
|
|
|
217
221
|
* Document 工具函数
|
|
218
222
|
*/
|
|
219
223
|
domUtils: VxeDomUtils
|
|
224
|
+
/**
|
|
225
|
+
* 滚动条工具函数
|
|
226
|
+
*/
|
|
227
|
+
scrollbarUtils: VxeScrollbarUtils
|
|
228
|
+
/**
|
|
229
|
+
* 弹出元素定位工具函数
|
|
230
|
+
*/
|
|
231
|
+
popperUtils: VxePopperUtils
|
|
220
232
|
|
|
221
233
|
/**
|
|
222
234
|
* 全局事件管理
|
|
@@ -302,6 +314,8 @@ export * from './permission'
|
|
|
302
314
|
|
|
303
315
|
export * from './base-utils'
|
|
304
316
|
export * from './dom-utils'
|
|
317
|
+
export * from './scrollbar-utils'
|
|
318
|
+
export * from './popper-utils'
|
|
305
319
|
|
|
306
320
|
export * from './log'
|
|
307
321
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface VxePopperOptions {
|
|
2
|
+
defaultTop?: number
|
|
3
|
+
defaultLeft?: number
|
|
4
|
+
placement?: '' | 'top' | 'bottom' | null
|
|
5
|
+
defaultPlacement?: '' | 'top' | 'bottom' | null
|
|
6
|
+
appendTo?: string | HTMLElement | ((params: any) => string | HTMLElement)
|
|
7
|
+
teleportTo?: boolean
|
|
8
|
+
marginSize?: number
|
|
9
|
+
isMinWidth?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface VxePopperPlacementResult {
|
|
13
|
+
top: number
|
|
14
|
+
bottom: number
|
|
15
|
+
left: number
|
|
16
|
+
arrowLeft: number
|
|
17
|
+
style: Record<string, string>
|
|
18
|
+
placement: 'top' | 'bottom'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface VxePopperUtils {
|
|
22
|
+
/**
|
|
23
|
+
* 更新位置
|
|
24
|
+
* @param targetElem
|
|
25
|
+
* @param panelElem
|
|
26
|
+
* @param options
|
|
27
|
+
*/
|
|
28
|
+
updatePlacement (targetElem: HTMLElement | null | undefined, panelElem: HTMLElement | null | undefined, options: VxePopperOptions): VxePopperPlacementResult
|
|
29
|
+
/**
|
|
30
|
+
* 获取包裹容器的元素
|
|
31
|
+
* @param panelElem
|
|
32
|
+
*/
|
|
33
|
+
getWrapperElement (panelElem: HTMLElement | null | undefined): HTMLElement | null
|
|
34
|
+
/**
|
|
35
|
+
* 获取插入到指定容器的元素或字符串
|
|
36
|
+
* @param appendTo
|
|
37
|
+
*/
|
|
38
|
+
getAppendSelector (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined): HTMLElement | string
|
|
39
|
+
/**
|
|
40
|
+
* 获取插入到指定容器的元素
|
|
41
|
+
* @param appendTo
|
|
42
|
+
*/
|
|
43
|
+
getAppendElement (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined): HTMLElement | null
|
|
44
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
export interface VxeScrollbarUtils {
|
|
3
|
+
/**
|
|
4
|
+
* 计算滚动条滑块的长度
|
|
5
|
+
* @param viewportSize
|
|
6
|
+
* @param contentSize
|
|
7
|
+
* @param trackSize
|
|
8
|
+
*/
|
|
9
|
+
getThumbSize (viewportSize: number, contentSize: number, trackSize: number): number
|
|
10
|
+
/**
|
|
11
|
+
* 计算滚动条滑块的偏移位置
|
|
12
|
+
* @param offsetSize
|
|
13
|
+
* @param viewportSize
|
|
14
|
+
* @param contentSize
|
|
15
|
+
* @param trackSize
|
|
16
|
+
* @param thumbSize
|
|
17
|
+
*/
|
|
18
|
+
getThumbOffsetSize (offsetSize: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number): number
|
|
19
|
+
/**
|
|
20
|
+
* 根据点击轨道的位置,计算滑块的偏移位置
|
|
21
|
+
* @param clickPosition
|
|
22
|
+
* @param viewportSize
|
|
23
|
+
* @param contentSize
|
|
24
|
+
* @param trackSize
|
|
25
|
+
* @param thumbSize
|
|
26
|
+
*/
|
|
27
|
+
getScrollFromClick (clickPosition: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number): number
|
|
28
|
+
/**
|
|
29
|
+
* 拖拽 thumb 时,根据鼠标位置计算滑块的偏移位置
|
|
30
|
+
* @param pointerPosition
|
|
31
|
+
* @param dragOffset
|
|
32
|
+
* @param viewportSize
|
|
33
|
+
* @param contentSize
|
|
34
|
+
* @param trackSize
|
|
35
|
+
* @param thumbSize
|
|
36
|
+
*/
|
|
37
|
+
getScrollFromDrag (pointerPosition: number, dragOffset: number, viewportSize: number, contentSize: number, trackSize: number, thumbSize: number): number
|
|
38
|
+
}
|