@expertrees/react 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -0
- package/package.json +16 -3
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# @expertrees/react
|
|
2
|
+
|
|
3
|
+
React hook and component for [@expertrees/core](https://www.npmjs.com/package/@expertrees/core) — a hierarchical knowledge graph visualizer with a star map aesthetic.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm add @expertrees/core @expertrees/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Component usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { ExpertreeCanvas } from '@expertrees/react'
|
|
15
|
+
import type { SkillGraph } from '@expertrees/core'
|
|
16
|
+
|
|
17
|
+
const graph: SkillGraph = {
|
|
18
|
+
id: 'my-skills',
|
|
19
|
+
label: 'My Skills',
|
|
20
|
+
nodes: [
|
|
21
|
+
{ id: 'eng', label: 'Engineering', depth: 0, childIds: ['fe', 'be'] },
|
|
22
|
+
{ id: 'fe', label: 'Frontend', depth: 1, parentId: 'eng', childIds: ['react'] },
|
|
23
|
+
{ id: 'be', label: 'Backend', depth: 1, parentId: 'eng' },
|
|
24
|
+
{ id: 'react', label: 'React', depth: 2, parentId: 'fe' },
|
|
25
|
+
],
|
|
26
|
+
edges: [],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function App() {
|
|
30
|
+
return (
|
|
31
|
+
<ExpertreeCanvas
|
|
32
|
+
data={graph}
|
|
33
|
+
style={{ width: '100%', height: '600px' }}
|
|
34
|
+
on={{
|
|
35
|
+
'node:click': node => console.log(node),
|
|
36
|
+
'context:enter': (node, stack) => console.log('entered', node.label),
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Component props
|
|
44
|
+
|
|
45
|
+
| Prop | Type | Default | Description |
|
|
46
|
+
|------|------|---------|-------------|
|
|
47
|
+
| `data` | `SkillGraph` | required | Graph data |
|
|
48
|
+
| `theme` | `ThemeInput` | — | Visual theme overrides |
|
|
49
|
+
| `lod` | `LodThreshold[]` | — | Level-of-detail config |
|
|
50
|
+
| `initialContextNodeId` | `string` | — | Start inside a specific bubble |
|
|
51
|
+
| `on` | `Partial<SkillTreeEvents>` | — | Event handlers |
|
|
52
|
+
| `width` | `string` | `'100%'` | Canvas width (CSS) |
|
|
53
|
+
| `height` | `string` | `'100%'` | Canvas height (CSS) |
|
|
54
|
+
| `style` | `CSSProperties` | — | Additional inline styles |
|
|
55
|
+
| `className` | `string` | — | CSS class name |
|
|
56
|
+
|
|
57
|
+
### Imperative ref API
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { useRef } from 'react'
|
|
61
|
+
import { ExpertreeCanvas, type ExpertreeCanvasHandle } from '@expertrees/react'
|
|
62
|
+
|
|
63
|
+
export function App() {
|
|
64
|
+
const ref = useRef<ExpertreeCanvasHandle>(null)
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<>
|
|
68
|
+
<ExpertreeCanvas ref={ref} data={graph} style={{ width: '100%', height: '600px' }} />
|
|
69
|
+
<button onClick={() => ref.current?.setNodeState('react', 'unlocked')}>
|
|
70
|
+
Unlock React
|
|
71
|
+
</button>
|
|
72
|
+
<button onClick={() => ref.current?.goBack()}>Back</button>
|
|
73
|
+
</>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The ref exposes all imperative methods plus read-only state properties:
|
|
79
|
+
|
|
80
|
+
| Name | Type | Description |
|
|
81
|
+
|------|------|-------------|
|
|
82
|
+
| `setNodeState(id, state)` | `(string, NodeState) => void` | Update a node's semantic state |
|
|
83
|
+
| `addEvidence(id, ev)` | `(string, Evidence) => void` | Attach evidence to a node |
|
|
84
|
+
| `removeEvidence(id, evId)` | `(string, string) => void` | Remove evidence |
|
|
85
|
+
| `updateTheme(theme)` | `(ThemeInput) => void` | Hot-swap the visual theme |
|
|
86
|
+
| `zoomIn()` | `() => void` | Programmatic zoom in |
|
|
87
|
+
| `zoomOut()` | `() => void` | Programmatic zoom out |
|
|
88
|
+
| `goBack()` | `() => void` | Exit to parent context |
|
|
89
|
+
| `enterContext(id)` | `(string) => void` | Programmatically enter a bubble |
|
|
90
|
+
| `jumpToNavDepth(n)` | `(number) => void` | Jump to stack depth `n` in one animation |
|
|
91
|
+
| `getGraph()` | `() => SkillGraph` | Serialize current graph state |
|
|
92
|
+
| `hoveredNode` | `SkillNode \| null` | Currently hovered node (read-only) |
|
|
93
|
+
| `selectedNode` | `SkillNode \| null` | Currently selected node (read-only) |
|
|
94
|
+
| `zoom` | `number` | Current zoom level (read-only) |
|
|
95
|
+
| `navigationStack` | `readonly NavigationFrame[]` | Current nav stack (read-only) |
|
|
96
|
+
| `canGoBack` | `boolean` | Whether a parent context exists (read-only) |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Hook usage
|
|
101
|
+
|
|
102
|
+
Use `useExpertree` directly for full control over the canvas and layout.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { useExpertree } from '@expertrees/react'
|
|
106
|
+
import type { SkillGraph } from '@expertrees/core'
|
|
107
|
+
|
|
108
|
+
declare const graph: SkillGraph
|
|
109
|
+
|
|
110
|
+
export function SkillMap() {
|
|
111
|
+
const {
|
|
112
|
+
canvasRef,
|
|
113
|
+
hoveredNode,
|
|
114
|
+
selectedNode,
|
|
115
|
+
zoom,
|
|
116
|
+
navigationStack,
|
|
117
|
+
canGoBack,
|
|
118
|
+
goBack,
|
|
119
|
+
jumpToNavDepth,
|
|
120
|
+
setNodeState,
|
|
121
|
+
} = useExpertree({
|
|
122
|
+
data: graph,
|
|
123
|
+
on: { 'node:click': node => console.log(node) },
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div style={{ position: 'relative', width: '100%', height: '600px' }}>
|
|
128
|
+
<canvas ref={canvasRef} style={{ width: '100%', height: '100%' }} />
|
|
129
|
+
|
|
130
|
+
{/* Breadcrumbs */}
|
|
131
|
+
<nav style={{ position: 'absolute', top: 8, left: 8 }}>
|
|
132
|
+
{navigationStack.map((frame, i) => (
|
|
133
|
+
<button key={frame.nodeId ?? 'root'} onClick={() => jumpToNavDepth(i + 1)}>
|
|
134
|
+
{frame.label}
|
|
135
|
+
</button>
|
|
136
|
+
))}
|
|
137
|
+
</nav>
|
|
138
|
+
|
|
139
|
+
{/* Side panel */}
|
|
140
|
+
{hoveredNode && (
|
|
141
|
+
<aside style={{ position: 'absolute', right: 0, top: 0 }}>
|
|
142
|
+
<h3>{hoveredNode.label}</h3>
|
|
143
|
+
</aside>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### `useExpertree` return values
|
|
151
|
+
|
|
152
|
+
| Name | Type | Description |
|
|
153
|
+
|------|------|-------------|
|
|
154
|
+
| `canvasRef` | callback ref | Pass directly to `<canvas ref={canvasRef}>` |
|
|
155
|
+
| `hoveredNode` | `SkillNode \| null` | Currently hovered node |
|
|
156
|
+
| `selectedNode` | `SkillNode \| null` | Currently selected node |
|
|
157
|
+
| `zoom` | `number` | Current zoom level |
|
|
158
|
+
| `navigationStack` | `readonly NavigationFrame[]` | Full nav stack; last entry is active context |
|
|
159
|
+
| `canGoBack` | `boolean` | Whether a parent context exists |
|
|
160
|
+
| `goBack()` | `() => void` | Exit to parent context |
|
|
161
|
+
| `jumpToNavDepth(n)` | `(number) => void` | Jump to stack depth `n` in one animation |
|
|
162
|
+
| `enterContext(id)` | `(string) => void` | Programmatically enter a bubble |
|
|
163
|
+
| `setNodeState(id, state)` | `(string, NodeState) => void` | Update a node's semantic state |
|
|
164
|
+
| `addEvidence(id, ev)` | `(string, Evidence) => void` | Attach evidence to a node |
|
|
165
|
+
| `removeEvidence(id, evId)` | `(string, string) => void` | Remove evidence |
|
|
166
|
+
| `updateTheme(theme)` | `(ThemeInput) => void` | Hot-swap the visual theme |
|
|
167
|
+
| `zoomIn()` | `() => void` | Programmatic zoom in |
|
|
168
|
+
| `zoomOut()` | `() => void` | Programmatic zoom out |
|
|
169
|
+
| `getGraph()` | `() => SkillGraph` | Serialize current graph state |
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT — [github.com/0xMack/expertrees](https://github.com/0xMack/expertrees)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expertrees/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "React hook and component for @expertrees/core",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,11 +14,24 @@
|
|
|
14
14
|
"require": "./dist/index.cjs"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"files": [
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/0xMack/expertrees.git",
|
|
24
|
+
"directory": "packages/react"
|
|
25
|
+
},
|
|
18
26
|
"publishConfig": {
|
|
19
27
|
"access": "public"
|
|
20
28
|
},
|
|
21
|
-
"keywords": [
|
|
29
|
+
"keywords": [
|
|
30
|
+
"knowledge-graph",
|
|
31
|
+
"skill-tree",
|
|
32
|
+
"react",
|
|
33
|
+
"visualization"
|
|
34
|
+
],
|
|
22
35
|
"scripts": {
|
|
23
36
|
"build": "vite build",
|
|
24
37
|
"dev": "vite build --watch",
|