Skip to content

Commit

Permalink
Add action animation selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Marek Rozmus committed Apr 10, 2020
1 parent fda0847 commit e5a9db8
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 30 deletions.
13 changes: 12 additions & 1 deletion examples/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { v4 as uuidv4 } from 'uuid';
import {
ActionAnimation,
SwipeableList,
SwipeableListItem
} from '@sandstreamdev/react-swipeable-list';
Expand Down Expand Up @@ -35,7 +36,17 @@ function App() {
<span>Left content</span>
</div>
),
endAnimation: 'delete',
actionAnimation: ActionAnimation.REMOVE,
action: () =>
setItems(items => items.filter(item => item.id !== id))
}}
swipeLeft={{
content: (
<div className={styles.contentRight}>
<span>Right content</span>
</div>
),
actionAnimation: ActionAnimation.NONE,
action: () =>
setItems(items => items.filter(item => item.id !== id))
}}
Expand Down
2 changes: 1 addition & 1 deletion src/SwipeableList.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const SwipeableList = ({
);

SwipeableList.propTypes = {
children: PropTypes.any,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
scrollStartThreshold: PropTypes.number,
swipeStartThreshold: PropTypes.number,
threshold: PropTypes.number
Expand Down
96 changes: 70 additions & 26 deletions src/SwipeableListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import PropTypes from 'prop-types';

import styles from './SwipeableListItem.css';

export const ActionAnimation = {
RETURN: 'RETURN',
REMOVE: 'REMOVE',
NONE: 'NONE'
};

const SwipeActionPropType = PropTypes.shape({
action: PropTypes.func.isRequired,
actionAnimation: PropTypes.oneOf(Object.values(ActionAnimation)),
content: PropTypes.node.isRequired
});

Expand Down Expand Up @@ -166,19 +173,74 @@ class SwipeableListItem extends PureComponent {
this.handleDragEnd();
};

playReturnAnimation = () => {
const { contentLeft, contentRight, listElement } = this;

if (listElement) {
listElement.className = styles.contentReturn;
listElement.style.transform = 'translateX(0px)';
}

// hide backgrounds
if (contentLeft !== null) {
contentLeft.style.opacity = 0;
contentLeft.className = styles.contentLeftReturn;
}

if (contentRight !== null) {
contentRight.style.opacity = 0;
contentRight.className = styles.contentRightReturn;
}
};

playRemoveAnimation = direction => {
const { listElement } = this;

if (listElement) {
listElement.className = styles.contentRemove;
listElement.style.transform = `translateX(${
direction === DragDirection.LEFT ? '-' : ''
}${listElement.offsetWidth}px)`;
}
};

playActionAnimation = (type, direction) => {
const { listElement } = this;

if (listElement) {
switch (type) {
case ActionAnimation.REMOVE:
this.playRemoveAnimation(direction);
break;
case ActionAnimation.NONE:
break;
default:
this.playReturnAnimation();
}
}
};

handleDragEnd = () => {
const { left, listElement, props } = this;
const { swipeLeft, swipeRight, threshold = 0.5 } = props;
let actionTriggered = false;

if (this.isSwiping()) {
const threshold = this.props.threshold || 0.5;

if (this.listElement) {
if (this.left < this.listElement.offsetWidth * threshold * -1) {
actionTriggered = true;
if (listElement) {
if (left < listElement.offsetWidth * threshold * -1) {
this.playActionAnimation(
swipeLeft.actionAnimation,
DragDirection.LEFT
);
this.handleSwipedLeft();
} else if (this.left > this.listElement.offsetWidth * threshold) {
actionTriggered = true;
} else if (left > listElement.offsetWidth * threshold) {
this.playActionAnimation(
swipeRight.actionAnimation,
DragDirection.RIGHT
);
this.handleSwipedRight();
actionTriggered = true;
}
}

Expand All @@ -189,25 +251,8 @@ class SwipeableListItem extends PureComponent {

this.resetState();

if (this.listElement) {
if (this.props.swipeRight.endAnimation === 'delete' && actionTriggered) {
this.listElement.className = styles.contentRemove;
this.listElement.style.transform = `translateX(${this.listElement.offsetWidth}px)`;
} else {
this.listElement.className = styles.contentReturn;
this.listElement.style.transform = 'translateX(0px)';
}
}

// hide backgrounds
if (this.contentLeft !== null) {
this.contentLeft.style.opacity = 0;
this.contentLeft.className = styles.contentLeftReturn;
}

if (this.contentRight !== null) {
this.contentRight.style.opacity = 0;
this.contentRight.className = styles.contentRightReturn;
if (!actionTriggered) {
this.playReturnAnimation();
}
};

Expand Down Expand Up @@ -426,7 +471,6 @@ class SwipeableListItem extends PureComponent {
SwipeableListItem.propTypes = {
blockSwipe: PropTypes.bool,
children: PropTypes.node.isRequired,
// endAnimation: PropTypes.string,
swipeLeft: SwipeActionPropType,
swipeRight: SwipeActionPropType,
scrollStartThreshold: PropTypes.number,
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SwipeableList from './SwipeableList';
import SwipeableListItem from './SwipeableListItem';
import SwipeableListItem, { ActionAnimation } from './SwipeableListItem';

export { SwipeableList, SwipeableListItem };
export { ActionAnimation, SwipeableList, SwipeableListItem };

0 comments on commit e5a9db8

Please sign in to comment.