@nocobase/flow-engine 2.2.0-alpha.1 → 2.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/JSRunner.d.ts +1 -0
- package/lib/JSRunner.js +110 -20
- package/lib/components/FieldModelRenderer.js +44 -31
- package/lib/components/FlowContextSelector.js +24 -3
- package/lib/components/dnd/index.js +9 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +86 -32
- package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +20 -0
- package/lib/components/variables/VariableHybridInput.d.ts +8 -0
- package/lib/components/variables/VariableHybridInput.js +128 -12
- package/lib/components/variables/types.d.ts +8 -0
- package/lib/flowContext.d.ts +1 -1
- package/lib/flowContext.js +87 -36
- package/lib/flowI18n.js +3 -3
- package/lib/flowSettings.d.ts +5 -1
- package/lib/flowSettings.js +70 -0
- package/lib/locale/en-US.json +1 -0
- package/lib/locale/index.d.ts +2 -0
- package/lib/locale/zh-CN.json +1 -0
- package/lib/resources/apiResource.js +2 -1
- package/lib/resources/baseRecordResource.js +6 -17
- package/lib/resources/multiRecordResource.js +13 -3
- package/lib/resources/singleRecordResource.js +7 -2
- package/lib/runjs-context/helpers.js +12 -5
- package/lib/types.d.ts +12 -0
- package/lib/utils/dataSourceDirty.d.ts +20 -0
- package/lib/utils/dataSourceDirty.js +139 -0
- package/lib/utils/dirtyAwareApiClient.d.ts +11 -0
- package/lib/utils/dirtyAwareApiClient.js +378 -0
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +11 -11
- package/lib/utils/openViewRouteState.d.ts +28 -0
- package/lib/utils/openViewRouteState.js +125 -0
- package/lib/utils/parsePathnameToViewParams.d.ts +3 -0
- package/lib/utils/parsePathnameToViewParams.js +18 -1
- package/lib/utils/resolveRunJSObjectValues.js +3 -2
- package/lib/utils/runjsModuleLoader.js +0 -30
- package/lib/views/ViewNavigation.js +5 -0
- package/package.json +4 -4
- package/src/JSRunner.ts +112 -25
- package/src/__tests__/JSRunner.test.ts +4 -5
- package/src/__tests__/flowContext.test.ts +131 -0
- package/src/__tests__/flowEngine.dataSourceDirty.test.ts +51 -0
- package/src/__tests__/flowI18n.test.ts +11 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
- package/src/__tests__/flowSettings.test.ts +72 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +15 -2
- package/src/components/FieldModelRenderer.tsx +50 -36
- package/src/components/FlowContextSelector.tsx +33 -2
- package/src/components/__tests__/FieldModelRenderer.test.tsx +165 -0
- package/src/components/dnd/index.tsx +11 -2
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +105 -35
- package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +381 -12
- package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +28 -0
- package/src/components/variables/VariableHybridInput.tsx +166 -9
- package/src/components/variables/__tests__/VariableHybridInput.test.tsx +178 -0
- package/src/components/variables/types.ts +8 -0
- package/src/flowContext.ts +100 -33
- package/src/flowI18n.ts +8 -3
- package/src/flowSettings.ts +85 -1
- package/src/locale/en-US.json +1 -0
- package/src/locale/zh-CN.json +1 -0
- package/src/resources/apiResource.ts +2 -1
- package/src/resources/baseRecordResource.ts +6 -23
- package/src/resources/multiRecordResource.ts +13 -3
- package/src/resources/singleRecordResource.ts +6 -1
- package/src/runjs-context/helpers.ts +12 -6
- package/src/types.ts +14 -0
- package/src/utils/__tests__/dirtyAwareApiClient.test.ts +392 -0
- package/src/utils/__tests__/openViewRouteState.test.ts +40 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +36 -0
- package/src/utils/dataSourceDirty.ts +126 -0
- package/src/utils/dirtyAwareApiClient.ts +430 -0
- package/src/utils/index.ts +10 -9
- package/src/utils/openViewRouteState.ts +107 -0
- package/src/utils/parsePathnameToViewParams.ts +23 -1
- package/src/utils/resolveRunJSObjectValues.ts +5 -2
- package/src/utils/runjsModuleLoader.ts +0 -32
- package/src/views/ViewNavigation.ts +6 -1
- package/src/views/__tests__/ViewNavigation.test.ts +15 -0
- package/lib/utils/safeGlobals.d.ts +0 -28
- package/lib/utils/safeGlobals.js +0 -367
- package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +0 -38
- package/src/utils/__tests__/safeGlobals.test.ts +0 -106
- package/src/utils/safeGlobals.ts +0 -406
package/lib/JSRunner.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export interface JSRunnerOptions {
|
|
|
27
27
|
* 3. Fallback keeps v1-compatible behavior (enabled).
|
|
28
28
|
*/
|
|
29
29
|
export declare function shouldPreprocessRunJSTemplates(options?: Pick<JSRunnerOptions, 'preprocessTemplates' | 'version'>): boolean;
|
|
30
|
+
export declare const RUNJS_ALLOWED_BARE_GLOBAL_NAMES: readonly ["ctx", "console", "window", "document", "navigator", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "Array", "ArrayBuffer", "BigInt", "BigInt64Array", "BigUint64Array", "Boolean", "DataView", "Date", "Error", "EvalError", "FinalizationRegistry", "Float32Array", "Float64Array", "Int8Array", "Int16Array", "Int32Array", "Map", "Math", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "Reflect", "RegExp", "Set", "String", "Symbol", "SyntaxError", "TypeError", "URIError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap", "WeakRef", "WeakSet", "JSON", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "isFinite", "isNaN", "parseFloat", "parseInt", "undefined", "NaN", "Infinity", "fetch", "localStorage", "sessionStorage", "XMLHttpRequest", "WebSocket", "Worker", "SharedWorker", "ServiceWorker", "BroadcastChannel", "EventSource", "indexedDB", "caches", "Function", "eval", "globalThis", "Intl", "Blob", "URL", "location"];
|
|
30
31
|
export declare class JSRunner {
|
|
31
32
|
private globals;
|
|
32
33
|
private timeoutMs;
|
package/lib/JSRunner.js
CHANGED
|
@@ -28,6 +28,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
28
28
|
var JSRunner_exports = {};
|
|
29
29
|
__export(JSRunner_exports, {
|
|
30
30
|
JSRunner: () => JSRunner,
|
|
31
|
+
RUNJS_ALLOWED_BARE_GLOBAL_NAMES: () => RUNJS_ALLOWED_BARE_GLOBAL_NAMES,
|
|
31
32
|
shouldPreprocessRunJSTemplates: () => shouldPreprocessRunJSTemplates
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(JSRunner_exports);
|
|
@@ -40,6 +41,113 @@ function shouldPreprocessRunJSTemplates(options) {
|
|
|
40
41
|
return (options == null ? void 0 : options.version) !== "v2";
|
|
41
42
|
}
|
|
42
43
|
__name(shouldPreprocessRunJSTemplates, "shouldPreprocessRunJSTemplates");
|
|
44
|
+
const RUNJS_BROWSER_GLOBAL_NAMES = [
|
|
45
|
+
"fetch",
|
|
46
|
+
"localStorage",
|
|
47
|
+
"sessionStorage",
|
|
48
|
+
"XMLHttpRequest",
|
|
49
|
+
"WebSocket",
|
|
50
|
+
"Worker",
|
|
51
|
+
"SharedWorker",
|
|
52
|
+
"ServiceWorker",
|
|
53
|
+
"BroadcastChannel",
|
|
54
|
+
"EventSource",
|
|
55
|
+
"indexedDB",
|
|
56
|
+
"caches",
|
|
57
|
+
"Function",
|
|
58
|
+
"eval",
|
|
59
|
+
"globalThis",
|
|
60
|
+
"Intl",
|
|
61
|
+
"Blob",
|
|
62
|
+
"URL",
|
|
63
|
+
"location"
|
|
64
|
+
];
|
|
65
|
+
const RUNJS_ALLOWED_BARE_GLOBAL_NAMES = [
|
|
66
|
+
"ctx",
|
|
67
|
+
"console",
|
|
68
|
+
"window",
|
|
69
|
+
"document",
|
|
70
|
+
"navigator",
|
|
71
|
+
"setTimeout",
|
|
72
|
+
"clearTimeout",
|
|
73
|
+
"setInterval",
|
|
74
|
+
"clearInterval",
|
|
75
|
+
"Array",
|
|
76
|
+
"ArrayBuffer",
|
|
77
|
+
"BigInt",
|
|
78
|
+
"BigInt64Array",
|
|
79
|
+
"BigUint64Array",
|
|
80
|
+
"Boolean",
|
|
81
|
+
"DataView",
|
|
82
|
+
"Date",
|
|
83
|
+
"Error",
|
|
84
|
+
"EvalError",
|
|
85
|
+
"FinalizationRegistry",
|
|
86
|
+
"Float32Array",
|
|
87
|
+
"Float64Array",
|
|
88
|
+
"Int8Array",
|
|
89
|
+
"Int16Array",
|
|
90
|
+
"Int32Array",
|
|
91
|
+
"Map",
|
|
92
|
+
"Math",
|
|
93
|
+
"Number",
|
|
94
|
+
"Object",
|
|
95
|
+
"Promise",
|
|
96
|
+
"Proxy",
|
|
97
|
+
"RangeError",
|
|
98
|
+
"ReferenceError",
|
|
99
|
+
"Reflect",
|
|
100
|
+
"RegExp",
|
|
101
|
+
"Set",
|
|
102
|
+
"String",
|
|
103
|
+
"Symbol",
|
|
104
|
+
"SyntaxError",
|
|
105
|
+
"TypeError",
|
|
106
|
+
"URIError",
|
|
107
|
+
"Uint8Array",
|
|
108
|
+
"Uint8ClampedArray",
|
|
109
|
+
"Uint16Array",
|
|
110
|
+
"Uint32Array",
|
|
111
|
+
"WeakMap",
|
|
112
|
+
"WeakRef",
|
|
113
|
+
"WeakSet",
|
|
114
|
+
"JSON",
|
|
115
|
+
"decodeURI",
|
|
116
|
+
"decodeURIComponent",
|
|
117
|
+
"encodeURI",
|
|
118
|
+
"encodeURIComponent",
|
|
119
|
+
"isFinite",
|
|
120
|
+
"isNaN",
|
|
121
|
+
"parseFloat",
|
|
122
|
+
"parseInt",
|
|
123
|
+
"undefined",
|
|
124
|
+
"NaN",
|
|
125
|
+
"Infinity",
|
|
126
|
+
...RUNJS_BROWSER_GLOBAL_NAMES
|
|
127
|
+
];
|
|
128
|
+
function collectRunJSBrowserGlobals(providedGlobals = {}) {
|
|
129
|
+
const windowGlobal = providedGlobals.window;
|
|
130
|
+
if (!windowGlobal || typeof windowGlobal !== "object") {
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
const windowRecord = windowGlobal;
|
|
134
|
+
const globals = {};
|
|
135
|
+
RUNJS_BROWSER_GLOBAL_NAMES.forEach((name) => {
|
|
136
|
+
if (Object.prototype.hasOwnProperty.call(providedGlobals, name)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const value = windowRecord[name];
|
|
141
|
+
if (typeof value === "undefined") {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
globals[name] = name === "fetch" && typeof value === "function" ? value.bind(windowGlobal) : value;
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return globals;
|
|
149
|
+
}
|
|
150
|
+
__name(collectRunJSBrowserGlobals, "collectRunJSBrowserGlobals");
|
|
43
151
|
const BARE_CTX_TEMPLATE_RE = /(^|[=(:,[\s)])(\{\{\s*(ctx(?:\.|\[|\?\.)[^}]*)\s*\}\})/m;
|
|
44
152
|
function extractDeprecatedCtxTemplateUsage(code) {
|
|
45
153
|
const src = String(code || "");
|
|
@@ -78,7 +186,6 @@ const _JSRunner = class _JSRunner {
|
|
|
78
186
|
globals;
|
|
79
187
|
timeoutMs;
|
|
80
188
|
constructor(options = {}) {
|
|
81
|
-
var _a, _b;
|
|
82
189
|
const bindWindowFn = /* @__PURE__ */ __name((key) => {
|
|
83
190
|
if (typeof window !== "undefined" && typeof window[key] === "function") {
|
|
84
191
|
return window[key].bind(window);
|
|
@@ -87,25 +194,7 @@ const _JSRunner = class _JSRunner {
|
|
|
87
194
|
return typeof fn === "function" ? fn.bind(globalThis) : fn;
|
|
88
195
|
}, "bindWindowFn");
|
|
89
196
|
const providedGlobals = options.globals || {};
|
|
90
|
-
const liftedGlobals =
|
|
91
|
-
if (!Object.prototype.hasOwnProperty.call(providedGlobals, "Blob")) {
|
|
92
|
-
try {
|
|
93
|
-
const blobCtor = (_a = providedGlobals.window) == null ? void 0 : _a.Blob;
|
|
94
|
-
if (typeof blobCtor !== "undefined") {
|
|
95
|
-
liftedGlobals.Blob = blobCtor;
|
|
96
|
-
}
|
|
97
|
-
} catch {
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (!Object.prototype.hasOwnProperty.call(providedGlobals, "URL")) {
|
|
101
|
-
try {
|
|
102
|
-
const urlCtor = (_b = providedGlobals.window) == null ? void 0 : _b.URL;
|
|
103
|
-
if (typeof urlCtor !== "undefined") {
|
|
104
|
-
liftedGlobals.URL = urlCtor;
|
|
105
|
-
}
|
|
106
|
-
} catch {
|
|
107
|
-
}
|
|
108
|
-
}
|
|
197
|
+
const liftedGlobals = collectRunJSBrowserGlobals(providedGlobals);
|
|
109
198
|
this.globals = {
|
|
110
199
|
console,
|
|
111
200
|
setTimeout: bindWindowFn("setTimeout"),
|
|
@@ -169,5 +258,6 @@ let JSRunner = _JSRunner;
|
|
|
169
258
|
// Annotate the CommonJS export names for ESM import in node:
|
|
170
259
|
0 && (module.exports = {
|
|
171
260
|
JSRunner,
|
|
261
|
+
RUNJS_ALLOWED_BARE_GLOBAL_NAMES,
|
|
172
262
|
shouldPreprocessRunJSTemplates
|
|
173
263
|
});
|
|
@@ -58,41 +58,54 @@ const flowModelRendererPropKeys = [
|
|
|
58
58
|
"extraToolbarItems"
|
|
59
59
|
];
|
|
60
60
|
function FieldModelRenderer(props) {
|
|
61
|
-
const { model, ...rest } = props;
|
|
61
|
+
const { model, onChange, ...rest } = props;
|
|
62
62
|
const composingRef = (0, import_react.useRef)(false);
|
|
63
|
-
const handleChange =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
const handleChange = (0, import_react.useCallback)(
|
|
64
|
+
(e) => {
|
|
65
|
+
var _a;
|
|
66
|
+
let val;
|
|
67
|
+
if (e && e.target && typeof e.target.value !== "undefined") {
|
|
68
|
+
val = e.target.value;
|
|
69
|
+
} else if (typeof e === "string" || typeof e === "number" || typeof e === "boolean" || typeof e === "object" && !(e instanceof Event)) {
|
|
70
|
+
val = e;
|
|
71
|
+
} else {
|
|
72
|
+
val = null;
|
|
73
|
+
}
|
|
74
|
+
const isComposing = composingRef.current || ((_a = e == null ? void 0 : e.nativeEvent) == null ? void 0 : _a.isComposing);
|
|
75
|
+
if (isComposing) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
model.setProps({ value: val });
|
|
79
|
+
if (!composingRef.current) {
|
|
80
|
+
onChange == null ? void 0 : onChange(val);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[model, onChange]
|
|
84
|
+
);
|
|
85
|
+
const handleCompositionStart = (0, import_react.useCallback)(() => {
|
|
79
86
|
composingRef.current = true;
|
|
80
|
-
},
|
|
81
|
-
const handleCompositionEnd =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
}, []);
|
|
88
|
+
const handleCompositionEnd = (0, import_react.useCallback)(
|
|
89
|
+
(e, flag = true) => {
|
|
90
|
+
composingRef.current = false;
|
|
91
|
+
if (flag) {
|
|
92
|
+
handleChange(e);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
[handleChange]
|
|
96
|
+
);
|
|
97
|
+
const modelProps = (0, import_react.useMemo)(
|
|
98
|
+
() => ({
|
|
99
|
+
onCompositionStart: handleCompositionStart,
|
|
100
|
+
onCompositionEnd: handleCompositionEnd,
|
|
101
|
+
...import_lodash.default.omit(rest, flowModelRendererPropKeys),
|
|
102
|
+
onChange: handleChange
|
|
103
|
+
}),
|
|
104
|
+
[handleChange, handleCompositionEnd, handleCompositionStart, rest]
|
|
105
|
+
);
|
|
93
106
|
(0, import_react.useEffect)(() => {
|
|
94
107
|
model && model.setProps(modelProps);
|
|
95
|
-
}, [modelProps]);
|
|
108
|
+
}, [model, modelProps]);
|
|
96
109
|
return /* @__PURE__ */ import_react.default.createElement(import_FlowModelRenderer.FlowModelRenderer, { model, ...rest });
|
|
97
110
|
}
|
|
98
111
|
__name(FieldModelRenderer, "FieldModelRenderer");
|
|
@@ -97,6 +97,7 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
|
|
|
97
97
|
open,
|
|
98
98
|
onlyLeafSelectable = false,
|
|
99
99
|
ignoreFieldNames,
|
|
100
|
+
dropdownFooter,
|
|
100
101
|
...cascaderProps
|
|
101
102
|
}) => {
|
|
102
103
|
const { token } = import_antd.theme.useToken();
|
|
@@ -289,12 +290,32 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
|
|
|
289
290
|
},
|
|
290
291
|
[cascaderOnDropdownVisibleChange, open]
|
|
291
292
|
);
|
|
293
|
+
const footerNode = (0, import_react.useMemo)(() => {
|
|
294
|
+
if (dropdownFooter !== void 0) {
|
|
295
|
+
return dropdownFooter;
|
|
296
|
+
}
|
|
297
|
+
if (onlyLeafSelectable) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
301
|
+
"div",
|
|
302
|
+
{
|
|
303
|
+
className: import_css.css`
|
|
304
|
+
padding: 6px 12px;
|
|
305
|
+
color: ${token.colorTextDescription};
|
|
306
|
+
border-top: 1px solid ${token.colorSplit};
|
|
307
|
+
font-size: ${token.fontSizeSM}px;
|
|
308
|
+
`
|
|
309
|
+
},
|
|
310
|
+
flowCtx.t("Double click to choose entire object")
|
|
311
|
+
);
|
|
312
|
+
}, [dropdownFooter, onlyLeafSelectable, token, flowCtx]);
|
|
292
313
|
const renderDropdown = (0, import_react.useCallback)(
|
|
293
314
|
(menu) => {
|
|
294
315
|
const cascaderMenuNode = cascaderDropdownRender ? cascaderDropdownRender(menu) : menu;
|
|
295
316
|
const cascaderMenu = import_react.default.isValidElement(cascaderMenuNode) ? cascaderMenuNode : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, cascaderMenuNode);
|
|
296
317
|
if (!isSearchEnabled || children === null) {
|
|
297
|
-
return cascaderMenu;
|
|
318
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, cascaderMenu, footerNode);
|
|
298
319
|
}
|
|
299
320
|
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: cascaderSearchInputClassName }, /* @__PURE__ */ import_react.default.createElement(
|
|
300
321
|
import_antd.Input,
|
|
@@ -306,9 +327,9 @@ const FlowContextSelectorComponent = /* @__PURE__ */ __name(({
|
|
|
306
327
|
onChange: (e) => setSearchText(e.target.value),
|
|
307
328
|
onKeyDown: (e) => e.stopPropagation()
|
|
308
329
|
}
|
|
309
|
-
)), cascaderMenu);
|
|
330
|
+
)), cascaderMenu, footerNode);
|
|
310
331
|
},
|
|
311
|
-
[cascaderDropdownRender, cascaderSearchInputClassName, children, flowCtx, isSearchEnabled, searchText]
|
|
332
|
+
[cascaderDropdownRender, cascaderSearchInputClassName, children, flowCtx, isSearchEnabled, searchText, footerNode]
|
|
312
333
|
);
|
|
313
334
|
const inlinePlaceholder = typeof restCascaderProps.placeholder === "string" ? restCascaderProps.placeholder : flowCtx.t("Search");
|
|
314
335
|
const hasSelectedPath = Array.isArray(effectivePath) && effectivePath.length > 0;
|
|
@@ -57,6 +57,10 @@ const EMPTY_COLUMN_UID = "EMPTY_COLUMN";
|
|
|
57
57
|
const TOOLBAR_DRAG_ACTIVITY_EVENT = "nb-toolbar-drag-activity";
|
|
58
58
|
const TOOLBAR_DRAG_ANCHOR_EVENT = "nb-toolbar-drag-anchor";
|
|
59
59
|
const MENU_SUBMENU_POPUP_SELECTOR = ".ant-menu-submenu-popup";
|
|
60
|
+
const getToolbarModelUidFromNode = /* @__PURE__ */ __name((node) => {
|
|
61
|
+
var _a;
|
|
62
|
+
return ((_a = node == null ? void 0 : node.closest(".nb-toolbar-container[data-model-uid]")) == null ? void 0 : _a.getAttribute("data-model-uid")) || null;
|
|
63
|
+
}, "getToolbarModelUidFromNode");
|
|
60
64
|
const resolveOverlayAnchorTransform = /* @__PURE__ */ __name(({
|
|
61
65
|
activeId,
|
|
62
66
|
active,
|
|
@@ -76,7 +80,7 @@ const resolveOverlayAnchorTransform = /* @__PURE__ */ __name(({
|
|
|
76
80
|
const resolveDraggableHostNode = /* @__PURE__ */ __name((activatorNode) => {
|
|
77
81
|
const ownerDocument = activatorNode == null ? void 0 : activatorNode.ownerDocument;
|
|
78
82
|
const floatToolbarContainer = activatorNode == null ? void 0 : activatorNode.closest(".nb-toolbar-container[data-model-uid]");
|
|
79
|
-
const toolbarModelUid =
|
|
83
|
+
const toolbarModelUid = getToolbarModelUidFromNode(activatorNode);
|
|
80
84
|
if (!ownerDocument || !toolbarModelUid) {
|
|
81
85
|
return activatorNode;
|
|
82
86
|
}
|
|
@@ -99,6 +103,7 @@ const DragHandler = /* @__PURE__ */ __name(({
|
|
|
99
103
|
const dragHandlerRef = (0, import_react.useRef)(null);
|
|
100
104
|
const draggableNodeRef = (0, import_react.useRef)(null);
|
|
101
105
|
const pointerPressCleanupRef = (0, import_react.useRef)(null);
|
|
106
|
+
const toolbarDragModelUidRef = (0, import_react.useRef)(null);
|
|
102
107
|
const isDraggingRef = (0, import_react.useRef)(isDragging);
|
|
103
108
|
const isPointerPressActiveRef = (0, import_react.useRef)(false);
|
|
104
109
|
const isToolbarDragActiveRef = (0, import_react.useRef)(false);
|
|
@@ -128,9 +133,11 @@ const DragHandler = /* @__PURE__ */ __name(({
|
|
|
128
133
|
if (!ownerDocument) {
|
|
129
134
|
return;
|
|
130
135
|
}
|
|
136
|
+
const toolbarModelUid = getToolbarModelUidFromNode(dragHandlerRef.current) || toolbarDragModelUidRef.current || model.uid;
|
|
137
|
+
toolbarDragModelUidRef.current = active ? toolbarModelUid : null;
|
|
131
138
|
ownerDocument.dispatchEvent(
|
|
132
139
|
new CustomEvent(TOOLBAR_DRAG_ACTIVITY_EVENT, {
|
|
133
|
-
detail: { active, modelUid:
|
|
140
|
+
detail: { active, modelUid: toolbarModelUid }
|
|
134
141
|
})
|
|
135
142
|
);
|
|
136
143
|
},
|
|
@@ -44,6 +44,7 @@ var import_react = __toESM(require("react"));
|
|
|
44
44
|
var import_react_dom = require("react-dom");
|
|
45
45
|
var import_antd = require("antd");
|
|
46
46
|
var import_css = require("@emotion/css");
|
|
47
|
+
var import_ahooks = require("ahooks");
|
|
47
48
|
var import_hooks = require("../../../../hooks");
|
|
48
49
|
var import_provider = require("../../../../provider");
|
|
49
50
|
var import_utils = require("../../../../utils");
|
|
@@ -312,6 +313,38 @@ const buildToolbarContainerStyle = /* @__PURE__ */ __name((portalRect, toolbarSt
|
|
|
312
313
|
const isModelByIdProps = /* @__PURE__ */ __name((props) => {
|
|
313
314
|
return "uid" in props && "modelClassName" in props && Boolean(props.uid) && Boolean(props.modelClassName);
|
|
314
315
|
}, "isModelByIdProps");
|
|
316
|
+
const stopResizeInteractionEvent = /* @__PURE__ */ __name((event) => {
|
|
317
|
+
var _a;
|
|
318
|
+
if (!event) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
event.preventDefault();
|
|
322
|
+
event.stopPropagation();
|
|
323
|
+
const nativeEvent = "nativeEvent" in event ? event.nativeEvent : event;
|
|
324
|
+
(_a = nativeEvent.stopImmediatePropagation) == null ? void 0 : _a.call(nativeEvent);
|
|
325
|
+
}, "stopResizeInteractionEvent");
|
|
326
|
+
const pendingResizeClickSuppressions = /* @__PURE__ */ new WeakMap();
|
|
327
|
+
const clearPendingResizeClickSuppression = /* @__PURE__ */ __name((ownerDocument) => {
|
|
328
|
+
const pending = pendingResizeClickSuppressions.get(ownerDocument);
|
|
329
|
+
if (!pending) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
ownerDocument.removeEventListener("click", pending.listener, true);
|
|
333
|
+
(ownerDocument.defaultView || window).clearTimeout(pending.timer);
|
|
334
|
+
pendingResizeClickSuppressions.delete(ownerDocument);
|
|
335
|
+
}, "clearPendingResizeClickSuppression");
|
|
336
|
+
const suppressNextResizeClick = /* @__PURE__ */ __name((ownerDocument) => {
|
|
337
|
+
clearPendingResizeClickSuppression(ownerDocument);
|
|
338
|
+
const listener = /* @__PURE__ */ __name((event) => {
|
|
339
|
+
stopResizeInteractionEvent(event);
|
|
340
|
+
clearPendingResizeClickSuppression(ownerDocument);
|
|
341
|
+
}, "listener");
|
|
342
|
+
const timer = (ownerDocument.defaultView || window).setTimeout(() => {
|
|
343
|
+
clearPendingResizeClickSuppression(ownerDocument);
|
|
344
|
+
}, 0);
|
|
345
|
+
pendingResizeClickSuppressions.set(ownerDocument, { listener, timer });
|
|
346
|
+
ownerDocument.addEventListener("click", listener, true);
|
|
347
|
+
}, "suppressNextResizeClick");
|
|
315
348
|
const FlowsFloatContextMenu = (0, import_reactive.observer)((props) => {
|
|
316
349
|
const ctx = (0, import__.useFlowContext)();
|
|
317
350
|
if (!ctx.flowSettingsEnabled) {
|
|
@@ -326,44 +359,64 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
|
|
|
326
359
|
const isDraggingRef = (0, import_react.useRef)(false);
|
|
327
360
|
const dragTypeRef = (0, import_react.useRef)(null);
|
|
328
361
|
const dragStartPosRef = (0, import_react.useRef)({ x: 0, y: 0 });
|
|
362
|
+
const dragOwnerDocumentRef = (0, import_react.useRef)(null);
|
|
329
363
|
const { onDragStart, onDragEnd } = props;
|
|
330
|
-
const handleDragMove = (0,
|
|
331
|
-
(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
364
|
+
const handleDragMove = (0, import_ahooks.useMemoizedFn)((e) => {
|
|
365
|
+
if (!isDraggingRef.current || !dragTypeRef.current) return;
|
|
366
|
+
stopResizeInteractionEvent(e);
|
|
367
|
+
const deltaX = e.clientX - dragStartPosRef.current.x;
|
|
368
|
+
switch (dragTypeRef.current) {
|
|
369
|
+
case "left":
|
|
370
|
+
props.model.parent.emitter.emit("onResizeLeft", { resizeDistance: -deltaX, model: props.model });
|
|
371
|
+
break;
|
|
372
|
+
case "right":
|
|
373
|
+
props.model.parent.emitter.emit("onResizeRight", { resizeDistance: deltaX, model: props.model });
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
const handleDragEnd = (0, import_ahooks.useMemoizedFn)((e) => {
|
|
378
|
+
if (!isDraggingRef.current) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
stopResizeInteractionEvent(e);
|
|
382
|
+
const ownerDocument = dragOwnerDocumentRef.current || document;
|
|
383
|
+
ownerDocument.removeEventListener("mousemove", handleDragMove, true);
|
|
384
|
+
ownerDocument.removeEventListener("mouseup", handleDragEnd, true);
|
|
385
|
+
suppressNextResizeClick(ownerDocument);
|
|
346
386
|
isDraggingRef.current = false;
|
|
347
387
|
dragTypeRef.current = null;
|
|
348
388
|
dragStartPosRef.current = { x: 0, y: 0 };
|
|
349
|
-
|
|
350
|
-
document.removeEventListener("mouseup", handleDragEnd);
|
|
389
|
+
dragOwnerDocumentRef.current = null;
|
|
351
390
|
props.model.parent.emitter.emit("onResizeEnd");
|
|
352
391
|
onDragEnd == null ? void 0 : onDragEnd();
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
392
|
+
});
|
|
393
|
+
(0, import_react.useEffect)(() => {
|
|
394
|
+
return () => {
|
|
395
|
+
const dragOwnerDocument = dragOwnerDocumentRef.current;
|
|
396
|
+
dragOwnerDocument == null ? void 0 : dragOwnerDocument.removeEventListener("mousemove", handleDragMove, true);
|
|
397
|
+
dragOwnerDocument == null ? void 0 : dragOwnerDocument.removeEventListener("mouseup", handleDragEnd, true);
|
|
398
|
+
if (isDraggingRef.current) {
|
|
399
|
+
suppressNextResizeClick(dragOwnerDocument || document);
|
|
400
|
+
props.model.parent.emitter.emit("onResizeEnd");
|
|
401
|
+
onDragEnd == null ? void 0 : onDragEnd();
|
|
402
|
+
}
|
|
403
|
+
isDraggingRef.current = false;
|
|
404
|
+
dragTypeRef.current = null;
|
|
405
|
+
dragStartPosRef.current = { x: 0, y: 0 };
|
|
406
|
+
dragOwnerDocumentRef.current = null;
|
|
407
|
+
};
|
|
408
|
+
}, [handleDragMove, handleDragEnd, onDragEnd, props.model]);
|
|
409
|
+
const handleDragStart = (0, import_ahooks.useMemoizedFn)((e, type) => {
|
|
410
|
+
stopResizeInteractionEvent(e);
|
|
411
|
+
const ownerDocument = e.currentTarget.ownerDocument;
|
|
412
|
+
isDraggingRef.current = true;
|
|
413
|
+
dragTypeRef.current = type;
|
|
414
|
+
dragStartPosRef.current = { x: e.clientX, y: e.clientY };
|
|
415
|
+
dragOwnerDocumentRef.current = ownerDocument;
|
|
416
|
+
ownerDocument.addEventListener("mousemove", handleDragMove, true);
|
|
417
|
+
ownerDocument.addEventListener("mouseup", handleDragEnd, true);
|
|
418
|
+
onDragStart == null ? void 0 : onDragStart();
|
|
419
|
+
});
|
|
367
420
|
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
|
|
368
421
|
"div",
|
|
369
422
|
{
|
|
@@ -466,6 +519,7 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
|
|
|
466
519
|
getPopupContainer,
|
|
467
520
|
handleSettingsMenuOpenChange,
|
|
468
521
|
model,
|
|
522
|
+
modelUid,
|
|
469
523
|
settingsMenuLevel,
|
|
470
524
|
showCopyUidButton,
|
|
471
525
|
showDeleteButton,
|
|
@@ -44,6 +44,17 @@ const getToolbarModelUidFromTarget = /* @__PURE__ */ __name((target) => {
|
|
|
44
44
|
}
|
|
45
45
|
return ((_a = target.closest(".nb-toolbar-container[data-model-uid]")) == null ? void 0 : _a.getAttribute("data-model-uid")) || null;
|
|
46
46
|
}, "getToolbarModelUidFromTarget");
|
|
47
|
+
const escapeCssAttributeValue = /* @__PURE__ */ __name((value) => {
|
|
48
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\a ").replace(/\r/g, "\\d ").replace(/\f/g, "\\c ");
|
|
49
|
+
}, "escapeCssAttributeValue");
|
|
50
|
+
const isToolbarModelUidRendered = /* @__PURE__ */ __name((ownerDocument, modelUid) => {
|
|
51
|
+
if (!ownerDocument) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return !!ownerDocument.querySelector(
|
|
55
|
+
`.nb-toolbar-container[data-model-uid="${escapeCssAttributeValue(modelUid)}"]`
|
|
56
|
+
);
|
|
57
|
+
}, "isToolbarModelUidRendered");
|
|
47
58
|
const isNodeWithinDescendantFloatToolbar = /* @__PURE__ */ __name((target, container, currentModelUid) => {
|
|
48
59
|
const targetModelUid = getToolbarModelUidFromTarget(target);
|
|
49
60
|
if (!container || !targetModelUid || targetModelUid === currentModelUid) {
|
|
@@ -222,6 +233,15 @@ const useFloatToolbarVisibility = /* @__PURE__ */ __name(({
|
|
|
222
233
|
const isCurrentHostTarget = !childWithMenu || childWithMenu === containerRef.current;
|
|
223
234
|
if (isCurrentHostTarget) {
|
|
224
235
|
clearHideToolbarTimer();
|
|
236
|
+
setActiveChildToolbarIds((prevIds) => {
|
|
237
|
+
var _a;
|
|
238
|
+
if (!prevIds.length) {
|
|
239
|
+
return prevIds;
|
|
240
|
+
}
|
|
241
|
+
const ownerDocument = ((_a = containerRef.current) == null ? void 0 : _a.ownerDocument) ?? null;
|
|
242
|
+
const nextIds = prevIds.filter((id) => isToolbarModelUidRendered(ownerDocument, id));
|
|
243
|
+
return nextIds.length === prevIds.length ? prevIds : nextIds;
|
|
244
|
+
});
|
|
225
245
|
setHostHovered(true);
|
|
226
246
|
}
|
|
227
247
|
setHideMenu(!!childWithMenu && childWithMenu !== containerRef.current);
|
|
@@ -23,5 +23,13 @@ export interface VariableHybridInputProps {
|
|
|
23
23
|
converters?: VariableHybridInputConverters;
|
|
24
24
|
style?: React.CSSProperties;
|
|
25
25
|
className?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Validation status — turns the input border red (`error`) or amber
|
|
28
|
+
* (`warning`). Usually omitted: when rendered inside an antd `Form.Item`, the
|
|
29
|
+
* status is read automatically from `FormItemInputContext`, so dropping this
|
|
30
|
+
* into a `Form.Item` with failing rules colours the border with no extra
|
|
31
|
+
* wiring. An explicit prop wins over the inherited form status.
|
|
32
|
+
*/
|
|
33
|
+
status?: 'error' | 'warning';
|
|
26
34
|
}
|
|
27
35
|
export declare const VariableHybridInput: React.NamedExoticComponent<VariableHybridInputProps>;
|