@nocobase/flow-engine 2.2.0-alpha.7 → 2.2.0-beta.10

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.
@@ -57,15 +57,6 @@ const cascaderPopupAutoHeightClassName = import_css.css`
57
57
  max-height: 50vh;
58
58
  }
59
59
  `;
60
- function getMetaNodeTooltip(meta) {
61
- if (!meta) {
62
- return void 0;
63
- }
64
- const metaWithTooltip = meta;
65
- const options = meta.options;
66
- return metaWithTooltip.tooltip ?? (options == null ? void 0 : options.tooltip);
67
- }
68
- __name(getMetaNodeTooltip, "getMetaNodeTooltip");
69
60
  const normalizePath = /* @__PURE__ */ __name((path) => {
70
61
  if (!Array.isArray(path)) {
71
62
  return void 0;
@@ -99,7 +90,6 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
99
90
  value,
100
91
  onChange,
101
92
  children,
102
- active,
103
93
  metaTree,
104
94
  showSearch = false,
105
95
  parseValueToPath: customParseValueToPath = import_utils.parseValueToPath,
@@ -107,7 +97,6 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
107
97
  open,
108
98
  onlyLeafSelectable = false,
109
99
  ignoreFieldNames,
110
- dropdownFooter,
111
100
  ...cascaderProps
112
101
  }) => {
113
102
  const { token } = import_antd.theme.useToken();
@@ -122,27 +111,15 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
122
111
  const disabled = meta ? !!(typeof meta.disabled === "function" ? meta.disabled() : meta.disabled) : false;
123
112
  const disabledReason = meta ? typeof meta.disabledReason === "function" ? meta.disabledReason() : meta.disabledReason : void 0;
124
113
  const baseLabel = typeof o.label === "string" ? flowCtx.t(o.label) : o.label;
125
- const labelText = typeof baseLabel === "string" ? baseLabel : String(o.value);
126
- const tooltip = getMetaNodeTooltip(meta);
127
- const tooltipTitle = disabled ? disabledReason || tooltip || flowCtx.t("This variable is not available") : tooltip;
128
- const label = tooltipTitle ? /* @__PURE__ */ import_react.default.createElement("span", null, baseLabel, /* @__PURE__ */ import_react.default.createElement(
114
+ const label = disabled ? /* @__PURE__ */ import_react.default.createElement("span", null, baseLabel, /* @__PURE__ */ import_react.default.createElement(
129
115
  import_antd.Tooltip,
130
116
  {
131
- title: typeof tooltipTitle === "string" ? flowCtx.t(tooltipTitle) : tooltipTitle,
132
- placement: "top",
133
- classNames: { root: "flow-variable-tip" },
117
+ title: disabledReason || flowCtx.t("This variable is not available"),
118
+ placement: "right",
119
+ overlayClassName: "flow-variable-disabled-tip",
134
120
  destroyTooltipOnHide: true
135
121
  },
136
- /* @__PURE__ */ import_react.default.createElement(
137
- import_icons.QuestionCircleOutlined,
138
- {
139
- "aria-label": `${labelText} tooltip`,
140
- style: {
141
- marginLeft: token.marginXXS,
142
- color: disabled ? token.colorTextDisabled : token.colorTextDescription
143
- }
144
- }
145
- )
122
+ /* @__PURE__ */ import_react.default.createElement(import_icons.QuestionCircleOutlined, { style: { marginLeft: 6, color: "rgba(0,0,0,0.35)" } })
146
123
  )) : baseLabel;
147
124
  return {
148
125
  ...o,
@@ -152,7 +129,7 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
152
129
  };
153
130
  });
154
131
  },
155
- [flowCtx, token.colorTextDescription, token.colorTextDisabled, token.marginXXS]
132
+ [flowCtx]
156
133
  );
157
134
  const [updateFlag, setUpdateFlag] = (0, import_react.useState)(0);
