◆ wire に渡す参照がなくなる
◆ wire の参照がないと input イベントのたびに毎回新規 HTML 要素に置き換えられる
◆ テキスト入力中に置き換えられるのでフォーカスがはずれてちゃんと打てない
◆ 文字列の配列などにせず オブジェクトの配列にしてオブジェクトのプロパティに値もたせる

wire の引数を設定できない

hyperHTML を使ったシンプルなページでこういうのがあります

import { bind, wire } from "https://cdn.jsdelivr.net/npm/hyperhtml@2.25.5/esm.js"

const data = ["aaa", "", ""]

const render = () => {
bind(document.body)`
<h4>inputs</h4>
${data.map((e, i) => wire()`
<div><input data-index=${i} value=${e}></div>
`)}
<h4>preview</h4>
<pre>${data.join("\n")}</pre>
`
}

document.body.addEventListener("input", eve => {
const index = eve.target.dataset.index
if (index != null) {
data[index] = eve.target.value
render()
}
})

render()

データは文字列の配列です
それぞれをテキストの input に関連付けて表示します

繰り返し部分は map を使って wire で作ったパーツの配列を返します
通常 wire の引数にはテンプレートに関連付けるオブジェクトを設定します
しかし今回はそれぞれの要素はプリミティブ値なので引数はなしです
内部で WeakMap で保存するのでオブジェクト以外は設定できないためです

`${data.map((e, i) => wire()`
<div><input data-index=${i} value=${e}></div>
`)}`

フォーカスが外れる

一見問題なさそうですが input を操作してみると 2 文字以上打てません
1 文字打つごとにフォーカスがはずれてしまっています

input イベントが起きて再 render の処理で map で繰り返してる ${} の中身部分がすべて再作成されます
wire の引数で関連付けたオブジェクトの参照で同一テンプレートを使うかを hyperHTML は判断しているので参照なしの wire は毎回新規作成した HTML 要素に置き換えられます

対処方法

1) 配列の中はオブジェクトにする

単純なものは 配列を使ったテンプレートの繰り返しになる部分ではプリミティブな値を設定せずオブジェクトを設定するようにするというものです
文字列の配列ではなくオブジェクトの配列にします

import { bind, wire } from "https://cdn.jsdelivr.net/npm/hyperhtml@2.25.5/esm.js"

const data = [{ text: "aaa" }, { text: "" }, { text: "" }]

const render = () => {
bind(document.body)`
<h4>inputs</h4>
${data.map((e, i) => wire(e)`
<div><input data-index=${i} value=${e.text}></div>
`)}
<h4>preview</h4>
<pre>${data.map(e => e.text).join("\n")}</pre>
`
}

document.body.addEventListener("input", eve => {
const index = eve.target.dataset.index
if (index != null) {
data[index].text = eve.target.value
render()
}
})

render()

すべてに .text が必要になるのは少し面倒ですが 将来の拡張性も考えればそこまで悪い方法ではないです

2) 別に参照オブジェクトを持つ

その配列の各要素に対応するオブジェクトがあればよいので それ作って wire に指定することもできます

import { bind, wire } from "https://cdn.jsdelivr.net/npm/hyperhtml@2.25.5/esm.js"

const data = ["aaa", "", ""]
data.refs = data.map(e => Object())

const render = () => {
bind(document.body)`
<h4>inputs</h4>
${data.map((e, i, a) => wire(a.refs[i])`
<div><input data-index=${i} value=${e}></div>
`)}
<h4>preview</h4>
<pre>${data.join("\n")}</pre>
`
}

document.body.addEventListener("input", eve => {
const index = eve.target.dataset.index
if (index != null) {
data[index] = eve.target.value
render()
}
})

render()

配列の要素と同じ数だけ オブジェクトを作っておき それを wire に指定します
data に関連するものなので data.refs に設定してます

自分で refs を毎回作ったり配列の要素数が増えたときにオブジェクトも追加など管理が面倒なのが欠点です

3) 2 を便利に

その面倒な部分を自動でするようにしてみました

hh というヘルパを作ってます
プリミティブ型の配列を map して wire する場合は hh.map を代わりに使います

import { bind, wire } from "https://cdn.jsdelivr.net/npm/hyperhtml@2.25.5/esm.js"

const hh = {
map(parray, fn) {
if (!this.refs.has(parray)) {
this.refs.set(parray, [])
}
const refs = this.refs.get(parray)
const r = []
for (const [index, item] of parray.entries()) {
while (refs.length <= index) {
refs.push(Object())
}
r.push(fn(item, index, refs[index], parray))
}
return r
},
refs: new WeakMap(),
}

const data = ["aaa", "", ""]

const render = () => {
bind(document.body)`
<h4>inputs</h4>
${hh.map(data, (e, i, r) => wire(r)`
<div><input data-index=${i} value=${e}></div>
`)}
<h4>preview</h4>
<pre>${data.join("\n")}</pre>
`
}

document.body.addEventListener("input", eve => {
const index = eve.target.dataset.index
if (index != null) {
data[index] = eve.target.value
render()
}
})

render()

hh.map ではコールバック関数に渡される 3 つ目の引数が配列自身ではなく その要素のための参照となる空オブジェクトです
これを wire の参照として渡すだけです
hh.map を実行したときに 1 つ目の引数に渡す配列に対応するオブジェクトの配列を取得して 足りなければ空オブジェクトを作ってから map の処理を行います
なので 複数の配列を使っても問題ないですし 要素数が増えても大丈夫です

プリミティブ型の配列を使わないのが一番

こういうことで対処できそうということで楽にするヘルパを作って見たましたが hh.map にすることを忘れて通常の map にしてしまいがちですし データの構造が変わって中の要素が一つになったから配列の要素をオブジェクトからテキストにしたとか 複数になったからテキストからオブジェクトにしたとか そういった変更のたびにここも直さないといけないのは手間です

またこのヘルパを毎回用意する必要もあります
そういうことを考えるとシンプルに配列の中はデータ 1 つでもオブジェクトにするとしておいたほうが良いかと思います
追加削除があっても常にオブジェクト型のほうが楽ですしね