Skip to content

Commit

Permalink
feat: Picker's onOpen & onClose should decouple with onEnter & onExit (
Browse files Browse the repository at this point in the history
…#3228)

* feat(PickerTrigger): add `onOpen` & `onClose`

* feat(Picker): remove onOpen/onClose inside Picker

* fix(Picker): 修复picker重复调用onClose

* fix(Picker): fix datepicker onClose not triggered

* refactor(Picker): bind onOpen/onClose with open state

* test(Picker): add test case for onOpen/onClose with open props

* test(OverlayTrigger): add open control with onOpen/onClose

* test: add tests for the open state of all pickers

* fix: update testPickers.tsx

---------

Co-authored-by: simonguo <simonguo.2009@gmail.com>
  • Loading branch information
MarvelSQ and simonguo committed Mar 27, 2024
1 parent b278b4e commit 09db561
Show file tree
Hide file tree
Showing 21 changed files with 206 additions and 103 deletions.
4 changes: 0 additions & 4 deletions src/Cascader/Cascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ const Cascader = React.forwardRef(<T extends DataItemValue>(props: CascaderProps
onChange,
onSelect,
onSearch,
onClose,
onOpen,
getChildren,
menuClassName: DEPRECATED_menuClassName,
menuStyle: DEPRECATED_menuStyle,
Expand Down Expand Up @@ -322,8 +320,6 @@ const Cascader = React.forwardRef(<T extends DataItemValue>(props: CascaderProps
});

const { active, handleEntered, handleExited } = useActive({
onOpen,
onClose,
onEntered,
onExited,
target,
Expand Down
2 changes: 1 addition & 1 deletion src/Cascader/test/CascaderSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('Cascader', () => {
return screen.getByRole('combobox');
}
});
testPickers(Cascader);
testPickers(Cascader, { ariaHaspopup: 'tree' });
testControlledUnControlled(Cascader, {
componentProps: { data: items, defaultOpen: true },
value: '1',
Expand Down
7 changes: 0 additions & 7 deletions src/CheckPicker/CheckPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ const CheckPicker = React.forwardRef(
onClean,
onChange,
onSelect,
onClose,
onOpen,
...rest
} = props;

Expand Down Expand Up @@ -220,9 +218,6 @@ const CheckPicker = React.forwardRef(
onMenuKeyDown: onFocusItem,
onMenuPressEnter: handleMenuPressEnter,
onMenuPressBackspace: handleClean,
onClose: () => {
setFocusItemValue(null);
},
...rest
});

Expand Down Expand Up @@ -252,14 +247,12 @@ const CheckPicker = React.forwardRef(

const handleEntered = useEventCallback(() => {
setActive(true);
onOpen?.();
});

const handleExited = useEventCallback(() => {
resetSearch();
setFocusItemValue(null);
setActive(false);
onClose?.();
});

const selectedItems =
Expand Down
18 changes: 18 additions & 0 deletions src/CheckPicker/test/CheckPickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,24 @@ describe('CheckPicker', () => {
expect(screen.getAllByRole('checkbox')[2]).to.be.checked;
});

it('Should trigger onOpen & onClose with open props set', () => {
const onOpenSpy = sinon.spy();
const onCloseSpy = sinon.spy();
const { rerender } = render(
<CheckPicker data={data} onOpen={onOpenSpy} onClose={onCloseSpy} open />
);

fireEvent.click(screen.getByRole('combobox'));

expect(onCloseSpy).to.have.been.calledOnce;

rerender(<CheckPicker data={data} onOpen={onOpenSpy} onClose={onCloseSpy} open={false} />);

fireEvent.click(screen.getByRole('combobox'));

expect(onOpenSpy).to.have.been.calledOnce;
});

it('Should render a button by toggleAs={Button}', () => {
render(<CheckPicker open data={data} toggleAs={Button} />);
expect(screen.getByRole('combobox')).to.have.class('rs-btn');
Expand Down
7 changes: 0 additions & 7 deletions src/CheckTreePicker/CheckTreePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,10 @@ const CheckTreePicker: PickerComponent<CheckTreePickerProps> = React.forwardRef(
onEntered,
onChange,
onClean,
onClose,
onExited,
onSearch,
onSelect,
onSelectItem,
onOpen,
onScroll,
onExpand,
renderValue,
Expand Down Expand Up @@ -425,17 +423,13 @@ const CheckTreePicker: PickerComponent<CheckTreePickerProps> = React.forwardRef(
});

const handleOpen = useEventCallback(() => {
trigger.current?.open?.();
setFocusItemValue(activeNode?.[valueKey]);
focusActiveNode();
onOpen?.();
setActive(true);
});

const handleClose = useEventCallback(() => {
trigger.current?.close?.();
setSearchKeyword('');
onClose?.();
setFocusItemValue(null);
setActive(false);

Expand Down Expand Up @@ -577,7 +571,6 @@ const CheckTreePicker: PickerComponent<CheckTreePickerProps> = React.forwardRef(
searchInput,
active,
onExit: handleClean,
onClose: handleClose,
onMenuKeyDown: event => {
onMenuKeyDown(event, {
down: () => handleFocusItem(KEY_VALUES.DOWN),
Expand Down
2 changes: 1 addition & 1 deletion src/CheckTreePicker/test/CheckTreePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('CheckTreePicker', () => {
return screen.getByRole('combobox');
}
});
testPickers(CheckTreePicker, { virtualized: true });
testPickers(CheckTreePicker, { virtualized: true, ariaHaspopup: 'tree' });
testControlledUnControlled(CheckTreePicker, {
componentProps: {
data: controlledData,
Expand Down
9 changes: 4 additions & 5 deletions src/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Stack from '../Stack';
import PredefinedRanges from './PredefinedRanges';
import { DatePickerLocale } from '../locales';
import {
createChainedFunction,
mergeRefs,
useClassNames,
useControlled,
Expand Down Expand Up @@ -274,12 +273,10 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
onChange,
onChangeCalendarDate,
onClean,
onClose,
onEntered,
onExited,
onNextMonth,
onOk,
onOpen,
onPrevMonth,
onSelect,
onToggleMonthDropdown,
Expand Down Expand Up @@ -721,6 +718,8 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
}

setShowMonthDropdown(false);

props.onClose?.();
});

const showCleanButton = cleanable && hasValue && !readOnly;
Expand All @@ -734,8 +733,8 @@ const DatePicker: RsRefForwardingComponent<'div', DatePickerProps> = React.forwa
ref={trigger}
placement={placement}
onClose={handleTriggerClose}
onEntered={createChainedFunction(onOpen, onEntered)}
onExited={createChainedFunction(onClose, onExited)}
onEntered={onEntered}
onExited={onExited}
speaker={renderCalendarOverlay}
>
<Component
Expand Down
2 changes: 1 addition & 1 deletion src/DatePicker/test/DatePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('DatePicker', () => {
}
});

testPickers(DatePicker);
testPickers(DatePicker, { role: 'textbox', ariaHaspopup: 'dialog' });

testControlledUnControlled(DatePicker, {
defaultValue: new Date('2023-10-01'),
Expand Down
6 changes: 2 additions & 4 deletions src/DateRangePicker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,10 @@ const DateRangePicker = React.forwardRef((props: DateRangePickerProps, ref) => {
value: valueProp,
onChange,
onClean,
onClose,
onEnter,
onEntered,
onExited,
onOk,
onOpen,
onSelect,
onShortcutClick,
renderTitle,
Expand Down Expand Up @@ -900,8 +898,8 @@ const DateRangePicker = React.forwardRef((props: DateRangePickerProps, ref) => {
pickerProps={pick(props, pickTriggerPropKeys)}
placement={placement}
onEnter={createChainedFunction(handleEnter, onEnter)}
onEntered={createChainedFunction(onOpen, onEntered)}
onExited={createChainedFunction(onClose, onExited)}
onEntered={onEntered}
onExited={onExited}
speaker={renderCalendarOverlay}
>
<Component
Expand Down
2 changes: 1 addition & 1 deletion src/DateRangePicker/test/DateRangePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('DateRangePicker', () => {
}
});

testPickers(DateRangePicker);
testPickers(DateRangePicker, { role: 'textbox', ariaHaspopup: 'dialog' });
testControlledUnControlled(DateRangePicker, {
defaultValue: [new Date('2023-11-01'), new Date('2023-11-02')],
value: [new Date('2023-11-03'), new Date('2023-11-04')],
Expand Down
5 changes: 1 addition & 4 deletions src/InputPicker/InputPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ const InputPicker: PickerComponent<InputPickerProps> = React.forwardRef(
onCreate,
onSearch,
onSelect,
onOpen,
onClose,
onBlur,
onFocus,
searchBy,
Expand Down Expand Up @@ -524,7 +522,6 @@ const InputPicker: PickerComponent<InputPickerProps> = React.forwardRef(
const handleExited = useEventCallback(() => {
setFocusItemValue(multi ? value?.[0] : value);
resetSearch();
onClose?.();
});

const handleFocus = useEventCallback(() => {
Expand Down Expand Up @@ -747,7 +744,7 @@ const InputPicker: PickerComponent<InputPickerProps> = React.forwardRef(
ref={triggerRef}
trigger="active"
onEnter={createChainedFunction(handleEnter, onEnter)}
onEntered={createChainedFunction(onEntered, onOpen)}
onEntered={onEntered}
onExit={createChainedFunction(handleExit, onExit)}
onExited={createChainedFunction(handleExited, onExited)}
speaker={renderPopup}
Expand Down
4 changes: 0 additions & 4 deletions src/MultiCascader/MultiCascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ const MultiCascader: PickerComponent<MultiCascaderProps<DataItemValue>> = React.
onSearch,
onSelect,
onChange,
onOpen,
onClose,
onCheck,
menuClassName: DEPRECATED_menuClassName,
menuStyle: DEPRECATED_menuStyle,
Expand Down Expand Up @@ -274,8 +272,6 @@ const MultiCascader: PickerComponent<MultiCascaderProps<DataItemValue>> = React.
});

const { active, handleEntered, handleExited } = useActive({
onOpen,
onClose,
onEntered,
onExited,
target,
Expand Down
2 changes: 1 addition & 1 deletion src/MultiCascader/test/MultiCascaderSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('MultiCascader', () => {
return screen.getByRole('combobox');
}
});
testPickers(MultiCascader);
testPickers(MultiCascader, { ariaHaspopup: 'tree' });
testControlledUnControlled(MultiCascader, {
componentProps: {
data: items,
Expand Down
8 changes: 1 addition & 7 deletions src/SelectPicker/SelectPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,6 @@ const SelectPicker = React.forwardRef(
onChange,
onSelect,
onSearch,
onClose,
onOpen,
sort,
renderValue,
renderMenu,
Expand Down Expand Up @@ -276,23 +274,19 @@ const SelectPicker = React.forwardRef(
onExit: handleClean,
onMenuKeyDown: onFocusItem,
onMenuPressEnter: handleMenuPressEnter,
onClose: () => {
setFocusItemValue(null);
},
...rest
});

const handleExited = useEventCallback(() => {
resetSearch();
setActive(false);
onSearch?.('');
onClose?.();
setFocusItemValue(null);
});

const handleEntered = useEventCallback(() => {
setActive(true);
setFocusItemValue(value);
onOpen?.();
});

// Find active `MenuItem` by `value`
Expand Down
8 changes: 1 addition & 7 deletions src/TreePicker/TreePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,11 @@ const TreePicker: PickerComponent<TreePickerProps> = React.forwardRef((props, re
onExit,
onExited,
onClean,
onOpen,
onSearch,
onSelect,
onSelectItem,
onChange,
onEntered,
onClose,
onDragEnd,
onDragStart,
onDragEnter,
Expand Down Expand Up @@ -476,14 +474,11 @@ const TreePicker: PickerComponent<TreePickerProps> = React.forwardRef((props, re
});

const handleOpen = useEventCallback(() => {
trigger.current?.open?.();
focusActiveNode();
onOpen?.();
setActive(true);
});

const handleClose = useEventCallback(() => {
trigger.current?.close?.();
setSearchKeyword('');
setActive(false);
setFocusItemValue(activeNode?.[valueKey]);
Expand Down Expand Up @@ -580,7 +575,6 @@ const TreePicker: PickerComponent<TreePickerProps> = React.forwardRef((props, re
searchInput,
active,
onExit: handleClean,
onClose: handleClose,
onMenuKeyDown: event => {
onMenuKeyDown(event, {
down: () => handleFocusItem(KEY_VALUES.DOWN),
Expand Down Expand Up @@ -795,7 +789,7 @@ const TreePicker: PickerComponent<TreePickerProps> = React.forwardRef((props, re
placement={placement}
onEnter={handleOpen}
onEntered={onEntered}
onExit={createChainedFunction(onClose, onExit)}
onExit={onExit}
onExited={createChainedFunction(handleClose, onExited)}
speaker={renderTreeView}
>
Expand Down
2 changes: 1 addition & 1 deletion src/TreePicker/test/TreePickerSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('TreePicker', () => {
}
});

testPickers(TreePicker);
testPickers(TreePicker, { ariaHaspopup: 'tree' });
testControlledUnControlled(TreePicker, {
componentProps: { data, defaultOpen: true },
value: '1',
Expand Down

0 comments on commit 09db561

Please sign in to comment.