@nocobase/flow-engine 2.1.0-alpha.3 → 2.1.0-alpha.31

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 (165) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/JSRunner.d.ts +10 -1
  4. package/lib/JSRunner.js +50 -5
  5. package/lib/ViewScopedFlowEngine.js +5 -1
  6. package/lib/components/FieldModelRenderer.js +2 -2
  7. package/lib/components/FlowModelRenderer.d.ts +3 -1
  8. package/lib/components/FlowModelRenderer.js +12 -6
  9. package/lib/components/FormItem.d.ts +6 -0
  10. package/lib/components/FormItem.js +11 -3
  11. package/lib/components/MobilePopup.js +6 -5
  12. package/lib/components/dnd/gridDragPlanner.d.ts +59 -2
  13. package/lib/components/dnd/gridDragPlanner.js +613 -21
  14. package/lib/components/dnd/index.d.ts +19 -1
  15. package/lib/components/dnd/index.js +243 -23
  16. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +2 -1
  17. package/lib/components/settings/wrappers/component/SelectWithTitle.js +14 -12
  18. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +3 -0
  19. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +68 -10
  20. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +23 -43
  21. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +352 -295
  22. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +16 -2
  23. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.d.ts +36 -0
  24. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +274 -0
  25. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.d.ts +30 -0
  26. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +315 -0
  27. package/lib/components/subModel/AddSubModelButton.js +27 -1
  28. package/lib/components/subModel/index.d.ts +1 -0
  29. package/lib/components/subModel/index.js +19 -0
  30. package/lib/components/subModel/utils.d.ts +1 -1
  31. package/lib/components/subModel/utils.js +2 -2
  32. package/lib/data-source/index.d.ts +75 -0
  33. package/lib/data-source/index.js +246 -4
  34. package/lib/executor/FlowExecutor.js +31 -8
  35. package/lib/flowContext.d.ts +2 -0
  36. package/lib/flowContext.js +31 -1
  37. package/lib/flowEngine.d.ts +151 -1
  38. package/lib/flowEngine.js +389 -15
  39. package/lib/flowI18n.js +2 -1
  40. package/lib/flowSettings.d.ts +14 -6
  41. package/lib/flowSettings.js +34 -6
  42. package/lib/lazy-helper.d.ts +14 -0
  43. package/lib/lazy-helper.js +71 -0
  44. package/lib/locale/en-US.json +1 -0
  45. package/lib/locale/index.d.ts +2 -0
  46. package/lib/locale/zh-CN.json +1 -0
  47. package/lib/models/DisplayItemModel.d.ts +1 -1
  48. package/lib/models/EditableItemModel.d.ts +1 -1
  49. package/lib/models/FilterableItemModel.d.ts +1 -1
  50. package/lib/models/flowModel.d.ts +13 -10
  51. package/lib/models/flowModel.js +78 -18
  52. package/lib/provider.js +38 -23
  53. package/lib/reactive/observer.js +46 -16
  54. package/lib/runjs-context/registry.d.ts +1 -1
  55. package/lib/runjs-context/setup.js +20 -12
  56. package/lib/runjs-context/snippets/index.js +13 -2
  57. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts +11 -0
  58. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.js +50 -0
  59. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts +11 -0
  60. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
  61. package/lib/scheduler/ModelOperationScheduler.d.ts +5 -1
  62. package/lib/scheduler/ModelOperationScheduler.js +3 -2
  63. package/lib/types.d.ts +47 -1
  64. package/lib/utils/createCollectionContextMeta.js +6 -2
  65. package/lib/utils/index.d.ts +2 -2
  66. package/lib/utils/index.js +4 -0
  67. package/lib/utils/parsePathnameToViewParams.js +1 -1
  68. package/lib/utils/runjsTemplateCompat.js +1 -1
  69. package/lib/utils/runjsValue.js +41 -11
  70. package/lib/utils/schema-utils.d.ts +7 -1
  71. package/lib/utils/schema-utils.js +19 -0
  72. package/lib/views/FlowView.d.ts +7 -1
  73. package/lib/views/runViewBeforeClose.d.ts +10 -0
  74. package/lib/views/runViewBeforeClose.js +45 -0
  75. package/lib/views/useDialog.d.ts +2 -1
  76. package/lib/views/useDialog.js +20 -3
  77. package/lib/views/useDrawer.d.ts +2 -1
  78. package/lib/views/useDrawer.js +20 -3
  79. package/lib/views/usePage.d.ts +2 -1
  80. package/lib/views/usePage.js +10 -3
  81. package/package.json +6 -5
  82. package/src/JSRunner.ts +68 -4
  83. package/src/ViewScopedFlowEngine.ts +4 -0
  84. package/src/__tests__/JSRunner.test.ts +27 -1
  85. package/src/__tests__/flow-engine.test.ts +166 -0
  86. package/src/__tests__/flowContext.test.ts +65 -1
  87. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  88. package/src/__tests__/flowSettings.test.ts +94 -15
  89. package/src/__tests__/objectVariable.test.ts +24 -0
  90. package/src/__tests__/provider.test.tsx +24 -2
  91. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  92. package/src/__tests__/runjsContext.test.ts +16 -0
  93. package/src/__tests__/runjsContextRuntime.test.ts +2 -0
  94. package/src/__tests__/runjsPreprocessDefault.test.ts +23 -0
  95. package/src/__tests__/runjsSnippets.test.ts +21 -0
  96. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  97. package/src/components/FieldModelRenderer.tsx +2 -1
  98. package/src/components/FlowModelRenderer.tsx +18 -6
  99. package/src/components/FormItem.tsx +7 -1
  100. package/src/components/MobilePopup.tsx +4 -2
  101. package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
  102. package/src/components/__tests__/FormItem.test.tsx +25 -0
  103. package/src/components/__tests__/dnd.test.ts +44 -0
  104. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +20 -10
  105. package/src/components/__tests__/gridDragPlanner.test.ts +558 -3
  106. package/src/components/dnd/__tests__/DndProvider.test.tsx +98 -0
  107. package/src/components/dnd/gridDragPlanner.ts +758 -19
  108. package/src/components/dnd/index.tsx +291 -27
  109. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +21 -9
  110. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +88 -10
  111. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +487 -440
  112. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +18 -2
  113. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +189 -3
  114. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +778 -0
  115. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +360 -0
  116. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +361 -0
  117. package/src/components/subModel/AddSubModelButton.tsx +32 -2
  118. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +142 -32
  119. package/src/components/subModel/index.ts +1 -0
  120. package/src/components/subModel/utils.ts +1 -1
  121. package/src/data-source/__tests__/collection.test.ts +41 -2
  122. package/src/data-source/__tests__/index.test.ts +68 -1
  123. package/src/data-source/index.ts +303 -5
  124. package/src/executor/FlowExecutor.ts +34 -9
  125. package/src/executor/__tests__/flowExecutor.test.ts +57 -0
  126. package/src/flowContext.ts +37 -3
  127. package/src/flowEngine.ts +445 -11
  128. package/src/flowI18n.ts +2 -1
  129. package/src/flowSettings.ts +40 -6
  130. package/src/lazy-helper.tsx +57 -0
  131. package/src/locale/en-US.json +1 -0
  132. package/src/locale/zh-CN.json +1 -0
  133. package/src/models/DisplayItemModel.tsx +1 -1
  134. package/src/models/EditableItemModel.tsx +1 -1
  135. package/src/models/FilterableItemModel.tsx +1 -1
  136. package/src/models/__tests__/dispatchEvent.when.test.ts +214 -0
  137. package/src/models/__tests__/flowModel.test.ts +19 -3
  138. package/src/models/flowModel.tsx +119 -33
  139. package/src/provider.tsx +41 -25
  140. package/src/reactive/__tests__/observer.test.tsx +82 -0
  141. package/src/reactive/observer.tsx +87 -25
  142. package/src/runjs-context/registry.ts +1 -1
  143. package/src/runjs-context/setup.ts +22 -12
  144. package/src/runjs-context/snippets/index.ts +12 -1
  145. package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
  146. package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
  147. package/src/scheduler/ModelOperationScheduler.ts +14 -3
  148. package/src/types.ts +60 -0
  149. package/src/utils/__tests__/createCollectionContextMeta.test.ts +48 -0
  150. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +7 -0
  151. package/src/utils/__tests__/runjsValue.test.ts +11 -0
  152. package/src/utils/__tests__/utils.test.ts +62 -0
  153. package/src/utils/createCollectionContextMeta.ts +6 -2
  154. package/src/utils/index.ts +2 -1
  155. package/src/utils/parsePathnameToViewParams.ts +2 -2
  156. package/src/utils/runjsTemplateCompat.ts +1 -1
  157. package/src/utils/runjsValue.ts +50 -11
  158. package/src/utils/schema-utils.ts +30 -1
  159. package/src/views/FlowView.tsx +11 -1
  160. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  161. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +13 -12
  162. package/src/views/runViewBeforeClose.ts +19 -0
  163. package/src/views/useDialog.tsx +25 -3
  164. package/src/views/useDrawer.tsx +25 -3
  165. package/src/views/usePage.tsx +12 -3
