@burdenoff/fluidgrids-fe-sdk 2026.702.1 → 2026.703.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,11 +14,11 @@ import { useParams, useNavigate } from 'react-router-dom';
14
14
  import { useShallow, shallow } from 'zustand/shallow';
15
15
  import * as React2 from 'react';
16
16
  import React2__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, useNodeId, ReactFlowProvider, ReactFlow, Background, useOnSelectionChange, MiniMap, getSmoothStepPath, EdgeLabelRenderer, getOutgoers, useNodes, useNodesState, useEdgesState, addEdge, Controls, Panel } from '@xyflow/react';
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';
18
18
  import { produce } from 'immer';
19
19
  import { nanoid } from 'nanoid/non-secure';
20
20
  import { cn } from '@burdenoff/fe-libs/utils';
21
- import { Textarea, Input, Button, Card, Badge, CardContent as CardContent$1, Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, 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';
21
+ 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
22
  import { Icon } from '@iconify/react';
23
23
  import * as AdaptiveCards from 'adaptivecards';
24
24
  import { formatDistanceToNow } from 'date-fns';
@@ -41,27 +41,6 @@ import { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';
41
41
  function ThemeProvider({ children }) {
42
42
  return /* @__PURE__ */ jsx(ThemeProvider$1, { children });
43
43
  }
44
-
45
- // src/builder/components/flow-builder/components/blocks/types.ts
46
- var HeaderGradientColors = {
47
- purple: "from-purple-700",
48
- red: "from-red-700",
49
- blue: "from-blue-700",
50
- green: "from-green-700",
51
- yellow: "from-yellow-700",
52
- pink: "from-pink-700",
53
- orange: "from-orange-700",
54
- teal: "from-teal-700",
55
- lime: "from-lime-700",
56
- indigo: "from-indigo-700",
57
- fuchsia: "from-fuchsia-700",
58
- emerald: "from-emerald-700",
59
- cyan: "from-cyan-700",
60
- rose: "from-rose-700",
61
- sky: "from-sky-700",
62
- gray: "from-gray-200",
63
- slate: "from-slate-700"
64
- };
65
44
  function useDeleteNode() {
66
45
  const { getNode, getEdges, deleteElements } = useReactFlow();
67
46
  const [deleteNode, deleteEdge] = useFlowStore(
@@ -88,6 +67,7 @@ function useDeleteNode() {
88
67
  function CustomHandle({
89
68
  className,
90
69
  isConnectable,
70
+ accent,
91
71
  ...props
92
72
  }) {
93
73
  const { nodeLookup, edges } = useStore(({ nodeLookup: nodeLookup2, edges: edges2 }) => ({
@@ -110,11 +90,19 @@ function CustomHandle({
110
90
  Handle,
111
91
  {
112
92
  className: cn(
113
- "cursor-crosshair",
114
- "size-3 hover:border-primary/50 border-2 border-card-foreground/40",
93
+ "cursor-crosshair transition-transform hover:scale-110",
94
+ !accent && "size-3 border-2 border-card-foreground/40 hover:border-primary/50",
115
95
  className
116
96
  ),
117
97
  isConnectable: isHandleConnectable,
98
+ style: accent ? {
99
+ width: 14,
100
+ height: 14,
101
+ borderRadius: "50%",
102
+ background: "var(--card, #fff)",
103
+ border: `2.5px solid ${accent}`,
104
+ boxShadow: `0 0 0 3px color-mix(in srgb, ${accent} 12%, transparent)`
105
+ } : void 0,
118
106
  ...props
119
107
  }
120
108
  ) });
@@ -7780,12 +7768,255 @@ function NodePropertyPanel({
7780
7768
  ] })
7781
7769
  ] });
7782
7770
  }
7783
- var HeaderWithIcon = ({ icon, title }) => {
7784
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
7785
- /* @__PURE__ */ jsx(Icon, { icon, className: `size-4` }),
7786
- /* @__PURE__ */ jsx("div", { className: "ml-2.5 flex items-center text-xs font-medium leading-none tracking-wide uppercase opacity-80", children: /* @__PURE__ */ jsx("span", { className: "translate-y-px", children: title }) })
7787
- ] });
7788
- };
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";
7789
8020
  var nodeDetails = {
7790
8021
  node_type: "gmail_reader",
7791
8022
  version: "1.0.0",
@@ -8000,212 +8231,6 @@ function NodeInfoButtonWithModal({
8000
8231
  ] })
