@nocobase/flow-engine 2.1.0-beta.2 → 2.1.0-beta.21

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 (126) 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/FlowModelRenderer.d.ts +1 -1
  7. package/lib/components/FlowModelRenderer.js +10 -6
  8. package/lib/components/MobilePopup.js +6 -5
  9. package/lib/components/dnd/gridDragPlanner.js +6 -2
  10. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +3 -0
  11. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +48 -9
  12. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +19 -43
  13. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +339 -295
  14. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +16 -2
  15. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.d.ts +36 -0
  16. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +272 -0
  17. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.d.ts +30 -0
  18. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +247 -0
  19. package/lib/components/subModel/AddSubModelButton.js +27 -1
  20. package/lib/components/subModel/utils.js +2 -2
  21. package/lib/data-source/index.js +6 -0
  22. package/lib/executor/FlowExecutor.js +31 -8
  23. package/lib/flowContext.js +31 -1
  24. package/lib/flowEngine.d.ts +151 -1
  25. package/lib/flowEngine.js +389 -15
  26. package/lib/flowSettings.d.ts +14 -6
  27. package/lib/flowSettings.js +34 -6
  28. package/lib/lazy-helper.d.ts +14 -0
  29. package/lib/lazy-helper.js +71 -0
  30. package/lib/locale/en-US.json +1 -0
  31. package/lib/locale/index.d.ts +2 -0
  32. package/lib/locale/zh-CN.json +1 -0
  33. package/lib/models/flowModel.d.ts +2 -1
  34. package/lib/models/flowModel.js +28 -9
  35. package/lib/reactive/observer.js +46 -16
  36. package/lib/runjs-context/registry.d.ts +1 -1
  37. package/lib/runjs-context/setup.js +20 -12
  38. package/lib/runjs-context/snippets/index.js +13 -2
  39. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts +11 -0
  40. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.js +50 -0
  41. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts +11 -0
  42. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
  43. package/lib/scheduler/ModelOperationScheduler.d.ts +5 -1
  44. package/lib/scheduler/ModelOperationScheduler.js +3 -2
  45. package/lib/types.d.ts +47 -1
  46. package/lib/utils/index.d.ts +2 -2
  47. package/lib/utils/index.js +4 -0
  48. package/lib/utils/parsePathnameToViewParams.js +1 -1
  49. package/lib/utils/runjsTemplateCompat.js +1 -1
  50. package/lib/utils/runjsValue.js +41 -11
  51. package/lib/utils/schema-utils.d.ts +7 -1
  52. package/lib/utils/schema-utils.js +19 -0
  53. package/lib/views/FlowView.d.ts +7 -1
  54. package/lib/views/runViewBeforeClose.d.ts +10 -0
  55. package/lib/views/runViewBeforeClose.js +45 -0
  56. package/lib/views/useDialog.d.ts +2 -1
  57. package/lib/views/useDialog.js +20 -3
  58. package/lib/views/useDrawer.d.ts +2 -1
  59. package/lib/views/useDrawer.js +20 -3
  60. package/lib/views/usePage.d.ts +2 -1
  61. package/lib/views/usePage.js +10 -3
  62. package/package.json +6 -5
  63. package/src/JSRunner.ts +68 -4
  64. package/src/ViewScopedFlowEngine.ts +4 -0
  65. package/src/__tests__/JSRunner.test.ts +27 -1
  66. package/src/__tests__/flow-engine.test.ts +166 -0
  67. package/src/__tests__/flowContext.test.ts +65 -1
  68. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  69. package/src/__tests__/flowSettings.test.ts +94 -15
  70. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  71. package/src/__tests__/runjsContext.test.ts +16 -0
  72. package/src/__tests__/runjsContextRuntime.test.ts +2 -0
  73. package/src/__tests__/runjsPreprocessDefault.test.ts +23 -0
  74. package/src/__tests__/runjsSnippets.test.ts +21 -0
  75. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  76. package/src/components/FlowModelRenderer.tsx +12 -6
  77. package/src/components/MobilePopup.tsx +4 -2
  78. package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
  79. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +20 -10
  80. package/src/components/__tests__/gridDragPlanner.test.ts +88 -0
  81. package/src/components/dnd/gridDragPlanner.ts +8 -2
  82. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +63 -9
  83. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +468 -440
  84. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +18 -2
  85. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +95 -0
  86. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +609 -0
  87. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +358 -0
  88. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +281 -0
  89. package/src/components/subModel/AddSubModelButton.tsx +32 -2
  90. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +142 -32
  91. package/src/components/subModel/utils.ts +1 -1
  92. package/src/data-source/index.ts +6 -0
  93. package/src/executor/FlowExecutor.ts +34 -9
  94. package/src/executor/__tests__/flowExecutor.test.ts +57 -0
  95. package/src/flowContext.ts +35 -3
  96. package/src/flowEngine.ts +445 -11
  97. package/src/flowSettings.ts +40 -6
  98. package/src/lazy-helper.tsx +57 -0
  99. package/src/locale/en-US.json +1 -0
  100. package/src/locale/zh-CN.json +1 -0
  101. package/src/models/__tests__/dispatchEvent.when.test.ts +214 -0
  102. package/src/models/flowModel.tsx +31 -10
  103. package/src/reactive/__tests__/observer.test.tsx +82 -0
  104. package/src/reactive/observer.tsx +87 -25
  105. package/src/runjs-context/registry.ts +1 -1
  106. package/src/runjs-context/setup.ts +22 -12
  107. package/src/runjs-context/snippets/index.ts +12 -1
  108. package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
  109. package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
  110. package/src/scheduler/ModelOperationScheduler.ts +14 -3
  111. package/src/types.ts +60 -0
  112. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +7 -0
  113. package/src/utils/__tests__/runjsValue.test.ts +11 -0
  114. package/src/utils/__tests__/utils.test.ts +62 -0
  115. package/src/utils/index.ts +2 -1
  116. package/src/utils/parsePathnameToViewParams.ts +2 -2
  117. package/src/utils/runjsTemplateCompat.ts +1 -1
  118. package/src/utils/runjsValue.ts +50 -11
  119. package/src/utils/schema-utils.ts +30 -1
  120. package/src/views/FlowView.tsx +11 -1
  121. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  122. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +13 -12
  123. package/src/views/runViewBeforeClose.ts +19 -0
  124. package/src/views/useDialog.tsx +25 -3
  125. package/src/views/useDrawer.tsx +25 -3
  126. package/src/views/usePage.tsx +12 -3
