resolver-egretimp-plus 0.1.30 → 0.1.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/h5/index.js +18 -18
- package/dist/theme/element/index.css +1 -1
- package/dist/theme/element/src/components/form.scss +2 -0
- package/dist/web/index.js +128 -128
- package/dist/web/index.js.LICENSE.txt +15 -0
- package/package.json +5 -1
- package/scripts/webpack.config.js +18 -2
- package/src/components/packages-web/CustomComponentTable.jsx +8 -5
- package/src/components/table/index.ts +29 -0
- package/src/components/table/src/composables/use-scrollbar.ts +30 -0
- package/src/components/table/src/config.ts +256 -0
- package/src/components/table/src/filter-panel.vue +260 -0
- package/src/components/table/src/h-helper.ts +34 -0
- package/src/components/table/src/layout-observer.ts +78 -0
- package/src/components/table/src/store/current.ts +85 -0
- package/src/components/table/src/store/expand.ts +76 -0
- package/src/components/table/src/store/helper.ts +74 -0
- package/src/components/table/src/store/index.ts +246 -0
- package/src/components/table/src/store/tree.ts +230 -0
- package/src/components/table/src/store/watcher.ts +543 -0
- package/src/components/table/src/table/defaults.ts +402 -0
- package/src/components/table/src/table/key-render-helper.ts +27 -0
- package/src/components/table/src/table/style-helper.ts +378 -0
- package/src/components/table/src/table/utils-helper.ts +47 -0
- package/src/components/table/src/table-body/defaults.ts +52 -0
- package/src/components/table/src/table-body/events-helper.ts +203 -0
- package/src/components/table/src/table-body/index.ts +119 -0
- package/src/components/table/src/table-body/render-helper.ts +283 -0
- package/src/components/table/src/table-body/styles-helper.ts +164 -0
- package/src/components/table/src/table-column/defaults.ts +237 -0
- package/src/components/table/src/table-column/index.ts +202 -0
- package/src/components/table/src/table-column/render-helper.ts +214 -0
- package/src/components/table/src/table-column/watcher-helper.ts +88 -0
- package/src/components/table/src/table-footer/index.ts +128 -0
- package/src/components/table/src/table-footer/mapState-helper.ts +33 -0
- package/src/components/table/src/table-footer/style-helper.ts +51 -0
- package/src/components/table/src/table-header/event-helper.ts +213 -0
- package/src/components/table/src/table-header/index.ts +244 -0
- package/src/components/table/src/table-header/style.helper.ts +119 -0
- package/src/components/table/src/table-header/utils-helper.ts +94 -0
- package/src/components/table/src/table-layout.ts +259 -0
- package/src/components/table/src/table.vue +389 -0
- package/src/components/table/src/tableColumn.ts +3 -0
- package/src/components/table/src/tokens.ts +5 -0
- package/src/components/table/src/util.ts +521 -0
- package/src/components/table/style/css.ts +5 -0
- package/src/components/table/style/index.ts +5 -0
- package/src/theme/element/components/form.scss +2 -0
- package/tsconfig.json +19 -0
- package/vue-shims.d.ts +4 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import {
|
|
3
|
+
computed,
|
|
4
|
+
nextTick,
|
|
5
|
+
onMounted,
|
|
6
|
+
ref,
|
|
7
|
+
unref,
|
|
8
|
+
watch,
|
|
9
|
+
watchEffect,
|
|
10
|
+
} from 'vue'
|
|
11
|
+
import { useEventListener, useResizeObserver } from '@vueuse/core'
|
|
12
|
+
import { useFormSize } from 'element-plus/es/components/form/index.mjs'
|
|
13
|
+
|
|
14
|
+
import type { Table, TableProps } from './defaults'
|
|
15
|
+
import type { Store } from '../store'
|
|
16
|
+
import type TableLayout from '../table-layout'
|
|
17
|
+
import type { TableColumnCtx } from '../table-column/defaults'
|
|
18
|
+
|
|
19
|
+
function useStyle<T>(
|
|
20
|
+
props: TableProps<T>,
|
|
21
|
+
layout: TableLayout<T>,
|
|
22
|
+
store: Store<T>,
|
|
23
|
+
table: Table<T>
|
|
24
|
+
) {
|
|
25
|
+
const isHidden = ref(false)
|
|
26
|
+
const renderExpanded = ref(null)
|
|
27
|
+
const resizeProxyVisible = ref(false)
|
|
28
|
+
const setDragVisible = (visible: boolean) => {
|
|
29
|
+
resizeProxyVisible.value = visible
|
|
30
|
+
}
|
|
31
|
+
const resizeState = ref<{
|
|
32
|
+
width: null | number
|
|
33
|
+
height: null | number
|
|
34
|
+
headerHeight: null | number
|
|
35
|
+
}>({
|
|
36
|
+
width: null,
|
|
37
|
+
height: null,
|
|
38
|
+
headerHeight: null,
|
|
39
|
+
})
|
|
40
|
+
const isGroup = ref(false)
|
|
41
|
+
const scrollbarViewStyle = {
|
|
42
|
+
display: 'inline-block',
|
|
43
|
+
verticalAlign: 'middle',
|
|
44
|
+
}
|
|
45
|
+
const tableWidth = ref()
|
|
46
|
+
const tableScrollHeight = ref(0)
|
|
47
|
+
const bodyScrollHeight = ref(0)
|
|
48
|
+
const headerScrollHeight = ref(0)
|
|
49
|
+
const footerScrollHeight = ref(0)
|
|
50
|
+
const appendScrollHeight = ref(0)
|
|
51
|
+
|
|
52
|
+
watchEffect(() => {
|
|
53
|
+
layout.setHeight(props.height)
|
|
54
|
+
})
|
|
55
|
+
watchEffect(() => {
|
|
56
|
+
layout.setMaxHeight(props.maxHeight)
|
|
57
|
+
})
|
|
58
|
+
watch(
|
|
59
|
+
() => [props.currentRowKey, store.states.rowKey],
|
|
60
|
+
([currentRowKey, rowKey]) => {
|
|
61
|
+
if (!unref(rowKey) || !unref(currentRowKey)) return
|
|
62
|
+
store.setCurrentRowKey(`${currentRowKey}`)
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
immediate: true,
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
watch(
|
|
69
|
+
() => props.data,
|
|
70
|
+
(data) => {
|
|
71
|
+
table.store.commit('setData', data)
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
immediate: true,
|
|
75
|
+
deep: true,
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
watchEffect(() => {
|
|
79
|
+
if (props.expandRowKeys) {
|
|
80
|
+
store.setExpandRowKeysAdapter(props.expandRowKeys)
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
const handleMouseLeave = () => {
|
|
85
|
+
table.store.commit('setHoverRow', null)
|
|
86
|
+
if (table.hoverState) table.hoverState = null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const handleHeaderFooterMousewheel = (event, data) => {
|
|
90
|
+
const { pixelX, pixelY } = data
|
|
91
|
+
if (Math.abs(pixelX) >= Math.abs(pixelY)) {
|
|
92
|
+
table.refs.bodyWrapper.scrollLeft += data.pixelX / 5
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const shouldUpdateHeight = computed(() => {
|
|
97
|
+
return (
|
|
98
|
+
props.height ||
|
|
99
|
+
props.maxHeight ||
|
|
100
|
+
store.states.fixedColumns.value.length > 0 ||
|
|
101
|
+
store.states.rightFixedColumns.value.length > 0
|
|
102
|
+
)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const tableBodyStyles = computed(() => {
|
|
106
|
+
return {
|
|
107
|
+
width: layout.bodyWidth.value ? `${layout.bodyWidth.value}px` : '',
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const doLayout = () => {
|
|
112
|
+
if (shouldUpdateHeight.value) {
|
|
113
|
+
layout.updateElsHeight()
|
|
114
|
+
}
|
|
115
|
+
layout.updateColumnsWidth()
|
|
116
|
+
requestAnimationFrame(syncPosition)
|
|
117
|
+
}
|
|
118
|
+
onMounted(async () => {
|
|
119
|
+
await nextTick()
|
|
120
|
+
store.updateColumns()
|
|
121
|
+
bindEvents()
|
|
122
|
+
requestAnimationFrame(doLayout)
|
|
123
|
+
|
|
124
|
+
const el: HTMLElement = table.vnode.el as HTMLElement
|
|
125
|
+
const tableHeader: HTMLElement = table.refs.headerWrapper
|
|
126
|
+
if (props.flexible && el && el.parentElement) {
|
|
127
|
+
// Automatic minimum size of flex-items
|
|
128
|
+
// Ensure that the main axis does not follow the width of the items
|
|
129
|
+
el.parentElement.style.minWidth = '0'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
resizeState.value = {
|
|
133
|
+
width: (tableWidth.value = el.offsetWidth),
|
|
134
|
+
height: el.offsetHeight,
|
|
135
|
+
headerHeight:
|
|
136
|
+
props.showHeader && tableHeader ? tableHeader.offsetHeight : null,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// init filters
|
|
140
|
+
store.states.columns.value.forEach((column: TableColumnCtx<T>) => {
|
|
141
|
+
if (column.filteredValue && column.filteredValue.length) {
|
|
142
|
+
table.store.commit('filterChange', {
|
|
143
|
+
column,
|
|
144
|
+
values: column.filteredValue,
|
|
145
|
+
silent: true,
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
table.$ready = true
|
|
150
|
+
})
|
|
151
|
+
const setScrollClassByEl = (el: HTMLElement, className: string) => {
|
|
152
|
+
if (!el) return
|
|
153
|
+
const classList = Array.from(el.classList).filter(
|
|
154
|
+
(item) => !item.startsWith('is-scrolling-')
|
|
155
|
+
)
|
|
156
|
+
classList.push(layout.scrollX.value ? className : 'is-scrolling-none')
|
|
157
|
+
el.className = classList.join(' ')
|
|
158
|
+
}
|
|
159
|
+
const setScrollClass = (className: string) => {
|
|
160
|
+
const { tableWrapper } = table.refs
|
|
161
|
+
setScrollClassByEl(tableWrapper, className)
|
|
162
|
+
}
|
|
163
|
+
const hasScrollClass = (className: string) => {
|
|
164
|
+
const { tableWrapper } = table.refs
|
|
165
|
+
return !!(tableWrapper && tableWrapper.classList.contains(className))
|
|
166
|
+
}
|
|
167
|
+
const syncPosition = function () {
|
|
168
|
+
if (!table.refs.scrollBarRef) return
|
|
169
|
+
if (!layout.scrollX.value) {
|
|
170
|
+
const scrollingNoneClass = 'is-scrolling-none'
|
|
171
|
+
if (!hasScrollClass(scrollingNoneClass)) {
|
|
172
|
+
setScrollClass(scrollingNoneClass)
|
|
173
|
+
}
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
const scrollContainer = table.refs.scrollBarRef.wrapRef
|
|
177
|
+
if (!scrollContainer) return
|
|
178
|
+
const { scrollLeft, offsetWidth, scrollWidth } = scrollContainer
|
|
179
|
+
const { headerWrapper, footerWrapper } = table.refs
|
|
180
|
+
if (headerWrapper) headerWrapper.scrollLeft = scrollLeft
|
|
181
|
+
if (footerWrapper) footerWrapper.scrollLeft = scrollLeft
|
|
182
|
+
const maxScrollLeftPosition = scrollWidth - offsetWidth - 1
|
|
183
|
+
if (scrollLeft >= maxScrollLeftPosition) {
|
|
184
|
+
setScrollClass('is-scrolling-right')
|
|
185
|
+
} else if (scrollLeft === 0) {
|
|
186
|
+
setScrollClass('is-scrolling-left')
|
|
187
|
+
} else {
|
|
188
|
+
setScrollClass('is-scrolling-middle')
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const bindEvents = () => {
|
|
193
|
+
if (!table.refs.scrollBarRef) return
|
|
194
|
+
if (table.refs.scrollBarRef.wrapRef) {
|
|
195
|
+
useEventListener(
|
|
196
|
+
table.refs.scrollBarRef.wrapRef,
|
|
197
|
+
'scroll',
|
|
198
|
+
syncPosition,
|
|
199
|
+
{
|
|
200
|
+
passive: true,
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
if (props.fit) {
|
|
205
|
+
useResizeObserver(table.vnode.el as HTMLElement, resizeListener)
|
|
206
|
+
} else {
|
|
207
|
+
useEventListener(window, 'resize', resizeListener)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
useResizeObserver(table.refs.bodyWrapper, () => {
|
|
211
|
+
resizeListener()
|
|
212
|
+
table.refs?.scrollBarRef?.update()
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
const resizeListener = () => {
|
|
216
|
+
const el = table.vnode.el
|
|
217
|
+
if (!table.$ready || !el) return
|
|
218
|
+
|
|
219
|
+
let shouldUpdateLayout = false
|
|
220
|
+
const {
|
|
221
|
+
width: oldWidth,
|
|
222
|
+
height: oldHeight,
|
|
223
|
+
headerHeight: oldHeaderHeight,
|
|
224
|
+
} = resizeState.value
|
|
225
|
+
|
|
226
|
+
const width = (tableWidth.value = el.offsetWidth)
|
|
227
|
+
if (oldWidth !== width) {
|
|
228
|
+
shouldUpdateLayout = true
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const height = el.offsetHeight
|
|
232
|
+
if ((props.height || shouldUpdateHeight.value) && oldHeight !== height) {
|
|
233
|
+
shouldUpdateLayout = true
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const tableHeader: HTMLElement =
|
|
237
|
+
props.tableLayout === 'fixed'
|
|
238
|
+
? table.refs.headerWrapper
|
|
239
|
+
: table.refs.tableHeaderRef?.$el
|
|
240
|
+
if (props.showHeader && tableHeader?.offsetHeight !== oldHeaderHeight) {
|
|
241
|
+
shouldUpdateLayout = true
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
tableScrollHeight.value = table.refs.tableWrapper?.scrollHeight || 0
|
|
245
|
+
headerScrollHeight.value = tableHeader?.scrollHeight || 0
|
|
246
|
+
footerScrollHeight.value = table.refs.footerWrapper?.offsetHeight || 0
|
|
247
|
+
appendScrollHeight.value = table.refs.appendWrapper?.offsetHeight || 0
|
|
248
|
+
bodyScrollHeight.value =
|
|
249
|
+
tableScrollHeight.value -
|
|
250
|
+
headerScrollHeight.value -
|
|
251
|
+
footerScrollHeight.value -
|
|
252
|
+
appendScrollHeight.value
|
|
253
|
+
|
|
254
|
+
if (shouldUpdateLayout) {
|
|
255
|
+
resizeState.value = {
|
|
256
|
+
width,
|
|
257
|
+
height,
|
|
258
|
+
headerHeight: (props.showHeader && tableHeader?.offsetHeight) || 0,
|
|
259
|
+
}
|
|
260
|
+
doLayout()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const tableSize = useFormSize()
|
|
264
|
+
const bodyWidth = computed(() => {
|
|
265
|
+
const { bodyWidth: bodyWidth_, scrollY, gutterWidth } = layout
|
|
266
|
+
return bodyWidth_.value
|
|
267
|
+
? `${(bodyWidth_.value as number) - (scrollY.value ? gutterWidth : 0)}px`
|
|
268
|
+
: ''
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
const tableLayout = computed(() => {
|
|
272
|
+
if (props.maxHeight) return 'fixed'
|
|
273
|
+
return props.tableLayout
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
const emptyBlockStyle = computed(() => {
|
|
277
|
+
if (props.data && props.data.length) return null
|
|
278
|
+
let height = '100%'
|
|
279
|
+
if (props.height && bodyScrollHeight.value) {
|
|
280
|
+
height = `${bodyScrollHeight.value}px`
|
|
281
|
+
}
|
|
282
|
+
const width = tableWidth.value
|
|
283
|
+
return {
|
|
284
|
+
width: width ? `${width}px` : '',
|
|
285
|
+
height,
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
const tableInnerStyle = computed(() => {
|
|
290
|
+
if (props.height) {
|
|
291
|
+
return {
|
|
292
|
+
height: !Number.isNaN(Number(props.height))
|
|
293
|
+
? `${props.height}px`
|
|
294
|
+
: props.height,
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (props.maxHeight) {
|
|
298
|
+
return {
|
|
299
|
+
maxHeight: !Number.isNaN(Number(props.maxHeight))
|
|
300
|
+
? `${props.maxHeight}px`
|
|
301
|
+
: props.maxHeight,
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return {}
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
const scrollbarStyle = computed(() => {
|
|
308
|
+
if (props.height) {
|
|
309
|
+
return {
|
|
310
|
+
height: '100%',
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (props.maxHeight) {
|
|
314
|
+
if (!Number.isNaN(Number(props.maxHeight))) {
|
|
315
|
+
return {
|
|
316
|
+
maxHeight: `${
|
|
317
|
+
props.maxHeight -
|
|
318
|
+
headerScrollHeight.value -
|
|
319
|
+
footerScrollHeight.value
|
|
320
|
+
}px`,
|
|
321
|
+
}
|
|
322
|
+
} else {
|
|
323
|
+
return {
|
|
324
|
+
maxHeight: `calc(${props.maxHeight} - ${
|
|
325
|
+
headerScrollHeight.value + footerScrollHeight.value
|
|
326
|
+
}px)`,
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return {}
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* fix layout
|
|
336
|
+
*/
|
|
337
|
+
const handleFixedMousewheel = (event, data) => {
|
|
338
|
+
const bodyWrapper = table.refs.bodyWrapper
|
|
339
|
+
if (Math.abs(data.spinY) > 0) {
|
|
340
|
+
const currentScrollTop = bodyWrapper.scrollTop
|
|
341
|
+
if (data.pixelY < 0 && currentScrollTop !== 0) {
|
|
342
|
+
event.preventDefault()
|
|
343
|
+
}
|
|
344
|
+
if (
|
|
345
|
+
data.pixelY > 0 &&
|
|
346
|
+
bodyWrapper.scrollHeight - bodyWrapper.clientHeight > currentScrollTop
|
|
347
|
+
) {
|
|
348
|
+
event.preventDefault()
|
|
349
|
+
}
|
|
350
|
+
bodyWrapper.scrollTop += Math.ceil(data.pixelY / 5)
|
|
351
|
+
} else {
|
|
352
|
+
bodyWrapper.scrollLeft += Math.ceil(data.pixelX / 5)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
isHidden,
|
|
358
|
+
renderExpanded,
|
|
359
|
+
setDragVisible,
|
|
360
|
+
isGroup,
|
|
361
|
+
handleMouseLeave,
|
|
362
|
+
handleHeaderFooterMousewheel,
|
|
363
|
+
tableSize,
|
|
364
|
+
emptyBlockStyle,
|
|
365
|
+
handleFixedMousewheel,
|
|
366
|
+
resizeProxyVisible,
|
|
367
|
+
bodyWidth,
|
|
368
|
+
resizeState,
|
|
369
|
+
doLayout,
|
|
370
|
+
tableBodyStyles,
|
|
371
|
+
tableLayout,
|
|
372
|
+
scrollbarViewStyle,
|
|
373
|
+
tableInnerStyle,
|
|
374
|
+
scrollbarStyle,
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export default useStyle
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import type { Store } from '../store'
|
|
3
|
+
|
|
4
|
+
function useUtils<T>(store: Store<T>) {
|
|
5
|
+
const setCurrentRow = (row: T) => {
|
|
6
|
+
store.commit('setCurrentRow', row)
|
|
7
|
+
}
|
|
8
|
+
const getSelectionRows = () => {
|
|
9
|
+
return store.getSelectionRows()
|
|
10
|
+
}
|
|
11
|
+
const toggleRowSelection = (row: T, selected: boolean) => {
|
|
12
|
+
store.toggleRowSelection(row, selected, false)
|
|
13
|
+
store.updateAllSelected()
|
|
14
|
+
}
|
|
15
|
+
const clearSelection = () => {
|
|
16
|
+
store.clearSelection()
|
|
17
|
+
}
|
|
18
|
+
const clearFilter = (columnKeys?: string[]) => {
|
|
19
|
+
store.clearFilter(columnKeys)
|
|
20
|
+
}
|
|
21
|
+
const toggleAllSelection = () => {
|
|
22
|
+
store.commit('toggleAllSelection')
|
|
23
|
+
}
|
|
24
|
+
const toggleRowExpansion = (row: T, expanded?: boolean) => {
|
|
25
|
+
store.toggleRowExpansionAdapter(row, expanded)
|
|
26
|
+
}
|
|
27
|
+
const clearSort = () => {
|
|
28
|
+
store.clearSort()
|
|
29
|
+
}
|
|
30
|
+
const sort = (prop: string, order: string) => {
|
|
31
|
+
store.commit('sort', { prop, order })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
setCurrentRow,
|
|
36
|
+
getSelectionRows,
|
|
37
|
+
toggleRowSelection,
|
|
38
|
+
clearSelection,
|
|
39
|
+
clearFilter,
|
|
40
|
+
toggleAllSelection,
|
|
41
|
+
toggleRowExpansion,
|
|
42
|
+
clearSort,
|
|
43
|
+
sort,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default useUtils
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
import type { Store } from '../store'
|
|
4
|
+
import type {
|
|
5
|
+
ColumnCls,
|
|
6
|
+
ColumnStyle,
|
|
7
|
+
DefaultRow,
|
|
8
|
+
Table,
|
|
9
|
+
} from '../table/defaults'
|
|
10
|
+
import type { TableOverflowTooltipOptions } from '../util'
|
|
11
|
+
|
|
12
|
+
interface TableBodyProps<T> {
|
|
13
|
+
store: Store<T>
|
|
14
|
+
stripe?: boolean
|
|
15
|
+
context: Table<T>
|
|
16
|
+
rowClassName: ColumnCls<T>
|
|
17
|
+
rowStyle: ColumnStyle<T>
|
|
18
|
+
fixed: string
|
|
19
|
+
highlight: boolean
|
|
20
|
+
tooltipEffect?: string
|
|
21
|
+
tooltipOptions?: TableOverflowTooltipOptions
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const defaultProps = {
|
|
25
|
+
store: {
|
|
26
|
+
required: true,
|
|
27
|
+
type: Object as PropType<TableBodyProps<DefaultRow>['store']>,
|
|
28
|
+
},
|
|
29
|
+
stripe: Boolean,
|
|
30
|
+
tooltipEffect: String,
|
|
31
|
+
tooltipOptions: {
|
|
32
|
+
type: Object as PropType<TableBodyProps<DefaultRow>['tooltipOptions']>,
|
|
33
|
+
},
|
|
34
|
+
context: {
|
|
35
|
+
default: () => ({}),
|
|
36
|
+
type: Object as PropType<TableBodyProps<DefaultRow>['context']>,
|
|
37
|
+
},
|
|
38
|
+
rowClassName: [String, Function] as PropType<
|
|
39
|
+
TableBodyProps<DefaultRow>['rowClassName']
|
|
40
|
+
>,
|
|
41
|
+
rowStyle: [Object, Function] as PropType<
|
|
42
|
+
TableBodyProps<DefaultRow>['rowStyle']
|
|
43
|
+
>,
|
|
44
|
+
fixed: {
|
|
45
|
+
type: String,
|
|
46
|
+
default: '',
|
|
47
|
+
},
|
|
48
|
+
highlight: Boolean,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { TableBodyProps }
|
|
52
|
+
export default defaultProps
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { h, inject, ref } from 'vue'
|
|
3
|
+
import { debounce } from 'lodash-unified'
|
|
4
|
+
import { addClass, hasClass, removeClass } from 'element-plus/es/utils/index.mjs'
|
|
5
|
+
import { createTablePopper, getCell, getColumnByCell } from '../util'
|
|
6
|
+
import { TABLE_INJECTION_KEY } from '../tokens'
|
|
7
|
+
import type { TableColumnCtx } from '../table-column/defaults'
|
|
8
|
+
import type { TableBodyProps } from './defaults'
|
|
9
|
+
import type { TableOverflowTooltipOptions } from '../util'
|
|
10
|
+
|
|
11
|
+
function isGreaterThan(a: number, b: number, epsilon = 0.01) {
|
|
12
|
+
return a - b > epsilon
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function useEvents<T>(props: Partial<TableBodyProps<T>>) {
|
|
16
|
+
const parent = inject(TABLE_INJECTION_KEY)
|
|
17
|
+
const tooltipContent = ref('')
|
|
18
|
+
const tooltipTrigger = ref(h('div'))
|
|
19
|
+
const handleEvent = (event: Event, row: T, name: string) => {
|
|
20
|
+
const table = parent
|
|
21
|
+
const cell = getCell(event)
|
|
22
|
+
let column: TableColumnCtx<T>
|
|
23
|
+
const namespace = table?.vnode.el?.dataset.prefix
|
|
24
|
+
if (cell) {
|
|
25
|
+
column = getColumnByCell(
|
|
26
|
+
{
|
|
27
|
+
columns: props.store.states.columns.value,
|
|
28
|
+
},
|
|
29
|
+
cell,
|
|
30
|
+
namespace
|
|
31
|
+
)
|
|
32
|
+
if (column) {
|
|
33
|
+
table?.emit(`cell-${name}`, row, column, cell, event)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
table?.emit(`row-${name}`, row, column, event)
|
|
37
|
+
}
|
|
38
|
+
const handleDoubleClick = (event: Event, row: T) => {
|
|
39
|
+
handleEvent(event, row, 'dblclick')
|
|
40
|
+
}
|
|
41
|
+
const handleClick = (event: Event, row: T) => {
|
|
42
|
+
props.store.commit('setCurrentRow', row)
|
|
43
|
+
handleEvent(event, row, 'click')
|
|
44
|
+
}
|
|
45
|
+
const handleContextMenu = (event: Event, row: T) => {
|
|
46
|
+
handleEvent(event, row, 'contextmenu')
|
|
47
|
+
}
|
|
48
|
+
const handleMouseEnter = debounce((index: number) => {
|
|
49
|
+
props.store.commit('setHoverRow', index)
|
|
50
|
+
}, 30)
|
|
51
|
+
const handleMouseLeave = debounce(() => {
|
|
52
|
+
props.store.commit('setHoverRow', null)
|
|
53
|
+
}, 30)
|
|
54
|
+
const getPadding = (el: HTMLElement) => {
|
|
55
|
+
const style = window.getComputedStyle(el, null)
|
|
56
|
+
const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0
|
|
57
|
+
const paddingRight = Number.parseInt(style.paddingRight, 10) || 0
|
|
58
|
+
const paddingTop = Number.parseInt(style.paddingTop, 10) || 0
|
|
59
|
+
const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0
|
|
60
|
+
return {
|
|
61
|
+
left: paddingLeft,
|
|
62
|
+
right: paddingRight,
|
|
63
|
+
top: paddingTop,
|
|
64
|
+
bottom: paddingBottom,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const toggleRowClassByCell = (
|
|
69
|
+
rowSpan: number,
|
|
70
|
+
event: MouseEvent,
|
|
71
|
+
toggle: (el: Element, cls: string) => void
|
|
72
|
+
) => {
|
|
73
|
+
let node = event.target.parentNode
|
|
74
|
+
while (rowSpan > 1) {
|
|
75
|
+
node = node?.nextSibling
|
|
76
|
+
if (!node || node.nodeName !== 'TR') break
|
|
77
|
+
toggle(node, 'hover-row hover-fixed-row')
|
|
78
|
+
rowSpan--
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const handleCellMouseEnter = (
|
|
83
|
+
event: MouseEvent,
|
|
84
|
+
row: T,
|
|
85
|
+
tooltipOptions: TableOverflowTooltipOptions
|
|
86
|
+
) => {
|
|
87
|
+
const table = parent
|
|
88
|
+
const cell = getCell(event)
|
|
89
|
+
const namespace = table?.vnode.el?.dataset.prefix
|
|
90
|
+
if (cell) {
|
|
91
|
+
const column = getColumnByCell(
|
|
92
|
+
{
|
|
93
|
+
columns: props.store.states.columns.value,
|
|
94
|
+
},
|
|
95
|
+
cell,
|
|
96
|
+
namespace
|
|
97
|
+
)
|
|
98
|
+
if (cell.rowSpan > 1) {
|
|
99
|
+
toggleRowClassByCell(cell.rowSpan, event, addClass)
|
|
100
|
+
}
|
|
101
|
+
const hoverState = (table.hoverState = { cell, column, row })
|
|
102
|
+
table?.emit(
|
|
103
|
+
'cell-mouse-enter',
|
|
104
|
+
hoverState.row,
|
|
105
|
+
hoverState.column,
|
|
106
|
+
hoverState.cell,
|
|
107
|
+
event
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!tooltipOptions) {
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
if (tooltipOptions.showOverflowTooltip && typeof tooltipOptions.showOverflowTooltip === 'function') {
|
|
115
|
+
if (!tooltipOptions.showOverflowTooltip()) {
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 判断是否text-overflow, 如果是就显示tooltip
|
|
121
|
+
const cellChild = (event.target as HTMLElement).querySelector(
|
|
122
|
+
'.cell'
|
|
123
|
+
) as HTMLElement
|
|
124
|
+
if (
|
|
125
|
+
!(
|
|
126
|
+
hasClass(cellChild, `${namespace}-tooltip`) &&
|
|
127
|
+
cellChild.childNodes.length
|
|
128
|
+
)
|
|
129
|
+
) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
// use range width instead of scrollWidth to determine whether the text is overflowing
|
|
133
|
+
// to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
|
|
134
|
+
const range = document.createRange()
|
|
135
|
+
range.setStart(cellChild, 0)
|
|
136
|
+
range.setEnd(cellChild, cellChild.childNodes.length)
|
|
137
|
+
/** detail: https://github.com/element-plus/element-plus/issues/10790
|
|
138
|
+
* What went wrong?
|
|
139
|
+
* UI > Browser > Zoom, In Blink/WebKit, getBoundingClientRect() sometimes returns inexact values, probably due to lost precision during internal calculations. In the example above:
|
|
140
|
+
* - Expected: 188
|
|
141
|
+
* - Actual: 188.00000762939453
|
|
142
|
+
*/
|
|
143
|
+
let { width: rangeWidth, height: rangeHeight } =
|
|
144
|
+
range.getBoundingClientRect()
|
|
145
|
+
const offsetWidth = rangeWidth - Math.floor(rangeWidth)
|
|
146
|
+
const { width: cellChildWidth, height: cellChildHeight } =
|
|
147
|
+
cellChild.getBoundingClientRect()
|
|
148
|
+
if (offsetWidth < 0.001) {
|
|
149
|
+
rangeWidth = Math.floor(rangeWidth)
|
|
150
|
+
}
|
|
151
|
+
const offsetHeight = rangeHeight - Math.floor(rangeHeight)
|
|
152
|
+
if (offsetHeight < 0.001) {
|
|
153
|
+
rangeHeight = Math.floor(rangeHeight)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const { top, left, right, bottom } = getPadding(cellChild)
|
|
157
|
+
const horizontalPadding = left + right
|
|
158
|
+
const verticalPadding = top + bottom
|
|
159
|
+
if (
|
|
160
|
+
isGreaterThan(rangeWidth + horizontalPadding, cellChildWidth) ||
|
|
161
|
+
isGreaterThan(rangeHeight + verticalPadding, cellChildHeight) ||
|
|
162
|
+
// When using a high-resolution screen, it is possible that a returns cellChild.scrollWidth value of 1921 and
|
|
163
|
+
// cellChildWidth returns a value of 1920.994140625. #16856 #16673
|
|
164
|
+
isGreaterThan(cellChild.scrollWidth, cellChildWidth)
|
|
165
|
+
) {
|
|
166
|
+
createTablePopper(
|
|
167
|
+
tooltipOptions,
|
|
168
|
+
cell.innerText || cell.textContent,
|
|
169
|
+
cell,
|
|
170
|
+
table
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const handleCellMouseLeave = (event) => {
|
|
175
|
+
const cell = getCell(event)
|
|
176
|
+
if (!cell) return
|
|
177
|
+
if (cell.rowSpan > 1) {
|
|
178
|
+
toggleRowClassByCell(cell.rowSpan, event, removeClass)
|
|
179
|
+
}
|
|
180
|
+
const oldHoverState = parent?.hoverState
|
|
181
|
+
parent?.emit(
|
|
182
|
+
'cell-mouse-leave',
|
|
183
|
+
oldHoverState?.row,
|
|
184
|
+
oldHoverState?.column,
|
|
185
|
+
oldHoverState?.cell,
|
|
186
|
+
event
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
handleDoubleClick,
|
|
192
|
+
handleClick,
|
|
193
|
+
handleContextMenu,
|
|
194
|
+
handleMouseEnter,
|
|
195
|
+
handleMouseLeave,
|
|
196
|
+
handleCellMouseEnter,
|
|
197
|
+
handleCellMouseLeave,
|
|
198
|
+
tooltipContent,
|
|
199
|
+
tooltipTrigger,
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export default useEvents
|