Skip to content

Commit

Permalink
feat: add onSlideTransitionEnd prop, fix keepPrecedingViewsMounted
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1211 committed Dec 14, 2021
1 parent 13bb643 commit 9ab8ff4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 14 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ The duration of the transition between views.

The timing function for the transition between views.

##### `onSlideTransitionEnd: () => any`

If given, will be called when the slide transition ends.

##### `prefixer: Prefixer`

If given, overrides the `inline-style-prefixer` used to autoprefix inline styles.
Expand Down
24 changes: 17 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type Props = {
animateHeight?: ?boolean,
transitionDuration?: ?number,
transitionTimingFunction?: ?string,
onSlideTransitionEnd?: ?() => mixed,
prefixer?: ?Prefixer,
fillParent?: ?boolean,
className?: ?string,
Expand Down Expand Up @@ -73,6 +74,7 @@ export type State = {
height: ?number,
transitioning: boolean,
activeView: number,
numViews: number,
prevActiveView: ?number,
}

Expand Down Expand Up @@ -118,6 +120,7 @@ export default class ViewSlider extends React.Component<Props, State> {
height: undefined,
transitioning: false,
activeView: this.props.activeView,
numViews: this.props.numViews,
// this is used to determine the correct transitionState for the previous active view.
prevActiveView: null,
}
Expand Down Expand Up @@ -176,6 +179,7 @@ export default class ViewSlider extends React.Component<Props, State> {
// phase 3: change height/activeView
newState = {
activeView,
numViews: Math.max(this.state.numViews, activeView + 1),
prevActiveView: this.state.activeView,
height: this.measureHeight(this.views[activeView]),
}
Expand All @@ -199,11 +203,18 @@ export default class ViewSlider extends React.Component<Props, State> {
// ignore transitionend events from deeper components
if (event && event.target !== this.viewport) return
// phase 0: unset height and disable transitions
this.setState({
height: undefined,
prevActiveView: null,
transitioning: false,
})
this.setState(
{
height: undefined,
numViews: this.props.numViews,
prevActiveView: null,
transitioning: false,
},
() => {
const { onSlideTransitionEnd } = this.props
if (onSlideTransitionEnd) onSlideTransitionEnd()
}
)
}

componentWillUnmount() {
Expand Down Expand Up @@ -295,7 +306,6 @@ export default class ViewSlider extends React.Component<Props, State> {
className,
viewportClassName,
viewportStyle,
numViews,
prefixer,
fillParent,
transitionDuration,
Expand All @@ -305,7 +315,7 @@ export default class ViewSlider extends React.Component<Props, State> {
spacing,
} = this.getDefaultedProps()
const animateHeight = this.animateHeight()
const { activeView, height, transitioning } = this.state
const { activeView, numViews, height, transitioning } = this.state

const finalOuterStyle = {
transitionProperty: 'height',
Expand Down
26 changes: 19 additions & 7 deletions src/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type Props = {
animateHeight?: ?boolean,
transitionDuration?: ?number,
transitionTimingFunction?: ?string,
onSlideTransitionEnd?: ?() => mixed,
prefixer?: ?Prefixer,
fillParent?: ?boolean,
className?: ?string,
Expand Down Expand Up @@ -58,19 +59,29 @@ export function createSimpleViewSlider(
const activeView = parseInt(child.key)
const views = [...this.state.views]
views[activeView] = child
if (!this.props.keepViewsMounted) {
views.length = Math.min(views.length, activeView + 1)
}
this.setState({ views, activeView })
} else if (prevProps.keepViewsMounted && !this.props.keepViewsMounted) {
const views = [...this.state.views]
views.length = Math.min(views.length, this.state.activeView + 1)
this.setState({ views })
}
}

renderView = renderView.bind(this)

handleSlideTransitionEnd = () => {
if (!this.props.keepViewsMounted) {
const { views, activeView } = this.state
if (activeView < views.length - 1) {
this.setState(
{
views: views.slice(0, activeView + 1),
},
() => {
const { onSlideTransitionEnd } = this.props
if (onSlideTransitionEnd) onSlideTransitionEnd()
}
)
}
}
}

render(): React.Node {
const {
children, // eslint-disable-line no-unused-vars
Expand All @@ -91,6 +102,7 @@ export function createSimpleViewSlider(
renderView={this.renderView}
numViews={views.length}
activeView={activeView}
onSlideTransitionEnd={this.handleSlideTransitionEnd}
/>
)
}
Expand Down
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ describe('SimpleViewSlider', () => {
comp.setProps({
children: <div key={1}>Child a</div>,
})
expect(comp.update().text()).to.equal('Child 0Child aChild 2')

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

0 comments on commit 9ab8ff4

Please sign in to comment.