Events
Every payload is plain data: your own items, headings, foci and numbers, never a PixiJS object. An
item comes back exactly as your source wrote it, including its data, typed by the source’s second
type parameter (createSceneSource<Focus, Data>).
events.tsximport { useState } from "react";import { createSceneSource, DataExplorer, type ExplorerItem } from "@data-xplorer/core";
// Your own data rides along on each item as `data`, and comes back with it in the events.type Planet = { moons: number };const planets: [string, number][] = [["Mercury", 0], ["Venus", 0], ["Earth", 1], ["Mars", 2], ["Jupiter", 95]];
const source = createSceneSource<string, Planet>({ load(focus) { if (focus !== null) { const moons = planets.find(([name]) => name === focus)![1]; return { id: focus, heading: focus, clusters: [], nodes: Array.from({ length: Math.min(moons, 12) }, (_, i) => ({ id: `${focus}-${i}`, label: `Moon ${i + 1}`, weight: 1, href: `#${focus}-${i}`, drillsInto: null, shape: "disc" as const, })), edges: [], }; } return { id: "sun", heading: "Planets", nodes: [], edges: [], clusters: planets.map(([name, moons]) => ({ id: name, label: name, weight: 1 + moons, href: `#${name}`, drillsInto: moons > 0 ? name : null, shape: "cloud" as const, data: { moons }, })), }; }, parentOf: (planet) => ({ kind: "anchored", focus: null, anchorId: planet }),});
export default function Events() { const [focus, setFocus] = useState<string | null>(null); const [log, setLog] = useState<string[]>([]); const [openInstead, setOpenInstead] = useState(false); const say = (line: string) => setLog((lines) => [line, ...lines].slice(0, 30)); const name = (item: ExplorerItem<string, Planet> | null) => (item ? item.label : "nothing");
return ( <> <div className="demo-toolbar"> <label> <input type="checkbox" checked={openInstead} onChange={(e) => setOpenInstead(e.target.checked)} /> Double-click opens details instead of entering </label> </div> <DataExplorer source={source} focus={focus} onSettle={(next) => { setFocus(next); say(`onSettle: ${next ?? "top"}`); }} onNodeSelect={(item) => say(`onNodeSelect: ${name(item)}${item?.data ? `, ${item.data.moons} moons` : ""}`)} onNodeHover={(item) => item && say(`onNodeHover: ${name(item)}`)} onEnter={({ heading, direction }) => say(`onEnter: ${heading} (${direction})`)} onLeave={({ heading, direction }) => say(`onLeave: ${heading} (${direction})`)} onBackgroundClick={({ world }) => say(`onBackgroundClick at ${world.x.toFixed(0)}, ${world.y.toFixed(0)}`)} onNodeActivate={(event) => { say(`onNodeActivate: ${event.item.label} by ${event.source}`); if (openInstead) { event.preventDefault(); // the explorer will not enter it say(` ...details for ${event.item.label} would open here`); } }} /> <pre className="demo-log" aria-live="polite"> {log.join("\n") || "Click, hover or double-click an item."} </pre> </> );}| Event | Fires | Payload |
|---|---|---|
onSettle |
The camera came to rest on a scene, once per burst of motion. | the focus |
onSceneChange |
Every scene swap, immediately, including a scene filling in as it streams. Good for a breadcrumb. | { heading, focus, scene } |
onNodeSelect |
A confirmed single click or tap on an item, or null on empty space. |
the item, or null |
onNodeHover |
The item under the mouse changes. Mouse only. | the item, or null |
onNodeActivate |
A double-click or double-tap on an item, or Enter on its outline entry. | { item, source, preventDefault() } |
onLeave, onEnter |
The viewer left a scene, then arrived at one, by any route. | { heading, focus, scene, direction } |
onCameraChange |
The camera moved: at most once per drawn frame. | { x, y, scale } |
onBackgroundClick |
A confirmed single click or tap on empty space. | { screen, world } |
onTextureError |
An item image could not be drawn; once per URL. | { url } |
direction is "in" (entering an item), "out" (zooming out) or "jump" (a focus change
from outside, such as Back). A scene filling in as it streams, or refreshing after invalidate, is
not a navigation and fires neither.
onNodeActivate is cancellable. By default the explorer enters the item if it can, and for a
pointer otherwise zooms in at that point. Call preventDefault() to do something else, such as
opening a panel: tick the box in the demo and double-click a planet.