@nocobase/flow-engine 2.1.0-beta.22 → 2.1.0-beta.23

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 (45) hide show
  1. package/lib/components/FieldModelRenderer.js +2 -2
  2. package/lib/components/FlowModelRenderer.d.ts +2 -0
  3. package/lib/components/FlowModelRenderer.js +2 -0
  4. package/lib/components/dnd/index.d.ts +19 -1
  5. package/lib/components/dnd/index.js +239 -21
  6. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +20 -1
  7. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +4 -0
  8. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +21 -8
  9. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +2 -0
  10. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +100 -32
  11. package/lib/components/subModel/index.d.ts +1 -0
  12. package/lib/components/subModel/index.js +19 -0
  13. package/lib/components/subModel/utils.d.ts +1 -1
  14. package/lib/data-source/index.d.ts +73 -0
  15. package/lib/data-source/index.js +205 -1
  16. package/lib/flowContext.d.ts +2 -0
  17. package/lib/flowI18n.js +2 -1
  18. package/lib/models/DisplayItemModel.d.ts +1 -1
  19. package/lib/models/EditableItemModel.d.ts +1 -1
  20. package/lib/models/FilterableItemModel.d.ts +1 -1
  21. package/lib/models/flowModel.d.ts +11 -9
  22. package/lib/models/flowModel.js +48 -9
  23. package/lib/provider.js +38 -23
  24. package/package.json +4 -4
  25. package/src/__tests__/provider.test.tsx +24 -2
  26. package/src/components/FieldModelRenderer.tsx +2 -1
  27. package/src/components/FlowModelRenderer.tsx +6 -0
  28. package/src/components/__tests__/dnd.test.ts +44 -0
  29. package/src/components/dnd/index.tsx +286 -26
  30. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +25 -1
  31. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +24 -5
  32. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +94 -3
  33. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +171 -2
  34. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +2 -0
  35. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +112 -32
  36. package/src/components/subModel/index.ts +1 -0
  37. package/src/data-source/__tests__/index.test.ts +34 -1
  38. package/src/data-source/index.ts +252 -2
  39. package/src/flowContext.ts +2 -0
  40. package/src/flowI18n.ts +2 -1
  41. package/src/models/DisplayItemModel.tsx +1 -1
  42. package/src/models/EditableItemModel.tsx +1 -1
  43. package/src/models/FilterableItemModel.tsx +1 -1
  44. package/src/models/flowModel.tsx +85 -23
  45. package/src/provider.tsx +41 -25
@@ -40,7 +40,7 @@ __export(FieldModelRenderer_exports, {
40
40
  FieldModelRenderer: () => FieldModelRenderer
41
41
  });
42
42
  module.exports = __toCommonJS(FieldModelRenderer_exports);
43
- var import_flow_engine = require("@nocobase/flow-engine");
43
+ var import_FlowModelRenderer = require("./FlowModelRenderer");
44
44
  var import_lodash = __toESM(require("lodash"));
45
45
  var import_react = __toESM(require("react"));
