@flowuent-org/diagramming-core 1.2.1 → 1.2.2

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/apps/diagramming/src/AutomationDiagramData.ts +65 -1
  2. package/package.json +1 -1
  3. package/packages/diagrams/src/lib/components/CanvasSearchBar.tsx +281 -0
  4. package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +796 -788
  5. package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +608 -600
  6. package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +833 -825
  7. package/packages/diagrams/src/lib/components/automation/AutomationNavigationNode.tsx +584 -0
  8. package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +422 -414
  9. package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +1120 -1112
  10. package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +511 -503
  11. package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -0
  12. package/packages/diagrams/src/lib/components/automation/NodeActionButtons.tsx +146 -145
  13. package/packages/diagrams/src/lib/components/automation/index.ts +21 -12
  14. package/packages/diagrams/src/lib/contexts/SearchContext.tsx +78 -0
  15. package/packages/diagrams/src/lib/templates/DiagramContainer.tsx +79 -76
  16. package/packages/diagrams/src/lib/templates/DiagramContent.tsx +276 -61
  17. package/packages/diagrams/src/lib/types/automation-node-data-types.ts +22 -2
  18. package/packages/diagrams/src/lib/types/node-types.ts +2 -0
  19. package/packages/diagrams/src/lib/utils/highlightText.tsx +93 -0
  20. package/packages/diagrams/src/lib/utils/nodeAIAssistantConfig.ts +54 -0
