vxe-table 4.23.7 → 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 (148) hide show
  1. package/dist/all.esm.js +5859 -4018
  2. package/es/colgroup/index.js +1 -1
  3. package/es/column/index.js +1 -1
  4. package/es/components.d.ts +3 -0
  5. package/es/components.js +4 -8
  6. package/es/grid/index.js +1 -1
  7. package/es/grid/src/emits.js +1 -15
  8. package/es/grid/src/grid.js +398 -121
  9. package/es/grid/src/props.js +1 -1
  10. package/es/index.esm.js +6 -0
  11. package/es/index.js +6 -0
  12. package/es/table/index.js +1 -1
  13. package/es/table/module/custom/hook.js +50 -43
  14. package/es/table/module/custom/panel.js +778 -528
  15. package/es/table/module/edit/hook.js +141 -63
  16. package/es/table/module/export/export-panel.js +400 -317
  17. package/es/table/module/export/hook.js +396 -338
  18. package/es/table/module/export/import-panel.js +153 -124
  19. package/es/table/module/filter/hook.js +17 -3
  20. package/es/table/module/filter/panel.js +147 -85
  21. package/es/table/module/keyboard/hook.js +9 -5
  22. package/es/table/module/menu/hook.js +1 -1
  23. package/es/table/module/menu/panel.js +198 -127
  24. package/es/table/module/validator/hook.js +1 -1
  25. package/es/table/render/index.js +152 -99
  26. package/es/table/src/body.js +356 -234
  27. package/es/table/src/cell.js +427 -270
  28. package/es/table/src/columnInfo.js +2 -1
  29. package/es/table/src/footer.js +145 -100
  30. package/es/table/src/group.js +7 -3
  31. package/es/table/src/header.js +230 -173
  32. package/es/table/src/props.js +1 -1
  33. package/es/table/src/table.js +1504 -1031
  34. package/es/table/src/util.js +15 -19
  35. package/es/toolbar/index.js +1 -1
  36. package/es/toolbar/src/toolbar.js +133 -76
  37. package/es/ui/index.d.ts +0 -1
  38. package/es/ui/index.js +1 -2
  39. package/es/ui/src/dom.js +9 -6
  40. package/es/ui/src/log.js +1 -1
  41. package/es/ui/src/utils.d.ts +1 -1
  42. package/es/v-x-e-table/index.d.ts +0 -1
  43. package/es/v-x-e-table/index.js +0 -1
  44. package/lib/colgroup/index.js +5 -5
  45. package/lib/column/index.js +5 -5
  46. package/lib/components.js +8 -12
  47. package/lib/grid/index.js +4 -4
  48. package/lib/grid/src/emits.js +1 -15
  49. package/lib/grid/src/grid.js +419 -142
  50. package/lib/grid/src/props.js +2 -2
  51. package/lib/index.common.js +6 -0
  52. package/lib/index.js +6 -0
  53. package/lib/index.umd.js +5825 -3945
  54. package/lib/index.umd.min.js +3 -3
  55. package/lib/table/index.js +5 -5
  56. package/lib/table/module/custom/hook.js +51 -44
  57. package/lib/table/module/custom/panel.js +790 -540
  58. package/lib/table/module/edit/hook.js +142 -64
  59. package/lib/table/module/export/export-panel.js +406 -323
  60. package/lib/table/module/export/hook.js +419 -361
  61. package/lib/table/module/export/import-panel.js +157 -128
  62. package/lib/table/module/filter/hook.js +18 -4
  63. package/lib/table/module/filter/panel.js +149 -87
  64. package/lib/table/module/keyboard/hook.js +10 -6
  65. package/lib/table/module/menu/hook.js +2 -2
  66. package/lib/table/module/menu/panel.js +199 -128
  67. package/lib/table/module/validator/hook.js +2 -2
  68. package/lib/table/render/index.js +153 -100
  69. package/lib/table/src/body.js +357 -235
  70. package/lib/table/src/cell.js +428 -271
  71. package/lib/table/src/columnInfo.js +3 -2
  72. package/lib/table/src/footer.js +146 -101
  73. package/lib/table/src/group.js +7 -3
  74. package/lib/table/src/header.js +231 -174
  75. package/lib/table/src/props.js +2 -2
  76. package/lib/table/src/table.js +1487 -1045
  77. package/lib/table/src/util.js +15 -19
  78. package/lib/toolbar/index.js +4 -4
  79. package/lib/toolbar/src/toolbar.js +135 -78
  80. package/lib/ui/index.js +1 -3
  81. package/lib/ui/src/dom.js +9 -6
  82. package/lib/ui/src/log.js +1 -1
  83. package/lib/v-x-e-table/index.js +0 -2
  84. package/package.json +8 -3
  85. package/packages/colgroup/index.ts +22 -22
  86. package/packages/column/index.ts +22 -22
  87. package/packages/components.ts +41 -43
  88. package/packages/grid/index.ts +18 -18
  89. package/packages/grid/src/emits.ts +5 -19
  90. package/packages/grid/src/grid.ts +2229 -1925
  91. package/packages/grid/src/props.ts +22 -23
  92. package/packages/index.ts +11 -4
  93. package/packages/locale/lang/fr-FR.ts +15 -15
  94. package/packages/locale/lang/it-IT.ts +4 -4
  95. package/packages/locale/lang/uk-UA.ts +1 -1
  96. package/packages/locale/lang/uz-UZ.ts +13 -13
  97. package/packages/locale/lang/zh-CN.ts +907 -907
  98. package/packages/table/index.ts +26 -26
  99. package/packages/table/module/custom/hook.ts +510 -503
  100. package/packages/table/module/custom/panel.ts +2002 -1743
  101. package/packages/table/module/edit/hook.ts +1224 -1131
  102. package/packages/table/module/export/export-panel.ts +697 -611
  103. package/packages/table/module/export/hook.ts +2160 -2059
  104. package/packages/table/module/export/import-panel.ts +319 -279
  105. package/packages/table/module/export/util.ts +25 -24
  106. package/packages/table/module/filter/hook.ts +519 -501
  107. package/packages/table/module/filter/panel.ts +368 -304
  108. package/packages/table/module/keyboard/hook.ts +498 -494
  109. package/packages/table/module/menu/hook.ts +330 -330
  110. package/packages/table/module/menu/panel.ts +272 -201
  111. package/packages/table/module/validator/hook.ts +653 -635
  112. package/packages/table/render/index.ts +1819 -1744
  113. package/packages/table/src/body.ts +1078 -955
  114. package/packages/table/src/cell.ts +1524 -1359
  115. package/packages/table/src/column.ts +192 -192
  116. package/packages/table/src/columnInfo.ts +232 -232
  117. package/packages/table/src/emits.ts +134 -134
  118. package/packages/table/src/footer.ts +425 -380
  119. package/packages/table/src/group.ts +67 -63
  120. package/packages/table/src/header.ts +642 -581
  121. package/packages/table/src/props.ts +336 -336
  122. package/packages/table/src/store.ts +14 -14
  123. package/packages/table/src/table.ts +16011 -15454
  124. package/packages/table/src/use/cell-view.ts +41 -44
  125. package/packages/table/src/use/index.ts +1 -1
  126. package/packages/table/src/util.ts +1206 -1216
  127. package/packages/toolbar/index.ts +18 -18
  128. package/packages/toolbar/src/toolbar.ts +768 -706
  129. package/packages/ui/index.ts +519 -521
  130. package/packages/ui/src/anime.ts +51 -52
  131. package/packages/ui/src/comp.ts +3 -3
  132. package/packages/ui/src/dom.ts +466 -463
  133. package/packages/ui/src/log.ts +19 -19
  134. package/packages/ui/src/utils.ts +66 -66
  135. package/packages/ui/src/vn.ts +55 -55
  136. package/packages/v-x-e-table/index.d.ts +3 -4
  137. package/packages/v-x-e-table/index.ts +3 -4
  138. package/types/all.d.ts +76 -76
  139. package/types/index.d.ts +4 -4
  140. /package/dist/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  141. /package/dist/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  142. /package/dist/{iconfont.1792979665397.woff2 → iconfont.1793009263429.woff2} +0 -0
  143. /package/es/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  144. /package/es/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  145. /package/es/{iconfont.1792979665397.woff2 → iconfont.1793009263429.woff2} +0 -0
  146. /package/lib/{iconfont.1792979665397.ttf → iconfont.1793009263429.ttf} +0 -0
  147. /package/lib/{iconfont.1792979665397.woff → iconfont.1793009263429.woff} +0 -0
  148. /package/lib/{iconfont.1792979665397.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
+ }