158
135
  const [searchText, setSearchText] = (0, import_react.useState)("");
@@ -242,9 +219,9 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
242
219
  (0, import_utils.preloadContextSelectorPath)(options, pathToPreload, triggerUpdate);
243
220
  }, [options, pathToPreload, triggerUpdate]);
244
221
  const defaultChildren = (0, import_react.useMemo)(() => {
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, disabled: cascaderProps.disabled }, "x");
247
- }, [active, cascaderProps.disabled, currentPath]);
222
+ const hasSelected = currentPath && currentPath.length > 0;
223
+ return /* @__PURE__ */ import_react.default.createElement(import_antd.Button, { type: hasSelected ? "primary" : "default", style: defaultButtonStyle }, "x");
224
+ }, [currentPath]);
248
225
  const handleChange = (0, import_react.useCallback)(
249
226
  (selectedValues, selectedOptions) => {
250
227
  const lastOption = selectedOptions == null ? void 0 : selectedOptions[selectedOptions.length - 1];
@@ -312,32 +289,12 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
312
289
  },
313
290
  [cascaderOnDropdownVisibleChange, open]
314
291
  );
315
- const footerNode = (0, import_react.useMemo)(() => {
316
- if (dropdownFooter !== void 0) {
317
- return dropdownFooter;
318
- }
319
- if (onlyLeafSelectable) {
320
- return null;
321
- }
322
- return /* @__PURE__ */ import_react.default.createElement(
323
- "div",
324
- {
325
- className: import_css.css`
326
- padding: 6px 12px;
327
- color: ${token.colorTextDescription};
328
- border-top: 1px solid ${token.colorSplit};
329
- font-size: ${token.fontSizeSM}px;
330
- `
331
- },
332
- flowCtx.t("Double click to choose entire object")
333
- );
334
- }, [dropdownFooter, onlyLeafSelectable, token, flowCtx]);
335
292
  const renderDropdown = (0, import_react.useCallback)(
336
293
  (menu) => {
337
294
  const cascaderMenuNode = cascaderDropdownRender ? cascaderDropdownRender(menu) : menu;
338
295
  const cascaderMenu = import_react.default.isValidElement(cascaderMenuNode) ? cascaderMenuNode : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, cascaderMenuNode);
339
296
  if (!isSearchEnabled || children === null) {
340
- return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, cascaderMenu, footerNode);
297
+ return cascaderMenu;
341
298
  }
342
299
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: cascaderSearchInputClassName }, /* @__PURE__ */ import_react.default.createElement(
343
300
  import_antd.Input,
@@ -349,9 +306,9 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
349
306
  onChange: (e) => setSearchText(e.target.value),
350
307
  onKeyDown: (e) => e.stopPropagation()
351
308
  }
352
- )), cascaderMenu, footerNode);
309
+ )), cascaderMenu);
353
310
  },
354
- [cascaderDropdownRender, cascaderSearchInputClassName, children, flowCtx, isSearchEnabled, searchText, footerNode]
311
+ [cascaderDropdownRender, cascaderSearchInputClassName, children, flowCtx, isSearchEnabled, searchText]
355
312
  );
356
313
  const inlinePlaceholder = typeof restCascaderProps.placeholder === "string" ? restCascaderProps.placeholder : flowCtx.t("Search");
357
314
  const hasSelectedPath = Array.isArray(effectivePath) && effectivePath.length > 0;
@@ -77,18 +77,14 @@ const formItemPropKeys = [
77
77
  "required",
78
78
  "showLabel"
79
79
  ];
