Skip to content

Commit 4e851f8

Browse files
author
Marek Rozmus
committed
Merge branch 'allow_passing_props_to_list_div'
2 parents 86cd97a + 7151e18 commit 4e851f8

File tree

9 files changed

+152
-42
lines changed

9 files changed

+152
-42
lines changed

README.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,26 @@ import '@sandstreamdev/react-swipeable-list/dist/styles.css';
6060
</SwipeableList>
6161
```
6262

63-
or use function as children pattern if other container is needed (check animation example)
63+
or use function as children pattern if other container is needed (check animation and styled container examples). Note that in this case you need to provide list wrapper and pass default `className` props to have same behaviour. Default `SwipeableList` styles are passed in `className` prop.
6464

6565
```jsx
6666
<SwipeableList>
67-
{props => (
68-
<TransitionGroup>
69-
<CSSTransition>
70-
<SwipeableListItem
71-
swipeLeft={{
72-
content: <div>Revealed content during swipe</div>,
73-
action: () => console.info('swipe action triggered')
74-
}}
75-
swipeRight={{
76-
content: <div>Revealed content during swipe</div>,
77-
action: () => console.info('swipe action triggered')
78-
}}
79-
{...props}
80-
>
81-
<div>Item name</div>
82-
</SwipeableListItem>
83-
</CSSTransition>
84-
</TransitionGroup>
67+
{({ className, ...rest }) => (
68+
<div className={className}>
69+
<SwipeableListItem
70+
swipeLeft={{
71+
content: <div>Revealed content during swipe</div>,
72+
action: () => console.info('swipe action triggered')
73+
}}
74+
swipeRight={{
75+
content: <div>Revealed content during swipe</div>,
76+
action: () => console.info('swipe action triggered')
77+
}}
78+
{...rest}
79+
>
80+
<div>Item name</div>
81+
</SwipeableListItem>
82+
</div>
8583
)}
8684
</SwipeableList>
8785
```

examples/src/App.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import BasicList from './basic/List';
55
import ComplexList from './complex/List';
66
import SizeToContentList from './size-to-content/List';
77
import AnimationsList from './animations/List';
8+
import StyledList from './styled/List';
89

910
import styles from './app.module.css';
1011

1112
const ExampleType = enumerable(
1213
'BASIC',
1314
'COMPLEX',
1415
'SIZE_TO_CONTENT',
15-
'ANIMATIONS'
16+
'ANIMATIONS',
17+
'STYLED'
1618
);
1719

1820
const Examples = [
@@ -22,7 +24,8 @@ const Examples = [
2224
id: ExampleType.SIZE_TO_CONTENT,
2325
text: 'List in size to content container'
2426
},
25-
{ id: ExampleType.ANIMATIONS, text: 'Animations' }
27+
{ id: ExampleType.ANIMATIONS, text: 'Animations' },
28+
{ id: ExampleType.STYLED, text: 'Custom container' }
2629
];
2730

2831
class App extends PureComponent {
@@ -46,6 +49,8 @@ class App extends PureComponent {
4649
return <SizeToContentList />;
4750
case ExampleType.ANIMATIONS:
4851
return <AnimationsList />;
52+
case ExampleType.STYLED:
53+
return <StyledList />;
4954
}
5055

5156
return null;

examples/src/animations/List.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,14 @@ const SimpleList = () => {
7272
</span>
7373
<div className={styles.listContainer}>
7474
<SwipeableList threshold={threshold}>
75-
{({ scrollStartThreshold, swipeStartThreshold, threshold }) => (
75+
{({
76+
className,
77+
scrollStartThreshold,
78+
swipeStartThreshold,
79+
threshold
80+
}) => (
7681
<TransitionGroup
77-
className="todo-list"
82+
className={className}
7883
enter={listAnimations}
7984
exit={listAnimations}
8085
>

examples/src/size-to-content/List.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
SwipeableListItem
55
} from '@sandstreamdev/react-swipeable-list';
66
import '@sandstreamdev/react-swipeable-list/dist/styles.css';
7-
import { identity } from '@sandstreamdev/std/function';
7+
import { noOp } from '@sandstreamdev/std/function';
88

99
import ListItem from '../complex/ListItem';
1010
import ItemContent from '../complex/ItemContent';
@@ -37,7 +37,7 @@ const SizeToContentList = () => {
3737
side="right"
3838
/>
3939
),
40-
action: identity
40+
action: noOp
4141
});
4242

4343
const swipeLeftOptions = () => ({
@@ -49,7 +49,7 @@ const SizeToContentList = () => {
4949
side="left"
5050
/>
5151
),
52-
action: identity
52+
action: noOp
5353
});
5454

5555
return (

examples/src/styled/List.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React from 'react';
2+
import { v4 as uuidv4 } from 'uuid';
3+
import {
4+
SwipeableList,
5+
SwipeableListItem
6+
} from '@sandstreamdev/react-swipeable-list';
7+
import '@sandstreamdev/react-swipeable-list/dist/styles.css';
8+
import { classNames } from '@sandstreamdev/std/web';
9+
import { noOp } from '@sandstreamdev/std/function';
10+
11+
import styles from '../app.module.css';
12+
import customStyles from './custom.module.css';
13+
14+
const itemContent = name => (
15+
<div className={styles.listItem}>
16+
<span>{name}</span>
17+
</div>
18+
);
19+
20+
const StyledList = () => {
21+
const items = [
22+
{ id: uuidv4(), text: 'Item 1' },
23+
{ id: uuidv4(), text: 'Item 2' },
24+
{ id: uuidv4(), text: 'Item 3' },
25+
{ id: uuidv4(), text: 'Item 4' }
26+
];
27+
28+
const swipeRightOptions = () => ({
29+
content: (
30+
<div className={styles.contentLeft}>
31+
<span>Delete</span>
32+
</div>
33+
),
34+
action: noOp
35+
});
36+
37+
const swipeLeftOptions = () => ({
38+
content: (
39+
<div className={styles.contentRight}>
40+
<span>Delete</span>
41+
</div>
42+
),
43+
action: noOp
44+
});
45+
46+
return (
47+
<>
48+
<span className={styles.actionInfo}>Custom styled list wrapper</span>
49+
<div className={styles.listContainer}>
50+
<SwipeableList>
51+
{({ className, ...rest }) => (
52+
<div className={classNames(className, customStyles.customList)}>
53+
{items.map(({ id, text }) => (
54+
<SwipeableListItem
55+
key={id}
56+
swipeLeft={swipeLeftOptions(id)}
57+
swipeRight={swipeRightOptions(id)}
58+
{...rest}
59+
>
60+
{itemContent(text)}
61+
</SwipeableListItem>
62+
))}
63+
</div>
64+
)}
65+
</SwipeableList>
66+
</div>
67+
</>
68+
);
69+
};
70+
71+
export default StyledList;

examples/src/styled/custom.module.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.customList {
2+
height: 320px;
3+
background-color: cornsilk;
4+
}

src/SwipeableList.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@ const SwipeableList = ({
88
scrollStartThreshold,
99
swipeStartThreshold,
1010
threshold
11-
}) => (
12-
<div className={styles.swipeableList} data-testid="list-wrapper">
13-
{typeof children === 'function'
14-
? children({ scrollStartThreshold, swipeStartThreshold, threshold })
15-
: React.Children.map(children, child =>
16-
React.cloneElement(child, {
17-
scrollStartThreshold,
18-
swipeStartThreshold,
19-
threshold
20-
})
21-
)}
22-
</div>
23-
);
11+
}) =>
12+
typeof children === 'function' ? (
13+
children({
14+
className: styles.swipeableList,
15+
scrollStartThreshold,
16+
swipeStartThreshold,
17+
threshold
18+
})
19+
) : (
20+
<div className={styles.swipeableList}>
21+
{React.Children.map(children, child =>
22+
React.cloneElement(child, {
23+
scrollStartThreshold,
24+
swipeStartThreshold,
25+
threshold
26+
})
27+
)}
28+
</div>
29+
);
2430

2531
SwipeableList.propTypes = {
2632
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),

src/__tests__/SwipeableList.test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
afterEach(cleanup);
1515

1616
test('list rendering with items', () => {
17-
const { getByText } = render(
17+
const { container, getByText } = render(
1818
<SwipeableList>
1919
<SwipeableListItem>
2020
<span>Item content 1</span>
@@ -27,10 +27,11 @@ test('list rendering with items', () => {
2727

2828
expect(getByText('Item content 1')).toBeInTheDocument();
2929
expect(getByText('Item content 2')).toBeInTheDocument();
30+
expect(container.firstChild).toHaveClass('swipeableList');
3031
});
3132

3233
test('list rendering with items when child as function', () => {
33-
const { getByText } = render(
34+
const { container, getByText } = render(
3435
<SwipeableList>
3536
{props => (
3637
<>
@@ -47,6 +48,22 @@ test('list rendering with items when child as function', () => {
4748

4849
expect(getByText('Item content 1')).toBeInTheDocument();
4950
expect(getByText('Item content 2')).toBeInTheDocument();
51+
expect(container.firstChild).not.toHaveClass('swipeableList');
52+
});
53+
54+
test('passing className to child function', () => {
55+
const { container, getByTestId } = render(
56+
<SwipeableList>
57+
{({ className }) => (
58+
<div>
59+
<div className={className} data-testid="tested-div" />
60+
</div>
61+
)}
62+
</SwipeableList>
63+
);
64+
65+
expect(container.firstChild).not.toHaveClass('swipeableList');
66+
expect(getByTestId('tested-div')).toHaveClass('swipeableList');
5067
});
5168

5269
test('blocking swipe on scroll', () => {

src/module.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,13 @@ interface IBaseSwipeableListProps {
112112
threshold?: number;
113113
}
114114

115+
interface IStyledSwipeableListProps extends IBaseSwipeableListProps {
116+
className: string;
117+
}
118+
115119
type SwipeableListChildren =
116120
| ReactNode
117-
| ((props: IBaseSwipeableListProps) => ReactNode);
121+
| ((props: IStyledSwipeableListProps) => ReactNode);
118122

119123
interface ISwipeableListProps extends IBaseSwipeableListProps {
120124
/**

0 commit comments

Comments
 (0)