@v-c/table 1.1.9 → 1.2.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.
@@ -26,7 +26,207 @@ export declare function getCellProps<RecordType>(rowInfo: ReturnType<typeof useR
26
26
  key: import('../interface').Key;
27
27
  fixedInfo: import('../utils/fixUtil').FixedInfo;
28
28
  appendCellNode: any;
29
- additionalCellProps: Partial<import('../interface').CellAttributes>;
29
+ additionalCellProps: {
30
+ innerHTML?: string | undefined;
31
+ class?: import('vue').ClassValue | undefined;
32
+ style?: import('vue').StyleValue | undefined;
33
+ accesskey?: string | undefined;
34
+ contenteditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
35
+ contextmenu?: string | undefined;
36
+ dir?: string | undefined;
37
+ draggable?: (boolean | "true" | "false") | undefined;
38
+ enterkeyhint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined;
39
+ enterKeyHint?: import('vue').HTMLAttributes["enterkeyhint"];
40
+ hidden?: (boolean | "true" | "false") | "" | "hidden" | "until-found" | undefined;
41
+ id?: string | undefined;
42
+ inert?: (boolean | "true" | "false") | undefined;
43
+ lang?: string | undefined;
44
+ placeholder?: string | undefined;
45
+ spellcheck?: (boolean | "true" | "false") | undefined;
46
+ tabindex?: (string | number) | undefined;
47
+ title?: string | undefined;
48
+ translate?: "yes" | "no" | undefined;
49
+ radiogroup?: string | undefined;
50
+ role?: string | undefined;
51
+ about?: string | undefined;
52
+ datatype?: string | undefined;
53
+ inlist?: any;
54
+ prefix?: string | undefined;
55
+ property?: string | undefined;
56
+ resource?: string | undefined;
57
+ typeof?: string | undefined;
58
+ vocab?: string | undefined;
59
+ autocapitalize?: string | undefined;
60
+ autocorrect?: string | undefined;
61
+ autosave?: string | undefined;
62
+ color?: string | undefined;
63
+ itemprop?: string | undefined;
64
+ itemscope?: (boolean | "true" | "false") | undefined;
65
+ itemtype?: string | undefined;
66
+ itemid?: string | undefined;
67
+ itemref?: string | undefined;
68
+ results?: (string | number) | undefined;
69
+ security?: string | undefined;
70
+ unselectable?: "on" | "off" | undefined;
71
+ inputmode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined;
72
+ is?: string | undefined;
73
+ exportparts?: string;
74
+ part?: string;
75
+ 'aria-activedescendant'?: string | undefined;
76
+ 'aria-atomic'?: (boolean | "true" | "false") | undefined;
77
+ 'aria-autocomplete'?: "none" | "inline" | "list" | "both" | undefined;
78
+ 'aria-busy'?: (boolean | "true" | "false") | undefined;
79
+ 'aria-checked'?: (boolean | "true" | "false") | "mixed" | undefined;
80
+ 'aria-colcount'?: (string | number) | undefined;
81
+ 'aria-colindex'?: (string | number) | undefined;
82
+ 'aria-colspan'?: (string | number) | undefined;
83
+ 'aria-controls'?: string | undefined;
84
+ 'aria-current'?: (boolean | "true" | "false") | "page" | "step" | "location" | "date" | "time" | undefined;
85
+ 'aria-describedby'?: string | undefined;
86
+ 'aria-details'?: string | undefined;
87
+ 'aria-disabled'?: (boolean | "true" | "false") | undefined;
88
+ 'aria-dropeffect'?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined;
89
+ 'aria-errormessage'?: string | undefined;
90
+ 'aria-expanded'?: (boolean | "true" | "false") | undefined;
91
+ 'aria-flowto'?: string | undefined;
92
+ 'aria-grabbed'?: (boolean | "true" | "false") | undefined;
93
+ 'aria-haspopup'?: (boolean | "true" | "false") | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined;
94
+ 'aria-hidden'?: (boolean | "true" | "false") | undefined;
95
+ 'aria-invalid'?: (boolean | "true" | "false") | "grammar" | "spelling" | undefined;
96
+ 'aria-keyshortcuts'?: string | undefined;
97
+ 'aria-label'?: string | undefined;
98
+ 'aria-labelledby'?: string | undefined;
99
+ 'aria-level'?: (string | number) | undefined;
100
+ 'aria-live'?: "off" | "assertive" | "polite" | undefined;
101
+ 'aria-modal'?: (boolean | "true" | "false") | undefined;
102
+ 'aria-multiline'?: (boolean | "true" | "false") | undefined;
103
+ 'aria-multiselectable'?: (boolean | "true" | "false") | undefined;
104
+ 'aria-orientation'?: "horizontal" | "vertical" | undefined;
105
+ 'aria-owns'?: string | undefined;
106
+ 'aria-placeholder'?: string | undefined;
107
+ 'aria-posinset'?: (string | number) | undefined;
108
+ 'aria-pressed'?: (boolean | "true" | "false") | "mixed" | undefined;
109
+ 'aria-readonly'?: (boolean | "true" | "false") | undefined;
110
+ 'aria-relevant'?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined;
111
+ 'aria-required'?: (boolean | "true" | "false") | undefined;
112
+ 'aria-roledescription'?: string | undefined;
113
+ 'aria-rowcount'?: (string | number) | undefined;
114
+ 'aria-rowindex'?: (string | number) | undefined;
115
+ 'aria-rowspan'?: (string | number) | undefined;
116
+ 'aria-selected'?: (boolean | "true" | "false") | undefined;
117
+ 'aria-setsize'?: (string | number) | undefined;
118
+ 'aria-sort'?: "none" | "ascending" | "descending" | "other" | undefined;
119
+ 'aria-valuemax'?: (string | number) | undefined;
120
+ 'aria-valuemin'?: (string | number) | undefined;
121
+ 'aria-valuenow'?: (string | number) | undefined;
122
+ 'aria-valuetext'?: string | undefined;
123
+ onCopy?: ((payload: ClipboardEvent) => void) | undefined;
124
+ onCut?: ((payload: ClipboardEvent) => void) | undefined;
125
+ onPaste?: ((payload: ClipboardEvent) => void) | undefined;
126
+ onCompositionend?: ((payload: CompositionEvent) => void) | undefined;
127
+ onCompositionstart?: ((payload: CompositionEvent) => void) | undefined;
128
+ onCompositionupdate?: ((payload: CompositionEvent) => void) | undefined;
129
+ onDrag?: ((payload: DragEvent) => void) | undefined;
130
+ onDragend?: ((payload: DragEvent) => void) | undefined;
131
+ onDragenter?: ((payload: DragEvent) => void) | undefined;
132
+ onDragexit?: ((payload: DragEvent) => void) | undefined;
133
+ onDragleave?: ((payload: DragEvent) => void) | undefined;
134
+ onDragover?: ((payload: DragEvent) => void) | undefined;
135
+ onDragstart?: ((payload: DragEvent) => void) | undefined;
136
+ onDrop?: ((payload: DragEvent) => void) | undefined;
137
+ onFocus?: ((payload: FocusEvent) => void) | undefined;
138
+ onFocusin?: ((payload: FocusEvent) => void) | undefined;
139
+ onFocusout?: ((payload: FocusEvent) => void) | undefined;
140
+ onBlur?: ((payload: FocusEvent) => void) | undefined;
141
+ onChange?: ((payload: Event) => void) | undefined;
142
+ onBeforeinput?: ((payload: InputEvent) => void) | undefined;
143
+ onFormdata?: ((payload: FormDataEvent) => void) | undefined;
144
+ onInput?: ((payload: InputEvent) => void) | undefined;
145
+ onReset?: ((payload: Event) => void) | undefined;
146
+ onSubmit?: ((payload: SubmitEvent) => void) | undefined;
147
+ onInvalid?: ((payload: Event) => void) | undefined;
148
+ onFullscreenchange?: ((payload: Event) => void) | undefined;
149
+ onFullscreenerror?: ((payload: Event) => void) | undefined;
150
+ onLoad?: ((payload: Event) => void) | undefined;
151
+ onError?: ((payload: Event) => void) | undefined;
152
+ onKeydown?: ((payload: KeyboardEvent) => void) | undefined;
153
+ onKeypress?: ((payload: KeyboardEvent) => void) | undefined;
154
+ onKeyup?: ((payload: KeyboardEvent) => void) | undefined;
155
+ onDblclick?: ((payload: MouseEvent) => void) | undefined;
156
+ onMousedown?: ((payload: MouseEvent) => void) | undefined;
157
+ onMouseenter?: ((payload: MouseEvent) => void) | undefined;
158
+ onMouseleave?: ((payload: MouseEvent) => void) | undefined;
159
+ onMousemove?: ((payload: MouseEvent) => void) | undefined;
160
+ onMouseout?: ((payload: MouseEvent) => void) | undefined;
161
+ onMouseover?: ((payload: MouseEvent) => void) | undefined;
162
+ onMouseup?: ((payload: MouseEvent) => void) | undefined;
163
+ onAbort?: ((payload: UIEvent) => void) | undefined;
164
+ onCanplay?: ((payload: Event) => void) | undefined;
165
+ onCanplaythrough?: ((payload: Event) => void) | undefined;
166
+ onDurationchange?: ((payload: Event) => void) | undefined;
167
+ onEmptied?: ((payload: Event) => void) | undefined;
168
+ onEncrypted?: ((payload: MediaEncryptedEvent) => void) | undefined;
169
+ onEnded?: ((payload: Event) => void) | undefined;
170
+ onLoadeddata?: ((payload: Event) => void) | undefined;
171
+ onLoadedmetadata?: ((payload: Event) => void) | undefined;
172
+ onLoadstart?: ((payload: Event) => void) | undefined;
173
+ onPause?: ((payload: Event) => void) | undefined;
174
+ onPlay?: ((payload: Event) => void) | undefined;
175
+ onPlaying?: ((payload: Event) => void) | undefined;
176
+ onProgress?: ((payload: ProgressEvent<EventTarget>) => void) | undefined;
177
+ onRatechange?: ((payload: Event) => void) | undefined;
178
+ onSeeked?: ((payload: Event) => void) | undefined;
179
+ onSeeking?: ((payload: Event) => void) | undefined;
180
+ onStalled?: ((payload: Event) => void) | undefined;
181
+ onSuspend?: ((payload: Event) => void) | undefined;
182
+ onTimeupdate?: ((payload: Event) => void) | undefined;
183
+ onVolumechange?: ((payload: Event) => void) | undefined;
184
+ onWaiting?: ((payload: Event) => void) | undefined;
185
+ onSelect?: ((payload: Event) => void) | undefined;
186
+ onScroll?: ((payload: Event) => void) | undefined;
187
+ onScrollend?: ((payload: Event) => void) | undefined;
188
+ onTouchcancel?: ((payload: TouchEvent) => void) | undefined;
189
+ onTouchend?: ((payload: TouchEvent) => void) | undefined;
190
+ onTouchmove?: ((payload: TouchEvent) => void) | undefined;
191
+ onTouchstart?: ((payload: TouchEvent) => void) | undefined;
192
+ onAuxclick?: ((payload: PointerEvent) => void) | undefined;
193
+ onClick?: ((payload: PointerEvent) => void) | undefined;
194
+ onContextmenu?: ((payload: PointerEvent) => void) | undefined;
195
+ onGotpointercapture?: ((payload: PointerEvent) => void) | undefined;
196
+ onLostpointercapture?: ((payload: PointerEvent) => void) | undefined;
197
+ onPointerdown?: ((payload: PointerEvent) => void) | undefined;
198
+ onPointermove?: ((payload: PointerEvent) => void) | undefined;
199
+ onPointerup?: ((payload: PointerEvent) => void) | undefined;
200
+ onPointercancel?: ((payload: PointerEvent) => void) | undefined;
201
+ onPointerenter?: ((payload: PointerEvent) => void) | undefined;
202
+ onPointerleave?: ((payload: PointerEvent) => void) | undefined;
203
+ onPointerover?: ((payload: PointerEvent) => void) | undefined;
204
+ onPointerout?: ((payload: PointerEvent) => void) | undefined;
205
+ onBeforetoggle?: ((payload: ToggleEvent) => void) | undefined;
206
+ onToggle?: ((payload: ToggleEvent) => void) | undefined;
207
+ onWheel?: ((payload: WheelEvent) => void) | undefined;
208
+ onAnimationcancel?: ((payload: AnimationEvent) => void) | undefined;
209
+ onAnimationstart?: ((payload: AnimationEvent) => void) | undefined;
210
+ onAnimationend?: ((payload: AnimationEvent) => void) | undefined;
211
+ onAnimationiteration?: ((payload: AnimationEvent) => void) | undefined;
212
+ onSecuritypolicyviolation?: ((payload: SecurityPolicyViolationEvent) => void) | undefined;
213
+ onTransitioncancel?: ((payload: TransitionEvent) => void) | undefined;
214
+ onTransitionend?: ((payload: TransitionEvent) => void) | undefined;
215
+ onTransitionrun?: ((payload: TransitionEvent) => void) | undefined;
216
+ onTransitionstart?: ((payload: TransitionEvent) => void) | undefined;
217
+ align?: "left" | "center" | "right" | "justify" | "char" | undefined;
218
+ colspan?: number | undefined;
219
+ headers?: string | undefined;
220
+ rowspan?: number | undefined;
221
+ scope?: string | undefined;
222
+ abbr?: string | undefined;
223
+ height?: (string | number) | undefined;
224
+ width?: (string | number) | undefined;
225
+ valign?: "top" | "middle" | "bottom" | "baseline" | undefined;
226
+ colSpan?: number;
227
+ rowSpan?: number;
228
+ className?: string;
229
+ };
30
230
  hoverRowSpan: number | undefined;
31
231
  };
