Skip to content

Commit eaa87c9

Browse files
committed
Merge pull request react-bootstrap#1048 from react-bootstrap/overlay-transition-hooks
[added] Overlay and OverlayTrigger accept Transition callbacks
2 parents 381f616 + d272389 commit eaa87c9

File tree

3 files changed

+92
-14
lines changed

3 files changed

+92
-14
lines changed

src/Overlay.js

+43-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,20 @@ class Overlay extends React.Component {
5959
);
6060

6161
if (Transition) {
62+
let { onExit, onExiting, onEnter, onEntering, onEntered } = props;
63+
6264
// This animates the child node by injecting props, so it must precede
6365
// anything that adds a wrapping div.
6466
child = (
6567
<Transition
6668
in={props.show}
6769
transitionAppear
70+
onExit={onExit}
71+
onExiting={onExiting}
6872
onExited={this.onHiddenListener}
73+
onEnter={onEnter}
74+
onEntering={onEntering}
75+
onEntered={onEntered}
6976
>
7077
{child}
7178
</Transition>
@@ -93,8 +100,12 @@ class Overlay extends React.Component {
93100
);
94101
}
95102

96-
handleHidden() {
103+
handleHidden(...args) {
97104
this.setState({exited: true});
105+
106+
if (this.props.onExited) {
107+
this.props.onExited(...args);
108+
}
98109
}
99110
}
100111

@@ -120,7 +131,37 @@ Overlay.propTypes = {
120131
animation: React.PropTypes.oneOfType([
121132
React.PropTypes.bool,
122133
CustomPropTypes.elementType
123-
])
134+
]),
135+
136+
/**
137+
* Callback fired before the Overlay transitions in
138+
*/
139+
onEnter: React.PropTypes.func,
140+
141+
/**
142+
* Callback fired as the Overlay begins to transition in
143+
*/
144+
onEntering: React.PropTypes.func,
145+
146+
/**
147+
* Callback fired after the Overlay finishes transitioning in
148+
*/
149+
onEntered: React.PropTypes.func,
150+
151+
/**
152+
* Callback fired right before the Overlay transitions out
153+
*/
154+
onExit: React.PropTypes.func,
155+
156+
/**
157+
* Callback fired as the Overlay begins to transition out
158+
*/
159+
onExiting: React.PropTypes.func,
160+
161+
/**
162+
* Callback fired after the Overlay finishes transitioning out
163+
*/
164+
onExited: React.PropTypes.func
124165
};
125166

126167
Overlay.defaultProps = {

src/OverlayTrigger.js

+14-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import createChainedFunction from './utils/createChainedFunction';
55
import createContextWrapper from './utils/createContextWrapper';
66
import Overlay from './Overlay';
77
import warning from 'react/lib/warning';
8-
8+
import pick from 'lodash/object/pick';
99
/**
1010
* Check if value one is inside or equal to the of value
1111
*
@@ -148,24 +148,26 @@ const OverlayTrigger = React.createClass({
148148
},
149149

150150
getOverlay() {
151-
let props = {
152-
show: this.state.isOverlayShown,
153-
onHide: this.hide,
154-
rootClose: this.props.rootClose,
155-
animation: this.props.animation,
151+
let overlayProps = {
152+
...pick(this.props, Object.keys(Overlay.propTypes)),
153+
show: this.state.isOverlayShown,
154+
onHide: this.hide,
156155
target: this.getOverlayTarget,
157-
placement: this.props.placement,
158-
container: this.props.container,
159-
containerPadding: this.props.containerPadding
156+
onExit: this.props.onExit,
157+
onExiting: this.props.onExiting,
158+
onExited: this.props.onExited,
159+
onEnter: this.props.onEnter,
160+
onEntering: this.props.onEntering,
161+
onEntered: this.props.onEntered
160162
};
161163

162164
let overlay = cloneElement(this.props.overlay, {
163-
placement: props.placement,
164-
container: props.container
165+
placement: overlayProps.placement,
166+
container: overlayProps.container
165167
});
166168

167169
return (
168-
<Overlay {...props}>
170+
<Overlay {...overlayProps}>
169171
{ overlay }
170172
</Overlay>
171173
);

test/OverlayTriggerSpec.js

+35
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,41 @@ describe('OverlayTrigger', function() {
3939
instance.state.isOverlayShown.should.be.true;
4040
});
4141

42+
it('Should pass transition callbacks to Transition', function (done) {
43+
let count = 0;
44+
let increment = ()=> count++;
45+
46+
let overlayTrigger;
47+
48+
let instance = ReactTestUtils.renderIntoDocument(
49+
<OverlayTrigger
50+
trigger='click'
51+
overlay={<div>test</div>}
52+
onHide={()=>{}}
53+
onExit={increment}
54+
onExiting={increment}
55+
onExited={()=> {
56+
increment();
57+
expect(count).to.equal(6);
58+
done();
59+
}}
60+
onEnter={increment}
61+
onEntering={increment}
62+
onEntered={()=> {
63+
increment();
64+
ReactTestUtils.Simulate.click(overlayTrigger);
65+
}}
66+
>
67+
<button>button</button>
68+
</OverlayTrigger>
69+
);
70+
71+
overlayTrigger = React.findDOMNode(instance);
72+
73+
ReactTestUtils.Simulate.click(overlayTrigger);
74+
});
75+
76+
4277
it('Should forward requested context', function() {
4378
const contextTypes = {
4479
key: React.PropTypes.string

0 commit comments

Comments
 (0)