@nocobase/flow-engine 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (597) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +30 -0
  3. package/lib/ContextPathProxy.d.ts +17 -0
  4. package/lib/ContextPathProxy.js +65 -0
  5. package/lib/ElementProxy.d.ts +17 -0
  6. package/lib/ElementProxy.js +93 -0
  7. package/lib/FlowContextProvider.d.ts +24 -0
  8. package/lib/FlowContextProvider.js +82 -0
  9. package/lib/FlowDefinition.d.ts +423 -0
  10. package/lib/FlowDefinition.js +257 -0
  11. package/lib/JSRunner.d.ts +32 -0
  12. package/lib/JSRunner.js +95 -0
  13. package/lib/ReactView.d.ts +20 -0
  14. package/lib/ReactView.js +120 -0
  15. package/lib/ViewScopedFlowEngine.d.ts +23 -0
  16. package/lib/ViewScopedFlowEngine.js +81 -0
  17. package/lib/acl/Acl.d.ts +31 -0
  18. package/lib/acl/Acl.js +115 -0
  19. package/lib/action-registry/BaseActionRegistry.d.ts +23 -0
  20. package/lib/action-registry/BaseActionRegistry.js +57 -0
  21. package/lib/action-registry/EngineActionRegistry.d.ts +20 -0
  22. package/lib/action-registry/EngineActionRegistry.js +47 -0
  23. package/lib/action-registry/ModelActionRegistry.d.ts +34 -0
  24. package/lib/action-registry/ModelActionRegistry.js +79 -0
  25. package/lib/components/DynamicFlowsEditor.d.ts +17 -0
  26. package/lib/components/DynamicFlowsEditor.js +49 -0
  27. package/lib/components/FieldModelRenderer.d.ts +10 -0
  28. package/lib/components/FieldModelRenderer.js +94 -0
  29. package/lib/components/FlowContextSelector.d.ts +11 -0
  30. package/lib/components/FlowContextSelector.js +221 -0
  31. package/lib/components/FlowErrorFallback.d.ts +25 -0
  32. package/lib/components/FlowErrorFallback.js +264 -0
  33. package/lib/components/FlowModelRenderer.d.ts +64 -0
  34. package/lib/components/FlowModelRenderer.js +254 -0
  35. package/lib/components/FormItem.d.ts +18 -0
  36. package/lib/components/FormItem.js +147 -0
  37. package/lib/components/common/FlowSettingsButton.d.ts +11 -0
  38. package/lib/components/common/FlowSettingsButton.js +66 -0
  39. package/lib/components/common/index.d.ts +9 -0
  40. package/lib/components/common/index.js +30 -0
  41. package/lib/components/common/withFlowDesignMode.d.ts +26 -0
  42. package/lib/components/common/withFlowDesignMode.js +61 -0
  43. package/lib/components/dnd/getMousePositionOnElement.d.ts +50 -0
  44. package/lib/components/dnd/getMousePositionOnElement.js +95 -0
  45. package/lib/components/dnd/index.d.ts +24 -0
  46. package/lib/components/dnd/index.js +164 -0
  47. package/lib/components/dnd/moveBlock.d.ts +33 -0
  48. package/lib/components/dnd/moveBlock.js +302 -0
  49. package/lib/components/index.d.ts +18 -0
  50. package/lib/components/index.js +48 -0
  51. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.d.ts +46 -0
  52. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +225 -0
  53. package/lib/components/settings/independents/dropdown/index.d.ts +9 -0
  54. package/lib/components/settings/independents/dropdown/index.js +30 -0
  55. package/lib/components/settings/independents/index.d.ts +1 -0
  56. package/lib/components/settings/independents/index.js +30 -0
  57. package/lib/components/settings/index.d.ts +10 -0
  58. package/lib/components/settings/index.js +32 -0
  59. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +24 -0
  60. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +501 -0
  61. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.d.ts +45 -0
  62. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +231 -0
  63. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +111 -0
  64. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +484 -0
  65. package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.d.ts +26 -0
  66. package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.js +342 -0
  67. package/lib/components/settings/wrappers/contextual/StepSettings.d.ts +23 -0
  68. package/lib/components/settings/wrappers/contextual/StepSettings.js +110 -0
  69. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.d.ts +20 -0
  70. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +206 -0
  71. package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.d.ts +20 -0
  72. package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.js +47 -0
  73. package/lib/components/settings/wrappers/contextual/index.d.ts +14 -0
  74. package/lib/components/settings/wrappers/contextual/index.js +40 -0
  75. package/lib/components/settings/wrappers/embedded/FlowSettings.d.ts +33 -0
  76. package/lib/components/settings/wrappers/embedded/FlowSettings.js +207 -0
  77. package/lib/components/settings/wrappers/embedded/FlowsSettings.d.ts +41 -0
  78. package/lib/components/settings/wrappers/embedded/FlowsSettings.js +84 -0
  79. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.d.ts +16 -0
  80. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +88 -0
  81. package/lib/components/settings/wrappers/embedded/index.d.ts +10 -0
  82. package/lib/components/settings/wrappers/embedded/index.js +32 -0
  83. package/lib/components/settings/wrappers/index.d.ts +2 -0
  84. package/lib/components/settings/wrappers/index.js +32 -0
  85. package/lib/components/subModel/AddSubModelButton.d.ts +62 -0
  86. package/lib/components/subModel/AddSubModelButton.js +415 -0
  87. package/lib/components/subModel/LazyDropdown.d.ts +55 -0
  88. package/lib/components/subModel/LazyDropdown.js +524 -0
  89. package/lib/components/subModel/index.d.ts +10 -0
  90. package/lib/components/subModel/index.js +32 -0
  91. package/lib/components/subModel/utils.d.ts +34 -0
  92. package/lib/components/subModel/utils.js +287 -0
  93. package/lib/components/variables/InlineVariableTag.d.ts +21 -0
  94. package/lib/components/variables/InlineVariableTag.js +123 -0
  95. package/lib/components/variables/SlateVariableEditor.d.ts +46 -0
  96. package/lib/components/variables/SlateVariableEditor.js +302 -0
  97. package/lib/components/variables/VariableInput.d.ts +11 -0
  98. package/lib/components/variables/VariableInput.js +322 -0
  99. package/lib/components/variables/VariableTag.d.ts +11 -0
  100. package/lib/components/variables/VariableTag.js +148 -0
  101. package/lib/components/variables/VariableTrigger.d.ts +20 -0
  102. package/lib/components/variables/VariableTrigger.js +136 -0
  103. package/lib/components/variables/index.d.ts +15 -0
  104. package/lib/components/variables/index.js +53 -0
  105. package/lib/components/variables/types.d.ts +93 -0
  106. package/lib/components/variables/types.js +24 -0
  107. package/lib/components/variables/useResolvedMetaTree.d.ts +19 -0
  108. package/lib/components/variables/useResolvedMetaTree.js +91 -0
  109. package/lib/components/variables/utils.d.ts +22 -0
  110. package/lib/components/variables/utils.js +177 -0
  111. package/lib/data-source/index.d.ts +180 -0
  112. package/lib/data-source/index.js +733 -0
  113. package/lib/data-source/jioToJoiSchema.d.ts +19 -0
  114. package/lib/data-source/jioToJoiSchema.js +114 -0
  115. package/lib/decorators/index.d.ts +9 -0
  116. package/lib/decorators/index.js +36 -0
  117. package/lib/decorators/largeField.d.ts +9 -0
  118. package/lib/decorators/largeField.js +42 -0
  119. package/lib/emitter.d.ts +16 -0
  120. package/lib/emitter.js +58 -0
  121. package/lib/event-registry/BaseEventRegistry.d.ts +22 -0
  122. package/lib/event-registry/BaseEventRegistry.js +57 -0
  123. package/lib/event-registry/EngineEventRegistry.d.ts +19 -0
  124. package/lib/event-registry/EngineEventRegistry.js +47 -0
  125. package/lib/event-registry/ModelEventRegistry.d.ts +33 -0
  126. package/lib/event-registry/ModelEventRegistry.js +79 -0
  127. package/lib/executor/FlowExecutor.d.ts +26 -0
  128. package/lib/executor/FlowExecutor.js +262 -0
  129. package/lib/flow-registry/BaseFlowRegistry.d.ts +46 -0
  130. package/lib/flow-registry/BaseFlowRegistry.js +86 -0
  131. package/lib/flow-registry/GlobalFlowRegistry.d.ts +22 -0
  132. package/lib/flow-registry/GlobalFlowRegistry.js +95 -0
  133. package/lib/flow-registry/InstanceFlowRegistry.d.ts +21 -0
  134. package/lib/flow-registry/InstanceFlowRegistry.js +59 -0
  135. package/lib/flow-registry/index.d.ts +11 -0
  136. package/lib/flow-registry/index.js +34 -0
  137. package/lib/flowContext.d.ts +215 -0
  138. package/lib/flowContext.js +1266 -0
  139. package/lib/flowEngine.d.ts +340 -0
  140. package/lib/flowEngine.js +781 -0
  141. package/lib/flowI18n.d.ts +46 -0
  142. package/lib/flowI18n.js +117 -0
  143. package/lib/flowSettings.d.ts +266 -0
  144. package/lib/flowSettings.js +850 -0
  145. package/lib/hooks/index.d.ts +14 -0
  146. package/lib/hooks/index.js +40 -0
  147. package/lib/hooks/useApplyAutoFlows.d.ts +21 -0
  148. package/lib/hooks/useApplyAutoFlows.js +62 -0
  149. package/lib/hooks/useFlowModel.d.ts +29 -0
  150. package/lib/hooks/useFlowModel.js +72 -0
  151. package/lib/hooks/useFlowModelById.d.ts +11 -0
  152. package/lib/hooks/useFlowModelById.js +61 -0
  153. package/lib/hooks/useFlowSettingsContext.d.ts +20 -0
  154. package/lib/hooks/useFlowSettingsContext.js +61 -0
  155. package/lib/hooks/useFlowStep.d.ts +17 -0
  156. package/lib/hooks/useFlowStep.js +56 -0
  157. package/lib/hooks/useNiceDropdownMaxHeight.d.ts +13 -0
  158. package/lib/hooks/useNiceDropdownMaxHeight.js +52 -0
  159. package/lib/index.d.ts +27 -0
  160. package/lib/index.js +73 -0
  161. package/lib/locale/en-US.json +61 -0
  162. package/lib/locale/index.d.ts +141 -0
  163. package/lib/locale/index.js +70 -0
  164. package/lib/locale/zh-CN.json +61 -0
  165. package/lib/models/CollectionFieldModel.d.ts +50 -0
  166. package/lib/models/CollectionFieldModel.js +242 -0
  167. package/lib/models/DisplayItemModel.d.ts +12 -0
  168. package/lib/models/DisplayItemModel.js +41 -0
  169. package/lib/models/EditableItemModel.d.ts +12 -0
  170. package/lib/models/EditableItemModel.js +41 -0
  171. package/lib/models/FilterableItemModel.d.ts +12 -0
  172. package/lib/models/FilterableItemModel.js +41 -0
  173. package/lib/models/flowModel.d.ts +344 -0
  174. package/lib/models/flowModel.js +1133 -0
  175. package/lib/models/forkFlowModel.d.ts +83 -0
  176. package/lib/models/forkFlowModel.js +257 -0
  177. package/lib/models/index.d.ts +14 -0
  178. package/lib/models/index.js +40 -0
  179. package/lib/provider.d.ts +22 -0
  180. package/lib/provider.js +114 -0
  181. package/lib/resources/apiResource.d.ts +34 -0
  182. package/lib/resources/apiResource.js +153 -0
  183. package/lib/resources/baseRecordResource.d.ts +61 -0
  184. package/lib/resources/baseRecordResource.js +264 -0
  185. package/lib/resources/filterItem.d.ts +33 -0
  186. package/lib/resources/filterItem.js +93 -0
  187. package/lib/resources/flowResource.d.ts +45 -0
  188. package/lib/resources/flowResource.js +146 -0
  189. package/lib/resources/index.d.ts +15 -0
  190. package/lib/resources/index.js +42 -0
  191. package/lib/resources/multiRecordResource.d.ts +53 -0
  192. package/lib/resources/multiRecordResource.js +230 -0
  193. package/lib/resources/singleRecordResource.d.ts +23 -0
  194. package/lib/resources/singleRecordResource.js +111 -0
  195. package/lib/resources/sqlResource.d.ts +73 -0
  196. package/lib/resources/sqlResource.js +294 -0
  197. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +38 -0
  198. package/lib/runjs-context/contexts/FlowRunJSContext.js +217 -0
  199. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +16 -0
  200. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +66 -0
  201. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +16 -0
  202. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +78 -0
  203. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +12 -0
  204. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +59 -0
  205. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +16 -0
  206. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +70 -0
  207. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +16 -0
  208. package/lib/runjs-context/contexts/JSItemRunJSContext.js +66 -0
  209. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +12 -0
  210. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +61 -0
  211. package/lib/runjs-context/contexts/LinkageRunJSContext.d.ts +12 -0
  212. package/lib/runjs-context/contexts/LinkageRunJSContext.js +62 -0
  213. package/lib/runjs-context/helpers.d.ts +17 -0
  214. package/lib/runjs-context/helpers.js +79 -0
  215. package/lib/runjs-context/index.d.ts +19 -0
  216. package/lib/runjs-context/index.js +57 -0
  217. package/lib/runjs-context/registry.d.ts +17 -0
  218. package/lib/runjs-context/registry.js +93 -0
  219. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +16 -0
  220. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +42 -0
  221. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +16 -0
  222. package/lib/runjs-context/snippets/global/api-request-post.snippet.js +42 -0
  223. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +16 -0
  224. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +41 -0
  225. package/lib/runjs-context/snippets/global/copy-record-json.snippet.d.ts +11 -0
  226. package/lib/runjs-context/snippets/global/copy-record-json.snippet.js +42 -0
  227. package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.d.ts +11 -0
  228. package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.js +42 -0
  229. package/lib/runjs-context/snippets/global/log-json-record.snippet.d.ts +11 -0
  230. package/lib/runjs-context/snippets/global/log-json-record.snippet.js +42 -0
  231. package/lib/runjs-context/snippets/global/message-error.snippet.d.ts +11 -0
  232. package/lib/runjs-context/snippets/global/message-error.snippet.js +41 -0
  233. package/lib/runjs-context/snippets/global/message-success.snippet.d.ts +11 -0
  234. package/lib/runjs-context/snippets/global/message-success.snippet.js +41 -0
  235. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +16 -0
  236. package/lib/runjs-context/snippets/global/notification-open.snippet.js +43 -0
  237. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.d.ts +11 -0
  238. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +47 -0
  239. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.d.ts +11 -0
  240. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +47 -0
  241. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +16 -0
  242. package/lib/runjs-context/snippets/global/requireAsync.snippet.js +46 -0
  243. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +16 -0
  244. package/lib/runjs-context/snippets/global/sleep.snippet.js +43 -0
  245. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +16 -0
  246. package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +44 -0
  247. package/lib/runjs-context/snippets/global/view-navigation-push.snippet.d.ts +11 -0
  248. package/lib/runjs-context/snippets/global/view-navigation-push.snippet.js +44 -0
  249. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +16 -0
  250. package/lib/runjs-context/snippets/global/window-open.snippet.js +41 -0
  251. package/lib/runjs-context/snippets/index.d.ts +11 -0
  252. package/lib/runjs-context/snippets/index.js +94 -0
  253. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +15 -0
  254. package/lib/runjs-context/snippets/libs/echarts-init.snippet.js +46 -0
  255. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +15 -0
  256. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.js +44 -0
  257. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +15 -0
  258. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.js +43 -0
  259. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +15 -0
  260. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +43 -0
  261. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +15 -0
  262. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +40 -0
  263. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +15 -0
  264. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.js +46 -0
  265. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +15 -0
  266. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +42 -0
  267. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +15 -0
  268. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +46 -0
  269. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +15 -0
  270. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +41 -0
  271. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +15 -0
  272. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +41 -0
  273. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +15 -0
  274. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.js +46 -0
  275. package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.d.ts +11 -0
  276. package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +45 -0
  277. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +15 -0
  278. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.js +56 -0
  279. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +15 -0
  280. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.js +42 -0
  281. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +15 -0
  282. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.js +41 -0
  283. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +15 -0
  284. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.js +40 -0
  285. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +15 -0
  286. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.js +44 -0
  287. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +15 -0
  288. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.js +60 -0
  289. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +15 -0
  290. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.js +59 -0
  291. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +15 -0
  292. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.js +60 -0
  293. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +15 -0
  294. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.js +60 -0
  295. package/lib/runjs-context/snippets/types.d.ts +16 -0
  296. package/lib/runjs-context/snippets/types.js +24 -0
  297. package/lib/types.d.ts +398 -0
  298. package/lib/types.js +43 -0
  299. package/lib/utils/autoFlowError.d.ts +16 -0
  300. package/lib/utils/autoFlowError.js +53 -0
  301. package/lib/utils/constants.d.ts +29 -0
  302. package/lib/utils/constants.js +77 -0
  303. package/lib/utils/context.d.ts +40 -0
  304. package/lib/utils/context.js +63 -0
  305. package/lib/utils/createCollectionContextMeta.d.ts +11 -0
  306. package/lib/utils/createCollectionContextMeta.js +117 -0
  307. package/lib/utils/exceptions.d.ts +22 -0
  308. package/lib/utils/exceptions.js +62 -0
  309. package/lib/utils/flow-definitions.d.ts +11 -0
  310. package/lib/utils/flow-definitions.js +40 -0
  311. package/lib/utils/index.d.ts +22 -0
  312. package/lib/utils/index.js +117 -0
  313. package/lib/utils/inheritance.d.ts +16 -0
  314. package/lib/utils/inheritance.js +53 -0
  315. package/lib/utils/params-resolvers.d.ts +51 -0
  316. package/lib/utils/params-resolvers.js +309 -0
  317. package/lib/utils/parsePathnameToViewParams.d.ts +34 -0
  318. package/lib/utils/parsePathnameToViewParams.js +84 -0
  319. package/lib/utils/safeGlobals.d.ts +16 -0
  320. package/lib/utils/safeGlobals.js +179 -0
  321. package/lib/utils/schema-utils.d.ts +40 -0
  322. package/lib/utils/schema-utils.js +161 -0
  323. package/lib/utils/serverContextParams.d.ts +28 -0
  324. package/lib/utils/serverContextParams.js +106 -0
  325. package/lib/utils/setupRuntimeContextSteps.d.ts +19 -0
  326. package/lib/utils/setupRuntimeContextSteps.js +88 -0
  327. package/lib/utils/translation.d.ts +18 -0
  328. package/lib/utils/translation.js +58 -0
  329. package/lib/utils/variablesParams.d.ts +51 -0
  330. package/lib/utils/variablesParams.js +150 -0
  331. package/lib/views/DialogComponent.d.ts +22 -0
  332. package/lib/views/DialogComponent.js +98 -0
  333. package/lib/views/DrawerComponent.d.ts +11 -0
  334. package/lib/views/DrawerComponent.js +101 -0
  335. package/lib/views/FlowView.d.ts +76 -0
  336. package/lib/views/FlowView.js +81 -0
  337. package/lib/views/PageComponent.d.ts +10 -0
  338. package/lib/views/PageComponent.js +167 -0
  339. package/lib/views/ViewNavigation.d.ts +45 -0
  340. package/lib/views/ViewNavigation.js +97 -0
  341. package/lib/views/createViewMeta.d.ts +16 -0
  342. package/lib/views/createViewMeta.js +171 -0
  343. package/lib/views/index.d.ts +13 -0
  344. package/lib/views/index.js +48 -0
  345. package/lib/views/useDialog.d.ts +32 -0
  346. package/lib/views/useDialog.js +199 -0
  347. package/lib/views/useDrawer.d.ts +33 -0
  348. package/lib/views/useDrawer.js +206 -0
  349. package/lib/views/usePage.d.ts +32 -0
  350. package/lib/views/usePage.js +193 -0
  351. package/lib/views/usePatchElement.d.ts +10 -0
  352. package/lib/views/usePatchElement.js +54 -0
  353. package/lib/views/usePopover.d.ts +17 -0
  354. package/lib/views/usePopover.js +159 -0
  355. package/package.json +37 -0
  356. package/src/ContextPathProxy.ts +45 -0
  357. package/src/ElementProxy.ts +69 -0
  358. package/src/FlowContextProvider.tsx +40 -0
  359. package/src/FlowDefinition.ts +275 -0
  360. package/src/JSRunner.ts +84 -0
  361. package/src/ReactView.tsx +104 -0
  362. package/src/ViewScopedFlowEngine.ts +75 -0
  363. package/src/__tests__/ElementProxy.test.ts +51 -0
  364. package/src/__tests__/JSRunner.test.ts +92 -0
  365. package/src/__tests__/ReactView.test.tsx +63 -0
  366. package/src/__tests__/context-path-proxy.test.ts +35 -0
  367. package/src/__tests__/flow-engine.test.ts +189 -0
  368. package/src/__tests__/flowContext.test.ts +2012 -0
  369. package/src/__tests__/flowEngine.saveModel.test.ts +171 -0
  370. package/src/__tests__/flowI18n.test.ts +28 -0
  371. package/src/__tests__/flowModel.getFlows.test.ts +61 -0
  372. package/src/__tests__/flowModel.openView.navigation.test.ts +78 -0
  373. package/src/__tests__/flowRuntimeContext.test.ts +187 -0
  374. package/src/__tests__/flowSettings.open.test.tsx +1920 -0
  375. package/src/__tests__/flowSettings.test.ts +566 -0
  376. package/src/__tests__/globalFlowRegistry.test.ts +77 -0
  377. package/src/__tests__/isFieldInterfaceMatch.test.ts +51 -0
  378. package/src/__tests__/metaTreeNodeCache.test.ts +234 -0
  379. package/src/__tests__/path-aggregation.test.ts +85 -0
  380. package/src/__tests__/provider.test.tsx +28 -0
  381. package/src/__tests__/renderHiddenInConfig.test.tsx +91 -0
  382. package/src/__tests__/runjsContext.test.ts +60 -0
  383. package/src/__tests__/viewScopedFlowEngine.test.ts +212 -0
  384. package/src/acl/Acl.tsx +109 -0
  385. package/src/acl/__tests__/Acl.test.tsx +72 -0
  386. package/src/action-registry/BaseActionRegistry.ts +46 -0
  387. package/src/action-registry/EngineActionRegistry.ts +32 -0
  388. package/src/action-registry/ModelActionRegistry.ts +75 -0
  389. package/src/action-registry/__tests__/engineActionRegistry.test.ts +43 -0
  390. package/src/action-registry/__tests__/modelActionRegistry.test.ts +107 -0
  391. package/src/components/DynamicFlowsEditor.tsx +318 -0
  392. package/src/components/FieldModelRenderer.tsx +62 -0
  393. package/src/components/FlowContextSelector.tsx +255 -0
  394. package/src/components/FlowErrorFallback.tsx +316 -0
  395. package/src/components/FlowModelRenderer.tsx +428 -0
  396. package/src/components/FormItem.tsx +130 -0
  397. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +226 -0
  398. package/src/components/common/FlowSettingsButton.tsx +30 -0
  399. package/src/components/common/index.ts +10 -0
  400. package/src/components/common/withFlowDesignMode.tsx +49 -0
  401. package/src/components/dnd/getMousePositionOnElement.ts +115 -0
  402. package/src/components/dnd/index.tsx +128 -0
  403. package/src/components/dnd/moveBlock.ts +379 -0
  404. package/src/components/index.ts +20 -0
  405. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +279 -0
  406. package/src/components/settings/independents/dropdown/index.ts +10 -0
  407. package/src/components/settings/independents/index.ts +2 -0
  408. package/src/components/settings/index.ts +11 -0
  409. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +617 -0
  410. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +292 -0
  411. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +655 -0
  412. package/src/components/settings/wrappers/contextual/StepRequiredSettingsDialog.tsx +446 -0
  413. package/src/components/settings/wrappers/contextual/StepSettings.tsx +109 -0
  414. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +217 -0
  415. package/src/components/settings/wrappers/contextual/StepSettingsDrawer.tsx +32 -0
  416. package/src/components/settings/wrappers/contextual/index.ts +15 -0
  417. package/src/components/settings/wrappers/embedded/FlowSettings.tsx +258 -0
  418. package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +111 -0
  419. package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +96 -0
  420. package/src/components/settings/wrappers/embedded/index.ts +11 -0
  421. package/src/components/settings/wrappers/index.ts +5 -0
  422. package/src/components/subModel/AddSubModelButton.tsx +575 -0
  423. package/src/components/subModel/LazyDropdown.tsx +714 -0
  424. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1185 -0
  425. package/src/components/subModel/__tests__/buildWrapperFieldChildren.test.ts +192 -0
  426. package/src/components/subModel/__tests__/utils.test.ts +425 -0
  427. package/src/components/subModel/index.ts +12 -0
  428. package/src/components/subModel/utils.ts +278 -0
  429. package/src/components/variables/InlineVariableTag.tsx +97 -0
  430. package/src/components/variables/SlateVariableEditor.tsx +384 -0
  431. package/src/components/variables/VariableInput.tsx +342 -0
  432. package/src/components/variables/VariableTag.tsx +123 -0
  433. package/src/components/variables/VariableTrigger.tsx +116 -0
  434. package/src/components/variables/__tests__/FlowContextSelector.test.tsx +553 -0
  435. package/src/components/variables/__tests__/VariableInput.test.tsx +550 -0
  436. package/src/components/variables/__tests__/VariableTag.test.tsx +347 -0
  437. package/src/components/variables/__tests__/test-utils.tsx +62 -0
  438. package/src/components/variables/__tests__/utils.test.ts +310 -0
  439. package/src/components/variables/index.ts +16 -0
  440. package/src/components/variables/types.ts +100 -0
  441. package/src/components/variables/useResolvedMetaTree.ts +76 -0
  442. package/src/components/variables/utils.ts +192 -0
  443. package/src/data-source/__tests__/collection.test.ts +58 -0
  444. package/src/data-source/__tests__/index.test.ts +82 -0
  445. package/src/data-source/__tests__/jioToJoiSchema.test.ts +56 -0
  446. package/src/data-source/index.ts +812 -0
  447. package/src/data-source/jioToJoiSchema.ts +103 -0
  448. package/src/decorators/index.ts +10 -0
  449. package/src/decorators/largeField.ts +14 -0
  450. package/src/emitter.ts +33 -0
  451. package/src/event-registry/BaseEventRegistry.ts +40 -0
  452. package/src/event-registry/EngineEventRegistry.ts +26 -0
  453. package/src/event-registry/ModelEventRegistry.ts +69 -0
  454. package/src/event-registry/__tests__/engineEventRegistry.test.ts +48 -0
  455. package/src/executor/FlowExecutor.ts +256 -0
  456. package/src/executor/__tests__/eventStep.test.ts +157 -0
  457. package/src/executor/__tests__/flowExecutor.test.ts +163 -0
  458. package/src/flow-registry/BaseFlowRegistry.ts +91 -0
  459. package/src/flow-registry/GlobalFlowRegistry.ts +82 -0
  460. package/src/flow-registry/InstanceFlowRegistry.ts +39 -0
  461. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +141 -0
  462. package/src/flow-registry/__tests__/instance-and-global-registry.test.ts +67 -0
  463. package/src/flow-registry/__tests__/instanceFlowRegistry.test.ts +83 -0
  464. package/src/flow-registry/index.ts +12 -0
  465. package/src/flowContext.ts +1639 -0
  466. package/src/flowEngine.ts +905 -0
  467. package/src/flowI18n.ts +96 -0
  468. package/src/flowSettings.ts +1045 -0
  469. package/src/hooks/index.ts +15 -0
  470. package/src/hooks/useApplyAutoFlows.ts +51 -0
  471. package/src/hooks/useFlowModel.tsx +59 -0
  472. package/src/hooks/useFlowModelById.ts +37 -0
  473. package/src/hooks/useFlowSettingsContext.tsx +37 -0
  474. package/src/hooks/useFlowStep.tsx +19 -0
  475. package/src/hooks/useNiceDropdownMaxHeight.ts +34 -0
  476. package/src/index.ts +38 -0
  477. package/src/locale/en-US.json +61 -0
  478. package/src/locale/index.ts +38 -0
  479. package/src/locale/zh-CN.json +61 -0
  480. package/src/models/CollectionFieldModel.tsx +269 -0
  481. package/src/models/DisplayItemModel.tsx +13 -0
  482. package/src/models/EditableItemModel.tsx +13 -0
  483. package/src/models/FilterableItemModel.tsx +13 -0
  484. package/src/models/__tests__/CollectionFieldModel.test.ts +122 -0
  485. package/src/models/__tests__/defaultParams-on-create.test.ts +83 -0
  486. package/src/models/__tests__/flow-model-oninit.test.ts +44 -0
  487. package/src/models/__tests__/flowModel.actions.integration.test.ts +100 -0
  488. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +100 -0
  489. package/src/models/__tests__/flowModel.test.ts +2746 -0
  490. package/src/models/__tests__/flowRegistry.test.ts +512 -0
  491. package/src/models/__tests__/forkFlowModel.test.ts +1047 -0
  492. package/src/models/__tests__/model-actions.test.ts +70 -0
  493. package/src/models/__tests__/model-events.test.ts +69 -0
  494. package/src/models/flowModel.tsx +1398 -0
  495. package/src/models/forkFlowModel.ts +287 -0
  496. package/src/models/index.ts +17 -0
  497. package/src/provider.tsx +101 -0
  498. package/src/resources/__tests__/apiResource.test.ts +201 -0
  499. package/src/resources/__tests__/baseRecordResource.test.ts +262 -0
  500. package/src/resources/__tests__/filterItem.test.ts +260 -0
  501. package/src/resources/__tests__/flowResource.test.ts +127 -0
  502. package/src/resources/apiResource.ts +148 -0
  503. package/src/resources/baseRecordResource.ts +279 -0
  504. package/src/resources/filterItem.ts +74 -0
  505. package/src/resources/flowResource.ts +143 -0
  506. package/src/resources/index.ts +17 -0
  507. package/src/resources/multiRecordResource.ts +219 -0
  508. package/src/resources/singleRecordResource.ts +83 -0
  509. package/src/resources/sqlResource.ts +299 -0
  510. package/src/runjs-context/contexts/FlowRunJSContext.ts +190 -0
  511. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +39 -0
  512. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +52 -0
  513. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +32 -0
  514. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +43 -0
  515. package/src/runjs-context/contexts/JSItemRunJSContext.ts +39 -0
  516. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +34 -0
  517. package/src/runjs-context/contexts/LinkageRunJSContext.ts +35 -0
  518. package/src/runjs-context/helpers.ts +56 -0
  519. package/src/runjs-context/index.ts +20 -0
  520. package/src/runjs-context/registry.ts +65 -0
  521. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +20 -0
  522. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +20 -0
  523. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +19 -0
  524. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +21 -0
  525. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +21 -0
  526. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +21 -0
  527. package/src/runjs-context/snippets/global/message-error.snippet.ts +20 -0
  528. package/src/runjs-context/snippets/global/message-success.snippet.ts +20 -0
  529. package/src/runjs-context/snippets/global/notification-open.snippet.ts +21 -0
  530. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +26 -0
  531. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +26 -0
  532. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +24 -0
  533. package/src/runjs-context/snippets/global/sleep.snippet.ts +21 -0
  534. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +22 -0
  535. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +23 -0
  536. package/src/runjs-context/snippets/global/window-open.snippet.ts +19 -0
  537. package/src/runjs-context/snippets/index.ts +59 -0
  538. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +24 -0
  539. package/src/runjs-context/snippets/scene/actions/collection-selected-count.snippet.ts +22 -0
  540. package/src/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.ts +21 -0
  541. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +21 -0
  542. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +18 -0
  543. package/src/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.ts +29 -0
  544. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +20 -0
  545. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +24 -0
  546. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +19 -0
  547. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +24 -0
  548. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +24 -0
  549. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +30 -0
  550. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +34 -0
  551. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +20 -0
  552. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +19 -0
  553. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +18 -0
  554. package/src/runjs-context/snippets/scene/jsitem/render-basic.snippet.ts +27 -0
  555. package/src/runjs-context/snippets/scene/linkage/set-disabled.snippet.ts +38 -0
  556. package/src/runjs-context/snippets/scene/linkage/set-field-value.snippet.ts +37 -0
  557. package/src/runjs-context/snippets/scene/linkage/set-required.snippet.ts +38 -0
  558. package/src/runjs-context/snippets/scene/linkage/toggle-visible.snippet.ts +38 -0
  559. package/src/runjs-context/snippets/types.ts +17 -0
  560. package/src/types.ts +474 -0
  561. package/src/utils/__tests__/context.test.ts +93 -0
  562. package/src/utils/__tests__/params-resolvers.test.ts +652 -0
  563. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +104 -0
  564. package/src/utils/__tests__/safeGlobals.test.ts +29 -0
  565. package/src/utils/__tests__/utils.test.ts +1021 -0
  566. package/src/utils/__tests__/variablesParams.test.ts +52 -0
  567. package/src/utils/autoFlowError.ts +29 -0
  568. package/src/utils/constants.ts +60 -0
  569. package/src/utils/context.ts +70 -0
  570. package/src/utils/createCollectionContextMeta.ts +122 -0
  571. package/src/utils/exceptions.ts +36 -0
  572. package/src/utils/flow-definitions.ts +16 -0
  573. package/src/utils/index.ts +63 -0
  574. package/src/utils/inheritance.ts +39 -0
  575. package/src/utils/params-resolvers.ts +482 -0
  576. package/src/utils/parsePathnameToViewParams.ts +103 -0
  577. package/src/utils/safeGlobals.ts +188 -0
  578. package/src/utils/schema-utils.ts +201 -0
  579. package/src/utils/serverContextParams.ts +111 -0
  580. package/src/utils/setupRuntimeContextSteps.ts +89 -0
  581. package/src/utils/translation.ts +37 -0
  582. package/src/utils/variablesParams.ts +175 -0
  583. package/src/views/DialogComponent.tsx +79 -0
  584. package/src/views/DrawerComponent.tsx +72 -0
  585. package/src/views/FlowView.tsx +103 -0
  586. package/src/views/PageComponent.tsx +150 -0
  587. package/src/views/ViewNavigation.ts +122 -0
  588. package/src/views/__tests__/FlowView.test.ts +31 -0
  589. package/src/views/__tests__/ViewNavigation.test.ts +191 -0
  590. package/src/views/__tests__/usePatchElement.test.tsx +28 -0
  591. package/src/views/createViewMeta.ts +157 -0
  592. package/src/views/index.tsx +14 -0
  593. package/src/views/useDialog.tsx +192 -0
  594. package/src/views/useDrawer.tsx +205 -0
  595. package/src/views/usePage.tsx +182 -0
  596. package/src/views/usePatchElement.tsx +27 -0
  597. package/src/views/usePopover.tsx +131 -0
