@nocobase/flow-engine 2.0.0-alpha.40 → 2.0.0-alpha.41

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 (47) hide show
  1. package/lib/flowContext.js +9 -0
  2. package/lib/flowEngine.js +25 -2
  3. package/lib/flowSettings.js +4 -0
  4. package/lib/models/CollectionFieldModel.js +4 -1
  5. package/lib/models/flowModel.js +20 -4
  6. package/lib/runjs-context/contexts/base.js +28 -6
  7. package/lib/runjs-context/snippets/index.js +1 -0
  8. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  9. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  10. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.js +1 -1
  11. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +1 -1
  12. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.js +1 -1
  13. package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +1 -1
  14. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +1 -1
  15. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +1 -1
  16. package/lib/utils/index.d.ts +1 -1
  17. package/lib/utils/index.js +2 -0
  18. package/lib/utils/variablesParams.d.ts +13 -0
  19. package/lib/utils/variablesParams.js +85 -0
  20. package/lib/views/useDialog.d.ts +1 -0
  21. package/lib/views/useDialog.js +15 -11
  22. package/lib/views/useDrawer.d.ts +1 -0
  23. package/lib/views/useDrawer.js +15 -11
  24. package/lib/views/usePage.d.ts +1 -0
  25. package/lib/views/usePage.js +16 -11
  26. package/package.json +4 -4
  27. package/src/__tests__/runjsRuntimeFeatures.test.ts +12 -0
  28. package/src/flowContext.ts +13 -0
  29. package/src/flowEngine.ts +23 -1
  30. package/src/flowSettings.ts +3 -0
  31. package/src/models/CollectionFieldModel.tsx +4 -1
  32. package/src/models/flowModel.tsx +19 -2
  33. package/src/runjs-context/contexts/base.ts +31 -6
  34. package/src/runjs-context/snippets/index.ts +1 -0
  35. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  36. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +1 -1
  37. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +1 -1
  38. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +1 -1
  39. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +1 -1
  40. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +1 -1
  41. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +1 -1
  42. package/src/utils/__tests__/variablesParams.test.ts +63 -0
  43. package/src/utils/index.ts +1 -0
  44. package/src/utils/variablesParams.ts +106 -0
  45. package/src/views/useDialog.tsx +16 -12
  46. package/src/views/useDrawer.tsx +17 -13
  47. package/src/views/usePage.tsx +18 -12
@@ -57,6 +57,7 @@ __export(flowContext_exports, {
57
57
  module.exports = __toCommonJS(flowContext_exports);
58
58
  var import_reactive = require("@formily/reactive");
59
59
  var antd = __toESM(require("antd"));
60
+ var antdIcons = __toESM(require("@ant-design/icons"));
60
61
  var import_lodash = __toESM(require("lodash"));
61
62
  var import_qs = __toESM(require("qs"));
62
63
  var import_react = __toESM(require("react"));
@@ -1294,6 +1295,14 @@ const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
1294
1295
  }, "createRoot")
1295
1296
  };
1296
1297
  this.defineProperty("ReactDOM", { value: ReactDOMShim });
