Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Select support maxCount #1015

Merged
merged 19 commits into from
Jan 2, 2024
1 change: 1 addition & 0 deletions docs/examples/auto-tokenization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const Demo: React.FC = () => (
<h2>自动分词</h2>
<Select
mode="tags"
maxCount={3}
style={{ width: '100%' }}
tokenSeparators={[',']}
options={Array.from({ length: 20 }, (_, i) => ({ label: i.toString(), value: i.toString() }))}
Expand Down
13 changes: 12 additions & 1 deletion src/BaseSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import type { RefTriggerProps } from './SelectTrigger';
import SelectTrigger from './SelectTrigger';
import TransBtn from './TransBtn';
import { getSeparatedContent } from './utils/valueUtil';
import SelectContext from './SelectContext';
import type { SelectContextProps } from './SelectContext';

export type {
DisplayInfoType,
Expand Down Expand Up @@ -394,12 +396,21 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
[tokenSeparators],
);

const { maxCount, rawValues } = React.useContext<SelectContextProps>(SelectContext) || {};

const onInternalSearch = (searchText: string, fromTyping: boolean, isCompositing: boolean) => {
if (rawValues?.size >= maxCount) {
return;
}
Comment on lines +402 to +404
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可能会有点怪,不过感觉问题不大,看看用户接受度

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

意思是复制不上去,有点反直觉吗?

let ret = true;
let newSearchText = searchText;
onActiveValueChange?.(null);

const separatedList = getSeparatedContent(searchText, tokenSeparators);
const separatedList = getSeparatedContent(
searchText,
tokenSeparators,
maxCount && maxCount - rawValues.size,
);

// Check if match the `tokenSeparators`
const patchLabels: string[] = isCompositing ? null : separatedList;
Expand Down
8 changes: 6 additions & 2 deletions src/utils/valueUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function injectPropsWithOption<T extends object>(option: T): T {
return newOption;
}

export const getSeparatedContent = (text: string, tokens: string[]): string[] => {
export const getSeparatedContent = (text: string, tokens: string[], end?: number): string[] => {
if (!tokens || !tokens.length) {
return null;
}
Expand All @@ -127,5 +127,9 @@ export const getSeparatedContent = (text: string, tokens: string[]): string[] =>
.filter(Boolean);
};
const list = separate(text, tokens);
return match ? list : null;
if (match) {
return typeof end !== 'undefined' ? list.slice(0, end) : list;
} else {
return null;
}
};
23 changes: 22 additions & 1 deletion tests/Tags.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import { fireEvent, render } from '@testing-library/react';
import KeyCode from 'rc-util/lib/KeyCode';
import classNames from 'classnames';
import * as React from 'react';
Expand Down Expand Up @@ -505,4 +505,25 @@ describe('Select.Tags', () => {
expect(wrapper.find('.rc-select-item-option').length).toBe(1);
expect(errSpy).not.toHaveBeenCalled();
});

it(`paste content to split when count >= maxCount`, () => {
const onChange = jest.fn();
const { container } = render(
<Select
mode="tags"
maxCount={3}
onChange={onChange}
tokenSeparators={[',']}
value={['1', '2', '3']}
/>,
);
const input = container.querySelector<HTMLInputElement>('input');
fireEvent.paste(input, {
clipboardData: { getData: () => 'test' },
});
fireEvent.change(input, {
target: { value: 'test' },
});
expect(onChange).not.toBeCalled();
});
});
Loading