@burdenoff/fluidgrids-fe-sdk 2026.703.1 → 2026.705.1
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-BWB3552Z.js → WorkflowBuilder-FG5PRFZY.js} +3 -3
- package/dist/{WorkflowBuilder-BWB3552Z.js.map → WorkflowBuilder-FG5PRFZY.js.map} +1 -1
- package/dist/{chunk-5GIC24CM.js → chunk-HNN7T6G6.js} +1115 -307
- package/dist/chunk-HNN7T6G6.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-5GIC24CM.js.map +0 -1
|
@@ -9,17 +9,17 @@ import { config, getFluidGridsConfig, validateTrustedOrigin, setFluidGridsConfig
|
|
|
9
9
|
import { deepClone, applyTemplateInputs } from './chunk-XQP33UJR.js';
|
|
10
10
|
import { cn as cn$1, Badge as Badge$1, Button as Button$1 } from './chunk-Z54K22LP.js';
|
|
11
11
|
import { ThemeProvider as ThemeProvider$1 } from '@burdenoff/fe-libs/shared/providers/shell';
|
|
12
|
-
import {
|
|
12
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
14
14
|
import { useShallow, shallow } from 'zustand/shallow';
|
|
15
|
-
import * as
|
|
16
|
-
import
|
|
17
|
-
import { Handle, Position, getBezierPath, MarkerType, useStore, useReactFlow, getConnectedEdges, useNodeId, ReactFlowProvider, ReactFlow, Background, useOnSelectionChange, MiniMap, EdgeLabelRenderer, getOutgoers, useNodes, useNodesState, useEdgesState, addEdge, Controls, Panel } from '@xyflow/react';
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import React__default, { forwardRef, useState, useImperativeHandle, useRef, useEffect, useMemo, createContext, lazy, memo, useCallback, useContext, useLayoutEffect, Suspense, useDeferredValue } from 'react';
|
|
17
|
+
import { Handle, Position, getBezierPath, MarkerType, useStore, useReactFlow, getConnectedEdges, useUpdateNodeInternals, useNodeId, ReactFlowProvider, ReactFlow, Background, useOnSelectionChange, MiniMap, EdgeLabelRenderer, getOutgoers, useNodes, useNodesState, useEdgesState, addEdge, Controls, Panel } from '@xyflow/react';
|
|
18
18
|
import { produce } from 'immer';
|
|
19
19
|
import { nanoid } from 'nanoid/non-secure';
|
|
20
|
+
import { Icon } from '@iconify/react';
|
|
20
21
|
import { cn } from '@burdenoff/fe-libs/utils';
|
|
21
22
|
import { Textarea, Input, Button, Card, Badge, CardContent as CardContent$1, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, Popover, PopoverTrigger, PopoverContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@burdenoff/fe-libs/ui';
|
|
22
|
-
import { Icon } from '@iconify/react';
|
|
23
23
|
import * as AdaptiveCards from 'adaptivecards';
|
|
24
24
|
import { formatDistanceToNow } from 'date-fns';
|
|
25
25
|
import { gql } from '@apollo/client';
|
|
@@ -64,6 +64,255 @@ function useDeleteNode() {
|
|
|
64
64
|
[deleteElements, getEdges, getNode, deleteNode, deleteEdge]
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
|
+
var BRAND_ACCENTS = [
|
|
68
|
+
[/gmail|google/, "#ea4335"],
|
|
69
|
+
[/slack/, "#611f69"],
|
|
70
|
+
[/github/, "#334155"],
|
|
71
|
+
[/gitlab/, "#fc6d26"],
|
|
72
|
+
[/stripe/, "#635bff"],
|
|
73
|
+
[/discord/, "#5865f2"],
|
|
74
|
+
[/notion/, "#111827"],
|
|
75
|
+
[/telegram/, "#2aabee"],
|
|
76
|
+
[/whatsapp/, "#25d366"],
|
|
77
|
+
[/openai/, "#10a37f"],
|
|
78
|
+
[/anthropic|claude/, "#d97757"],
|
|
79
|
+
[/twilio/, "#f22f46"],
|
|
80
|
+
[/sheet|excel/, "#21a366"],
|
|
81
|
+
[/http|api|webhook|rest/, "#6366f1"],
|
|
82
|
+
[/db|sql|postgres|mysql|mongo/, "#0ea5e9"]
|
|
83
|
+
];
|
|
84
|
+
var HASH_PALETTE = [
|
|
85
|
+
"#6366f1",
|
|
86
|
+
"#0ea5e9",
|
|
87
|
+
"#10b981",
|
|
88
|
+
"#f59e0b",
|
|
89
|
+
"#ef4444",
|
|
90
|
+
"#a855f7",
|
|
91
|
+
"#ec4899",
|
|
92
|
+
"#14b8a6",
|
|
93
|
+
"#f97316",
|
|
94
|
+
"#8b5cf6"
|
|
95
|
+
];
|
|
96
|
+
function nodeAccent(key) {
|
|
97
|
+
const k = (key || "").toLowerCase();
|
|
98
|
+
for (const [re, hex] of BRAND_ACCENTS) if (re.test(k)) return hex;
|
|
99
|
+
let h = 0;
|
|
100
|
+
for (let i = 0; i < k.length; i++) h = h * 31 + k.charCodeAt(i) >>> 0;
|
|
101
|
+
return HASH_PALETTE[h % HASH_PALETTE.length];
|
|
102
|
+
}
|
|
103
|
+
function tint(hex, pct = 14) {
|
|
104
|
+
return `color-mix(in srgb, ${hex} ${pct}%, transparent)`;
|
|
105
|
+
}
|
|
106
|
+
var NodeCard = React.forwardRef(
|
|
107
|
+
({
|
|
108
|
+
className,
|
|
109
|
+
selected = false,
|
|
110
|
+
executionStatus = "idle",
|
|
111
|
+
itemCount,
|
|
112
|
+
isTrigger = false,
|
|
113
|
+
accent = "#3b82f6",
|
|
114
|
+
onSettings,
|
|
115
|
+
onExecute,
|
|
116
|
+
onDelete,
|
|
117
|
+
isExecuting = false,
|
|
118
|
+
infoButton,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) => {
|
|
122
|
+
const [hovered, setHovered] = React.useState(false);
|
|
123
|
+
const statusRing = executionStatus === "running" ? "ring-2 ring-[var(--color-status-success-border)] animate-pulse-border" : executionStatus === "success" ? "ring-2 ring-[var(--color-status-success-border)]" : executionStatus === "error" ? "ring-2 ring-[var(--color-status-error-border)]" : "";
|
|
124
|
+
return /* @__PURE__ */ jsxs(
|
|
125
|
+
"div",
|
|
126
|
+
{
|
|
127
|
+
className: "group/node relative",
|
|
128
|
+
onMouseEnter: () => setHovered(true),
|
|
129
|
+
onMouseLeave: () => setHovered(false),
|
|
130
|
+
children: [
|
|
131
|
+
itemCount !== void 0 && itemCount > 0 && /* @__PURE__ */ jsx("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 z-10", children: /* @__PURE__ */ jsxs("div", { className: "rounded-full border border-border bg-card px-2 py-0.5 text-[10px] font-medium text-muted-foreground shadow-sm", children: [
|
|
132
|
+
itemCount,
|
|
133
|
+
" item",
|
|
134
|
+
itemCount !== 1 ? "s" : ""
|
|
135
|
+
] }) }),
|
|
136
|
+
(onSettings || onExecute || onDelete || infoButton) && /* @__PURE__ */ jsxs(
|
|
137
|
+
"div",
|
|
138
|
+
{
|
|
139
|
+
className: cn(
|
|
140
|
+
"absolute right-1 z-20 flex items-center gap-0.5 rounded-lg border border-border bg-card p-0.5 shadow-md transition-all duration-150",
|
|
141
|
+
hovered ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0"
|
|
142
|
+
),
|
|
143
|
+
style: {
|
|
144
|
+
// Inline offset (not a `-top-*` class) so it survives the host
|
|
145
|
+
// app's Tailwind scan of fe-sdk source, which drops some spacing
|
|
146
|
+
// utilities. The toolbar is ~30px tall; top:-15px centers it on
|
|
147
|
+
// the card's top edge (half outside, half over the card).
|
|
148
|
+
top: -15,
|
|
149
|
+
transform: hovered ? "translateY(0)" : "translateY(4px)"
|
|
150
|
+
},
|
|
151
|
+
onDoubleClick: (e) => e.stopPropagation(),
|
|
152
|
+
children: [
|
|
153
|
+
onSettings && /* @__PURE__ */ jsx(ToolbarButton, { title: "Configure", onClick: onSettings, children: /* @__PURE__ */ jsx(Icon, { icon: "lucide:sliders-horizontal", className: "size-4" }) }),
|
|
154
|
+
onExecute && /* @__PURE__ */ jsx(
|
|
155
|
+
ToolbarButton,
|
|
156
|
+
{
|
|
157
|
+
title: "Execute step",
|
|
158
|
+
onClick: onExecute,
|
|
159
|
+
disabled: isExecuting,
|
|
160
|
+
children: isExecuting ? /* @__PURE__ */ jsx(
|
|
161
|
+
Icon,
|
|
162
|
+
{
|
|
163
|
+
icon: "svg-spinners:ring-resize",
|
|
164
|
+
className: "size-4 text-[var(--color-status-success-text)]"
|
|
165
|
+
}
|
|
166
|
+
) : /* @__PURE__ */ jsx(
|
|
167
|
+
Icon,
|
|
168
|
+
{
|
|
169
|
+
icon: "mdi:play",
|
|
170
|
+
className: "size-4 text-[var(--color-status-success-text)]"
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
infoButton,
|
|
176
|
+
onDelete && /* @__PURE__ */ jsx(ToolbarButton, { title: "Delete", onClick: onDelete, children: /* @__PURE__ */ jsx(
|
|
177
|
+
Icon,
|
|
178
|
+
{
|
|
179
|
+
icon: "mynaui:trash",
|
|
180
|
+
className: "size-4 text-[var(--color-status-error-text)]"
|
|
181
|
+
}
|
|
182
|
+
) })
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
/* @__PURE__ */ jsxs(
|
|
187
|
+
"div",
|
|
188
|
+
{
|
|
189
|
+
ref,
|
|
190
|
+
"data-selected": selected,
|
|
191
|
+
className: cn(
|
|
192
|
+
"relative w-72 rounded-xl border border-border bg-card shadow-sm will-change-transform",
|
|
193
|
+
statusRing,
|
|
194
|
+
executionStatus === "success" && "animate-success-glow",
|
|
195
|
+
className
|
|
196
|
+
),
|
|
197
|
+
style: {
|
|
198
|
+
borderTop: `3px solid ${accent}`,
|
|
199
|
+
transition: "transform 0.15s ease, box-shadow 0.15s ease",
|
|
200
|
+
transform: hovered ? "translateY(-2px)" : "none",
|
|
201
|
+
boxShadow: hovered ? "0 2px 4px rgba(16,24,40,0.06), 0 16px 34px -12px rgba(16,24,40,0.24)" : void 0
|
|
202
|
+
},
|
|
203
|
+
...props,
|
|
204
|
+
children: [
|
|
205
|
+
/* @__PURE__ */ jsx(
|
|
206
|
+
"div",
|
|
207
|
+
{
|
|
208
|
+
className: "pointer-events-none absolute -inset-0.5 transition-opacity duration-150",
|
|
209
|
+
style: {
|
|
210
|
+
borderRadius: 14,
|
|
211
|
+
opacity: selected || hovered ? 1 : 0,
|
|
212
|
+
boxShadow: selected ? `0 0 0 2px ${accent}, 0 0 0 5px ${tint(accent, 18)}` : `0 0 0 2px ${accent}`
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
isTrigger && /* @__PURE__ */ jsx(
|
|
217
|
+
"div",
|
|
218
|
+
{
|
|
219
|
+
className: "absolute -top-2 -left-2 z-10 flex size-5 items-center justify-center rounded-full shadow-md ring-2 ring-card",
|
|
220
|
+
style: { backgroundColor: "var(--color-status-success-text)" },
|
|
221
|
+
children: /* @__PURE__ */ jsx(
|
|
222
|
+
Icon,
|
|
223
|
+
{
|
|
224
|
+
icon: "mdi:lightning-bolt",
|
|
225
|
+
className: "size-3",
|
|
226
|
+
style: { color: "var(--color-status-success-text-inverse)" }
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
children
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
executionStatus === "success" && /* @__PURE__ */ jsx(StatusCorner, { icon: "mdi:check", tone: "success" }),
|
|
236
|
+
executionStatus === "error" && /* @__PURE__ */ jsx(StatusCorner, { icon: "mdi:close", tone: "error" }),
|
|
237
|
+
executionStatus === "running" && /* @__PURE__ */ jsx(StatusCorner, { icon: "svg-spinners:ring-resize", tone: "success" })
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
NodeCard.displayName = "NodeCard";
|
|
244
|
+
function ToolbarButton({
|
|
245
|
+
title,
|
|
246
|
+
onClick,
|
|
247
|
+
disabled,
|
|
248
|
+
children
|
|
249
|
+
}) {
|
|
250
|
+
return /* @__PURE__ */ jsx(
|
|
251
|
+
"button",
|
|
252
|
+
{
|
|
253
|
+
type: "button",
|
|
254
|
+
title,
|
|
255
|
+
disabled,
|
|
256
|
+
onClick: (e) => {
|
|
257
|
+
e.stopPropagation();
|
|
258
|
+
onClick?.();
|
|
259
|
+
},
|
|
260
|
+
className: "flex size-6 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50",
|
|
261
|
+
children
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
function StatusCorner({
|
|
266
|
+
icon,
|
|
267
|
+
tone
|
|
268
|
+
}) {
|
|
269
|
+
const bg = tone === "success" ? "var(--color-status-success-bg)" : "var(--color-status-error-bg)";
|
|
270
|
+
const fg = tone === "success" ? "var(--color-status-success-text-inverse)" : "var(--color-status-error-text-inverse)";
|
|
271
|
+
return /* @__PURE__ */ jsx("div", { className: "absolute -bottom-1.5 -right-1.5 z-10", children: /* @__PURE__ */ jsx(
|
|
272
|
+
"div",
|
|
273
|
+
{
|
|
274
|
+
className: "rounded-full p-0.5 shadow-md animate-in zoom-in duration-200",
|
|
275
|
+
style: { backgroundColor: bg },
|
|
276
|
+
children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-3", style: { color: fg } })
|
|
277
|
+
}
|
|
278
|
+
) });
|
|
279
|
+
}
|
|
280
|
+
var NodeCardHeader = React.forwardRef(
|
|
281
|
+
({ icon, appName, accentKey }, ref) => {
|
|
282
|
+
const accent = nodeAccent(accentKey);
|
|
283
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: "flex items-center gap-2.5 px-3 pb-3 pt-4", children: [
|
|
284
|
+
/* @__PURE__ */ jsx(
|
|
285
|
+
"div",
|
|
286
|
+
{
|
|
287
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-lg",
|
|
288
|
+
style: {
|
|
289
|
+
backgroundColor: tint(accent, 13),
|
|
290
|
+
color: accent,
|
|
291
|
+
border: `1px solid ${tint(accent, 26)}`
|
|
292
|
+
},
|
|
293
|
+
children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-[18px]" })
|
|
294
|
+
}
|
|
295
|
+
),
|
|
296
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: appName })
|
|
297
|
+
] });
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
NodeCardHeader.displayName = "NodeCardHeader";
|
|
301
|
+
var NodeCardBody = React.forwardRef(
|
|
302
|
+
({ operationName, description }, ref) => /* @__PURE__ */ jsxs(
|
|
303
|
+
"div",
|
|
304
|
+
{
|
|
305
|
+
ref,
|
|
306
|
+
className: "rounded-b-xl border-t border-border/60 px-3 pb-3 pt-2.5",
|
|
307
|
+
children: [
|
|
308
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: "Operation" }),
|
|
309
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 truncate font-mono text-[13px] font-bold text-card-foreground", children: operationName }),
|
|
310
|
+
description ? /* @__PURE__ */ jsx("p", { className: "mt-1 line-clamp-2 text-xs leading-snug text-muted-foreground", children: description }) : null
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
)
|
|
314
|
+
);
|
|
315
|
+
NodeCardBody.displayName = "NodeCardBody";
|
|
67
316
|
function CustomHandle({
|
|
68
317
|
className,
|
|
69
318
|
isConnectable,
|
|
@@ -105,7 +354,259 @@ function CustomHandle({
|
|
|
105
354
|
} : void 0,
|
|
106
355
|
...props
|
|
107
356
|
}
|
|
108
|
-
) });
|
|
357
|
+
) });
|
|
358
|
+
}
|
|
359
|
+
var TONE_COLORS = {
|
|
360
|
+
success: "var(--color-status-success-text)",
|
|
361
|
+
error: "var(--color-status-error-text)",
|
|
362
|
+
warning: "var(--color-status-warning-text)",
|
|
363
|
+
info: "#3b82f6",
|
|
364
|
+
neutral: "var(--muted-foreground, #6b7280)"
|
|
365
|
+
};
|
|
366
|
+
function isDynamicSpec(spec) {
|
|
367
|
+
return !!spec && !Array.isArray(spec) && typeof spec.fromStateRecord === "string";
|
|
368
|
+
}
|
|
369
|
+
var DEFAULT_HANDLES = [{ id: "source", label: "" }];
|
|
370
|
+
function resolveOutputHandles(data) {
|
|
371
|
+
const nodeData = data?.nodeData;
|
|
372
|
+
const spec = nodeData?.outputHandles ?? nodeData?.operations?.outputHandles;
|
|
373
|
+
if (!spec) return DEFAULT_HANDLES;
|
|
374
|
+
if (isDynamicSpec(spec)) {
|
|
375
|
+
const args = data?.args;
|
|
376
|
+
const record = args?.state?.[spec.fromStateRecord] ?? data?.[spec.fromStateRecord] ?? {};
|
|
377
|
+
const dynamic = Object.entries(record).filter(([, handleId]) => typeof handleId === "string" && handleId).map(([label, handleId]) => ({ id: handleId, label }));
|
|
378
|
+
return [...dynamic, ...spec.extra ?? []];
|
|
379
|
+
}
|
|
380
|
+
if (spec.length === 0) return DEFAULT_HANDLES;
|
|
381
|
+
return spec;
|
|
382
|
+
}
|
|
383
|
+
function OutputHandles({
|
|
384
|
+
nodeId,
|
|
385
|
+
handles,
|
|
386
|
+
accent,
|
|
387
|
+
isConnectable
|
|
388
|
+
}) {
|
|
389
|
+
const updateNodeInternals = useUpdateNodeInternals();
|
|
390
|
+
const signature = useMemo(
|
|
391
|
+
() => handles.map((h) => h.id).join("|"),
|
|
392
|
+
[handles]
|
|
393
|
+
);
|
|
394
|
+
useEffect(() => {
|
|
395
|
+
updateNodeInternals(nodeId);
|
|
396
|
+
}, [nodeId, signature, updateNodeInternals]);
|
|
397
|
+
if (handles.length === 1) {
|
|
398
|
+
const handle = handles[0];
|
|
399
|
+
return /* @__PURE__ */ jsx(
|
|
400
|
+
CustomHandle,
|
|
401
|
+
{
|
|
402
|
+
type: "source",
|
|
403
|
+
id: handle.id,
|
|
404
|
+
position: Position.Right,
|
|
405
|
+
isConnectable,
|
|
406
|
+
accent: handle.tone ? TONE_COLORS[handle.tone] : accent
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
const total = handles.length;
|
|
411
|
+
return /* @__PURE__ */ jsx(Fragment, { children: handles.map((handle, index) => {
|
|
412
|
+
const top = `${(index + 1) / (total + 1) * 100}%`;
|
|
413
|
+
const color = handle.tone ? TONE_COLORS[handle.tone] : accent;
|
|
414
|
+
return /* @__PURE__ */ jsxs(
|
|
415
|
+
"div",
|
|
416
|
+
{
|
|
417
|
+
className: "absolute right-0",
|
|
418
|
+
style: { top, transform: "translateY(-50%)" },
|
|
419
|
+
children: [
|
|
420
|
+
/* @__PURE__ */ jsx(
|
|
421
|
+
CustomHandle,
|
|
422
|
+
{
|
|
423
|
+
type: "source",
|
|
424
|
+
id: handle.id,
|
|
425
|
+
position: Position.Right,
|
|
426
|
+
isConnectable,
|
|
427
|
+
accent: color
|
|
428
|
+
}
|
|
429
|
+
),
|
|
430
|
+
handle.label && /* @__PURE__ */ jsx(
|
|
431
|
+
"span",
|
|
432
|
+
{
|
|
433
|
+
className: "pointer-events-none absolute whitespace-nowrap text-[10px] font-medium leading-none",
|
|
434
|
+
style: {
|
|
435
|
+
color,
|
|
436
|
+
left: "100%",
|
|
437
|
+
marginLeft: 16,
|
|
438
|
+
top: "50%",
|
|
439
|
+
transform: "translateY(-50%)"
|
|
440
|
+
},
|
|
441
|
+
title: handle.label,
|
|
442
|
+
children: handle.label
|
|
443
|
+
}
|
|
444
|
+
)
|
|
445
|
+
]
|
|
446
|
+
},
|
|
447
|
+
handle.id
|
|
448
|
+
);
|
|
449
|
+
}) });
|
|
450
|
+
}
|
|
451
|
+
var DEFAULT_INPUT_HANDLES = [{ id: "target", label: "" }];
|
|
452
|
+
function resolveInputHandles(data) {
|
|
453
|
+
const nodeData = data?.nodeData;
|
|
454
|
+
const spec = nodeData?.inputHandles ?? nodeData?.operations?.inputHandles;
|
|
455
|
+
if (!Array.isArray(spec) || spec.length === 0) return DEFAULT_INPUT_HANDLES;
|
|
456
|
+
return spec;
|
|
457
|
+
}
|
|
458
|
+
function InputHandles({
|
|
459
|
+
nodeId,
|
|
460
|
+
handles,
|
|
461
|
+
accent,
|
|
462
|
+
isConnectable
|
|
463
|
+
}) {
|
|
464
|
+
const updateNodeInternals = useUpdateNodeInternals();
|
|
465
|
+
const signature = useMemo(
|
|
466
|
+
() => handles.map((h) => h.id).join("|"),
|
|
467
|
+
[handles]
|
|
468
|
+
);
|
|
469
|
+
useEffect(() => {
|
|
470
|
+
updateNodeInternals(nodeId);
|
|
471
|
+
}, [nodeId, signature, updateNodeInternals]);
|
|
472
|
+
if (handles.length === 1) {
|
|
473
|
+
const handle = handles[0];
|
|
474
|
+
return /* @__PURE__ */ jsx(
|
|
475
|
+
CustomHandle,
|
|
476
|
+
{
|
|
477
|
+
type: "target",
|
|
478
|
+
id: handle.id,
|
|
479
|
+
position: Position.Left,
|
|
480
|
+
isConnectable,
|
|
481
|
+
accent: handle.tone ? TONE_COLORS[handle.tone] : accent
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
const total = handles.length;
|
|
486
|
+
return /* @__PURE__ */ jsx(Fragment, { children: handles.map((handle, index) => {
|
|
487
|
+
const top = `${(index + 1) / (total + 1) * 100}%`;
|
|
488
|
+
const color = handle.tone ? TONE_COLORS[handle.tone] : accent;
|
|
489
|
+
return /* @__PURE__ */ jsxs(
|
|
490
|
+
"div",
|
|
491
|
+
{
|
|
492
|
+
className: "absolute left-0",
|
|
493
|
+
style: { top, transform: "translateY(-50%)" },
|
|
494
|
+
children: [
|
|
495
|
+
/* @__PURE__ */ jsx(
|
|
496
|
+
CustomHandle,
|
|
497
|
+
{
|
|
498
|
+
type: "target",
|
|
499
|
+
id: handle.id,
|
|
500
|
+
position: Position.Left,
|
|
501
|
+
isConnectable,
|
|
502
|
+
accent: color
|
|
503
|
+
}
|
|
504
|
+
),
|
|
505
|
+
handle.label && /* @__PURE__ */ jsx(
|
|
506
|
+
"span",
|
|
507
|
+
{
|
|
508
|
+
className: "pointer-events-none absolute whitespace-nowrap text-[10px] font-medium leading-none",
|
|
509
|
+
style: {
|
|
510
|
+
color,
|
|
511
|
+
right: "100%",
|
|
512
|
+
marginRight: 16,
|
|
513
|
+
top: "50%",
|
|
514
|
+
transform: "translateY(-50%)"
|
|
515
|
+
},
|
|
516
|
+
title: handle.label,
|
|
517
|
+
children: handle.label
|
|
518
|
+
}
|
|
519
|
+
)
|
|
520
|
+
]
|
|
521
|
+
},
|
|
522
|
+
handle.id
|
|
523
|
+
);
|
|
524
|
+
}) });
|
|
525
|
+
}
|
|
526
|
+
function outputHandlesSpacerHeight(count2) {
|
|
527
|
+
return count2 > 2 ? (count2 - 2) * 26 : 0;
|
|
528
|
+
}
|
|
529
|
+
function LogicNodeCard({
|
|
530
|
+
title,
|
|
531
|
+
subtitle,
|
|
532
|
+
icon,
|
|
533
|
+
accent,
|
|
534
|
+
selected,
|
|
535
|
+
executionStatus,
|
|
536
|
+
itemCount,
|
|
537
|
+
isTrigger,
|
|
538
|
+
isExecuting,
|
|
539
|
+
nodeId,
|
|
540
|
+
inputHandles,
|
|
541
|
+
outputHandles,
|
|
542
|
+
isConnectable,
|
|
543
|
+
onDoubleClick,
|
|
544
|
+
onSettings,
|
|
545
|
+
onExecute,
|
|
546
|
+
onDelete,
|
|
547
|
+
infoButton
|
|
548
|
+
}) {
|
|
549
|
+
const minHeight = Math.max(
|
|
550
|
+
64,
|
|
551
|
+
Math.max(outputHandles.length, inputHandles.length) * 30 + 24
|
|
552
|
+
);
|
|
553
|
+
return /* @__PURE__ */ jsxs(
|
|
554
|
+
NodeCard,
|
|
555
|
+
{
|
|
556
|
+
className: "w-48",
|
|
557
|
+
"data-selected": selected,
|
|
558
|
+
selected,
|
|
559
|
+
onDoubleClick,
|
|
560
|
+
executionStatus,
|
|
561
|
+
itemCount,
|
|
562
|
+
isTrigger,
|
|
563
|
+
accent,
|
|
564
|
+
isExecuting,
|
|
565
|
+
onSettings,
|
|
566
|
+
onExecute,
|
|
567
|
+
onDelete,
|
|
568
|
+
infoButton,
|
|
569
|
+
children: [
|
|
570
|
+
/* @__PURE__ */ jsxs(
|
|
571
|
+
"div",
|
|
572
|
+
{
|
|
573
|
+
className: "flex flex-col items-center justify-center gap-1 px-3 py-3 text-center",
|
|
574
|
+
style: { minHeight },
|
|
575
|
+
children: [
|
|
576
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-9 items-center justify-center rounded-lg bg-muted", children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-5", style: { color: accent } }) }),
|
|
577
|
+
/* @__PURE__ */ jsx("span", { className: "max-w-full truncate text-sm font-semibold leading-tight", children: title }),
|
|
578
|
+
subtitle && /* @__PURE__ */ jsx(
|
|
579
|
+
"span",
|
|
580
|
+
{
|
|
581
|
+
className: "max-w-full truncate font-mono text-[10px] text-muted-foreground",
|
|
582
|
+
title: subtitle,
|
|
583
|
+
children: subtitle
|
|
584
|
+
}
|
|
585
|
+
)
|
|
586
|
+
]
|
|
587
|
+
}
|
|
588
|
+
),
|
|
589
|
+
/* @__PURE__ */ jsx(
|
|
590
|
+
InputHandles,
|
|
591
|
+
{
|
|
592
|
+
nodeId,
|
|
593
|
+
handles: inputHandles,
|
|
594
|
+
accent,
|
|
595
|
+
isConnectable
|
|
596
|
+
}
|
|
597
|
+
),
|
|
598
|
+
/* @__PURE__ */ jsx(
|
|
599
|
+
OutputHandles,
|
|
600
|
+
{
|
|
601
|
+
nodeId,
|
|
602
|
+
handles: outputHandles,
|
|
603
|
+
accent,
|
|
604
|
+
isConnectable
|
|
605
|
+
}
|
|
606
|
+
)
|
|
607
|
+
]
|
|
608
|
+
}
|
|
609
|
+
);
|
|
109
610
|
}
|
|
110
611
|
|
|
111
612
|
// src/modules/ui-blocks/registry.ts
|
|
@@ -173,27 +674,27 @@ function ExpressionEditor({
|
|
|
173
674
|
"button",
|
|
174
675
|
{
|
|
175
676
|
type: "button",
|
|
176
|
-
onClick: () => insertTemplate("{
|
|
677
|
+
onClick: () => insertTemplate("${TriggerInput.}"),
|
|
177
678
|
className: "text-xs px-2 py-0.5 rounded bg-primary/10 text-primary hover:bg-primary/20 transition-colors",
|
|
178
|
-
children: "{
|
|
679
|
+
children: "${TriggerInput}"
|
|
179
680
|
}
|
|
180
681
|
),
|
|
181
682
|
/* @__PURE__ */ jsx(
|
|
182
683
|
"button",
|
|
183
684
|
{
|
|
184
685
|
type: "button",
|
|
185
|
-
onClick: () => insertTemplate("{
|
|
686
|
+
onClick: () => insertTemplate("${output.}"),
|
|
186
687
|
className: "text-xs px-2 py-0.5 rounded bg-primary/10 text-primary hover:bg-primary/20 transition-colors",
|
|
187
|
-
children: "{
|
|
688
|
+
children: "${output}"
|
|
188
689
|
}
|
|
189
690
|
),
|
|
190
691
|
/* @__PURE__ */ jsx(
|
|
191
692
|
"button",
|
|
192
693
|
{
|
|
193
694
|
type: "button",
|
|
194
|
-
onClick: () => insertTemplate("{
|
|
695
|
+
onClick: () => insertTemplate("${WorkflowState[''].output}"),
|
|
195
696
|
className: "text-xs px-2 py-0.5 rounded bg-primary/10 text-primary hover:bg-primary/20 transition-colors",
|
|
196
|
-
children: "{
|
|
697
|
+
children: "${WorkflowState}"
|
|
197
698
|
}
|
|
198
699
|
)
|
|
199
700
|
] }),
|
|
@@ -7744,279 +8245,30 @@ function NodePropertyPanel({
|
|
|
7744
8245
|
onChange: handleConnectionsChange,
|
|
7745
8246
|
compact: true
|
|
7746
8247
|
}
|
|
7747
|
-
)
|
|
7748
|
-
] }),
|
|
7749
|
-
hasAutoManagedConnections && visibleConnectionAdapters.length === 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: [
|
|
7750
|
-
/* @__PURE__ */ jsx(Icon, { icon: "mdi:shield-check", className: "mt-0.5 h-4 w-4 shrink-0" }),
|
|
7751
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7752
|
-
/* @__PURE__ */ jsx("div", { className: "font-medium text-card-foreground", children: "Connection handled automatically" }),
|
|
7753
|
-
/* @__PURE__ */ jsx("div", { children: "This node uses the workspace BigConsole app connection at run time. You only need to configure the DataSink target below." })
|
|
7754
|
-
] })
|
|
7755
|
-
] }),
|
|
7756
|
-
/* @__PURE__ */ jsxs("div", { className: "flex pt-5 flex-col", children: [
|
|
7757
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs text-card-foreground/60 font-semibold", children: "Properties" }),
|
|
7758
|
-
resolvedUi ? /* @__PURE__ */ jsx(
|
|
7759
|
-
BlocksRenderer,
|
|
7760
|
-
{
|
|
7761
|
-
spec: resolvedUi.spec,
|
|
7762
|
-
synthesized: resolvedUi.synthesized,
|
|
7763
|
-
state: sampleData2,
|
|
7764
|
-
onApply: submittedData
|
|
7765
|
-
},
|
|
7766
|
-
`${id}:${data?.operation_name ?? ""}`
|
|
7767
|
-
) : /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground py-2", children: "No Properties" })
|
|
7768
|
-
] })
|
|
7769
|
-
] });
|
|
7770
|
-
}
|
|
7771
|
-
var BRAND_ACCENTS = [
|
|
7772
|
-
[/gmail|google/, "#ea4335"],
|
|
7773
|
-
[/slack/, "#611f69"],
|
|
7774
|
-
[/github/, "#334155"],
|
|
7775
|
-
[/gitlab/, "#fc6d26"],
|
|
7776
|
-
[/stripe/, "#635bff"],
|
|
7777
|
-
[/discord/, "#5865f2"],
|
|
7778
|
-
[/notion/, "#111827"],
|
|
7779
|
-
[/telegram/, "#2aabee"],
|
|
7780
|
-
[/whatsapp/, "#25d366"],
|
|
7781
|
-
[/openai/, "#10a37f"],
|
|
7782
|
-
[/anthropic|claude/, "#d97757"],
|
|
7783
|
-
[/twilio/, "#f22f46"],
|
|
7784
|
-
[/sheet|excel/, "#21a366"],
|
|
7785
|
-
[/http|api|webhook|rest/, "#6366f1"],
|
|
7786
|
-
[/db|sql|postgres|mysql|mongo/, "#0ea5e9"]
|
|
7787
|
-
];
|
|
7788
|
-
var HASH_PALETTE = [
|
|
7789
|
-
"#6366f1",
|
|
7790
|
-
"#0ea5e9",
|
|
7791
|
-
"#10b981",
|
|
7792
|
-
"#f59e0b",
|
|
7793
|
-
"#ef4444",
|
|
7794
|
-
"#a855f7",
|
|
7795
|
-
"#ec4899",
|
|
7796
|
-
"#14b8a6",
|
|
7797
|
-
"#f97316",
|
|
7798
|
-
"#8b5cf6"
|
|
7799
|
-
];
|
|
7800
|
-
function nodeAccent(key) {
|
|
7801
|
-
const k = (key || "").toLowerCase();
|
|
7802
|
-
for (const [re, hex] of BRAND_ACCENTS) if (re.test(k)) return hex;
|
|
7803
|
-
let h = 0;
|
|
7804
|
-
for (let i = 0; i < k.length; i++) h = h * 31 + k.charCodeAt(i) >>> 0;
|
|
7805
|
-
return HASH_PALETTE[h % HASH_PALETTE.length];
|
|
7806
|
-
}
|
|
7807
|
-
function tint(hex, pct = 14) {
|
|
7808
|
-
return `color-mix(in srgb, ${hex} ${pct}%, transparent)`;
|
|
7809
|
-
}
|
|
7810
|
-
var NodeCard = React2.forwardRef(
|
|
7811
|
-
({
|
|
7812
|
-
className,
|
|
7813
|
-
selected = false,
|
|
7814
|
-
executionStatus = "idle",
|
|
7815
|
-
itemCount,
|
|
7816
|
-
isTrigger = false,
|
|
7817
|
-
accent = "#3b82f6",
|
|
7818
|
-
onSettings,
|
|
7819
|
-
onExecute,
|
|
7820
|
-
onDelete,
|
|
7821
|
-
isExecuting = false,
|
|
7822
|
-
infoButton,
|
|
7823
|
-
children,
|
|
7824
|
-
...props
|
|
7825
|
-
}, ref) => {
|
|
7826
|
-
const [hovered, setHovered] = React2.useState(false);
|
|
7827
|
-
const statusRing = executionStatus === "running" ? "ring-2 ring-[var(--color-status-success-border)] animate-pulse-border" : executionStatus === "success" ? "ring-2 ring-[var(--color-status-success-border)]" : executionStatus === "error" ? "ring-2 ring-[var(--color-status-error-border)]" : "";
|
|
7828
|
-
return /* @__PURE__ */ jsxs(
|
|
7829
|
-
"div",
|
|
7830
|
-
{
|
|
7831
|
-
className: "group/node relative",
|
|
7832
|
-
onMouseEnter: () => setHovered(true),
|
|
7833
|
-
onMouseLeave: () => setHovered(false),
|
|
7834
|
-
children: [
|
|
7835
|
-
itemCount !== void 0 && itemCount > 0 && /* @__PURE__ */ jsx("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 z-10", children: /* @__PURE__ */ jsxs("div", { className: "rounded-full border border-border bg-card px-2 py-0.5 text-[10px] font-medium text-muted-foreground shadow-sm", children: [
|
|
7836
|
-
itemCount,
|
|
7837
|
-
" item",
|
|
7838
|
-
itemCount !== 1 ? "s" : ""
|
|
7839
|
-
] }) }),
|
|
7840
|
-
(onSettings || onExecute || onDelete || infoButton) && /* @__PURE__ */ jsxs(
|
|
7841
|
-
"div",
|
|
7842
|
-
{
|
|
7843
|
-
className: cn(
|
|
7844
|
-
"absolute right-1 z-20 flex items-center gap-0.5 rounded-lg border border-border bg-card p-0.5 shadow-md transition-all duration-150",
|
|
7845
|
-
hovered ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0"
|
|
7846
|
-
),
|
|
7847
|
-
style: {
|
|
7848
|
-
// Inline offset (not a `-top-*` class) so it survives the host
|
|
7849
|
-
// app's Tailwind scan of fe-sdk source, which drops some spacing
|
|
7850
|
-
// utilities. The toolbar is ~30px tall; top:-15px centers it on
|
|
7851
|
-
// the card's top edge (half outside, half over the card).
|
|
7852
|
-
top: -15,
|
|
7853
|
-
transform: hovered ? "translateY(0)" : "translateY(4px)"
|
|
7854
|
-
},
|
|
7855
|
-
onDoubleClick: (e) => e.stopPropagation(),
|
|
7856
|
-
children: [
|
|
7857
|
-
onSettings && /* @__PURE__ */ jsx(ToolbarButton, { title: "Configure", onClick: onSettings, children: /* @__PURE__ */ jsx(Icon, { icon: "lucide:sliders-horizontal", className: "size-4" }) }),
|
|
7858
|
-
onExecute && /* @__PURE__ */ jsx(
|
|
7859
|
-
ToolbarButton,
|
|
7860
|
-
{
|
|
7861
|
-
title: "Execute step",
|
|
7862
|
-
onClick: onExecute,
|
|
7863
|
-
disabled: isExecuting,
|
|
7864
|
-
children: isExecuting ? /* @__PURE__ */ jsx(
|
|
7865
|
-
Icon,
|
|
7866
|
-
{
|
|
7867
|
-
icon: "svg-spinners:ring-resize",
|
|
7868
|
-
className: "size-4 text-[var(--color-status-success-text)]"
|
|
7869
|
-
}
|
|
7870
|
-
) : /* @__PURE__ */ jsx(
|
|
7871
|
-
Icon,
|
|
7872
|
-
{
|
|
7873
|
-
icon: "mdi:play",
|
|
7874
|
-
className: "size-4 text-[var(--color-status-success-text)]"
|
|
7875
|
-
}
|
|
7876
|
-
)
|
|
7877
|
-
}
|
|
7878
|
-
),
|
|
7879
|
-
infoButton,
|
|
7880
|
-
onDelete && /* @__PURE__ */ jsx(ToolbarButton, { title: "Delete", onClick: onDelete, children: /* @__PURE__ */ jsx(
|
|
7881
|
-
Icon,
|
|
7882
|
-
{
|
|
7883
|
-
icon: "mynaui:trash",
|
|
7884
|
-
className: "size-4 text-[var(--color-status-error-text)]"
|
|
7885
|
-
}
|
|
7886
|
-
) })
|
|
7887
|
-
]
|
|
7888
|
-
}
|
|
7889
|
-
),
|
|
7890
|
-
/* @__PURE__ */ jsxs(
|
|
7891
|
-
"div",
|
|
7892
|
-
{
|
|
7893
|
-
ref,
|
|
7894
|
-
"data-selected": selected,
|
|
7895
|
-
className: cn(
|
|
7896
|
-
"relative w-72 rounded-xl border border-border bg-card shadow-sm will-change-transform",
|
|
7897
|
-
statusRing,
|
|
7898
|
-
executionStatus === "success" && "animate-success-glow",
|
|
7899
|
-
className
|
|
7900
|
-
),
|
|
7901
|
-
style: {
|
|
7902
|
-
borderTop: `3px solid ${accent}`,
|
|
7903
|
-
transition: "transform 0.15s ease, box-shadow 0.15s ease",
|
|
7904
|
-
transform: hovered ? "translateY(-2px)" : "none",
|
|
7905
|
-
boxShadow: hovered ? "0 2px 4px rgba(16,24,40,0.06), 0 16px 34px -12px rgba(16,24,40,0.24)" : void 0
|
|
7906
|
-
},
|
|
7907
|
-
...props,
|
|
7908
|
-
children: [
|
|
7909
|
-
/* @__PURE__ */ jsx(
|
|
7910
|
-
"div",
|
|
7911
|
-
{
|
|
7912
|
-
className: "pointer-events-none absolute -inset-0.5 transition-opacity duration-150",
|
|
7913
|
-
style: {
|
|
7914
|
-
borderRadius: 14,
|
|
7915
|
-
opacity: selected || hovered ? 1 : 0,
|
|
7916
|
-
boxShadow: selected ? `0 0 0 2px ${accent}, 0 0 0 5px ${tint(accent, 18)}` : `0 0 0 2px ${accent}`
|
|
7917
|
-
}
|
|
7918
|
-
}
|
|
7919
|
-
),
|
|
7920
|
-
isTrigger && /* @__PURE__ */ jsx(
|
|
7921
|
-
"div",
|
|
7922
|
-
{
|
|
7923
|
-
className: "absolute -top-2 -left-2 z-10 flex size-5 items-center justify-center rounded-full shadow-md ring-2 ring-card",
|
|
7924
|
-
style: { backgroundColor: "var(--color-status-success-text)" },
|
|
7925
|
-
children: /* @__PURE__ */ jsx(
|
|
7926
|
-
Icon,
|
|
7927
|
-
{
|
|
7928
|
-
icon: "mdi:lightning-bolt",
|
|
7929
|
-
className: "size-3",
|
|
7930
|
-
style: { color: "var(--color-status-success-text-inverse)" }
|
|
7931
|
-
}
|
|
7932
|
-
)
|
|
7933
|
-
}
|
|
7934
|
-
),
|
|
7935
|
-
children
|
|
7936
|
-
]
|
|
7937
|
-
}
|
|
7938
|
-
),
|
|
7939
|
-
executionStatus === "success" && /* @__PURE__ */ jsx(StatusCorner, { icon: "mdi:check", tone: "success" }),
|
|
7940
|
-
executionStatus === "error" && /* @__PURE__ */ jsx(StatusCorner, { icon: "mdi:close", tone: "error" }),
|
|
7941
|
-
executionStatus === "running" && /* @__PURE__ */ jsx(StatusCorner, { icon: "svg-spinners:ring-resize", tone: "success" })
|
|
7942
|
-
]
|
|
7943
|
-
}
|
|
7944
|
-
);
|
|
7945
|
-
}
|
|
7946
|
-
);
|
|
7947
|
-
NodeCard.displayName = "NodeCard";
|
|
7948
|
-
function ToolbarButton({
|
|
7949
|
-
title,
|
|
7950
|
-
onClick,
|
|
7951
|
-
disabled,
|
|
7952
|
-
children
|
|
7953
|
-
}) {
|
|
7954
|
-
return /* @__PURE__ */ jsx(
|
|
7955
|
-
"button",
|
|
7956
|
-
{
|
|
7957
|
-
type: "button",
|
|
7958
|
-
title,
|
|
7959
|
-
disabled,
|
|
7960
|
-
onClick: (e) => {
|
|
7961
|
-
e.stopPropagation();
|
|
7962
|
-
onClick?.();
|
|
7963
|
-
},
|
|
7964
|
-
className: "flex size-6 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50",
|
|
7965
|
-
children
|
|
7966
|
-
}
|
|
7967
|
-
);
|
|
7968
|
-
}
|
|
7969
|
-
function StatusCorner({
|
|
7970
|
-
icon,
|
|
7971
|
-
tone
|
|
7972
|
-
}) {
|
|
7973
|
-
const bg = tone === "success" ? "var(--color-status-success-bg)" : "var(--color-status-error-bg)";
|
|
7974
|
-
const fg = tone === "success" ? "var(--color-status-success-text-inverse)" : "var(--color-status-error-text-inverse)";
|
|
7975
|
-
return /* @__PURE__ */ jsx("div", { className: "absolute -bottom-1.5 -right-1.5 z-10", children: /* @__PURE__ */ jsx(
|
|
7976
|
-
"div",
|
|
7977
|
-
{
|
|
7978
|
-
className: "rounded-full p-0.5 shadow-md animate-in zoom-in duration-200",
|
|
7979
|
-
style: { backgroundColor: bg },
|
|
7980
|
-
children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-3", style: { color: fg } })
|
|
7981
|
-
}
|
|
7982
|
-
) });
|
|
7983
|
-
}
|
|
7984
|
-
var NodeCardHeader = React2.forwardRef(
|
|
7985
|
-
({ icon, appName, accentKey }, ref) => {
|
|
7986
|
-
const accent = nodeAccent(accentKey);
|
|
7987
|
-
return /* @__PURE__ */ jsxs("div", { ref, className: "flex items-center gap-2.5 px-3 pb-3 pt-4", children: [
|
|
7988
|
-
/* @__PURE__ */ jsx(
|
|
7989
|
-
"div",
|
|
7990
|
-
{
|
|
7991
|
-
className: "flex size-8 shrink-0 items-center justify-center rounded-lg",
|
|
7992
|
-
style: {
|
|
7993
|
-
backgroundColor: tint(accent, 13),
|
|
7994
|
-
color: accent,
|
|
7995
|
-
border: `1px solid ${tint(accent, 26)}`
|
|
7996
|
-
},
|
|
7997
|
-
children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-[18px]" })
|
|
7998
|
-
}
|
|
7999
|
-
),
|
|
8000
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: appName })
|
|
8001
|
-
] });
|
|
8002
|
-
}
|
|
8003
|
-
);
|
|
8004
|
-
NodeCardHeader.displayName = "NodeCardHeader";
|
|
8005
|
-
var NodeCardBody = React2.forwardRef(
|
|
8006
|
-
({ operationName, description }, ref) => /* @__PURE__ */ jsxs(
|
|
8007
|
-
"div",
|
|
8008
|
-
{
|
|
8009
|
-
ref,
|
|
8010
|
-
className: "rounded-b-xl border-t border-border/60 px-3 pb-3 pt-2.5",
|
|
8011
|
-
children: [
|
|
8012
|
-
/* @__PURE__ */ jsx("div", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: "Operation" }),
|
|
8013
|
-
/* @__PURE__ */ jsx("div", { className: "mt-0.5 truncate font-mono text-[13px] font-bold text-card-foreground", children: operationName }),
|
|
8014
|
-
description ? /* @__PURE__ */ jsx("p", { className: "mt-1 line-clamp-2 text-xs leading-snug text-muted-foreground", children: description }) : null
|
|
8015
|
-
]
|
|
8016
|
-
}
|
|
8017
|
-
)
|
|
8018
|
-
);
|
|
8019
|
-
NodeCardBody.displayName = "NodeCardBody";
|
|
8248
|
+
)
|
|
8249
|
+
] }),
|
|
8250
|
+
hasAutoManagedConnections && visibleConnectionAdapters.length === 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: [
|
|
8251
|
+
/* @__PURE__ */ jsx(Icon, { icon: "mdi:shield-check", className: "mt-0.5 h-4 w-4 shrink-0" }),
|
|
8252
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8253
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-card-foreground", children: "Connection handled automatically" }),
|
|
8254
|
+
/* @__PURE__ */ jsx("div", { children: "This node uses the workspace BigConsole app connection at run time. You only need to configure the DataSink target below." })
|
|
8255
|
+
] })
|
|
8256
|
+
] }),
|
|
8257
|
+
/* @__PURE__ */ jsxs("div", { className: "flex pt-5 flex-col", children: [
|
|
8258
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-card-foreground/60 font-semibold", children: "Properties" }),
|
|
8259
|
+
resolvedUi ? /* @__PURE__ */ jsx(
|
|
8260
|
+
BlocksRenderer,
|
|
8261
|
+
{
|
|
8262
|
+
spec: resolvedUi.spec,
|
|
8263
|
+
synthesized: resolvedUi.synthesized,
|
|
8264
|
+
state: sampleData2,
|
|
8265
|
+
onApply: submittedData
|
|
8266
|
+
},
|
|
8267
|
+
`${id}:${data?.operation_name ?? ""}`
|
|
8268
|
+
) : /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground py-2", children: "No Properties" })
|
|
8269
|
+
] })
|
|
8270
|
+
] });
|
|
8271
|
+
}
|
|
8020
8272
|
var nodeDetails = {
|
|
8021
8273
|
node_type: "gmail_reader",
|
|
8022
8274
|
version: "1.0.0",
|
|
@@ -8885,6 +9137,65 @@ var getNodeMetadata = (value) => {
|
|
|
8885
9137
|
(value?.type || "").toLowerCase()
|
|
8886
9138
|
);
|
|
8887
9139
|
const roleAccent = isTrigger ? "#10b981" : isLogicNode ? "#f59e0b" : "#3b82f6";
|
|
9140
|
+
const outputHandles = resolveOutputHandles(
|
|
9141
|
+
data
|
|
9142
|
+
);
|
|
9143
|
+
const inputHandles = resolveInputHandles(
|
|
9144
|
+
data
|
|
9145
|
+
);
|
|
9146
|
+
const handleSpacer = outputHandlesSpacerHeight(
|
|
9147
|
+
Math.max(outputHandles.length, inputHandles.length)
|
|
9148
|
+
);
|
|
9149
|
+
const manifestKind = data?.nodeData?.kind;
|
|
9150
|
+
const isControlFlowNode = (value?.type || "").startsWith("internal:") && (Array.isArray(manifestKind) ? manifestKind.includes("control") : isLogicNode);
|
|
9151
|
+
if (isControlFlowNode) {
|
|
9152
|
+
const argsState = data?.args?.state;
|
|
9153
|
+
const rules = argsState?.rules;
|
|
9154
|
+
const mode = argsState?.mode;
|
|
9155
|
+
const logicSubtitle = Array.isArray(rules) ? `${rules.length} rule${rules.length === 1 ? "" : "s"}` : typeof mode === "string" ? mode : void 0;
|
|
9156
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
9157
|
+
/* @__PURE__ */ jsx(
|
|
9158
|
+
LogicNodeCard,
|
|
9159
|
+
{
|
|
9160
|
+
nodeId: id,
|
|
9161
|
+
title: data?.label || meta.title,
|
|
9162
|
+
subtitle: logicSubtitle,
|
|
9163
|
+
icon: meta.icon,
|
|
9164
|
+
accent: roleAccent,
|
|
9165
|
+
selected: !!selected,
|
|
9166
|
+
executionStatus,
|
|
9167
|
+
itemCount,
|
|
9168
|
+
isTrigger,
|
|
9169
|
+
isExecuting: isThisNodeExecuting,
|
|
9170
|
+
inputHandles,
|
|
9171
|
+
outputHandles,
|
|
9172
|
+
isConnectable: typeof isConnectable === "boolean" ? isConnectable : void 0,
|
|
9173
|
+
onDoubleClick: handleOpenNdv,
|
|
9174
|
+
onSettings: handleShowNodeProperties,
|
|
9175
|
+
onExecute: handleExecuteStep,
|
|
9176
|
+
onDelete: handleDeleteNode,
|
|
9177
|
+
infoButton: /* @__PURE__ */ jsx(
|
|
9178
|
+
NodeInfoButtonWithModal,
|
|
9179
|
+
{
|
|
9180
|
+
metadata: {
|
|
9181
|
+
icon: meta.icon,
|
|
9182
|
+
title: meta.title,
|
|
9183
|
+
description: nodeDescription,
|
|
9184
|
+
gradientColor: meta.gradientColor
|
|
9185
|
+
}
|
|
9186
|
+
}
|
|
9187
|
+
)
|
|
9188
|
+
}
|
|
9189
|
+
),
|
|
9190
|
+
/* @__PURE__ */ jsx(
|
|
9191
|
+
AdapterConnectors,
|
|
9192
|
+
{
|
|
9193
|
+
nodeId: id,
|
|
9194
|
+
adapters: data?.nodeData?.nodeAdapters
|
|
9195
|
+
}
|
|
9196
|
+
)
|
|
9197
|
+
] });
|
|
9198
|
+
}
|
|
8888
9199
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
8889
9200
|
/* @__PURE__ */ jsxs(
|
|
8890
9201
|
NodeCard,
|
|
@@ -8920,31 +9231,34 @@ var getNodeMetadata = (value) => {
|
|
|
8920
9231
|
accentKey: value?.type || meta.title
|
|
8921
9232
|
}
|
|
8922
9233
|
),
|
|
8923
|
-
|
|
9234
|
+
operationDisplay === "execute" && (value?.type || "").startsWith("internal:") ? (
|
|
9235
|
+
// Internal single-op nodes: 'execute' is an implementation detail,
|
|
9236
|
+
// not a user choice — show only the description.
|
|
9237
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-b-xl border-t border-border/60 px-3 pb-3 pt-2.5", children: /* @__PURE__ */ jsx("p", { className: "line-clamp-2 text-xs leading-snug text-muted-foreground", children: nodeDescription }) })
|
|
9238
|
+
) : /* @__PURE__ */ jsx(
|
|
8924
9239
|
NodeCardBody,
|
|
8925
9240
|
{
|
|
8926
9241
|
operationName: operationDisplay,
|
|
8927
9242
|
description: nodeDescription
|
|
8928
9243
|
}
|
|
8929
9244
|
),
|
|
9245
|
+
handleSpacer > 0 && /* @__PURE__ */ jsx("div", { style: { height: handleSpacer } }),
|
|
8930
9246
|
/* @__PURE__ */ jsx(
|
|
8931
|
-
|
|
9247
|
+
InputHandles,
|
|
8932
9248
|
{
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
isConnectable
|
|
8937
|
-
accent: roleAccent
|
|
9249
|
+
nodeId: id,
|
|
9250
|
+
handles: inputHandles,
|
|
9251
|
+
accent: roleAccent,
|
|
9252
|
+
isConnectable: typeof isConnectable === "boolean" ? isConnectable : void 0
|
|
8938
9253
|
}
|
|
8939
9254
|
),
|
|
8940
9255
|
/* @__PURE__ */ jsx(
|
|
8941
|
-
|
|
9256
|
+
OutputHandles,
|
|
8942
9257
|
{
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
isConnectable
|
|
8947
|
-
accent: roleAccent
|
|
9258
|
+
nodeId: id,
|
|
9259
|
+
handles: outputHandles,
|
|
9260
|
+
accent: roleAccent,
|
|
9261
|
+
isConnectable: typeof isConnectable === "boolean" ? isConnectable : void 0
|
|
8948
9262
|
}
|
|
8949
9263
|
)
|
|
8950
9264
|
]
|
|
@@ -12490,7 +12804,7 @@ function TemplateCard({
|
|
|
12490
12804
|
onClick,
|
|
12491
12805
|
onUseTemplate
|
|
12492
12806
|
}) {
|
|
12493
|
-
const [imageError, setImageError] =
|
|
12807
|
+
const [imageError, setImageError] = React__default.useState(false);
|
|
12494
12808
|
const previewImage = template.screenshots?.[0] || template.icon || void 0;
|
|
12495
12809
|
const hasPreview = Boolean(previewImage) && !imageError;
|
|
12496
12810
|
const handleUseTemplate = (e) => {
|
|
@@ -13350,7 +13664,7 @@ function ThemeProvider2({
|
|
|
13350
13664
|
defaultTheme = "system",
|
|
13351
13665
|
storageKey = "vite-ui-theme"
|
|
13352
13666
|
}) {
|
|
13353
|
-
|
|
13667
|
+
React.useEffect(() => {
|
|
13354
13668
|
if (typeof window !== "undefined") {
|
|
13355
13669
|
try {
|
|
13356
13670
|
localStorage.removeItem(storageKey);
|
|
@@ -14270,8 +14584,8 @@ function toast5({ ...props }) {
|
|
|
14270
14584
|
};
|
|
14271
14585
|
}
|
|
14272
14586
|
function useToast() {
|
|
14273
|
-
const [state, setState] =
|
|
14274
|
-
|
|
14587
|
+
const [state, setState] = React.useState(memoryState);
|
|
14588
|
+
React.useEffect(() => {
|
|
14275
14589
|
listeners.push(setState);
|
|
14276
14590
|
return () => {
|
|
14277
14591
|
const index = listeners.indexOf(setState);
|
|
@@ -19290,6 +19604,9 @@ function buildOperationSeed(type, operationName, existingData) {
|
|
|
19290
19604
|
if (!op) return null;
|
|
19291
19605
|
const manifest = config2.defaultData?.nodeData;
|
|
19292
19606
|
const prevArgs = existingData.args ?? {};
|
|
19607
|
+
const manifestOps = manifest?.operations;
|
|
19608
|
+
const outputHandles = manifest?.outputHandles ?? manifestOps?.outputHandles;
|
|
19609
|
+
const inputHandles = manifest?.inputHandles ?? manifestOps?.inputHandles;
|
|
19293
19610
|
return {
|
|
19294
19611
|
...existingData,
|
|
19295
19612
|
operation_name: op.name,
|
|
@@ -19300,7 +19617,12 @@ function buildOperationSeed(type, operationName, existingData) {
|
|
|
19300
19617
|
state: { ...op.adaptive_card?.defaultValue ?? {} }
|
|
19301
19618
|
},
|
|
19302
19619
|
// Slim manifest: keep node-level metadata but only the pinned operation.
|
|
19303
|
-
nodeData: {
|
|
19620
|
+
nodeData: {
|
|
19621
|
+
...manifest ?? {},
|
|
19622
|
+
...outputHandles !== void 0 ? { outputHandles } : {},
|
|
19623
|
+
...inputHandles !== void 0 ? { inputHandles } : {},
|
|
19624
|
+
operations: [op]
|
|
19625
|
+
}
|
|
19304
19626
|
};
|
|
19305
19627
|
}
|
|
19306
19628
|
function useInsertNode() {
|
|
@@ -19320,10 +19642,18 @@ function useInsertNode() {
|
|
|
19320
19642
|
position: _pos,
|
|
19321
19643
|
selected: true
|
|
19322
19644
|
});
|
|
19323
|
-
|
|
19645
|
+
let pinTo = operationName;
|
|
19646
|
+
if (!pinTo) {
|
|
19647
|
+
const config2 = NODE_CONFIGS.find((c) => c.type === type);
|
|
19648
|
+
const ops = config2?.operations ?? [];
|
|
19649
|
+
if (ops.length === 1 && ops[0]?.name) {
|
|
19650
|
+
pinTo = ops[0].name;
|
|
19651
|
+
}
|
|
19652
|
+
}
|
|
19653
|
+
if (pinTo) {
|
|
19324
19654
|
const seeded = buildOperationSeed(
|
|
19325
19655
|
type,
|
|
19326
|
-
|
|
19656
|
+
pinTo,
|
|
19327
19657
|
newNode.data ?? {}
|
|
19328
19658
|
);
|
|
19329
19659
|
if (seeded) newNode.data = seeded;
|
|
@@ -20907,6 +21237,449 @@ function FieldTree({
|
|
|
20907
21237
|
field.path
|
|
20908
21238
|
)) });
|
|
20909
21239
|
}
|
|
21240
|
+
function emptyGroup() {
|
|
21241
|
+
return { type: "group", combinator: "AND", children: [] };
|
|
21242
|
+
}
|
|
21243
|
+
function emptyRule(field = "") {
|
|
21244
|
+
return { type: "rule", field, operator: "==", value: "" };
|
|
21245
|
+
}
|
|
21246
|
+
var OPERATORS2 = {
|
|
21247
|
+
string: [
|
|
21248
|
+
{ value: "==", label: "equals", needsValue: true },
|
|
21249
|
+
{ value: "!=", label: "not equals", needsValue: true },
|
|
21250
|
+
{ value: "contains", label: "contains", needsValue: true },
|
|
21251
|
+
{ value: "notContains", label: "does not contain", needsValue: true },
|
|
21252
|
+
{ value: "startsWith", label: "starts with", needsValue: true },
|
|
21253
|
+
{ value: "endsWith", label: "ends with", needsValue: true },
|
|
21254
|
+
{ value: "regex", label: "matches regex", needsValue: true },
|
|
21255
|
+
{ value: "isEmpty", label: "is empty", needsValue: false },
|
|
21256
|
+
{ value: "isNotEmpty", label: "is not empty", needsValue: false },
|
|
21257
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21258
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21259
|
+
],
|
|
21260
|
+
number: [
|
|
21261
|
+
{ value: "==", label: "equals", needsValue: true },
|
|
21262
|
+
{ value: "!=", label: "not equals", needsValue: true },
|
|
21263
|
+
{ value: ">", label: "greater than", needsValue: true },
|
|
21264
|
+
{ value: ">=", label: "greater or equal", needsValue: true },
|
|
21265
|
+
{ value: "<", label: "less than", needsValue: true },
|
|
21266
|
+
{ value: "<=", label: "less or equal", needsValue: true },
|
|
21267
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21268
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21269
|
+
],
|
|
21270
|
+
boolean: [
|
|
21271
|
+
{ value: "isTrue", label: "is true", needsValue: false },
|
|
21272
|
+
{ value: "isFalse", label: "is false", needsValue: false },
|
|
21273
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21274
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21275
|
+
],
|
|
21276
|
+
array: [
|
|
21277
|
+
{ value: "contains", label: "contains", needsValue: true },
|
|
21278
|
+
{ value: "notContains", label: "does not contain", needsValue: true },
|
|
21279
|
+
{ value: "isEmpty", label: "is empty", needsValue: false },
|
|
21280
|
+
{ value: "isNotEmpty", label: "is not empty", needsValue: false },
|
|
21281
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21282
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21283
|
+
],
|
|
21284
|
+
object: [
|
|
21285
|
+
{ value: "hasProperty", label: "has property", needsValue: true },
|
|
21286
|
+
{ value: "isEmpty", label: "is empty", needsValue: false },
|
|
21287
|
+
{ value: "isNotEmpty", label: "is not empty", needsValue: false },
|
|
21288
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21289
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21290
|
+
],
|
|
21291
|
+
any: [
|
|
21292
|
+
{ value: "==", label: "equals", needsValue: true },
|
|
21293
|
+
{ value: "!=", label: "not equals", needsValue: true },
|
|
21294
|
+
{ value: ">", label: "greater than", needsValue: true },
|
|
21295
|
+
{ value: "<", label: "less than", needsValue: true },
|
|
21296
|
+
{ value: "contains", label: "contains", needsValue: true },
|
|
21297
|
+
{ value: "isEmpty", label: "is empty", needsValue: false },
|
|
21298
|
+
{ value: "isNotEmpty", label: "is not empty", needsValue: false },
|
|
21299
|
+
{ value: "isNull", label: "is null", needsValue: false },
|
|
21300
|
+
{ value: "isNotNull", label: "is not null", needsValue: false }
|
|
21301
|
+
]
|
|
21302
|
+
};
|
|
21303
|
+
function operatorsFor(type) {
|
|
21304
|
+
return OPERATORS2[type ?? "any"] ?? OPERATORS2.any;
|
|
21305
|
+
}
|
|
21306
|
+
function flattenFields(nodes) {
|
|
21307
|
+
const out = [];
|
|
21308
|
+
const walk = (list) => {
|
|
21309
|
+
for (const node of list) {
|
|
21310
|
+
if (node.path) out.push({ path: node.path, type: node.type ?? "any" });
|
|
21311
|
+
if (Array.isArray(node.children)) walk(node.children);
|
|
21312
|
+
}
|
|
21313
|
+
};
|
|
21314
|
+
walk(nodes);
|
|
21315
|
+
return out.sort((a, b) => a.path.localeCompare(b.path));
|
|
21316
|
+
}
|
|
21317
|
+
var rowInput = "rounded-md border border-input bg-background px-2 py-1 text-xs outline-none focus:border-primary";
|
|
21318
|
+
function RuleRow({
|
|
21319
|
+
rule,
|
|
21320
|
+
fields,
|
|
21321
|
+
onChange,
|
|
21322
|
+
onRemove
|
|
21323
|
+
}) {
|
|
21324
|
+
const fieldType = fields.find((f) => f.path === rule.field)?.type ?? "any";
|
|
21325
|
+
const ops = operatorsFor(fieldType);
|
|
21326
|
+
const currentOp = ops.find((o) => o.value === rule.operator) ?? ops[0];
|
|
21327
|
+
const knownField = fields.some((f) => f.path === rule.field);
|
|
21328
|
+
return /* @__PURE__ */ jsxs(
|
|
21329
|
+
"div",
|
|
21330
|
+
{
|
|
21331
|
+
className: "flex flex-wrap items-center gap-1.5",
|
|
21332
|
+
"data-testid": "condition-rule",
|
|
21333
|
+
children: [
|
|
21334
|
+
fields.length > 0 && (knownField || rule.field === "") ? /* @__PURE__ */ jsxs(
|
|
21335
|
+
"select",
|
|
21336
|
+
{
|
|
21337
|
+
value: rule.field,
|
|
21338
|
+
onChange: (e) => {
|
|
21339
|
+
const nextField = e.target.value;
|
|
21340
|
+
const nextType = fields.find((f) => f.path === nextField)?.type ?? "any";
|
|
21341
|
+
const nextOps = operatorsFor(nextType);
|
|
21342
|
+
const operator = nextOps.some((o) => o.value === rule.operator) ? rule.operator : nextOps[0].value;
|
|
21343
|
+
onChange({ ...rule, field: nextField, operator });
|
|
21344
|
+
},
|
|
21345
|
+
className: cn(rowInput, "max-w-[180px] flex-1"),
|
|
21346
|
+
"data-testid": "condition-field",
|
|
21347
|
+
children: [
|
|
21348
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select field\u2026" }),
|
|
21349
|
+
fields.map((f) => /* @__PURE__ */ jsxs("option", { value: f.path, children: [
|
|
21350
|
+
f.path,
|
|
21351
|
+
" (",
|
|
21352
|
+
f.type,
|
|
21353
|
+
")"
|
|
21354
|
+
] }, f.path)),
|
|
21355
|
+
/* @__PURE__ */ jsx("option", { value: "__custom__", children: "Custom path\u2026" })
|
|
21356
|
+
]
|
|
21357
|
+
}
|
|
21358
|
+
) : /* @__PURE__ */ jsx(
|
|
21359
|
+
"input",
|
|
21360
|
+
{
|
|
21361
|
+
type: "text",
|
|
21362
|
+
value: rule.field === "__custom__" ? "" : rule.field,
|
|
21363
|
+
placeholder: "field.path",
|
|
21364
|
+
onChange: (e) => onChange({ ...rule, field: e.target.value }),
|
|
21365
|
+
className: cn(rowInput, "max-w-[180px] flex-1 font-mono"),
|
|
21366
|
+
"data-testid": "condition-field"
|
|
21367
|
+
}
|
|
21368
|
+
),
|
|
21369
|
+
/* @__PURE__ */ jsx(
|
|
21370
|
+
"select",
|
|
21371
|
+
{
|
|
21372
|
+
value: currentOp.value,
|
|
21373
|
+
onChange: (e) => onChange({ ...rule, operator: e.target.value }),
|
|
21374
|
+
className: rowInput,
|
|
21375
|
+
"data-testid": "condition-operator",
|
|
21376
|
+
children: ops.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
21377
|
+
}
|
|
21378
|
+
),
|
|
21379
|
+
currentOp.needsValue && /* @__PURE__ */ jsx(
|
|
21380
|
+
"input",
|
|
21381
|
+
{
|
|
21382
|
+
type: fieldType === "number" ? "number" : "text",
|
|
21383
|
+
value: rule.value === null || rule.value === void 0 ? "" : String(rule.value),
|
|
21384
|
+
placeholder: "value",
|
|
21385
|
+
onChange: (e) => {
|
|
21386
|
+
const raw = e.target.value;
|
|
21387
|
+
const value = fieldType === "number" && raw.trim() !== "" && !Number.isNaN(Number(raw)) ? Number(raw) : raw;
|
|
21388
|
+
onChange({ ...rule, value });
|
|
21389
|
+
},
|
|
21390
|
+
className: cn(rowInput, "min-w-[90px] flex-1"),
|
|
21391
|
+
"data-testid": "condition-value"
|
|
21392
|
+
}
|
|
21393
|
+
),
|
|
21394
|
+
/* @__PURE__ */ jsx(
|
|
21395
|
+
"button",
|
|
21396
|
+
{
|
|
21397
|
+
type: "button",
|
|
21398
|
+
onClick: onRemove,
|
|
21399
|
+
title: "Remove condition",
|
|
21400
|
+
className: "rounded p-1 text-muted-foreground hover:text-[var(--color-status-error-text)]",
|
|
21401
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:trash", className: "size-3.5" })
|
|
21402
|
+
}
|
|
21403
|
+
)
|
|
21404
|
+
]
|
|
21405
|
+
}
|
|
21406
|
+
);
|
|
21407
|
+
}
|
|
21408
|
+
function GroupEditor({
|
|
21409
|
+
group,
|
|
21410
|
+
fields,
|
|
21411
|
+
depth,
|
|
21412
|
+
onChange,
|
|
21413
|
+
onRemove
|
|
21414
|
+
}) {
|
|
21415
|
+
const setChild = (index, child) => {
|
|
21416
|
+
const children = group.children.slice();
|
|
21417
|
+
children[index] = child;
|
|
21418
|
+
onChange({ ...group, children });
|
|
21419
|
+
};
|
|
21420
|
+
const removeChild = (index) => {
|
|
21421
|
+
onChange({
|
|
21422
|
+
...group,
|
|
21423
|
+
children: group.children.filter((_, i) => i !== index)
|
|
21424
|
+
});
|
|
21425
|
+
};
|
|
21426
|
+
return /* @__PURE__ */ jsxs(
|
|
21427
|
+
"div",
|
|
21428
|
+
{
|
|
21429
|
+
className: cn(
|
|
21430
|
+
"flex flex-col gap-1.5 rounded-md",
|
|
21431
|
+
depth > 0 && "border border-border/70 bg-muted/20 p-2"
|
|
21432
|
+
),
|
|
21433
|
+
"data-testid": `condition-group-depth-${depth}`,
|
|
21434
|
+
children: [
|
|
21435
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
21436
|
+
/* @__PURE__ */ jsx("div", { className: "flex overflow-hidden rounded-md border border-input text-[10px] font-semibold", children: ["AND", "OR"].map((c) => /* @__PURE__ */ jsx(
|
|
21437
|
+
"button",
|
|
21438
|
+
{
|
|
21439
|
+
type: "button",
|
|
21440
|
+
onClick: () => onChange({ ...group, combinator: c }),
|
|
21441
|
+
className: cn(
|
|
21442
|
+
"px-2 py-0.5",
|
|
21443
|
+
group.combinator === c ? "bg-primary text-primary-foreground" : "bg-background text-muted-foreground hover:text-foreground"
|
|
21444
|
+
),
|
|
21445
|
+
"data-testid": `combinator-${c}`,
|
|
21446
|
+
children: c
|
|
21447
|
+
},
|
|
21448
|
+
c
|
|
21449
|
+
)) }),
|
|
21450
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: group.combinator === "AND" ? "all conditions must match" : "any condition may match" }),
|
|
21451
|
+
onRemove && /* @__PURE__ */ jsx(
|
|
21452
|
+
"button",
|
|
21453
|
+
{
|
|
21454
|
+
type: "button",
|
|
21455
|
+
onClick: onRemove,
|
|
21456
|
+
title: "Remove group",
|
|
21457
|
+
className: "ml-auto rounded p-1 text-muted-foreground hover:text-[var(--color-status-error-text)]",
|
|
21458
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:trash", className: "size-3.5" })
|
|
21459
|
+
}
|
|
21460
|
+
)
|
|
21461
|
+
] }),
|
|
21462
|
+
group.children.map(
|
|
21463
|
+
(child, index) => child.type === "rule" ? /* @__PURE__ */ jsx(
|
|
21464
|
+
RuleRow,
|
|
21465
|
+
{
|
|
21466
|
+
rule: child,
|
|
21467
|
+
fields,
|
|
21468
|
+
onChange: (next) => setChild(index, next),
|
|
21469
|
+
onRemove: () => removeChild(index)
|
|
21470
|
+
},
|
|
21471
|
+
index
|
|
21472
|
+
) : /* @__PURE__ */ jsx(
|
|
21473
|
+
GroupEditor,
|
|
21474
|
+
{
|
|
21475
|
+
group: child,
|
|
21476
|
+
fields,
|
|
21477
|
+
depth: depth + 1,
|
|
21478
|
+
onChange: (next) => setChild(index, next),
|
|
21479
|
+
onRemove: () => removeChild(index)
|
|
21480
|
+
},
|
|
21481
|
+
index
|
|
21482
|
+
)
|
|
21483
|
+
),
|
|
21484
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
21485
|
+
/* @__PURE__ */ jsxs(
|
|
21486
|
+
"button",
|
|
21487
|
+
{
|
|
21488
|
+
type: "button",
|
|
21489
|
+
onClick: () => onChange({
|
|
21490
|
+
...group,
|
|
21491
|
+
children: [...group.children, emptyRule(fields[0]?.path ?? "")]
|
|
21492
|
+
}),
|
|
21493
|
+
className: "flex items-center gap-1 text-[11px] font-medium text-primary hover:underline",
|
|
21494
|
+
"data-testid": "add-condition",
|
|
21495
|
+
children: [
|
|
21496
|
+
/* @__PURE__ */ jsx(Icon, { icon: "basil:add-solid", className: "size-3.5" }),
|
|
21497
|
+
" Add condition"
|
|
21498
|
+
]
|
|
21499
|
+
}
|
|
21500
|
+
),
|
|
21501
|
+
depth < 2 && /* @__PURE__ */ jsxs(
|
|
21502
|
+
"button",
|
|
21503
|
+
{
|
|
21504
|
+
type: "button",
|
|
21505
|
+
onClick: () => onChange({
|
|
21506
|
+
...group,
|
|
21507
|
+
children: [...group.children, emptyGroup()]
|
|
21508
|
+
}),
|
|
21509
|
+
className: "flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground",
|
|
21510
|
+
"data-testid": "add-group",
|
|
21511
|
+
children: [
|
|
21512
|
+
/* @__PURE__ */ jsx(Icon, { icon: "basil:add-solid", className: "size-3.5" }),
|
|
21513
|
+
" Add group"
|
|
21514
|
+
]
|
|
21515
|
+
}
|
|
21516
|
+
)
|
|
21517
|
+
] })
|
|
21518
|
+
]
|
|
21519
|
+
}
|
|
21520
|
+
);
|
|
21521
|
+
}
|
|
21522
|
+
function ConditionTreeBuilder({
|
|
21523
|
+
value,
|
|
21524
|
+
fields,
|
|
21525
|
+
onChange
|
|
21526
|
+
}) {
|
|
21527
|
+
const tree = value && typeof value === "object" && value.type === "group" ? value : emptyGroup();
|
|
21528
|
+
return /* @__PURE__ */ jsx("div", { "data-testid": "condition-tree-builder", children: /* @__PURE__ */ jsx(
|
|
21529
|
+
GroupEditor,
|
|
21530
|
+
{
|
|
21531
|
+
group: tree,
|
|
21532
|
+
fields,
|
|
21533
|
+
depth: 0,
|
|
21534
|
+
onChange: (next) => onChange(next.children.length === 0 ? void 0 : next)
|
|
21535
|
+
}
|
|
21536
|
+
) });
|
|
21537
|
+
}
|
|
21538
|
+
function newRuleHandle(existing) {
|
|
21539
|
+
let n = existing.length;
|
|
21540
|
+
const taken = new Set(existing.map((r) => r.handle));
|
|
21541
|
+
let handle = `rule-${n}`;
|
|
21542
|
+
while (taken.has(handle)) handle = `rule-${++n}`;
|
|
21543
|
+
return handle;
|
|
21544
|
+
}
|
|
21545
|
+
function casesFromRules(rules) {
|
|
21546
|
+
const cases = {};
|
|
21547
|
+
rules.forEach((rule, index) => {
|
|
21548
|
+
cases[rule.name || `Rule ${index + 1}`] = rule.handle;
|
|
21549
|
+
});
|
|
21550
|
+
return cases;
|
|
21551
|
+
}
|
|
21552
|
+
function SwitchRulesEditor({
|
|
21553
|
+
rules,
|
|
21554
|
+
fallbackHandle,
|
|
21555
|
+
fields,
|
|
21556
|
+
onChange
|
|
21557
|
+
}) {
|
|
21558
|
+
const setRule = (index, rule) => {
|
|
21559
|
+
const next = rules.slice();
|
|
21560
|
+
next[index] = rule;
|
|
21561
|
+
onChange({ rules: next, fallbackHandle });
|
|
21562
|
+
};
|
|
21563
|
+
const move = (index, dir) => {
|
|
21564
|
+
const target = index + dir;
|
|
21565
|
+
if (target < 0 || target >= rules.length) return;
|
|
21566
|
+
const next = rules.slice();
|
|
21567
|
+
const tmp = next[index];
|
|
21568
|
+
next[index] = next[target];
|
|
21569
|
+
next[target] = tmp;
|
|
21570
|
+
onChange({ rules: next, fallbackHandle });
|
|
21571
|
+
};
|
|
21572
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", "data-testid": "switch-rules-editor", children: [
|
|
21573
|
+
rules.map((rule, index) => /* @__PURE__ */ jsxs(
|
|
21574
|
+
"div",
|
|
21575
|
+
{
|
|
21576
|
+
className: "rounded-md border border-border/70 bg-muted/10 p-2",
|
|
21577
|
+
"data-testid": `switch-rule-${index}`,
|
|
21578
|
+
children: [
|
|
21579
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-1.5 flex items-center gap-1.5", children: [
|
|
21580
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[10px] font-semibold text-muted-foreground", children: [
|
|
21581
|
+
index + 1,
|
|
21582
|
+
"."
|
|
21583
|
+
] }),
|
|
21584
|
+
/* @__PURE__ */ jsx(
|
|
21585
|
+
"input",
|
|
21586
|
+
{
|
|
21587
|
+
type: "text",
|
|
21588
|
+
value: rule.name,
|
|
21589
|
+
placeholder: `Rule ${index + 1}`,
|
|
21590
|
+
onChange: (e) => setRule(index, { ...rule, name: e.target.value }),
|
|
21591
|
+
className: cn(rowInput, "flex-1 font-medium"),
|
|
21592
|
+
"data-testid": "switch-rule-name"
|
|
21593
|
+
}
|
|
21594
|
+
),
|
|
21595
|
+
/* @__PURE__ */ jsx(
|
|
21596
|
+
"button",
|
|
21597
|
+
{
|
|
21598
|
+
type: "button",
|
|
21599
|
+
onClick: () => move(index, -1),
|
|
21600
|
+
disabled: index === 0,
|
|
21601
|
+
title: "Move up",
|
|
21602
|
+
className: "rounded p-0.5 text-muted-foreground hover:text-foreground disabled:opacity-30",
|
|
21603
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:chevron-up", className: "size-4" })
|
|
21604
|
+
}
|
|
21605
|
+
),
|
|
21606
|
+
/* @__PURE__ */ jsx(
|
|
21607
|
+
"button",
|
|
21608
|
+
{
|
|
21609
|
+
type: "button",
|
|
21610
|
+
onClick: () => move(index, 1),
|
|
21611
|
+
disabled: index === rules.length - 1,
|
|
21612
|
+
title: "Move down",
|
|
21613
|
+
className: "rounded p-0.5 text-muted-foreground hover:text-foreground disabled:opacity-30",
|
|
21614
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:chevron-down", className: "size-4" })
|
|
21615
|
+
}
|
|
21616
|
+
),
|
|
21617
|
+
/* @__PURE__ */ jsx(
|
|
21618
|
+
"button",
|
|
21619
|
+
{
|
|
21620
|
+
type: "button",
|
|
21621
|
+
onClick: () => onChange({
|
|
21622
|
+
rules: rules.filter((_, i) => i !== index),
|
|
21623
|
+
fallbackHandle
|
|
21624
|
+
}),
|
|
21625
|
+
title: "Remove rule",
|
|
21626
|
+
className: "rounded p-0.5 text-muted-foreground hover:text-[var(--color-status-error-text)]",
|
|
21627
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:trash", className: "size-3.5" })
|
|
21628
|
+
}
|
|
21629
|
+
)
|
|
21630
|
+
] }),
|
|
21631
|
+
/* @__PURE__ */ jsx(
|
|
21632
|
+
ConditionTreeBuilder,
|
|
21633
|
+
{
|
|
21634
|
+
value: rule.conditionTree,
|
|
21635
|
+
fields,
|
|
21636
|
+
onChange: (tree) => setRule(index, { ...rule, conditionTree: tree ?? emptyGroup() })
|
|
21637
|
+
}
|
|
21638
|
+
)
|
|
21639
|
+
]
|
|
21640
|
+
},
|
|
21641
|
+
rule.handle
|
|
21642
|
+
)),
|
|
21643
|
+
/* @__PURE__ */ jsxs(
|
|
21644
|
+
"button",
|
|
21645
|
+
{
|
|
21646
|
+
type: "button",
|
|
21647
|
+
onClick: () => onChange({
|
|
21648
|
+
rules: [
|
|
21649
|
+
...rules,
|
|
21650
|
+
{
|
|
21651
|
+
name: `Rule ${rules.length + 1}`,
|
|
21652
|
+
handle: newRuleHandle(rules),
|
|
21653
|
+
conditionTree: emptyGroup()
|
|
21654
|
+
}
|
|
21655
|
+
],
|
|
21656
|
+
fallbackHandle
|
|
21657
|
+
}),
|
|
21658
|
+
className: "flex w-fit items-center gap-1 text-[11px] font-medium text-primary hover:underline",
|
|
21659
|
+
"data-testid": "add-switch-rule",
|
|
21660
|
+
children: [
|
|
21661
|
+
/* @__PURE__ */ jsx(Icon, { icon: "basil:add-solid", className: "size-3.5" }),
|
|
21662
|
+
" Add rule"
|
|
21663
|
+
]
|
|
21664
|
+
}
|
|
21665
|
+
),
|
|
21666
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2", children: [
|
|
21667
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: "Fallback output (no rule matches):" }),
|
|
21668
|
+
/* @__PURE__ */ jsx(
|
|
21669
|
+
"input",
|
|
21670
|
+
{
|
|
21671
|
+
type: "text",
|
|
21672
|
+
value: fallbackHandle,
|
|
21673
|
+
placeholder: "default",
|
|
21674
|
+
onChange: (e) => onChange({ rules, fallbackHandle: e.target.value }),
|
|
21675
|
+
className: cn(rowInput, "w-28"),
|
|
21676
|
+
"data-testid": "switch-fallback"
|
|
21677
|
+
}
|
|
21678
|
+
)
|
|
21679
|
+
] }),
|
|
21680
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] leading-snug text-muted-foreground", children: "Rules are checked top-down; the first matching rule routes the item to its output. Each rule renders as an output handle on the node." })
|
|
21681
|
+
] });
|
|
21682
|
+
}
|
|
20910
21683
|
function coerceNumber(type, raw) {
|
|
20911
21684
|
if (raw.trim() === "") return void 0;
|
|
20912
21685
|
const n = type === "integer" ? parseInt(raw, 10) : parseFloat(raw);
|
|
@@ -21036,6 +21809,7 @@ function NodeDetailView() {
|
|
|
21036
21809
|
[currentOp]
|
|
21037
21810
|
);
|
|
21038
21811
|
const params = useMemo(() => paramsFromOperation(currentOp), [currentOp]);
|
|
21812
|
+
const pickerFields = useMemo(() => flattenFields(inputFields), [inputFields]);
|
|
21039
21813
|
const mapping = currentEdge?.mapping?.definition ?? {};
|
|
21040
21814
|
const argsState = useMemo(() => {
|
|
21041
21815
|
const data = asRecord(node?.data);
|
|
@@ -21284,6 +22058,40 @@ function NodeDetailView() {
|
|
|
21284
22058
|
] }),
|
|
21285
22059
|
!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." }),
|
|
21286
22060
|
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) => {
|
|
22061
|
+
if (p.type === "condition") {
|
|
22062
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
22063
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name === "conditionTree" ? "Conditions" : p.name }),
|
|
22064
|
+
/* @__PURE__ */ jsx(
|
|
22065
|
+
ConditionTreeBuilder,
|
|
22066
|
+
{
|
|
22067
|
+
value: argsState[p.name],
|
|
22068
|
+
fields: pickerFields,
|
|
22069
|
+
onChange: (tree) => writeFixed(p.name, tree)
|
|
22070
|
+
}
|
|
22071
|
+
),
|
|
22072
|
+
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
22073
|
+
] }, p.name);
|
|
22074
|
+
}
|
|
22075
|
+
if (p.type === "switch-rules") {
|
|
22076
|
+
const rules = Array.isArray(argsState[p.name]) ? argsState[p.name] : [];
|
|
22077
|
+
const fallbackHandle = typeof argsState.fallbackHandle === "string" ? argsState.fallbackHandle : "default";
|
|
22078
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
22079
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: "Routing rules" }),
|
|
22080
|
+
/* @__PURE__ */ jsx(
|
|
22081
|
+
SwitchRulesEditor,
|
|
22082
|
+
{
|
|
22083
|
+
rules,
|
|
22084
|
+
fallbackHandle,
|
|
22085
|
+
fields: pickerFields,
|
|
22086
|
+
onChange: (next) => {
|
|
22087
|
+
writeFixed(p.name, next.rules);
|
|
22088
|
+
writeFixed("cases", casesFromRules(next.rules));
|
|
22089
|
+
writeFixed("fallbackHandle", next.fallbackHandle);
|
|
22090
|
+
}
|
|
22091
|
+
}
|
|
22092
|
+
)
|
|
22093
|
+
] }, p.name);
|
|
22094
|
+
}
|
|
21287
22095
|
const mode = modeByField[p.name] ?? (mapping[p.name] !== void 0 ? "expression" : "fixed");
|
|
21288
22096
|
const exprValue = mapping[p.name] ?? "";
|
|
21289
22097
|
const fixedValue = argsState[p.name];
|
|
@@ -22221,5 +23029,5 @@ function WorkflowBuilder() {
|
|
|
22221
23029
|
}
|
|
22222
23030
|
|
|
22223
23031
|
export { Card2 as Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConfigSchemaForm, ConnectionFormDialog, ConnectionSelector, FluidGridsProvider, ProviderPicker, TemplateCard, WorkflowBuilder, getProviderForm, listCustomBlocks, refetchStoreNodes, registerCustomBlock, resolveUiSpec, stripSubmitActions, useConnection, useConnectionDialog, useConnections, useConnectionsByProvider, useCreateConnection, useFluidGridsContext, useImportWorkflowTemplate, useInitiateOAuth, useNodeExecution, useProviderByKey, useProviderCatalog, useProviders, useWorkflowTemplates };
|
|
22224
|
-
//# sourceMappingURL=chunk-
|
|
22225
|
-
//# sourceMappingURL=chunk-
|
|
23032
|
+
//# sourceMappingURL=chunk-HNN7T6G6.js.map
|
|
23033
|
+
//# sourceMappingURL=chunk-HNN7T6G6.js.map
|