<div class="js-sortable" data-name="">
<ol class="Sortable">
</ol>
</div>
<div class="js-sortable" data-name="{{name}}">
<ol class="Sortable">
{{#each items}}
<li class="Sortable-item" data-value="{{value}}">{{text}}</li>
{{/each}}
</ol>
</div>
/* No context defined for this component. */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import update from 'react/lib/update';
import cx from 'classnames';
import { DragDropContext } from 'react-dnd';
import TouchBackend from 'react-dnd-touch-backend';
import SortableItem from './Sortable-item/SortableItem';
class Container extends Component {
static propTypes = {
style: PropTypes.object,
modifier: PropTypes.string,
items: PropTypes.array,
name: PropTypes.string
};
constructor(props) {
super(props);
this.state = {
selected: null,
items: this.props.items
};
}
serializeItems = ()=> {
return this.state.items
.map((item)=> item.value)
.join(',');
};
moveItem = (dragIndex, hoverIndex)=> {
const { items } = this.state;
const dragItem = items[dragIndex];
this.setState(update(this.state, {
items: {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragItem]
]
}
}));
};
selectItem = (index)=> {
return (event)=> {
event.preventDefault();
this.setState({
selected: index
});
};
};
shiftItem = (amount)=> {
return (event)=> {
event.preventDefault();
const { items, selected } = this.state;
const dragItem = items[selected];
const newIndex = selected + amount;
if (newIndex < 0) return;
if (newIndex > items.length - 1) return;
this.setState(update(this.state, {
items: {
$splice: [
[selected, 1],
[newIndex, 0, dragItem]
]
}
}));
this.selectItem(newIndex)(event);
};
};
shiftItemUp = this.shiftItem(-1);
shiftItemDown = this.shiftItem(1);
onKeyDown = (index)=> {
return (event)=> {
const { selected } = this.state;
if (event.keyCode == 32) {
// Spacebar
this.selectItem(index)(event);
} else if (selected != null && event.keyCode == 38) {
// Up arrow
this.shiftItemUp(event);
} else if (selected != null && event.keyCode == 40) {
// Down arrow
this.shiftItemDown(event);
}
};
};
render() {
const { items } = this.state;
return (
<ol
style={this.props.style}
className={cx('Sortable', this.props.modifier)}
>
{items.map((item, i) => (
<SortableItem
key={item.id}
index={i}
id={item.id}
text={item.text}
moveItem={this.moveItem}
selectItem={this.selectItem(i)}
onKeyDown={this.onKeyDown(i)}
isSelected={this.state.selected === i}
/>
))}
<input
type="hidden"
name={this.props.name}
defaultValue={this.serializeItems()}
/>
</ol>
);
}
}
export default DragDropContext(TouchBackend({
enableMouseEvents: true
}))(Container);
$transition: transform $transition-time-default $transition-move-default;
.Sortable {
@include unstyled-list;
}
.Sortable-item {
@include Elevation("Card");
position: relative;
display: flex;
padding: .5rem 1rem;
align-items: center;
text-align: left;
background-color: get-color(neutral, 0);
border: 1px solid get-color(neutral, 100);
border-radius: $Border-radius--500;
outline: 0;
cursor: grab;
transition: $transition;
&:hover {
@include Elevate("Card-hover");
@include ZIndex("Card-hover");
}
&:active,
&:focus {
@include Elevate("Card-pressed");
@include ZIndex("Card-pressed");
}
}
.Sortable-item + .Sortable-item {
margin-top: .5rem;
}
.Sortable-item .DragHandle {
margin-right: 1rem;
}
There are no notes for this item.