flow-lib-creomnia 1.0.16 → 1.0.17-dev.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.
@@ -26,22 +26,37 @@ const HorizontalDrawer = ({ Content, HeaderContent, open, onClose }) => {
26
26
  return "40%";
27
27
  return "35%";
28
28
  };
29
- const handleDrag = (event) => {
30
- const maxWidthPercent = 90;
31
- const minWidthPercent = 30;
32
- const newWidthPercent = ((window.innerWidth - event.clientX) * 100) / window.innerWidth;
33
- if (newWidthPercent < minWidthPercent || newWidthPercent > maxWidthPercent) {
34
- return;
35
- }
36
- setDrawerWidth(`${newWidthPercent}%`);
37
- };
38
29
  const DraggerElement = () => {
39
30
  return ((0, jsx_runtime_1.jsx)(material_1.Box, { onMouseDown: (e) => {
40
31
  e.preventDefault();
41
- window.addEventListener("mousemove", handleDrag);
42
- window.addEventListener("mouseup", () => {
43
- window.removeEventListener("mousemove", handleDrag);
44
- });
32
+ // Capture the drawer paper + its positioned host (canvas
33
+ // Box) at drag start. We can't rely on `event.target` during
34
+ // mousemove because the cursor is over the canvas, not the
35
+ // drawer; closing over `host` here keeps the math correct
36
+ // both in the main editor (host = NodesFlow Box ≈ viewport)
37
+ // and inside a modal (host = the same canvas Box, just
38
+ // rendered inside a smaller window).
39
+ const dragger = e.currentTarget;
40
+ const drawerEl = dragger.closest(".MuiDrawer-paper");
41
+ const host = drawerEl?.parentElement;
42
+ const onMove = (ev) => {
43
+ const rect = host?.getBoundingClientRect();
44
+ const hostRight = rect?.right ?? window.innerWidth;
45
+ const hostWidth = rect?.width ?? window.innerWidth;
46
+ const maxWidthPercent = 90;
47
+ const minWidthPercent = 30;
48
+ const newWidthPercent = ((hostRight - ev.clientX) * 100) / hostWidth;
49
+ if (newWidthPercent < minWidthPercent || newWidthPercent > maxWidthPercent) {
50
+ return;
51
+ }
52
+ setDrawerWidth(`${newWidthPercent}%`);
53
+ };
54
+ const onUp = () => {
55
+ window.removeEventListener("mousemove", onMove);
56
+ window.removeEventListener("mouseup", onUp);
57
+ };
58
+ window.addEventListener("mousemove", onMove);
59
+ window.addEventListener("mouseup", onUp);
45
60
  }, sx: {
46
61
  display: "flex",
47
62
  alignItems: "center",
@@ -55,10 +70,18 @@ const HorizontalDrawer = ({ Content, HeaderContent, open, onClose }) => {
55
70
  };
56
71
  return ((0, jsx_runtime_1.jsx)(material_1.Drawer, { variant: "persistent", open: open, anchor: "right", sx: {
57
72
  flexShrink: 0,
73
+ // Anchor paper to its positioned ancestor (the NodesFlow Box,
74
+ // which sets `position: relative`) rather than the viewport.
75
+ // The top offset is read from `--drawer-top-offset` so the
76
+ // main flow editor can leave room for the app header (66px,
77
+ // default), while a host like `ToolFlowConfigModal` can set
78
+ // it to `0` and have the drawer fill the entire canvas.
58
79
  "& .MuiDrawer-paper": {
80
+ position: "absolute",
59
81
  width: drawerWidth || getDefaultWidth(),
60
- height: "calc(100% - 66px)",
61
- marginTop: "66px",
82
+ height: "calc(100% - var(--drawer-top-offset, 66px))",
83
+ marginTop: "var(--drawer-top-offset, 66px)",
84
+ right: 0,
62
85
  borderTopLeftRadius: "16px",
63
86
  boxShadow: "0px 9px 46px 0px #00000014",
64
87
  border: "none",
@@ -31,6 +31,6 @@ const NodesFlow = ({ theme, nodes, menuTabs, addNewNodeCallback, permissions, dr
31
31
  addNewNodeCallback,
32
32
  }), [nodeDrawers, menuTabs, addNewNodeCallback, processedNodeIds]);
33
33
  const containerRef = (0, react_1.useRef)(null);
34
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: permissions.canRead && ((0, jsx_runtime_1.jsx)(ThemeContext_1.ThemeContextProvider, { themContextValue: theme, children: (0, jsx_runtime_1.jsx)(react_dnd_1.DndProvider, { backend: react_dnd_html5_backend_1.HTML5Backend, children: (0, jsx_runtime_1.jsx)(material_1.Box, { ref: containerRef, style: { height: "100%", width: "100%", background: theme?.palette.background.default || colors_1.Colors.DIRTY_WHITE }, children: (0, jsx_runtime_1.jsx)(SettingsContext_1.NodeSettingsProvider, { permissions: permissions, drawerProps: drawerProps, children: (0, jsx_runtime_1.jsx)(FlowPosition_1.FlowPositionProvider, { children: (0, jsx_runtime_1.jsx)(FlowSandbox_1.default, { permissions: permissions, connectionDrawers: connectionDrawers, nodeDrawers: nodeDrawers, containerRef: containerRef, processedNodeIds: processedNodeIds, failedNodeId: failedNodeId, failedNodeColor: failedNodeColor, onRedirect: onRedirect, onUpdateNodePosition: onUpdateNodePosition, emptyMenuItemsComponent: emptyMenuItemsComponent, searchPlaceholder: searchPlaceholder }) }) }) }) }) })) }));
34
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: permissions.canRead && ((0, jsx_runtime_1.jsx)(ThemeContext_1.ThemeContextProvider, { themContextValue: theme, children: (0, jsx_runtime_1.jsx)(react_dnd_1.DndProvider, { backend: react_dnd_html5_backend_1.HTML5Backend, children: (0, jsx_runtime_1.jsx)(material_1.Box, { ref: containerRef, style: { position: "relative", height: "100%", width: "100%", background: theme?.palette.background.default || colors_1.Colors.DIRTY_WHITE }, children: (0, jsx_runtime_1.jsx)(SettingsContext_1.NodeSettingsProvider, { permissions: permissions, drawerProps: drawerProps, children: (0, jsx_runtime_1.jsx)(FlowPosition_1.FlowPositionProvider, { children: (0, jsx_runtime_1.jsx)(FlowSandbox_1.default, { permissions: permissions, connectionDrawers: connectionDrawers, nodeDrawers: nodeDrawers, containerRef: containerRef, processedNodeIds: processedNodeIds, failedNodeId: failedNodeId, failedNodeColor: failedNodeColor, onRedirect: onRedirect, onUpdateNodePosition: onUpdateNodePosition, emptyMenuItemsComponent: emptyMenuItemsComponent, searchPlaceholder: searchPlaceholder }) }) }) }) }) })) }));
35
35
  };
36
36
  exports.default = NodesFlow;
@@ -48,8 +48,13 @@ const NodeSettingsProvider = ({ children, permissions: { canUpdate, canDelete },
48
48
  }, config_1.Config.CLEAR_NODE_DELAY);
49
49
  };
50
50
  const onSaveNode = async () => {
51
+ // `onSave` is allowed to be sync OR async — host apps that wrap a
52
+ // server call in an async handler need to surface validation errors
53
+ // BEFORE the drawer closes. Awaiting handles both cases: a sync
54
+ // `false` short-circuits, a `Promise<false>` resolves and short-
55
+ // circuits, anything else closes the drawer.
51
56
  const result = await node?.settings?.footer?.onSave?.(node?.id);
52
- if (result !== true)
57
+ if (result === false)
53
58
  return;
54
59
  handleClose();
55
60
  };
@@ -8,5 +8,6 @@ export declare enum NodeTypeEnum {
8
8
  }
9
9
  export declare enum NodeMenuItemType {
10
10
  EXTENSION = "extension",
11
- AI_AGENT = "ai-agent"
11
+ AI_AGENT = "ai-agent",
12
+ S2S_AGENT = "s2s-agent"
12
13
  }
@@ -14,4 +14,5 @@ var NodeMenuItemType;
14
14
  (function (NodeMenuItemType) {
15
15
  NodeMenuItemType["EXTENSION"] = "extension";
16
16
  NodeMenuItemType["AI_AGENT"] = "ai-agent";
17
+ NodeMenuItemType["S2S_AGENT"] = "s2s-agent";
17
18
  })(NodeMenuItemType || (exports.NodeMenuItemType = NodeMenuItemType = {}));
@@ -5,7 +5,7 @@ export type NodesFooterType = {
5
5
  saveText?: string;
6
6
  cancelText?: string;
7
7
  deleteText?: string;
8
- onSave?: (nodeId: string) => void | boolean | Promise<void | boolean>;
8
+ onSave?: (nodeId: string) => void | false;
9
9
  onCancel?: (nodeId: string) => void;
10
10
  onDelete?: (nodeId: string) => void;
11
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-lib-creomnia",
3
- "version": "1.0.16",
3
+ "version": "1.0.17-dev.1",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",