@jetlinks-web/components 3.2.1 → 3.2.3

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.
@@ -5,15 +5,15 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
8
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
9
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _vue = require("vue");
11
11
  var _antDesignVue = require("ant-design-vue");
12
12
  var _table = require("ant-design-vue/lib/table");
13
13
  var _useVirtualScroll = require("./useVirtualScroll");
14
14
  var _useTreeData = require("./useTreeData");
15
- // 展开图标组件
16
- var ExpandIcon = (0, _vue.defineComponent)({
15
+ // 展开图标组件 - 使用 markRaw 避免响应式包装
16
+ var ExpandIcon = (0, _vue.markRaw)((0, _vue.defineComponent)({
17
17
  name: 'VirtualExpandIcon',
18
18
  props: {
19
19
  expanded: Boolean,
@@ -32,7 +32,6 @@ var ExpandIcon = (0, _vue.defineComponent)({
32
32
  };
33
33
  return function () {
34
34
  if (!props.hasChildren) {
35
- // 占位符,保持对齐
36
35
  return (0, _vue.createVNode)("span", {
37
36
  "class": "".concat(props.prefixCls, "-row-expand-icon ").concat(props.prefixCls, "-row-expand-icon-spaced")
38
37
  }, null);
@@ -45,11 +44,57 @@ var ExpandIcon = (0, _vue.defineComponent)({
45
44
  }, null);
46
45
  };
47
46
  }
48
- });
47
+ }));
48
+ // Proxy 缓存池
49
+ var proxyCache = new WeakMap();
50
+ function getOrCreateProxy(record, node) {
51
+ var proxy = proxyCache.get(record);
52
+ if (proxy && proxy.__virtual_tree_node__ === node) {
53
+ return proxy;
54
+ }
55
+ proxy = new Proxy(record, {
56
+ get: function get(target, prop) {
57
+ if (prop === '__virtual_tree_node__') {
58
+ return node;
59
+ }
60
+ return Reflect.get(target, prop);
61
+ },
62
+ set: function set(target, prop, value) {
63
+ if (prop !== '__virtual_tree_node__') {
64
+ return Reflect.set(target, prop, value);
65
+ }
66
+ return true;
67
+ },
68
+ has: function has(target, prop) {
69
+ if (prop === '__virtual_tree_node__') {
70
+ return true;
71
+ }
72
+ return Reflect.has(target, prop);
73
+ },
74
+ ownKeys: function ownKeys(target) {
75
+ return [].concat((0, _toConsumableArray2.default)(Reflect.ownKeys(target)), ['__virtual_tree_node__']);
76
+ },
77
+ getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, prop) {
78
+ if (prop === '__virtual_tree_node__') {
79
+ return {
80
+ configurable: true,
81
+ enumerable: false,
82
+ value: node
83
+ };
84
+ }
85
+ return Reflect.getOwnPropertyDescriptor(target, prop);
86
+ }
87
+ });
88
+ proxyCache.set(record, proxy);
89
+ return proxy;
90
+ }
49
91
  /**
50
92
  * 虚拟滚动 Table 组件
51
- * 完全兼容 a-table 的所有功能,同时支持大数据虚拟滚动
52
- * 支持树形数据的虚拟滚动
93
+ * 性能优化:
94
+ * 1. 数据切片使用 computed 缓存,避免重复切片
95
+ * 2. 使用 shallowRef 减少响应式开销
96
+ * 3. 使用 passive 滚动事件监听
97
+ * 4. rowKey 确保组件正确复用
53
98
  */
54
99
  var _default = exports.default = (0, _vue.defineComponent)({
55
100
  name: 'JVirtualTable',
@@ -67,9 +112,8 @@ var _default = exports.default = (0, _vue.defineComponent)({
67
112
  slots = _ref.slots,
68
113
  expose = _ref.expose,
69
114
  emit = _ref.emit;
70
- // Table ref
71
115
  var tableRef = (0, _vue.ref)();
72
- var scrollContainerRef = (0, _vue.ref)();
116
+ var scrollContainerRef = (0, _vue.shallowRef)();
73
117
  // 解析虚拟滚动配置
74
118
  var virtualConfig = (0, _vue.computed)(function () {
75
119
  if (!props.virtual) return null;
@@ -86,21 +130,18 @@ var _default = exports.default = (0, _vue.defineComponent)({
86
130
  threshold: props.virtual.threshold || 100
87
131
  };
88
132
  });
89
- // 获取容器高度
133
+ // 容器高度
90
134
  var containerHeight = (0, _vue.computed)(function () {
91
135
  var _props$scroll;
92
136
  if (!((_props$scroll = props.scroll) !== null && _props$scroll !== void 0 && _props$scroll.y)) return 0;
93
137
  var y = props.scroll.y;
94
138
  if (typeof y === 'number') return y;
95
- // 解析 '500px' 这样的字符串
96
139
  var num = parseInt(String(y), 10);
97
140
  return isNaN(num) ? 0 : num;
98
141
  });
99
- // 获取子节点字段名
100
142
  var childrenColumnName = (0, _vue.computed)(function () {
101
143
  return props.childrenColumnName || 'children';
102
144
  });
103
- // 获取 rowKey
104
145
  var rowKeyProp = (0, _vue.computed)(function () {
105
146
  return props.rowKey || 'key';
106
147
  });
@@ -112,7 +153,7 @@ var _default = exports.default = (0, _vue.defineComponent)({
112
153
  return children && Array.isArray(children) && children.length > 0;
113
154
  });
114
155
  });
115
- // 使用树形数据 hook
156
+ // 树形数据处理
116
157
  var treeDataResult = (0, _useTreeData.useTreeData)({
117
158
  data: (0, _vue.toRef)(props, 'dataSource'),
118
159
  childrenColumnName: childrenColumnName.value,
@@ -121,32 +162,29 @@ var _default = exports.default = (0, _vue.defineComponent)({
121
162
  expandedRowKeys: props.expandedRowKeys ? (0, _vue.toRef)(props, 'expandedRowKeys') : undefined,
122
163
  defaultExpandAllRows: props.defaultExpandAllRows,
123
164
  onExpandedRowsChange: function onExpandedRowsChange(keys) {
124
- emit('expandedRowsChange', keys);
165
+ return emit('expandedRowsChange', keys);
125
166
  }
126
167
  });
127
- // 处理展开/折叠
128
168
  var handleExpand = function handleExpand(node) {
129
169
  treeDataResult.toggle(node.key);
130
170
  emit('expand', !node.expanded, node.record);
131
171
  };
132
- // 判断是否启用虚拟滚动
133
- var shouldEnableVirtual = (0, _vue.computed)(function () {
134
- var _props$scroll2, _props$dataSource;
135
- if (!virtualConfig.value) return false;
136
- if (!((_props$scroll2 = props.scroll) !== null && _props$scroll2 !== void 0 && _props$scroll2.y)) return false;
137
- // 对于树形数据,使用扁平化后的数据长度
138
- var dataLength = isTreeData.value ? treeDataResult.flattenedData.value.length : ((_props$dataSource = props.dataSource) === null || _props$dataSource === void 0 ? void 0 : _props$dataSource.length) || 0;
139
- return dataLength >= virtualConfig.value.threshold;
140
- });
141
- // 虚拟滚动的数据数量(树形数据使用扁平化后的长度)
172
+ // 数据数量
142
173
  var itemCount = (0, _vue.computed)(function () {
143
- var _props$dataSource2;
174
+ var _props$dataSource;
144
175
  if (isTreeData.value) {
145
176
  return treeDataResult.flattenedData.value.length;
146
177
  }
147
- return ((_props$dataSource2 = props.dataSource) === null || _props$dataSource2 === void 0 ? void 0 : _props$dataSource2.length) || 0;
178
+ return ((_props$dataSource = props.dataSource) === null || _props$dataSource === void 0 ? void 0 : _props$dataSource.length) || 0;
148
179
  });
149
- // 初始化虚拟滚动
180
+ // 判断是否启用虚拟滚动
181
+ var shouldEnableVirtual = (0, _vue.computed)(function () {
182
+ var _props$scroll2;
183
+ if (!virtualConfig.value) return false;
184
+ if (!((_props$scroll2 = props.scroll) !== null && _props$scroll2 !== void 0 && _props$scroll2.y)) return false;
185
+ return itemCount.value >= virtualConfig.value.threshold;
186
+ });
187
+ // 虚拟滚动 hook
150
188
  var virtualScroll = (0, _useVirtualScroll.useVirtualScroll)({
151
189
  itemCount: itemCount,
152
190
  containerHeight: containerHeight,
@@ -154,178 +192,86 @@ var _default = exports.default = (0, _vue.defineComponent)({
154
192
  overscan: ((_virtualConfig$value2 = virtualConfig.value) === null || _virtualConfig$value2 === void 0 ? void 0 : _virtualConfig$value2.overscan) || 5,
155
193
  threshold: ((_virtualConfig$value3 = virtualConfig.value) === null || _virtualConfig$value3 === void 0 ? void 0 : _virtualConfig$value3.threshold) || 100
156
194
  });
157
- // 查找并监听滚动容器
158
- var findScrollContainer = function findScrollContainer() {
159
- if (!tableRef.value) return null;
160
- // 查找 .ant-table-body 元素(这是实际的滚动容器)
161
- var tableElement = tableRef.value.$el || tableRef.value;
162
- var scrollBody = tableElement.querySelector('.ant-table-body');
163
- return scrollBody;
164
- };
165
- // 设置滚动监听
166
- var setupScrollListener = function setupScrollListener() {
167
- (0, _vue.nextTick)(function () {
168
- var container = findScrollContainer();
169
- if (container) {
170
- scrollContainerRef.value = container;
171
- container.addEventListener('scroll', virtualScroll.handleScroll);
172
- }
173
- });
174
- };
175
- // 移除滚动监听
176
- var removeScrollListener = function removeScrollListener() {
177
- if (scrollContainerRef.value) {
178
- scrollContainerRef.value.removeEventListener('scroll', virtualScroll.handleScroll);
179
- scrollContainerRef.value = undefined;
180
- }
181
- };
182
- // 监听虚拟滚动启用状态变化
183
- (0, _vue.watch)(shouldEnableVirtual, function (enabled) {
184
- if (enabled) {
185
- setupScrollListener();
186
- } else {
187
- removeScrollListener();
195
+ // ⭐ 关键优化:使用 computed 缓存切片数据,避免每次渲染都创建新数组
196
+ var virtualDataSource = (0, _vue.computed)(function () {
197
+ if (!shouldEnableVirtual.value) {
198
+ return props.dataSource || [];
188
199
  }
189
- });
190
- // 生命周期
191
- (0, _vue.onMounted)(function () {
192
- if (shouldEnableVirtual.value) {
193
- setupScrollListener();
200
+ var start = virtualScroll.startIndex.value;
201
+ var end = virtualScroll.endIndex.value;
202
+ if (isTreeData.value) {
203
+ var flatData = treeDataResult.flattenedData.value;
204
+ var visibleNodes = flatData.slice(start, end);
205
+ return visibleNodes.map(function (node) {
206
+ return getOrCreateProxy(node.record, node);
207
+ });
194
208
  }
209
+ return (props.dataSource || []).slice(start, end);
195
210
  });
196
- (0, _vue.onBeforeUnmount)(function () {
197
- removeScrollListener();
198
- });
199
- // 暴露方法
200
- (0, _vue.defineExpose)({
201
- scrollTo: virtualScroll.scrollTo,
202
- scrollToIndex: virtualScroll.scrollToIndex,
203
- // 树形数据相关方法
204
- expand: treeDataResult.expand,
205
- collapse: treeDataResult.collapse,
206
- toggle: treeDataResult.toggle,
207
- expandAll: treeDataResult.expandAll,
208
- collapseAll: treeDataResult.collapseAll,
209
- expandTo: treeDataResult.expandTo,
210
- isExpanded: treeDataResult.isExpanded
211
- });
212
- // 渲染函数
213
- return function () {
211
+ // 缓存 columns 处理
212
+ var processedColumns = (0, _vue.computed)(function () {
214
213
  var _props$indentSize;
215
- // 不使用虚拟滚动的情况
216
- if (!shouldEnableVirtual.value) {
217
- return (0, _vue.createVNode)(_antDesignVue.Table, (0, _objectSpread2.default)((0, _objectSpread2.default)({
218
- "ref": tableRef
219
- }, attrs), props), slots);
214
+ if (!isTreeData.value || !shouldEnableVirtual.value) {
215
+ return props.columns;
220
216
  }
221
- // 使用虚拟滚动
222
- var startIndex = virtualScroll.startIndex,
223
- endIndex = virtualScroll.endIndex,
224
- offsetY = virtualScroll.offsetY,
225
- totalHeight = virtualScroll.totalHeight;
226
- // 准备虚拟滚动数据
227
- var virtualDataSource;
228
- var needsCustomIndent = false;
217
+ var columns = props.columns;
218
+ if (!columns || columns.length === 0) return columns;
229
219
  var indentSize = (_props$indentSize = props.indentSize) !== null && _props$indentSize !== void 0 ? _props$indentSize : 15;
230
- if (isTreeData.value) {
231
- // 树形数据:使用扁平化后的数据
232
- var flatData = treeDataResult.flattenedData.value;
233
- var visibleNodes = flatData.slice(startIndex.value, endIndex.value);
234
- // 使用 Proxy 代理原始 record,确保修改能同步到原始数据
235
- virtualDataSource = visibleNodes.map(function (node) {
236
- return new Proxy(node.record, {
237
- get: function get(target, prop) {
238
- if (prop === '__virtual_tree_node__') {
239
- return node;
220
+ return columns.map(function (col, colIndex) {
221
+ if (colIndex === 0) {
222
+ var originalRender = col.customRender;
223
+ return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, col), {}, {
224
+ customRender: function customRender(renderProps) {
225
+ var record = renderProps.record,
226
+ text = renderProps.text;
227
+ var treeNode = record.__virtual_tree_node__;
228
+ if (!treeNode) {
229
+ if (originalRender) return originalRender(renderProps);
230
+ return text;
240
231
  }
241
- return Reflect.get(target, prop);
242
- },
243
- set: function set(target, prop, value) {
244
- if (prop !== '__virtual_tree_node__') {
245
- return Reflect.set(target, prop, value);
246
- }
247
- return true;
248
- },
249
- has: function has(target, prop) {
250
- if (prop === '__virtual_tree_node__') {
251
- return true;
252
- }
253
- return Reflect.has(target, prop);
254
- },
255
- ownKeys: function ownKeys(target) {
256
- return [].concat((0, _toConsumableArray2.default)(Reflect.ownKeys(target)), ['__virtual_tree_node__']);
257
- },
258
- getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, prop) {
259
- if (prop === '__virtual_tree_node__') {
260
- return {
261
- configurable: true,
262
- enumerable: false,
263
- value: node
264
- };
265
- }
266
- return Reflect.getOwnPropertyDescriptor(target, prop);
232
+ var level = treeNode.level,
233
+ hasChildren = treeNode.hasChildren,
234
+ expanded = treeNode.expanded;
235
+ var indentStyle = {
236
+ paddingLeft: "".concat(level * indentSize, "px"),
237
+ display: 'inline-flex',
238
+ alignItems: 'center'
239
+ };
240
+ var content = originalRender ? originalRender(renderProps) : text;
241
+ return (0, _vue.createVNode)("span", {
242
+ "style": indentStyle
243
+ }, [(0, _vue.createVNode)(ExpandIcon, {
244
+ "expanded": expanded,
245
+ "hasChildren": hasChildren,
246
+ "onExpand": function onExpand() {
247
+ return handleExpand(treeNode);
248
+ }
249
+ }, null), (0, _vue.createVNode)("span", null, [content])]);
267
250
  }
268
251
  });
269
- });
270
- needsCustomIndent = true;
271
- } else {
272
- // 普通数据:直接切片
273
- virtualDataSource = (props.dataSource || []).slice(startIndex.value, endIndex.value);
274
- }
275
- // 处理列,添加树形展开功能
276
- var processedColumns = props.columns;
277
- if (needsCustomIndent && processedColumns && processedColumns.length > 0) {
278
- // 克隆 columns,修改第一列以添加展开按钮和缩进
279
- processedColumns = processedColumns.map(function (col, colIndex) {
280
- if (colIndex === 0) {
281
- var originalRender = col.customRender;
282
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, col), {}, {
283
- customRender: function customRender(renderProps) {
284
- var record = renderProps.record,
285
- text = renderProps.text,
286
- index = renderProps.index;
287
- var treeNode = record.__virtual_tree_node__;
288
- if (!treeNode) {
289
- // 非树形数据行,使用原始渲染
290
- if (originalRender) {
291
- return originalRender(renderProps);
292
- }
293
- return text;
294
- }
295
- var level = treeNode.level,
296
- hasChildren = treeNode.hasChildren,
297
- expanded = treeNode.expanded;
298
- var indentStyle = {
299
- paddingLeft: "".concat(level * indentSize, "px"),
300
- display: 'inline-flex',
301
- alignItems: 'center'
302
- };
303
- var content = originalRender ? originalRender(renderProps) : text;
304
- return (0, _vue.createVNode)("span", {
305
- "style": indentStyle
306
- }, [(0, _vue.createVNode)(ExpandIcon, {
307
- "expanded": expanded,
308
- "hasChildren": hasChildren,
309
- "onExpand": function onExpand() {
310
- return handleExpand(treeNode);
311
- }
312
- }, null), (0, _vue.createVNode)("span", null, [content])]);
313
- }
314
- });
315
- }
316
- return col;
317
- });
252
+ }
253
+ return col;
254
+ });
255
+ });
256
+ // 缓存 components
257
+ var virtualComponents = (0, _vue.computed)(function () {
258
+ if (!shouldEnableVirtual.value) {
259
+ return props.components;
318
260
  }
319
- // 自定义 body 组件
320
- var customComponents = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props.components || {}), {}, {
261
+ var startIndex = virtualScroll.startIndex,
262
+ endIndex = virtualScroll.endIndex,
263
+ offsetY = virtualScroll.offsetY,
264
+ totalHeight = virtualScroll.totalHeight,
265
+ getItemHeight = virtualScroll.getItemHeight;
266
+ var columns = processedColumns.value;
267
+ return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props.components || {}), {}, {
321
268
  body: {
322
269
  wrapper: function wrapper(bodyProps, _ref2) {
323
- var _processedColumns, _bodySlots$default, _processedColumns2;
270
+ var _bodySlots$default;
324
271
  var bodySlots = _ref2.slots;
325
- // 计算底部占位高度
326
272
  var accumulatedHeight = offsetY.value;
327
273
  for (var i = startIndex.value; i < endIndex.value; i++) {
328
- accumulatedHeight += virtualScroll.getItemHeight(i);
274
+ accumulatedHeight += getItemHeight(i);
329
275
  }
330
276
  var bottomHeight = totalHeight.value - accumulatedHeight;
331
277
  return (0, _vue.createVNode)("tbody", (0, _objectSpread2.default)((0, _objectSpread2.default)({}, bodyProps), {}, {
@@ -341,7 +287,7 @@ var _default = exports.default = (0, _vue.defineComponent)({
341
287
  border: 0,
342
288
  height: "".concat(offsetY.value, "px")
343
289
  },
344
- "colSpan": ((_processedColumns = processedColumns) === null || _processedColumns === void 0 ? void 0 : _processedColumns.length) || 1
290
+ "colSpan": (columns === null || columns === void 0 ? void 0 : columns.length) || 1
345
291
  }, null)]), (_bodySlots$default = bodySlots.default) === null || _bodySlots$default === void 0 ? void 0 : _bodySlots$default.call(bodySlots), bottomHeight > 0 && (0, _vue.createVNode)("tr", {
346
292
  "aria-hidden": "true",
347
293
  "style": {
@@ -353,22 +299,85 @@ var _default = exports.default = (0, _vue.defineComponent)({
353
299
  border: 0,
354
300
  height: "".concat(bottomHeight, "px")
355
301
  },
356
- "colSpan": ((_processedColumns2 = processedColumns) === null || _processedColumns2 === void 0 ? void 0 : _processedColumns2.length) || 1
302
+ "colSpan": (columns === null || columns === void 0 ? void 0 : columns.length) || 1
357
303
  }, null)])]);
358
304
  }
359
305
  }
360
306
  });
361
- // 移除树形数据的 children 配置,因为我们自己处理
362
- var tableProps = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
363
- dataSource: virtualDataSource,
364
- columns: processedColumns,
365
- components: customComponents
366
- }, isTreeData.value ? {
307
+ });
308
+ // 滚动监听
309
+ var findScrollContainer = function findScrollContainer() {
310
+ if (!tableRef.value) return null;
311
+ var tableElement = tableRef.value.$el || tableRef.value;
312
+ return tableElement.querySelector('.ant-table-body');
313
+ };
314
+ var setupScrollListener = function setupScrollListener() {
315
+ (0, _vue.nextTick)(function () {
316
+ var container = findScrollContainer();
317
+ if (container) {
318
+ scrollContainerRef.value = container;
319
+ container.addEventListener('scroll', virtualScroll.handleScroll, {
320
+ passive: true
321
+ });
322
+ }
323
+ });
324
+ };
325
+ var removeScrollListener = function removeScrollListener() {
326
+ if (scrollContainerRef.value) {
327
+ scrollContainerRef.value.removeEventListener('scroll', virtualScroll.handleScroll);
328
+ scrollContainerRef.value = undefined;
329
+ }
330
+ };
331
+ (0, _vue.watch)(shouldEnableVirtual, function (enabled) {
332
+ if (enabled) setupScrollListener();else removeScrollListener();
333
+ });
334
+ (0, _vue.onMounted)(function () {
335
+ if (shouldEnableVirtual.value) setupScrollListener();
336
+ });
337
+ (0, _vue.onBeforeUnmount)(function () {
338
+ removeScrollListener();
339
+ });
340
+ // 滚动到指定索引(同时更新虚拟状态和真实 DOM)
341
+ var scrollToIndex = function scrollToIndex(index) {
342
+ virtualScroll.scrollToIndex(index);
343
+ // 同步滚动真实 DOM
344
+ (0, _vue.nextTick)(function () {
345
+ if (scrollContainerRef.value) {
346
+ scrollContainerRef.value.scrollTop = virtualScroll.scrollTop.value;
347
+ }
348
+ });
349
+ };
350
+ // 滚动到指定位置
351
+ var scrollTo = function scrollTo(offset) {
352
+ virtualScroll.scrollTo(offset);
353
+ (0, _vue.nextTick)(function () {
354
+ if (scrollContainerRef.value) {
355
+ scrollContainerRef.value.scrollTop = virtualScroll.scrollTop.value;
356
+ }
357
+ });
358
+ };
359
+ expose({
360
+ scrollTo: scrollTo,
361
+ scrollToIndex: scrollToIndex,
362
+ expand: treeDataResult.expand,
363
+ collapse: treeDataResult.collapse,
364
+ toggle: treeDataResult.toggle,
365
+ expandAll: treeDataResult.expandAll,
366
+ collapseAll: treeDataResult.collapseAll,
367
+ expandTo: treeDataResult.expandTo,
368
+ isExpanded: treeDataResult.isExpanded
369
+ });
370
+ return function () {
371
+ var tablePropsObj = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
372
+ dataSource: virtualDataSource.value,
373
+ columns: processedColumns.value,
374
+ components: virtualComponents.value
375
+ }, isTreeData.value && shouldEnableVirtual.value ? {
367
376
  childrenColumnName: '__disabled__'
368
377
  } : {});
369
378
  return (0, _vue.createVNode)(_antDesignVue.Table, (0, _objectSpread2.default)((0, _objectSpread2.default)({
370
379
  "ref": tableRef
371
- }, attrs), tableProps), slots);
380
+ }, attrs), tablePropsObj), slots);
372
381
  };
373
382
  }
374
383
  });