@@ -41,6 +41,7 @@ __export(FlowsFloatContextMenu_exports, {
41
41
  });
42
42
  module.exports = __toCommonJS(FlowsFloatContextMenu_exports);
43
43
  var import_react = __toESM(require("react"));
44
+ var import_react_dom = require("react-dom");
44
45
  var import_antd = require("antd");
45
46
  var import_css = require("@emotion/css");
46
47
  var import_hooks = require("../../../../hooks");
@@ -48,238 +49,266 @@ var import_provider = require("../../../../provider");
48
49
  var import_utils = require("../../../../utils");
49
50
  var import__ = require("../../../..");
50
51
  var import_reactive = require("../../../../reactive");
51
- const detectButtonInDOM = /* @__PURE__ */ __name((container) => {
52
- if (!container) return false;
53
- const directChildren = container.children;
54
- for (let i = 0; i < directChildren.length; i++) {
55
- const child = directChildren[i];
56
- if (child.tagName === "BUTTON" || child.getAttribute("role") === "button" || child.classList.contains("ant-btn")) {
57
- return true;
58
- }
59
- }
60
- return false;
61
- }, "detectButtonInDOM");
62
- const renderToolbarItems = /* @__PURE__ */ __name((model, showDeleteButton, showCopyUidButton, flowEngine, settingsMenuLevel, extraToolbarItems) => {
63
- var _a, _b;
64
- const toolbarItems = ((_b = (_a = flowEngine == null ? void 0 : flowEngine.flowSettings) == null ? void 0 : _a.getToolbarItems) == null ? void 0 : _b.call(_a)) || [];
65
- const allToolbarItems = [...toolbarItems, ...extraToolbarItems || []];
66
- allToolbarItems.sort((a, b) => (a.sort || 0) - (b.sort || 0)).reverse();
67
- return allToolbarItems.filter((itemConfig) => {
68
- return itemConfig.visible ? itemConfig.visible(model) : true;
69
- }).map((itemConfig) => {
70
- const ItemComponent = itemConfig.component;
71
- if (itemConfig.key === "settings-menu") {
72
- return /* @__PURE__ */ import_react.default.createElement(
73
- ItemComponent,
74
- {
75
- key: itemConfig.key,
76
- model,
77
- id: model.uid,
78
- showDeleteButton,
79
- showCopyUidButton,
80
- menuLevels: settingsMenuLevel
81
- }
82
- );
83
- }
84
- return /* @__PURE__ */ import_react.default.createElement(ItemComponent, { key: itemConfig.key, model });
85
- });
86
- }, "renderToolbarItems");
52
+ var import_useFloatToolbarPortal = require("./useFloatToolbarPortal");
53
+ var import_useFloatToolbarVisibility = require("./useFloatToolbarVisibility");
87
54
  const TOOLBAR_ITEM_WIDTH = 19;
