コンテンツへスキップ

サイドバーのオプション ​

サイドバーは、画面サイズまたはユーザーの好みに応じて、デフォルトで折りたたむことができます。

サイドバーがデフォルトで折りたたまれているかどうかを決定します。

  • 'auto' デフォルト: 十分な画面スペースがない限り、サイドバーを開いたままにします。十分な画面スペースがない場合、サイドバーは自動的に折りたたまれます。
  • true サイドバーは折りたたまれて開始されます。
  • false サイドバーが展開されて始まります。

サイドバーには、グラフ要素のコンテキスト情報が表示されます。これには 3 つのカスタマイズ可能なコンポーネントがあります。

UI.sidebar.enabled: false は列全体を削除し、その幅をキャンバスに戻します。 プロパティパネルと近隣パネルにはそれぞれスイッチがあります — UI.propertiesPanel.enabled, UI.neighborsPanel.enabled — パネルとセパレーターを削除しますが、残りの部分は削除されます。 サイドバーは残ります。 機能をオフにするを参照してください。

クリックしてコードを表示します
js
UI: {
    mode: 'full',
    sidebar: {
        collapsed: false,
    },
    mainHeader: {
        render: (element) => {
            const div = document.createElement('div')
            div.textContent = 'Main Header'
            div.style.fontWeight = 'bold'
            div.style.color = 'darkred'
            div.style.background = 'var(--pvt-bg-color-8)'
            div.style.padding = '4px 8px'
            div.style.borderRadius = '4px'
            return div
        }
    },
    propertiesPanel: {
        render: (element) => {
            const div = document.createElement('div')
            div.textContent = 'Properties Panel'
            div.style.fontWeight = 'bold'
            div.style.color = 'darkred'
            div.style.background = 'var(--pvt-bg-color-8)'
            div.style.padding = '4px 8px'
            div.style.borderRadius = '4px'
            return div
        }
    },
    extraPanels: [
        {
            title: 'Extra panel #1',
            render: (node) => {
                const div = document.createElement('div')
                div.textContent = 'Extra Panel #1'
                div.style.fontWeight = 'bold'
                div.style.color = 'darkred'
                div.style.background = 'var(--pvt-bg-color-8)'
                div.style.padding = '4px 8px'
                div.style.borderRadius = '4px'
                return div
            },
        },
        {
            title: 'Extra panel #2',
            render: (node) => {
                const div = document.createElement('div')
                div.textContent = 'Extra Panel #2'
                div.style.fontWeight = 'bold'
                div.style.color = 'darkred'
                div.style.background = 'var(--pvt-bg-color-8)'
                div.style.padding = '4px 8px'
                div.style.borderRadius = '4px'
                return div
            },
        },
    ],
    tooltip: {
        enabled: false,
    },
    contextMenu: {
        enabled: false,
    },
},

メインヘッダーインターフェース ​

タイトルやサブタイトルなど、選択したノードまたはエッジの簡潔な概要を表示します。これは、ユーザーが現在選択されている要素をすばやく識別するのに役立ちます。

メインヘッダーパネルはマッピング機能を通じてカスタマイズできます。ノードのデフォルトのマッピングは次のとおりです。

ts
{
    title:    node => node.data.label ?? "Could not resolve title"
    subtitle: node => node.data.description ?? ""
}

このマッピングは、必要な部分をオーバーライドすることで変更できます。

ts
const options = {
    UI: {
        mainHeader: {
            nodeHeaderMap: {
                title: node => `Node ${node.id}`,
                subtitle: node => node.data.type ?? "",
            }
        }
    }
}
ts
const options = {
    UI: {
        mainHeader: {
            edgeHeaderMap: {
                title: node => `Node ${node.id}`,
                subtitle: node => node.data.type ?? "",
            }
        }
    }
}
ts
const options = {
    UI: {
        mainHeader: {
            render: (element) => {
                const div = document.createElement('div')
                div.textContent = 'Main Header'
                return div 
            }
        }
    }
}

警告

render() が指定された場合、Pivotick は、undefined を返さない限り、デフォルトのマッピング ロジックをすべてスキップします。 undefined の結果 (または undefined に解決される Promise) は、その選択のデフォルトのヘッダーを描画します: 1 つの要素の nodeHeaderMap / edgeHeaderMap タイトル、複数の選択数、および何も選択されていない場合のキャンバスの合計。ヘッダーを空のままにするには、null を返します。

ts
mainHeader: {
    // A custom header for a lone element, the default counts for everything else.
    render: (element) => (element && !Array.isArray(element)) ? myHeader(element) : undefined,
}

プロパティパネルインターフェース ​