@@ -0,0 +1,71 @@
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
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, { get: all[name], enumerable: true });
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (let key of __getOwnPropNames(from))
24
+ if (!__hasOwnProp.call(to, key) && key !== except)
25
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
26
+ }
27
+ return to;
28
+ };
29
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
30
+ // If the importer is in node compatibility mode or this is not an ESM
31
+ // file that has been converted to a CommonJS file using a Babel-
32
+ // compatible transform (i.e. "__esModule" has not been set), then set
33
+ // "default" to the CommonJS "module.exports" for node compatibility.
34
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
35
+ mod
36
+ ));
37
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
+ var lazy_helper_exports = {};
39
+ __export(lazy_helper_exports, {
40
+ lazy: () => lazy
41
+ });
42
+ module.exports = __toCommonJS(lazy_helper_exports);
43
+ var import_react = __toESM(require("react"));
44
+ function lazy(factory, ...componentNames) {
45
+ if (componentNames.length === 0) {
46
+ const LazyComponent = (0, import_react.lazy)(
47
+ () => factory().then((module2) => ({
48
+ default: module2.default
49
+ }))
50
+ );
51
+ const Component = /* @__PURE__ */ __name((props) => /* @__PURE__ */ import_react.default.createElement(import_react.default.Suspense, { fallback: null }, /* @__PURE__ */ import_react.default.createElement(LazyComponent, { ...props })), "Component");
52
+ return Component;
53
+ }
54
+ return componentNames.reduce(
55
+ (acc, name) => {
56
+ const LazyComponent = (0, import_react.lazy)(
57
+ () => factory().then((module2) => ({
58
+ default: module2[name]
59
+ }))
60
+ );
61
+ acc[name] = (props) => /* @__PURE__ */ import_react.default.createElement(import_react.default.Suspense, { fallback: null }, /* @__PURE__ */ import_react.default.createElement(LazyComponent, { ...props }));
62
+ return acc;
63
+ },
64
+ {}
65
+ );
66
+ }
67
+ __name(lazy, "lazy");
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ lazy
71
+ });
@@ -34,6 +34,7 @@
34
34
  "Failed to destroy model after creation error": "Failed to destroy model after creation error",
35
35
  "Failed to get action {{action}}": "Failed to get action {{action}}",
36
36
  "Failed to get configurable flows for model {{model}}": "Failed to get configurable flows for model {{model}}",
37
+ "Attributes are unavailable before selecting a record": "Attributes are unavailable before selecting a record",
37
38
  "Failed to import FormDialog": "Failed to import FormDialog",
38
39
  "Failed to import FormDialog or FormStep": "Failed to import FormDialog or FormStep",
39
40
  "Failed to import Formily components": "Failed to import Formily components",
