|
import React, { Component } from 'react' |
|
import classnames from 'classnames' |
|
|
|
import './List.css' |
|
|
|
class List extends Component { |
|
constructor(props) { |
|
super(props) |
|
|
|
this.innerPos = 0 |
|
} |
|
|
|
componentDidMount() { |
|
if (this.props.scrollable) { |
|
this.domElem.addEventListener('wheel', this._onMouseWeel.bind(this)) |
|
} |
|
} |
|
|
|
componentWillReceiveProps(nextProps) { |
|
if (nextProps.selectedID === this.selectedID) { |
|
return |
|
} |
|
|
|
setTimeout(() => { |
|
const cerrentItemIndex = this.getCurrentItemIndex(this.props.selectedID) |
|
const itemWidth = this.inner.offsetWidth / this.props.items.length |
|
const newPos = -cerrentItemIndex * itemWidth + itemWidth |
|
|
|
this.updatePosition(newPos) |
|
this.selectedID = this.props.selectedID |
|
}, 0) |
|
} |
|
|
|
getCurrentItemIndex(id) { |
|
let index = 0; |
|
|
|
this.props.items.some((data, i) => { |
|
if (data.id === id) { |
|
index = i |
|
return true |
|
} |
|
}); |
|
|
|
return index |
|
} |
|
|
|
_onMouseWeel(e) { |
|
const pos = this.innerPos + e.wheelDelta |
|
|
|
this.updatePosition(pos) |
|
} |
|
|
|
updatePosition(pos) { |
|
const wrapWidth = this.domElem.offsetWidth |
|
const innerWidth = this.inner.offsetWidth |
|
const rightLimit = -innerWidth + wrapWidth |
|
|
|
// left border |
|
if (pos > 0) { |
|
pos = 0 |
|
} |
|
// right border |
|
if (pos < rightLimit) { |
|
pos = rightLimit |
|
} |
|
|
|
this.innerPos = pos |
|
this.forceUpdate() |
|
} |
|
|
|
_getFades() { |
|
const { scrollable } = this.props |
|
|
|
if (!this.domElem) { |
|
return {} |
|
} |
|
|
|
const classes = {scrollable: this.props.scrollable} |
|
const wrapWidth = this.domElem.offsetWidth |
|
const innerWidth = this.inner.offsetWidth |
|
const rightLimit = -innerWidth + wrapWidth |
|
const pos = this.innerPos |
|
|
|
if (innerWidth > wrapWidth) { |
|
classes['fade-left'] = pos < 0 |
|
classes['fade-right'] = pos > rightLimit |
|
} |
|
|
|
return classes |
|
} |
|
|
|
_getClasses() { |
|
const { mix } = this.props |
|
const classes = Object.assign({ |
|
'List': true, |
|
[mix]: Boolean(mix) |
|
}, this._getFades()) |
|
|
|
return classnames(classes) |
|
} |
|
|
|
_onItemClick(data) { |
|
this.props.onItemClick(data) |
|
} |
|
|
|
_renderItem(data) { |
|
const id = data.id |
|
const name = data.name |
|
const classes = classnames({ |
|
List__item: true, |
|
selected: id === this.props.selectedID |
|
}); |
|
|
|
return ( |
|
<li className={classes} |
|
key={id} |
|
onClick={this._onItemClick.bind(this, id)} |
|
title={name}> |
|
{data.content} |
|
</li> |
|
) |
|
} |
|
|
|
render() { |
|
const classes = this._getClasses() |
|
const innerStyle = {transform: `translateX(${this.innerPos}px)`} |
|
const itemsContent = this.props.items.map(item => this._renderItem(item)) |
|
|
|
return( |
|
<div className={classes} |
|
ref={elem => this.domElem = elem}> |
|
<ul className='List__inner' |
|
ref={elem => this.inner = elem} |
|
style={innerStyle}> |
|
{itemsContent} |
|
</ul> |
|
</div> |
|
); |
|
} |
|
}; |
|
|
|
export default List |
#govnocode