vxe-table 4.23.8 → 4.23.9

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 (126) hide show
  1. package/dist/all.esm.js +5715 -3783
  2. package/es/components.d.ts +1 -0
  3. package/es/components.js +2 -7
  4. package/es/grid/src/emits.js +1 -15
  5. package/es/grid/src/grid.js +397 -120
  6. package/es/index.esm.js +1 -0
  7. package/es/index.js +1 -0
  8. package/es/table/module/custom/hook.js +49 -42
  9. package/es/table/module/custom/panel.js +777 -527
  10. package/es/table/module/edit/hook.js +140 -62
  11. package/es/table/module/export/export-panel.js +399 -316
  12. package/es/table/module/export/hook.js +395 -337
  13. package/es/table/module/export/import-panel.js +152 -123
  14. package/es/table/module/filter/hook.js +16 -2
  15. package/es/table/module/filter/panel.js +146 -84
  16. package/es/table/module/keyboard/hook.js +8 -4
  17. package/es/table/module/menu/panel.js +197 -126
  18. package/es/table/render/index.js +151 -98
  19. package/es/table/src/body.js +355 -233
  20. package/es/table/src/cell.js +426 -269
  21. package/es/table/src/columnInfo.js +1 -0
  22. package/es/table/src/footer.js +144 -99
  23. package/es/table/src/group.js +7 -3
  24. package/es/table/src/header.js +229 -172
  25. package/es/table/src/table.js +1503 -1030
  26. package/es/table/src/util.js +15 -19
  27. package/es/toolbar/src/toolbar.js +132 -75
  28. package/es/ui/index.js +1 -1
  29. package/es/ui/src/dom.js +9 -6
  30. package/es/ui/src/log.js +1 -1
  31. package/es/ui/src/utils.d.ts +1 -1
  32. package/lib/components.js +2 -7
  33. package/lib/grid/src/emits.js +1 -15
  34. package/lib/grid/src/grid.js +397 -120
  35. package/lib/index.common.js +1 -0
  36. package/lib/index.js +1 -0
  37. package/lib/index.umd.js +5732 -3800
  38. package/lib/index.umd.min.js +3 -3
  39. package/lib/table/module/custom/hook.js +49 -42
  40. package/lib/table/module/custom/panel.js +777 -527
  41. package/lib/table/module/edit/hook.js +140 -62
  42. package/lib/table/module/export/export-panel.js +399 -316
  43. package/lib/table/module/export/hook.js +395 -337
  44. package/lib/table/module/export/import-panel.js +152 -123
  45. package/lib/table/module/filter/hook.js +16 -2
  46. package/lib/table/module/filter/panel.js +146 -84
  47. package/lib/table/module/keyboard/hook.js +8 -4
  48. package/lib/table/module/menu/panel.js +197 -126
  49. package/lib/table/render/index.js +151 -98
  50. package/lib/table/src/body.js +355 -233
  51. package/lib/table/src/cell.js +426 -269
  52. package/lib/table/src/columnInfo.js +1 -0
  53. package/lib/table/src/footer.js +144 -99
  54. package/lib/table/src/group.js +7 -3
  55. package/lib/table/src/header.js +229 -172
  56. package/lib/table/src/table.js +1471 -1029
  57. package/lib/table/src/util.js +15 -19
  58. package/lib/toolbar/src/toolbar.js +132 -75
  59. package/lib/ui/index.js +1 -1
  60. package/lib/ui/src/dom.js +9 -6
  61. package/lib/ui/src/log.js +1 -1
  62. package/package.json +2 -2
  63. package/packages/colgroup/index.ts +22 -22
  64. package/packages/column/index.ts +22 -22
  65. package/packages/components.ts +41 -44
  66. package/packages/grid/index.ts +18 -18
  67. package/packages/grid/src/emits.ts +5 -19
  68. package/packages/grid/src/grid.ts +2229 -1925
  69. package/packages/grid/src/props.ts +22 -23
  70. package/packages/index.ts +11 -11
  71. package/packages/locale/lang/fr-FR.ts +15 -15
  72. package/packages/locale/lang/it-IT.ts +4 -4
  73. package/packages/locale/lang/uk-UA.ts +1 -1
  74. package/packages/locale/lang/uz-UZ.ts +13 -13
  75. package/packages/locale/lang/zh-CN.ts +907 -907
  76. package/packages/table/index.ts +26 -26
  77. package/packages/table/module/custom/hook.ts +510 -503
  78. package/packages/table/module/custom/panel.ts +2002 -1743
  79. package/packages/table/module/edit/hook.ts +1224 -1131
  80. package/packages/table/module/export/export-panel.ts +697 -611
  81. package/packages/table/module/export/hook.ts +2160 -2059
  82. package/packages/table/module/export/import-panel.ts +319 -279
  83. package/packages/table/module/export/util.ts +25 -24
  84. package/packages/table/module/filter/hook.ts +519 -501
  85. package/packages/table/module/filter/panel.ts +368 -304
  86. package/packages/table/module/keyboard/hook.ts +498 -494
  87. package/packages/table/module/menu/hook.ts +330 -330
  88. package/packages/table/module/menu/panel.ts +272 -201
  89. package/packages/table/module/validator/hook.ts +653 -635
  90. package/packages/table/render/index.ts +1819 -1744
  91. package/packages/table/src/body.ts +1078 -955
  92. package/packages/table/src/cell.ts +1524 -1359
  93. package/packages/table/src/column.ts +192 -192
  94. package/packages/table/src/columnInfo.ts +232 -232
  95. package/packages/table/src/emits.ts +134 -134
  96. package/packages/table/src/footer.ts +425 -380
  97. package/packages/table/src/group.ts +67 -63
  98. package/packages/table/src/header.ts +642 -581
  99. package/packages/table/src/props.ts +336 -336
  100. package/packages/table/src/store.ts +14 -14
  101. package/packages/table/src/table.ts +16011 -15454
  102. package/packages/table/src/use/cell-view.ts +41 -44
  103. package/packages/table/src/use/index.ts +1 -1
  104. package/packages/table/src/util.ts +1206 -1216
  105. package/packages/toolbar/index.ts +18 -18
  106. package/packages/toolbar/src/toolbar.ts +768 -706
  107. package/packages/ui/index.ts +519 -520
  108. package/packages/ui/src/anime.ts +51 -52
  109. package/packages/ui/src/comp.ts +3 -3
  110. package/packages/ui/src/dom.ts +466 -463
  111. package/packages/ui/src/log.ts +19 -19
  112. package/packages/ui/src/utils.ts +66 -66
  113. package/packages/ui/src/vn.ts +55 -55
  114. package/packages/v-x-e-table/index.d.ts +3 -3
  115. package/packages/v-x-e-table/index.ts +3 -3
  116. package/types/all.d.ts +76 -76
  117. package/types/index.d.ts +4 -4
  118. /package/dist/{iconfont.1793007753347.ttf → iconfont.1793009263429.ttf} +0 -0
  119. /package/dist/{iconfont.1793007753347.woff → iconfont.1793009263429.woff} +0 -0
  120. /package/dist/{iconfont.1793007753347.woff2 → iconfont.1793009263429.woff2} +0 -0
  121. /package/es/{iconfont.1793007753347.ttf → iconfont.1793009263429.ttf} +0 -0
  122. /package/es/{iconfont.1793007753347.woff → iconfont.1793009263429.woff} +0 -0
  123. /package/es/{iconfont.1793007753347.woff2 → iconfont.1793009263429.woff2} +0 -0
  124. /package/lib/{iconfont.1793007753347.ttf → iconfont.1793009263429.ttf} +0 -0
  125. /package/lib/{iconfont.1793007753347.woff → iconfont.1793009263429.woff} +0 -0
  126. /package/lib/{iconfont.1793007753347.woff2 → iconfont.1793009263429.woff2} +0 -0
