Skip to content

Commit

Permalink
Add actionDelay parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
marekrozmus committed Nov 13, 2022
1 parent 54031fd commit 70ce3c0
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 19 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ const trailingActions = () => (

## SwipeableList Props

### actionDelay

Type: `milliseconds` (optional, default: `0`)

Time in milliseconds after which swipe action and animation should be called after trigggering swipe action.

It can be set for the whole list or for every item. See `actionDelay` for `SwipeableListItem`. Value from the `SwipeableListItem` takes precedence.

### fullSwipe

Type: `boolean` (optional, default: `false`)
Expand Down Expand Up @@ -163,6 +171,14 @@ It can be set for the whole list or for every item. See `threshold` for `Swipeab

## SwipeableListItem Props

### actionDelay

Type: `milliseconds` (optional, default: `0`)

Time in milliseconds after which swipe action and animation should be called after trigggering swipe action.

It can be set for the whole list or for every item. See `actionDelay` for `SwipeableList`. Value from the `SwipeableListItem` takes precedence.

### blockSwipe

Type: `boolean` (optional, default: `false`)
Expand Down
17 changes: 16 additions & 1 deletion src/SwipeAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const SwipeAction = ({
Tag = 'span',
}) => {
const {
actionDelay,
destructiveCallbackDelay,
leadingFullSwipe,
listType,
Expand All @@ -30,13 +31,27 @@ const SwipeAction = ({
} = React.useContext(ItemContext);

const onHandleClick = React.useCallback(() => {
if (actionDelay) {
window.setTimeout(() => {
onActionTriggered(destructive);
onClick();
}, actionDelay);
return;
}

onActionTriggered(destructive);
if (destructive) {
window.setTimeout(() => onClick(), destructiveCallbackDelay);
} else {
onClick();
}
}, [destructive, destructiveCallbackDelay, onActionTriggered, onClick]);
}, [
actionDelay,
destructive,
destructiveCallbackDelay,
onActionTriggered,
onClick,
]);

React.useEffect(() => {
if (leading && main) {
Expand Down
3 changes: 3 additions & 0 deletions src/SwipeableList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const Type = {
};

const SwipeableList = ({
actionDelay = 0,
children,
className = '',
fullSwipe = false,
Expand All @@ -25,6 +26,7 @@ const SwipeableList = ({
<Tag className={clsx('swipeable-list', className)} style={style}>
{React.Children.map(children, child =>
React.cloneElement(child, {
actionDelay,
destructiveCallbackDelay,
fullSwipe,
listType: type,
Expand All @@ -37,6 +39,7 @@ const SwipeableList = ({
);

SwipeableList.propTypes = {
actionDelay: PropTypes.number,
children: PropTypes.node,
className: PropTypes.string,
fullSwipe: PropTypes.bool,
Expand Down
4 changes: 3 additions & 1 deletion src/SwipeableListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ class SwipeableListItem extends PureComponent {
bindTrailingActionsElement = ref => (this.trailingActionsElement = ref);

renderActions = (actions, type, binder) => {
const { destructiveCallbackDelay, listType } = this.props;
const { actionDelay, destructiveCallbackDelay, listType } = this.props;
const { leadingFullSwipe, trailingFullSwipe, scaleLeading, scaleTrailing } =
this.state;
const {
Expand All @@ -747,6 +747,7 @@ class SwipeableListItem extends PureComponent {
>
<ItemContext.Provider
value={{
actionDelay,
destructiveCallbackDelay,
listType,
leadingFullSwipe,
Expand Down Expand Up @@ -803,6 +804,7 @@ class SwipeableListItem extends PureComponent {
}

SwipeableListItem.propTypes = {
actionDelay: PropTypes.number,
blockSwipe: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
Expand Down
73 changes: 57 additions & 16 deletions src/__tests__/SwipeableListItem.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,26 +203,26 @@ describe('SwipeableListItem (type ANDROID) - behavior ', () => {
swipeLeftMouse(listItem, toThreshold());
swipeLeftTouch(listItem, toThreshold());

expect(onSwipeStartCallback).toHaveBeenLastCalledWith("left");
expect(onSwipeEndCallback).toHaveBeenLastCalledWith("left");
expect(onSwipeStartCallback).toHaveBeenLastCalledWith('left');
expect(onSwipeEndCallback).toHaveBeenLastCalledWith('left');

swipeRightMouse(listItem, toThreshold());
swipeRightTouch(listItem, toThreshold());
expect(onSwipeStartCallback).toHaveBeenLastCalledWith("right");
expect(onSwipeEndCallback).toHaveBeenLastCalledWith("right");

expect(onSwipeStartCallback).toHaveBeenLastCalledWith('right');
expect(onSwipeEndCallback).toHaveBeenLastCalledWith('right');

swipeLeftMouse(listItem, beyondThreshold());
swipeLeftTouch(listItem, beyondThreshold());
expect(onSwipeStartCallback).toHaveBeenLastCalledWith("left");
expect(onSwipeEndCallback).toHaveBeenLastCalledWith("left");

expect(onSwipeStartCallback).toHaveBeenLastCalledWith('left');
expect(onSwipeEndCallback).toHaveBeenLastCalledWith('left');

swipeRightMouse(listItem, beyondThreshold());
swipeRightTouch(listItem, beyondThreshold());

expect(onSwipeStartCallback).toHaveBeenLastCalledWith("right");
expect(onSwipeEndCallback).toHaveBeenLastCalledWith("right");
expect(onSwipeStartCallback).toHaveBeenLastCalledWith('right');
expect(onSwipeEndCallback).toHaveBeenLastCalledWith('right');

expect(onSwipeStartCallback).toHaveBeenCalledTimes(8);
expect(onSwipeEndCallback).toHaveBeenCalledTimes(8);
Expand Down Expand Up @@ -301,22 +301,34 @@ describe('SwipeableListItem (type ANDROID) - behavior ', () => {
swipeLeftMouse(listItem, toThreshold());
swipeLeftTouch(listItem, toThreshold());

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(expect.anything(), "left");
expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(
expect.anything(),
'left'
);

swipeRightMouse(listItem, toThreshold());
swipeRightTouch(listItem, toThreshold());

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(expect.anything(), "right");

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(
expect.anything(),
'right'
);

swipeLeftMouse(listItem, beyondThreshold());
swipeLeftTouch(listItem, beyondThreshold());

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(expect.anything(), "left");

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(
expect.anything(),
'left'
);

swipeRightMouse(listItem, beyondThreshold());
swipeRightTouch(listItem, beyondThreshold());

expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(expect.anything(), "right");
expect(onSwipeProgressCallback).toHaveBeenLastCalledWith(
expect.anything(),
'right'
);

expect(onSwipeProgressCallback).toHaveBeenCalledTimes(8);
});
Expand Down Expand Up @@ -720,4 +732,33 @@ describe('SwipeableListItem (type IOS) - behavior', () => {
fireEvent.click(listItem);
expect(onClickCallback).toHaveBeenCalledTimes(1);
});

test('triggering swipe action and return animation after specified time', () => {
const trailingActionCallback = jest.fn();

renderIosOneActionType({
actionDelay: 2000,
fullSwipe: false,
trailingActionCallback,
});

const listItem = screen.getByTestId('content');
const trailingActions = screen.getByTestId('trailing-actions');

const {
children: [swipeAction],
} = trailingActions;

swipeLeftMouse(listItem, beyondOpenActionsThreshold());

expect(trailingActions).toHaveClass('test-actions-opened');

fireEvent.click(swipeAction);

expect(trailingActionCallback).toHaveBeenCalledTimes(0);

setTimeout(() => {
expect(trailingActionCallback).toHaveBeenCalledTimes(1);
}, 2000);
});
});
8 changes: 7 additions & 1 deletion src/__tests__/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ export const beforeEachTest = () => {
};

export const afterEachTest = () => {
window.requestAnimationFrame.mockRestore();
if (window.requestAnimationFrame.mockRestore) {
window.requestAnimationFrame.mockRestore();
}

global.Date.now = RealDate;
};
Expand Down Expand Up @@ -259,6 +261,7 @@ export const renderAndroidType = ({
);

export const renderIosOneActionType = ({
actionDelay = 0,
blockSwipe = false,
fullSwipe = true,
leadingActionCallback = jest.fn(),
Expand All @@ -272,6 +275,7 @@ export const renderIosOneActionType = ({
} = {}) =>
render(
<SwipeableListItem
actionDelay={actionDelay}
blockSwipe={blockSwipe}
fullSwipe={fullSwipe}
leadingActions={
Expand All @@ -297,6 +301,7 @@ export const renderIosOneActionType = ({
);

export const renderIosTwoActionsType = ({
actionDelay = 0,
blockSwipe = false,
fullSwipe = true,
leadingActionCallbacks = [jest.fn(), jest.fn()],
Expand All @@ -310,6 +315,7 @@ export const renderIosTwoActionsType = ({
} = {}) =>
render(
<SwipeableListItem
actionDelay={actionDelay}
blockSwipe={blockSwipe}
fullSwipe={fullSwipe}
leadingActions={
Expand Down
6 changes: 6 additions & 0 deletions src/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ interface SwipeableListProps {
export const SwipeableList: FunctionComponent<SwipeableListProps>;

interface SwipeableListItemProps {
/**
* default: 0
*
* Time in milliseconds after which swipe action and animation should be called after trigggering swipe action.
*/
actionDelay?: number;
/**
* default: `false`
*
Expand Down

0 comments on commit 70ce3c0

Please sign in to comment.