新しいエッジを検証して強化する
2 つの接続時フックにより、コンシューマーが独自にエッジを作成できるようになります。 isValidConnection ジェスチャ中にライブで実行されます。無効なターゲットは赤いプレビューを描画し、実行できません。 削除され、それに対して before-create フックが参照されることはありません。 onBeforeEdgeCreate 有効なターゲットが選択されると、エッジが存在する直前に実行されます: return false to 拒否権を発動するか、{ accept: true, data, style, directed } を受け入れて新しいエッジにスタンプを押します ラベル、スタイル、方向を指定します。非同期である可能性があります - シャドウエッジのプレビューはそのままです 落ち着くまで。
Edit Graph (右上) → Add Edge をクリックし、ノードを接続します。ここでは、 人をプロジェクトにリンクするだけ — 同じタイプのリンクは赤色でプレビューされ、拒否されます 生きる。有効なドロップは保存をシミュレートし、ラベル付きの有向エッジを作成します。 archived プロジェクトに追加します。作成前のフックは事後的に拒否します。
js
// Both hooks live under the full UI mode's Edit Graph → Add Edge tool.
const options = {
// Off: `full` mode brings a minimap and the data dock, and this card is about
// neither (see the Minimap and Data table cards for those).
UI: { mode: 'full', minimap: false, table: false },
callbacks: {
// Live predicate — runs on every hover while connecting. Only cross-type
// links (person ↔ project) are valid; anything else previews red and can't
// be dropped. onBeforeEdgeCreate is never consulted for a rejected target.
isValidConnection: (source, target) =>
source.getData().type !== target.getData().type,
// Before-create hook — fires once a valid target is picked, before the edge
// exists. Async here: we simulate persisting the link, then either veto or
// accept with an enriched label / style / direction.
onBeforeEdgeCreate: async ({ source, target, origin }) => {
// Veto after the fact: no new links onto an archived project.
if (source.getData().archived || target.getData().archived) {
graph.notifier.warning('Archived', 'Project Orion is archived — no new links.')
return false
}
graph.notifier.info('Saving…', `${source.getData().label} → ${target.getData().label}`)
await wait(600) // stand-in for a backend POST that could fail
const person = source.getData().type === 'person' ? source : target
const project = person === source ? target : source
graph.notifier.success('Linked', `${person.getData().label} assigned to ${project.getData().label}`)
// Accept and stamp the new edge — the consumer decides what it carries.
return {
accept: true,
data: { label: 'assigned-to', via: origin },
style: { edge: { strokeColor: '#6366f1' } },
directed: true
}
}
}
}js
const data = {
nodes: [
{ id: 'alice', data: { label: 'Alice', type: 'person' } },
{ id: 'bob', data: { label: 'Bob', type: 'person' } },
{ id: 'carol', data: { label: 'Carol', type: 'person' } },
{ id: 'atlas', data: { label: 'Project Atlas', type: 'project' } },
{ id: 'nova', data: { label: 'Project Nova', type: 'project' } },
{ id: 'orion', data: { label: 'Orion (archived)', type: 'project', archived: true } }
],
edges: [
{ from: 'alice', to: 'atlas', data: { label: 'assigned-to' } }
]
}