@flowuent-org/diagramming-core 1.1.8 → 1.2.0
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 +116 -116
- package/packages/diagrams/src/index.ts +1 -0
- package/packages/diagrams/src/lib/atoms/ConnectionPoints.tsx +149 -0
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +794 -650
- package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +606 -449
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +831 -687
- package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +420 -275
- package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +1118 -974
- package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +509 -344
- package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -0
- package/packages/diagrams/src/lib/components/automation/NodeActionButtons.tsx +146 -0
- package/packages/diagrams/src/lib/components/automation/index.ts +20 -11
- package/packages/diagrams/src/lib/molecules/SideHandles.tsx +177 -12
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge-generator.tsx +10 -5
- package/packages/diagrams/src/lib/styles.css +53 -0
- package/packages/diagrams/src/lib/templates/DiagramContainer.tsx +59 -0
- package/packages/diagrams/src/lib/templates/Diagramming.tsx +246 -204
- package/packages/diagrams/src/lib/types/edge-types.ts +17 -0
- package/packages/diagrams/src/lib/utils/generateEdgesFromNodeOrder.ts +113 -0
- package/packages/diagrams/src/lib/utils/nodeAIAssistantConfig.ts +54 -0
|
@@ -7,24 +7,93 @@ import { useSelectedNode } from '../contexts/DiagramProvider';
|
|
|
7
7
|
// Define the props type for the component
|
|
8
8
|
interface SideHandlesProps {
|
|
9
9
|
className?: string;
|
|
10
|
+
/** Show all handles regardless of selection state */
|
|
11
|
+
alwaysShow?: boolean;
|
|
12
|
+
/** Which positions to show handles on */
|
|
13
|
+
positions?: ('top' | 'bottom' | 'left' | 'right')[];
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
// Connection point handle styles
|
|
17
|
+
const handleBaseStyle: React.CSSProperties = {
|
|
18
|
+
width: '14px',
|
|
19
|
+
height: '14px',
|
|
20
|
+
borderRadius: '50%',
|
|
21
|
+
border: '3px solid #10B981',
|
|
22
|
+
backgroundColor: '#1a1a2e',
|
|
23
|
+
transition: 'all 0.2s ease-in-out',
|
|
24
|
+
cursor: 'crosshair',
|
|
25
|
+
zIndex: 10,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Hidden handle style for the duplicate (allows bidirectional but only shows one visual handle)
|
|
29
|
+
const hiddenHandleStyle: React.CSSProperties = {
|
|
30
|
+
...handleBaseStyle,
|
|
31
|
+
opacity: 0,
|
|
32
|
+
pointerEvents: 'all',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handleHoverStyle = `
|
|
36
|
+
.connection-handle:hover {
|
|
37
|
+
transform: scale(1.3);
|
|
38
|
+
background-color: #10B981 !important;
|
|
39
|
+
box-shadow: 0 0 12px rgba(16, 185, 129, 0.6);
|
|
40
|
+
}
|
|
41
|
+
.connection-handle:active {
|
|
42
|
+
transform: scale(1.1);
|
|
43
|
+
background-color: #059669 !important;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
|
|
12
47
|
export const SideHandles: React.FC<SideHandlesProps> = React.memo(
|
|
13
|
-
({ className }) => {
|
|
48
|
+
({ className, alwaysShow = false, positions = ['top', 'bottom', 'left', 'right'] }) => {
|
|
14
49
|
const sideHandles = useNodeSideHandles();
|
|
15
50
|
const nodeId = useNodeId();
|
|
16
51
|
const selectedNode = useSelectedNode();
|
|
52
|
+
|
|
53
|
+
const isSelected = selectedNode === nodeId;
|
|
54
|
+
const shouldShow = alwaysShow || isSelected;
|
|
55
|
+
|
|
56
|
+
// Inject hover styles
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
const styleId = 'connection-handle-styles';
|
|
59
|
+
if (!document.getElementById(styleId)) {
|
|
60
|
+
const styleSheet = document.createElement('style');
|
|
61
|
+
styleSheet.id = styleId;
|
|
62
|
+
styleSheet.textContent = handleHoverStyle;
|
|
63
|
+
document.head.appendChild(styleSheet);
|
|
64
|
+
}
|
|
65
|
+
}, []);
|
|
17
66
|
|
|
18
67
|
if (sideHandles) {
|
|
19
68
|
return (
|
|
20
69
|
<div>
|
|
70
|
+
{/* Left - Bidirectional */}
|
|
21
71
|
<Handle
|
|
22
72
|
type="source"
|
|
73
|
+
id={`${nodeId}-left-source`}
|
|
74
|
+
position={Position.Left}
|
|
75
|
+
className="connection-handle"
|
|
76
|
+
style={handleBaseStyle}
|
|
77
|
+
/>
|
|
78
|
+
<Handle
|
|
79
|
+
type="target"
|
|
80
|
+
id={`${nodeId}-left-target`}
|
|
23
81
|
position={Position.Left}
|
|
82
|
+
style={hiddenHandleStyle}
|
|
24
83
|
/>
|
|
84
|
+
{/* Right - Bidirectional */}
|
|
25
85
|
<Handle
|
|
26
86
|
type="source"
|
|
87
|
+
id={`${nodeId}-right-source`}
|
|
88
|
+
position={Position.Right}
|
|
89
|
+
className="connection-handle"
|
|
90
|
+
style={handleBaseStyle}
|
|
91
|
+
/>
|
|
92
|
+
<Handle
|
|
93
|
+
type="target"
|
|
94
|
+
id={`${nodeId}-right-target`}
|
|
27
95
|
position={Position.Right}
|
|
96
|
+
style={hiddenHandleStyle}
|
|
28
97
|
/>
|
|
29
98
|
</div>
|
|
30
99
|
);
|
|
@@ -32,18 +101,114 @@ export const SideHandles: React.FC<SideHandlesProps> = React.memo(
|
|
|
32
101
|
|
|
33
102
|
return (
|
|
34
103
|
<Box
|
|
35
|
-
|
|
104
|
+
sx={{
|
|
105
|
+
opacity: shouldShow ? 1 : 0,
|
|
106
|
+
transition: 'opacity 0.2s ease-in-out',
|
|
107
|
+
pointerEvents: shouldShow ? 'auto' : 'none',
|
|
108
|
+
'& .react-flow__handle': {
|
|
109
|
+
visibility: shouldShow ? 'visible' : 'hidden',
|
|
110
|
+
}
|
|
111
|
+
}}
|
|
36
112
|
>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
113
|
+
{/* Top Handle - Bidirectional (source + target) */}
|
|
114
|
+
{positions.includes('top') && (
|
|
115
|
+
<>
|
|
116
|
+
<Handle
|
|
117
|
+
type="source"
|
|
118
|
+
id={`${nodeId}-top-source`}
|
|
119
|
+
position={Position.Top}
|
|
120
|
+
className="connection-handle"
|
|
121
|
+
style={{
|
|
122
|
+
...handleBaseStyle,
|
|
123
|
+
top: '-8px',
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
<Handle
|
|
127
|
+
type="target"
|
|
128
|
+
id={`${nodeId}-top-target`}
|
|
129
|
+
position={Position.Top}
|
|
130
|
+
style={{
|
|
131
|
+
...hiddenHandleStyle,
|
|
132
|
+
top: '-8px',
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
</>
|
|
136
|
+
)}
|
|
137
|
+
|
|
138
|
+
{/* Bottom Handle - Bidirectional (source + target) */}
|
|
139
|
+
{positions.includes('bottom') && (
|
|
140
|
+
<>
|
|
141
|
+
<Handle
|
|
142
|
+
type="source"
|
|
143
|
+
id={`${nodeId}-bottom-source`}
|
|
144
|
+
position={Position.Bottom}
|
|
145
|
+
className="connection-handle"
|
|
146
|
+
style={{
|
|
147
|
+
...handleBaseStyle,
|
|
148
|
+
bottom: '-8px',
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
<Handle
|
|
152
|
+
type="target"
|
|
153
|
+
id={`${nodeId}-bottom-target`}
|
|
154
|
+
position={Position.Bottom}
|
|
155
|
+
style={{
|
|
156
|
+
...hiddenHandleStyle,
|
|
157
|
+
bottom: '-8px',
|
|
158
|
+
}}
|
|
159
|
+
/>
|
|
160
|
+
</>
|
|
161
|
+
)}
|
|
162
|
+
|
|
163
|
+
{/* Left Handle - Bidirectional (source + target) */}
|
|
164
|
+
{positions.includes('left') && (
|
|
165
|
+
<>
|
|
166
|
+
<Handle
|
|
167
|
+
type="source"
|
|
168
|
+
id={`${nodeId}-left-source`}
|
|
169
|
+
position={Position.Left}
|
|
170
|
+
className="connection-handle"
|
|
171
|
+
style={{
|
|
172
|
+
...handleBaseStyle,
|
|
173
|
+
left: '-8px',
|
|
174
|
+
}}
|
|
175
|
+
/>
|
|
176
|
+
<Handle
|
|
177
|
+
type="target"
|
|
178
|
+
id={`${nodeId}-left-target`}
|
|
179
|
+
position={Position.Left}
|
|
180
|
+
style={{
|
|
181
|
+
...hiddenHandleStyle,
|
|
182
|
+
left: '-8px',
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
</>
|
|
186
|
+
)}
|
|
187
|
+
|
|
188
|
+
{/* Right Handle - Bidirectional (source + target) */}
|
|
189
|
+
{positions.includes('right') && (
|
|
190
|
+
<>
|
|
191
|
+
<Handle
|
|
192
|
+
type="source"
|
|
193
|
+
id={`${nodeId}-right-source`}
|
|
194
|
+
position={Position.Right}
|
|
195
|
+
className="connection-handle"
|
|
196
|
+
style={{
|
|
197
|
+
...handleBaseStyle,
|
|
198
|
+
right: '-8px',
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
<Handle
|
|
202
|
+
type="target"
|
|
203
|
+
id={`${nodeId}-right-target`}
|
|
204
|
+
position={Position.Right}
|
|
205
|
+
style={{
|
|
206
|
+
...hiddenHandleStyle,
|
|
207
|
+
right: '-8px',
|
|
208
|
+
}}
|
|
209
|
+
/>
|
|
210
|
+
</>
|
|
211
|
+
)}
|
|
47
212
|
</Box>
|
|
48
213
|
);
|
|
49
214
|
},
|
|
@@ -94,21 +94,26 @@ export const CustomEdgeGenerator = (type: EdgeTypes = EdgeTypes.Default) => {
|
|
|
94
94
|
onDoubleClick={createBendPoint}
|
|
95
95
|
style={{
|
|
96
96
|
...style,
|
|
97
|
-
strokeWidth: (Number(style?.strokeWidth) ||
|
|
98
|
-
strokeOpacity: selectedEdgeId === id ? 0.
|
|
97
|
+
strokeWidth: (Number(style?.strokeWidth) || 2) * 4,
|
|
98
|
+
strokeOpacity: selectedEdgeId === id ? 0.2 : 0.05,
|
|
99
|
+
stroke: style?.stroke || '#10B981',
|
|
99
100
|
}}
|
|
100
101
|
fill="none"
|
|
101
102
|
/>
|
|
102
103
|
|
|
103
|
-
{/* Main path for the edge */}
|
|
104
|
+
{/* Main path for the edge - always visible */}
|
|
104
105
|
<path
|
|
105
106
|
id={id}
|
|
106
107
|
d={edgePath}
|
|
107
108
|
onClick={() => isErDiagram && toggleModal(setSelectedEdgeId)}
|
|
108
109
|
onDoubleClick={createBendPoint}
|
|
109
|
-
style={{
|
|
110
|
+
style={{
|
|
111
|
+
...style,
|
|
112
|
+
stroke: style?.stroke || '#10B981',
|
|
113
|
+
strokeWidth: style?.strokeWidth || 2,
|
|
114
|
+
}}
|
|
110
115
|
markerStart={isErDiagram ? `url(#${id}-marker-start)` : markerStart}
|
|
111
|
-
markerEnd={isErDiagram ? `url(#${id}-marker-end)` : markerEnd}
|
|
116
|
+
markerEnd={isErDiagram ? `url(#${id}-marker-end)` : (markerEnd || 'url(#arrow)')}
|
|
112
117
|
fill="none"
|
|
113
118
|
/>
|
|
114
119
|
</g>
|
|
@@ -1,3 +1,56 @@
|
|
|
1
1
|
.react-flow__edges {
|
|
2
2
|
z-index: 20 !important;
|
|
3
3
|
}
|
|
4
|
+
|
|
5
|
+
/* Connection Handle Styles */
|
|
6
|
+
.react-flow__handle {
|
|
7
|
+
transition: all 0.2s ease-in-out;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.react-flow__handle.connection-handle {
|
|
11
|
+
width: 14px;
|
|
12
|
+
height: 14px;
|
|
13
|
+
border-radius: 50%;
|
|
14
|
+
border: 3px solid #10B981;
|
|
15
|
+
background-color: #1a1a2e;
|
|
16
|
+
cursor: crosshair;
|
|
17
|
+
z-index: 10;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.react-flow__handle.connection-handle:hover {
|
|
21
|
+
transform: scale(1.3);
|
|
22
|
+
background-color: #10B981;
|
|
23
|
+
box-shadow: 0 0 12px rgba(16, 185, 129, 0.6);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.react-flow__handle.connection-handle:active,
|
|
27
|
+
.react-flow__handle.connection-handle.connecting {
|
|
28
|
+
transform: scale(1.1);
|
|
29
|
+
background-color: #059669;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Pulse animation for selected node handles */
|
|
33
|
+
@keyframes handle-pulse {
|
|
34
|
+
0%, 100% {
|
|
35
|
+
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
|
|
36
|
+
}
|
|
37
|
+
50% {
|
|
38
|
+
box-shadow: 0 0 0 6px rgba(16, 185, 129, 0);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.react-flow__node.selected .connection-handle {
|
|
43
|
+
animation: handle-pulse 1.5s ease-in-out infinite;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Connection line styles when drawing */
|
|
47
|
+
.react-flow__connectionline {
|
|
48
|
+
stroke: #10B981;
|
|
49
|
+
stroke-width: 2;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Valid connection target highlight */
|
|
53
|
+
.react-flow__handle.connectionindicator {
|
|
54
|
+
background-color: #10B981;
|
|
55
|
+
border-color: #fff;
|
|
56
|
+
}
|
|
@@ -8,9 +8,68 @@ interface DiagramContainerProps
|
|
|
8
8
|
showAutomationExecutionPanel?: boolean;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
// Default arrow marker definitions for edges
|
|
12
|
+
const EdgeMarkerDefinitions = () => (
|
|
13
|
+
<svg style={{ position: 'absolute', width: 0, height: 0 }}>
|
|
14
|
+
<defs>
|
|
15
|
+
{/* Arrow marker - Green */}
|
|
16
|
+
<marker
|
|
17
|
+
id="arrow"
|
|
18
|
+
viewBox="0 0 10 10"
|
|
19
|
+
refX="8"
|
|
20
|
+
refY="5"
|
|
21
|
+
markerWidth="6"
|
|
22
|
+
markerHeight="6"
|
|
23
|
+
orient="auto-start-reverse"
|
|
24
|
+
>
|
|
25
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#10B981" />
|
|
26
|
+
</marker>
|
|
27
|
+
|
|
28
|
+
{/* Arrow marker - Blue */}
|
|
29
|
+
<marker
|
|
30
|
+
id="arrow-blue"
|
|
31
|
+
viewBox="0 0 10 10"
|
|
32
|
+
refX="8"
|
|
33
|
+
refY="5"
|
|
34
|
+
markerWidth="6"
|
|
35
|
+
markerHeight="6"
|
|
36
|
+
orient="auto-start-reverse"
|
|
37
|
+
>
|
|
38
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4858E9" />
|
|
39
|
+
</marker>
|
|
40
|
+
|
|
41
|
+
{/* Arrow marker - White */}
|
|
42
|
+
<marker
|
|
43
|
+
id="arrow-white"
|
|
44
|
+
viewBox="0 0 10 10"
|
|
45
|
+
refX="8"
|
|
46
|
+
refY="5"
|
|
47
|
+
markerWidth="6"
|
|
48
|
+
markerHeight="6"
|
|
49
|
+
orient="auto-start-reverse"
|
|
50
|
+
>
|
|
51
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ffffff" />
|
|
52
|
+
</marker>
|
|
53
|
+
|
|
54
|
+
{/* Circle marker */}
|
|
55
|
+
<marker
|
|
56
|
+
id="circle"
|
|
57
|
+
viewBox="0 0 10 10"
|
|
58
|
+
refX="5"
|
|
59
|
+
refY="5"
|
|
60
|
+
markerWidth="5"
|
|
61
|
+
markerHeight="5"
|
|
62
|
+
>
|
|
63
|
+
<circle cx="5" cy="5" r="4" fill="#10B981" />
|
|
64
|
+
</marker>
|
|
65
|
+
</defs>
|
|
66
|
+
</svg>
|
|
67
|
+
);
|
|
68
|
+
|
|
11
69
|
export const DiagramContainer: React.FC<DiagramContainerProps> = (props) => {
|
|
12
70
|
return (
|
|
13
71
|
<ReactFlowProvider>
|
|
72
|
+
<EdgeMarkerDefinitions />
|
|
14
73
|
<DiagramContent {...props} />
|
|
15
74
|
</ReactFlowProvider>
|
|
16
75
|
);
|