入力の永続化
stimeo--persist
フォームの値を localStorage に保存し、リロードや Turbo 遷移をまたいで復元する。
stimeo--persist コントローラは connect 時に key(無ければ要素の id)配下の保存値を復元し、以後は input/change のたびにデバウンス保存します。復元したらフォームに data-persist-restored を付与し、stimeo--persist:restore / :save / :clear を発火します。password フィールド(および exclude に挙げた name/type)は保存しません。clear() アクション、または clearOn イベント(例: submit)で下書きを破棄します。復元時にフォーカスは移動しません。ライブラリは挙動のみで、状態は localStorage に保持するため(モジュールスコープ状態なし)複数インスタンスが干渉しません。入力リスナと保存デバウンスは disconnect(Turbo 遷移含む)で解除し、保留中の保存を flush して編集中の値を失いません。
<%# Persist demo: type into the fields and the draft is saved to localStorage
(debounced). Reload or navigate away and back — the values are restored and the
"draft restored" note appears (data-persist-restored). "Clear draft" calls the
clear() action. The library owns the storage and the data hook; this demo only
styles the restored note. %>
<div class="persist-demo">
<form
class="persist"
data-controller="stimeo--persist"
data-stimeo--persist-key-value="stimeo-demo-contact">
<p class="persist__restored"><%= t("components.persist.demo.restored") %></p>
<label class="persist__field">
<span><%= t("components.persist.demo.name") %></span>
<input type="text" name="name">
</label>
<label class="persist__field">
<span><%= t("components.persist.demo.message") %></span>
<textarea name="message" rows="3"></textarea>
</label>
<button type="button" class="demo-trigger" data-action="stimeo--persist#clear">
<%= t("components.persist.demo.clear") %>
</button>
</form>
</div>
/*
* Presentation-only styles for the persist demo.
* The library toggles data-persist-restored on the form; this CSS reveals the
* "draft restored" note while that hook is present.
*/
.persist-demo {
max-width: 28rem;
}
.persist {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.persist__field {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.persist__field input,
.persist__field textarea {
padding: 0.5rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
font: inherit;
resize: vertical;
}
/* The note appears only after a draft has been restored. */
.persist__restored {
display: none;
margin: 0;
font-size: 0.85rem;
color: var(--accent);
}
.persist[data-persist-restored] .persist__restored {
display: block;
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--persist"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
field
|
保存対象を限定する任意のフィールド。既定はフォーム内の名前付きコントロール。 | data-stimeo--persist-target="field" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
key
|
localStorage の名前空間。無ければ要素 id。両方無ければ無効。 |
data-stimeo--persist-key-value |
debounce
|
保存までのデバウンス(ミリ秒、既定 400)。 | data-stimeo--persist-debounce-value |
exclude
|
保存しない name/type(既定 ["password"])。 |
data-stimeo--persist-exclude-value |
clearOn
|
下書きをクリアするイベント名(例: submit)。空で無効。 |
data-stimeo--persist-clear-on-value |
アクション
| 名前 | アクション |
|---|---|
clear
|
stimeo--persist#clear |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
restore
|
値を復元したときに発火。detail.key を伴う。 |
stimeo--persist:restore |
save
|
デバウンス保存後に発火。detail.key を伴う。 |
stimeo--persist:save |
clear
|
下書きをクリアしたときに発火。detail.key を伴う。 |
stimeo--persist:clear |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
data-persist-restored |
フォーム(ルート) | 保存済みの下書きから復元したときに付与。 |