Domain Architecture
A domain is a self-contained plugin that teaches Olli how to handle a specific kind of data — charts, diagrams, or anything else. Domains provide a lowerer (spec → hypergraph) and optional contributions: tokens, presets, keybindings, dialogs, and predicate providers.
Olli ships two built-in domains:
- olli-vis — the visualization domain (charts with tabular data).
- olli-diagram — the diagram domain (elements with relations).
You can create custom domains for other data types.
OlliDomain<Spec, Payload>
ts
interface OlliDomain<Spec, Payload> {
name: string;
toHypergraph(spec: Spec): Hypergraph<Payload>;
tokens?: ReadonlyArray<DescriptionToken<Payload>>;
presets?: ReadonlyArray<{ name: string; customizations: Customization[] }>;
defaultPreset?: string;
keybindings?: ReadonlyArray<KeybindingContribution<Payload>>;
dialogs?: ReadonlyArray<DialogContribution<Payload>>;
predicateProviders?: ReadonlyArray<PredicateProvider<Payload>>;
}| Property | Type | Required | Description |
|---|---|---|---|
name | string | yes | Identifier for the domain (e.g., 'olli-vis'). |
toHypergraph | (spec: Spec) => Hypergraph<Payload> | yes | Converts the domain-specific spec into a hypergraph. |
tokens | DescriptionToken<Payload>[] | no | Description tokens to register. |
presets | { name, customizations }[] | no | Named recipe presets. |
defaultPreset | string | no | Preset to apply automatically on registration. |
keybindings | KeybindingContribution<Payload>[] | no | Keyboard shortcuts. |
dialogs | DialogContribution<Payload>[] | no | Dialog contributions. |
predicateProviders | PredicateProvider<Payload>[] | no | Predicate providers for full-predicate composition. |
The two type parameters:
- Spec — the input type (e.g.,
OlliVisSpec,DiagramSpec). - Payload — the hyperedge payload type (e.g.,
VisPayload,DiagramPayload).
registerDomain
ts
function registerDomain<Spec, Payload>(
runtime: NavigationRuntime<Payload>,
domain: OlliDomain<Spec, Payload>,
): voidRegisters all of a domain's contributions onto a runtime:
- Registers each token via
runtime.registerToken. - Registers each keybinding via
runtime.registerKeybinding. - Registers each dialog via
runtime.registerDialog. - Registers each predicate provider via
runtime.registerPredicateProvider. - Registers each preset via
runtime.customization.registerPreset. - If
defaultPresetis set, applies it viaruntime.customization.applyPreset.
Built-in domains
Visualization domain
ts
// olli-vis
const visDomain: OlliDomain<OlliVisSpec, VisPayload> = {
name: 'olli-vis',
toHypergraph: lowerVisSpec,
tokens: allVisTokens(), // 9 tokens
predicateProviders: [visPredicateProvider()],
keybindings: visKeybindings(), // x, y, l jump shortcuts
presets: visPresets(), // detailed, standard, minimal
defaultPreset: 'standard',
dialogs: [tableDialog(), filterDialog(), targetedNavDialog(), descriptionSettingsDialog()],
};Diagram domain
ts
// olli-diagram
const diagramDomain: OlliDomain<DiagramSpec, DiagramPayload> = {
name: 'diagram',
toHypergraph: lowerDiagramSpec,
tokens: [elementKindToken],
predicateProviders: [diagramPredicateProvider()],
dialogs: [descriptionSettingsDialog()],
};The diagram domain is simpler — no presets, no keybindings, one token, one dialog.
How entry points use domains
The olliVis and olliDiagram entry points handle domain wiring automatically:
- Call
domain.toHypergraph(spec)to produce the initial hypergraph. - Call
createNavigationRuntime(graph)to create the runtime. - Call
registerDomain(runtime, domain)to wire up all contributions. - Mount the renderer.
When using the low-level olli entry point, no domain is registered — you get only generic navigation and built-in tokens.
Next
- Creating a Domain — step-by-step guide.
- Contributing Tokens — adding description tokens.
- Contributing Dialogs — adding dialogs.
- Contributing Keybindings — adding keyboard shortcuts.
- Contributing Predicates — adding predicate providers.