Skip to content

Commit

Permalink
feat(Select): add OnOpenChange options
Browse files Browse the repository at this point in the history
  • Loading branch information
Leonid Fedorov committed Oct 26, 2024
1 parent b6516f4 commit 717deb1
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 14 deletions.
6 changes: 3 additions & 3 deletions src/components/Select/__tests__/Select.base-actions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ describe('Select base actions', () => {
setup({onOpenChange});

await toggleSelectPopup();
expect(onOpenChange).toHaveBeenCalledWith(true);
expect(onOpenChange).toHaveBeenCalledWith(true, {reason: 'outside-click'});
await toggleSelectPopup();
expect(onOpenChange).toHaveBeenCalledWith(false);
expect(onOpenChange).toHaveBeenCalledWith(false, {reason: 'outside-click'});
expect(onOpenChange).toHaveBeenCalledTimes(2);
});
test('should call onOpenChange whith controlled open', async () => {
Expand All @@ -145,7 +145,7 @@ describe('Select base actions', () => {

await toggleSelectPopup();

expect(onOpenChange).toHaveBeenCalledWith(false);
expect(onOpenChange).toHaveBeenCalledWith(false, {reason: 'outside-click'});
expect(onOpenChange).toHaveBeenCalledTimes(1);
});
});
Expand Down
19 changes: 16 additions & 3 deletions src/hooks/useSelect/__tests__/useOpenState.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ describe('useOpenState', () => {
});
rerender(props);

expect(onOpenChange).toHaveBeenCalledWith(true);
expect(onOpenChange).toHaveBeenCalledWith(true, {reason: 'outside-click'});

act(() => {
result.current.toggleOpen();
});
rerender(props);

expect(onOpenChange).toHaveBeenCalledWith(false);
expect(onOpenChange).toHaveBeenCalledWith(false, {reason: 'outside-click'});
});
test('if the same value is set, the onOpenChange will not be called', () => {
const onOpenChange = jest.fn();
Expand Down Expand Up @@ -150,7 +150,20 @@ describe('useOpenState', () => {
});
rerender(props);

expect(onOpenChange).toHaveBeenCalledWith(false);
expect(onOpenChange).toHaveBeenCalledWith(false, {reason: 'outside-click'});
});

test('onOpenChange is called with reason', () => {
const onOpenChange = jest.fn();
const props = {open: true, onOpenChange};
const {result, rerender} = renderUseOpenStateHook(props);

act(() => {
result.current.toggleOpen(false, {reason: 'selection'});
});
rerender(props);

expect(onOpenChange).toHaveBeenCalledWith(false, {reason: 'selection'});
});

test('if the same value is set, the onOpenChange will not be called', () => {
Expand Down
8 changes: 6 additions & 2 deletions src/hooks/useSelect/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
export type UseSelectOption<T = unknown> = T & {value: string};

export type OnOpenChangeOptions = {
reason: 'selection' | 'outside-click';
};

export type UseOpenProps = {
defaultOpen?: boolean;
open?: boolean;
onClose?: () => void;
onOpenChange?: (open: boolean) => void;
onOpenChange?: (open: boolean, options: OnOpenChangeOptions) => void;
};

export type UseSelectProps = {
Expand All @@ -22,6 +26,6 @@ export type UseSelectResult<T> = {
handleSelection: (option: UseSelectOption<T>) => void;
handleClearValue: () => void;
setValue: (value: string[]) => void;
toggleOpen: (val?: boolean | undefined) => void;
toggleOpen: (val?: boolean, options?: OnOpenChangeOptions) => void;
setActiveIndex: React.Dispatch<React.SetStateAction<number | undefined>>;
};
10 changes: 5 additions & 5 deletions src/hooks/useSelect/useOpenState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React from 'react';

import {useControlledState} from '../useControlledState/useControlledState';

import type {UseOpenProps} from './types';
import type {OnOpenChangeOptions, UseOpenProps} from './types';

export const useOpenState = (props: UseOpenProps) => {
const {onOpenChange, onClose} = props;
const handleOpenChange = React.useCallback(
(newOpen: boolean) => {
onOpenChange?.(newOpen);
(newOpen: boolean, options: OnOpenChangeOptions = {reason: 'outside-click'}) => {
onOpenChange?.(newOpen, options);
if (newOpen === false && onClose) {
onClose();
}
Expand All @@ -23,9 +23,9 @@ export const useOpenState = (props: UseOpenProps) => {
);

const toggleOpen = React.useCallback(
(val?: boolean) => {
(val?: boolean, options?: OnOpenChangeOptions) => {
const newOpen = typeof val === 'boolean' ? val : !open;
setOpenState(newOpen);
setOpenState(newOpen, options);
},
[open, setOpenState],
);
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSelect/useSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const useSelect = <T extends unknown>({
setValue(nextValue);
}

toggleOpen(false);
toggleOpen(false, {reason: 'selection'});
},
[value, setValue, toggleOpen],
);
Expand Down

0 comments on commit 717deb1

Please sign in to comment.