Edges
A scene’s edges always shape a radial scene’s layout.
With edges={{ visible: true }} they are also drawn, in packed and radial scenes alike: under
the items, fading with them through every transition, and culled off screen. An edge naming an item
that is not in the scene is skipped.
Each edge’s style starts from style and is overridden by styles[kind]. In the demo, a module
sits in the middle: solid arrows to what it imports, dashed curves from what imports it.
Double-click a neighbour to walk the graph.
edges.tsximport { useState } from "react";import { createSceneSource, DataExplorer, type ExplorerEdges } from "@data-xplorer/core";
// A module and its neighbours: what it imports, and what imports it.const imports: Record<string, string[]> = { app: ["router", "store", "ui"], router: ["history"], store: ["immer", "history"], ui: ["theme", "icons"], theme: [], icons: [], history: [], immer: [],};const importers = (m: string) => Object.keys(imports).filter((other) => imports[other]!.includes(m));
const source = createSceneSource<string>({ // A radial scene per module: it sits in the middle, its neighbours round it. load(focus) { const me = focus ?? "app"; const out = imports[me]!; const ins = importers(me); return { id: me, heading: me, focusId: me, clusters: [], nodes: [me, ...out, ...ins].map((m) => ({ id: m, label: m, weight: 1 + imports[m]!.length, href: `#${m}`, drillsInto: m, // double-click a neighbour to walk the graph shape: "square" as const, })), edges: [ ...out.map((m) => ({ id: `${me}>${m}`, sourceId: me, targetId: m, kind: "imports" })), ...ins.map((m) => ({ id: `${m}>${me}`, sourceId: m, targetId: me, kind: "imported-by" })), ], }; },});
// Edges are drawn only when `visible`; each style is merged over `style`, by the edge's `kind`.const edges: ExplorerEdges = { visible: true, style: { width: 1.5, alpha: 0.7 }, styles: { imports: { arrow: "end", color: "#93c5fd" }, "imported-by": { arrow: "end", dash: [5, 4], curve: 0.2, color: "#fca5a5" }, },};
export default function Edges() { const [focus, setFocus] = useState<string | null>(null); const [visible, setVisible] = useState(true); return ( <> <div className="demo-toolbar"> <button onClick={() => setVisible(!visible)}>{visible ? "Hide" : "Show"} edges</button> <button onClick={() => setFocus(null)}>Back to app</button> </div> <DataExplorer source={source} focus={focus} onSettle={setFocus} edges={{ ...edges, visible }} /> </> );}| Style | Default | Effect |
|---|---|---|
color |
palette.label |
Any colour. |
width |
1.5 |
Screen pixels, whatever the zoom. |
alpha |
0.5 |
Multiplied by the lower opacity of the edge’s two items. |
dash |
null |
[dash, gap] in screen pixels, or null for solid. |
arrow |
"none" |
"start", "end" (at targetId) or "both". |
curve |
0 |
Bows the edge sideways by this fraction of its length (−1 to 1). Edges both ways between one pair, with the same curve, part. |
Every drawn edge is also in the outline, as a link to its far end, so a relationship that can be seen can also be followed from the keyboard and by a screen reader.
Cap. A scene draws at most edges.max edges (default 500). Over it, edges to the scene’s
focusId come first, then the rest in order, and the outline says how many are shown. Dashes are
the expensive style: see Performance.