@medicine-wheel/graph-viz 0.2.2
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 +96 -0
- package/dist/MedicineWheelGraph.d.ts +10 -0
- package/dist/MedicineWheelGraph.d.ts.map +1 -0
- package/dist/MedicineWheelGraph.js +124 -0
- package/dist/MedicineWheelGraph.js.map +1 -0
- package/dist/converters.d.ts +24 -0
- package/dist/converters.d.ts.map +1 -0
- package/dist/converters.js +73 -0
- package/dist/converters.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +37 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +204 -0
- package/dist/layout.js.map +1 -0
- package/dist/rsis-viz.d.ts +68 -0
- package/dist/rsis-viz.d.ts.map +1 -0
- package/dist/rsis-viz.js +91 -0
- package/dist/rsis-viz.js.map +1 -0
- package/dist/types.d.ts +133 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# @medicine-wheel/graph-viz
|
|
2
|
+
|
|
3
|
+
Medicine Wheel graph visualization — circular layout with four-direction node positioning, ceremony-aware edges, and OCAP® indicators.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Circular medicine wheel layout** — nodes positioned by direction (East/South/West/North)
|
|
8
|
+
- **Direction quadrant backgrounds** with Ojibwe names
|
|
9
|
+
- **Ceremony-aware edges** — gold dashed lines for honored relations
|
|
10
|
+
- **OCAP® indicators** — red/green dots showing compliance status
|
|
11
|
+
- **Wilson alignment halos** — color-coded rings showing relational accountability
|
|
12
|
+
- **Hover highlighting** — dims unconnected nodes, highlights neighbors
|
|
13
|
+
- **Pure SVG React** — no D3 runtime dependency, SSR-compatible
|
|
14
|
+
- **Dark mode** by default
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @medicine-wheel/graph-viz @medicine-wheel/ontology-core
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { MedicineWheelGraph, buildGraphData } from '@medicine-wheel/graph-viz';
|
|
26
|
+
|
|
27
|
+
// From ontology-core data
|
|
28
|
+
const graphData = buildGraphData(relationalNodes, relationalEdges);
|
|
29
|
+
|
|
30
|
+
<MedicineWheelGraph
|
|
31
|
+
data={graphData}
|
|
32
|
+
width={600}
|
|
33
|
+
height={600}
|
|
34
|
+
showDirectionLabels
|
|
35
|
+
showQuadrants
|
|
36
|
+
showNodeLabels
|
|
37
|
+
darkMode
|
|
38
|
+
onNodeClick={(node) => console.log('Clicked:', node.label)}
|
|
39
|
+
/>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Manual data
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
const data = {
|
|
46
|
+
nodes: [
|
|
47
|
+
{ id: 'n1', label: 'Ceremony', type: 'spirit', direction: 'east' },
|
|
48
|
+
{ id: 'n2', label: 'Elder', type: 'human', direction: 'north' },
|
|
49
|
+
],
|
|
50
|
+
links: [
|
|
51
|
+
{ source: 'n1', target: 'n2', label: 'guides', ceremonyHonored: true },
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
<MedicineWheelGraph data={data} />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API
|
|
59
|
+
|
|
60
|
+
### `<MedicineWheelGraph>` Props
|
|
61
|
+
|
|
62
|
+
| Prop | Type | Default | Description |
|
|
63
|
+
|------|------|---------|-------------|
|
|
64
|
+
| `data` | `MWGraphData` | required | Nodes and links |
|
|
65
|
+
| `width` | `number` | 600 | SVG width |
|
|
66
|
+
| `height` | `number` | 600 | SVG height |
|
|
67
|
+
| `layout` | `Partial<WheelLayoutConfig>` | auto | Layout configuration |
|
|
68
|
+
| `showDirectionLabels` | `boolean` | true | Show direction labels |
|
|
69
|
+
| `showQuadrants` | `boolean` | true | Show quadrant backgrounds |
|
|
70
|
+
| `showNodeLabels` | `boolean` | true | Show node labels |
|
|
71
|
+
| `showLinkLabels` | `boolean` | false | Show link labels |
|
|
72
|
+
| `showOcapIndicators` | `boolean` | false | Show OCAP® compliance dots |
|
|
73
|
+
| `showWilsonHalos` | `boolean` | false | Show Wilson alignment halos |
|
|
74
|
+
| `darkMode` | `boolean` | true | Dark background |
|
|
75
|
+
| `onNodeClick` | `(node) => void` | - | Node click handler |
|
|
76
|
+
| `onNodeHover` | `(node\|null) => void` | - | Node hover handler |
|
|
77
|
+
| `onLinkClick` | `(link) => void` | - | Link click handler |
|
|
78
|
+
|
|
79
|
+
### Layout Engine (headless)
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { applyWheelLayout, getQuadrantGeometries } from '@medicine-wheel/graph-viz';
|
|
83
|
+
|
|
84
|
+
const positioned = applyWheelLayout(data, { radius: 300, centerX: 400, centerY: 400 });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Data Converters
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { buildGraphData, nodesToGraphNodes, edgesToGraphLinks } from '@medicine-wheel/graph-viz';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT — IAIP Collaborative, Shawinigan, QC
|
|
96
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz — MedicineWheelGraph Component
|
|
3
|
+
*
|
|
4
|
+
* A pure SVG React component for rendering relational graphs
|
|
5
|
+
* in a medicine wheel circular layout. No D3 runtime dependency —
|
|
6
|
+
* layout is computed by the layout engine, rendering is pure React SVG.
|
|
7
|
+
*/
|
|
8
|
+
import type { MedicineWheelGraphProps } from './types.js';
|
|
9
|
+
export declare function MedicineWheelGraph({ data, width, height, layout: layoutConfig, showDirectionLabels, showQuadrants, showCenter, showLinkLabels, showNodeLabels, showOcapIndicators, showWilsonHalos, darkMode, className, onNodeClick, onNodeHover, onLinkClick, onBackgroundClick, }: MedicineWheelGraphProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=MedicineWheelGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MedicineWheelGraph.d.ts","sourceRoot":"","sources":["../src/MedicineWheelGraph.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,OAAO,KAAK,EAAE,uBAAuB,EAA4B,MAAM,YAAY,CAAC;AAsHpF,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,KAAW,EACX,MAAY,EACZ,MAAM,EAAE,YAAY,EACpB,mBAA0B,EAC1B,aAAoB,EACpB,UAAiB,EACjB,cAAsB,EACtB,cAAqB,EACrB,kBAA0B,EAC1B,eAAuB,EACvB,QAAe,EACf,SAAS,EACT,WAAW,EACX,WAAW,EACX,WAAW,EACX,iBAAiB,GAClB,EAAE,uBAAuB,2CA0NzB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MedicineWheelGraph = MedicineWheelGraph;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
/**
|
|
6
|
+
* @medicine-wheel/graph-viz — MedicineWheelGraph Component
|
|
7
|
+
*
|
|
8
|
+
* A pure SVG React component for rendering relational graphs
|
|
9
|
+
* in a medicine wheel circular layout. No D3 runtime dependency —
|
|
10
|
+
* layout is computed by the layout engine, rendering is pure React SVG.
|
|
11
|
+
*/
|
|
12
|
+
const react_1 = require("react");
|
|
13
|
+
const ontology_core_1 = require("@medicine-wheel/ontology-core");
|
|
14
|
+
const layout_js_1 = require("./layout.js");
|
|
15
|
+
// ── Link Style Helpers ──────────────────────────────────────────────────────
|
|
16
|
+
function linkStrokeDash(style) {
|
|
17
|
+
switch (style) {
|
|
18
|
+
case 'dashed': return '6,3';
|
|
19
|
+
case 'dotted': return '2,2';
|
|
20
|
+
case 'ceremony': return '8,3,2,3';
|
|
21
|
+
default: return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function linkColor(link, darkMode) {
|
|
25
|
+
if (link.color)
|
|
26
|
+
return link.color;
|
|
27
|
+
if (link.ceremonyHonored)
|
|
28
|
+
return '#c9a23a'; // gold for ceremony
|
|
29
|
+
return darkMode ? '#555' : '#ccc';
|
|
30
|
+
}
|
|
31
|
+
function NodeElement({ node, showLabel, showOcap, showWilson, darkMode, isHovered, isSelected, onClick, onMouseEnter, onMouseLeave, }) {
|
|
32
|
+
const x = node.x ?? 0;
|
|
33
|
+
const y = node.y ?? 0;
|
|
34
|
+
const size = node.size ?? 8;
|
|
35
|
+
const color = node.color ?? ontology_core_1.NODE_TYPE_COLORS[node.type] ?? '#888';
|
|
36
|
+
const opacity = node.opacity ?? 1;
|
|
37
|
+
const r = size * (isHovered ? 1.3 : 1);
|
|
38
|
+
return ((0, jsx_runtime_1.jsxs)("g", { transform: `translate(${x}, ${y})`, style: { cursor: 'pointer' }, onClick: () => onClick(node), onMouseEnter: () => onMouseEnter(node), onMouseLeave: onMouseLeave, children: [showWilson && node.wilsonAlignment !== undefined && ((0, jsx_runtime_1.jsx)("circle", { r: r + 4, fill: "none", stroke: node.wilsonAlignment > 0.7 ? '#4a9e5c' : node.wilsonAlignment > 0.4 ? '#c9a23a' : '#dc143c', strokeWidth: 2, strokeDasharray: node.wilsonAlignment > 0.7 ? undefined : '3,2', opacity: 0.6 })), isSelected && ((0, jsx_runtime_1.jsx)("circle", { r: r + 6, fill: "none", stroke: "#fff", strokeWidth: 2, opacity: 0.8 })), (0, jsx_runtime_1.jsx)("circle", { r: r, fill: color, opacity: opacity, stroke: darkMode ? '#222' : '#fff', strokeWidth: 1.5 }), showOcap && node.ocapCompliant !== undefined && ((0, jsx_runtime_1.jsx)("circle", { cx: r * 0.7, cy: -r * 0.7, r: 3, fill: node.ocapCompliant ? '#4a9e5c' : '#dc143c', stroke: darkMode ? '#222' : '#fff', strokeWidth: 1 })), showLabel && ((0, jsx_runtime_1.jsx)("text", { y: r + 14, textAnchor: "middle", fill: darkMode ? '#ccc' : '#333', fontSize: 11, fontFamily: "system-ui, sans-serif", children: node.label }))] }));
|
|
39
|
+
}
|
|
40
|
+
// ── Main Component ──────────────────────────────────────────────────────────
|
|
41
|
+
function MedicineWheelGraph({ data, width = 600, height = 600, layout: layoutConfig, showDirectionLabels = true, showQuadrants = true, showCenter = true, showLinkLabels = false, showNodeLabels = true, showOcapIndicators = false, showWilsonHalos = false, darkMode = true, className, onNodeClick, onNodeHover, onLinkClick, onBackgroundClick, }) {
|
|
42
|
+
const [hoveredNode, setHoveredNode] = (0, react_1.useState)(null);
|
|
43
|
+
const [selectedNode, setSelectedNode] = (0, react_1.useState)(null);
|
|
44
|
+
// Merge layout config
|
|
45
|
+
const cfg = (0, react_1.useMemo)(() => ({
|
|
46
|
+
...layout_js_1.DEFAULT_LAYOUT,
|
|
47
|
+
centerX: width / 2,
|
|
48
|
+
centerY: height / 2,
|
|
49
|
+
radius: Math.min(width, height) / 2 - 50,
|
|
50
|
+
...layoutConfig,
|
|
51
|
+
}), [width, height, layoutConfig]);
|
|
52
|
+
// Apply layout
|
|
53
|
+
const laidOut = (0, react_1.useMemo)(() => (0, layout_js_1.applyWheelLayout)({ ...data, nodes: data.nodes.map(n => ({ ...n })) }, cfg), [data, cfg]);
|
|
54
|
+
// Quadrant geometries
|
|
55
|
+
const quadrants = (0, react_1.useMemo)(() => (0, layout_js_1.getQuadrantGeometries)(cfg), [cfg]);
|
|
56
|
+
// Node position lookup
|
|
57
|
+
const nodePos = (0, react_1.useMemo)(() => {
|
|
58
|
+
const map = new Map();
|
|
59
|
+
for (const n of laidOut.nodes) {
|
|
60
|
+
if (n.x !== undefined && n.y !== undefined) {
|
|
61
|
+
map.set(n.id, { x: n.x, y: n.y });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return map;
|
|
65
|
+
}, [laidOut]);
|
|
66
|
+
// Connected node IDs for hover highlighting
|
|
67
|
+
const connectedTo = (0, react_1.useMemo)(() => {
|
|
68
|
+
const map = new Map();
|
|
69
|
+
for (const link of laidOut.links) {
|
|
70
|
+
if (!map.has(link.source))
|
|
71
|
+
map.set(link.source, new Set());
|
|
72
|
+
if (!map.has(link.target))
|
|
73
|
+
map.set(link.target, new Set());
|
|
74
|
+
map.get(link.source).add(link.target);
|
|
75
|
+
map.get(link.target).add(link.source);
|
|
76
|
+
}
|
|
77
|
+
return map;
|
|
78
|
+
}, [laidOut]);
|
|
79
|
+
// Handlers
|
|
80
|
+
const handleNodeClick = (0, react_1.useCallback)((node) => {
|
|
81
|
+
setSelectedNode(prev => prev === node.id ? null : node.id);
|
|
82
|
+
onNodeClick?.(node);
|
|
83
|
+
}, [onNodeClick]);
|
|
84
|
+
const handleNodeHover = (0, react_1.useCallback)((node) => {
|
|
85
|
+
setHoveredNode(node.id);
|
|
86
|
+
onNodeHover?.(node);
|
|
87
|
+
}, [onNodeHover]);
|
|
88
|
+
const handleNodeLeave = (0, react_1.useCallback)(() => {
|
|
89
|
+
setHoveredNode(null);
|
|
90
|
+
onNodeHover?.(null);
|
|
91
|
+
}, [onNodeHover]);
|
|
92
|
+
const handleBgClick = (0, react_1.useCallback)(() => {
|
|
93
|
+
setSelectedNode(null);
|
|
94
|
+
onBackgroundClick?.();
|
|
95
|
+
}, [onBackgroundClick]);
|
|
96
|
+
// Determine if a node should be dimmed (when hovering another node)
|
|
97
|
+
const isNodeDimmed = (nodeId) => {
|
|
98
|
+
if (!hoveredNode)
|
|
99
|
+
return false;
|
|
100
|
+
if (nodeId === hoveredNode)
|
|
101
|
+
return false;
|
|
102
|
+
return !(connectedTo.get(hoveredNode)?.has(nodeId) ?? false);
|
|
103
|
+
};
|
|
104
|
+
return ((0, jsx_runtime_1.jsxs)("svg", { width: width, height: height, viewBox: `0 0 ${width} ${height}`, className: className, style: { background: darkMode ? '#0a0a1a' : '#fafafa' }, onClick: handleBgClick, children: [(0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsx)("marker", { id: "mw-arrow", viewBox: "0 0 10 6", refX: 10, refY: 3, markerWidth: 8, markerHeight: 6, orient: "auto", children: (0, jsx_runtime_1.jsx)("path", { d: "M0,0 L10,3 L0,6 Z", fill: darkMode ? '#555' : '#999' }) }) }), showQuadrants && quadrants.map(q => ((0, jsx_runtime_1.jsx)("path", { d: (0, layout_js_1.quadrantArcPath)(cfg.centerX, cfg.centerY, cfg.radius + 10, cfg.innerRadius ?? 60, q.startAngle, q.endAngle), fill: q.color, opacity: darkMode ? 0.06 : 0.08 }, q.direction))), showCenter && ((0, jsx_runtime_1.jsx)("circle", { cx: cfg.centerX, cy: cfg.centerY, r: cfg.innerRadius ?? 60, fill: "none", stroke: darkMode ? '#333' : '#ddd', strokeWidth: 1, strokeDasharray: "4,4" })), showDirectionLabels && quadrants.map(q => {
|
|
105
|
+
const pos = (0, layout_js_1.directionLabelPosition)(cfg.centerX, cfg.centerY, cfg.radius, q.direction);
|
|
106
|
+
return ((0, jsx_runtime_1.jsxs)("g", { children: [(0, jsx_runtime_1.jsx)("text", { x: pos.x, y: pos.y, textAnchor: pos.anchor, fill: q.color, fontSize: 14, fontWeight: "bold", fontFamily: "system-ui, sans-serif", opacity: 0.9, children: q.label }), (0, jsx_runtime_1.jsx)("text", { x: pos.x, y: pos.y + 16, textAnchor: pos.anchor, fill: q.color, fontSize: 10, fontFamily: "system-ui, sans-serif", opacity: 0.6, children: q.ojibwe })] }, `label-${q.direction}`));
|
|
107
|
+
}), (0, jsx_runtime_1.jsx)("g", { children: laidOut.links.map((link, i) => {
|
|
108
|
+
const src = nodePos.get(link.source);
|
|
109
|
+
const tgt = nodePos.get(link.target);
|
|
110
|
+
if (!src || !tgt)
|
|
111
|
+
return null;
|
|
112
|
+
const isDimmed = hoveredNode
|
|
113
|
+
&& link.source !== hoveredNode
|
|
114
|
+
&& link.target !== hoveredNode;
|
|
115
|
+
return ((0, jsx_runtime_1.jsxs)("g", { opacity: isDimmed ? 0.1 : 1, children: [(0, jsx_runtime_1.jsx)("path", { d: (0, layout_js_1.curvedLinkPath)(src.x, src.y, tgt.x, tgt.y, link.curvature ?? 0), fill: "none", stroke: linkColor(link, darkMode), strokeWidth: link.width ?? 1, strokeDasharray: linkStrokeDash(link.style), markerEnd: "url(#mw-arrow)", style: { cursor: 'pointer' }, onClick: (e) => {
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
onLinkClick?.(link);
|
|
118
|
+
} }), showLinkLabels && link.label && ((0, jsx_runtime_1.jsx)("text", { x: (src.x + tgt.x) / 2, y: (src.y + tgt.y) / 2 - 5, textAnchor: "middle", fill: darkMode ? '#666' : '#999', fontSize: 9, fontFamily: "system-ui, sans-serif", children: link.label }))] }, `link-${i}`));
|
|
119
|
+
}) }), (0, jsx_runtime_1.jsx)("g", { children: laidOut.nodes.map(node => ((0, jsx_runtime_1.jsx)(NodeElement, { node: {
|
|
120
|
+
...node,
|
|
121
|
+
opacity: isNodeDimmed(node.id) ? 0.15 : (node.opacity ?? 1),
|
|
122
|
+
}, showLabel: showNodeLabels, showOcap: showOcapIndicators, showWilson: showWilsonHalos, darkMode: darkMode, isHovered: hoveredNode === node.id, isSelected: selectedNode === node.id, onClick: handleNodeClick, onMouseEnter: handleNodeHover, onMouseLeave: handleNodeLeave }, node.id))) })] }));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=MedicineWheelGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MedicineWheelGraph.js","sourceRoot":"","sources":["../src/MedicineWheelGraph.tsx"],"names":[],"mappings":";;AAuIA,gDA4OC;;AAnXD;;;;;;GAMG;AAEH,iCAA8D;AAE9D,iEAKuC;AAGvC,2CAOqB;AAErB,+EAA+E;AAE/E,SAAS,cAAc,CAAC,KAAc;IACpC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC;QAC5B,KAAK,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC;QAC5B,KAAK,UAAU,CAAC,CAAC,OAAO,SAAS,CAAC;QAClC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAiB,EAAE,QAAiB;IACrD,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC;IAClC,IAAI,IAAI,CAAC,eAAe;QAAE,OAAO,SAAS,CAAC,CAAC,oBAAoB;IAChE,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACpC,CAAC;AAiBD,SAAS,WAAW,CAAC,EACnB,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EACrC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAC/B,OAAO,EAAE,YAAY,EAAE,YAAY,GAClB;IACjB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,gCAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvC,OAAO,CACL,+BACE,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,EAClC,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAC5B,YAAY,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EACtC,YAAY,EAAE,YAAY,aAGzB,UAAU,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,IAAI,CACnD,mCACE,CAAC,EAAE,CAAC,GAAG,CAAC,EACR,IAAI,EAAC,MAAM,EACX,MAAM,EAAE,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EACnG,WAAW,EAAE,CAAC,EACd,eAAe,EAAE,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAC/D,OAAO,EAAE,GAAG,GACZ,CACH,EAGA,UAAU,IAAI,CACb,mCAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,MAAM,EAAC,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAI,CAC7E,EAGD,mCACE,CAAC,EAAE,CAAC,EACJ,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAClC,WAAW,EAAE,GAAG,GAChB,EAGD,QAAQ,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,CAC/C,mCACE,EAAE,EAAE,CAAC,GAAG,GAAG,EACX,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,EACZ,CAAC,EAAE,CAAC,EACJ,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAChD,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAClC,WAAW,EAAE,CAAC,GACd,CACH,EAGA,SAAS,IAAI,CACZ,iCACE,CAAC,EAAE,CAAC,GAAG,EAAE,EACT,UAAU,EAAC,QAAQ,EACnB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAChC,QAAQ,EAAE,EAAE,EACZ,UAAU,EAAC,uBAAuB,YAEjC,IAAI,CAAC,KAAK,GACN,CACR,IACC,CACL,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,SAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,KAAK,GAAG,GAAG,EACX,MAAM,GAAG,GAAG,EACZ,MAAM,EAAE,YAAY,EACpB,mBAAmB,GAAG,IAAI,EAC1B,aAAa,GAAG,IAAI,EACpB,UAAU,GAAG,IAAI,EACjB,cAAc,GAAG,KAAK,EACtB,cAAc,GAAG,IAAI,EACrB,kBAAkB,GAAG,KAAK,EAC1B,eAAe,GAAG,KAAK,EACvB,QAAQ,GAAG,IAAI,EACf,SAAS,EACT,WAAW,EACX,WAAW,EACX,WAAW,EACX,iBAAiB,GACO;IACxB,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IACpE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IAEtE,sBAAsB;IACtB,MAAM,GAAG,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE,CAAC,CAAC;QACzB,GAAG,0BAAc;QACjB,OAAO,EAAE,KAAK,GAAG,CAAC;QAClB,OAAO,EAAE,MAAM,GAAG,CAAC;QACnB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;QACxC,GAAG,YAAY;KAChB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAEnC,eAAe;IACf,MAAM,OAAO,GAAG,IAAA,eAAO,EACrB,GAAG,EAAE,CAAC,IAAA,4BAAgB,EAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAChF,CAAC,IAAI,EAAE,GAAG,CAAC,CACZ,CAAC;IAEF,sBAAsB;IACtB,MAAM,SAAS,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE,CAAC,IAAA,iCAAqB,EAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEnE,uBAAuB;IACvB,MAAM,OAAO,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoC,CAAC;QACxD,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC3C,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,4CAA4C;IAC5C,MAAM,WAAW,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,WAAW;IACX,MAAM,eAAe,GAAG,IAAA,mBAAW,EAAC,CAAC,IAAiB,EAAE,EAAE;QACxD,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,eAAe,GAAG,IAAA,mBAAW,EAAC,CAAC,IAAiB,EAAE,EAAE;QACxD,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,eAAe,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACvC,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,aAAa,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QACrC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,iBAAiB,EAAE,EAAE,CAAC;IACxB,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAExB,oEAAoE;IACpE,MAAM,YAAY,GAAG,CAAC,MAAc,EAAW,EAAE;QAC/C,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAC/B,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,OAAO,CACL,iCACE,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,KAAK,IAAI,MAAM,EAAE,EACjC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,EACvD,OAAO,EAAE,aAAa,aAEtB,2CAEE,mCACE,EAAE,EAAC,UAAU,EACb,OAAO,EAAC,UAAU,EAClB,IAAI,EAAE,EAAE,EACR,IAAI,EAAE,CAAC,EACP,WAAW,EAAE,CAAC,EACd,YAAY,EAAE,CAAC,EACf,MAAM,EAAC,MAAM,YAEb,iCAAM,CAAC,EAAC,mBAAmB,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAI,GACzD,GACJ,EAGN,aAAa,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACnC,iCAEE,CAAC,EAAE,IAAA,2BAAe,EAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,EAAE,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,EAC9G,IAAI,EAAE,CAAC,CAAC,KAAK,EACb,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAH1B,CAAC,CAAC,SAAS,CAIhB,CACH,CAAC,EAGD,UAAU,IAAI,CACb,mCACE,EAAE,EAAE,GAAG,CAAC,OAAO,EACf,EAAE,EAAE,GAAG,CAAC,OAAO,EACf,CAAC,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE,EACxB,IAAI,EAAC,MAAM,EACX,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAClC,WAAW,EAAE,CAAC,EACd,eAAe,EAAC,KAAK,GACrB,CACH,EAGA,mBAAmB,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACxC,MAAM,GAAG,GAAG,IAAA,kCAAsB,EAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;gBACtF,OAAO,CACL,0CACE,iCACE,CAAC,EAAE,GAAG,CAAC,CAAC,EACR,CAAC,EAAE,GAAG,CAAC,CAAC,EACR,UAAU,EAAE,GAAG,CAAC,MAAM,EACtB,IAAI,EAAE,CAAC,CAAC,KAAK,EACb,QAAQ,EAAE,EAAE,EACZ,UAAU,EAAC,MAAM,EACjB,UAAU,EAAC,uBAAuB,EAClC,OAAO,EAAE,GAAG,YAEX,CAAC,CAAC,KAAK,GACH,EACP,iCACE,CAAC,EAAE,GAAG,CAAC,CAAC,EACR,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EACb,UAAU,EAAE,GAAG,CAAC,MAAM,EACtB,IAAI,EAAE,CAAC,CAAC,KAAK,EACb,QAAQ,EAAE,EAAE,EACZ,UAAU,EAAC,uBAAuB,EAClC,OAAO,EAAE,GAAG,YAEX,CAAC,CAAC,MAAM,GACJ,KAvBD,SAAS,CAAC,CAAC,SAAS,EAAE,CAwB1B,CACL,CAAC;YACJ,CAAC,CAAC,EAGF,wCACG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;oBAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG;wBAAE,OAAO,IAAI,CAAC;oBAE9B,MAAM,QAAQ,GAAG,WAAW;2BACvB,IAAI,CAAC,MAAM,KAAK,WAAW;2BAC3B,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC;oBAEjC,OAAO,CACL,+BAAqB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAC9C,iCACE,CAAC,EAAE,IAAA,0BAAc,EAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,EAClE,IAAI,EAAC,MAAM,EACX,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,EACjC,WAAW,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,EAC5B,eAAe,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAC3C,SAAS,EAAC,gBAAgB,EAC1B,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAC5B,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;oCACb,CAAC,CAAC,eAAe,EAAE,CAAC;oCACpB,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;gCACtB,CAAC,GACD,EACD,cAAc,IAAI,IAAI,CAAC,KAAK,IAAI,CAC/B,iCACE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EACtB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAC1B,UAAU,EAAC,QAAQ,EACnB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAChC,QAAQ,EAAE,CAAC,EACX,UAAU,EAAC,uBAAuB,YAEjC,IAAI,CAAC,KAAK,GACN,CACR,KAzBK,QAAQ,CAAC,EAAE,CA0Bf,CACL,CAAC;gBACJ,CAAC,CAAC,GACA,EAGJ,wCACG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CACzB,uBAAC,WAAW,IAEV,IAAI,EAAE;wBACJ,GAAG,IAAI;wBACP,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;qBAC5D,EACD,SAAS,EAAE,cAAc,EACzB,QAAQ,EAAE,kBAAkB,EAC5B,UAAU,EAAE,eAAe,EAC3B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,WAAW,KAAK,IAAI,CAAC,EAAE,EAClC,UAAU,EAAE,YAAY,KAAK,IAAI,CAAC,EAAE,EACpC,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,eAAe,EAC7B,YAAY,EAAE,eAAe,IAbxB,IAAI,CAAC,EAAE,CAcZ,CACH,CAAC,GACA,IACA,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz — Conversion Utilities
|
|
3
|
+
*
|
|
4
|
+
* Convert ontology-core data structures into graph visualization format.
|
|
5
|
+
*/
|
|
6
|
+
import type { RelationalNode, RelationalEdge, Relation } from '@medicine-wheel/ontology-core';
|
|
7
|
+
import type { MWGraphNode, MWGraphLink, MWGraphData } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Convert RelationalNode[] to MWGraphNode[]
|
|
10
|
+
*/
|
|
11
|
+
export declare function nodesToGraphNodes(nodes: RelationalNode[]): MWGraphNode[];
|
|
12
|
+
/**
|
|
13
|
+
* Convert RelationalEdge[] to MWGraphLink[]
|
|
14
|
+
*/
|
|
15
|
+
export declare function edgesToGraphLinks(edges: RelationalEdge[]): MWGraphLink[];
|
|
16
|
+
/**
|
|
17
|
+
* Convert first-class Relation[] to MWGraphLink[]
|
|
18
|
+
*/
|
|
19
|
+
export declare function relationsToGraphLinks(relations: Relation[]): MWGraphLink[];
|
|
20
|
+
/**
|
|
21
|
+
* Build complete MWGraphData from ontology-core entities.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildGraphData(nodes: RelationalNode[], edges: RelationalEdge[] | Relation[]): MWGraphData;
|
|
24
|
+
//# sourceMappingURL=converters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../src/converters.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,QAAQ,EACT,MAAM,+BAA+B,CAAC;AAMvC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAa,MAAM,YAAY,CAAC;AAEnF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,WAAW,EAAE,CAYxE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,WAAW,EAAE,CAWxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,CAa1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,GAAG,QAAQ,EAAE,GACnC,WAAW,CAYb"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/graph-viz — Conversion Utilities
|
|
4
|
+
*
|
|
5
|
+
* Convert ontology-core data structures into graph visualization format.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.nodesToGraphNodes = nodesToGraphNodes;
|
|
9
|
+
exports.edgesToGraphLinks = edgesToGraphLinks;
|
|
10
|
+
exports.relationsToGraphLinks = relationsToGraphLinks;
|
|
11
|
+
exports.buildGraphData = buildGraphData;
|
|
12
|
+
const ontology_core_1 = require("@medicine-wheel/ontology-core");
|
|
13
|
+
/**
|
|
14
|
+
* Convert RelationalNode[] to MWGraphNode[]
|
|
15
|
+
*/
|
|
16
|
+
function nodesToGraphNodes(nodes) {
|
|
17
|
+
return nodes.map(node => ({
|
|
18
|
+
id: node.id,
|
|
19
|
+
label: node.name,
|
|
20
|
+
type: node.type,
|
|
21
|
+
direction: node.direction,
|
|
22
|
+
color: ontology_core_1.NODE_TYPE_COLORS[node.type],
|
|
23
|
+
size: 8,
|
|
24
|
+
opacity: 1,
|
|
25
|
+
data: node,
|
|
26
|
+
metadata: node.metadata,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert RelationalEdge[] to MWGraphLink[]
|
|
31
|
+
*/
|
|
32
|
+
function edgesToGraphLinks(edges) {
|
|
33
|
+
return edges.map(edge => ({
|
|
34
|
+
source: edge.from_id,
|
|
35
|
+
target: edge.to_id,
|
|
36
|
+
label: edge.relationship_type,
|
|
37
|
+
strength: edge.strength,
|
|
38
|
+
ceremonyHonored: edge.ceremony_honored,
|
|
39
|
+
style: edge.ceremony_honored ? 'ceremony' : 'solid',
|
|
40
|
+
width: 1 + edge.strength * 2,
|
|
41
|
+
curvature: 0.15,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Convert first-class Relation[] to MWGraphLink[]
|
|
46
|
+
*/
|
|
47
|
+
function relationsToGraphLinks(relations) {
|
|
48
|
+
return relations.map(rel => ({
|
|
49
|
+
source: rel.from_id,
|
|
50
|
+
target: rel.to_id,
|
|
51
|
+
label: rel.relationship_type,
|
|
52
|
+
strength: rel.strength,
|
|
53
|
+
ceremonyHonored: rel.ceremony_context?.ceremony_honored ?? false,
|
|
54
|
+
ceremonyType: rel.ceremony_context?.ceremony_type,
|
|
55
|
+
style: (rel.ceremony_context?.ceremony_honored ? 'ceremony' : 'solid'),
|
|
56
|
+
width: 1 + rel.strength * 2,
|
|
57
|
+
curvature: 0.15,
|
|
58
|
+
metadata: rel.metadata,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build complete MWGraphData from ontology-core entities.
|
|
63
|
+
*/
|
|
64
|
+
function buildGraphData(nodes, edges) {
|
|
65
|
+
const graphNodes = nodesToGraphNodes(nodes);
|
|
66
|
+
// Type guard: first-class Relations carry 'accountability' + 'ocap' fields
|
|
67
|
+
const isRelation = (e) => 'accountability' in e && 'ocap' in e;
|
|
68
|
+
const graphLinks = edges.length > 0 && isRelation(edges[0])
|
|
69
|
+
? relationsToGraphLinks(edges)
|
|
70
|
+
: edgesToGraphLinks(edges);
|
|
71
|
+
return { nodes: graphNodes, links: graphLinks };
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=converters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converters.js","sourceRoot":"","sources":["../src/converters.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAiBH,8CAYC;AAKD,8CAWC;AAKD,sDAaC;AAKD,wCAeC;AA3ED,iEAEuC;AAIvC;;GAEG;AACH,SAAgB,iBAAiB,CAAC,KAAuB;IACvD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,IAAI;QAChB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,gCAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;QAClC,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,KAAuB;IACvD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,EAAE,IAAI,CAAC,OAAO;QACpB,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,KAAK,EAAE,IAAI,CAAC,iBAAiB;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,eAAe,EAAE,IAAI,CAAC,gBAAgB;QACtC,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAuB,CAAC,CAAC,CAAC,OAAoB;QAC7E,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC;QAC5B,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,SAAqB;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,MAAM,EAAE,GAAG,CAAC,KAAK;QACjB,KAAK,EAAE,GAAG,CAAC,iBAAiB;QAC5B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,eAAe,EAAE,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,IAAI,KAAK;QAChE,YAAY,EAAE,GAAG,CAAC,gBAAgB,EAAE,aAAa;QACjD,KAAK,EAAE,CAAC,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAc;QACnF,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,CAAC;QAC3B,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACvB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAC5B,KAAuB,EACvB,KAAoC;IAEpC,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAE5C,2EAA2E;IAC3E,MAAM,UAAU,GAAG,CAAC,CAA4B,EAAiB,EAAE,CACjE,gBAAgB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;IAEvC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,qBAAqB,CAAC,KAAmB,CAAC;QAC5C,CAAC,CAAC,iBAAiB,CAAC,KAAyB,CAAC,CAAC;IAEjD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAClD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz
|
|
3
|
+
*
|
|
4
|
+
* Medicine Wheel graph visualization — circular layout with
|
|
5
|
+
* four-direction node positioning, ceremony-aware edges,
|
|
6
|
+
* and OCAP® indicators.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export { MedicineWheelGraph } from './MedicineWheelGraph.js';
|
|
11
|
+
export type { MWGraphNode, MWGraphLink, MWGraphData, LinkStyle, LayoutMode, WheelLayoutConfig, MedicineWheelGraphProps, QuadrantGeometry, } from './types.js';
|
|
12
|
+
export { applyWheelLayout, DEFAULT_LAYOUT, getQuadrantGeometries, quadrantArcPath, curvedLinkPath, directionLabelPosition, } from './layout.js';
|
|
13
|
+
export { nodesToGraphNodes, edgesToGraphLinks, relationsToGraphLinks, buildGraphData, } from './converters.js';
|
|
14
|
+
export type { KinshipGraphNode, KinshipGraphEdge, FlowDiagramNode, FlowDiagramLink, DirectionWheelSegment, TimelineEntry, } from './rsis-viz.js';
|
|
15
|
+
export { toKinshipGraphLayout, toReciprocityFlowDiagram, toDirectionWheelData, toCeremonyTimelineData, toMermaidDiagram, } from './rsis-viz.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/graph-viz
|
|
4
|
+
*
|
|
5
|
+
* Medicine Wheel graph visualization — circular layout with
|
|
6
|
+
* four-direction node positioning, ceremony-aware edges,
|
|
7
|
+
* and OCAP® indicators.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.toMermaidDiagram = exports.toCeremonyTimelineData = exports.toDirectionWheelData = exports.toReciprocityFlowDiagram = exports.toKinshipGraphLayout = exports.buildGraphData = exports.relationsToGraphLinks = exports.edgesToGraphLinks = exports.nodesToGraphNodes = exports.directionLabelPosition = exports.curvedLinkPath = exports.quadrantArcPath = exports.getQuadrantGeometries = exports.DEFAULT_LAYOUT = exports.applyWheelLayout = exports.MedicineWheelGraph = void 0;
|
|
13
|
+
// ── Component ───────────────────────────────────────────────────────────────
|
|
14
|
+
var MedicineWheelGraph_js_1 = require("./MedicineWheelGraph.js");
|
|
15
|
+
Object.defineProperty(exports, "MedicineWheelGraph", { enumerable: true, get: function () { return MedicineWheelGraph_js_1.MedicineWheelGraph; } });
|
|
16
|
+
// ── Layout Engine ───────────────────────────────────────────────────────────
|
|
17
|
+
var layout_js_1 = require("./layout.js");
|
|
18
|
+
Object.defineProperty(exports, "applyWheelLayout", { enumerable: true, get: function () { return layout_js_1.applyWheelLayout; } });
|
|
19
|
+
Object.defineProperty(exports, "DEFAULT_LAYOUT", { enumerable: true, get: function () { return layout_js_1.DEFAULT_LAYOUT; } });
|
|
20
|
+
Object.defineProperty(exports, "getQuadrantGeometries", { enumerable: true, get: function () { return layout_js_1.getQuadrantGeometries; } });
|
|
21
|
+
Object.defineProperty(exports, "quadrantArcPath", { enumerable: true, get: function () { return layout_js_1.quadrantArcPath; } });
|
|
22
|
+
Object.defineProperty(exports, "curvedLinkPath", { enumerable: true, get: function () { return layout_js_1.curvedLinkPath; } });
|
|
23
|
+
Object.defineProperty(exports, "directionLabelPosition", { enumerable: true, get: function () { return layout_js_1.directionLabelPosition; } });
|
|
24
|
+
// ── Data Converters ─────────────────────────────────────────────────────────
|
|
25
|
+
var converters_js_1 = require("./converters.js");
|
|
26
|
+
Object.defineProperty(exports, "nodesToGraphNodes", { enumerable: true, get: function () { return converters_js_1.nodesToGraphNodes; } });
|
|
27
|
+
Object.defineProperty(exports, "edgesToGraphLinks", { enumerable: true, get: function () { return converters_js_1.edgesToGraphLinks; } });
|
|
28
|
+
Object.defineProperty(exports, "relationsToGraphLinks", { enumerable: true, get: function () { return converters_js_1.relationsToGraphLinks; } });
|
|
29
|
+
Object.defineProperty(exports, "buildGraphData", { enumerable: true, get: function () { return converters_js_1.buildGraphData; } });
|
|
30
|
+
var rsis_viz_js_1 = require("./rsis-viz.js");
|
|
31
|
+
Object.defineProperty(exports, "toKinshipGraphLayout", { enumerable: true, get: function () { return rsis_viz_js_1.toKinshipGraphLayout; } });
|
|
32
|
+
Object.defineProperty(exports, "toReciprocityFlowDiagram", { enumerable: true, get: function () { return rsis_viz_js_1.toReciprocityFlowDiagram; } });
|
|
33
|
+
Object.defineProperty(exports, "toDirectionWheelData", { enumerable: true, get: function () { return rsis_viz_js_1.toDirectionWheelData; } });
|
|
34
|
+
Object.defineProperty(exports, "toCeremonyTimelineData", { enumerable: true, get: function () { return rsis_viz_js_1.toCeremonyTimelineData; } });
|
|
35
|
+
Object.defineProperty(exports, "toMermaidDiagram", { enumerable: true, get: function () { return rsis_viz_js_1.toMermaidDiagram; } });
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,+EAA+E;AAC/E,iEAA6D;AAApD,2HAAA,kBAAkB,OAAA;AAc3B,+EAA+E;AAC/E,yCAOqB;AANnB,6GAAA,gBAAgB,OAAA;AAChB,2GAAA,cAAc,OAAA;AACd,kHAAA,qBAAqB,OAAA;AACrB,4GAAA,eAAe,OAAA;AACf,2GAAA,cAAc,OAAA;AACd,mHAAA,sBAAsB,OAAA;AAGxB,+EAA+E;AAC/E,iDAKyB;AAJvB,kHAAA,iBAAiB,OAAA;AACjB,kHAAA,iBAAiB,OAAA;AACjB,sHAAA,qBAAqB,OAAA;AACrB,+GAAA,cAAc,OAAA;AAahB,6CAMuB;AALrB,mHAAA,oBAAoB,OAAA;AACpB,uHAAA,wBAAwB,OAAA;AACxB,mHAAA,oBAAoB,OAAA;AACpB,qHAAA,sBAAsB,OAAA;AACtB,+GAAA,gBAAgB,OAAA"}
|
package/dist/layout.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz — Circular Layout Engine
|
|
3
|
+
*
|
|
4
|
+
* Positions nodes in a medicine wheel pattern:
|
|
5
|
+
* - East (right): 315°–45°
|
|
6
|
+
* - South (bottom): 45°–135°
|
|
7
|
+
* - West (left): 135°–225°
|
|
8
|
+
* - North (top): 225°–315°
|
|
9
|
+
*
|
|
10
|
+
* Nodes without a direction are placed in the center.
|
|
11
|
+
*/
|
|
12
|
+
import type { DirectionName } from '@medicine-wheel/ontology-core';
|
|
13
|
+
import type { MWGraphData, WheelLayoutConfig, QuadrantGeometry } from './types.js';
|
|
14
|
+
export declare const DEFAULT_LAYOUT: WheelLayoutConfig;
|
|
15
|
+
export declare function getQuadrantGeometries(config?: WheelLayoutConfig): QuadrantGeometry[];
|
|
16
|
+
/**
|
|
17
|
+
* Apply medicine wheel circular layout to graph data.
|
|
18
|
+
* Mutates node x/y positions in place and returns the data.
|
|
19
|
+
*/
|
|
20
|
+
export declare function applyWheelLayout(data: MWGraphData, config?: Partial<WheelLayoutConfig>): MWGraphData;
|
|
21
|
+
/**
|
|
22
|
+
* Generate an SVG arc path for a quadrant background sector.
|
|
23
|
+
*/
|
|
24
|
+
export declare function quadrantArcPath(cx: number, cy: number, outerRadius: number, innerRadius: number, startAngleDeg: number, endAngleDeg: number): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate a curved link path between two nodes.
|
|
27
|
+
*/
|
|
28
|
+
export declare function curvedLinkPath(x1: number, y1: number, x2: number, y2: number, curvature?: number): string;
|
|
29
|
+
/**
|
|
30
|
+
* Generate a direction label position (outside the wheel).
|
|
31
|
+
*/
|
|
32
|
+
export declare function directionLabelPosition(cx: number, cy: number, radius: number, direction: DirectionName): {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
anchor: 'start' | 'middle' | 'end';
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,aAAa,EACd,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAEV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAiBpB,eAAO,MAAM,cAAc,EAAE,iBAU5B,CAAC;AAIF,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,iBAAkC,GACzC,gBAAgB,EAAE,CAsBpB;AA8BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACtC,WAAW,CAwEb;AAID;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,MAAM,CAmBR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EACtB,SAAS,GAAE,MAAU,GACpB,MAAM,CAYR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,aAAa,GACvB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;CAAE,CAY9D"}
|
package/dist/layout.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/graph-viz — Circular Layout Engine
|
|
4
|
+
*
|
|
5
|
+
* Positions nodes in a medicine wheel pattern:
|
|
6
|
+
* - East (right): 315°–45°
|
|
7
|
+
* - South (bottom): 45°–135°
|
|
8
|
+
* - West (left): 135°–225°
|
|
9
|
+
* - North (top): 225°–315°
|
|
10
|
+
*
|
|
11
|
+
* Nodes without a direction are placed in the center.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.DEFAULT_LAYOUT = void 0;
|
|
15
|
+
exports.getQuadrantGeometries = getQuadrantGeometries;
|
|
16
|
+
exports.applyWheelLayout = applyWheelLayout;
|
|
17
|
+
exports.quadrantArcPath = quadrantArcPath;
|
|
18
|
+
exports.curvedLinkPath = curvedLinkPath;
|
|
19
|
+
exports.directionLabelPosition = directionLabelPosition;
|
|
20
|
+
const ontology_core_1 = require("@medicine-wheel/ontology-core");
|
|
21
|
+
// ── Direction → Angle Mapping ───────────────────────────────────────────────
|
|
22
|
+
// Medicine wheel: East at right (0°/360°), clockwise
|
|
23
|
+
// SVG angles: 0° = right, increases clockwise
|
|
24
|
+
const DIRECTION_ANGLES = {
|
|
25
|
+
east: { start: 315, end: 45 },
|
|
26
|
+
south: { start: 45, end: 135 },
|
|
27
|
+
west: { start: 135, end: 225 },
|
|
28
|
+
north: { start: 225, end: 315 },
|
|
29
|
+
};
|
|
30
|
+
const DIRECTION_ORDER = ['east', 'south', 'west', 'north'];
|
|
31
|
+
// ── Default Layout Config ───────────────────────────────────────────────────
|
|
32
|
+
exports.DEFAULT_LAYOUT = {
|
|
33
|
+
mode: 'wheel',
|
|
34
|
+
centerX: 300,
|
|
35
|
+
centerY: 300,
|
|
36
|
+
radius: 250,
|
|
37
|
+
innerRadius: 60,
|
|
38
|
+
quadrantPadding: 5,
|
|
39
|
+
startAngle: 0,
|
|
40
|
+
jitter: true,
|
|
41
|
+
jitterAmount: 15,
|
|
42
|
+
};
|
|
43
|
+
// ── Quadrant Geometry ───────────────────────────────────────────────────────
|
|
44
|
+
function getQuadrantGeometries(config = exports.DEFAULT_LAYOUT) {
|
|
45
|
+
const padding = config.quadrantPadding ?? 5;
|
|
46
|
+
const offset = config.startAngle ?? 0;
|
|
47
|
+
return DIRECTION_ORDER.map(dir => {
|
|
48
|
+
const angles = DIRECTION_ANGLES[dir];
|
|
49
|
+
const start = ((angles.start + offset) % 360);
|
|
50
|
+
const end = ((angles.end + offset) % 360);
|
|
51
|
+
const centerAngle = dir === 'east'
|
|
52
|
+
? (start + (end + 360 - start) / 2) % 360
|
|
53
|
+
: (start + end) / 2;
|
|
54
|
+
return {
|
|
55
|
+
direction: dir,
|
|
56
|
+
startAngle: start + padding / 2,
|
|
57
|
+
endAngle: (dir === 'east' ? end + 360 : end) - padding / 2,
|
|
58
|
+
centerAngle,
|
|
59
|
+
color: ontology_core_1.DIRECTION_COLORS[dir],
|
|
60
|
+
label: dir.charAt(0).toUpperCase() + dir.slice(1),
|
|
61
|
+
ojibwe: ontology_core_1.OJIBWE_NAMES[dir],
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// ── Polar → Cartesian ───────────────────────────────────────────────────────
|
|
66
|
+
function degToRad(deg) {
|
|
67
|
+
return (deg * Math.PI) / 180;
|
|
68
|
+
}
|
|
69
|
+
function polarToCartesian(cx, cy, radius, angleDeg) {
|
|
70
|
+
const rad = degToRad(angleDeg);
|
|
71
|
+
return {
|
|
72
|
+
x: cx + radius * Math.cos(rad),
|
|
73
|
+
y: cy + radius * Math.sin(rad),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// ── Seeded pseudo-random for deterministic jitter ───────────────────────────
|
|
77
|
+
function seededRandom(seed) {
|
|
78
|
+
const x = Math.sin(seed * 9301 + 49297) * 49297;
|
|
79
|
+
return x - Math.floor(x);
|
|
80
|
+
}
|
|
81
|
+
// ── Layout Engine ───────────────────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Apply medicine wheel circular layout to graph data.
|
|
84
|
+
* Mutates node x/y positions in place and returns the data.
|
|
85
|
+
*/
|
|
86
|
+
function applyWheelLayout(data, config = {}) {
|
|
87
|
+
const cfg = { ...exports.DEFAULT_LAYOUT, ...config };
|
|
88
|
+
const { centerX, centerY, radius, innerRadius = 60, jitter, jitterAmount = 15 } = cfg;
|
|
89
|
+
const quadrants = getQuadrantGeometries(cfg);
|
|
90
|
+
// Group nodes by direction
|
|
91
|
+
const grouped = {
|
|
92
|
+
east: [], south: [], west: [], north: [], center: [],
|
|
93
|
+
};
|
|
94
|
+
for (const node of data.nodes) {
|
|
95
|
+
if (node.direction && node.direction in grouped) {
|
|
96
|
+
grouped[node.direction].push(node);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
grouped.center.push(node);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Position nodes in each quadrant
|
|
103
|
+
for (const quad of quadrants) {
|
|
104
|
+
const nodes = grouped[quad.direction];
|
|
105
|
+
if (nodes.length === 0)
|
|
106
|
+
continue;
|
|
107
|
+
// Effective angle range for this quadrant
|
|
108
|
+
let startDeg = quad.startAngle;
|
|
109
|
+
let endDeg = quad.endAngle;
|
|
110
|
+
if (endDeg < startDeg)
|
|
111
|
+
endDeg += 360; // handle wrap (east)
|
|
112
|
+
const angleRange = endDeg - startDeg;
|
|
113
|
+
const angleStep = nodes.length > 1 ? angleRange / (nodes.length) : 0;
|
|
114
|
+
nodes.forEach((node, i) => {
|
|
115
|
+
// Distribute evenly within quadrant
|
|
116
|
+
const angle = startDeg + angleStep * (i + 0.5);
|
|
117
|
+
// Vary radius between inner and outer
|
|
118
|
+
const radiusRange = radius - innerRadius;
|
|
119
|
+
const nodeRadius = innerRadius + radiusRange * (0.3 + 0.5 * seededRandom(i + quad.direction.length));
|
|
120
|
+
const pos = polarToCartesian(centerX, centerY, nodeRadius, angle);
|
|
121
|
+
// Apply jitter
|
|
122
|
+
if (jitter) {
|
|
123
|
+
const jx = (seededRandom(i * 7 + 1) - 0.5) * jitterAmount;
|
|
124
|
+
const jy = (seededRandom(i * 13 + 3) - 0.5) * jitterAmount;
|
|
125
|
+
pos.x += jx;
|
|
126
|
+
pos.y += jy;
|
|
127
|
+
}
|
|
128
|
+
node.x = pos.x;
|
|
129
|
+
node.y = pos.y;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Position center nodes in a small circle
|
|
133
|
+
const centerNodes = grouped.center;
|
|
134
|
+
if (centerNodes.length > 0) {
|
|
135
|
+
const centerRadius = Math.min(innerRadius * 0.6, 40);
|
|
136
|
+
const angleStep = (2 * Math.PI) / Math.max(centerNodes.length, 1);
|
|
137
|
+
centerNodes.forEach((node, i) => {
|
|
138
|
+
if (centerNodes.length === 1) {
|
|
139
|
+
node.x = centerX;
|
|
140
|
+
node.y = centerY;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
node.x = centerX + centerRadius * Math.cos(angleStep * i);
|
|
144
|
+
node.y = centerY + centerRadius * Math.sin(angleStep * i);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return data;
|
|
149
|
+
}
|
|
150
|
+
// ── SVG Path Helpers ────────────────────────────────────────────────────────
|
|
151
|
+
/**
|
|
152
|
+
* Generate an SVG arc path for a quadrant background sector.
|
|
153
|
+
*/
|
|
154
|
+
function quadrantArcPath(cx, cy, outerRadius, innerRadius, startAngleDeg, endAngleDeg) {
|
|
155
|
+
// Handle wrap-around for east quadrant
|
|
156
|
+
let endDeg = endAngleDeg;
|
|
157
|
+
if (endDeg < startAngleDeg)
|
|
158
|
+
endDeg += 360;
|
|
159
|
+
const outerStart = polarToCartesian(cx, cy, outerRadius, startAngleDeg);
|
|
160
|
+
const outerEnd = polarToCartesian(cx, cy, outerRadius, endDeg);
|
|
161
|
+
const innerStart = polarToCartesian(cx, cy, innerRadius, endDeg);
|
|
162
|
+
const innerEnd = polarToCartesian(cx, cy, innerRadius, startAngleDeg);
|
|
163
|
+
const largeArc = (endDeg - startAngleDeg) > 180 ? 1 : 0;
|
|
164
|
+
return [
|
|
165
|
+
`M ${outerStart.x} ${outerStart.y}`,
|
|
166
|
+
`A ${outerRadius} ${outerRadius} 0 ${largeArc} 1 ${outerEnd.x} ${outerEnd.y}`,
|
|
167
|
+
`L ${innerStart.x} ${innerStart.y}`,
|
|
168
|
+
`A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${innerEnd.x} ${innerEnd.y}`,
|
|
169
|
+
'Z',
|
|
170
|
+
].join(' ');
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Generate a curved link path between two nodes.
|
|
174
|
+
*/
|
|
175
|
+
function curvedLinkPath(x1, y1, x2, y2, curvature = 0) {
|
|
176
|
+
if (curvature === 0) {
|
|
177
|
+
return `M ${x1} ${y1} L ${x2} ${y2}`;
|
|
178
|
+
}
|
|
179
|
+
const dx = x2 - x1;
|
|
180
|
+
const dy = y2 - y1;
|
|
181
|
+
const mx = (x1 + x2) / 2;
|
|
182
|
+
const my = (y1 + y2) / 2;
|
|
183
|
+
// Perpendicular offset for the control point
|
|
184
|
+
const cx = mx - dy * curvature;
|
|
185
|
+
const cy = my + dx * curvature;
|
|
186
|
+
return `M ${x1} ${y1} Q ${cx} ${cy} ${x2} ${y2}`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Generate a direction label position (outside the wheel).
|
|
190
|
+
*/
|
|
191
|
+
function directionLabelPosition(cx, cy, radius, direction) {
|
|
192
|
+
const angles = {
|
|
193
|
+
east: 0,
|
|
194
|
+
south: 90,
|
|
195
|
+
west: 180,
|
|
196
|
+
north: 270,
|
|
197
|
+
};
|
|
198
|
+
const pos = polarToCartesian(cx, cy, radius + 30, angles[direction]);
|
|
199
|
+
const anchor = direction === 'east' ? 'start'
|
|
200
|
+
: direction === 'west' ? 'end'
|
|
201
|
+
: 'middle';
|
|
202
|
+
return { ...pos, anchor };
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz — RSIS Visualization Utilities
|
|
3
|
+
*
|
|
4
|
+
* Transforms relational graph data into renderable formats
|
|
5
|
+
* for D3, Sigma, Mermaid, and polar charts.
|
|
6
|
+
*/
|
|
7
|
+
import type { KinshipHubInfo, KinshipRelation, ReciprocityFlow, DirectionName, DirectionDistribution } from '@medicine-wheel/ontology-core';
|
|
8
|
+
export interface KinshipGraphNode {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
identity: string;
|
|
12
|
+
group: string;
|
|
13
|
+
}
|
|
14
|
+
export interface KinshipGraphEdge {
|
|
15
|
+
source: string;
|
|
16
|
+
target: string;
|
|
17
|
+
label: string;
|
|
18
|
+
}
|
|
19
|
+
/** Transform kinship hubs and relations into D3/Sigma-compatible graph data */
|
|
20
|
+
export declare function toKinshipGraphLayout(hubs: KinshipHubInfo[], relations: KinshipRelation[]): {
|
|
21
|
+
nodes: KinshipGraphNode[];
|
|
22
|
+
edges: KinshipGraphEdge[];
|
|
23
|
+
};
|
|
24
|
+
export interface FlowDiagramNode {
|
|
25
|
+
id: string;
|
|
26
|
+
label: string;
|
|
27
|
+
value: number;
|
|
28
|
+
}
|
|
29
|
+
export interface FlowDiagramLink {
|
|
30
|
+
source: string;
|
|
31
|
+
target: string;
|
|
32
|
+
value: number;
|
|
33
|
+
}
|
|
34
|
+
/** Transform reciprocity flows into Sankey/flow diagram data */
|
|
35
|
+
export declare function toReciprocityFlowDiagram(flows: ReciprocityFlow[]): {
|
|
36
|
+
nodes: FlowDiagramNode[];
|
|
37
|
+
links: FlowDiagramLink[];
|
|
38
|
+
};
|
|
39
|
+
export interface DirectionWheelSegment {
|
|
40
|
+
direction: DirectionName;
|
|
41
|
+
emoji: string;
|
|
42
|
+
value: number;
|
|
43
|
+
label: string;
|
|
44
|
+
}
|
|
45
|
+
/** Transform direction distribution into polar chart data */
|
|
46
|
+
export declare function toDirectionWheelData(distribution: DirectionDistribution): DirectionWheelSegment[];
|
|
47
|
+
export interface TimelineEntry {
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
sun: string;
|
|
51
|
+
cycle: string;
|
|
52
|
+
phase: string;
|
|
53
|
+
startDate?: string;
|
|
54
|
+
endDate?: string;
|
|
55
|
+
}
|
|
56
|
+
/** Transform ceremony data into timeline chart data */
|
|
57
|
+
export declare function toCeremonyTimelineData(ceremonies: Array<{
|
|
58
|
+
id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
hostSun: string;
|
|
61
|
+
cycle: string;
|
|
62
|
+
phase: string;
|
|
63
|
+
startDate?: string;
|
|
64
|
+
endDate?: string;
|
|
65
|
+
}>): TimelineEntry[];
|
|
66
|
+
/** Generate a Mermaid diagram for kinship relationships */
|
|
67
|
+
export declare function toMermaidDiagram(hubs: KinshipHubInfo[], relations: KinshipRelation[]): string;
|
|
68
|
+
//# sourceMappingURL=rsis-viz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsis-viz.d.ts","sourceRoot":"","sources":["../src/rsis-viz.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,aAAa,EACb,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AAIvC,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,cAAc,EAAE,EACtB,SAAS,EAAE,eAAe,EAAE,GAC3B;IAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAAC,KAAK,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAa1D;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gEAAgE;AAChE,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,eAAe,EAAE,GACvB;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,CAkBxD;AAID,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,aAAa,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6DAA6D;AAC7D,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,qBAAqB,GAClC,qBAAqB,EAAE,CAazB;AAID,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uDAAuD;AACvD,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACnI,aAAa,EAAE,CAUjB;AAID,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,EAAE,EACtB,SAAS,EAAE,eAAe,EAAE,GAC3B,MAAM,CAYR"}
|
package/dist/rsis-viz.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @medicine-wheel/graph-viz — RSIS Visualization Utilities
|
|
4
|
+
*
|
|
5
|
+
* Transforms relational graph data into renderable formats
|
|
6
|
+
* for D3, Sigma, Mermaid, and polar charts.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.toKinshipGraphLayout = toKinshipGraphLayout;
|
|
10
|
+
exports.toReciprocityFlowDiagram = toReciprocityFlowDiagram;
|
|
11
|
+
exports.toDirectionWheelData = toDirectionWheelData;
|
|
12
|
+
exports.toCeremonyTimelineData = toCeremonyTimelineData;
|
|
13
|
+
exports.toMermaidDiagram = toMermaidDiagram;
|
|
14
|
+
/** Transform kinship hubs and relations into D3/Sigma-compatible graph data */
|
|
15
|
+
function toKinshipGraphLayout(hubs, relations) {
|
|
16
|
+
const nodes = hubs.map(hub => ({
|
|
17
|
+
id: hub.path,
|
|
18
|
+
label: hub.identity || hub.path,
|
|
19
|
+
identity: hub.identity,
|
|
20
|
+
group: hub.lineage || 'root',
|
|
21
|
+
}));
|
|
22
|
+
const edges = relations.map(rel => ({
|
|
23
|
+
source: rel.from,
|
|
24
|
+
target: rel.to,
|
|
25
|
+
label: rel.type,
|
|
26
|
+
}));
|
|
27
|
+
return { nodes, edges };
|
|
28
|
+
}
|
|
29
|
+
/** Transform reciprocity flows into Sankey/flow diagram data */
|
|
30
|
+
function toReciprocityFlowDiagram(flows) {
|
|
31
|
+
const nodeSet = new Set();
|
|
32
|
+
for (const flow of flows) {
|
|
33
|
+
nodeSet.add(flow.from);
|
|
34
|
+
nodeSet.add(flow.to);
|
|
35
|
+
}
|
|
36
|
+
const nodes = Array.from(nodeSet).map(name => ({
|
|
37
|
+
id: name,
|
|
38
|
+
label: name,
|
|
39
|
+
value: flows.filter(f => f.from === name || f.to === name)
|
|
40
|
+
.reduce((sum, f) => sum + f.count, 0),
|
|
41
|
+
}));
|
|
42
|
+
const links = flows.map(f => ({
|
|
43
|
+
source: f.from,
|
|
44
|
+
target: f.to,
|
|
45
|
+
value: f.count,
|
|
46
|
+
}));
|
|
47
|
+
return { nodes, links };
|
|
48
|
+
}
|
|
49
|
+
/** Transform direction distribution into polar chart data */
|
|
50
|
+
function toDirectionWheelData(distribution) {
|
|
51
|
+
const emojiMap = {
|
|
52
|
+
east: '🌸', south: '🧠', west: '⚡', north: '🕸️',
|
|
53
|
+
};
|
|
54
|
+
const labelMap = {
|
|
55
|
+
east: 'Vision', south: 'Architecture', west: 'Implementation', north: 'Reflection',
|
|
56
|
+
};
|
|
57
|
+
return ['east', 'south', 'west', 'north'].map(dir => ({
|
|
58
|
+
direction: dir,
|
|
59
|
+
emoji: emojiMap[dir],
|
|
60
|
+
value: distribution[dir],
|
|
61
|
+
label: labelMap[dir],
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/** Transform ceremony data into timeline chart data */
|
|
65
|
+
function toCeremonyTimelineData(ceremonies) {
|
|
66
|
+
return ceremonies.map(c => ({
|
|
67
|
+
id: c.id,
|
|
68
|
+
name: c.name,
|
|
69
|
+
sun: c.hostSun,
|
|
70
|
+
cycle: c.cycle,
|
|
71
|
+
phase: c.phase,
|
|
72
|
+
startDate: c.startDate,
|
|
73
|
+
endDate: c.endDate,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
// ── Mermaid Export ───────────────────────────────────────────────────────────
|
|
77
|
+
/** Generate a Mermaid diagram for kinship relationships */
|
|
78
|
+
function toMermaidDiagram(hubs, relations) {
|
|
79
|
+
const lines = ['graph TD'];
|
|
80
|
+
for (const hub of hubs) {
|
|
81
|
+
const id = hub.path.replace(/[^a-zA-Z0-9]/g, '_');
|
|
82
|
+
lines.push(` ${id}["${hub.identity || hub.path}"]`);
|
|
83
|
+
}
|
|
84
|
+
for (const rel of relations) {
|
|
85
|
+
const fromId = rel.from.replace(/[^a-zA-Z0-9]/g, '_');
|
|
86
|
+
const toId = rel.to.replace(/[^a-zA-Z0-9]/g, '_');
|
|
87
|
+
lines.push(` ${fromId} -->|${rel.type}| ${toId}`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=rsis-viz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsis-viz.js","sourceRoot":"","sources":["../src/rsis-viz.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @medicine-wheel/graph-viz — Types
|
|
3
|
+
*
|
|
4
|
+
* Graph data types for Medicine Wheel visualization.
|
|
5
|
+
* Built on ontology-core types.
|
|
6
|
+
*/
|
|
7
|
+
import type { DirectionName, NodeType, CeremonyType, RelationalNode } from '@medicine-wheel/ontology-core';
|
|
8
|
+
export interface MWGraphNode {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
/** Node type determines shape/icon */
|
|
12
|
+
type: NodeType;
|
|
13
|
+
/** Direction determines quadrant positioning */
|
|
14
|
+
direction?: DirectionName;
|
|
15
|
+
/** Computed x position (set by layout) */
|
|
16
|
+
x?: number;
|
|
17
|
+
/** Computed y position (set by layout) */
|
|
18
|
+
y?: number;
|
|
19
|
+
/** Node size override (default: 8) */
|
|
20
|
+
size?: number;
|
|
21
|
+
/** Color override (default: from NODE_TYPE_COLORS) */
|
|
22
|
+
color?: string;
|
|
23
|
+
/** Opacity (0–1, default: 1) */
|
|
24
|
+
opacity?: number;
|
|
25
|
+
/** Whether this node is selected */
|
|
26
|
+
selected?: boolean;
|
|
27
|
+
/** Whether this node is highlighted (e.g., on hover) */
|
|
28
|
+
highlighted?: boolean;
|
|
29
|
+
/** OCAP® compliance status */
|
|
30
|
+
ocapCompliant?: boolean;
|
|
31
|
+
/** Wilson alignment score (0–1) */
|
|
32
|
+
wilsonAlignment?: number;
|
|
33
|
+
/** Original RelationalNode data */
|
|
34
|
+
data?: RelationalNode;
|
|
35
|
+
/** Arbitrary extra metadata for rendering */
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
export type LinkStyle = 'solid' | 'dashed' | 'dotted' | 'ceremony';
|
|
39
|
+
export interface MWGraphLink {
|
|
40
|
+
source: string;
|
|
41
|
+
target: string;
|
|
42
|
+
/** Relationship type label */
|
|
43
|
+
label?: string;
|
|
44
|
+
/** Line style */
|
|
45
|
+
style?: LinkStyle;
|
|
46
|
+
/** Strength (0–1) maps to opacity/width */
|
|
47
|
+
strength?: number;
|
|
48
|
+
/** Whether ceremony was honored on this edge */
|
|
49
|
+
ceremonyHonored?: boolean;
|
|
50
|
+
/** Ceremony type if applicable */
|
|
51
|
+
ceremonyType?: CeremonyType;
|
|
52
|
+
/** Color override */
|
|
53
|
+
color?: string;
|
|
54
|
+
/** Width override (default: computed from strength) */
|
|
55
|
+
width?: number;
|
|
56
|
+
/** Curvature (0 = straight, positive = clockwise arc) */
|
|
57
|
+
curvature?: number;
|
|
58
|
+
/** Arbitrary metadata */
|
|
59
|
+
metadata?: Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
export interface MWGraphData {
|
|
62
|
+
nodes: MWGraphNode[];
|
|
63
|
+
links: MWGraphLink[];
|
|
64
|
+
/** Optional focused node ID (triggers zoom animation) */
|
|
65
|
+
focusedNodeId?: string;
|
|
66
|
+
}
|
|
67
|
+
export type LayoutMode = 'wheel' | 'force' | 'radial';
|
|
68
|
+
export interface WheelLayoutConfig {
|
|
69
|
+
/** Layout mode */
|
|
70
|
+
mode: LayoutMode;
|
|
71
|
+
/** Center X coordinate */
|
|
72
|
+
centerX: number;
|
|
73
|
+
/** Center Y coordinate */
|
|
74
|
+
centerY: number;
|
|
75
|
+
/** Outer radius of the wheel */
|
|
76
|
+
radius: number;
|
|
77
|
+
/** Inner radius (nodes placed between inner and outer) */
|
|
78
|
+
innerRadius?: number;
|
|
79
|
+
/** Padding between direction quadrants in degrees */
|
|
80
|
+
quadrantPadding?: number;
|
|
81
|
+
/** Starting angle offset in degrees (0 = East at right) */
|
|
82
|
+
startAngle?: number;
|
|
83
|
+
/** Whether to jitter positions slightly to avoid overlap */
|
|
84
|
+
jitter?: boolean;
|
|
85
|
+
/** Jitter amount in pixels */
|
|
86
|
+
jitterAmount?: number;
|
|
87
|
+
}
|
|
88
|
+
export interface MedicineWheelGraphProps {
|
|
89
|
+
/** Graph data */
|
|
90
|
+
data: MWGraphData;
|
|
91
|
+
/** Width of the SVG canvas */
|
|
92
|
+
width?: number;
|
|
93
|
+
/** Height of the SVG canvas */
|
|
94
|
+
height?: number;
|
|
95
|
+
/** Layout configuration */
|
|
96
|
+
layout?: Partial<WheelLayoutConfig>;
|
|
97
|
+
/** Show direction labels */
|
|
98
|
+
showDirectionLabels?: boolean;
|
|
99
|
+
/** Show direction quadrant backgrounds */
|
|
100
|
+
showQuadrants?: boolean;
|
|
101
|
+
/** Show center point */
|
|
102
|
+
showCenter?: boolean;
|
|
103
|
+
/** Show link labels */
|
|
104
|
+
showLinkLabels?: boolean;
|
|
105
|
+
/** Show node labels */
|
|
106
|
+
showNodeLabels?: boolean;
|
|
107
|
+
/** Show OCAP indicators */
|
|
108
|
+
showOcapIndicators?: boolean;
|
|
109
|
+
/** Show Wilson alignment halos */
|
|
110
|
+
showWilsonHalos?: boolean;
|
|
111
|
+
/** Dark mode */
|
|
112
|
+
darkMode?: boolean;
|
|
113
|
+
/** Custom CSS class */
|
|
114
|
+
className?: string;
|
|
115
|
+
/** Node click handler */
|
|
116
|
+
onNodeClick?: (node: MWGraphNode) => void;
|
|
117
|
+
/** Node hover handler */
|
|
118
|
+
onNodeHover?: (node: MWGraphNode | null) => void;
|
|
119
|
+
/** Link click handler */
|
|
120
|
+
onLinkClick?: (link: MWGraphLink) => void;
|
|
121
|
+
/** Background click handler */
|
|
122
|
+
onBackgroundClick?: () => void;
|
|
123
|
+
}
|
|
124
|
+
export interface QuadrantGeometry {
|
|
125
|
+
direction: DirectionName;
|
|
126
|
+
startAngle: number;
|
|
127
|
+
endAngle: number;
|
|
128
|
+
centerAngle: number;
|
|
129
|
+
color: string;
|
|
130
|
+
label: string;
|
|
131
|
+
ojibwe: string;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@medicine-wheel/graph-viz",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Medicine Wheel graph visualization — circular layout with four-direction node positioning, ceremony-aware edges, and OCAP® indicators",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"lint": "tsc --noEmit",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"medicine-wheel",
|
|
29
|
+
"graph-visualization",
|
|
30
|
+
"d3",
|
|
31
|
+
"react",
|
|
32
|
+
"four-directions",
|
|
33
|
+
"indigenous-research",
|
|
34
|
+
"circular-layout"
|
|
35
|
+
],
|
|
36
|
+
"author": "IAIP Collaborative - Shawinigan, QC",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@medicine-wheel/ontology-core": "^0.2.2"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"react": ">=18.0.0",
|
|
43
|
+
"react-dom": ">=18.0.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.10.0",
|
|
47
|
+
"@types/react": "^19.0.0",
|
|
48
|
+
"@types/react-dom": "^19.0.0",
|
|
49
|
+
"react": "^19.0.0",
|
|
50
|
+
"react-dom": "^19.0.0",
|
|
51
|
+
"typescript": "^5.3.0"
|
|
52
|
+
}
|
|
53
|
+
}
|