Skip to content

Commit cca4c62

Browse files
authored
type: revert SafeKey and upgrade rc-tree (#586)
1 parent cfc4a11 commit cca4c62

14 files changed

+99
-183
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"@babel/runtime": "^7.25.7",
4848
"classnames": "2.x",
4949
"rc-select": "~14.15.2",
50-
"rc-tree": "~5.10.0",
50+
"rc-tree": "~5.10.1",
5151
"rc-util": "^5.43.0"
5252
},
5353
"devDependencies": {

src/LegacyContext.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
import * as React from 'react';
22
import type { DataEntity, IconType } from 'rc-tree/lib/interface';
3-
import type { LegacyDataNode, SafeKey } from './interface';
3+
import type { LegacyDataNode, SafeKey, Key } from './interface';
44

55
interface LegacyContextProps {
66
checkable: boolean | React.ReactNode;
7-
checkedKeys: SafeKey[];
8-
halfCheckedKeys: SafeKey[];
9-
treeExpandedKeys: SafeKey[];
10-
treeDefaultExpandedKeys: SafeKey[];
11-
onTreeExpand: (keys: SafeKey[]) => void;
7+
checkedKeys: Key[];
8+
halfCheckedKeys: Key[];
9+
treeExpandedKeys: Key[];
10+
treeDefaultExpandedKeys: Key[];
11+
onTreeExpand: (keys: Key[]) => void;
1212
treeDefaultExpandAll: boolean;
1313
treeIcon: IconType;
1414
showTreeIcon: boolean;
1515
switcherIcon: IconType;
1616
treeLine: boolean;
1717
treeNodeFilterProp: string;
18-
treeLoadedKeys: SafeKey[];
18+
treeLoadedKeys: Key[];
1919
treeMotion: any;
2020
loadData: (treeNode: LegacyDataNode) => Promise<unknown>;
21-
onTreeLoad: (loadedKeys: SafeKey[]) => void;
21+
onTreeLoad: (loadedKeys: Key[]) => void;
2222

2323
keyEntities: Record<SafeKey, DataEntity<any>>;
2424
}

src/OptionList.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import useMemo from 'rc-util/lib/hooks/useMemo';
88
import * as React from 'react';
99
import LegacyContext from './LegacyContext';
1010
import TreeSelectContext from './TreeSelectContext';
11-
import type { SafeKey, TreeDataNode } from './interface';
11+
import type { Key, SafeKey } from './interface';
1212
import { getAllKeys, isCheckDisabled } from './utils/valueUtil';
1313

1414
const HIDDEN_STYLE = {
@@ -23,7 +23,7 @@ const HIDDEN_STYLE = {
2323
};
2424

2525
interface TreeEventInfo {
26-
node: { key: SafeKey };
26+
node: { key: Key };
2727
selected?: boolean;
2828
checked?: boolean;
2929
}
@@ -77,8 +77,8 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
7777
);
7878

7979
// ========================== Active ==========================
80-
const [activeKey, setActiveKey] = React.useState<SafeKey>(null);
81-
const activeEntity = keyEntities[activeKey];
80+
const [activeKey, setActiveKey] = React.useState<Key>(null);
81+
const activeEntity = keyEntities[activeKey as SafeKey];
8282

8383
// ========================== Values ==========================
8484
const mergedCheckedKeys = React.useMemo(() => {
@@ -112,8 +112,8 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
112112
};
113113

114114
// =========================== Keys ===========================
115-
const [expandedKeys, setExpandedKeys] = React.useState<SafeKey[]>(treeDefaultExpandedKeys);
116-
const [searchExpandedKeys, setSearchExpandedKeys] = React.useState<SafeKey[]>(null);
115+
const [expandedKeys, setExpandedKeys] = React.useState<Key[]>(treeDefaultExpandedKeys);
116+
const [searchExpandedKeys, setSearchExpandedKeys] = React.useState<Key[]>(null);
117117

118118
const mergedExpandedKeys = React.useMemo(() => {
119119
if (treeExpandedKeys) {
@@ -129,7 +129,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
129129
// eslint-disable-next-line react-hooks/exhaustive-deps
130130
}, [searchValue]);
131131

132-
const onInternalExpand = (keys: SafeKey[]) => {
132+
const onInternalExpand = (keys: Key[]) => {
133133
setExpandedKeys(keys);
134134
setSearchExpandedKeys(keys);
135135

@@ -143,7 +143,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
143143
event.preventDefault();
144144
};
145145

146-
const onInternalSelect = (__: SafeKey[], info: TreeEventInfo) => {
146+
const onInternalSelect = (__: Key[], info: TreeEventInfo) => {
147147
const { node } = info;
148148

149149
if (checkable && isCheckDisabled(node)) {
@@ -227,7 +227,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
227227
ref={treeRef}
228228
focusable={false}
229229
prefixCls={`${prefixCls}-tree`}
230-
treeData={memoTreeData as TreeDataNode[]}
230+
treeData={memoTreeData}
231231
height={listHeight}
232232
itemHeight={listItemHeight}
233233
itemScrollOffset={listItemScrollOffset}

src/TreeNode.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* istanbul ignore file */
22
import type * as React from 'react';
3-
import type { DataNode, SafeKey } from './interface';
3+
import type { DataNode, Key } from './interface';
44

55
export interface TreeNodeProps extends Omit<DataNode, 'children'> {
6-
value: SafeKey;
6+
value: Key;
77
children?: React.ReactNode;
88
}
99

src/TreeSelect.tsx

+37-95
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import type {
2-
BaseSelectProps,
3-
BaseSelectPropsWithoutPrivate,
4-
BaseSelectRef,
5-
SelectProps,
6-
} from 'rc-select';
1+
import type { BaseSelectPropsWithoutPrivate, BaseSelectRef } from 'rc-select';
72
import { BaseSelect } from 'rc-select';
83
import useId from 'rc-select/lib/hooks/useId';
94
import type { IconType } from 'rc-tree/lib/interface';
@@ -28,72 +23,21 @@ import type { CheckedStrategy } from './utils/strategyUtil';
2823
import { formatStrategyValues, SHOW_ALL, SHOW_CHILD, SHOW_PARENT } from './utils/strategyUtil';
2924
import { fillFieldNames, isNil, toArray } from './utils/valueUtil';
3025
import warningProps from './utils/warningPropsUtil';
31-
import type { LabeledValueType, SafeKey, SelectSource, DefaultValueType } from './interface';
32-
33-
export type OnInternalSelect = (value: SafeKey, info: { selected: boolean }) => void;
34-
35-
/** @deprecated This is only used for legacy compatible. Not works on new code. */
36-
export interface LegacyCheckedNode {
37-
pos: string;
38-
node: React.ReactElement;
39-
children?: LegacyCheckedNode[];
40-
}
41-
42-
export interface ChangeEventExtra {
43-
/** @deprecated Please save prev value by control logic instead */
44-
preValue: LabeledValueType[];
45-
triggerValue: SafeKey;
46-
/** @deprecated Use `onSelect` or `onDeselect` instead. */
47-
selected?: boolean;
48-
/** @deprecated Use `onSelect` or `onDeselect` instead. */
49-
checked?: boolean;
50-
51-
// Not sure if exist user still use this. We have to keep but not recommend user to use
52-
/** @deprecated This prop not work as react node anymore. */
53-
triggerNode: React.ReactElement;
54-
/** @deprecated This prop not work as react node anymore. */
55-
allCheckedNodes: LegacyCheckedNode[];
56-
}
57-
58-
export interface FieldNames {
59-
value?: string;
60-
label?: string;
61-
children?: string;
62-
}
63-
64-
export interface InternalFieldName extends Omit<FieldNames, 'label'> {
65-
_title: string[];
66-
}
67-
68-
export interface SimpleModeConfig {
69-
id?: SafeKey;
70-
pId?: SafeKey;
71-
rootPId?: SafeKey;
72-
}
73-
74-
export interface BaseOptionType {
75-
disabled?: boolean;
76-
checkable?: boolean;
77-
disableCheckbox?: boolean;
78-
children?: BaseOptionType[];
79-
[name: string]: any;
80-
}
81-
82-
export interface DefaultOptionType extends BaseOptionType {
83-
value?: SafeKey;
84-
title?: React.ReactNode | ((data: DefaultOptionType) => React.ReactNode);
85-
label?: React.ReactNode;
86-
key?: SafeKey;
87-
children?: DefaultOptionType[];
88-
}
89-
90-
export interface LegacyDataNode extends DefaultOptionType {
91-
props: any;
92-
}
93-
export interface TreeSelectProps<
94-
ValueType = any,
95-
OptionType extends BaseOptionType = DefaultOptionType,
96-
> extends Omit<BaseSelectPropsWithoutPrivate, 'mode'> {
26+
import type {
27+
LabeledValueType,
28+
SafeKey,
29+
Key,
30+
DataNode,
31+
SimpleModeConfig,
32+
ChangeEventExtra,
33+
SelectSource,
34+
DefaultValueType,
35+
FieldNames,
36+
LegacyDataNode,
37+
} from './interface';
38+
39+
export interface TreeSelectProps<ValueType = any, OptionType extends DataNode = DataNode>
40+
extends Omit<BaseSelectPropsWithoutPrivate, 'mode'> {
9741
prefixCls?: string;
9842
id?: string;
9943
children?: React.ReactNode;
@@ -109,12 +53,12 @@ export interface TreeSelectProps<
10953
inputValue?: string;
11054
onSearch?: (value: string) => void;
11155
autoClearSearchValue?: boolean;
112-
filterTreeNode?: boolean | ((inputValue: string, treeNode: DefaultOptionType) => boolean);
56+
filterTreeNode?: boolean | ((inputValue: string, treeNode: DataNode) => boolean);
11357
treeNodeFilterProp?: string;
11458

11559
// >>> Select
116-
onSelect?: SelectProps<ValueType, OptionType>['onSelect'];
117-
onDeselect?: SelectProps<ValueType, OptionType>['onDeselect'];
60+
onSelect?: (value: ValueType, option: OptionType) => void;
61+
onDeselect?: (value: ValueType, option: OptionType) => void;
11862

11963
// >>> Selector
12064
showCheckedStrategy?: CheckedStrategy;
@@ -255,7 +199,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
255199
}
256200

257201
// ========================= FieldNames =========================
258-
const mergedFieldNames: InternalFieldName = React.useMemo(
202+
const mergedFieldNames: FieldNames = React.useMemo(
259203
() => fillFieldNames(fieldNames),
260204
/* eslint-disable react-hooks/exhaustive-deps */
261205
[JSON.stringify(fieldNames)],
@@ -268,7 +212,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
268212
postState: search => search || '',
269213
});
270214

271-
const onInternalSearch: BaseSelectProps['onSearch'] = searchText => {
215+
const onInternalSearch = searchText => {
272216
setSearchValue(searchText);
273217
onSearch?.(searchText);
274218
};
@@ -310,7 +254,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
310254

311255
// =========================== Label ============================
312256
const getLabel = React.useCallback(
313-
(item: DefaultOptionType) => {
257+
(item: DataNode) => {
314258
if (item) {
315259
if (treeNodeLabelProp) {
316260
return item[treeNodeLabelProp];
@@ -418,7 +362,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
418362
const displayValues = React.useMemo(() => {
419363
// Collect keys which need to show
420364
const displayKeys = formatStrategyValues(
421-
rawCheckedValues,
365+
rawCheckedValues as SafeKey[],
422366
mergedShowCheckedStrategy,
423367
keyEntities,
424368
mergedFieldNames,
@@ -574,7 +518,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
574518
const keyList = existRawValues.map(val => valueEntities.get(val).key);
575519

576520
// Conduction by selected or not
577-
let checkedKeys: SafeKey[];
521+
let checkedKeys: Key[];
578522
if (selected) {
579523
({ checkedKeys } = conductCheck(keyList, true, keyEntities));
580524
} else {
@@ -588,7 +532,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
588532
// Fill back of keys
589533
newRawValues = [
590534
...missingRawValues,
591-
...checkedKeys.map(key => keyEntities[key].node[mergedFieldNames.value]),
535+
...checkedKeys.map(key => keyEntities[key as SafeKey].node[mergedFieldNames.value]),
592536
];
593537
}
594538
triggerChange(newRawValues, { selected, triggerValue: selectedValue }, source || 'option');
@@ -637,21 +581,19 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
637581
);
638582

639583
// ====================== Display Change ========================
640-
const onDisplayValuesChange = useRefFunc<BaseSelectProps['onDisplayValuesChange']>(
641-
(newValues, info) => {
642-
const newRawValues = newValues.map(item => item.value);
584+
const onDisplayValuesChange = useRefFunc((newValues, info) => {
585+
const newRawValues = newValues.map(item => item.value);
643586

644-
if (info.type === 'clear') {
645-
triggerChange(newRawValues, {}, 'selection');
646-
return;
647-
}
587+
if (info.type === 'clear') {
588+
triggerChange(newRawValues, {}, 'selection');
589+
return;
590+
}
648591

649-
// TreeSelect only have multiple mode which means display change only has remove
650-
if (info.values.length) {
651-
onOptionSelect(info.values[0].value, { selected: false, source: 'selection' });
652-
}
653-
},
654-
);
592+
// TreeSelect only have multiple mode which means display change only has remove
593+
if (info.values.length) {
594+
onOptionSelect(info.values[0].value, { selected: false, source: 'selection' });
595+
}
596+
});
655597

656598
// ========================== Context ===========================
657599
const treeSelectContext = React.useMemo<TreeSelectContextProps>(
@@ -760,7 +702,7 @@ if (process.env.NODE_ENV !== 'production') {
760702

761703
const GenericTreeSelect = TreeSelect as unknown as (<
762704
ValueType = any,
763-
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType,
705+
OptionType extends DataNode = DataNode,
764706
>(
765707
props: React.PropsWithChildren<TreeSelectProps<ValueType, OptionType>> & {
766708
ref?: React.Ref<BaseSelectRef>;

src/TreeSelectContext.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import * as React from 'react';
22
import type { ExpandAction } from 'rc-tree/lib/Tree';
3-
import type { DefaultOptionType, InternalFieldName, OnInternalSelect } from './TreeSelect';
3+
import type { DataNode, FieldNames, Key } from './interface';
44

55
export interface TreeSelectContextProps {
66
virtual?: boolean;
77
dropdownMatchSelectWidth?: boolean | number;
88
listHeight: number;
99
listItemHeight: number;
1010
listItemScrollOffset?: number;
11-
treeData: DefaultOptionType[];
12-
fieldNames: InternalFieldName;
13-
onSelect: OnInternalSelect;
11+
treeData: DataNode[];
12+
fieldNames: FieldNames;
13+
onSelect: (value: Key, info: { selected: boolean }) => void;
1414
treeExpandAction?: ExpandAction;
1515
treeTitleRender?: (node: any) => React.ReactNode;
1616
onPopupScroll?: React.UIEventHandler<HTMLDivElement>;

src/hooks/useCheckedKeys.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import type { DataEntity } from 'rc-tree/lib/interface';
33
import { conductCheck } from 'rc-tree/lib/utils/conductUtil';
4-
import type { LabeledValueType, SafeKey } from '../interface';
4+
import type { LabeledValueType, SafeKey, Key } from '../interface';
55

66
const useCheckedKeys = (
77
rawLabeledValues: LabeledValueType[],
@@ -10,13 +10,12 @@ const useCheckedKeys = (
1010
keyEntities: Record<SafeKey, DataEntity>,
1111
) => {
1212
return React.useMemo(() => {
13-
const extractValues = (values: LabeledValueType[]): SafeKey[] =>
14-
values.map(({ value }) => value);
13+
const extractValues = (values: LabeledValueType[]): Key[] => values.map(({ value }) => value);
1514

1615
const checkedKeys = extractValues(rawLabeledValues);
1716
const halfCheckedKeys = extractValues(rawHalfCheckedValues);
1817

19-
const missingValues = checkedKeys.filter(key => !keyEntities[key]);
18+
const missingValues = checkedKeys.filter(key => !keyEntities[key as SafeKey]);
2019

2120
let finalCheckedKeys = checkedKeys;
2221
let finalHalfCheckedKeys = halfCheckedKeys;

src/hooks/useDataEntities.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import * as React from 'react';
22
import { convertDataToEntities } from 'rc-tree/lib/utils/treeUtil';
33
import type { DataEntity } from 'rc-tree/lib/interface';
4-
import type { FieldNames } from '../TreeSelect';
5-
import type { SafeKey } from '../interface';
4+
import type { SafeKey, FieldNames } from '../interface';
65
import warning from 'rc-util/lib/warning';
76
import { isNil } from '../utils/valueUtil';
87

0 commit comments

Comments
 (0)