32
232
  declare const BodyRow: import('vue').DefineComponent<BodyRowProps<any>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<BodyRowProps<any>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
@@ -24,7 +24,7 @@ function getCellProps(rowInfo, record, column, colIndex, indent, index, rowKeys
24
24
  record,
25
25
  onExpand: onTriggerExpand
26
26
  })]);
27
- const additionalCellProps = column.onCell?.(record, index) || {};
27
+ const additionalCellProps = { ...column.onCell?.(record, index) };
28
28
  let hoverRowSpan;
29
29
  if (expandedRowOffset && expandable.value && colIndex < expandedRowOffset) {
30
30
  const { rowSpan = 1 } = additionalCellProps;
@@ -75,6 +75,7 @@ var BodyRow = /* @__PURE__ */ defineComponent({
75
75
  const flattenColumns = tableContext.flattenColumns;
76
76
  const expandedRowClassName = tableContext.expandedRowClassName;
77
77
  const expandedRowRender = tableContext.expandedRowRender;
78
+ const forceRender = tableContext.forceRender;
78
79
  const expandedClsName = computedExpandedClassName(expandedRowClassName, record, index, indent);
79
80
  const rowPropsStyle = rowProps.value?.style;
80
81
  const mergedRowStyle = {
@@ -116,7 +117,7 @@ var BodyRow = /* @__PURE__ */ defineComponent({
116
117
  }), null);
117
118
  })) ? _slot : { default: () => [_slot] });