46
46
  const flowModelRendererPropKeys = [
@@ -93,7 +93,7 @@ function FieldModelRenderer(props) {
93
93
  (0, import_react.useEffect)(() => {
94
94
  model && model.setProps(modelProps);
95
95
  }, [modelProps]);
96
- return /* @__PURE__ */ import_react.default.createElement(import_flow_engine.FlowModelRenderer, { model, ...rest });
96
+ return /* @__PURE__ */ import_react.default.createElement(import_FlowModelRenderer.FlowModelRenderer, { model, ...rest });
97
97
  }
98
98
  __name(FieldModelRenderer, "FieldModelRenderer");
99
99
  // Annotate the CommonJS export names for ESM import in node:
@@ -19,6 +19,8 @@ export interface FlowModelRendererProps {
19
19
  showBackground?: boolean;
20
20
  showBorder?: boolean;
21
21
  showDragHandle?: boolean;
22
+ /** 是否显示事件流入口,默认 true */
23
+ showDynamicFlowsEditor?: boolean;
22
24
  /** 自定义工具栏样式,`top/left/right/bottom` 会作为 portal overlay 的 inset 使用 */
23
25
  style?: React.CSSProperties;
24
26
  /**
@@ -135,6 +135,7 @@ const FlowModelRendererCore = (0, import_reactive.observer)(
135
135
  showBackground: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showBackground : void 0,
136
136
  showBorder: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showBorder : void 0,
137
137
  showDragHandle: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showDragHandle : void 0,
138
+ showDynamicFlowsEditor: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showDynamicFlowsEditor : void 0,
138
139
  settingsMenuLevel,
139
140
  extraToolbarItems,
140
141
  toolbarStyle: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.style : void 0,
@@ -167,6 +168,7 @@ const FlowModelRendererCore = (0, import_reactive.observer)(
167
168
  showBackground: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showBackground : void 0,
168
169
  showBorder: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showBorder : void 0,
169
170
  showDragHandle: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showDragHandle : void 0,
171
+ showDynamicFlowsEditor: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.showDynamicFlowsEditor : void 0,
170
172
  settingsMenuLevel,
171
173
  extraToolbarItems,
172
174
  toolbarStyle: import_lodash.default.isObject(showFlowSettings) ? showFlowSettings.style : void 0,
@@ -7,15 +7,33 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
  import { DndContextProps } from '@dnd-kit/core';
10
+ import type { Transform } from '@dnd-kit/utilities';
10
11
  import React, { FC } from 'react';
11
12
  import { FlowModel } from '../../models';
12
13
  import { PersistOptions } from '../../types';
13
14
  export * from './findModelUidPosition';
14
15
  export * from './gridDragPlanner';
15
16
  export declare const EMPTY_COLUMN_UID = "EMPTY_COLUMN";
17
+ export declare const TOOLBAR_DRAG_ACTIVITY_EVENT = "nb-toolbar-drag-activity";
18
+ type ToolbarDragAnchorPoint = {
19
+ x: number;
20
+ y: number;
21
+ };
22
+ export declare const resolveOverlayAnchorTransform: ({ activeId, active, transform, activeNodeRect, dragAnchorPoint, }: {
23
+ activeId: string | null;
24
+ active: {
25
+ id: string | number;
26
+ } | null | undefined;
27
+ transform: Transform;
28
+ activeNodeRect: {
29
+ top: number;
30
+ left: number;
31
+ } | null;
32
+ dragAnchorPoint: ToolbarDragAnchorPoint | null;
33
+ }) => Transform;
16
34
  export declare const DragHandler: FC<{
17
35
  model: FlowModel;
18
- children: React.ReactNode;
36
+ children?: React.ReactNode;
19
37
  }>;
20
38
  export declare const Droppable: FC<{
21
39
  model: FlowModel<any>;
@@ -41,7 +41,9 @@ __export(dnd_exports, {
41
41
  DndProvider: () => DndProvider,
42
42
  DragHandler: () => DragHandler,
43
43
  Droppable: () => Droppable,
44
- EMPTY_COLUMN_UID: () => EMPTY_COLUMN_UID
44
+ EMPTY_COLUMN_UID: () => EMPTY_COLUMN_UID,
45
+ TOOLBAR_DRAG_ACTIVITY_EVENT: () => TOOLBAR_DRAG_ACTIVITY_EVENT,
46
+ resolveOverlayAnchorTransform: () => resolveOverlayAnchorTransform
45
47
  });
46
48
  module.exports = __toCommonJS(dnd_exports);
47
49
  var import_icons = require("@ant-design/icons");
@@ -52,17 +54,186 @@ var import_provider = require("../../provider");
52
54
  __reExport(dnd_exports, require("./findModelUidPosition"), module.exports);
53
55
  __reExport(dnd_exports, require("./gridDragPlanner"), module.exports);
54
56
  const EMPTY_COLUMN_UID = "EMPTY_COLUMN";
57
+ const TOOLBAR_DRAG_ACTIVITY_EVENT = "nb-toolbar-drag-activity";
58
+ const TOOLBAR_DRAG_ANCHOR_EVENT = "nb-toolbar-drag-anchor";
59
+ const MENU_SUBMENU_POPUP_SELECTOR = ".ant-menu-submenu-popup";
60
+ const resolveOverlayAnchorTransform = /* @__PURE__ */ __name(({
61
+ activeId,
62
+ active,
63
+ transform,
64
+ activeNodeRect,
65
+ dragAnchorPoint
66
+ }) => {
67
+ if (!activeId || (active == null ? void 0 : active.id) !== activeId || !dragAnchorPoint || !activeNodeRect) {
68
+ return transform;
69
+ }
70
+ return {
71
+ ...transform,
72
+ x: transform.x + dragAnchorPoint.x - activeNodeRect.left,
73
+ y: transform.y + dragAnchorPoint.y - activeNodeRect.top
74
+ };
75
+ }, "resolveOverlayAnchorTransform");
76
+ const resolveDraggableHostNode = /* @__PURE__ */ __name((activatorNode) => {
77
+ const ownerDocument = activatorNode == null ? void 0 : activatorNode.ownerDocument;
78
+ const floatToolbarContainer = activatorNode == null ? void 0 : activatorNode.closest(".nb-toolbar-container[data-model-uid]");
79
+ const toolbarModelUid = floatToolbarContainer == null ? void 0 : floatToolbarContainer.getAttribute("data-model-uid");
80
+ if (!ownerDocument || !toolbarModelUid) {
81
+ return activatorNode;
82
+ }
83
+ const matchedHosts = Array.from(
84
+ ownerDocument.querySelectorAll(
85
+ `[data-has-float-menu="true"][data-float-menu-model-uid="${toolbarModelUid}"]`
86
+ )
87
+ );
88
+ const popupRoot = floatToolbarContainer.closest(MENU_SUBMENU_POPUP_SELECTOR);
89
+ if (popupRoot) {
90
+ return matchedHosts.find((hostNode) => hostNode.closest(MENU_SUBMENU_POPUP_SELECTOR) === popupRoot) || activatorNode;
91
+ }
92
+ return matchedHosts.find((hostNode) => !hostNode.closest(MENU_SUBMENU_POPUP_SELECTOR)) || matchedHosts[0] || activatorNode;
93
+ }, "resolveDraggableHostNode");
55
94
  const DragHandler = /* @__PURE__ */ __name(({
56
95
  model,
57
96
  children = /* @__PURE__ */ import_react.default.createElement(import_icons.DragOutlined, null)
58
97
  }) => {
59
- const { attributes, listeners, setNodeRef } = (0, import_core.useDraggable)({ id: model.uid });
98
+ const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef } = (0, import_core.useDraggable)({ id: model.uid });
99
+ const dragHandlerRef = (0, import_react.useRef)(null);
100
+ const draggableNodeRef = (0, import_react.useRef)(null);
101
+ const pointerPressCleanupRef = (0, import_react.useRef)(null);
102
+ const isDraggingRef = (0, import_react.useRef)(isDragging);
103
+ const isPointerPressActiveRef = (0, import_react.useRef)(false);
104
+ const isToolbarDragActiveRef = (0, import_react.useRef)(false);
105
+ const syncDraggableNodeRef = (0, import_react.useCallback)(
106
+ (activatorNode) => {
107
+ const nextNode = resolveDraggableHostNode(activatorNode);
108
+ if (draggableNodeRef.current === nextNode) {
109
+ return;
110
+ }
111
+ draggableNodeRef.current = nextNode;
112
+ setNodeRef(nextNode);
113
+ },
114
+ [setNodeRef]
115
+ );
116
+ const setDragHandlerNodeRef = (0, import_react.useCallback)(
117
+ (node) => {
118
+ dragHandlerRef.current = node;
119
+ setActivatorNodeRef(node);
120
+ syncDraggableNodeRef(node);
121
+ },
122
+ [setActivatorNodeRef, syncDraggableNodeRef]
123
+ );
124
+ const dispatchToolbarDragActivity = (0, import_react.useCallback)(
125
+ (active) => {
126
+ var _a;
127
+ const ownerDocument = (_a = dragHandlerRef.current) == null ? void 0 : _a.ownerDocument;
128
+ if (!ownerDocument) {
129
+ return;
130
+ }
131
+ ownerDocument.dispatchEvent(
132
+ new CustomEvent(TOOLBAR_DRAG_ACTIVITY_EVENT, {
133
+ detail: { active, modelUid: model.uid }
134
+ })
135
+ );
136
+ },
137
+ [model.uid]
138
+ );
139
+ const dispatchToolbarDragAnchor = (0, import_react.useCallback)(
140
+ (detail) => {
141
+ var _a;
142
+ const ownerDocument = (_a = dragHandlerRef.current) == null ? void 0 : _a.ownerDocument;
143
+ if (!ownerDocument) {
144
+ return;
145
+ }
146
+ ownerDocument.dispatchEvent(
147
+ new CustomEvent(TOOLBAR_DRAG_ANCHOR_EVENT, {
148
+ detail: { modelUid: model.uid, point: detail.point }
149
+ })
150
+ );
151
+ },
152
+ [model.uid]
153
+ );
154
+ const clearPointerPressListeners = (0, import_react.useCallback)(() => {
155
+ var _a;
156
+ (_a = pointerPressCleanupRef.current) == null ? void 0 : _a.call(pointerPressCleanupRef);
157
+ pointerPressCleanupRef.current = null;
158
+ }, []);
159
+ const syncToolbarDragActivity = (0, import_react.useCallback)(() => {
160
+ const nextActive = isPointerPressActiveRef.current || isDraggingRef.current;
161
+ if (nextActive === isToolbarDragActiveRef.current) {
162
+ return;
163
+ }
164
+ isToolbarDragActiveRef.current = nextActive;
165
+ dispatchToolbarDragActivity(nextActive);
166
+ }, [dispatchToolbarDragActivity]);
167
+ const handlePointerPressEnd = (0, import_react.useCallback)(() => {
168
+ isPointerPressActiveRef.current = false;
169
+ clearPointerPressListeners();
170
+ syncToolbarDragActivity();
171
+ }, [clearPointerPressListeners, syncToolbarDragActivity]);
172
+ const registerPointerPressListeners = (0, import_react.useCallback)(() => {
173
+ var _a;
174
+ const ownerDocument = (_a = dragHandlerRef.current) == null ? void 0 : _a.ownerDocument;
175
+ const ownerWindow = ownerDocument == null ? void 0 : ownerDocument.defaultView;
176
+ if (!ownerDocument) {
177
+ return;
178
+ }
179
+ clearPointerPressListeners();
180
+ const handlePointerEnd = /* @__PURE__ */ __name(() => {
181
+ handlePointerPressEnd();
182
+ }, "handlePointerEnd");
183
+ const handleKeyDown = /* @__PURE__ */ __name((event) => {
184
+ if (event.key === "Escape") {
185
+ handlePointerPressEnd();
186
+ }
187
+ }, "handleKeyDown");
188
+ ownerDocument.addEventListener("pointerup", handlePointerEnd, true);
189
+ ownerDocument.addEventListener("pointercancel", handlePointerEnd, true);
190
+ ownerDocument.addEventListener("keydown", handleKeyDown, true);
191
+ ownerWindow == null ? void 0 : ownerWindow.addEventListener("blur", handlePointerEnd);
192
+ pointerPressCleanupRef.current = () => {
193
+ ownerDocument.removeEventListener("pointerup", handlePointerEnd, true);
194
+ ownerDocument.removeEventListener("pointercancel", handlePointerEnd, true);
195
+ ownerDocument.removeEventListener("keydown", handleKeyDown, true);
196
+ ownerWindow == null ? void 0 : ownerWindow.removeEventListener("blur", handlePointerEnd);
197
+ };
198
+ }, [clearPointerPressListeners, handlePointerPressEnd]);
199
+ (0, import_react.useEffect)(() => {
200
+ syncDraggableNodeRef(dragHandlerRef.current);
201
+ }, [syncDraggableNodeRef]);
202
+ (0, import_react.useEffect)(() => {
203
+ isDraggingRef.current = isDragging;
204
+ syncToolbarDragActivity();
205
+ }, [isDragging, syncToolbarDragActivity]);
206
+ (0, import_react.useEffect)(() => {
207
+ return () => {
208
+ if (isToolbarDragActiveRef.current) {
209
+ dispatchToolbarDragActivity(false);
210
+ }
211
+ isPointerPressActiveRef.current = false;
212
+ isDraggingRef.current = false;
213
+ isToolbarDragActiveRef.current = false;
214
+ clearPointerPressListeners();
215
+ };
216
+ }, [clearPointerPressListeners, dispatchToolbarDragActivity]);
60
217
  return /* @__PURE__ */ import_react.default.createElement(
61
218
  "span",
62
219
  {
63
- ref: setNodeRef,
220
+ ref: setDragHandlerNodeRef,
64
221
  ...listeners,
65
222
  ...attributes,
223
+ onPointerDownCapture: (event) => {
224
+ if (event.button !== 0) {
225
+ return;
226
+ }
227
+ dispatchToolbarDragAnchor({
228
+ point: {
229
+ x: event.clientX,
230
+ y: event.clientY
231
+ }
232
+ });
233
+ isPointerPressActiveRef.current = true;
234
+ syncToolbarDragActivity();
235
+ registerPointerPressListeners();
236
+ },
66
237
  style: {
67
238
  cursor: "grab"
68
239
  }
@@ -108,7 +279,35 @@ const DndProvider = /* @__PURE__ */ __name(({
108
279
  ...restProps
109
280
  }) => {
110
281
  const [activeId, setActiveId] = (0, import_react.useState)(null);
282
+ const [dragAnchorPoint, setDragAnchorPoint] = (0, import_react.useState)(null);
111
283
  const flowEngine = (0, import_provider.useFlowEngine)();
284
+ (0, import_react.useEffect)(() => {
285
+ if (typeof document === "undefined") {
286
+ return;
287
+ }
288
+ const handleToolbarDragAnchor = /* @__PURE__ */ __name((event) => {
289
+ var _a;
290
+ const customEvent = event;
291
+ setDragAnchorPoint(((_a = customEvent.detail) == null ? void 0 : _a.point) || null);
292
+ }, "handleToolbarDragAnchor");
293
+ document.addEventListener(TOOLBAR_DRAG_ANCHOR_EVENT, handleToolbarDragAnchor);
294
+ return () => {
295
+ document.removeEventListener(TOOLBAR_DRAG_ANCHOR_EVENT, handleToolbarDragAnchor);
296
+ };
297
+ }, []);
298
+ const overlayAnchorModifier = (0, import_react.useCallback)(
299
+ ({ active, activeNodeRect, transform }) => {
300
+ const nextTransform = resolveOverlayAnchorTransform({
301
+ activeId,
302
+ active,
303
+ transform,
304
+ activeNodeRect,
305
+ dragAnchorPoint
306
+ });
307
+ return nextTransform;
308
+ },
309
+ [activeId, dragAnchorPoint]
310
+ );
112
311
  return /* @__PURE__ */ import_react.default.createElement(
113
312
  import_core.DndContext,
114
313
  {
@@ -119,6 +318,7 @@ const DndProvider = /* @__PURE__ */ __name(({
119
318
  },
120
319
  onDragEnd: (event) => {
121
320
  setActiveId(null);
321
+ setDragAnchorPoint(null);
122
322
  if (!onDragEnd) {
123
323
  if (event.over) {
124
324
  flowEngine.moveModel(event.active.id, event.over.id, { persist });
@@ -127,30 +327,46 @@ const DndProvider = /* @__PURE__ */ __name(({
127
327
  onDragEnd(event);
128
328
  }
129
329
  },
330
+ onDragCancel: (event) => {
331
+ var _a;
332
+ setActiveId(null);
333
+ setDragAnchorPoint(null);
334
+ (_a = restProps.onDragCancel) == null ? void 0 : _a.call(restProps, event);
335
+ },
130
336
  ...restProps
131
337
  },
132
338
  children,
133
- (0, import_react_dom.createPortal)(
134
- /* @__PURE__ */ import_react.default.createElement(import_core.DragOverlay, { dropAnimation: null, zIndex: 2e3 }, activeId && /* @__PURE__ */ import_react.default.createElement(
135
- "span",
339
+ typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
340
+ /* @__PURE__ */ import_react.default.createElement(
341
+ import_core.DragOverlay,
136
342
  {
137
- style: {
138
- display: "inline-flex",
139
- alignItems: "center",
140
- whiteSpace: "nowrap",
141
- background: "#fff",
142
- border: "1px solid #1890ff",
143
- borderRadius: 4,
144
- padding: "4px 12px",
145
- color: "#1890ff",
146
- // fontSize: 18,
147
- boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
148
- }
343
+ dropAnimation: null,
344
+ modifiers: [overlayAnchorModifier],
345
+ zIndex: 2e3,
346
+ style: { pointerEvents: "none" }
149
347
  },
150
- flowEngine.translate("Dragging")
151
- )),
348
+ activeId && /* @__PURE__ */ import_react.default.createElement(
349
+ "span",
350
+ {
351
+ style: {
352
+ display: "inline-flex",
353
+ alignItems: "center",
354
+ whiteSpace: "nowrap",
355
+ background: "#fff",
356
+ border: "1px solid #1890ff",
357
+ borderRadius: 4,
358
+ padding: "4px 12px",
359
+ color: "#1890ff",
360
+ pointerEvents: "none",
361
+ // fontSize: 18,
362
+ boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
363
+ }
364
+ },
365
+ flowEngine.translate("Dragging")
366
+ )
367
+ ),
152
368
  document.body
153
- )
369
+ ) : null
154
370
  );
155
371
  }, "DndProvider");
156
372
  // Annotate the CommonJS export names for ESM import in node:
@@ -159,6 +375,8 @@ const DndProvider = /* @__PURE__ */ __name(({
159
375
  DragHandler,
160
376
  Droppable,
161
377
  EMPTY_COLUMN_UID,
378
+ TOOLBAR_DRAG_ACTIVITY_EVENT,
379
+ resolveOverlayAnchorTransform,
162
380
  ...require("./findModelUidPosition"),
163
381
  ...require("./gridDragPlanner")
164
382
  });
@@ -49,6 +49,22 @@ var import_utils = require("../../../../utils");
49
49
  var import_hooks = require("../../../../hooks");
50
50
  var import_SwitchWithTitle = require("../component/SwitchWithTitle");
51
51
  var import_SelectWithTitle = require("../component/SelectWithTitle");
52
+ const findExtraMenuItemByKey = /* @__PURE__ */ __name((items, targetKey) => {
53
+ var _a;
54
+ for (const item of items) {
55
+ const itemKey = String((item == null ? void 0 : item.key) ?? "");
56
+ if (itemKey === targetKey) {
57
+ return item;
58
+ }
59
+ if ((_a = item.children) == null ? void 0 : _a.length) {
60
+ const matched = findExtraMenuItemByKey(item.children, targetKey);
61
+ if (matched) {
62
+ return matched;
63
+ }
64
+ }
65
+ }
66
+ return void 0;
67
+ }, "findExtraMenuItemByKey");
52
68
  const walkSubModels = /* @__PURE__ */ __name((rootModel, options, cb) => {
53
69
  const maxDepth = options.maxDepth;
54
70
  const arrayLimit = typeof options.arrayLimit === "number" ? options.arrayLimit : Number.POSITIVE_INFINITY;
@@ -389,7 +405,10 @@ const DefaultSettingsIcon = /* @__PURE__ */ __name(({
389
405
  handleCopyPopupUid(cleanKey);
390
406
  return;
391
407
  }
392
- const extra = extraMenuItems.find((it) => (it == null ? void 0 : it.key) === originalKey || (it == null ? void 0 : it.key) === cleanKey);
408
+ const extra = findExtraMenuItemByKey(extraMenuItems, originalKey) || findExtraMenuItemByKey(extraMenuItems, cleanKey);
409
+ if (extra == null ? void 0 : extra.disabled) {
410
+ return;
411
+ }
393
412
  if (extra == null ? void 0 : extra.onClick) {
394
413
  closeDropdown();
395
414
  extra.onClick();
@@ -43,6 +43,10 @@ interface BaseFloatContextMenuProps {
43
43
  * Extra toolbar items to add to this context menu instance
44
44
  */
45
45
  extraToolbarItems?: ToolbarItemConfig[];
46
+ /**
47
+ * @default true
48
+ */
49
+ showDynamicFlowsEditor?: boolean;
46
50
  /**
47
51
  * @default 'inside'
48
52
  */
@@ -51,7 +51,8 @@ var import__ = require("../../../..");
51
51
  var import_reactive = require("../../../../reactive");
52
52
  var import_useFloatToolbarPortal = require("./useFloatToolbarPortal");
53
53
  var import_useFloatToolbarVisibility = require("./useFloatToolbarVisibility");
54
- const TOOLBAR_Z_INDEX = 999;
54
+ const TOOLBAR_ITEM_WIDTH = 19;
55
+ const DEFAULT_POPUP_BASE_Z_INDEX = 1e3;
55
56
  const getFloatMenuInstanceId = /* @__PURE__ */ __name((model) => {
56
57
  if (!model) {
57
58
  return "";
@@ -74,9 +75,10 @@ const toolbarPositionClassNames = {
74
75
  const toolbarContainerStyles = /* @__PURE__ */ __name(({
75
76
  showBackground,
76
77
  showBorder,
77
- ctx
78
+ ctx,
79
+ toolbarZIndex
78
80
  }) => import_css.css`
79
- z-index: ${TOOLBAR_Z_INDEX};
81
+ z-index: ${toolbarZIndex};
80
82
  opacity: 0;
81
83
  pointer-events: none;
82
84
  overflow: visible;
@@ -254,12 +256,15 @@ const detectButtonInDOM = /* @__PURE__ */ __name((container) => {
254
256
  }
255
257
  return false;
256
258
  }, "detectButtonInDOM");
257
- const renderToolbarItems = /* @__PURE__ */ __name((model, modelInstanceId, showDeleteButton, showCopyUidButton, flowEngine, settingsMenuLevel, extraToolbarItems, onSettingsMenuOpenChange, getPopupContainer) => {
259
+ const renderToolbarItems = /* @__PURE__ */ __name((model, modelInstanceId, showDeleteButton, showCopyUidButton, flowEngine, settingsMenuLevel, extraToolbarItems, showDynamicFlowsEditor = true, onSettingsMenuOpenChange, getPopupContainer) => {
258
260
  var _a, _b;
259
261
  const toolbarItems = ((_b = (_a = flowEngine == null ? void 0 : flowEngine.flowSettings) == null ? void 0 : _a.getToolbarItems) == null ? void 0 : _b.call(_a)) || [];
260
262
  const allToolbarItems = [...toolbarItems, ...extraToolbarItems || []];
261
263
  allToolbarItems.sort((a, b) => (a.sort || 0) - (b.sort || 0)).reverse();
262
264
  return allToolbarItems.filter((itemConfig) => {
265
+ if (itemConfig.key === "dynamic-flows-editor" && showDynamicFlowsEditor === false) {
266
+ return false;
267
+ }
263
268
  return itemConfig.visible ? itemConfig.visible(model) : true;
264
269
  }).map((itemConfig) => {
265
270
  const ItemComponent = itemConfig.component;
@@ -285,21 +290,23 @@ const buildToolbarContainerClassName = /* @__PURE__ */ __name(({
285
290
  showBackground,
286
291
  showBorder,
287
292
  ctx,
293
+ toolbarZIndex,
288
294
  portalRenderSnapshot,
289
295
  isToolbarVisible,
290
296
  className
291
297
  }) => [
292
- toolbarContainerStyles({ showBackground, showBorder, ctx }),
298
+ toolbarContainerStyles({ showBackground, showBorder, ctx, toolbarZIndex }),
293
299
  "nb-toolbar-portal",
294
300
  (portalRenderSnapshot == null ? void 0 : portalRenderSnapshot.positioningMode) === "absolute" ? "nb-toolbar-portal-absolute" : "nb-toolbar-portal-fixed",
295
301
  isToolbarVisible ? "nb-toolbar-visible" : "",
296
302
  (className == null ? void 0 : className.includes("nb-in-template")) ? "nb-in-template" : ""
297
303
  ].filter(Boolean).join(" "), "buildToolbarContainerClassName");
298
- const buildToolbarContainerStyle = /* @__PURE__ */ __name((portalRect, toolbarStyle) => ({
304
+ const buildToolbarContainerStyle = /* @__PURE__ */ __name((portalRect, toolbarStyle, toolbarItemCount = 0) => ({
299
305
  top: `${portalRect.top}px`,
300
306
  left: `${portalRect.left}px`,
301
307
  width: `${portalRect.width}px`,
302
308
  height: `${portalRect.height}px`,
309
+ minWidth: toolbarItemCount ? `${TOOLBAR_ITEM_WIDTH * toolbarItemCount}px` : void 0,
303
310
  ...(0, import_useFloatToolbarPortal.omitToolbarPortalInsetStyle)(toolbarStyle)
304
311
  }), "buildToolbarContainerStyle");
305
312
  const isModelByIdProps = /* @__PURE__ */ __name((props) => {
@@ -392,9 +399,11 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
392
399
  showDragHandle = false,
393
400
  settingsMenuLevel,
394
401
  extraToolbarItems,
402
+ showDynamicFlowsEditor = true,
395
403
  toolbarStyle,
396
404
  toolbarPosition = "inside"
397
405
  }) => {
406
+ var _a;
398
407
  const [hasButton, setHasButton] = (0, import_react.useState)(false);
399
408
  const containerRef = (0, import_react.useRef)(null);
400
409
  const toolbarContainerRef = (0, import_react.useRef)(null);
@@ -447,6 +456,7 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
447
456
  flowEngine,
448
457
  settingsMenuLevel,
449
458
  extraToolbarItems,
459
+ showDynamicFlowsEditor,
450
460
  handleSettingsMenuOpenChange,
451
461
  getPopupContainer
452
462
  ) : [],
@@ -458,7 +468,8 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
458
468
  model,
459
469
  settingsMenuLevel,
460
470
  showCopyUidButton,
461
- showDeleteButton
471
+ showDeleteButton,
472
+ showDynamicFlowsEditor
462
473
  ]
463
474
  );
464
475
  (0, import_react.useEffect)(() => {
@@ -488,15 +499,17 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
488
499
  if (!enabled || !children) {
489
500
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, children);
490
501
  }
502
+ const toolbarZIndex = (((_a = model.context.themeToken) == null ? void 0 : _a.zIndexPopupBase) || DEFAULT_POPUP_BASE_Z_INDEX) + 1;
491
503
  const toolbarContainerClassName = buildToolbarContainerClassName({
492
504
  showBackground,
493
505
  showBorder,
494
506
  ctx: model.context,
507
+ toolbarZIndex,
495
508
  portalRenderSnapshot,
496
509
  isToolbarVisible,
497
510
  className
498
511
  });
499
- const toolbarContainerStyle = buildToolbarContainerStyle(portalRect, toolbarStyle);
512
+ const toolbarContainerStyle = buildToolbarContainerStyle(portalRect, toolbarStyle, toolbarItems.length);
500
513
  const toolbarNode = shouldRenderToolbar ? /* @__PURE__ */ import_react.default.createElement(
501
514
  "div",
502
515
  {
@@ -33,6 +33,7 @@ __export(useFloatToolbarPortal_exports, {
33
33
  module.exports = __toCommonJS(useFloatToolbarPortal_exports);
34
34
  var import_react = require("react");
35
35
  const APP_CONTAINER_SELECTOR = "#nocobase-app-container";
36
+ const MENU_SUBMENU_POPUP_SELECTOR = ".ant-menu-submenu-popup";
36
37
  const DRAWER_CONTENT_WRAPPER_SELECTOR = ".ant-drawer-content-wrapper";
37
38
  const DRAWER_CONTENT_SELECTOR = ".ant-drawer-content";
38
39
  const DRAWER_ROOT_SELECTOR = ".ant-drawer-root";
@@ -52,6 +53,7 @@ const createAbsolutePortalHostConfig = /* @__PURE__ */ __name((element) => ({
52
53
  positioningMode: "absolute"
53
54
  }), "createAbsolutePortalHostConfig");
54
55
  const popupPortalHostResolvers = [
56
+ (hostEl) => getClosestElement(hostEl, MENU_SUBMENU_POPUP_SELECTOR),
55
57
  (hostEl) => getClosestElement(hostEl, DRAWER_CONTENT_WRAPPER_SELECTOR),
56
58
  (hostEl) => getClosestElement(hostEl, MODAL_WRAP_SELECTOR),
57
59
  (hostEl) => getClosestElement(hostEl, MODAL_SELECTOR),