# Ontology Graph 01 - Cross-source semantic graph (`ontology-graph-01`) - SignalOS page block

> Interactive, draggable node graph of a pipeline's merged ontology: tables, columns and glossary terms clustered by domain, filterable by use case. Fully host-owned - the block only renders positions/selection/hover it derives from props and reports every interaction back through callbacks.

- **Version:** 0.1.5
- **Kind:** block (group: ontology-graph) · **Category:** pages
- **Install:** `npx shadcn@4.1.2 add @signalos/ontology-graph-01`
- **Registry dependencies (pulled automatically):** @signalos/tokens, @signalos/utils, @signalos/button, @signalos/badge, @signalos/tooltip, @signalos/split-panel, @signalos/page-header, @signalos/badge-list
- **npm dependencies:** lucide-react@^1.7.0, @xyflow/react@^12.0.0
- **Files installed:** `src/components/blocks/ontology-graph-01/OntologyGraph.tsx`, `src/components/blocks/ontology-graph-01/OntologyGraph.types.ts`, `src/components/blocks/ontology-graph-01/OntologyGraph.constants.ts`, `src/components/blocks/ontology-graph-01/OntologyGraph.utils.ts`, `src/components/blocks/ontology-graph-01/components/OntologyGraphCanvas.tsx`, `src/components/blocks/ontology-graph-01/components/OntologyGraphNode.tsx`, `src/components/blocks/ontology-graph-01/components/OntologyGraphInspector.tsx`, `src/components/blocks/ontology-graph-01/components/OntologyGraphLegend.tsx`, `src/components/blocks/ontology-graph-01/components/OntologyUseCaseFilter.tsx`

## Access

This is a private registry: pulling source requires a `SIGNALOS_REGISTRY_TOKEN`
(GitHub fine-grained PAT with read access to the signal-widgets repo) and an
`@signalos` entry in components.json `"registries"`. Previews and this document are public.

## Usage

```tsx
// after: npx shadcn@4.1.2 add @signalos/ontology-graph-01
// mount the pulled page in a route, e.g. src/app/ontology-graph/page.tsx
import OntologyGraph from "@/components/blocks/ontology-graph-01/OntologyGraph"

export default function Page() {
  return <OntologyGraph />
}
```

## Props

### `OntologyNodeData`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `string` | yes | - |  |
| `kind` | `string` | yes | - |  |
| `cluster` | `string` | yes | - |  |
| `color` | `string` | yes | - |  |
| `degree` | `number` | yes | - |  |
| `useCaseIds` | `string[]` | yes | - |  |
| `isDimmed` | `boolean` | yes | - |  |
| `isHovered` | `boolean` | yes | - |  |
| `isSelected` | `boolean` | yes | - |  |
| `sizePx` | `number` | yes | - |  |
| `fontSizePx` | `number` | yes | - |  |

### `SubUseCaseStatus`

```ts
export type SubUseCaseStatus = "proposed" | "confirmed" | "rejected"
```

### `UseCaseTreeNode`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `pipeline_id` | `string` | yes | - |  |
| `use_case_id` | `string \| undefined` | no | - |  |
| `parent_use_case_id` | `string \| null` | yes | - |  |
| `title` | `string` | yes | - |  |
| `statement` | `string` | yes | - |  |
| `source` | `string \| null \| undefined` | no | - |  |
| `status` | `SubUseCaseStatus` | yes | - |  |
| `derivation_basis` | `string[]` | yes | - |  |
| `hand_added` | `boolean` | yes | - |  |
| `review_origin` | `string \| null \| undefined` | no | - |  |
| `review_note` | `string \| null \| undefined` | no | - |  |
| `created_at` | `string \| null \| undefined` | no | - |  |
| `updated_at` | `string \| null \| undefined` | no | - |  |
| `children` | `UseCaseTreeNode[]` | yes | - |  |

### `OntologyEdgeData`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `kind` | `string` | yes | - |  |
| `isCrossSource` | `boolean` | yes | - |  |
| `detectionMethod` | `string` | yes | - |  |
| `useCaseIds` | `string[]` | yes | - |  |
| `isDimmed` | `boolean` | yes | - |  |

### `OntologyFlowNode`

```ts
export type OntologyFlowNode = Node<OntologyNodeData>
```

### `OntologyFlowEdge`

```ts
export type OntologyFlowEdge = Edge<OntologyEdgeData>
```

