@webdevarif/reactflow
Version: 
Reusable ReactFlow components for social media bot automation
1,140 lines (1,128 loc) • 58.7 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/facebook/index.ts
var facebook_exports = {};
__export(facebook_exports, {
  AIReplyNode: () => AIReplyNode,
  AudioMessageNode: () => AudioMessageNode,
  CarouselNode: () => CarouselNode,
  ConditionNode: () => ConditionNode,
  DelayNode: () => DelayNode,
  EcommerceNode: () => EcommerceNode,
  FacebookMediaNode: () => FacebookMediaNode,
  FacebookWorkflow: () => FacebookWorkflow_default,
  FacebookWorkflowCore: () => FacebookWorkflow,
  FileMessageNode: () => FileMessageNode,
  ImageMessageNode: () => ImageMessageNode,
  TextMessageNode: () => TextMessageNode,
  TriggerNode: () => TriggerNode,
  VideoMessageNode: () => VideoMessageNode,
  facebookEdgeTypes: () => facebookEdgeTypes,
  facebookNodeTemplates: () => facebookNodeTemplates,
  facebookNodeTypes: () => facebookNodeTypes,
  facebookSupportedMessageTypes: () => facebookSupportedMessageTypes
});
module.exports = __toCommonJS(facebook_exports);
// src/facebook/FacebookWorkflow.tsx
var import_react = __toESM(require("react"));
var import_reactflow2 = __toESM(require("reactflow"));
var import_style = require("reactflow/dist/style.css");
var import_lucide_react2 = require("lucide-react");
// src/facebook/components/MessageNodes.tsx
var import_reactflow = require("reactflow");
var import_jsx_runtime = require("react/jsx-runtime");
var BaseNode = ({ data, selected }) => {
  const getIcon = (type) => {
    switch (type) {
      case "text":
        return "\u{1F4AC}";
      case "image":
        return "\u{1F5BC}\uFE0F";
      case "audio":
        return "\u{1F3B5}";
      case "video":
        return "\u{1F3A5}";
      case "file":
        return "\u{1F4C4}";
      case "fb_media":
        return "\u{1F4F1}";
      case "carousel":
        return "\u{1F3A0}";
      case "ecommerce":
        return "\u{1F6D2}";
      case "ai_reply":
        return "\u{1F916}";
      default:
        return "\u2699\uFE0F";
    }
  };
  const getColor = (type) => {
    switch (type) {
      case "text":
        return "bg-blue-50 border-blue-200 text-blue-800";
      case "image":
        return "bg-green-50 border-green-200 text-green-800";
      case "audio":
        return "bg-purple-50 border-purple-200 text-purple-800";
      case "video":
        return "bg-red-50 border-red-200 text-red-800";
      case "file":
        return "bg-gray-50 border-gray-200 text-gray-800";
      case "fb_media":
        return "bg-indigo-50 border-indigo-200 text-indigo-800";
      case "carousel":
        return "bg-yellow-50 border-yellow-200 text-yellow-800";
      case "ecommerce":
        return "bg-pink-50 border-pink-200 text-pink-800";
      case "ai_reply":
        return "bg-gradient-to-r from-purple-50 to-pink-50 border-purple-200 text-purple-800";
      default:
        return "bg-gray-50 border-gray-200 text-gray-800";
    }
  };
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `px-4 py-3 shadow-sm rounded-lg border-2 min-w-[200px] max-w-[250px] ${getColor(data.type)} ${selected ? "ring-2 ring-blue-500 shadow-lg" : "hover:shadow-md"} transition-all duration-200`, children: [
    /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xl", children: getIcon(data.type) }),
      /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-semibold text-sm truncate", children: data.label }),
        data.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-gray-600 mt-1 line-clamp-2", children: data.content })
      ] })
    ] }),
    data.mediaUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-2 text-xs text-gray-500 flex items-center gap-1", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u{1F4CE}" }),
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: data.mediaType || "media" })
    ] }),
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
      import_reactflow.Handle,
      {
        type: "target",
        position: import_reactflow.Position.Top,
        className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-blue-500",
        style: { top: -6 }
      }
    ),
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
      import_reactflow.Handle,
      {
        type: "source",
        position: import_reactflow.Position.Bottom,
        className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-blue-500",
        style: { bottom: -6 }
      }
    )
  ] });
};
var TextMessageNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var ImageMessageNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var AudioMessageNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var VideoMessageNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var FileMessageNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var FacebookMediaNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var CarouselNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var EcommerceNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var AIReplyNode = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BaseNode, { ...props });
var ConditionNode = ({ data, selected }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `px-4 py-3 shadow-sm rounded-lg border-2 min-w-[200px] max-w-[250px] bg-orange-50 border-orange-200 text-orange-800 ${selected ? "ring-2 ring-orange-500 shadow-lg" : "hover:shadow-md"} transition-all duration-200`, children: [
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3", children: [
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xl", children: "\u{1F500}" }),
    /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-semibold text-sm truncate", children: data.label }),
      data.metadata?.condition && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-gray-600 mt-1", children: data.metadata.condition })
    ] })
  ] }),
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
    import_reactflow.Handle,
    {
      type: "target",
      position: import_reactflow.Position.Top,
      className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-orange-500",
      style: { top: -6 }
    }
  ),
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
    import_reactflow.Handle,
    {
      type: "source",
      position: import_reactflow.Position.Bottom,
      className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-orange-500",
      style: { bottom: -6 }
    }
  )
] });
var DelayNode = ({ data, selected }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `px-4 py-3 shadow-sm rounded-lg border-2 min-w-[200px] max-w-[250px] bg-cyan-50 border-cyan-200 text-cyan-800 ${selected ? "ring-2 ring-cyan-500 shadow-lg" : "hover:shadow-md"} transition-all duration-200`, children: [
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3", children: [
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xl", children: "\u23F1\uFE0F" }),
    /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-semibold text-sm truncate", children: data.label }),
      data.metadata?.delay && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-xs text-gray-600 mt-1", children: [
        (data.metadata.delay / 1e3).toFixed(1),
        "s"
      ] })
    ] })
  ] }),
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
    import_reactflow.Handle,
    {
      type: "target",
      position: import_reactflow.Position.Top,
      className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-cyan-500",
      style: { top: -6 }
    }
  ),
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
    import_reactflow.Handle,
    {
      type: "source",
      position: import_reactflow.Position.Bottom,
      className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-cyan-500",
      style: { bottom: -6 }
    }
  )
] });
var TriggerNode = ({ data, selected }) => {
  const getIcon = (type) => {
    switch (type) {
      case "receive_message":
        return "\u{1F4AC}";
      case "receive_comment":
        return "\u{1F4AC}";
      case "receive_post_reaction":
        return "\u{1F44D}";
      case "receive_page_like":
        return "\u2764\uFE0F";
      default:
        return "\u26A1";
    }
  };
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `px-4 py-3 shadow-sm rounded-lg border-2 min-w-[200px] max-w-[250px] bg-green-50 border-green-200 text-green-800 ${selected ? "ring-2 ring-green-500 shadow-lg" : "hover:shadow-md"} transition-all duration-200`, children: [
    /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3", children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xl", children: getIcon(data.type) }),
      /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-semibold text-sm truncate", children: data.label }),
        data.metadata?.keywords && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-xs text-green-600 mt-1 font-medium", children: [
          "Keywords: ",
          data.metadata.keywords
        ] })
      ] })
    ] }),
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-2 text-xs text-green-600 font-medium", children: "TRIGGER" }),
    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
      import_reactflow.Handle,
      {
        type: "source",
        position: import_reactflow.Position.Bottom,
        className: "w-3 h-3 bg-white border-2 border-gray-400 hover:border-green-500",
        style: { bottom: -6 }
      }
    )
  ] });
};
// src/facebook/config.ts
var facebookNodeTypes = {
  // Trigger nodes
  receive_message: TriggerNode,
  receive_comment: TriggerNode,
  receive_post_reaction: TriggerNode,
  receive_page_like: TriggerNode,
  // Action nodes
  text: TextMessageNode,
  image: ImageMessageNode,
  audio: AudioMessageNode,
  video: VideoMessageNode,
  file: FileMessageNode,
  fb_media: FacebookMediaNode,
  carousel: CarouselNode,
  ecommerce: EcommerceNode,
  ai_reply: AIReplyNode,
  condition: ConditionNode,
  delay: DelayNode
};
var facebookEdgeTypes = {
  default: "smoothstep",
  conditional: "smoothstep"
};
var facebookSupportedMessageTypes = [
  "text",
  "image",
  "audio",
  "video",
  "file",
  "fb_media",
  "carousel",
  "ecommerce",
  "ai_reply"
];
var facebookNodeTemplates = {
  // Trigger nodes
  receive_message: {
    type: "receive_message",
    data: {
      label: "Receive Message",
      type: "trigger",
      metadata: {
        triggerType: "message",
        event: "message_received",
        keywords: "{{ body }}",
        matchType: "contains",
        exactMatch: false
      }
    },
    position: { x: 0, y: 0 }
  },
  receive_comment: {
    type: "receive_comment",
    data: {
      label: "Receive Comment",
      type: "trigger",
      metadata: {
        triggerType: "comment",
        event: "comment_received",
        keywords: "{{ body }}",
        matchType: "contains",
        exactMatch: false
      }
    },
    position: { x: 0, y: 0 }
  },
  receive_post_reaction: {
    type: "receive_post_reaction",
    data: {
      label: "Receive Post Reaction",
      type: "trigger",
      metadata: {
        triggerType: "reaction",
        event: "post_reaction"
      }
    },
    position: { x: 0, y: 0 }
  },
  receive_page_like: {
    type: "receive_page_like",
    data: {
      label: "Receive Page Like",
      type: "trigger",
      metadata: {
        triggerType: "page_like",
        event: "page_liked"
      }
    },
    position: { x: 0, y: 0 }
  },
  // Action nodes
  text: {
    type: "text",
    data: {
      label: "Text Message",
      type: "text",
      content: "Hello! How can I help you today?"
    },
    position: { x: 0, y: 0 }
  },
  image: {
    type: "image",
    data: {
      label: "Image Message",
      type: "image",
      content: "Check out this image!",
      mediaType: "image"
    },
    position: { x: 0, y: 0 }
  },
  audio: {
    type: "audio",
    data: {
      label: "Audio Message",
      type: "audio",
      content: "Listen to this audio",
      mediaType: "audio"
    },
    position: { x: 0, y: 0 }
  },
  video: {
    type: "video",
    data: {
      label: "Video Message",
      type: "video",
      content: "Watch this video",
      mediaType: "video"
    },
    position: { x: 0, y: 0 }
  },
  file: {
    type: "file",
    data: {
      label: "File Message",
      type: "file",
      content: "Here is your file",
      mediaType: "file"
    },
    position: { x: 0, y: 0 }
  },
  fb_media: {
    type: "fb_media",
    data: {
      label: "Facebook Media",
      type: "fb_media",
      content: "Facebook media content",
      mediaType: "image"
    },
    position: { x: 0, y: 0 }
  },
  carousel: {
    type: "carousel",
    data: {
      label: "Carousel",
      type: "carousel",
      content: "Browse our products",
      metadata: {
        items: []
      }
    },
    position: { x: 0, y: 0 }
  },
  ecommerce: {
    type: "ecommerce",
    data: {
      label: "E-commerce",
      type: "ecommerce",
      content: "Shop now",
      metadata: {
        products: []
      }
    },
    position: { x: 0, y: 0 }
  },
  ai_reply: {
    type: "ai_reply",
    data: {
      label: "AI Reply",
      type: "ai_reply",
      content: "AI-powered response",
      metadata: {
        prompt: "",
        model: "gpt-3.5-turbo"
      }
    },
    position: { x: 0, y: 0 }
  },
  condition: {
    type: "condition",
    data: {
      label: "Condition",
      type: "condition",
      metadata: {
        condition: "user_input",
        operator: "contains",
        value: "help"
      }
    },
    position: { x: 0, y: 0 }
  },
  delay: {
    type: "delay",
    data: {
      label: "Delay",
      type: "delay",
      metadata: {
        delay: 300
      }
    },
    position: { x: 0, y: 0 }
  }
};
// src/components/ui/button.tsx
var React = __toESM(require("react"));
var import_react_slot = require("@radix-ui/react-slot");
var import_class_variance_authority = require("class-variance-authority");
// src/lib/utils.ts
var import_clsx = require("clsx");
var import_tailwind_merge = require("tailwind-merge");
function cn(...inputs) {
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
}
// src/components/ui/button.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var buttonVariants = (0, import_class_variance_authority.cva)(
  "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline"
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        icon: "h-10 w-10"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Button = React.forwardRef(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? import_react_slot.Slot : "button";
    return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
      Comp,
      {
        className: cn(buttonVariants({ variant, size, className })),
        ref,
        ...props
      }
    );
  }
);
Button.displayName = "Button";
// src/components/ui/input.tsx
var React2 = __toESM(require("react"));
var import_jsx_runtime3 = require("react/jsx-runtime");
var Input = React2.forwardRef(
  ({ className, type, ...props }, ref) => {
    return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
      "input",
      {
        type,
        className: cn(
          "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
          className
        ),
        ref,
        ...props
      }
    );
  }
);
Input.displayName = "Input";
// src/components/ui/select.tsx
var React3 = __toESM(require("react"));
var SelectPrimitive = __toESM(require("@radix-ui/react-select"));
var import_lucide_react = require("lucide-react");
var import_jsx_runtime4 = require("react/jsx-runtime");
var Select = SelectPrimitive.Root;
var SelectValue = SelectPrimitive.Value;
var SelectTrigger = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
  SelectPrimitive.Trigger,
  {
    ref,
    className: cn(
      "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
      className
    ),
    ...props,
    children: [
      children,
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
    ]
  }
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
var SelectScrollUpButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
  SelectPrimitive.ScrollUpButton,
  {
    ref,
    className: cn(
      "flex cursor-default items-center justify-center py-1",
      className
    ),
    ...props,
    children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.ChevronUp, { className: "h-4 w-4" })
  }
));
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
var SelectScrollDownButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
  SelectPrimitive.ScrollDownButton,
  {
    ref,
    className: cn(
      "flex cursor-default items-center justify-center py-1",
      className
    ),
    ...props,
    children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4" })
  }
));
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
var SelectContent = React3.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
  SelectPrimitive.Content,
  {
    ref,
    className: cn(
      "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
      className
    ),
    position,
    ...props,
    children: [
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectScrollUpButton, {}),
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
        SelectPrimitive.Viewport,
        {
          className: cn(
            "p-1",
            position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
          ),
          children
        }
      ),
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectScrollDownButton, {})
    ]
  }
) }));
SelectContent.displayName = SelectPrimitive.Content.displayName;
var SelectLabel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
  SelectPrimitive.Label,
  {
    ref,
    className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className),
    ...props
  }
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
var SelectItem = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
  SelectPrimitive.Item,
  {
    ref,
    className: cn(
      "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    ),
    ...props,
    children: [
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Check, { className: "h-4 w-4" }) }) }),
      /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.ItemText, { children })
    ]
  }
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
var SelectSeparator = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
  SelectPrimitive.Separator,
  {
    ref,
    className: cn("-mx-1 my-1 h-px bg-muted", className),
    ...props
  }
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
// src/components/ui/switch.tsx
var React4 = __toESM(require("react"));
var SwitchPrimitives = __toESM(require("@radix-ui/react-switch"));
var import_jsx_runtime5 = require("react/jsx-runtime");
var Switch = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
  SwitchPrimitives.Root,
  {
    className: cn(
      "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
      className
    ),
    ...props,
    ref,
    children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
      SwitchPrimitives.Thumb,
      {
        className: cn(
          "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
        )
      }
    )
  }
));
Switch.displayName = SwitchPrimitives.Root.displayName;
// src/components/ui/textarea.tsx
var React5 = __toESM(require("react"));
var import_jsx_runtime6 = require("react/jsx-runtime");
var Textarea = React5.forwardRef(
  ({ className, ...props }, ref) => {
    return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
      "textarea",
      {
        className: cn(
          "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
          className
        ),
        ref,
        ...props
      }
    );
  }
);
Textarea.displayName = "Textarea";
// src/facebook/FacebookWorkflow.tsx
var import_jsx_runtime7 = require("react/jsx-runtime");
var FacebookWorkflow = ({
  initialNodes = [],
  initialEdges = [],
  initialTitle = "Facebook Bot Workflow",
  onSave,
  onNodeClick,
  onEdgeClick,
  onTitleChange,
  className = "",
  height = "600px"
}) => {
  const [nodes, setNodes, onNodesChange] = (0, import_reactflow2.useNodesState)(initialNodes);
  const [edges, setEdges, onEdgesChange] = (0, import_reactflow2.useEdgesState)(initialEdges);
  const [selectedNode, setSelectedNode] = (0, import_react.useState)(null);
  const [showTriggerPopup, setShowTriggerPopup] = (0, import_react.useState)(false);
  const [showSidebar, setShowSidebar] = (0, import_react.useState)(true);
  const [sidebarTab, setSidebarTab] = (0, import_react.useState)("nodes");
  const [isDragOver, setIsDragOver] = (0, import_react.useState)(false);
  const [isClient, setIsClient] = (0, import_react.useState)(false);
  const [forceUpdate, setForceUpdate] = (0, import_react.useState)(0);
  const [workflowTitle, setWorkflowTitle] = (0, import_react.useState)(initialTitle);
  const [isEditingTitle, setIsEditingTitle] = (0, import_react.useState)(false);
  const reactFlowInstance = (0, import_react.useRef)(null);
  import_react.default.useEffect(() => {
    setIsClient(true);
  }, []);
  const memoizedNodeTypes = (0, import_react.useMemo)(() => facebookNodeTypes, []);
  const memoizedEdgeTypes = (0, import_react.useMemo)(() => facebookEdgeTypes, []);
  const forceRerender = (0, import_react.useCallback)(() => {
    setForceUpdate((prev) => prev + 1);
  }, []);
  const handleTitleChange = (0, import_react.useCallback)((newTitle) => {
    setWorkflowTitle(newTitle);
    onTitleChange?.(newTitle);
  }, [onTitleChange]);
  const handleTitleSubmit = (0, import_react.useCallback)(() => {
    setIsEditingTitle(false);
    onTitleChange?.(workflowTitle);
  }, [workflowTitle, onTitleChange]);
  const handleTitleKeyDown = (0, import_react.useCallback)((e) => {
    if (e.key === "Enter") {
      handleTitleSubmit();
    } else if (e.key === "Escape") {
      setWorkflowTitle(initialTitle);
      setIsEditingTitle(false);
    }
  }, [handleTitleSubmit, initialTitle]);
  const onConnect = (0, import_react.useCallback)(
    (params) => setEdges((eds) => (0, import_reactflow2.addEdge)(params, eds)),
    [setEdges]
  );
  const handleNodeClick = (0, import_react.useCallback)((event, node) => {
    setSelectedNode(node);
    setSidebarTab("properties");
    onNodeClick?.(node);
  }, [onNodeClick]);
  const handleEdgeClick = (0, import_react.useCallback)((event, edge) => {
    onEdgeClick?.(edge);
  }, [onEdgeClick]);
  const addNode = (0, import_react.useCallback)((nodeType, position) => {
    const template = facebookNodeTemplates[nodeType];
    if (template) {
      const newNode = {
        ...template,
        id: `${nodeType}_${Date.now()}`,
        position: position || {
          x: Math.random() * 400 + 200,
          y: Math.random() * 400 + 200
        }
      };
      setNodes((nds) => [...nds, newNode]);
    }
    setShowTriggerPopup(false);
  }, [setNodes]);
  const onInit = (0, import_react.useCallback)((instance) => {
    reactFlowInstance.current = instance;
  }, []);
  const onDragOver = (0, import_react.useCallback)((event) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = "move";
    setIsDragOver(true);
  }, []);
  const onDrop = (0, import_react.useCallback)((event) => {
    event.preventDefault();
    setIsDragOver(false);
    const nodeType = event.dataTransfer.getData("application/reactflow");
    if (!nodeType || !reactFlowInstance.current) {
      return;
    }
    const position = reactFlowInstance.current.screenToFlowPosition({
      x: event.clientX,
      y: event.clientY
    });
    addNode(nodeType, position);
  }, [addNode]);
  const onDragLeave = (0, import_react.useCallback)(() => {
    setIsDragOver(false);
  }, []);
  const onDragStart = (0, import_react.useCallback)((event, nodeType) => {
    event.dataTransfer.setData("application/reactflow", nodeType);
    event.dataTransfer.effectAllowed = "move";
  }, []);
  const deleteNode = (0, import_react.useCallback)((nodeId) => {
    setNodes((nds) => nds.filter((node) => node.id !== nodeId));
    setEdges((eds) => eds.filter((edge) => edge.source !== nodeId && edge.target !== nodeId));
    setSelectedNode(null);
  }, [setNodes, setEdges]);
  const saveWorkflow = (0, import_react.useCallback)(() => {
    const config = {
      name: workflowTitle,
      description: "Automated Facebook Messenger bot workflow",
      platform: "facebook",
      nodes,
      edges
    };
    onSave?.(config);
  }, [nodes, edges, workflowTitle, onSave]);
  const nodeGroups = {
    "Triggers": [
      { type: "receive_message", label: "Receive Message", icon: "\u{1F4E8}", description: "Triggered when user sends a message" },
      { type: "receive_comment", label: "Receive Comment", icon: "\u{1F4AC}", description: "Triggered when user comments on post" },
      { type: "receive_post_reaction", label: "Receive Post Reaction", icon: "\u{1F44D}", description: "Triggered when user reacts to post" },
      { type: "receive_page_like", label: "Receive Page Like", icon: "\u2764\uFE0F", description: "Triggered when user likes the page" }
    ],
    "Messages": [
      { type: "text", label: "Text Message", icon: "\u{1F4AC}", description: "Send a text message" },
      { type: "image", label: "Image Message", icon: "\u{1F5BC}\uFE0F", description: "Send an image" },
      { type: "audio", label: "Audio Message", icon: "\u{1F3B5}", description: "Send audio" },
      { type: "video", label: "Video Message", icon: "\u{1F3A5}", description: "Send video" }
    ],
    "Media": [
      { type: "file", label: "File Message", icon: "\u{1F4C4}", description: "Send a file" },
      { type: "fb_media", label: "Facebook Media", icon: "\u{1F4F1}", description: "Facebook media content" },
      { type: "carousel", label: "Carousel", icon: "\u{1F3A0}", description: "Carousel of items" }
    ],
    "Commerce": [
      { type: "ecommerce", label: "E-commerce", icon: "\u{1F6D2}", description: "E-commerce products" }
    ],
    "AI & Logic": [
      { type: "ai_reply", label: "AI Reply", icon: "\u{1F916}", description: "AI-powered response" },
      { type: "condition", label: "Condition", icon: "\u{1F500}", description: "Conditional logic" },
      { type: "delay", label: "Delay", icon: "\u23F1\uFE0F", description: "Add delay" }
    ]
  };
  if (!isClient) {
    return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `w-full h-full bg-gray-50 flex items-center justify-center ${className}`, style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-center", children: [
      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-4" }),
      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-gray-600", children: "Loading workflow builder..." })
    ] }) });
  }
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `w-full h-full bg-gray-50 flex flex-col ${className}`, style: { height }, children: [
    /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "h-14 bg-white border-b border-gray-200 flex items-center justify-between px-4", children: [
      /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-4", children: [
        isEditingTitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
          Input,
          {
            value: workflowTitle,
            onChange: (e) => setWorkflowTitle(e.target.value),
            onBlur: handleTitleSubmit,
            onKeyDown: handleTitleKeyDown,
            className: "text-lg font-semibold text-gray-900 bg-transparent border-none p-0 focus:ring-0 focus:border-none",
            autoFocus: true
          }
        ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
          "h1",
          {
            className: "text-lg font-semibold text-gray-900 cursor-pointer hover:bg-gray-100 px-2 py-1 rounded transition-colors",
            onClick: () => setIsEditingTitle(true),
            title: "Click to edit workflow title",
            children: workflowTitle
          }
        ),
        /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
          "button",
          {
            onClick: () => setShowSidebar(!showSidebar),
            className: "p-2 hover:bg-gray-100 rounded-md transition-colors",
            children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Settings, { className: "w-4 h-4" })
          }
        ) })
      ] }),
      /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
        /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Button, { variant: "outline", size: "sm", children: [
          /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Upload, { className: "w-4 h-4 mr-2" }),
          "Import"
        ] }),
        /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Button, { variant: "outline", size: "sm", children: [
          /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Download, { className: "w-4 h-4 mr-2" }),
          "Export"
        ] }),
        /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Button, { variant: "default", size: "sm", children: [
          /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Play, { className: "w-4 h-4 mr-2" }),
          "Test"
        ] }),
        /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
          Button,
          {
            onClick: saveWorkflow,
            variant: "default",
            size: "sm",
            className: "bg-green-600 hover:bg-green-700",
            children: [
              /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Save, { className: "w-4 h-4 mr-2" }),
              "Save"
            ]
          }
        )
      ] })
    ] }),
    /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex h-[calc(100%-3.5rem)] flex-1", children: [
      showSidebar && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "w-80 bg-white border-r border-gray-200 flex flex-col h-full", children: [
        /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex border-b border-gray-200", children: [
          /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
            "button",
            {
              onClick: () => setSidebarTab("nodes"),
              className: `flex-1 px-4 py-3 text-sm font-medium transition-colors ${sidebarTab === "nodes" ? "text-blue-600 border-b-2 border-blue-600 bg-blue-50" : "text-gray-600 hover:text-gray-900"}`,
              children: "Nodes"
            }
          ),
          /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
            "button",
            {
              onClick: () => setSidebarTab("properties"),
              className: `flex-1 px-4 py-3 text-sm font-medium transition-colors ${sidebarTab === "properties" ? "text-blue-600 border-b-2 border-blue-600 bg-blue-50" : "text-gray-600 hover:text-gray-900"}`,
              children: "Properties"
            }
          )
        ] }),
        /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex-1 overflow-y-auto", children: sidebarTab === "nodes" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "p-4", children: nodes.length === 0 ? (
          // Show only triggers when canvas is empty
          /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-6", children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-sm font-semibold text-gray-900 mb-3 uppercase tracking-wide", children: "Triggers" }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "space-y-2", children: nodeGroups["Triggers"].map((node) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
              "div",
              {
                draggable: true,
                onDragStart: (event) => onDragStart(event, node.type),
                onClick: () => addNode(node.type),
                className: "w-full flex items-center gap-3 p-3 text-left hover:bg-gray-50 rounded-lg border border-gray-200 transition-colors group cursor-grab active:cursor-grabbing",
                children: [
                  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-2xl", children: node.icon }),
                  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex-1 min-w-0", children: [
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm font-medium text-gray-900 group-hover:text-blue-600", children: node.label }),
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-gray-500 mt-0.5", children: node.description })
                  ] })
                ]
              },
              node.type
            )) })
          ] })
        ) : (
          // Show action nodes when canvas has nodes (hide triggers)
          Object.entries(nodeGroups).filter(([groupName]) => groupName !== "Triggers").map(([groupName, groupNodes]) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-6", children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-sm font-semibold text-gray-900 mb-3 uppercase tracking-wide", children: groupName }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "space-y-2", children: groupNodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
              "div",
              {
                draggable: true,
                onDragStart: (event) => onDragStart(event, node.type),
                onClick: () => addNode(node.type),
                className: "w-full flex items-center gap-3 p-3 text-left hover:bg-gray-50 rounded-lg border border-gray-200 transition-colors group cursor-grab active:cursor-grabbing",
                children: [
                  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-2xl", children: node.icon }),
                  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex-1 min-w-0", children: [
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm font-medium text-gray-900 group-hover:text-blue-600", children: node.label }),
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-gray-500 mt-0.5", children: node.description })
                  ] })
                ]
              },
              node.type
            )) })
          ] }, groupName))
        ) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "p-4", children: selectedNode ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-4", children: [
          /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Node Type" }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-sm text-gray-900 bg-gray-50 px-3 py-2 rounded-md", children: selectedNode.type })
          ] }),
          /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Label" }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
              Input,
              {
                type: "text",
                value: selectedNode.data.label,
                onChange: (e) => {
                  setNodes((nds) => nds.map(
                    (n) => n.id === selectedNode.id ? { ...n, data: { ...n.data, label: e.target.value } } : n
                  ));
                  setSelectedNode((prev) => prev ? { ...prev, data: { ...prev.data, label: e.target.value } } : null);
                  forceRerender();
                }
              }
            )
          ] }),
          selectedNode.data.type !== "trigger" && selectedNode.data.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Content" }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
              Textarea,
              {
                value: selectedNode.data.content || "",
                onChange: (e) => {
                  setNodes((nds) => nds.map(
                    (n) => n.id === selectedNode.id ? { ...n, data: { ...n.data, content: e.target.value } } : n
                  ));
                  setSelectedNode((prev) => prev ? { ...prev, data: { ...prev.data, content: e.target.value } } : null);
                  forceRerender();
                },
                rows: 3
              }
            )
          ] }),
          selectedNode.data.type === "trigger" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
              /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Keywords" }),
              /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
                Textarea,
                {
                  placeholder: "hello, help, {{ body }}",
                  value: selectedNode.data.metadata?.keywords || "",
                  onChange: (e) => {
                    setNodes((nds) => nds.map(
                      (n) => n.id === selectedNode.id ? {
                        ...n,
                        data: {
                          ...n.data,
                          metadata: {
                            ...n.data.metadata,
                            keywords: e.target.value
                          }
                        }
                      } : n
                    ));
                    setSelectedNode((prev) => prev ? {
                      ...prev,
                      data: {
                        ...prev.data,
                        metadata: {
                          ...prev.data.metadata,
                          keywords: e.target.value
                        }
                      }
                    } : null);
                    forceRerender();
                  },
                  rows: 3
                }
              ),
              /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-xs text-gray-500 mt-1", children: [
                "Comma separated keywords or ",
                `{{ body }}`,
                " for full content"
              ] })
            ] }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
              /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Match Type" }),
              /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
                Select,
                {
                  value: selectedNode.data.metadata?.matchType || "contains",
                  onValueChange: (value) => {
                    setNodes((nds) => nds.map(
                      (n) => n.id === selectedNode.id ? {
                        ...n,
                        data: {
                          ...n.data,
                          metadata: {
                            ...n.data.metadata,
                            matchType: value
                          }
                        }
                      } : n
                    ));
                    setSelectedNode((prev) => prev ? {
                      ...prev,
                      data: {
                        ...prev.data,
                        metadata: {
                          ...prev.data.metadata,
                          matchType: value
                        }
                      }
                    } : null);
                    forceRerender();
                  },
                  children: [
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectValue, { placeholder: "Select match type" }) }),
                    /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(SelectContent, { children: [
                      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectItem, { value: "contains", children: "Contains" }),
                      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectItem, { value: "exact", children: "Exact Match" }),
                      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectItem, { value: "starts_with", children: "Starts With" }),
                      /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectItem, { value: "ends_with", children: "Ends With" })
                    ] })
                  ]
                }
              )
            ] }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
              /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
                /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { htmlFor: "exactMatch", className: "text-sm font-medium text-gray-700", children: "Exact Match (case sensitive)" }),
                /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs text-gray-500 mt-1", children: "Enable case-sensitive matching" })
              ] }),
              /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
                Switch,
                {
                  checked: selectedNode.data.metadata?.exactMatch || false,
                  onCheckedChange: (checked) => {
                    console.log("Switch toggled:", { checked, nodeId: selectedNode.id });
                    setNodes((nds) => nds.map(
                      (n) => n.id === selectedNode.id ? {
                        ...n,
                        data: {
                          ...n.data,
                          metadata: {
                            ...n.data.metadata,
                            exactMatch: checked
                          }
                        }
                      } : n
                    ));
                    setSelectedNode((prev) => prev ? {
                      ...prev,
                      data: {
                        ...prev.data,
                        metadata: {
                          ...prev.data.metadata,
                          exactMatch: checked
                        }
                      }
                    } : null);
                  }
                }
              ) })
            ] })
          ] }),
          selectedNode.data.type === "delay" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Delay Duration (milliseconds)" }),
            /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
              Input,
              {
                type: "number",
                min: "0",
                step: "100",
                value: selectedNode.data.metadata?.