8001
8232
  ] });
8002
8233
  }
8003
- var NodeCard = React2.forwardRef(
8004
- ({ className, executionStatus = "idle", itemCount, children, ...props }, ref) => {
8005
- const statusClasses = {
8006
- idle: "",
8007
- running: "ring-2 ring-[var(--color-status-success-border)] animate-pulse-border",
8008
- success: "ring-2 ring-[var(--color-status-success-border)]",
8009
- error: "ring-2 ring-[var(--color-status-error-border)]"
8010
- };
8011
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
8012
- itemCount !== void 0 && itemCount > 0 && /* @__PURE__ */ jsx("div", { className: "absolute -top-6 left-1/2 -translate-x-1/2 z-10", children: /* @__PURE__ */ jsxs("div", { className: "bg-card border border-card-foreground/20 px-2 py-0.5 rounded text-[10px] text-card-foreground/70 whitespace-nowrap shadow-sm", children: [
8013
- itemCount,
8014
- " item",
8015
- itemCount !== 1 ? "s" : ""
8016
- ] }) }),
8017
- /* @__PURE__ */ jsx(
8018
- "div",
8019
- {
8020
- ref,
8021
- className: cn(
8022
- "w-72 border border-card-foreground/10 rounded-sm bg-card/50 shadow-sm backdrop-blur-xl transition-all duration-200 divide-y divide-card-foreground/10 data-[selected=true]:border-border-primary hover:border-border-primary",
8023
- statusClasses[executionStatus],
8024
- executionStatus === "success" && "animate-success-glow",
8025
- className
8026
- ),
8027
- ...props,
8028
- children
8029
- }
8030
- ),
8031
- executionStatus === "success" && /* @__PURE__ */ jsx("div", { className: "absolute -bottom-1.5 -right-1.5 z-10", children: /* @__PURE__ */ jsx("div", { className: "bg-[var(--color-status-success-bg)] rounded-full p-0.5 shadow-md animate-in zoom-in duration-200", children: /* @__PURE__ */ jsx(
8032
- Icon,
8033
- {
8034
- icon: "mdi:check",
8035
- className: "size-3 text-[var(--color-status-success-text-inverse)]"
8036
- }
8037
- ) }) }),
8038
- executionStatus === "error" && /* @__PURE__ */ jsx("div", { className: "absolute -bottom-1.5 -right-1.5 z-10", children: /* @__PURE__ */ jsx("div", { className: "bg-[var(--color-status-error-bg)] rounded-full p-0.5 shadow-md animate-in zoom-in duration-200", children: /* @__PURE__ */ jsx(
8039
- Icon,
8040
- {
8041
- icon: "mdi:close",
8042
- className: "size-3 text-[var(--color-status-error-text-inverse)]"
8043
- }
8044
- ) }) }),
8045
- executionStatus === "running" && /* @__PURE__ */ jsx("div", { className: "absolute -bottom-1.5 -right-1.5 z-10", children: /* @__PURE__ */ jsx("div", { className: "bg-[var(--color-status-success-bg)] rounded-full p-0.5 shadow-md", children: /* @__PURE__ */ jsx(
8046
- Icon,
8047
- {
8048
- icon: "svg-spinners:ring-resize",
8049
- className: "size-3 text-[var(--color-status-success-text-inverse)]"
8050
- }
8051
- ) }) })
8052
- ] });
8053
- }
8054
- );
8055
- NodeCard.displayName = "NodeCard";
8056
- var NodeCardHeader = React2.forwardRef(
8057
- ({
8058
- className,
8059
- icon,
8060
- title,
8061
- handleDeleteNode,
8062
- handleShowNodeProperties,
8063
- handleExecuteStep,
8064
- isExecuting,
8065
- executionStatus,
8066
- gradientColor,
8067
- ...props
8068
- }, ref) => {
8069
- const gradientColorClass = HeaderGradientColors[gradientColor];
8070
- return /* @__PURE__ */ jsxs(
8071
- "div",
8072
- {
8073
- ref,
8074
- className: `relative overflow-clip rounded-sm bg-card/50 ${className}`,
8075
- ...props,
8076
- children: [
8077
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx(
8078
- "div",
8079
- {
8080
- className: `absolute h-full w-3/5 ${gradientColor ? gradientColorClass : "from-primary/40"} to-transparent bg-gradient-to-r`
8081
- }
8082
- ) }),
8083
- /* @__PURE__ */ jsxs("div", { className: "relative h-9 flex items-center justify-between gap-x-4 px-0.5 py-0.5", children: [
8084
- /* @__PURE__ */ jsx("div", { className: "flex grow items-center pl-1 gap-2", children: /* @__PURE__ */ jsx(HeaderWithIcon, { icon, title }) }),
8085
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-x-0.5 pr-0.5", children: [
8086
- /* @__PURE__ */ jsx("div", { className: "mx-1 h-4 w-px bg-card-foreground/10" }),
8087
- /* @__PURE__ */ jsx(
8088
- Button,
8089
- {
8090
- type: "button",
8091
- size: "icon",
8092
- variant: "ghost",
8093
- className: "size-7",
8094
- onClick: handleShowNodeProperties,
8095
- children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:cog-solid", className: "size-4" })
8096
- }
8097
- ),
8098
- handleExecuteStep && /* @__PURE__ */ jsx(
8099
- Button,
8100
- {
8101
- type: "button",
8102
- size: "icon",
8103
- variant: "ghost",
8104
- className: "size-7 transition-transform hover:scale-110",
8105
- onClick: (e) => {
8106
- e.stopPropagation();
8107
- handleExecuteStep();
8108
- },
8109
- disabled: isExecuting,
8110
- title: "Execute step",
8111
- children: isExecuting ? /* @__PURE__ */ jsx(
8112
- Icon,
8113
- {
8114
- icon: "svg-spinners:ring-resize",
8115
- className: "size-4 text-accent"
8116
- }
8117
- ) : executionStatus === "success" ? /* @__PURE__ */ jsx(
8118
- Icon,
8119
- {
8120
- icon: "mdi:check-circle",
8121
- className: "size-4 text-[var(--color-status-success-text)]"
8122
- }
8123
- ) : executionStatus === "error" ? /* @__PURE__ */ jsx(
8124
- Icon,
8125
- {
8126
- icon: "mdi:close-circle",
8127
- className: "size-4 text-[var(--color-status-error-text)]"
8128
- }
8129
- ) : /* @__PURE__ */ jsx(
8130
- Icon,
8131
- {
8132
- icon: "mdi:play",
8133
- className: "size-4 text-[var(--color-status-warning-text)]"
8134
- }
8135
- )
8136
- }
8137
- ),
8138
- /* @__PURE__ */ jsx(
8139
- Button,
8140
- {
8141
- type: "button",
8142
- variant: "ghost",
8143
- size: "icon",
8144
- className: "size-7 transition-transform hover:scale-110",
8145
- onClick: handleDeleteNode,
8146
- children: /* @__PURE__ */ jsx(
8147
- Icon,
8148
- {
8149
- icon: "basil:trash-solid",
8150
- className: "size-4 text-[var(--color-status-error-text)]"
8151
- }
8152
- )
8153
- }
8154
- ),
8155
- /* @__PURE__ */ jsx(
8156
- NodeInfoButtonWithModal,
8157
- {
8158
- metadata: {
8159
- className,
8160
- icon,
8161
- title,
8162
- handleDeleteNode,
8163
- handleShowNodeProperties,
8164
- gradientColor,
8165
- ...props
8166
- }
8167
- }
8168
- )
8169
- ] })
8170
- ] })
8171
- ]
8172
- }
8173
- );
8174
- }
8175
- );
8176
- NodeCardHeader.displayName = "NodeCardHeader";
8177
- var NodeCardDescription = React2.forwardRef(({ className, description, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("px-4 py-2", className), ...props, children: /* @__PURE__ */ jsx("div", { className: "text-xs text-card-foreground", children: description }) }));
8178
- NodeCardDescription.displayName = "NodeCardDescription";
8179
- var NodeCardContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
8180
- "div",
8181
- {
8182
- ref,
8183
- className: cn(
8184
- "flex flex-col divide-y divide-card-foreground/10",
8185
- className
8186
- ),
8187
- ...props
8188
- }
8189
- ));
8190
- NodeCardContent.displayName = "NodeCardContent";
8191
- var NodeCardFooter = React2.forwardRef(
8192
- ({ className, nodeId, ...props }, ref) => /* @__PURE__ */ jsxs(
8193
- "div",
8194
- {
8195
- ref,
8196
- className: `bg-card-foreground/10 overflow-clip rounded-sm px-4 py-2 text-[10px] text-card-foreground/50 ${className}`,
8197
- ...props,
8198
- children: [
8199
- "Node: ",
8200
- /* @__PURE__ */ jsxs("span", { className: "font-semibold", children: [
8201
- "#",
8202
- nodeId
8203
- ] })
8204
- ]
8205
- }
8206
- )
8207
- );
8208
- NodeCardFooter.displayName = "NodeCardFooter";
8209
8234
  var TRIGGER_WORKFLOW = TriggerWorkflowDocument;
