rc-tabs@10.0.0

tabs ui component for react

/* eslint react/no-multi-comp:0, no-console:0, react/prop-types:0 */
import 'rc-tabs/assets/index.css';
import React from 'react';
import HTML5Backend from 'react-dnd-html5-backend'
import ReactDOM from 'react-dom';
import Tabs, { TabPane } from 'rc-tabs';
import update from 'immutability-helper';
import TabContent from 'rc-tabs/lib/SwipeableTabContent';
import ScrollableInkTabBar from 'rc-tabs/lib/ScrollableInkTabBar';
import {
	DragSource,
  DropTarget,
  DragDropContextProvider,
} from 'react-dnd';

// Drag & Drop node
class TabNode extends React.Component {
  render() {
		const {
			connectDragSource,
      connectDropTarget,
      children,
		} = this.props

		return connectDragSource(
			connectDropTarget(children),
    );
	}
}

const cardTarget = {
  drop(props, monitor) {
    const dragKey = monitor.getItem().index;
    const hoverKey = props.index;

    if (dragKey === hoverKey) {
      return;
    }

    props.moveTabNode(dragKey, hoverKey);
    monitor.getItem().index = hoverKey;
  },
};

const cardSource = {
	beginDrag(props) {
		return {
			id: props.id,
			index: props.index,
		}
	},
};

const WrapTabNode = DropTarget(
	'DND_NODE',
	cardTarget,
	(connect) => ({
		connectDropTarget: connect.dropTarget(),
	}),
)(
	DragSource(
		'DND_NODE',
		cardSource,
		(connect, monitor) => ({
			connectDragSource: connect.dragSource(),
			isDragging: monitor.isDragging(),
		}),
	)(TabNode),
);

// Demo
class Demo extends React.Component {
  state = {
    activeKey: '1',
    tabs: ['1', '2', '3'],
  };

  onChange = (activeKey) => {
    console.log(`onChange ${activeKey}`);
    this.setState({
      activeKey,
    });
  }

  onTabClick = (key) => {
    console.log(`onTabClick ${key}`);
    if (key === this.state.activeKey) {
      this.setState({
        activeKey: '',
      });
    }
  }

  moveTabNode = (dragKey, hoverKey) => {
    const { tabs } = this.state;
    const dragIndex = tabs.indexOf(dragKey);
    const hoverIndex = tabs.indexOf(hoverKey);
    const dragTab = this.state.tabs[dragIndex];
    this.setState(
			update(this.state, {
				tabs: {
					$splice: [[dragIndex, 1], [hoverIndex, 0, dragTab]],
				},
			}),
		);
  };

  renderTabBarNode = (node) => {
    return (
      <WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>{node}</WrapTabNode>
    );
  };

  render() {
    return (
      <DragDropContextProvider backend={HTML5Backend}>
        <div style={{ margin: 20 }}>
          <h1>Simple Tabs</h1>
          <Tabs
            renderTabBar={() => (
              <ScrollableInkTabBar onTabClick={this.onTabClick}>
                {this.renderTabBarNode}
              </ScrollableInkTabBar>
            )}
            renderTabContent={() => <TabContent animatedWithMargin />}
            activeKey={this.state.activeKey}
            onChange={this.onChange}
          >
            {this.state.tabs.map(id => (
              <TabPane tab={`tab ${id}`} key={id}>
                {id}
              </TabPane>
            ))}
          </Tabs>
        </div>
      </DragDropContextProvider>
    );
  }
}

ReactDOM.render(<Demo />, document.getElementById('__react-content'));
Fork me on GitHub