はじめに
Constelaは、AIによるUI生成に最適化されたコンパイラファーストのUI言語です。JSONでUIを宣言的に記述し、コンパイル時に検証・解析されます。
今回のリリースでは、React/Next.jsと同等の表現力を実現するための重要な機能を追加しました。
新機能一覧
- タイマー機能 - delay, interval, clearTimer
- 拡張イベントデータ - キーボード、マウス、タッチ、スクロール、ファイル
- フォーム機能 - focus操作、バリデーション状態
- Portal & Observer - ポータルノード、IntersectionObserver、debounce/throttle
1. タイマー機能
delay - 遅延実行
指定したミリ秒後にステップを実行します。
{
"name": "showNotification",
"steps": [
{ "do": "set", "target": "notification", "value": { "expr": "lit", "value": "保存しました" } },
{
"do": "delay",
"ms": { "expr": "lit", "value": 3000 },
"then": [
{ "do": "set", "target": "notification", "value": { "expr": "lit", "value": "" } }
]
}
]
}
interval - 定期実行
指定した間隔でアクションを繰り返し実行します。resultにタイマーIDが格納されます。
{
"name": "startPolling",
"steps": [
{
"do": "interval",
"ms": { "expr": "lit", "value": 5000 },
"action": "fetchLatestData",
"result": "pollingTimerId"
}
]
}
clearTimer - タイマー停止
実行中のタイマーを停止します。
{
"name": "stopPolling",
"steps": [
{ "do": "clearTimer", "target": { "expr": "state", "name": "pollingTimerId" } }
]
}
2. 拡張イベントデータ
イベントハンドラ内で利用可能な変数が大幅に拡張されました。
| イベント種別 | 利用可能な変数 |
|---|---|
| Input |
value, checked
|
| Keyboard |
key, code, ctrlKey, shiftKey, altKey, metaKey
|
| Mouse |
clientX, clientY, pageX, pageY, button
|
| Touch |
touches(配列: clientX, clientY, pageX, pageY) |
| Scroll |
scrollTop, scrollLeft
|
| File Input |
files(配列: name, size, type) |
例: キーボードショートカット
{
"onKeyDown": {
"event": "keydown",
"action": "handleShortcut",
"payload": {
"key": { "expr": "var", "name": "key" },
"isCtrl": { "expr": "var", "name": "ctrlKey" }
}
}
}
例: ファイルアップロード
{
"kind": "element",
"tag": "input",
"props": {
"type": { "expr": "lit", "value": "file" },
"multiple": { "expr": "lit", "value": true },
"onChange": {
"event": "change",
"action": "handleFiles",
"payload": { "expr": "var", "name": "files" }
}
}
}
3. フォーム機能
focus操作
フォーム要素のフォーカス制御ができるようになりました。
// フォーカスを当てる
{ "do": "focus", "target": { "expr": "ref", "name": "emailInput" }, "operation": "focus" }
// テキストを選択
{ "do": "focus", "target": { "expr": "ref", "name": "codeInput" }, "operation": "select" }
// フォーカスを外す
{ "do": "focus", "target": { "expr": "ref", "name": "searchInput" }, "operation": "blur" }
validity式 - バリデーション状態の取得
HTML5 Constraint Validation APIを通じてフォーム要素のバリデーション状態を取得できます。
{
"kind": "element",
"tag": "input",
"ref": "emailInput",
"props": {
"type": { "expr": "lit", "value": "email" },
"required": { "expr": "lit", "value": true }
}
}
// バリデーション状態を表示
{
"kind": "if",
"condition": {
"expr": "not",
"operand": { "expr": "validity", "ref": "emailInput", "property": "valid" }
},
"then": {
"kind": "text",
"value": { "expr": "validity", "ref": "emailInput", "property": "message" }
}
}
利用可能なプロパティ:
-
valid- 全体の有効性 -
valueMissing- 必須フィールドが空 -
typeMismatch- 型が一致しない(email, url等) -
patternMismatch- パターンが一致しない -
tooLong/tooShort- 長さ制約違反 -
rangeUnderflow/rangeOverflow- 範囲制約違反 -
message- ブラウザのエラーメッセージ
4. Portal & Observer
Portal - コンポーネントツリー外へのレンダリング
モーダルやツールチップなど、DOMツリーの別の場所にレンダリングする必要がある場合に使用します。
{
"kind": "portal",
"target": "body",
"children": [
{
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "modal-overlay" } },
"children": [
{
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "modal-content" } },
"children": [...]
}
]
}
]
}
target指定:
-
"body"- document.body -
"head"- document.head - CSSセレクター(例:
"#modal-root")
IntersectionObserver - 要素の可視性検出
無限スクロールやレイジーロードの実装に便利です。
{
"kind": "element",
"tag": "div",
"ref": "sentinel",
"props": {
"onIntersect": {
"event": "intersect",
"action": "loadMoreItems",
"options": {
"threshold": 0.5,
"rootMargin": "100px"
}
}
}
}
debounce / throttle
イベントハンドラの実行頻度を制御します。
// Debounce: 最後のイベントから300ms後に実行
{
"onInput": {
"event": "input",
"action": "search",
"debounce": 300
}
}
// Throttle: 100msに1回だけ実行
{
"onScroll": {
"event": "scroll",
"action": "trackScroll",
"throttle": 100
}
}
まとめ
これらの新機能により、Constelaは以下のようなユースケースに対応できるようになりました:
- 通知のオートハイド - delayで数秒後に非表示
- リアルタイムデータ更新 - intervalでポーリング
- キーボードショートカット - 拡張イベントデータで修飾キーを検出
- ファイルアップロード - filesデータでファイル情報を取得
- フォームバリデーション - validity式でリアルタイム検証
- モーダルダイアログ - portalでbodyに直接レンダリング
- 無限スクロール - intersectイベントで可視性を検出
- 検索入力 - debounceで過剰なAPI呼び出しを防止