@rainbow-oh/yee-c 0.14.7 → 0.15.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/Form/index.d.ts +1 -1
- package/dist/cjs/Input/style/index.less +1 -0
- package/dist/cjs/InputNumber/style/index.less +1 -0
- package/dist/cjs/Select/hooks/useSelectKeyboard.js +5 -2
- package/dist/cjs/Selector/selector.js +6 -3
- package/dist/cjs/TableSelect/hooks/useTableSelectKeyboard.d.ts +27 -0
- package/dist/cjs/TableSelect/hooks/useTableSelectKeyboard.js +128 -0
- package/dist/cjs/TableSelect/interface.d.ts +9 -4
- package/dist/cjs/TableSelect/internal-table.js +27 -14
- package/dist/cjs/TableSelect/style/index.less +3 -11
- package/dist/cjs/TableSelect/table-select.js +40 -3
- package/dist/cjs/style/size.css +1 -1
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +2 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Form/index.d.ts +1 -1
- package/dist/esm/Input/style/index.less +1 -0
- package/dist/esm/InputNumber/style/index.less +1 -0
- package/dist/esm/Select/hooks/useSelectKeyboard.js +7 -2
- package/dist/esm/Selector/selector.js +10 -5
- package/dist/esm/TableSelect/hooks/useTableSelectKeyboard.d.ts +27 -0
- package/dist/esm/TableSelect/hooks/useTableSelectKeyboard.js +132 -0
- package/dist/esm/TableSelect/interface.d.ts +9 -4
- package/dist/esm/TableSelect/internal-table.js +6 -2
- package/dist/esm/TableSelect/style/index.less +3 -11
- package/dist/esm/TableSelect/table-select.js +36 -3
- package/dist/esm/style/size.css +1 -1
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +2 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +2 -2
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Form/index.ts +4 -0
- package/src/Input/style/index.less +1 -0
- package/src/InputNumber/style/index.less +1 -0
- package/src/Select/hooks/useSelectKeyboard.ts +7 -2
- package/src/Selector/selector.tsx +10 -5
- package/src/TableSelect/hooks/useTableSelectKeyboard.ts +141 -0
- package/src/TableSelect/index.en-US.md +47 -44
- package/src/TableSelect/index.zh-CN.md +47 -44
- package/src/TableSelect/interface.ts +9 -4
- package/src/TableSelect/internal-table.tsx +14 -6
- package/src/TableSelect/style/index.less +3 -11
- package/src/TableSelect/table-select.tsx +45 -3
- package/src/style/size.css +1 -1
- package/src/version.ts +1 -1
package/package.json
CHANGED
package/src/Form/index.ts
CHANGED
|
@@ -261,8 +261,13 @@ export default function useSelectKeyboard({
|
|
|
261
261
|
handleEnter();
|
|
262
262
|
break;
|
|
263
263
|
case 'Escape':
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
// Only swallow Escape while open so outer layers (e.g. a Dialog's
|
|
265
|
+
// useEsc listening on document) still receive it when closed.
|
|
266
|
+
if (open) {
|
|
267
|
+
event.preventDefault();
|
|
268
|
+
event.stopPropagation();
|
|
269
|
+
handleEscape();
|
|
270
|
+
}
|
|
266
271
|
break;
|
|
267
272
|
default:
|
|
268
273
|
}
|
|
@@ -284,12 +284,17 @@ const Selector = React.forwardRef(
|
|
|
284
284
|
aria-disabled={disabled || undefined}
|
|
285
285
|
onKeyDown={(event) => {
|
|
286
286
|
if (disabled) return;
|
|
287
|
-
//
|
|
288
|
-
if (
|
|
289
|
-
|
|
287
|
+
// Enter opens the dropdown while it is closed
|
|
288
|
+
if (event.key === 'Enter' && !open && onOpenChange) {
|
|
289
|
+
event.preventDefault();
|
|
290
|
+
onOpenChange(true);
|
|
291
|
+
}
|
|
292
|
+
// Input forwards this handler for its own keydowns; handling them
|
|
293
|
+
// here too would fire the handler twice per keypress. Only handle
|
|
294
|
+
// events that originate on the container (non-searchable focus).
|
|
295
|
+
if (event.target !== inputRef.current) {
|
|
296
|
+
externalOnKeyDown?.(event as React.KeyboardEvent<HTMLInputElement>);
|
|
290
297
|
}
|
|
291
|
-
// Also call external onKeyDown if provided
|
|
292
|
-
externalOnKeyDown?.(event as React.KeyboardEvent<HTMLInputElement>);
|
|
293
298
|
}}
|
|
294
299
|
ref={ref}
|
|
295
300
|
>
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import type { TableSelectDataType } from '../interface';
|
|
3
|
+
|
|
4
|
+
type KeyType = string | number;
|
|
5
|
+
|
|
6
|
+
interface UseTableSelectKeyboardParams {
|
|
7
|
+
open: boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
dataSource: Array<TableSelectDataType>;
|
|
10
|
+
rowKey: string | ((record: any) => string);
|
|
11
|
+
selectionType: 'radio' | 'checkbox';
|
|
12
|
+
selectedRowKeys: Array<KeyType>;
|
|
13
|
+
searchValue: string;
|
|
14
|
+
onSelect: (keys: Array<KeyType>, rows: Array<TableSelectDataType>) => void;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Keyboard navigation for the popup table. The highlight is positional (like a
|
|
20
|
+
* hover cursor): `activeRow` is a rendered row index, and Space selects the
|
|
21
|
+
* record displayed there. The rendered order is the filter→sort→paginate
|
|
22
|
+
* result inside Table and is not derivable from `dataSource`, so the row count
|
|
23
|
+
* and the highlighted row's key are both read from the popup DOM.
|
|
24
|
+
*/
|
|
25
|
+
export default function useTableSelectKeyboard({
|
|
26
|
+
open,
|
|
27
|
+
disabled,
|
|
28
|
+
dataSource,
|
|
29
|
+
rowKey,
|
|
30
|
+
selectionType,
|
|
31
|
+
selectedRowKeys,
|
|
32
|
+
searchValue,
|
|
33
|
+
onSelect,
|
|
34
|
+
onClose,
|
|
35
|
+
}: UseTableSelectKeyboardParams) {
|
|
36
|
+
const popupRef = useRef<HTMLDivElement | null>(null);
|
|
37
|
+
// 1-based index of the highlighted row (`tr[data-row-index]`), 0 = none.
|
|
38
|
+
const [activeRow, setActiveRow] = useState(0);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
setActiveRow(0);
|
|
42
|
+
}, [open, searchValue]);
|
|
43
|
+
|
|
44
|
+
const getRecordKey = (item: TableSelectDataType) =>
|
|
45
|
+
typeof rowKey === 'function' ? rowKey(item) : item[rowKey];
|
|
46
|
+
|
|
47
|
+
const getRowCount = () =>
|
|
48
|
+
popupRef.current?.querySelectorAll('tr[data-row-index]').length ?? 0;
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!open || activeRow < 1) return;
|
|
52
|
+
const rowEl = popupRef.current?.querySelector(
|
|
53
|
+
`tr[data-row-index="${activeRow}"]`,
|
|
54
|
+
) as HTMLElement | null;
|
|
55
|
+
if (!rowEl) return;
|
|
56
|
+
// Manual scroll instead of scrollIntoView: the popup renders in a portal,
|
|
57
|
+
// and scrollIntoView would scroll the page as well as the popup.
|
|
58
|
+
let parent = rowEl.parentElement;
|
|
59
|
+
while (parent && parent !== popupRef.current) {
|
|
60
|
+
const { overflowY } = window.getComputedStyle(parent);
|
|
61
|
+
if (
|
|
62
|
+
/(auto|scroll)/.test(overflowY) &&
|
|
63
|
+
parent.scrollHeight > parent.clientHeight
|
|
64
|
+
) {
|
|
65
|
+
const parentRect = parent.getBoundingClientRect();
|
|
66
|
+
const rowRect = rowEl.getBoundingClientRect();
|
|
67
|
+
if (rowRect.bottom > parentRect.bottom) {
|
|
68
|
+
parent.scrollTop += rowRect.bottom - parentRect.bottom;
|
|
69
|
+
} else if (rowRect.top < parentRect.top) {
|
|
70
|
+
parent.scrollTop -= parentRect.top - rowRect.top;
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
parent = parent.parentElement;
|
|
75
|
+
}
|
|
76
|
+
}, [activeRow, open]);
|
|
77
|
+
|
|
78
|
+
const selectActiveRow = () => {
|
|
79
|
+
const rowEl = popupRef.current?.querySelector(
|
|
80
|
+
`tr[data-row-index="${activeRow}"]`,
|
|
81
|
+
);
|
|
82
|
+
const inputEl = rowEl?.querySelector(
|
|
83
|
+
'input[type="radio"],input[type="checkbox"]',
|
|
84
|
+
) as HTMLInputElement | null;
|
|
85
|
+
if (!inputEl || inputEl.disabled) return;
|
|
86
|
+
|
|
87
|
+
const record = dataSource.find(
|
|
88
|
+
(item) => String(getRecordKey(item)) === inputEl.value,
|
|
89
|
+
);
|
|
90
|
+
if (!record) return;
|
|
91
|
+
const key = getRecordKey(record);
|
|
92
|
+
|
|
93
|
+
if (selectionType === 'radio') {
|
|
94
|
+
// Same shape as the click path: arrays, normalized by the consumer.
|
|
95
|
+
onSelect([key], [record]);
|
|
96
|
+
onClose();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const checked = selectedRowKeys.some((k) => String(k) === String(key));
|
|
101
|
+
const nextKeys = checked
|
|
102
|
+
? selectedRowKeys.filter((k) => String(k) !== String(key))
|
|
103
|
+
: [...selectedRowKeys, key];
|
|
104
|
+
const rows = dataSource.filter((item) =>
|
|
105
|
+
nextKeys.some((k) => String(getRecordKey(item)) === String(k)),
|
|
106
|
+
);
|
|
107
|
+
onSelect(nextKeys, rows);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
111
|
+
if (!open || disabled) return;
|
|
112
|
+
switch (event.key) {
|
|
113
|
+
case 'ArrowDown':
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
setActiveRow(Math.min(activeRow + 1, getRowCount()));
|
|
116
|
+
break;
|
|
117
|
+
case 'ArrowUp':
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
setActiveRow(activeRow <= 1 ? getRowCount() : activeRow - 1);
|
|
120
|
+
break;
|
|
121
|
+
case ' ':
|
|
122
|
+
// With nothing highlighted, space keeps its native input behavior.
|
|
123
|
+
if (activeRow > 0) {
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
selectActiveRow();
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case 'Escape':
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
// Stop the event from reaching outer layers (e.g. a Dialog's useEsc
|
|
131
|
+
// listening on document) so only the dropdown closes.
|
|
132
|
+
event.stopPropagation();
|
|
133
|
+
onClose();
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return { popupRef, activeRow, handleKeyDown };
|
|
141
|
+
}
|
|
@@ -31,45 +31,45 @@ A component for selecting one or more options from table data, combining feature
|
|
|
31
31
|
|
|
32
32
|
### TableSelectProps
|
|
33
33
|
|
|
34
|
-
| Property
|
|
35
|
-
|
|
|
36
|
-
| prefixCls
|
|
37
|
-
| className
|
|
38
|
-
| style
|
|
39
|
-
| rowKey
|
|
40
|
-
| columns
|
|
41
|
-
| dataSource
|
|
42
|
-
| rowSelection
|
|
43
|
-
| value
|
|
44
|
-
| defaultValue
|
|
45
|
-
| disabled
|
|
46
|
-
| loading
|
|
47
|
-
| placement
|
|
48
|
-
| searchable
|
|
49
|
-
| searchOnInput
|
|
50
|
-
| allowClear
|
|
51
|
-
| closable
|
|
52
|
-
| placeholder
|
|
53
|
-
| optionLabelProp | `string \| ((option:
|
|
54
|
-
| type
|
|
55
|
-
| options
|
|
56
|
-
| isShowFilter
|
|
57
|
-
| containerId
|
|
58
|
-
| io
|
|
59
|
-
| onChange
|
|
60
|
-
| onSearch
|
|
61
|
-
| onOpenChange
|
|
34
|
+
| Property | Type | Description | Default Value |
|
|
35
|
+
| --------------- | ----------------------------------------------------- | ---------------------------------------------------------- | -------------------- |
|
|
36
|
+
| prefixCls | `string` | Custom class name prefix | `'yee-table-select'` |
|
|
37
|
+
| className | `string` | Root element class name | - |
|
|
38
|
+
| style | `React.CSSProperties` | Root element inline styles | - |
|
|
39
|
+
| rowKey | `string \| ((record: any) => string)` | Unique identifier field name for data | `'id'` |
|
|
40
|
+
| columns | `Array<any>` | Table column configuration | - |
|
|
41
|
+
| dataSource | `Array<TableSelectDataType>` | Data source | - |
|
|
42
|
+
| rowSelection | `RowSelectionType` | Row selection configuration | - |
|
|
43
|
+
| value | `SelectionKeyType \| SelectionKeyType[]` | Controlled value | - |
|
|
44
|
+
| defaultValue | `SelectionKeyType \| SelectionKeyType[]` | Default value | - |
|
|
45
|
+
| disabled | `boolean` | Whether disabled | - |
|
|
46
|
+
| loading | `boolean` | Whether data is loading; displays a gray loading indicator | `false` |
|
|
47
|
+
| placement | `'bottomLeft' \| 'topLeft'` | Popup placement | `'bottomLeft'` |
|
|
48
|
+
| searchable | `boolean` | Whether searchable | `true` |
|
|
49
|
+
| searchOnInput | `boolean` | Whether to search while typing | `true` |
|
|
50
|
+
| allowClear | `boolean` | Whether allow clear | `true` |
|
|
51
|
+
| closable | `boolean` | Whether tags are closable | `true` |
|
|
52
|
+
| placeholder | `string` | Placeholder text | - |
|
|
53
|
+
| optionLabelProp | `string \| ((option: TableSelectDataType) => string)` | Option label property | `'name'` |
|
|
54
|
+
| type | `'radio' \| 'checkbox'` | Selection type | `'radio'` |
|
|
55
|
+
| options | `TagType[]` | Preset options | - |
|
|
56
|
+
| isShowFilter | `boolean` | Whether to show filter (All/Selected for multiple) | `true` |
|
|
57
|
+
| containerId | `string` | Container ID (for popup mounting) | - |
|
|
58
|
+
| io | `'out'` | Input direction | - |
|
|
59
|
+
| onChange | `(keys, data, checked, changeData) => void` | Selection change callback | - |
|
|
60
|
+
| onSearch | `(value: string, e?) => void` | Search callback | - |
|
|
61
|
+
| onOpenChange | `(open: boolean) => void` | Popup state change callback | - |
|
|
62
62
|
|
|
63
63
|
### RowSelectionType
|
|
64
64
|
|
|
65
65
|
Row selection configuration, inherited from Table component's RowSelectionType.
|
|
66
66
|
|
|
67
|
-
| Property
|
|
68
|
-
|
|
|
69
|
-
| type
|
|
70
|
-
| selectedRowKeys
|
|
71
|
-
| defaultSelectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | Default selected row keys
|
|
72
|
-
| onChange
|
|
67
|
+
| Property | Type | Description | Default Value |
|
|
68
|
+
| ---------------------- | --------------------------------------------- | ------------------------------- | ------------- |
|
|
69
|
+
| type | `'radio' \| 'checkbox'` | Single/multiple selection | - |
|
|
70
|
+
| selectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | (Controlled) selected row keys | - |
|
|
71
|
+
| defaultSelectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | Default selected row keys | - |
|
|
72
|
+
| onChange | `(selectedRowKeys, selectedRows) => void` | Callback when selection changes | - |
|
|
73
73
|
|
|
74
74
|
## Methods
|
|
75
75
|
|
|
@@ -77,17 +77,20 @@ Row selection configuration, inherited from Table component's RowSelectionType.
|
|
|
77
77
|
|
|
78
78
|
InternalTable is an internal component of TableSelect and typically doesn't need to be used directly.
|
|
79
79
|
|
|
80
|
-
| Property
|
|
81
|
-
|
|
|
82
|
-
| rowKey
|
|
83
|
-
| columns
|
|
84
|
-
| dataSource
|
|
85
|
-
| rowSelection | `RowSelectionType`
|
|
86
|
-
| type
|
|
87
|
-
| value
|
|
88
|
-
| isShowFilter | `boolean`
|
|
89
|
-
| visible
|
|
80
|
+
| Property | Type | Description | Default Value |
|
|
81
|
+
| ------------ | ------------------------------------------- | ---------------------------------------------------------------------- | ------------- |
|
|
82
|
+
| rowKey | `string` | Unique identifier field name for data | - |
|
|
83
|
+
| columns | `Array<any>` | Table column configuration | - |
|
|
84
|
+
| dataSource | `Array<TableSelectDataType>` | Data source | - |
|
|
85
|
+
| rowSelection | `RowSelectionType` | Row selection configuration | - |
|
|
86
|
+
| type | `'radio' \| 'checkbox'` | Selection type | - |
|
|
87
|
+
| value | `SelectedKeyType \| Array<SelectedKeyType>` | Selected value | - |
|
|
88
|
+
| isShowFilter | `boolean` | Whether to show filter | `true` |
|
|
89
|
+
| visible | `boolean` | Whether popup is visible | - |
|
|
90
|
+
| popupRef | `React.RefObject<HTMLDivElement \| null>` | Ref to the popup root element, used internally for keyboard navigation | - |
|
|
90
91
|
|
|
91
92
|
## Notes
|
|
92
93
|
|
|
94
|
+
- When the dropdown is open, keyboard is supported: `↑`/`↓` move the highlight across rows, `Space` selects/toggles the highlighted row, `Esc` closes the dropdown; the text caret always stays in the input; press `Enter` while closed to open the dropdown
|
|
95
|
+
|
|
93
96
|
- Adapted for mobile (popup constrained with max-width/height and scrollable)
|
|
@@ -31,45 +31,45 @@ toc: 'content'
|
|
|
31
31
|
|
|
32
32
|
### TableSelectProps
|
|
33
33
|
|
|
34
|
-
| 属性名
|
|
35
|
-
|
|
|
36
|
-
| prefixCls
|
|
37
|
-
| className
|
|
38
|
-
| style
|
|
39
|
-
| rowKey
|
|
40
|
-
| columns
|
|
41
|
-
| dataSource
|
|
42
|
-
| rowSelection
|
|
43
|
-
| value
|
|
44
|
-
| defaultValue
|
|
45
|
-
| disabled
|
|
46
|
-
| loading
|
|
47
|
-
| placement
|
|
48
|
-
| searchable
|
|
49
|
-
| searchOnInput
|
|
50
|
-
| allowClear
|
|
51
|
-
| closable
|
|
52
|
-
| placeholder
|
|
53
|
-
| optionLabelProp | `string \| ((option:
|
|
54
|
-
| type
|
|
55
|
-
| options
|
|
56
|
-
| isShowFilter
|
|
57
|
-
| containerId
|
|
58
|
-
| io
|
|
59
|
-
| onChange
|
|
60
|
-
| onSearch
|
|
61
|
-
| onOpenChange
|
|
34
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
35
|
+
| --------------- | ----------------------------------------------------- | ---------------------------------------- | -------------------- |
|
|
36
|
+
| prefixCls | `string` | 自定义类名前缀 | `'yee-table-select'` |
|
|
37
|
+
| className | `string` | 根元素类名 | - |
|
|
38
|
+
| style | `React.CSSProperties` | 根元素行内样式 | - |
|
|
39
|
+
| rowKey | `string \| ((record: any) => string)` | 数据的唯一标识字段名 | `'id'` |
|
|
40
|
+
| columns | `Array<any>` | 表格列的配置信息 | - |
|
|
41
|
+
| dataSource | `Array<TableSelectDataType>` | 数据源 | - |
|
|
42
|
+
| rowSelection | `RowSelectionType` | 行选择配置 | - |
|
|
43
|
+
| value | `SelectionKeyType \| SelectionKeyType[]` | 受控值 | - |
|
|
44
|
+
| defaultValue | `SelectionKeyType \| SelectionKeyType[]` | 默认值 | - |
|
|
45
|
+
| disabled | `boolean` | 是否禁用 | - |
|
|
46
|
+
| loading | `boolean` | 是否处于加载状态,加载时显示灰色加载图标 | `false` |
|
|
47
|
+
| placement | `'bottomLeft' \| 'topLeft'` | 弹出层位置 | `'bottomLeft'` |
|
|
48
|
+
| searchable | `boolean` | 是否可搜索 | `true` |
|
|
49
|
+
| searchOnInput | `boolean` | 是否边输入边搜索 | `true` |
|
|
50
|
+
| allowClear | `boolean` | 是否允许清除 | `true` |
|
|
51
|
+
| closable | `boolean` | 标签是否可关闭 | `true` |
|
|
52
|
+
| placeholder | `string` | 占位符文本 | - |
|
|
53
|
+
| optionLabelProp | `string \| ((option: TableSelectDataType) => string)` | 选项标签属性 | `'name'` |
|
|
54
|
+
| type | `'radio' \| 'checkbox'` | 选择类型 | `'radio'` |
|
|
55
|
+
| options | `TagType[]` | 预设选项 | - |
|
|
56
|
+
| isShowFilter | `boolean` | 是否显示过滤器(多选时 All/Selected) | `true` |
|
|
57
|
+
| containerId | `string` | 容器 ID(用于弹出层挂载) | - |
|
|
58
|
+
| io | `'out'` | 输入方向 | - |
|
|
59
|
+
| onChange | `(keys, data, checked, changeData) => void` | 选中变更回调 | - |
|
|
60
|
+
| onSearch | `(value: string, e?) => void` | 搜索回调 | - |
|
|
61
|
+
| onOpenChange | `(open: boolean) => void` | 弹出层状态变更回调 | - |
|
|
62
62
|
|
|
63
63
|
### RowSelectionType
|
|
64
64
|
|
|
65
65
|
表格行选择配置,继承自 Table 组件的 RowSelectionType。
|
|
66
66
|
|
|
67
|
-
| 属性名
|
|
68
|
-
|
|
|
69
|
-
| type
|
|
70
|
-
| selectedRowKeys
|
|
71
|
-
| defaultSelectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | 默认选中的行keys
|
|
72
|
-
| onChange
|
|
67
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
68
|
+
| ---------------------- | --------------------------------------------- | ---------------------- | ------ |
|
|
69
|
+
| type | `'radio' \| 'checkbox'` | 单选/多选 | - |
|
|
70
|
+
| selectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | (受控)选中的行keys | - |
|
|
71
|
+
| defaultSelectedRowKeys | `Array<SelectionKeyType> \| SelectionKeyType` | 默认选中的行keys | - |
|
|
72
|
+
| onChange | `(selectedRowKeys, selectedRows) => void` | 选中项发生变化时的回调 | - |
|
|
73
73
|
|
|
74
74
|
## 方法
|
|
75
75
|
|
|
@@ -77,17 +77,20 @@ toc: 'content'
|
|
|
77
77
|
|
|
78
78
|
InternalTable 组件是 TableSelect 的内部组件,通常不需要直接使用。
|
|
79
79
|
|
|
80
|
-
| 属性名
|
|
81
|
-
|
|
|
82
|
-
| rowKey
|
|
83
|
-
| columns
|
|
84
|
-
| dataSource
|
|
85
|
-
| rowSelection | `RowSelectionType`
|
|
86
|
-
| type
|
|
87
|
-
| value
|
|
88
|
-
| isShowFilter | `boolean`
|
|
89
|
-
| visible
|
|
80
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
81
|
+
| ------------ | ------------------------------------------- | ---------------------------------- | ------ |
|
|
82
|
+
| rowKey | `string` | 数据的唯一标识字段名 | - |
|
|
83
|
+
| columns | `Array<any>` | 表格列的配置信息 | - |
|
|
84
|
+
| dataSource | `Array<TableSelectDataType>` | 数据源 | - |
|
|
85
|
+
| rowSelection | `RowSelectionType` | 行选择配置 | - |
|
|
86
|
+
| type | `'radio' \| 'checkbox'` | 选择类型 | - |
|
|
87
|
+
| value | `SelectedKeyType \| Array<SelectedKeyType>` | 选中的值 | - |
|
|
88
|
+
| isShowFilter | `boolean` | 是否显示过滤器 | `true` |
|
|
89
|
+
| visible | `boolean` | 弹出层是否可见 | - |
|
|
90
|
+
| popupRef | `React.RefObject<HTMLDivElement \| null>` | 弹层根元素 ref,供键盘导航内部使用 | - |
|
|
90
91
|
|
|
91
92
|
## 注意事项
|
|
92
93
|
|
|
94
|
+
- 下拉展开后支持键盘操作:`↑`/`↓` 在行间移动高亮,`空格` 选中/取消勾选高亮行,`Esc` 关闭下拉;输入光标始终保留在输入框内;收起时按 `回车` 可展开下拉
|
|
95
|
+
|
|
93
96
|
- 已适配移动端(弹窗限制最大宽高并支持滚动)
|
|
@@ -10,7 +10,7 @@ type SelectedKeyType = string | number;
|
|
|
10
10
|
/**
|
|
11
11
|
* Data item type
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
13
|
+
export type TableSelectDataType = {
|
|
14
14
|
[propName: string]: any;
|
|
15
15
|
};
|
|
16
16
|
|
|
@@ -42,7 +42,7 @@ export interface InternalTableProps {
|
|
|
42
42
|
/**
|
|
43
43
|
* Data source
|
|
44
44
|
*/
|
|
45
|
-
dataSource: Array<
|
|
45
|
+
dataSource: Array<TableSelectDataType>;
|
|
46
46
|
/**
|
|
47
47
|
* Custom class name
|
|
48
48
|
*/
|
|
@@ -67,6 +67,11 @@ export interface InternalTableProps {
|
|
|
67
67
|
* Whether popup is visible (for focus trap)
|
|
68
68
|
*/
|
|
69
69
|
visible?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Ref to the popup root element, used by TableSelect for keyboard navigation
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
popupRef?: React.RefObject<HTMLDivElement | null>;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
/**
|
|
@@ -96,7 +101,7 @@ export interface TableSelectProps
|
|
|
96
101
|
/**
|
|
97
102
|
* Data source
|
|
98
103
|
*/
|
|
99
|
-
dataSource: Array<
|
|
104
|
+
dataSource: Array<TableSelectDataType>;
|
|
100
105
|
/**
|
|
101
106
|
* Single or multiple selection
|
|
102
107
|
* @default: 'radio'
|
|
@@ -180,7 +185,7 @@ export interface TableSelectProps
|
|
|
180
185
|
* Option label property (text field for displaying labels)
|
|
181
186
|
* @default 'name'
|
|
182
187
|
*/
|
|
183
|
-
optionLabelProp?: string | ((option:
|
|
188
|
+
optionLabelProp?: string | ((option: TableSelectDataType) => string);
|
|
184
189
|
/**
|
|
185
190
|
* Selection change callback
|
|
186
191
|
* @param keys Selected keys
|
|
@@ -7,7 +7,7 @@ import { InternalTableProps } from './interface';
|
|
|
7
7
|
|
|
8
8
|
type SelectedKeyType = string | number;
|
|
9
9
|
|
|
10
|
-
type
|
|
10
|
+
type TableSelectDataType = {
|
|
11
11
|
[propName: string]: any;
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -22,12 +22,13 @@ const InternalTable: React.FC<InternalTableProps> = (props) => {
|
|
|
22
22
|
isShowFilter = true,
|
|
23
23
|
rowSelection = {},
|
|
24
24
|
visible,
|
|
25
|
+
popupRef: externalPopupRef,
|
|
25
26
|
...rest
|
|
26
27
|
} = props;
|
|
27
28
|
|
|
28
|
-
const [internalDataSource, setInternalDataSource] = useState<
|
|
29
|
-
[]
|
|
30
|
-
);
|
|
29
|
+
const [internalDataSource, setInternalDataSource] = useState<
|
|
30
|
+
TableSelectDataType[]
|
|
31
|
+
>([]);
|
|
31
32
|
const renderRowSelection = { type, selectedRowKeys: value, ...rowSelection };
|
|
32
33
|
|
|
33
34
|
useEffect(() => {
|
|
@@ -45,7 +46,7 @@ const InternalTable: React.FC<InternalTableProps> = (props) => {
|
|
|
45
46
|
setInternalDataSource(dataSource);
|
|
46
47
|
} else {
|
|
47
48
|
setInternalDataSource(
|
|
48
|
-
dataSource.filter((data:
|
|
49
|
+
dataSource.filter((data: TableSelectDataType) =>
|
|
49
50
|
(selectedRowKeys as SelectedKeyType[])?.includes(
|
|
50
51
|
typeof rowKey === 'function' ? rowKey(data) : data[rowKey],
|
|
51
52
|
),
|
|
@@ -76,7 +77,14 @@ const InternalTable: React.FC<InternalTableProps> = (props) => {
|
|
|
76
77
|
return null;
|
|
77
78
|
};
|
|
78
79
|
return (
|
|
79
|
-
<div
|
|
80
|
+
<div
|
|
81
|
+
className={`${prefixCls}-popup`}
|
|
82
|
+
tabIndex={0}
|
|
83
|
+
ref={(node) => {
|
|
84
|
+
popupRef.current = node;
|
|
85
|
+
if (externalPopupRef) externalPopupRef.current = node;
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
80
88
|
{renderRadio()}
|
|
81
89
|
<Table
|
|
82
90
|
{...rest}
|
|
@@ -6,16 +6,8 @@
|
|
|
6
6
|
margin: 0;
|
|
7
7
|
padding: 12px 0;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.rb-table-select {
|
|
16
|
-
margin-bottom: 0;
|
|
17
|
-
|
|
18
|
-
.rb-table-footer-operate {
|
|
19
|
-
padding: 0 12px;
|
|
9
|
+
// Keyboard-navigated row (TableSelect arrow keys)
|
|
10
|
+
.yee-table-highlight-row {
|
|
11
|
+
background-color: var(--yee-table-tbody-tr-hover-bg-color);
|
|
20
12
|
}
|
|
21
13
|
}
|