JSFiddle - React, Tailwind, and code Playground
by ozzon91
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
<script src="https://cdn.jsdelivr.net/ramda/0.18.0/ramda.min.js"></script>
<div class="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
</div>
CSS
.container {
display: flex;
justify-content: space-between;
width: 700px;
}
.item {
font-size: 40px;
width: 100px;
height: 100px;
outline: 1px solid #ccc;
text-align: center;
line-height: 100px;
cursor: pointer;
transition: background-color 0.5s ease;
background-color: yellow;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.item:hover {
background-color: lightblue;
}
.item.active {
outline: 2px solid red;
}
Babel + JSX
const {
fromEvent
} = Rx.Observable;
const {
unapply, identity, equals, apply, lt, or, not, map, pipe, pluck, prop, invoker, curry
} = R;
const fromKey = curry((type, code) => fromEvent(document.body, type).filter(pipe(prop('keyCode'), equals(code))));
const orObs = (o1, o2) => o1.combineLatest(o2, or);
const notObs = o => o.map(not);
const fromKeyDown = fromKey('keydown');
const fromKeyUp = fromKey('keyup');
const fromKeyPress = code => fromKeyDown(code).map(true).merge(fromKeyUp(code).map(false)).shareValue(false);
const [ctrlKey, shiftKey] = R.map(fromKeyPress)([17, 16]);
const clickItem = fromEvent($('.item'), 'click');
clickItem.pausable(notObs(orObs(ctrlKey, shiftKey)))
.map(pipe(prop('target'), identity($)))
.subscribe(el => el.toggleClass('active').siblings().removeClass('active'));
clickItem.pausable(ctrlKey).map(pipe(prop('target'), identity($))).subscribe(el => el.toggleClass('active'));
clickItem.pausable(notObs(shiftKey)).combineLatest(
clickItem.pausable(shiftKey),
unapply(identity)
)
.filter(pipe(pluck('timeStamp'), apply(lt)))
.map(pipe(pluck('currentTarget'), map(pipe(identity($), invoker(0, 'index')))))
.subscribe(([ai, bi]) => $(".item").slice.apply($(".item"), ai < bi ? [ai, bi + 1] : [bi, ai + 1]).addClass('active'));