@nocobase/flow-engine 2.2.0-alpha.6 → 2.2.0-alpha.8

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.
@@ -243,8 +243,8 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
243
243
  }, [options, pathToPreload, triggerUpdate]);
244
244
  const defaultChildren = (0, import_react.useMemo)(() => {
245
245
  const hasSelected = active ?? Boolean(currentPath && currentPath.length > 0);
246
- return /* @__PURE__ */ import_react.default.createElement(import_antd.Button, { type: hasSelected ? "primary" : "default", style: defaultButtonStyle }, "x");
247
- }, [active, currentPath]);
246
+ return /* @__PURE__ */ import_react.default.createElement(import_antd.Button, { type: hasSelected ? "primary" : "default", style: defaultButtonStyle, disabled: cascaderProps.disabled }, "x");
247
+ }, [active, cascaderProps.disabled, currentPath]);
248
248
  const handleChange = (0, import_react.useCallback)(
249
249
  (selectedValues, selectedOptions) => {
250
250
  const lastOption = selectedOptions == null ? void 0 : selectedOptions[selectedOptions.length - 1];
@@ -77,14 +77,18 @@ const formItemPropKeys = [
77
77
  "required",
78
78
  "showLabel"
79
79
  ];
80
+ const modelInternalPropKeys = ["globalSort"];
80
81
  const FormItem = /* @__PURE__ */ __name(({
81
82
  children,
82
83
  showLabel = true,
83
84
  labelWidth,
84
85
  ...rest
85
86
  }) => {
87
+ const forwardedRest = Object.fromEntries(
88
+ Object.entries(rest).filter(([key]) => !modelInternalPropKeys.includes(key))
89
+ );
86
90
  const childProps = Object.fromEntries(
87
- Object.entries(rest).filter(([key]) => !formItemPropKeys.includes(key))
91
+ Object.entries(forwardedRest).filter(([key]) => !formItemPropKeys.includes(key))
88
92
  );
89
93
  const processedChildren = typeof children === "function" ? children : import_react.default.Children.map(children, (child) => {
90
94
  if (import_react.default.isValidElement(child)) {
@@ -92,7 +96,7 @@ const FormItem = /* @__PURE__ */ __name(({
92
96
  }
93
97
  return child;
94
98
  });
95
- const { label, labelWrap, colon = true, layout } = rest;
99
+ const { label, labelWrap, colon = true, layout } = forwardedRest;
96
100
  const effectiveLabelWrap = !layout || layout === "vertical" ? true : labelWrap;
97
101
  const labelColStyle = layout === "vertical" ? { width: labelWidth, ...verticalFormItemLabelStyle } : { width: labelWidth };
98
102
  const renderLabel = /* @__PURE__ */ __name(() => {
@@ -136,15 +140,15 @@ const FormItem = /* @__PURE__ */ __name(({
136
140
  return /* @__PURE__ */ import_react.default.createElement(
137
141
  import_antd.Form.Item,
138
142
  {
139
- ...rest,
140
- style: { ...formItemStyle, ...rest.style },
143
+ ...forwardedRest,
144
+ style: { ...formItemStyle, ...forwardedRest.style },
141
145
  labelCol: { style: labelColStyle },
142
146
  layout,
143
147
  label: renderLabel(),
144
148
  colon: false,
145
- extra: rest.extra && /* @__PURE__ */ import_react.default.createElement("span", { style: { whiteSpace: "pre-wrap" } }, rest.extra),
146
- tooltip: rest.tooltip && {
147
- title: rest.tooltip,
149
+ extra: forwardedRest.extra && /* @__PURE__ */ import_react.default.createElement("span", { style: { whiteSpace: "pre-wrap" } }, forwardedRest.extra),
150
+ tooltip: forwardedRest.tooltip && {
151
+ title: forwardedRest.tooltip,
148
152
  overlayInnerStyle: { whiteSpace: "pre-line" }
149
153
  }
150
154
  },
@@ -48,14 +48,34 @@ var import_lazy_helper = require("../lazy-helper");
48
48
  const { Popup } = (0, import_lazy_helper.lazy)(() => import("antd-mobile"), "Popup");
49
49
  const { CloseOutline } = (0, import_lazy_helper.lazy)(() => import("antd-mobile-icons"), "CloseOutline");
50
50
  const MobilePopup = /* @__PURE__ */ __name((props) => {
51
+ var _a;
51
52
  const { title, visible, onClose: closePopup, children, minHeight, className, footer } = props;
52
53
  const { t } = (0, import_react_i18next.useTranslation)();
53
54
  const { componentCls, hashId } = (0, import_MobilePopup.useMobileActionDrawerStyle)();
54
- const style = (0, import_react.useMemo)(() => {
55
+ const bodyStyles = (_a = props.styles) == null ? void 0 : _a.body;
56
+ const popupStyle = (0, import_react.useMemo)(() => {
55
57
  return {
56
- minHeight
58
+ minHeight: (bodyStyles == null ? void 0 : bodyStyles.minHeight) ?? minHeight,
59
+ height: bodyStyles == null ? void 0 : bodyStyles.height,
60
+ maxHeight: bodyStyles == null ? void 0 : bodyStyles.maxHeight
57
61
  };
58
- }, [minHeight]);
62
+ }, [bodyStyles == null ? void 0 : bodyStyles.height, bodyStyles == null ? void 0 : bodyStyles.maxHeight, bodyStyles == null ? void 0 : bodyStyles.minHeight, minHeight]);
63
+ const bodyStyle = (0, import_react.useMemo)(() => {
64
+ return {
65
+ padding: 0,
66
+ ...bodyStyles
67
+ };
68
+ }, [bodyStyles]);
69
+ const handleCloseKeyDown = (0, import_react.useCallback)(
70
+ (event) => {
71
+ if (event.key !== "Enter" && event.key !== " ") {
72
+ return;
73
+ }
74
+ event.preventDefault();
75
+ closePopup();
76
+ },
77
+ [closePopup]
78
+ );
59
79
  const theme = (0, import_react.useMemo)(() => {
60
80
  return {
61
81
  token: {
@@ -75,21 +95,19 @@ const MobilePopup = /* @__PURE__ */ __name((props) => {
75
95
  onClose: closePopup,
76
96
  onMaskClick: closePopup,
77
97
  bodyClassName: "nb-mobile-action-drawer-body",
78
- bodyStyle: {
79
- padding: 0
80
- },
81
- maskStyle: style,
82
- style,
98
+ bodyStyle,
99
+ style: popupStyle,
83
100
  destroyOnClose: true
84
101
  },
85
- /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-mobile-action-drawer-header" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "nb-mobile-action-drawer-placeholder" }, /* @__PURE__ */ import_react.default.createElement(CloseOutline, null)), /* @__PURE__ */ import_react.default.createElement("span", null, title), /* @__PURE__ */ import_react.default.createElement(
102
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "nb-mobile-action-drawer-header" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "nb-mobile-action-drawer-placeholder" }, /* @__PURE__ */ import_react.default.createElement(CloseOutline, null)), /* @__PURE__ */ import_react.default.createElement("span", { className: "nb-mobile-action-drawer-title" }, title), /* @__PURE__ */ import_react.default.createElement(
86
103
  "span",
87
104
  {
88
105
  className: "nb-mobile-action-drawer-close-icon",
89
106
  onClick: closePopup,
90
107
  role: "button",
91
108
  tabIndex: 0,
92
- "aria-label": t("Close")
109
+ "aria-label": t("Close"),
110
+ onKeyDown: handleCloseKeyDown
93
111
  },
94
112
  /* @__PURE__ */ import_react.default.createElement(CloseOutline, null)
95
113
  )),
@@ -127,7 +127,7 @@ const useMobileActionDrawerStyle = genStyleHook("nb-mobile-action-drawer", (toke
127
127
  borderBottom: `1px solid ${token.colorSplit}`,
128
128
  position: "sticky",
129
129
  top: 0,
130
- backgroundColor: "white",
130
+ backgroundColor: token.colorBgContainer,
131
131
  zIndex: 1e3,
132
132
  // to match the button named 'Add block'
133
133
  "& + .nb-grid-container > .nb-grid > .nb-grid-warp > .ant-btn": {
@@ -137,11 +137,21 @@ const useMobileActionDrawerStyle = genStyleHook("nb-mobile-action-drawer", (toke
137
137
  ".nb-mobile-action-drawer-placeholder": {
138
138
  display: "inline-block",
139
139
  padding: 12,
140
+ flex: "0 0 auto",
140
141
  visibility: "hidden"
141
142
  },
143
+ ".nb-mobile-action-drawer-title": {
144
+ flex: "1 1 auto",
145
+ minWidth: 0,
146
+ overflow: "hidden",
147
+ textAlign: "center",
148
+ textOverflow: "ellipsis",
149
+ whiteSpace: "nowrap"
150
+ },
142
151
  ".nb-mobile-action-drawer-close-icon": {
143
152
  display: "inline-block",
144
153
  padding: 12,
154
+ flex: "0 0 auto",
145
155
  cursor: "pointer"
146
156
  },
147
157
  ".nb-mobile-action-drawer-body": {
@@ -132,16 +132,18 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
132
132
  },
133
133
  [onChange]
134
134
  );
135
+ const resolvedPath = (0, import_react.useMemo)(() => {
136
+ return resolvePathFromValue == null ? void 0 : resolvePathFromValue(innerValue);
137
+ }, [innerValue, resolvePathFromValue]);
135
138
  const resolvedMetaTreeNode = (0, import_react.useMemo)(() => {
136
139
  if (currentMetaTreeNode) return currentMetaTreeNode;
137
140
  if (Array.isArray(resolvedMetaTree)) {
138
- const path = resolvePathFromValue == null ? void 0 : resolvePathFromValue(innerValue);
139
- if (path) {
140
- return findMetaTreeNodeByPath(resolvedMetaTree, path);
141
+ if (resolvedPath) {
142
+ return findMetaTreeNodeByPath(resolvedMetaTree, resolvedPath);
141
143
  }
142
144
  }
143
145
  return null;
144
- }, [currentMetaTreeNode, innerValue, resolvedMetaTree, resolvePathFromValue]);
146
+ }, [currentMetaTreeNode, resolvedMetaTree, resolvedPath]);
145
147
  (0, import_react.useEffect)(() => {
146
148
  const restoreFromValue = /* @__PURE__ */ __name(async () => {
147
149
  if (!Array.isArray(resolvedMetaTree) || value == null) return;
@@ -192,9 +194,13 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
192
194
  const ValueComponent = (0, import_react.useMemo)(() => {
193
195
  const Component = renderInputComponent == null ? void 0 : renderInputComponent(resolvedMetaTreeNode);
194
196
  const CustomComponent = resolvedMetaTreeNode == null ? void 0 : resolvedMetaTreeNode.render;
195
- const finalComponent = (0, import_utils.isVariableValue)(innerValue) ? import_VariableTag.VariableTag : Component || CustomComponent || import_antd.Input;
197
+ const shouldRenderVariableTag = (0, import_utils.isVariableValue)(innerValue) || Boolean(resolvedMetaTreeNode) && Array.isArray(resolvedPath) && resolvedPath.length > 0 && !Component && !CustomComponent;
198
+ const finalComponent = shouldRenderVariableTag ? import_VariableTag.VariableTag : Component || CustomComponent || import_antd.Input;
196
199
  return finalComponent;
197
- }, [renderInputComponent, resolvedMetaTreeNode, innerValue]);
200
+ }, [renderInputComponent, resolvedMetaTreeNode, innerValue, resolvedPath]);
201
+ const isVariableActive = (0, import_react.useMemo)(() => {
202
+ return (0, import_utils.isVariableValue)(innerValue) || Boolean(resolvedMetaTreeNode) && Array.isArray(resolvedPath) && resolvedPath.length > 0 && !(renderInputComponent == null ? void 0 : renderInputComponent(resolvedMetaTreeNode)) && !(resolvedMetaTreeNode == null ? void 0 : resolvedMetaTreeNode.render);
203
+ }, [innerValue, renderInputComponent, resolvedMetaTreeNode, resolvedPath]);
198
204
  (0, import_react.useEffect)(() => {
199
205
  if (!resolvedMetaTreeNode) return;
200
206
  if (!Array.isArray(resolvedMetaTree) || innerValue == null) return;
@@ -278,6 +284,8 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
278
284
  return {
279
285
  ...baseProps,
280
286
  onClear: handleClear,
287
+ disabled,
288
+ allowCustomTagInput: false,
281
289
  metaTreeNode: resolvedMetaTreeNode,
282
290
  metaTree,
283
291
  style: stableProps.style
@@ -325,7 +333,8 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
325
333
  {
326
334
  metaTree: resolvedMetaTree,
327
335
  value: innerValue,
328
- active: (0, import_utils.isVariableValue)(innerValue),
336
+ active: isVariableActive,
337
+ disabled,
329
338
  onChange: handleVariableSelect,
330
339
  parseValueToPath: resolvePathFromValue,
331
340
  formatPathToValue: resolveValueFromPath,
@@ -47,9 +47,12 @@ var import_utils = require("./utils");
47
47
  var import_useResolvedMetaTree = require("./useResolvedMetaTree");
48
48
  var import_ahooks = require("ahooks");
49
49
  var import_FlowContextProvider = require("../../FlowContextProvider");
50
+ const VARIABLE_PARSING_FAILED_TEXT = "Variable parsing failed";
50
51
  const VariableTagComponent = /* @__PURE__ */ __name(({
51
52
  value,
52
53
  onClear,
54
+ disabled = false,
55
+ allowCustomTagInput = true,
53
56
  className,
54
57
  style,
55
58
  metaTreeNode,
@@ -57,25 +60,23 @@ const VariableTagComponent = /* @__PURE__ */ __name(({
57
60
  }) => {
58
61
  const { resolvedMetaTree } = (0, import_useResolvedMetaTree.useResolvedMetaTree)(metaTree);
59
62
  const ctx = (0, import_FlowContextProvider.useFlowContext)();
60
- const { data: displayedValue } = (0, import_ahooks.useRequest)(
63
+ const { data: displayState } = (0, import_ahooks.useRequest)(
61
64
  async () => {
62
65
  const resolveLabelFromPath = /* @__PURE__ */ __name(async (rawPath2) => {
63
- if (!rawPath2) return null;
64
- if (!Array.isArray(rawPath2)) return null;
65
- if (!Array.isArray(resolvedMetaTree)) return null;
66
+ if (!rawPath2) return { label: null, resolved: false, attempted: false };
67
+ if (!Array.isArray(rawPath2)) return { label: null, resolved: false, attempted: false };
68
+ if (!Array.isArray(resolvedMetaTree)) return { label: null, resolved: false, attempted: false };
66
69
  const topNames = new Set((resolvedMetaTree || []).map((n) => String(n == null ? void 0 : n.name)));
67
70
  const path = !topNames.has(String(rawPath2[0])) ? rawPath2.slice(1) : rawPath2;
68
- if (!path.length) return "";
71
+ if (!path.length) return { label: "", resolved: true, attempted: true };
69
72
  let nodes = resolvedMetaTree;
70
73
  const titleChain = [];
71
- let matchedCount = 0;
72
74
  for (let i = 0; i < path.length; i++) {
73
- if (!nodes) break;
75
+ if (!nodes) return { label: null, resolved: false, attempted: true };
74
76
  const seg = String(path[i]);
75
77
  const node = nodes.find((n) => String(n == null ? void 0 : n.name) === seg);
76
- if (!node) break;
78
+ if (!node) return { label: null, resolved: false, attempted: true };
77
79
  titleChain.push(String(node.title ?? node.name ?? seg));
78
- matchedCount = i + 1;
79
80
  if (i < path.length - 1) {
80
81
  if (Array.isArray(node.children)) {
81
82
  nodes = node.children;
@@ -92,27 +93,35 @@ const VariableTagComponent = /* @__PURE__ */ __name(({
92
93
  }
93
94
  }
94
95
  }
95
- if (matchedCount === 0) return null;
96
- let label2 = titleChain.map(ctx.t).join("/");
97
- if (matchedCount < path.length) {
98
- const tail = path.slice(matchedCount).join("/");
99
- label2 = tail ? `${label2}/${tail}` : label2;
100
- }
101
- return label2;
96
+ return { label: titleChain.map(ctx.t).join("/"), resolved: true, attempted: true };
102
97
  }, "resolveLabelFromPath");
103
98
  if (metaTreeNode == null ? void 0 : metaTreeNode.parentTitles) {
104
- return [...metaTreeNode.parentTitles, metaTreeNode.title].map(ctx.t).join("/");
99
+ return {
100
+ text: [...metaTreeNode.parentTitles, metaTreeNode.title].map(ctx.t).join("/"),
101
+ invalid: false
102
+ };
105
103
  }
106
104
  if (metaTreeNode) {
107
105
  const rawPath2 = (0, import_utils.parseValueToPath)(value) || metaTreeNode.paths;
108
- const label2 = await resolveLabelFromPath(rawPath2);
109
- return label2 ?? ctx.t(metaTreeNode.title) ?? "";
106
+ const result2 = await resolveLabelFromPath(rawPath2);
107
+ if (result2.resolved && result2.label != null) {
108
+ return { text: result2.label, invalid: false };
109
+ }
110
+ if (result2.attempted) {
111
+ return { text: VARIABLE_PARSING_FAILED_TEXT, invalid: true, rawValue: String(value ?? "") };
112
+ }
113
+ return { text: ctx.t(metaTreeNode.title) ?? "", invalid: false };
110
114
  }
111
- if (!value) return String(value);
115
+ if (!value) return { text: String(value), invalid: false };
112
116
  const rawPath = (0, import_utils.parseValueToPath)(value);
113
- const label = await resolveLabelFromPath(rawPath);
114
- if (label != null) return label;
115
- return Array.isArray(rawPath) ? rawPath.join("/") : String(value);
117
+ const result = await resolveLabelFromPath(rawPath);
118
+ if (result.resolved && result.label != null) {
119
+ return { text: result.label, invalid: false };
120
+ }
121
+ if (result.attempted) {
122
+ return { text: VARIABLE_PARSING_FAILED_TEXT, invalid: true, rawValue: String(value ?? "") };
123
+ }
124
+ return { text: Array.isArray(rawPath) ? rawPath.join("/") : String(value), invalid: false };
116
125
  },
117
126
  { refreshDeps: [resolvedMetaTree, value, metaTreeNode] }
118
127
  );
@@ -129,12 +138,12 @@ const VariableTagComponent = /* @__PURE__ */ __name(({
129
138
  }
130
139
  `;
131
140
  const customTagRender = /* @__PURE__ */ __name((props) => {
132
- const { label } = props;
133
- const fullText = typeof label === "string" ? label : String(label);
134
- return /* @__PURE__ */ import_react.default.createElement(import_antd.Tooltip, { title: fullText, placement: "top", getPopupContainer: () => document.body }, /* @__PURE__ */ import_react.default.createElement(
141
+ const fullText = (displayState == null ? void 0 : displayState.text) || (typeof props.label === "string" ? props.label : String(props.label));
142
+ const tooltipText = (displayState == null ? void 0 : displayState.invalid) ? displayState.rawValue || fullText : fullText;
143
+ return /* @__PURE__ */ import_react.default.createElement(import_antd.Tooltip, { title: tooltipText, placement: "top", getPopupContainer: () => document.body }, /* @__PURE__ */ import_react.default.createElement(
135
144
  import_antd.Tag,
136
145
  {
137
- color: "blue",
146
+ color: (displayState == null ? void 0 : displayState.invalid) ? "error" : "blue",
138
147
  style: {
139
148
  margin: `0 ${token.marginXXS || token.marginXS}px`,
140
149
  borderRadius: token.borderRadiusSM,
@@ -175,12 +184,14 @@ const VariableTagComponent = /* @__PURE__ */ __name(({
175
184
  flex: "1 1 auto",
176
185
  ...style
177
186
  },
178
- value: displayedValue ? [displayedValue] : [],
179
- mode: "tags",
187
+ value: (displayState == null ? void 0 : displayState.text) ? [displayState.text] : [],
188
+ mode: allowCustomTagInput ? "tags" : "multiple",
180
189
  open: false,
181
- allowClear: !!onClear,
182
- onClear,
183
- disabled: !onClear,
190
+ showSearch: allowCustomTagInput,
191
+ searchValue: allowCustomTagInput ? void 0 : "",
192
+ allowClear: !disabled && !!onClear,
193
+ onClear: disabled ? void 0 : onClear,
194
+ disabled: disabled || !onClear,
184
195
  variant: "outlined",
185
196
  suffixIcon: null,
186
197
  tagRender: customTagRender,
@@ -87,6 +87,8 @@ export interface VariableInputProps {
87
87
  export interface VariableTagProps {
88
88
  value?: string;
89
89
  onClear?: () => void;
90
+ disabled?: boolean;
91
+ allowCustomTagInput?: boolean;
90
92
  className?: string;
91
93
  style?: React.CSSProperties;
92
94
  metaTreeNode?: MetaTreeNode | null;
package/lib/flowEngine.js CHANGED
@@ -1141,6 +1141,9 @@ const _FlowEngine = class _FlowEngine {
1141
1141
  if (!this.ensureModelRepository()) return;
1142
1142
  const refresh = !!(options == null ? void 0 : options.refresh);
1143
1143
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1144
+ if (this.context.flowSettingsEnabled) {
1145
+ this._loadedPageCache.markDirtyForOptions(options);
1146
+ }
1144
1147
  if (!refresh && !bypassLoadedPageCache) {
1145
1148
  const model2 = this.findModelByParentId(options.parentId, options.subKey);
1146
1149
  if (model2) {
@@ -1201,6 +1204,9 @@ const _FlowEngine = class _FlowEngine {
1201
1204
  if (!this.ensureModelRepository()) return;
1202
1205
  const { uid, parentId, subKey } = options;
1203
1206
  const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
1207
+ if (this.context.flowSettingsEnabled) {
1208
+ this._loadedPageCache.markDirtyForOptions(options);
1209
+ }
1204
1210
  if (uid && !bypassLoadedPageCache && this._modelInstances.has(uid)) {
1205
1211
  return this._modelInstances.get(uid);
1206
1212
  }