選択したノードまたはエッジの詳細なプロパティをサイドバーに表示します。各プロパティには、静的または動的に計算できる名前と値があります。

デフォルトの動作では、ノードまたはエッジの getData() のすべてのキーと値のペアが表示されます。

マッピング関数 (nodePropertiesMap および edgePropertiesMap) または完全なカスタム レンダラーを使用して、表示されるプロパティとそのレンダリング方法をカスタマイズできます。

ts
const options = {
    UI: {
        propertiesPanel: {
            nodePropertiesMap: (node: Node) => {
                return [
                    {
                        name: 'Node ID',
                        value: node.id,
                    },
                    {
                        name: (node) => `Type of node`,
                        value: (node) => el ? el.type : 'Unknown'
                    },
                    {
                        name: 'Custom HTML',
                        value: document.createElement('div')
                    }
                ]
            }
        }
    }
}
ts
const options = {
    UI: {
        propertiesPanel: {
            edgePropertiesMap: (node: Node) => {
                return [
                    {
                        name: 'Edge ID',
                        value: node.id,
                    },
                    {
                        name: (node) => `Type of edge`,
                        value: (node) => el ? el.type : 'Unknown'
                    },
                    {
                        name: 'Custom HTML',
                        value: document.createElement('div')
                    }
                ]
            }
        }
    }
}
ts
const options = {
    UI: {
        propertiesPanel: {
            render: (element: Node | Edge | Node[] | Edge[] | null) => {
                const div = document.createElement('div')
                div.textContent = `Element ID: ${element?.id}`
                div.style.fontWeight = 'bold'
                return div
            }
        }
    }
}
ts
const options = {
    UI: {
        propertiesPanel: {
            nodePropertiesMap: (node: Node) => {
                return Object.entries(node.getData())
                    .filter(([key, value]) => key && value)
                    .map(([key, value]) => ({ name: key, value }))
            }
        }
    }
}

プロパティ マップは、タグごとに 1 つの Tag エントリなど、同じ名前を持つ複数のエントリを返す場合があります。複数選択では、各値はそれを保持するノードをカウントし、保持/除外はノードのエントリのいずれかと一致し、値が重複するため、各値は独自のバーを取得します。

ts
nodePropertiesMap: (node) => node.getData().tags.map((tag) => ({ name: 'Tag', value: tag }))

ヒント

render() が指定された場合、Pivotick は、undefined を返さない限り、デフォルトのマッピング ロジックをすべてスキップします。 undefined 結果 (または undefined に解決される Promise) は、その選択のデフォルト パネルを描画します。つまり、1 つの要素については nodePropertiesMap / edgePropertiesMap 行、いくつかについては保持/除外フィルターを備えた集計テーブルが描画されます。パネルを空のままにするには、null を返します。

ts
const options = {
    UI: {
        propertiesPanel: {
            // A custom view for a lone node, the default aggregated table for everything else.
            render: (element) => (element instanceof Node) ? myNodeView(element) : undefined,
        }
    }
}

近隣パネルインターフェース ​

選択したノードの接続 (近隣ノードの小さなグラフ、接続統計、およびリスト) を表示します。

隣接グラフは、デフォルトでメイン グラフのレンダリング オプションを使用して描画されます。ノード詳細層やフォーカス カードなど、キャンバス全体に適したスタイルは、このサイズのパネルに詰め込む可能性があるため、 graph は独自のオーバーライドを受け取ります。

  • graph.render はメイン グラフのレンダリング オプションにマージされます。パネル独自の設定 (ドラッグなし、ズームなし、ノード展開なし) は引き続き適用されます。ここでの maxZoom は、グラフがどの程度ズームインしてフィットするかを制限するため、隣接するノードが 1 つあるノードが拡大されることはありません。
  • graph.layout はパネルの放射状レイアウト上にマージされます。ルートは常に選択されたノードになります。
ts
const options = {
    UI: {
        neighborsPanel: {
            graph: {
                render: {
                    // Plain small nodes: no tiers, no focus card.
                    nodeStyleMap: { event: { shape: 'circle', size: 10 } },
                    maxZoom: 1,
                },
                layout: { radialGap: 80 },
            },
        },
    },
}

追加パネルインターフェース ​

動的または静的コンテンツを含む完全にカスタムのパネルを追加できます。これらのパネルは、選択した要素に関連する追加のコンテキスト情報、カスタム コントロール、または対話型ウィジェットを表示するのに最適です。

各追加パネルにはオプションの title と render() があり、両方とも静的 (文字列/HTMLElement) または現在の選択の関数にすることができます。返された string は text としてレンダリングされます。独自のマークアップをレンダリングするには、HTMLElement を返します。 null を返して、パネル本体を空のままにします。

