-
-
Notifications
You must be signed in to change notification settings - Fork 466
feat: add activeOptionFilter prop and update combobox examples #1156
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -60,6 +60,7 @@ const OptionList: React.ForwardRefRenderFunction<RefOptionListProps, {}> = (_, r | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
listHeight, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
listItemHeight, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
optionRender, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
activeOptionFilter, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
classNames: contextClassNames, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
styles: contextStyles, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} = React.useContext(SelectContext); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -159,9 +160,12 @@ const OptionList: React.ForwardRefRenderFunction<RefOptionListProps, {}> = (_, r | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!multiple && open && rawValues.size === 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const value: RawValueType = Array.from(rawValues)[0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Scroll to the option closest to the searchValue if searching. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const index = memoFlattenOptions.findIndex(({ data }) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
searchValue ? String(data.value).startsWith(searchValue) : data.value === value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const index = memoFlattenOptions.findIndex(({ data }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (activeOptionFilter) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return activeOptionFilter(searchValue, data); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return searchValue ? String(data.value).startsWith(searchValue) : data.value === value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
160
to
169
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 主动过滤逻辑对分组项存在空指针风险
建议在回调里先排除分组节点或缺少 - const index = memoFlattenOptions.findIndex(({ data }) => {
- if (activeOptionFilter) {
- return activeOptionFilter(searchValue, data);
- }
- return searchValue ? String(data.value).startsWith(searchValue) : data.value === value;
- });
+ const index = memoFlattenOptions.findIndex(({ group, data }) => {
+ // 忽略分组标题或异常节点
+ if (group || !data) {
+ return false;
+ }
+
+ if (activeOptionFilter) {
+ return activeOptionFilter(searchValue, data);
+ }
+ return searchValue
+ ? String(data.value).startsWith(searchValue)
+ : data.value === value;
+ }); 这样可以避免空指针,同时保持逻辑的一致性。 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (index !== -1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setActive(index); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -117,6 +117,53 @@ describe('Select.Combobox', () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(container.querySelector('input').value).toEqual('1'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
it('activeOptionFilter should work', async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { container } = render( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Select | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mode="combobox" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
showSearch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
activeOptionFilter={(searchValue, option) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return String(option.value).includes(searchValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="apple">apple</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="banana">banana</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="orange">orange</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</Select>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+120
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 建议使用
- fireEvent.change(input, { target: { value: 'an' } });
- await delay();
+ fireEvent.change(input, { target: { value: 'an' } });
+ await waitFor(() =>
+ expect(
+ container.querySelector('.rc-select-item-option-active .rc-select-item-option-content'),
+ ).toHaveTextContent('banana'),
+ ); 同理可删除自定义 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const input = container.querySelector('input')!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fireEvent.change(input, { target: { value: 'an' } }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await delay(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
container.querySelector('.rc-select-item-option-active .rc-select-item-option-content'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
).toHaveTextContent('banana'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fireEvent.change(input, { target: { value: 'ora' } }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await delay(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
container.querySelector('.rc-select-item-option-active .rc-select-item-option-content'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
).toHaveTextContent('orange'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
it('activeOptionFilter with empty function should not activate any option', async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { container } = render( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Select mode="combobox" showSearch activeOptionFilter={() => false}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="apple">apple</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="banana">banana</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Option value="orange">orange</Option> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</Select>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const input = container.querySelector('input')!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fireEvent.change(input, { target: { value: 'an' } }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await delay(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expect(container.querySelector('.rc-select-item-option-active')).toBeNull(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
describe('input value', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const createSelect = (props?: Partial<SelectProps>) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Select mode="combobox" {...props}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
感觉有点怪异,如果是
value
被选中了,展开不应该是用当前这个逻辑。否则会导致选中的是一个,展开激活的却是另一个。它应该是 default active 的逻辑