InputRange

基本的な使用法

<input-range>にshadow DOM treeがアタッチされDOMを追加します。
ドキュメントのstyleは適用されません。

<input-range min=-10 max=10 value=0></input-range>

値をthumbと連動して動かす

open属性を付けることで<input-range>の子孫要素をLight DOMに追加し、ドキュメントのstyleを適用することができます。
値は<input-range>直下の<output>要素に出力され、styleには予め値に応じたleftプロパティが設定されます。
normalize cssなどでinputのmarginが上書きされている場合はデフォルト値(2px)に設定し直す必要があります。

<input-range open id="ir1" min=-10 max=10 value=0></input-range>
#ir1{
    position: relative;
}
#ir1 input{
    margin: 2px;
}
#ir1 output{
    position: absolute;
    transform: translate(-50%, 100%);
}

もっとstyleを付ける

参照:Value Bubbles for Range Inputs | CSS-Tricks

<input-range open id="ir2" min=-10 max=10 value=0></input-range>
#ir2{
    position: relative;
}
#ir2 input{
    margin: 2px;
}
#ir2 output{
    width: 30px;
    height: 24px;
    line-height: 24px;
    text-align: center;
    background: #03a9f4;
    color: #fff;
    font-size: 12px;
    display: block;
    position: absolute;
    transform: translate(-50%, -56px);
    border-radius: 6px;
}
#ir2 output::before {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    border-top: 10px solid #03a9f4;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    top: 100%;
    left: 50%;
    margin-left: -5px;
    margin-top: -1px;
}

OutputFor

基本的な使用法

data-forで指定したセレクターと最初に一致するインプット要素のvalueを表示します。

<input type="text" value="some text">
<output-for data-for='input[type="text"]'></output-for>

出力を加工する

data-funcに加工用の関数名を指定します。

function toUpper(str){return str.toUpperCase()}
<input id="in1" type="text" value="to upper case">
<output-for data-for='#in1' data-func="toUpper"></output-for>

もっと出力を加工する

実用性はありませんが可能性として。

キーワードで検索した最初の書籍のサムネイルを出力

async function book(str) {
    const data = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${str}`).then(res => res.json());
    return `<img src="${data.items[0].volumeInfo.imageLinks.smallThumbnail}">`
}
<input id="book" type="text" value="webcomponent">
<p><output-for data-for='#book' data-func="book"></output-for></p>

都道府県の天気予報

window.forcast = (function () {
    const areaURL = "https://www.jma.go.jp/bosai/common/const/area.json";
    const areaPromise = fetch(areaURL).then(res => res.json());
    return async function forcast(pref) {
        if (!pref) return "";
        const area = await areaPromise;
        let code;
        Object.entries(area.offices).forEach(([c, obj]) => { if (obj.name.startsWith(pref)) { code = c } })
        if (!code) return "";
        const forcastURL = `https://www.jma.go.jp/bosai/forecast/data/forecast/${code}.json`;
        const data = await fetch(forcastURL).then(res => res.json());
        return data[0].timeSeries[0].areas[0].weathers[0];
    }
})();
<input id="tenki" type="text" value="東京">
<p><output-for data-for='#tenki' data-func="forcast"></output-for></p>

(出所:気象庁ホームページ)