`<wa-combobox>` に「オプション動的作成」機能と `input` イベントを追加
<wa-combobox> に allow-create 属性による新規オプションの動的生成機能と、入力時の input イベント発火が追加されました。あわせて allow-custom-value 使用時の2つのバグが修正され、コンボボックスの実用性が大幅に向上しています。
背景
従来の <wa-combobox> は、ドロップダウンに存在する選択肢を選ぶ操作に限られており、ユーザーが入力したテキストをそのまま新しいオプションとして追加する手段がありませんでした。タグ入力やフリーテキスト選択のようなUIパターンを実現するには、コンポーネント外で独自実装を行う必要がありました。
また、ユーザーがコンボボックスに文字を入力しても input イベントが発火しないため、<wa-input> やネイティブの <input> と異なる挙動になっていました。この非一貫性は、フォームライブラリや入力監視処理との統合を複雑にしていました。
さらに allow-custom-value が設定されている環境では、ブラー時にカスタム値がコミットされない問題や、入力をクリアしてフォーカスを外すと直前の選択値が復元されてしまう問題も存在していました。
技術的な変更
今回の変更は、新機能の追加・イベント対応・バグ修正の3軸で構成されます。
allow-create 属性と wa-create イベントの追加が中心的な変更です。既存のどのオプションにもマッチしないテキストを入力すると、ドロップダウンに「Create \"[value]\"」という選択肢が出現します。これを選ぶと実際の <wa-option> がDOMに追加され、キャンセル可能な wa-create イベントが発火します。このイベントはカスタムハンドリングにも対応しており、独自のオプション追加ロジックを割り込ませることが可能です。
wa-create イベントの型定義は src/events/create.ts として新設されました。
export class WaCreateEvent extends Event {
readonly detail;
constructor(detail: WaCreateEventDetail) {
super('wa-create', { bubbles: true, cancelable: true, composed: true });
this.detail = detail;
}
}
export interface WaCreateEventDetail {
inputValue: string;
}
declare global {
interface GlobalEventHandlersEventMap {
'wa-create': WaCreateEvent;
}
}
GlobalEventHandlersEventMap への登録により、TypeScript環境でも addEventListener('wa-create', ...) が型安全に利用できます。events.ts にも WaCreateEvent のre-exportが追加されており、他のイベント型と同様に公開APIとして扱われます。
input イベントの発火 は、コンボボックスへの入力時に標準的な input イベントを発火させることで、<wa-input> やネイティブフォームコントロールとの一貫性を確保します。これにより、フォームライブラリや入力監視処理が <wa-combobox> に対しても同じコードで機能します。
翻訳対応として、「Create \"[value]\"」というラベルの createOption キーが全30言語以上の翻訳ファイルに追加されました。各言語ごとに value => \...`形式の関数として定義されており、入力値を埋め込んで表示できます。日本語訳は「${value}」を作成、フランス語訳はCréer « ${value} »` のように、各言語の引用符スタイルも適切に反映されています。
設計判断
wa-create イベントをキャンセル可能(cancelable)にした設計が注目されます。{ cancelable: true } を指定することで、イベントハンドラ内で event.preventDefault() を呼び出せば、デフォルトのDOM追加処理を抑止できます。これにより、バリデーションや非同期処理を挟みながらオプション追加の可否を制御するパターンが実現可能です。
composed: true の指定も意図的な判断です。Shadow DOMの境界を越えてイベントが伝播するため、コンポーネントをラップしたカスタム要素からでもイベントリスナーで捕捉できます。
ビルドスクリプト(build.js)でも小さな改善が加えられており、getVersion の非同期関数が同期的なトップレベルの await に変更されています。ora スピナーの初期化もオプションなしのシンプルな呼び出しになり、バージョン情報は chalk を使ったカラー出力に統一されました。
まとめ
本PRは <wa-combobox> を「選ぶだけ」のコンポーネントから「作って選べる」コンポーネントへと拡張し、タグ入力のようなリッチなUXパターンへの対応を実現しています。キャンセル可能なイベントと全言語対応の翻訳キーを同時に整備したことで、国際化対応アプリケーションでも即座に組み込める設計になっています。