UNPKG

@nocobase/flow-engine

Version:

A standalone flow engine for NocoBase, managing workflows, models, and actions.

323 lines (321 loc) 12.2 kB
/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var VariableInput_exports = {}; __export(VariableInput_exports, { VariableInput: () => VariableInput }); module.exports = __toCommonJS(VariableInput_exports); var import_react = __toESM(require("react")); var import_antd = require("antd"); var import_FlowContextSelector = require("../FlowContextSelector"); var import_VariableTag = require("./VariableTag"); var import_utils = require("./utils"); var import_utils2 = require("./utils"); var import_ahooks = require("ahooks"); const compactStyle = { display: "flex", alignItems: "flex-start" }; const findMetaTreeNodeByPath = /* @__PURE__ */ __name((metaTree, targetPath) => { if (!targetPath || targetPath.length === 0) return null; const searchInNodes = /* @__PURE__ */ __name((nodes, path) => { for (const node of nodes) { if (node.paths && arraysEqual(node.paths, path)) { return node; } if (node.paths && isPathPrefix(node.paths, path) && node.children) { if (Array.isArray(node.children)) { const found = searchInNodes(node.children, path); if (found) return found; } } } return null; }, "searchInNodes"); const direct = searchInNodes(metaTree, targetPath); if (direct) return direct; const topNames = new Set((metaTree || []).map((n) => String(n.name))); if (!topNames.has(String(targetPath[0]))) { const trimmed = targetPath.slice(1); if (trimmed.length > 0) { return searchInNodes(metaTree, trimmed); } } return null; }, "findMetaTreeNodeByPath"); const arraysEqual = /* @__PURE__ */ __name((a, b) => { if (a.length !== b.length) return false; return a.every((val, index) => val === b[index]); }, "arraysEqual"); const isPathPrefix = /* @__PURE__ */ __name((pathA, pathB) => { if (pathA.length >= pathB.length) return false; return pathA.every((val, index) => val === pathB[index]); }, "isPathPrefix"); const VariableInputComponent = /* @__PURE__ */ __name(({ value, onChange, converters: propConverters, metaTree, showValueComponent = true, onlyLeafSelectable = false, clearValue, ...restProps }) => { const [currentMetaTreeNode, setCurrentMetaTreeNode] = (0, import_react.useState)(null); const lastEmitRef = (0, import_react.useRef)(null); const [innerValue, setInnerValue] = (0, import_react.useState)(value); (0, import_react.useEffect)(() => { setInnerValue(value); }, [value]); const { resolveValueFromPath, resolvePathFromValue, renderInputComponent } = (0, import_react.useMemo)(() => { return (0, import_utils2.createFinalConverters)(propConverters); }, [propConverters]); const { data: resolvedMetaTree, loading } = (0, import_ahooks.useRequest)( async () => { if (typeof metaTree === "function") { const ret = await metaTree(); if (typeof ret === "function") { return await ret(); } return ret; } return metaTree; }, { refreshDeps: [metaTree] } ); const emitChange = (0, import_react.useCallback)( (nextValue, meta) => { const nextPath = (meta == null ? void 0 : meta.paths) ? meta.paths.join(".") : void 0; const last = lastEmitRef.current; if (last && last.value === nextValue && last.path === nextPath) { return false; } lastEmitRef.current = { value: nextValue, path: nextPath }; onChange == null ? void 0 : onChange(nextValue, meta); return true; }, [onChange] ); const resolvedMetaTreeNode = (0, import_react.useMemo)(() => { if (currentMetaTreeNode) return currentMetaTreeNode; if (Array.isArray(resolvedMetaTree)) { const path = resolvePathFromValue == null ? void 0 : resolvePathFromValue(innerValue); if (path) { return findMetaTreeNodeByPath(resolvedMetaTree, path); } } return null; }, [currentMetaTreeNode, innerValue, resolvedMetaTree, resolvePathFromValue]); (0, import_react.useEffect)(() => { const restoreFromValue = /* @__PURE__ */ __name(async () => { if (!Array.isArray(resolvedMetaTree) || !value) return; if (currentMetaTreeNode) { return; } const rawPath = resolvePathFromValue == null ? void 0 : resolvePathFromValue(value); if (!rawPath || rawPath.length === 0) return; const topNames = new Set(resolvedMetaTree.map((n) => String(n.name))); const path = !topNames.has(String(rawPath[0])) ? rawPath.slice(1) : rawPath; if (path.length === 0) return; let nodes = resolvedMetaTree; let found = null; for (let i = 0; i < path.length; i++) { if (!nodes) { found = null; break; } const seg = String(path[i]); const node = nodes.find((n) => String(n == null ? void 0 : n.name) === seg); if (!node) { found = null; break; } found = node; if (i < path.length - 1) { if (Array.isArray(node.children)) { nodes = node.children; } else if (typeof node.children === "function") { try { const childNodes = await node.children(); node.children = childNodes; nodes = childNodes; } catch { nodes = void 0; } } else { nodes = void 0; } } } if (found) { setCurrentMetaTreeNode(found); } }, "restoreFromValue"); restoreFromValue(); }, [resolvedMetaTree, innerValue, resolvePathFromValue, currentMetaTreeNode]); const ValueComponent = (0, import_react.useMemo)(() => { const Component = renderInputComponent == null ? void 0 : renderInputComponent(resolvedMetaTreeNode); const CustomComponent = resolvedMetaTreeNode == null ? void 0 : resolvedMetaTreeNode.render; const finalComponent = (0, import_utils.isVariableValue)(innerValue) ? import_VariableTag.VariableTag : Component || CustomComponent || import_antd.Input; return finalComponent; }, [renderInputComponent, resolvedMetaTreeNode, innerValue]); (0, import_react.useEffect)(() => { if (!resolvedMetaTreeNode) return; if (!Array.isArray(resolvedMetaTree) || !innerValue) return; const finalValue = (resolveValueFromPath == null ? void 0 : resolveValueFromPath(resolvedMetaTreeNode)) || innerValue; emitChange(finalValue, resolvedMetaTreeNode); setCurrentMetaTreeNode(resolvedMetaTreeNode); }, [resolvedMetaTreeNode]); const composingRef = (0, import_react.useRef)(false); const handleComposition = (0, import_react.useCallback)( (e) => { var _a; if ((e == null ? void 0 : e.type) === "compositionend") { composingRef.current = false; const newValue = ((_a = e == null ? void 0 : e.target) == null ? void 0 : _a.value) !== void 0 ? e.target.value : e; setInnerValue(newValue); emitChange(newValue); } else { composingRef.current = true; } }, [emitChange] ); const handleInputChange = (0, import_react.useCallback)( (e) => { var _a; const newValue = ((_a = e == null ? void 0 : e.target) == null ? void 0 : _a.value) !== void 0 ? e.target.value : e; setInnerValue(newValue); const isComposing = composingRef.current || (e == null ? void 0 : e.nativeEvent) && e.nativeEvent.isComposing; if (isComposing) return; emitChange(newValue); }, [emitChange] ); const handleVariableSelect = (0, import_react.useCallback)( (variableValue, metaTreeNode) => { setCurrentMetaTreeNode(metaTreeNode); const finalValue = (resolveValueFromPath == null ? void 0 : resolveValueFromPath(metaTreeNode)) || variableValue; setInnerValue(finalValue); emitChange(finalValue, metaTreeNode); }, [emitChange, resolveValueFromPath] ); const { disabled } = restProps; const handleClear = (0, import_react.useCallback)(() => { if (disabled) { return; } setCurrentMetaTreeNode(null); const cleared = clearValue !== void 0 ? clearValue : null; setInnerValue(cleared); emitChange(cleared); }, [emitChange, disabled, clearValue]); const stableProps = (0, import_react.useMemo)(() => { const { style, onFocus, onBlur, disabled: disabled2, ...otherProps } = restProps; return { style, onFocus, onBlur, otherProps }; }, [restProps]); const inputProps = (0, import_react.useMemo)(() => { const baseProps = { value: innerValue || "", onChange: handleInputChange, disabled }; if (ValueComponent === import_VariableTag.VariableTag) { return { ...baseProps, onClear: handleClear, metaTreeNode: resolvedMetaTreeNode, metaTree, style: stableProps.style }; } const { value: _ignoredValue, onChange: _ignoredOnChange, ...restOthers } = stableProps.otherProps || {}; const props = { ...baseProps, ...restOthers, // Ensure IME composition works correctly for text inputs onCompositionStart: handleComposition, onCompositionUpdate: handleComposition, onCompositionEnd: handleComposition }; return props; }, [ innerValue, handleInputChange, handleComposition, disabled, handleClear, resolvedMetaTreeNode, metaTree, ValueComponent, stableProps ]); const finalStyle = (0, import_react.useMemo)( () => ({ ...compactStyle, ...restProps.style }), [restProps.style] ); if (loading) { return null; } return /* @__PURE__ */ import_react.default.createElement(import_antd.Space.Compact, { style: finalStyle }, showValueComponent && /* @__PURE__ */ import_react.default.createElement( ValueComponent, { style: { width: "100%", minWidth: 0, ...inputProps["style"] }, ...inputProps } ), /* @__PURE__ */ import_react.default.createElement( import_FlowContextSelector.FlowContextSelector, { metaTree: resolvedMetaTree, value: innerValue, onChange: handleVariableSelect, parseValueToPath: resolvePathFromValue, formatPathToValue: resolveValueFromPath, onlyLeafSelectable, ...!showValueComponent && { children: null, placeholder: restProps == null ? void 0 : restProps.placeholder } } )); }, "VariableInputComponent"); const VariableInput = import_react.default.memo(VariableInputComponent); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { VariableInput });