Skip to content

Instantly share code, notes, and snippets.

@apostololeg
Created June 5, 2017 09:45
Show Gist options
  • Save apostololeg/32edb026233f5406d34babb2d1ff14a2 to your computer and use it in GitHub Desktop.
Save apostololeg/32edb026233f5406d34babb2d1ff14a2 to your computer and use it in GitHub Desktop.

=== List

  • selectable-список с возможностью абсолютной кастомизации элементов
  • .scrollable – горизонтальный скролл с фейдингом (scrollbar не реализован)
.List {
height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.List__inner {
margin: 0;
padding: 0;
list-style: none;
}
.List__item {
position: relative;
display: block;
cursor: pointer;
}
.List__item.selected,
.List__item:not(.selected):hover {
background-color: rgba(46, 148, 177, 0.2);
}
.List__item:not(.selected):hover {
opacity: .8;
}
/* scrollable */
.List.scrollable {
margin-left: -2px;
}
.List.scrollable:after {
content: '';
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
pointer-events: none;
}
.List.scrollable.fade-left:after {
background-image: linear-gradient(to right, #222 0%, rgba(0,0,0,0) 40px);
}
.List.scrollable.fade-right:after {
background-image: linear-gradient(to left, #222 0%, rgba(0,0,0,0) 40px);
}
.List.scrollable.fade-left.fade-right:after {
background-image: linear-gradient(to right, #222 0%, rgba(0,0,0,0) 40px),
linear-gradient(to left, #222 0%, rgba(0,0,0,0) 40px);
}
.List.scrollable .List__inner {
white-space: nowrap;
transition: transform .1s ease-out;
overflow-x: auto;
display: inline-block;
}
.List.scrollable .List__item {
display: inline-block;
margin-left: 2px;
margin-bottom: 2px;
transition: opacity .1s ease-out;
}
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
@apostololeg
Copy link
Author

#govnocode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment