Skip to content

Commit

Permalink
type: fix type errors of React.Key (ant-design#45018)
Browse files Browse the repository at this point in the history
* Update index.zh-CN.md

Signed-off-by: 红 <[email protected]>

* Revert "Update index.zh-CN.md"

This reverts commit cfcce5d.

* docs: format

ref: https://github.com/ant-design/ant-design/pull/37144/files#diff-0bdf37a1fc0ec124fb3aa391932eaa134bd1de8c6f766f5e4082edbc30ce6c42

* chore: update snapshots

* type: fix type errors of React.Key

ref: ant-design#44938

Co-authored-by: afc163 <[email protected]>

* test: fix test logic

(cherry picked from commit 6a349f6)

* deps: bump [email protected]

ref: ant-design#45018 (comment)

* type: fix FormItem Key

* chore: fix lint

* chore: fix lint

---------

Signed-off-by: 红 <[email protected]>
Co-authored-by: afc163 <[email protected]>
Co-authored-by: 二货机器人 <[email protected]>
  • Loading branch information
3 people authored Sep 27, 2023
1 parent 5f82d5b commit 775b119
Show file tree
Hide file tree
Showing 14 changed files with 55 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42717,6 +42717,7 @@ exports[`ConfigProvider components Upload configProvider componentDisabled 1`] =
>
<input
accept=""
disabled=""
style="display: none;"
type="file"
/>
Expand Down
4 changes: 2 additions & 2 deletions components/form/FormItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FormInstance } from 'rc-field-form';
import { Field, FieldContext, ListContext } from 'rc-field-form';
import type { FieldProps } from 'rc-field-form/lib/Field';
import type { Meta, NamePath } from 'rc-field-form/lib/interface';
import type { Meta, NamePath, InternalNamePath } from 'rc-field-form/lib/interface';
import useState from 'rc-util/lib/hooks/useState';
import { supportRef } from 'rc-util/lib/ref';
import * as React from 'react';
Expand Down Expand Up @@ -120,7 +120,7 @@ function InternalFormItem<Values = any>(props: FormItemProps<Values>): React.Rea
// ========================= MISC =========================
// Get `noStyle` required info
const listContext = React.useContext(ListContext);
const fieldKeyPathRef = React.useRef<React.Key[]>();
const fieldKeyPathRef = React.useRef<InternalNamePath>();

