マニフェスト駆動インスペクタ
ビルダーのプロパティインスペクタには「各コンポーネントのどの属性が
どの値を取るか」の知識が必要です。それはまさに
コアのマニフェストが
公開しているものです: すべての components[] エントリが
attributeValues{}(値を取る各 data-* 属性 → 列挙値)と
cssVars[](テーマ可能なカスタムプロパティ面)を持ちます。CSS の
パースも手書きの表も不要 — マニフェストはスタイルシートから生成され、
CI が実装との一致を強制します。
このページでは実物の editor-kit が動いています。キャンバス上の
コンポーネントをクリックすると、インスペクタがその
attributeValues をセレクトとして列挙します。すべての編集は
CommandStack を通るので、Undo/Redo はそのまま動きます。選択
マーカーは足場属性 data-hc-editor-selected です — 下部の
シリアライズ出力に注目してください。serialize() が
data-hc-editor-* 名前空間を剥がすため、そこには決して現れません。
インスペクタ全体は、マニフェストエントリを巡るループです:
import { createEditor, setAttribute, removeAttribute } from '@hypermedia-components/editor-kit';import manifest from '@hypermedia-components/core/manifest.json' with { type: 'json' };
const byBlock = new Map(manifest.components.map((c) => [c.block, c]));const editor = createEditor({ root: canvas, manifest });
function renderInspector(node) { const block = [...node.classList].find((c) => byBlock.has(c)); const { attributeValues } = byBlock.get(block);
for (const [attr, values] of Object.entries(attributeValues)) { const select = buildSelect(attr, values, node.getAttribute(attr)); select.addEventListener('change', () => { editor.stack.apply( select.value === '' ? removeAttribute(node, attr) // デフォルトに戻す : setAttribute(node, attr, select.value), ); }); }}ここで効くスタックの性質は 3 つ:
- Coalescing — 自由入力(
aria-labelフィールドなど)には{ coalesce: true }を渡すと、タイピングが undo 1 ステップに まとまります。 transact()— インスペクタの 1 操作が複数の属性書き込みを 伴うときはグループ化し、Undo 1 回で操作全体が戻るようにします。changeイベント — スタック変更時にインスペクタを再描画して ください。undo/redo は選択中ノードの属性を裏で書き換えます。
テーマのつまみ
Section titled “テーマのつまみ”cssVars[] は、そのコンポーネントのスタイルシートが読むすべての
--hc-* カスタムプロパティ —
トークンシステムの
マニフェスト側 — を列挙します。インスペクタはこれを「デザイン」
タブとして出せます: インスタンス単位の上書きはインライン style の
カスタムプロパティへ、アプリ単位の上書きはスタイルシートへ。どちらも
普通の属性/DOM 編集なので、同じコマンドスタックを流れます。
同じマニフェストデータがビルダーの残りも駆動します:
- パレット —
components[]+docsPathはそのままカタログに なります。htmx 連携パターンはrecipes[](機械検証つき契約)が カバーします。 - ドロップ規則 —
ドラッグ&ドロップコントローラの
canAccept(container, payload)フックからparts[]と独自の 合成規則を参照できます。 - 構造化生成 — マニフェストは JSON なので、スキーマ制約つき生成
(LLM の structured output →
fromJson())を文書化された語彙の 内側に保てます。