Skip to content

Commit 9ab8ff4

Browse files
committed
feat: add onSlideTransitionEnd prop, fix keepPrecedingViewsMounted
1 parent 13bb643 commit 9ab8ff4

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ The duration of the transition between views.
113113

114114
The timing function for the transition between views.
115115

116+
##### `onSlideTransitionEnd: () => any`
117+
118+
If given, will be called when the slide transition ends.
119+
116120
##### `prefixer: Prefixer`
117121

118122
If given, overrides the `inline-style-prefixer` used to autoprefix inline styles.

src/index.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export type Props = {
3333
animateHeight?: ?boolean,
3434
transitionDuration?: ?number,
3535
transitionTimingFunction?: ?string,
36+
onSlideTransitionEnd?: ?() => mixed,
3637
prefixer?: ?Prefixer,
3738
fillParent?: ?boolean,
3839
className?: ?string,
@@ -73,6 +74,7 @@ export type State = {
7374
height: ?number,
7475
transitioning: boolean,
7576
activeView: number,
77+
numViews: number,
7678
prevActiveView: ?number,
7779
}
7880

@@ -118,6 +120,7 @@ export default class ViewSlider extends React.Component<Props, State> {
118120
height: undefined,
119121
transitioning: false,
120122
activeView: this.props.activeView,
123+
numViews: this.props.numViews,
121124
// this is used to determine the correct transitionState for the previous active view.
122125
prevActiveView: null,
123126
}
@@ -176,6 +179,7 @@ export default class ViewSlider extends React.Component<Props, State> {
176179
// phase 3: change height/activeView
177180
newState = {
178181
activeView,
182+
numViews: Math.max(this.state.numViews, activeView + 1),
179183
prevActiveView: this.state.activeView,
180184
height: this.measureHeight(this.views[activeView]),
181185
}
@@ -199,11 +203,18 @@ export default class ViewSlider extends React.Component<Props, State> {
199203
// ignore transitionend events from deeper components
200204
if (event && event.target !== this.viewport) return
201205
// phase 0: unset height and disable transitions
202-
this.setState({
203-
height: undefined,
204-
prevActiveView: null,
205-
transitioning: false,
206-
})
206+
this.setState(
207+
{
208+
height: undefined,
209+
numViews: this.props.numViews,
210+
prevActiveView: null,
211+
transitioning: false,
212+
},
213+
() => {
214+
const { onSlideTransitionEnd } = this.props
215+
if (onSlideTransitionEnd) onSlideTransitionEnd()
216+
}
217+
)
207218
}
208219

209220
componentWillUnmount() {
@@ -295,7 +306,6 @@ export default class ViewSlider extends React.Component<Props, State> {
295306
className,
296307
viewportClassName,
297308
viewportStyle,
298-
numViews,
299309
prefixer,
300310
fillParent,
301311
transitionDuration,
@@ -305,7 +315,7 @@ export default class ViewSlider extends React.Component<Props, State> {
305315
spacing,
306316
} = this.getDefaultedProps()
307317
const animateHeight = this.animateHeight()
308-
const { activeView, height, transitioning } = this.state
318+
const { activeView, numViews, height, transitioning } = this.state
309319

310320
const finalOuterStyle = {
311321
transitionProperty: 'height',

src/simple.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type Props = {
1313
animateHeight?: ?boolean,
1414
transitionDuration?: ?number,
1515
transitionTimingFunction?: ?string,
16+
onSlideTransitionEnd?: ?() => mixed,
1617
prefixer?: ?Prefixer,
1718
fillParent?: ?boolean,
1819
className?: ?string,
@@ -58,19 +59,29 @@ export function createSimpleViewSlider(
5859
const activeView = parseInt(child.key)
5960
const views = [...this.state.views]
6061
views[activeView] = child
61-
if (!this.props.keepViewsMounted) {
62-
views.length = Math.min(views.length, activeView + 1)
63-
}
6462
this.setState({ views, activeView })
65-
} else if (prevProps.keepViewsMounted && !this.props.keepViewsMounted) {
66-
const views = [...this.state.views]
67-
views.length = Math.min(views.length, this.state.activeView + 1)
68-
this.setState({ views })
6963
}
7064
}
7165

7266
renderView = renderView.bind(this)
7367

68+
handleSlideTransitionEnd = () => {
69+
if (!this.props.keepViewsMounted) {
70+
const { views, activeView } = this.state
71+
if (activeView < views.length - 1) {
72+
this.setState(
73+
{
74+
views: views.slice(0, activeView + 1),
75+
},
76+
() => {
77+
const { onSlideTransitionEnd } = this.props
78+
if (onSlideTransitionEnd) onSlideTransitionEnd()
79+
}
80+
)
81+
}
82+
}
83+
}
84+
7485
render(): React.Node {
7586
const {
7687
children, // eslint-disable-line no-unused-vars
@@ -91,6 +102,7 @@ export function createSimpleViewSlider(
91102
renderView={this.renderView}
92103
numViews={views.length}
93104
activeView={activeView}
105+
onSlideTransitionEnd={this.handleSlideTransitionEnd}
94106
/>
95107
)
96108
}

test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ describe('SimpleViewSlider', () => {
217217
comp.setProps({
218218
children: <div key={1}>Child a</div>,
219219
})
220+
expect(comp.update().text()).to.equal('Child 0Child aChild 2')
220221

221222
clock.tick(1000)
222223
expect(comp.update().text()).to.equal('Child 0Child a')

0 commit comments

Comments
 (0)