React Base Fiddle (JSX)

Starting point for creating JSFiddles with React.

by Stepan Parunashvili

HTML

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

CSS

body {
  font-family: Helvetica Neue;
  -webkit-font-smoothing: antialiased;
}
.item {
  background: blue;
  color: white;
  width: 50px;
  height: 50px;
  margin: 20px;
  display: inline-block;
  padding: 10px;
}

.selected {
  background: pink;
}
.Area {
  width: 100vw;
  height: 100vh;
}

Babel + JSX

function emptyState() {
  return {
    showBoundingBox: false,
    startPos: null,
    endPos: null,
  };
}

function rectFromPositions(startPos, endPos) {
  const [startX, startY] = startPos;
  const [endX, endY] = endPos;
  const width = Math.abs(startX - endX);
  const height = Math.abs(startY - endY);

  const left = startX < endX ? startX : endX;
  const top = startY < endY ? startY : endY;
  return {
    width,
    height,
    left,
    top,
  };
}

// enumerate all the possible ways a rect cannot intersect
// i.e one box to the left, to the top, to the right, to the bottom of another box
function rectIntersects(boundingBox, nodeRect) {
  return !(
    boundingBox.left > nodeRect.right ||
    boundingBox.top > nodeRect.top + nodeRect.height ||
    boundingBox.left + boundingBox.width < nodeRect.left ||
    boundingBox.top + boundingBox.height < nodeRect.top
  );
}

class Selectable extends React.Component {
  constructor(props) {
  	super(props);
	  this.state = emptyState();
    this.onMouseDown = e => {
      this.setState({
        showBoundingBox: true,
        startPos: [e.pageX, e.pageY],
      });
    };
    this.onMouseMove = e => {
      e.preventDefault();
      this.setState({
        endPos: [e.pageX, e.pageY],
      });
    };
    this.onMouseUp = () => {
      const { startPos, endPos } = this.state;
      startPos &&
        endPos &&
        this._handleSelection(rectFromPositions(startPos, endPos));

      this.setState(emptyState());
    };
    this.portalNode = document.createElement('div');
    document.body.appendChild(this.portalNode);
    this._cleanup = () => {
      document.body.removeChild(this.portalNode);
    };
  }
  componentWillUnmount() {
    this._cleanup();
  }

  _handleSelection(boundingBox) {
    const selectedKeys = Object.keys(this.props.selectableRefs).reduce(
      (res, k) => {
        const node = this.props.selectableRefs[k];
        const nodeRect = node.getBoundingClientRect();
        if...