10 changed files with 243 additions and 70 deletions
@ -0,0 +1,91 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import Scrollbar from 'react-smooth-scrollbar' |
|||
import noop from 'lodash/noop' |
|||
|
|||
import Box from 'components/base/Box' |
|||
|
|||
type Props = { |
|||
maxHeight?: number | string, |
|||
children: any, |
|||
offsetLimit: Object, |
|||
onUpdate: Function, |
|||
} |
|||
|
|||
class GrowScroll extends PureComponent<Props> { |
|||
static defaultProps = { |
|||
onUpdate: noop, |
|||
offsetLimit: { |
|||
y: { |
|||
max: -3, |
|||
min: 3, |
|||
}, |
|||
}, |
|||
} |
|||
|
|||
componentDidMount() { |
|||
const { offsetLimit } = this.props |
|||
|
|||
if (this._scrollbar) { |
|||
this._scrollbar.addListener(function onScroll({ limit, offset }) { |
|||
if (limit.y > 0) { |
|||
const maxY = limit.y + offsetLimit.y.max |
|||
const minY = offsetLimit.y.min |
|||
|
|||
if (offset.y > maxY) { |
|||
this.scrollTo(offset.x, maxY) |
|||
} |
|||
|
|||
if (offset.y < minY) { |
|||
this.scrollTo(offset.x, minY) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
this.handleUpdate(this.props) |
|||
} |
|||
|
|||
componentWillReceiveProps(nextProps: Props) { |
|||
this.handleUpdate(nextProps) |
|||
} |
|||
|
|||
handleUpdate = (props: Props) => { |
|||
if (this._scrollbar) { |
|||
props.onUpdate(this._scrollbar) |
|||
} |
|||
} |
|||
|
|||
_scrollbar = undefined |
|||
|
|||
render() { |
|||
const { onUpdate, children, maxHeight, ...props } = this.props |
|||
|
|||
return ( |
|||
<Box grow relative> |
|||
<Scrollbar |
|||
damping={1} |
|||
style={{ |
|||
...(maxHeight |
|||
? { |
|||
maxHeight, |
|||
} |
|||
: { |
|||
bottom: 0, |
|||
left: 0, |
|||
position: 'absolute', |
|||
right: 0, |
|||
top: 0, |
|||
}), |
|||
}} |
|||
ref={r => r && (this._scrollbar = r.scrollbar)} |
|||
> |
|||
<Box {...props}>{children}</Box> |
|||
</Scrollbar> |
|||
</Box> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default GrowScroll |
@ -0,0 +1,13 @@ |
|||
import React from 'react' |
|||
import { storiesOf } from '@storybook/react' |
|||
|
|||
import Box from 'components/base/Box' |
|||
import GrowScroll from 'components/base/GrowScroll' |
|||
|
|||
const stories = storiesOf('GrowScroll', module) |
|||
|
|||
stories.add('basic', () => ( |
|||
<Box style={{ height: 400, border: '1px solid black' }}> |
|||
<GrowScroll>{[...Array(1000).keys()].map(v => <div key={v}>{v}</div>)}</GrowScroll> |
|||
</Box> |
|||
)) |
Loading…
Reference in new issue