118
119
  let expandRowNode;
119
- if (rowSupportExpand.value && (expandedRef.value || expanded.value)) {
120
+ if (rowSupportExpand.value && (forceRender || expandedRef.value || expanded.value)) {
120
121
  const expandContent = expandedRowRender(record, index, indent + 1, expanded.value);
121
122
  const computedExpandedRowClassName = computedExpandedClassName(expandedRowClassName, record, index, indent);
122
123
  expandRowNode = createVNode(ExpandedRow, {
@@ -17,6 +17,7 @@ export interface CellProps<RecordType extends DefaultRecordType> {
17
17
  children?: any;
18
18
  colSpan?: number;
19
19
  rowSpan?: number;
20
+ /** @private Original rowSpan before patching it for expanded rows */
20
21
  hoverRowSpan?: number;
21
22
  scope?: ScopeType;
22
23
  ellipsis?: CellEllipsisType;
package/dist/Table.js CHANGED
@@ -86,7 +86,7 @@ var ImmutableTable = /* @__PURE__ */ defineComponent((props, { attrs, slots, exp
86
86
  });
87
87
  const customizeScrollBody = computed(() => getComponent(["body"]));
88
88
  const [startRow, endRow, onHover] = useHover();
89
- const [expandableConfig, expandableType, mergedExpandedKeys, mergedExpandIcon, mergedChildrenColumnName, onTriggerExpand] = useExpand(props, mergedData, getRowKey);
89
+ const [expandableConfig, expandableType, mergedExpandedKeys, mergedExpandIcon, mergedChildrenColumnName, onTriggerExpand, expandAllInfo] = useExpand(props, mergedData, getRowKey);
90
90
  const componentWidth = ref(0);
91
91
  const slotChildren = shallowRef(null);
92
92
  const [columns, flattenColumns, flattenScrollX] = useColumns({
@@ -99,6 +99,8 @@ var ImmutableTable = /* @__PURE__ */ defineComponent((props, { attrs, slots, exp
99
99
  getRowKey,
100
100
  onTriggerExpand,
101
101
  expandIcon: mergedExpandIcon,
102
+ ExpandIcon: computed(() => props.components?.ExpandIcon),
103
+ expandAllInfo,
102
104
  rowExpandable: computed(() => expandableConfig.value.rowExpandable),
103
105
  expandIconColumnIndex: computed(() => expandableConfig.value.expandIconColumnIndex),
104
106
  expandedRowOffset: expandableConfig.value.expandedRowOffset,
@@ -337,6 +339,7 @@ var ImmutableTable = /* @__PURE__ */ defineComponent((props, { attrs, slots, exp
337
339
  tableContext.expandableType = expandableType.value;
338
340
  tableContext.expandRowByClick = expandableConfig.value.expandRowByClick;
339
341
  tableContext.expandedRowRender = expandableConfig.value.expandedRowRender;
342
+ tableContext.forceRender = expandableConfig.value.forceRender ?? false;
340
343
  tableContext.expandedRowOffset = expandableConfig.value.expandedRowOffset;
341
344
  tableContext.onTriggerExpand = onTriggerExpand;
342
345
  tableContext.expandIconColumnIndex = expandableConfig.value.expandIconColumnIndex;
@@ -33,14 +33,18 @@ var BodyLine = /* @__PURE__ */ defineComponent({
33
33
  const { rowSupportExpand, expanded, rowProps } = rowInfo;
34
34
  const expandedRowRender = tableContext.expandedRowRender;
35
35
  const expandedRowClassName = tableContext.expandedRowClassName;
36
+ const forceRender = tableContext.forceRender;
36
37
  let expandRowNode;
37
- if (rowSupportExpand.value && expanded.value) {
38
+ if (!extra && rowSupportExpand.value && (forceRender || expanded.value)) {
38
39
  const expandContent = expandedRowRender(record, index, indent + 1, expanded.value);
39
40
  const expandedClsName = computedExpandedClassName(expandedRowClassName, record, index, indent);
40
41
  let additionalProps = {};
41
42
  if (tableContext.fixColumn) additionalProps = { style: { ["--virtual-width"]: `${tableContext.componentWidth}px` } };
42
43
  const rowCellCls = `${tableContext.prefixCls}-expanded-row-cell`;
43
- expandRowNode = createVNode(RowComponent, { "class": clsx(`${tableContext.prefixCls}-expanded-row`, `${tableContext.prefixCls}-expanded-row-level-${indent + 1}`, expandedClsName) }, { default: () => [createVNode(Cell, {
44
+ expandRowNode = createVNode(RowComponent, {
45
+ "class": clsx(`${tableContext.prefixCls}-expanded-row`, `${tableContext.prefixCls}-expanded-row-level-${indent + 1}`, expandedClsName),
46
+ "style": { display: expanded.value ? void 0 : "none" }
47
+ }, { default: () => [createVNode(Cell, {
44
48
  "component": CellComponent,
45
49
  "prefixCls": tableContext.prefixCls,
46
50
  "className": clsx(rowCellCls, { [`${rowCellCls}-fixed`]: tableContext.fixColumn }),
@@ -28,6 +28,7 @@ export interface TableContextProps<RecordType = any> {
28
28
  expandableType: ExpandableType;
29
29
  expandRowByClick: boolean;
30
30
  expandedRowRender: ExpandedRowRender<RecordType>;
31
+ forceRender: boolean;
31
32
  expandIcon: RenderExpandIcon<RecordType>;
32
33
  onTriggerExpand: TriggerEventHandler<RecordType>;
33
34
  expandIconColumnIndex: number;
@@ -1,5 +1,5 @@
1
1
  import { Ref } from 'vue';
2
- import { ColumnsType, ColumnType, Direction, FixedType, GetRowKey, Key, RenderExpandIcon, TriggerEventHandler } from '../../interface';
2
+ import { ColumnsType, ColumnType, Direction, ExpandColumnTitle, ExpandIconComponent, ExpandIconProps, FixedType, GetRowKey, Key, RenderExpandIcon, TriggerEventHandler } from '../../interface';
3
3
  export declare function convertChildrenToColumns<RecordType>(children: any): ColumnsType<RecordType>;
4
4
  export default function useColumns<RecordType>(options: {
5
5
  prefixCls?: Ref<string> | string;
@@ -7,10 +7,12 @@ export default function useColumns<RecordType>(options: {
7
7
  children?: any;
8
8
  expandable: Ref<boolean> | boolean;
9
9
  expandedKeys: Ref<Set<Key>> | Set<Key>;
10
- columnTitle?: Ref<any> | any;
10
+ columnTitle?: Ref<ExpandColumnTitle | undefined> | ExpandColumnTitle;
11
11
  getRowKey: Ref<GetRowKey<RecordType>> | GetRowKey<RecordType>;
12
12
  onTriggerExpand: TriggerEventHandler<RecordType>;
13
13
  expandIcon?: Ref<RenderExpandIcon<RecordType> | undefined> | RenderExpandIcon<RecordType>;
14
+ ExpandIcon?: Ref<ExpandIconComponent<RecordType> | undefined> | ExpandIconComponent<RecordType>;
15
+ expandAllInfo?: Ref<Pick<ExpandIconProps<RecordType>, 'expanded' | 'expandable' | 'onClick'> | undefined>;
14
16
  rowExpandable?: Ref<((record: RecordType) => boolean) | undefined> | ((record: RecordType) => boolean) | undefined;
15
17
  expandIconColumnIndex?: Ref<number | undefined> | number;
16
18
  expandedRowOffset?: number;
@@ -1,10 +1,19 @@
1
1
  import { INTERNAL_COL_DEFINE } from "../../utils/legacyUtil.js";
2
+ import { DefaultExpandIcon } from "../../utils/expandUtil.js";
2
3
  import { EXPAND_COLUMN } from "../../constant.js";
3
4
  import useWidthColumns from "./useWidthColumns.js";
4
- import { computed, createVNode, isVNode, unref } from "vue";
5
+ import { computed, createVNode, h, isVNode, toRaw, unref } from "vue";
5
6
  import { warning } from "@v-c/util";
6
7
  import { flattenChildren } from "@v-c/util/dist/props-util";
7
8
  //#region src/hooks/useColumns/index.tsx
9
+ /**
10
+ * `EXPAND_COLUMN` is a sentinel matched by reference. When `columns` comes from a deep
11
+ * reactive source (component props, `reactive()` or `ref()`), every entry is handed out
12
+ * as a proxy, so the raw value must be unwrapped before comparing identity.
13
+ */
14
+ function isExpandColumn(column) {
15
+ return toRaw(column) === EXPAND_COLUMN;
16
+ }
8
17
  function convertChildrenToColumns(children) {
9
18
  return flattenChildren(children).filter((node) => isVNode(node)).map((node) => {
10
19
  const { key, props, children: nodeChildren } = node;
@@ -52,27 +61,36 @@ function useColumns(options, transformColumns) {
52
61
  let cloneColumns = baseColumns.value.slice();
53
62
  const expandIconColumnIndex = unref(options.expandIconColumnIndex);
54
63
  if (process.env.NODE_ENV !== "production" && expandIconColumnIndex !== void 0) warning(false, "`expandIconColumnIndex` is deprecated. Please use `Table.EXPAND_COLUMN` in `columns` instead.");
55
- if (!cloneColumns.includes(EXPAND_COLUMN)) {
64
+ if (!cloneColumns.some(isExpandColumn)) {
56
65
  const expandColIndex = expandIconColumnIndex || 0;
57
66
  const fixed = unref(options.fixed);
58
67
  const insertIndex = expandColIndex === 0 && (fixed === "right" || fixed === "end") ? baseColumns.value.length : expandColIndex;
59
68
  if (insertIndex >= 0) cloneColumns.splice(insertIndex, 0, EXPAND_COLUMN);
60
69
  }
61
- if (process.env.NODE_ENV !== "production" && cloneColumns.filter((c) => c === EXPAND_COLUMN).length > 1) warning(false, "There exist more than one `EXPAND_COLUMN` in `columns`.");
62
- const expandColumnIndex = cloneColumns.indexOf(EXPAND_COLUMN);
63
- cloneColumns = cloneColumns.filter((column, index) => column !== EXPAND_COLUMN || index === expandColumnIndex);
70
+ if (process.env.NODE_ENV !== "production" && cloneColumns.filter((c) => isExpandColumn(c)).length > 1) warning(false, "There exist more than one `EXPAND_COLUMN` in `columns`.");
71
+ const expandColumnIndex = cloneColumns.findIndex(isExpandColumn);
72
+ cloneColumns = cloneColumns.filter((column, index) => !isExpandColumn(column) || index === expandColumnIndex);
64
73
  const prevColumn = baseColumns.value[expandColumnIndex];
65
74
  let fixedColumn;
66
75
  const fixed = unref(options.fixed);
67
76
  if (fixed) fixedColumn = fixed;
68
77
  else fixedColumn = prevColumn?.fixed;
69
78
  const prefixCls = unref(options.prefixCls) || "";
79
+ const MergedExpandIcon = unref(options.ExpandIcon) || DefaultExpandIcon;
80
+ const expandAllInfo = unref(options.expandAllInfo);
81
+ const expandAllNode = expandAllInfo ? h(MergedExpandIcon, {
82
+ type: "all",
83
+ prefixCls,
84
+ ...expandAllInfo
85
+ }) : void 0;
86
+ const columnTitle = unref(options.columnTitle);
87
+ const mergedColumnTitle = typeof columnTitle === "function" ? columnTitle({ expandIcon: expandAllNode }) : columnTitle ?? expandAllNode;
70
88
  const expandColumn = {
71
89
  [INTERNAL_COL_DEFINE]: {
72
90
  className: `${prefixCls}-expand-icon-col`,
73
91
  columnType: "EXPAND_COLUMN"
74
92
  },
75
- title: unref(options.columnTitle),
93
+ title: mergedColumnTitle,
76
94
  fixed: fixedColumn,
77
95
  className: `${prefixCls}-row-expand-icon-cell`,
78
96
  width: unref(options.columnWidth),
@@ -94,7 +112,7 @@ function useColumns(options, transformColumns) {
94
112
  }
95
113
  };
96
114
  return cloneColumns.map((col, index) => {
97
- const column = col === EXPAND_COLUMN ? expandColumn : col;
115
+ const column = isExpandColumn(col) ? expandColumn : col;
98
116
  if ((options.expandedRowOffset || 0) && index < (options.expandedRowOffset || 0)) return {
99
117
  ...column,
100
118
  fixed: column.fixed || "start"
@@ -102,8 +120,8 @@ function useColumns(options, transformColumns) {
102
120
  return column;
103
121
  });
104
122
  }
105
- if (process.env.NODE_ENV !== "production" && baseColumns.value.includes(EXPAND_COLUMN)) warning(false, "`expandable` is not config but there exist `EXPAND_COLUMN` in `columns`.");
106
- return baseColumns.value.filter((col) => col !== EXPAND_COLUMN);
123
+ if (process.env.NODE_ENV !== "production" && baseColumns.value.some(isExpandColumn)) warning(false, "`expandable` is not config but there exist `EXPAND_COLUMN` in `columns`.");
124
+ return baseColumns.value.filter((col) => !isExpandColumn(col));
107
125
  });
108
126
  const mergedColumns = computed(() => {
109
127
  let finalColumns = withExpandColumns.value;
@@ -1,11 +1,14 @@
1
1
  import { Ref } from 'vue';
2
- import { ExpandableConfig, ExpandableType, GetRowKey, Key, RenderExpandIcon, TriggerEventHandler } from '../interface';
2
+ import { ExpandableConfig, ExpandableType, ExpandIconProps, GetRowKey, Key, RenderExpandIcon, TriggerEventHandler } from '../interface';
3
3
  import { TableProps } from '../Table';
4
+ type ExpandAllInfo<RecordType> = Pick<ExpandIconProps<RecordType>, 'expanded' | 'expandable' | 'onClick'>;
4
5
  export default function useExpand<RecordType>(props: TableProps<RecordType>, mergedData: Ref<readonly RecordType[]> | readonly RecordType[], getRowKey: Ref<GetRowKey<RecordType>> | GetRowKey<RecordType>): [
5
6
  expandableConfig: Ref<ExpandableConfig<RecordType>>,
6
7
  expandableType: Ref<ExpandableType>,
7
8
  expandedKeys: Ref<Set<Key>>,
8
9
  expandIcon: Ref<RenderExpandIcon<RecordType>>,
9
10
  childrenColumnName: Ref<string>,
10
- onTriggerExpand: TriggerEventHandler<RecordType>
11
+ onTriggerExpand: TriggerEventHandler<RecordType>,
12
+ expandAllInfo: Ref<ExpandAllInfo<RecordType> | undefined>
11
13
  ];
14
+ export {};
@@ -1,12 +1,16 @@
1
1
  import { getExpandableProps } from "../utils/legacyUtil.js";
2
- import { findAllChildrenKeys, renderExpandIcon } from "../utils/expandUtil.js";
2
+ import { findAllChildrenKeys, renderExpandIcon, renderRowExpandIcon } from "../utils/expandUtil.js";
3
3
  import "../constant.js";
4
4
  import { computed, ref, unref } from "vue";
5
5
  import { warning } from "@v-c/util";
6
6
  //#region src/hooks/useExpand.ts
7
7
  function useExpand(props, mergedData, getRowKey) {
8
8
  const expandableConfig = computed(() => getExpandableProps(props));
9
- const mergedExpandIcon = computed(() => expandableConfig.value.expandIcon || renderExpandIcon);
9
+ const mergedExpandIcon = computed(() => {
10
+ const customizeExpandIcon = props.components?.ExpandIcon;
11
+ if (customizeExpandIcon) return (iconProps) => renderRowExpandIcon(customizeExpandIcon, iconProps);
12
+ return expandableConfig.value.expandIcon || renderExpandIcon;
13
+ });
10
14
  const mergedChildrenColumnName = computed(() => expandableConfig.value.childrenColumnName || "children");
11
15
  const expandableType = computed(() => {
12
16
  if (expandableConfig.value.expandedRowRender) return "row";
@@ -37,6 +41,38 @@ function useExpand(props, mergedData, getRowKey) {
37
41
  props["onUpdate:expandedRowKeys"]?.(Array.from(newExpandedKeys));
38
42
  event?.stopPropagation?.();
39
43
  };
44
+ const expandableRows = computed(() => {
45
+ if (!expandableConfig.value.showExpandAll || expandableType.value !== "row") return [];
46
+ const rowExpandable = expandableConfig.value.rowExpandable;
47
+ return (unref(mergedData) || []).reduce((rows, record, index) => {
48
+ if (!rowExpandable || rowExpandable(record)) rows.push({
49
+ key: unref(getRowKey)(record, index),
50
+ record
51
+ });
52
+ return rows;
53
+ }, []);
54
+ });
55
+ const allExpanded = computed(() => expandableRows.value.length > 0 && expandableRows.value.every(({ key }) => mergedExpandedKeys.value.has(key)));
56
+ const onTriggerExpandAll = (event) => {
57
+ event.stopPropagation();
58
+ if (!expandableRows.value.length) return;
59
+ const nextExpanded = !allExpanded.value;
60
+ const nextExpandedKeys = new Set(mergedExpandedKeys.value);
61
+ expandableRows.value.forEach(({ key }) => {
62
+ if (nextExpanded) nextExpandedKeys.add(key);
63
+ else nextExpandedKeys.delete(key);
64
+ });
65
+ const keys = [...nextExpandedKeys];
66
+ innerExpandedKeys.value = keys;
67
+ expandableConfig.value.onExpandAll?.(nextExpanded);
68
+ expandableConfig.value.onExpandedRowsChange?.(keys);
69
+ props["onUpdate:expandedRowKeys"]?.(keys);
70
+ };
71
+ const expandAllInfo = computed(() => expandableConfig.value.showExpandAll && expandableType.value === "row" ? {
72
+ expanded: allExpanded.value,
73
+ expandable: expandableRows.value.length > 0,
74
+ onClick: onTriggerExpandAll
75
+ } : void 0);
40
76
  if (process.env.NODE_ENV !== "production" && expandableConfig.value.expandedRowRender && (unref(mergedData) || []).some((record) => {
41
77
  return Array.isArray(record?.[mergedChildrenColumnName.value]);
42
78
  })) warning(false, "`expandedRowRender` should not use with nested Table");
@@ -46,7 +82,8 @@ function useExpand(props, mergedData, getRowKey) {
46
82
  mergedExpandedKeys,
47
83
  mergedExpandIcon,
48
84
  mergedChildrenColumnName,
49
- onTriggerExpand
85
+ onTriggerExpand,
86
+ expandAllInfo
50
87
  ];
51
88
  }
52
89
  //#endregion
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ColumnsType, ColumnType, DataIndex, ExpandableConfig, FixedType, GetComponentProps, GetRowKey, Reference, RenderedCell } from './interface';
1
+ import { ColumnsType, ColumnType, DataIndex, ExpandableConfig, ExpandIconComponent, ExpandIconProps, FixedType, GetComponentProps, GetRowKey, Reference, RenderedCell } from './interface';
2
2
  import { TableProps, default as Table } from './Table';
3
3
  import { VirtualTableProps, default as VirtualTable } from './VirtualTable';
4
4
  import { EXPAND_COLUMN, INTERNAL_HOOKS } from './constant';
@@ -6,6 +6,6 @@ import { FooterComponents as Summary, SummaryCell, SummaryRow } from './Footer';
6
6
  import { default as Column } from './sugar/Column';
7
7
  import { default as ColumnGroup } from './sugar/ColumnGroup';
8
8
  import { INTERNAL_COL_DEFINE } from './utils/legacyUtil';
9
- export type { DataIndex, ExpandableConfig, FixedType, GetComponentProps, GetRowKey, RenderedCell, };
9
+ export type { DataIndex, ExpandableConfig, ExpandIconComponent, ExpandIconProps, FixedType, GetComponentProps, GetRowKey, RenderedCell, };
10
10
  export { Column, ColumnGroup, type ColumnsType, type ColumnType, EXPAND_COLUMN, INTERNAL_COL_DEFINE, INTERNAL_HOOKS, type Reference, Summary, SummaryCell, SummaryRow, type TableProps, VirtualTable, type VirtualTableProps, };
11
11
  export default Table;
@@ -1,5 +1,5 @@
1
1
  import { VueNode } from '@v-c/util';
2
- import { CSSProperties, HTMLAttributes, Ref, TdHTMLAttributes } from 'vue';
2
+ import { CSSProperties, HTMLAttributes, Ref, TdHTMLAttributes, Component as VueComponent } from 'vue';
3
3
  import { DeepNamePath } from './namePathType';
4
4
  export type Key = string | number;
5
5
  /**
@@ -118,6 +118,7 @@ export type CustomizeScrollBody<RecordType = Record<string, any>> = (data: reado
118
118
  onScroll: OnCustomizeScroll;
119
119
  }) => any;
120
120
  export interface TableComponents<RecordType> {
121
+ ExpandIcon?: ExpandIconComponent<RecordType>;
121
122
  table?: CustomizeComponent;
122
123
  header?: {
123
124
  table?: CustomizeComponent;
@@ -169,20 +170,41 @@ export interface RenderExpandIconProps<RecordType> {
169
170
  onExpand: TriggerEventHandler<RecordType>;
170
171
  }
171
172
  export type RenderExpandIcon<RecordType> = (props: RenderExpandIconProps<RecordType>) => any;
173
+ export type ExpandIconProps<RecordType> = {
174
+ prefixCls: string;
175
+ expanded: boolean;
176
+ expandable: boolean;
177
+ onClick: (event: MouseEvent) => void;
178
+ } & ({
179
+ type: 'row';
180
+ record: RecordType;
181
+ } | {
182
+ type: 'all';
183
+ record?: never;
184
+ });
185
+ export type ExpandIconComponent<RecordType> = VueComponent<ExpandIconProps<RecordType>>;
186
+ export interface ExpandColumnTitleProps {
187
+ expandIcon: VueNode;
188
+ }
189
+ export type ExpandColumnTitle = VueNode | ((props: ExpandColumnTitleProps) => VueNode);
172
190
  export interface ExpandableConfig<RecordType> {
173
191
  expandedRowKeys?: readonly Key[];
174
192
  defaultExpandedRowKeys?: readonly Key[];
175
193
  expandedRowRender?: ExpandedRowRender<RecordType>;
176
- columnTitle?: VueNode;
194
+ forceRender?: boolean;
195
+ columnTitle?: ExpandColumnTitle;
177
196
  expandRowByClick?: boolean;
197
+ /** @deprecated Please use `components.ExpandIcon` instead. This only customizes row icons. */
178
198
  expandIcon?: RenderExpandIcon<RecordType>;
179
199
  onExpand?: (expanded: boolean, record: RecordType) => void;
200
+ onExpandAll?: (expanded: boolean) => void;
180
201
  onExpandedRowsChange?: (expandedKeys: readonly Key[]) => void;
181
202
  defaultExpandAllRows?: boolean;
182
203
  indentSize?: number;
183
204
  /** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */
184
205
  expandIconColumnIndex?: number;
185
206
  showExpandColumn?: boolean;
207
+ showExpandAll?: boolean;
186
208
  expandedRowClassName?: string | RowClassName<RecordType>;
187
209
  childrenColumnName?: string;
188
210
  rowExpandable?: (record: RecordType) => boolean;
@@ -1,4 +1,8 @@
1
- import { ExpandableConfig, GetRowKey, Key, RenderExpandIconProps } from '../interface';
1
+ import { ExpandableConfig, ExpandIconComponent, ExpandIconProps, GetRowKey, Key, RenderExpandIconProps } from '../interface';
2
+ export declare function DefaultExpandIcon<RecordType>({ prefixCls, type, onClick, expanded, expandable, }: ExpandIconProps<RecordType>): import("vue/jsx-runtime").JSX.Element;
2
3
  export declare function renderExpandIcon<RecordType>({ prefixCls, record, onExpand, expanded, expandable, }: RenderExpandIconProps<RecordType>): import("vue/jsx-runtime").JSX.Element;
4
+ export declare function renderRowExpandIcon<RecordType>(ExpandIcon: ExpandIconComponent<RecordType>, props: RenderExpandIconProps<RecordType>): import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
5
+ [key: string]: any;
6
+ }>;
3
7
  export declare function findAllChildrenKeys<RecordType>(data: readonly RecordType[], getRowKey: GetRowKey<RecordType>, childrenColumnName: string): Key[];
4
8
  export declare function computedExpandedClassName<RecordType>(cls: ExpandableConfig<RecordType>['expandedRowClassName'], record: RecordType, index: number, indent: number): string;
@@ -1,21 +1,54 @@
1
- import { createVNode } from "vue";
1
+ import { createVNode, h } from "vue";
2
2
  import { clsx } from "@v-c/util";
3
3
  //#region src/utils/expandUtil.tsx
4
- function renderExpandIcon({ prefixCls, record, onExpand, expanded, expandable }) {
4
+ function DefaultExpandIcon({ prefixCls, type, onClick, expanded, expandable }) {
5
5
  const expandClassName = `${prefixCls}-row-expand-icon`;
6
6
  if (!expandable) return createVNode("span", { "class": clsx(expandClassName, `${prefixCls}-row-spaced`) }, null);
7
+ const className = clsx(expandClassName, {
8
+ [`${prefixCls}-row-expanded`]: expanded,
9
+ [`${prefixCls}-row-collapsed`]: !expanded
10
+ });
11
+ if (type === "all") return createVNode("button", {
12
+ "type": "button",
13
+ "aria-expanded": expanded,
14
+ "aria-label": expanded ? "Collapse all rows" : "Expand all rows",
15
+ "class": className,
16
+ "onClick": onClick
17
+ }, null);
18
+ return createVNode("span", {
19
+ "class": className,
20
+ "onClick": onClick
21
+ }, null);
22
+ }
23
+ function renderExpandIcon({ prefixCls, record, onExpand, expanded, expandable }) {
7
24
  const onClick = (event) => {
8
25
  onExpand(record, event);
9
26
  event.stopPropagation();
10
27
  };
11
- return createVNode("span", {
12
- "class": clsx(expandClassName, {
13
- [`${prefixCls}-row-expanded`]: expanded,
14
- [`${prefixCls}-row-collapsed`]: !expanded
15
- }),
28
+ return createVNode(DefaultExpandIcon, {
29
+ "type": "row",
30
+ "prefixCls": prefixCls,
31
+ "record": record,
32
+ "expanded": expanded,
33
+ "expandable": !!expandable,
16
34
  "onClick": onClick
17
35
  }, null);
18
36
  }
37
+ function renderRowExpandIcon(ExpandIcon, props) {
38
+ const { prefixCls, record, onExpand, expanded, expandable } = props;
39
+ const onClick = (event) => {
40
+ onExpand(record, event);
41
+ event.stopPropagation();
42
+ };
43
+ return h(ExpandIcon, {
44
+ type: "row",
45
+ prefixCls,
46
+ record,
47
+ expanded,
48
+ expandable: !!expandable,
49
+ onClick
50
+ });
51
+ }
19
52
  function findAllChildrenKeys(data, getRowKey, childrenColumnName) {
20
53
  const keys = [];
21
54
  function dig(list) {
@@ -33,4 +66,4 @@ function computedExpandedClassName(cls, record, index, indent) {
33
66
  return "";
34
67
  }
35
68
  //#endregion
36
- export { computedExpandedClassName, findAllChildrenKeys, renderExpandIcon };
69
+ export { DefaultExpandIcon, computedExpandedClassName, findAllChildrenKeys, renderExpandIcon, renderRowExpandIcon };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@v-c/table",
3
3
  "type": "module",
4
- "version": "1.1.9",
4
+ "version": "1.2.1",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/antdv-next/vue-components/tree/next/packages/table",
7
7
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "dependencies": {
29
29
  "@v-c/resize-observer": "^1.1.3",
30
30
  "@v-c/util": "^1.1.0",
31
- "@v-c/virtual-list": "^1.1.0"
31
+ "@v-c/virtual-list": "^1.1.1"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"