Skip to content

Commit 4471e04

Browse files
author
wfbn8821
committed
introducing stack layout
1 parent ef27082 commit 4471e04

File tree

7 files changed

+298
-37
lines changed

7 files changed

+298
-37
lines changed

example/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8">
55
<title>React-card-scroll example</title>
66
</head>
7-
<body style="overflow-x: hidden">
7+
<body>
88
<div id="example"></div>
99
</body>
1010
</html>

example/index.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,22 @@ import CardScroll from '../lib'
55
const ScrollableTitleCard = React.createClass({
66
componentDidMount() {
77
this.refs.title.addEventListener('wheel', event => {
8-
this.props.onScrollTitle({toLeft:event.wheelDelta>0})
8+
this.props.scrollCards({toLeft:event.wheelDelta>0})
99
event.preventDefault()
1010
})
1111
},
1212
render() {
1313
const {title, children, className, style} = this.props
14+
const onClick = ev => {
15+
const offset = this.props.getCardOffset()
16+
if(offset!=0){
17+
ev.preventDefault()
18+
this.props.scrollCards({toLeft:offset<0})
19+
}
20+
}
1421
return (
15-
<div className={"col-sm-6 col-md-4 "+className} style={style}>
16-
<div className="card">
22+
<div className={"col rcs-col-sm-6 rcs-col-md-4 rcs-col-lg-3 "+className} style={style}>
23+
<div onClick={onClick} className="card">
1724
<div ref="title" className="card-header">
1825
{title}
1926
</div>
@@ -64,13 +71,14 @@ const Example = React.createClass({
6471
},
6572

6673
render() {
67-
const onScrollTitle = params => this.refs.cardScroll.scrollCards(params)
74+
const scrollCards = params => this.refs.cardScroll.scrollCards(params)
75+
const getCardOffset = index => () => this.refs.cardScroll.getCardOffset(index)
6876
return (
6977
<div>
7078
<button onClick={this.addCard}>Add card</button>
7179
<button onClick={this.removeCard}>Remove last card</button>
7280
<CardScroll ref="cardScroll">
73-
{this.state.cards.map(el => React.cloneElement(el, {onScrollTitle}))}
81+
{this.state.cards.map((el, index) => React.cloneElement(el, {scrollCards, getCardOffset:getCardOffset(index)}))}
7482
</CardScroll>
7583
</div>
7684
)

example/theme.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
$enable-flex: true;
22

33
@import "../node_modules/bootstrap/scss/bootstrap";
4+
45
@import "../lib/assets/styles.css";
56

7+
.col{
8+
pointer-events: none;
9+
}
10+
11+
.card {
12+
pointer-events: auto;
13+
}
14+
615
.card-header{
716
&:hover{
817
background-image: linear-gradient(0, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
918
}
1019
}
20+
21+
.rcs-left-stack,.rcs-right-stack{
22+
.card:hover {
23+
background-image: linear-gradient(0, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
24+
cursor: pointer;
25+
}
26+
}

lib/assets/styles.css

Lines changed: 151 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
.row._1H7C65wd8WJqBtCRmAfokb {
2-
position: relative; }
1+
._1H7C65wd8WJqBtCRmAfokb {
2+
position: relative;
3+
box-sizing: border-box; }
34

45
._1H7C65wd8WJqBtCRmAfokb ._358enaiolY7BZPuXLuxdRA {
56
position: absolute;
6-
transition: left 1s; }
7+
transition: left 1s cubic-bezier(0, 0.7, 0.7, 1);
8+
box-sizing: border-box; }
79

810
._22yQcZhJvmCSA52vE9VrUe {
911
position: fixed;
@@ -51,3 +53,149 @@
5153
._1bIeR72ojeoWY-MxcIhjT-:hover {
5254
background: linear-gradient(to left, #ddd, #ccc);
5355
margin-left: 0; }
56+
57+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-1, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-2, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-3, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-4, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-5, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-6, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-7, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-8, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-9, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-10, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-11, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-12, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-1, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-2, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-3, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-4, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-5, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-6, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-7, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-8, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-9, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-10, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-11, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-12, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-1, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-2, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-3, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-4, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-5, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-6, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-7, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-8, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-9, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-10, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-11, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-12, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-1, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-2, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-3, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-4, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-5, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-6, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-7, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-8, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-9, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-10, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-11, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-12, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-1, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-2, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-3, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-4, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-5, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-6, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-7, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-8, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-9, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-10, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-11, ._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-12 {
58+
min-height: 1px;
59+
padding-left: 0.9375rem;
60+
padding-right: 0.9375rem;
61+
width: 100%; }
62+
63+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-1 {
64+
width: 8.33333%; }
65+
66+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-2 {
67+
width: 16.66667%; }
68+
69+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-3 {
70+
width: 25%; }
71+
72+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-4 {
73+
width: 33.33333%; }
74+
75+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-5 {
76+
width: 41.66667%; }
77+
78+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-6 {
79+
width: 50%; }
80+
81+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-7 {
82+
width: 58.33333%; }
83+
84+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-8 {
85+
width: 66.66667%; }
86+
87+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-9 {
88+
width: 75%; }
89+
90+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-10 {
91+
width: 83.33333%; }
92+
93+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-11 {
94+
width: 91.66667%; }
95+
96+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xs-12 {
97+
width: 100%; }
98+
99+
@media (min-width: 544px) {
100+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-1 {
101+
width: 8.33333%; }
102+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-2 {
103+
width: 16.66667%; }
104+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-3 {
105+
width: 25%; }
106+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-4 {
107+
width: 33.33333%; }
108+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-5 {
109+
width: 41.66667%; }
110+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-6 {
111+
width: 50%; }
112+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-7 {
113+
width: 58.33333%; }
114+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-8 {
115+
width: 66.66667%; }
116+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-9 {
117+
width: 75%; }
118+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-10 {
119+
width: 83.33333%; }
120+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-11 {
121+
width: 91.66667%; }
122+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-sm-12 {
123+
width: 100%; } }
124+
125+
@media (min-width: 768px) {
126+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-1 {
127+
width: 8.33333%; }
128+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-2 {
129+
width: 16.66667%; }
130+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-3 {
131+
width: 25%; }
132+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-4 {
133+
width: 33.33333%; }
134+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-5 {
135+
width: 41.66667%; }
136+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-6 {
137+
width: 50%; }
138+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-7 {
139+
width: 58.33333%; }
140+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-8 {
141+
width: 66.66667%; }
142+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-9 {
143+
width: 75%; }
144+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-10 {
145+
width: 83.33333%; }
146+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-11 {
147+
width: 91.66667%; }
148+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-md-12 {
149+
width: 100%; } }
150+
151+
@media (min-width: 992px) {
152+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-1 {
153+
width: 8.33333%; }
154+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-2 {
155+
width: 16.66667%; }
156+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-3 {
157+
width: 25%; }
158+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-4 {
159+
width: 33.33333%; }
160+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-5 {
161+
width: 41.66667%; }
162+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-6 {
163+
width: 50%; }
164+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-7 {
165+
width: 58.33333%; }
166+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-8 {
167+
width: 66.66667%; }
168+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-9 {
169+
width: 75%; }
170+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-10 {
171+
width: 83.33333%; }
172+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-11 {
173+
width: 91.66667%; }
174+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-lg-12 {
175+
width: 100%; } }
176+
177+
@media (min-width: 1200px) {
178+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-1 {
179+
width: 8.33333%; }
180+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-2 {
181+
width: 16.66667%; }
182+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-3 {
183+
width: 25%; }
184+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-4 {
185+
width: 33.33333%; }
186+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-5 {
187+
width: 41.66667%; }
188+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-6 {
189+
width: 50%; }
190+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-7 {
191+
width: 58.33333%; }
192+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-8 {
193+
width: 66.66667%; }
194+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-9 {
195+
width: 75%; }
196+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-10 {
197+
width: 83.33333%; }
198+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-11 {
199+
width: 91.66667%; }
200+
._1H7C65wd8WJqBtCRmAfokb .rcs-col-xl-12 {
201+
width: 100%; } }

lib/index.js

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ var _reactDom2 = _interopRequireDefault(_reactDom);
1414

1515
var _lodash = require('lodash');
1616

17-
var _reactMotion = require('react-motion');
18-
1917
var _styles = {
2018
"container": "_1H7C65wd8WJqBtCRmAfokb",
2119
"stack": "_358enaiolY7BZPuXLuxdRA",
@@ -41,11 +39,11 @@ var CardScroll = _react2.default.createClass({
4139
return { currentCard: 0 };
4240
},
4341
componentWillMount: function componentWillMount() {
42+
this.maxOffset = (0, _offset.getMaxOffset)();
4443
this.widths = defaultWidths;
4544
this.children = {};
4645
},
4746
componentDidMount: function componentDidMount() {
48-
this.maxOffset = (0, _offset.getMaxOffset)();
4947
this.widths = this.computeWidths();
5048
this.setState(this.getInitialState());
5149
window.addEventListener('resize', this.handleResize);
@@ -75,9 +73,10 @@ var CardScroll = _react2.default.createClass({
7573
if (childrenCount == 0) {
7674
return defaultWidths;
7775
}
76+
// anticipate the margin that we will add
77+
var container = this._container.getBoundingClientRect().width - this.maxOffset * 2;
7878
// get first child as all children should be of equal width
79-
var card = _reactDom2.default.findDOMNode(this._child).getBoundingClientRect().width;
80-
var container = this._container.clientWidth;
79+
var card = _reactDom2.default.findDOMNode(this._child).getBoundingClientRect().width * container / this._container.getBoundingClientRect().width;
8180
return {
8281
card: card,
8382
container: container
@@ -113,7 +112,7 @@ var CardScroll = _react2.default.createClass({
113112
) : null,
114113
_react2.default.createElement(
115114
'div',
116-
{ className: 'row ' + _styles2.default.container,
115+
{ className: _styles2.default.container,
117116
style: { marginLeft: this.maxOffset, marginRight: this.maxOffset },
118117
ref: updateContainer },
119118
_react2.default.Children.map(this.props.children, function (child, index) {
@@ -124,20 +123,23 @@ var CardScroll = _react2.default.createClass({
124123
props.ref = updateChild;
125124
}
126125

127-
var offset = (0, _offset.getOffset)({ index: index, firstVisibleIndex: currentCard, lastVisibleIndex: lastCard, cardWidth: _this2.widths.card });
126+
var offset = (0, _offset.getOffset)({ index: index, firstVisibleIndex: currentCard, lastVisibleIndex: lastCard });
128127
var position = offset;
129128
var zIndex = 0;
129+
var className = "rcs-left-stack";
130130
if (offset == 0) {
131131
position = (index - currentCard) * _this2.widths.card;
132-
if (index == lastCard) {
132+
if (index == lastCard && currentCard != lastCard) {
133133
zIndex = -1;
134134
}
135+
className = "rcs-center";
135136
} else if (offset > 0) {
136137
position = offset + (lastCard - currentCard) * _this2.widths.card;
137138
zIndex = lastCard - index - 1;
139+
className = "rcs-right-stack";
138140
}
139141
props.style = { left: position, zIndex: zIndex };
140-
props.className = _styles2.default.stack;
142+
props.className = className + ' ' + _styles2.default.stack;
141143

142144
return _react2.default.cloneElement(child, props);
143145
})
@@ -151,8 +153,6 @@ var CardScroll = _react2.default.createClass({
151153
return _this3.scrollCards(params);
152154
};
153155
},
154-
155-
//TODO write TESTS!!!
156156
scrollCards: function scrollCards() {
157157
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
158158

@@ -181,16 +181,26 @@ var CardScroll = _react2.default.createClass({
181181
this.setState({ currentLeft: currentLeft, currentCard: currentCard });
182182
},
183183
getVisibleCardCount: function getVisibleCardCount() {
184-
return Math.floor(this.widths.container / this.widths.card);
184+
return this.widths.card ? Math.floor(this.widths.container / this.widths.card) : 1;
185185
},
186186
lastVisibleCardIndex: function lastVisibleCardIndex() {
187187
return this.state.currentCard + this.getVisibleCardCount() - 1;
188188
},
189189
canScrollRight: function canScrollRight() {
190-
return this.lastVisibleCardIndex() + 1 < _react2.default.Children.count(this.props.children);
190+
return this.props.showArrows && this.lastVisibleCardIndex() + 1 < _react2.default.Children.count(this.props.children);
191191
},
192192
canScrollLeft: function canScrollLeft() {
193-
return this.state.currentCard > 0;
193+
return this.props.showArrows && this.state.currentCard > 0;
194+
},
195+
196+
197+
/**
198+
* Get card offset
199+
* @param index
200+
* return negative number if card is on left stack, 0 if visible, positive number if card is on right stack
201+
*/
202+
getCardOffset: function getCardOffset(index) {
203+
return (0, _offset.getOffset)({ index: index, firstVisibleIndex: this.state.currentCard, lastVisibleIndex: this.lastVisibleCardIndex() });
194204
}
195205
});
196206

0 commit comments

Comments
 (0)