@qin-ui/antd-vue-pro 2.5.3 → 2.6.1

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 (42) hide show
  1. package/AI-CONTEXT.md +30 -10
  2. package/api.json +23 -3
  3. package/es/antd-vue-pro.css +6 -6
  4. package/es/components/component-provider/components/index.vue.d.ts.map +1 -1
  5. package/es/components/component-provider/types/index.d.ts +1 -1
  6. package/es/components/component-provider/types/index.d.ts.map +1 -1
  7. package/es/components/form/components/BaseField/index.vue.d.ts.map +1 -1
  8. package/es/components/form/components/BaseField/utils/index.d.ts +1 -2
  9. package/es/components/form/components/BaseField/utils/index.d.ts.map +1 -1
  10. package/es/components/form/components/ProForm/index.vue.d.ts.map +1 -1
  11. package/es/components/table/components/ProTable.vue.d.ts +11 -3
  12. package/es/components/table/components/ProTable.vue.d.ts.map +1 -1
  13. package/es/components/table/components/TableEllipsisTooltip.vue.d.ts +19 -0
  14. package/es/components/table/components/TableEllipsisTooltip.vue.d.ts.map +1 -0
  15. package/es/components/table/hooks/useEllipsisTooltip.d.ts +45 -0
  16. package/es/components/table/hooks/useEllipsisTooltip.d.ts.map +1 -0
  17. package/es/components/table/hooks/useEllipsisTooltipColumns.d.ts +19 -0
  18. package/es/components/table/hooks/useEllipsisTooltipColumns.d.ts.map +1 -0
  19. package/es/components/table/index.d.ts +1 -1
  20. package/es/components/table/index.d.ts.map +1 -1
  21. package/es/components/table/types/index.d.ts +47 -2
  22. package/es/components/table/types/index.d.ts.map +1 -1
  23. package/es/index.js +544 -118
  24. package/es/index.js.map +1 -1
  25. package/es/shared/core/index.d.ts +1 -1
  26. package/es/shared/core/index.d.ts.map +1 -1
  27. package/es/shared/ui/index.d.ts +2 -1
  28. package/es/shared/ui/index.d.ts.map +1 -1
  29. package/package.json +2 -2
  30. package/src/components/component-provider/components/index.vue +31 -8
  31. package/src/components/component-provider/types/index.ts +1 -0
  32. package/src/components/form/components/BaseField/index.vue +21 -12
  33. package/src/components/form/components/BaseField/utils/index.ts +5 -5
  34. package/src/components/form/components/ProForm/index.vue +9 -2
  35. package/src/components/table/components/ProTable.vue +198 -71
  36. package/src/components/table/components/TableEllipsisTooltip.vue +90 -0
  37. package/src/components/table/hooks/useEllipsisTooltip.ts +244 -0
  38. package/src/components/table/hooks/useEllipsisTooltipColumns.ts +154 -0
  39. package/src/components/table/index.ts +7 -1
  40. package/src/components/table/types/index.ts +63 -2
  41. package/src/shared/core/index.ts +2 -0
  42. package/src/shared/ui/index.ts +3 -0
@@ -46,11 +46,12 @@
46
46
  * @param {boolean | Partial<Control>} [control] - 是否展示尺寸与列控制按钮;显式传入 columns 时列控入口不渲染
47
47
  * @param {SearchFormConfig} [searchFormConfig] - 搜索栏查询字段表单配置
48
48
  * @param {ContainerComponent | false} [tableContainer] - 表格区域包裹容器
49
+ * @param {boolean | EllipsisTooltipConfig} [ellipsisTooltip] - truthy 时全局启用所有列;对象同时作为 Tooltip 配置;列上 `showTooltip: false` 或 `ellipsis: false` 可退出
49
50
  *
50
51
  * @slot search-form - 搜索区域插槽,作用域参数 form / search / reset
51
52
  * @slot button-bar - 表格头部按钮区插槽
52
53
  * @slot toolbar - 工具栏插槽
53
- * @slot default - 透传给宿主表格的默认插槽(可用于以宿主列组件声明列)
54
+ * @slot default - 透传给宿主表格的默认插槽;未显式绑定 `columns` 且表格实例无列时用于声明列,显式传入(含空数组)时以列配置为准
54
55
  * @slot table - 表格区域插槽,作用域参数 columns / dataSource / pagination / loading / size / onChange
55
56
  */
