@canmingir/link 1.2.7 → 1.2.10

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.
@@ -4,6 +4,7 @@ import { getContentParts } from "./flowUtils";
4
4
 
5
5
  import { Box, Card, Typography } from "@mui/material";
6
6
  import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
7
+ import { SelectionProvider, useSelection } from "./SelectionContext";
7
8
  import {
8
9
  applySemanticTokens,
9
10
  getBaseStyleForVariant,
@@ -61,6 +62,7 @@ const NodeContent = ({
61
62
  const nodeStyle = applySemanticTokens(rawNodeStyle, baseStyle);
62
63
 
63
64
  const {
65
+ direction = "vertical",
64
66
  lineColor = baseStyle.lineColor,
65
67
  lineWidth = baseStyle.lineWidth,
66
68
  lineStyle = baseStyle.lineStyle,
@@ -73,9 +75,20 @@ const NodeContent = ({
73
75
  shape,
74
76
  shadowLevel,
75
77
  minHeight,
76
- connectorType = baseStyle.connectorType ?? "default",
78
+ showDots = baseStyle.showDots ?? false,
79
+ dotRadius = baseStyle.dotRadius ?? 4,
80
+ dotColor = baseStyle.dotColor,
81
+ showArrow = baseStyle.showArrow ?? true,
82
+ arrowSize = baseStyle.arrowSize ?? 6,
83
+ animated = baseStyle.animated ?? false,
84
+ animationSpeed = baseStyle.animationSpeed ?? 1,
85
+ gradient = baseStyle.gradient ?? null,
86
+ curvature = baseStyle.curvature ?? 0.5,
87
+ selectionColor = baseStyle.selectionColor ?? "#64748b",
77
88
  } = nodeStyle;
78
89
 
90
+ const isHorizontal = direction === "horizontal";
91
+
79
92
  const strokeWidth = toPxNumber(lineWidth, 1.5);
80
93
  const dashStyle =
81
94
  lineStyle === "dashed" || lineStyle === "dotted" ? lineStyle : "solid";
@@ -220,7 +233,7 @@ const NodeContent = ({
220
233
  ref={containerRef}
221
234
  sx={{
222
235
  display: "inline-flex",
223
- flexDirection: "column",
236
+ flexDirection: isHorizontal ? "row" : "column",
224
237
  alignItems: "center",
225
238
  position: "relative",
226
239
  }}
@@ -231,6 +244,8 @@ const NodeContent = ({
231
244
  if (registerRef) registerRef(el);
232
245
  }}
233
246
  onDrag={handleDrag}
247
+ nodeId={node.id}
248
+ selectionColor={selectionColor}
234
249
  >
235
250
  {renderContent()}
236
251
  </DraggableNode>
@@ -244,16 +259,32 @@ const NodeContent = ({
244
259
  stroke={lineColor}
245
260
  strokeWidth={strokeWidth}
246
261
  lineStyle={dashStyle}
247
- connectorType={connectorType}
248
262
  tick={connectorTick}
263
+ orientation={direction}
264
+ showDots={showDots}
265
+ dotRadius={dotRadius}
266
+ dotColor={dotColor}
267
+ showArrow={showArrow}
268
+ arrowSize={arrowSize}
269
+ animated={animated}
270
+ animationSpeed={animationSpeed}
271
+ gradient={gradient}
272
+ curvature={curvature}
249
273
  />
250
274
 
251
275
  <Box
252
276
  sx={{
253
277
  display: "flex",
254
- flexDirection: "row",
255
- columnGap: gap,
256
- marginTop: levelGap,
278
+ flexDirection: isHorizontal ? "column" : "row",
279
+ ...(isHorizontal
280
+ ? {
281
+ marginLeft: levelGap,
282
+ rowGap: gap,
283
+ }
284
+ : {
285
+ marginTop: levelGap,
286
+ columnGap: gap,
287
+ }),
257
288
  position: "relative",
258
289
  alignItems: "flex-start",
259
290
  justifyContent: "center",
@@ -279,15 +310,49 @@ const NodeContent = ({
279
310
  );
280
311
  };
281
312
 
282
- const FlowNode = ({ isRoot = false, ...props }) => {
283
- if (!isRoot) {
284
- return <NodeContent {...props} />;
285
- }
313
+ const hexToRgba = (hex, alpha) => {
314
+ const r = parseInt(hex.slice(1, 3), 16);
315
+ const g = parseInt(hex.slice(3, 5), 16);
316
+ const b = parseInt(hex.slice(5, 7), 16);
317
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
318
+ };
319
+
320
+ const SelectionBox = ({ box, selectionColor = "#64748b" }) => {
321
+ if (!box) return null;
286
322
 
323
+ const { startX, startY, currentX, currentY } = box;
324
+ const left = Math.min(startX, currentX);
325
+ const top = Math.min(startY, currentY);
326
+ const width = Math.abs(currentX - startX);
327
+ const height = Math.abs(currentY - startY);
328
+
329
+ return (
330
+ <Box
331
+ sx={{
332
+ position: "fixed",
333
+ left,
334
+ top,
335
+ width,
336
+ height,
337
+ border: `2px solid ${selectionColor}`,
338
+ backgroundColor: hexToRgba(selectionColor, 0.1),
339
+ pointerEvents: "none",
340
+ zIndex: 9999,
341
+ borderRadius: "4px",
342
+ }}
343
+ />
344
+ );
345
+ };
346
+
347
+ const FlowCanvas = ({ children, selectionColor = "#64748b" }) => {
287
348
  const [offset, setOffset] = useState({ x: 0, y: 0 });
288
349
  const [isDragging, setIsDragging] = useState(false);
289
-
290
350
  const [zoom, setZoom] = useState(1);
351
+ const [selectionBox, setSelectionBox] = useState(null);
352
+ const containerRef = useRef(null);
353
+ const selectionBoxRef = useRef(null);
354
+
355
+ const { clearSelection, selectMultiple, addToSelection } = useSelection();
291
356
 
292
357
  const clampZoom = (z) => Math.min(2.5, Math.max(0.25, z));
293
358
 
@@ -295,28 +360,92 @@ const FlowNode = ({ isRoot = false, ...props }) => {
295
360
  const onWheel = (e) => {
296
361
  const wantsZoom = e.ctrlKey || e.metaKey;
297
362
  if (!wantsZoom) return;
298
-
299
363
  e.preventDefault();
300
-
301
364
  const direction = e.deltaY > 0 ? -1 : 1;
302
365
  const factor = direction > 0 ? 1.1 : 1 / 1.1;
303
-
304
366
  setZoom((z) => clampZoom(z * factor));
305
367
  };
306
-
307
368
  window.addEventListener("wheel", onWheel, { passive: false });
308
369
  return () => window.removeEventListener("wheel", onWheel);
309
370
  }, []);
310
371
 
311
372
  const handleCanvasMouseDown = (e) => {
312
- if (e.target?.closest?.('[data-flow-zoom="true"]')) return;
373
+ if (e.target?.closest?.(".MuiCard-root") || e.target?.closest?.("button"))
374
+ return;
313
375
 
314
376
  if (e.button !== 0) return;
315
377
 
316
- setIsDragging(true);
317
-
318
378
  const startX = e.clientX;
319
379
  const startY = e.clientY;
380
+
381
+ if (e.shiftKey || e.ctrlKey || e.metaKey) {
382
+ setSelectionBox({ startX, startY, currentX: startX, currentY: startY });
383
+ selectionBoxRef.current = {
384
+ startX,
385
+ startY,
386
+ currentX: startX,
387
+ currentY: startY,
388
+ };
389
+
390
+ const onMove = (ev) => {
391
+ const newBox = {
392
+ startX,
393
+ startY,
394
+ currentX: ev.clientX,
395
+ currentY: ev.clientY,
396
+ };
397
+ setSelectionBox(newBox);
398
+ selectionBoxRef.current = newBox;
399
+ };
400
+
401
+ const onUp = () => {
402
+ if (containerRef.current && selectionBoxRef.current) {
403
+ const box = selectionBoxRef.current;
404
+ const nodes = containerRef.current.querySelectorAll("[data-node-id]");
405
+ const selectedNodeIds = [];
406
+
407
+ const boxLeft = Math.min(box.startX, box.currentX);
408
+ const boxRight = Math.max(box.startX, box.currentX);
409
+ const boxTop = Math.min(box.startY, box.currentY);
410
+ const boxBottom = Math.max(box.startY, box.currentY);
411
+
412
+ nodes.forEach((node) => {
413
+ const rect = node.getBoundingClientRect();
414
+
415
+ if (
416
+ rect.left < boxRight &&
417
+ rect.right > boxLeft &&
418
+ rect.top < boxBottom &&
419
+ rect.bottom > boxTop
420
+ ) {
421
+ const nodeId = node.getAttribute("data-node-id");
422
+ if (nodeId) selectedNodeIds.push(nodeId);
423
+ }
424
+ });
425
+
426
+ if (selectedNodeIds.length > 0) {
427
+ if (e.shiftKey) {
428
+ addToSelection(selectedNodeIds);
429
+ } else {
430
+ selectMultiple(selectedNodeIds);
431
+ }
432
+ }
433
+ }
434
+
435
+ setSelectionBox(null);
436
+ selectionBoxRef.current = null;
437
+ window.removeEventListener("mousemove", onMove);
438
+ window.removeEventListener("mouseup", onUp);
439
+ };
440
+
441
+ window.addEventListener("mousemove", onMove);
442
+ window.addEventListener("mouseup", onUp);
443
+ return;
444
+ }
445
+
446
+ clearSelection();
447
+
448
+ setIsDragging(true);
320
449
  const startOffset = { ...offset };
321
450
 
322
451
  const onMove = (ev) => {
@@ -338,6 +467,7 @@ const FlowNode = ({ isRoot = false, ...props }) => {
338
467
 
339
468
  return (
340
469
  <Box
470
+ ref={containerRef}
341
471
  onMouseDown={handleCanvasMouseDown}
342
472
  sx={{
343
473
  width: "100vw",
@@ -349,6 +479,7 @@ const FlowNode = ({ isRoot = false, ...props }) => {
349
479
  position: "relative",
350
480
  }}
351
481
  >
482
+ <SelectionBox box={selectionBox} selectionColor={selectionColor} />
352
483
  <Box
353
484
  sx={{
354
485
  transform: `translate(${offset.x}px, ${offset.y}px) scale(${zoom})`,
@@ -362,10 +493,27 @@ const FlowNode = ({ isRoot = false, ...props }) => {
362
493
  pointerEvents: "auto",
363
494
  }}
364
495
  >
365
- <NodeContent {...props} />
496
+ {children}
366
497
  </Box>
367
498
  </Box>
368
499
  );
369
500
  };
370
501
 
502
+ const FlowNode = ({ isRoot = false, onAddNode, variant, ...props }) => {
503
+ if (!isRoot) {
504
+ return <NodeContent onAddNode={onAddNode} variant={variant} {...props} />;
505
+ }
506
+
507
+ const baseStyle = getBaseStyleForVariant(variant);
508
+ const selectionColor = baseStyle.selectionColor ?? "#64748b";
509
+
510
+ return (
511
+ <SelectionProvider>
512
+ <FlowCanvas selectionColor={selectionColor}>
513
+ <NodeContent onAddNode={onAddNode} variant={variant} {...props} />
514
+ </FlowCanvas>
515
+ </SelectionProvider>
516
+ );
517
+ };
518
+
371
519
  export default FlowNode;
@@ -0,0 +1,123 @@
1
+ import React, {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useRef,
6
+ useState,
7
+ } from "react";
8
+
9
+ const SelectionContext = createContext(null);
10
+
11
+ export const SelectionProvider = ({ children }) => {
12
+ const [selectedIds, setSelectedIds] = useState(new Set());
13
+ const nodeHandlersRef = useRef(new Map());
14
+
15
+ const selectNode = useCallback((id, addToSelection = false) => {
16
+ setSelectedIds((prev) => {
17
+ const next = new Set(addToSelection ? prev : []);
18
+ next.add(id);
19
+ return next;
20
+ });
21
+ }, []);
22
+
23
+ const deselectNode = useCallback((id) => {
24
+ setSelectedIds((prev) => {
25
+ const next = new Set(prev);
26
+ next.delete(id);
27
+ return next;
28
+ });
29
+ }, []);
30
+
31
+ const toggleSelection = useCallback((id) => {
32
+ setSelectedIds((prev) => {
33
+ const next = new Set(prev);
34
+ if (next.has(id)) {
35
+ next.delete(id);
36
+ } else {
37
+ next.add(id);
38
+ }
39
+ return next;
40
+ });
41
+ }, []);
42
+
43
+ const clearSelection = useCallback(() => {
44
+ setSelectedIds(new Set());
45
+ }, []);
46
+
47
+ const selectMultiple = useCallback((ids) => {
48
+ setSelectedIds(new Set(ids));
49
+ }, []);
50
+
51
+ const addToSelection = useCallback((ids) => {
52
+ setSelectedIds((prev) => new Set([...prev, ...ids]));
53
+ }, []);
54
+
55
+ const isSelected = useCallback((id) => selectedIds.has(id), [selectedIds]);
56
+
57
+ const registerNodeHandlers = useCallback((id, handlers) => {
58
+ nodeHandlersRef.current.set(id, handlers);
59
+ return () => nodeHandlersRef.current.delete(id);
60
+ }, []);
61
+
62
+ const moveSelectedNodes = useCallback(
63
+ (deltaX, deltaY, excludeId = null) => {
64
+ selectedIds.forEach((id) => {
65
+ if (id !== excludeId) {
66
+ const handlers = nodeHandlersRef.current.get(id);
67
+ if (handlers) {
68
+ if (handlers.setOffset) {
69
+ handlers.setOffset((prev) => ({
70
+ x: prev.x + deltaX,
71
+ y: prev.y + deltaY,
72
+ }));
73
+ }
74
+ if (handlers.onDrag) {
75
+ handlers.onDrag();
76
+ }
77
+ }
78
+ }
79
+ });
80
+ },
81
+ [selectedIds]
82
+ );
83
+
84
+ return (
85
+ <SelectionContext.Provider
86
+ value={{
87
+ selectedIds,
88
+ selectNode,
89
+ deselectNode,
90
+ toggleSelection,
91
+ clearSelection,
92
+ selectMultiple,
93
+ addToSelection,
94
+ isSelected,
95
+ registerNodeHandlers,
96
+ moveSelectedNodes,
97
+ }}
98
+ >
99
+ {children}
100
+ </SelectionContext.Provider>
101
+ );
102
+ };
103
+
104
+ export const useSelection = () => {
105
+ const context = useContext(SelectionContext);
106
+ if (!context) {
107
+ return {
108
+ selectedIds: new Set(),
109
+ selectNode: () => {},
110
+ deselectNode: () => {},
111
+ toggleSelection: () => {},
112
+ clearSelection: () => {},
113
+ selectMultiple: () => {},
114
+ addToSelection: () => {},
115
+ isSelected: () => false,
116
+ registerNodeHandlers: () => () => {},
117
+ moveSelectedNodes: () => {},
118
+ };
119
+ }
120
+ return context;
121
+ };
122
+
123
+ export default SelectionContext;
@@ -9,12 +9,12 @@ const MainContainer = styled("div", {
9
9
  shouldForwardProp: (prop) => prop !== "$style",
10
10
  })(({ theme, $style = {} }) => {
11
11
  const {
12
- minWidth = 120,
13
- minHeight = 120,
14
- maxWidth = 160,
15
- maxHeight = 160,
16
- borderRadius = 16,
17
- borderColor = "rgba(255, 255, 255, 0.2)",
12
+ minWidth = 280,
13
+ minHeight = 220,
14
+ maxWidth = 320,
15
+ maxHeight = "auto",
16
+ borderRadius = 20,
17
+ borderColor = "rgba(255, 255, 255, 0.08)",
18
18
  bgFrom,
19
19
  bgTo,
20
20
  } = $style;
@@ -28,10 +28,11 @@ const MainContainer = styled("div", {
28
28
  return {
29
29
  display: "flex",
30
30
  flexDirection: "column",
31
- alignItems: "center",
31
+ alignItems: "flex-start",
32
+ justifyContent: "flex-start",
32
33
  color: "#ffffff",
33
34
  borderRadius,
34
- padding: "16px 20px",
35
+ padding: "24px",
35
36
  border: `1px solid ${borderColor}`,
36
37
  backdropFilter: "blur(10px)",
37
38
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
@@ -56,26 +57,38 @@ const MainContainer = styled("div", {
56
57
  };
57
58
  });
58
59
 
60
+ const HeaderRow = styled("div")({
61
+ display: "flex",
62
+ flexDirection: "row",
63
+ alignItems: "center",
64
+ width: "100%",
65
+ gap: "16px",
66
+ marginBottom: "16px",
67
+ minHeight: "44px",
68
+ });
69
+
59
70
  const IconContainer = styled("div", {
60
71
  shouldForwardProp: (prop) => prop !== "$style",
61
72
  })(({ $style = {} }) => {
62
73
  const {
63
74
  bg = "rgba(255, 255, 255, 0.1)",
64
- hoverBg = "rgba(255, 255, 255, 0.15)",
65
- borderRadius = 12,
66
- padding = 8,
67
- borderColor = "rgba(255, 255, 255, 0.3)",
68
- marginBottom = 12,
75
+ hoverBg = "rgba(255, 255, 255, 0.2)",
76
+ borderRadius = 14,
77
+ padding = 10,
78
+ borderColor = "rgba(255, 255, 255, 0.1)",
69
79
  } = $style;
70
80
 
71
81
  return {
72
82
  backgroundColor: bg,
73
83
  borderRadius,
74
84
  padding,
75
- marginBottom,
76
85
  transition: "all 0.4s ease",
77
86
  backdropFilter: "blur(5px)",
78
87
  border: `1px solid ${borderColor}`,
88
+ flexShrink: 0,
89
+ display: "flex",
90
+ alignItems: "center",
91
+ justifyContent: "center",
79
92
 
80
93
  '[data-hovered="true"] &': {
81
94
  backgroundColor: hoverBg,
@@ -88,44 +101,90 @@ const LabelText = styled("div", {
88
101
  })(({ $style = {} }) => {
89
102
  const {
90
103
  color = "#ffffff",
91
- fontWeight = 600,
92
- fontSize = 13,
93
- letterSpacing = 0.5,
104
+ fontWeight = 700,
105
+ fontSize = 15,
106
+ letterSpacing = 0.3,
94
107
  } = $style;
95
108
 
96
109
  return {
97
110
  fontWeight,
98
111
  fontSize,
99
112
  letterSpacing: `${letterSpacing}px`,
100
- textAlign: "center",
113
+ textAlign: "left",
101
114
  transition: "all 0.5s cubic-bezier(0.4, 0, 0.2, 1)",
102
- textShadow: "none",
103
- lineHeight: "1.4",
115
+ lineHeight: "1.2",
104
116
  opacity: 0,
105
- transform: "translateY(10px)",
117
+ transform: "translateX(10px)",
106
118
  color,
119
+ flex: 1,
107
120
 
108
121
  '&[data-animated="true"]': {
109
122
  opacity: 1,
110
- transform: "translateY(0)",
123
+ transform: "translateX(0)",
111
124
  },
112
125
  };
113
126
  });
114
127
 
128
+ const DescriptionText = styled("div")(({ theme }) => ({
129
+ fontSize: "12px",
130
+ fontWeight: 400,
131
+ color: alpha("#fff", 0.6),
132
+ textAlign: "left",
133
+ lineHeight: "1.5",
134
+ width: "100%",
135
+ flex: 1,
136
+ opacity: 0,
137
+ transform: "translateY(10px)",
138
+ transition: "all 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s",
139
+ marginBottom: "16px",
140
+ display: "-webkit-box",
141
+ WebkitLineClamp: 4,
142
+ WebkitBoxOrient: "vertical",
143
+ overflow: "hidden",
144
+
145
+ '&[data-animated="true"]': {
146
+ opacity: 1,
147
+ transform: "translateY(0)",
148
+ },
149
+ }));
150
+
151
+ const ActionText = styled("div")(({ theme }) => ({
152
+ fontSize: "10px",
153
+ fontWeight: 700,
154
+ textTransform: "uppercase",
155
+ letterSpacing: "1px",
156
+ color: alpha("#fff", 0.4),
157
+ marginTop: "auto",
158
+ textAlign: "left",
159
+ width: "100%",
160
+ fontFamily: "monospace",
161
+ opacity: 0,
162
+ transform: "translateY(5px)",
163
+ transition: "all 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.2s",
164
+
165
+ '&[data-animated="true"]': {
166
+ opacity: 1,
167
+ transform: "translateY(0)",
168
+ },
169
+ }));
170
+
115
171
  const getIcon = (node) => {
116
172
  if (node.icon) return node.icon;
117
173
  if (node.type === "CONDITION" || node.type === "decision")
118
174
  return "mdi:help-circle-outline";
119
175
  if (node.type === "NORMAL") return "mdi:checkbox-blank-circle-outline";
120
- return "mdi:cube-outline";
176
+ return "mdi:map-marker";
121
177
  };
122
178
 
123
- const InfoNode = ({ node, nodeStyle = {} }) => {
179
+ const InfoNode = ({ node, nodeStyle = {}, children }) => {
124
180
  const [animated, setAnimated] = useState(false);
125
181
  const [isHovered, setIsHovered] = useState(false);
126
182
 
127
- const label =
128
- node.label || node.title || node.name || node.id || "Responsibility";
183
+ const label = node.label || node.title || node.name || node.id || "Get Data";
184
+
185
+ const action = node.action || "SYSTEM:DEFAULT_ACTION";
186
+ const description =
187
+ node.description || "Description of the operation goes here.";
129
188
 
130
189
  useEffect(() => {
131
190
  const timer = setTimeout(() => setAnimated(true), ANIMATION_DELAY_MS);
@@ -133,14 +192,9 @@ const InfoNode = ({ node, nodeStyle = {} }) => {
133
192
  }, []);
134
193
 
135
194
  const layoutStyle = {
136
- minWidth: nodeStyle.cardWidth || nodeStyle.minWidth || 120,
137
- minHeight: nodeStyle.minHeight || 120,
138
- maxWidth: nodeStyle.maxWidth || 160,
139
- maxHeight: nodeStyle.maxHeight || 160,
140
- borderRadius: typeof nodeStyle.shape === "number" ? nodeStyle.shape : 16,
141
- borderColor: nodeStyle.borderColor || "rgba(255, 255, 255, 0.2)",
142
- bgFrom: nodeStyle.bgFrom,
143
- bgTo: nodeStyle.bgTo,
195
+ ...nodeStyle,
196
+ minWidth: nodeStyle.cardWidth || nodeStyle.minWidth || 280,
197
+ minHeight: nodeStyle.minHeight || 220,
144
198
  };
145
199
 
146
200
  const iconContainerStyle = {
@@ -149,7 +203,6 @@ const InfoNode = ({ node, nodeStyle = {} }) => {
149
203
  iconBorderRadius: nodeStyle.iconRadius,
150
204
  iconPadding: nodeStyle.iconPadding,
151
205
  iconBorderColor: nodeStyle.iconBorderColor,
152
- iconMarginBottom: nodeStyle.iconMarginBottom,
153
206
  };
154
207
 
155
208
  const labelStyle = {
@@ -168,27 +221,33 @@ const InfoNode = ({ node, nodeStyle = {} }) => {
168
221
  onMouseEnter={() => setIsHovered(true)}
169
222
  onMouseLeave={() => setIsHovered(false)}
170
223
  >
171
- <IconContainer $style={iconContainerStyle}>
172
- <Iconify
173
- icon={icon}
174
- width={28}
175
- height={28}
176
- sx={{
177
- transition: "all 0.6s cubic-bezier(0.4, 0, 0.2, 1)",
178
- transform: animated
179
- ? isHovered
180
- ? "rotate(360deg) scale(1.1)"
181
- : "rotate(0deg) scale(1)"
182
- : "rotate(-90deg) scale(0.8)",
183
- filter: "none",
184
- color: nodeStyle.iconColor || "#ffffff",
185
- }}
186
- />
187
- </IconContainer>
188
-
189
- <LabelText data-animated={animated} $style={labelStyle}>
190
- {label}
191
- </LabelText>
224
+ <HeaderRow>
225
+ <IconContainer $style={iconContainerStyle}>
226
+ <Iconify
227
+ icon={icon}
228
+ width={24}
229
+ height={24}
230
+ sx={{
231
+ filter: "none",
232
+ color: nodeStyle.iconColor || "#ffffff",
233
+ }}
234
+ />
235
+ </IconContainer>
236
+
237
+ <LabelText data-animated={animated} $style={labelStyle}>
238
+ {label}
239
+ </LabelText>
240
+ </HeaderRow>
241
+
242
+ {description && (
243
+ <DescriptionText data-animated={animated}>
244
+ {description}
245
+ </DescriptionText>
246
+ )}
247
+
248
+ {action && <ActionText data-animated={animated}>{action}</ActionText>}
249
+
250
+ {children}
192
251
  </MainContainer>
193
252
  );
194
253
  };