mirror of
https://github.com/xodio/xod.git
synced 2026-03-25 01:56:54 +01:00
feat(tabs, sortables): add tabs reordering feature
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
>
|
||||
×
|
||||
</span>
|
||||
|
||||
@@ -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
19
src/client/utils/array.js
Normal 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'));
|
||||
Reference in New Issue
Block a user