JSFiddle - React, Tailwind, and code Playground

HTML

<input id="inputCell" style="position: absolute; top: -10000px; left: 0;" >
<table border="1">
    <tr>
        <td>11</td>
        <td>12</td>
        <td>13</td>
    </tr>
    <tr>
        <td>21</td>
        <td>22</td>
        <td>23</td>
    </tr>
    <tr>
        <td>31</td>
        <td>32</td>
        <td>33</td>
    </tr>
</table>

CSS

td {
    width: 200px;
    white-space: nowrap;
}

* {
    box-sizing: border-box;
}

table {
    border: solid 1px #666;
    border-collapse: collapse;
}

.selected {
    background-color: aliceblue;
}

#inputCell {
    border: 1px solid #666;
}

input:focus {
    outline: none;
}

JavaScript

// 対象のテーブル
var table = document.querySelector("table")
// 対象のテーブルセル
var cells = table.querySelectorAll("td")
// 編集用エレメント
var editorElem = document.getElementById("inputCell")
// 編集中かどうか
var isEditing = false

// マウスダウン時にセルが選択されるようイベントを登録する
var setupSelectionEvent = function () {
    for (var i = 0; i < cells.length; i++) {
        cells[i].addEventListener("mousedown", function () {
            // 編集中なら終了
            endEdit(true)
            var cell = this
            // 既存の選択セルは解除
            for (var j = 0; j < cells.length; j++) {
                cells[j].classList.remove("selected")
            }
            // 新たにセルを選択
            this.classList.add("selected")
            readyEdit()
        })
        cells[i].addEventListener("dblclick", function () {
            startEdit(true)
        })
    }
}

// 選択中のセル取得関数
var getSelectedCell = function () {
    for (var i = 0; i < cells.length; i++) {
        var cell = cells[i]
        if (cell.classList.contains("selected")) return cell
    }
}

// イベントON/OFFを簡単に切り替えるようにするためのユーティリティ的関数
var createEventOnOffHandler = function (elem, eventName, callback) {
    return {
        on: function () {
            this.off()
            elem.addEventListener(eventName, callback)
        },
        off: function () {
            elem.removeEventListener(eventName, callback)
        }
    }
}
// 上記ON/OFF切り替えハンドラを束ねるユーティリティ的関数
var bundleEventOnOffHandlers = function (handlers) {
    return {
        on: function () {
            handlers.forEach(function (h) { h.on() })
        },
        off: function () {
            handlers.forEach(function (h) { h.off() })
        }
    }
}

// 対象がテーブルかどうかの判定関数
var isTargetTableElem = function (target) {
    while (target) {
        if (table == target) { return true }
        target = target.parentNode
    }
    return false
}

// 編集準備中に登録するイベントハンドラ
var eventHandlers4readyEdit = bundleEventOnOffHandlers([
    // documentのmousedownイベント
    // フォーカスが外れたときに編集終了するようにイベントを登録しておく
   ...