webcake-ui-kit 1.2.0 → 1.2.2

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 (68) hide show
  1. package/package.json +8 -2
  2. package/src/components/checkbox/Checkbox.vue +1 -1
  3. package/src/components/drawer/Drawer.vue +261 -0
  4. package/src/components/drawer/drawer.css +162 -0
  5. package/src/components/dropdown/Dropdown.vue +15 -9
  6. package/src/components/hover-card/HoverCard.vue +159 -0
  7. package/src/components/hover-card/hover-card.css +10 -0
  8. package/src/components/input-counter/InputCounter.vue +250 -0
  9. package/src/components/input-counter/input-counter.css +209 -0
  10. package/src/components/menu/Menu.vue +4 -2
  11. package/src/components/popover/Popover.vue +144 -0
  12. package/src/components/popover/popover.css +3 -0
  13. package/src/components/select/Select.vue +10 -2
  14. package/src/components/select/select.css +12 -4
  15. package/src/components/select-option/SelectOption.vue +8 -2
  16. package/src/components/table-v2/ColumnDragHandle.vue +103 -0
  17. package/src/components/table-v2/Table.vue +304 -0
  18. package/src/components/table-v2/TableColGroup.vue +55 -0
  19. package/src/components/table-v2/TableEmpty.vue +10 -0
  20. package/src/components/table-v2/TableLoading.vue +25 -0
  21. package/src/components/table-v2/TableResizeObserver.vue +91 -0
  22. package/src/components/table-v2/TableWrapper.vue +207 -0
  23. package/src/components/table-v2/body/DragPreview.vue +65 -0
  24. package/src/components/table-v2/body/MeasureCell.vue +42 -0
  25. package/src/components/table-v2/body/TableBody.vue +133 -0
  26. package/src/components/table-v2/body/TableCell.vue +114 -0
  27. package/src/components/table-v2/body/TableRow.vue +73 -0
  28. package/src/components/table-v2/composables/useColumns.js +19 -0
  29. package/src/components/table-v2/composables/useSorter.js +12 -0
  30. package/src/components/table-v2/composables/useSticky.js +31 -0
  31. package/src/components/table-v2/constants.js +2 -0
  32. package/src/components/table-v2/context/createTableContext.js +80 -0
  33. package/src/components/table-v2/header/TableHeader.vue +15 -0
  34. package/src/components/table-v2/header/TableHeaderCell.vue +89 -0
  35. package/src/components/table-v2/header/TableHeaderRow.vue +107 -0
  36. package/src/components/table-v2/style/table-body.css +0 -0
  37. package/src/components/table-v2/style/table-header.css +0 -0
  38. package/src/components/table-v2/style/table-loading.css +19 -0
  39. package/src/components/table-v2/style/table-wrapper.css +287 -0
  40. package/src/components/table-v2/style/table.css +5 -0
  41. package/src/icons/BoxShadow.vue +35 -0
  42. package/src/icons/Carousel.vue +34 -0
  43. package/src/icons/CloudSync2.vue +42 -0
  44. package/src/icons/CornerBottomLeft.vue +26 -0
  45. package/src/icons/CornerBottomRight.vue +26 -0
  46. package/src/icons/CornerTopLeft.vue +26 -0
  47. package/src/icons/CornerTopRight.vue +26 -0
  48. package/src/icons/DistanceRight.vue +30 -0
  49. package/src/icons/DistanceTop.vue +30 -0
  50. package/src/icons/DropShadow.vue +35 -0
  51. package/src/icons/Fire.vue +26 -0
  52. package/src/icons/GlobeAccess.vue +32 -0
  53. package/src/icons/InnerShadow.vue +33 -0
  54. package/src/icons/Livestream.vue +54 -0
  55. package/src/icons/PaddingBottom.vue +30 -0
  56. package/src/icons/PaddingLeft.vue +30 -0
  57. package/src/icons/PaddingRight.vue +30 -0
  58. package/src/icons/PaddingTop.vue +30 -0
  59. package/src/icons/SkewHeight.vue +32 -0
  60. package/src/icons/SkewWidth.vue +32 -0
  61. package/src/icons/SquareDashedBottomSolid.vue +26 -0
  62. package/src/icons/SquareDashedLeftSolid.vue +26 -0
  63. package/src/icons/SquareDashedRightSolid.vue +26 -0
  64. package/src/icons/StrokeLine.vue +23 -0
  65. package/src/icons/Topline.vue +26 -0
  66. package/src/icons/index.js +25 -0
  67. package/src/index.js +5 -0
  68. package/src/utils/common.js +34 -0
