feat(tabs, sortables): add tabs reordering feature

This commit is contained in:
Kirill Shumilov
2016-08-23 20:28:07 +03:00
parent 3b1b9c413f
commit 97d2e9ec1d
5 changed files with 94 additions and 12 deletions

View File

@@ -44,6 +44,7 @@
"react-hotkeys": "git+https://github.com/brusherru/react-hotkeys.git#npm",
"react-redux": "^4.0.6",
"react-skylight": "^0.4.0",
"react-sortable-hoc": "0.0.7",
"react-ui-tree": "^2.5.0",
"redux": "^3.0.5",
"redux-thunk": "^2.1.0",

View File

@@ -5,6 +5,8 @@
padding: 0 10px 0 14px;
height: 26px;
box-sizing: border-box;
background: $color-tabs-unactive-background;
color: $color-tabs-unactive-text;
line-height: 30px;
@@ -13,6 +15,7 @@
border-top-left-radius: 4px;
text-shadow: 0 1px 0 rgba(0,0,0, .5);
cursor: default;
white-space: nowrap;
transition: 0.1s ease-out all;

View File

@@ -15,14 +15,14 @@ const TabsItem = ({ data, onClick, onClose }) => {
return (
<li
className={classes}
onClick={handleClick}
onMouseDown={handleClick}
>
<span className="tab-name">
{data.name}
</span>
<span
className="tab-close"
onClick={handleClose}
onMouseDown={handleClose}
>
&times;
</span>

View File

@@ -5,15 +5,65 @@ import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import * as EditorSelectors from '../selectors';
import { arrayMoveIndex, arrayUpdateIndex, arrayIndexById } from 'xod/client/utils/array';
import {
SortableContainer as sortableContainer,
SortableElement as sortableElement,
} from 'react-sortable-hoc';
import TabsContainer from '../components/TabsContainer';
import TabsItem from '../components/TabsItem';
const SortableItem = sortableElement(
({ value }) => {
return (
<TabsItem
key={value.id}
data={value}
onClick={value.onClick}
onClose={value.onClose}
/>
);
}
);
const SortableList = sortableContainer(
({ items, onClick, onClose }) => (
<TabsContainer>
{items.map((value, index) => {
const item = R.merge(
value,
{
onClick,
onClose,
}
);
return (
<SortableItem
key={`item-${value.id}`}
index={index}
value={item}
onClick={onClick}
onClose={onClose}
/>
);
}
)}
</TabsContainer>
)
);
class Tabs extends React.Component {
constructor(props) {
super(props);
this.onSwitchPatch = this.onSwitchPatch.bind(this);
this.onCloseTab = this.onCloseTab.bind(this);
this.onSortEnd = this.onSortEnd.bind(this);
}
onSwitchPatch(patchId) {
@@ -24,6 +74,14 @@ class Tabs extends React.Component {
return this.props.actions.closeTab(patchId);
}
onSortEnd(changes) {
const sortedTabs = arrayMoveIndex(changes.oldIndex, changes.newIndex, this.getTabs());
const newTabs = arrayUpdateIndex(sortedTabs);
const indexedTabs = arrayIndexById(newTabs);
this.props.actions.sortTabs(indexedTabs);
}
getTabs() {
return R.sortBy(
R.prop('index')
@@ -33,16 +91,17 @@ class Tabs extends React.Component {
render() {
const tabs = this.getTabs();
return (
<TabsContainer>
{tabs.map(tab =>
<TabsItem
key={tab.id}
data={tab}
onClick={this.onSwitchPatch}
onClose={this.onCloseTab}
/>
)}
</TabsContainer>
<SortableList
items={tabs}
onSortEnd={this.onSortEnd}
axis="x"
lockAxis="x"
lockToContainerEdges
lockOffset="0%"
onClick={this.onSwitchPatch}
onClose={this.onCloseTab}
/>
);
}
}

19
src/client/utils/array.js Normal file
View File

@@ -0,0 +1,19 @@
import R from 'ramda';
const mapIndexed = R.addIndex(R.map);
export const arrayMoveIndex = R.curry(
(oldIndex, newIndex, array) => {
const oldItem = R.nth(oldIndex, array);
const newItem = R.nth(newIndex, array);
return R.pipe(
R.update(oldIndex, newItem),
R.update(newIndex, oldItem)
)(array);
}
);
export const arrayUpdateIndex = mapIndexed((item, index) => R.assoc('index', index, item));
export const arrayIndexById = R.indexBy(R.prop('id'));