diff --git a/README.md b/README.md index a923f09..e55c921 100644 --- a/README.md +++ b/README.md @@ -180,3 +180,10 @@ ReactDOM.render( document.getElementById('root') ) ``` + +### Additional props + +##### `keepPrecedingViewsMounted: boolean` (default: `false`) + +If `true`, `SimpleViewSlider` will keep views preceding the active view mounted, but not views following the active view. +(As mentioned above, the order is determined by the `children`'s `key`s.) diff --git a/src/index.js b/src/index.js index b2faa94..16495d4 100644 --- a/src/index.js +++ b/src/index.js @@ -318,7 +318,9 @@ export default class ViewSlider extends React.Component { const finalViewportStyle = { position: 'relative', - transform: `translateX(${activeView * spacing * (rtl ? 100 : -100)}%)`, + transform: `translateX(calc(${activeView * + spacing * + (rtl ? 100 : -100)}% + 0px))`, whiteSpace: 'nowrap', minHeight: '100%', direction: rtl ? 'rtl' : 'ltr', diff --git a/src/simple.js b/src/simple.js index 34ccec9..335941d 100644 --- a/src/simple.js +++ b/src/simple.js @@ -9,6 +9,7 @@ import type { Props as ViewSliderProps, ViewProps } from './index' export type Props = { children?: any, keepViewsMounted?: ?boolean, + keepPrecedingViewsMounted?: ?boolean, animateHeight?: ?boolean, transitionDuration?: ?number, transitionTimingFunction?: ?string, @@ -48,10 +49,7 @@ export function createSimpleViewSlider( const activeView = parseInt(child.key) const views = [] views[activeView] = child - this.state = { - views, - activeView, - } + this.state = { views, activeView } } componentDidUpdate(prevProps: Props) { @@ -60,10 +58,14 @@ export function createSimpleViewSlider( const activeView = parseInt(child.key) const views = [...this.state.views] views[activeView] = child - this.setState({ - views, - activeView, - }) + 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 }) } } @@ -75,12 +77,15 @@ export function createSimpleViewSlider( // Flow's React.ComponentType + defaultProps is foobar... spacing, rtl, + keepViewsMounted, + keepPrecedingViewsMounted, ...props } = this.props const { activeView, views } = this.state return ( { clock.tick(1000) expect(comp.text()).to.equal('Child 1') + comp.unmount() + }) + it('keepViewsMounted works', () => { + const comp = mount( + +
Child 0
+
+ ) + + expect(comp.text()).to.equal('Child 0') + + comp.setProps({ + children:
Child 1
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1') + + comp.setProps({ + children:
Child 2
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1Child 2') + + comp.setProps({ + children:
Child a
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child aChild 2') + + comp.unmount() + }) + it('keepPrecedingViewsMounted works', () => { + const comp = mount( + +
Child 0
+
+ ) + + expect(comp.text()).to.equal('Child 0') + + comp.setProps({ + children:
Child 1
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1') + + comp.setProps({ + children:
Child 2
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1Child 2') + + comp.setProps({ + children:
Child a
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child a') + + comp.unmount() + }) + it('changing keepPrecedingViewsMounted works', () => { + const comp = mount( + +
Child 0
+
+ ) + + expect(comp.text()).to.equal('Child 0') + + comp.setProps({ + children:
Child 1
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1') + + comp.setProps({ + children:
Child 2
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child 1Child 2') + + comp.setProps({ + keepViewsMounted: false, + keepPrecedingViewsMounted: true, + children:
Child a
, + }) + + clock.tick(1000) + expect(comp.update().text()).to.equal('Child 0Child a') + comp.unmount() }) })