@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.
Files changed (96) hide show
  1. package/README.md +111 -0
  2. package/dist/components/ConfigurationSelector.d.ts +37 -0
  3. package/dist/components/ConfigurationSelector.d.ts.map +1 -0
  4. package/dist/components/ConfigurationSelector.js +67 -0
  5. package/dist/components/ConfigurationSelector.js.map +1 -0
  6. package/dist/components/EdgeInfoPanel.d.ts +16 -0
  7. package/dist/components/EdgeInfoPanel.d.ts.map +1 -0
  8. package/dist/components/EdgeInfoPanel.js +85 -0
  9. package/dist/components/EdgeInfoPanel.js.map +1 -0
  10. package/dist/components/EventLog.d.ts +20 -0
  11. package/dist/components/EventLog.d.ts.map +1 -0
  12. package/dist/components/EventLog.js +13 -0
  13. package/dist/components/EventLog.js.map +1 -0
  14. package/dist/components/EventLog.test.d.ts +2 -0
  15. package/dist/components/EventLog.test.d.ts.map +1 -0
  16. package/dist/components/EventLog.test.js +73 -0
  17. package/dist/components/EventLog.test.js.map +1 -0
  18. package/dist/components/GraphRenderer.d.ts +121 -0
  19. package/dist/components/GraphRenderer.d.ts.map +1 -0
  20. package/dist/components/GraphRenderer.js +809 -0
  21. package/dist/components/GraphRenderer.js.map +1 -0
  22. package/dist/components/GraphRenderer.test.d.ts +2 -0
  23. package/dist/components/GraphRenderer.test.d.ts.map +1 -0
  24. package/dist/components/GraphRenderer.test.js +88 -0
  25. package/dist/components/GraphRenderer.test.js.map +1 -0
  26. package/dist/components/MetricsDashboard.d.ts +14 -0
  27. package/dist/components/MetricsDashboard.d.ts.map +1 -0
  28. package/dist/components/MetricsDashboard.js +13 -0
  29. package/dist/components/MetricsDashboard.js.map +1 -0
  30. package/dist/components/NodeInfoPanel.d.ts +21 -0
  31. package/dist/components/NodeInfoPanel.d.ts.map +1 -0
  32. package/dist/components/NodeInfoPanel.js +217 -0
  33. package/dist/components/NodeInfoPanel.js.map +1 -0
  34. package/dist/edges/CustomEdge.d.ts +16 -0
  35. package/dist/edges/CustomEdge.d.ts.map +1 -0
  36. package/dist/edges/CustomEdge.js +200 -0
  37. package/dist/edges/CustomEdge.js.map +1 -0
  38. package/dist/edges/GenericEdge.d.ts +18 -0
  39. package/dist/edges/GenericEdge.d.ts.map +1 -0
  40. package/dist/edges/GenericEdge.js +14 -0
  41. package/dist/edges/GenericEdge.js.map +1 -0
  42. package/dist/hooks/usePathBasedEvents.d.ts +42 -0
  43. package/dist/hooks/usePathBasedEvents.d.ts.map +1 -0
  44. package/dist/hooks/usePathBasedEvents.js +122 -0
  45. package/dist/hooks/usePathBasedEvents.js.map +1 -0
  46. package/dist/index.d.ts +33 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +41 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/nodes/CustomNode.d.ts +18 -0
  51. package/dist/nodes/CustomNode.d.ts.map +1 -0
  52. package/dist/nodes/CustomNode.js +298 -0
  53. package/dist/nodes/CustomNode.js.map +1 -0
  54. package/dist/nodes/GenericNode.d.ts +20 -0
  55. package/dist/nodes/GenericNode.d.ts.map +1 -0
  56. package/dist/nodes/GenericNode.js +24 -0
  57. package/dist/nodes/GenericNode.js.map +1 -0
  58. package/dist/utils/animationMapping.d.ts +53 -0
  59. package/dist/utils/animationMapping.d.ts.map +1 -0
  60. package/dist/utils/animationMapping.js +133 -0
  61. package/dist/utils/animationMapping.js.map +1 -0
  62. package/dist/utils/graphConverter.d.ts +22 -0
  63. package/dist/utils/graphConverter.d.ts.map +1 -0
  64. package/dist/utils/graphConverter.js +176 -0
  65. package/dist/utils/graphConverter.js.map +1 -0
  66. package/dist/utils/iconResolver.d.ts +29 -0
  67. package/dist/utils/iconResolver.d.ts.map +1 -0
  68. package/dist/utils/iconResolver.js +68 -0
  69. package/dist/utils/iconResolver.js.map +1 -0
  70. package/package.json +61 -0
  71. package/src/components/ConfigurationSelector.tsx +147 -0
  72. package/src/components/EdgeInfoPanel.tsx +198 -0
  73. package/src/components/EventLog.test.tsx +85 -0
  74. package/src/components/EventLog.tsx +51 -0
  75. package/src/components/GraphRenderer.test.tsx +118 -0
  76. package/src/components/GraphRenderer.tsx +1222 -0
  77. package/src/components/MetricsDashboard.tsx +40 -0
  78. package/src/components/NodeInfoPanel.tsx +425 -0
  79. package/src/edges/CustomEdge.tsx +344 -0
  80. package/src/edges/GenericEdge.tsx +40 -0
  81. package/src/hooks/usePathBasedEvents.ts +182 -0
  82. package/src/index.ts +67 -0
  83. package/src/nodes/CustomNode.tsx +432 -0
  84. package/src/nodes/GenericNode.tsx +54 -0
  85. package/src/stories/AnimationWorkshop.stories.tsx +608 -0
  86. package/src/stories/EventDrivenAnimations.stories.tsx +499 -0
  87. package/src/stories/EventLog.stories.tsx +161 -0
  88. package/src/stories/GraphRenderer.stories.tsx +628 -0
  89. package/src/stories/Introduction.mdx +51 -0
  90. package/src/stories/MetricsDashboard.stories.tsx +227 -0
  91. package/src/stories/MultiConfig.stories.tsx +531 -0
  92. package/src/stories/MultiDirectionalConnections.stories.tsx +345 -0
  93. package/src/stories/NodeShapes.stories.tsx +769 -0
  94. package/src/utils/animationMapping.ts +170 -0
  95. package/src/utils/graphConverter.ts +218 -0
  96. 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
+ };