Skip to content

Commit 7a64114

Browse files
authored
[WIP] Replace Transition (reactjs#212)
Replace Transition
1 parent 06f4887 commit 7a64114

17 files changed

+9802
-477
lines changed

.storybook/webpack.config.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
module.exports = (config) => {
2-
config.plugins = config.plugins
3-
.filter(p => p.constructor.name !== 'CaseSensitivePathsPlugin');
1+
const { plugins, rules } = require('webpack-atoms');
42

3+
module.exports = (config) => {
54
config.module = {
6-
loaders: [
7-
{
8-
test: /\.js$/,
9-
exclude: /node_modules/,
10-
loader: 'babel-loader!css-literal-loader',
11-
},
12-
{
13-
test: /\.css$/,
14-
loader: 'style-loader!css-loader',
15-
},
5+
rules: [
6+
rules.js.inlineCss(),
7+
rules.css({ modules: true }),
168
],
179
};
1810

11+
config.plugins.push(
12+
plugins.extractText({ disable: true })
13+
)
1914
return config;
2015
};

package.json

+4-5
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"warning": "^3.0.0"
5858
},
5959
"devDependencies": {
60-
"@storybook/react": "3.2.10",
60+
"@storybook/addon-actions": "^3.2.11",
61+
"@storybook/react": "^3.2.11",
6162
"babel-cli": "^6.24.0",
6263
"babel-core": "^6.24.0",
6364
"babel-eslint": "^7.1.1",
@@ -70,8 +71,6 @@
7071
"babel-preset-latest": "^6.24.0",
7172
"babel-preset-react": "^6.23.0",
7273
"babel-preset-stage-2": "^6.18.0",
73-
"css-literal-loader": "^0.2.0",
74-
"css-loader": "^0.28.0",
7574
"enzyme": "^3.0.0",
7675
"enzyme-adapter-react-16": "^1.0.0",
7776
"eslint": "^3.17.1",
@@ -86,8 +85,8 @@
8685
"release-script": "^1.0.2",
8786
"rimraf": "^2.6.1",
8887
"sinon": "^2.1.0",
89-
"style-loader": "^0.16.1",
90-
"webpack": "^2.2.1"
88+
"webpack": "^3.6.0",
89+
"webpack-atoms": "^3.0.2"
9190
},
9291
"release-script": {
9392
"altPkgRootFolder": "lib"

src/CSSTransition.js

+1-53
Original file line numberDiff line numberDiff line change
@@ -104,59 +104,7 @@ const propTypes = {
104104
* the `example-enter` CSS class and the `example-enter-active` CSS class
105105
* added in the next tick. This is a convention based on the `classNames` prop.
106106
*
107-
* ```js
108-
* import CSSTransition from 'react-transition-group/CSSTransition';
109-
*
110-
* const Fade = ({ children, ...props }) => (
111-
* <CSSTransition
112-
* {...props}
113-
* timeout={500}
114-
* classNames="fade"
115-
* >
116-
* {children}
117-
* </CSSTransition>
118-
* );
119-
*
120-
* class FadeInAndOut extends React.Component {
121-
* constructor(...args) {
122-
* super(...args);
123-
* this.state= { show: false }
124-
*
125-
* setInterval(() => {
126-
* this.setState({ show: !this.state.show })
127-
* }, 5000)
128-
* }
129-
* render() {
130-
* return (
131-
* <Fade in={this.state.show}>
132-
* <div>Hello world</div>
133-
* </Fade>
134-
* )
135-
* }
136-
* }
137-
* ```
138-
*
139-
* And the corresponding CSS for the `<Fade>` component:
140-
*
141-
* ```css
142-
* .fade-enter {
143-
* opacity: 0.01;
144-
* }
145-
*
146-
* .fade-enter.fade-enter-active {
147-
* opacity: 1;
148-
* transition: opacity 500ms ease-in;
149-
* }
150-
*
151-
* .fade-exit {
152-
* opacity: 1;
153-
* }
154-
*
155-
* .fade-exit.fade-exit-active {
156-
* opacity: 0.01;
157-
* transition: opacity 300ms ease-in;
158-
* }
159-
* ```
107+
* <iframe src="https://codesandbox.io/embed/yv645oq21x?autoresize=1&fontsize=12&hidenavigation=1&moduleview=1" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
160108
*/
161109
class CSSTransition extends React.Component {
162110
onEnter = (node, appearing) => {

src/ReplaceTransition.js

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import { findDOMNode } from 'react-dom'
4+
import TransitionGroup from './TransitionGroup';
5+
6+
const propTypes = {
7+
in: PropTypes.bool.isRequired,
8+
children(props, propName) {
9+
if (React.Children.count(props[propName]) !== 2)
10+
return new Error(`"${propName}" must be exactly two transition components.`)
11+
12+
return null;
13+
},
14+
};
15+
16+
/**
17+
* The `<ReplaceTransition>` component is a specialized `Transition` component
18+
* that animates between two children.
19+
*
20+
* ```jsx
21+
* <ReplaceTransition in>
22+
* <Fade><div>I appear first</div></Fade>
23+
* <Fade><div>I replace the above</div></Fade>
24+
* </ReplaceTransition>
25+
* ```
26+
*/
27+
class ReplaceTransition extends React.Component {
28+
handleEnter = (...args) => this.handleLifecycle('onEnter', 0, args)
29+
handleEntering = (...args) => this.handleLifecycle('onEntering', 0, args)
30+
handleEntered = (...args) => this.handleLifecycle('onEntered', 0, args)
31+
32+
handleExit = (...args) => this.handleLifecycle('onExit', 1, args)
33+
handleExiting = (...args) => this.handleLifecycle('onExiting', 1, args)
34+
handleExited = (...args) => this.handleLifecycle('onExited', 1, args)
35+
36+
handleLifecycle(handler, idx, originalArgs) {
37+
const { children } = this.props;
38+
const child = React.Children.toArray(children)[idx];
39+
40+
if (child.props[handler]) child.props[handler](...originalArgs)
41+
if (this.props[handler]) this.props[handler](findDOMNode(this))
42+
}
43+
44+
render() {
45+
const {
46+
children,
47+
in: inProp,
48+
...props
49+
} = this.props;
50+
const [first, second] = React.Children.toArray(children);
51+
52+
delete props.onEnter;
53+
delete props.onEntering;
54+
delete props.onEntered;
55+
delete props.onExit;
56+
delete props.onExiting;
57+
delete props.onExited;
58+
59+
return (
60+
<TransitionGroup {...props}>
61+
{inProp ?
62+
React.cloneElement(first, {
63+
key: 'first',
64+
onEnter: this.handleEnter,
65+
onEntering: this.handleEntering,
66+
onEntered: this.handleEntered,
67+
68+
}) :
69+
React.cloneElement(second, {
70+
key: 'second',
71+
onEnter: this.handleExit,
72+
onEntering: this.handleExiting,
73+
onEntered: this.handleExited,
74+
})
75+
}
76+
</TransitionGroup>
77+
);
78+
}
79+
}
80+
81+
ReplaceTransition.propTypes = propTypes;
82+
83+
export default ReplaceTransition;

src/Transition.js

+5
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ export const EXITING = 'exiting';
8686
* stay there for 500ms (the value of `timeout`) when finally switches to `'entered'`.
8787
*
8888
* When `in` is `false` the same thing happens except the state moves from `'exiting'` to `'exited'`.
89+
*
90+
* ### Example
91+
*
92+
* <iframe src="https://codesandbox.io/embed/y26rj99yov?autoresize=1&fontsize=12&hidenavigation=1&moduleview=1" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
93+
*
8994
*/
9095
class Transition extends React.Component {
9196
static contextTypes = {

src/TransitionGroup.js

+2-41
Original file line numberDiff line numberDiff line change
@@ -66,47 +66,8 @@ const defaultProps = {
6666
* As items are removed or added to the TodoList the `in` prop is toggled
6767
* automatically by the `<TransitionGroup>`. You can use _any_ `<Transition>`
6868
* component in a `<TransitionGroup>`, not just css.
69-
*
70-
* ```jsx
71-
* import TransitionGroup from 'react-transition-group/TransitionGroup';
72-
*
73-
* class TodoList extends React.Component {
74-
* constructor(props) {
75-
* super(props)
76-
* this.state = {items: ['hello', 'world', 'click', 'me']}
77-
* }
78-
* handleAdd() {
79-
* const newItems = this.state.items.concat([
80-
* prompt('Enter some text')
81-
* ]);
82-
* this.setState({ items: newItems });
83-
* }
84-
* handleRemove(i) {
85-
* let newItems = this.state.items.slice();
86-
* newItems.splice(i, 1);
87-
* this.setState({items: newItems});
88-
* }
89-
* render() {
90-
* return (
91-
* <div>
92-
* <button onClick={() => this.handleAdd()}>Add Item</button>
93-
* <TransitionGroup>
94-
* {this.state.items.map((item, i) => (
95-
* <FadeTransition key={item}>
96-
* <div>
97-
* {item}{' '}
98-
* <button onClick={() => this.handleRemove(i)}>
99-
* remove
100-
* </button>
101-
* </div>
102-
* </FadeTransition>
103-
* ))}
104-
* </TransitionGroup>
105-
* </div>
106-
* );
107-
* }
108-
* }
109-
* ```
69+
* *
70+
* <iframe src="https://codesandbox.io/embed/43v5wj62q9?autoresize=1&fontsize=12&hidenavigation=1&moduleview=1" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
11071
*
11172
* Note that `<TransitionGroup>` does not define any animation behavior!
11273
* Exactly _how_ a list item animates is up to the individual `<Transition>`

stories/NestedTransition.js

+2-72
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,8 @@
11
import React from 'react';
2-
import CSSTransition from '../src/CSSTransition';
32
import StoryFixture from './StoryFixture';
43

5-
6-
const _ = css`
7-
.nested-fade-enter,
8-
.nested-fade-appear,
9-
.nested-fade-exit {
10-
transition: opacity 500ms;
11-
}
12-
13-
.nested-fade-enter,
14-
.nested-fade-appear {
15-
opacity: 0;
16-
}
17-
18-
.nested-fade-enter-active,
19-
.nested-fade-appear-active {
20-
opacity: 1
21-
}
22-
23-
.nested-fade-exit {
24-
opacity: 1;
25-
}
26-
27-
.nested-fade-exit-active {
28-
opacity: 0
29-
}
30-
31-
.nested-scale-enter,
32-
.nested-scale-appear,
33-
.nested-scale-exit {
34-
transition: transform 500ms;
35-
}
36-
37-
.nested-scale-enter,
38-
.nested-scale-appear {
39-
transform: scale(0);
40-
}
41-
42-
.nested-scale-enter-active,
43-
.nested-scale-appear-active {
44-
transform: scale(1);
45-
}
46-
47-
.nested-scale-exit {
48-
transform: scale(1);
49-
}
50-
51-
.nested-scale-exit-active {
52-
transform: scale(0);
53-
}
54-
`;
4+
import Fade from './transitions/Fade';
5+
import Scale from './transitions/Scale';
556

567
const FadeAndScale = (props) => (
578
<Fade {...props}>
@@ -72,27 +23,6 @@ const FadeAndScale = (props) => (
7223
</Fade>
7324
)
7425

75-
const Fade = (props) => {
76-
return (
77-
<CSSTransition
78-
{...props}
79-
timeout={500}
80-
classNames="nested-fade"
81-
/>
82-
)
83-
}
84-
85-
86-
const Scale = (props) => {
87-
return (
88-
<CSSTransition
89-
{...props}
90-
timeout={500}
91-
classNames="nested-scale"
92-
/>
93-
)
94-
}
95-
9626

9727
export default class Example extends React.Component {
9828
constructor(props, context) {

0 commit comments

Comments
 (0)