@burdenoff/fluidgrids-fe-sdk 2026.801.1 → 2026.801.3
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/dist/{WorkflowBuilder-IGQYC2UR.js → WorkflowBuilder-UVADHNKZ.js} +5 -5
- package/dist/{WorkflowBuilder-IGQYC2UR.js.map → WorkflowBuilder-UVADHNKZ.js.map} +1 -1
- package/dist/WorkflowsList-F5QRVKAW.js +10 -0
- package/dist/{WorkflowsList-S2MGY2UT.js.map → WorkflowsList-F5QRVKAW.js.map} +1 -1
- package/dist/{blocks-K5JPCH3D.js → blocks-5FEPZOHW.js} +4 -4
- package/dist/{blocks-K5JPCH3D.js.map → blocks-5FEPZOHW.js.map} +1 -1
- package/dist/{chunk-JIZFSX6X.js → chunk-3VY2DAPD.js} +3 -3
- package/dist/{chunk-JIZFSX6X.js.map → chunk-3VY2DAPD.js.map} +1 -1
- package/dist/{chunk-2XMPJHCW.js → chunk-7WQUDC5E.js} +712 -247
- package/dist/chunk-7WQUDC5E.js.map +1 -0
- package/dist/{chunk-IVKT244I.js → chunk-AI5S3GO5.js} +180 -39
- package/dist/chunk-AI5S3GO5.js.map +1 -0
- package/dist/{chunk-KU64CCSV.js → chunk-WSBRI47P.js} +38 -5
- package/dist/chunk-WSBRI47P.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +8 -8
- package/package.json +1 -1
- package/dist/WorkflowsList-S2MGY2UT.js +0 -10
- package/dist/chunk-2XMPJHCW.js.map +0 -1
- package/dist/chunk-IVKT244I.js.map +0 -1
- package/dist/chunk-KU64CCSV.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, Input as Input$1, DialogFooter } from './chunk-MRVS73S2.js';
|
|
2
2
|
import { Badge as Badge$1, Button } from './chunk-DBOMRIP5.js';
|
|
3
|
-
import { refetchStoreNodes, registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, STICKY_NOTE_TYPE, useNodeExecution, getNodeDetail,
|
|
3
|
+
import { refetchStoreNodes, registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, STICKY_NOTE_TYPE, useNodeExecution, getNodeDetail, mergeStickyNotes, buildStickyNode, ConnectionSelector, nodeAccent, NODES_METADATA, isNodeConfigsInitialized, NODE_CONFIGS, NODES, NodePropertyPanel, resolveInputHandles } from './chunk-AI5S3GO5.js';
|
|
4
4
|
import { createGlobalStoreClient, setGlobalStoreClient, resetGlobalStoreClient, getGlobalStoreClient } from './chunk-BQXHJIER.js';
|
|
5
5
|
import { BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, GetMyNodeInstallationsDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument } from './chunk-PNOA7CQV.js';
|
|
6
6
|
import { useLazyWorkflowDefinition, useCreateWorkflow, useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useDeactivateWorkflow } from './chunk-NMS2QUXG.js';
|
|
7
|
-
import { useFlowStore } from './chunk-
|
|
7
|
+
import { useFlowStore } from './chunk-WSBRI47P.js';
|
|
8
8
|
import { SdkPermissionButton, FLUIDGRIDS_PERMISSIONS } from './chunk-UIY2HBWA.js';
|
|
9
9
|
import { cn } from './chunk-3ZYUGTIT.js';
|
|
10
10
|
import { throwIfResultError, NodeSchemaIntrospectionDocument, EventRegistrationsDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-XEYNX7YJ.js';
|
|
@@ -2432,10 +2432,15 @@ function StoreCategoryList({
|
|
|
2432
2432
|
searchTerm,
|
|
2433
2433
|
onSearchChange,
|
|
2434
2434
|
onSelectCategory,
|
|
2435
|
-
onSelectNode
|
|
2435
|
+
onSelectNode,
|
|
2436
|
+
autoFocusSearch = false
|
|
2436
2437
|
}) {
|
|
2437
2438
|
const isSearching = searchTerm.trim().length > 0;
|
|
2438
2439
|
const [showDeprecated, setShowDeprecated] = useState(false);
|
|
2440
|
+
const searchRef = useRef(null);
|
|
2441
|
+
useEffect(() => {
|
|
2442
|
+
if (autoFocusSearch) searchRef.current?.focus();
|
|
2443
|
+
}, [autoFocusSearch]);
|
|
2439
2444
|
const { products, loading, hasMore, fetchMore } = useStoreNodes({
|
|
2440
2445
|
filter: {
|
|
2441
2446
|
type: "NODE",
|
|
@@ -2459,6 +2464,7 @@ function StoreCategoryList({
|
|
|
2459
2464
|
/* @__PURE__ */ jsx(
|
|
2460
2465
|
Input$1,
|
|
2461
2466
|
{
|
|
2467
|
+
ref: searchRef,
|
|
2462
2468
|
value: searchTerm,
|
|
2463
2469
|
onChange: (e) => {
|
|
2464
2470
|
onSearchChange(e.target.value);
|
|
@@ -2868,6 +2874,57 @@ var UninstallNodeDialog = ({
|
|
|
2868
2874
|
] })
|
|
2869
2875
|
] }) });
|
|
2870
2876
|
};
|
|
2877
|
+
|
|
2878
|
+
// src/builder/hooks/attach-node-helpers.ts
|
|
2879
|
+
var ATTACH_GAP_X = 120;
|
|
2880
|
+
var DEFAULT_NODE_WIDTH = 288;
|
|
2881
|
+
function computeAttachPosition(source) {
|
|
2882
|
+
if (!source) return void 0;
|
|
2883
|
+
const width = source.measured?.width ?? DEFAULT_NODE_WIDTH;
|
|
2884
|
+
return {
|
|
2885
|
+
x: source.position.x + width + ATTACH_GAP_X,
|
|
2886
|
+
y: source.position.y
|
|
2887
|
+
};
|
|
2888
|
+
}
|
|
2889
|
+
function firstInputHandleId(data) {
|
|
2890
|
+
return resolveInputHandles(data)[0]?.id ?? "target";
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
// src/builder/hooks/use-attach-store-node.ts
|
|
2894
|
+
function useAddNodeFromStore() {
|
|
2895
|
+
const { getNode } = useReactFlow();
|
|
2896
|
+
const insertNode = useInsertNode();
|
|
2897
|
+
return useCallback(
|
|
2898
|
+
(nodeType, operationName) => {
|
|
2899
|
+
const store = useFlowStore.getState();
|
|
2900
|
+
const pending = store.workflow.pendingConnection;
|
|
2901
|
+
if (!pending) {
|
|
2902
|
+
insertNode(nodeType, void 0, operationName);
|
|
2903
|
+
return { attached: false };
|
|
2904
|
+
}
|
|
2905
|
+
const source = getNode(pending.nodeId);
|
|
2906
|
+
const created = insertNode(
|
|
2907
|
+
nodeType,
|
|
2908
|
+
computeAttachPosition(source),
|
|
2909
|
+
operationName
|
|
2910
|
+
);
|
|
2911
|
+
if (created?.id && source) {
|
|
2912
|
+
store.actions.edges.onConnect({
|
|
2913
|
+
source: pending.nodeId,
|
|
2914
|
+
sourceHandle: pending.handleId,
|
|
2915
|
+
target: created.id,
|
|
2916
|
+
targetHandle: firstInputHandleId(
|
|
2917
|
+
created.data
|
|
2918
|
+
)
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
store.actions.pendingConnection.clear();
|
|
2922
|
+
store.actions.sidebar.setActivePanel("none");
|
|
2923
|
+
return { attached: true };
|
|
2924
|
+
},
|
|
2925
|
+
[getNode, insertNode]
|
|
2926
|
+
);
|
|
2927
|
+
}
|
|
2871
2928
|
function isTriggerOperation(op) {
|
|
2872
2929
|
return op.role === "trigger" || !!op.delivery || op.type === "subscription";
|
|
2873
2930
|
}
|
|
@@ -2879,6 +2936,9 @@ function userSelectableOperations(ops) {
|
|
|
2879
2936
|
function StoreNodeOperations({ nodeType }) {
|
|
2880
2937
|
const [, bump] = useState(0);
|
|
2881
2938
|
useEffect(() => onNodeTypesUpdate(() => bump((n) => n + 1)), []);
|
|
2939
|
+
const pendingConnection = useFlowStore((s) => s.workflow.pendingConnection);
|
|
2940
|
+
const addNodeFromStore = useAddNodeFromStore();
|
|
2941
|
+
const attachMode = !!pendingConnection;
|
|
2882
2942
|
const config = nodeType ? NODE_CONFIGS.find((c) => c.type === nodeType) : void 0;
|
|
2883
2943
|
const operations = userSelectableOperations(
|
|
2884
2944
|
config?.operations
|
|
@@ -2893,6 +2953,13 @@ function StoreNodeOperations({ nodeType }) {
|
|
|
2893
2953
|
},
|
|
2894
2954
|
[nodeType]
|
|
2895
2955
|
);
|
|
2956
|
+
const handleClick = useCallback(
|
|
2957
|
+
(opName) => {
|
|
2958
|
+
if (!nodeType) return;
|
|
2959
|
+
addNodeFromStore(nodeType, opName);
|
|
2960
|
+
},
|
|
2961
|
+
[nodeType, addNodeFromStore]
|
|
2962
|
+
);
|
|
2896
2963
|
if (!nodeType) return null;
|
|
2897
2964
|
if (operations.length === 0) {
|
|
2898
2965
|
return /* @__PURE__ */ jsx("div", { className: "px-3 pt-3 pb-1", children: /* @__PURE__ */ jsxs(
|
|
@@ -2900,12 +2967,14 @@ function StoreNodeOperations({ nodeType }) {
|
|
|
2900
2967
|
{
|
|
2901
2968
|
draggable: true,
|
|
2902
2969
|
onDragStart: (e) => handleDragStart(e),
|
|
2903
|
-
|
|
2970
|
+
onClick: () => handleClick(),
|
|
2971
|
+
title: attachMode ? "Click to attach to the selected output" : "Click to add, or drag onto the canvas",
|
|
2904
2972
|
className: "w-full flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-muted/60 transition-colors text-left group",
|
|
2905
|
-
style: { cursor: "grab" },
|
|
2973
|
+
style: { cursor: attachMode ? "pointer" : "grab" },
|
|
2974
|
+
"data-testid": "store-op-add-to-canvas",
|
|
2906
2975
|
children: [
|
|
2907
2976
|
/* @__PURE__ */ jsx("div", { className: "size-7 shrink-0 rounded-md bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:plus", className: "size-3.5 text-primary" }) }),
|
|
2908
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: "Add to canvas" }),
|
|
2977
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: attachMode ? "Attach to canvas" : "Add to canvas" }),
|
|
2909
2978
|
/* @__PURE__ */ jsx(
|
|
2910
2979
|
Icon,
|
|
2911
2980
|
{
|
|
@@ -2918,17 +2987,22 @@ function StoreNodeOperations({ nodeType }) {
|
|
|
2918
2987
|
) });
|
|
2919
2988
|
}
|
|
2920
2989
|
return /* @__PURE__ */ jsxs("div", { className: "px-3 pt-3 pb-1", children: [
|
|
2921
|
-
/* @__PURE__ */ jsx("p", { className: "px-1 pb-2 text-xs font-medium text-muted-foreground", children: "Operations \u2014
|
|
2990
|
+
/* @__PURE__ */ jsx("p", { className: "px-1 pb-2 text-xs font-medium text-muted-foreground", children: attachMode ? "Operations \u2014 click one to attach it" : "Operations \u2014 click to add, or drag onto the canvas" }),
|
|
2922
2991
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: operations.map((op) => {
|
|
2923
2992
|
const isTrigger = isTriggerOperation(op);
|
|
2993
|
+
const attachBlocked = attachMode && isTrigger;
|
|
2924
2994
|
return /* @__PURE__ */ jsxs(
|
|
2925
2995
|
"button",
|
|
2926
2996
|
{
|
|
2927
2997
|
draggable: true,
|
|
2928
2998
|
onDragStart: (e) => handleDragStart(e, op.name),
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2999
|
+
onClick: attachBlocked ? void 0 : () => handleClick(op.name),
|
|
3000
|
+
title: attachBlocked ? "Triggers start a flow \u2014 they can't be attached to an output" : attachMode ? `${op.name} \u2014 click to attach to the selected output` : `${op.name} \u2014 click to add, or drag onto the canvas`,
|
|
3001
|
+
className: `w-full flex items-center gap-2.5 px-2 py-2 rounded-md transition-colors text-left group ${attachBlocked ? "opacity-45" : "hover:bg-muted/60"}`,
|
|
3002
|
+
style: {
|
|
3003
|
+
cursor: attachBlocked ? "not-allowed" : attachMode ? "pointer" : "grab"
|
|
3004
|
+
},
|
|
3005
|
+
"data-testid": `store-op-${op.name}`,
|
|
2932
3006
|
children: [
|
|
2933
3007
|
/* @__PURE__ */ jsx("div", { className: "size-7 shrink-0 rounded-md bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
2934
3008
|
Icon,
|
|
@@ -3345,10 +3419,70 @@ function StoreNodeDetail({ node, onBack }) {
|
|
|
3345
3419
|
)
|
|
3346
3420
|
] });
|
|
3347
3421
|
}
|
|
3422
|
+
function AttachModeBanner() {
|
|
3423
|
+
const pendingConnection = useFlowStore((s) => s.workflow.pendingConnection);
|
|
3424
|
+
const nodes = useFlowStore((s) => s.workflow.nodes);
|
|
3425
|
+
const clearPending = useFlowStore((s) => s.actions.pendingConnection.clear);
|
|
3426
|
+
if (!pendingConnection) return null;
|
|
3427
|
+
const source = nodes.find((n) => n.id === pendingConnection.nodeId);
|
|
3428
|
+
const data = source?.data;
|
|
3429
|
+
const sourceTitle = typeof data?.label === "string" && data.label || getNodeDetail(source?.type).title || pendingConnection.nodeId;
|
|
3430
|
+
const handleLabel = pendingConnection.handleId === "source" || pendingConnection.handleId === "output" ? void 0 : pendingConnection.handleId;
|
|
3431
|
+
return /* @__PURE__ */ jsx(
|
|
3432
|
+
"div",
|
|
3433
|
+
{
|
|
3434
|
+
className: "mx-3 mt-3 shrink-0 rounded-lg border px-3 py-2",
|
|
3435
|
+
style: {
|
|
3436
|
+
borderColor: "var(--color-status-info-border)",
|
|
3437
|
+
background: "var(--color-status-info-bgSubtle)"
|
|
3438
|
+
},
|
|
3439
|
+
"data-testid": "store-attach-banner",
|
|
3440
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3441
|
+
/* @__PURE__ */ jsx(
|
|
3442
|
+
Icon,
|
|
3443
|
+
{
|
|
3444
|
+
icon: "mynaui:git-branch",
|
|
3445
|
+
className: "size-4 shrink-0",
|
|
3446
|
+
style: { color: "var(--color-status-info-text)" }
|
|
3447
|
+
}
|
|
3448
|
+
),
|
|
3449
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
3450
|
+
/* @__PURE__ */ jsxs(
|
|
3451
|
+
"p",
|
|
3452
|
+
{
|
|
3453
|
+
className: "text-xs font-semibold leading-tight",
|
|
3454
|
+
style: { color: "var(--color-status-info-text)" },
|
|
3455
|
+
children: [
|
|
3456
|
+
"Attaching after \u201C",
|
|
3457
|
+
sourceTitle,
|
|
3458
|
+
"\u201D",
|
|
3459
|
+
handleLabel ? ` \u2192 ${handleLabel}` : ""
|
|
3460
|
+
]
|
|
3461
|
+
}
|
|
3462
|
+
),
|
|
3463
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Click an operation below to add & connect it." })
|
|
3464
|
+
] }),
|
|
3465
|
+
/* @__PURE__ */ jsx(
|
|
3466
|
+
"button",
|
|
3467
|
+
{
|
|
3468
|
+
type: "button",
|
|
3469
|
+
"aria-label": "Cancel attach",
|
|
3470
|
+
title: "Cancel attach",
|
|
3471
|
+
onClick: clearPending,
|
|
3472
|
+
className: "shrink-0 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
3473
|
+
"data-testid": "store-attach-cancel",
|
|
3474
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", className: "size-3.5" })
|
|
3475
|
+
}
|
|
3476
|
+
)
|
|
3477
|
+
] })
|
|
3478
|
+
}
|
|
3479
|
+
);
|
|
3480
|
+
}
|
|
3348
3481
|
function StoreBrowsePanel() {
|
|
3349
3482
|
const [view, setView] = useState({ type: "categories" });
|
|
3350
3483
|
const [globalSearch, setGlobalSearch] = useState("");
|
|
3351
3484
|
const [, setNodesReady] = useState(isNodeConfigsInitialized);
|
|
3485
|
+
const attachArmed = useFlowStore((s) => !!s.workflow.pendingConnection);
|
|
3352
3486
|
useEffect(() => {
|
|
3353
3487
|
void ensureNodeConfigsLoaded().then(() => setNodesReady(true));
|
|
3354
3488
|
}, []);
|
|
@@ -3370,6 +3504,7 @@ function StoreBrowsePanel() {
|
|
|
3370
3504
|
});
|
|
3371
3505
|
}, []);
|
|
3372
3506
|
return /* @__PURE__ */ jsxs(SidebarPanelWrapper, { children: [
|
|
3507
|
+
/* @__PURE__ */ jsx(AttachModeBanner, {}),
|
|
3373
3508
|
view.type === "categories" && /* @__PURE__ */ jsxs("div", { className: "px-4 pt-4 pb-2 shrink-0 flex items-center gap-2", children: [
|
|
3374
3509
|
/* @__PURE__ */ jsx("div", { className: "size-7 flex items-center justify-center rounded-lg bg-primary", children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:store", className: "size-4 text-white" }) }),
|
|
3375
3510
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -3384,7 +3519,8 @@ function StoreBrowsePanel() {
|
|
|
3384
3519
|
searchTerm: globalSearch,
|
|
3385
3520
|
onSearchChange: setGlobalSearch,
|
|
3386
3521
|
onSelectCategory: openCategory,
|
|
3387
|
-
onSelectNode: openNodeDetail
|
|
3522
|
+
onSelectNode: openNodeDetail,
|
|
3523
|
+
autoFocusSearch: attachArmed
|
|
3388
3524
|
}
|
|
3389
3525
|
),
|
|
3390
3526
|
view.type === "category-nodes" && /* @__PURE__ */ jsx(
|
|
@@ -4075,7 +4211,7 @@ function DesktopSidebarFragment({
|
|
|
4075
4211
|
if (nodes) {
|
|
4076
4212
|
const requiredNodeTypes = [];
|
|
4077
4213
|
try {
|
|
4078
|
-
const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-
|
|
4214
|
+
const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-5FEPZOHW.js');
|
|
4079
4215
|
await ensureNodeConfigsLoaded2().catch(() => {
|
|
4080
4216
|
});
|
|
4081
4217
|
const workflowNodeTypes = [
|
|
@@ -12629,6 +12765,8 @@ function useWebhookRegistration(workflowKey, triggerNodeId, enabled = true) {
|
|
|
12629
12765
|
refetch: fetchData
|
|
12630
12766
|
};
|
|
12631
12767
|
}
|
|
12768
|
+
|
|
12769
|
+
// src/builder/components/ndv/use-node-config.ts
|
|
12632
12770
|
function coerceNumber(type, raw) {
|
|
12633
12771
|
if (raw.trim() === "") return void 0;
|
|
12634
12772
|
const n = type === "integer" ? parseInt(raw, 10) : parseFloat(raw);
|
|
@@ -12673,66 +12811,32 @@ function nodeSubtitle(node) {
|
|
|
12673
12811
|
const data = asRecord(node?.data);
|
|
12674
12812
|
return typeof data?.operation_name === "string" ? data.operation_name : void 0;
|
|
12675
12813
|
}
|
|
12676
|
-
|
|
12677
|
-
function NodeDetailView() {
|
|
12678
|
-
const ndv = useFlowStore((s) => s.workflow.ndv);
|
|
12814
|
+
function useNodeConfig(target, options) {
|
|
12679
12815
|
const nodes = useFlowStore((s) => s.workflow.nodes);
|
|
12680
12816
|
const edges = useFlowStore((s) => s.workflow.edges);
|
|
12681
|
-
const
|
|
12682
|
-
const
|
|
12683
|
-
(s) => s.actions.sidebar.showNodePropertiesOf
|
|
12684
|
-
);
|
|
12685
|
-
const open = !!ndv;
|
|
12817
|
+
const workflowKey = useFlowStore((s) => s.workflow.workflowKey);
|
|
12818
|
+
const nodeId = target?.nodeId;
|
|
12686
12819
|
const node = useMemo(
|
|
12687
|
-
() =>
|
|
12688
|
-
[
|
|
12820
|
+
() => nodeId ? nodes.find((n) => n.id === nodeId) : void 0,
|
|
12821
|
+
[nodeId, nodes]
|
|
12689
12822
|
);
|
|
12690
12823
|
const incoming = useMemo(
|
|
12691
|
-
() =>
|
|
12692
|
-
[edges,
|
|
12824
|
+
() => nodeId ? edges.filter((e) => e.target === nodeId) : [],
|
|
12825
|
+
[edges, nodeId]
|
|
12693
12826
|
);
|
|
12694
12827
|
const sourceIds = useMemo(() => incoming.map((e) => e.source), [incoming]);
|
|
12695
12828
|
const sourceKey = sourceIds.join(",");
|
|
12696
12829
|
const [selectedSource, setSelectedSource] = useState();
|
|
12697
|
-
const [tab, setTab] = useState("parameters");
|
|
12698
|
-
const [outputView, setOutputView] = useState("schema");
|
|
12699
12830
|
const [dragField, setDragField] = useState(null);
|
|
12700
12831
|
const [modeByField, setModeByField] = useState({});
|
|
12701
|
-
const panesRef = useRef(null);
|
|
12702
|
-
const dragCleanupRef = useRef(null);
|
|
12703
|
-
const [leftPct, setLeftPct] = useState(30);
|
|
12704
|
-
const [rightPct, setRightPct] = useState(30);
|
|
12705
|
-
const startDrag = (which) => (e) => {
|
|
12706
|
-
e.preventDefault();
|
|
12707
|
-
const el = panesRef.current;
|
|
12708
|
-
if (!el) return;
|
|
12709
|
-
const rect = el.getBoundingClientRect();
|
|
12710
|
-
const onMove = (ev) => {
|
|
12711
|
-
const pct = (ev.clientX - rect.left) / rect.width * 100;
|
|
12712
|
-
if (which === "left") setLeftPct(Math.min(55, Math.max(15, pct)));
|
|
12713
|
-
else setRightPct(Math.min(55, Math.max(15, 100 - pct)));
|
|
12714
|
-
};
|
|
12715
|
-
const cleanup = () => {
|
|
12716
|
-
window.removeEventListener("mousemove", onMove);
|
|
12717
|
-
window.removeEventListener("mouseup", cleanup);
|
|
12718
|
-
dragCleanupRef.current = null;
|
|
12719
|
-
};
|
|
12720
|
-
dragCleanupRef.current = cleanup;
|
|
12721
|
-
window.addEventListener("mousemove", onMove);
|
|
12722
|
-
window.addEventListener("mouseup", cleanup);
|
|
12723
|
-
};
|
|
12724
|
-
useEffect(() => () => dragCleanupRef.current?.(), []);
|
|
12725
12832
|
useEffect(() => {
|
|
12726
12833
|
setSelectedSource(
|
|
12727
12834
|
(prev) => prev && sourceIds.includes(prev) ? prev : sourceIds[0]
|
|
12728
12835
|
);
|
|
12729
|
-
}, [
|
|
12730
|
-
useEffect(() => {
|
|
12731
|
-
if (open) setTab("parameters");
|
|
12732
|
-
}, [open, ndv?.nodeId]);
|
|
12836
|
+
}, [nodeId, sourceKey, sourceIds]);
|
|
12733
12837
|
useEffect(() => {
|
|
12734
12838
|
setModeByField({});
|
|
12735
|
-
}, [
|
|
12839
|
+
}, [nodeId, selectedSource]);
|
|
12736
12840
|
const sourceNode = useMemo(
|
|
12737
12841
|
() => nodes.find((n) => n.id === selectedSource),
|
|
12738
12842
|
[nodes, selectedSource]
|
|
@@ -12762,11 +12866,10 @@ function NodeDetailView() {
|
|
|
12762
12866
|
() => !!asRecord(currentOp?.output_fields)?.webhookUrl,
|
|
12763
12867
|
[currentOp]
|
|
12764
12868
|
);
|
|
12765
|
-
const workflowKey = useFlowStore((s) => s.workflow.workflowKey);
|
|
12766
12869
|
const { webhookUrl, loading: webhookUrlLoading } = useWebhookRegistration(
|
|
12767
12870
|
workflowKey || void 0,
|
|
12768
12871
|
node?.id,
|
|
12769
|
-
isWebhookTrigger &&
|
|
12872
|
+
isWebhookTrigger && (options?.webhookEnabled ?? true)
|
|
12770
12873
|
);
|
|
12771
12874
|
const pickerFields = useMemo(() => flattenFields(inputFields), [inputFields]);
|
|
12772
12875
|
const mapping = currentEdge?.mapping?.definition ?? {};
|
|
@@ -12799,10 +12902,10 @@ function NodeDetailView() {
|
|
|
12799
12902
|
return fromList(args?.credentials, "id");
|
|
12800
12903
|
}, [node]);
|
|
12801
12904
|
const handleConnectionsChange = (connections) => {
|
|
12802
|
-
if (!
|
|
12905
|
+
if (!nodeId) return;
|
|
12803
12906
|
const store = useFlowStore.getState();
|
|
12804
12907
|
const next = store.workflow.nodes.map((n) => {
|
|
12805
|
-
if (n.id !==
|
|
12908
|
+
if (n.id !== nodeId) return n;
|
|
12806
12909
|
const data = { ...asRecord(n.data) ?? {} };
|
|
12807
12910
|
const args = { ...asRecord(data.args) ?? {} };
|
|
12808
12911
|
delete args.credentials;
|
|
@@ -12828,19 +12931,19 @@ function NodeDetailView() {
|
|
|
12828
12931
|
...e,
|
|
12829
12932
|
mapping: {
|
|
12830
12933
|
definition: def,
|
|
12831
|
-
comment: e.mapping?.comment ?? `Map ${selectedSource} \u2192 ${
|
|
12934
|
+
comment: e.mapping?.comment ?? `Map ${selectedSource} \u2192 ${nodeId ?? ""}`
|
|
12832
12935
|
}
|
|
12833
12936
|
};
|
|
12834
12937
|
});
|
|
12835
12938
|
store.actions.edges.setEdges(next);
|
|
12836
12939
|
};
|
|
12837
12940
|
const clearMappingFromAllIncoming = (field) => {
|
|
12838
|
-
if (!
|
|
12941
|
+
if (!nodeId) return;
|
|
12839
12942
|
const store = useFlowStore.getState();
|
|
12840
12943
|
const fresh = store.workflow.edges;
|
|
12841
12944
|
let changed = false;
|
|
12842
12945
|
const next = fresh.map((e) => {
|
|
12843
|
-
if (e.target !==
|
|
12946
|
+
if (e.target !== nodeId || !e.mapping?.definition) return e;
|
|
12844
12947
|
if (!(field in e.mapping.definition)) return e;
|
|
12845
12948
|
const def = { ...e.mapping.definition };
|
|
12846
12949
|
delete def[field];
|
|
@@ -12850,10 +12953,10 @@ function NodeDetailView() {
|
|
|
12850
12953
|
if (changed) store.actions.edges.setEdges(next);
|
|
12851
12954
|
};
|
|
12852
12955
|
const writeFixed = (field, value) => {
|
|
12853
|
-
if (!
|
|
12956
|
+
if (!nodeId) return;
|
|
12854
12957
|
const store = useFlowStore.getState();
|
|
12855
12958
|
const next = store.workflow.nodes.map((n) => {
|
|
12856
|
-
if (n.id !==
|
|
12959
|
+
if (n.id !== nodeId) return n;
|
|
12857
12960
|
const data = { ...asRecord(n.data) ?? {} };
|
|
12858
12961
|
const args = { ...asRecord(data.args) ?? {} };
|
|
12859
12962
|
const state = { ...asRecord(args.state) ?? {} };
|
|
@@ -12887,6 +12990,279 @@ function NodeDetailView() {
|
|
|
12887
12990
|
setModeByField((m) => ({ ...m, [field]: "expression" }));
|
|
12888
12991
|
}
|
|
12889
12992
|
};
|
|
12993
|
+
return {
|
|
12994
|
+
node,
|
|
12995
|
+
nodes,
|
|
12996
|
+
incoming,
|
|
12997
|
+
sourceIds,
|
|
12998
|
+
selectedSource,
|
|
12999
|
+
setSelectedSource,
|
|
13000
|
+
currentEdge,
|
|
13001
|
+
currentOp,
|
|
13002
|
+
params,
|
|
13003
|
+
argsState,
|
|
13004
|
+
mapping,
|
|
13005
|
+
inputFields,
|
|
13006
|
+
outputFields,
|
|
13007
|
+
pickerFields,
|
|
13008
|
+
connectionAdapters,
|
|
13009
|
+
selectedConnections,
|
|
13010
|
+
isWebhookTrigger,
|
|
13011
|
+
webhookUrl,
|
|
13012
|
+
webhookUrlLoading,
|
|
13013
|
+
modeByField,
|
|
13014
|
+
dragField,
|
|
13015
|
+
setDragField,
|
|
13016
|
+
writeFixed,
|
|
13017
|
+
writeMapping,
|
|
13018
|
+
handleConnectionsChange,
|
|
13019
|
+
toggleMode,
|
|
13020
|
+
handleDropOnParam
|
|
13021
|
+
};
|
|
13022
|
+
}
|
|
13023
|
+
var SECTION_LABEL2 = "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground";
|
|
13024
|
+
function NodeParamsForm({
|
|
13025
|
+
config,
|
|
13026
|
+
nodeType,
|
|
13027
|
+
testIdPrefix = "ndv"
|
|
13028
|
+
}) {
|
|
13029
|
+
const {
|
|
13030
|
+
params,
|
|
13031
|
+
argsState,
|
|
13032
|
+
mapping,
|
|
13033
|
+
pickerFields,
|
|
13034
|
+
connectionAdapters,
|
|
13035
|
+
selectedConnections,
|
|
13036
|
+
isWebhookTrigger,
|
|
13037
|
+
webhookUrl,
|
|
13038
|
+
webhookUrlLoading,
|
|
13039
|
+
currentEdge,
|
|
13040
|
+
modeByField,
|
|
13041
|
+
dragField,
|
|
13042
|
+
setDragField,
|
|
13043
|
+
writeFixed,
|
|
13044
|
+
writeMapping,
|
|
13045
|
+
handleConnectionsChange,
|
|
13046
|
+
toggleMode,
|
|
13047
|
+
handleDropOnParam
|
|
13048
|
+
} = config;
|
|
13049
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13050
|
+
isWebhookTrigger && /* @__PURE__ */ jsx(WebhookUrlField, { webhookUrl, loading: webhookUrlLoading }),
|
|
13051
|
+
connectionAdapters.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": `${testIdPrefix}-connections`, children: [
|
|
13052
|
+
/* @__PURE__ */ jsx("div", { className: SECTION_LABEL2, children: "Connections" }),
|
|
13053
|
+
/* @__PURE__ */ jsx(
|
|
13054
|
+
ConnectionSelector,
|
|
13055
|
+
{
|
|
13056
|
+
adapters: connectionAdapters,
|
|
13057
|
+
selectedConnections,
|
|
13058
|
+
onChange: handleConnectionsChange,
|
|
13059
|
+
compact: true
|
|
13060
|
+
}
|
|
13061
|
+
)
|
|
13062
|
+
] }),
|
|
13063
|
+
!currentEdge && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: "No upstream node connected \u2014 set fixed values below, or connect a node to map fields with expressions." }),
|
|
13064
|
+
params.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-xs text-muted-foreground", children: "This operation has no input parameters." }) : params.map((p) => {
|
|
13065
|
+
if (p.type === "condition") {
|
|
13066
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
13067
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name === "conditionTree" ? "Conditions" : p.name }),
|
|
13068
|
+
/* @__PURE__ */ jsx(
|
|
13069
|
+
ConditionTreeBuilder,
|
|
13070
|
+
{
|
|
13071
|
+
value: argsState[p.name],
|
|
13072
|
+
fields: pickerFields,
|
|
13073
|
+
onChange: (tree) => writeFixed(p.name, tree)
|
|
13074
|
+
}
|
|
13075
|
+
),
|
|
13076
|
+
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
13077
|
+
] }, p.name);
|
|
13078
|
+
}
|
|
13079
|
+
if (p.type === "switch-rules") {
|
|
13080
|
+
const rules = Array.isArray(argsState[p.name]) ? argsState[p.name] : [];
|
|
13081
|
+
const fallbackHandle = typeof argsState.fallbackHandle === "string" ? argsState.fallbackHandle : "default";
|
|
13082
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
13083
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: "Routing rules" }),
|
|
13084
|
+
/* @__PURE__ */ jsx(
|
|
13085
|
+
SwitchRulesEditor,
|
|
13086
|
+
{
|
|
13087
|
+
rules,
|
|
13088
|
+
fallbackHandle,
|
|
13089
|
+
fields: pickerFields,
|
|
13090
|
+
onChange: (next) => {
|
|
13091
|
+
writeFixed(p.name, next.rules);
|
|
13092
|
+
writeFixed("cases", casesFromRules(next.rules));
|
|
13093
|
+
writeFixed("fallbackHandle", next.fallbackHandle);
|
|
13094
|
+
}
|
|
13095
|
+
}
|
|
13096
|
+
)
|
|
13097
|
+
] }, p.name);
|
|
13098
|
+
}
|
|
13099
|
+
const mode = modeByField[p.name] ?? (mapping[p.name] !== void 0 ? "expression" : "fixed");
|
|
13100
|
+
const exprValue = mapping[p.name] ?? "";
|
|
13101
|
+
const fixedValue = argsState[p.name];
|
|
13102
|
+
const isCodeParam = p.type === "code" || nodeType === "internal:code" && p.name === "code";
|
|
13103
|
+
const highlight = dragField === p.name;
|
|
13104
|
+
const inputCx = cn$1(
|
|
13105
|
+
"w-full rounded-md border bg-background px-2.5 py-1.5 text-sm outline-none transition-colors disabled:opacity-50",
|
|
13106
|
+
highlight ? "border-primary ring-1 ring-primary" : "border-input focus:border-primary"
|
|
13107
|
+
);
|
|
13108
|
+
return /* @__PURE__ */ jsxs(
|
|
13109
|
+
"div",
|
|
13110
|
+
{
|
|
13111
|
+
className: "flex flex-col gap-1.5",
|
|
13112
|
+
onDragOver: (e) => e.preventDefault(),
|
|
13113
|
+
onDragEnter: () => setDragField(p.name),
|
|
13114
|
+
onDragLeave: () => setDragField((f) => f === p.name ? null : f),
|
|
13115
|
+
onDrop: handleDropOnParam(p.name),
|
|
13116
|
+
children: [
|
|
13117
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
13118
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name }),
|
|
13119
|
+
p.required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" }),
|
|
13120
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto text-[10px] uppercase tracking-wide text-muted-foreground", children: p.type }),
|
|
13121
|
+
/* @__PURE__ */ jsx(
|
|
13122
|
+
"button",
|
|
13123
|
+
{
|
|
13124
|
+
type: "button",
|
|
13125
|
+
onClick: () => toggleMode(p.name, mode),
|
|
13126
|
+
title: mode === "expression" ? "Switch to a fixed value" : "Switch to an expression",
|
|
13127
|
+
"data-testid": `${testIdPrefix}-mode-${p.name}`,
|
|
13128
|
+
className: cn$1(
|
|
13129
|
+
"ml-1 rounded p-0.5 hover:text-foreground",
|
|
13130
|
+
mode === "expression" ? "text-primary" : "text-muted-foreground"
|
|
13131
|
+
),
|
|
13132
|
+
children: /* @__PURE__ */ jsx(
|
|
13133
|
+
Icon,
|
|
13134
|
+
{
|
|
13135
|
+
icon: mode === "expression" ? "mdi:variable" : "mdi:form-textbox",
|
|
13136
|
+
className: "size-3.5"
|
|
13137
|
+
}
|
|
13138
|
+
)
|
|
13139
|
+
}
|
|
13140
|
+
)
|
|
13141
|
+
] }),
|
|
13142
|
+
mode === "expression" ? /* @__PURE__ */ jsx(
|
|
13143
|
+
"input",
|
|
13144
|
+
{
|
|
13145
|
+
type: "text",
|
|
13146
|
+
value: exprValue,
|
|
13147
|
+
placeholder: currentEdge ? "Drop a field or type ${output.\u2026}" : "Connect an upstream node to use expressions",
|
|
13148
|
+
disabled: !currentEdge,
|
|
13149
|
+
onChange: (e) => writeMapping(p.name, e.target.value),
|
|
13150
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`,
|
|
13151
|
+
className: cn$1(inputCx, "font-mono text-primary")
|
|
13152
|
+
}
|
|
13153
|
+
) : isCodeParam ? /* @__PURE__ */ jsx(
|
|
13154
|
+
CodeEditorField,
|
|
13155
|
+
{
|
|
13156
|
+
value: typeof fixedValue === "string" ? fixedValue : "",
|
|
13157
|
+
language: normalizeCodeLanguage(
|
|
13158
|
+
argsState.runtime ?? params.find((f) => f.name === "runtime")?.defaultValue
|
|
13159
|
+
),
|
|
13160
|
+
placeholder: typeof p.defaultValue === "string" ? p.defaultValue : p.description,
|
|
13161
|
+
onChange: (v) => writeFixed(p.name, v),
|
|
13162
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`
|
|
13163
|
+
}
|
|
13164
|
+
) : p.type === "boolean" ? /* @__PURE__ */ jsxs("label", { className: "flex w-fit cursor-pointer items-center gap-2 text-sm", children: [
|
|
13165
|
+
/* @__PURE__ */ jsx(
|
|
13166
|
+
"input",
|
|
13167
|
+
{
|
|
13168
|
+
type: "checkbox",
|
|
13169
|
+
checked: fixedValue === true,
|
|
13170
|
+
onChange: (e) => writeFixed(p.name, e.target.checked),
|
|
13171
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`,
|
|
13172
|
+
className: "size-4"
|
|
13173
|
+
}
|
|
13174
|
+
),
|
|
13175
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: fixedValue === void 0 ? "Not set (default)" : fixedValue === true ? "true" : "false" })
|
|
13176
|
+
] }) : p.options && p.options.length > 0 ? /* @__PURE__ */ jsxs(
|
|
13177
|
+
"select",
|
|
13178
|
+
{
|
|
13179
|
+
value: typeof fixedValue === "string" ? fixedValue : "",
|
|
13180
|
+
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
13181
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`,
|
|
13182
|
+
className: inputCx,
|
|
13183
|
+
children: [
|
|
13184
|
+
/* @__PURE__ */ jsx("option", { value: "", children: p.defaultValue !== void 0 ? `Default (${String(p.defaultValue)})` : "Select\u2026" }),
|
|
13185
|
+
p.options.map((o) => /* @__PURE__ */ jsx("option", { value: o, children: o }, o))
|
|
13186
|
+
]
|
|
13187
|
+
}
|
|
13188
|
+
) : p.type === "integer" || p.type === "number" ? /* @__PURE__ */ jsx(
|
|
13189
|
+
"input",
|
|
13190
|
+
{
|
|
13191
|
+
type: "number",
|
|
13192
|
+
step: p.type === "integer" ? "1" : "any",
|
|
13193
|
+
value: typeof fixedValue === "number" ? String(fixedValue) : "",
|
|
13194
|
+
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a number",
|
|
13195
|
+
onChange: (e) => writeFixed(p.name, coerceNumber(p.type, e.target.value)),
|
|
13196
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`,
|
|
13197
|
+
className: inputCx
|
|
13198
|
+
}
|
|
13199
|
+
) : /* @__PURE__ */ jsx(
|
|
13200
|
+
"input",
|
|
13201
|
+
{
|
|
13202
|
+
type: "text",
|
|
13203
|
+
value: fixedValue === void 0 || fixedValue === null ? "" : String(fixedValue),
|
|
13204
|
+
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a value",
|
|
13205
|
+
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
13206
|
+
"data-testid": `${testIdPrefix}-param-${p.name}`,
|
|
13207
|
+
className: inputCx
|
|
13208
|
+
}
|
|
13209
|
+
),
|
|
13210
|
+
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
13211
|
+
]
|
|
13212
|
+
},
|
|
13213
|
+
p.name
|
|
13214
|
+
);
|
|
13215
|
+
})
|
|
13216
|
+
] });
|
|
13217
|
+
}
|
|
13218
|
+
var SECTION_LABEL3 = "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground";
|
|
13219
|
+
function NodeDetailView() {
|
|
13220
|
+
const ndv = useFlowStore((s) => s.workflow.ndv);
|
|
13221
|
+
const closeNdv = useFlowStore((s) => s.actions.ndv.close);
|
|
13222
|
+
const showNodePropertiesOf = useFlowStore(
|
|
13223
|
+
(s) => s.actions.sidebar.showNodePropertiesOf
|
|
13224
|
+
);
|
|
13225
|
+
const open = !!ndv;
|
|
13226
|
+
const config = useNodeConfig(ndv ?? null, { webhookEnabled: open });
|
|
13227
|
+
const {
|
|
13228
|
+
node,
|
|
13229
|
+
nodes,
|
|
13230
|
+
sourceIds,
|
|
13231
|
+
selectedSource,
|
|
13232
|
+
setSelectedSource,
|
|
13233
|
+
currentOp,
|
|
13234
|
+
inputFields,
|
|
13235
|
+
outputFields
|
|
13236
|
+
} = config;
|
|
13237
|
+
const [tab, setTab] = useState("parameters");
|
|
13238
|
+
const [outputView, setOutputView] = useState("schema");
|
|
13239
|
+
const panesRef = useRef(null);
|
|
13240
|
+
const dragCleanupRef = useRef(null);
|
|
13241
|
+
const [leftPct, setLeftPct] = useState(30);
|
|
13242
|
+
const [rightPct, setRightPct] = useState(30);
|
|
13243
|
+
const startDrag = (which) => (e) => {
|
|
13244
|
+
e.preventDefault();
|
|
13245
|
+
const el = panesRef.current;
|
|
13246
|
+
if (!el) return;
|
|
13247
|
+
const rect = el.getBoundingClientRect();
|
|
13248
|
+
const onMove = (ev) => {
|
|
13249
|
+
const pct = (ev.clientX - rect.left) / rect.width * 100;
|
|
13250
|
+
if (which === "left") setLeftPct(Math.min(55, Math.max(15, pct)));
|
|
13251
|
+
else setRightPct(Math.min(55, Math.max(15, 100 - pct)));
|
|
13252
|
+
};
|
|
13253
|
+
const cleanup = () => {
|
|
13254
|
+
window.removeEventListener("mousemove", onMove);
|
|
13255
|
+
window.removeEventListener("mouseup", cleanup);
|
|
13256
|
+
dragCleanupRef.current = null;
|
|
13257
|
+
};
|
|
13258
|
+
dragCleanupRef.current = cleanup;
|
|
13259
|
+
window.addEventListener("mousemove", onMove);
|
|
13260
|
+
window.addEventListener("mouseup", cleanup);
|
|
13261
|
+
};
|
|
13262
|
+
useEffect(() => () => dragCleanupRef.current?.(), []);
|
|
13263
|
+
useEffect(() => {
|
|
13264
|
+
if (open) setTab("parameters");
|
|
13265
|
+
}, [open, ndv?.nodeId]);
|
|
12890
13266
|
const openClassicPanel = () => {
|
|
12891
13267
|
if (!ndv) return;
|
|
12892
13268
|
showNodePropertiesOf({
|
|
@@ -12944,7 +13320,7 @@ function NodeDetailView() {
|
|
|
12944
13320
|
className: "flex min-h-0 min-w-[180px] flex-col bg-card/40",
|
|
12945
13321
|
children: [
|
|
12946
13322
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-2.5", children: [
|
|
12947
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
13323
|
+
/* @__PURE__ */ jsx("span", { className: SECTION_LABEL3, children: "Input" }),
|
|
12948
13324
|
sourceIds.length > 0 && /* @__PURE__ */ jsx(
|
|
12949
13325
|
"select",
|
|
12950
13326
|
{
|
|
@@ -12997,188 +13373,19 @@ function NodeDetailView() {
|
|
|
12997
13373
|
}
|
|
12998
13374
|
)
|
|
12999
13375
|
] }),
|
|
13000
|
-
tab === "parameters" ? /* @__PURE__ */
|
|
13376
|
+
tab === "parameters" ? /* @__PURE__ */ jsx(
|
|
13001
13377
|
"div",
|
|
13002
13378
|
{
|
|
13003
13379
|
className: "min-h-0 flex-1 space-y-4 overflow-auto p-4",
|
|
13004
13380
|
"data-testid": "ndv-params",
|
|
13005
|
-
children:
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
connectionAdapters.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": "ndv-connections", children: [
|
|
13014
|
-
/* @__PURE__ */ jsx("div", { className: SECTION_LABEL2, children: "Connections" }),
|
|
13015
|
-
/* @__PURE__ */ jsx(
|
|
13016
|
-
ConnectionSelector,
|
|
13017
|
-
{
|
|
13018
|
-
adapters: connectionAdapters,
|
|
13019
|
-
selectedConnections,
|
|
13020
|
-
onChange: handleConnectionsChange,
|
|
13021
|
-
compact: true
|
|
13022
|
-
}
|
|
13023
|
-
)
|
|
13024
|
-
] }),
|
|
13025
|
-
!currentEdge && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: "No upstream node connected \u2014 set fixed values below, or connect a node to map fields with expressions." }),
|
|
13026
|
-
params.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-xs text-muted-foreground", children: "This operation has no input parameters." }) : params.map((p) => {
|
|
13027
|
-
if (p.type === "condition") {
|
|
13028
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
13029
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name === "conditionTree" ? "Conditions" : p.name }),
|
|
13030
|
-
/* @__PURE__ */ jsx(
|
|
13031
|
-
ConditionTreeBuilder,
|
|
13032
|
-
{
|
|
13033
|
-
value: argsState[p.name],
|
|
13034
|
-
fields: pickerFields,
|
|
13035
|
-
onChange: (tree) => writeFixed(p.name, tree)
|
|
13036
|
-
}
|
|
13037
|
-
),
|
|
13038
|
-
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
13039
|
-
] }, p.name);
|
|
13040
|
-
}
|
|
13041
|
-
if (p.type === "switch-rules") {
|
|
13042
|
-
const rules = Array.isArray(argsState[p.name]) ? argsState[p.name] : [];
|
|
13043
|
-
const fallbackHandle = typeof argsState.fallbackHandle === "string" ? argsState.fallbackHandle : "default";
|
|
13044
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
13045
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: "Routing rules" }),
|
|
13046
|
-
/* @__PURE__ */ jsx(
|
|
13047
|
-
SwitchRulesEditor,
|
|
13048
|
-
{
|
|
13049
|
-
rules,
|
|
13050
|
-
fallbackHandle,
|
|
13051
|
-
fields: pickerFields,
|
|
13052
|
-
onChange: (next) => {
|
|
13053
|
-
writeFixed(p.name, next.rules);
|
|
13054
|
-
writeFixed("cases", casesFromRules(next.rules));
|
|
13055
|
-
writeFixed("fallbackHandle", next.fallbackHandle);
|
|
13056
|
-
}
|
|
13057
|
-
}
|
|
13058
|
-
)
|
|
13059
|
-
] }, p.name);
|
|
13060
|
-
}
|
|
13061
|
-
const mode = modeByField[p.name] ?? (mapping[p.name] !== void 0 ? "expression" : "fixed");
|
|
13062
|
-
const exprValue = mapping[p.name] ?? "";
|
|
13063
|
-
const fixedValue = argsState[p.name];
|
|
13064
|
-
const isCodeParam = p.type === "code" || node?.type === "internal:code" && p.name === "code";
|
|
13065
|
-
const highlight = dragField === p.name;
|
|
13066
|
-
const inputCx = cn$1(
|
|
13067
|
-
"w-full rounded-md border bg-background px-2.5 py-1.5 text-sm outline-none transition-colors disabled:opacity-50",
|
|
13068
|
-
highlight ? "border-primary ring-1 ring-primary" : "border-input focus:border-primary"
|
|
13069
|
-
);
|
|
13070
|
-
return /* @__PURE__ */ jsxs(
|
|
13071
|
-
"div",
|
|
13072
|
-
{
|
|
13073
|
-
className: "flex flex-col gap-1.5",
|
|
13074
|
-
onDragOver: (e) => e.preventDefault(),
|
|
13075
|
-
onDragEnter: () => setDragField(p.name),
|
|
13076
|
-
onDragLeave: () => setDragField((f) => f === p.name ? null : f),
|
|
13077
|
-
onDrop: handleDropOnParam(p.name),
|
|
13078
|
-
children: [
|
|
13079
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
13080
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name }),
|
|
13081
|
-
p.required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" }),
|
|
13082
|
-
/* @__PURE__ */ jsx("span", { className: "ml-auto text-[10px] uppercase tracking-wide text-muted-foreground", children: p.type }),
|
|
13083
|
-
/* @__PURE__ */ jsx(
|
|
13084
|
-
"button",
|
|
13085
|
-
{
|
|
13086
|
-
type: "button",
|
|
13087
|
-
onClick: () => toggleMode(p.name, mode),
|
|
13088
|
-
title: mode === "expression" ? "Switch to a fixed value" : "Switch to an expression",
|
|
13089
|
-
"data-testid": `ndv-mode-${p.name}`,
|
|
13090
|
-
className: cn$1(
|
|
13091
|
-
"ml-1 rounded p-0.5 hover:text-foreground",
|
|
13092
|
-
mode === "expression" ? "text-primary" : "text-muted-foreground"
|
|
13093
|
-
),
|
|
13094
|
-
children: /* @__PURE__ */ jsx(
|
|
13095
|
-
Icon,
|
|
13096
|
-
{
|
|
13097
|
-
icon: mode === "expression" ? "mdi:variable" : "mdi:form-textbox",
|
|
13098
|
-
className: "size-3.5"
|
|
13099
|
-
}
|
|
13100
|
-
)
|
|
13101
|
-
}
|
|
13102
|
-
)
|
|
13103
|
-
] }),
|
|
13104
|
-
mode === "expression" ? /* @__PURE__ */ jsx(
|
|
13105
|
-
"input",
|
|
13106
|
-
{
|
|
13107
|
-
type: "text",
|
|
13108
|
-
value: exprValue,
|
|
13109
|
-
placeholder: currentEdge ? "Drop a field or type ${output.\u2026}" : "Connect an upstream node to use expressions",
|
|
13110
|
-
disabled: !currentEdge,
|
|
13111
|
-
onChange: (e) => writeMapping(p.name, e.target.value),
|
|
13112
|
-
"data-testid": `ndv-param-${p.name}`,
|
|
13113
|
-
className: cn$1(inputCx, "font-mono text-primary")
|
|
13114
|
-
}
|
|
13115
|
-
) : isCodeParam ? /* @__PURE__ */ jsx(
|
|
13116
|
-
CodeEditorField,
|
|
13117
|
-
{
|
|
13118
|
-
value: typeof fixedValue === "string" ? fixedValue : "",
|
|
13119
|
-
language: normalizeCodeLanguage(
|
|
13120
|
-
argsState.runtime ?? params.find((f) => f.name === "runtime")?.defaultValue
|
|
13121
|
-
),
|
|
13122
|
-
placeholder: typeof p.defaultValue === "string" ? p.defaultValue : p.description,
|
|
13123
|
-
onChange: (v) => writeFixed(p.name, v),
|
|
13124
|
-
"data-testid": `ndv-param-${p.name}`
|
|
13125
|
-
}
|
|
13126
|
-
) : p.type === "boolean" ? /* @__PURE__ */ jsxs("label", { className: "flex w-fit cursor-pointer items-center gap-2 text-sm", children: [
|
|
13127
|
-
/* @__PURE__ */ jsx(
|
|
13128
|
-
"input",
|
|
13129
|
-
{
|
|
13130
|
-
type: "checkbox",
|
|
13131
|
-
checked: fixedValue === true,
|
|
13132
|
-
onChange: (e) => writeFixed(p.name, e.target.checked),
|
|
13133
|
-
"data-testid": `ndv-param-${p.name}`,
|
|
13134
|
-
className: "size-4"
|
|
13135
|
-
}
|
|
13136
|
-
),
|
|
13137
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: fixedValue === void 0 ? "Not set (default)" : fixedValue === true ? "true" : "false" })
|
|
13138
|
-
] }) : p.options && p.options.length > 0 ? /* @__PURE__ */ jsxs(
|
|
13139
|
-
"select",
|
|
13140
|
-
{
|
|
13141
|
-
value: typeof fixedValue === "string" ? fixedValue : "",
|
|
13142
|
-
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
13143
|
-
"data-testid": `ndv-param-${p.name}`,
|
|
13144
|
-
className: inputCx,
|
|
13145
|
-
children: [
|
|
13146
|
-
/* @__PURE__ */ jsx("option", { value: "", children: p.defaultValue !== void 0 ? `Default (${String(p.defaultValue)})` : "Select\u2026" }),
|
|
13147
|
-
p.options.map((o) => /* @__PURE__ */ jsx("option", { value: o, children: o }, o))
|
|
13148
|
-
]
|
|
13149
|
-
}
|
|
13150
|
-
) : p.type === "integer" || p.type === "number" ? /* @__PURE__ */ jsx(
|
|
13151
|
-
"input",
|
|
13152
|
-
{
|
|
13153
|
-
type: "number",
|
|
13154
|
-
step: p.type === "integer" ? "1" : "any",
|
|
13155
|
-
value: typeof fixedValue === "number" ? String(fixedValue) : "",
|
|
13156
|
-
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a number",
|
|
13157
|
-
onChange: (e) => writeFixed(
|
|
13158
|
-
p.name,
|
|
13159
|
-
coerceNumber(p.type, e.target.value)
|
|
13160
|
-
),
|
|
13161
|
-
"data-testid": `ndv-param-${p.name}`,
|
|
13162
|
-
className: inputCx
|
|
13163
|
-
}
|
|
13164
|
-
) : /* @__PURE__ */ jsx(
|
|
13165
|
-
"input",
|
|
13166
|
-
{
|
|
13167
|
-
type: "text",
|
|
13168
|
-
value: fixedValue === void 0 || fixedValue === null ? "" : String(fixedValue),
|
|
13169
|
-
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a value",
|
|
13170
|
-
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
13171
|
-
"data-testid": `ndv-param-${p.name}`,
|
|
13172
|
-
className: inputCx
|
|
13173
|
-
}
|
|
13174
|
-
),
|
|
13175
|
-
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
13176
|
-
]
|
|
13177
|
-
},
|
|
13178
|
-
p.name
|
|
13179
|
-
);
|
|
13180
|
-
})
|
|
13181
|
-
]
|
|
13381
|
+
children: /* @__PURE__ */ jsx(
|
|
13382
|
+
NodeParamsForm,
|
|
13383
|
+
{
|
|
13384
|
+
config,
|
|
13385
|
+
nodeType: node?.type,
|
|
13386
|
+
testIdPrefix: "ndv"
|
|
13387
|
+
}
|
|
13388
|
+
)
|
|
13182
13389
|
}
|
|
13183
13390
|
) : /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4 text-xs text-muted-foreground", children: "No additional settings for this node." })
|
|
13184
13391
|
] }),
|
|
@@ -13190,7 +13397,7 @@ function NodeDetailView() {
|
|
|
13190
13397
|
className: "flex min-h-0 min-w-[180px] flex-col bg-card/40",
|
|
13191
13398
|
children: [
|
|
13192
13399
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-2.5", children: [
|
|
13193
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
13400
|
+
/* @__PURE__ */ jsx("span", { className: SECTION_LABEL3, children: "Output" }),
|
|
13194
13401
|
outputFields.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
13195
13402
|
/* @__PURE__ */ jsx(
|
|
13196
13403
|
ToggleChip,
|
|
@@ -13292,6 +13499,261 @@ function EmptyState({
|
|
|
13292
13499
|
/* @__PURE__ */ jsx("div", { className: "max-w-[14rem] text-xs text-muted-foreground", children: hint })
|
|
13293
13500
|
] });
|
|
13294
13501
|
}
|
|
13502
|
+
var PANEL_WIDTH = 380;
|
|
13503
|
+
var PANEL_EST_HEIGHT = 480;
|
|
13504
|
+
var MAPPER_WIDTH = 260;
|
|
13505
|
+
var VIEWPORT_MARGIN = 12;
|
|
13506
|
+
function clampToViewport(pos) {
|
|
13507
|
+
const maxX = window.innerWidth - PANEL_WIDTH - VIEWPORT_MARGIN;
|
|
13508
|
+
const maxY = window.innerHeight - PANEL_EST_HEIGHT - VIEWPORT_MARGIN;
|
|
13509
|
+
return {
|
|
13510
|
+
x: Math.min(
|
|
13511
|
+
Math.max(VIEWPORT_MARGIN, pos.x),
|
|
13512
|
+
Math.max(VIEWPORT_MARGIN, maxX)
|
|
13513
|
+
),
|
|
13514
|
+
y: Math.min(
|
|
13515
|
+
Math.max(VIEWPORT_MARGIN, pos.y),
|
|
13516
|
+
Math.max(VIEWPORT_MARGIN, maxY)
|
|
13517
|
+
)
|
|
13518
|
+
};
|
|
13519
|
+
}
|
|
13520
|
+
function QuickConfigPanel() {
|
|
13521
|
+
const quickConfig = useFlowStore((s) => s.workflow.quickConfig);
|
|
13522
|
+
if (!quickConfig) return null;
|
|
13523
|
+
return (
|
|
13524
|
+
// Remount per node so panel position/flyout state reset naturally.
|
|
13525
|
+
/* @__PURE__ */ jsx(
|
|
13526
|
+
QuickConfigPanelInner,
|
|
13527
|
+
{
|
|
13528
|
+
nodeId: quickConfig.nodeId,
|
|
13529
|
+
type: quickConfig.type,
|
|
13530
|
+
anchor: quickConfig.anchor
|
|
13531
|
+
},
|
|
13532
|
+
quickConfig.nodeId
|
|
13533
|
+
)
|
|
13534
|
+
);
|
|
13535
|
+
}
|
|
13536
|
+
function QuickConfigPanelInner({
|
|
13537
|
+
nodeId,
|
|
13538
|
+
type,
|
|
13539
|
+
anchor
|
|
13540
|
+
}) {
|
|
13541
|
+
const close = useFlowStore((s) => s.actions.quickConfig.close);
|
|
13542
|
+
const openNdv = useFlowStore((s) => s.actions.ndv.open);
|
|
13543
|
+
const config = useNodeConfig({ nodeId});
|
|
13544
|
+
const {
|
|
13545
|
+
node,
|
|
13546
|
+
nodes,
|
|
13547
|
+
sourceIds,
|
|
13548
|
+
selectedSource,
|
|
13549
|
+
setSelectedSource,
|
|
13550
|
+
inputFields
|
|
13551
|
+
} = config;
|
|
13552
|
+
const [pos, setPos] = useState(
|
|
13553
|
+
() => clampToViewport(
|
|
13554
|
+
anchor ?? {
|
|
13555
|
+
x: window.innerWidth / 2 - PANEL_WIDTH / 2,
|
|
13556
|
+
y: window.innerHeight / 4
|
|
13557
|
+
}
|
|
13558
|
+
)
|
|
13559
|
+
);
|
|
13560
|
+
const [showMapper, setShowMapper] = useState(false);
|
|
13561
|
+
const dragStateRef = useRef(null);
|
|
13562
|
+
const handleHeaderPointerDown = useCallback(
|
|
13563
|
+
(e) => {
|
|
13564
|
+
if (e.target.closest("button")) return;
|
|
13565
|
+
dragStateRef.current = {
|
|
13566
|
+
startX: e.clientX,
|
|
13567
|
+
startY: e.clientY,
|
|
13568
|
+
baseX: pos.x,
|
|
13569
|
+
baseY: pos.y
|
|
13570
|
+
};
|
|
13571
|
+
const onMove = (ev) => {
|
|
13572
|
+
const s = dragStateRef.current;
|
|
13573
|
+
if (!s) return;
|
|
13574
|
+
setPos(
|
|
13575
|
+
clampToViewport({
|
|
13576
|
+
x: s.baseX + (ev.clientX - s.startX),
|
|
13577
|
+
y: s.baseY + (ev.clientY - s.startY)
|
|
13578
|
+
})
|
|
13579
|
+
);
|
|
13580
|
+
};
|
|
13581
|
+
const onUp = () => {
|
|
13582
|
+
dragStateRef.current = null;
|
|
13583
|
+
window.removeEventListener("pointermove", onMove);
|
|
13584
|
+
window.removeEventListener("pointerup", onUp);
|
|
13585
|
+
};
|
|
13586
|
+
window.addEventListener("pointermove", onMove);
|
|
13587
|
+
window.addEventListener("pointerup", onUp);
|
|
13588
|
+
},
|
|
13589
|
+
[pos.x, pos.y]
|
|
13590
|
+
);
|
|
13591
|
+
useEffect(() => {
|
|
13592
|
+
const onKey = (e) => {
|
|
13593
|
+
if (e.key === "Escape") close();
|
|
13594
|
+
};
|
|
13595
|
+
window.addEventListener("keydown", onKey);
|
|
13596
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
13597
|
+
}, [close]);
|
|
13598
|
+
useEffect(() => {
|
|
13599
|
+
if (!nodes.some((n) => n.id === nodeId)) close();
|
|
13600
|
+
}, [nodes, nodeId, close]);
|
|
13601
|
+
if (!node) return null;
|
|
13602
|
+
const meta = getNodeDetail(node.type);
|
|
13603
|
+
const accent = nodeAccent(node.type || meta.title);
|
|
13604
|
+
const subtitle = nodeSubtitle(node);
|
|
13605
|
+
const expandToNdv = () => {
|
|
13606
|
+
openNdv({ nodeId, type });
|
|
13607
|
+
};
|
|
13608
|
+
return /* @__PURE__ */ jsxs(
|
|
13609
|
+
"div",
|
|
13610
|
+
{
|
|
13611
|
+
className: "fixed",
|
|
13612
|
+
style: { left: pos.x, top: pos.y, zIndex: 300, width: PANEL_WIDTH },
|
|
13613
|
+
"data-testid": "quick-config-panel",
|
|
13614
|
+
children: [
|
|
13615
|
+
showMapper && /* @__PURE__ */ jsxs(
|
|
13616
|
+
"div",
|
|
13617
|
+
{
|
|
13618
|
+
className: "absolute overflow-hidden rounded-xl border border-border bg-card shadow-xl",
|
|
13619
|
+
style: {
|
|
13620
|
+
right: "100%",
|
|
13621
|
+
marginRight: 10,
|
|
13622
|
+
top: 0,
|
|
13623
|
+
width: MAPPER_WIDTH,
|
|
13624
|
+
maxHeight: "min(60vh, 480px)",
|
|
13625
|
+
display: "flex",
|
|
13626
|
+
flexDirection: "column"
|
|
13627
|
+
},
|
|
13628
|
+
"data-testid": "quick-config-mapper",
|
|
13629
|
+
children: [
|
|
13630
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-2", children: [
|
|
13631
|
+
/* @__PURE__ */ jsx(
|
|
13632
|
+
Icon,
|
|
13633
|
+
{
|
|
13634
|
+
icon: "mdi:tray-arrow-down",
|
|
13635
|
+
className: "size-3.5 text-muted-foreground"
|
|
13636
|
+
}
|
|
13637
|
+
),
|
|
13638
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: "Input" }),
|
|
13639
|
+
sourceIds.length > 0 && /* @__PURE__ */ jsx(
|
|
13640
|
+
"select",
|
|
13641
|
+
{
|
|
13642
|
+
className: "ml-auto max-w-[55%] truncate rounded-md border border-input bg-background px-1.5 py-0.5 text-[11px] text-foreground outline-none focus:border-primary",
|
|
13643
|
+
value: selectedSource ?? "",
|
|
13644
|
+
onChange: (e) => setSelectedSource(e.target.value),
|
|
13645
|
+
"data-testid": "qc-source-selector",
|
|
13646
|
+
children: sourceIds.map((sid) => {
|
|
13647
|
+
const sn = nodes.find((n) => n.id === sid);
|
|
13648
|
+
return /* @__PURE__ */ jsx("option", { value: sid, children: nodeTitle(sn) }, sid);
|
|
13649
|
+
})
|
|
13650
|
+
}
|
|
13651
|
+
)
|
|
13652
|
+
] }),
|
|
13653
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto px-2 py-2", children: inputFields.length > 0 ? /* @__PURE__ */ jsx(FieldTree, { fields: inputFields, draggable: true }) : /* @__PURE__ */ jsx("p", { className: "px-2 py-4 text-center text-xs text-muted-foreground", children: sourceIds.length === 0 ? "Connect an upstream node to map its fields." : "The selected source has no declared output fields." }) }),
|
|
13654
|
+
/* @__PURE__ */ jsx("p", { className: "shrink-0 border-t border-border px-3 py-1.5 text-[10px] leading-snug text-muted-foreground", children: "Drag a field onto a parameter to map it." })
|
|
13655
|
+
]
|
|
13656
|
+
}
|
|
13657
|
+
),
|
|
13658
|
+
/* @__PURE__ */ jsxs(
|
|
13659
|
+
"div",
|
|
13660
|
+
{
|
|
13661
|
+
className: "flex flex-col overflow-hidden rounded-xl border border-border bg-card shadow-2xl animate-in fade-in zoom-in-95 duration-150",
|
|
13662
|
+
style: {
|
|
13663
|
+
maxHeight: "min(70vh, 560px)",
|
|
13664
|
+
borderTop: `3px solid ${accent}`
|
|
13665
|
+
},
|
|
13666
|
+
children: [
|
|
13667
|
+
/* @__PURE__ */ jsxs(
|
|
13668
|
+
"div",
|
|
13669
|
+
{
|
|
13670
|
+
className: "flex shrink-0 cursor-move items-center gap-2.5 border-b border-border px-3 py-2.5 select-none",
|
|
13671
|
+
onPointerDown: handleHeaderPointerDown,
|
|
13672
|
+
children: [
|
|
13673
|
+
/* @__PURE__ */ jsx(
|
|
13674
|
+
"div",
|
|
13675
|
+
{
|
|
13676
|
+
className: "flex size-7 shrink-0 items-center justify-center rounded-lg",
|
|
13677
|
+
style: {
|
|
13678
|
+
backgroundColor: `color-mix(in srgb, ${accent} 13%, transparent)`,
|
|
13679
|
+
color: accent,
|
|
13680
|
+
border: `1px solid color-mix(in srgb, ${accent} 26%, transparent)`
|
|
13681
|
+
},
|
|
13682
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: meta.icon, className: "size-4" })
|
|
13683
|
+
}
|
|
13684
|
+
),
|
|
13685
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
13686
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold leading-tight text-foreground", children: nodeTitle(node) }),
|
|
13687
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "truncate font-mono text-[11px] leading-tight text-muted-foreground", children: subtitle })
|
|
13688
|
+
] }),
|
|
13689
|
+
/* @__PURE__ */ jsx(
|
|
13690
|
+
"button",
|
|
13691
|
+
{
|
|
13692
|
+
type: "button",
|
|
13693
|
+
title: showMapper ? "Hide input data" : "Map data from input",
|
|
13694
|
+
"aria-label": "Toggle input mapper",
|
|
13695
|
+
onClick: () => setShowMapper((v) => !v),
|
|
13696
|
+
className: `rounded-md p-1.5 transition-colors hover:bg-muted ${showMapper ? "text-primary" : "text-muted-foreground"} hover:text-foreground`,
|
|
13697
|
+
"data-testid": "qc-toggle-mapper",
|
|
13698
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:tray-arrow-down", className: "size-4" })
|
|
13699
|
+
}
|
|
13700
|
+
),
|
|
13701
|
+
/* @__PURE__ */ jsx(
|
|
13702
|
+
"button",
|
|
13703
|
+
{
|
|
13704
|
+
type: "button",
|
|
13705
|
+
title: "Open full editor",
|
|
13706
|
+
"aria-label": "Open full editor",
|
|
13707
|
+
onClick: expandToNdv,
|
|
13708
|
+
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
13709
|
+
"data-testid": "qc-expand",
|
|
13710
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-expand", className: "size-4" })
|
|
13711
|
+
}
|
|
13712
|
+
),
|
|
13713
|
+
/* @__PURE__ */ jsx(
|
|
13714
|
+
"button",
|
|
13715
|
+
{
|
|
13716
|
+
type: "button",
|
|
13717
|
+
title: "Close",
|
|
13718
|
+
"aria-label": "Close",
|
|
13719
|
+
onClick: close,
|
|
13720
|
+
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
13721
|
+
"data-testid": "qc-close",
|
|
13722
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", className: "size-4" })
|
|
13723
|
+
}
|
|
13724
|
+
)
|
|
13725
|
+
]
|
|
13726
|
+
}
|
|
13727
|
+
),
|
|
13728
|
+
/* @__PURE__ */ jsx(
|
|
13729
|
+
"div",
|
|
13730
|
+
{
|
|
13731
|
+
className: "min-h-0 flex-1 space-y-4 overflow-auto p-3",
|
|
13732
|
+
"data-testid": "qc-params",
|
|
13733
|
+
onFocusCapture: (e) => {
|
|
13734
|
+
const tag = e.target.tagName;
|
|
13735
|
+
if (sourceIds.length > 0 && (tag === "INPUT" || tag === "SELECT" || tag === "TEXTAREA")) {
|
|
13736
|
+
setShowMapper(true);
|
|
13737
|
+
}
|
|
13738
|
+
},
|
|
13739
|
+
children: /* @__PURE__ */ jsx(
|
|
13740
|
+
NodeParamsForm,
|
|
13741
|
+
{
|
|
13742
|
+
config,
|
|
13743
|
+
nodeType: node.type,
|
|
13744
|
+
testIdPrefix: "qc"
|
|
13745
|
+
}
|
|
13746
|
+
)
|
|
13747
|
+
}
|
|
13748
|
+
),
|
|
13749
|
+
/* @__PURE__ */ jsx("p", { className: "shrink-0 border-t border-border px-3 py-1.5 text-[10px] leading-snug text-muted-foreground", children: "Changes apply instantly \xB7 double-click the node for the full editor" })
|
|
13750
|
+
]
|
|
13751
|
+
}
|
|
13752
|
+
)
|
|
13753
|
+
]
|
|
13754
|
+
}
|
|
13755
|
+
);
|
|
13756
|
+
}
|
|
13295
13757
|
var STATUS_STYLES = {
|
|
13296
13758
|
DRAFT: { label: "Draft", variant: "secondary" },
|
|
13297
13759
|
ACTIVE: { label: "Active", variant: "default" },
|
|
@@ -13786,6 +14248,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
13786
14248
|
];
|
|
13787
14249
|
})
|
|
13788
14250
|
);
|
|
14251
|
+
const closeQuickConfig = useFlowStore((s) => s.actions.quickConfig.close);
|
|
13789
14252
|
const [nodeTypesVersion, setNodeTypesVersion] = useState(0);
|
|
13790
14253
|
useEffect(() => {
|
|
13791
14254
|
return onNodeTypesUpdate(() => setNodeTypesVersion((v) => v + 1));
|
|
@@ -14040,6 +14503,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
14040
14503
|
onNodeDragStop: (_, node) => {
|
|
14041
14504
|
autoAdjustNode(node);
|
|
14042
14505
|
},
|
|
14506
|
+
onPaneClick: closeQuickConfig,
|
|
14043
14507
|
onNodesDelete,
|
|
14044
14508
|
isValidConnection,
|
|
14045
14509
|
nodesDraggable: !isReadOnly,
|
|
@@ -14072,6 +14536,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
14072
14536
|
/* @__PURE__ */ jsx(ChatPanel, {}),
|
|
14073
14537
|
/* @__PURE__ */ jsx(LogsPanel, {}),
|
|
14074
14538
|
/* @__PURE__ */ jsx(NodeDetailView, {}),
|
|
14539
|
+
/* @__PURE__ */ jsx(QuickConfigPanel, {}),
|
|
14075
14540
|
/* @__PURE__ */ jsx(
|
|
14076
14541
|
"div",
|
|
14077
14542
|
{
|
|
@@ -14310,7 +14775,7 @@ function WorkflowItem({
|
|
|
14310
14775
|
};
|
|
14311
14776
|
const requiredNodeTypes = [];
|
|
14312
14777
|
try {
|
|
14313
|
-
const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-
|
|
14778
|
+
const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-5FEPZOHW.js');
|
|
14314
14779
|
await ensureNodeConfigsLoaded2().catch(() => {
|
|
14315
14780
|
});
|
|
14316
14781
|
const workflowNodeTypes = [
|
|
@@ -14608,5 +15073,5 @@ function WorkflowBuilder() {
|
|
|
14608
15073
|
}
|
|
14609
15074
|
|
|
14610
15075
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, FlowBuilderPage, FluidGridsProvider, TemplateCard, WorkflowBuilder, useFluidGridsContext, useImportWorkflowTemplate, useWorkflowTemplates };
|
|
14611
|
-
//# sourceMappingURL=chunk-
|
|
14612
|
-
//# sourceMappingURL=chunk-
|
|
15076
|
+
//# sourceMappingURL=chunk-7WQUDC5E.js.map
|
|
15077
|
+
//# sourceMappingURL=chunk-7WQUDC5E.js.map
|