88
- const toolbarPositionToCSS = {
89
- inside: `
90
- top: 2px;
91
- `,
92
- above: `
93
- top: 0px;
94
- transform: translateY(-100%);
95
- padding-bottom: 0px;
96
- margin-bottom: -2px;
97
- `,
98
- below: `
99
- top: 0px;
100
- transform: translateY(100%);
101
- padding-top: 2px;
102
- margin-top: -2px;
103
- `
104
- };
105
- const floatContainerStyles = /* @__PURE__ */ __name(({ showBackground, showBorder, ctx, toolbarPosition = "inside", toolbarCount }) => import_css.css`
55
+ const DEFAULT_POPUP_BASE_Z_INDEX = 1e3;
56
+ const getFloatMenuInstanceId = /* @__PURE__ */ __name((model) => {
57
+ if (!model) {
58
+ return "";
59
+ }
60
+ const forkId = (model == null ? void 0 : model.isFork) ? model == null ? void 0 : model.forkId : void 0;
61
+ return forkId == null || forkId === "" ? String(model.uid || "") : `${String(model.uid || "")}::${String(forkId)}`;
62
+ }, "getFloatMenuInstanceId");
63
+ const hostContainerStyles = import_css.css`
106
64
  position: relative;
107
65
 
108
- /* 当检测到button时使用inline-block */
109
66
  &.has-button-child {
110
67
  display: inline-block;
111
68
  }
69
+ `;
70
+ const toolbarPositionClassNames = {
71
+ inside: "nb-toolbar-position-inside",
72
+ above: "nb-toolbar-position-above",
73
+ below: "nb-toolbar-position-below"
74
+ };
75
+ const toolbarContainerStyles = /* @__PURE__ */ __name(({
76
+ showBackground,
77
+ showBorder,
78
+ ctx,
79
+ toolbarZIndex
80
+ }) => import_css.css`
81
+ z-index: ${toolbarZIndex};
82
+ opacity: 0;
83
+ pointer-events: none;
84
+ overflow: visible;
85
+ transition: opacity 0.12s ease;
86
+ background: ${showBackground ? "var(--colorBgSettingsHover)" : "transparent"};
87
+ border: ${showBorder ? "2px solid var(--colorBorderSettingsHover)" : "none"};
88
+ border-radius: ${ctx.themeToken.borderRadiusLG}px;
112
89
 
113
- /* 正常的hover行为 - 添加延迟显示 */
114
- &:hover > .nb-toolbar-container {
90
+ &.nb-toolbar-visible {
115
91
  opacity: 1;
116
92
  transition-delay: 0.1s;
93
+ }
117
94
 
118
- .nb-toolbar-container-icons {
119
- display: block;
120
- }
95
+ &.nb-toolbar-portal {
96
+ top: 0;
97
+ left: 0;
121
98
  }
122
99
 
123
- /* 当有.hide-parent-menu类时隐藏菜单 */
124
- &.hide-parent-menu > .nb-toolbar-container {
125
- opacity: 0 !important;
100
+ &.nb-toolbar-portal-fixed {
101
+ position: fixed;
126
102
  }
127
103
 
128
- > .nb-toolbar-container {
104
+ &.nb-toolbar-portal-absolute {
129
105
  position: absolute;
130
- top: 0;
131
- bottom: 0;
132
- left: 0;
133
- right: 0;
134
- z-index: 999;
135
- opacity: 0;
136
- background: ${showBackground ? "var(--colorBgSettingsHover)" : ""};
137
- border: ${showBorder ? "2px solid var(--colorBorderSettingsHover)" : ""};
138
- border-radius: ${ctx.themeToken.borderRadiusLG}px;
106
+ }
107
+
108
+ &.nb-in-template {
109
+ background: var(--colorTemplateBgSettingsHover);
110
+ }
111
+
112
+ > .nb-toolbar-container-title {
139
113
  pointer-events: none;
140
- min-width: ${TOOLBAR_ITEM_WIDTH * toolbarCount}px;
114
+ position: absolute;
115
+ top: 2px;
116
+ left: 2px;
117
+ display: flex;
118
+ align-items: center;
119
+ gap: 4px;
120
+ height: 16px;
121
+ padding: 0;
122
+ font-size: 12px;
123
+ line-height: 16px;
124
+ border-bottom-right-radius: 2px;
125
+ border-radius: 2px;
141
126
 
142
- &.nb-in-template {
143
- background: var(--colorTemplateBgSettingsHover);
127
+ .title-tag {
128
+ display: inline-flex;
129
+ padding: 0 3px;
130
+ border-radius: 2px;
131
+ background: var(--colorSettings);
132
+ color: #fff;
144
133
  }
134
+ }
145
135
 
146
- > .nb-toolbar-container-title {
147
- pointer-events: none;
148
- position: absolute;
149
- font-size: 12px;
150
- padding: 0;
151
- line-height: 16px;
152
- height: 16px;
153
- border-bottom-right-radius: 2px;
154
- border-radius: 2px;
155
- top: 2px;
156
- left: 2px;
157
- display: flex;
158
- align-items: center;
159
- gap: 4px;
136
+ > .nb-toolbar-container-icons {
137
+ display: none;
138
+ position: absolute;
139
+ right: 2px;
140
+ line-height: 16px;
141
+ pointer-events: all;
160
142
 
161
- .title-tag {
162
- padding: 0 3px;
163
- border-radius: 2px;
164
- background: var(--colorSettings);
165
- color: #fff;
166
- display: inline-flex;
167
- }
143
+ &.nb-toolbar-position-inside {
144
+ top: 2px;
168
145
  }
169
146
 
170
- > .nb-toolbar-container-icons {
171
- display: none; // 防止遮挡其它 icons
172
- position: absolute;
173
- right: 2px;
174
- ${toolbarPositionToCSS[toolbarPosition] || ""}
175
- line-height: 16px;
176
- pointer-events: all;
147
+ &.nb-toolbar-position-above {
148
+ top: 0;
149
+ transform: translateY(-100%);
150
+ padding-bottom: 0;
151
+ margin-bottom: -2px;
152
+ }
177
153
 
178
- .ant-space-item {
179
- background-color: var(--colorSettings);
180
- color: #fff;
181
- line-height: 16px;
182
- width: 16px;
183
- height: 16px;
184
- padding: 2px;
185
- display: flex;
186
- align-items: center;
187
- justify-content: center;
188
- }
154
+ &.nb-toolbar-position-below {
155
+ top: 0;
156
+ transform: translateY(100%);
157
+ padding-top: 2px;
158
+ margin-top: -2px;
189
159
  }
190
160
 
191
- /* 拖拽把手样式 - 参考 AirTable 样式 */
192
- > .resize-handle {
193
- position: absolute;
194
- pointer-events: all;
195
- background: var(--colorSettings);
196
- opacity: 0.6;
197
- border-radius: 4px;
161
+ .ant-space-item {
198
162
  display: flex;
199
163
  align-items: center;
200
164
  justify-content: center;
165
+ width: 16px;
166
+ height: 16px;
167
+ padding: 2px;
168
+ line-height: 16px;
169
+ background-color: var(--colorSettings);
170
+ color: #fff;
171
+ }
172
+ }
201
173
 
202
- &:hover {
203
- opacity: 0.9;
204
- background: var(--colorSettingsHover, var(--colorSettings));
205
- }
174
+ &.nb-toolbar-visible > .nb-toolbar-container-icons {
175
+ display: block;
176
+ }
206
177
 
207
- &::before {
208
- content: '';
209
- position: absolute;
210
- background: rgba(255, 255, 255, 0.9);
211
- border-radius: 50%;
212
- }
178
+ > .resize-handle {
179
+ position: absolute;
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ pointer-events: all;
184
+ opacity: 0.6;
185
+ border-radius: 4px;
186
+ background: var(--colorSettings);
213
187
 
214
- &::after {
215
- content: '';
216
- position: absolute;
217
- background: rgba(255, 255, 255, 0.9);
218
- border-radius: 50%;
219
- }
188
+ &:hover {
189
+ opacity: 0.9;
190
+ background: var(--colorSettingsHover, var(--colorSettings));
220
191
  }
221
192
 
222
- > .resize-handle-left {
223
- left: -4px;
224
- top: 50%;
225
- transform: translateY(-50%);
226
- width: 6px;
227
- height: 20px;
228
- cursor: ew-resize;
193
+ &::before {
194
+ content: '';
195
+ position: absolute;
196
+ border-radius: 50%;
197
+ background: rgba(255, 255, 255, 0.9);
198
+ }
229
199
 
230
- &::before {
231
- width: 2px;
232
- height: 2px;
233
- top: 6px;
234
- left: 50%;
235
- transform: translateX(-50%);
236
- box-shadow:
237
- 0 4px 0 rgba(255, 255, 255, 0.9),
238
- 0 8px 0 rgba(255, 255, 255, 0.9);
239
- }
200
+ &::after {
201
+ content: '';
202
+ position: absolute;
203
+ border-radius: 50%;
204
+ background: rgba(255, 255, 255, 0.9);
240
205
  }
206
+ }
241
207
 
242
- > .resize-handle-right {
243
- right: -4px;
244
- top: 50%;
245
- transform: translateY(-50%);
246
- width: 6px;
247
- height: 20px;
248
- cursor: ew-resize;
208
+ > .resize-handle-left {
209
+ top: 50%;
210
+ left: -4px;
211
+ width: 6px;
212
+ height: 20px;
213
+ cursor: ew-resize;
214
+ transform: translateY(-50%);
249
215
 
250
- &::before {
251
- width: 2px;
252
- height: 2px;
253
- top: 6px;
254
- left: 50%;
255
- transform: translateX(-50%);
256
- box-shadow:
257
- 0 4px 0 rgba(255, 255, 255, 0.9),
258
- 0 8px 0 rgba(255, 255, 255, 0.9);
259
- }
216
+ &::before {
217
+ top: 6px;
218
+ left: 50%;
219
+ width: 2px;
220
+ height: 2px;
221
+ transform: translateX(-50%);
222
+ box-shadow:
223
+ 0 4px 0 rgba(255, 255, 255, 0.9),
224
+ 0 8px 0 rgba(255, 255, 255, 0.9);
260
225
  }
226
+ }
227
+
228
+ > .resize-handle-right {
229
+ top: 50%;
230
+ right: -4px;
231
+ width: 6px;
232
+ height: 20px;
233
+ cursor: ew-resize;
234
+ transform: translateY(-50%);
261
235
 
262
- > .resize-handle-bottom {
263
- bottom: -4px;
236
+ &::before {
237
+ top: 6px;
264
238
  left: 50%;
239
+ width: 2px;
240
+ height: 2px;
265
241
  transform: translateX(-50%);
266
- width: 20px;
267
- height: 6px;
268
- cursor: ns-resize;
269
-
270
- &::before {
271
- width: 2px;
272
- height: 2px;
273
- left: 6px;
274
- top: 50%;
275
- transform: translateY(-50%);
276
- box-shadow:
277
- 4px 0 0 rgba(255, 255, 255, 0.9),
278
- 8px 0 0 rgba(255, 255, 255, 0.9);
279
- }
242
+ box-shadow:
243
+ 0 4px 0 rgba(255, 255, 255, 0.9),
244
+ 0 8px 0 rgba(255, 255, 255, 0.9);
245
+ }
246
+ }
247
+ `, "toolbarContainerStyles");
248
+ const detectButtonInDOM = /* @__PURE__ */ __name((container) => {
249
+ if (!container) return false;
250
+ const directChildren = container.children;
251
+ for (let i = 0; i < directChildren.length; i++) {
252
+ const child = directChildren[i];
253
+ if (child.tagName === "BUTTON" || child.getAttribute("role") === "button" || child.classList.contains("ant-btn")) {
254
+ return true;
280
255
  }
281
256
  }
282
- `, "floatContainerStyles");
257
+ return false;
258
+ }, "detectButtonInDOM");
259
+ const renderToolbarItems = /* @__PURE__ */ __name((model, modelInstanceId, showDeleteButton, showCopyUidButton, flowEngine, settingsMenuLevel, extraToolbarItems, showDynamicFlowsEditor = true, onSettingsMenuOpenChange, getPopupContainer) => {
260
+ var _a, _b;
261
+ const toolbarItems = ((_b = (_a = flowEngine == null ? void 0 : flowEngine.flowSettings) == null ? void 0 : _a.getToolbarItems) == null ? void 0 : _b.call(_a)) || [];
262
+ const allToolbarItems = [...toolbarItems, ...extraToolbarItems || []];
263
+ allToolbarItems.sort((a, b) => (a.sort || 0) - (b.sort || 0)).reverse();
264
+ return allToolbarItems.filter((itemConfig) => {
265
+ if (itemConfig.key === "dynamic-flows-editor" && showDynamicFlowsEditor === false) {
266
+ return false;
267
+ }
268
+ return itemConfig.visible ? itemConfig.visible(model) : true;
269
+ }).map((itemConfig) => {
270
+ const ItemComponent = itemConfig.component;
271
+ if (itemConfig.key === "settings-menu") {
272
+ return /* @__PURE__ */ import_react.default.createElement(
273
+ ItemComponent,
274
+ {
275
+ key: itemConfig.key,
276
+ model,
277
+ id: modelInstanceId,
278
+ showDeleteButton,
279
+ showCopyUidButton,
280
+ menuLevels: settingsMenuLevel,
281
+ onDropdownVisibleChange: onSettingsMenuOpenChange,
282
+ getPopupContainer
283
+ }
284
+ );
285
+ }
286
+ return /* @__PURE__ */ import_react.default.createElement(ItemComponent, { key: itemConfig.key, model });
287
+ });
288
+ }, "renderToolbarItems");
289
+ const buildToolbarContainerClassName = /* @__PURE__ */ __name(({
290
+ showBackground,
291
+ showBorder,
292
+ ctx,
293
+ toolbarZIndex,
294
+ portalRenderSnapshot,
295
+ isToolbarVisible,
296
+ className
297
+ }) => [
298
+ toolbarContainerStyles({ showBackground, showBorder, ctx, toolbarZIndex }),
299
+ "nb-toolbar-portal",
300
+ (portalRenderSnapshot == null ? void 0 : portalRenderSnapshot.positioningMode) === "absolute" ? "nb-toolbar-portal-absolute" : "nb-toolbar-portal-fixed",
301
+ isToolbarVisible ? "nb-toolbar-visible" : "",
302
+ (className == null ? void 0 : className.includes("nb-in-template")) ? "nb-in-template" : ""
303
+ ].filter(Boolean).join(" "), "buildToolbarContainerClassName");
304
+ const buildToolbarContainerStyle = /* @__PURE__ */ __name((portalRect, toolbarStyle, toolbarItemCount = 0) => ({
305
+ top: `${portalRect.top}px`,
306
+ left: `${portalRect.left}px`,
307
+ width: `${portalRect.width}px`,
308
+ height: `${portalRect.height}px`,
309
+ minWidth: toolbarItemCount ? `${TOOLBAR_ITEM_WIDTH * toolbarItemCount}px` : void 0,
310
+ ...(0, import_useFloatToolbarPortal.omitToolbarPortalInsetStyle)(toolbarStyle)
311
+ }), "buildToolbarContainerStyle");
283
312
  const isModelByIdProps = /* @__PURE__ */ __name((props) => {
284
313
  return "uid" in props && "modelClassName" in props && Boolean(props.uid) && Boolean(props.modelClassName);
285
314
  }, "isModelByIdProps");
@@ -290,9 +319,8 @@ const FlowsFloatContextMenu = (0, import_reactive.observer)((props) => {
290
319
  }
291
320
  if (isModelByIdProps(props)) {
292
321
  return /* @__PURE__ */ import_react.default.createElement(FlowsFloatContextMenuWithModelById, { ...props });
293
- } else {
294
- return /* @__PURE__ */ import_react.default.createElement(FlowsFloatContextMenuWithModel, { ...props });
295
322
  }
323
+ return /* @__PURE__ */ import_react.default.createElement(FlowsFloatContextMenuWithModel, { ...props });
296
324
  });
297
325
  const ResizeHandles = /* @__PURE__ */ __name((props) => {
298
326
  const isDraggingRef = (0, import_react.useRef)(false);
@@ -303,27 +331,13 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
303
331
  (e) => {
304
332
  if (!isDraggingRef.current || !dragTypeRef.current) return;
305
333
  const deltaX = e.clientX - dragStartPosRef.current.x;
306
- const deltaY = e.clientY - dragStartPosRef.current.y;
307
- let resizeDistance = 0;
308
334
  switch (dragTypeRef.current) {
309
335
  case "left":
310
- resizeDistance = -deltaX;
311
- props.model.parent.emitter.emit("onResizeLeft", { resizeDistance, model: props.model });
336
+ props.model.parent.emitter.emit("onResizeLeft", { resizeDistance: -deltaX, model: props.model });
312
337
  break;
313
338
  case "right":
314
- resizeDistance = deltaX;
315
- props.model.parent.emitter.emit("onResizeRight", { resizeDistance, model: props.model });
339
+ props.model.parent.emitter.emit("onResizeRight", { resizeDistance: deltaX, model: props.model });
316
340
  break;
317
- case "bottom":
318
- resizeDistance = deltaY;
319
- props.model.parent.emitter.emit("onResizeBottom", { resizeDistance, model: props.model });
320
- break;
321
- case "corner": {
322
- const widthDelta = deltaX;
323
- const heightDelta = deltaY;
324
- props.model.parent.emitter.emit("onResizeCorner", { widthDelta, heightDelta, model: props.model });
325
- break;
326
- }
327
341
  }
328
342
  },
329
343
  [props.model]
@@ -336,7 +350,7 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
336
350
  document.removeEventListener("mouseup", handleDragEnd);
337
351
  props.model.parent.emitter.emit("onResizeEnd");
338
352
  onDragEnd == null ? void 0 : onDragEnd();
339
- }, [handleDragMove, props.model, onDragEnd]);
353
+ }, [handleDragMove, onDragEnd, props.model]);
340
354
  const handleDragStart = (0, import_react.useCallback)(
341
355
  (e, type) => {
342
356
  e.preventDefault();
@@ -355,6 +369,8 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
355
369
  {
356
370
  className: "resize-handle resize-handle-left",
357
371
  title: "\u62D6\u62FD\u8C03\u8282\u5BBD\u5EA6",
372
+ onMouseEnter: props.onMouseEnter,
373
+ onMouseLeave: props.onMouseLeave,
358
374
  onMouseDown: (e) => handleDragStart(e, "left")
359
375
  }
360
376
  ), /* @__PURE__ */ import_react.default.createElement(
@@ -362,6 +378,8 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
362
378
  {
363
379
  className: "resize-handle resize-handle-right",
364
380
  title: "\u62D6\u62FD\u8C03\u8282\u5BBD\u5EA6",
381
+ onMouseEnter: props.onMouseEnter,
382
+ onMouseLeave: props.onMouseLeave,
365
383
  onMouseDown: (e) => handleDragStart(e, "right")
366
384
  }
367
385
  ));
@@ -381,31 +399,90 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
381
399
  showDragHandle = false,
382
400
  settingsMenuLevel,
383
401
  extraToolbarItems,
402
+ showDynamicFlowsEditor = true,
384
403
  toolbarStyle,
385
404
  toolbarPosition = "inside"
386
405
  }) => {
387
- const [hideMenu, setHideMenu] = (0, import_react.useState)(false);
406
+ var _a;
388
407
  const [hasButton, setHasButton] = (0, import_react.useState)(false);
389
408
  const containerRef = (0, import_react.useRef)(null);
390
- const flowEngine = (0, import_provider.useFlowEngine)();
391
- const [style, setStyle] = (0, import_react.useState)({});
392
409
  const toolbarContainerRef = (0, import_react.useRef)(null);
393
- const toolbarContainerStyle = (0, import_react.useMemo)(() => ({ ...toolbarStyle, ...style }), [style, toolbarStyle]);
410
+ const portalActionsRef = (0, import_react.useRef)({
411
+ updatePortalRect: /* @__PURE__ */ __name(() => {
412
+ }, "updatePortalRect"),
413
+ schedulePortalRectUpdate: /* @__PURE__ */ __name(() => {
414
+ }, "schedulePortalRectUpdate")
415
+ });
416
+ const modelUid = getFloatMenuInstanceId(model);
417
+ const flowEngine = (0, import_provider.useFlowEngine)();
418
+ const updatePortalRectProxy = (0, import_react.useCallback)(() => {
419
+ portalActionsRef.current.updatePortalRect();
420
+ }, []);
421
+ const schedulePortalRectUpdateProxy = (0, import_react.useCallback)(() => {
422
+ portalActionsRef.current.schedulePortalRectUpdate();
423
+ }, []);
424
+ const {
425
+ isToolbarVisible,
426
+ shouldRenderToolbar,
427
+ handleSettingsMenuOpenChange,
428
+ handleChildHover,
429
+ handleHostMouseEnter,
430
+ handleHostMouseLeave,
431
+ handleToolbarMouseEnter,
432
+ handleToolbarMouseLeave,
433
+ handleResizeDragStart,
434
+ handleResizeDragEnd
435
+ } = (0, import_useFloatToolbarVisibility.useFloatToolbarVisibility)({
436
+ modelUid,
437
+ containerRef,
438
+ toolbarContainerRef,
439
+ updatePortalRect: updatePortalRectProxy,
440
+ schedulePortalRectUpdate: schedulePortalRectUpdateProxy
441
+ });
442
+ const { portalRect, portalRenderSnapshot, getPopupContainer, updatePortalRect, schedulePortalRectUpdate } = (0, import_useFloatToolbarPortal.useFloatToolbarPortal)({
443
+ active: shouldRenderToolbar,
444
+ containerRef,
445
+ toolbarContainerRef,
446
+ toolbarStyle
447
+ });
448
+ portalActionsRef.current.updatePortalRect = updatePortalRect;
449
+ portalActionsRef.current.schedulePortalRectUpdate = schedulePortalRectUpdate;
450
+ const toolbarItems = (0, import_react.useMemo)(
451
+ () => model ? renderToolbarItems(
452
+ model,
453
+ modelUid,
454
+ showDeleteButton,
455
+ showCopyUidButton,
456
+ flowEngine,
457
+ settingsMenuLevel,
458
+ extraToolbarItems,
459
+ showDynamicFlowsEditor,
460
+ handleSettingsMenuOpenChange,
461
+ getPopupContainer
462
+ ) : [],
463
+ [
464
+ extraToolbarItems,
465
+ flowEngine,
466
+ getPopupContainer,
467
+ handleSettingsMenuOpenChange,
468
+ model,
469
+ settingsMenuLevel,
470
+ showCopyUidButton,
471
+ showDeleteButton,
472
+ showDynamicFlowsEditor
473
+ ]
474
+ );
394
475
  (0, import_react.useEffect)(() => {
395
- if (containerRef.current) {
396
- const hasButtonElement = detectButtonInDOM(containerRef.current);
397
- setHasButton(hasButtonElement);
476
+ const container = containerRef.current;
477
+ if (!container) {
478
+ return;
398
479
  }
399
- }, [children]);
400
- (0, import_react.useEffect)(() => {
401
- if (!containerRef.current) return;
402
- const observer2 = new MutationObserver(() => {
403
- if (containerRef.current) {
404
- const hasButtonElement = detectButtonInDOM(containerRef.current);
405
- setHasButton(hasButtonElement);
406
- }
407
- });
408
- observer2.observe(containerRef.current, {
480
+ const syncHasButton = /* @__PURE__ */ __name(() => {
481
+ setHasButton(detectButtonInDOM(container));
482
+ }, "syncHasButton");
483
+ syncHasButton();
484
+ const observer2 = new MutationObserver(syncHasButton);
485
+ observer2.observe(container, {
409
486
  childList: true,
410
487
  subtree: true,
411
488
  attributes: true,
@@ -415,15 +492,6 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
415
492
  observer2.disconnect();
416
493
  };
417
494
  }, []);
418
- const handleChildHover = (0, import_react.useCallback)((e) => {
419
- const target = e.target;
420
- const childWithMenu = target.closest("[data-has-float-menu]");
421
- if (childWithMenu && childWithMenu !== containerRef.current) {
422
- setHideMenu(true);
423
- } else {
424
- setHideMenu(false);
425
- }
426
- }, []);
427
495
  if (!model) {
428
496
  const t = (0, import_utils.getT)(model || {});
429
497
  return /* @__PURE__ */ import_react.default.createElement(import_antd.Alert, { message: t("Invalid model provided"), type: "error" });
@@ -431,39 +499,63 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
431
499
  if (!enabled || !children) {
432
500
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, children);
433
501
  }
434
- return /* @__PURE__ */ import_react.default.createElement(
502
+ const toolbarZIndex = (((_a = model.context.themeToken) == null ? void 0 : _a.zIndexPopupBase) || DEFAULT_POPUP_BASE_Z_INDEX) + 1;
503
+ const toolbarContainerClassName = buildToolbarContainerClassName({
504
+ showBackground,
505
+ showBorder,
506
+ ctx: model.context,
507
+ toolbarZIndex,
508
+ portalRenderSnapshot,
509
+ isToolbarVisible,
510
+ className
511
+ });
512
+ const toolbarContainerStyle = buildToolbarContainerStyle(portalRect, toolbarStyle, toolbarItems.length);
513
+ const toolbarNode = shouldRenderToolbar ? /* @__PURE__ */ import_react.default.createElement(
435
514
  "div",
436
515
  {
437
- ref: containerRef,
438
- className: `${floatContainerStyles({
439
- showBackground,
440
- showBorder,
441
- ctx: model.context,
442
- toolbarPosition,
443
- toolbarCount: getToolbarCount(flowEngine, extraToolbarItems)
444
- })} ${hideMenu ? "hide-parent-menu" : ""} ${hasButton ? "has-button-child" : ""} ${className || ""}`,
445
- style: containerStyle,
446
- "data-has-float-menu": "true",
447
- onMouseMove: handleChildHover
516
+ ref: toolbarContainerRef,
517
+ className: `nb-toolbar-container ${toolbarContainerClassName}`,
518
+ style: toolbarContainerStyle,
519
+ "data-model-uid": modelUid
448
520
  },
449
- children,
450
- /* @__PURE__ */ import_react.default.createElement("div", { ref: toolbarContainerRef, className: "nb-toolbar-container", style: toolbarContainerStyle }, showTitle && (model.title || model.extraTitle) && /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-toolbar-container-title" }, model.title && /* @__PURE__ */ import_react.default.createElement("span", { className: "title-tag" }, model.title), model.extraTitle && /* @__PURE__ */ import_react.default.createElement("span", { className: "title-tag" }, model.extraTitle)), /* @__PURE__ */ import_react.default.createElement(
521
+ showTitle && (model.title || model.extraTitle) && /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-toolbar-container-title" }, model.title && /* @__PURE__ */ import_react.default.createElement("span", { className: "title-tag" }, model.title), model.extraTitle && /* @__PURE__ */ import_react.default.createElement("span", { className: "title-tag" }, model.extraTitle)),
522
+ /* @__PURE__ */ import_react.default.createElement(
451
523
  "div",
452
524
  {
453
- className: "nb-toolbar-container-icons",
525
+ className: `nb-toolbar-container-icons ${toolbarPositionClassNames[toolbarPosition]}`,
454
526
  onClick: (e) => e.stopPropagation(),
455
527
  onMouseDown: (e) => e.stopPropagation(),
456
- onMouseMove: (e) => e.stopPropagation()
528
+ onMouseMove: (e) => e.stopPropagation(),
529
+ onMouseEnter: handleToolbarMouseEnter,
530
+ onMouseLeave: handleToolbarMouseLeave
457
531
  },
458
- /* @__PURE__ */ import_react.default.createElement(import_antd.Space, { size: 3, align: "center" }, renderToolbarItems(
532
+ /* @__PURE__ */ import_react.default.createElement(import_antd.Space, { size: 3, align: "center" }, toolbarItems)
533
+ ),
534
+ showDragHandle && /* @__PURE__ */ import_react.default.createElement(
535
+ ResizeHandles,
536
+ {
459
537
  model,
460
- showDeleteButton,
461
- showCopyUidButton,
462
- flowEngine,
463
- settingsMenuLevel,
464
- extraToolbarItems
465
- ))
466
- ), showDragHandle && /* @__PURE__ */ import_react.default.createElement(ResizeHandles, { model, onDragStart: () => setStyle({ opacity: 1 }), onDragEnd: () => setStyle({}) }))
538
+ onMouseEnter: handleToolbarMouseEnter,
539
+ onMouseLeave: handleToolbarMouseLeave,
540
+ onDragStart: handleResizeDragStart,
541
+ onDragEnd: handleResizeDragEnd
542
+ }
543
+ )
544
+ ) : null;
545
+ return /* @__PURE__ */ import_react.default.createElement(
546
+ "div",
547
+ {
548
+ ref: containerRef,
549
+ className: `${hostContainerStyles} ${hasButton ? "has-button-child" : ""} ${className || ""}`,
550
+ style: containerStyle,
551
+ "data-has-float-menu": "true",
552
+ "data-float-menu-model-uid": modelUid,
553
+ onMouseMove: handleChildHover,
554
+ onMouseEnter: handleHostMouseEnter,
555
+ onMouseLeave: handleHostMouseLeave
556
+ },
557
+ children,
558
+ toolbarNode && ((portalRenderSnapshot == null ? void 0 : portalRenderSnapshot.mountElement) ? (0, import_react_dom.createPortal)(toolbarNode, portalRenderSnapshot.mountElement) : toolbarNode)
467
559
  );
468
560
  },
469
561
  {
@@ -471,53 +563,18 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
471
563
  }
472
564
  );
473
565
  const FlowsFloatContextMenuWithModelById = (0, import_reactive.observer)(
474
- ({
475
- uid,
476
- modelClassName,
477
- children,
478
- enabled = true,
479
- showDeleteButton = true,
480
- showCopyUidButton = true,
481
- containerStyle,
482
- className,
483
- showTitle = false,
484
- settingsMenuLevel,
485
- extraToolbarItems,
486
- toolbarPosition
487
- }) => {
566
+ ({ uid, modelClassName, children, ...restProps }) => {
488
567
  const model = (0, import_hooks.useFlowModelById)(uid, modelClassName);
489
568
  const flowEngine = (0, import_provider.useFlowEngine)();
490
569
  if (!model) {
491
570
  return /* @__PURE__ */ import_react.default.createElement(import_antd.Alert, { message: flowEngine.translate("Model with ID {{uid}} not found", { uid }), type: "error" });
492
571
  }
493
- return /* @__PURE__ */ import_react.default.createElement(
494
- FlowsFloatContextMenuWithModel,
495
- {
496
- model,
497
- enabled,
498
- showDeleteButton,
499
- showCopyUidButton,
500
- containerStyle,
501
- className,
502
- showTitle,
503
- settingsMenuLevel,
504
- extraToolbarItems,
505
- toolbarPosition
506
- },
507
- children
508
- );
572
+ return /* @__PURE__ */ import_react.default.createElement(FlowsFloatContextMenuWithModel, { model, ...restProps }, children);
509
573
  },
510
574
  {
511
575
  displayName: "FlowsFloatContextMenuWithModelById"
512
576
  }
513
577
  );
514
- function getToolbarCount(flowEngine, extraToolbarItems) {
515
- var _a, _b;
516
- const toolbarItems = ((_b = (_a = flowEngine == null ? void 0 : flowEngine.flowSettings) == null ? void 0 : _a.getToolbarItems) == null ? void 0 : _b.call(_a)) || [];
517
- const allToolbarItems = [...toolbarItems, ...extraToolbarItems || []];
518
- return allToolbarItems.length;
519
- }
520
- __name(getToolbarCount, "getToolbarCount");
521
578
  // Annotate the CommonJS export names for ESM import in node:
522
579
  0 && (module.exports = {
523
580
  FlowsFloatContextMenu