8210
8235
  var WORKFLOW_RUN = WorkflowRunDocument;
8211
8236
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -8848,52 +8873,68 @@ var getNodeMetadata = (value) => {
8848
8873
  const nodeStatus = nodeStatuses[id] || "idle";
8849
8874
  const executionStatus = nodeStatus === "success" ? "success" : nodeStatus === "error" ? "error" : nodeStatus === "running" ? "running" : "idle";
8850
8875
  const itemCount = nodeItemCounts[id];
8876
+ const isTrigger = (data?.operation_type || "").toLowerCase() === "trigger" || (value?.type || "").toLowerCase().includes("trigger");
8877
+ const appName = (meta.title || nodeType || "Node").split(/\s+/)[0].toUpperCase();
8878
+ const operationDisplay = nodeType === "integration/channel" ? (() => {
8879
+ const explicitRole = data.args?.state?.role;
8880
+ const isAction = explicitRole === "action" || !explicitRole && edges.some((e) => e.target === id);
8881
+ return isAction ? "sendChannelMessage" : "onChannelMessageReceived";
8882
+ })() : nodeType === "store/conversation" ? "storeAndForward" : data?.operation_name || "Not configured";
8883
+ const nodeDescription = data?.nodeData?.description || meta?.description || "";
8884
+ const isLogicNode = /(^|[:/])(if|switch|merge|loop|filter|branch|router|condition|aggregate)/.test(
8885
+ (value?.type || "").toLowerCase()
8886
+ );
8887
+ const roleAccent = isTrigger ? "#10b981" : isLogicNode ? "#f59e0b" : "#3b82f6";
8851
8888
  return /* @__PURE__ */ jsxs("div", { children: [
8852
8889
  /* @__PURE__ */ jsxs(
8853
8890
  NodeCard,
8854
8891
  {
8855
8892
  "data-selected": selected,
8893
+ selected,
8856
8894
  onDoubleClick: handleOpenNdv,
8857
8895
  executionStatus,
8858
8896
  itemCount,
8897
+ isTrigger,
8898
+ accent: roleAccent,
8899
+ isExecuting: isThisNodeExecuting,
8900
+ onSettings: handleShowNodeProperties,
8901
+ onExecute: handleExecuteStep,
8902
+ onDelete: handleDeleteNode,
8903
+ infoButton: /* @__PURE__ */ jsx(
8904
+ NodeInfoButtonWithModal,
8905
+ {
8906
+ metadata: {
8907
+ icon: meta.icon,
8908
+ title: meta.title,
8909
+ description: nodeDescription,
8910
+ gradientColor: meta.gradientColor
8911
+ }
8912
+ }
8913
+ ),
8859
8914
  children: [
8860
8915
  /* @__PURE__ */ jsx(
8861
8916
  NodeCardHeader,
8862
8917
  {
8863
8918
  icon: meta.icon,
8864
- title: meta.title,
8865
- handleDeleteNode,
8866
- handleShowNodeProperties,
8867
- handleExecuteStep,
8868
- isExecuting: isThisNodeExecuting,
8869
- executionStatus,
8870
- gradientColor: meta.gradientColor
8919
+ appName,
8920
+ accentKey: value?.type || meta.title
8921
+ }
8922
+ ),
8923
+ /* @__PURE__ */ jsx(
8924
+ NodeCardBody,
8925
+ {
8926
+ operationName: operationDisplay,
8927
+ description: nodeDescription
8871
8928
  }
8872
8929
  ),
8873
- /* @__PURE__ */ jsxs(NodeCardContent, { children: [
8874
- nodeType === "integration/channel" || nodeType === "store/conversation" ? /* @__PURE__ */ jsx("div", { className: "flex flex-col p-4", children: /* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-card-foreground", children: nodeType === "integration/channel" ? (() => {
8875
- const explicitRole = data.args?.state?.role;
8876
- const isAction = explicitRole === "action" || !explicitRole && edges.some((e) => e.target === id);
8877
- return isAction ? "Send Message" : "Receive Messages";
8878
- })() : "Store & Forward" }) }) : (
8879
- // Operation is chosen in the Node Store (drag a specific
8880
- // operation onto the canvas), so the card just shows which one
8881
- // this node is pinned to — no in-card operation dropdown.
8882
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col p-4", children: [
8883
- /* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-muted-foreground", children: "Operation" }),
8884
- /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-card-foreground mt-0.5 truncate", children: data?.operation_name || "Not configured" })
8885
- ] })
8886
- ),
8887
- /* @__PURE__ */ jsx(NodeCardDescription, { description: meta?.description ?? "" }),
8888
- /* @__PURE__ */ jsx(NodeCardFooter, { nodeId: id })
8889
- ] }),
8890
8930
  /* @__PURE__ */ jsx(
8891
8931
  CustomHandle,
8892
8932
  {
8893
8933
  type: "target",
8894
8934
  id: "target",
8895
8935
  position: Position.Left,
8896
- isConnectable
8936
+ isConnectable,
8937
+ accent: roleAccent
8897
8938
  }
8898
8939
  ),
8899
8940
  /* @__PURE__ */ jsx(
@@ -8902,7 +8943,8 @@ var getNodeMetadata = (value) => {
8902
8943
  type: "source",
8903
8944
  id: "source",
8904
8945
  position: Position.Right,
8905
- isConnectable
8946
+ isConnectable,
8947
+ accent: roleAccent
8906
8948
  }
8907
8949
  )
8908
8950
  ]
@@ -9297,6 +9339,12 @@ function SidebarPanelHeading({
9297
9339
  }
9298
9340
  );
9299
9341
  }
9342
+ var HeaderWithIcon = ({ icon, title }) => {
9343
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
9344
+ /* @__PURE__ */ jsx(Icon, { icon, className: `size-4` }),
9345
+ /* @__PURE__ */ jsx("div", { className: "ml-2.5 flex items-center text-xs font-medium leading-none tracking-wide uppercase opacity-80", children: /* @__PURE__ */ jsx("span", { className: "translate-y-px", children: title }) })
9346
+ ] });
9347
+ };
9300
9348
  function truncateMiddle(text, maxLength) {
9301
9349
  if (text.length <= maxLength) return text;
9302
9350
  const half = maxLength / 2;
@@ -18421,15 +18469,7 @@ function CustomDeletableEdge(props) {
18421
18469
  const isRunning = sourceNodeStatus === "running";
18422
18470
  const isSuccess = sourceNodeStatus === "success";
18423
18471
  const isError = sourceNodeStatus === "error";
18424
- const [edgePath] = getSmoothStepPath({
18425
- sourceX,
18426
- sourceY,
18427
- sourcePosition,
18428
- targetX,
18429
- targetY,
18430
- targetPosition
18431
- });
18432
- const bezierResult = getBezierPath({
18472
+ const [edgePath, labelX, labelY] = getBezierPath({
18433
18473
  sourceX,
18434
18474
  sourceY,
18435
18475
  sourcePosition,
@@ -18437,8 +18477,6 @@ function CustomDeletableEdge(props) {
18437
18477
  targetY,
18438
18478
  targetPosition
18439
18479
  });
18440
- const labelX = bezierResult[1];
18441
- const labelY = bezierResult[2];
18442
18480
  useEffect(() => {
18443
18481
  const edges = getEdges();
18444
18482
  const currentEdge = edges?.find((e) => e.id === id);
@@ -18993,10 +19031,18 @@ function CustomDeletableEdge(props) {
18993
19031
  return {
18994
19032
  stroke: "var(--color-text-tertiary)",
18995
19033
  // Theme-aware default color
18996
- strokeWidth: 1.5
19034
+ strokeWidth: 2
18997
19035
  };
18998
19036
  };
18999
19037
  const edgeStyle = getEdgeStyle();
19038
+ const isIdle = !isRunning && !isSuccess && !isError;
19039
+ const srcType = (sourceNodeData?.type || "").toLowerCase();
19040
+ const srcOpType = (sourceNodeData?.data?.operation_type || "").toLowerCase();
19041
+ const srcIsTrigger = srcOpType === "trigger" || srcType.includes("trigger");
19042
+ const srcIsLogic = /(if|switch|merge|loop|filter|branch|router|condition|aggregate)/.test(
19043
+ srcType
19044
+ );
19045
+ const flowAccent = srcIsTrigger ? "#10b981" : srcIsLogic ? "#f59e0b" : "#3b82f6";
19000
19046
  const edgeClassName = [isRunning && "animated-edge edge-glow"].filter(Boolean).join(" ");
19001
19047
  return /* @__PURE__ */ jsxs(Fragment, { children: [
19002
19048
  /* @__PURE__ */ jsx(
@@ -19029,10 +19075,30 @@ function CustomDeletableEdge(props) {
19029
19075
  className: edgeClassName,
19030
19076
  d: edgePath,
19031
19077
  fill: "none",
19032
- style: edgeStyle,
19078
+ style: isIdle ? { stroke: flowAccent, strokeWidth: 1.25, strokeOpacity: 0.22 } : edgeStyle,
19033
19079
  markerEnd
19034
19080
  }
19035
19081
  ),
19082
+ isIdle && /* @__PURE__ */ jsx(
19083
+ "path",
19084
+ {
19085
+ d: edgePath,
19086
+ fill: "none",
19087
+ stroke: flowAccent,
19088
+ strokeWidth: 2,
19089
+ strokeDasharray: "6 8",
19090
+ style: { pointerEvents: "none" },
19091
+ children: /* @__PURE__ */ jsx(
19092
+ "animate",
19093
+ {
19094
+ attributeName: "stroke-dashoffset",
19095
+ values: "0;-14",
19096
+ dur: "0.55s",
19097
+ repeatCount: "indefinite"
19098
+ }
19099
+ )
19100
+ }
19101
+ ),
19036
19102
  isRunning && /* @__PURE__ */ jsx(
19037
19103
  "path",
19038
19104
  {
@@ -21646,7 +21712,7 @@ var edgeTypes2 = {
21646
21712
  deletable: CustomDeletableEdge
21647
21713
  };
21648
21714
  var edgeOptions = {
21649
- type: "smoothstep",
21715
+ type: "deletable",
21650
21716
  markerEnd: {
21651
21717
  type: MarkerType.ArrowClosed,
21652
21718
  width: 21,
@@ -21859,7 +21925,7 @@ var FlowBuilder = () => {
21859
21925
  ReactFlow,
21860
21926
  {
21861
21927
  proOptions: { hideAttribution: true },
21862
- onInit: ({ fitView }) => fitView().then(),
21928
+ onInit: ({ fitView }) => fitView({ minZoom: 1, maxZoom: 1 }).then(),
21863
21929
  nodeTypes: nodeTypes3,
21864
21930
  nodes,
21865
21931
  onNodesChange: handleNodesChange,
@@ -21880,6 +21946,7 @@ var FlowBuilder = () => {
21880
21946
  snapGrid: [16, 16],
21881
21947
  snapToGrid: true,
21882
21948
  fitView: true,
21949
+ fitViewOptions: { minZoom: 1, maxZoom: 1 },
21883
21950
  defaultEdgeOptions: edgeOptions,
21884
21951
  children: /* @__PURE__ */ jsx(Background, { gap: 24 })
21885
21952
  }
@@ -22154,5 +22221,5 @@ function WorkflowBuilder() {
22154
22221
  }
22155
22222
 
22156
22223
  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 };
22157
- //# sourceMappingURL=chunk-WPCOE4Z5.js.map
22158
- //# sourceMappingURL=chunk-WPCOE4Z5.js.map
22224
+ //# sourceMappingURL=chunk-5GIC24CM.js.map
22225
+ //# sourceMappingURL=chunk-5GIC24CM.js.map