Skip to content

Commit c77d585

Browse files
committed
feat: adjust maxCount implement logic
1 parent ac9010c commit c77d585

File tree

5 files changed

+53
-36
lines changed

5 files changed

+53
-36
lines changed

examples/mutiple-with-maxCount.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export default () => {
2121
value: '1-2',
2222
title: '1-2',
2323
},
24+
{
25+
key: '1-3',
26+
value: '1-3',
27+
title: '1-3',
28+
},
2429
],
2530
},
2631
{
@@ -58,7 +63,10 @@ export default () => {
5863
style={{ width: 300 }}
5964
multiple
6065
treeCheckable
61-
maxCount={3}
66+
// showCheckedStrategy="SHOW_ALL"
67+
showCheckedStrategy="SHOW_PARENT"
68+
// showCheckedStrategy="SHOW_CHILD"
69+
maxCount={4}
6270
treeData={treeData}
6371
onChange={onChange}
6472
value={value}

src/OptionList.tsx

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as React from 'react';
99
import LegacyContext from './LegacyContext';
1010
import TreeSelectContext from './TreeSelectContext';
1111
import type { Key, SafeKey } from './interface';
12-
import { getAllKeys, isCheckDisabled, isValidCount } from './utils/valueUtil';
12+
import { getAllKeys, isCheckDisabled } from './utils/valueUtil';
1313

1414
const HIDDEN_STYLE = {
1515
width: 0,
@@ -46,6 +46,7 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
4646
treeTitleRender,
4747
onPopupScroll,
4848
maxCount,
49+
displayValues,
4950
} = React.useContext(TreeSelectContext);
5051

5152
const {
@@ -77,24 +78,6 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
7778
(prev, next) => next[0] && prev[1] !== next[1],
7879
);
7980

80-
const isOverMaxCount = React.useMemo<boolean>(
81-
() => multiple && isValidCount(maxCount) && checkedKeys.length >= maxCount,
82-
[checkedKeys, maxCount, multiple],
83-
);
84-
85-
const traverse = (nodes: EventDataNode<any>[]): EventDataNode<any>[] => {
86-
return nodes.map(node => ({
87-
...node,
88-
disabled: isOverMaxCount && !checkedKeys.includes(node.key as SafeKey) ? true : node.disabled,
89-
children: node.children ? traverse(node.children) : undefined,
90-
}));
91-
};
92-
93-
const processedTreeData = React.useMemo(
94-
() => traverse(memoTreeData),
95-
[memoTreeData, isOverMaxCount, checkedKeys],
96-
);
97-
9881
// ========================== Values ==========================
9982
const mergedCheckedKeys = React.useMemo(() => {
10083
if (!checkable) {
@@ -202,13 +185,6 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
202185
const [activeKey, setActiveKey] = React.useState<Key>(null);
203186
const activeEntity = keyEntities[activeKey as SafeKey];
204187

205-
const onActiveChange = (key: Key) => {
206-
if (isOverMaxCount && !checkedKeys.includes(key)) {
207-
return;
208-
}
209-
setActiveKey(key);
210-
};
211-
212188
React.useEffect(() => {
213189
if (!open) {
214190
return;
@@ -274,8 +250,36 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
274250
preSearchValue !== nextSearchValue && !!(nextSearchValue || nextExcludeSearchExpandedKeys),
275251
);
276252

253+
const onActiveChange = (key: Key) => {
254+
if (isOverMaxCount && !displayValues?.some(v => v.value === key)) {
255+
return;
256+
}
257+
setActiveKey(key);
258+
};
259+
260+
const isOverMaxCount = React.useMemo<boolean>(
261+
() => multiple && maxCount !== undefined && displayValues?.length >= maxCount,
262+
[multiple, maxCount, displayValues?.length],
263+
);
264+
265+
const traverse = (nodes: EventDataNode<any>[]): EventDataNode<any>[] => {
266+
return nodes.map(node => ({
267+
...node,
268+
disabled:
269+
isOverMaxCount && !displayValues?.some(v => v.value === node[fieldNames.value])
270+
? true
271+
: node.disabled,
272+
children: node.children ? traverse(node.children) : undefined,
273+
}));
274+
};
275+
276+
const processedTreeData = React.useMemo(
277+
() => traverse(memoTreeData),
278+
[memoTreeData, isOverMaxCount, displayValues, fieldNames],
279+
);
280+
277281
// ========================== Render ==========================
278-
if (memoTreeData.length === 0) {
282+
if (processedTreeData.length === 0) {
279283
return (
280284
<div role="listbox" className={`${prefixCls}-empty`} onMouseDown={onListMouseDown}>
281285
{notFoundContent}

src/TreeSelect.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,16 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
415415
extra: { triggerValue?: SafeKey; selected?: boolean },
416416
source: SelectSource,
417417
) => {
418-
// if treeCheckable and not treeCheckStrictly, check if exceed maxCount
419-
if (treeCheckable && !treeCheckStrictly && maxCount !== undefined) {
420-
const { checkedKeys } = conductCheck(newRawValues, true, keyEntities);
418+
// if multiple and maxCount is set, check if exceed maxCount
419+
if (mergedMultiple && maxCount !== undefined) {
420+
const formattedKeyList = formatStrategyValues(
421+
newRawValues,
422+
mergedShowCheckedStrategy,
423+
keyEntities,
424+
mergedFieldNames,
425+
);
421426

422-
if (checkedKeys.length > maxCount) {
427+
if (formattedKeyList.length > maxCount) {
423428
return;
424429
}
425430
}
@@ -622,6 +627,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
622627
treeTitleRender,
623628
onPopupScroll,
624629
maxCount,
630+
displayValues: cachedDisplayValues,
625631
}),
626632
[
627633
virtual,
@@ -636,6 +642,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
636642
treeTitleRender,
637643
onPopupScroll,
638644
maxCount,
645+
cachedDisplayValues,
639646
],
640647
);
641648

src/TreeSelectContext.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import type { ExpandAction } from 'rc-tree/lib/Tree';
3-
import type { DataNode, FieldNames, Key } from './interface';
3+
import type { DataNode, FieldNames, Key, LabeledValueType } from './interface';
44

55
export interface TreeSelectContextProps {
66
virtual?: boolean;
@@ -15,6 +15,7 @@ export interface TreeSelectContextProps {
1515
treeTitleRender?: (node: any) => React.ReactNode;
1616
onPopupScroll?: React.UIEventHandler<HTMLDivElement>;
1717
maxCount?: number;
18+
displayValues?: LabeledValueType[];
1819
}
1920

2021
const TreeSelectContext = React.createContext<TreeSelectContextProps>(null as any);

src/utils/valueUtil.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,3 @@ export const getAllKeys = (treeData: DataNode[], fieldNames: FieldNames): SafeKe
3535
};
3636

3737
export const isNil = (val: any): boolean => val === null || val === undefined;
38-
39-
export const isValidCount = (value?: number) =>
40-
typeof value !== 'undefined' && !Number.isNaN(value);

0 commit comments

Comments
 (0)