1298
+ const libs = Object.freeze({
1299
+ React: import_react.default,
1300
+ ReactDOM: ReactDOMShim,
1301
+ antd,
1302
+ dayjs: import_dayjs.default,
1303
+ antdIcons
1304
+ });
1305
+ this.defineProperty("libs", { value: libs });
1297
1306
  this.defineMethod(
1298
1307
  "render",
1299
1308
  function(vnode, container) {
package/lib/flowEngine.js CHANGED
@@ -494,7 +494,7 @@ const _FlowEngine = class _FlowEngine {
494
494
  * @returns {boolean} Returns true if successfully destroyed, false otherwise (e.g. instance does not exist)
495
495
  */
496
496
  removeModel(uid) {
497
- var _a;
497
+ var _a, _b, _c;
498
498
  if (!this._modelInstances.has(uid)) {
499
499
  console.warn(`FlowEngine: Model with UID '${uid}' does not exist.`);
500
500
  return false;
@@ -509,11 +509,21 @@ const _FlowEngine = class _FlowEngine {
509
509
  if (index !== -1) {
510
510
  subModelValue.splice(index, 1);
511
511
  modelInstance.parent.emitter.emit("onSubModelRemoved", modelInstance);
512
+ (_b = this.emitter) == null ? void 0 : _b.emit("model:subModel:removed", {
513
+ parentUid: modelInstance.parent.uid,
514
+ parent: modelInstance.parent,
515
+ model: modelInstance
516
+ });
512
517
  break;
513
518
  }
514
519
  } else if (subModelValue && subModelValue === modelInstance) {
515
520
  delete modelInstance.parent.subModels[subKey];
516
521
  modelInstance.parent.emitter.emit("onSubModelRemoved", modelInstance);
522
+ (_c = this.emitter) == null ? void 0 : _c.emit("model:subModel:removed", {
523
+ parentUid: modelInstance.parent.uid,
524
+ parent: modelInstance.parent,
525
+ model: modelInstance
526
+ });
517
527
  break;
518
528
  }
519
529
  }
@@ -688,7 +698,7 @@ const _FlowEngine = class _FlowEngine {
688
698
  * @returns {Promise<T | null>} Newly created model instance
689
699
  */
690
700
  async replaceModel(uid, optionsOrFn) {
691
- var _a;
701
+ var _a, _b;
692
702
  const oldModel = this.getModel(uid);
693
703
  if (!oldModel) {
694
704
  console.warn(`FlowEngine: Cannot replace model. Model with UID '${uid}' not found.`);
@@ -725,6 +735,12 @@ const _FlowEngine = class _FlowEngine {
725
735
  currentParent.parent.invalidateFlowCache("beforeRender", true);
726
736
  (_a = currentParent.parent) == null ? void 0 : _a.rerender();
727
737
  currentParent.emitter.emit("onSubModelReplaced", { oldModel, newModel });
738
+ (_b = this.emitter) == null ? void 0 : _b.emit("model:subModel:replaced", {
739
+ parentUid: currentParent.uid,
740
+ parent: currentParent,
741
+ oldModel,
742
+ newModel
743
+ });
728
744
  }
729
745
  await newModel.save();
730
746
  return newModel;
@@ -736,6 +752,7 @@ const _FlowEngine = class _FlowEngine {
736
752
  * @returns {Promise<void>} No return value
737
753
  */
738
754
  async moveModel(sourceId, targetId, options) {
755
+ var _a, _b;
739
756
  const sourceModel = this.getModel(sourceId);
740
757
  const targetModel = this.getModel(targetId);
741
758
  if (!sourceModel || !targetModel) {
@@ -778,6 +795,12 @@ const _FlowEngine = class _FlowEngine {
778
795
  await this._modelRepository.move(sourceId, targetId, position);
779
796
  }
780
797
  sourceModel.parent.emitter.emit("onSubModelMoved", { source: sourceModel, target: targetModel });
798
+ (_b = this.emitter) == null ? void 0 : _b.emit("model:subModel:moved", {
799
+ parentUid: (_a = sourceModel.parent) == null ? void 0 : _a.uid,
800
+ parent: sourceModel.parent,
801
+ source: sourceModel,
802
+ target: targetModel
803
+ });
781
804
  }
782
805
  /**
783
806
  * Filter model classes by parent class (supports multi-level inheritance).
@@ -485,6 +485,10 @@ const _FlowSettings = class _FlowSettings {
485
485
  const flowRuntimeContext = new import_flowContext.FlowRuntimeContext(model, fk, "settings");
486
486
  (0, import_utils.setupRuntimeContextSteps)(flowRuntimeContext, flow.steps, model, fk);
487
487
  flowRuntimeContext.defineProperty("currentStep", { value: step });
488
+ flowRuntimeContext.defineMethod("getStepFormValues", (flowKey2, stepKey2) => {
489
+ var _a2;
490
+ return (_a2 = forms.get(keyOf({ flowKey: flowKey2, stepKey: stepKey2 }))) == null ? void 0 : _a2.values;
491
+ });
488
492
  const modelStepParams = model.getStepParams(fk, sk) || {};
489
493
  const resolvedDefaultParams = await (0, import_utils.resolveDefaultParams)(step.defaultParams, flowRuntimeContext);
490
494
  const resolvedActionDefaults = await (0, import_utils.resolveDefaultParams)(actionDefaultParams, flowRuntimeContext);
@@ -51,6 +51,7 @@ var import_hooks = require("../hooks");
51
51
  var import_utils = require("../utils");
52
52
  var import_flowModel = require("./flowModel");
53
53
  function FieldPlaceholder() {
54
+ const { t } = (0, import_react_i18next.useTranslation)();
54
55
  return /* @__PURE__ */ import_react.default.createElement(import_antd.Form.Item, null, /* @__PURE__ */ import_react.default.createElement(
55
56
  import_antd.Card,
56
57
  {
@@ -61,7 +62,9 @@ function FieldPlaceholder() {
61
62
  }
62
63
  }
63
64
  },
64
- "\u8BE5\u5B57\u6BB5\u5DF2\u88AB\u9690\u85CF\uFF0C\u4F60\u65E0\u6CD5\u67E5\u770B\uFF08\u8BE5\u5185\u5BB9\u4EC5\u5728\u6FC0\u6D3B UI Editor \u65F6\u663E\u793A\uFF09\u3002"
65
+ t(
66
+ "This field has been hidden and you cannot view it (this content is only visible when the UI Editor is activated)."
67
+ )
65
68
  ));
66
69
  }
67
70
  __name(FieldPlaceholder, "FieldPlaceholder");
@@ -620,10 +620,14 @@ const _FlowModel = class _FlowModel {
620
620
  if (isBeforeRender) {
621
621
  this._lastAutoRunParams = [inputArgs, execOptions.useCache];
622
622
  }
623
+ let finalInputArgs = inputArgs;
624
+ if (this.context.record) {
625
+ finalInputArgs = { record: this.context.record, ...inputArgs };
626
+ }
623
627
  if (options == null ? void 0 : options.debounce) {
624
- return this._dispatchEventWithDebounce(eventName, inputArgs, execOptions);
628
+ return this._dispatchEventWithDebounce(eventName, finalInputArgs, execOptions);
625
629
  }
626
- return this._dispatchEvent(eventName, inputArgs, execOptions);
630
+ return this._dispatchEvent(eventName, finalInputArgs, execOptions);
627
631
  }
628
632
  /**
629
633
  * 按事件名获取对应的流程集合(保持 getFlows 的顺序,即按 sort 排序)。
@@ -828,7 +832,7 @@ const _FlowModel = class _FlowModel {
828
832
  this.context.removeDelegate(this.parent.context);
829
833
  }
830
834
  addSubModel(subKey, options) {
831
- var _a;
835
+ var _a, _b, _c;
832
836
  const actualParent = this["master"] || this;
833
837
  let model;
834
838
  if (options instanceof _FlowModel) {
@@ -855,10 +859,16 @@ const _FlowModel = class _FlowModel {
855
859
  model.sortIndex = maxSortIndex + 1;
856
860
  subModels[subKey].push(model);
857
861
  actualParent.emitter.emit("onSubModelAdded", model);
862
+ (_c = (_b = actualParent.flowEngine) == null ? void 0 : _b.emitter) == null ? void 0 : _c.emit("model:subModel:added", {
863
+ parentUid: actualParent.uid,
864
+ parent: actualParent,
865
+ subKey,
866
+ model
867
+ });
858
868
  return model;
859
869
  }
860
870
  setSubModel(subKey, options) {
861
- var _a;
871
+ var _a, _b, _c;
862
872
  const actualParent = this["master"] || this;
863
873
  let model;
864
874
  if (options instanceof _FlowModel) {
@@ -879,6 +889,12 @@ const _FlowModel = class _FlowModel {
879
889
  model.setParent(actualParent);
880
890
  actualParent.subModels[subKey] = model;
881
891
  actualParent.emitter.emit("onSubModelAdded", model);
892
+ (_c = (_b = actualParent.flowEngine) == null ? void 0 : _b.emitter) == null ? void 0 : _c.emit("model:subModel:added", {
893
+ parentUid: actualParent.uid,
894
+ parent: actualParent,
895
+ subKey,
896
+ model
897
+ });
882
898
  return model;
883
899
  }
884
900
  filterSubModels(subKey, callback) {
@@ -63,9 +63,20 @@ function defineBaseContextMeta() {
63
63
  language: "Current active language code."
64
64
  }
65
65
  },
66
- React: "React namespace providing React library functions and hooks (available in RunJS environment)",
67
- ReactDOM: "ReactDOM client API including createRoot for rendering React components",
68
- antd: "Ant Design component library"
66
+ React: "React namespace providing React library functions and hooks (available in RunJS environment). Recommended access path: `ctx.libs.React`.",
67
+ ReactDOM: "ReactDOM client API including createRoot for rendering React components. Also available via `ctx.libs.ReactDOM`.",
68
+ antd: "Ant Design component library. Recommended access path: `ctx.libs.antd`.",
69
+ libs: {
70
+ description: "Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, and dayjs.",
71
+ detail: "Libraries namespace",
72
+ properties: {
73
+ React: "React namespace (same as ctx.React).",
74
+ ReactDOM: "ReactDOM client API (same as ctx.ReactDOM).",
75
+ antd: "Ant Design component library (same as ctx.antd).",
76
+ dayjs: "dayjs date-time utility library.",
77
+ antdIcons: "Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`."
78
+ }
79
+ }
69
80
  },
70
81
  methods: {
71
82
  t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {name}", { name: "World" })`',
@@ -141,9 +152,20 @@ function defineBaseContextMeta() {
141
152
  language: "\u5F53\u524D\u6FC0\u6D3B\u7684\u8BED\u8A00\u4EE3\u7801"
142
153
  }
143
154
  },
144
- React: "React \u547D\u540D\u7A7A\u95F4\uFF0C\u63D0\u4F9B React \u51FD\u6570\u4E0E hooks\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09",
145
- ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF0C\u542B createRoot \u7B49\u6E32\u67D3\u65B9\u6CD5",
146
- antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09"
155
+ React: "React \u547D\u540D\u7A7A\u95F4\uFF0C\u63D0\u4F9B React \u51FD\u6570\u4E0E hooks\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09\u3002\u63A8\u8350\u4F7F\u7528 `ctx.libs.React` \u8BBF\u95EE\u3002",
156
+ ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF0C\u542B createRoot \u7B49\u6E32\u67D3\u65B9\u6CD5\u3002\u63A8\u8350\u901A\u8FC7 `ctx.libs.ReactDOM` \u8BBF\u95EE\u3002",
157
+ antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09\u3002\u63A8\u8350\u4F7F\u7528 `ctx.libs.antd` \u8BBF\u95EE\u3002",
158
+ libs: {
159
+ description: "\u7B2C\u4E09\u65B9/\u901A\u7528\u5E93\u7684\u7EDF\u4E00\u547D\u540D\u7A7A\u95F4\uFF0C\u5305\u542B React\u3001ReactDOM\u3001Ant Design\u3001dayjs \u7B49\u3002\u540E\u7EED\u65B0\u589E\u5E93\u4F1A\u4F18\u5148\u6302\u5728\u6B64\u5904\u3002",
160
+ detail: "\u901A\u7528\u5E93\u547D\u540D\u7A7A\u95F4",
161
+ properties: {
162
+ React: "React \u547D\u540D\u7A7A\u95F4\uFF08\u7B49\u4EF7\u4E8E ctx.React\uFF09\u3002",
163
+ ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF08\u7B49\u4EF7\u4E8E ctx.ReactDOM\uFF09\u3002",
164
+ antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08\u7B49\u4EF7\u4E8E ctx.antd\uFF09\u3002",
165
+ dayjs: "dayjs \u65E5\u671F\u65F6\u95F4\u5DE5\u5177\u5E93\u3002",
166
+ antdIcons: "Ant Design \u56FE\u6807\u5E93\u3002 \u4F8B\u5982\uFF1A`ctx.libs.antdIcons.PlusOutlined`\u3002"
167
+ }
168
+ }
147
169
  },
148
170
  methods: {
149
171
  t: '\u56FD\u9645\u5316\u51FD\u6570\uFF0C\u7528\u4E8E\u7FFB\u8BD1\u6587\u6848\u3002\u53C2\u6570\uFF1A(key: string, variables?: object) => string\u3002\u793A\u4F8B\uFF1A`ctx.t("\u4F60\u597D {name}", { name: "\u4E16\u754C" })`',
@@ -61,6 +61,7 @@ const snippets = {
61
61
  // scene/block
62
62
  "scene/block/render-react": /* @__PURE__ */ __name(() => import("./scene/block/render-react.snippet"), "scene/block/render-react"),
63
63
  "scene/block/render-react-jsx": /* @__PURE__ */ __name(() => import("./scene/block/render-react-jsx.snippet"), "scene/block/render-react-jsx"),
64
+ "scene/block/render-antd-icons": /* @__PURE__ */ __name(() => import("./scene/block/render-antd-icons.snippet"), "scene/block/render-antd-icons"),
64
65
  "scene/block/render-button-handler": /* @__PURE__ */ __name(() => import("./scene/block/render-button-handler.snippet"), "scene/block/render-button-handler"),
65
66
  "scene/block/add-event-listener": /* @__PURE__ */ __name(() => import("./scene/block/add-event-listener.snippet"), "scene/block/add-event-listener"),
66
67
  "scene/block/chartjs-bar": /* @__PURE__ */ __name(() => import("./scene/block/chartjs-bar.snippet"), "scene/block/chartjs-bar"),
@@ -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,65 @@
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 render_antd_icons_snippet_exports = {};
28
+ __export(render_antd_icons_snippet_exports, {
29
+ default: () => render_antd_icons_snippet_default
30
+ });
31
+ module.exports = __toCommonJS(render_antd_icons_snippet_exports);
32
+ var import_JSBlockRunJSContext = require("../../../contexts/JSBlockRunJSContext");
33
+ const snippet = {
34
+ contexts: [import_JSBlockRunJSContext.JSBlockRunJSContext],
35
+ prefix: "sn-jsb-antd-icons",
36
+ label: "Render Ant Design icons",
37
+ description: "Render Ant Design icons with buttons inside the block container",
38
+ locales: {
39
+ "zh-CN": {
40
+ label: "\u6E32\u67D3 Ant Design \u56FE\u6807",
41
+ description: "\u5728\u533A\u5757\u5BB9\u5668\u4E2D\u4F7F\u7528 Ant Design \u56FE\u6807\u4E0E\u6309\u94AE\u8FDB\u884C\u6E32\u67D3"
42
+ }
43
+ },
44
+ content: `
45
+ // Render Ant Design icons with buttons via ctx.libs
46
+ const { React, antd, antdIcons } = ctx.libs;
47
+ const { Button, Space } = antd;
48
+ const { PlusOutlined, EditOutlined, DeleteOutlined } = antdIcons;
49
+
50
+ const IconButtons = () => (
51
+ <Space style={{ padding: 12 }}>
52
+ <Button type="primary" icon={<PlusOutlined />}>
53
+ {ctx.t('Add')}
54
+ </Button>
55
+ <Button icon={<EditOutlined />}>{ctx.t('Edit')}</Button>
56
+ <Button danger icon={<DeleteOutlined />}>
57
+ {ctx.t('Delete')}
58
+ </Button>
59
+ </Space>
60
+ );
61
+
62
+ ctx.render(<IconButtons />);
63
+ `
64
+ };
65
+ var render_antd_icons_snippet_default = snippet;
@@ -42,7 +42,7 @@ const snippet = {
42
42
  }
43
43
  },
44
44
  content: `
45
- const { Button } = ctx.antd;
45
+ const { Button } = ctx.libs.antd;
46
46
 
47
47
  ctx.render(
48
48
  <Button type="primary" onClick={() => ctx.message.success(ctx.t('Clicked!'))}>
@@ -42,7 +42,7 @@ const snippet = {
42
42
  }
43
43
  },
44
44
  content: `
45
- const { Card, Descriptions, Tag } = ctx.antd;
45
+ const { Card, Descriptions, Tag } = ctx.libs.antd;
46
46
 
47
47
  if (!ctx.record) {
48
48
  ctx.render('<div style="padding:16px;color:#999;">' + ctx.t('No record data') + '</div>');
@@ -43,7 +43,7 @@ const snippet = {
43
43
  },
44
44
  content: `
45
45
  // Render a React component with JSX
46
- const { React } = ctx;
46
+ const { React } = ctx.libs;
47
47
 
48
48
  const App = () => (
49
49
  <div style={{ padding: 12 }}>
@@ -43,7 +43,7 @@ const snippet = {
43
43
  },
44
44
  content: `
45
45
  // Render a React element into ctx.element via ReactDOM
46
- const { Button } = ctx.antd;
46
+ const { Button } = ctx.libs.antd;
47
47
 
48
48
  ctx.render(
49
49
  <div style={{ padding: 12 }}>
@@ -42,7 +42,7 @@ const snippet = {
42
42
  }
43
43
  },
44
44
  content: `
45
- const { Card, Statistic, Row, Col } = ctx.antd;
45
+ const { Card, Statistic, Row, Col } = ctx.libs.antd;
46
46
 
47
47
  const res = await ctx.api.request({
48
48
  url: 'users:list',
@@ -42,7 +42,7 @@ const snippet = {
42
42
  }
43
43
  },
44
44
  content: `
45
- const { Timeline, Card } = ctx.antd;
45
+ const { Timeline, Card } = ctx.libs.antd;
46
46
 
47
47
  const res = await ctx.api.request({
48
48
  url: 'users:list',
@@ -16,7 +16,7 @@ export { compileUiSchema, resolveStepUiSchema, resolveUiMode } from './schema-ut
16
16
  export { setupRuntimeContextSteps } from './setupRuntimeContextSteps';
17
17
  export { createCollectionContextMeta } from './createCollectionContextMeta';
18
18
  export { createAssociationAwareObjectMetaFactory, createAssociationSubpathResolver } from './associationObjectVariable';
19
- export { buildRecordMeta, collectContextParamsForTemplate, createCurrentRecordMetaFactory, createRecordMetaFactory, extractUsedVariableNames, extractUsedVariablePaths, inferRecordRef, type RecordParamsBuilder, } from './variablesParams';
19
+ export { buildRecordMeta, collectContextParamsForTemplate, createCurrentRecordMetaFactory, createRecordResolveOnServerWithLocal, createRecordMetaFactory, extractUsedVariableNames, extractUsedVariablePaths, inferRecordRef, type RecordParamsBuilder, } from './variablesParams';
20
20
  export { extractPropertyPath, formatPathToVariable, isVariableExpression } from './context';
21
21
  export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
22
22
  export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
@@ -42,6 +42,7 @@ __export(utils_exports, {
42
42
  createCurrentRecordMetaFactory: () => import_variablesParams.createCurrentRecordMetaFactory,
43
43
  createEphemeralContext: () => import_createEphemeralContext.createEphemeralContext,
44
44
  createRecordMetaFactory: () => import_variablesParams.createRecordMetaFactory,
45
+ createRecordResolveOnServerWithLocal: () => import_variablesParams.createRecordResolveOnServerWithLocal,
45
46
  createSafeDocument: () => import_safeGlobals.createSafeDocument,
46
47
  createSafeNavigator: () => import_safeGlobals.createSafeNavigator,
47
48
  createSafeWindow: () => import_safeGlobals.createSafeWindow,
@@ -106,6 +107,7 @@ var import_flows = require("./flows");
106
107
  createCurrentRecordMetaFactory,
107
108
  createEphemeralContext,
108
109
  createRecordMetaFactory,
110
+ createRecordResolveOnServerWithLocal,
109
111
  createSafeDocument,
110
112
  createSafeNavigator,
111
113
  createSafeWindow,
@@ -13,6 +13,19 @@ import { type RecordRef, type ServerContextParams } from '../utils/serverContext
13
13
  import type { JSONValue } from './params-resolvers';
14
14
  export declare function inferRecordRef(ctx: FlowContext): RecordRef | undefined;
15
15
  export declare function inferViewRecordRef(ctx: FlowContext): RecordRef | undefined;
16
+ export declare function getViewRecordFromParent(flowContext: FlowContext, viewContext: FlowContext): unknown;
17
+ export declare function createViewRecordResolveOnServer(ctx: FlowContext, getLocalRecord: () => unknown): (subPath: string) => boolean;
18
+ /**
19
+ * 创建一个用于 “ctx.record” 变量的 resolveOnServer 判定函数:
20
+ * - 若本地 record 不存在:统一走服务端;
21
+ * - 若本地 record 存在:
22
+ * - 访问空子路径("{{ ctx.record }}")时使用本地值,不走服务端;
23
+ * - 访问非关联字段(如 id/title):使用本地值;
24
+ * - 访问关联字段:
25
+ * - 若本地该字段无值(undefined/null),则交给服务端解析(无论是 "author" 还是 "author.name");
26
+ * - 若本地已有值,则仅在访问子属性且本地缺少该子属性值时交给服务端。
27
+ */
28
+ export declare function createRecordResolveOnServerWithLocal(collectionAccessor: () => Collection | null, valueAccessor: () => unknown): (subPath: string) => boolean;
16
29
  export declare function inferParentRecordRef(ctx: FlowContext): RecordRef | undefined;
17
30
  export type RecordParamsBuilder = (ctx: FlowContext) => RecordRef | Promise<RecordRef> | undefined;
18
31
  /**
@@ -7,9 +7,11 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ var __create = Object.create;
10
11
  var __defProp = Object.defineProperty;
11
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
13
  var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
13
15
  var __hasOwnProp = Object.prototype.hasOwnProperty;
14
16
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
17
  var __export = (target, all) => {
@@ -24,6 +26,14 @@ var __copyProps = (to, from, except, desc) => {
24
26
  }
25
27
  return to;
26
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
+ ));
27
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
38
  var variablesParams_exports = {};
29
39
  __export(variablesParams_exports, {
@@ -31,8 +41,11 @@ __export(variablesParams_exports, {
31
41
  collectContextParamsForTemplate: () => collectContextParamsForTemplate,
32
42
  createCurrentRecordMetaFactory: () => createCurrentRecordMetaFactory,
33
43
  createRecordMetaFactory: () => createRecordMetaFactory,
44
+ createRecordResolveOnServerWithLocal: () => createRecordResolveOnServerWithLocal,
45
+ createViewRecordResolveOnServer: () => createViewRecordResolveOnServer,
34
46
  extractUsedVariableNames: () => extractUsedVariableNames,
35
47
  extractUsedVariablePaths: () => extractUsedVariablePaths,
48
+ getViewRecordFromParent: () => getViewRecordFromParent,
36
49
  inferParentRecordRef: () => inferParentRecordRef,
37
50
  inferRecordRef: () => inferRecordRef,
38
51
  inferViewRecordRef: () => inferViewRecordRef
@@ -41,6 +54,8 @@ module.exports = __toCommonJS(variablesParams_exports);
41
54
  var import_shared = require("@nocobase/shared");
42
55
  var import_serverContextParams = require("../utils/serverContextParams");
43
56
  var import_createCollectionContextMeta = require("./createCollectionContextMeta");
57
+ var import_associationObjectVariable = require("./associationObjectVariable");
58
+ var import_lodash = __toESM(require("lodash"));
44
59
  function isObject(value) {
45
60
  return typeof value === "object" && value !== null;
46
61
  }
@@ -85,6 +100,73 @@ function inferViewRecordRef(ctx) {
85
100
  return { collection, dataSourceKey, filterByTk, sourceId };
86
101
  }
87
102
  __name(inferViewRecordRef, "inferViewRecordRef");
103
+ function getViewRecordFromParent(flowContext, viewContext) {
104
+ var _a, _b, _c;
105
+ const parentRecord = (_a = flowContext.inputArgs) == null ? void 0 : _a.record;
106
+ const parentTk = (_b = flowContext.collection) == null ? void 0 : _b.filterTargetKey;
107
+ if (!parentRecord || !parentTk) return void 0;
108
+ const view = viewContext.view;
109
+ const viewFilterByTk = (_c = view == null ? void 0 : view.inputArgs) == null ? void 0 : _c.filterByTk;
110
+ const recordFilterByTk = parentRecord[parentTk];
111
+ if (viewFilterByTk == null || recordFilterByTk == null) return void 0;
112
+ if (viewFilterByTk !== recordFilterByTk) return void 0;
113
+ return import_lodash.default.cloneDeep(parentRecord);
114
+ }
115
+ __name(getViewRecordFromParent, "getViewRecordFromParent");
116
+ function createViewRecordResolveOnServer(ctx, getLocalRecord) {
117
+ return (p) => {
118
+ var _a, _b, _c, _d;
119
+ if (!(p === "record" || p.startsWith("record."))) return false;
120
+ const local = getLocalRecord();
121
+ if (!local) return true;
122
+ if (p === "record") return false;
123
+ const ref = inferViewRecordRef(ctx);
124
+ const colName = ref == null ? void 0 : ref.collection;
125
+ const dsKey = (ref == null ? void 0 : ref.dataSourceKey) || "main";
126
+ if (!colName) return true;
127
+ const ds = (_b = (_a = ctx.dataSourceManager) == null ? void 0 : _a.getDataSource) == null ? void 0 : _b.call(_a, dsKey);
128
+ const collection = (_d = (_c = ds == null ? void 0 : ds.collectionManager) == null ? void 0 : _c.getCollection) == null ? void 0 : _d.call(_c, colName);
129
+ if (!collection) return true;
130
+ const resolver = (0, import_associationObjectVariable.createAssociationSubpathResolver)(
131
+ () => collection,
132
+ () => local
133
+ );
134
+ const subPath = p.startsWith("record.") ? p.slice("record.".length) : "";
135
+ if (!subPath) return false;
136
+ return resolver(subPath);
137
+ };
138
+ }
139
+ __name(createViewRecordResolveOnServer, "createViewRecordResolveOnServer");
140
+ function createRecordResolveOnServerWithLocal(collectionAccessor, valueAccessor) {
141
+ const assocSubpathResolver = (0, import_associationObjectVariable.createAssociationSubpathResolver)(collectionAccessor, () => valueAccessor());
142
+ return (p) => {
143
+ var _a;
144
+ const local = valueAccessor();
145
+ if (!local) return true;
146
+ if (!p) return false;
147
+ const collection = collectionAccessor();
148
+ if (!p.includes(".")) {
149
+ const name = p;
150
+ let field;
151
+ if (collection) {
152
+ if (typeof collection.getField === "function") {
153
+ field = collection.getField(name);
154
+ }
155
+ if (!field && typeof collection.getFields === "function") {
156
+ const fields = collection.getFields() || [];
157
+ field = fields.find((f) => (f == null ? void 0 : f.name) === name);
158
+ }
159
+ }
160
+ const isAssoc = !!((_a = field == null ? void 0 : field.isAssociationField) == null ? void 0 : _a.call(field));
161
+ if (!isAssoc) return false;
162
+ const value = local == null ? void 0 : local[name];
163
+ if (value === void 0 || value === null) return true;
164
+ return false;
165
+ }
166
+ return assocSubpathResolver(p);
167
+ };
168
+ }
169
+ __name(createRecordResolveOnServerWithLocal, "createRecordResolveOnServerWithLocal");
88
170
  function inferParentRecordRef(ctx) {
89
171
  var _a, _b, _c, _d;
90
172
  const resource = getResource(ctx);
@@ -153,8 +235,11 @@ __name(collectContextParamsForTemplate, "collectContextParamsForTemplate");
153
235
  collectContextParamsForTemplate,
154
236
  createCurrentRecordMetaFactory,
155
237
  createRecordMetaFactory,
238
+ createRecordResolveOnServerWithLocal,
239
+ createViewRecordResolveOnServer,
156
240
  extractUsedVariableNames,
157
241
  extractUsedVariablePaths,
242
+ getViewRecordFromParent,
158
243
  inferParentRecordRef,
159
244
  inferRecordRef,
160
245
  inferViewRecordRef
@@ -28,5 +28,6 @@ export declare function useDialog(): (React.JSX.Element | {
28
28
  extra?: React.ReactNode;
29
29
  }) => void;
30
30
  navigation: any;
31
+ readonly record: unknown;
31
32
  };
32
33
  })[];
@@ -50,6 +50,7 @@ var import_DialogComponent = __toESM(require("./DialogComponent"));
50
50
  var import_usePatchElement = __toESM(require("./usePatchElement"));
51
51
  var import_provider = require("../provider");
52
52
  var import_ViewScopedFlowEngine = require("../ViewScopedFlowEngine");
53
+ var import_variablesParams = require("../utils/variablesParams");
53
54
  let uuid = 0;
54
55
  function useDialog() {
55
56
  const holderRef = React.useRef(null);
@@ -90,6 +91,15 @@ function useDialog() {
90
91
  }, [props]);
91
92
  return null;
92
93
  }, "HeaderComponent");
94
+ const ctx = new import_flowContext.FlowContext();
95
+ const scopedEngine = (0, import_ViewScopedFlowEngine.createViewScopedEngine)(flowContext.engine);
96
+ ctx.defineProperty("engine", { value: scopedEngine });
97
+ ctx.addDelegate(scopedEngine.context);
98
+ if (config.inheritContext !== false) {
99
+ ctx.addDelegate(flowContext);
100
+ } else {
101
+ ctx.addDelegate(flowContext.engine.context);
102
+ }
93
103
  const currentDialog = {
94
104
  type: "dialog",
95
105
  inputArgs: config.inputArgs || {},
@@ -123,21 +133,15 @@ function useDialog() {
123
133
  currentHeader = header;
124
134
  (_a2 = dialogRef.current) == null ? void 0 : _a2.setHeader(header);
125
135
  }, "setHeader"),
126
- navigation: (_a = config.inputArgs) == null ? void 0 : _a.navigation
136
+ navigation: (_a = config.inputArgs) == null ? void 0 : _a.navigation,
137
+ get record() {
138
+ return (0, import_variablesParams.getViewRecordFromParent)(flowContext, ctx);
139
+ }
127
140
  };
128
- const ctx = new import_flowContext.FlowContext();
129
- const scopedEngine = (0, import_ViewScopedFlowEngine.createViewScopedEngine)(flowContext.engine);
130
- ctx.defineProperty("engine", { value: scopedEngine });
131
- ctx.addDelegate(scopedEngine.context);
132
- if (config.inheritContext !== false) {
133
- ctx.addDelegate(flowContext);
134
- } else {
135
- ctx.addDelegate(flowContext.engine.context);
136
- }
137
141
  ctx.defineProperty("view", {
138
142
  get: /* @__PURE__ */ __name(() => currentDialog, "get"),
139
143
  // meta: createViewMeta(ctx),
140
- resolveOnServer: /* @__PURE__ */ __name((p) => p === "record" || p.startsWith("record."), "resolveOnServer")
144
+ resolveOnServer: (0, import_variablesParams.createViewRecordResolveOnServer)(ctx, () => (0, import_variablesParams.getViewRecordFromParent)(flowContext, ctx))
141
145
  });
142
146
  (0, import_createViewMeta.registerPopupVariable)(ctx, currentDialog);
143
147
  const DialogWithContext = (0, import__.observer)(
@@ -29,5 +29,6 @@ export declare function useDrawer(): (React.JSX.Element | {
29
29
  extra?: React.ReactNode;
30
30
  }) => void;
31
31
  navigation: any;
32
+ readonly record: unknown;
32
33
  };
33
34
  })[];