Skip to content

Commit 315f358

Browse files
committed
Replace class mimics ReactTransitionGroup.
1 parent ccce9f2 commit 315f358

File tree

7 files changed

+543
-805
lines changed

7 files changed

+543
-805
lines changed

demo/assets/app.js

Lines changed: 474 additions & 555 deletions
Large diffs are not rendered by default.

demo/assets/transitions.css

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ body {
1212
}
1313
.cross-fade-leave.cross-fade-leave-active {
1414
opacity: 0;
15-
transition: opacity .2s ease-in;
15+
transition: opacity 1s ease-in;
1616
}
1717

1818
.cross-fade-enter {
1919
opacity: 0;
2020
}
2121
.cross-fade-enter.cross-fade-enter-active {
2222
opacity: 1;
23-
transition: opacity .2s ease-in;
23+
transition: opacity 1s ease-in;
2424
}
2525

2626
.cross-fade-height {
27-
transition: height .15s ease-in-out;
27+
transition: height 1s ease-in-out;
2828
}
2929

3030

@@ -55,8 +55,6 @@ body {
5555
/* Carousel-like transition */
5656

5757
.carousel {
58-
position: relative;
59-
overflow: hidden;
6058
display: block;
6159
width: 100%;
6260
}

demo/components/ContentLong.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
22

33

4-
function ContentLong() {
4+
function ContentLong(props) {
55
return (
6-
<div>
6+
<div {...props}>
77
<b>Some longer content</b>
88
<p>
99
Suspendisse non ante dui. Phasellus tempor sem non cursus feugiat. Pellentesque quis justo neque. Proin est

demo/components/ContentShort.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
22

33

4-
function ContentShort() {
4+
function ContentShort(props) {
55
return (
6-
<div>
6+
<div {...props}>
77
<b>Some shorter content</b>
88
<p>
99
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce pulvinar pharetra magna ac rhoncus. Pellentesque

demo/components/Demo.jsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class Demo extends React.Component {
1515
'/img/vista3.jpg',
1616
'/img/vista4.jpg'
1717
].forEach(src => {
18-
const img = new window.Image();
19-
img.src = src;
20-
});
18+
const img = new window.Image();
19+
img.src = src;
20+
});
2121
}
2222

2323
render() {
@@ -41,15 +41,17 @@ class Demo extends React.Component {
4141
<p className="text-danger"><em>Click any content to trigger the transition.</em></p>
4242

4343
<h2>Cross-fade transition</h2>
44-
<ContentSwapper {...transitionProps} transitionName="cross-fade">
44+
<ContentSwapper transitionName="cross-fade" transitionHeight={false}
45+
transitionEnterTimeout={1000} transitionLeaveTimeout={1000}>
4546
<img key="img1" src="/img/vista1.jpg"/>
4647
<img key="img2" src="/img/vista2.jpg"/>
4748
</ContentSwapper>
4849

4950
<h2>Fade out, then fade in transition</h2>
50-
<ContentSwapper {...transitionProps} transitionName="wait-fade">
51-
<ContentShort key="short"/>
51+
<ContentSwapper transitionName="cross-fade" transitionHeight={false}
52+
transitionEnterTimeout={1000} transitionLeaveTimeout={1000}>
5253
<ContentLong key="long"/>
54+
<ContentShort key="short"/>
5355
</ContentSwapper>
5456

5557
<h2>Carousel-like transition</h2>

src/ReactCSSTransitionReplace.jsx

Lines changed: 54 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import ReactDOM from 'react-dom';
99
import objectAssign from 'react/lib/Object.assign';
1010
import ReactTransitionGroup from 'react-addons-transition-group';
1111

12-
import ReplaceChildComponent from './ReactCSSTransitionReplaceChild';
12+
import emptyFunction from 'react/node_modules/fbjs/lib/emptyFunction';
13+
14+
import ReplaceChildComponent from 'react/lib/ReactCSSTransitionGroupChild';
1315

1416
const reactCSSTransitionReplaceChild = React.createFactory(ReplaceChildComponent);
1517

@@ -53,7 +55,8 @@ export default class ReactCSSTransitionReplace extends React.Component {
5355
transitionAppear: false,
5456
transitionEnter: true,
5557
transitionLeave: true,
56-
transitionHeight: true
58+
transitionHeight: true,
59+
component: 'span'
5760
};
5861

5962
state = {
@@ -73,58 +76,23 @@ export default class ReactCSSTransitionReplace extends React.Component {
7376
});
7477
}
7578

76-
const transitionHeight = nextProps.transitionHeight;
77-
const currentHeight = transitionHeight ? ReactDOM.findDOMNode(this.refs.container).offsetHeight : 'auto';
78-
79-
// The child was removed, so animate out.
80-
if (!nextChild) {
81-
return this.setState({
82-
height: currentHeight,
83-
currentChild: null
84-
}, () => transitionHeight && this.setState({height: 0}));
85-
}
86-
87-
// The child was replaced or added, setting a nextChild will eventually animate it in.
8879
this.setState({
89-
height: currentHeight,
90-
currentChild: null,
9180
nextChild
9281
});
9382
}
9483

9584
componentDidUpdate() {
96-
const nextChild = this.refs.nextChild;
97-
98-
// If there is a next child we'll be animating it in soon, so change to its height.
99-
if (nextChild && nextChild.offsetHeight !== this.state.height) {
100-
this.setState({
101-
height: nextChild.offsetHeight
102-
});
103-
}
104-
}
105-
106-
_childLeft = () => {
107-
// Swap the children after the current child left.
108-
this.setState({
109-
currentChild: this.state.nextChild,
110-
nextChild: null
111-
});
112-
}
113-
114-
_childEntered = () => {
115-
// The height animation would have finished, so switch back to auto.
116-
if (this.props.transitionHeight) {
117-
this.setState({
118-
height: 'auto'
119-
});
85+
if (this.state.nextChild) {
86+
this.enterNext();
87+
this.leaveCurrent();
12088
}
12189
}
12290

123-
_wrapChild = (child) => {
91+
_wrapChild = (child, moreProps) => {
12492
// We need to provide this childFactory so that
12593
// ReactCSSTransitionReplaceChild can receive updates to name,
12694
// enter, and leave while it is leaving.
127-
return reactCSSTransitionReplaceChild({
95+
return reactCSSTransitionReplaceChild(objectAssign({
12896
name: this.props.transitionName,
12997
appear: this.props.transitionAppear,
13098
enter: this.props.transitionEnter,
@@ -134,43 +102,58 @@ export default class ReactCSSTransitionReplace extends React.Component {
134102
leaveTimeout: this.props.transitionLeaveTimeout,
135103
onEntered: this._childEntered,
136104
onLeft: this._childLeft
137-
}, child);
105+
}, moreProps), child);
138106
}
139107

140-
render() {
141-
let { style, className = '' } = this.props;
142-
let nextChildShadow;
143-
144-
if (this.props.transitionHeight) {
145-
if (this.state.nextChild) {
146-
nextChildShadow = (
147-
<div ref="nextChild" style={{position: 'absolute', visibility: 'hidden'}}>
148-
{this.state.nextChild}
149-
</div>
150-
);
151-
}
108+
enterNext() {
109+
this.refs.next.componentWillEnter(this._handleDoneEntering);
110+
}
152111

153-
const animatingHeight = this.state.height !== 'auto';
112+
_handleDoneEntering = () => {
113+
this.setState({
114+
currentChild: this.state.nextChild,
115+
nextChild: null
116+
});
117+
}
154118

155-
if (animatingHeight) {
156-
className = `${className} ${this.props.transitionName}-height`;
157-
}
119+
leaveCurrent() {
120+
this.refs.curr.componentWillLeave(this._handleDoneLeaving);
121+
}
122+
123+
render() {
124+
let { currentChild, nextChild } = this.state;
125+
let containerProps = this.props;
126+
const childrenToRender = [];
127+
128+
if (currentChild) {
129+
childrenToRender.push(this._wrapChild(currentChild, {
130+
ref: 'curr', key: 'curr'
131+
}));
132+
}
158133

159-
style = objectAssign(style || {}, {
160-
overflow: animatingHeight ? 'hidden' : 'visible',
161-
height: this.state.height,
134+
if (nextChild) {
135+
const style = objectAssign({}, this.props.style, {
136+
position: 'relative',
137+
overflow: 'hidden',
162138
display: 'block'
163139
});
140+
141+
containerProps = objectAssign({}, this.props, {style});
142+
143+
const nextChildStyle = objectAssign({}, nextChild.props.style, {
144+
position: 'absolute',
145+
left: 0,
146+
top: 0
147+
});
148+
149+
childrenToRender.push(
150+
React.createElement('span', {
151+
style: nextChildStyle,
152+
key: 'next'
153+
}, this._wrapChild(nextChild, {ref: 'next'}))
154+
);
164155
}
165156

166-
return (
167-
<span>
168-
{nextChildShadow}
169-
<ReactTransitionGroup ref="container" {...this.props} childFactory={this._wrapChild}
170-
style={style} className={className}>
171-
{this.state.currentChild}
172-
</ReactTransitionGroup>
173-
</span>
174-
);
157+
return React.createElement(this.props.component, containerProps, childrenToRender);
175158
}
176159
}

0 commit comments

Comments
 (0)