@rainbow-oh/yee-c 0.12.2 → 0.13.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/controlled-filter.d.ts +3 -0
- package/dist/cjs/Table/demo/controlled-filter.js +105 -0
- package/dist/cjs/Table/hooks/useFilter.d.ts +5 -1
- package/dist/cjs/Table/hooks/useFilter.js +80 -42
- package/dist/cjs/Table/index.d.ts +1 -1
- package/dist/cjs/Table/interface.d.ts +14 -4
- package/dist/cjs/Table/table.js +22 -25
- package/dist/cjs/Table/theader/cell.js +0 -3
- package/dist/cjs/Table/theader/filter.js +22 -5
- 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/controlled-filter.d.ts +3 -0
- package/dist/esm/Table/demo/controlled-filter.js +122 -0
- package/dist/esm/Table/hooks/useFilter.d.ts +5 -1
- package/dist/esm/Table/hooks/useFilter.js +112 -69
- package/dist/esm/Table/index.d.ts +1 -1
- package/dist/esm/Table/interface.d.ts +14 -4
- package/dist/esm/Table/table.js +34 -21
- package/dist/esm/Table/theader/cell.js +1 -3
- package/dist/esm/Table/theader/filter.js +22 -1
- 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.js +1 -1
- package/package.json +1 -1
- package/src/Table/demo/controlled-filter.tsx +107 -0
- package/src/Table/hooks/useFilter.ts +107 -49
- package/src/Table/index.en-US.md +22 -1
- package/src/Table/index.ts +1 -0
- package/src/Table/index.zh-CN.md +22 -1
- package/src/Table/interface.ts +14 -2
- package/src/Table/table-filter.test.tsx +343 -0
- package/src/Table/table.tsx +29 -27
- package/src/Table/theader/cell.tsx +0 -2
- package/src/Table/theader/filter.tsx +26 -1
- package/src/version.ts +1 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/Table/demo/controlled-filter.tsx
|
|
30
|
+
var controlled_filter_exports = {};
|
|
31
|
+
__export(controlled_filter_exports, {
|
|
32
|
+
default: () => controlled_filter_default
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(controlled_filter_exports);
|
|
35
|
+
var import_yee_c = require("../..");
|
|
36
|
+
var import_react = __toESM(require("react"));
|
|
37
|
+
var allData = [
|
|
38
|
+
{ key: "1", name: "John Brown", age: 32, gender: "male" },
|
|
39
|
+
{ key: "2", name: "Jim Green", age: 42, gender: "male" },
|
|
40
|
+
{ key: "3", name: "Joe Black", age: 32, gender: "male" },
|
|
41
|
+
{ key: "4", name: "Jon Snow", age: 42, gender: "female" },
|
|
42
|
+
{ key: "5", name: "Arya Stark", age: 16, gender: "female" }
|
|
43
|
+
];
|
|
44
|
+
var controlled_filter_default = () => {
|
|
45
|
+
const { messageApi, messageHolder } = import_yee_c.message.useMessage();
|
|
46
|
+
const [nameKeyword, setNameKeyword] = (0, import_react.useState)("");
|
|
47
|
+
const [genders, setGenders] = (0, import_react.useState)([]);
|
|
48
|
+
const columns = [
|
|
49
|
+
{
|
|
50
|
+
title: "Name",
|
|
51
|
+
dataIndex: "name",
|
|
52
|
+
key: "name",
|
|
53
|
+
filter: {
|
|
54
|
+
searchable: true,
|
|
55
|
+
// No onFilter: no local matching, the search hits the "server".
|
|
56
|
+
filteredValue: nameKeyword
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: "Age",
|
|
61
|
+
dataIndex: "age",
|
|
62
|
+
key: "age"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: "Gender",
|
|
66
|
+
dataIndex: "gender",
|
|
67
|
+
key: "gender",
|
|
68
|
+
filter: {
|
|
69
|
+
filterMode: "tree",
|
|
70
|
+
items: [
|
|
71
|
+
{ label: "Male", key: "male" },
|
|
72
|
+
{ label: "Female", key: "female" }
|
|
73
|
+
],
|
|
74
|
+
filteredValue: genders,
|
|
75
|
+
onFilter: (value, record) => value === record.gender
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
const handleChange = (info) => {
|
|
80
|
+
var _a, _b, _c;
|
|
81
|
+
if (info.action !== "filter")
|
|
82
|
+
return;
|
|
83
|
+
const filters = (_a = info.filters) != null ? _a : {};
|
|
84
|
+
const name = (_b = filters.name) != null ? _b : "";
|
|
85
|
+
if (name !== nameKeyword) {
|
|
86
|
+
messageApi.info(`Fetch: /api/users?name=${name}`);
|
|
87
|
+
setNameKeyword(name);
|
|
88
|
+
}
|
|
89
|
+
setGenders((_c = filters.gender) != null ? _c : []);
|
|
90
|
+
};
|
|
91
|
+
const data = allData.filter((item) => {
|
|
92
|
+
const matchName = nameKeyword ? item.name.toLowerCase().includes(nameKeyword.toLowerCase()) : true;
|
|
93
|
+
const matchGender = genders.length ? genders.includes(item.gender) : true;
|
|
94
|
+
return matchName && matchGender;
|
|
95
|
+
});
|
|
96
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, messageHolder, /* @__PURE__ */ import_react.default.createElement(import_yee_c.Space, { block: true, style: { marginBottom: 16 } }, /* @__PURE__ */ import_react.default.createElement(import_yee_c.Button, { onClick: () => setNameKeyword("") }, "Reset name search"), /* @__PURE__ */ import_react.default.createElement(import_yee_c.Button, { onClick: () => setGenders([]) }, "Reset gender filter")), /* @__PURE__ */ import_react.default.createElement(
|
|
97
|
+
import_yee_c.Table,
|
|
98
|
+
{
|
|
99
|
+
columns,
|
|
100
|
+
dataSource: data,
|
|
101
|
+
onChange: handleChange,
|
|
102
|
+
pagination: false
|
|
103
|
+
}
|
|
104
|
+
));
|
|
105
|
+
};
|
|
@@ -8,12 +8,16 @@ type FilterRecord = {
|
|
|
8
8
|
value: FilterInput;
|
|
9
9
|
dataIndex: string;
|
|
10
10
|
};
|
|
11
|
+
export declare const isControlledFilter: (column?: ColumnProps) => boolean;
|
|
11
12
|
export default function useFilter({ data, columns, }: {
|
|
12
13
|
data: Array<Record<string, unknown>>;
|
|
13
14
|
columns: ColumnProps[];
|
|
14
15
|
}): {
|
|
15
16
|
data: Record<string, unknown>[];
|
|
16
17
|
filterRecords: FilterRecord[];
|
|
17
|
-
onFilter: ({ value, dataIndex }: FilterOptions) =>
|
|
18
|
+
onFilter: ({ value, dataIndex }: FilterOptions) => {
|
|
19
|
+
data: Record<string, unknown>[];
|
|
20
|
+
filterRecords: FilterRecord[];
|
|
21
|
+
};
|
|
18
22
|
};
|
|
19
23
|
export {};
|
|
@@ -36,17 +36,71 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
36
36
|
// src/Table/hooks/useFilter.ts
|
|
37
37
|
var useFilter_exports = {};
|
|
38
38
|
__export(useFilter_exports, {
|
|
39
|
-
default: () => useFilter
|
|
39
|
+
default: () => useFilter,
|
|
40
|
+
isControlledFilter: () => isControlledFilter
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(useFilter_exports);
|
|
42
43
|
var import_react = require("react");
|
|
43
44
|
var isEmptyFilterValue = (value) => value === "" || Array.isArray(value) && value.length === 0;
|
|
45
|
+
var isControlledFilter = (column) => {
|
|
46
|
+
var _a;
|
|
47
|
+
return ((_a = column == null ? void 0 : column.filter) == null ? void 0 : _a.filteredValue) !== void 0;
|
|
48
|
+
};
|
|
44
49
|
var normalizeValue = (value) => value === null || value === void 0 ? "" : String(value).toLowerCase();
|
|
50
|
+
var mergeRecords = (internalRecords, columnMap) => {
|
|
51
|
+
const controlled = [];
|
|
52
|
+
columnMap.forEach((column, dataIndex) => {
|
|
53
|
+
var _a;
|
|
54
|
+
if (!isControlledFilter(column))
|
|
55
|
+
return;
|
|
56
|
+
const value = (_a = column.filter) == null ? void 0 : _a.filteredValue;
|
|
57
|
+
if (!isEmptyFilterValue(value)) {
|
|
58
|
+
controlled.push({ dataIndex, value });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const merged = internalRecords.filter(
|
|
62
|
+
(record) => !isControlledFilter(columnMap.get(record.dataIndex))
|
|
63
|
+
);
|
|
64
|
+
if (!controlled.length && merged.length === internalRecords.length) {
|
|
65
|
+
return internalRecords;
|
|
66
|
+
}
|
|
67
|
+
return [...merged, ...controlled];
|
|
68
|
+
};
|
|
69
|
+
var applyFilters = (data, records, columnMap) => {
|
|
70
|
+
const handled = records.filter(
|
|
71
|
+
({ dataIndex, value }) => Boolean(dataIndex) && columnMap.has(dataIndex) && !isEmptyFilterValue(value)
|
|
72
|
+
);
|
|
73
|
+
if (!handled.length) {
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
return data.filter((item) => {
|
|
77
|
+
return handled.every(({ dataIndex, value }) => {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const column = columnMap.get(dataIndex);
|
|
80
|
+
if (isControlledFilter(column) && !((_a = column == null ? void 0 : column.filter) == null ? void 0 : _a.onFilter)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
const customFilter = (_b = column == null ? void 0 : column.filter) == null ? void 0 : _b.onFilter;
|
|
84
|
+
if (customFilter) {
|
|
85
|
+
return Array.isArray(value) ? value.some((filterValue) => customFilter(filterValue, item)) : customFilter(value, item);
|
|
86
|
+
}
|
|
87
|
+
const targetValue = normalizeValue(item[dataIndex]);
|
|
88
|
+
if (Array.isArray(value)) {
|
|
89
|
+
return value.some(
|
|
90
|
+
(filterValue) => targetValue === normalizeValue(filterValue)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return targetValue.includes(normalizeValue(value));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
};
|
|
45
97
|
function useFilter({
|
|
46
98
|
data,
|
|
47
99
|
columns
|
|
48
100
|
}) {
|
|
49
|
-
const [
|
|
101
|
+
const [internalRecords, setInternalRecords] = (0, import_react.useState)(
|
|
102
|
+
[]
|
|
103
|
+
);
|
|
50
104
|
const columnMap = (0, import_react.useMemo)(
|
|
51
105
|
() => new Map(
|
|
52
106
|
columns.flatMap(
|
|
@@ -56,52 +110,36 @@ function useFilter({
|
|
|
56
110
|
[columns]
|
|
57
111
|
);
|
|
58
112
|
(0, import_react.useEffect)(() => {
|
|
59
|
-
|
|
113
|
+
setInternalRecords((current) => {
|
|
60
114
|
const next = current.filter(({ dataIndex }) => columnMap.has(dataIndex));
|
|
61
115
|
return next.length === current.length ? current : next;
|
|
62
116
|
});
|
|
63
117
|
}, [columnMap]);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return handled.every(({ dataIndex, value }) => {
|
|
87
|
-
var _a, _b;
|
|
88
|
-
const customFilter = (_b = (_a = columnMap.get(dataIndex)) == null ? void 0 : _a.filter) == null ? void 0 : _b.onFilter;
|
|
89
|
-
if (customFilter) {
|
|
90
|
-
return Array.isArray(value) ? value.some((filterValue) => customFilter(filterValue, item)) : customFilter(value, item);
|
|
91
|
-
}
|
|
92
|
-
const targetValue = normalizeValue(item[dataIndex]);
|
|
93
|
-
if (Array.isArray(value)) {
|
|
94
|
-
return value.some(
|
|
95
|
-
(filterValue) => targetValue === normalizeValue(filterValue)
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
return targetValue.includes(normalizeValue(value));
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
}, [columnMap, data, filterRecords]);
|
|
118
|
+
const activeRecords = (0, import_react.useMemo)(
|
|
119
|
+
() => mergeRecords(internalRecords, columnMap),
|
|
120
|
+
[internalRecords, columnMap]
|
|
121
|
+
);
|
|
122
|
+
const filtered = (0, import_react.useMemo)(
|
|
123
|
+
() => applyFilters(data, activeRecords, columnMap),
|
|
124
|
+
[columnMap, data, activeRecords]
|
|
125
|
+
);
|
|
126
|
+
const onFilter = (0, import_react.useCallback)(
|
|
127
|
+
({ value, dataIndex }) => {
|
|
128
|
+
const nextInternal = isEmptyFilterValue(value) ? internalRecords.filter((item) => item.dataIndex !== dataIndex) : internalRecords.some((item) => item.dataIndex === dataIndex) ? internalRecords.map(
|
|
129
|
+
(item) => item.dataIndex === dataIndex ? __spreadProps(__spreadValues({}, item), { value }) : item
|
|
130
|
+
) : [...internalRecords, { dataIndex, value }];
|
|
131
|
+
setInternalRecords(nextInternal);
|
|
132
|
+
const nextActive = mergeRecords(nextInternal, columnMap);
|
|
133
|
+
return {
|
|
134
|
+
data: applyFilters(data, nextActive, columnMap),
|
|
135
|
+
filterRecords: nextActive
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
[internalRecords, columnMap, data]
|
|
139
|
+
);
|
|
102
140
|
return {
|
|
103
141
|
data: filtered,
|
|
104
|
-
filterRecords,
|
|
142
|
+
filterRecords: activeRecords,
|
|
105
143
|
onFilter
|
|
106
144
|
};
|
|
107
145
|
}
|
|
@@ -2,7 +2,7 @@ import Column from './column';
|
|
|
2
2
|
import Summary from './summary';
|
|
3
3
|
import InternalTable from './table';
|
|
4
4
|
import Head from './theader';
|
|
5
|
-
export type { ColumnProps, HeaderCell, PaginationType, RowSelectionType, TableBodyComponents, TableComponents, TableProps, TableRowRendererProps, onChangeParams, } from './interface';
|
|
5
|
+
export type { ColumnProps, FilterValue, HeaderCell, PaginationType, RowSelectionType, TableBodyComponents, TableComponents, TableProps, TableRowRendererProps, onChangeParams, } from './interface';
|
|
6
6
|
type TableType = typeof InternalTable & {
|
|
7
7
|
Column: typeof Column;
|
|
8
8
|
Summary: typeof Summary;
|
|
@@ -62,11 +62,13 @@ export interface HeadCellProps extends Omit<WrapedColumnProps, 'title'> {
|
|
|
62
62
|
[prop: string]: number;
|
|
63
63
|
};
|
|
64
64
|
showSorterTooltip?: boolean;
|
|
65
|
-
internalFilters?: {
|
|
66
|
-
[dataIndex: string]: boolean;
|
|
67
|
-
};
|
|
68
65
|
onSort?: (dataIndex: string, sorter: any) => void;
|
|
69
|
-
onInternalFilter?: (
|
|
66
|
+
onInternalFilter?: (options: {
|
|
67
|
+
dataIndex: string;
|
|
68
|
+
value: FilterValue | FilterValue[];
|
|
69
|
+
type?: 'filter' | 'search';
|
|
70
|
+
column: WrapedColumnProps;
|
|
71
|
+
}) => void;
|
|
70
72
|
/**
|
|
71
73
|
* `resizeKey` of the column currently being dragged, if any
|
|
72
74
|
*/
|
|
@@ -188,6 +190,14 @@ export interface ColumnProps {
|
|
|
188
190
|
* Whether searchable, when items is undefined, it acts as a search component
|
|
189
191
|
*/
|
|
190
192
|
searchable?: boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Controlled filter state. When defined, this column's filter state is
|
|
195
|
+
* controlled: the dropdown echo, icon highlight and the `filters` in
|
|
196
|
+
* onChange all derive from it. With no `onFilter`, local matching is
|
|
197
|
+
* skipped entirely (server mode — filter in your onChange handler).
|
|
198
|
+
* Reset with `[]` / `''`.
|
|
199
|
+
*/
|
|
200
|
+
filteredValue?: FilterValue | FilterValue[];
|
|
191
201
|
/**
|
|
192
202
|
* Filter icon
|
|
193
203
|
*/
|
package/dist/cjs/Table/table.js
CHANGED
|
@@ -248,6 +248,27 @@ var Table = import_react.default.forwardRef((baseprops, ref) => {
|
|
|
248
248
|
},
|
|
249
249
|
[onSortInternal, onChange, pagination, current, pageSize, filters]
|
|
250
250
|
);
|
|
251
|
+
const handleFilter = import_react.default.useCallback(
|
|
252
|
+
(options) => {
|
|
253
|
+
const next = onFilterInternal(options);
|
|
254
|
+
const emitted = next.filterRecords.filter(
|
|
255
|
+
(record) => record.dataIndex !== options.dataIndex
|
|
256
|
+
);
|
|
257
|
+
emitted.push({ dataIndex: options.dataIndex, value: options.value });
|
|
258
|
+
onChange == null ? void 0 : onChange({
|
|
259
|
+
pagination: pagination === false ? void 0 : { current, pageSize },
|
|
260
|
+
sorter: sorters,
|
|
261
|
+
filters: Object.fromEntries(
|
|
262
|
+
emitted.map(({ dataIndex, value }) => [dataIndex, value])
|
|
263
|
+
),
|
|
264
|
+
// Filtered but not yet re-sorted; symmetric with handleSort, whose
|
|
265
|
+
// payload is sorted but not re-paginated.
|
|
266
|
+
currentDataSource: next.data,
|
|
267
|
+
action: "filter"
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
[onFilterInternal, onChange, pagination, current, pageSize, sorters]
|
|
271
|
+
);
|
|
251
272
|
const { expandedRowKeys, onExpand } = (0, import_useExpand.default)(
|
|
252
273
|
expandable,
|
|
253
274
|
allKeys,
|
|
@@ -259,7 +280,6 @@ var Table = import_react.default.forwardRef((baseprops, ref) => {
|
|
|
259
280
|
onCheckAll,
|
|
260
281
|
onChange: onSelectionChange
|
|
261
282
|
} = (0, import_useSelection.default)({ pageData, dataSource, getRowKey, rowSelection, allKeys });
|
|
262
|
-
const prevFilterRecordsRef = (0, import_react.useRef)(filterRecords);
|
|
263
283
|
const [horizontalScroll, setHorizontalScroll] = import_react.default.useState({
|
|
264
284
|
left: false,
|
|
265
285
|
right: false
|
|
@@ -309,29 +329,6 @@ var Table = import_react.default.forwardRef((baseprops, ref) => {
|
|
|
309
329
|
return unchanged ? current2 : nextWidths;
|
|
310
330
|
});
|
|
311
331
|
}, [wrapedColumnsRef]);
|
|
312
|
-
(0, import_react.useEffect)(() => {
|
|
313
|
-
if (prevFilterRecordsRef.current === filterRecords)
|
|
314
|
-
return;
|
|
315
|
-
prevFilterRecordsRef.current = filterRecords;
|
|
316
|
-
if (!onChange)
|
|
317
|
-
return;
|
|
318
|
-
onChange({
|
|
319
|
-
pagination: pagination === false ? void 0 : { current, pageSize },
|
|
320
|
-
sorter: sorters,
|
|
321
|
-
filters,
|
|
322
|
-
currentDataSource: sortedData,
|
|
323
|
-
action: "filter"
|
|
324
|
-
});
|
|
325
|
-
}, [
|
|
326
|
-
filterRecords,
|
|
327
|
-
filters,
|
|
328
|
-
sortedData,
|
|
329
|
-
pagination,
|
|
330
|
-
current,
|
|
331
|
-
pageSize,
|
|
332
|
-
sorters,
|
|
333
|
-
onChange
|
|
334
|
-
]);
|
|
335
332
|
(0, import_react.useEffect)(() => {
|
|
336
333
|
const content = contentRef.current;
|
|
337
334
|
const tableElement = tableRef.current;
|
|
@@ -387,7 +384,7 @@ var Table = import_react.default.forwardRef((baseprops, ref) => {
|
|
|
387
384
|
sorters,
|
|
388
385
|
onSort: handleSort,
|
|
389
386
|
onCheckAll,
|
|
390
|
-
onInternalFilter:
|
|
387
|
+
onInternalFilter: handleFilter,
|
|
391
388
|
resizingKey,
|
|
392
389
|
onResizeStart,
|
|
393
390
|
onResizeStep
|
|
@@ -84,7 +84,6 @@ var HeadCell = (props) => {
|
|
|
84
84
|
classNames,
|
|
85
85
|
showSorterTooltip = true,
|
|
86
86
|
tableActionBarShowOnHover,
|
|
87
|
-
internalFilters,
|
|
88
87
|
style,
|
|
89
88
|
width,
|
|
90
89
|
colSpan,
|
|
@@ -112,7 +111,6 @@ var HeadCell = (props) => {
|
|
|
112
111
|
"classNames",
|
|
113
112
|
"showSorterTooltip",
|
|
114
113
|
"tableActionBarShowOnHover",
|
|
115
|
-
"internalFilters",
|
|
116
114
|
"style",
|
|
117
115
|
"width",
|
|
118
116
|
"colSpan",
|
|
@@ -190,7 +188,6 @@ var HeadCell = (props) => {
|
|
|
190
188
|
__spreadProps(__spreadValues({}, rest), {
|
|
191
189
|
filter,
|
|
192
190
|
column: props,
|
|
193
|
-
internalFilters,
|
|
194
191
|
onInternalFilter,
|
|
195
192
|
dataIndex
|
|
196
193
|
})
|
|
@@ -56,6 +56,7 @@ var areFilterValuesEqual = (a, b) => {
|
|
|
56
56
|
};
|
|
57
57
|
var hasFilterValue = (value) => Array.isArray(value) ? value.length > 0 : value !== "";
|
|
58
58
|
var HeaderFilter = import_react.default.memo((props) => {
|
|
59
|
+
var _a;
|
|
59
60
|
const { filter, column, getPopupContainer, onInternalFilter } = props;
|
|
60
61
|
const { prefixCls } = (0, import_react.useContext)(import_table.TableCtx);
|
|
61
62
|
const { locale } = (0, import_locale.useLocale)();
|
|
@@ -77,12 +78,28 @@ var HeaderFilter = import_react.default.memo((props) => {
|
|
|
77
78
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
78
79
|
const [selectNodes, setSelectNodes] = (0, import_react.useState)([]);
|
|
79
80
|
const [searchValue, setSearchValue] = (0, import_react.useState)("");
|
|
81
|
+
const controlled = filter.filteredValue !== void 0;
|
|
82
|
+
(0, import_react.useEffect)(() => {
|
|
83
|
+
if (!controlled || open)
|
|
84
|
+
return;
|
|
85
|
+
const value = filter.filteredValue;
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
setSelectNodes([...value]);
|
|
88
|
+
setSearchValue("");
|
|
89
|
+
} else {
|
|
90
|
+
setSearchValue(String(value));
|
|
91
|
+
setSelectNodes([]);
|
|
92
|
+
}
|
|
93
|
+
const committed = Array.isArray(value) ? [...value] : value;
|
|
94
|
+
committedValueRef.current = committed;
|
|
95
|
+
setCommittedValue(committed);
|
|
96
|
+
}, [controlled, filter.filteredValue, open]);
|
|
80
97
|
(0, import_react.useEffect)(() => {
|
|
81
98
|
if (!open)
|
|
82
99
|
return;
|
|
83
100
|
const raf = requestAnimationFrame(() => {
|
|
84
|
-
var
|
|
85
|
-
(
|
|
101
|
+
var _a2;
|
|
102
|
+
(_a2 = inputRef.current) == null ? void 0 : _a2.focus({ preventScroll: true });
|
|
86
103
|
});
|
|
87
104
|
return () => cancelAnimationFrame(raf);
|
|
88
105
|
}, [open]);
|
|
@@ -139,8 +156,8 @@ var HeaderFilter = import_react.default.memo((props) => {
|
|
|
139
156
|
const inputValue = getStrLower(searchValue);
|
|
140
157
|
const filteredItems = inputValue ? items.filter(
|
|
141
158
|
(item) => {
|
|
142
|
-
var
|
|
143
|
-
return (
|
|
159
|
+
var _a2;
|
|
160
|
+
return (_a2 = getStrLower(item.label)) == null ? void 0 : _a2.includes(getStrLower(searchValue));
|
|
144
161
|
}
|
|
145
162
|
) : items;
|
|
146
163
|
if (filterMode === "menu") {
|
|
@@ -186,7 +203,7 @@ var HeaderFilter = import_react.default.memo((props) => {
|
|
|
186
203
|
}
|
|
187
204
|
setOpen(nextOpen);
|
|
188
205
|
};
|
|
189
|
-
const isFiltered = filtered != null ? filtered : hasFilterValue(committedValue);
|
|
206
|
+
const isFiltered = filtered != null ? filtered : controlled ? hasFilterValue((_a = filter.filteredValue) != null ? _a : "") : hasFilterValue(committedValue);
|
|
190
207
|
const renderTrigger = () => {
|
|
191
208
|
const trigger = typeof icon === "function" ? icon(isFiltered) : /* @__PURE__ */ import_react.default.createElement(
|
|
192
209
|
import_Button.default,
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
import { Button, message, Space, Table } from "../..";
|
|
8
|
+
import React, { useState } from 'react';
|
|
9
|
+
var allData = [{
|
|
10
|
+
key: '1',
|
|
11
|
+
name: 'John Brown',
|
|
12
|
+
age: 32,
|
|
13
|
+
gender: 'male'
|
|
14
|
+
}, {
|
|
15
|
+
key: '2',
|
|
16
|
+
name: 'Jim Green',
|
|
17
|
+
age: 42,
|
|
18
|
+
gender: 'male'
|
|
19
|
+
}, {
|
|
20
|
+
key: '3',
|
|
21
|
+
name: 'Joe Black',
|
|
22
|
+
age: 32,
|
|
23
|
+
gender: 'male'
|
|
24
|
+
}, {
|
|
25
|
+
key: '4',
|
|
26
|
+
name: 'Jon Snow',
|
|
27
|
+
age: 42,
|
|
28
|
+
gender: 'female'
|
|
29
|
+
}, {
|
|
30
|
+
key: '5',
|
|
31
|
+
name: 'Arya Stark',
|
|
32
|
+
age: 16,
|
|
33
|
+
gender: 'female'
|
|
34
|
+
}];
|
|
35
|
+
export default (function () {
|
|
36
|
+
var _message$useMessage = message.useMessage(),
|
|
37
|
+
messageApi = _message$useMessage.messageApi,
|
|
38
|
+
messageHolder = _message$useMessage.messageHolder;
|
|
39
|
+
|
|
40
|
+
// Server-side search: keep the keyword controlled, refetch in onChange.
|
|
41
|
+
var _useState = useState(''),
|
|
42
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
43
|
+
nameKeyword = _useState2[0],
|
|
44
|
+
setNameKeyword = _useState2[1];
|
|
45
|
+
|
|
46
|
+
// Controlled local filter: the tree selection lives in the parent state.
|
|
47
|
+
var _useState3 = useState([]),
|
|
48
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
49
|
+
genders = _useState4[0],
|
|
50
|
+
setGenders = _useState4[1];
|
|
51
|
+
var columns = [{
|
|
52
|
+
title: 'Name',
|
|
53
|
+
dataIndex: 'name',
|
|
54
|
+
key: 'name',
|
|
55
|
+
filter: {
|
|
56
|
+
searchable: true,
|
|
57
|
+
// No onFilter: no local matching, the search hits the "server".
|
|
58
|
+
filteredValue: nameKeyword
|
|
59
|
+
}
|
|
60
|
+
}, {
|
|
61
|
+
title: 'Age',
|
|
62
|
+
dataIndex: 'age',
|
|
63
|
+
key: 'age'
|
|
64
|
+
}, {
|
|
65
|
+
title: 'Gender',
|
|
66
|
+
dataIndex: 'gender',
|
|
67
|
+
key: 'gender',
|
|
68
|
+
filter: {
|
|
69
|
+
filterMode: 'tree',
|
|
70
|
+
items: [{
|
|
71
|
+
label: 'Male',
|
|
72
|
+
key: 'male'
|
|
73
|
+
}, {
|
|
74
|
+
label: 'Female',
|
|
75
|
+
key: 'female'
|
|
76
|
+
}],
|
|
77
|
+
filteredValue: genders,
|
|
78
|
+
onFilter: function onFilter(value, record) {
|
|
79
|
+
return value === record.gender;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}];
|
|
83
|
+
var handleChange = function handleChange(info) {
|
|
84
|
+
var _info$filters, _filters$name, _filters$gender;
|
|
85
|
+
if (info.action !== 'filter') return;
|
|
86
|
+
var filters = (_info$filters = info.filters) !== null && _info$filters !== void 0 ? _info$filters : {};
|
|
87
|
+
|
|
88
|
+
// The committing column's key is always present in the payload — with its
|
|
89
|
+
// empty value on clear — so both setting and clearing are mirrored here.
|
|
90
|
+
var name = (_filters$name = filters.name) !== null && _filters$name !== void 0 ? _filters$name : '';
|
|
91
|
+
if (name !== nameKeyword) {
|
|
92
|
+
// Pretend to refetch with ?name=<keyword>.
|
|
93
|
+
messageApi.info("Fetch: /api/users?name=".concat(name));
|
|
94
|
+
setNameKeyword(name);
|
|
95
|
+
}
|
|
96
|
+
setGenders((_filters$gender = filters.gender) !== null && _filters$gender !== void 0 ? _filters$gender : []);
|
|
97
|
+
};
|
|
98
|
+
var data = allData.filter(function (item) {
|
|
99
|
+
var matchName = nameKeyword ? item.name.toLowerCase().includes(nameKeyword.toLowerCase()) : true;
|
|
100
|
+
var matchGender = genders.length ? genders.includes(item.gender) : true;
|
|
101
|
+
return matchName && matchGender;
|
|
102
|
+
});
|
|
103
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, messageHolder, /*#__PURE__*/React.createElement(Space, {
|
|
104
|
+
block: true,
|
|
105
|
+
style: {
|
|
106
|
+
marginBottom: 16
|
|
107
|
+
}
|
|
108
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
109
|
+
onClick: function onClick() {
|
|
110
|
+
return setNameKeyword('');
|
|
111
|
+
}
|
|
112
|
+
}, "Reset name search"), /*#__PURE__*/React.createElement(Button, {
|
|
113
|
+
onClick: function onClick() {
|
|
114
|
+
return setGenders([]);
|
|
115
|
+
}
|
|
116
|
+
}, "Reset gender filter")), /*#__PURE__*/React.createElement(Table, {
|
|
117
|
+
columns: columns,
|
|
118
|
+
dataSource: data,
|
|
119
|
+
onChange: handleChange,
|
|
120
|
+
pagination: false
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
@@ -8,12 +8,16 @@ type FilterRecord = {
|
|
|
8
8
|
value: FilterInput;
|
|
9
9
|
dataIndex: string;
|
|
10
10
|
};
|
|
11
|
+
export declare const isControlledFilter: (column?: ColumnProps) => boolean;
|
|
11
12
|
export default function useFilter({ data, columns, }: {
|
|
12
13
|
data: Array<Record<string, unknown>>;
|
|
13
14
|
columns: ColumnProps[];
|
|
14
15
|
}): {
|
|
15
16
|
data: Record<string, unknown>[];
|
|
16
17
|
filterRecords: FilterRecord[];
|
|
17
|
-
onFilter: ({ value, dataIndex }: FilterOptions) =>
|
|
18
|
+
onFilter: ({ value, dataIndex }: FilterOptions) => {
|
|
19
|
+
data: Record<string, unknown>[];
|
|
20
|
+
filterRecords: FilterRecord[];
|
|
21
|
+
};
|
|
18
22
|
};
|
|
19
23
|
export {};
|