@@ -0,0 +1,714 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { css } from '@emotion/css';
11
+ import { Dropdown, DropdownProps, Empty, Input, InputProps, Spin } from 'antd';
12
+ import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
13
+ import { useFlowEngine } from '../../provider';
14
+
15
+ // ==================== Types ====================
16
+
17
+ export type Item = {
18
+ key?: string;
19
+ type?: 'group' | 'divider';
20
+ label?: React.ReactNode;
21
+ children?: Item[] | (() => Item[] | Promise<Item[]>);
22
+ searchable?: boolean;
23
+ searchPlaceholder?: string;
24
+ keepDropdownOpen?: boolean;
25
+ /**
26
+ * 开关状态标记(内部使用)
27
+ */
28
+ isToggled?: boolean;
29
+ /**
30
+ * 原始菜单项数据(内部使用)
31
+ */
32
+ originalItem?: any;
33
+ /**
34
+ * 是否为唯一项标记(内部使用)
35
+ */
36
+ unique?: boolean;
37
+ [key: string]: any;
38
+ };
39
+
40
+ export type ItemsType = Item[] | (() => Item[] | Promise<Item[]>);
41
+
42
+ interface LazyDropdownMenuProps extends Omit<DropdownProps['menu'], 'items'> {
43
+ items: ItemsType;
44
+ keepDropdownOpen?: boolean;
45
+ /**
46
+ * 在父节点短暂重建(卸载/重挂载)时用于恢复打开状态的持久键。
47
+ * 不需要手动传入,调用方(如 AddSubModelButton)会自动生成。
48
+ */
49
+ persistKey?: string;
50
+ /**
51
+ * 仅用于“状态刷新”的版本号。变化时会重新计算根 items,
52
+ * 但不会清空已加载的 children,避免 UI 闪烁。
53
+ */
54
+ stateVersion?: number;
55
+ /**
56
+ * 额外刷新目标(多路径):每条路径的祖先都会被刷新
57
+ */
58
+ refreshKeys?: string[];
59
+ }
60
+
61
+ interface ExtendedMenuInfo {
62
+ key: string;
63
+ keyPath: string[];
64
+ item: any;
65
+ domEvent: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>;
66
+ originalItem: Item;
67
+ keepDropdownOpen: boolean;
68
+ }
69
+
70
+ // ==================== Custom Hooks ====================
71
+
72
+ /**
73
+ * 计算合适的下拉菜单最大高度
74
+ */
75
+ const useNiceDropdownMaxHeight = () => {
76
+ return useMemo(() => {
77
+ const maxHeight = Math.min(window.innerHeight * 0.6, 400);
78
+ return maxHeight;
79
+ }, []);
80
+ };
81
+
82
+ /**
83
+ * 处理异步菜单项加载的逻辑
84
+ */
85
+ const useAsyncMenuItems = (
86
+ menuVisible: boolean,
87
+ rootItems: Item[],
88
+ resetKey?: any,
89
+ openKeySet?: Set<string>,
90
+ refreshKeys?: string[],
91
+ ) => {
92
+ const [loadedChildren, setLoadedChildren] = useState<Record<string, Item[]>>({});
93
+ const [loadingKeys, setLoadingKeys] = useState<Set<string>>(new Set());
94
+ // 记录已处理过的 stateVersion,避免重复强制刷新
95
+ const lastRefreshedVersion = useRef<any>(null);
96
+ // 预取逻辑已移除:不再使用签名缓存
97
+
98
+ const handleLoadChildren = useCallback(
99
+ async (keyPath: string, loader: () => Item[] | Promise<Item[]>, force = false) => {
100
+ // 若已在加载中,直接跳过,避免重复进入(即便是 force 情况也避免重入)
101
+ if (loadingKeys.has(keyPath)) return;
102
+ if (!force && loadedChildren[keyPath]) return;
103
+
104
+ setLoadingKeys((prev) => new Set(prev).add(keyPath));
105
+ try {
106
+ const children = loader();
107
+ const resolved = children instanceof Promise ? await children : children;
108
+ setLoadedChildren((prev) => ({ ...prev, [keyPath]: resolved }));
109
+ } catch (err) {
110
+ console.error(`Failed to load children for ${keyPath}`, err);
111
+ } finally {
112
+ setLoadingKeys((prev) => {
113
+ const next = new Set(prev);
114
+ next.delete(keyPath);
115
+ return next;
116
+ });
117
+ }
118
+ },
119
+ [loadedChildren, loadingKeys],
120
+ );
121
+
122
+ // 收集所有“children 为函数”的节点(无论是否为 group),支持从 rootItems 与已加载的 loadedChildren 中同时收集。
123
+ const collectAsyncNodes = (
124
+ root: Item[],
125
+ loaded: Record<string, Item[]>,
126
+ ): [string, () => Item[] | Promise<Item[]>][] => {
127
+ const result: [string, () => Item[] | Promise<Item[]>][] = [];
128
+ const scan = (items: Item[], path: string[] = []) => {
129
+ for (const item of items) {
130
+ const keyPath = getKeyPath(path, item.key);
131
+ if (typeof item.children === 'function') {
132
+ result.push([keyPath, item.children]);
133
+ }
134
+ if (Array.isArray(item.children)) {
135
+ scan(item.children, [...path, item.key]);
136
+ }
137
+ }
138
+ };
139
+ // 1) 扫描根
140
+ scan(root, []);
141
+ // 2) 扫描已加载的分支(保持 keyPath 前缀)
142
+ for (const keyPath of Object.keys(loaded)) {
143
+ const items = loaded[keyPath] || [];
144
+ const parts = keyPath ? keyPath.split('/') : [];
145
+ scan(items, parts);
146
+ }
147
+ return result;
148
+ };
149
+
150
+ // 当 resetKey(stateVersion)变化时,尽量“原位刷新”已加载的 children:
151
+ // 1) 不清空 loadedChildren,避免 UI 闪烁;
152
+ // 2) 仅对 children 为函数的节点强制后台刷新,刷新完成后无感替换。
153
+ useEffect(() => {
154
+ if (!menuVisible) return;
155
+ // 避免同一 stateVersion 被重复刷新
156
+ if (lastRefreshedVersion.current === resetKey) {
157
+ return;
158
+ }
159
+ lastRefreshedVersion.current = resetKey;
160
+ // 构建当前可用的 loader 索引表(keyPath -> loader)
161
+ const loaderMap = new Map<string, () => Item[] | Promise<Item[]>>();
162
+ for (const [kp, loader] of collectAsyncNodes(rootItems, loadedChildren)) {
163
+ loaderMap.set(kp, loader);
164
+ }
165
+ // 仅刷新“当前展开”的分支,避免刷新未展开的所有分支导致的循环/卡顿
166
+ const openKeys = openKeySet ? Array.from(openKeySet) : [];
167
+ let targetKeys: string[] = [];
168
+ const candidates = Array.from(new Set([...(refreshKeys || [])].filter(Boolean))) as string[];
169
+ if (candidates.length > 0) {
170
+ // 精确刷新:仅刷新 focusKey 的祖先路径中已加载的分支
171
+ for (const rk of candidates) {
172
+ const parts = rk.split('/').filter(Boolean);
173
+ for (let i = 1; i <= parts.length; i++) {
174
+ const prefix = parts.slice(0, i).join('/');
175
+ if (!targetKeys.includes(prefix) && loadedChildren[prefix]) targetKeys.push(prefix);
176
+ }
177
+ }
178
+ } else {
179
+ // 无焦点路径时,以当前展开项为准
180
+ targetKeys = Object.keys(loadedChildren).filter((kp) =>
181
+ openKeys.some((ok) => kp === ok || kp.startsWith(ok + '/')),
182
+ );
183
+ }
184
+ // 若没有匹配到“当前展开”的分支,则回退刷新顶层已加载分支(如 TableColumnModel)
185
+ if (targetKeys.length === 0) {
186
+ targetKeys = Object.keys(loadedChildren).filter((kp) => kp.indexOf('/') === -1);
187
+ }
188
+ const refreshedInThisVersion = new Set<string>();
189
+ for (const keyPath of targetKeys) {
190
+ const loader = loaderMap.get(keyPath);
191
+ if (!loader) continue;
192
+ try {
193
+ if (!refreshedInThisVersion.has(keyPath)) {
194
+ refreshedInThisVersion.add(keyPath);
195
+ handleLoadChildren(keyPath, loader, true);
196
+ }
197
+ } catch (e) {
198
+ // 忽略刷新错误
199
+ }
200
+ }
201
+ }, [menuVisible, resetKey, rootItems, handleLoadChildren, loadedChildren, openKeySet, refreshKeys]);
202
+
203
+ // 取消全量递归预取:避免层级结构导致的重复加载。
204
+
205
+ return {
206
+ loadedChildren,
207
+ loadingKeys,
208
+ handleLoadChildren,
209
+ };
210
+ };
211
+
212
+ /**
213
+ * 处理保持下拉菜单打开状态的逻辑
214
+ */
215
+ const useKeepDropdownOpen = () => {
216
+ const shouldKeepOpenRef = useRef(false);
217
+ const [forceKeepOpen, setForceKeepOpen] = useState(false);
218
+ const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
219
+
220
+ const requestKeepOpen = useCallback(() => {
221
+ shouldKeepOpenRef.current = true;
222
+ setForceKeepOpen(true);
223
+
224
+ // 使用短 TTL 保持打开,覆盖子菜单关闭级联到顶层的延迟调用
225
+ if (timerRef.current) clearTimeout(timerRef.current);
226
+ timerRef.current = setTimeout(() => {
227
+ shouldKeepOpenRef.current = false;
228
+ setForceKeepOpen(false);
229
+ timerRef.current = null;
230
+ }, 250);
231
+ }, []);
232
+
233
+ useEffect(() => () => timerRef.current && clearTimeout(timerRef.current), []);
234
+
235
+ const shouldPreventClose = useCallback(() => {
236
+ return shouldKeepOpenRef.current || forceKeepOpen;
237
+ }, [forceKeepOpen]);
238
+
239
+ return {
240
+ requestKeepOpen,
241
+ shouldPreventClose,
242
+ };
243
+ };
244
+
245
+ /**
246
+ * 处理菜单搜索状态
247
+ */
248
+ const useMenuSearch = () => {
249
+ const [searchValues, setSearchValues] = useState<Record<string, string>>({});
250
+ const [isSearching, setIsSearching] = useState(false);
251
+ const searchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
252
+
253
+ const updateSearchValue = (key: string, value: string) => {
254
+ setIsSearching(true);
255
+ setSearchValues((prev) => ({ ...prev, [key]: value }));
256
+
257
+ if (searchTimeoutRef.current) {
258
+ clearTimeout(searchTimeoutRef.current);
259
+ }
260
+ searchTimeoutRef.current = setTimeout(() => setIsSearching(false), 300);
261
+ };
262
+
263
+ useEffect(() => {
264
+ return () => {
265
+ if (searchTimeoutRef.current) {
266
+ clearTimeout(searchTimeoutRef.current);
267
+ }
268
+ };
269
+ }, []);
270
+
271
+ return {
272
+ searchValues,
273
+ isSearching,
274
+ updateSearchValue,
275
+ };
276
+ };
277
+
278
+ /**
279
+ * 处理动态子菜单样式
280
+ */
281
+ const useSubmenuStyles = (menuVisible: boolean, dropdownMaxHeight: number) => {
282
+ useEffect(() => {
283
+ if (!menuVisible || dropdownMaxHeight <= 0) return;
284
+
285
+ const observer = new MutationObserver((mutations) => {
286
+ mutations.forEach((mutation) => {
287
+ mutation.addedNodes.forEach((node) => {
288
+ if (node.nodeType === Node.ELEMENT_NODE) {
289
+ const element = node as HTMLElement;
290
+
291
+ if (element.classList?.contains('ant-dropdown-menu-submenu-popup')) {
292
+ requestAnimationFrame(() => {
293
+ const menuContainer = element.querySelector('.ant-dropdown-menu');
294
+ if (menuContainer) {
295
+ const container = menuContainer as HTMLElement;
296
+ container.style.maxHeight = `${dropdownMaxHeight}px`;
297
+ container.style.overflowY = 'auto';
298
+ // 移除 ready/opacity 切换,避免可见的淡入闪烁
299
+ }
300
+ });
301
+ }
302
+ }
303
+ });
304
+ });
305
+ });
306
+
307
+ observer.observe(document.body, {
308
+ childList: true,
309
+ subtree: false,
310
+ });
311
+
312
+ const intervalId = setInterval(() => {
313
+ const submenuPopups = document.querySelectorAll('.ant-dropdown-menu-submenu-popup .ant-dropdown-menu');
314
+ submenuPopups.forEach((menu) => {
315
+ const container = menu as HTMLElement;
316
+ const rect = container.getBoundingClientRect();
317
+
318
+ if (rect.width > 0 && rect.height > 0) {
319
+ container.style.maxHeight = `${dropdownMaxHeight}px`;
320
+ container.style.overflowY = 'auto';
321
+ // 无需额外的 class 标记
322
+ }
323
+ });
324
+ }, 200);
325
+
326
+ return () => {
327
+ observer.disconnect();
328
+ clearInterval(intervalId);
329
+ };
330
+ }, [menuVisible, dropdownMaxHeight]);
331
+ };
332
+
333
+ // ==================== Components ====================
334
+
335
+ /**
336
+ * 使搜索输入框在显示下拉菜单时自动聚焦
337
+ */
338
+ const SearchInputWithAutoFocus: FC<InputProps & { visible: boolean }> = (props) => {
339
+ const inputRef = useRef<any>(null);
340
+ const { visible, ...rest } = props;
341
+
342
+ useEffect(() => {
343
+ if (inputRef.current && visible) {
344
+ const el = inputRef.current.input || inputRef.current.resizableTextArea?.textArea || inputRef.current;
345
+ try {
346
+ // 防止聚焦导致页面滚动到顶部
347
+ el?.focus?.({ preventScroll: true });
348
+ } catch (e) {
349
+ el?.focus?.();
350
+ }
351
+ }
352
+ }, [visible]);
353
+
354
+ return <Input ref={inputRef} {...rest} />;
355
+ };
356
+
357
+ // ==================== Utility Functions ====================
358
+
359
+ const getKeyPath = (path: string[], key: string) => [...path, key].join('/');
360
+
361
+ const createSearchItem = (
362
+ item: Item,
363
+ searchKey: string,
364
+ currentSearchValue: string,
365
+ menuVisible: boolean,
366
+ t: (key: string) => string,
367
+ updateSearchValue: (key: string, value: string) => void,
368
+ ) => ({
369
+ key: `${searchKey}-search`,
370
+ type: 'group' as const,
371
+ label: (
372
+ <div>
373
+ <SearchInputWithAutoFocus
374
+ visible={menuVisible}
375
+ variant="borderless"
376
+ allowClear
377
+ placeholder={t(item.searchPlaceholder || 'Search')}
378
+ value={currentSearchValue}
379
+ onChange={(e) => {
380
+ e.stopPropagation();
381
+ updateSearchValue(searchKey, e.target.value);
382
+ }}
383
+ onClick={(e) => e.stopPropagation()}
384
+ onMouseDown={(e) => {
385
+ // 防止菜单聚焦丢失或页面滚动
386
+ e.stopPropagation();
387
+ }}
388
+ size="small"
389
+ style={{
390
+ width: '100%',
391
+ paddingLeft: 0,
392
+ paddingRight: 0,
393
+ }}
394
+ />
395
+ </div>
396
+ ),
397
+ });
398
+
399
+ const createEmptyItem = (itemKey: string, t: (key: string) => string) => ({
400
+ key: `${itemKey}-empty`,
401
+ label: (
402
+ <div style={{ padding: '16px', textAlign: 'center' as const }}>
403
+ <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={t('No data')} style={{ margin: 0 }} />
404
+ </div>
405
+ ),
406
+ disabled: true,
407
+ });
408
+
409
+ // ==================== Main Component ====================
410
+
411
+ // 短暂保持打开状态的注册表(用于跨父节点快速重建时的恢复)
412
+ const DROPDOWN_PERSIST_TTL_MS = 350;
413
+ const dropdownPersistRegistry: Map<string, number> = new Map();
414
+
415
+ const LazyDropdown: React.FC<Omit<DropdownProps, 'menu'> & { menu: LazyDropdownMenuProps }> = ({ menu, ...props }) => {
416
+ const engine = useFlowEngine();
417
+ const [menuVisible, setMenuVisible] = useState(false);
418
+ const [openKeys, setOpenKeys] = useState<Set<string>>(new Set());
419
+ const [rootItems, setRootItems] = useState<Item[]>([]);
420
+ const [rootLoading, setRootLoading] = useState(false);
421
+ const dropdownMaxHeight = useNiceDropdownMaxHeight();
422
+ const t = engine.translate.bind(engine);
423
+
424
+ // 解构 menu,避免在 effect 中直接依赖整个对象,减少不必要的重跑并满足 exhaustive-deps
425
+ const { items: menuItems, keepDropdownOpen, persistKey, stateVersion, refreshKeys, ...dropdownMenuProps } = menu;
426
+
427
+ // 使用自定义 hooks
428
+ const { loadedChildren, loadingKeys, handleLoadChildren } = useAsyncMenuItems(
429
+ menuVisible,
430
+ rootItems,
431
+ stateVersion,
432
+ openKeys,
433
+ refreshKeys,
434
+ );
435
+ const { searchValues, isSearching, updateSearchValue } = useMenuSearch();
436
+ const { requestKeepOpen, shouldPreventClose } = useKeepDropdownOpen();
437
+ useSubmenuStyles(menuVisible, dropdownMaxHeight);
438
+
439
+ // 在挂载时,若存在 persistKey 且仍在持久期内,则尝试恢复打开状态
440
+ useEffect(() => {
441
+ if (!persistKey) return;
442
+ const until = dropdownPersistRegistry.get(persistKey) || 0;
443
+ if (until > Date.now()) {
444
+ setMenuVisible(true);
445
+ }
446
+ }, [persistKey]);
447
+
448
+ // 在卸载时,若当前是打开状态,记录一个短暂的保持时间窗,供下次重挂载时恢复
449
+ useEffect(() => {
450
+ return () => {
451
+ if (persistKey && menuVisible) {
452
+ const until = Date.now() + DROPDOWN_PERSIST_TTL_MS;
453
+ dropdownPersistRegistry.set(persistKey, until);
454
+ // 定时清理
455
+ setTimeout(() => {
456
+ const v = dropdownPersistRegistry.get(persistKey) || 0;
457
+ if (v <= Date.now()) dropdownPersistRegistry.delete(persistKey);
458
+ }, DROPDOWN_PERSIST_TTL_MS + 100);
459
+ }
460
+ };
461
+ }, [persistKey, menuVisible]);
462
+
463
+ // 加载根 items,支持同步/异步函数
464
+ useEffect(() => {
465
+ const loadRootItems = async () => {
466
+ let resolvedItems: Item[];
467
+ if (typeof menuItems === 'function') {
468
+ setRootLoading(true);
469
+ try {
470
+ const res = menuItems();
471
+ resolvedItems = res instanceof Promise ? await res : res;
472
+ } finally {
473
+ setRootLoading(false);
474
+ }
475
+ } else {
476
+ resolvedItems = menuItems;
477
+ }
478
+ setRootItems(resolvedItems);
479
+ };
480
+
481
+ if (menuVisible) {
482
+ loadRootItems();
483
+ }
484
+ }, [menuVisible, stateVersion, menuItems]);
485
+
486
+ // 递归解析 items,支持 children 为同步/异步函数
487
+ function buildSearchChildren(
488
+ children: Item[],
489
+ item: Item,
490
+ keyPath: string,
491
+ path: string[],
492
+ menuVisible: boolean,
493
+ resolve: (items: Item[], path?: string[]) => any[],
494
+ ): any[] {
495
+ const searchKey = keyPath;
496
+ const currentSearchValue = searchValues[searchKey] || '';
497
+
498
+ // 递归过滤:当 child 为分组时,会继续向下过滤其 children;
499
+ // 仅保留自身匹配或存在匹配子项的分组。
500
+ const filteredChildren = currentSearchValue
501
+ ? (function deepFilter(items: Item[]): Item[] {
502
+ const searchText = currentSearchValue.toLowerCase();
503
+ const tryString = (v: any) => {
504
+ if (!v) return '';
505
+ return typeof v === 'string' ? v : String(v);
506
+ };
507
+ return items
508
+ .map((child) => {
509
+ const labelStr = tryString(child.label).toLowerCase();
510
+ const selfMatch =
511
+ labelStr.includes(searchText) || (child.key && String(child.key).toLowerCase().includes(searchText));
512
+ if (child.type === 'group' && Array.isArray(child.children)) {
513
+ const nested = deepFilter(child.children);
514
+ if (selfMatch || nested.length > 0) {
515
+ return { ...child, children: nested } as Item;
516
+ }
517
+ return null;
518
+ }
519
+ return selfMatch ? child : null;
520
+ })
521
+ .filter(Boolean) as Item[];
522
+ })(children)
523
+ : children;
524
+
525
+ const resolvedFiltered = resolve(filteredChildren, [...path, item.key]);
526
+ const searchItem = createSearchItem(item, searchKey, currentSearchValue, menuVisible, t, updateSearchValue);
527
+ const dividerItem = { key: `${keyPath}-search-divider`, type: 'divider' as const };
528
+
529
+ if (currentSearchValue && resolvedFiltered.length === 0) {
530
+ return [searchItem, dividerItem, createEmptyItem(keyPath, t)];
531
+ }
532
+ return [searchItem, dividerItem, ...resolvedFiltered];
533
+ }
534
+
535
+ const resolveItems = (items: Item[], path: string[] = []): any[] => {
536
+ return items.map((item) => {
537
+ const keyPath = getKeyPath(path, item.key);
538
+ const isGroup = item.type === 'group';
539
+ const hasAsyncChildren = typeof item.children === 'function';
540
+ const isLoading = loadingKeys.has(keyPath);
541
+ const loaded = loadedChildren[keyPath];
542
+
543
+ // 非 group 的异步 children,鼠标悬浮时加载
544
+ const shouldLoadChildren =
545
+ !isGroup && menuVisible && openKeys.has(keyPath) && hasAsyncChildren && !loaded && !isLoading;
546
+
547
+ if (shouldLoadChildren) {
548
+ handleLoadChildren(keyPath, item.children as () => Item[] | Promise<Item[]>);
549
+ }
550
+
551
+ let children: Item[] | undefined;
552
+ if (hasAsyncChildren) {
553
+ children = loaded ?? [];
554
+ } else if (Array.isArray(item.children)) {
555
+ children = item.children;
556
+ }
557
+
558
+ if (hasAsyncChildren && !loaded) {
559
+ children = [
560
+ {
561
+ key: `${keyPath}-loading`,
562
+ label: <Spin size="small" />,
563
+ disabled: true,
564
+ } as Item,
565
+ ];
566
+ }
567
+
568
+ if (isGroup) {
569
+ // 对于 group 的异步 children,若尚未加载则在解析阶段直接触发加载,
570
+ // 以支持“嵌套分组”的按需预取(上层 effect 仅能捕获到初始根层分组)。
571
+ if (hasAsyncChildren && !loaded && menuVisible) {
572
+ handleLoadChildren(keyPath, item.children as () => Item[] | Promise<Item[]>);
573
+ }
574
+ let groupChildren = children ? resolveItems(children, [...path, item.key]) : [];
575
+
576
+ // 如果 group 启用了搜索功能,在 children 前面添加搜索框
577
+ if (item.searchable && children) {
578
+ groupChildren = buildSearchChildren(children, item, keyPath, path, menuVisible, resolveItems);
579
+ }
580
+
581
+ return {
582
+ type: 'group',
583
+ key: keyPath,
584
+ label: typeof item.label === 'string' ? t(item.label) : item.label,
585
+ children: groupChildren,
586
+ };
587
+ }
588
+
589
+ if (item.type === 'divider') {
590
+ return { type: 'divider', key: keyPath };
591
+ }
592
+
593
+ // 非 group 的“子菜单”也支持本层级搜索:当 item.searchable = true 且存在 children 时
594
+ if (item.searchable && children) {
595
+ return {
596
+ key: item.key,
597
+ label: typeof item.label === 'string' ? t(item.label) : item.label,
598
+ onClick: (info: any) => {},
599
+ onMouseEnter: () => {
600
+ setOpenKeys((prev) => {
601
+ if (prev.has(keyPath)) return prev;
602
+ const next = new Set(prev);
603
+ next.add(keyPath);
604
+ return next;
605
+ });
606
+ },
607
+ children: buildSearchChildren(children, item, keyPath, path, menuVisible, resolveItems),
608
+ };
609
+ }
610
+
611
+ return {
612
+ key: keyPath,
613
+ label: typeof item.label === 'string' ? t(item.label) : item.label,
614
+ onClick: (info: any) => {
615
+ if (children) {
616
+ return;
617
+ }
618
+
619
+ // 检查是否应该保持下拉菜单打开
620
+ const itemShouldKeepOpen = item.keepDropdownOpen ?? keepDropdownOpen ?? false;
621
+
622
+ // 如果需要保持菜单打开,请求保持打开状态
623
+ if (itemShouldKeepOpen) {
624
+ requestKeepOpen();
625
+ }
626
+
627
+ const extendedInfo: ExtendedMenuInfo = {
628
+ ...info,
629
+ item: info.item || item,
630
+ originalItem: item,
631
+ keepDropdownOpen: itemShouldKeepOpen,
632
+ };
633
+
634
+ menu.onClick?.(extendedInfo);
635
+ },
636
+ onMouseEnter: () => {
637
+ setOpenKeys((prev) => {
638
+ if (prev.has(keyPath)) return prev;
639
+ const next = new Set(prev);
640
+ next.add(keyPath);
641
+ return next;
642
+ });
643
+ },
644
+ children:
645
+ children && children.length > 0
646
+ ? resolveItems(children, [...path, item.key])
647
+ : children && children.length === 0
648
+ ? [createEmptyItem(keyPath, t)]
649
+ : undefined,
650
+ };
651
+ });
652
+ };
653
+
654
+ // 创建优化的 CSS 样式
655
+ const overlayClassName = useMemo(() => {
656
+ return css`
657
+ .ant-dropdown-menu {
658
+ max-height: ${dropdownMaxHeight}px;
659
+ overflow-y: auto;
660
+ }
661
+ .ant-dropdown-menu-submenu-popup .ant-dropdown-menu,
662
+ .ant-dropdown-menu-submenu-popup .ant-dropdown-menu-submenu-popup .ant-dropdown-menu {
663
+ max-height: ${dropdownMaxHeight}px !important;
664
+ overflow-y: auto !important;
665
+ }
666
+ `;
667
+ }, [dropdownMaxHeight]);
668
+
669
+ return (
670
+ <Dropdown
671
+ {...props}
672
+ open={menuVisible}
673
+ destroyPopupOnHide
674
+ overlayClassName={overlayClassName}
675
+ placement="bottomLeft"
676
+ menu={{
677
+ ...dropdownMenuProps,
678
+ items:
679
+ rootLoading && rootItems.length === 0
680
+ ? [
681
+ {
682
+ key: 'root-loading',
683
+ label: <Spin size="small" />,
684
+ disabled: true,
685
+ },
686
+ ]
687
+ : resolveItems(rootItems),
688
+ onClick: () => {},
689
+ style: {
690
+ maxHeight: dropdownMaxHeight,
691
+ overflowY: 'auto',
692
+ ...dropdownMenuProps?.style,
693
+ },
694
+ }}
695
+ onOpenChange={(visible) => {
696
+ // 阻止在搜索时关闭菜单
697
+ if (!visible && isSearching) {
698
+ return;
699
+ }
700
+
701
+ // 阻止在需要保持打开时关闭菜单
702
+ if (!visible && shouldPreventClose()) {
703
+ return;
704
+ }
705
+
706
+ setMenuVisible(visible);
707
+ }}
708
+ >
709
+ {props.children}
710
+ </Dropdown>
711
+ );
712
+ };
713
+
714
+ export default LazyDropdown;