@principal-ai/principal-view-react 0.6.6
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 +111 -0
- package/dist/components/ConfigurationSelector.d.ts +37 -0
- package/dist/components/ConfigurationSelector.d.ts.map +1 -0
- package/dist/components/ConfigurationSelector.js +67 -0
- package/dist/components/ConfigurationSelector.js.map +1 -0
- package/dist/components/EdgeInfoPanel.d.ts +16 -0
- package/dist/components/EdgeInfoPanel.d.ts.map +1 -0
- package/dist/components/EdgeInfoPanel.js +85 -0
- package/dist/components/EdgeInfoPanel.js.map +1 -0
- package/dist/components/EventLog.d.ts +20 -0
- package/dist/components/EventLog.d.ts.map +1 -0
- package/dist/components/EventLog.js +13 -0
- package/dist/components/EventLog.js.map +1 -0
- package/dist/components/EventLog.test.d.ts +2 -0
- package/dist/components/EventLog.test.d.ts.map +1 -0
- package/dist/components/EventLog.test.js +73 -0
- package/dist/components/EventLog.test.js.map +1 -0
- package/dist/components/GraphRenderer.d.ts +121 -0
- package/dist/components/GraphRenderer.d.ts.map +1 -0
- package/dist/components/GraphRenderer.js +809 -0
- package/dist/components/GraphRenderer.js.map +1 -0
- package/dist/components/GraphRenderer.test.d.ts +2 -0
- package/dist/components/GraphRenderer.test.d.ts.map +1 -0
- package/dist/components/GraphRenderer.test.js +88 -0
- package/dist/components/GraphRenderer.test.js.map +1 -0
- package/dist/components/MetricsDashboard.d.ts +14 -0
- package/dist/components/MetricsDashboard.d.ts.map +1 -0
- package/dist/components/MetricsDashboard.js +13 -0
- package/dist/components/MetricsDashboard.js.map +1 -0
- package/dist/components/NodeInfoPanel.d.ts +21 -0
- package/dist/components/NodeInfoPanel.d.ts.map +1 -0
- package/dist/components/NodeInfoPanel.js +217 -0
- package/dist/components/NodeInfoPanel.js.map +1 -0
- package/dist/edges/CustomEdge.d.ts +16 -0
- package/dist/edges/CustomEdge.d.ts.map +1 -0
- package/dist/edges/CustomEdge.js +200 -0
- package/dist/edges/CustomEdge.js.map +1 -0
- package/dist/edges/GenericEdge.d.ts +18 -0
- package/dist/edges/GenericEdge.d.ts.map +1 -0
- package/dist/edges/GenericEdge.js +14 -0
- package/dist/edges/GenericEdge.js.map +1 -0
- package/dist/hooks/usePathBasedEvents.d.ts +42 -0
- package/dist/hooks/usePathBasedEvents.d.ts.map +1 -0
- package/dist/hooks/usePathBasedEvents.js +122 -0
- package/dist/hooks/usePathBasedEvents.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/CustomNode.d.ts +18 -0
- package/dist/nodes/CustomNode.d.ts.map +1 -0
- package/dist/nodes/CustomNode.js +298 -0
- package/dist/nodes/CustomNode.js.map +1 -0
- package/dist/nodes/GenericNode.d.ts +20 -0
- package/dist/nodes/GenericNode.d.ts.map +1 -0
- package/dist/nodes/GenericNode.js +24 -0
- package/dist/nodes/GenericNode.js.map +1 -0
- package/dist/utils/animationMapping.d.ts +53 -0
- package/dist/utils/animationMapping.d.ts.map +1 -0
- package/dist/utils/animationMapping.js +133 -0
- package/dist/utils/animationMapping.js.map +1 -0
- package/dist/utils/graphConverter.d.ts +22 -0
- package/dist/utils/graphConverter.d.ts.map +1 -0
- package/dist/utils/graphConverter.js +176 -0
- package/dist/utils/graphConverter.js.map +1 -0
- package/dist/utils/iconResolver.d.ts +29 -0
- package/dist/utils/iconResolver.d.ts.map +1 -0
- package/dist/utils/iconResolver.js +68 -0
- package/dist/utils/iconResolver.js.map +1 -0
- package/package.json +61 -0
- package/src/components/ConfigurationSelector.tsx +147 -0
- package/src/components/EdgeInfoPanel.tsx +198 -0
- package/src/components/EventLog.test.tsx +85 -0
- package/src/components/EventLog.tsx +51 -0
- package/src/components/GraphRenderer.test.tsx +118 -0
- package/src/components/GraphRenderer.tsx +1222 -0
- package/src/components/MetricsDashboard.tsx +40 -0
- package/src/components/NodeInfoPanel.tsx +425 -0
- package/src/edges/CustomEdge.tsx +344 -0
- package/src/edges/GenericEdge.tsx +40 -0
- package/src/hooks/usePathBasedEvents.ts +182 -0
- package/src/index.ts +67 -0
- package/src/nodes/CustomNode.tsx +432 -0
- package/src/nodes/GenericNode.tsx +54 -0
- package/src/stories/AnimationWorkshop.stories.tsx +608 -0
- package/src/stories/EventDrivenAnimations.stories.tsx +499 -0
- package/src/stories/EventLog.stories.tsx +161 -0
- package/src/stories/GraphRenderer.stories.tsx +628 -0
- package/src/stories/Introduction.mdx +51 -0
- package/src/stories/MetricsDashboard.stories.tsx +227 -0
- package/src/stories/MultiConfig.stories.tsx +531 -0
- package/src/stories/MultiDirectionalConnections.stories.tsx +345 -0
- package/src/stories/NodeShapes.stories.tsx +769 -0
- package/src/utils/animationMapping.ts +170 -0
- package/src/utils/graphConverter.ts +218 -0
- package/src/utils/iconResolver.tsx +49 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToXYFlowNodes = convertToXYFlowNodes;
|
|
4
|
+
exports.convertToXYFlowEdges = convertToXYFlowEdges;
|
|
5
|
+
exports.autoLayoutNodes = autoLayoutNodes;
|
|
6
|
+
const react_1 = require("@xyflow/react");
|
|
7
|
+
/**
|
|
8
|
+
* Convert our NodeState to xyflow Node format
|
|
9
|
+
*/
|
|
10
|
+
function convertToXYFlowNodes(nodes, configuration, violations = []) {
|
|
11
|
+
return nodes.map((node) => {
|
|
12
|
+
const typeDefinition = configuration.nodeTypes[node.type];
|
|
13
|
+
// Warn if node type is not defined in configuration
|
|
14
|
+
if (!typeDefinition) {
|
|
15
|
+
console.warn(`Node type "${node.type}" not found in configuration for node "${node.id}"`);
|
|
16
|
+
}
|
|
17
|
+
const hasViolations = violations.some(v => v.context?.nodeId === node.id);
|
|
18
|
+
return {
|
|
19
|
+
id: node.id,
|
|
20
|
+
type: 'custom',
|
|
21
|
+
position: node.position || { x: 0, y: 0 },
|
|
22
|
+
data: {
|
|
23
|
+
label: node.id,
|
|
24
|
+
typeDefinition,
|
|
25
|
+
state: node.state,
|
|
26
|
+
hasViolations,
|
|
27
|
+
data: node.data,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Convert our EdgeState to xyflow Edge format
|
|
34
|
+
*/
|
|
35
|
+
function convertToXYFlowEdges(edges, configuration, violations = []) {
|
|
36
|
+
return edges.map((edge) => {
|
|
37
|
+
const typeDefinition = configuration.edgeTypes[edge.type];
|
|
38
|
+
// Warn if edge type is not defined in configuration
|
|
39
|
+
if (!typeDefinition) {
|
|
40
|
+
console.warn(`Edge type "${edge.type}" not found in configuration for edge "${edge.id}"`);
|
|
41
|
+
}
|
|
42
|
+
const hasViolations = violations.some(v => v.context?.edgeId === edge.id);
|
|
43
|
+
const edgeWithHandles = edge;
|
|
44
|
+
// Add arrow marker if edge type is directed
|
|
45
|
+
const markerEnd = typeDefinition?.directed !== false ? {
|
|
46
|
+
type: react_1.MarkerType.ArrowClosed,
|
|
47
|
+
color: typeDefinition?.color || '#888',
|
|
48
|
+
width: 20,
|
|
49
|
+
height: 20,
|
|
50
|
+
} : undefined;
|
|
51
|
+
return {
|
|
52
|
+
id: edge.id,
|
|
53
|
+
source: edge.from,
|
|
54
|
+
target: edge.to,
|
|
55
|
+
sourceHandle: edgeWithHandles.sourceHandle,
|
|
56
|
+
targetHandle: edgeWithHandles.targetHandle,
|
|
57
|
+
type: 'custom',
|
|
58
|
+
animated: typeDefinition?.style === 'animated',
|
|
59
|
+
markerEnd,
|
|
60
|
+
data: {
|
|
61
|
+
typeDefinition,
|
|
62
|
+
hasViolations,
|
|
63
|
+
data: edge.data,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Auto-layout nodes if they don't have positions
|
|
70
|
+
*/
|
|
71
|
+
function autoLayoutNodes(nodes, edges, layoutType = 'hierarchical') {
|
|
72
|
+
// Skip if all nodes have positions
|
|
73
|
+
const hasPositions = nodes.every(n => n.position.x !== 0 || n.position.y !== 0);
|
|
74
|
+
if (hasPositions || layoutType === 'manual') {
|
|
75
|
+
return nodes;
|
|
76
|
+
}
|
|
77
|
+
switch (layoutType) {
|
|
78
|
+
case 'hierarchical':
|
|
79
|
+
return applyHierarchicalLayout(nodes, edges);
|
|
80
|
+
case 'circular':
|
|
81
|
+
return applyCircularLayout(nodes);
|
|
82
|
+
case 'force-directed':
|
|
83
|
+
// For now, use hierarchical as fallback
|
|
84
|
+
// TODO: Implement force-directed with elkjs
|
|
85
|
+
return applyHierarchicalLayout(nodes, edges);
|
|
86
|
+
default:
|
|
87
|
+
return nodes;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Simple hierarchical layout algorithm
|
|
92
|
+
*/
|
|
93
|
+
function applyHierarchicalLayout(nodes, edges) {
|
|
94
|
+
// Build adjacency list
|
|
95
|
+
const adjacency = new Map();
|
|
96
|
+
const inDegree = new Map();
|
|
97
|
+
nodes.forEach(node => {
|
|
98
|
+
adjacency.set(node.id, []);
|
|
99
|
+
inDegree.set(node.id, 0);
|
|
100
|
+
});
|
|
101
|
+
edges.forEach(edge => {
|
|
102
|
+
const targets = adjacency.get(edge.source) || [];
|
|
103
|
+
targets.push(edge.target);
|
|
104
|
+
adjacency.set(edge.source, targets);
|
|
105
|
+
inDegree.set(edge.target, (inDegree.get(edge.target) || 0) + 1);
|
|
106
|
+
});
|
|
107
|
+
// Topological sort to determine layers
|
|
108
|
+
const layers = [];
|
|
109
|
+
const queue = [];
|
|
110
|
+
// Start with nodes that have no incoming edges
|
|
111
|
+
inDegree.forEach((degree, nodeId) => {
|
|
112
|
+
if (degree === 0) {
|
|
113
|
+
queue.push(nodeId);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const visited = new Set();
|
|
117
|
+
while (queue.length > 0) {
|
|
118
|
+
const currentLayer = [];
|
|
119
|
+
const layerSize = queue.length;
|
|
120
|
+
for (let i = 0; i < layerSize; i++) {
|
|
121
|
+
const nodeId = queue.shift();
|
|
122
|
+
currentLayer.push(nodeId);
|
|
123
|
+
visited.add(nodeId);
|
|
124
|
+
const neighbors = adjacency.get(nodeId) || [];
|
|
125
|
+
neighbors.forEach(neighbor => {
|
|
126
|
+
const degree = inDegree.get(neighbor) - 1;
|
|
127
|
+
inDegree.set(neighbor, degree);
|
|
128
|
+
if (degree === 0 && !visited.has(neighbor)) {
|
|
129
|
+
queue.push(neighbor);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (currentLayer.length > 0) {
|
|
134
|
+
layers.push(currentLayer);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Handle any remaining nodes (cycles or disconnected)
|
|
138
|
+
const remainingNodes = nodes.filter(n => !visited.has(n.id)).map(n => n.id);
|
|
139
|
+
if (remainingNodes.length > 0) {
|
|
140
|
+
layers.push(remainingNodes);
|
|
141
|
+
}
|
|
142
|
+
// Position nodes based on layers
|
|
143
|
+
const LAYER_HEIGHT = 150;
|
|
144
|
+
const NODE_WIDTH = 200;
|
|
145
|
+
return nodes.map(node => {
|
|
146
|
+
const layerIndex = layers.findIndex(layer => layer.includes(node.id));
|
|
147
|
+
const layer = layers[layerIndex] || [];
|
|
148
|
+
const positionInLayer = layer.indexOf(node.id);
|
|
149
|
+
const layerWidth = layer.length * NODE_WIDTH;
|
|
150
|
+
return {
|
|
151
|
+
...node,
|
|
152
|
+
position: {
|
|
153
|
+
x: (positionInLayer * NODE_WIDTH) + (NODE_WIDTH / 2) - (layerWidth / 2),
|
|
154
|
+
y: layerIndex * LAYER_HEIGHT,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Simple circular layout algorithm
|
|
161
|
+
*/
|
|
162
|
+
function applyCircularLayout(nodes) {
|
|
163
|
+
const radius = Math.max(200, nodes.length * 30);
|
|
164
|
+
const angleStep = (2 * Math.PI) / nodes.length;
|
|
165
|
+
return nodes.map((node, index) => {
|
|
166
|
+
const angle = index * angleStep;
|
|
167
|
+
return {
|
|
168
|
+
...node,
|
|
169
|
+
position: {
|
|
170
|
+
x: radius * Math.cos(angle) + radius,
|
|
171
|
+
y: radius * Math.sin(angle) + radius,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=graphConverter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphConverter.js","sourceRoot":"","sources":["../../src/utils/graphConverter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Icon Resolver
|
|
4
|
+
*
|
|
5
|
+
* Resolves icon strings to React components. Supports:
|
|
6
|
+
* 1. Lucide icon names (e.g., "Database", "Settings", "Package")
|
|
7
|
+
* 2. Emoji/Unicode strings (e.g., "⚙️", "💾", "📦")
|
|
8
|
+
*
|
|
9
|
+
* This keeps configurations JSON-serializable while supporting icon libraries.
|
|
10
|
+
*/
|
|
11
|
+
export interface IconProps {
|
|
12
|
+
icon?: string;
|
|
13
|
+
size?: number;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolves an icon string to a React element
|
|
18
|
+
*
|
|
19
|
+
* @param icon - Icon name (Lucide) or emoji/text string
|
|
20
|
+
* @param size - Icon size in pixels (default: 20)
|
|
21
|
+
* @param className - Optional CSS class
|
|
22
|
+
* @returns React element or null
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveIcon(icon?: string, size?: number, className?: string): React.ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Icon component that resolves icon strings
|
|
27
|
+
*/
|
|
28
|
+
export declare const Icon: React.FC<IconProps>;
|
|
29
|
+
//# sourceMappingURL=iconResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iconResolver.d.ts","sourceRoot":"","sources":["../../src/utils/iconResolver.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;;;;;GAQG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,MAAW,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAcjG;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAEpC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Icon = void 0;
|
|
37
|
+
exports.resolveIcon = resolveIcon;
|
|
38
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
39
|
+
const LucideIcons = __importStar(require("lucide-react"));
|
|
40
|
+
/**
|
|
41
|
+
* Resolves an icon string to a React element
|
|
42
|
+
*
|
|
43
|
+
* @param icon - Icon name (Lucide) or emoji/text string
|
|
44
|
+
* @param size - Icon size in pixels (default: 20)
|
|
45
|
+
* @param className - Optional CSS class
|
|
46
|
+
* @returns React element or null
|
|
47
|
+
*/
|
|
48
|
+
function resolveIcon(icon, size = 20, className) {
|
|
49
|
+
if (!icon)
|
|
50
|
+
return null;
|
|
51
|
+
// Try to resolve as Lucide icon first
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
const LucideIcon = LucideIcons[icon];
|
|
54
|
+
// Check if it's a valid React component (function or object with $$typeof)
|
|
55
|
+
if (LucideIcon && (typeof LucideIcon === 'function' || typeof LucideIcon === 'object')) {
|
|
56
|
+
return (0, jsx_runtime_1.jsx)(LucideIcon, { size: size, className: className });
|
|
57
|
+
}
|
|
58
|
+
// Fall back to rendering as text (emoji or unicode)
|
|
59
|
+
return (0, jsx_runtime_1.jsx)("span", { className: className, style: { fontSize: `${size}px` }, children: icon });
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Icon component that resolves icon strings
|
|
63
|
+
*/
|
|
64
|
+
const Icon = ({ icon, size = 20, className }) => {
|
|
65
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: resolveIcon(icon, size, className) });
|
|
66
|
+
};
|
|
67
|
+
exports.Icon = Icon;
|
|
68
|
+
//# sourceMappingURL=iconResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iconResolver.js","sourceRoot":"","sources":["../../src/utils/iconResolver.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,kCAcC;;AAxCD,0DAA4C;AAkB5C;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,IAAa,EAAE,OAAe,EAAE,EAAE,SAAkB;IAC9E,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,sCAAsC;IACtC,8DAA8D;IAC9D,MAAM,UAAU,GAAI,WAAmB,CAAC,IAAI,CAAC,CAAC;IAE9C,2EAA2E;IAC3E,IAAI,UAAU,IAAI,CAAC,OAAO,UAAU,KAAK,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,CAAC,EAAE,CAAC;QACvF,OAAO,uBAAC,UAAU,IAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,GAAI,CAAC;IAC1D,CAAC;IAED,oDAAoD;IACpD,OAAO,iCAAM,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,IAAI,IAAI,EAAE,YAAG,IAAI,GAAQ,CAAC;AACrF,CAAC;AAED;;GAEG;AACI,MAAM,IAAI,GAAwB,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;IAC1E,OAAO,2DAAG,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,GAAI,CAAC;AACnD,CAAC,CAAC;AAFW,QAAA,IAAI,QAEf"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@principal-ai/principal-view-react",
|
|
3
|
+
"version": "0.6.6",
|
|
4
|
+
"description": "React components for graph-based principal view framework",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "tsc --watch",
|
|
10
|
+
"clean": "rm -rf dist",
|
|
11
|
+
"test": "bun test",
|
|
12
|
+
"test:watch": "bun test --watch",
|
|
13
|
+
"storybook": "storybook dev -p 6006",
|
|
14
|
+
"build-storybook": "storybook build"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@principal-ai/principal-view-core": "^0.5.6",
|
|
18
|
+
"@xyflow/react": "^12.0.0",
|
|
19
|
+
"elkjs": "^0.9.0",
|
|
20
|
+
"framer-motion": "^11.0.0",
|
|
21
|
+
"lucide-react": "^0.554.0",
|
|
22
|
+
"zustand": "^4.5.0"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
26
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@storybook/addon-essentials": "^8.5.0",
|
|
30
|
+
"@storybook/addon-interactions": "^8.5.0",
|
|
31
|
+
"@storybook/addon-links": "^8.5.0",
|
|
32
|
+
"@storybook/blocks": "^8.5.0",
|
|
33
|
+
"@storybook/react": "^8.5.0",
|
|
34
|
+
"@storybook/react-vite": "^8.5.0",
|
|
35
|
+
"@storybook/test": "^8.5.0",
|
|
36
|
+
"@testing-library/react": "^14.0.0",
|
|
37
|
+
"@types/react": "^18.0.0",
|
|
38
|
+
"happy-dom": "^12.10.3",
|
|
39
|
+
"react": "^19.0.0",
|
|
40
|
+
"react-dom": "^19.0.0",
|
|
41
|
+
"storybook": "^8.5.0",
|
|
42
|
+
"typescript": "^5.0.0",
|
|
43
|
+
"vite": "^5.0.0"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"src"
|
|
48
|
+
],
|
|
49
|
+
"keywords": [
|
|
50
|
+
"validation",
|
|
51
|
+
"graph",
|
|
52
|
+
"visualization",
|
|
53
|
+
"react",
|
|
54
|
+
"testing"
|
|
55
|
+
],
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public",
|
|
59
|
+
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ConfigurationFile } from '@principal-ai/principal-view-core';
|
|
3
|
+
|
|
4
|
+
export interface ConfigurationSelectorProps {
|
|
5
|
+
/** Available configurations */
|
|
6
|
+
configurations: ConfigurationFile[];
|
|
7
|
+
|
|
8
|
+
/** Currently selected configuration name */
|
|
9
|
+
selectedConfig: string;
|
|
10
|
+
|
|
11
|
+
/** Callback when configuration changes */
|
|
12
|
+
onConfigChange: (configName: string) => void;
|
|
13
|
+
|
|
14
|
+
/** Optional custom className */
|
|
15
|
+
className?: string;
|
|
16
|
+
|
|
17
|
+
/** Optional custom styles */
|
|
18
|
+
style?: React.CSSProperties;
|
|
19
|
+
|
|
20
|
+
/** Whether to show description */
|
|
21
|
+
showDescription?: boolean;
|
|
22
|
+
|
|
23
|
+
/** Whether to show version */
|
|
24
|
+
showVersion?: boolean;
|
|
25
|
+
|
|
26
|
+
/** Label text for the selector */
|
|
27
|
+
label?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Configuration selector component for switching between multiple graph configurations
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const [selectedConfig, setSelectedConfig] = useState('simple-service');
|
|
36
|
+
*
|
|
37
|
+
* <ConfigurationSelector
|
|
38
|
+
* configurations={loadedConfigs}
|
|
39
|
+
* selectedConfig={selectedConfig}
|
|
40
|
+
* onConfigChange={setSelectedConfig}
|
|
41
|
+
* showDescription
|
|
42
|
+
* />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export const ConfigurationSelector: React.FC<ConfigurationSelectorProps> = ({
|
|
46
|
+
configurations,
|
|
47
|
+
selectedConfig,
|
|
48
|
+
onConfigChange,
|
|
49
|
+
className,
|
|
50
|
+
style,
|
|
51
|
+
showDescription = false,
|
|
52
|
+
showVersion = false,
|
|
53
|
+
label = 'Graph Configuration',
|
|
54
|
+
}) => {
|
|
55
|
+
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
|
56
|
+
onConfigChange(event.target.value);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const selectedConfigData = configurations.find(c => c.name === selectedConfig);
|
|
60
|
+
|
|
61
|
+
const defaultStyle: React.CSSProperties = {
|
|
62
|
+
backgroundColor: 'white',
|
|
63
|
+
padding: '12px 16px',
|
|
64
|
+
borderRadius: '8px',
|
|
65
|
+
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
|
66
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
67
|
+
...style,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const labelStyle: React.CSSProperties = {
|
|
71
|
+
display: 'block',
|
|
72
|
+
fontSize: '14px',
|
|
73
|
+
fontWeight: 600,
|
|
74
|
+
marginBottom: '8px',
|
|
75
|
+
color: '#333',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const selectStyle: React.CSSProperties = {
|
|
79
|
+
width: '100%',
|
|
80
|
+
padding: '8px 12px',
|
|
81
|
+
fontSize: '14px',
|
|
82
|
+
border: '1px solid #ddd',
|
|
83
|
+
borderRadius: '4px',
|
|
84
|
+
backgroundColor: 'white',
|
|
85
|
+
cursor: 'pointer',
|
|
86
|
+
outline: 'none',
|
|
87
|
+
transition: 'border-color 0.2s',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const infoStyle: React.CSSProperties = {
|
|
91
|
+
marginTop: '8px',
|
|
92
|
+
fontSize: '12px',
|
|
93
|
+
color: '#666',
|
|
94
|
+
lineHeight: '1.5',
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (configurations.length === 0) {
|
|
98
|
+
return (
|
|
99
|
+
<div className={className} style={defaultStyle}>
|
|
100
|
+
<div style={{ ...labelStyle, color: '#999' }}>
|
|
101
|
+
No configurations available
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div className={className} style={defaultStyle}>
|
|
109
|
+
<label style={labelStyle} htmlFor="config-selector">
|
|
110
|
+
{label}
|
|
111
|
+
</label>
|
|
112
|
+
|
|
113
|
+
<select
|
|
114
|
+
id="config-selector"
|
|
115
|
+
value={selectedConfig}
|
|
116
|
+
onChange={handleChange}
|
|
117
|
+
style={selectStyle}
|
|
118
|
+
onMouseEnter={(e) => {
|
|
119
|
+
e.currentTarget.style.borderColor = '#4A90E2';
|
|
120
|
+
}}
|
|
121
|
+
onMouseLeave={(e) => {
|
|
122
|
+
e.currentTarget.style.borderColor = '#ddd';
|
|
123
|
+
}}
|
|
124
|
+
>
|
|
125
|
+
{configurations.map((config) => (
|
|
126
|
+
<option key={config.name} value={config.name}>
|
|
127
|
+
{config.config.metadata.name}
|
|
128
|
+
{showVersion && config.config.metadata.version && ` (v${config.config.metadata.version})`}
|
|
129
|
+
</option>
|
|
130
|
+
))}
|
|
131
|
+
</select>
|
|
132
|
+
|
|
133
|
+
{selectedConfigData && (showDescription || showVersion) && (
|
|
134
|
+
<div style={infoStyle}>
|
|
135
|
+
{showVersion && selectedConfigData.config.metadata.version && (
|
|
136
|
+
<div style={{ marginBottom: '4px' }}>
|
|
137
|
+
<strong>Version:</strong> {selectedConfigData.config.metadata.version}
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
140
|
+
{showDescription && selectedConfigData.config.metadata.description && (
|
|
141
|
+
<div>{selectedConfigData.config.metadata.description}</div>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
};
|