@principal-ai/principal-view-react 0.7.15 → 0.7.16
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 +9 -24
- package/dist/components/ConfigurationSelector.d.ts +1 -1
- package/dist/components/ConfigurationSelector.d.ts.map +1 -1
- package/dist/components/ConfigurationSelector.js +6 -10
- package/dist/components/ConfigurationSelector.js.map +1 -1
- package/dist/components/EdgeInfoPanel.d.ts +1 -1
- package/dist/components/EdgeInfoPanel.d.ts.map +1 -1
- package/dist/components/EdgeInfoPanel.js +14 -18
- package/dist/components/EdgeInfoPanel.js.map +1 -1
- package/dist/components/GraphRenderer.d.ts +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +89 -92
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/NarrativeRenderer.d.ts +19 -0
- package/dist/components/NarrativeRenderer.d.ts.map +1 -0
- package/dist/components/NarrativeRenderer.js +103 -0
- package/dist/components/NarrativeRenderer.js.map +1 -0
- package/dist/components/NodeInfoPanel.d.ts +1 -1
- package/dist/components/NodeInfoPanel.d.ts.map +1 -1
- package/dist/components/NodeInfoPanel.js +33 -37
- package/dist/components/NodeInfoPanel.js.map +1 -1
- package/dist/components/NodeTooltip.js +15 -19
- package/dist/components/NodeTooltip.js.map +1 -1
- package/dist/components/SelectionSidebar.d.ts +1 -1
- package/dist/components/SelectionSidebar.d.ts.map +1 -1
- package/dist/components/SelectionSidebar.js +26 -30
- package/dist/components/SelectionSidebar.js.map +1 -1
- package/dist/components/TestEventPanel.d.ts +6 -0
- package/dist/components/TestEventPanel.d.ts.map +1 -1
- package/dist/components/TestEventPanel.js +157 -161
- package/dist/components/TestEventPanel.js.map +1 -1
- package/dist/edges/CustomEdge.d.ts +1 -1
- package/dist/edges/CustomEdge.d.ts.map +1 -1
- package/dist/edges/CustomEdge.js +18 -22
- package/dist/edges/CustomEdge.js.map +1 -1
- package/dist/edges/GenericEdge.d.ts +1 -1
- package/dist/edges/GenericEdge.d.ts.map +1 -1
- package/dist/edges/GenericEdge.js +3 -7
- package/dist/edges/GenericEdge.js.map +1 -1
- package/dist/hooks/usePathBasedEvents.d.ts +1 -1
- package/dist/hooks/usePathBasedEvents.d.ts.map +1 -1
- package/dist/hooks/usePathBasedEvents.js +14 -18
- package/dist/hooks/usePathBasedEvents.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -33
- package/dist/index.js.map +1 -1
- package/dist/nodes/CustomNode.d.ts +1 -1
- package/dist/nodes/CustomNode.d.ts.map +1 -1
- package/dist/nodes/CustomNode.js +22 -26
- package/dist/nodes/CustomNode.js.map +1 -1
- package/dist/nodes/GenericNode.d.ts +1 -1
- package/dist/nodes/GenericNode.d.ts.map +1 -1
- package/dist/nodes/GenericNode.js +4 -8
- package/dist/nodes/GenericNode.js.map +1 -1
- package/dist/utils/animationMapping.d.ts +1 -1
- package/dist/utils/animationMapping.d.ts.map +1 -1
- package/dist/utils/animationMapping.js +6 -13
- package/dist/utils/animationMapping.js.map +1 -1
- package/dist/utils/graphConverter.d.ts +1 -1
- package/dist/utils/graphConverter.d.ts.map +1 -1
- package/dist/utils/graphConverter.js +4 -8
- package/dist/utils/graphConverter.js.map +1 -1
- package/dist/utils/iconResolver.js +7 -45
- package/dist/utils/iconResolver.js.map +1 -1
- package/dist/utils/narrative-converter.d.ts +45 -0
- package/dist/utils/narrative-converter.d.ts.map +1 -0
- package/dist/utils/narrative-converter.js +113 -0
- package/dist/utils/narrative-converter.js.map +1 -0
- package/dist/utils/narrative-loader.d.ts +53 -0
- package/dist/utils/narrative-loader.d.ts.map +1 -0
- package/dist/utils/narrative-loader.js +163 -0
- package/dist/utils/narrative-loader.js.map +1 -0
- package/package.json +22 -25
- package/src/components/ConfigurationSelector.tsx +1 -1
- package/src/components/EdgeInfoPanel.tsx +1 -1
- package/src/components/GraphRenderer.test.tsx +1 -1
- package/src/components/GraphRenderer.tsx +2 -2
- package/src/components/NarrativeRenderer.tsx +171 -0
- package/src/components/NodeInfoPanel.tsx +1 -1
- package/src/components/NodeTooltip.tsx +3 -3
- package/src/components/PendingChanges.test.tsx +1 -1
- package/src/components/SelectionSidebar.tsx +1 -1
- package/src/components/TestEventPanel.tsx +140 -117
- package/src/edges/CustomEdge.tsx +1 -1
- package/src/edges/GenericEdge.tsx +1 -1
- package/src/hooks/usePathBasedEvents.ts +1 -1
- package/src/index.ts +1 -7
- package/src/nodes/CustomNode.tsx +1 -1
- package/src/nodes/GenericNode.tsx +1 -1
- package/src/stories/AnimationWorkshop.stories.tsx +1 -1
- package/src/stories/CanvasEdgeTypes.stories.tsx +1 -1
- package/src/stories/CanvasNodeTypes.stories.tsx +1 -1
- package/src/stories/ColorPriority.stories.tsx +1 -1
- package/src/stories/EventDrivenAnimations.stories.tsx +1 -1
- package/src/stories/GraphRenderer.stories.tsx +1 -1
- package/src/stories/Introduction.mdx +4 -21
- package/src/stories/MultiConfig.stories.tsx +1 -1
- package/src/stories/MultiDirectionalConnections.stories.tsx +1 -1
- package/src/stories/NodeFieldsAudit.stories.tsx +1 -1
- package/src/stories/NodeShapes.stories.tsx +1 -1
- package/src/stories/OtelComponents.stories.tsx +1 -1
- package/src/stories/RealTestExecution.stories.tsx +111 -1
- package/src/stories/TraceViewer.stories.tsx +1 -1
- package/src/stories/ValidatedExecution.stories.tsx +1 -1
- package/src/stories/data/graph-converter-test-execution.json +204 -326
- package/src/stories/data/graph-converter-test.narrative.json +106 -0
- package/src/stories/data/graph-converter-validated-execution.json +6 -6
- package/src/utils/animationMapping.ts +1 -1
- package/src/utils/graphConverter.ts +1 -1
- package/src/utils/narrative-converter.ts +147 -0
- package/src/utils/narrative-loader.ts +172 -0
- package/dist/components/EventLog.d.ts +0 -20
- package/dist/components/EventLog.d.ts.map +0 -1
- package/dist/components/EventLog.js +0 -13
- package/dist/components/EventLog.js.map +0 -1
- package/dist/components/EventLog.test.d.ts +0 -2
- package/dist/components/EventLog.test.d.ts.map +0 -1
- package/dist/components/EventLog.test.js +0 -73
- package/dist/components/EventLog.test.js.map +0 -1
- package/dist/components/GraphRenderer.test.d.ts +0 -2
- package/dist/components/GraphRenderer.test.d.ts.map +0 -1
- package/dist/components/GraphRenderer.test.js +0 -88
- package/dist/components/GraphRenderer.test.js.map +0 -1
- package/dist/components/LayerPanel.d.ts +0 -31
- package/dist/components/LayerPanel.d.ts.map +0 -1
- package/dist/components/LayerPanel.js +0 -207
- package/dist/components/LayerPanel.js.map +0 -1
- package/dist/components/MetricsDashboard.d.ts +0 -14
- package/dist/components/MetricsDashboard.d.ts.map +0 -1
- package/dist/components/MetricsDashboard.js +0 -13
- package/dist/components/MetricsDashboard.js.map +0 -1
- package/src/components/EventLog.test.tsx +0 -85
- package/src/components/EventLog.tsx +0 -51
- package/src/components/MetricsDashboard.tsx +0 -40
- package/src/stories/EventLog.stories.tsx +0 -161
- package/src/stories/IndustryThemes.stories.tsx +0 -483
- package/src/stories/MetricsDashboard.stories.tsx +0 -227
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{
|
|
3
3
|
"id": "span-1",
|
|
4
4
|
"name": "graph conversion with validation",
|
|
5
|
-
"startTime":
|
|
5
|
+
"startTime": 1768578318244,
|
|
6
6
|
"attributes": {
|
|
7
7
|
"span.kind": "test.case",
|
|
8
8
|
"test.name": "graph conversion with validation",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"events": [
|
|
14
14
|
{
|
|
15
|
-
"time":
|
|
15
|
+
"time": 1768578318244,
|
|
16
16
|
"name": "conversion.started",
|
|
17
17
|
"attributes": {
|
|
18
18
|
"code.filepath": "GraphConverter.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
"time":
|
|
25
|
+
"time": 1768578318244,
|
|
26
26
|
"name": "conversion.processingNodes",
|
|
27
27
|
"attributes": {
|
|
28
28
|
"code.filepath": "GraphConverter.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"time":
|
|
34
|
+
"time": 1768578318244,
|
|
35
35
|
"name": "conversion.processingEdges",
|
|
36
36
|
"attributes": {
|
|
37
37
|
"code.filepath": "GraphConverter.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
"time":
|
|
43
|
+
"time": 1768578318244,
|
|
44
44
|
"name": "conversion.complete",
|
|
45
45
|
"attributes": {
|
|
46
46
|
"code.filepath": "GraphConverter.ts",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
],
|
|
54
54
|
"status": "OK",
|
|
55
|
-
"endTime":
|
|
55
|
+
"endTime": 1768578318244,
|
|
56
56
|
"duration": 0
|
|
57
57
|
}
|
|
58
58
|
]
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
EdgeState,
|
|
5
5
|
GraphConfiguration,
|
|
6
6
|
Violation,
|
|
7
|
-
} from '@principal-ai/principal-view-core';
|
|
7
|
+
} from '@principal-ai/principal-view-core/browser';
|
|
8
8
|
import type { CustomNodeData } from '../nodes/CustomNode';
|
|
9
9
|
import type { CustomEdgeData } from '../edges/CustomEdge';
|
|
10
10
|
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for converting TestEventPanel data to OtelEvent format
|
|
3
|
+
* for use with the narrative renderer
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { OtelEvent } from '@principal-ai/principal-view-core';
|
|
7
|
+
import type { OtelLog, OtelSeverity } from '../components/TestEventPanel';
|
|
8
|
+
|
|
9
|
+
// TestEventPanel types (matching TestEventPanel.tsx)
|
|
10
|
+
interface SpanEvent {
|
|
11
|
+
time: number;
|
|
12
|
+
name: string;
|
|
13
|
+
attributes: Record<string, string | number | boolean>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TestSpan {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
startTime: number;
|
|
20
|
+
endTime?: number;
|
|
21
|
+
duration?: number;
|
|
22
|
+
attributes: Record<string, string | number | boolean>;
|
|
23
|
+
events: SpanEvent[];
|
|
24
|
+
status: 'OK' | 'ERROR';
|
|
25
|
+
errorMessage?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Convert OtelSeverity to severity number (OpenTelemetry spec)
|
|
30
|
+
*/
|
|
31
|
+
function severityToNumber(severity: OtelSeverity): number {
|
|
32
|
+
const severityMap: Record<OtelSeverity, number> = {
|
|
33
|
+
TRACE: 1,
|
|
34
|
+
DEBUG: 5,
|
|
35
|
+
INFO: 9,
|
|
36
|
+
WARN: 13,
|
|
37
|
+
ERROR: 17,
|
|
38
|
+
FATAL: 21,
|
|
39
|
+
};
|
|
40
|
+
return severityMap[severity] || 9;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Convert TestSpan events to OtelEvent spans
|
|
45
|
+
*/
|
|
46
|
+
function convertSpanEvents(span: TestSpan): OtelEvent[] {
|
|
47
|
+
return span.events.map((event) => ({
|
|
48
|
+
name: event.name,
|
|
49
|
+
timestamp: event.time,
|
|
50
|
+
type: 'span' as const,
|
|
51
|
+
spanId: span.id,
|
|
52
|
+
traceId: span.id, // Use span ID as trace ID for single-span tests
|
|
53
|
+
attributes: event.attributes,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert OtelLogs to OtelEvent logs
|
|
59
|
+
*/
|
|
60
|
+
function convertLogs(logs: OtelLog[]): OtelEvent[] {
|
|
61
|
+
return logs.map((log) => ({
|
|
62
|
+
name: 'log',
|
|
63
|
+
timestamp: typeof log.timestamp === 'number' ? log.timestamp : new Date(log.timestamp).getTime(),
|
|
64
|
+
type: 'log' as const,
|
|
65
|
+
spanId: log.spanId,
|
|
66
|
+
traceId: log.traceId,
|
|
67
|
+
severityText: log.severity,
|
|
68
|
+
severityNumber: severityToNumber(log.severity),
|
|
69
|
+
body: typeof log.body === 'string' ? log.body : JSON.stringify(log.body),
|
|
70
|
+
attributes: {
|
|
71
|
+
...log.attributes,
|
|
72
|
+
...log.resource,
|
|
73
|
+
},
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Convert TestSpan and OtelLogs to OtelEvent array
|
|
79
|
+
*
|
|
80
|
+
* @param span - The test span to convert
|
|
81
|
+
* @param logs - Optional OTEL logs to include
|
|
82
|
+
* @returns Array of OtelEvents in chronological order
|
|
83
|
+
*/
|
|
84
|
+
export function convertToOtelEvents(span: TestSpan, logs: OtelLog[] = []): OtelEvent[] {
|
|
85
|
+
const spanEvents = convertSpanEvents(span);
|
|
86
|
+
|
|
87
|
+
// Filter logs for this specific span
|
|
88
|
+
const spanLogs = logs.filter((log) => log.spanId === span.id || log.traceId === span.id);
|
|
89
|
+
const logEvents = convertLogs(spanLogs);
|
|
90
|
+
|
|
91
|
+
// Combine and sort by timestamp
|
|
92
|
+
const allEvents = [...spanEvents, ...logEvents].sort((a, b) => {
|
|
93
|
+
const aTime = typeof a.timestamp === 'number' ? a.timestamp : new Date(a.timestamp).getTime();
|
|
94
|
+
const bTime = typeof b.timestamp === 'number' ? b.timestamp : new Date(b.timestamp).getTime();
|
|
95
|
+
return aTime - bTime;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return allEvents;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Convert all TestSpans to OtelEvents
|
|
103
|
+
*
|
|
104
|
+
* @param spans - Array of test spans
|
|
105
|
+
* @param logs - Optional OTEL logs to include
|
|
106
|
+
* @returns Array of OtelEvents for all spans
|
|
107
|
+
*/
|
|
108
|
+
export function convertAllSpansToOtelEvents(spans: TestSpan[], logs: OtelLog[] = []): OtelEvent[] {
|
|
109
|
+
const allEvents: OtelEvent[] = [];
|
|
110
|
+
|
|
111
|
+
for (const span of spans) {
|
|
112
|
+
const spanEvents = convertToOtelEvents(span, logs);
|
|
113
|
+
allEvents.push(...spanEvents);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Sort all events chronologically
|
|
117
|
+
return allEvents.sort((a, b) => {
|
|
118
|
+
const aTime = typeof a.timestamp === 'number' ? a.timestamp : new Date(a.timestamp).getTime();
|
|
119
|
+
const bTime = typeof b.timestamp === 'number' ? b.timestamp : new Date(b.timestamp).getTime();
|
|
120
|
+
return aTime - bTime;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Extract test result attributes from TestSpan
|
|
126
|
+
* Useful for narrative templates that check assertions
|
|
127
|
+
*/
|
|
128
|
+
export function extractTestAttributes(span: TestSpan): Record<string, unknown> {
|
|
129
|
+
// Find assertion.complete event
|
|
130
|
+
const assertionComplete = span.events.find((e) => e.name === 'assertion.complete');
|
|
131
|
+
|
|
132
|
+
if (assertionComplete) {
|
|
133
|
+
return {
|
|
134
|
+
'assertions.passed': assertionComplete.attributes['assertions.passed'] || 0,
|
|
135
|
+
'assertions.failed': assertionComplete.attributes['assertions.failed'] || 0,
|
|
136
|
+
'test.status': span.status,
|
|
137
|
+
'test.name': span.name,
|
|
138
|
+
...span.attributes,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
'test.status': span.status,
|
|
144
|
+
'test.name': span.name,
|
|
145
|
+
...span.attributes,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for loading and managing narrative templates
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { NarrativeTemplate } from '@principal-ai/principal-view-core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Load a narrative template from a URL or file path
|
|
9
|
+
*
|
|
10
|
+
* Note: In most cases, you should import templates directly:
|
|
11
|
+
* import template from './my-template.narrative.json';
|
|
12
|
+
*
|
|
13
|
+
* This function is useful when you need to dynamically load templates.
|
|
14
|
+
*
|
|
15
|
+
* @param path - Path to the narrative template JSON file
|
|
16
|
+
* @returns Promise resolving to the narrative template, or null if not found
|
|
17
|
+
*/
|
|
18
|
+
export async function loadNarrativeTemplate(path: string): Promise<NarrativeTemplate | null> {
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(path);
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
console.warn(`Narrative template not found: ${path}`);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const template = await response.json();
|
|
26
|
+
return template as NarrativeTemplate;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.warn(`Failed to load narrative template from ${path}:`, error);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Auto-discover narrative template for a given canvas path
|
|
35
|
+
*
|
|
36
|
+
* Example:
|
|
37
|
+
* Canvas: "/path/to/graph-converter.otel.canvas"
|
|
38
|
+
* Narrative: "/path/to/graph-converter.narrative.json"
|
|
39
|
+
*
|
|
40
|
+
* @param canvasPath - Path to the .otel.canvas file
|
|
41
|
+
* @returns Promise resolving to the narrative template, or null if not found
|
|
42
|
+
*/
|
|
43
|
+
export async function discoverNarrativeTemplate(canvasPath: string): Promise<NarrativeTemplate | null> {
|
|
44
|
+
const narrativePath = canvasPath.replace('.otel.canvas', '.narrative.json');
|
|
45
|
+
return loadNarrativeTemplate(narrativePath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validate a narrative template has required fields
|
|
50
|
+
*
|
|
51
|
+
* @param template - Template to validate
|
|
52
|
+
* @returns True if valid, false otherwise
|
|
53
|
+
*/
|
|
54
|
+
export function validateNarrativeTemplate(template: unknown): template is NarrativeTemplate {
|
|
55
|
+
if (!template || typeof template !== 'object') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const t = template as Partial<NarrativeTemplate>;
|
|
60
|
+
|
|
61
|
+
// Check required fields
|
|
62
|
+
if (!t.version || !t.canvas || !t.name || !t.mode || !t.scenarioSelection || !t.scenarios) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check scenarios array
|
|
67
|
+
if (!Array.isArray(t.scenarios) || t.scenarios.length === 0) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Check each scenario has required fields
|
|
72
|
+
for (const scenario of t.scenarios) {
|
|
73
|
+
if (!scenario.id || !scenario.priority || !scenario.condition || !scenario.template) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get a user-friendly error message for invalid templates
|
|
83
|
+
*
|
|
84
|
+
* @param template - Template to check
|
|
85
|
+
* @returns Error message, or null if valid
|
|
86
|
+
*/
|
|
87
|
+
export function getNarrativeTemplateError(template: unknown): string | null {
|
|
88
|
+
if (!template || typeof template !== 'object') {
|
|
89
|
+
return 'Template must be a valid JSON object';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const t = template as Partial<NarrativeTemplate>;
|
|
93
|
+
|
|
94
|
+
if (!t.version) return 'Missing required field: version';
|
|
95
|
+
if (!t.canvas) return 'Missing required field: canvas';
|
|
96
|
+
if (!t.name) return 'Missing required field: name';
|
|
97
|
+
if (!t.mode) return 'Missing required field: mode';
|
|
98
|
+
if (!t.scenarioSelection) return 'Missing required field: scenarioSelection';
|
|
99
|
+
if (!t.scenarios) return 'Missing required field: scenarios';
|
|
100
|
+
|
|
101
|
+
if (!Array.isArray(t.scenarios)) {
|
|
102
|
+
return 'Field "scenarios" must be an array';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (t.scenarios.length === 0) {
|
|
106
|
+
return 'Template must have at least one scenario';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (let i = 0; i < t.scenarios.length; i++) {
|
|
110
|
+
const scenario = t.scenarios[i];
|
|
111
|
+
if (!scenario.id) return `Scenario ${i}: missing required field "id"`;
|
|
112
|
+
if (scenario.priority === undefined) return `Scenario ${i}: missing required field "priority"`;
|
|
113
|
+
if (!scenario.condition) return `Scenario ${i}: missing required field "condition"`;
|
|
114
|
+
if (!scenario.template) return `Scenario ${i}: missing required field "template"`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* React hook for loading narrative templates
|
|
122
|
+
*
|
|
123
|
+
* @param templatePath - Path to template, or null to skip loading
|
|
124
|
+
* @returns {template, loading, error}
|
|
125
|
+
*/
|
|
126
|
+
export function useNarrativeTemplate(templatePath: string | null) {
|
|
127
|
+
const [template, setTemplate] = React.useState<NarrativeTemplate | null>(null);
|
|
128
|
+
const [loading, setLoading] = React.useState<boolean>(false);
|
|
129
|
+
const [error, setError] = React.useState<string | null>(null);
|
|
130
|
+
|
|
131
|
+
React.useEffect(() => {
|
|
132
|
+
if (!templatePath) {
|
|
133
|
+
setTemplate(null);
|
|
134
|
+
setLoading(false);
|
|
135
|
+
setError(null);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
setLoading(true);
|
|
140
|
+
setError(null);
|
|
141
|
+
|
|
142
|
+
loadNarrativeTemplate(templatePath)
|
|
143
|
+
.then((loadedTemplate) => {
|
|
144
|
+
if (loadedTemplate) {
|
|
145
|
+
const validationError = getNarrativeTemplateError(loadedTemplate);
|
|
146
|
+
if (validationError) {
|
|
147
|
+
setError(validationError);
|
|
148
|
+
setTemplate(null);
|
|
149
|
+
} else {
|
|
150
|
+
setTemplate(loadedTemplate);
|
|
151
|
+
setError(null);
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
setError('Template not found');
|
|
155
|
+
setTemplate(null);
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
.catch((err) => {
|
|
159
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
160
|
+
setTemplate(null);
|
|
161
|
+
})
|
|
162
|
+
.finally(() => {
|
|
163
|
+
setLoading(false);
|
|
164
|
+
});
|
|
165
|
+
}, [templatePath]);
|
|
166
|
+
|
|
167
|
+
return { template, loading, error };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Note: React import is expected to be available in the React package
|
|
171
|
+
// If this causes issues, we can remove the hook and export it separately
|
|
172
|
+
import React from 'react';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { GraphEvent, Violation } from '@principal-ai/principal-view-core';
|
|
3
|
-
export interface EventLogProps {
|
|
4
|
-
/** List of events to display */
|
|
5
|
-
events: GraphEvent[];
|
|
6
|
-
/** Optional violations to highlight */
|
|
7
|
-
violations?: Violation[];
|
|
8
|
-
/** Callback when an event is clicked */
|
|
9
|
-
onEventClick?: (event: GraphEvent) => void;
|
|
10
|
-
/** Optional class name */
|
|
11
|
-
className?: string;
|
|
12
|
-
/** Optional max height */
|
|
13
|
-
maxHeight?: number | string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Event log component for displaying graph events
|
|
17
|
-
* TODO: Implement filtering, search, and severity indicators
|
|
18
|
-
*/
|
|
19
|
-
export declare const EventLog: React.FC<EventLogProps>;
|
|
20
|
-
//# sourceMappingURL=EventLog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventLog.d.ts","sourceRoot":"","sources":["../../src/components/EventLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAE/E,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,MAAM,EAAE,UAAU,EAAE,CAAC;IAErB,uCAAuC;IACvC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAEzB,wCAAwC;IACxC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAE3C,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA0B5C,CAAC"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EventLog = void 0;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
/**
|
|
6
|
-
* Event log component for displaying graph events
|
|
7
|
-
* TODO: Implement filtering, search, and severity indicators
|
|
8
|
-
*/
|
|
9
|
-
const EventLog = ({ events, violations = [], className, maxHeight = '400px', }) => {
|
|
10
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: className, style: { maxHeight, overflowY: 'auto', border: '1px solid #ccc' }, children: (0, jsx_runtime_1.jsxs)("div", { style: { padding: '10px' }, children: [(0, jsx_runtime_1.jsx)("h3", { children: "Event Log (TODO)" }), (0, jsx_runtime_1.jsxs)("p", { children: ["Events: ", events.length] }), (0, jsx_runtime_1.jsxs)("p", { children: ["Violations: ", violations.length] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("strong", { children: "TODO:" }), (0, jsx_runtime_1.jsxs)("ul", { children: [(0, jsx_runtime_1.jsx)("li", { children: "Display events in chronological order" }), (0, jsx_runtime_1.jsx)("li", { children: "Show event type, category, operation" }), (0, jsx_runtime_1.jsx)("li", { children: "Highlight violations with color coding" }), (0, jsx_runtime_1.jsx)("li", { children: "Add filtering by category, type, severity" }), (0, jsx_runtime_1.jsx)("li", { children: "Add text search" }), (0, jsx_runtime_1.jsx)("li", { children: "Add timestamp formatting" })] })] })] }) }));
|
|
11
|
-
};
|
|
12
|
-
exports.EventLog = EventLog;
|
|
13
|
-
//# sourceMappingURL=EventLog.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventLog.js","sourceRoot":"","sources":["../../src/components/EventLog.tsx"],"names":[],"mappings":";;;;AAoBA;;;GAGG;AACI,MAAM,QAAQ,GAA4B,CAAC,EAChD,MAAM,EACN,UAAU,GAAG,EAAE,EACf,SAAS,EACT,SAAS,GAAG,OAAO,GACpB,EAAE,EAAE;IACH,OAAO,CACL,gCAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,YAC1F,iCAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAC7B,8DAAyB,EACzB,sDAAY,MAAM,CAAC,MAAM,IAAK,EAC9B,0DAAgB,UAAU,CAAC,MAAM,IAAK,EACtC,4CACE,uDAAsB,EACtB,2CACE,mFAA8C,EAC9C,kFAA6C,EAC7C,oFAA+C,EAC/C,uFAAkD,EAClD,6DAAwB,EACxB,sEAAiC,IAC9B,IACD,IACF,GACF,CACP,CAAC;AACJ,CAAC,CAAC;AA1BW,QAAA,QAAQ,YA0BnB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventLog.test.d.ts","sourceRoot":"","sources":["../../src/components/EventLog.test.tsx"],"names":[],"mappings":""}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
-
const react_1 = require("@testing-library/react");
|
|
5
|
-
const EventLog_1 = require("./EventLog");
|
|
6
|
-
describe('EventLog', () => {
|
|
7
|
-
const testEvents = [
|
|
8
|
-
{
|
|
9
|
-
id: 'evt-1',
|
|
10
|
-
type: 'node_created',
|
|
11
|
-
timestamp: Date.now(),
|
|
12
|
-
category: 'node',
|
|
13
|
-
operation: 'create',
|
|
14
|
-
payload: {
|
|
15
|
-
operation: 'create',
|
|
16
|
-
nodeId: 'user-1',
|
|
17
|
-
nodeType: 'user',
|
|
18
|
-
data: { userId: 'alice' },
|
|
19
|
-
},
|
|
20
|
-
expected: true,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
id: 'evt-2',
|
|
24
|
-
type: 'edge_created',
|
|
25
|
-
timestamp: Date.now(),
|
|
26
|
-
category: 'edge',
|
|
27
|
-
operation: 'create',
|
|
28
|
-
payload: {
|
|
29
|
-
operation: 'create',
|
|
30
|
-
edgeId: 'conn-1',
|
|
31
|
-
edgeType: 'connection',
|
|
32
|
-
from: 'user-1',
|
|
33
|
-
to: 'user-2',
|
|
34
|
-
},
|
|
35
|
-
expected: true,
|
|
36
|
-
},
|
|
37
|
-
];
|
|
38
|
-
const testViolations = [
|
|
39
|
-
{
|
|
40
|
-
id: 'violation-1',
|
|
41
|
-
severity: 'error',
|
|
42
|
-
type: 'connection',
|
|
43
|
-
description: 'Invalid connection',
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
it('should render without crashing', () => {
|
|
47
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: testEvents }));
|
|
48
|
-
expect(react_1.screen.getByText(/Event Log/i)).toBeDefined();
|
|
49
|
-
});
|
|
50
|
-
it('should display event count', () => {
|
|
51
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: testEvents }));
|
|
52
|
-
expect(react_1.screen.getByText(/Events: 2/i)).toBeDefined();
|
|
53
|
-
});
|
|
54
|
-
it('should display violation count', () => {
|
|
55
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: testEvents, violations: testViolations }));
|
|
56
|
-
expect(react_1.screen.getByText(/Violations: 1/i)).toBeDefined();
|
|
57
|
-
});
|
|
58
|
-
it('should render with empty events', () => {
|
|
59
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: [] }));
|
|
60
|
-
expect(react_1.screen.getByText(/Events: 0/i)).toBeDefined();
|
|
61
|
-
});
|
|
62
|
-
it('should apply custom className', () => {
|
|
63
|
-
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: testEvents, className: "custom-log" }));
|
|
64
|
-
const element = container.querySelector('.custom-log');
|
|
65
|
-
expect(element).toBeDefined();
|
|
66
|
-
});
|
|
67
|
-
it('should apply custom maxHeight', () => {
|
|
68
|
-
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(EventLog_1.EventLog, { events: testEvents, maxHeight: "300px" }));
|
|
69
|
-
const element = container.querySelector('div');
|
|
70
|
-
expect(element?.style.maxHeight).toBe('300px');
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
//# sourceMappingURL=EventLog.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventLog.test.js","sourceRoot":"","sources":["../../src/components/EventLog.test.tsx"],"names":[],"mappings":";;;AACA,kDAAwD;AACxD,yCAAsC;AAGtC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,MAAM,UAAU,GAAiB;QAC/B;YACE,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,cAAc;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE;gBACP,SAAS,EAAE,QAAQ;gBACnB,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;aAC1B;YACD,QAAQ,EAAE,IAAI;SACf;QACD;YACE,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,cAAc;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE;gBACP,SAAS,EAAE,QAAQ;gBACnB,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,YAAY;gBACtB,IAAI,EAAE,QAAQ;gBACd,EAAE,EAAE,QAAQ;aACb;YACD,QAAQ,EAAE,IAAI;SACf;KACF,CAAC;IAEF,MAAM,cAAc,GAAgB;QAClC;YACE,EAAE,EAAE,aAAa;YACjB,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,oBAAoB;SAClC;KACF,CAAC;IAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,UAAU,GAAI,CAAC,CAAC;QAEzC,MAAM,CAAC,cAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,UAAU,GAAI,CAAC,CAAC;QAEzC,MAAM,CAAC,cAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,GAAI,CAAC,CAAC;QAErE,MAAM,CAAC,cAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,EAAE,GAAI,CAAC,CAAC;QAEjC,MAAM,CAAC,cAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAC,YAAY,GAAG,CAAC,CAAC;QAEtF,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAA,cAAM,EAAC,uBAAC,mBAAQ,IAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAC,OAAO,GAAG,CAAC,CAAC;QAEjF,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GraphRenderer.test.d.ts","sourceRoot":"","sources":["../../src/components/GraphRenderer.test.tsx"],"names":[],"mappings":""}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
-
const react_1 = require("@testing-library/react");
|
|
5
|
-
const GraphRenderer_1 = require("./GraphRenderer");
|
|
6
|
-
describe('GraphRenderer', () => {
|
|
7
|
-
const testConfig = {
|
|
8
|
-
metadata: {
|
|
9
|
-
name: 'Test Graph',
|
|
10
|
-
version: '1.0.0',
|
|
11
|
-
},
|
|
12
|
-
nodeTypes: {
|
|
13
|
-
user: {
|
|
14
|
-
shape: 'circle',
|
|
15
|
-
color: '#4CAF50',
|
|
16
|
-
dataSchema: {
|
|
17
|
-
userId: { type: 'string', required: true },
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
edgeTypes: {
|
|
22
|
-
connection: {
|
|
23
|
-
style: 'solid',
|
|
24
|
-
directed: true,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
allowedConnections: [{ from: 'user', to: 'user', via: 'connection' }],
|
|
28
|
-
};
|
|
29
|
-
const testNodes = [
|
|
30
|
-
{
|
|
31
|
-
id: 'user-1',
|
|
32
|
-
type: 'user',
|
|
33
|
-
data: { userId: 'alice' },
|
|
34
|
-
createdAt: Date.now(),
|
|
35
|
-
updatedAt: Date.now(),
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: 'user-2',
|
|
39
|
-
type: 'user',
|
|
40
|
-
data: { userId: 'bob' },
|
|
41
|
-
createdAt: Date.now(),
|
|
42
|
-
updatedAt: Date.now(),
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
const testEdges = [
|
|
46
|
-
{
|
|
47
|
-
id: 'conn-1',
|
|
48
|
-
type: 'connection',
|
|
49
|
-
from: 'user-1',
|
|
50
|
-
to: 'user-2',
|
|
51
|
-
createdAt: Date.now(),
|
|
52
|
-
updatedAt: Date.now(),
|
|
53
|
-
},
|
|
54
|
-
];
|
|
55
|
-
it('should render without crashing', () => {
|
|
56
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges }));
|
|
57
|
-
expect(react_1.screen.getByText(/Graph Renderer/i)).toBeDefined();
|
|
58
|
-
});
|
|
59
|
-
it('should display configuration name', () => {
|
|
60
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges }));
|
|
61
|
-
expect(react_1.screen.getByText(/Test Graph/i)).toBeDefined();
|
|
62
|
-
});
|
|
63
|
-
it('should display node count', () => {
|
|
64
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges }));
|
|
65
|
-
expect(react_1.screen.getByText(/Nodes: 2/i)).toBeDefined();
|
|
66
|
-
});
|
|
67
|
-
it('should display edge count', () => {
|
|
68
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges }));
|
|
69
|
-
expect(react_1.screen.getByText(/Edges: 1/i)).toBeDefined();
|
|
70
|
-
});
|
|
71
|
-
it('should render with empty nodes and edges', () => {
|
|
72
|
-
(0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: [], edges: [] }));
|
|
73
|
-
expect(react_1.screen.getByText(/Nodes: 0/i)).toBeDefined();
|
|
74
|
-
expect(react_1.screen.getByText(/Edges: 0/i)).toBeDefined();
|
|
75
|
-
});
|
|
76
|
-
it('should apply custom className', () => {
|
|
77
|
-
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges, className: "custom-class" }));
|
|
78
|
-
const element = container.querySelector('.custom-class');
|
|
79
|
-
expect(element).toBeDefined();
|
|
80
|
-
});
|
|
81
|
-
it('should apply custom width and height', () => {
|
|
82
|
-
const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(GraphRenderer_1.GraphRenderer, { configuration: testConfig, nodes: testNodes, edges: testEdges, width: "500px", height: "400px" }));
|
|
83
|
-
const element = container.querySelector('div');
|
|
84
|
-
expect(element?.style.width).toBe('500px');
|
|
85
|
-
expect(element?.style.height).toBe('400px');
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
//# sourceMappingURL=GraphRenderer.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GraphRenderer.test.js","sourceRoot":"","sources":["../../src/components/GraphRenderer.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface Layer {
|
|
3
|
-
id: string;
|
|
4
|
-
label: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
order: number;
|
|
7
|
-
color?: string;
|
|
8
|
-
narrative?: string;
|
|
9
|
-
visible?: boolean;
|
|
10
|
-
nodeCount?: number;
|
|
11
|
-
}
|
|
12
|
-
export interface LayerPanelProps {
|
|
13
|
-
layers: Layer[];
|
|
14
|
-
/** Callback when layer visibility is toggled */
|
|
15
|
-
onToggleLayer?: (layerId: string, visible: boolean) => void;
|
|
16
|
-
/** Callback when a layer is focused/highlighted */
|
|
17
|
-
onFocusLayer?: (layerId: string) => void;
|
|
18
|
-
/** Show narrative flow mode toggle */
|
|
19
|
-
showNarrativeMode?: boolean;
|
|
20
|
-
/** Narrative mode active state */
|
|
21
|
-
narrativeMode?: boolean;
|
|
22
|
-
/** Callback when narrative mode is toggled */
|
|
23
|
-
onToggleNarrativeMode?: (active: boolean) => void;
|
|
24
|
-
/** Position: 'left' or 'right' */
|
|
25
|
-
position?: 'left' | 'right';
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Panel that displays and controls layer visibility and organization
|
|
29
|
-
*/
|
|
30
|
-
export declare const LayerPanel: React.FC<LayerPanelProps>;
|
|
31
|
-
//# sourceMappingURL=LayerPanel.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LayerPanel.d.ts","sourceRoot":"","sources":["../../src/components/LayerPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,gDAAgD;IAChD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,mDAAmD;IACnD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kCAAkC;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAyWhD,CAAC"}
|