@@ -15,13 +15,13 @@
15
15
  :aria-disabled="isDisabled ? 'true' : null"
16
16
  @click="handleClick"
17
17
  >
18
- <span v-if="$slots.prefix" class="ui-select-option__prefix">
18
+ <span v-if="hasPrefix" class="ui-select-option__prefix">
19
19
  <slot name="prefix" />
20
20
  </span>
21
21
  <span class="ui-select-option--label">
22
22
  <slot>{{ label || value }}</slot>
23
23
  </span>
24
- <span v-if="$slots.suffix" class="ui-select-option__suffix">
24
+ <span v-if="hasSuffix" class="ui-select-option__suffix">
25
25
  <slot name="suffix" />
26
26
  </span>
27
27
  <WkiCheck v-if="isSelected && isMultiMode" :size="16" color="var(--muted-fg)" />
@@ -100,6 +100,12 @@ export default {
100
100
  // explicit prop wins; otherwise inherit from parent Select; else regular
101
101
  return this.size || (this.select && (this.select.optionSize || this.select.size)) || 'md'
102
102
  },
103
+ hasPrefix() {
104
+ return !!((this.$scopedSlots && this.$scopedSlots.prefix) || this.$slots.prefix)
105
+ },
106
+ hasSuffix() {
107
+ return !!((this.$scopedSlots && this.$scopedSlots.suffix) || this.$slots.suffix)
108
+ },
103
109
  isHidden() {
104
110
  if (!this.select || !this.select.filterText) return false
105
111
  var q = this.select.filterText.toLowerCase()
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <div
3
+ :class="['ui-table-v2__cell-resize-handle', dragging && 'dragging', reversed && 'reversed']"
4
+ @mousedown.stop.prevent="handleMouseDown"
5
+ @touchstart.stop.prevent="handleTouchStart"
6
+ @click.stop.prevent
7
+ >
8
+ <div class="ui-table-v2__cell-resize-line"></div>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ export default {
14
+ name: 'ColumnDragHandle',
15
+ props: {
16
+ column: { type: Object, required: true },
17
+ width: { type: Number, default: 0 },
18
+ minWidth: { type: Number, default: 50 },
19
+ maxWidth: { type: Number, default: Infinity },
20
+ reversed: { type: Boolean, default: false }
21
+ },
22
+ emits: ['resize'],
23
+ data: function () {
24
+ return {
25
+ dragging: false
26
+ }
27
+ },
28
+ created: function () {
29
+ this._startX = 0
30
+ this._baseWidth = 0
31
+ this._rafId = null
32
+ this._moveHandler = null
33
+ this._stopHandler = null
34
+ },
35
+ beforeUnmount: function () {
36
+ this._removeEvents()
37
+ },
38
+ // eslint-disable-next-line vue/no-deprecated-destroyed-lifecycle, vue/no-dupe-keys
39
+ beforeDestroy: function () {
40
+ this._removeEvents()
41
+ },
42
+ methods: {
43
+ _getPageX: function (e) {
44
+ if (e.touches) {
45
+ return e.touches.length ? e.touches[0].pageX : e.changedTouches[0].pageX
46
+ }
47
+ return e.pageX
48
+ },
49
+ _clampWidth: function (w) {
50
+ const min = typeof this.minWidth === 'number' && !isNaN(this.minWidth) ? this.minWidth : 50
51
+ const max = typeof this.maxWidth === 'number' && !isNaN(this.maxWidth) ? this.maxWidth : Infinity
52
+ return Math.min(Math.max(w, min), max)
53
+ },
54
+ _updateWidth: function (e) {
55
+ const deltaX = this._startX - this._getPageX(e)
56
+ const w = this._clampWidth(this.reversed ? this._baseWidth + deltaX : this._baseWidth - deltaX)
57
+ if (this._rafId) cancelAnimationFrame(this._rafId)
58
+ this._rafId = requestAnimationFrame(() => {
59
+ this.$emit('resize', w, this.column)
60
+ })
61
+ },
62
+ _removeEvents: function () {
63
+ if (this._moveHandler) {
64
+ document.documentElement.removeEventListener('mousemove', this._moveHandler)
65
+ document.documentElement.removeEventListener('touchmove', this._moveHandler)
66
+ this._moveHandler = null
67
+ }
68
+ if (this._stopHandler) {
69
+ document.documentElement.removeEventListener('mouseup', this._stopHandler)
70
+ document.documentElement.removeEventListener('touchend', this._stopHandler)
71
+ this._stopHandler = null
72
+ }
73
+ if (this._rafId) {
74
+ cancelAnimationFrame(this._rafId)
75
+ this._rafId = null
76
+ }
77
+ },
78
+ _handleStart: function (e) {
79
+ this.dragging = true
80
+ this._removeEvents()
81
+ this._baseWidth = this.$el.parentNode.getBoundingClientRect().width
82
+ this._startX = this._getPageX(e)
83
+ this._moveHandler = this._updateWidth.bind(this)
84
+ this._stopHandler = e => {
85
+ this.dragging = false
86
+ this._updateWidth(e)
87
+ this._removeEvents()
88
+ }
89
+ document.documentElement.addEventListener('mousemove', this._moveHandler)
90
+ document.documentElement.addEventListener('touchmove', this._moveHandler, { passive: false })
91
+ document.documentElement.addEventListener('mouseup', this._stopHandler)
92
+ document.documentElement.addEventListener('touchend', this._stopHandler)
93
+ },
94
+ handleMouseDown: function (e) {
95
+ if (e.which !== 1) return
96
+ this._handleStart(e)
97
+ },
98
+ handleTouchStart: function (e) {
99
+ this._handleStart(e)
100
+ }
101
+ }
102
+ }
103
+ </script>
@@ -0,0 +1,304 @@
1
+ <template>
2
+ <div class="ui-table-v2">
3
+ <TableLoading>
4
+ <TableResizeObserver @resize="handleContainerResize">
5
+ <TableWrapper>
6
+ <template #bodyCell="slotData">
7
+ <slot name="bodyCell" v-bind="slotData"></slot>
8
+ </template>
9
+ <template #empty>
10
+ <slot name="empty"></slot>
11
+ </template>
12
+ </TableWrapper>
13
+ </TableResizeObserver>
14
+ </TableLoading>
15
+ </div>
16
+ </template>
17
+
18
+ <script>
19
+ import { createTableContext } from './context/createTableContext.js'
20
+ import { flattenColumns } from './composables/useColumns.js'
21
+ import { sortData } from './composables/useSorter.js'
22
+ import { computeOffsets } from './composables/useSticky.js'
23
+ import { SELECTION_COLUMN, DRAGGABLE_COLUMN } from './constants.js'
24
+ import TableWrapper from './TableWrapper.vue'
25
+ import TableLoading from './TableLoading.vue'
26
+ import TableResizeObserver from './TableResizeObserver.vue'
27
+
28
+ export default {
29
+ name: 'TableV2',
30
+
31
+ components: { TableWrapper, TableLoading, TableResizeObserver },
32
+
33
+ provide: function () {
34
+ return { tableContext: this.tableCtx }
35
+ },
36
+
37
+ props: {
38
+ columns: {
39
+ type: Array,
40
+ default: function () {
41
+ return []
42
+ }
43
+ },
44
+ dataSource: {
45
+ type: Array,
46
+ default: function () {
47
+ return []
48
+ }
49
+ },
50
+ bordered: { type: Boolean, default: false },
51
+ size: { type: String, default: 'md' },
52
+ rowKey: { type: String, default: 'key' },
53
+ scroll: { type: Object, default: null },
54
+ loading: { type: Boolean, default: false },
55
+ rowSelection: { type: Object, default: null },
56
+ customRow: { type: Function, default: null },
57
+ customHeaderRow: { type: Function, default: null },
58
+ rowDraggable: { type: Object, default: null },
59
+ enableFixedLeft: { type: Boolean, default: false },
60
+ rowHeight: { type: Number, default: 36 },
61
+ headerHeight: { type: Number, default: 50 },
62
+ emptyText: { type: String, default: '' },
63
+ height: { type: [Number, String], default: 0 }
64
+ },
65
+
66
+ emits: ['change', 'sort-change', 'select-change'],
67
+
68
+ data: function () {
69
+ return { tableCtx: createTableContext() }
70
+ },
71
+
72
+ computed: {
73
+ isEmpty: function () {
74
+ return this.tableCtx.data.display.length === 0
75
+ },
76
+
77
+ columnsInput: function () {
78
+ return {
79
+ columns: this.columns,
80
+ rowKey: this.rowKey,
81
+ hasSelection: !!this.rowSelection,
82
+ hasDraggable: !!this.rowDraggable
83
+ }
84
+ },
85
+
86
+ rowsInput: function () {
87
+ return { customRow: this.customRow, customHeaderRow: this.customHeaderRow }
88
+ },
89
+
90
+ layoutInput: function () {
91
+ return {
92
+ bordered: this.bordered,
93
+ size: this.size,
94
+ scroll: this.scroll,
95
+ rowHeight: this.rowHeight,
96
+ headerHeight: this.headerHeight,
97
+ height: this.height
98
+ }
99
+ },
100
+
101
+ dataInput: function () {
102
+ return {
103
+ source: this.dataSource,
104
+ sortKey: this.tableCtx.sort.columnKey,
105
+ sortOrder: this.tableCtx.sort.order,
106
+ loading: this.loading,
107
+ emptyText: this.emptyText
108
+ }
109
+ },
110
+
111
+ stickyInput: function () {
112
+ return {
113
+ columns: this.tableCtx.columns.flat,
114
+ widths: this.tableCtx.layout.columnWidths
115
+ }
116
+ },
117
+
118
+ selectionInput: function () {
119
+ return this.rowSelection
120
+ },
121
+
122
+ draggableInput: function () {
123
+ return this.rowDraggable
124
+ }
125
+ },
126
+
127
+ watch: {
128
+ columnsInput: {
129
+ immediate: true,
130
+ handler: function (v) {
131
+ var cols = flattenColumns(v.columns)
132
+ const isHasFixedLeft = cols.some(col => col.fixed === 'left')
133
+ if (v.hasSelection) {
134
+ cols.unshift({
135
+ key: '__selection__',
136
+ type: SELECTION_COLUMN,
137
+ width: 36,
138
+ dataIndex: '',
139
+ title: '',
140
+ align: null,
141
+ fixed: isHasFixedLeft || this.enableFixedLeft ? 'left' : null,
142
+ ellipsis: false
143
+ })
144
+ }
145
+ if (v.hasDraggable) {
146
+ cols.unshift({
147
+ key: '__draggable__',
148
+ type: DRAGGABLE_COLUMN,
149
+ width: 36,
150
+ dataIndex: '',
151
+ title: '',
152
+ align: null,
153
+ fixed: isHasFixedLeft || this.enableFixedLeft ? 'left' : null,
154
+ ellipsis: false
155
+ })
156
+ }
157
+ this.tableCtx.columns.flat = cols
158
+ this.tableCtx.layout.rowKey = v.rowKey
159
+ }
160
+ },
161
+
162
+ rowsInput: {
163
+ immediate: true,
164
+ handler: function (v) {
165
+ this.tableCtx.rows.customRow = v.customRow
166
+ this.tableCtx.rows.customHeaderRow = v.customHeaderRow
167
+ }
168
+ },
169
+
170
+ layoutInput: {
171
+ immediate: true,
172
+ deep: true,
173
+ handler: function (v) {
174
+ this.tableCtx.layout.bordered = v.bordered
175
+ this.tableCtx.layout.size = v.size
176
+ this.tableCtx.layout.scroll = v.scroll
177
+ this.tableCtx.layout.tableLayout = v.scroll && v.scroll.y ? 'fixed' : 'auto'
178
+ this.tableCtx.layout.height = v.height
179
+ }
180
+ },
181
+
182
+ dataInput: {
183
+ immediate: true,
184
+ handler: function (v) {
185
+ this.tableCtx.data.source = v.source
186
+ ;((this.tableCtx.data.display = v.sortKey ? sortData(v.source, v.sortKey, v.sortOrder) : v.source),
187
+ (this.tableCtx.data.loading = v.loading))
188
+ this.tableCtx.data.emptyText = v.emptyText
189
+ console.log(this.tableCtx.data.emptyText)
190
+ }
191
+ },
192
+
193
+ stickyInput: {
194
+ deep: true,
195
+ immediate: true,
196
+ handler: function (v) {
197
+ if (!v.columns.length) return
198
+ var offsets = computeOffsets(v.columns, v.widths)
199
+ this.tableCtx.sticky.leftOffsets = offsets.left
200
+ this.tableCtx.sticky.rightOffsets = offsets.right
201
+ }
202
+ },
203
+
204
+ selectionInput: {
205
+ immediate: true,
206
+ deep: true,
207
+ handler: function (v) {
208
+ if (!v) return
209
+ this.tableCtx.selection.selectedRowKeys = v.selectedRowKeys || []
210
+ this.tableCtx.selection.hideSelectAll = v.hideSelectAll
211
+ this.tableCtx.selection.columnWidth = v.columnWidth
212
+ this.tableCtx.selection.type = v.type
213
+ this.tableCtx.selection.onChange = v.onChange
214
+ this.tableCtx.selection.onSelect = v.onSelect
215
+ this.tableCtx.selection.onSelectAll = v.onSelectAll
216
+ this.tableCtx.selection.onSelectNone = v.onSelectNone
217
+ }
218
+ },
219
+
220
+ draggableInput: {
221
+ immediate: true,
222
+ deep: true,
223
+ handler: function (v) {
224
+ this.tableCtx.draggable.enabled = !!v
225
+ if (!v) return
226
+ this.tableCtx.draggable.columnWidth = v.columnWidth || 36
227
+ this.tableCtx.draggable.handleReorder = v.handleReorder || null
228
+ this.tableCtx.draggable.enableAnimationFlip = v.enableAnimationFlip || false
229
+ }
230
+ }
231
+ },
232
+
233
+ created: function () {
234
+ this.tableCtx.actions.sort = this.handleSort
235
+ this.tableCtx.actions.select = this.handleSelect
236
+ this.tableCtx.actions.resize = this.handleResize
237
+ this.tableCtx.actions.reorder = this.handleReorder
238
+ },
239
+
240
+ methods: {
241
+ handleSort: function (columnKey, order) {
242
+ this.tableCtx.sort.columnKey = columnKey
243
+ this.tableCtx.sort.order = order
244
+ this.$emit('sort-change', { columnKey: columnKey, order: order })
245
+ this.$emit('change', { sort: { columnKey: columnKey, order: order } })
246
+ },
247
+
248
+ handleSelect: function (keys, meta) {
249
+ var prevKeys = this.tableCtx.selection.selectedRowKeys
250
+ var display = this.tableCtx.data.display
251
+ var rowKey = this.tableCtx.layout.rowKey
252
+ var rs = this.rowSelection || {}
253
+
254
+ this.tableCtx.selection.checkAll = keys.length === display.length && display.length > 0
255
+
256
+ var selectedRows = display.filter(function (r) {
257
+ return keys.indexOf(r[rowKey]) !== -1
258
+ })
259
+
260
+ if (rs.onChange) rs.onChange(keys, selectedRows)
261
+
262
+ if (!meta) return
263
+
264
+ if (meta.type === 'row') {
265
+ if (rs.onSelect) rs.onSelect(meta.record, meta.selected, selectedRows, meta.nativeEvent)
266
+ } else if (meta.type === 'all') {
267
+ // changeRows = rows mới được check (chưa có trong prevKeys)
268
+ var changeRows = display.filter(function (r) {
269
+ return prevKeys.indexOf(r[rowKey]) === -1
270
+ })
271
+ if (rs.onSelectAll) rs.onSelectAll(true, selectedRows, changeRows)
272
+ } else if (meta.type === 'none') {
273
+ // changeRows = rows bị uncheck (đang có trong prevKeys)
274
+ changeRows = display.filter(function (r) {
275
+ return prevKeys.indexOf(r[rowKey]) !== -1
276
+ })
277
+ if (rs.onSelectAll) rs.onSelectAll(false, [], changeRows)
278
+ if (rs.onSelectNone) rs.onSelectNone()
279
+ }
280
+ },
281
+
282
+ handleResize: function (colKey, width) {
283
+ var widths = new Map(this.tableCtx.layout.columnWidths)
284
+ widths.set(colKey, width)
285
+ this.tableCtx.layout.columnWidths = widths
286
+ },
287
+
288
+ handleReorder: function (oldIndex, newIndex) {
289
+ const display = this.tableCtx.data.display.slice()
290
+ const moved = display.splice(oldIndex, 1)[0]
291
+ display.splice(newIndex, 0, moved)
292
+
293
+ const cb = this.tableCtx.draggable.handleReorder
294
+ if (typeof cb === 'function') cb(oldIndex, newIndex, display)
295
+ },
296
+
297
+ handleContainerResize: function (size) {
298
+ this.tableCtx.layout.containerWidth = size.width
299
+ }
300
+ }
301
+ }
302
+ </script>
303
+
304
+ <style src="./style/table.css" scoped></style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <colgroup>
3
+ <col
4
+ v-for="col in tableContext.columns.flat"
5
+ :key="col.key"
6
+ :class="isSelectionCol(col) ? 'ui-table-v2__selection-col' : ''"
7
+ :style="colStyle(col)"
8
+ />
9
+ <col v-if="hasScrollBar" :style="{ width: tableContext.layout.scrollBarWidth }" />
10
+ </colgroup>
11
+ </template>
12
+
13
+ <script>
14
+ import { toCssSize } from '../../utils/common'
15
+ import { SELECTION_COLUMN, DRAGGABLE_COLUMN } from './constants.js'
16
+
17
+ export default {
18
+ name: 'TableV2ColGroup',
19
+ inject: ['tableContext'],
20
+ props: {
21
+ isHeader: { type: Boolean, default: false }
22
+ },
23
+ methods: {
24
+ toCssSize,
25
+ colStyle: function (col) {
26
+ const res = {}
27
+ res.width = (this.tableContext.layout.columnWidths.get(col.key) || col.width) + 'px'
28
+ if (col.type === SELECTION_COLUMN) {
29
+ const w = (this.tableContext.selection.columnWidth || 36) + 'px'
30
+ res.width = w
31
+ res.minWidth = w
32
+ res.maxWidth = w
33
+ }
34
+ if (col.type === DRAGGABLE_COLUMN) {
35
+ const w = (this.tableContext.draggable.columnWidth || 36) + 'px'
36
+ res.width = w
37
+ res.minWidth = w
38
+ res.maxWidth = w
39
+ }
40
+ return res
41
+ },
42
+ isSelectionCol: function (col) {
43
+ return col.type === SELECTION_COLUMN
44
+ },
45
+ isDraggableCol: function (col) {
46
+ return col.key === DRAGGABLE_COLUMN
47
+ }
48
+ },
49
+ computed: {
50
+ hasScrollBar: function () {
51
+ return this.isHeader && this.tableContext.layout.scrollBarWidth != '0px'
52
+ }
53
+ }
54
+ }
55
+ </script>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <div class="ui-table-v2__empty"></div>
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ name: 'TableV2Empty',
8
+ inject: ['tableContext']
9
+ }
10
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <div class="ui-table-v2__loading-wrap" :class="{ 'ui-table-v2__loading-wrap--loading': isLoading }">
3
+ <slot />
4
+ <div v-if="isLoading" class="ui-table-v2__loading-overlay">
5
+ <Spinner size="md" />
6
+ </div>
7
+ </div>
8
+ </template>
9
+
10
+ <script>
11
+ import Spinner from '../spinner/Spinner.vue'
12
+
13
+ export default {
14
+ name: 'TableV2Loading',
15
+ components: { Spinner },
16
+ inject: ['tableContext'],
17
+ computed: {
18
+ isLoading: function () {
19
+ return this.tableContext.data.loading
20
+ }
21
+ }
22
+ }
23
+ </script>
24
+
25
+ <style src="./style/table-loading.css" scoped></style>
@@ -0,0 +1,91 @@
1
+ <script>
2
+ import { findDOMNode } from '../../utils/common'
3
+
4
+ export default {
5
+ name: 'TableResizeObserver',
6
+ emits: ['resize'],
7
+
8
+ data() {
9
+ return {
10
+ state: {
11
+ width: 0,
12
+ height: 0,
13
+ offsetHeight: 0,
14
+ offsetWidth: 0
15
+ },
16
+ currentElement: null,
17
+ resizeObserver: null
18
+ }
19
+ },
20
+
21
+ render() {
22
+ // eslint-disable-next-line vue/require-slots-as-functions
23
+ const slot = this.$slots.default
24
+ if (typeof slot === 'function') {
25
+ return slot()
26
+ }
27
+ return (slot && slot[0]) || null
28
+ },
29
+
30
+ methods: {
31
+ registerObserver() {
32
+ const element = findDOMNode(this)
33
+ const elementChanged = element !== this.currentElement
34
+ if (elementChanged) {
35
+ this.destroyObserver()
36
+ this.currentElement = element
37
+ }
38
+ if (!element) return
39
+ this.resizeObserver = new ResizeObserver(entries => {
40
+ this.handleEmitResize(entries)
41
+ })
42
+ this.resizeObserver.observe(this.currentElement)
43
+ },
44
+ handleEmitResize(entries) {
45
+ const target = entries[0].target
46
+
47
+ const { width, height } = target.getBoundingClientRect()
48
+ const { offsetWidth, offsetHeight } = target
49
+
50
+ const fixedWidth = Math.floor(width)
51
+ const fixedHeight = Math.floor(height)
52
+
53
+ if (
54
+ this.state.width !== fixedWidth ||
55
+ this.state.height !== fixedHeight ||
56
+ this.state.offsetWidth !== offsetWidth ||
57
+ this.state.offsetHeight !== offsetHeight
58
+ ) {
59
+ const size = { width: fixedWidth, height: fixedHeight, offsetWidth, offsetHeight }
60
+
61
+ Object.assign(this.state, size)
62
+ Promise.resolve().then(() => {
63
+ this.$emit('resize', {
64
+ ...size,
65
+ offsetWidth,
66
+ offsetHeight
67
+ })
68
+ })
69
+ }
70
+ },
71
+ destroyObserver() {
72
+ if (this.resizeObserver) {
73
+ this.resizeObserver.disconnect()
74
+ this.resizeObserver = null
75
+ }
76
+ }
77
+ },
78
+
79
+ mounted() {
80
+ this.registerObserver()
81
+ },
82
+
83
+ beforeUnmount() {
84
+ this.destroyObserver()
85
+ },
86
+ // eslint-disable-next-line vue/no-deprecated-destroyed-lifecycle, vue/no-dupe-keys
87
+ beforeDestroy() {
88
+ this.destroyObserver()
89
+ }
90
+ }
91
+ </script>