@nesso-how/graph 0.1.0-alpha.26 → 0.1.0-alpha.27
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 +11 -7
- package/dist/{ReadOnlyConceptNode.d.ts → ConceptNode.d.ts} +1 -1
- package/dist/ConceptNode.js +19 -0
- package/dist/ConceptNodeBody.d.ts +20 -0
- package/dist/{ReadOnlyConceptNode.js → ConceptNodeBody.js} +17 -29
- package/dist/{ReadOnlyNessoEdge.d.ts → NessoEdge.d.ts} +1 -1
- package/dist/{ReadOnlyNessoEdge.js → NessoEdge.js} +14 -7
- package/dist/NessoGraph.d.ts +7 -1
- package/dist/NessoGraph.js +18 -9
- package/dist/context.d.ts +6 -0
- package/dist/context.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -13,8 +13,7 @@ npm install @nesso-how/graph
|
|
|
13
13
|
```tsx
|
|
14
14
|
import { NessoGraph } from '@nesso-how/graph'
|
|
15
15
|
import '@xyflow/react/dist/style.css'
|
|
16
|
-
|
|
17
|
-
<NessoGraph
|
|
16
|
+
;<NessoGraph
|
|
18
17
|
nodes={nodes}
|
|
19
18
|
edges={edges}
|
|
20
19
|
display={{ edgeEncoding: 'full', curveStyle: 'straight' }}
|
|
@@ -23,19 +22,24 @@ import '@xyflow/react/dist/style.css'
|
|
|
23
22
|
```
|
|
24
23
|
|
|
25
24
|
`nodes`/`edges` (or a full `graph: NessoGraphFile`) render read-only by default —
|
|
26
|
-
no drag, connect, or selection.
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
no drag, connect, or selection. Default `nodeTypes`/`edgeTypes` use `ConceptNode` and
|
|
26
|
+
`NessoEdge` from this package (display settings via `GraphDisplayContext`).
|
|
27
|
+
|
|
28
|
+
Pass `display`/`palette` to control categories, glyphs, and curves. Use
|
|
29
|
+
`categoryColorMode: 'css'` when `--cat-*` CSS variables are set on the page (the main
|
|
30
|
+
app); embeds default to `palette` (hex from `PALETTES`). Optional `getRelationLabel`
|
|
31
|
+
and `isItemSelected` customize labels and selection. Pass any other
|
|
32
|
+
[`ReactFlow`](https://reactflow.dev/api-reference/react-flow) prop through `reactFlowProps`.
|
|
29
33
|
|
|
30
34
|
### Interactivity
|
|
31
35
|
|
|
32
36
|
Turn on `nodesDraggable`/`nodesConnectable`/`elementsSelectable` as needed. How you
|
|
33
37
|
provide nodes determines who owns their state:
|
|
34
38
|
|
|
35
|
-
- `nodes`/`edges` —
|
|
39
|
+
- `nodes`/`edges` — _controlled_: you own the state and must also pass
|
|
36
40
|
`onNodesChange`/`onEdgesChange`/`onConnect` to apply updates (e.g. the main app,
|
|
37
41
|
where positions live in its own store).
|
|
38
|
-
- `defaultNodes`/`defaultEdges` —
|
|
42
|
+
- `defaultNodes`/`defaultEdges` — _uncontrolled_: React Flow seeds its internal
|
|
39
43
|
state once and manages drag/connect/selection itself — no wiring needed, the
|
|
40
44
|
right choice for decorative or one-off embeds.
|
|
41
45
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Node, NodeProps } from '@xyflow/react';
|
|
2
2
|
import type { ConceptNodeData } from '@nesso-how/types';
|
|
3
3
|
type ConceptNodeType = Node<ConceptNodeData>;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function ConceptNode({ data, selected }: NodeProps<ConceptNodeType>): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { Handle, Position } from '@xyflow/react';
|
|
4
|
+
import { ConceptNodeBody } from './ConceptNodeBody.js';
|
|
5
|
+
import { useGraphDisplay } from './context.js';
|
|
6
|
+
const HIDDEN_HANDLE = {
|
|
7
|
+
width: 1,
|
|
8
|
+
height: 1,
|
|
9
|
+
minWidth: 0,
|
|
10
|
+
background: 'transparent',
|
|
11
|
+
border: 'none',
|
|
12
|
+
borderRadius: 0,
|
|
13
|
+
opacity: 0,
|
|
14
|
+
pointerEvents: 'none',
|
|
15
|
+
};
|
|
16
|
+
export function ConceptNode({ data, selected }) {
|
|
17
|
+
const { showHeatmap, showConfidence } = useGraphDisplay();
|
|
18
|
+
return (_jsxs("div", { style: { position: 'relative' }, children: [_jsx(ConceptNodeBody, { text: data.text, selected: selected, showHeatmap: showHeatmap, showConfidence: showConfidence, lastRating: data.lastRating ?? 0, reps: data.reps, due: data.due }), _jsx(Handle, { id: "out", type: "source", position: Position.Right, style: HIDDEN_HANDLE }), _jsx(Handle, { id: "in", type: "target", position: Position.Left, style: HIDDEN_HANDLE })] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CSSProperties, MouseEventHandler, ReactNode, Ref } from 'react';
|
|
2
|
+
export interface ConceptNodeBodyProps {
|
|
3
|
+
text: string;
|
|
4
|
+
selected: boolean;
|
|
5
|
+
showHeatmap: boolean;
|
|
6
|
+
showConfidence: boolean;
|
|
7
|
+
lastRating: number;
|
|
8
|
+
reps: number;
|
|
9
|
+
due: number;
|
|
10
|
+
cursor?: CSSProperties['cursor'];
|
|
11
|
+
userSelect?: CSSProperties['userSelect'];
|
|
12
|
+
className?: string;
|
|
13
|
+
connectionTarget?: boolean;
|
|
14
|
+
hideUnderline?: boolean;
|
|
15
|
+
rootRef?: Ref<HTMLDivElement>;
|
|
16
|
+
onDoubleClick?: MouseEventHandler<HTMLDivElement>;
|
|
17
|
+
/** Replaces the default label span (e.g. inline edit overlay). */
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
export declare function ConceptNodeBody({ text, selected, showHeatmap, showConfidence, lastRating, reps, due, cursor, userSelect, className, connectionTarget, hideUnderline, rootRef, onDoubleClick, children, }: ConceptNodeBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,35 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
import { Handle, Position } from '@xyflow/react';
|
|
4
|
-
import { useGraphDisplay } from './context.js';
|
|
5
2
|
import { ratingColor } from './ratingColor.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
height: 1,
|
|
9
|
-
minWidth: 0,
|
|
10
|
-
background: 'transparent',
|
|
11
|
-
border: 'none',
|
|
12
|
-
borderRadius: 0,
|
|
13
|
-
opacity: 0,
|
|
14
|
-
pointerEvents: 'none',
|
|
15
|
-
};
|
|
16
|
-
export function ReadOnlyConceptNode({ data, selected }) {
|
|
17
|
-
const { showHeatmap, showConfidence } = useGraphDisplay();
|
|
18
|
-
const heatTint = ratingColor(data.lastRating ?? 0);
|
|
3
|
+
export function ConceptNodeBody({ text, selected, showHeatmap, showConfidence, lastRating, reps, due, cursor = 'default', userSelect = 'none', className, connectionTarget = false, hideUnderline = false, rootRef, onDoubleClick, children, }) {
|
|
4
|
+
const heatTint = ratingColor(lastRating);
|
|
19
5
|
const confColor = showConfidence ? heatTint : 'var(--ink, #1a1a1a)';
|
|
20
|
-
const isStale =
|
|
21
|
-
return (_jsxs("div", { style: {
|
|
6
|
+
const isStale = reps > 0 && due <= Date.now();
|
|
7
|
+
return (_jsxs("div", { ref: rootRef, className: className, onDoubleClick: onDoubleClick, style: {
|
|
22
8
|
position: 'relative',
|
|
23
9
|
padding: '6px 14px',
|
|
24
10
|
borderRadius: 999,
|
|
25
|
-
background: selected || showHeatmap
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
? '0.5px solid var(--line, #d0d0d0)'
|
|
30
|
-
: '0.5px solid transparent',
|
|
31
|
-
cursor: 'default',
|
|
32
|
-
userSelect: 'none',
|
|
11
|
+
background: selected || showHeatmap ? 'var(--bg-card, #f5f5f5)' : 'transparent',
|
|
12
|
+
border: selected || showHeatmap ? '0.5px solid var(--line, #d0d0d0)' : '0.5px solid transparent',
|
|
13
|
+
cursor,
|
|
14
|
+
userSelect,
|
|
33
15
|
minWidth: 60,
|
|
34
16
|
}, children: [showHeatmap && (_jsx("div", { style: {
|
|
35
17
|
position: 'absolute',
|
|
@@ -45,13 +27,19 @@ export function ReadOnlyConceptNode({ data, selected }) {
|
|
|
45
27
|
border: '1px dashed var(--accent, #3b82f6)',
|
|
46
28
|
opacity: 0.7,
|
|
47
29
|
pointerEvents: 'none',
|
|
48
|
-
} })), _jsx("
|
|
30
|
+
} })), connectionTarget && (_jsx("div", { style: {
|
|
31
|
+
position: 'absolute',
|
|
32
|
+
inset: -4,
|
|
33
|
+
borderRadius: 999,
|
|
34
|
+
border: '1.5px dotted color-mix(in srgb, var(--accent, #3b82f6) 65%, transparent)',
|
|
35
|
+
pointerEvents: 'none',
|
|
36
|
+
} })), children ?? (_jsx("span", { style: {
|
|
49
37
|
font: '500 16px Fraunces, ui-serif, Georgia, serif',
|
|
50
38
|
letterSpacing: '-0.005em',
|
|
51
39
|
color: 'var(--ink, #1a1a1a)',
|
|
52
40
|
display: 'block',
|
|
53
41
|
whiteSpace: 'pre',
|
|
54
|
-
}, children:
|
|
42
|
+
}, children: text })), !hideUnderline && (_jsx("div", { style: {
|
|
55
43
|
position: 'absolute',
|
|
56
44
|
bottom: 5,
|
|
57
45
|
left: 16,
|
|
@@ -61,5 +49,5 @@ export function ReadOnlyConceptNode({ data, selected }) {
|
|
|
61
49
|
? `repeating-linear-gradient(90deg, ${confColor} 0, ${confColor} 4px, transparent 4px, transparent 8px)`
|
|
62
50
|
: confColor,
|
|
63
51
|
opacity: selected ? 0.9 : 0.55,
|
|
64
|
-
} })
|
|
52
|
+
} }))] }));
|
|
65
53
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Edge, EdgeProps } from '@xyflow/react';
|
|
2
2
|
import type { NessoEdgeData } from '@nesso-how/types';
|
|
3
3
|
type NessoFlowEdge = Edge<NessoEdgeData, 'nesso'>;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function NessoEdge({ id, source, target, data, selected }: EdgeProps<NessoFlowEdge>): import("react/jsx-runtime").JSX.Element | null;
|
|
5
5
|
export {};
|
|
@@ -9,6 +9,11 @@ import { effectiveCurveFlip, flowNodeCenterX, flowNodeCenterY, nessoArcPath, rec
|
|
|
9
9
|
function asEdgeTypeName(value, fallback = 'causes') {
|
|
10
10
|
return typeof value === 'string' && value in RELATION_TYPES ? value : fallback;
|
|
11
11
|
}
|
|
12
|
+
function categoryColor(cat, mode, palette) {
|
|
13
|
+
if (mode === 'css')
|
|
14
|
+
return `var(--cat-${cat})`;
|
|
15
|
+
return PALETTES[palette]?.[cat] ?? '#666666';
|
|
16
|
+
}
|
|
12
17
|
function EdgePathElement({ d, color, lineStyle, width = 1.5, opacity = 0.78, }) {
|
|
13
18
|
const base = {
|
|
14
19
|
fill: 'none',
|
|
@@ -29,19 +34,21 @@ function EdgePathElement({ d, color, lineStyle, width = 1.5, opacity = 0.78, })
|
|
|
29
34
|
return _jsx("path", { d: d, ...base, strokeDasharray: "0.1 5", strokeWidth: width * 1.4 });
|
|
30
35
|
return _jsx("path", { d: d, ...base });
|
|
31
36
|
}
|
|
32
|
-
export function
|
|
37
|
+
export function NessoEdge({ id, source, target, data, selected }) {
|
|
33
38
|
const [hovered, setHovered] = useState(false);
|
|
34
|
-
const { edgeEncoding, curveStyle, autoCurveFlip, palette } = useGraphDisplay();
|
|
39
|
+
const { edgeEncoding, curveStyle, autoCurveFlip, palette, categoryColorMode, getRelationLabel, isItemSelected, } = useGraphDisplay();
|
|
35
40
|
const sourceNode = useStore((s) => s.nodeLookup.get(source));
|
|
36
41
|
const targetNode = useStore((s) => s.nodeLookup.get(target));
|
|
37
42
|
const edgeType = asEdgeTypeName(data?.type);
|
|
38
43
|
const T = RELATION_TYPES[edgeType];
|
|
39
44
|
const color = edgeEncoding === 'minimal'
|
|
40
45
|
? 'var(--ink-3, #888888)'
|
|
41
|
-
: (
|
|
46
|
+
: categoryColor(T.cat, categoryColorMode, palette);
|
|
42
47
|
const lineStyle = edgeEncoding === 'minimal' ? 'solid' : T.line;
|
|
43
|
-
const
|
|
48
|
+
const isSelected = selected || isItemSelected?.('edge', id) === true;
|
|
49
|
+
const showLabel = edgeEncoding === 'full' || (edgeEncoding !== 'minimal' && (hovered || isSelected));
|
|
44
50
|
const straight = curveStyle === 'straight';
|
|
51
|
+
const label = getRelationLabel?.(edgeType) ?? T.label;
|
|
45
52
|
if (!sourceNode || !targetNode)
|
|
46
53
|
return null;
|
|
47
54
|
const sw = sourceNode.measured?.width ?? 80;
|
|
@@ -82,8 +89,8 @@ export function ReadOnlyNessoEdge({ source, target, data, selected, }) {
|
|
|
82
89
|
const ay1 = b.y + Math.sin(a1) * arrowSize;
|
|
83
90
|
const ax2 = b.x + Math.cos(a2) * arrowSize;
|
|
84
91
|
const ay2 = b.y + Math.sin(a2) * arrowSize;
|
|
85
|
-
const w =
|
|
86
|
-
const op =
|
|
92
|
+
const w = isSelected ? 2 : 1.4;
|
|
93
|
+
const op = isSelected || hovered ? 1 : 0.78;
|
|
87
94
|
const r = 11;
|
|
88
95
|
return (_jsxs("g", { onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), style: { cursor: 'default' }, children: [_jsx("path", { d: path, stroke: "transparent", strokeWidth: 14, fill: "none" }), _jsx(EdgePathElement, { d: path, color: color, lineStyle: lineStyle, width: w, opacity: op }), T.inverse !== 'self' && edgeEncoding !== 'minimal' && (_jsx("polygon", { points: `${b.x},${b.y} ${ax1},${ay1} ${ax2},${ay2}`, fill: color, opacity: 0.85 })), edgeEncoding !== 'minimal' && (_jsxs("g", { style: { pointerEvents: 'all' }, children: [_jsx("circle", { cx: labelX, cy: labelY, r: r, fill: "var(--paper, #ffffff)", stroke: color, strokeWidth: 1.2 }), _jsx("g", { transform: `translate(${labelX - 7}, ${labelY - 7})`, children: _jsx(GlyphSVG, { kind: T.glyph, color: color, size: 14 }) })] })), showLabel && (_jsx("foreignObject", { x: labelX - 60, y: labelY + r + 2, width: 120, height: 20, style: { overflow: 'visible', pointerEvents: 'none' }, children: _jsx("div", { style: {
|
|
89
96
|
display: 'inline-block',
|
|
@@ -96,5 +103,5 @@ export function ReadOnlyNessoEdge({ source, target, data, selected, }) {
|
|
|
96
103
|
letterSpacing: '0.02em',
|
|
97
104
|
whiteSpace: 'nowrap',
|
|
98
105
|
lineHeight: '16px',
|
|
99
|
-
}, children:
|
|
106
|
+
}, children: label }) }))] }));
|
|
100
107
|
}
|
package/dist/NessoGraph.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Node, Edge, NodeTypes, EdgeTypes, ReactFlowProps, Viewport, OnNodesChange, OnEdgesChange, OnConnect, OnConnectStart, OnConnectEnd, OnMoveEnd } from '@xyflow/react';
|
|
2
2
|
import type { NessoGraphFile } from '@nesso-how/formats';
|
|
3
|
+
import type { EdgeTypeName } from '@nesso-how/relation-types';
|
|
3
4
|
import type { ConceptNodeData, NessoEdgeData, GraphDisplaySettings, CategoryPalette } from '@nesso-how/types';
|
|
5
|
+
import { type CategoryColorMode } from './context.js';
|
|
4
6
|
type PassthroughKeys = 'nodes' | 'defaultNodes' | 'edges' | 'defaultEdges' | 'nodeTypes' | 'edgeTypes' | 'nodesDraggable' | 'nodesConnectable' | 'elementsSelectable' | 'onNodesChange' | 'onEdgesChange' | 'onConnect' | 'onConnectStart' | 'onConnectEnd' | 'onSelectionChange' | 'onMoveEnd' | 'onNodeClick' | 'onEdgeClick' | 'fitView' | 'defaultViewport' | 'minZoom' | 'maxZoom' | 'panOnDrag' | 'zoomOnScroll';
|
|
5
7
|
export interface NessoGraphProps {
|
|
6
8
|
graph?: NessoGraphFile;
|
|
@@ -11,6 +13,10 @@ export interface NessoGraphProps {
|
|
|
11
13
|
display?: Partial<GraphDisplaySettings>;
|
|
12
14
|
palette?: CategoryPalette;
|
|
13
15
|
showConfidence?: boolean;
|
|
16
|
+
/** `palette` (default) for embeds; `css` when `--cat-*` vars are set on the page. */
|
|
17
|
+
categoryColorMode?: CategoryColorMode;
|
|
18
|
+
getRelationLabel?: (type: EdgeTypeName) => string;
|
|
19
|
+
isItemSelected?: (kind: 'node' | 'edge', id: string) => boolean;
|
|
14
20
|
nodeTypes?: NodeTypes;
|
|
15
21
|
edgeTypes?: EdgeTypes;
|
|
16
22
|
nodesDraggable?: boolean;
|
|
@@ -37,5 +43,5 @@ export interface NessoGraphProps {
|
|
|
37
43
|
onDoubleClick?: React.MouseEventHandler<HTMLDivElement>;
|
|
38
44
|
children?: React.ReactNode;
|
|
39
45
|
}
|
|
40
|
-
export declare function NessoGraph({ graph, nodes: nodesProp, defaultNodes, edges: edgesProp, defaultEdges, display, palette, showConfidence, nodeTypes, edgeTypes, nodesDraggable, nodesConnectable, elementsSelectable, panOnDrag, zoomOnScroll, onNodesChange, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onSelectionChange, onMoveEnd, onNodeClick, onEdgeClick, fitView, defaultViewport, minZoom, maxZoom, reactFlowProps, style, className, onDoubleClick, children, }: NessoGraphProps): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
export declare function NessoGraph({ graph, nodes: nodesProp, defaultNodes, edges: edgesProp, defaultEdges, display, palette, showConfidence, categoryColorMode, getRelationLabel, isItemSelected, nodeTypes, edgeTypes, nodesDraggable, nodesConnectable, elementsSelectable, panOnDrag, zoomOnScroll, onNodesChange, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onSelectionChange, onMoveEnd, onNodeClick, onEdgeClick, fitView, defaultViewport, minZoom, maxZoom, reactFlowProps, style, className, onDoubleClick, children, }: NessoGraphProps): import("react/jsx-runtime").JSX.Element;
|
|
41
47
|
export {};
|
package/dist/NessoGraph.js
CHANGED
|
@@ -3,11 +3,11 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { useMemo } from 'react';
|
|
4
4
|
import { ReactFlow, Background, Controls } from '@xyflow/react';
|
|
5
5
|
import { GraphDisplayContext } from './context.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
const DEFAULT_NODE_TYPES = { concept:
|
|
9
|
-
const DEFAULT_EDGE_TYPES = { nesso:
|
|
10
|
-
export function NessoGraph({ graph, nodes: nodesProp, defaultNodes, edges: edgesProp, defaultEdges, display, palette = 'default', showConfidence = false, nodeTypes = DEFAULT_NODE_TYPES, edgeTypes = DEFAULT_EDGE_TYPES, nodesDraggable = false, nodesConnectable = false, elementsSelectable = true, panOnDrag = true, zoomOnScroll = true, onNodesChange, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onSelectionChange, onMoveEnd, onNodeClick, onEdgeClick, fitView = true, defaultViewport, minZoom, maxZoom, reactFlowProps, style, className, onDoubleClick, children, }) {
|
|
6
|
+
import { ConceptNode } from './ConceptNode.js';
|
|
7
|
+
import { NessoEdge } from './NessoEdge.js';
|
|
8
|
+
const DEFAULT_NODE_TYPES = { concept: ConceptNode };
|
|
9
|
+
const DEFAULT_EDGE_TYPES = { nesso: NessoEdge };
|
|
10
|
+
export function NessoGraph({ graph, nodes: nodesProp, defaultNodes, edges: edgesProp, defaultEdges, display, palette = 'default', showConfidence = false, categoryColorMode = 'palette', getRelationLabel, isItemSelected, nodeTypes = DEFAULT_NODE_TYPES, edgeTypes = DEFAULT_EDGE_TYPES, nodesDraggable = false, nodesConnectable = false, elementsSelectable = true, panOnDrag = true, zoomOnScroll = true, onNodesChange, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onSelectionChange, onMoveEnd, onNodeClick, onEdgeClick, fitView = true, defaultViewport, minZoom, maxZoom, reactFlowProps, style, className, onDoubleClick, children, }) {
|
|
11
11
|
const controlledNodes = nodesProp ?? graph?.nodes;
|
|
12
12
|
const controlledEdges = (edgesProp ?? graph?.edges);
|
|
13
13
|
// Controlled (`nodes`/`graph`) takes precedence; otherwise fall back to ReactFlow's
|
|
@@ -25,10 +25,19 @@ export function NessoGraph({ graph, nodes: nodesProp, defaultNodes, edges: edges
|
|
|
25
25
|
autoCurveFlip: display?.autoCurveFlip ?? graph?.display?.autoCurveFlip ?? true,
|
|
26
26
|
palette,
|
|
27
27
|
showConfidence,
|
|
28
|
-
|
|
28
|
+
categoryColorMode,
|
|
29
|
+
getRelationLabel,
|
|
30
|
+
isItemSelected,
|
|
31
|
+
}), [
|
|
32
|
+
display,
|
|
33
|
+
graph?.display,
|
|
34
|
+
palette,
|
|
35
|
+
showConfidence,
|
|
36
|
+
categoryColorMode,
|
|
37
|
+
getRelationLabel,
|
|
38
|
+
isItemSelected,
|
|
39
|
+
]);
|
|
29
40
|
return (_jsx("div", { style: { width: '100%', height: '100%', ...style }, className: className, onDoubleClick: onDoubleClick, children: _jsx(GraphDisplayContext.Provider, { value: ctx, children: _jsx(ReactFlow, { ...nodesProps, ...edgesProps, nodeTypes: nodeTypes, edgeTypes: edgeTypes, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, elementsSelectable: elementsSelectable, panOnDrag: panOnDrag, zoomOnScroll: zoomOnScroll, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onSelectionChange: onSelectionChange, onMoveEnd: onMoveEnd, fitView: fitView, defaultViewport: defaultViewport, minZoom: minZoom, maxZoom: maxZoom, onNodeClick: onNodeClick
|
|
30
41
|
? (_, node) => onNodeClick(node.id, node.data)
|
|
31
|
-
: undefined, onEdgeClick: onEdgeClick
|
|
32
|
-
? (_, edge) => onEdgeClick(edge.id, edge.data)
|
|
33
|
-
: undefined, ...reactFlowProps, children: children ?? (_jsxs(_Fragment, { children: [_jsx(Background, {}), _jsx(Controls, {})] })) }) }) }));
|
|
42
|
+
: undefined, onEdgeClick: onEdgeClick ? (_, edge) => onEdgeClick(edge.id, edge.data) : undefined, ...reactFlowProps, children: children ?? (_jsxs(_Fragment, { children: [_jsx(Background, {}), _jsx(Controls, {})] })) }) }) }));
|
|
34
43
|
}
|
package/dist/context.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { EdgeTypeName } from '@nesso-how/relation-types';
|
|
1
2
|
import type { EdgeEncoding, CurveStyle, CategoryPalette } from '@nesso-how/types';
|
|
3
|
+
export type CategoryColorMode = 'palette' | 'css';
|
|
2
4
|
export interface NessoGraphDisplayContext {
|
|
3
5
|
edgeEncoding: EdgeEncoding;
|
|
4
6
|
showHeatmap: boolean;
|
|
@@ -6,6 +8,10 @@ export interface NessoGraphDisplayContext {
|
|
|
6
8
|
autoCurveFlip: boolean;
|
|
7
9
|
palette: CategoryPalette;
|
|
8
10
|
showConfidence: boolean;
|
|
11
|
+
/** `palette` uses hex from PALETTES; `css` uses `var(--cat-*)` (app with live palette switching). */
|
|
12
|
+
categoryColorMode: CategoryColorMode;
|
|
13
|
+
getRelationLabel?: (type: EdgeTypeName) => string;
|
|
14
|
+
isItemSelected?: (kind: 'node' | 'edge', id: string) => boolean;
|
|
9
15
|
}
|
|
10
16
|
export declare const GraphDisplayContext: import("react").Context<NessoGraphDisplayContext>;
|
|
11
17
|
export declare function useGraphDisplay(): NessoGraphDisplayContext;
|
package/dist/context.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export { NessoGraph } from './NessoGraph.js';
|
|
2
2
|
export type { NessoGraphProps } from './NessoGraph.js';
|
|
3
|
+
export { ConceptNode } from './ConceptNode.js';
|
|
4
|
+
export { ConceptNodeBody } from './ConceptNodeBody.js';
|
|
5
|
+
export type { ConceptNodeBodyProps } from './ConceptNodeBody.js';
|
|
6
|
+
export { NessoEdge } from './NessoEdge.js';
|
|
7
|
+
export { useGraphDisplay, GraphDisplayContext } from './context.js';
|
|
8
|
+
export type { NessoGraphDisplayContext, CategoryColorMode } from './context.js';
|
|
3
9
|
export { GlyphSVG } from './GlyphSVG.js';
|
|
4
10
|
export { ratingColor } from './ratingColor.js';
|
|
5
11
|
export { defaultCurveFlip, nodeCenterX, nodeCenterY, flowNodeCenterX, flowNodeCenterY, effectiveCurveFlip, rectExit, nessoArcPath, } from './geometry.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
export { NessoGraph } from './NessoGraph.js';
|
|
3
|
+
export { ConceptNode } from './ConceptNode.js';
|
|
4
|
+
export { ConceptNodeBody } from './ConceptNodeBody.js';
|
|
5
|
+
export { NessoEdge } from './NessoEdge.js';
|
|
6
|
+
export { useGraphDisplay, GraphDisplayContext } from './context.js';
|
|
3
7
|
// Shared canvas utilities — import from here to avoid duplication with the main app.
|
|
4
8
|
export { GlyphSVG } from './GlyphSVG.js';
|
|
5
9
|
export { ratingColor } from './ratingColor.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nesso-how/graph",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.27",
|
|
4
4
|
"description": "Embeddable read-only Nesso knowledge graph React component",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,15 +21,10 @@
|
|
|
21
21
|
"import": "./dist/index.js"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "rm -rf dist && tsc",
|
|
26
|
-
"prepublishOnly": "pnpm build",
|
|
27
|
-
"dev": "tsc --watch"
|
|
28
|
-
},
|
|
29
24
|
"dependencies": {
|
|
30
|
-
"@nesso-how/formats": "
|
|
31
|
-
"@nesso-how/relation-types": "
|
|
32
|
-
"@nesso-how/types": "
|
|
25
|
+
"@nesso-how/formats": "0.1.0-alpha.27",
|
|
26
|
+
"@nesso-how/relation-types": "0.1.0-alpha.27",
|
|
27
|
+
"@nesso-how/types": "0.1.0-alpha.27"
|
|
33
28
|
},
|
|
34
29
|
"peerDependencies": {
|
|
35
30
|
"@xyflow/react": "^12.6.4",
|
|
@@ -40,5 +35,9 @@
|
|
|
40
35
|
"@types/react": "^18.3.23",
|
|
41
36
|
"@types/react-dom": "^18.3.7",
|
|
42
37
|
"typescript": "~5.8.3"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "rm -rf dist && tsc",
|
|
41
|
+
"dev": "tsc --watch"
|
|
43
42
|
}
|
|
44
|
-
}
|
|
43
|
+
}
|