はじめに
lilでテキストを入力するとき、普通に実装するとエンターキーを押すときにフォーカスが外れて不便なので、それを解消する話。
コード全文
index.html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>lil focusout</title>
    <script src="https://cdn.jsdelivr.net/npm/lil-gui@0.20.0"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
    <p id="string"></p>
    <script src="main.js"></script>
  </body>
</html>
style.css
html {
  font-size:62.5%;
}
* {
  box-sizing: border-box;
}
html, body {
  margin:0;
  padding:0;
}
main{
  display:grid;
  place-items:center;
  height:100dvh;
  overflow:auto; /* autoです。 */
}
p{
  font-size:1.8rem;
}
main.js
function sketch(){
  // addColorの方は日本語入力時のエンターでfocusoutしないが
  // テキストの場合はfocusoutするので不便である。
  const config = {txt:"", col:'#FF0000'};
  let elem;
  const gui = new lil.GUI();
  gui.add(config, "txt").onChange((t) => {
    document.querySelector("#string").innerText = t;
    if(elem === undefined){
      // elemにそのときのフォーカスエレメントを代入することで入力部分のDOMを扱えるようにする
      elem = document.activeElement;
      elem.addEventListener("keydown", (e) => {
        // エンターキーを押したときにフォーカスイベントが発生するようにする。
        // このイベントはフォーカスアウトの後で発生するのでフォーカスを戻すことができる。
        if(e.code === 'Enter'){
          elem.focus();
        }
      });
    }
  });
  gui.addColor(config, "col");
}
document.addEventListener("DOMContentLoaded", sketch);
普通にやった場合のlilの挙動
lilで文字を入力する場面は、オブジェクトタイプがstringの場合と、addColorで文字入力をする場合である。addColorのボックスはなぜか文字入力の際にフォーカスが外れないようになっているが、タイプがstringの場合はなぜか、漢字変換などの際にエンターキーを押すとフォーカスが外れてしまう。
解消
フォーカスイベントを使う。
  let elem;
  const gui = new lil.GUI();
  gui.add(config, "txt").onChange((t) => {
    document.querySelector("#string").innerText = t;
    if(elem === undefined){
      // elemにそのときのフォーカスエレメントを代入することで入力部分のDOMを扱えるようにする
      elem = document.activeElement;
      elem.addEventListener("keydown", (e) => {
        // エンターキーを押したときにフォーカスイベントが発生するようにする。
        // このイベントはフォーカスアウトの後で発生するのでフォーカスを戻すことができる。
        if(e.code === 'Enter'){
          elem.focus();
        }
      });
    }
  });
あらかじめ要素の代入先を用意しておき、文字入力の際にフォーカスエレメントの取得により入力部分のDOMを取得する。そしてその際に、Enterキーのイベントとしてフォーカスさせるイベントが発生するようにする。こうすると、フォーカスの際のフォーカスアウトの後でこれが発生するので、問題なく引き続き入力することができる。
おわりに
ここまでお読みいただいてありがとうございました。