React

by Lexogram

HTML

<div id="app"></div>

CSS

html, body {
  height: 100vh;
}


body {
  margin: 0;
  font-size: 20vmin;
}

* {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
}

span.selected {
  background-color: #9c9;
  opacity: 0.5;
}

span.removed {
  opacity: 0.05;
}

div#board{
  background-color: #efe;
  height: 100vh;
}

div[class|="row"] {
  display: flex;
  justify-content: center;
}

@keyframes ants {
  from { stroke-dashoffset: 0; }
  to { stroke-dashoffset: 10; }
}

@keyframes tsan {
  from { stroke-dashoffset: -5; }
  to { stroke-dashoffset: 5; }
}

React

class Board extends React.Component {
  _getClassName(id) {
    let className = ""

    if (this.props.removed.indexOf(id) < 0) {
      if (this.props.selected.indexOf(id) < 0) {
        // This span is neither selected nor removed. Leave it alone
      } else {
        className = "selected"
      }

    } else {
      className = "removed"
    }

    return className
  }


  render () {
    const rows = this.props.data.map((rowData, rowIndex) => {
      const cells = rowData.map((cellData, cellIndex) => {
        const id = "cell-" + rowIndex + "-" + cellIndex
        const className = this._getClassName(id)

        return (
          <span       
            key={cellIndex}
            id={id}
            className={className}
          >
            {cellData}
          </span>
        )
      })

      return (
         <div
           key={rowIndex}
           className={"row-" + rowIndex}
          >
          {cells}
        </div>
      )
    })

    return (
      <div
        id="board"
        onMouseDown={this.props.drag}
      >
        {rows}
      </div>
    )
  }
}


const Ants = ({ rect }) => {

  if (!rect) {
    console.log("No ants")
    return ""
  }

  const svg = (
    <svg
      width="100vw"
      height="100vh"
      xmlns="http://www.w3.org/2000/svg"
      xmlnsXlink="http://www.w3.org/1999/xlink"
      style={{
        position: "fixed"
      , top: 0
      , left: 0
      , pointerEvents: "none"
      }}
    >
      <rect
        x={rect.x}
        y={rect.y}
        width={rect.width}
        height={rect.height}
        stroke="#000"
        strokeWidth="1"
        strokeOpacity="0.75"
        strokeDasharray="5,5"
        style={{ animation: "ants 1s linear infinite" }}
        fill="#030"
        fillOpacity="0.1"
      />
      <rect
        x={rect.x}
        y={rect.y}
        width={rect.width}
        height={rect.height}
        stroke="#fff"
        strokeWidth="1"
        strokeOpacity="0.75"
       ...