@@ -43,6 +43,7 @@ export declare const locales: {
43
43
  "Failed to destroy model after creation error": string;
44
44
  "Failed to get action {{action}}": string;
45
45
  "Failed to get configurable flows for model {{model}}": string;
46
+ "Attributes are unavailable before selecting a record": string;
46
47
  "Failed to import FormDialog": string;
47
48
  "Failed to import FormDialog or FormStep": string;
48
49
  "Failed to import Formily components": string;
@@ -120,6 +121,7 @@ export declare const locales: {
120
121
  "Failed to destroy model after creation error": string;
121
122
  "Failed to get action {{action}}": string;
122
123
  "Failed to get configurable flows for model {{model}}": string;
124
+ "Attributes are unavailable before selecting a record": string;
123
125
  "Failed to import FormDialog": string;
124
126
  "Failed to import FormDialog or FormStep": string;
125
127
  "Failed to import Formily components": string;
@@ -31,6 +31,7 @@
31
31
  "Failed to destroy model after creation error": "创建错误后销毁模型失败",
32
32
  "Failed to get action {{action}}": "获取 action '{{action}}' 失败",
33
33
  "Failed to get configurable flows for model {{model}}": "获取模型 '{{model}}' 的可配置 flows 失败",
34
+ "Attributes are unavailable before selecting a record": "选择记录之前,当前项属性不可用",
34
35
  "Failed to import FormDialog": "导入 FormDialog 失败",
35
36
  "Failed to import FormDialog or FormStep": "导入 FormDialog 或 FormStep 失败",
36
37
  "Failed to import Formily components": "导入 Formily 组件失败",
@@ -13,6 +13,7 @@ import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContex
13
13
  import { FlowEngine } from '../flowEngine';
14
14
  import type { ActionDefinition, ArrayElementType, CreateModelOptions, CreateSubModelOptions, DefaultStructure, FlowDefinitionOptions, FlowModelMeta, FlowModelOptions, ModelConstructor, ParamObject, ParentFlowModel, PersistOptions, ResolveUseResult, StepParams } from '../types';
15
15
  import { IModelComponentProps, ReadonlyModelProps } from '../types';
16
+ import type { MenuProps } from 'antd';
16
17
  import { ModelActionRegistry } from '../action-registry/ModelActionRegistry';
17
18
  import { ModelEventRegistry } from '../event-registry/ModelEventRegistry';
18
19
  import { GlobalFlowRegistry } from '../flow-registry/GlobalFlowRegistry';
@@ -21,7 +22,6 @@ import { FlowSettingsOpenOptions } from '../flowSettings';
21
22
  import type { ScheduleOptions } from '../scheduler/ModelOperationScheduler';
22
23
  import type { DispatchEventOptions, EventDefinition } from '../types';
23
24
  import { ForkFlowModel } from './forkFlowModel';
24
- import type { MenuProps } from 'antd';
25
25
  type BaseMenuItem = NonNullable<MenuProps['items']>[number];
26
26
  type MenuLeafItem = Exclude<BaseMenuItem, {
27
27
  children: MenuProps['items'];
@@ -239,6 +239,7 @@ export declare class FlowModel<Structure extends DefaultStructure = DefaultStruc
239
239
  * 使用 lodash debounce 避免频繁调用
240
240
  */
241
241
  private _rerunLastAutoRun;
242
+ private resetAutoRunState;
242
243
  /**
243
244
  * 通用事件分发钩子:开始
244
245
  * 子类可覆盖;beforeRender 事件可通过抛出 FlowExitException 提前终止。
@@ -56,25 +56,33 @@ var import_reactive = require("@formily/reactive");
56
56
  var import_lodash = __toESM(require("lodash"));
57
57
  var import_react = __toESM(require("react"));
58
58
  var import_secure = require("uid/secure");
59
- var import_StepRequiredSettingsDialog = require("../components/settings/wrappers/contextual/StepRequiredSettingsDialog");
60
- var import_StepSettingsDialog = require("../components/settings/wrappers/contextual/StepSettingsDialog");
61
59
  var import_emitter = require("../emitter");
62
60
  var import_InstanceFlowRegistry = require("../flow-registry/InstanceFlowRegistry");
63
61
  var import_flowContext = require("../flowContext");
64
62
  var import_utils = require("../utils");
65
- var import_lib = require("antd/lib");
63
+ var import_antd = require("antd");
64
+ var import__ = require("..");
66
65
  var import_ModelActionRegistry = require("../action-registry/ModelActionRegistry");
67
66
  var import_utils2 = require("../components/subModel/utils");
68
67
  var import_ModelEventRegistry = require("../event-registry/ModelEventRegistry");
69
68
  var import_GlobalFlowRegistry = require("../flow-registry/GlobalFlowRegistry");
70
69
  var import_forkFlowModel = require("./forkFlowModel");
71
- var import__ = require("..");
72
70
  var _flowContext;
73
71
  const classActionRegistries = /* @__PURE__ */ new WeakMap();
74
72
  const classEventRegistries = /* @__PURE__ */ new WeakMap();
75
73
  const modelMetas = /* @__PURE__ */ new WeakMap();
76
74
  const modelGlobalRegistries = /* @__PURE__ */ new WeakMap();
77
75
  const classMenuExtensions = /* @__PURE__ */ new WeakMap();
76
+ async function loadOpenStepSettingsDialog() {
77
+ const mod = await import("../components/settings/wrappers/contextual/StepSettingsDialog");
78
+ return mod.openStepSettingsDialog;
79
+ }
80
+ __name(loadOpenStepSettingsDialog, "loadOpenStepSettingsDialog");
81
+ async function loadOpenRequiredParamsStepFormDialog() {
82
+ const mod = await import("../components/settings/wrappers/contextual/StepRequiredSettingsDialog");
83
+ return mod.openRequiredParamsStepFormDialog;
84
+ }
85
+ __name(loadOpenRequiredParamsStepFormDialog, "loadOpenRequiredParamsStepFormDialog");
78
86
  var ModelRenderMode = /* @__PURE__ */ ((ModelRenderMode2) => {
79
87
  ModelRenderMode2["ReactElement"] = "reactElement";
80
88
  ModelRenderMode2["RenderFunction"] = "renderFunction";
@@ -183,10 +191,13 @@ const _FlowModel = class _FlowModel {
183
191
  if (changed.type === "set" && import_lodash.default.isEqual(changed.value, changed.oldValue)) {
184
192
  return;
185
193
  }
194
+ const hasLastAutoRun = !!this._lastAutoRunParams;
186
195
  if (this.flowEngine) {
187
196
  this.invalidateFlowCache("beforeRender");
188
197
  }
189
- this._rerunLastAutoRun();
198
+ if (hasLastAutoRun) {
199
+ this._rerunLastAutoRun();
200
+ }
190
201
  this.forks.forEach((fork) => {
191
202
  fork.rerender();
192
203
  });
@@ -674,6 +685,11 @@ const _FlowModel = class _FlowModel {
674
685
  }, "isMatch");
675
686
  return Array.from(allFlows.values()).filter(isMatch);
676
687
  }
688
+ resetAutoRunState() {
689
+ var _a, _b;
690
+ (_b = (_a = this._rerunLastAutoRun) == null ? void 0 : _a.cancel) == null ? void 0 : _b.call(_a);
691
+ this._lastAutoRunParams = null;
692
+ }
677
693
  /**
678
694
  * 通用事件分发钩子:开始
679
695
  * 子类可覆盖;beforeRender 事件可通过抛出 FlowExitException 提前终止。
@@ -763,6 +779,7 @@ const _FlowModel = class _FlowModel {
763
779
  }));
764
780
  return () => {
765
781
  var _a3, _b3;
782
+ renderTarget.resetAutoRunState();
766
783
  if (typeof renderTarget.onUnmount === "function") {
767
784
  renderTarget.onUnmount();
768
785
  }
@@ -1058,7 +1075,7 @@ const _FlowModel = class _FlowModel {
1058
1075
  * @param {string} stepKey 步骤的唯一标识符
1059
1076
  * @returns {void}
1060
1077
  */
1061
- openStepSettingsDialog(flowKey, stepKey) {
1078
+ async openStepSettingsDialog(flowKey, stepKey) {
1062
1079
  var _a;
1063
1080
  const flow = this.getFlow(flowKey);
1064
1081
  const step = (_a = flow == null ? void 0 : flow.steps) == null ? void 0 : _a[stepKey];
@@ -1069,7 +1086,8 @@ const _FlowModel = class _FlowModel {
1069
1086
  const ctx = new import_flowContext.FlowRuntimeContext(this, flowKey, "settings");
1070
1087
  (0, import_utils.setupRuntimeContextSteps)(ctx, flow.steps, this, flowKey);
1071
1088
  ctx.defineProperty("currentStep", { value: step });
1072
- return (0, import_StepSettingsDialog.openStepSettingsDialog)({
1089
+ const openStepSettingsDialog = await loadOpenStepSettingsDialog();
1090
+ return openStepSettingsDialog({
1073
1091
  model: this,
1074
1092
  flowKey,
1075
1093
  stepKey,
@@ -1084,7 +1102,8 @@ const _FlowModel = class _FlowModel {
1084
1102
  * @returns {Promise<any>} 返回表单提交的值
1085
1103
  */
1086
1104
  async configureRequiredSteps(dialogWidth, dialogTitle) {
1087
- return (0, import_StepRequiredSettingsDialog.openRequiredParamsStepFormDialog)({
1105
+ const openRequiredParamsStepFormDialog = await loadOpenRequiredParamsStepFormDialog();
1106
+ return openRequiredParamsStepFormDialog({
1088
1107
  model: this,
1089
1108
  dialogWidth,
1090
1109
  dialogTitle
@@ -1303,7 +1322,7 @@ const _ErrorFlowModel = class _ErrorFlowModel extends FlowModel {
1303
1322
  this.errorMessage = msg;
1304
1323
  }
1305
1324
  render() {
1306
- return /* @__PURE__ */ import_react.default.createElement(import_lib.Typography.Text, { type: "danger" }, this.errorMessage);
1325
+ return /* @__PURE__ */ import_react.default.createElement(import_antd.Typography.Text, { type: "danger" }, this.errorMessage);
1307
1326
  }
1308
1327
  };
1309
1328
  __name(_ErrorFlowModel, "ErrorFlowModel");
@@ -51,8 +51,31 @@ const observer = /* @__PURE__ */ __name((Component, options) => {
51
51
  const ctxRef = (0, import_react.useRef)(ctx);
52
52
  ctxRef.current = ctx;
53
53
  const pendingDisposerRef = (0, import_react.useRef)(null);
54
+ const pendingTimerRef = (0, import_react.useRef)(null);
55
+ const clearPendingDisposer = /* @__PURE__ */ __name(() => {
56
+ if (pendingDisposerRef.current) {
57
+ pendingDisposerRef.current();
58
+ pendingDisposerRef.current = null;
59
+ }
60
+ }, "clearPendingDisposer");
61
+ const clearPendingTimer = /* @__PURE__ */ __name(() => {
62
+ if (pendingTimerRef.current) {
63
+ clearTimeout(pendingTimerRef.current);
64
+ pendingTimerRef.current = null;
65
+ }
66
+ }, "clearPendingTimer");
67
+ const isContextActive = /* @__PURE__ */ __name(() => {
68
+ var _a, _b;
69
+ const pageActive = getPageActive(ctxRef.current);
70
+ const tabActive = (_b = (_a = ctxRef.current) == null ? void 0 : _a.tabActive) == null ? void 0 : _b.value;
71
+ return pageActive !== false && tabActive !== false;
72
+ }, "isContextActive");
54
73
  (0, import_react.useEffect)(() => {
55
74
  return () => {
75
+ if (pendingTimerRef.current) {
76
+ clearTimeout(pendingTimerRef.current);
77
+ pendingTimerRef.current = null;
78
+ }
56
79
  if (pendingDisposerRef.current) {
57
80
  pendingDisposerRef.current();
58
81
  pendingDisposerRef.current = null;
@@ -62,30 +85,37 @@ const observer = /* @__PURE__ */ __name((Component, options) => {
62
85
  const ObservedComponent = (0, import_react.useMemo)(
63
86
  () => (0, import_reactive_react.observer)(Component, {
64
87
  scheduler(updater) {
65
- var _a, _b;
66
- const pageActive = getPageActive(ctxRef.current);
67
- const tabActive = (_b = (_a = ctxRef.current) == null ? void 0 : _a.tabActive) == null ? void 0 : _b.value;
68
- if (pageActive === false || tabActive === false) {
69
- setTimeout(() => {
88
+ if (!isContextActive()) {
89
+ if (pendingTimerRef.current || pendingDisposerRef.current) {
90
+ return;
91
+ }
92
+ pendingTimerRef.current = setTimeout(() => {
93
+ pendingTimerRef.current = null;
70
94
  if (pendingDisposerRef.current) {
71
95
  return;
72
96
  }
73
- const disposer = (0, import_reactive.autorun)(() => {
74
- var _a2, _b2, _c, _d, _e, _f;
75
- if (((_b2 = (_a2 = ctxRef.current) == null ? void 0 : _a2.pageActive) == null ? void 0 : _b2.value) && (((_d = (_c = ctxRef.current) == null ? void 0 : _c.tabActive) == null ? void 0 : _d.value) === true || ((_f = (_e = ctxRef.current) == null ? void 0 : _e.tabActive) == null ? void 0 : _f.value) === void 0)) {
97
+ if (isContextActive()) {
98
+ updater();
99
+ return;
100
+ }
101
+ pendingDisposerRef.current = (0, import_reactive.reaction)(
102
+ () => isContextActive(),
103
+ (active) => {
104
+ if (!active) {
105
+ return;
106
+ }
107
+ clearPendingDisposer();
76
108
  updater();
77
- disposer == null ? void 0 : disposer();
78
- pendingDisposerRef.current = null;
109
+ },
110
+ {
111
+ name: "FlowObserverPendingUpdate"
79
112
  }
80
- });
81
- pendingDisposerRef.current = disposer;
113
+ );
82
114
  });
83
115
  return;
84
116
  }
85
- if (pendingDisposerRef.current) {
86
- pendingDisposerRef.current();
87
- pendingDisposerRef.current = null;
88
- }
117
+ clearPendingTimer();
118
+ clearPendingDisposer();
89
119
  updater();
90
120
  },
91
121
  ...options
@@ -6,7 +6,7 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- export type RunJSVersion = 'v1' | (string & {});
9
+ export type RunJSVersion = 'v1' | 'v2' | (string & {});
10
10
  export type RunJSContextCtor = new (delegate: any) => any;
11
11
  export type RunJSContextMeta = {
12
12
  scenes?: string[];
@@ -67,19 +67,27 @@ async function setupRunJSContexts() {
67
67
  import("./contexts/JSRecordActionRunJSContext"),
68
68
  import("./contexts/JSCollectionActionRunJSContext")
69
69
  ]);
70
- const v1 = "v1";
71
- import_registry.RunJSContextRegistry.register(v1, "*", import_flowContext.FlowRunJSContext);
72
- import_registry.RunJSContextRegistry.register(v1, "JSBlockModel", JSBlockRunJSContext, { scenes: ["block"] });
73
- import_registry.RunJSContextRegistry.register(v1, "JSFieldModel", JSFieldRunJSContext, { scenes: ["detail"] });
74
- import_registry.RunJSContextRegistry.register(v1, "JSEditableFieldModel", JSEditableFieldRunJSContext, { scenes: ["form"] });
75
- import_registry.RunJSContextRegistry.register(v1, "JSItemModel", JSItemRunJSContext, { scenes: ["form"] });
76
- import_registry.RunJSContextRegistry.register(v1, "JSColumnModel", JSColumnRunJSContext, { scenes: ["table"] });
77
- import_registry.RunJSContextRegistry.register(v1, "FormJSFieldItemModel", FormJSFieldItemRunJSContext, { scenes: ["form"] });
78
- import_registry.RunJSContextRegistry.register(v1, "JSRecordActionModel", JSRecordActionRunJSContext, { scenes: ["table"] });
79
- import_registry.RunJSContextRegistry.register(v1, "JSCollectionActionModel", JSCollectionActionRunJSContext, { scenes: ["table"] });
80
- await (0, import_contributions.applyRunJSContextContributions)(v1);
70
+ const registerBuiltins = /* @__PURE__ */ __name((version) => {
71
+ import_registry.RunJSContextRegistry.register(version, "*", import_flowContext.FlowRunJSContext);
72
+ import_registry.RunJSContextRegistry.register(version, "JSBlockModel", JSBlockRunJSContext, { scenes: ["block"] });
73
+ import_registry.RunJSContextRegistry.register(version, "JSFieldModel", JSFieldRunJSContext, { scenes: ["detail"] });
74
+ import_registry.RunJSContextRegistry.register(version, "JSEditableFieldModel", JSEditableFieldRunJSContext, { scenes: ["form"] });
75
+ import_registry.RunJSContextRegistry.register(version, "JSItemModel", JSItemRunJSContext, { scenes: ["form"] });
76
+ import_registry.RunJSContextRegistry.register(version, "JSItemActionModel", JSItemRunJSContext, { scenes: ["table"] });
77
+ import_registry.RunJSContextRegistry.register(version, "JSColumnModel", JSColumnRunJSContext, { scenes: ["table"] });
78
+ import_registry.RunJSContextRegistry.register(version, "FormJSFieldItemModel", FormJSFieldItemRunJSContext, { scenes: ["form"] });
79
+ import_registry.RunJSContextRegistry.register(version, "JSRecordActionModel", JSRecordActionRunJSContext, { scenes: ["table"] });
80
+ import_registry.RunJSContextRegistry.register(version, "JSCollectionActionModel", JSCollectionActionRunJSContext, {
81
+ scenes: ["table"]
82
+ });
83
+ }, "registerBuiltins");
84
+ const versions = ["v1", "v2"];
85
+ for (const version of versions) {
86
+ registerBuiltins(version);
87
+ await (0, import_contributions.applyRunJSContextContributions)(version);
88
+ (0, import_contributions.markRunJSContextsSetupDone)(version);
89
+ }
81
90
  done = true;
82
- (0, import_contributions.markRunJSContextsSetupDone)(v1);
83
91
  }
84
92
  __name(setupRunJSContexts, "setupRunJSContexts");
85
93
  // Annotate the CommonJS export names for ESM import in node:
@@ -81,6 +81,7 @@ const snippets = {
81
81
  "scene/detail/status-tag": /* @__PURE__ */ __name(() => import("./scene/detail/status-tag.snippet"), "scene/detail/status-tag"),
82
82
  "scene/detail/relative-time": /* @__PURE__ */ __name(() => import("./scene/detail/relative-time.snippet"), "scene/detail/relative-time"),
83
83
  "scene/detail/percentage-bar": /* @__PURE__ */ __name(() => import("./scene/detail/percentage-bar.snippet"), "scene/detail/percentage-bar"),
84
+ "scene/detail/set-field-style": /* @__PURE__ */ __name(() => import("./scene/detail/set-field-style.snippet"), "scene/detail/set-field-style"),
84
85
  // scene/form
85
86
  "scene/form/render-basic": /* @__PURE__ */ __name(() => import("./scene/form/render-basic.snippet"), "scene/form/render-basic"),
86
87
  "scene/form/set-field-value": /* @__PURE__ */ __name(() => import("./scene/form/set-field-value.snippet"), "scene/form/set-field-value"),
@@ -98,7 +99,8 @@ const snippets = {
98
99
  "scene/table/collection-selected-count": /* @__PURE__ */ __name(() => import("./scene/table/collection-selected-count.snippet"), "scene/table/collection-selected-count"),
99
100
  "scene/table/iterate-selected-rows": /* @__PURE__ */ __name(() => import("./scene/table/iterate-selected-rows.snippet"), "scene/table/iterate-selected-rows"),
100
101
  "scene/table/destroy-selected": /* @__PURE__ */ __name(() => import("./scene/table/destroy-selected.snippet"), "scene/table/destroy-selected"),
101
- "scene/table/export-selected-json": /* @__PURE__ */ __name(() => import("./scene/table/export-selected-json.snippet"), "scene/table/export-selected-json")
102
+ "scene/table/export-selected-json": /* @__PURE__ */ __name(() => import("./scene/table/export-selected-json.snippet"), "scene/table/export-selected-json"),
103
+ "scene/table/set-cell-style": /* @__PURE__ */ __name(() => import("./scene/table/set-cell-style.snippet"), "scene/table/set-cell-style")
102
104
  };
103
105
  var snippets_default = snippets;
104
106
  function registerRunJSSnippet(ref, loader, options) {
@@ -131,10 +133,19 @@ function normalizeScenes(def, key) {
131
133
  return [];
132
134
  }
133
135
  __name(normalizeScenes, "normalizeScenes");
136
+ function normalizeSceneGroup(scene) {
137
+ const mapping = {
138
+ detailFieldEvent: "detail",
139
+ tableFieldEvent: "table",
140
+ formFieldEvent: "form"
141
+ };
142
+ return mapping[scene] || scene;
143
+ }
144
+ __name(normalizeSceneGroup, "normalizeSceneGroup");
134
145
  function computeGroups(def, key) {
135
146
  const scenes = normalizeScenes(def, key);
136
147
  if (scenes.length) {
137
- return scenes.map((scene) => `scene/${scene}`);
148
+ return Array.from(new Set(scenes.map((scene) => `scene/${normalizeSceneGroup(scene)}`)));
138
149
  }
139
150
  const parts = key.split("/");
140
151
  if (!parts.length) return [];
@@ -0,0 +1,11 @@
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
+ import type { SnippetModule } from '../../types';
10
+ declare const snippet: SnippetModule;
11
+ export default snippet;
@@ -0,0 +1,50 @@
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
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var set_field_style_snippet_exports = {};
28
+ __export(set_field_style_snippet_exports, {
29
+ default: () => set_field_style_snippet_default
30
+ });
31
+ module.exports = __toCommonJS(set_field_style_snippet_exports);
32
+ const snippet = {
33
+ contexts: ["*"],
34
+ scenes: ["detailFieldEvent", "formFieldEvent"],
35
+ prefix: "sn-item-style",
36
+ label: "Set form item/details item style",
37
+ description: "Customize form item and details item container styles",
38
+ locales: {
39
+ "zh-CN": {
40
+ label: "\u8BBE\u7F6E\u8868\u5355\u9879/\u8BE6\u60C5\u9879\u6837\u5F0F",
41
+ description: "\u81EA\u5B9A\u4E49\u8868\u5355\u9879\u548C\u8BE6\u60C5\u9879\u5BB9\u5668\u6837\u5F0F"
42
+ }
43
+ },
44
+ content: `
45
+ ctx.model.props.style = {
46
+ background: 'red',
47
+ };
48
+ `
49
+ };
50
+ var set_field_style_snippet_default = snippet;
@@ -0,0 +1,11 @@
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
+ import type { SnippetModule } from '../../types';
10
+ declare const snippet: SnippetModule;
11
+ export default snippet;
@@ -0,0 +1,54 @@
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
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var set_cell_style_snippet_exports = {};
28
+ __export(set_cell_style_snippet_exports, {
29
+ default: () => set_cell_style_snippet_default
30
+ });
31
+ module.exports = __toCommonJS(set_cell_style_snippet_exports);
32
+ const snippet = {
33
+ contexts: ["*"],
34
+ scenes: ["tableFieldEvent"],
35
+ prefix: "sn-table-cell-style",
36
+ label: "Set table cell style",
37
+ description: "Customize table field cell styles with onCell",
38
+ locales: {
39
+ "zh-CN": {
40
+ label: "\u8868\u683C\u5B57\u6BB5\u6837\u5F0F\u8BBE\u7F6E",
41
+ description: "\u901A\u8FC7 onCell \u81EA\u5B9A\u4E49\u8868\u683C\u5B57\u6BB5\u5355\u5143\u683C\u6837\u5F0F"
42
+ }
43
+ },
44
+ content: `
45
+ ctx.model.props.onCell = (record, rowIndex) => {
46
+ return {
47
+ style: {
48
+ background: 'red',
49
+ },
50
+ };
51
+ };
52
+ `
53
+ };
54
+ var set_cell_style_snippet_default = snippet;
@@ -9,7 +9,10 @@
9
9
  import type { FlowEngine } from '../flowEngine';
10
10
  import type { FlowModel } from '../models/flowModel';
11
11
  type LifecycleType = 'created' | 'mounted' | 'unmounted' | 'destroyed' | `event:${string}:start` | `event:${string}:end` | `event:${string}:error`;
12
- export type ScheduleWhen = LifecycleType | ((e: LifecycleEvent) => boolean);
12
+ type EventPredicateWhen = ((e: LifecycleEvent) => boolean) & {
13
+ __eventType?: string;
14
+ };
15
+ export type ScheduleWhen = LifecycleType | EventPredicateWhen;
13
16
  export interface ScheduleOptions {
14
17
  when?: ScheduleWhen;
15
18
  }
@@ -22,6 +25,7 @@ export interface LifecycleEvent {
22
25
  error?: any;
23
26
  inputArgs?: Record<string, any>;
24
27
  result?: any;
28
+ aborted?: boolean;
25
29
  flowKey?: string;
26
30
  stepKey?: string;
27
31
  }
@@ -171,8 +171,9 @@ const _ModelOperationScheduler = class _ModelOperationScheduler {
171
171
  this.unbindHandlers.push(() => emitter.off("model:destroyed", onDestroyed));
172
172
  }
173
173
  ensureEventSubscriptionIfNeeded(when) {
174
- if (!when || typeof when !== "string") return;
175
- const parsed = this.parseEventWhen(when);
174
+ const eventType = typeof when === "string" ? when : typeof when === "function" ? when.__eventType : void 0;
175
+ if (!eventType) return;
176
+ const parsed = this.parseEventWhen(eventType);
176
177
  if (!parsed) return;
177
178
  const { name } = parsed;
178
179
  if (this.subscribedEventNames.has(name)) return;
package/lib/types.d.ts CHANGED
@@ -177,7 +177,7 @@ export interface ActionDefinition<TModel extends FlowModel = FlowModel, TCtx ext
177
177
  * - 收录内置常用事件,便于智能提示;
178
178
  * - 允许扩展字符串以保持向后兼容。
179
179
  */
180
- export type FlowEventName = 'click' | 'submit' | 'reset' | 'remove' | 'openView' | 'dropdownOpen' | 'popupScroll' | 'search' | 'customRequest' | 'collapseToggle' | (string & {});
180
+ export type FlowEventName = 'click' | 'close' | 'submit' | 'reset' | 'remove' | 'openView' | 'dropdownOpen' | 'popupScroll' | 'search' | 'customRequest' | 'collapseToggle' | (string & {});
181
181
  /**
182
182
  * 事件流的执行时机(phase)。
183
183
  *
@@ -303,6 +303,52 @@ export interface CreateModelOptions {
303
303
  delegateToParent?: boolean;
304
304
  [key: string]: any;
305
305
  }
306
+ /**
307
+ * FlowModel loader result.
308
+ * Supports returning the model constructor directly, a default export, or a module object containing the named export.
309
+ */
310
+ export type FlowModelLoaderResult = ModelConstructor | {
311
+ default?: ModelConstructor;
312
+ [key: string]: unknown;
313
+ } | Record<string, unknown>;
314
+ /**
315
+ * FlowModel loader function.
316
+ */
317
+ export type FlowModelLoader = () => Promise<FlowModelLoaderResult>;
318
+ /**
319
+ * FlowModel loader entry (normalized internal form).
320
+ */
321
+ export interface FlowModelLoaderEntry {
322
+ loader: FlowModelLoader;
323
+ extends?: string[];
324
+ }
325
+ /**
326
+ * FlowModel loader input (user-facing form for registerModelLoaders).
327
+ * The `extends` field accepts flexible formats that will be normalized to `string[]` at registration time.
328
+ */
329
+ export interface FlowModelLoaderInput {
330
+ loader: FlowModelLoader;
331
+ extends?: string | ModelConstructor | (string | ModelConstructor)[];
332
+ }
333
+ /**
334
+ * FlowModel loader entry map (normalized internal form).
335
+ */
336
+ export type FlowModelLoaderMap = Record<string, FlowModelLoaderEntry>;
337
+ /**
338
+ * FlowModel loader input map (user-facing form for registerModelLoaders).
339
+ */
340
+ export type FlowModelLoaderInputMap = Record<string, FlowModelLoaderInput>;
341
+ /**
342
+ * Batch ensure result.
343
+ */
344
+ export interface EnsureBatchResult {
345
+ requested: string[];
346
+ loaded: string[];
347
+ failed: Array<{
348
+ name: string;
349
+ error?: unknown;
350
+ }>;
351
+ }
306
352
  export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
307
353
  findOne(query: Record<string, any>): Promise<Record<string, any> | null>;
308
354
  save(model: T, options?: {