@@ -1,145 +1,146 @@
1
- import React from 'react';
2
- import { Box, IconButton, Tooltip } from '@mui/material';
3
- import {
4
- IconLayoutGrid,
5
- IconMessage,
6
- IconPlus,
7
- IconCopy,
8
- IconTrash,
9
- } from '@tabler/icons-react';
10
-
11
- interface NodeActionButtonsProps {
12
- selected?: boolean;
13
- onLayout?: () => void;
14
- onAddNote?: () => void;
15
- onAddToGroup?: () => void;
16
- onDuplicate?: () => void;
17
- onDelete?: () => void;
18
- }
19
-
20
- export const NodeActionButtons: React.FC<NodeActionButtonsProps> = ({
21
- selected,
22
- onLayout,
23
- onAddNote,
24
- onAddToGroup,
25
- onDuplicate,
26
- onDelete,
27
- }) => {
28
- if (!selected) return null;
29
-
30
- return (
31
- <Box
32
- sx={{
33
- position: 'absolute',
34
- left: '100%',
35
- top: '50%',
36
- transform: 'translateY(-50%)',
37
- marginLeft: '12px',
38
- display: 'flex',
39
- flexDirection: 'column',
40
- gap: 0.5,
41
- backgroundColor: 'rgba(15, 15, 35, 0.95)',
42
- borderRadius: '12px',
43
- border: '1px solid rgba(255, 255, 255, 0.1)',
44
- p: 0.5,
45
- zIndex: 1000,
46
- boxShadow: '0 4px 20px rgba(0, 0, 0, 0.3)',
47
- }}
48
- onClick={(e) => e.stopPropagation()}
49
- >
50
- <Tooltip title="Layout" placement="right">
51
- <IconButton
52
- size="small"
53
- onClick={(e) => {
54
- e.stopPropagation();
55
- onLayout?.();
56
- }}
57
- sx={{
58
- color: 'rgba(255, 255, 255, 0.6)',
59
- '&:hover': {
60
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
61
- color: '#fff',
62
- },
63
- }}
64
- >
65
- <IconLayoutGrid size={18} />
66
- </IconButton>
67
- </Tooltip>
68
- <Tooltip title="Add Note" placement="right">
69
- <IconButton
70
- size="small"
71
- onClick={(e) => {
72
- e.stopPropagation();
73
- onAddNote?.();
74
- }}
75
- sx={{
76
- color: 'rgba(255, 255, 255, 0.6)',
77
- '&:hover': {
78
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
79
- color: '#fff',
80
- },
81
- }}
82
- >
83
- <IconMessage size={18} />
84
- </IconButton>
85
- </Tooltip>
86
- <Tooltip title="Add to Group" placement="right">
87
- <IconButton
88
- size="small"
89
- onClick={(e) => {
90
- e.stopPropagation();
91
- onAddToGroup?.();
92
- }}
93
- sx={{
94
- color: 'rgba(255, 255, 255, 0.6)',
95
- '&:hover': {
96
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
97
- color: '#fff',
98
- },
99
- }}
100
- >
101
- <IconPlus size={18} />
102
- </IconButton>
103
- </Tooltip>
104
- <Tooltip title="Duplicate" placement="right">
105
- <IconButton
106
- size="small"
107
- onClick={(e) => {
108
- e.stopPropagation();
109
- onDuplicate?.();
110
- }}
111
- sx={{
112
- color: 'rgba(255, 255, 255, 0.6)',
113
- '&:hover': {
114
- backgroundColor: 'rgba(255, 255, 255, 0.1)',
115
- color: '#fff',
116
- },
117
- }}
118
- >
119
- <IconCopy size={18} />
120
- </IconButton>
121
- </Tooltip>
122
- <Tooltip title="Delete" placement="right">
123
- <IconButton
124
- size="small"
125
- onClick={(e) => {
126
- e.stopPropagation();
127
- onDelete?.();
128
- }}
129
- sx={{
130
- color: 'rgba(255, 255, 255, 0.6)',
131
- '&:hover': {
132
- backgroundColor: 'rgba(239, 68, 68, 0.2)',
133
- color: '#EF4444',
134
- },
135
- }}
136
- >
137
- <IconTrash size={18} />
138
- </IconButton>
139
- </Tooltip>
140
- </Box>
141
- );
142
- };
143
-
144
- export default NodeActionButtons;
145
-
1
+ import React from 'react';
2
+ import { Box, IconButton, Tooltip } from '@mui/material';
3
+ import {
4
+ IconLayoutGrid,
5
+ IconMessage,
6
+ IconPlus,
7
+ IconCopy,
8
+ IconTrash,
9
+ } from '@tabler/icons-react';
10
+
11
+ interface NodeActionButtonsProps {
12
+ selected?: boolean;
13
+ onLayout?: () => void;
14
+ onOpenAIAssistant?: (buttonElement: HTMLElement) => void;
15
+ onAddToGroup?: () => void;
16
+ onDuplicate?: () => void;
17
+ onDelete?: () => void;
18
+ }
19
+
20
+ export const NodeActionButtons: React.FC<NodeActionButtonsProps> = ({
21
+ selected,
22
+ onLayout,
23
+ onOpenAIAssistant,
24
+ onAddToGroup,
25
+ onDuplicate,
26
+ onDelete,
27
+ }) => {
28
+ if (!selected) return null;
29
+
30
+ return (
31
+ <Box
32
+ sx={{
33
+ position: 'absolute',
34
+ left: '100%',
35
+ top: '50%',
36
+ transform: 'translateY(-50%)',
37
+ marginLeft: '12px',
38
+ display: 'flex',
39
+ flexDirection: 'column',
40
+ gap: 0.5,
41
+ backgroundColor: 'rgba(15, 15, 35, 0.95)',
42
+ borderRadius: '12px',
43
+ border: '1px solid rgba(255, 255, 255, 0.1)',
44
+ p: 0.5,
45
+ zIndex: 1000,
46
+ boxShadow: '0 4px 20px rgba(0, 0, 0, 0.3)',
47
+ }}
48
+ onClick={(e) => e.stopPropagation()}
49
+ >
50
+ <Tooltip title="Layout" placement="right">
51
+ <IconButton
52
+ size="small"
53
+ onClick={(e) => {
54
+ e.stopPropagation();
55
+ onLayout?.();
56
+ }}
57
+ sx={{
58
+ color: 'rgba(255, 255, 255, 0.6)',
59
+ '&:hover': {
60
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
61
+ color: '#fff',
62
+ },
63
+ }}
64
+ >
65
+ <IconLayoutGrid size={18} />
66
+ </IconButton>
67
+ </Tooltip>
68
+ <Tooltip title="Node AI Assistant" placement="right">
69
+ <IconButton
70
+ size="small"
71
+ data-node-ai-assistant-button
72
+ onClick={(e) => {
73
+ e.stopPropagation();
74
+ onOpenAIAssistant?.(e.currentTarget);
75
+ }}
76
+ sx={{
77
+ color: 'rgba(255, 255, 255, 0.6)',
78
+ '&:hover': {
79
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
80
+ color: '#fff',
81
+ },
82
+ }}
83
+ >
84
+ <IconMessage size={18} />
85
+ </IconButton>
86
+ </Tooltip>
87
+ <Tooltip title="Add to Group" placement="right">
88
+ <IconButton
89
+ size="small"
90
+ onClick={(e) => {
91
+ e.stopPropagation();
92
+ onAddToGroup?.();
93
+ }}
94
+ sx={{
95
+ color: 'rgba(255, 255, 255, 0.6)',
96
+ '&:hover': {
97
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
98
+ color: '#fff',
99
+ },
100
+ }}
101
+ >
102
+ <IconPlus size={18} />
103
+ </IconButton>
104
+ </Tooltip>
105
+ <Tooltip title="Duplicate" placement="right">
106
+ <IconButton
107
+ size="small"
108
+ onClick={(e) => {
109
+ e.stopPropagation();
110
+ onDuplicate?.();
111
+ }}
112
+ sx={{
113
+ color: 'rgba(255, 255, 255, 0.6)',
114
+ '&:hover': {
115
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
116
+ color: '#fff',
117
+ },
118
+ }}
119
+ >
120
+ <IconCopy size={18} />
121
+ </IconButton>
122
+ </Tooltip>
123
+ <Tooltip title="Delete" placement="right">
124
+ <IconButton
125
+ size="small"
126
+ onClick={(e) => {
127
+ e.stopPropagation();
128
+ onDelete?.();
129
+ }}
130
+ sx={{
131
+ color: 'rgba(255, 255, 255, 0.6)',
132
+ '&:hover': {
133
+ backgroundColor: 'rgba(239, 68, 68, 0.2)',
134
+ color: '#EF4444',
135
+ },
136
+ }}
137
+ >
138
+ <IconTrash size={18} />
139
+ </IconButton>
140
+ </Tooltip>
141
+ </Box>
142
+ );
143
+ };
144
+
145
+ export default NodeActionButtons;
146
+
@@ -1,12 +1,21 @@
1
- export { AutomationStartNode } from './AutomationStartNode';
2
- export { AutomationApiNode } from './AutomationApiNode';
3
- export { AutomationFormattingNode } from './AutomationFormattingNode';
4
- export { AutomationSheetsNode } from './AutomationSheetsNode';
5
- export { AutomationEndNode } from './AutomationEndNode';
6
- export { AutomationNoteNode } from './AutomationNoteNode';
7
- export { AutomationExecutionPanel } from './AutomationExecutionPanel';
8
- export { AutomationAISuggestionNode } from './AutomationAISuggestionNode';
9
- export { AISuggestionsModal, showAISuggestionsModal } from './AISuggestionsModal';
10
- export { AISuggestionsPanel } from './AISuggestionsPanel';
11
- export { NodeActionButtons } from './NodeActionButtons';
12
- export type { AISuggestion } from './AISuggestionsModal';
1
+ export { AutomationStartNode } from './AutomationStartNode';
2
+ export { AutomationApiNode } from './AutomationApiNode';
3
+ export { AutomationFormattingNode } from './AutomationFormattingNode';
4
+ export { AutomationSheetsNode } from './AutomationSheetsNode';
5
+ export { AutomationEndNode } from './AutomationEndNode';
6
+ export { AutomationNoteNode } from './AutomationNoteNode';
7
+ export { AutomationNavigationNode } from './AutomationNavigationNode';
8
+ export { AutomationExecutionPanel } from './AutomationExecutionPanel';
9
+ export { AutomationAISuggestionNode } from './AutomationAISuggestionNode';
10
+ export { AISuggestionsModal, showAISuggestionsModal } from './AISuggestionsModal';
11
+ export { AISuggestionsPanel } from './AISuggestionsPanel';
12
+ export { NodeActionButtons } from './NodeActionButtons';
13
+ export { NodeAIAssistantPopup, showNodeAIAssistantPopup } from './NodeAIAssistantPopup';
14
+ export type { AISuggestion } from './AISuggestionsModal';
15
+ export {
16
+ setNodeAIAssistantEndpoint,
17
+ setNodeAIAssistantHeaders,
18
+ getNodeAIAssistantEndpoint,
19
+ getNodeAIAssistantHeaders,
20
+ configureNodeAIAssistant,
21
+ } from '../../utils/nodeAIAssistantConfig';
@@ -0,0 +1,78 @@
1
+ import React, { createContext, useContext, useState, ReactNode } from 'react';
2
+
3
+ interface SearchContextType {
4
+ searchQuery: string;
5
+ setSearchQuery: (query: string) => void;
6
+ highlightText: (text: string) => React.ReactNode;
7
+ }
8
+
9
+ const SearchContext = createContext<SearchContextType | undefined>(undefined);
10
+
11
+ export const SearchProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
12
+ const [searchQuery, setSearchQuery] = useState('');
13
+
14
+ const highlightText = (text: string): React.ReactNode => {
15
+ if (!searchQuery.trim() || !text) {
16
+ return text;
17
+ }
18
+
19
+ const searchLower = searchQuery.toLowerCase();
20
+ const textLower = String(text).toLowerCase();
21
+ const parts: React.ReactNode[] = [];
22
+ let lastIndex = 0;
23
+ let index = textLower.indexOf(searchLower, lastIndex);
24
+
25
+ // Highlight all occurrences
26
+ while (index !== -1) {
27
+ // Add text before match
28
+ if (index > lastIndex) {
29
+ parts.push(String(text).substring(lastIndex, index));
30
+ }
31
+
32
+ // Add highlighted match
33
+ parts.push(
34
+ <mark
35
+ key={index}
36
+ style={{
37
+ backgroundColor: '#FFD700',
38
+ color: '#000',
39
+ padding: '2px 4px',
40
+ borderRadius: '3px',
41
+ fontWeight: 'bold',
42
+ }}
43
+ >
44
+ {String(text).substring(index, index + searchQuery.length)}
45
+ </mark>
46
+ );
47
+
48
+ lastIndex = index + searchQuery.length;
49
+ index = textLower.indexOf(searchLower, lastIndex);
50
+ }
51
+
52
+ // Add remaining text
53
+ if (lastIndex < String(text).length) {
54
+ parts.push(String(text).substring(lastIndex));
55
+ }
56
+
57
+ return parts.length > 0 ? <>{parts}</> : text;
58
+ };
59
+
60
+ return (
61
+ <SearchContext.Provider value={{ searchQuery, setSearchQuery, highlightText }}>
62
+ {children}
63
+ </SearchContext.Provider>
64
+ );
65
+ };
66
+
67
+ export const useSearch = () => {
68
+ const context = useContext(SearchContext);
69
+ if (!context) {
70
+ return {
71
+ searchQuery: '',
72
+ setSearchQuery: () => {},
73
+ highlightText: (text: string) => text,
74
+ };
75
+ }
76
+ return context;
77
+ };
78
+
@@ -1,76 +1,79 @@
1
- import React from 'react';
2
- import { ReactFlowProps, ReactFlowProvider } from '@xyflow/react';
3
- import '@xyflow/react/dist/style.css';
4
- import { DiagramContent } from './DiagramContent';
5
-
6
- interface DiagramContainerProps
7
- extends Omit<ReactFlowProps, 'nodes' | 'edges' | 'onChange'> {
8
- showAutomationExecutionPanel?: boolean;
9
- }
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
-
69
- export const DiagramContainer: React.FC<DiagramContainerProps> = (props) => {
70
- return (
71
- <ReactFlowProvider>
72
- <EdgeMarkerDefinitions />
73
- <DiagramContent {...props} />
74
- </ReactFlowProvider>
75
- );
76
- };
1
+ import React from 'react';
2
+ import { ReactFlowProps, ReactFlowProvider } from '@xyflow/react';
3
+ import '@xyflow/react/dist/style.css';
4
+ import { DiagramContent } from './DiagramContent';
5
+ import { SearchProvider } from '../contexts/SearchContext';
6
+
7
+ interface DiagramContainerProps
8
+ extends Omit<ReactFlowProps, 'nodes' | 'edges' | 'onChange'> {
9
+ showAutomationExecutionPanel?: boolean;
10
+ }
11
+
12
+ // Default arrow marker definitions for edges
13
+ const EdgeMarkerDefinitions = () => (
14
+ <svg style={{ position: 'absolute', width: 0, height: 0 }}>
15
+ <defs>
16
+ {/* Arrow marker - Green */}
17
+ <marker
18
+ id="arrow"
19
+ viewBox="0 0 10 10"
20
+ refX="8"
21
+ refY="5"
22
+ markerWidth="6"
23
+ markerHeight="6"
24
+ orient="auto-start-reverse"
25
+ >
26
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#10B981" />
27
+ </marker>
28
+
29
+ {/* Arrow marker - Blue */}
30
+ <marker
31
+ id="arrow-blue"
32
+ viewBox="0 0 10 10"
33
+ refX="8"
34
+ refY="5"
35
+ markerWidth="6"
36
+ markerHeight="6"
37
+ orient="auto-start-reverse"
38
+ >
39
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#4858E9" />
40
+ </marker>
41
+
42
+ {/* Arrow marker - White */}
43
+ <marker
44
+ id="arrow-white"
45
+ viewBox="0 0 10 10"
46
+ refX="8"
47
+ refY="5"
48
+ markerWidth="6"
49
+ markerHeight="6"
50
+ orient="auto-start-reverse"
51
+ >
52
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#ffffff" />
53
+ </marker>
54
+
55
+ {/* Circle marker */}
56
+ <marker
57
+ id="circle"
58
+ viewBox="0 0 10 10"
59
+ refX="5"
60
+ refY="5"
61
+ markerWidth="5"
62
+ markerHeight="5"
63
+ >
64
+ <circle cx="5" cy="5" r="4" fill="#10B981" />
65
+ </marker>
66
+ </defs>
67
+ </svg>
68
+ );
69
+
70
+ export const DiagramContainer: React.FC<DiagramContainerProps> = (props) => {
71
+ return (
72
+ <ReactFlowProvider>
73
+ <SearchProvider>
74
+ <EdgeMarkerDefinitions />
75
+ <DiagramContent {...props} />
76
+ </SearchProvider>
77
+ </ReactFlowProvider>
78
+ );
79
+ };