@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.
Files changed (2) hide show
  1. package/README.md +173 -0
  2. 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.0",
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": ["dist"],
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": ["knowledge-graph", "skill-tree", "react", "visualization"],
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",