### `OntologyNodePropertiesLike`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `domain` | `string \| null \| undefined` | no | - |  |
| `business_purpose` | `string \| null \| undefined` | no | - |  |
| `column_count` | `number \| null \| undefined` | no | - |  |
| `definition` | `string \| null \| undefined` | no | - |  |
| `mapped_entity` | `string \| null \| undefined` | no | - |  |
| `synonyms` | `string[] \| null \| undefined` | no | - |  |
| `domain_context` | `string \| null \| undefined` | no | - |  |

### `OntologyNodeLike`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `kind` | `string` | yes | - |  |
| `cluster` | `string \| null \| undefined` | no | - |  |
| `connector_id` | `string \| null \| undefined` | no | - |  |
| `use_case_ids` | `string[] \| null \| undefined` | no | - |  |
| `tags` | `string[] \| null \| undefined` | no | - |  |
| `properties` | `OntologyNodePropertiesLike \| null \| undefined` | no | - |  |

### `OntologyEdgeLike`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `source` | `string` | yes | - |  |
| `target` | `string` | yes | - |  |
| `kind` | `string` | yes | - |  |
| `is_cross_source` | `boolean \| null \| undefined` | no | - |  |
| `detection_method` | `string \| null \| undefined` | no | - |  |
| `use_case_ids` | `string[] \| null \| undefined` | no | - |  |

### `OntologyGraphSpecLike`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `nodes` | `TNode[]` | yes | - |  |
| `edges` | `TEdge[]` | yes | - |  |
| `clusters` | `string[] \| null \| undefined` | no | - |  |
| `connectors` | `string[] \| null \| undefined` | no | - |  |

### `OntologyUseCaseLike`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `title` | `string` | yes | - |  |
| `use_case_id` | `string \| undefined` | no | - |  |
| `children` | `OntologyUseCaseLike[] \| undefined` | no | - |  |
| `description` | `string \| null \| undefined` | no | - |  |
| `status` | `string \| undefined` | no | - |  |
| `source` | `string \| null \| undefined` | no | - |  |

### `OntologyUseCaseOption`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `hint` | `string \| undefined` | no | - |  |

### `OntologyInspectorRow`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `label` | `string` | yes | - |  |
| `value` | `string` | yes | - |  |

### `OntologyInspectorConnection`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `edgeId` | `string` | yes | - |  |
| `nodeId` | `string` | yes | - |  |
| `label` | `string` | yes | - |  |
| `direction` | `"incoming" \| "outgoing"` | yes | - |  |
| `kind` | `string` | yes | - |  |

### `OntologyInspectorDetails`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `node` | `TNode` | yes | - |  |
| `useCaseIds` | `string[]` | yes | - |  |
| `rows` | `OntologyInspectorRow[]` | yes | - |  |
| `connections` | `OntologyInspectorConnection[]` | yes | - |  |

### `OntologyUseCaseBadgesRenderProps`

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `useCases` | `TUseCase[]` | yes | - |  |

### `OntologyUseCaseBadgesRenderer`

```ts
export type OntologyUseCaseBadgesRenderer<
  TUseCase extends OntologyUseCaseLike = OntologyUseCaseLike,
> = (props: OntologyUseCaseBadgesRenderProps<TUseCase>) => ReactNode
```

## Changelog

# ontology-graph-01

## 0.1.5

- `renderUseCaseBadges`'s default now composes `BadgeList` instead of a
  hand-rolled `Badge` row, so the selected node's use cases pick up
  `BadgeList`'s info-popover affordance and `+N more` overflow for free.

## 0.1.0

- Initial release: a draggable, filterable ontology graph (`@xyflow/react`)
  composed from `PageHeader` and `SplitPanel`. All state that isn't pure view
  interaction — the spec, use-case filter options, glossary toggle, selection —
  is owned by the caller and passed in as props; drag position, hover, pan and
  zoom stay local to the canvas since they're not meaningful to persist.
- Generic over the caller's node (`TNode`), edge (`TEdge`) and sub-use-case
  (`TUseCase`) shapes via the `OntologyNodeLike` / `OntologyEdgeLike` /
  `OntologyUseCaseLike` structural interfaces in `OntologyGraph.types.ts` — no
  domain types are imported.
- `renderUseCaseBadges` is a content slot for the selected node's resolved use
  cases; it defaults to a plain `Badge` row so the block renders out of the box
  with zero required wiring.