80
- const modelInternalPropKeys = ["globalSort"];
81
80
  const FormItem = /* @__PURE__ */ __name(({
82
81
  children,
83
82
  showLabel = true,
84
83
  labelWidth,
85
84
  ...rest
86
85
  }) => {
87
- const forwardedRest = Object.fromEntries(
88
- Object.entries(rest).filter(([key]) => !modelInternalPropKeys.includes(key))
89
- );
90
86
  const childProps = Object.fromEntries(
91
- Object.entries(forwardedRest).filter(([key]) => !formItemPropKeys.includes(key))
87
+ Object.entries(rest).filter(([key]) => !formItemPropKeys.includes(key))
92
88
  );
93
89
  const processedChildren = typeof children === "function" ? children : import_react.default.Children.map(children, (child) => {
94
90
  if (import_react.default.isValidElement(child)) {
@@ -96,7 +92,7 @@ const FormItem = /* @__PURE__ */ __name(({
96
92
  }
97
93
  return child;
98
94
  });
99
- const { label, labelWrap, colon = true, layout } = forwardedRest;
95
+ const { label, labelWrap, colon = true, layout } = rest;
100
96
  const effectiveLabelWrap = !layout || layout === "vertical" ? true : labelWrap;
101
97
  const labelColStyle = layout === "vertical" ? { width: labelWidth, ...verticalFormItemLabelStyle } : { width: labelWidth };
102
98
  const renderLabel = /* @__PURE__ */ __name(() => {
@@ -140,15 +136,15 @@ const FormItem = /* @__PURE__ */ __name(({
140
136
  return /* @__PURE__ */ import_react.default.createElement(
141
137
  import_antd.Form.Item,
142
138
  {
143
- ...forwardedRest,
144
- style: { ...formItemStyle, ...forwardedRest.style },
139
+ ...rest,
140
+ style: { ...formItemStyle, ...rest.style },
145
141
  labelCol: { style: labelColStyle },
146
142
  layout,
147
143
  label: renderLabel(),
148
144
  colon: false,
149
- extra: forwardedRest.extra && /* @__PURE__ */ import_react.default.createElement("span", { style: { whiteSpace: "pre-wrap" } }, forwardedRest.extra),
150
- tooltip: forwardedRest.tooltip && {
151
- title: forwardedRest.tooltip,
145
+ extra: rest.extra && /* @__PURE__ */ import_react.default.createElement("span", { style: { whiteSpace: "pre-wrap" } }, rest.extra),
146
+ tooltip: rest.tooltip && {
147
+ title: rest.tooltip,
152
148
  overlayInnerStyle: { whiteSpace: "pre-line" }
153
149
  }
154
150
  },
@@ -17,20 +17,11 @@ export interface VariableHybridInputProps {
17
17
  value?: string;
18
18
  onChange?: (value: string) => void;
19
19
  disabled?: boolean;
20
- readOnly?: boolean;
21
20
  placeholder?: string;
22
21
  addonBefore?: React.ReactNode;
23
22
  metaTree?: MetaTreeNode[] | (() => MetaTreeNode[] | Promise<MetaTreeNode[]>);
24
23
  converters?: VariableHybridInputConverters;
25
24
  style?: React.CSSProperties;
26
25
  className?: string;
27
- /**
28
- * Validation status — turns the input border red (`error`) or amber
29
- * (`warning`). Usually omitted: when rendered inside an antd `Form.Item`, the
30
- * status is read automatically from `FormItemInputContext`, so dropping this
31
- * into a `Form.Item` with failing rules colours the border with no extra
32
- * wiring. An explicit prop wins over the inherited form status.
33
- */
34
- status?: 'error' | 'warning';
35
26
  }
36
27
  export declare const VariableHybridInput: React.NamedExoticComponent<VariableHybridInputProps>;
@@ -42,7 +42,6 @@ __export(VariableHybridInput_exports, {
42
42
  module.exports = __toCommonJS(VariableHybridInput_exports);
43
43
  var import_css = require("@emotion/css");
44
44
  var import_antd = require("antd");
45
- var import_context = require("antd/es/form/context");
46
45
  var import_react = __toESM(require("react"));
47
46
  var import_FlowContextProvider = require("../../FlowContextProvider");
48
47
  var import_FlowContextSelector = require("../FlowContextSelector");
@@ -84,28 +83,14 @@ function normalizeVariableKey(value) {
84
83
  return value.replace(/^\{\{\s*/, "").replace(/\s*\}\}$/, "").trim();
85
84
  }
86
85
  __name(normalizeVariableKey, "normalizeVariableKey");
87
- function renderHTML(value, regExp, resolveLabel) {
86
+ function renderHTML(value, labelMap, regExp) {
88
87
  const re = new RegExp(regExp.source, regExp.flags.includes("g") ? regExp.flags : `${regExp.flags}g`);
89
88
  return escapeHtml(value || "").replace(re, (matched) => {
90
- const label = resolveLabel(matched) || matched;
89
+ const label = labelMap.get(normalizeVariableKey(matched)) || matched;
91
90
  return createTagHTML(matched, label);
92
91
  });
93
92
  }
94
93
  __name(renderHTML, "renderHTML");
95
- function resolveTitlesByPath(roots, path, ctxT) {
96
- if (!roots || !path || !path.length) return void 0;
97
- const titles = [];
98
- let nodes = roots;
99
- for (const segment of path) {
100
- if (!nodes) return void 0;
101
- const matched = nodes.find((node) => node.name === segment);
102
- if (!matched) return void 0;
103
- titles.push(reactNodeToPlainText(matched.title || matched.name));
104
- nodes = Array.isArray(matched.children) ? matched.children : void 0;
105
- }
106
- return titles.map(ctxT).join("/");
107
- }
108
- __name(resolveTitlesByPath, "resolveTitlesByPath");
109
94
  function buildLabelMap(nodes, ctxT, converters) {
110
95
  const map = /* @__PURE__ */ new Map();
111
96
  function walk(items = [], parentTitles = []) {
@@ -127,34 +112,6 @@ function buildLabelMap(nodes, ctxT, converters) {
127
112
  return map;
128
113
  }
129
114
  __name(buildLabelMap, "buildLabelMap");
130
- function collectReferencePaths(value, regExp, parseValueToPath) {
131
- const re = new RegExp(regExp.source, regExp.flags.includes("g") ? regExp.flags : `${regExp.flags}g`);
132
- const paths = [];
133
- for (const matched of value.match(re) ?? []) {
134
- const path = parseValueToPath(matched);
135
- if (path && path.length) {
136
- paths.push(path);
137
- }
138
- }
139
- return paths;
140
- }
141
- __name(collectReferencePaths, "collectReferencePaths");
142
- async function preloadReferencePath(path, roots) {
143
- let nodes = roots;
144
- let didLoad = false;
145
- for (const segment of path) {
146
- if (!nodes) break;
147
- const matched = nodes.find((node) => node.name === segment);
148
- if (!matched) break;
149
- if (typeof matched.children === "function") {
150
- matched.children = await (0, import_utils.loadMetaTreeChildren)(matched);
151
- didLoad = true;
152
- }
153
- nodes = Array.isArray(matched.children) ? matched.children : void 0;
154
- }
155
- return didLoad;
156
- }
157
- __name(preloadReferencePath, "preloadReferencePath");
158
115
  function pasteHTML(container, html, indexes) {
159
116
  var _a;
160
117
  const selection = (_a = window.getSelection) == null ? void 0 : _a.call(window);
@@ -256,64 +213,21 @@ function getCurrentRange(element) {
256
213
  }
257
214
  __name(getCurrentRange, "getCurrentRange");
258
215
  const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
259
- var _a;
260
- const { addonBefore, className, converters, disabled, metaTree, onChange, placeholder, readOnly, style } = props;
216
+ const { addonBefore, className, converters, disabled, metaTree, onChange, placeholder, style } = props;
261
217
  const { token } = import_antd.theme.useToken();
262
218
  const ctx = (0, import_FlowContextProvider.useFlowContext)();
263
219
  const { resolvedMetaTree } = (0, import_useResolvedMetaTree.useResolvedMetaTree)(metaTree);
264
- const formItemStatus = (_a = (0, import_react.useContext)(import_context.FormItemInputContext)) == null ? void 0 : _a.status;
265
- const effectiveStatus = props.status ?? formItemStatus;
266
220
  const inputRef = (0, import_react.useRef)(null);
267
221
  const [isComposing, setIsComposing] = (0, import_react.useState)(false);
268
222
  const [changed, setChanged] = (0, import_react.useState)(false);
269
223
  const [range, setRange] = (0, import_react.useState)([-1, 0, -1, 0]);
270
224
  const value = typeof props.value === "string" ? props.value : props.value == null ? "" : String(props.value);
271
225
  const variableRegExp = (converters == null ? void 0 : converters.variableRegExp) ?? DEFAULT_VARIABLE_REGEXP;
272
- const parseValueToPath = (converters == null ? void 0 : converters.parseValueToPath) ?? import_utils.parseValueToPath;
273
- const [loadedFlag, setLoadedFlag] = (0, import_react.useState)(0);
274
- (0, import_react.useEffect)(() => {
275
- if (!value || !Array.isArray(resolvedMetaTree) || !resolvedMetaTree.length) {
276
- return;
277
- }
278
- const paths = collectReferencePaths(value, variableRegExp, parseValueToPath);
279
- if (!paths.length) {
280
- return;
281
- }
282
- let cancelled = false;
283
- const run = /* @__PURE__ */ __name(async () => {
284
- let didLoad = false;
285
- for (const path of paths) {
286
- const loaded = await preloadReferencePath(path, resolvedMetaTree);
287
- if (cancelled) return;
288
- didLoad = didLoad || loaded;
289
- }
290
- if (didLoad && !cancelled) {
291
- setLoadedFlag((prev) => prev + 1);
292
- }
293
- }, "run");
294
- run();
295
- return () => {
296
- cancelled = true;
297
- };
298
- }, [value, resolvedMetaTree, variableRegExp, parseValueToPath]);
299
226
  const labelMap = (0, import_react.useMemo)(
300
227
  () => buildLabelMap(resolvedMetaTree, ctx.t, converters),
301
- // `loadedFlag` is read so the map recomputes after a lazy level resolves.
302
- // eslint-disable-next-line react-hooks/exhaustive-deps
303
- [resolvedMetaTree, ctx, converters, loadedFlag]
228
+ [resolvedMetaTree, ctx, converters]
304
229
  );
305
- const resolveLabel = (0, import_react.useCallback)(
306
- (matched) => {
307
- const mapped = labelMap.get(normalizeVariableKey(matched));
308
- if (mapped) return mapped;
309
- const path = parseValueToPath(matched);
310
- return resolveTitlesByPath(resolvedMetaTree, path, ctx.t);
311
- },
312
- // `loadedFlag` is read so a resolved lazy level re-creates this callback and re-renders the tags. `ctx` carries the translation fn.
313
- // eslint-disable-next-line react-hooks/exhaustive-deps
314
- [labelMap, parseValueToPath, resolvedMetaTree, ctx, loadedFlag]
315
- );
316
- const [html, setHtml] = (0, import_react.useState)(() => renderHTML(value, variableRegExp, resolveLabel));
230
+ const [html, setHtml] = (0, import_react.useState)(() => renderHTML(value, labelMap, variableRegExp));
317
231
  const emitChange = (0, import_react.useCallback)(
318
232
  (target) => {
319
233
  onChange == null ? void 0 : onChange(getDomValue(target).trim());
@@ -321,20 +235,20 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
321
235
  [onChange]
322
236
  );
323
237
  (0, import_react.useEffect)(() => {
324
- setHtml(renderHTML(value, variableRegExp, resolveLabel));
238
+ setHtml(renderHTML(value, labelMap, variableRegExp));
325
239
  if (!changed) {
326
240
  setRange([-1, 0, -1, 0]);
327
241
  }
328
- }, [value, resolveLabel]);
242
+ }, [value, labelMap]);
329
243
  (0, import_react.useEffect)(() => {
330
- var _a2;
244
+ var _a;
331
245
  const element = inputRef.current;
332
246
  if (!element) return;
333
247
  if (document.activeElement !== element) return;
334
248
  const nextRange = new Range();
335
249
  if (changed) {
336
250
  if (range.join() === "-1,0,-1,0") return;
337
- const selection = (_a2 = window.getSelection) == null ? void 0 : _a2.call(window);
251
+ const selection = (_a = window.getSelection) == null ? void 0 : _a.call(window);
338
252
  if (!selection) return;
339
253
  try {
340
254
  const children = Array.from(element.childNodes);
@@ -390,13 +304,12 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
390
304
  );
391
305
  const handleInput = (0, import_react.useCallback)(
392
306
  ({ currentTarget }) => {
393
- if (readOnly) return;
394
307
  if (isComposing) return;
395
308
  setChanged(true);
396
309
  setRange(getCurrentRange(currentTarget));
397
310
  emitChange(currentTarget);
398
311
  },
399
- [emitChange, isComposing, readOnly]
312
+ [emitChange, isComposing]
400
313
  );
401
314
  const handleBlur = (0, import_react.useCallback)(({ currentTarget }) => {
402
315
  setRange(getCurrentRange(currentTarget));
@@ -409,7 +322,6 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
409
322
  const handlePaste = (0, import_react.useCallback)(
410
323
  (event) => {
411
324
  event.preventDefault();
412
- if (readOnly) return;
413
325
  const text = event.clipboardData.getData("text/plain").replace(/\n/g, " ");
414
326
  if (!text) return;
415
327
  setChanged(true);
@@ -417,18 +329,17 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
417
329
  setRange(getCurrentRange(event.currentTarget));
418
330
  emitChange(event.currentTarget);
419
331
  },
420
- [emitChange, readOnly]
332
+ [emitChange]
421
333
  );
422
334
  const handleCompositionStart = (0, import_react.useCallback)(() => setIsComposing(true), []);
423
335
  const handleCompositionEnd = (0, import_react.useCallback)(
424
336
  ({ currentTarget }) => {
425
337
  setIsComposing(false);
426
- if (readOnly) return;
427
338
  setChanged(true);
428
339
  setRange(getCurrentRange(currentTarget));
429
340
  emitChange(currentTarget);
430
341
  },
431
- [emitChange, readOnly]
342
+ [emitChange]
432
343
  );
433
344
  const wrapperClassName = (0, import_react.useMemo)(
434
345
  () => import_css.css`
@@ -546,42 +457,6 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
546
457
  border-color: ${token.colorBorder};
547
458
  }
548
459
  }
549
-
550
- &.is-readonly {
551
- cursor: default;
552
-
553
- &:hover {
554
- border-color: ${token.colorBorder};
555
- }
556
- }
557
-
558
- &.is-error {
559
- border-color: ${token.colorError};
560
-
561
- &:hover {
562
- border-color: ${token.colorErrorBorderHover};
563
- }
564
-
565
- &:focus,
566
- &:focus-visible {
567
- border-color: ${token.colorError};
568
- box-shadow: 0 0 0 ${token.controlOutlineWidth}px ${token.colorErrorOutline};
569
- }
570
- }
571
-
572
- &.is-warning {
573
- border-color: ${token.colorWarning};
574
-
575
- &:hover {
576
- border-color: ${token.colorWarningBorderHover};
577
- }
578
-
579
- &:focus,
580
- &:focus-visible {
581
- border-color: ${token.colorWarning};
582
- box-shadow: 0 0 0 ${token.controlOutlineWidth}px ${token.colorWarningOutline};
583
- }
584
- }
585
460
  `;
586
461
  }, [token, addonBefore]);
587
462
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_antd.Space.Compact, { className: (0, import_css.cx)("nb-variable-hybrid-input", wrapperClassName, className), style }, addonBefore != null && /* @__PURE__ */ import_react.default.createElement("span", { className: addonClassName }, addonBefore), /* @__PURE__ */ import_react.default.createElement(
@@ -591,13 +466,9 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
591
466
  role: "textbox",
592
467
  "aria-label": "textbox",
593
468
  className: (0, import_css.cx)(editorClassName, {
594
- "is-disabled": disabled,
595
- "is-readonly": readOnly,
596
- "is-error": effectiveStatus === "error",
597
- "is-warning": effectiveStatus === "warning"
469
+ "is-disabled": disabled
598
470
  }),
599
- contentEditable: !disabled && !readOnly,
600
- "aria-readonly": readOnly,
471
+ contentEditable: !disabled,
601
472
  "data-placeholder": placeholder,
602
473
  onInput: handleInput,
603
474
  onBlur: handleBlur,
@@ -612,10 +483,10 @@ const VariableHybridInputComponent = /* @__PURE__ */ __name((props) => {
612
483
  {
613
484
  metaTree,
614
485
  disabled,
615
- parseValueToPath,
486
+ parseValueToPath: (converters == null ? void 0 : converters.parseValueToPath) ?? import_utils.parseValueToPath,
616
487
  formatPathToValue: (item) => {
617
- var _a2;
618
- return ((_a2 = converters == null ? void 0 : converters.formatPathToValue) == null ? void 0 : _a2.call(converters, item)) || (0, import_utils.formatPathToValue)(item);
488
+ var _a;
489
+ return ((_a = converters == null ? void 0 : converters.formatPathToValue) == null ? void 0 : _a.call(converters, item)) || (0, import_utils.formatPathToValue)(item);
619
490
  },
620
491
  onChange: handleSelectorChange
621
492
  }
@@ -188,7 +188,7 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
188
188
  }
189
189
  }, "restoreFromValue");
190
190
  restoreFromValue();
191
- }, [resolvedMetaTree, innerValue, resolvePathFromValue, currentMetaTreeNode, value]);
191
+ }, [resolvedMetaTree, innerValue, resolvePathFromValue, currentMetaTreeNode]);
192
192
  const ValueComponent = (0, import_react.useMemo)(() => {
193
193
  const Component = renderInputComponent == null ? void 0 : renderInputComponent(resolvedMetaTreeNode);
194
194
  const CustomComponent = resolvedMetaTreeNode == null ? void 0 : resolvedMetaTreeNode.render;
@@ -325,8 +325,6 @@ const VariableInputComponent = /* @__PURE__ */ __name(({
325
325
  {
326
326
  metaTree: resolvedMetaTree,
327
327
  value: innerValue,
328
- active: (0, import_utils.isVariableValue)(innerValue),
329
- disabled,
330
328
  onChange: handleVariableSelect,
331
329
  parseValueToPath: resolvePathFromValue,
332
330
  formatPathToValue: resolveValueFromPath,
@@ -13,30 +13,12 @@ export interface FlowContextSelectorProps extends Omit<CascaderProps<ContextSele
13
13
  value?: string;
14
14
  onChange?: (value: string, metaTreeNode?: MetaTreeNode) => void;
15
15
  children?: CascaderProps<ContextSelectorItem>['children'];
16
- /**
17
- * Controls whether the default `x` trigger button is rendered as active
18
- * (`type="primary"`). When omitted, the selector falls back to its parsed
19
- * `value` path (`true` iff a valid variable path is currently selected).
20
- *
21
- * Use this when callers intentionally feed synthetic paths such as
22
- * `['constant']` / `['null']` into the cascader to keep menu state aligned,
23
- * but only want real variable references to show the blue active button.
24
- */
25
- active?: boolean;
26
16
  metaTree?: MetaTreeNode[] | (() => MetaTreeNode[] | Promise<MetaTreeNode[]>);
27
17
  parseValueToPath?: (value: string) => string[] | undefined;
28
18
  formatPathToValue?: (item: MetaTreeNode) => string;
29
19
  open?: boolean;
30
20
  onlyLeafSelectable?: boolean;
31
21
  ignoreFieldNames?: string[];
32
- /**
33
- * Footer rendered at the bottom of the dropdown. Defaults to a muted
34
- * "Double click to choose entire object" hint when non-leaf selection is
35
- * allowed (`onlyLeafSelectable` is false) — since double-clicking a non-leaf
36
- * node selects the whole object. Pass an explicit node to override, or `null`
37
- * to hide it.
38
- */
39
- dropdownFooter?: React.ReactNode;
40
22
  }
41
23
  export interface ContextSelectorItem {
42
24
  label: React.ReactNode;
package/lib/flowI18n.js CHANGED
@@ -81,7 +81,7 @@ const _FlowI18n = class _FlowI18n {
81
81
  * @private
82
82
  */
83
83
  isTemplate(str) {
84
- return /\{\{\s*t\s*\(\s*(["'`])(?:\\.|(?!\1).)*?\1\s*(?:,\s*.*?)?\s*\)\s*\}\}/.test(str);
84
+ return /\{\{\s*t\s*\(\s*["'`].*?["'`]\s*(?:,\s*.*?)?\s*\)\s*\}\}/g.test(str);
85
85
  }
86
86
  /**
87
87
  * 编译模板字符串
@@ -89,8 +89,8 @@ const _FlowI18n = class _FlowI18n {
89
89
  */
90
90
  compileTemplate(template) {
91
91
  return template.replace(
92
- /\{\{\s*t\s*\(\s*(["'`])((?:\\.|(?!\1).)*?)\1\s*(?:,\s*((?:[^{}]|\{[^}]*\})*?))?\s*\)\s*\}\}/g,
93
- (match, _quote, key, optionsStr) => {
92
+ /\{\{\s*t\s*\(\s*["'`](.*?)["'`]\s*(?:,\s*((?:[^{}]|\{[^}]*\})*?))?\s*\)\s*\}\}/g,
93
+ (match, key, optionsStr) => {
94
94
  try {
95
95
  let templateOptions = {};
96
96
  if (optionsStr) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.2.0-alpha.7",
3
+ "version": "2.2.0-beta.10",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.2.0-alpha.7",
12
- "@nocobase/shared": "2.2.0-alpha.7",
11
+ "@nocobase/sdk": "2.2.0-beta.10",
12
+ "@nocobase/shared": "2.2.0-beta.10",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "34ba02960fca9ab0b6881d3db7040a8a64067bba"
40
+ "gitHead": "d572beec24de46df948f28db72b25303a63bf62d"
41
41
  }
@@ -17,17 +17,6 @@ describe('FlowI18n', () => {
17
17
  expect(i18n.translate("{{ t('Hello') }}")).toBe('你好');
18
18
  });
19
19
 
20
- it('keeps embedded quotes of a different type inside the key', () => {
21
- // A single-quoted key whose text contains double quotes (and vice versa) must not be truncated at the first inner
22
- // quote.
23
- const key = 'Unlike "Post-action event", it listens for data changes.';
24
- const table: Record<string, string> = { [key]: '与“操作后事件”不同,它监听数据变动。' };
25
- const i18n = new FlowI18n({ i18n: { t: (k: string) => table[k] ?? k } });
26
-
27
- expect(i18n.translate(`{{t('${key}', { ns: "workflow" })}}`)).toBe(table[key]);
28
- expect(i18n.translate(`{{t("It's here", { ns: "workflow" })}}`)).toBe("It's here");
29
- });
30
-
31
20
  it('template compile ignores malformed options', () => {
32
21
  const spy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
33
22
  const i18n = new FlowI18n({ i18n: { t: (k: string) => k } });