ts
const options = {
    UI: {
        extraPanels: [
            {
                title: "Info",
                render: "This is a static extra panel content"
            }
        ]
    }
}
ts
// The selection is a Node, an Edge, an array of either, or null — this example
// only cares about a single element:
const single = (element) => (element && !Array.isArray(element)) ? element : null

const options = {
    UI: {
        extraPanels: [
            {
                // Both are called with the live selection, on every selection change.
                title: (element) => single(element) ? `Node #${single(element).id}` : 'Nothing selected',
                render: (element) => {
                    const div = document.createElement('div')
                    div.textContent = single(element)?.getData().description ?? 'No description'
                    return div
                }
            }
        ]
    }
}

パネルがレンダリングされる選択範囲 ​

title と render は、現在選択されている内容を使用して、選択が変更されるたびに で再度呼び出されます。

選択引数
1 つのノード / 1 つのエッジNode または Edge
複数のノード/エッジa Node[] / Edge[]
何も選択されていませんnull

パネルは、alwaysVisible: true を設定しない限り、何かが選択されている間は 表示 のみになります。ただし、リアクティブ パネルはどちらの場合でも再レンダリングされるため、古い選択内容を説明するコンテンツが保持されることはありません。

選択範囲を記述せず、構築にコストがかかるパネルには reactive: false を設定します。その後、一度レンダリングされ、明示的な refreshPanel() のみが再構築されます。

実行時にパネルを登録する ​

UI.extraPanels は、同じレジストリの宣言形式です。そこで宣言できるものはすべて、UIManager を通じて、グラフの存続期間中の任意の時点で登録および削除することもできます。

ts
const graph = new Pivotick(container, data, options)

// Register a panel that depends on the graph itself. Returns a disposer.
const dispose = graph.UIManager.addPanel({
    id: 'unlinked-items',
    title: 'Unlinked items',
    alwaysVisible: true,
    order: -1,                              // sorts above the option-declared panels
    render: (selection) => tray.render(selection),
})

// Your own data changed (a save landed) rather than the selection —
// ask for a re-render instead of hand-patching the panel's DOM.
graph.UIManager.refreshPanel('unlinked-items')

// Gone for good (equivalent to calling `dispose()`):
graph.UIManager.removePanel('unlinked-items')
方法
addPanel(panel)パネルを登録します。ディスポーザーを返します。省略時はidが自動生成されます。グラフの準備が完了する前後、およびプラグインの install (ctx.addPanel として) から機能します。
removePanel(id)パネルとその DOM を削除します。
refreshPanel(id?)1 つのパネルまたはすべてのパネルを再レンダリングします。 reactive: false パネルも更新します。
getPanels()登録されているパネルを表示順に並べます。

パネルは order (昇順、デフォルトは 0) で並べ替えられ、同じ値内で登録順序が維持されるため、UI.extraPanels は上から下に読み取り、実行時パネルはその後に追加されます。

パネル自体の title / render は 2 番目の引数 (それ自体のハンドル) を受け取るため、グラフにアクセスせずに独自の更新を実行できます。

ts
render: (selection, panel) => {
    const button = document.createElement('button')
    button.textContent = 'Reload'
    button.onclick = () => panel.refresh()   // …or panel.remove()
    return button
}

サイドバーのみ

パネルは、full モードにあるサイドバーに表示されます。登録はどのモードでも成功します。サイドバーがレンダリングするまで、パネルにはレンダリングする場所がありません。

パネルを非同期で埋める ​

title と render は両方とも async になる可能性があり、プロパティ パネルの render / nodePropertiesMap / edgePropertiesMap およびメインヘッダー render。 Promise が保留中の間、パネルにはプレースホルダーが表示されます。

ts
graph.UIManager.addPanel({
    id: 'sightings',
    title: 'Sightings',
    render: async (selection, panel, { signal }) => {
        if (!(selection instanceof Node)) return 'Select a node'
        const res = await fetch(`/sightings/${selection.id}`, { signal })
        return renderSightings(await res.json())
    },
})

引数の順序に注意してください。パネル ハンドルは 2 番目のままで、 RenderContext は いつも最後。

パネルは選択が変更されるたびに再レンダリングされるため、フェッチは定期的に行われます。 解決する前に置き換えられます。ライブラリがそれを処理します。 レンダリングの signal は中止され、選択範囲が移動した後に結果が到着します。 は、別のノードを説明するパネルにペイントされるのではなく、ドロップされます。の refreshPanel() およびパネルの取り外しにも同じことが当てはまります。参照 完全な契約の場合は、非同期コンテンツ。