// ======================== Errors ========================
// >>>>> Collect sub field errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5071,6 +5071,7 @@ Array [
>
<input
accept=""
disabled=""
style="display:none"
type="file"
/>
Expand Down
1 change: 1 addition & 0 deletions components/form/__tests__/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2554,6 +2554,7 @@ Array [
>
<input
accept=""
disabled=""
style="display:none"
type="file"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ exports[`Form form should support disabled 1`] = `
>
<input
accept=""
disabled=""
style="display: none;"
type="file"
/>
Expand Down
9 changes: 5 additions & 4 deletions components/form/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1558,20 +1558,21 @@ describe('Form', () => {
const App2 = () => <Form disabled>{renderComps()}</Form>;

const wrapper2 = render(<App2 />);
// 时间范围组件中会有两个 input 框,因此虽然上述只有 18 个组件,但,实际有 19 个 带有 disabled 属性的表单组件
expect(wrapper2.container.querySelectorAll('[disabled]').length).toBe(19);
// 时间范围组件中会有两个 input 框,Upload 为叠加
// 因此虽然上述只有 18 个组件,但实际有 20 个 带有 disabled 属性的表单组件
expect(wrapper2.container.querySelectorAll('[disabled]').length).toBe(20);

const App3 = () => <Form disabled>{renderComps(true)}</Form>;

const wrapper3 = render(<App3 />);

expect(wrapper3.container.querySelectorAll('[disabled]').length).toBe(19);
expect(wrapper3.container.querySelectorAll('[disabled]').length).toBe(20);

const App4 = () => <Form>{renderComps(true)}</Form>;

const wrapper4 = render(<App4 />);

expect(wrapper4.container.querySelectorAll('[disabled]').length).toBe(19);
expect(wrapper4.container.querySelectorAll('[disabled]').length).toBe(20);

const App5 = () => <Form>{renderComps()}</Form>;

Expand Down
2 changes: 1 addition & 1 deletion components/table/__tests__/Table.filter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ describe('Table.filter', () => {
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm }) => (
<div>
<Input
value={selectedKeys[0]}
value={selectedKeys[0] ? `${selectedKeys[0]}` : undefined}
onChange={e => {
setSelectedKeys(e.target.value ? [e.target.value] : []);
}}
Expand Down
2 changes: 1 addition & 1 deletion components/table/demo/custom-filter-panel.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const App: React.FC = () => {
<Input
ref={searchInput}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
value={`${selectedKeys[0] || ''}`}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => handleSearch(selectedKeys as string[], confirm, dataIndex)}
style={{ marginBottom: 8, display: 'block' }}
Expand Down
41 changes: 24 additions & 17 deletions components/table/hooks/useFilter/FilterDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import useSyncState from '../../../_util/hooks/useSyncState';
import type {
ColumnFilterItem,
ColumnType,
FilterKey,
FilterSearchType,
GetPopupContainer,
Key,
Expand All @@ -29,7 +30,7 @@ import type {
import FilterSearch from './FilterSearch';
import FilterDropdownMenuWrapper from './FilterWrapper';

type FilterTreeDataNode = FieldDataNode<{ title: React.ReactNode; key: React.Key }>;
type FilterTreeDataNode = FieldDataNode<{ title: React.ReactNode; key: string }>;

interface FilterRestProps {
confirm?: Boolean;
Expand Down Expand Up @@ -121,6 +122,10 @@ export interface FilterDropdownProps<RecordType> {
filterResetToDefaultFilteredValue?: boolean;
}

function wrapStringListType(keys?: FilterKey) {
return (keys as string[]) || [];
}

function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
const {
tablePrefixCls,
Expand Down Expand Up @@ -166,28 +171,30 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
}
// ===================== Select Keys =====================
const propFilteredKeys = filterState?.filteredKeys;
const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState(propFilteredKeys || []);
const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState(
wrapStringListType(propFilteredKeys),
);

const onSelectKeys = ({ selectedKeys }: { selectedKeys: Key[] }) => {
const onSelectKeys = ({ selectedKeys }: { selectedKeys: string[] }) => {
setFilteredKeysSync(selectedKeys);
};

const onCheck = (
keys: Key[],
keys: string[],
{ node, checked }: { node: EventDataNode<FilterTreeDataNode>; checked: boolean },
) => {
if (!filterMultiple) {
onSelectKeys({ selectedKeys: checked && node.key ? [node.key] : [] });
} else {
onSelectKeys({ selectedKeys: keys as Key[] });
onSelectKeys({ selectedKeys: keys });
}
};

React.useEffect(() => {
if (!visible) {
return;
}
onSelectKeys({ selectedKeys: propFilteredKeys || [] });
onSelectKeys({ selectedKeys: wrapStringListType(propFilteredKeys) });
}, [propFilteredKeys]);

// ====================== Open Keys ======================
Expand All @@ -210,7 +217,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
}, [visible]);

// ======================= Submit ========================
const internalTriggerFilter = (keys: Key[] | undefined | null) => {
const internalTriggerFilter = (keys: string[] | undefined | null) => {
const mergedKeys = keys && keys.length ? keys : null;
if (mergedKeys === null && (!filterState || !filterState.filteredKeys)) {
return null;
Expand Down Expand Up @@ -245,7 +252,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
setSearchValue('');

if (filterResetToDefaultFilteredValue) {
setFilteredKeysSync((defaultFilteredValue || []).map(key => String(key)));
setFilteredKeysSync((defaultFilteredValue || []).map((key) => String(key)));
} else {
setFilteredKeysSync([]);
}
Expand All @@ -261,7 +268,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
const onVisibleChange = (newVisible: boolean) => {
if (newVisible && propFilteredKeys !== undefined) {
// Sync filteredKeys on appear in controlled mode (propFilteredKeys !== undefiend)
setFilteredKeysSync(propFilteredKeys || []);
setFilteredKeysSync(wrapStringListType(propFilteredKeys));
}

triggerVisible(newVisible);
Expand All @@ -279,7 +286,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {

const onCheckAll = (e: CheckboxChangeEvent) => {
if (e.target.checked) {
const allFilterKeys = flattenKeys(column?.filters).map(key => String(key));
const allFilterKeys = flattenKeys(column?.filters).map((key) => String(key));
setFilteredKeysSync(allFilterKeys);
} else {
setFilteredKeysSync([]);
Expand All @@ -291,7 +298,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
const key = String(filter.value);
const item: FilterTreeDataNode = {
title: filter.text,
key: filter.value !== undefined ? key : index,
key: filter.value !== undefined ? key : String(index),
};
if (filter.children) {
item.children = getTreeData({ filters: filter.children });
Expand All @@ -302,15 +309,15 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
...node,
text: node.title,
value: node.key,
children: node.children?.map(item => getFilterData(item)) || [],
children: node.children?.map((item) => getFilterData(item)) || [],
});

let dropdownContent: React.ReactNode;

if (typeof column.filterDropdown === 'function') {
dropdownContent = column.filterDropdown({
prefixCls: `${dropdownPrefixCls}-custom`,
setSelectedKeys: (selectedKeys: Key[]) => onSelectKeys({ selectedKeys }),
setSelectedKeys: (selectedKeys: string[]) => onSelectKeys({ selectedKeys }),
selectedKeys: getFilteredKeysSync(),
confirm: doFilter,
clearFilters: onReset,
Expand All @@ -323,7 +330,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
} else if (column.filterDropdown) {
dropdownContent = column.filterDropdown;
} else {
const selectedKeys = (getFilteredKeysSync() || []) as any;
const selectedKeys = getFilteredKeysSync() || [];
const getFilterComponent = () => {
if ((column.filters || []).length === 0) {
return (
Expand Down Expand Up @@ -380,7 +387,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
defaultExpandAll
filterTreeNode={
searchValue.trim()
? node => {
? (node) => {
if (typeof filterSearch === 'function') {
return filterSearch(searchValue, getFilterData(node));
}
Expand Down Expand Up @@ -429,7 +436,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
const getResetDisabled = () => {
if (filterResetToDefaultFilteredValue) {
return isEqual(
(defaultFilteredValue || []).map(key => String(key)),
(defaultFilteredValue || []).map((key) => String(key)),
selectedKeys,
);
}
Expand Down Expand Up @@ -491,7 +498,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
className={classNames(`${prefixCls}-trigger`, {
active: filtered,
})}
onClick={e => {
onClick={(e) => {
e.stopPropagation();
}}
>
Expand Down
16 changes: 10 additions & 6 deletions components/table/hooks/useFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
FilterValue,
GetPopupContainer,
Key,
SafeKey,
TableLocale,
TransformColumns,
} from '../../interface';
Expand Down Expand Up @@ -144,14 +145,17 @@ function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[])
const currentFilters: Record<string, FilterValue | null> = {};

filterStates.forEach(({ key, filteredKeys, column }) => {
const keyAsString = key as SafeKey;
const { filters, filterDropdown } = column;
if (filterDropdown) {
currentFilters[key] = filteredKeys || null;
currentFilters[keyAsString] = filteredKeys || null;
} else if (Array.isArray(filteredKeys)) {
const keys = flattenKeys(filters);
currentFilters[key] = keys.filter(originKey => filteredKeys.includes(String(originKey)));
currentFilters[keyAsString] = keys.filter((originKey) =>
filteredKeys.includes(String(originKey)),
);
} else {
currentFilters[key] = null;
currentFilters[keyAsString] = null;
}
});

Expand All @@ -168,10 +172,10 @@ export function getFilterData<RecordType>(
filteredKeys,
} = filterState;
if (onFilter && filteredKeys && filteredKeys.length) {
return currentData.filter(record =>
filteredKeys.some(key => {
return currentData.filter((record) =>
filteredKeys.some((key) => {
const keys = flattenKeys(filters);
const keyIndex = keys.findIndex(k => String(k) === String(key));
const keyIndex = keys.findIndex((k) => String(k) === String(key));
const realKey = keyIndex !== -1 ? keys[keyIndex] : key;
return onFilter(realKey, record);
}),
Expand Down
8 changes: 5 additions & 3 deletions components/table/interface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export { GetRowKey, ExpandableConfig };

export type Key = React.Key;

export type SafeKey = Exclude<Key, bigint>;

export type RowSelectionType = 'checkbox' | 'radio';

export type SelectionItemSelectFn = (currentRowKeys: Key[]) => void;
Expand Down Expand Up @@ -52,7 +54,7 @@ export type CompareFn<T> = (a: T, b: T, sortOrder?: SortOrder) => number;

export interface ColumnFilterItem {
text: React.ReactNode;
value: string | number | boolean;
value: React.Key | boolean;
children?: ColumnFilterItem[];
}

Expand All @@ -71,7 +73,7 @@ export type ColumnTitle<RecordType> =
| ((props: ColumnTitleProps<RecordType>) => React.ReactNode);

export type FilterValue = (Key | boolean)[];
export type FilterKey = Key[] | null;
export type FilterKey = (string | number)[] | null;
export type FilterSearchType<RecordType = Record<string, any>> =
| boolean
| ((input: string, record: RecordType) => boolean);
Expand Down Expand Up @@ -121,7 +123,7 @@ export interface ColumnType<RecordType> extends Omit<RcColumnType<RecordType>, '
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
filterMode?: 'menu' | 'tree';
filterSearch?: FilterSearchType<ColumnFilterItem>;
onFilter?: (value: string | number | boolean, record: RecordType) => boolean;
onFilter?: (value: React.Key | boolean, record: RecordType) => boolean;
/**
* @deprecated `filterDropdownVisible` is deprecated which will be removed in next major version.
* Please use `filterDropdownOpen` instead.
Expand Down
2 changes: 1 addition & 1 deletion components/transfer/demo/tree-transfer.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface TreeTransferProps {
}

// Customize Table Transfer
const isChecked = (selectedKeys: (string | number)[], eventKey: string | number) =>
const isChecked = (selectedKeys: React.Key[], eventKey: React.Key) =>
selectedKeys.includes(eventKey);

const generateTree = (treeNodes: DataNode[] = [], checkedKeys: string[] = []): DataNode[] =>
Expand Down
2 changes: 1 addition & 1 deletion components/tree/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
### Tree props

| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- | --- |
| --- | --- | --- | --- | --- |
| allowDrop | 是否允许拖拽时放置在该节点 | ({ dropNode, dropPosition }) => boolean | - | |
| autoExpandParent | 是否自动展开父节点 | boolean | false | |
| blockNode | 是否节点占据一行 | boolean | false | |
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
"rc-dialog": "~9.0.2",
"rc-drawer": "~6.3.0",
"rc-dropdown": "~4.0.1",
"rc-field-form": "~1.34.2",
"rc-field-form": "~1.38.2",
"rc-image": "~5.13.0",
"rc-input": "~0.1.4",
"rc-input-number": "~7.3.11",
Expand Down

0 comments on commit 775b119

Please sign in to comment.