Tabs

by evgkch

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<div id="app"></div>

CSS

body {
  width: 100%;
}
.tabs-title {
  display: flex;
}

.tab {
   padding: 5px;
   margin: 5px;
   background-color: white;
}

.active-tab {
  color: blue;
}

.items {
  display: flex;
  flex-flow: row;
  flex-wrap: wrap;
}
.item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px;
  margin: 5px;
  background-color: white;
  cursor: pointer;
  user-select: none;
  flex: 1;
}
.item:hover {
  background-color: LemonChiffon;
}
.counter {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 5px;
  width: 15px;
  height: 15px;
  background-color: whitesmoke;
  border: solid 1px whitesmoke;
  border-radius: 100%;
}
.active {
  background-color: Gold;
}

Babel + JSX

class Store {
	constructor(storeID, data) {
  	this.storeID = storeID;
    this.data = data || {};
  }
	update(state) {
  	let bufferStore = Object.assign({}, this.data, state);
  	this.data = bufferStore;
    updateApp();
  }
  view() {
  	console.log(this)
  }
}

const contentController = (contentStore) => ({
  CHANGE_CONTENT(e) {
  	let buffer = contentStore.data.items.map((item, i) =>
    	i === e ? { value: Math.random(), counter: item.counter + 1 } : item );
  	contentStore.update({ items: buffer })
    contentStore.view();
    updateApp();
  }
})

const tabsController = (tabsStore) => ({
	CHANGE_TAB(e) {
  	tabsStore.update({ selectedItemIndex: e });
    tabsStore.view()
    updateApp();
  }
})

const updateApp = () => React.render(
	<App
    tabsStore={tabsStore.data}
    randomStore1={randomStore1.data}
    randomStore2={randomStore2.data}
  />,
  document.getElementById('app')
);

const checkUpdate = (thisProp, nextProp) => {
	let keys = Object.keys(thisProp).filter(key => key !== 'ctrl');
  switch(keys.length) {
  	case 0:
    	return false;
    case 1:
    	let key = keys[0]
    	return thisProp[key] !== nextProp[key];
    default:
    	return keys
      				.map((key) => thisProp[key] !== nextProp[key])
    					.reduce((a, b) => a | b) === 1 ? true : false
  }	
}

const tabsStore = new Store(
	'TABS_STORE',
  {
  	selectedItemIndex: 0,
  }
);
const randomStore1 = new Store(
	'RANDOM_STORE_1',
  {
  	items: Array.from({ length: 150 }, (v, k) => ({ value: Math.random(), counter: 0 }))
  }
)
const randomStore2 = new Store(
	'RANDOM_STORE_2',
  {
  	items: Array.from({ length: 150 }, (v, k) => ({ value: Math.random(), counter: 0 }))
  }
)
const ctrl = tabsController(tabsStore)
const ctrl1 = contentController(randomStore1);
const ctrl2 = contentController(randomStore2);

class App extends React.Component {
 	constructor(props) {
  	super(props);
  }
  shouldComponentUpdate(nextProp) {
  	return checkUpdate(this.props, nextProp);
  }
  render() {
 ...