@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.
Files changed (20) hide show
  1. package/package.json +116 -116
  2. package/packages/diagrams/src/index.ts +1 -0
  3. package/packages/diagrams/src/lib/atoms/ConnectionPoints.tsx +149 -0
  4. package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +794 -650
  5. package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +606 -449
  6. package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +831 -687
  7. package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +420 -275
  8. package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +1118 -974
  9. package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +509 -344
  10. package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -0
  11. package/packages/diagrams/src/lib/components/automation/NodeActionButtons.tsx +146 -0
  12. package/packages/diagrams/src/lib/components/automation/index.ts +20 -11
  13. package/packages/diagrams/src/lib/molecules/SideHandles.tsx +177 -12
  14. package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge-generator.tsx +10 -5
  15. package/packages/diagrams/src/lib/styles.css +53 -0
  16. package/packages/diagrams/src/lib/templates/DiagramContainer.tsx +59 -0
  17. package/packages/diagrams/src/lib/templates/Diagramming.tsx +246 -204
  18. package/packages/diagrams/src/lib/types/edge-types.ts +17 -0
  19. package/packages/diagrams/src/lib/utils/generateEdgesFromNodeOrder.ts +113 -0
  20. 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
- display={selectedNode ? undefined : 'none'}
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
- <Handle
38
- type="source"
39
- id={`${nodeId}-bottom`}
40
- position={Position.Bottom}
41
- />
42
- <Handle
43
- type="target"
44
- id={`${nodeId}-top`}
45
- position={Position.Top}
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) || 1) * 4,
98
- strokeOpacity: selectedEdgeId === id ? 0.1 : 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={{ ...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
  );