@rainbow-oh/yee-c 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Table/demo/components-override.d.ts +3 -0
- package/dist/cjs/Table/demo/components-override.js +54 -0
- package/dist/cjs/Table/demo/grouping.d.ts +3 -0
- package/dist/cjs/Table/demo/grouping.js +129 -0
- package/dist/cjs/Table/hooks/useColumns.d.ts +2 -2
- package/dist/cjs/Table/hooks/useColumns.js +15 -37
- package/dist/cjs/Table/index.d.ts +1 -1
- package/dist/cjs/Table/interface.d.ts +59 -8
- package/dist/cjs/Table/style/index.less +19 -1
- package/dist/cjs/Table/table.js +5 -7
- package/dist/cjs/Table/tbody/cell.d.ts +0 -1
- package/dist/cjs/Table/tbody/cell.js +0 -4
- package/dist/cjs/Table/tbody/index.js +19 -2
- package/dist/cjs/Table/tbody/row.js +15 -11
- package/dist/cjs/Table/theader/cell.js +7 -1
- package/dist/cjs/Table/theader/index.d.ts +5 -5
- package/dist/cjs/Table/theader/index.js +41 -27
- package/dist/cjs/Table/util/header.d.ts +23 -0
- package/dist/cjs/Table/util/header.js +109 -0
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Table/demo/components-override.d.ts +3 -0
- package/dist/esm/Table/demo/components-override.js +86 -0
- package/dist/esm/Table/demo/grouping.d.ts +3 -0
- package/dist/esm/Table/demo/grouping.js +102 -0
- package/dist/esm/Table/hooks/useColumns.d.ts +2 -2
- package/dist/esm/Table/hooks/useColumns.js +24 -50
- package/dist/esm/Table/index.d.ts +1 -1
- package/dist/esm/Table/interface.d.ts +59 -8
- package/dist/esm/Table/style/index.less +19 -1
- package/dist/esm/Table/table.js +5 -7
- package/dist/esm/Table/tbody/cell.d.ts +0 -1
- package/dist/esm/Table/tbody/cell.js +0 -5
- package/dist/esm/Table/tbody/index.js +21 -2
- package/dist/esm/Table/tbody/row.js +19 -15
- package/dist/esm/Table/theader/cell.js +6 -2
- package/dist/esm/Table/theader/index.d.ts +5 -5
- package/dist/esm/Table/theader/index.js +48 -35
- package/dist/esm/Table/util/header.d.ts +23 -0
- package/dist/esm/Table/util/header.js +107 -0
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +1 -1
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Table/demo/components-override.tsx +49 -0
- package/src/Table/demo/grouping.tsx +104 -0
- package/src/Table/hooks/useColumns.ts +29 -46
- package/src/Table/index.en-US.md +31 -3
- package/src/Table/index.ts +4 -0
- package/src/Table/index.zh-CN.md +30 -2
- package/src/Table/interface.ts +66 -8
- package/src/Table/style/index.less +19 -1
- package/src/Table/table.tsx +5 -7
- package/src/Table/tbody/cell.tsx +0 -6
- package/src/Table/tbody/index.tsx +21 -2
- package/src/Table/tbody/row.tsx +25 -14
- package/src/Table/theader/cell.tsx +4 -0
- package/src/Table/theader/index.tsx +61 -42
- package/src/Table/util/header.ts +111 -0
- package/src/version.ts +1 -1
|
@@ -8,7 +8,7 @@ import TableRow from './row';
|
|
|
8
8
|
const TableBody: React.FC<TableBodyProps> = (props) => {
|
|
9
9
|
const { columns, pageData, lazyLoad, ...rest } = props;
|
|
10
10
|
|
|
11
|
-
const { prefixCls } = React.useContext(TableCtx);
|
|
11
|
+
const { prefixCls, components, rowKey } = React.useContext(TableCtx);
|
|
12
12
|
const { locale } = useLocale();
|
|
13
13
|
const { table: tableLocale } = locale;
|
|
14
14
|
|
|
@@ -23,11 +23,30 @@ const TableBody: React.FC<TableBodyProps> = (props) => {
|
|
|
23
23
|
const dataLength = pageData.length;
|
|
24
24
|
if (dataLength === 0) return empty;
|
|
25
25
|
|
|
26
|
+
const BodyWrapper = components?.body?.tbody ?? 'tbody';
|
|
27
|
+
const RowRenderer = components?.body?.row;
|
|
28
|
+
|
|
29
|
+
const resolveRowKey = (record: Record<string, any>) =>
|
|
30
|
+
typeof rowKey === 'function' ? rowKey(record) : record[rowKey];
|
|
31
|
+
|
|
26
32
|
const getRenderRows = () => {
|
|
27
33
|
if (lazyLoad) {
|
|
28
34
|
return <LazyRow {...rest} pageData={pageData} columns={columns} />;
|
|
29
35
|
}
|
|
30
36
|
return pageData.map((record: Record<string, any>, index: number) => {
|
|
37
|
+
// 整行接管:由外部组件渲染 <tr> + 单元格(可放拖拽手柄等)
|
|
38
|
+
if (RowRenderer) {
|
|
39
|
+
const rk = resolveRowKey(record);
|
|
40
|
+
return (
|
|
41
|
+
<RowRenderer
|
|
42
|
+
key={rk ?? index}
|
|
43
|
+
record={record}
|
|
44
|
+
index={index}
|
|
45
|
+
columns={columns}
|
|
46
|
+
rowKey={rk}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
31
50
|
return (
|
|
32
51
|
<TableRow
|
|
33
52
|
{...rest}
|
|
@@ -41,7 +60,7 @@ const TableBody: React.FC<TableBodyProps> = (props) => {
|
|
|
41
60
|
};
|
|
42
61
|
|
|
43
62
|
const tbody = (
|
|
44
|
-
<
|
|
63
|
+
<BodyWrapper className={`${prefixCls}-tbody`}>{getRenderRows()}</BodyWrapper>
|
|
45
64
|
);
|
|
46
65
|
|
|
47
66
|
return tbody;
|
package/src/Table/tbody/row.tsx
CHANGED
|
@@ -56,27 +56,38 @@ const TableRow: React.FC<TableRowProps> = (props) => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const getSelection = (column: WrapedColumnProps) => {
|
|
59
|
-
const { type,
|
|
60
|
-
const
|
|
61
|
-
const props = onCell
|
|
62
|
-
const checked = selectedRowKeys?.includes(
|
|
63
|
-
|
|
59
|
+
const { type, disabled: colDisabled, onCell } = column;
|
|
60
|
+
const rowKeyValue = record[rowKey];
|
|
61
|
+
const props = (onCell?.(record, index) || {}) as Record<string, unknown>;
|
|
62
|
+
const checked = selectedRowKeys?.includes(rowKeyValue);
|
|
63
|
+
|
|
64
|
+
// rowSelection.disabled may be a boolean, a per-row array, or a function
|
|
65
|
+
const disabled =
|
|
66
|
+
typeof colDisabled === 'function'
|
|
67
|
+
? colDisabled(record, index)
|
|
68
|
+
: Array.isArray(colDisabled)
|
|
69
|
+
? colDisabled[index]
|
|
70
|
+
: !!colDisabled;
|
|
71
|
+
|
|
72
|
+
// Only forward input-relevant props. Spreading the whole column would leak
|
|
73
|
+
// rowSelection fields (selectedRowKeys/selectAll/...) and the synthetic
|
|
74
|
+
// `key` onto the DOM <input>.
|
|
64
75
|
const commonProps = {
|
|
65
|
-
// ...rest,
|
|
66
|
-
...restCol,
|
|
67
|
-
...props,
|
|
68
76
|
checked,
|
|
69
|
-
value:
|
|
77
|
+
value: rowKeyValue,
|
|
70
78
|
onChange: onSelectionChange,
|
|
79
|
+
disabled,
|
|
80
|
+
...props,
|
|
71
81
|
};
|
|
72
82
|
|
|
73
83
|
if (type === 'checkbox') {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
return (
|
|
85
|
+
<Checkbox
|
|
86
|
+
{...(commonProps as React.ComponentProps<typeof Checkbox>)}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
79
89
|
}
|
|
90
|
+
return <Radio {...(commonProps as React.ComponentProps<typeof Radio>)} />;
|
|
80
91
|
};
|
|
81
92
|
|
|
82
93
|
let colSpanStart = Infinity;
|
|
@@ -26,6 +26,8 @@ const HeadCell: React.FC<HeadCellProps> = (props) => {
|
|
|
26
26
|
internalFilters,
|
|
27
27
|
style,
|
|
28
28
|
width,
|
|
29
|
+
colSpan,
|
|
30
|
+
rowSpan,
|
|
29
31
|
onHeaderCell,
|
|
30
32
|
onSort,
|
|
31
33
|
onInternalFilter,
|
|
@@ -141,6 +143,8 @@ const HeadCell: React.FC<HeadCellProps> = (props) => {
|
|
|
141
143
|
className: cls,
|
|
142
144
|
scope: 'col',
|
|
143
145
|
style: styles,
|
|
146
|
+
colSpan,
|
|
147
|
+
rowSpan,
|
|
144
148
|
};
|
|
145
149
|
};
|
|
146
150
|
|
|
@@ -1,65 +1,84 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import React, { memo, useContext } from 'react';
|
|
3
3
|
import Checkbox from '../../Checkbox';
|
|
4
|
-
import {
|
|
4
|
+
import type { HeaderCell } from '../interface';
|
|
5
5
|
import { TableCtx } from '../table';
|
|
6
6
|
import HeadCell from './cell';
|
|
7
7
|
|
|
8
8
|
export interface TableHeadProps {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Resolved 2D header rows (one array per header row), produced by parseHeaderRows
|
|
11
|
+
*/
|
|
12
|
+
headerRows?: HeaderCell[][];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const TableHead: React.FC<any> = (props) => {
|
|
16
|
-
const {
|
|
16
|
+
const { headerRows = [], onCheckAll, checkedAll, onHeaderRow, ...rest } =
|
|
17
|
+
props;
|
|
17
18
|
|
|
18
19
|
const { prefixCls } = useContext(TableCtx);
|
|
19
20
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<Checkbox checked={checkedAll} onChange={onCheckAll} />
|
|
33
|
-
) : null}
|
|
34
|
-
</th>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
if (key === 'YEE_EXPAND_COL' && visible !== false) {
|
|
38
|
-
return (
|
|
39
|
-
<th
|
|
40
|
-
className={clsx(`${prefixCls}-cell`, `${prefixCls}-expand-col`)}
|
|
41
|
-
scope="col"
|
|
42
|
-
key="title-column-expandable"
|
|
43
|
-
></th>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
21
|
+
const renderCell = (
|
|
22
|
+
cell: HeaderCell,
|
|
23
|
+
rowIndex: number,
|
|
24
|
+
colIndex: number,
|
|
25
|
+
) => {
|
|
26
|
+
const { column, colSpan, rowSpan } = cell;
|
|
27
|
+
const { key, type, visible } = column;
|
|
28
|
+
const cellKey =
|
|
29
|
+
'title-column-' +
|
|
30
|
+
(column.key || column.dataIndex || `${rowIndex}-${colIndex}`);
|
|
31
|
+
|
|
32
|
+
if (key === 'YEE_SELECTION_COL') {
|
|
46
33
|
return (
|
|
47
|
-
<
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
key={
|
|
34
|
+
<th
|
|
35
|
+
className={`${prefixCls}-cell ${prefixCls}-selection-col`}
|
|
36
|
+
scope="col"
|
|
37
|
+
key={cellKey}
|
|
38
|
+
colSpan={colSpan}
|
|
39
|
+
rowSpan={rowSpan}
|
|
40
|
+
>
|
|
41
|
+
{type === 'checkbox' ? (
|
|
42
|
+
<Checkbox checked={checkedAll} onChange={onCheckAll} />
|
|
43
|
+
) : null}
|
|
44
|
+
</th>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
if (key === 'YEE_EXPAND_COL' && visible !== false) {
|
|
48
|
+
return (
|
|
49
|
+
<th
|
|
50
|
+
className={clsx(`${prefixCls}-cell`, `${prefixCls}-expand-col`)}
|
|
51
|
+
scope="col"
|
|
52
|
+
key={cellKey}
|
|
53
|
+
colSpan={colSpan}
|
|
54
|
+
rowSpan={rowSpan}
|
|
51
55
|
/>
|
|
52
56
|
);
|
|
53
|
-
}
|
|
57
|
+
}
|
|
58
|
+
return (
|
|
59
|
+
<HeadCell
|
|
60
|
+
{...rest}
|
|
61
|
+
{...column}
|
|
62
|
+
colSpan={colSpan}
|
|
63
|
+
rowSpan={rowSpan}
|
|
64
|
+
key={cellKey}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
54
67
|
};
|
|
55
68
|
|
|
56
|
-
const rowProps = onHeaderRow ? onHeaderRow(columns) : {};
|
|
57
|
-
|
|
58
69
|
return (
|
|
59
70
|
<thead className={clsx(`${prefixCls}-thead`)}>
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
{headerRows.map((row: HeaderCell[], rowIndex: number) => {
|
|
72
|
+
const rowColumns = row.map((cell) => cell.column);
|
|
73
|
+
const rowProps = onHeaderRow ? onHeaderRow(rowColumns) : {};
|
|
74
|
+
return (
|
|
75
|
+
<tr {...rowProps} key={`thead-row-${rowIndex}`}>
|
|
76
|
+
{row.map((cell, colIndex) =>
|
|
77
|
+
renderCell(cell, rowIndex, colIndex),
|
|
78
|
+
)}
|
|
79
|
+
</tr>
|
|
80
|
+
);
|
|
81
|
+
})}
|
|
63
82
|
</thead>
|
|
64
83
|
);
|
|
65
84
|
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ColumnProps,
|
|
3
|
+
ExpandableType,
|
|
4
|
+
HeaderCell,
|
|
5
|
+
RowSelectionType,
|
|
6
|
+
WrapedColumnProps,
|
|
7
|
+
} from '../interface';
|
|
8
|
+
|
|
9
|
+
type FixedType = ColumnProps['fixed'];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Recursively flatten a (possibly grouped) column tree into its leaf columns.
|
|
13
|
+
* A parent's `fixed` is inherited by its children when the child does not set its own.
|
|
14
|
+
*/
|
|
15
|
+
export function flattenLeafColumns(
|
|
16
|
+
columns: WrapedColumnProps[],
|
|
17
|
+
parentFixed?: FixedType,
|
|
18
|
+
): WrapedColumnProps[] {
|
|
19
|
+
return columns.reduce<WrapedColumnProps[]>((list, column) => {
|
|
20
|
+
const fixed = column.fixed ?? parentFixed;
|
|
21
|
+
const subColumns = column.children as WrapedColumnProps[] | undefined;
|
|
22
|
+
if (subColumns && subColumns.length > 0) {
|
|
23
|
+
return [...list, ...flattenLeafColumns(subColumns, fixed)];
|
|
24
|
+
}
|
|
25
|
+
return [...list, { ...column, fixed }];
|
|
26
|
+
}, []);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert a column tree into a 2D array of header cells (one array per header row),
|
|
31
|
+
* computing each cell's colSpan/rowSpan. Mirrors rc-table's parseHeaderRows.
|
|
32
|
+
*
|
|
33
|
+
* - Pass 1 (DFS): place each column into the row matching its depth; a group's
|
|
34
|
+
* colSpan equals the sum of its children's colSpans.
|
|
35
|
+
* - Pass 2: leaf cells (no sub-columns) get rowSpan = rowCount - rowIndex so
|
|
36
|
+
* they stretch down to the last header row; group cells keep rowSpan = 1.
|
|
37
|
+
*/
|
|
38
|
+
export function parseHeaderRows(
|
|
39
|
+
rootColumns: WrapedColumnProps[],
|
|
40
|
+
): HeaderCell[][] {
|
|
41
|
+
const rows: HeaderCell[][] = [];
|
|
42
|
+
|
|
43
|
+
const fillRowCells = (
|
|
44
|
+
columns: WrapedColumnProps[],
|
|
45
|
+
rowIndex: number,
|
|
46
|
+
): number => {
|
|
47
|
+
rows[rowIndex] = rows[rowIndex] || [];
|
|
48
|
+
let colSpanTotal = 0;
|
|
49
|
+
columns.filter(Boolean).forEach((column) => {
|
|
50
|
+
const cell: HeaderCell = {
|
|
51
|
+
column,
|
|
52
|
+
colSpan: 1,
|
|
53
|
+
rowSpan: 1,
|
|
54
|
+
};
|
|
55
|
+
const subColumns = column.children as WrapedColumnProps[] | undefined;
|
|
56
|
+
if (subColumns && subColumns.length > 0) {
|
|
57
|
+
cell.colSpan = fillRowCells(subColumns, rowIndex + 1);
|
|
58
|
+
cell.hasSubColumns = true;
|
|
59
|
+
}
|
|
60
|
+
rows[rowIndex].push(cell);
|
|
61
|
+
colSpanTotal += cell.colSpan;
|
|
62
|
+
});
|
|
63
|
+
return colSpanTotal;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
fillRowCells(rootColumns, 0);
|
|
67
|
+
|
|
68
|
+
const rowCount = rows.length;
|
|
69
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
|
|
70
|
+
rows[rowIndex].forEach((cell) => {
|
|
71
|
+
// Leaf cells stretch to the bottom row; group cells stay at rowSpan = 1.
|
|
72
|
+
if (!cell.hasSubColumns) {
|
|
73
|
+
cell.rowSpan = rowCount - rowIndex;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return rows;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Inject selection / expand columns into the top level of the column tree.
|
|
83
|
+
* `index` is a 1-based position among the top-level columns.
|
|
84
|
+
*/
|
|
85
|
+
export function injectSelectionExpand(
|
|
86
|
+
columns: WrapedColumnProps[],
|
|
87
|
+
rowSelection?: RowSelectionType,
|
|
88
|
+
expandable?: ExpandableType,
|
|
89
|
+
): WrapedColumnProps[] {
|
|
90
|
+
const result = [...columns];
|
|
91
|
+
if (rowSelection) {
|
|
92
|
+
const { index = 1 } = rowSelection;
|
|
93
|
+
result.splice(index - 1, 0, {
|
|
94
|
+
width: 50,
|
|
95
|
+
...rowSelection,
|
|
96
|
+
key: 'YEE_SELECTION_COL',
|
|
97
|
+
} as WrapedColumnProps);
|
|
98
|
+
}
|
|
99
|
+
if (expandable) {
|
|
100
|
+
const { index = 1, visible = true } = expandable;
|
|
101
|
+
const loc = index ? index - 1 : rowSelection ? 1 : 0;
|
|
102
|
+
if (visible !== false) {
|
|
103
|
+
result.splice(loc, 0, {
|
|
104
|
+
width: 50,
|
|
105
|
+
...expandable,
|
|
106
|
+
key: 'YEE_EXPAND_COL',
|
|
107
|
+
} as WrapedColumnProps);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|