56
57
  import type {
@@ -58,14 +59,19 @@ import type {
58
59
  TableProps,
59
60
  ColumnType,
60
61
  } from '../../../shared/ui';
61
- import { Table as ATable, tableProps } from '../../../shared/ui';
62
+ import { Table as ATable, TableColumn, tableProps } from '../../../shared/ui';
62
63
  import {
63
64
  computed,
64
65
  getCurrentInstance,
65
66
  nextTick,
66
67
  onMounted,
68
+ onUpdated,
67
69
  inject,
70
+ ref,
71
+ shallowRef,
68
72
  toValue,
73
+ triggerRef,
74
+ watch,
69
75
  type Slot,
70
76
  } from 'vue';
71
77
  import { INJECT_CONFIG } from '../../component-provider/constants';
@@ -78,6 +84,7 @@ import { useLocale } from '../../../locale';
78
84
  import type { Path } from '../../../shared/core';
79
85
  import {
80
86
  camelizeProperties,
87
+ callListeners,
81
88
  getObject,
82
89
  isObjectItem,
83
90
  isPlainObject,
@@ -91,7 +98,15 @@ import DefaultSearchFormContainer from './DefaultSearchFormContainer.vue';
91
98
  import DefaultTableContainer from './DefaultTableContainer.vue';
92
99
  import SizeControl from './SizeControl.vue';
93
100
  import ColumnControl from './ColumnControl.vue';
94
- import type { Column, Columns, ColumnControlConfig } from '../types';
101
+ import TableEllipsisTooltip from './TableEllipsisTooltip.vue';
102
+ import { useEllipsisTooltip } from '../hooks/useEllipsisTooltip';
103
+ import { useEllipsisTooltipColumns } from '../hooks/useEllipsisTooltipColumns';
104
+ import type {
105
+ Column,
106
+ Columns,
107
+ ColumnControlConfig,
108
+ EllipsisTooltipConfig,
109
+ } from '../types';
95
110
 
96
111
  defineOptions({ name: 'ProTable', inheritAttrs: false });
97
112
 
@@ -124,6 +139,8 @@ type Props = {
124
139
  searchFormConfig?: SearchFormConfig;
125
140
  /** 表格区域包裹容器 */
126
141
  tableContainer?: ContainerComponent | false;
142
+ /** 表格级省略 Tooltip 配置;truthy 时全局启用 */
143
+ ellipsisTooltip?: boolean | EllipsisTooltipConfig;
127
144
  } & /* @vue-ignore */ TableProps;
128
145
 
129
146
  const props = withDefaults(defineProps<Props>(), {
@@ -134,6 +151,7 @@ const props = withDefaults(defineProps<Props>(), {
134
151
  control: undefined,
135
152
  searchFormConfig: undefined,
136
153
  tableContainer: undefined,
154
+ ellipsisTooltip: undefined,
137
155
  });
138
156
 
139
157
  const { t } = useLocale();
@@ -171,6 +189,8 @@ const searchFormProps = computed(() => {
171
189
 
172
190
  const attrs: Record<string, any> = useReactiveAttrs();
173
191
 
192
+ const rootRef = ref<HTMLElement | null>(null);
193
+
174
194
  const size = defineModel<TableProps['size']>('size');
175
195
  const loading = defineModel<boolean>('loading', { default: false });
176
196
 
@@ -194,16 +214,21 @@ const _search = async () => {
194
214
  if (props.search && attrs.onSearch) {
195
215
  warnSearchConfig('duplicate');
196
216
  }
197
- if (!search) return;
198
- const searchPromise = search();
199
- if (!isPromise(searchPromise)) {
217
+ const results = callListeners(search);
218
+ if (!results.length) return;
219
+ const promises = results.filter(isPromise);
220
+ if (!promises.length) {
200
221
  warnSearchConfig('not-promise');
201
222
  return;
202
223
  }
203
224
  const seq = ++searchSequence;
204
225
  loading.value = true;
205
226
  try {
206
- await searchPromise;
227
+ const settled = await Promise.allSettled(promises);
228
+ const rejected = settled.find(item => item.status === 'rejected') as
229
+ | PromiseRejectedResult
230
+ | undefined;
231
+ if (rejected) throw rejected.reason;
207
232
  } finally {
208
233
  if (seq === searchSequence) {
209
234
  loading.value = false;
@@ -238,9 +263,17 @@ type TableSlots = Omit<ComponentSlots<typeof ATable>, 'bodyCell'> &
238
263
  column: Column<RecordType>;
239
264
  }) => void;
240
265
  }>;
241
- type Slots = Omit<TableSlots & CustomSlots, 'default'>;
266
+ type Slots = Omit<TableSlots & CustomSlots, 'default'> & {
267
+ /** 透传宿主表格的默认插槽,用于以宿主列组件声明列 */
268
+ default?: Slot;
269
+ };
242
270
 
243
271
  const slots = defineSlots<Slots>();
272
+ /* 默认插槽存在性随父级重渲染更新:运行期增删插槽后插槽列模式可感知 */
273
+ const slotsRef = shallowRef<Record<string, any>>(slots);
274
+ onUpdated(() => {
275
+ triggerRef(slotsRef);
276
+ });
244
277
  const forwardedSlotNames = () =>
245
278
  (Object.keys(slots) as Array<Extract<keyof Slots, string>>).filter(
246
279
  name => !customSlotNames.includes(name as any)
@@ -318,25 +351,6 @@ const effectiveSize = computed<TableProps['size']>(() => {
318
351
  return size.value ?? injectAttrs.value.size;
319
352
  });
320
353
 
321
- /*
322
- * 下发给宿主表格的属性:Provider 注入为底(其不可注入键已在注入层剔除),调用方绑定与 v-model 透传值覆盖同键。
323
- * size / loading 为声明模型,其 onUpdate:* 回写通道不进入 attrs,无需另行剔除
324
- */
325
- const computedTableProps = computed<TableProps>(() => {
326
- const merged = {
327
- ...injectAttrs.value,
328
- ...omitBy(
329
- pick(camelAttrs.value, tableProperties),
330
- value => value === undefined
331
- ),
332
- } as Record<string, any>;
333
- // onChange 由模板监听器收口,散落 attrs 中的同名监听器并入会形成重复回调
334
- delete merged.onChange;
335
- merged.size = effectiveSize.value;
336
- merged.loading = undefined;
337
- return merged as TableProps;
338
- });
339
-
340
354
  const computedTableContainer = computed(() => {
341
355
  const container =
342
356
  props.tableContainer ??
@@ -369,53 +383,125 @@ const indexColumn = computed<ColumnType>(() => ({
369
383
  customRender: ({ index }) => getIndex(index),
370
384
  }));
371
385
 
386
+ /** 插槽序号列的单元格渲染:按有效分页偏移行号 */
387
+ const slotIndexRender = ({ index }: { index: number }) => getIndex(index);
388
+
372
389
  // 列来源优先级:显式绑定 > table 实例(useTable 创建的 columns);显式列原样透传,不补齐 key
373
- const computedColumns = computed<Columns<RecordType>>(() => {
374
- const cols = (resolveOwnedProp('columns') ??
390
+ const columnSource = computed<any[]>(() => {
391
+ return (resolveOwnedProp('columns') ??
375
392
  toValue(props.table?.columns) ??
376
- []) as any;
377
- const needIndex = props.addIndexColumn ?? injectProps.value.addIndexColumn;
378
- return needIndex ? [indexColumn.value, ...cols] : cols;
393
+ []) as any[];
379
394
  });
380
395
 
396
+ /* 无列源且存在默认插槽时由宿主消费插槽列,序号列改由插槽内的列组件提供 */
397
+ const slotColumnsMode = computed(
398
+ () =>
399
+ !hasExplicitColumns.value &&
400
+ Boolean(slotsRef.value.default) &&
401
+ columnSource.value.length === 0
402
+ );
403
+ const indexEnabled = computed(() =>
404
+ Boolean(props.addIndexColumn ?? injectProps.value.addIndexColumn)
405
+ );
406
+
407
+ const computedColumns = computed<Columns<RecordType>>(() => {
408
+ if (slotColumnsMode.value) return [];
409
+ return indexEnabled.value
410
+ ? [indexColumn.value, ...columnSource.value]
411
+ : columnSource.value;
412
+ });
413
+
414
+ const ellipsisTooltipValue = computed(
415
+ () => props.ellipsisTooltip ?? injectProps.value.ellipsisTooltip
416
+ );
417
+ const ellipsisTooltipConfig = computed<EllipsisTooltipConfig>(() =>
418
+ typeof ellipsisTooltipValue.value === 'object' && ellipsisTooltipValue.value
419
+ ? ellipsisTooltipValue.value
420
+ : {}
421
+ );
422
+ const ellipsisTooltipGlobal = computed(() =>
423
+ Boolean(ellipsisTooltipValue.value)
424
+ );
425
+
426
+ const {
427
+ columns: visibleComputedColumns,
428
+ hasTooltip: ellipsisTooltipEnabled,
429
+ resolveOriginalColumn,
430
+ resolveSorterColumn,
431
+ } = useEllipsisTooltipColumns(
432
+ () => computedColumns.value,
433
+ () => ellipsisTooltipGlobal.value
434
+ );
435
+
436
+ /* 宿主列绑定:插槽列模式下不下发列配置,其余模式始终以列配置为准 */
437
+ const hostColumns = computed(() =>
438
+ slotColumnsMode.value ? undefined : visibleComputedColumns.value
439
+ );
440
+
381
441
  /*
382
- * 递归过滤 hidden 列(含分组子列):仅对被过滤过子列的列生成浅拷贝,
383
- * 未发生变动的列保持原对象引用(每次 columns 变化执行一次,不在渲染期递归)
442
+ * 下发给宿主表格的属性:Provider 注入为底(其不可注入键已在注入层剔除),调用方绑定与 v-model 透传值覆盖同键。
443
+ * size / loading 为声明模型,其 onUpdate:* 回写通道不进入 attrs,无需另行剔除
384
444
  */
385
- const filterVisibleColumns = (
386
- columns: any[],
387
- ancestors: Set<object> = new Set()
388
- ): { list: any[]; changed: boolean } => {
389
- const list: any[] = [];
390
- let changed = false;
391
- for (const column of columns) {
392
- if (!isObjectItem(column) || toValue((column as Column).hidden)) {
393
- changed = true;
394
- continue;
395
- }
396
- if (Array.isArray(column.children) && column.children.length > 0) {
397
- // 环状分组列不再深入,重复出现的祖先引用直接剔除
398
- if (ancestors.has(column)) {
399
- changed = true;
400
- continue;
401
- }
402
- ancestors.add(column);
403
- const filtered = filterVisibleColumns(column.children, ancestors);
404
- ancestors.delete(column);
405
- if (filtered.changed) {
406
- changed = true;
407
- list.push({ ...column, children: filtered.list });
408
- continue;
409
- }
410
- }
411
- list.push(column);
445
+ const computedTableProps = computed<TableProps>(() => {
446
+ const merged = {
447
+ ...injectAttrs.value,
448
+ ...omitBy(
449
+ pick(camelAttrs.value, tableProperties),
450
+ value => value === undefined
451
+ ),
452
+ } as Record<string, any>;
453
+ // onChange 由模板监听器收口,散落 attrs 中的同名监听器并入会形成重复回调
454
+ delete merged.onChange;
455
+ // resizeColumn 回传转换列时,用户回调仍操作原始列
456
+ const resizeColumn = merged.onResizeColumn;
457
+ if (typeof resizeColumn === 'function') {
458
+ merged.onResizeColumn = (width: number, column: any) =>
459
+ resizeColumn(width, resolveOriginalColumn(column));
412
460
  }
413
- return { list, changed };
414
- };
461
+ merged.size = effectiveSize.value;
462
+ merged.loading = undefined;
463
+ return merged as TableProps;
464
+ });
415
465
 
416
- const visibleComputedColumns = computed(() => {
417
- return filterVisibleColumns(computedColumns.value).list;
466
+ const ellipsisTooltipContainer = computed(() => {
467
+ const getPopupContainer = ellipsisTooltipConfig.value.getPopupContainer;
468
+ if (!getPopupContainer) return undefined;
469
+ return () => {
470
+ if (typeof document === 'undefined') return undefined;
471
+ const root = rootRef.value ?? document.body;
472
+ return getPopupContainer(root) ?? document.body;
473
+ };
418
474
  });
475
+ const ellipsisTooltipDelay = computed(() =>
476
+ Math.max(0, (ellipsisTooltipConfig.value.mouseEnterDelay ?? 0.2) * 1000)
477
+ );
478
+ const ellipsisTooltipLeaveDelay = computed(() =>
479
+ Math.max(0, (ellipsisTooltipConfig.value.mouseLeaveDelay ?? 0.1) * 1000)
480
+ );
481
+ const ellipsisTooltipProps = computed(() => {
482
+ const config = ellipsisTooltipConfig.value;
483
+ const {
484
+ getPopupContainer: _getPopupContainer,
485
+ mouseEnterDelay: _mouseEnterDelay,
486
+ mouseLeaveDelay: _mouseLeaveDelay,
487
+ ...rest
488
+ } = config;
489
+ return rest;
490
+ });
491
+
492
+ const {
493
+ open: ellipsisTooltipOpen,
494
+ content: ellipsisTooltipContent,
495
+ anchorStyle: ellipsisTooltipAnchorStyle,
496
+ onMouseOver: onEllipsisMouseOver,
497
+ onMouseOut: onEllipsisMouseOut,
498
+ close: closeEllipsisTooltip,
499
+ } = useEllipsisTooltip(
500
+ rootRef,
501
+ ellipsisTooltipEnabled,
502
+ ellipsisTooltipDelay,
503
+ ellipsisTooltipLeaveDelay
504
+ );
419
505
 
420
506
  // 数据源优先级:显式绑定 > table 实例(useTable 创建的 dataSource)
421
507
  const computedDataSource = computed<RecordType[]>(() => {
@@ -424,6 +510,9 @@ const computedDataSource = computed<RecordType[]>(() => {
424
510
  );
425
511
  });
426
512
 
513
+ // 列或数据变化后旧锚点失效,关闭共享 Tooltip
514
+ watch([visibleComputedColumns, computedDataSource], closeEllipsisTooltip);
515
+
427
516
  /*
428
517
  * 分页优先级:显式绑定 > provider 全局配置 > 默认合成;
429
518
  * provider 作为基础配置与 table.pageParam 合并,显式绑定的对象形态在其之上覆盖
@@ -479,9 +568,19 @@ const onTableChange: TableProps['onChange'] = (...args) => {
479
568
  );
480
569
  if (shadowed.length) warnPaginationShadow(shadowed);
481
570
  }
482
- // change 回放:模板监听器优先,未绑定时回退 Provider 全局配置
483
- (attrs.onChange ?? injectProps.value.onChange)?.(...args);
484
- _search();
571
+ // change 回放:模板监听器优先,未绑定时回退 Provider 全局配置;sorter.column 还原为原始列
572
+ const nextArgs = [...args] as any[];
573
+ const sorterArg = nextArgs[2];
574
+ if (Array.isArray(sorterArg)) {
575
+ nextArgs[2] = sorterArg.map(resolveSorterColumn);
576
+ } else if (sorterArg) {
577
+ nextArgs[2] = resolveSorterColumn(sorterArg);
578
+ }
579
+ try {
580
+ callListeners(attrs.onChange ?? injectProps.value.onChange, ...nextArgs);
581
+ } finally {
582
+ _search();
583
+ }
485
584
  };
486
585
 
487
586
  const searchFormVisible = computed(() => {
@@ -541,7 +640,15 @@ defineExpose({
541
640
  </script>
542
641
 
543
642
  <template>
544
- <div class="pro-table" :class="attrs.class" :style="attrs.style">
643
+ <div
644
+ ref="rootRef"
645
+ class="pro-table"
646
+ data-pro-table-root
647
+ :class="attrs.class"
648
+ :style="attrs.style"
649
+ @mouseover="onEllipsisMouseOver"
650
+ @mouseout="onEllipsisMouseOut"
651
+ >
545
652
  <ContainerFragment
546
653
  v-if="searchFormVisible || $slots['search-form']"
547
654
  :component="computedSearchFormConfig.container"
@@ -601,7 +708,7 @@ defineExpose({
601
708
  class="pro-table_content"
602
709
  v-bind="computedTableProps"
603
710
  :loading="loading"
604
- :columns="visibleComputedColumns"
711
+ :columns="hostColumns"
605
712
  :data-source="computedDataSource"
606
713
  :pagination="computedPagination"
607
714
  @change="onTableChange"
@@ -611,8 +718,19 @@ defineExpose({
611
718
  :key="name"
612
719
  #[name]="scoped"
613
720
  >
721
+ <template v-if="name === 'default'">
722
+ <TableColumn
723
+ v-if="slotColumnsMode && indexEnabled"
724
+ key="__INDEX__"
725
+ :title="t('table.index')"
726
+ :width="80"
727
+ data-index="__INDEX__"
728
+ :custom-render="slotIndexRender"
729
+ />
730
+ <slot name="default" v-bind="scoped || {}" />
731
+ </template>
614
732
  <slot
615
- v-if="isSlotRenderable(name, scoped)"
733
+ v-else-if="isSlotRenderable(name, scoped)"
616
734
  :name="name"
617
735
  v-bind="scoped"
618
736
  />
@@ -620,6 +738,15 @@ defineExpose({
620
738
  </ATable>
621
739
  </slot>
622
740
  </ContainerFragment>
741
+
742
+ <TableEllipsisTooltip
743
+ v-if="ellipsisTooltipEnabled"
744
+ :open="ellipsisTooltipOpen"
745
+ :content="ellipsisTooltipContent"
746
+ :anchor-style="ellipsisTooltipAnchorStyle"
747
+ :container="ellipsisTooltipContainer"
748
+ v-bind="ellipsisTooltipProps"
749
+ />
623
750
  </div>
624
751
  </template>
625
752
 
@@ -0,0 +1,90 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 表格级共享省略 Tooltip
4
+ *
5
+ * @component TableEllipsisTooltip
6
+ * @description 以固定定位锚点承载单个宿主 Tooltip,锚点位置由 ProTable 按悬停单元格更新;
7
+ * 整个表格只渲染一个 Tooltip 实例,实例数量不随单元格数量增长。
8
+ */
9
+ import { nextTick, ref, useAttrs, watch, type Component } from 'vue';
10
+ import { Tooltip as ATooltip } from '../../../shared/ui';
11
+ import type { EllipsisTooltipAnchorStyle } from '../hooks/useEllipsisTooltip';
12
+ import type { EllipsisTooltipConfig } from '../types';
13
+
14
+ defineOptions({ name: 'TableEllipsisTooltip', inheritAttrs: false });
15
+
16
+ type HostTooltipProps = Omit<
17
+ EllipsisTooltipConfig,
18
+ 'getPopupContainer' | 'mouseEnterDelay' | 'mouseLeaveDelay'
19
+ >;
20
+
21
+ type Props = {
22
+ open?: boolean;
23
+ content?: string;
24
+ anchorStyle?: EllipsisTooltipAnchorStyle;
25
+ container?: () => HTMLElement | null | undefined;
26
+ } & /* @vue-ignore */ HostTooltipProps;
27
+
28
+ const props = withDefaults(defineProps<Props>(), {
29
+ open: false,
30
+ content: '',
31
+ anchorStyle: () => ({
32
+ position: 'fixed',
33
+ pointerEvents: 'none',
34
+ opacity: 0,
35
+ }),
36
+ container: () => undefined,
37
+ });
38
+ const attrs = useAttrs() as HostTooltipProps;
39
+ const HostTooltip = ATooltip as unknown as Component;
40
+
41
+ type TooltipInstance = {
42
+ forceAlign?: () => void;
43
+ forcePopupAlign?: () => void;
44
+ };
45
+
46
+ const tooltipRef = ref<TooltipInstance | null>(null);
47
+
48
+ /** 锚点或内容变化后重算宿主浮层位置 */
49
+ const forceAlign = async () => {
50
+ if (!props.open) return;
51
+ await nextTick();
52
+ const instance = tooltipRef.value;
53
+ (instance?.forceAlign ?? instance?.forcePopupAlign)?.();
54
+ };
55
+
56
+ watch(() => props.anchorStyle, forceAlign, { deep: true });
57
+ watch(
58
+ () => props.open,
59
+ value => {
60
+ if (value) forceAlign();
61
+ }
62
+ );
63
+
64
+ const getContainerNode = (): HTMLElement | undefined => {
65
+ const container = props.container?.();
66
+ if (container) return container;
67
+ return typeof document !== 'undefined' ? document.body : undefined;
68
+ };
69
+
70
+ const getPopupContainer = () => getContainerNode() ?? document.body;
71
+ </script>
72
+
73
+ <template>
74
+ <Teleport :to="getContainerNode() ?? 'body'">
75
+ <HostTooltip
76
+ v-bind="attrs"
77
+ ref="tooltipRef"
78
+ :open="open"
79
+ :title="content"
80
+ :trigger="[]"
81
+ :get-popup-container="getPopupContainer"
82
+ >
83
+ <span
84
+ class="pro-table_ellipsis-tooltip-anchor"
85
+ :style="anchorStyle"
86
+ aria-hidden="true"
87
+ />
88
+ </HostTooltip>
89
+ </Teleport>
90
+ </template>