@@ -1,463 +1,466 @@
1
- import XEUtils from 'xe-utils'
2
-
3
- const reClsMap: { [key: string]: any } = {}
4
-
5
- let tpImgEl: HTMLImageElement | undefined
6
-
7
- export function initTpImg () {
8
- if (!tpImgEl) {
9
- tpImgEl = new Image()
10
- tpImgEl.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
11
- }
12
- return tpImgEl
13
- }
14
-
15
- export function getTpImg () {
16
- if (!tpImgEl) {
17
- return initTpImg()
18
- }
19
- return tpImgEl
20
- }
21
-
22
- export function getPropClass (property: any, params: any) {
23
- return property ? (XEUtils.isFunction(property) ? property(params) : property) || '' : ''
24
- }
25
-
26
- function getClsRE (cls: any) {
27
- if (!reClsMap[cls]) {
28
- reClsMap[cls] = new RegExp(`(?:^|\\s)${cls}(?!\\S)`, 'g')
29
- }
30
- return reClsMap[cls]
31
- }
32
-
33
- function getNodeOffset (elem: any, container: any, rest: any): any {
34
- if (elem) {
35
- const parentElem = elem.parentNode
36
- rest.top += elem.offsetTop
37
- rest.left += elem.offsetLeft
38
- if (parentElem && parentElem !== document.documentElement && parentElem !== document.body) {
39
- rest.top -= parentElem.scrollTop
40
- rest.left -= parentElem.scrollLeft
41
- }
42
- if (container && (elem === container || elem.offsetParent === container) ? 0 : elem.offsetParent) {
43
- return getNodeOffset(elem.offsetParent, container, rest)
44
- }
45
- }
46
- return rest
47
- }
48
-
49
- export function isPx (val: any) {
50
- return val && /^\d+(\.\d+)?(px)?$/.test(val)
51
- }
52
-
53
- export function isScale (val: any) {
54
- return val && /^\d+(\.\d+)?%$/.test(val)
55
- }
56
-
57
- export function hasClass (elem: any, cls: any) {
58
- if (elem) {
59
- if (elem.classList) {
60
- return elem.classList.contains(cls)
61
- }
62
- return !!(elem.className && elem.className.match && elem.className.match(getClsRE(cls)))
63
- }
64
- return false
65
- }
66
-
67
- export function removeClass (elem: any, cls: any) {
68
- if (elem && hasClass(elem, cls)) {
69
- elem.className = elem.className.replace(getClsRE(cls), '')
70
- }
71
- }
72
-
73
- export function addClass (elem: any, cls: string) {
74
- if (elem && !hasClass(elem, cls)) {
75
- removeClass(elem, cls)
76
- elem.className = `${elem.className} ${cls}`
77
- }
78
- }
79
-
80
- export function hasControlKey (evnt: KeyboardEvent | MouseEvent | DragEvent) {
81
- return evnt.ctrlKey || evnt.metaKey
82
- }
83
-
84
- export function toCssUnit (val?: number | string, unit = 'px') {
85
- if (XEUtils.isNumber(val) || /^\d+$/.test(`${val}`)) {
86
- return `${val}${unit}`
87
- }
88
- return `${val || ''}`
89
- }
90
-
91
- export function queryElement (elem: HTMLTableCellElement, selector: string) {
92
- if (elem) {
93
- return elem.querySelector<HTMLElement>(selector)
94
- }
95
- return null
96
- }
97
-
98
- export function getDomNode () {
99
- const documentElement = document.documentElement
100
- const bodyElem = document.body
101
- return {
102
- scrollTop: documentElement.scrollTop || bodyElem.scrollTop,
103
- scrollLeft: documentElement.scrollLeft || bodyElem.scrollLeft,
104
- visibleHeight: documentElement.clientHeight || bodyElem.clientHeight,
105
- visibleWidth: documentElement.clientWidth || bodyElem.clientWidth
106
- }
107
- }
108
-
109
- export function getOffsetHeight (elem?: HTMLElement) {
110
- return elem ? elem.offsetHeight : 0
111
- }
112
-
113
- export function getPaddingTopBottomSize (elem: HTMLElement) {
114
- if (elem) {
115
- const computedStyle = getComputedStyle(elem)
116
- const paddingTop = XEUtils.toNumber(computedStyle.paddingTop)
117
- const paddingBottom = XEUtils.toNumber(computedStyle.paddingBottom)
118
- return paddingTop + paddingBottom
119
- }
120
- return 0
121
- }
122
-
123
- export function setScrollTop (elem: HTMLElement | null | undefined, scrollTop: number) {
124
- if (elem) {
125
- elem.scrollTop = scrollTop
126
- }
127
- }
128
-
129
- export function setScrollLeft (elem: HTMLElement | null | undefined, scrollLeft: number) {
130
- if (elem) {
131
- elem.scrollLeft = scrollLeft
132
- }
133
- }
134
-
135
- // export function setScrollLeftAndTop (elem: HTMLElement | null, scrollLeft: number, scrollTop: number) {
136
- // if (elem) {
137
- // elem.scrollLeft = scrollLeft
138
- // elem.scrollTop = scrollTop
139
- // }
140
- // }
141
-
142
- export function updateCellTitle (overflowElem: any, column: any) {
143
- const content = column.type === 'html' ? overflowElem.innerText : overflowElem.textContent
144
- if (overflowElem.getAttribute('title') !== content) {
145
- overflowElem.setAttribute('title', content)
146
- }
147
- }
148
-
149
- export function checkTargetElement (target: HTMLElement | EventTarget | null, exEls: (HTMLElement | null)[], endEl?: HTMLElement | EventTarget | null) {
150
- let targetEl = target
151
- if (!exEls || !exEls.length) {
152
- return false
153
- }
154
- const [exEl1, exEl2, exEl3] = exEls
155
- while (targetEl) {
156
- if (exEl1 === targetEl || (exEl2 && targetEl === exEl2) || (exEl3 && targetEl === exEl3)) {
157
- return true
158
- }
159
- if (endEl && targetEl === endEl) {
160
- return false
161
- }
162
- targetEl = (targetEl as HTMLElement).parentElement
163
- }
164
- return false
165
- }
166
-
167
- /**
168
- * 检查触发源是否属于目标节点
169
- */
170
- export function getEventTargetNode (evnt: any, container: any, queryCls?: string, queryMethod?: (target: Element) => boolean) {
171
- let targetElem
172
- let target = (evnt.target.shadowRoot && evnt.composed) ? (evnt.composedPath()[0] || evnt.target) : evnt.target
173
- while (target && target.nodeType && target !== document) {
174
- if (queryCls && hasClass(target, queryCls) && (!queryMethod || queryMethod(target))) {
175
- targetElem = target
176
- } else if (target === container) {
177
- return { flag: queryCls ? !!targetElem : true, container, targetElem: targetElem }
178
- }
179
- target = target.parentNode
180
- }
181
- return { flag: false }
182
- }
183
-
184
- /**
185
- * 获取元素相对于 document 的位置
186
- */
187
- export function getOffsetPos (elem: any, container: any) {
188
- return getNodeOffset(elem, container, { left: 0, top: 0 })
189
- }
190
-
191
- export function getAbsolutePos (elem: any) {
192
- const bounding = elem.getBoundingClientRect()
193
- const boundingTop = bounding.top
194
- const boundingLeft = bounding.left
195
- const { scrollTop, scrollLeft, visibleHeight, visibleWidth } = getDomNode()
196
- return { boundingTop, top: scrollTop + boundingTop, boundingLeft, left: scrollLeft + boundingLeft, visibleHeight, visibleWidth }
197
- }
198
-
199
- export function hasEventInputTarget (target: EventTarget | Element | null) {
200
- const tagName = target ? (target as Element).tagName : ''
201
- return tagName && ['input', 'textarea'].includes((tagName.toLowerCase()))
202
- }
203
-
204
- /**
205
- * 判断是否由内部可复用控件触发,输入框带有 vxe-reusekeep-control
206
- */
207
- function hasReusekeepControl (elem: EventTarget | HTMLElement | null) {
208
- if (elem) {
209
- return hasClass(elem as HTMLElement, 'vxe-reusekeep-control')
210
- }
211
- return false
212
- }
213
-
214
- export function hasAxternalInputTarget (target: EventTarget | Element | null) {
215
- return hasEventInputTarget(target) ? !hasReusekeepControl(target) : false
216
- }
217
-
218
- const scrollIntoViewIfNeeded = 'scrollIntoViewIfNeeded'
219
- const scrollIntoView = 'scrollIntoView'
220
-
221
- export function scrollToView (elem: any) {
222
- if (elem) {
223
- if (elem[scrollIntoViewIfNeeded]) {
224
- elem[scrollIntoViewIfNeeded]()
225
- } else if (elem[scrollIntoView]) {
226
- elem[scrollIntoView]()
227
- }
228
- }
229
- }
230
-
231
- export function triggerEvent (targetElem: Element, type: string) {
232
- if (targetElem) {
233
- targetElem.dispatchEvent(new Event(type))
234
- }
235
- }
236
-
237
- export function isNodeElement (elem: any): elem is HTMLElement {
238
- return elem && elem.nodeType === 1
239
- }
240
-
241
- export function scrollTopTo (diffNum: number, cb: (progress: number) => void) {
242
- const duration = Math.abs(diffNum)
243
- const startTime = performance.now()
244
- let countTop = 0
245
- const step = (timestamp: number) => {
246
- let progress = (timestamp - startTime) / duration
247
- if (progress < 0) {
248
- progress = 0
249
- } else if (progress > 1) {
250
- progress = 1
251
- }
252
- const easedProgress = Math.pow(progress, 2)
253
- const offsetTop = Math.floor((diffNum * easedProgress)) - countTop
254
- countTop += offsetTop
255
- cb(offsetTop)
256
- if (progress < 1) {
257
- requestAnimationFrame(step)
258
- }
259
- }
260
- requestAnimationFrame(step)
261
- }
262
-
263
- let wtlFrame: any
264
- export function wheelScrollLeftTo (scrollLeft: number, cb: (offsetLeft: number) => void) {
265
- if (wtlFrame) {
266
- cancelAnimationFrame(wtlFrame)
267
- }
268
- wtlFrame = requestAnimationFrame(() => {
269
- cb(scrollLeft)
270
- wtlFrame = null
271
- })
272
- }
273
-
274
- let wtaFrame: any
275
- export function wheelScrollTopTo (diffNum: number, cb: (progress: number) => void) {
276
- if (wtaFrame) {
277
- cancelAnimationFrame(wtaFrame)
278
- }
279
- wtaFrame = requestAnimationFrame(() => {
280
- const offsetTop = diffNum
281
- cb(offsetTop)
282
- wtaFrame = null
283
- })
284
- }
285
-
286
- interface PanelPlacementOptions {
287
- defaultTop?: number
288
- defaultLeft?: number
289
- placement?: '' | 'top' | 'bottom' | null
290
- defaultPlacement?: '' | 'top' | 'bottom' | null
291
- appendTo?: string | HTMLElement | ((params: any) => string | HTMLElement)
292
- teleportTo?: boolean
293
- marginSize?: number
294
- isMinWidth?: boolean
295
- }
296
-
297
- /**
298
- * 通用定位计算
299
- */
300
- export function updatePanelPlacement (targetElem: HTMLElement | null | undefined, panelElem: HTMLElement | null | undefined, options: PanelPlacementOptions) {
301
- const { defaultTop, defaultLeft, placement, defaultPlacement, appendTo, teleportTo, marginSize, isMinWidth } = Object.assign({
302
- appendTo: '',
303
- teleportTo: false,
304
- marginSize: 18,
305
- isMinWidth: true
306
- }, options)
307
- let panelPlacement: 'top' | 'bottom' = 'bottom'
308
- let top: number | '' = ''
309
- let bottom: number | '' = ''
310
- let left = 0
311
- let minWidth: number | '' = ''
312
- let arrowLeft: number | '' = ''
313
- const stys: Record<string, string> = {}
314
- if (panelElem && targetElem) {
315
- const bodyEl = document.body
316
- const parentWrapperEl = getPopupWrapperElement(teleportTo ? getPopupAppendElement(appendTo) : panelElem)
317
- if (parentWrapperEl) {
318
- const targetWidth = targetElem.offsetWidth
319
- const targetHeight = targetElem.offsetHeight
320
- const panelWidth = panelElem.offsetWidth
321
- const panelHeight = panelElem.offsetHeight
322
-
323
- const parentWrapperRect = parentWrapperEl.getBoundingClientRect()
324
- const panelRect = panelElem.getBoundingClientRect()
325
- const targetRect = targetElem.getBoundingClientRect()
326
- const visibleHeight = bodyEl.clientHeight
327
- const visibleWidth = bodyEl.clientWidth
328
-
329
- const parentWrapperScrollLeft = parentWrapperEl.scrollLeft
330
- const parentWrapperScrollTop = parentWrapperEl.scrollTop
331
- const parentWrapperOffsetLeft = parentWrapperRect.left
332
- const parentWrapperOffsetTop = parentWrapperRect.top
333
- const targetLeft = targetRect.left
334
- const targetTop = targetRect.top
335
-
336
- minWidth = targetElem.offsetWidth
337
-
338
- if (teleportTo) {
339
- left = (defaultLeft || (targetLeft - (panelWidth - targetWidth) / 2)) - parentWrapperScrollLeft
340
- top = (defaultTop || (targetTop + targetHeight)) - parentWrapperScrollTop
341
- if (placement === 'top') {
342
- panelPlacement = 'top'
343
- top = targetTop - panelHeight
344
- } else if (!placement) {
345
- if (defaultPlacement === 'top') {
346
- panelPlacement = 'top'
347
- if (!defaultTop) {
348
- top = targetTop - panelHeight
349
- }
350
- // 如果上面不够放,则向下
351
- if (top < marginSize) {
352
- panelPlacement = 'bottom'
353
- top = targetTop + targetHeight
354
- }
355
- // 如果下面不够放,则向上(优先)
356
- if (top + panelHeight + marginSize > visibleHeight) {
357
- panelPlacement = 'top'
358
- top = targetTop - panelHeight
359
- }
360
- } else {
361
- // 如果下面不够放,则向上
362
- if (top + panelHeight + marginSize > visibleHeight) {
363
- panelPlacement = 'top'
364
- top = targetTop - panelHeight
365
- }
366
- // 如果上面不够放,则向下(优先)
367
- if (top < marginSize) {
368
- panelPlacement = 'bottom'
369
- top = targetTop + targetHeight
370
- }
371
- }
372
- }
373
- // 如果溢出右边
374
- if (left + panelWidth + marginSize > visibleWidth) {
375
- left -= left + panelWidth + marginSize - visibleWidth
376
- }
377
- // 如果溢出左边
378
- if (left < marginSize) {
379
- left = marginSize
380
- }
381
-
382
- // 偏移
383
- top -= parentWrapperOffsetTop
384
- left -= parentWrapperOffsetLeft
385
- } else {
386
- if (placement === 'top') {
387
- panelPlacement = 'top'
388
- bottom = targetHeight
389
- } else if (!placement) {
390
- // 如果下面不够放,则向上
391
- top = targetHeight
392
- if (targetTop + targetHeight + panelHeight + marginSize > visibleHeight) {
393
- // 如果上面不够放,则向下(优先)
394
- if (targetTop - targetHeight - panelHeight > marginSize) {
395
- panelPlacement = 'top'
396
- top = ''
397
- bottom = targetHeight
398
- }
399
- }
400
- }
401
- // 是否超出右侧
402
- if (panelRect.left + panelRect.width + marginSize > visibleWidth) {
403
- left = -(panelRect.left + panelRect.width + marginSize - visibleWidth)
404
- }
405
- }
406
- if (XEUtils.isNumber(top)) {
407
- stys.top = toCssUnit(top)
408
- }
409
- if (XEUtils.isNumber(bottom)) {
410
- stys.bottom = toCssUnit(bottom)
411
- }
412
- if (XEUtils.isNumber(left)) {
413
- stys.left = toCssUnit(left)
414
- }
415
- if (isMinWidth && XEUtils.isNumber(minWidth)) {
416
- stys.minWidth = toCssUnit(minWidth)
417
- }
418
-
419
- // 箭头
420
- if (left === targetLeft) {
421
- if (targetWidth <= panelWidth) {
422
- arrowLeft = targetWidth / 2
423
- }
424
- } else if (left < targetLeft) {
425
- if (left + panelWidth > targetLeft + targetWidth) {
426
- arrowLeft = (targetLeft - left) + targetWidth / 2
427
- } else {
428
- arrowLeft = (targetLeft - left) + (panelWidth - (targetLeft - left)) / 2
429
- }
430
- }
431
- }
432
- }
433
- return {
434
- top: top || 0,
435
- bottom: bottom || 0,
436
- left: left || 0,
437
- arrowLeft: arrowLeft || 0,
438
- style: stys,
439
- placement: panelPlacement
440
- }
441
- }
442
-
443
- export function getPopupWrapperElement (panelElem: HTMLElement | null | undefined) {
444
- if (!panelElem) {
445
- return null
446
- }
447
- const bodyEl = document.body
448
- const parentEl = panelElem.parentElement
449
- return (parentEl === bodyEl ? document.documentElement : parentEl) || null
450
- }
451
-
452
- export function getPopupContainer (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
453
- const selectElem = appendTo && XEUtils.isFunction(appendTo) ? appendTo({}) : appendTo
454
- return selectElem || 'body'
455
- }
456
-
457
- export function getPopupAppendElement (appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
458
- const selectElem = getPopupContainer(appendTo)
459
- if (XEUtils.isString(selectElem)) {
460
- return document.querySelector<HTMLElement>(selectElem) || document.body
461
- }
462
- return selectElem
463
- }
1
+ import XEUtils from 'xe-utils'
2
+
3
+ const reClsMap: { [key: string]: any } = {}
4
+
5
+ let tpImgEl: HTMLImageElement | undefined
6
+
7
+ export function initTpImg() {
8
+ if (!tpImgEl) {
9
+ tpImgEl = new Image()
10
+ tpImgEl.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
11
+ }
12
+ return tpImgEl
13
+ }
14
+
15
+ export function getTpImg() {
16
+ if (!tpImgEl) {
17
+ return initTpImg()
18
+ }
19
+ return tpImgEl
20
+ }
21
+
22
+ export function getPropClass(property: any, params: any) {
23
+ return property ? (XEUtils.isFunction(property) ? property(params) : property) || '' : ''
24
+ }
25
+
26
+ function getClsRE(cls: any) {
27
+ if (!reClsMap[cls]) {
28
+ reClsMap[cls] = new RegExp(`(?:^|\\s)${cls}(?!\\S)`, 'g')
29
+ }
30
+ return reClsMap[cls]
31
+ }
32
+
33
+ function getNodeOffset(elem: any, container: any, rest: any): any {
34
+ if (elem) {
35
+ const parentElem = elem.parentNode
36
+ rest.top += elem.offsetTop
37
+ rest.left += elem.offsetLeft
38
+ if (parentElem && parentElem !== document.documentElement && parentElem !== document.body) {
39
+ rest.top -= parentElem.scrollTop
40
+ rest.left -= parentElem.scrollLeft
41
+ }
42
+ if (container && (elem === container || elem.offsetParent === container) ? 0 : elem.offsetParent) {
43
+ return getNodeOffset(elem.offsetParent, container, rest)
44
+ }
45
+ }
46
+ return rest
47
+ }
48
+
49
+ export function isPx(val: any) {
50
+ return val && /^\d+(\.\d+)?(px)?$/.test(val)
51
+ }
52
+
53
+ export function isScale(val: any) {
54
+ return val && /^\d+(\.\d+)?%$/.test(val)
55
+ }
56
+
57
+ export function hasClass(elem: any, cls: any) {
58
+ if (elem) {
59
+ if (elem.classList) {
60
+ return elem.classList.contains(cls)
61
+ }
62
+ return !!(elem.className && elem.className.match && elem.className.match(getClsRE(cls)))
63
+ }
64
+ return false
65
+ }
66
+
67
+ export function removeClass(elem: any, cls: any) {
68
+ if (elem && hasClass(elem, cls)) {
69
+ elem.className = elem.className.replace(getClsRE(cls), '')
70
+ }
71
+ }
72
+
73
+ export function addClass(elem: any, cls: string) {
74
+ if (elem && !hasClass(elem, cls)) {
75
+ removeClass(elem, cls)
76
+ elem.className = `${elem.className} ${cls}`
77
+ }
78
+ }
79
+
80
+ export function hasControlKey(evnt: KeyboardEvent | MouseEvent | DragEvent) {
81
+ return evnt.ctrlKey || evnt.metaKey
82
+ }
83
+
84
+ export function toCssUnit(val?: number | string, unit = 'px') {
85
+ if (XEUtils.isNumber(val) || /^\d+$/.test(`${val}`)) {
86
+ return `${val}${unit}`
87
+ }
88
+ return `${val || ''}`
89
+ }
90
+
91
+ export function queryElement(elem: HTMLTableCellElement, selector: string) {
92
+ if (elem) {
93
+ return elem.querySelector<HTMLElement>(selector)
94
+ }
95
+ return null
96
+ }
97
+
98
+ export function getDomNode() {
99
+ const documentElement = document.documentElement
100
+ const bodyElem = document.body
101
+ return {
102
+ scrollTop: documentElement.scrollTop || bodyElem.scrollTop,
103
+ scrollLeft: documentElement.scrollLeft || bodyElem.scrollLeft,
104
+ visibleHeight: documentElement.clientHeight || bodyElem.clientHeight,
105
+ visibleWidth: documentElement.clientWidth || bodyElem.clientWidth
106
+ }
107
+ }
108
+
109
+ export function getOffsetHeight(elem?: HTMLElement) {
110
+ return elem ? elem.offsetHeight : 0
111
+ }
112
+
113
+ export function getPaddingTopBottomSize(elem: HTMLElement) {
114
+ if (elem) {
115
+ const computedStyle = getComputedStyle(elem)
116
+ const paddingTop = XEUtils.toNumber(computedStyle.paddingTop)
117
+ const paddingBottom = XEUtils.toNumber(computedStyle.paddingBottom)
118
+ return paddingTop + paddingBottom
119
+ }
120
+ return 0
121
+ }
122
+
123
+ export function setScrollTop(elem: HTMLElement | null | undefined, scrollTop: number) {
124
+ if (elem) {
125
+ elem.scrollTop = scrollTop
126
+ }
127
+ }
128
+
129
+ export function setScrollLeft(elem: HTMLElement | null | undefined, scrollLeft: number) {
130
+ if (elem) {
131
+ elem.scrollLeft = scrollLeft
132
+ }
133
+ }
134
+
135
+ // export function setScrollLeftAndTop (elem: HTMLElement | null, scrollLeft: number, scrollTop: number) {
136
+ // if (elem) {
137
+ // elem.scrollLeft = scrollLeft
138
+ // elem.scrollTop = scrollTop
139
+ // }
140
+ // }
141
+
142
+ export function updateCellTitle(overflowElem: any, column: any) {
143
+ const content = column.type === 'html' ? overflowElem.innerText : overflowElem.textContent
144
+ if (overflowElem.getAttribute('title') !== content) {
145
+ overflowElem.setAttribute('title', content)
146
+ }
147
+ }
148
+
149
+ export function checkTargetElement(target: HTMLElement | EventTarget | null, exEls: (HTMLElement | null)[], endEl?: HTMLElement | EventTarget | null) {
150
+ let targetEl = target
151
+ if (!exEls || !exEls.length) {
152
+ return false
153
+ }
154
+ const [exEl1, exEl2, exEl3] = exEls
155
+ while (targetEl) {
156
+ if (exEl1 === targetEl || (exEl2 && targetEl === exEl2) || (exEl3 && targetEl === exEl3)) {
157
+ return true
158
+ }
159
+ if (endEl && targetEl === endEl) {
160
+ return false
161
+ }
162
+ targetEl = (targetEl as HTMLElement).parentElement
163
+ }
164
+ return false
165
+ }
166
+
167
+ /**
168
+ * 检查触发源是否属于目标节点
169
+ */
170
+ export function getEventTargetNode(evnt: any, container: any, queryCls?: string, queryMethod?: (target: Element) => boolean) {
171
+ let targetElem
172
+ let target = evnt.target.shadowRoot && evnt.composed ? evnt.composedPath()[0] || evnt.target : evnt.target
173
+ while (target && target.nodeType && target !== document) {
174
+ if (queryCls && hasClass(target, queryCls) && (!queryMethod || queryMethod(target))) {
175
+ targetElem = target
176
+ } else if (target === container) {
177
+ return { flag: queryCls ? !!targetElem : true, container, targetElem: targetElem }
178
+ }
179
+ target = target.parentNode
180
+ }
181
+ return { flag: false }
182
+ }
183
+
184
+ /**
185
+ * 获取元素相对于 document 的位置
186
+ */
187
+ export function getOffsetPos(elem: any, container: any) {
188
+ return getNodeOffset(elem, container, { left: 0, top: 0 })
189
+ }
190
+
191
+ export function getAbsolutePos(elem: any) {
192
+ const bounding = elem.getBoundingClientRect()
193
+ const boundingTop = bounding.top
194
+ const boundingLeft = bounding.left
195
+ const { scrollTop, scrollLeft, visibleHeight, visibleWidth } = getDomNode()
196
+ return { boundingTop, top: scrollTop + boundingTop, boundingLeft, left: scrollLeft + boundingLeft, visibleHeight, visibleWidth }
197
+ }
198
+
199
+ export function hasEventInputTarget(target: EventTarget | Element | null) {
200
+ const tagName = target ? (target as Element).tagName : ''
201
+ return tagName && ['input', 'textarea'].includes(tagName.toLowerCase())
202
+ }
203
+
204
+ /**
205
+ * 判断是否由内部可复用控件触发,输入框带有 vxe-reusekeep-control
206
+ */
207
+ function hasReusekeepControl(elem: EventTarget | HTMLElement | null) {
208
+ if (elem) {
209
+ return hasClass(elem as HTMLElement, 'vxe-reusekeep-control')
210
+ }
211
+ return false
212
+ }
213
+
214
+ export function hasAxternalInputTarget(target: EventTarget | Element | null) {
215
+ return hasEventInputTarget(target) ? !hasReusekeepControl(target) : false
216
+ }
217
+
218
+ const scrollIntoViewIfNeeded = 'scrollIntoViewIfNeeded'
219
+ const scrollIntoView = 'scrollIntoView'
220
+
221
+ export function scrollToView(elem: any) {
222
+ if (elem) {
223
+ if (elem[scrollIntoViewIfNeeded]) {
224
+ elem[scrollIntoViewIfNeeded]()
225
+ } else if (elem[scrollIntoView]) {
226
+ elem[scrollIntoView]()
227
+ }
228
+ }
229
+ }
230
+
231
+ export function triggerEvent(targetElem: Element, type: string) {
232
+ if (targetElem) {
233
+ targetElem.dispatchEvent(new Event(type))
234
+ }
235
+ }
236
+
237
+ export function isNodeElement(elem: any): elem is HTMLElement {
238
+ return elem && elem.nodeType === 1
239
+ }
240
+
241
+ export function scrollTopTo(diffNum: number, cb: (progress: number) => void) {
242
+ const duration = Math.abs(diffNum)
243
+ const startTime = performance.now()
244
+ let countTop = 0
245
+ const step = (timestamp: number) => {
246
+ let progress = (timestamp - startTime) / duration
247
+ if (progress < 0) {
248
+ progress = 0
249
+ } else if (progress > 1) {
250
+ progress = 1
251
+ }
252
+ const easedProgress = Math.pow(progress, 2)
253
+ const offsetTop = Math.floor(diffNum * easedProgress) - countTop
254
+ countTop += offsetTop
255
+ cb(offsetTop)
256
+ if (progress < 1) {
257
+ requestAnimationFrame(step)
258
+ }
259
+ }
260
+ requestAnimationFrame(step)
261
+ }
262
+
263
+ let wtlFrame: any
264
+ export function wheelScrollLeftTo(scrollLeft: number, cb: (offsetLeft: number) => void) {
265
+ if (wtlFrame) {
266
+ cancelAnimationFrame(wtlFrame)
267
+ }
268
+ wtlFrame = requestAnimationFrame(() => {
269
+ cb(scrollLeft)
270
+ wtlFrame = null
271
+ })
272
+ }
273
+
274
+ let wtaFrame: any
275
+ export function wheelScrollTopTo(diffNum: number, cb: (progress: number) => void) {
276
+ if (wtaFrame) {
277
+ cancelAnimationFrame(wtaFrame)
278
+ }
279
+ wtaFrame = requestAnimationFrame(() => {
280
+ const offsetTop = diffNum
281
+ cb(offsetTop)
282
+ wtaFrame = null
283
+ })
284
+ }
285
+
286
+ interface PanelPlacementOptions {
287
+ defaultTop?: number
288
+ defaultLeft?: number
289
+ placement?: '' | 'top' | 'bottom' | null
290
+ defaultPlacement?: '' | 'top' | 'bottom' | null
291
+ appendTo?: string | HTMLElement | ((params: any) => string | HTMLElement)
292
+ teleportTo?: boolean
293
+ marginSize?: number
294
+ isMinWidth?: boolean
295
+ }
296
+
297
+ /**
298
+ * 通用定位计算
299
+ */
300
+ export function updatePanelPlacement(targetElem: HTMLElement | null | undefined, panelElem: HTMLElement | null | undefined, options: PanelPlacementOptions) {
301
+ const { defaultTop, defaultLeft, placement, defaultPlacement, appendTo, teleportTo, marginSize, isMinWidth } = Object.assign(
302
+ {
303
+ appendTo: '',
304
+ teleportTo: false,
305
+ marginSize: 18,
306
+ isMinWidth: true
307
+ },
308
+ options
309
+ )
310
+ let panelPlacement: 'top' | 'bottom' = 'bottom'
311
+ let top: number | '' = ''
312
+ let bottom: number | '' = ''
313
+ let left = 0
314
+ let minWidth: number | '' = ''
315
+ let arrowLeft: number | '' = ''
316
+ const stys: Record<string, string> = {}
317
+ if (panelElem && targetElem) {
318
+ const bodyEl = document.body
319
+ const parentWrapperEl = getPopupWrapperElement(teleportTo ? getPopupAppendElement(appendTo) : panelElem)
320
+ if (parentWrapperEl) {
321
+ const targetWidth = targetElem.offsetWidth
322
+ const targetHeight = targetElem.offsetHeight
323
+ const panelWidth = panelElem.offsetWidth
324
+ const panelHeight = panelElem.offsetHeight
325
+
326
+ const parentWrapperRect = parentWrapperEl.getBoundingClientRect()
327
+ const panelRect = panelElem.getBoundingClientRect()
328
+ const targetRect = targetElem.getBoundingClientRect()
329
+ const visibleHeight = bodyEl.clientHeight
330
+ const visibleWidth = bodyEl.clientWidth
331
+
332
+ const parentWrapperScrollLeft = parentWrapperEl.scrollLeft
333
+ const parentWrapperScrollTop = parentWrapperEl.scrollTop
334
+ const parentWrapperOffsetLeft = parentWrapperRect.left
335
+ const parentWrapperOffsetTop = parentWrapperRect.top
336
+ const targetLeft = targetRect.left
337
+ const targetTop = targetRect.top
338
+
339
+ minWidth = targetElem.offsetWidth
340
+
341
+ if (teleportTo) {
342
+ left = (defaultLeft || targetLeft - (panelWidth - targetWidth) / 2) - parentWrapperScrollLeft
343
+ top = (defaultTop || targetTop + targetHeight) - parentWrapperScrollTop
344
+ if (placement === 'top') {
345
+ panelPlacement = 'top'
346
+ top = targetTop - panelHeight
347
+ } else if (!placement) {
348
+ if (defaultPlacement === 'top') {
349
+ panelPlacement = 'top'
350
+ if (!defaultTop) {
351
+ top = targetTop - panelHeight
352
+ }
353
+ // 如果上面不够放,则向下
354
+ if (top < marginSize) {
355
+ panelPlacement = 'bottom'
356
+ top = targetTop + targetHeight
357
+ }
358
+ // 如果下面不够放,则向上(优先)
359
+ if (top + panelHeight + marginSize > visibleHeight) {
360
+ panelPlacement = 'top'
361
+ top = targetTop - panelHeight
362
+ }
363
+ } else {
364
+ // 如果下面不够放,则向上
365
+ if (top + panelHeight + marginSize > visibleHeight) {
366
+ panelPlacement = 'top'
367
+ top = targetTop - panelHeight
368
+ }
369
+ // 如果上面不够放,则向下(优先)
370
+ if (top < marginSize) {
371
+ panelPlacement = 'bottom'
372
+ top = targetTop + targetHeight
373
+ }
374
+ }
375
+ }
376
+ // 如果溢出右边
377
+ if (left + panelWidth + marginSize > visibleWidth) {
378
+ left -= left + panelWidth + marginSize - visibleWidth
379
+ }
380
+ // 如果溢出左边
381
+ if (left < marginSize) {
382
+ left = marginSize
383
+ }
384
+
385
+ // 偏移
386
+ top -= parentWrapperOffsetTop
387
+ left -= parentWrapperOffsetLeft
388
+ } else {
389
+ if (placement === 'top') {
390
+ panelPlacement = 'top'
391
+ bottom = targetHeight
392
+ } else if (!placement) {
393
+ // 如果下面不够放,则向上
394
+ top = targetHeight
395
+ if (targetTop + targetHeight + panelHeight + marginSize > visibleHeight) {
396
+ // 如果上面不够放,则向下(优先)
397
+ if (targetTop - targetHeight - panelHeight > marginSize) {
398
+ panelPlacement = 'top'
399
+ top = ''
400
+ bottom = targetHeight
401
+ }
402
+ }
403
+ }
404
+ // 是否超出右侧
405
+ if (panelRect.left + panelRect.width + marginSize > visibleWidth) {
406
+ left = -(panelRect.left + panelRect.width + marginSize - visibleWidth)
407
+ }
408
+ }
409
+ if (XEUtils.isNumber(top)) {
410
+ stys.top = toCssUnit(top)
411
+ }
412
+ if (XEUtils.isNumber(bottom)) {
413
+ stys.bottom = toCssUnit(bottom)
414
+ }
415
+ if (XEUtils.isNumber(left)) {
416
+ stys.left = toCssUnit(left)
417
+ }
418
+ if (isMinWidth && XEUtils.isNumber(minWidth)) {
419
+ stys.minWidth = toCssUnit(minWidth)
420
+ }
421
+
422
+ // 箭头
423
+ if (left === targetLeft) {
424
+ if (targetWidth <= panelWidth) {
425
+ arrowLeft = targetWidth / 2
426
+ }
427
+ } else if (left < targetLeft) {
428
+ if (left + panelWidth > targetLeft + targetWidth) {
429
+ arrowLeft = targetLeft - left + targetWidth / 2
430
+ } else {
431
+ arrowLeft = targetLeft - left + (panelWidth - (targetLeft - left)) / 2
432
+ }
433
+ }
434
+ }
435
+ }
436
+ return {
437
+ top: top || 0,
438
+ bottom: bottom || 0,
439
+ left: left || 0,
440
+ arrowLeft: arrowLeft || 0,
441
+ style: stys,
442
+ placement: panelPlacement
443
+ }
444
+ }
445
+
446
+ export function getPopupWrapperElement(panelElem: HTMLElement | null | undefined) {
447
+ if (!panelElem) {
448
+ return null
449
+ }
450
+ const bodyEl = document.body
451
+ const parentEl = panelElem.parentElement
452
+ return (parentEl === bodyEl ? document.documentElement : parentEl) || null
453
+ }
454
+
455
+ export function getPopupContainer(appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
456
+ const selectElem = appendTo && XEUtils.isFunction(appendTo) ? appendTo({}) : appendTo
457
+ return selectElem || 'body'
458
+ }
459
+
460
+ export function getPopupAppendElement(appendTo: string | HTMLElement | ((params: any) => string | HTMLElement) | undefined) {
461
+ const selectElem = getPopupContainer(appendTo)
462
+ if (XEUtils.isString(selectElem)) {
463
+ return document.querySelector<HTMLElement>(selectElem) || document.body
464
+ }
465
+ return selectElem
466
+ }