@principal-ai/subsystems-react 0.21.0 → 0.21.1
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/package.json +1 -1
- package/dist/components/ConfigurationSelector.d.ts +0 -35
- package/dist/components/ConfigurationSelector.d.ts.map +0 -1
- package/dist/components/ConfigurationSelector.js +0 -63
- package/dist/components/ConfigurationSelector.js.map +0 -1
- package/dist/components/GraphRenderer.d.ts +0 -295
- package/dist/components/GraphRenderer.d.ts.map +0 -1
- package/dist/components/GraphRenderer.js +0 -2008
- package/dist/components/GraphRenderer.js.map +0 -1
- package/dist/components/MultiCanvasRenderer.d.ts +0 -75
- package/dist/components/MultiCanvasRenderer.d.ts.map +0 -1
- package/dist/components/MultiCanvasRenderer.js +0 -203
- package/dist/components/MultiCanvasRenderer.js.map +0 -1
- package/dist/components/NodeTooltip.d.ts +0 -24
- package/dist/components/NodeTooltip.d.ts.map +0 -1
- package/dist/components/NodeTooltip.js +0 -160
- package/dist/components/NodeTooltip.js.map +0 -1
- package/dist/components/SelectionSidebar.d.ts +0 -18
- package/dist/components/SelectionSidebar.d.ts.map +0 -1
- package/dist/components/SelectionSidebar.js +0 -190
- package/dist/components/SelectionSidebar.js.map +0 -1
- package/dist/components/SequenceDiagramRenderer.d.ts +0 -77
- package/dist/components/SequenceDiagramRenderer.d.ts.map +0 -1
- package/dist/components/SequenceDiagramRenderer.js +0 -604
- package/dist/components/SequenceDiagramRenderer.js.map +0 -1
- package/dist/components/WorkflowSequenceDiagram.d.ts +0 -63
- package/dist/components/WorkflowSequenceDiagram.d.ts.map +0 -1
- package/dist/components/WorkflowSequenceDiagram.js +0 -147
- package/dist/components/WorkflowSequenceDiagram.js.map +0 -1
- package/dist/components/dashboard/DashboardRenderer.d.ts +0 -10
- package/dist/components/dashboard/DashboardRenderer.d.ts.map +0 -1
- package/dist/components/dashboard/DashboardRenderer.js +0 -179
- package/dist/components/dashboard/DashboardRenderer.js.map +0 -1
- package/dist/components/dashboard/MetricPanel.d.ts +0 -10
- package/dist/components/dashboard/MetricPanel.d.ts.map +0 -1
- package/dist/components/dashboard/MetricPanel.js +0 -103
- package/dist/components/dashboard/MetricPanel.js.map +0 -1
- package/dist/components/dashboard/MockDataProvider.d.ts +0 -30
- package/dist/components/dashboard/MockDataProvider.d.ts.map +0 -1
- package/dist/components/dashboard/MockDataProvider.js +0 -270
- package/dist/components/dashboard/MockDataProvider.js.map +0 -1
- package/dist/components/dashboard/components/BarChart.d.ts +0 -10
- package/dist/components/dashboard/components/BarChart.d.ts.map +0 -1
- package/dist/components/dashboard/components/BarChart.js +0 -167
- package/dist/components/dashboard/components/BarChart.js.map +0 -1
- package/dist/components/dashboard/components/LineChart.d.ts +0 -10
- package/dist/components/dashboard/components/LineChart.d.ts.map +0 -1
- package/dist/components/dashboard/components/LineChart.js +0 -141
- package/dist/components/dashboard/components/LineChart.js.map +0 -1
- package/dist/components/dashboard/components/MetricCard.d.ts +0 -9
- package/dist/components/dashboard/components/MetricCard.d.ts.map +0 -1
- package/dist/components/dashboard/components/MetricCard.js +0 -163
- package/dist/components/dashboard/components/MetricCard.js.map +0 -1
- package/dist/components/dashboard/components/SourceLink.d.ts +0 -9
- package/dist/components/dashboard/components/SourceLink.d.ts.map +0 -1
- package/dist/components/dashboard/components/SourceLink.js +0 -39
- package/dist/components/dashboard/components/SourceLink.js.map +0 -1
- package/dist/components/dashboard/components/TimeRangeSelector.d.ts +0 -9
- package/dist/components/dashboard/components/TimeRangeSelector.d.ts.map +0 -1
- package/dist/components/dashboard/components/TimeRangeSelector.js +0 -167
- package/dist/components/dashboard/components/TimeRangeSelector.js.map +0 -1
- package/dist/components/dashboard/components/index.d.ts +0 -6
- package/dist/components/dashboard/components/index.d.ts.map +0 -1
- package/dist/components/dashboard/components/index.js +0 -6
- package/dist/components/dashboard/components/index.js.map +0 -1
- package/dist/components/dashboard/index.d.ts +0 -6
- package/dist/components/dashboard/index.d.ts.map +0 -1
- package/dist/components/dashboard/index.js +0 -8
- package/dist/components/dashboard/index.js.map +0 -1
- package/dist/components/dashboard/types.d.ts +0 -74
- package/dist/components/dashboard/types.d.ts.map +0 -1
- package/dist/components/dashboard/types.js +0 -8
- package/dist/components/dashboard/types.js.map +0 -1
- package/dist/components/state-view/PipelineView.d.ts +0 -14
- package/dist/components/state-view/PipelineView.d.ts.map +0 -1
- package/dist/components/state-view/PipelineView.js +0 -195
- package/dist/components/state-view/PipelineView.js.map +0 -1
- package/dist/components/state-view/index.d.ts +0 -14
- package/dist/components/state-view/index.d.ts.map +0 -1
- package/dist/components/state-view/index.js +0 -12
- package/dist/components/state-view/index.js.map +0 -1
- package/dist/components/state-view/types.d.ts +0 -188
- package/dist/components/state-view/types.d.ts.map +0 -1
- package/dist/components/state-view/types.js +0 -10
- package/dist/components/state-view/types.js.map +0 -1
- package/dist/components/state-view/useStateView.d.ts +0 -32
- package/dist/components/state-view/useStateView.d.ts.map +0 -1
- package/dist/components/state-view/useStateView.js +0 -129
- package/dist/components/state-view/useStateView.js.map +0 -1
- package/dist/contexts/GraphEditContext.d.ts +0 -20
- package/dist/contexts/GraphEditContext.d.ts.map +0 -1
- package/dist/contexts/GraphEditContext.js +0 -8
- package/dist/contexts/GraphEditContext.js.map +0 -1
- package/dist/contexts/TooltipPortalContext.d.ts +0 -8
- package/dist/contexts/TooltipPortalContext.d.ts.map +0 -1
- package/dist/contexts/TooltipPortalContext.js +0 -8
- package/dist/contexts/TooltipPortalContext.js.map +0 -1
- package/dist/edges/CustomEdge.d.ts +0 -24
- package/dist/edges/CustomEdge.d.ts.map +0 -1
- package/dist/edges/CustomEdge.js +0 -222
- package/dist/edges/CustomEdge.js.map +0 -1
- package/dist/edges/GenericEdge.d.ts +0 -18
- package/dist/edges/GenericEdge.d.ts.map +0 -1
- package/dist/edges/GenericEdge.js +0 -10
- package/dist/edges/GenericEdge.js.map +0 -1
- package/dist/graphify/kind.d.ts +0 -23
- package/dist/graphify/kind.d.ts.map +0 -1
- package/dist/graphify/kind.js +0 -77
- package/dist/graphify/kind.js.map +0 -1
- package/dist/hooks/usePathBasedEvents.d.ts +0 -42
- package/dist/hooks/usePathBasedEvents.d.ts.map +0 -1
- package/dist/hooks/usePathBasedEvents.js +0 -119
- package/dist/hooks/usePathBasedEvents.js.map +0 -1
- package/dist/hooks/useSequenceLayout.d.ts +0 -186
- package/dist/hooks/useSequenceLayout.d.ts.map +0 -1
- package/dist/hooks/useSequenceLayout.js +0 -327
- package/dist/hooks/useSequenceLayout.js.map +0 -1
- package/dist/hooks/useUndoRedo.d.ts +0 -80
- package/dist/hooks/useUndoRedo.d.ts.map +0 -1
- package/dist/hooks/useUndoRedo.js +0 -70
- package/dist/hooks/useUndoRedo.js.map +0 -1
- package/dist/nodes/CustomNode.d.ts +0 -28
- package/dist/nodes/CustomNode.d.ts.map +0 -1
- package/dist/nodes/CustomNode.js +0 -820
- package/dist/nodes/CustomNode.js.map +0 -1
- package/dist/nodes/GenericNode.d.ts +0 -20
- package/dist/nodes/GenericNode.d.ts.map +0 -1
- package/dist/nodes/GenericNode.js +0 -20
- package/dist/nodes/GenericNode.js.map +0 -1
- package/dist/nodes/otel/OtelBoundaryNode.d.ts +0 -55
- package/dist/nodes/otel/OtelBoundaryNode.d.ts.map +0 -1
- package/dist/nodes/otel/OtelBoundaryNode.js +0 -81
- package/dist/nodes/otel/OtelBoundaryNode.js.map +0 -1
- package/dist/nodes/otel/OtelEventNode.d.ts +0 -59
- package/dist/nodes/otel/OtelEventNode.d.ts.map +0 -1
- package/dist/nodes/otel/OtelEventNode.js +0 -82
- package/dist/nodes/otel/OtelEventNode.js.map +0 -1
- package/dist/nodes/otel/OtelResourceNode.d.ts +0 -53
- package/dist/nodes/otel/OtelResourceNode.d.ts.map +0 -1
- package/dist/nodes/otel/OtelResourceNode.js +0 -105
- package/dist/nodes/otel/OtelResourceNode.js.map +0 -1
- package/dist/nodes/otel/OtelScopeNode.d.ts +0 -53
- package/dist/nodes/otel/OtelScopeNode.d.ts.map +0 -1
- package/dist/nodes/otel/OtelScopeNode.js +0 -81
- package/dist/nodes/otel/OtelScopeNode.js.map +0 -1
- package/dist/nodes/otel/OtelSpanConventionNode.d.ts +0 -61
- package/dist/nodes/otel/OtelSpanConventionNode.d.ts.map +0 -1
- package/dist/nodes/otel/OtelSpanConventionNode.js +0 -131
- package/dist/nodes/otel/OtelSpanConventionNode.js.map +0 -1
- package/dist/nodes/otel/index.d.ts +0 -17
- package/dist/nodes/otel/index.d.ts.map +0 -1
- package/dist/nodes/otel/index.js +0 -13
- package/dist/nodes/otel/index.js.map +0 -1
- package/dist/nodes/otel/shared/NodeBadges.d.ts +0 -10
- package/dist/nodes/otel/shared/NodeBadges.d.ts.map +0 -1
- package/dist/nodes/otel/shared/NodeBadges.js +0 -178
- package/dist/nodes/otel/shared/NodeBadges.js.map +0 -1
- package/dist/nodes/otel/shared/NodeContent.d.ts +0 -10
- package/dist/nodes/otel/shared/NodeContent.d.ts.map +0 -1
- package/dist/nodes/otel/shared/NodeContent.js +0 -96
- package/dist/nodes/otel/shared/NodeContent.js.map +0 -1
- package/dist/nodes/otel/shared/index.d.ts +0 -8
- package/dist/nodes/otel/shared/index.d.ts.map +0 -1
- package/dist/nodes/otel/shared/index.js +0 -8
- package/dist/nodes/otel/shared/index.js.map +0 -1
- package/dist/nodes/otel/shared/types.d.ts +0 -129
- package/dist/nodes/otel/shared/types.d.ts.map +0 -1
- package/dist/nodes/otel/shared/types.js +0 -5
- package/dist/nodes/otel/shared/types.js.map +0 -1
- package/dist/nodes/otel/shared/useNodeBehavior.d.ts +0 -42
- package/dist/nodes/otel/shared/useNodeBehavior.d.ts.map +0 -1
- package/dist/nodes/otel/shared/useNodeBehavior.js +0 -61
- package/dist/nodes/otel/shared/useNodeBehavior.js.map +0 -1
- package/dist/pierre/PierreThroughlineCodeView.d.ts +0 -22
- package/dist/pierre/PierreThroughlineCodeView.d.ts.map +0 -1
- package/dist/pierre/PierreThroughlineCodeView.js +0 -206
- package/dist/pierre/PierreThroughlineCodeView.js.map +0 -1
- package/dist/subsystem/SubsystemCarousel.d.ts +0 -36
- package/dist/subsystem/SubsystemCarousel.d.ts.map +0 -1
- package/dist/subsystem/SubsystemCarousel.js +0 -163
- package/dist/subsystem/SubsystemCarousel.js.map +0 -1
- package/dist/utils/animationMapping.d.ts +0 -53
- package/dist/utils/animationMapping.d.ts.map +0 -1
- package/dist/utils/animationMapping.js +0 -126
- package/dist/utils/animationMapping.js.map +0 -1
- package/dist/utils/canvasBounds.d.ts +0 -50
- package/dist/utils/canvasBounds.d.ts.map +0 -1
- package/dist/utils/canvasBounds.js +0 -88
- package/dist/utils/canvasBounds.js.map +0 -1
- package/dist/utils/graphConverter.d.ts +0 -18
- package/dist/utils/graphConverter.d.ts.map +0 -1
- package/dist/utils/graphConverter.js +0 -114
- package/dist/utils/graphConverter.js.map +0 -1
- package/dist/utils/iconResolver.d.ts +0 -29
- package/dist/utils/iconResolver.d.ts.map +0 -1
- package/dist/utils/iconResolver.js +0 -30
- package/dist/utils/iconResolver.js.map +0 -1
- package/dist/utils/orientationUtils.d.ts +0 -19
- package/dist/utils/orientationUtils.d.ts.map +0 -1
- package/dist/utils/orientationUtils.js +0 -62
- package/dist/utils/orientationUtils.js.map +0 -1
package/dist/nodes/CustomNode.js
DELETED
|
@@ -1,820 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useCallback } from 'react';
|
|
3
|
-
import { Handle, Position, NodeResizer, useNodeId } from '@xyflow/react';
|
|
4
|
-
import { useTheme } from '@principal-ade/industry-theme';
|
|
5
|
-
import { resolveIcon } from '../utils/iconResolver';
|
|
6
|
-
import { NodeTooltip } from '../components/NodeTooltip';
|
|
7
|
-
import { useGraphEdit } from '../contexts/GraphEditContext';
|
|
8
|
-
// OTEL node components
|
|
9
|
-
import { OtelSpanConventionNode, OtelEventNode, OtelScopeNode, OtelResourceNode, OtelBoundaryNode, } from './otel';
|
|
10
|
-
/**
|
|
11
|
-
* Custom node component for xyflow that renders based on NodeTypeDefinition
|
|
12
|
-
*
|
|
13
|
-
* This component now delegates to specialized OTEL node components when the
|
|
14
|
-
* node type matches an OTEL concept. This allows each OTEL node type to have
|
|
15
|
-
* its own specialized rendering and features (e.g., workflow chips on span nodes).
|
|
16
|
-
*/
|
|
17
|
-
export const CustomNode = (props) => {
|
|
18
|
-
const { data, selected, dragging } = props;
|
|
19
|
-
// Determine the OTEL node type from nodeData.nodeType (pv.nodeType in canvas)
|
|
20
|
-
// The typeDefinition.shape can also hint at OTEL types but nodeType is authoritative
|
|
21
|
-
const nodeType = data.data?.nodeType;
|
|
22
|
-
// Delegate to specialized OTEL node components
|
|
23
|
-
switch (nodeType) {
|
|
24
|
-
case 'otel-span-convention':
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
-
return _jsx(OtelSpanConventionNode, { ...props });
|
|
27
|
-
case 'otel-event':
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
return _jsx(OtelEventNode, { ...props });
|
|
30
|
-
case 'otel-scope':
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
return _jsx(OtelScopeNode, { ...props });
|
|
33
|
-
case 'otel-resource':
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
-
return _jsx(OtelResourceNode, { ...props });
|
|
36
|
-
case 'otel-boundary':
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
return _jsx(OtelBoundaryNode, { ...props });
|
|
39
|
-
}
|
|
40
|
-
// Fall through to legacy rendering for non-OTEL nodes
|
|
41
|
-
const { theme } = useTheme();
|
|
42
|
-
const { onNodeResizeEnd, onNodeTextChange, onToggleNodeHidden, onHideUnconnectedNodes } = useGraphEdit();
|
|
43
|
-
const nodeId = useNodeId();
|
|
44
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
45
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
46
|
-
const [editingText, setEditingText] = useState('');
|
|
47
|
-
const nodeRef = useRef(null);
|
|
48
|
-
const textareaRef = useRef(null);
|
|
49
|
-
const nodeProps = data;
|
|
50
|
-
const { typeDefinition, state, hasViolations, data: nodeData, animationType, animationDuration = 1000, editable = false, tooltipsEnabled = true, shiftKeyPressed = false, isHighlighted = false, isActive = true, // Default to active if not specified
|
|
51
|
-
isHidden = false, // Default to not hidden
|
|
52
|
-
} = nodeProps;
|
|
53
|
-
// Calculate opacity based on node state
|
|
54
|
-
// Hidden nodes (shift-clicked) are dimmed to 0.4
|
|
55
|
-
// Inactive nodes (scenario filtering) are dimmed to 0.1
|
|
56
|
-
const nodeOpacity = isHidden ? 0.4 : isActive ? 1 : 0.1;
|
|
57
|
-
// Handle resize end - notify parent to track the dimension change
|
|
58
|
-
const handleResizeEnd = useCallback((_event, params) => {
|
|
59
|
-
if (nodeId && onNodeResizeEnd && params.width && params.height) {
|
|
60
|
-
onNodeResizeEnd(nodeId, {
|
|
61
|
-
width: Math.round(params.width),
|
|
62
|
-
height: Math.round(params.height),
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}, [nodeId, onNodeResizeEnd]);
|
|
66
|
-
// Handle Cmd/Ctrl+mousedown to toggle hidden state
|
|
67
|
-
// We use mousedown instead of click because in edit mode with draggable nodes,
|
|
68
|
-
// ReactFlow's drag system intercepts Cmd+click before it becomes a click event
|
|
69
|
-
// - Cmd/Ctrl+Shift+click: hide all nodes not directly connected to this node
|
|
70
|
-
// - Cmd/Ctrl+click: toggle this single node's hidden state
|
|
71
|
-
const handleMouseDown = useCallback((event) => {
|
|
72
|
-
if ((event.metaKey || event.ctrlKey) && nodeId) {
|
|
73
|
-
event.preventDefault();
|
|
74
|
-
event.stopPropagation();
|
|
75
|
-
if (event.shiftKey && onHideUnconnectedNodes) {
|
|
76
|
-
// Cmd/Ctrl+Shift+click: hide unconnected nodes
|
|
77
|
-
onHideUnconnectedNodes(nodeId);
|
|
78
|
-
}
|
|
79
|
-
else if (onToggleNodeHidden) {
|
|
80
|
-
// Cmd/Ctrl+click: toggle single node
|
|
81
|
-
onToggleNodeHidden(nodeId);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}, [nodeId, onToggleNodeHidden, onHideUnconnectedNodes]);
|
|
85
|
-
// Show tooltip when:
|
|
86
|
-
// 1. Hovering + not dragging + shift key pressed (always works), OR
|
|
87
|
-
// 2. Node is selected AND not in edit mode (read-only selection shows tooltip)
|
|
88
|
-
const showTooltip = (isHovered && !dragging && shiftKeyPressed) || (!editable && !!selected);
|
|
89
|
-
// Extract OTEL info, description, sources/files, and references for tooltip
|
|
90
|
-
const otelInfo = nodeData?.otel;
|
|
91
|
-
const description = nodeData?.description;
|
|
92
|
-
const sources = nodeData?.sources; // deprecated
|
|
93
|
-
const references = nodeData?.references;
|
|
94
|
-
// Files from otel.files - these are source code files where the event is instrumented
|
|
95
|
-
const files = otelInfo?.files;
|
|
96
|
-
// Get badge shape styles based on node shape
|
|
97
|
-
const getBadgeShapeStyles = () => {
|
|
98
|
-
const shape = typeDefinition.shape;
|
|
99
|
-
const baseSize = 18;
|
|
100
|
-
switch (shape) {
|
|
101
|
-
case 'circle':
|
|
102
|
-
return {
|
|
103
|
-
width: baseSize,
|
|
104
|
-
height: baseSize,
|
|
105
|
-
borderRadius: '50%',
|
|
106
|
-
};
|
|
107
|
-
case 'diamond':
|
|
108
|
-
return {
|
|
109
|
-
width: baseSize - 4,
|
|
110
|
-
height: baseSize - 4,
|
|
111
|
-
borderRadius: 0,
|
|
112
|
-
transform: 'rotate(45deg)',
|
|
113
|
-
};
|
|
114
|
-
case 'hexagon':
|
|
115
|
-
return {
|
|
116
|
-
width: baseSize,
|
|
117
|
-
height: baseSize,
|
|
118
|
-
borderRadius: 0,
|
|
119
|
-
clipPath: 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)',
|
|
120
|
-
};
|
|
121
|
-
case 'rectangle':
|
|
122
|
-
default:
|
|
123
|
-
return {
|
|
124
|
-
width: baseSize,
|
|
125
|
-
height: baseSize,
|
|
126
|
-
borderRadius: 0,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
// Get badge position based on shape - diamonds need badges at their points, not bounding box corners
|
|
131
|
-
const getBadgePosition = (position) => {
|
|
132
|
-
const isDiamondShape = typeDefinition.shape === 'diamond';
|
|
133
|
-
if (isDiamondShape) {
|
|
134
|
-
// Diamond points are at the middle of each edge of the bounding box
|
|
135
|
-
switch (position) {
|
|
136
|
-
case 'top-left':
|
|
137
|
-
case 'left':
|
|
138
|
-
// Position at the LEFT point of the diamond (center-left)
|
|
139
|
-
return { top: '50%', left: 0, transform: 'translate(-50%, -50%)' };
|
|
140
|
-
case 'top-right':
|
|
141
|
-
case 'right':
|
|
142
|
-
// Position at the RIGHT point of the diamond (center-right)
|
|
143
|
-
return { top: '50%', right: 0, transform: 'translate(50%, -50%)' };
|
|
144
|
-
case 'top':
|
|
145
|
-
// Position at the TOP point of the diamond
|
|
146
|
-
return { top: 0, left: '50%', transform: 'translate(-50%, -50%)' };
|
|
147
|
-
case 'bottom':
|
|
148
|
-
case 'bottom-left':
|
|
149
|
-
case 'bottom-right':
|
|
150
|
-
// Position at the BOTTOM point of the diamond
|
|
151
|
-
return { bottom: 0, left: '50%', transform: 'translate(-50%, 50%)' };
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// Default positioning for rectangles, circles, hexagons (bounding box corners)
|
|
155
|
-
switch (position) {
|
|
156
|
-
case 'top-left':
|
|
157
|
-
return { top: -6, left: -6 };
|
|
158
|
-
case 'top-right':
|
|
159
|
-
return { top: -6, right: -6 };
|
|
160
|
-
case 'bottom-left':
|
|
161
|
-
return { bottom: -6, left: -6 };
|
|
162
|
-
case 'bottom-right':
|
|
163
|
-
return { bottom: -6, right: -6 };
|
|
164
|
-
case 'left':
|
|
165
|
-
return { top: -6, left: -6 };
|
|
166
|
-
case 'right':
|
|
167
|
-
return { top: -6, right: -6 };
|
|
168
|
-
case 'top':
|
|
169
|
-
return { top: -6, left: '50%', transform: 'translateX(-50%)' };
|
|
170
|
-
case 'bottom':
|
|
171
|
-
return { bottom: -6, left: '50%', transform: 'translateX(-50%)' };
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
// Render Sources badge (top-right) - shows "S" for files where event is instrumented
|
|
175
|
-
const renderSourcesBadge = () => {
|
|
176
|
-
// Use otel.files (source code files where event is instrumented)
|
|
177
|
-
// Fall back to deprecated sources field for backwards compatibility
|
|
178
|
-
const sourceFiles = files || sources;
|
|
179
|
-
if (!sourceFiles || sourceFiles.length === 0)
|
|
180
|
-
return null;
|
|
181
|
-
const shapeStyles = getBadgeShapeStyles();
|
|
182
|
-
const positionStyles = getBadgePosition('top-right');
|
|
183
|
-
return (_jsx("div", { style: {
|
|
184
|
-
position: 'absolute',
|
|
185
|
-
...positionStyles,
|
|
186
|
-
...shapeStyles,
|
|
187
|
-
// Override transform if shape has rotation but we already have a position transform
|
|
188
|
-
...(typeDefinition.shape === 'diamond' ? { transform: `${positionStyles.transform} rotate(45deg)` } : {}),
|
|
189
|
-
backgroundColor: '#10b981',
|
|
190
|
-
color: 'white',
|
|
191
|
-
fontSize: theme.fontSizes[0],
|
|
192
|
-
fontWeight: theme.fontWeights.bold,
|
|
193
|
-
fontFamily: theme.fonts.body,
|
|
194
|
-
display: 'flex',
|
|
195
|
-
alignItems: 'center',
|
|
196
|
-
justifyContent: 'center',
|
|
197
|
-
boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
|
|
198
|
-
zIndex: 10,
|
|
199
|
-
opacity: nodeOpacity,
|
|
200
|
-
}, title: `Source files: ${sourceFiles.join(', ')}`, children: _jsx("span", { style: { transform: shapeStyles.transform ? 'rotate(-45deg)' : undefined }, children: "S" }) }));
|
|
201
|
-
};
|
|
202
|
-
// Render References badge (bottom-left for rectangles, bottom for diamonds) - shows "R" for external references
|
|
203
|
-
const renderReferencesBadge = () => {
|
|
204
|
-
if (!references || references.length === 0)
|
|
205
|
-
return null;
|
|
206
|
-
const shapeStyles = getBadgeShapeStyles();
|
|
207
|
-
const positionStyles = getBadgePosition('bottom-left');
|
|
208
|
-
return (_jsx("div", { style: {
|
|
209
|
-
position: 'absolute',
|
|
210
|
-
...positionStyles,
|
|
211
|
-
...shapeStyles,
|
|
212
|
-
// Override transform if shape has rotation but we already have a position transform
|
|
213
|
-
...(typeDefinition.shape === 'diamond' ? { transform: `${positionStyles.transform} rotate(45deg)` } : {}),
|
|
214
|
-
backgroundColor: '#8b5cf6',
|
|
215
|
-
color: 'white',
|
|
216
|
-
fontSize: theme.fontSizes[0],
|
|
217
|
-
fontWeight: theme.fontWeights.bold,
|
|
218
|
-
fontFamily: theme.fonts.body,
|
|
219
|
-
display: 'flex',
|
|
220
|
-
alignItems: 'center',
|
|
221
|
-
justifyContent: 'center',
|
|
222
|
-
boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
|
|
223
|
-
zIndex: 10,
|
|
224
|
-
opacity: nodeOpacity,
|
|
225
|
-
}, title: `References: ${references.join(', ')}`, children: _jsx("span", { style: { transform: shapeStyles.transform ? 'rotate(-45deg)' : undefined }, children: "R" }) }));
|
|
226
|
-
};
|
|
227
|
-
// Render Boundary badge (right/left points) - shown instead of sources badge for boundary nodes
|
|
228
|
-
const renderBoundaryBadge = () => {
|
|
229
|
-
const boundary = nodeData?.boundary;
|
|
230
|
-
if (!boundary)
|
|
231
|
-
return null;
|
|
232
|
-
const direction = boundary.direction || 'outbound';
|
|
233
|
-
const isOutbound = direction === 'outbound';
|
|
234
|
-
// Direction indicators
|
|
235
|
-
const directionIcon = isOutbound ? '↗' : '↙';
|
|
236
|
-
const directionTitle = isOutbound ? 'Outbound boundary (calls external system)' : 'Inbound boundary (called by external system)';
|
|
237
|
-
const positionStyles = getBadgePosition(isOutbound ? 'right' : 'left');
|
|
238
|
-
return (_jsx("div", { style: {
|
|
239
|
-
position: 'absolute',
|
|
240
|
-
...positionStyles,
|
|
241
|
-
width: 18,
|
|
242
|
-
height: 18,
|
|
243
|
-
borderRadius: '50%',
|
|
244
|
-
backgroundColor: '#06b6d4',
|
|
245
|
-
color: 'white',
|
|
246
|
-
fontSize: 12,
|
|
247
|
-
fontWeight: theme.fontWeights.bold,
|
|
248
|
-
fontFamily: theme.fonts.body,
|
|
249
|
-
display: 'flex',
|
|
250
|
-
alignItems: 'center',
|
|
251
|
-
justifyContent: 'center',
|
|
252
|
-
boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
|
|
253
|
-
zIndex: 10,
|
|
254
|
-
opacity: nodeOpacity,
|
|
255
|
-
}, title: directionTitle, children: directionIcon }));
|
|
256
|
-
};
|
|
257
|
-
// Check if this is a boundary node
|
|
258
|
-
const isBoundaryNode = nodeData?.nodeType === 'boundary';
|
|
259
|
-
// Render Status badge (top-left, or top point for diamonds)
|
|
260
|
-
const renderStatusBadge = () => {
|
|
261
|
-
const status = nodeData?.status;
|
|
262
|
-
if (!status)
|
|
263
|
-
return null;
|
|
264
|
-
// Color mapping for status
|
|
265
|
-
const statusColors = {
|
|
266
|
-
draft: '#6b7280',
|
|
267
|
-
approved: '#3b82f6',
|
|
268
|
-
implemented: '#10b981', // Green
|
|
269
|
-
};
|
|
270
|
-
const statusLabels = {
|
|
271
|
-
draft: 'D',
|
|
272
|
-
approved: 'A',
|
|
273
|
-
implemented: 'I',
|
|
274
|
-
};
|
|
275
|
-
const statusTitles = {
|
|
276
|
-
draft: 'Draft - Design phase',
|
|
277
|
-
approved: 'Approved - Ready for implementation',
|
|
278
|
-
implemented: 'Implemented - Code exists',
|
|
279
|
-
};
|
|
280
|
-
const shapeStyles = getBadgeShapeStyles();
|
|
281
|
-
const positionStyles = getBadgePosition('top-left');
|
|
282
|
-
return (_jsx("div", { style: {
|
|
283
|
-
position: 'absolute',
|
|
284
|
-
...positionStyles,
|
|
285
|
-
...shapeStyles,
|
|
286
|
-
// Override transform if shape has rotation but we already have a position transform
|
|
287
|
-
...(typeDefinition.shape === 'diamond' ? { transform: `${positionStyles.transform} rotate(45deg)` } : {}),
|
|
288
|
-
backgroundColor: statusColors[status],
|
|
289
|
-
color: 'white',
|
|
290
|
-
fontSize: theme.fontSizes[0],
|
|
291
|
-
fontWeight: theme.fontWeights.bold,
|
|
292
|
-
fontFamily: theme.fonts.body,
|
|
293
|
-
display: 'flex',
|
|
294
|
-
alignItems: 'center',
|
|
295
|
-
justifyContent: 'center',
|
|
296
|
-
boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
|
|
297
|
-
zIndex: 10,
|
|
298
|
-
opacity: nodeOpacity,
|
|
299
|
-
}, title: statusTitles[status], children: _jsx("span", { style: { transform: shapeStyles.transform ? 'rotate(-45deg)' : undefined }, children: statusLabels[status] }) }));
|
|
300
|
-
};
|
|
301
|
-
// Guard against missing typeDefinition
|
|
302
|
-
if (!typeDefinition) {
|
|
303
|
-
return (_jsx("div", { style: { padding: '10px', border: '2px solid red', borderRadius: '4px' }, children: _jsx("div", { style: { fontSize: '12px', color: 'red' }, children: "Error: Missing node type definition" }) }));
|
|
304
|
-
}
|
|
305
|
-
// Color Contract:
|
|
306
|
-
// - scopeColor: Used as FILL/background color (from library.yaml scopes)
|
|
307
|
-
// - spanColor: Used as BORDER color in workflow context (from .spans.canvas)
|
|
308
|
-
// - For non-event canvases, falls back to legacy behavior (node color or type color)
|
|
309
|
-
// Get colors from node data (injected by GraphRenderer)
|
|
310
|
-
const nodeDataColor = nodeData.color;
|
|
311
|
-
const scopeColor = nodeData.scopeColor;
|
|
312
|
-
const spanColor = nodeData.spanColor;
|
|
313
|
-
// Check node's own states first (from pv.states), then fall back to type definition states
|
|
314
|
-
const nodeDataStates = nodeData.states;
|
|
315
|
-
const stateColor = state && (nodeDataStates?.[state]?.color || typeDefinition.states?.[state]?.color);
|
|
316
|
-
// Fill color priority: state color > node data color > scope color > type definition color > default
|
|
317
|
-
// scopeColor provides background color from the scope definition in library.yaml
|
|
318
|
-
const baseFillColor = nodeDataColor || scopeColor || typeDefinition.color || '#888';
|
|
319
|
-
const fillColor = stateColor || baseFillColor;
|
|
320
|
-
// Stroke/border color priority: explicit stroke > span color (workflow context) > fill color
|
|
321
|
-
// spanColor provides border color in workflow context (from .spans.canvas)
|
|
322
|
-
const nodeDataStroke = nodeData.stroke;
|
|
323
|
-
const baseStrokeColor = nodeDataStroke || spanColor || fillColor;
|
|
324
|
-
// Apply status-based border styling
|
|
325
|
-
const status = nodeData?.status;
|
|
326
|
-
const strokeColor = baseStrokeColor;
|
|
327
|
-
// Use fillColor as the primary "color" for backwards compatibility
|
|
328
|
-
const color = fillColor;
|
|
329
|
-
// Get display name - use pending text if available, otherwise use name from props
|
|
330
|
-
const displayName = nodeProps.pendingText ?? nodeProps.name;
|
|
331
|
-
// Extract identifier based on node type (for display below the label)
|
|
332
|
-
// Supports: event.name, otel.spanPattern, otel.scope, otel.resourceMatch, boundary.direction
|
|
333
|
-
const eventData = nodeData?.event;
|
|
334
|
-
const otelData = nodeData?.otel;
|
|
335
|
-
const boundaryData = nodeData?.boundary;
|
|
336
|
-
// Get identifier from multiple sources
|
|
337
|
-
const getNodeIdentifier = () => {
|
|
338
|
-
// Event name (for otel-event nodes)
|
|
339
|
-
if (eventData?.name)
|
|
340
|
-
return eventData.name;
|
|
341
|
-
// Event ref (for nodes using library events)
|
|
342
|
-
if (nodeData?.eventRef)
|
|
343
|
-
return nodeData.eventRef;
|
|
344
|
-
// Span pattern (for otel-span-convention nodes)
|
|
345
|
-
if (otelData?.spanPattern)
|
|
346
|
-
return otelData.spanPattern;
|
|
347
|
-
// Scope name (for otel-scope nodes)
|
|
348
|
-
if (otelData?.scope)
|
|
349
|
-
return otelData.scope;
|
|
350
|
-
// Resource match (for otel-resource nodes) - show first key:value
|
|
351
|
-
if (otelData?.resourceMatch) {
|
|
352
|
-
const entries = Object.entries(otelData.resourceMatch);
|
|
353
|
-
if (entries.length > 0) {
|
|
354
|
-
const [key, value] = entries[0];
|
|
355
|
-
return `${key}: ${Array.isArray(value) ? value[0] : value}`;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
// Boundary direction (for otel-boundary nodes)
|
|
359
|
-
if (boundaryData?.direction)
|
|
360
|
-
return boundaryData.direction;
|
|
361
|
-
return undefined;
|
|
362
|
-
};
|
|
363
|
-
const identifier = getNodeIdentifier();
|
|
364
|
-
// Show identifier if it differs from display name
|
|
365
|
-
const showIdentifier = identifier && identifier !== displayName;
|
|
366
|
-
// Helper to render text with word break opportunities after dots
|
|
367
|
-
const renderWithDotBreaks = (text) => {
|
|
368
|
-
const parts = text.split('.');
|
|
369
|
-
return parts.map((part, i) => (_jsxs("span", { children: [part, i < parts.length - 1 && (_jsxs(_Fragment, { children: [".", _jsx("wbr", {})] }))] }, i)));
|
|
370
|
-
};
|
|
371
|
-
// Helper component for rendering name with optional identifier
|
|
372
|
-
// Identifiers can come from: event.name, eventRef, otel.spanPattern, otel.scope, otel.resourceMatch, boundary.direction
|
|
373
|
-
const renderNameWithIdentifier = (centered = true) => (_jsxs("div", { style: { textAlign: centered ? 'center' : 'left', wordBreak: 'break-word' }, children: [_jsx("div", { children: displayName }), showIdentifier && (_jsx("div", { style: {
|
|
374
|
-
fontSize: theme.fontSizes[0] * 0.75,
|
|
375
|
-
color: 'rgba(0, 0, 0, 0.5)',
|
|
376
|
-
marginTop: '2px',
|
|
377
|
-
fontFamily: theme.fonts.monospace,
|
|
378
|
-
}, children: renderWithDotBreaks(identifier) }))] }));
|
|
379
|
-
// Icon priority: node data override > state icon (node data states first) > type definition icon
|
|
380
|
-
const icon = nodeData.icon ||
|
|
381
|
-
(state && (nodeDataStates?.[state]?.icon || typeDefinition.states?.[state]?.icon)) ||
|
|
382
|
-
typeDefinition.icon;
|
|
383
|
-
// Get animation class based on type
|
|
384
|
-
const getAnimationClass = () => {
|
|
385
|
-
switch (animationType) {
|
|
386
|
-
case 'pulse':
|
|
387
|
-
return 'node-pulse';
|
|
388
|
-
case 'flash':
|
|
389
|
-
return 'node-flash';
|
|
390
|
-
case 'shake':
|
|
391
|
-
return 'node-shake';
|
|
392
|
-
case 'entry':
|
|
393
|
-
return 'node-entry';
|
|
394
|
-
default:
|
|
395
|
-
return '';
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
const animationClass = getAnimationClass();
|
|
399
|
-
// Check if this is a group node or text node (canvas types that support inline editing)
|
|
400
|
-
const isGroup = nodeData.canvasType === 'group';
|
|
401
|
-
const isTextNode = nodeData.canvasType === 'text';
|
|
402
|
-
const isInlineEditable = (isGroup || isTextNode) && editable;
|
|
403
|
-
// Double-click handler for inline text editing
|
|
404
|
-
const lastClickTimeRef = useRef(0);
|
|
405
|
-
const handleNodeDoubleClick = useCallback((event) => {
|
|
406
|
-
if (!isInlineEditable || !nodeId || !onNodeTextChange)
|
|
407
|
-
return;
|
|
408
|
-
event.stopPropagation();
|
|
409
|
-
event.preventDefault();
|
|
410
|
-
setEditingText(displayName || '');
|
|
411
|
-
setIsEditing(true);
|
|
412
|
-
// Focus the textarea after state update
|
|
413
|
-
setTimeout(() => {
|
|
414
|
-
textareaRef.current?.focus();
|
|
415
|
-
textareaRef.current?.select();
|
|
416
|
-
}, 0);
|
|
417
|
-
}, [isInlineEditable, nodeId, onNodeTextChange, displayName]);
|
|
418
|
-
// Single click tracking for double-click detection
|
|
419
|
-
const handleNodeClick = useCallback((event) => {
|
|
420
|
-
const now = Date.now();
|
|
421
|
-
const timeSinceLastClick = now - lastClickTimeRef.current;
|
|
422
|
-
if (timeSinceLastClick < 300) {
|
|
423
|
-
// Double-click detected
|
|
424
|
-
handleNodeDoubleClick(event);
|
|
425
|
-
}
|
|
426
|
-
lastClickTimeRef.current = now;
|
|
427
|
-
}, [handleNodeDoubleClick]);
|
|
428
|
-
// Save text changes
|
|
429
|
-
const handleSaveText = useCallback(() => {
|
|
430
|
-
if (!nodeId || !onNodeTextChange)
|
|
431
|
-
return;
|
|
432
|
-
if (editingText !== displayName) {
|
|
433
|
-
onNodeTextChange(nodeId, editingText);
|
|
434
|
-
}
|
|
435
|
-
setIsEditing(false);
|
|
436
|
-
}, [nodeId, onNodeTextChange, editingText, displayName]);
|
|
437
|
-
// Cancel text editing
|
|
438
|
-
const handleCancelEdit = useCallback(() => {
|
|
439
|
-
setIsEditing(false);
|
|
440
|
-
setEditingText('');
|
|
441
|
-
}, []);
|
|
442
|
-
// Shape-specific styles
|
|
443
|
-
const getShapeStyles = () => {
|
|
444
|
-
const borderStyle = status === 'draft' ? 'dotted' : status === 'approved' ? 'dashed' : 'solid';
|
|
445
|
-
const baseStyles = {
|
|
446
|
-
padding: '12px 16px',
|
|
447
|
-
backgroundColor: isGroup ? 'rgba(255, 255, 255, 0.7)' : fillColor,
|
|
448
|
-
color: '#000',
|
|
449
|
-
border: `2px ${borderStyle} ${hasViolations ? '#D0021B' : strokeColor}`,
|
|
450
|
-
fontSize: theme.fontSizes[0],
|
|
451
|
-
fontWeight: theme.fontWeights.medium,
|
|
452
|
-
fontFamily: theme.fonts.body,
|
|
453
|
-
// Use 100% width/height to fill the node container (for resizing support)
|
|
454
|
-
width: '100%',
|
|
455
|
-
height: '100%',
|
|
456
|
-
// Use small absolute minimums - typeDefinition.size is the default, not the minimum
|
|
457
|
-
minWidth: 20,
|
|
458
|
-
minHeight: 20,
|
|
459
|
-
display: 'flex',
|
|
460
|
-
flexDirection: 'column',
|
|
461
|
-
alignItems: 'center',
|
|
462
|
-
justifyContent: isGroup ? 'flex-start' : 'center',
|
|
463
|
-
gap: '4px',
|
|
464
|
-
boxShadow: isHighlighted
|
|
465
|
-
? `0 0 0 3px #3b82f6, 0 0 20px rgba(59, 130, 246, 0.5)`
|
|
466
|
-
: selected
|
|
467
|
-
? `0 0 0 2px ${strokeColor}`
|
|
468
|
-
: '0 2px 4px rgba(0,0,0,0.1)',
|
|
469
|
-
opacity: nodeOpacity,
|
|
470
|
-
transition: 'box-shadow 0.2s ease, opacity 0.3s ease',
|
|
471
|
-
animationDuration: animationType ? `${animationDuration}ms` : undefined,
|
|
472
|
-
boxSizing: 'border-box',
|
|
473
|
-
};
|
|
474
|
-
switch (typeDefinition.shape) {
|
|
475
|
-
case 'circle':
|
|
476
|
-
return {
|
|
477
|
-
...baseStyles,
|
|
478
|
-
borderRadius: '50%',
|
|
479
|
-
padding: '8px',
|
|
480
|
-
};
|
|
481
|
-
case 'hexagon':
|
|
482
|
-
// Hexagon uses wrapper approach for proper border - styles returned here are for inner fill
|
|
483
|
-
// The outer border wrapper is rendered separately in the JSX
|
|
484
|
-
return {
|
|
485
|
-
...baseStyles,
|
|
486
|
-
border: 'none',
|
|
487
|
-
clipPath: 'polygon(20% 0%, 80% 0%, 100% 50%, 80% 100%, 20% 100%, 0% 50%)',
|
|
488
|
-
width: '100%',
|
|
489
|
-
height: '100%',
|
|
490
|
-
minWidth: 'unset',
|
|
491
|
-
minHeight: 'unset',
|
|
492
|
-
padding: '8px 20px',
|
|
493
|
-
boxShadow: 'none', // Shadow handled by wrapper
|
|
494
|
-
};
|
|
495
|
-
case 'diamond':
|
|
496
|
-
// Diamond uses wrapper approach for proper border - styles returned here are for inner fill
|
|
497
|
-
// The outer border wrapper is rendered separately in the JSX
|
|
498
|
-
return {
|
|
499
|
-
...baseStyles,
|
|
500
|
-
border: 'none',
|
|
501
|
-
clipPath: 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)',
|
|
502
|
-
width: '100%',
|
|
503
|
-
height: '100%',
|
|
504
|
-
minWidth: 'unset',
|
|
505
|
-
minHeight: 'unset',
|
|
506
|
-
padding: '8px 16px',
|
|
507
|
-
boxShadow: 'none', // Shadow handled by wrapper
|
|
508
|
-
};
|
|
509
|
-
case 'rectangle':
|
|
510
|
-
default:
|
|
511
|
-
return {
|
|
512
|
-
...baseStyles,
|
|
513
|
-
// Boundary nodes get rounded corners, regular rectangles get sharp corners
|
|
514
|
-
borderRadius: isBoundaryNode ? '8px' : '0',
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
|
-
const isDiamond = typeDefinition.shape === 'diamond';
|
|
519
|
-
const isHexagon = typeDefinition.shape === 'hexagon';
|
|
520
|
-
const isCircle = typeDefinition.shape === 'circle';
|
|
521
|
-
// Determine if aspect ratio should be locked (circles should maintain square aspect)
|
|
522
|
-
const keepAspectRatio = isCircle;
|
|
523
|
-
// Minimum dimensions for resizing - use small absolute values, not typeDefinition.size
|
|
524
|
-
const minWidth = 40;
|
|
525
|
-
const minHeight = isCircle ? 40 : 30;
|
|
526
|
-
// Hexagon border wrapper styles (outer shape that acts as border)
|
|
527
|
-
// Hexagon with gentle diagonals
|
|
528
|
-
const hexagonClipPath = 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)';
|
|
529
|
-
// Note: Dotted/dashed borders not supported for hexagon shape (CSS limitation with clip-path)
|
|
530
|
-
// All statuses use 2px solid border for hexagons
|
|
531
|
-
const hexagonBorderWidth = 2;
|
|
532
|
-
const hexagonBorderStyle = isHexagon
|
|
533
|
-
? {
|
|
534
|
-
position: 'relative',
|
|
535
|
-
clipPath: hexagonClipPath,
|
|
536
|
-
backgroundColor: hasViolations ? '#D0021B' : strokeColor,
|
|
537
|
-
// Use 100% to fill container for resizing support
|
|
538
|
-
width: '100%',
|
|
539
|
-
height: '100%',
|
|
540
|
-
// Use small absolute minimums - typeDefinition.size is the default, not the minimum
|
|
541
|
-
minWidth: 20,
|
|
542
|
-
minHeight: 20,
|
|
543
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
|
|
544
|
-
opacity: nodeOpacity,
|
|
545
|
-
transition: 'opacity 0.3s ease',
|
|
546
|
-
boxSizing: 'border-box',
|
|
547
|
-
}
|
|
548
|
-
: {};
|
|
549
|
-
// Hexagon inner fill styles (light color background inset from border)
|
|
550
|
-
const hexagonInnerStyle = isHexagon
|
|
551
|
-
? {
|
|
552
|
-
position: 'absolute',
|
|
553
|
-
top: hexagonBorderWidth,
|
|
554
|
-
left: hexagonBorderWidth,
|
|
555
|
-
right: hexagonBorderWidth,
|
|
556
|
-
bottom: hexagonBorderWidth,
|
|
557
|
-
clipPath: hexagonClipPath,
|
|
558
|
-
backgroundColor: fillColor,
|
|
559
|
-
color: '#000',
|
|
560
|
-
display: 'flex',
|
|
561
|
-
flexDirection: 'column',
|
|
562
|
-
alignItems: 'center',
|
|
563
|
-
justifyContent: 'center',
|
|
564
|
-
fontSize: theme.fontSizes[0],
|
|
565
|
-
fontWeight: theme.fontWeights.medium,
|
|
566
|
-
fontFamily: theme.fonts.body,
|
|
567
|
-
gap: '4px',
|
|
568
|
-
}
|
|
569
|
-
: {};
|
|
570
|
-
// Diamond clip-path
|
|
571
|
-
const diamondClipPath = 'polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)';
|
|
572
|
-
// Note: Dotted/dashed borders not supported for diamond shape (CSS limitation with clip-path)
|
|
573
|
-
// All statuses use 2px solid border for diamonds
|
|
574
|
-
const diamondBorderWidth = 2;
|
|
575
|
-
// Diamond border wrapper styles (outer shape that acts as border)
|
|
576
|
-
const diamondBorderStyle = isDiamond
|
|
577
|
-
? {
|
|
578
|
-
position: 'relative',
|
|
579
|
-
clipPath: diamondClipPath,
|
|
580
|
-
backgroundColor: hasViolations ? '#D0021B' : strokeColor,
|
|
581
|
-
width: '100%',
|
|
582
|
-
height: '100%',
|
|
583
|
-
// Use small absolute minimums - typeDefinition.size is the default, not the minimum
|
|
584
|
-
minWidth: 20,
|
|
585
|
-
minHeight: 20,
|
|
586
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
|
|
587
|
-
opacity: nodeOpacity,
|
|
588
|
-
transition: 'opacity 0.3s ease',
|
|
589
|
-
boxSizing: 'border-box',
|
|
590
|
-
}
|
|
591
|
-
: {};
|
|
592
|
-
// Diamond inner fill styles (light color background inset from border)
|
|
593
|
-
const diamondInnerStyle = isDiamond
|
|
594
|
-
? {
|
|
595
|
-
position: 'absolute',
|
|
596
|
-
top: diamondBorderWidth,
|
|
597
|
-
left: diamondBorderWidth,
|
|
598
|
-
right: diamondBorderWidth,
|
|
599
|
-
bottom: diamondBorderWidth,
|
|
600
|
-
clipPath: diamondClipPath,
|
|
601
|
-
backgroundColor: fillColor,
|
|
602
|
-
color: '#000',
|
|
603
|
-
display: 'flex',
|
|
604
|
-
flexDirection: 'column',
|
|
605
|
-
alignItems: 'center',
|
|
606
|
-
justifyContent: 'center',
|
|
607
|
-
fontSize: theme.fontSizes[0],
|
|
608
|
-
fontWeight: theme.fontWeights.medium,
|
|
609
|
-
fontFamily: theme.fonts.body,
|
|
610
|
-
gap: '4px',
|
|
611
|
-
}
|
|
612
|
-
: {};
|
|
613
|
-
// Handle styles - larger and more visible in edit mode, hidden otherwise
|
|
614
|
-
const baseHandleStyle = editable
|
|
615
|
-
? {
|
|
616
|
-
background: color,
|
|
617
|
-
width: 12,
|
|
618
|
-
height: 12,
|
|
619
|
-
border: '2px solid white',
|
|
620
|
-
boxShadow: '0 0 0 1px ' + color,
|
|
621
|
-
}
|
|
622
|
-
: {
|
|
623
|
-
background: color,
|
|
624
|
-
width: 8,
|
|
625
|
-
height: 8,
|
|
626
|
-
opacity: 0,
|
|
627
|
-
pointerEvents: 'none',
|
|
628
|
-
};
|
|
629
|
-
const getHandleStyle = (_position) => {
|
|
630
|
-
if (!isDiamond && !isHexagon)
|
|
631
|
-
return baseHandleStyle;
|
|
632
|
-
const offsetStyle = { ...baseHandleStyle };
|
|
633
|
-
// Bring handles above the clip-path layers for hexagon and diamond
|
|
634
|
-
if (isHexagon || isDiamond) {
|
|
635
|
-
offsetStyle.zIndex = 10;
|
|
636
|
-
}
|
|
637
|
-
return offsetStyle;
|
|
638
|
-
};
|
|
639
|
-
return (_jsxs(_Fragment, { children: [editable && (_jsx(NodeResizer, { color: strokeColor, isVisible: selected, minWidth: minWidth, minHeight: minHeight, keepAspectRatio: keepAspectRatio, onResizeEnd: handleResizeEnd, handleStyle: {
|
|
640
|
-
width: 8,
|
|
641
|
-
height: 8,
|
|
642
|
-
borderRadius: 2,
|
|
643
|
-
zIndex: 20,
|
|
644
|
-
}, lineStyle: {
|
|
645
|
-
borderWidth: 1,
|
|
646
|
-
zIndex: 20,
|
|
647
|
-
} })), _jsx(Handle, { type: "target", position: Position.Top, id: "top", style: getHandleStyle('top') }), _jsx(Handle, { type: "target", position: Position.Bottom, id: "bottom", style: getHandleStyle('bottom') }), _jsx(Handle, { type: "target", position: Position.Left, id: "left", style: getHandleStyle('left') }), _jsx(Handle, { type: "target", position: Position.Right, id: "right", style: getHandleStyle('right') }), isHexagon ? (_jsxs("div", { ref: nodeRef, style: {
|
|
648
|
-
position: 'relative',
|
|
649
|
-
width: '100%',
|
|
650
|
-
height: '100%',
|
|
651
|
-
boxShadow: isHighlighted
|
|
652
|
-
? `0 0 0 3px #3b82f6, 0 0 20px rgba(59, 130, 246, 0.5)`
|
|
653
|
-
: selected
|
|
654
|
-
? `0 0 0 2px ${strokeColor}`
|
|
655
|
-
: 'none',
|
|
656
|
-
transition: 'box-shadow 0.2s ease',
|
|
657
|
-
}, onMouseDown: handleMouseDown, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [renderStatusBadge(), isBoundaryNode ? renderBoundaryBadge() : (_jsxs(_Fragment, { children: [renderSourcesBadge(), renderReferencesBadge()] })), _jsx("div", { style: hexagonBorderStyle, className: animationClass, children: _jsxs("div", { style: hexagonInnerStyle, children: [icon && (_jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' }, children: resolveIcon(icon, 20) })), renderNameWithIdentifier(), state && (_jsx("div", { style: {
|
|
658
|
-
fontSize: theme.fontSizes[0],
|
|
659
|
-
fontFamily: theme.fonts.body,
|
|
660
|
-
backgroundColor: color,
|
|
661
|
-
color: 'white',
|
|
662
|
-
padding: '2px 6px',
|
|
663
|
-
borderRadius: '4px',
|
|
664
|
-
textAlign: 'center',
|
|
665
|
-
}, children: nodeDataStates?.[state]?.label || typeDefinition.states?.[state]?.label || state })), hasViolations && (_jsx("div", { style: {
|
|
666
|
-
fontSize: theme.fontSizes[0],
|
|
667
|
-
fontFamily: theme.fonts.body,
|
|
668
|
-
color: '#D0021B',
|
|
669
|
-
fontWeight: theme.fontWeights.bold,
|
|
670
|
-
}, children: "\u26A0\uFE0F" }))] }) }), tooltipsEnabled && (_jsx(NodeTooltip, { description: description, otel: otelInfo, sources: sources, references: references, visible: showTooltip, nodeRef: nodeRef }))] })) : isDiamond ? (_jsxs("div", { ref: nodeRef, style: {
|
|
671
|
-
position: 'relative',
|
|
672
|
-
width: '100%',
|
|
673
|
-
height: '100%',
|
|
674
|
-
boxShadow: isHighlighted
|
|
675
|
-
? `0 0 0 3px #3b82f6, 0 0 20px rgba(59, 130, 246, 0.5)`
|
|
676
|
-
: selected
|
|
677
|
-
? `0 0 0 2px ${strokeColor}`
|
|
678
|
-
: 'none',
|
|
679
|
-
transition: 'box-shadow 0.2s ease',
|
|
680
|
-
}, onMouseDown: handleMouseDown, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [renderStatusBadge(), isBoundaryNode ? renderBoundaryBadge() : (_jsxs(_Fragment, { children: [renderSourcesBadge(), renderReferencesBadge()] })), _jsx("div", { style: diamondBorderStyle, className: animationClass, children: _jsxs("div", { style: diamondInnerStyle, children: [icon && (_jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' }, children: resolveIcon(icon, 20) })), renderNameWithIdentifier(), state && (_jsx("div", { style: {
|
|
681
|
-
fontSize: theme.fontSizes[0],
|
|
682
|
-
fontFamily: theme.fonts.body,
|
|
683
|
-
backgroundColor: color,
|
|
684
|
-
color: 'white',
|
|
685
|
-
padding: '2px 6px',
|
|
686
|
-
borderRadius: '4px',
|
|
687
|
-
textAlign: 'center',
|
|
688
|
-
}, children: nodeDataStates?.[state]?.label || typeDefinition.states?.[state]?.label || state })), hasViolations && (_jsx("div", { style: {
|
|
689
|
-
fontSize: theme.fontSizes[0],
|
|
690
|
-
fontFamily: theme.fonts.body,
|
|
691
|
-
color: '#D0021B',
|
|
692
|
-
fontWeight: theme.fontWeights.bold,
|
|
693
|
-
}, children: "\u26A0\uFE0F" }))] }) }), tooltipsEnabled && (_jsx(NodeTooltip, { description: description, otel: otelInfo, sources: sources, references: references, visible: showTooltip, nodeRef: nodeRef }))] })) : (_jsxs("div", { ref: nodeRef, style: { position: 'relative', width: '100%', height: '100%' }, onMouseDown: handleMouseDown, onClick: handleNodeClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [renderStatusBadge(), isBoundaryNode ? renderBoundaryBadge() : (_jsxs(_Fragment, { children: [renderSourcesBadge(), renderReferencesBadge()] })), _jsx("div", { style: getShapeStyles(), className: animationClass, children: _jsxs("div", { style: {
|
|
694
|
-
...(isGroup ? { width: '100%' } : {}),
|
|
695
|
-
}, children: [isGroup ? (_jsxs("div", { style: {
|
|
696
|
-
display: 'flex',
|
|
697
|
-
alignItems: 'center',
|
|
698
|
-
justifyContent: 'center',
|
|
699
|
-
gap: '6px',
|
|
700
|
-
width: '100%',
|
|
701
|
-
}, children: [icon && resolveIcon(icon, 18), renderNameWithIdentifier(false)] })) : (_jsxs(_Fragment, { children: [icon && (_jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center' }, children: resolveIcon(icon, 20) })), renderNameWithIdentifier()] })), state && (_jsx("div", { style: {
|
|
702
|
-
fontSize: theme.fontSizes[0],
|
|
703
|
-
fontFamily: theme.fonts.body,
|
|
704
|
-
backgroundColor: color,
|
|
705
|
-
color: 'white',
|
|
706
|
-
padding: '2px 6px',
|
|
707
|
-
borderRadius: '4px',
|
|
708
|
-
textAlign: 'center',
|
|
709
|
-
}, children: nodeDataStates?.[state]?.label || typeDefinition.states?.[state]?.label || state })), hasViolations && (_jsx("div", { style: {
|
|
710
|
-
fontSize: theme.fontSizes[0],
|
|
711
|
-
fontFamily: theme.fonts.body,
|
|
712
|
-
color: '#D0021B',
|
|
713
|
-
fontWeight: theme.fontWeights.bold,
|
|
714
|
-
}, children: "\u26A0\uFE0F" }))] }) }), isEditing && isInlineEditable && (_jsx("div", { style: {
|
|
715
|
-
position: 'absolute',
|
|
716
|
-
top: 0,
|
|
717
|
-
left: 0,
|
|
718
|
-
width: '100%',
|
|
719
|
-
height: '100%',
|
|
720
|
-
zIndex: 1000,
|
|
721
|
-
display: 'flex',
|
|
722
|
-
flexDirection: 'column',
|
|
723
|
-
padding: theme.space[1],
|
|
724
|
-
boxSizing: 'border-box',
|
|
725
|
-
}, onClick: (e) => e.stopPropagation(), children: _jsx("textarea", { ref: textareaRef, value: editingText, onChange: (e) => setEditingText(e.target.value), placeholder: "Enter text...", style: {
|
|
726
|
-
flex: 1,
|
|
727
|
-
width: '100%',
|
|
728
|
-
padding: theme.space[2],
|
|
729
|
-
fontSize: theme.fontSizes[1],
|
|
730
|
-
fontFamily: theme.fonts.body,
|
|
731
|
-
color: theme.colors.text,
|
|
732
|
-
backgroundColor: theme.colors.background,
|
|
733
|
-
border: `3px solid ${theme.colors.primary}`,
|
|
734
|
-
borderRadius: theme.radii[1],
|
|
735
|
-
outline: 'none',
|
|
736
|
-
resize: 'none',
|
|
737
|
-
boxSizing: 'border-box',
|
|
738
|
-
boxShadow: '0 8px 24px rgba(0, 0, 0, 0.3)',
|
|
739
|
-
}, onKeyDown: (e) => {
|
|
740
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
741
|
-
e.preventDefault();
|
|
742
|
-
handleSaveText();
|
|
743
|
-
}
|
|
744
|
-
else if (e.key === 'Escape') {
|
|
745
|
-
e.preventDefault();
|
|
746
|
-
handleCancelEdit();
|
|
747
|
-
}
|
|
748
|
-
}, onBlur: handleSaveText }) })), tooltipsEnabled && (_jsx(NodeTooltip, { description: description, otel: otelInfo, sources: sources, references: references, visible: showTooltip, nodeRef: nodeRef }))] })), _jsx(Handle, { type: "source", position: Position.Top, id: "top-out", style: getHandleStyle('top') }), _jsx(Handle, { type: "source", position: Position.Bottom, id: "bottom-out", style: getHandleStyle('bottom') }), _jsx(Handle, { type: "source", position: Position.Left, id: "left-out", style: getHandleStyle('left') }), _jsx(Handle, { type: "source", position: Position.Right, id: "right-out", style: getHandleStyle('right') }), _jsx("style", { children: `
|
|
749
|
-
/* Processing pulse - continuous breathing effect */
|
|
750
|
-
.node-pulse {
|
|
751
|
-
animation: node-pulse ease-in-out infinite;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
@keyframes node-pulse {
|
|
755
|
-
0%, 100% {
|
|
756
|
-
transform: scale(1);
|
|
757
|
-
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
758
|
-
}
|
|
759
|
-
50% {
|
|
760
|
-
transform: scale(1.05);
|
|
761
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.2), 0 0 0 4px rgba(59, 130, 246, 0.3);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/* Success flash - brief green glow */
|
|
766
|
-
.node-flash {
|
|
767
|
-
animation: node-flash ease-out forwards;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
@keyframes node-flash {
|
|
771
|
-
0% {
|
|
772
|
-
box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.8);
|
|
773
|
-
background-color: rgba(34, 197, 94, 0.1);
|
|
774
|
-
}
|
|
775
|
-
50% {
|
|
776
|
-
box-shadow: 0 0 0 8px rgba(34, 197, 94, 0);
|
|
777
|
-
background-color: rgba(34, 197, 94, 0.2);
|
|
778
|
-
}
|
|
779
|
-
100% {
|
|
780
|
-
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
781
|
-
background-color: white;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
/* Error shake - vibrate effect */
|
|
786
|
-
.node-shake {
|
|
787
|
-
animation: node-shake ease-in-out;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
@keyframes node-shake {
|
|
791
|
-
0%, 100% {
|
|
792
|
-
transform: translateX(0);
|
|
793
|
-
}
|
|
794
|
-
10%, 30%, 50%, 70%, 90% {
|
|
795
|
-
transform: translateX(-4px);
|
|
796
|
-
}
|
|
797
|
-
20%, 40%, 60%, 80% {
|
|
798
|
-
transform: translateX(4px);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/* Entry animation - scale up and fade in */
|
|
803
|
-
.node-entry {
|
|
804
|
-
animation: node-entry ease-out forwards;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
@keyframes node-entry {
|
|
808
|
-
0% {
|
|
809
|
-
opacity: 0;
|
|
810
|
-
transform: scale(0.8);
|
|
811
|
-
}
|
|
812
|
-
100% {
|
|
813
|
-
opacity: 1;
|
|
814
|
-
transform: scale(1);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
` })] }));
|
|
819
|
-
};
|
|
820
|
-
//# sourceMappingURL=CustomNode.js.map
|