flowcloudai-ui 0.1.3 → 0.1.4

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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
- import React__default, { ReactNode, ComponentType, MouseEvent, CSSProperties } from 'react';
3
+ import React__default, { ReactNode, ComponentType, FC, MouseEvent, CSSProperties } from 'react';
4
4
 
5
5
  type Theme = 'light' | 'dark' | 'system';
6
6
  interface ThemeContextType {
@@ -676,7 +676,17 @@ interface RelationProps {
676
676
  enableNodeDrag?: boolean;
677
677
  onNodeContextMenu?: (nodeId: string, nodeData: RelationNodeData) => void;
678
678
  theme?: 'dark' | 'light';
679
+ edgeStyles?: {
680
+ defaultColor?: string;
681
+ hoverColor?: string;
682
+ selectedColor?: string;
683
+ };
684
+ nodeStyles?: {
685
+ borderRadius?: string;
686
+ minWidth?: string;
687
+ };
688
+ showHandles?: boolean;
679
689
  }
680
- declare const Relation: React.FC<RelationProps>;
690
+ declare const Relation: FC<RelationProps>;
681
691
 
682
692
  export { type AlertMode, type AlertProps, AlertProvider, type AlertProviderProps, type AlertType, Avatar, type AvatarProps, type AvatarShape, Button, ButtonGroup, ButtonToolbar, Card, type CardProps, type CategoryTreeNode, Chat, type ChatProps, CheckButton, type ContextMenuAction, type ContextMenuDivider, type ContextMenuItem, ContextMenuProvider, type ContextMenuProviderProps, type Conversation, DeleteDialog, type DeleteMode, type DropPosition, type FlatCategory, type FlatToTreeResult, Input, ListGroup, ListGroupItem, type ListGroupItemProps, type ListGroupProps, MarkdownEditor, type MarkdownEditorProps, type Message, type MessageRole, OrphanDialog, type OrphanResolution, type OrphanResolutionMap, Relation, type RelationEdgeData, type RelationNodeData, type RelationProps, RollingBox, Select, SideBar, type SideBarItem, type SideBarProps, Slider, SmartMessage, type SmartMessageProps, TabBar, type TabBarProps, type TabItem, TagItem, type TagItemProps, type TagSchema, type TagValue, type Theme, ThemeProvider, Tree, type TreeProps, VirtualList, findNodeInfo, flatToTree, isDescendantOf, lazyLoad, useAlert, useContextMenu, useTheme };
package/dist/index.js CHANGED
@@ -2040,7 +2040,7 @@ function useAdaptiveTabLayout(navRef, options) {
2040
2040
  const maxTabWidthRatioRef = useRef7(maxTabWidthRatio);
2041
2041
  maxTabWidthRatioRef.current = maxTabWidthRatio;
2042
2042
  const [layout, setLayout] = useState13({ scrollMode: false, tabWidth: void 0 });
2043
- const calculateTimeoutRef = useRef7(null);
2043
+ const rafRef = useRef7(null);
2044
2044
  const lastLayoutRef = useRef7({ scrollMode: false, tabWidth: void 0 });
2045
2045
  const addBtnWidthRef = useRef7(0);
2046
2046
  const lastAddableRef = useRef7(void 0);
@@ -2073,8 +2073,8 @@ function useAdaptiveTabLayout(navRef, options) {
2073
2073
  const tabGap = navWrap ? parseFloat(getComputedStyle(navWrap).gap) : 0;
2074
2074
  const totalGapWidth = (currentItemsLength - 1) * tabGap;
2075
2075
  const idealW = (navW - totalGapWidth) / currentItemsLength;
2076
- const threshold = window.innerWidth * currentMinWidthRatio;
2077
- const maxAllowedWidth = window.innerWidth * currentMaxTabWidthRatio;
2076
+ const threshold = screen.width * currentMinWidthRatio;
2077
+ const maxAllowedWidth = screen.width * currentMaxTabWidthRatio;
2078
2078
  const minAllowedWidth = 42;
2079
2079
  const prev = lastLayoutRef.current;
2080
2080
  const hysteresisFactor = 1.1;
@@ -2096,20 +2096,26 @@ function useAdaptiveTabLayout(navRef, options) {
2096
2096
  setLayout(newLayout);
2097
2097
  }
2098
2098
  }, [navRef]);
2099
- const calculateDebounced = useCallback8(() => {
2100
- if (calculateTimeoutRef.current) clearTimeout(calculateTimeoutRef.current);
2101
- calculateTimeoutRef.current = setTimeout(calculate, 50);
2102
- }, [calculate]);
2103
- const calculateDebouncedRef = useRef7(calculateDebounced);
2104
- calculateDebouncedRef.current = calculateDebounced;
2099
+ const calculateRef = useRef7(calculate);
2100
+ calculateRef.current = calculate;
2105
2101
  useEffect8(() => {
2106
- const rafId = requestAnimationFrame(calculate);
2107
- const handleResize = () => calculateDebouncedRef.current();
2108
- window.addEventListener("resize", handleResize);
2102
+ const navOuter = navRef.current?.parentElement;
2103
+ if (!navOuter) return;
2104
+ const ro = new ResizeObserver(() => {
2105
+ if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
2106
+ rafRef.current = requestAnimationFrame(() => {
2107
+ rafRef.current = null;
2108
+ calculateRef.current();
2109
+ });
2110
+ });
2111
+ ro.observe(navOuter);
2112
+ rafRef.current = requestAnimationFrame(() => {
2113
+ rafRef.current = null;
2114
+ calculateRef.current();
2115
+ });
2109
2116
  return () => {
2110
- cancelAnimationFrame(rafId);
2111
- window.removeEventListener("resize", handleResize);
2112
- if (calculateTimeoutRef.current) clearTimeout(calculateTimeoutRef.current);
2117
+ ro.disconnect();
2118
+ if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
2113
2119
  };
2114
2120
  }, []);
2115
2121
  useEffect8(() => {
@@ -2956,7 +2962,7 @@ var Chat = ({
2956
2962
  };
2957
2963
 
2958
2964
  // src/components/Relation/Relation.tsx
2959
- import { useCallback as useCallback12, useEffect as useEffect13 } from "react";
2965
+ import React13, { useCallback as useCallback12, useEffect as useEffect13, memo as memo5 } from "react";
2960
2966
  import {
2961
2967
  ReactFlow,
2962
2968
  useNodesState,
@@ -2970,7 +2976,7 @@ import {
2970
2976
  ReactFlowProvider
2971
2977
  } from "@xyflow/react";
2972
2978
  import "@xyflow/react/dist/style.css";
2973
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
2979
+ import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
2974
2980
  var getIconEmoji = (iconType) => {
2975
2981
  const map = {
2976
2982
  war: "\u2694\uFE0F",
@@ -2992,16 +2998,77 @@ var getStatusColor = (status) => {
2992
2998
  };
2993
2999
  return map[status || "active"];
2994
3000
  };
2995
- var CustomNode = ({ data, theme = "light" }) => {
2996
- const isDark = theme === "dark";
3001
+ var ConnectionHandles = ({ isDark, showHandles }) => {
3002
+ const handleStyle = {
3003
+ background: isDark ? "#ff8e8e" : "#ff6b6b",
3004
+ width: "8px",
3005
+ height: "8px",
3006
+ borderRadius: "50%",
3007
+ border: `1px solid ${isDark ? "#1e293b" : "#ffffff"}`,
3008
+ transition: "all 0.2s ease"
3009
+ };
3010
+ const hiddenHandleStyle = {
3011
+ opacity: 0,
3012
+ width: "0px",
3013
+ height: "0px",
3014
+ pointerEvents: "none"
3015
+ };
3016
+ const actualStyle = showHandles ? handleStyle : hiddenHandleStyle;
3017
+ return /* @__PURE__ */ jsxs18(Fragment5, { children: [
3018
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-left", style: { ...actualStyle, left: "25%" } }),
3019
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-left-source", style: { ...actualStyle, left: "25%" } }),
3020
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-center", style: { ...actualStyle, left: "50%" } }),
3021
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-center-source", style: { ...actualStyle, left: "50%" } }),
3022
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-right", style: { ...actualStyle, left: "75%" } }),
3023
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-right-source", style: { ...actualStyle, left: "75%" } }),
3024
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-top", style: { ...actualStyle, top: "25%" } }),
3025
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-top-source", style: { ...actualStyle, top: "25%" } }),
3026
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-center", style: { ...actualStyle, top: "50%" } }),
3027
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-center-source", style: { ...actualStyle, top: "50%" } }),
3028
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-bottom", style: { ...actualStyle, top: "75%" } }),
3029
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-bottom-source", style: { ...actualStyle, top: "75%" } }),
3030
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-left", style: { ...actualStyle, left: "25%" } }),
3031
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-left-source", style: { ...actualStyle, left: "25%" } }),
3032
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-center", style: { ...actualStyle, left: "50%" } }),
3033
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-center-source", style: { ...actualStyle, left: "50%" } }),
3034
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-right", style: { ...actualStyle, left: "75%" } }),
3035
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-right-source", style: { ...actualStyle, left: "75%" } }),
3036
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-top", style: { ...actualStyle, top: "25%" } }),
3037
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-top-source", style: { ...actualStyle, top: "25%" } }),
3038
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-center", style: { ...actualStyle, top: "50%" } }),
3039
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-center-source", style: { ...actualStyle, top: "50%" } }),
3040
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-bottom", style: { ...actualStyle, top: "75%" } }),
3041
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-bottom-source", style: { ...actualStyle, top: "75%" } }),
3042
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "corner-top-left", style: { ...actualStyle, left: "10%" } }),
3043
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "corner-top-left-source", style: { ...actualStyle, left: "10%" } }),
3044
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "corner-top-right", style: { ...actualStyle, left: "90%" } }),
3045
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "corner-top-right-source", style: { ...actualStyle, left: "90%" } }),
3046
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "corner-bottom-left", style: { ...actualStyle, left: "10%" } }),
3047
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "corner-bottom-left-source", style: { ...actualStyle, left: "10%" } }),
3048
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "corner-bottom-right", style: { ...actualStyle, left: "90%" } }),
3049
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "corner-bottom-right-source", style: { ...actualStyle, left: "90%" } }),
3050
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "corner-left-top", style: { ...actualStyle, top: "10%" } }),
3051
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "corner-left-top-source", style: { ...actualStyle, top: "10%" } }),
3052
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "corner-left-bottom", style: { ...actualStyle, top: "90%" } }),
3053
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "corner-left-bottom-source", style: { ...actualStyle, top: "90%" } }),
3054
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "corner-right-top", style: { ...actualStyle, top: "10%" } }),
3055
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "corner-right-top-source", style: { ...actualStyle, top: "10%" } }),
3056
+ /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "corner-right-bottom", style: { ...actualStyle, top: "90%" } }),
3057
+ /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "corner-right-bottom-source", style: { ...actualStyle, top: "90%" } })
3058
+ ] });
3059
+ };
3060
+ var CustomNode = memo5(({ data, theme: propTheme }) => {
3061
+ const isDark = (data.theme || propTheme) === "dark";
3062
+ const showHandles = data.showHandles !== void 0 ? data.showHandles : false;
2997
3063
  const nodeStyle = {
2998
3064
  background: isDark ? "linear-gradient(135deg, #1e293b 0%, #0f172a 100%)" : "linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)",
2999
- border: `2px solid ${isDark ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.08)"}`,
3065
+ border: `2px solid ${isDark ? "rgba(255, 255, 255, 0.15)" : "rgba(0, 0, 0, 0.08)"}`,
3000
3066
  borderRadius: "14px",
3001
- boxShadow: isDark ? "0 8px 20px rgba(0, 0, 0, 0.25)" : "0 4px 12px rgba(0, 0, 0, 0.08)",
3067
+ boxShadow: isDark ? "0 8px 20px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2)" : "0 4px 12px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.05)",
3002
3068
  minWidth: "240px",
3003
3069
  cursor: "pointer",
3004
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
3070
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
3071
+ position: "relative"
3005
3072
  };
3006
3073
  const iconStyle = {
3007
3074
  width: "52px",
@@ -3010,8 +3077,9 @@ var CustomNode = ({ data, theme = "light" }) => {
3010
3077
  display: "flex",
3011
3078
  alignItems: "center",
3012
3079
  justifyContent: "center",
3013
- background: isDark ? "rgba(255, 255, 255, 0.08)" : "rgba(0, 0, 0, 0.04)",
3014
- transition: "all 0.3s ease"
3080
+ background: isDark ? "linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.05) 100%)" : "linear-gradient(135deg, rgba(0, 0, 0, 0.04) 0%, rgba(0, 0, 0, 0.02) 100%)",
3081
+ transition: "all 0.3s ease",
3082
+ boxShadow: isDark ? "inset 0 1px 1px rgba(255, 255, 255, 0.1)" : "inset 0 1px 1px rgba(0, 0, 0, 0.02)"
3015
3083
  };
3016
3084
  const titleStyle = {
3017
3085
  fontWeight: 700,
@@ -3020,7 +3088,8 @@ var CustomNode = ({ data, theme = "light" }) => {
3020
3088
  whiteSpace: "nowrap",
3021
3089
  overflow: "hidden",
3022
3090
  textOverflow: "ellipsis",
3023
- color: isDark ? "#ffffff" : "#1e293b"
3091
+ color: isDark ? "#ffffff" : "#1e293b",
3092
+ letterSpacing: isDark ? "0.3px" : "normal"
3024
3093
  };
3025
3094
  const subtitleStyle = {
3026
3095
  fontSize: "11px",
@@ -3036,11 +3105,18 @@ var CustomNode = ({ data, theme = "light" }) => {
3036
3105
  textOverflow: "ellipsis",
3037
3106
  color: isDark ? "rgba(255, 255, 255, 0.45)" : "#94a3b8"
3038
3107
  };
3039
- return /* @__PURE__ */ jsxs18("div", { style: nodeStyle, children: [
3040
- /* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, isConnectable: true }),
3108
+ return /* @__PURE__ */ jsxs18("div", { style: nodeStyle, className: "relation-node", children: [
3109
+ /* @__PURE__ */ jsx24(ConnectionHandles, { isDark, showHandles }),
3041
3110
  /* @__PURE__ */ jsxs18("div", { style: { display: "flex", alignItems: "center", gap: "14px", padding: "14px 18px" }, children: [
3042
3111
  /* @__PURE__ */ jsxs18("div", { style: { position: "relative", flexShrink: 0 }, children: [
3043
- /* @__PURE__ */ jsx24("div", { style: iconStyle, children: data.imageUrl ? /* @__PURE__ */ jsx24("img", { src: data.imageUrl, alt: data.title, style: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "12px" } }) : /* @__PURE__ */ jsx24("span", { style: { fontSize: "28px" }, children: getIconEmoji(data.iconType) }) }),
3112
+ /* @__PURE__ */ jsx24("div", { style: iconStyle, children: data.imageUrl ? /* @__PURE__ */ jsx24(
3113
+ "img",
3114
+ {
3115
+ src: data.imageUrl,
3116
+ alt: data.title,
3117
+ style: { width: "100%", height: "100%", objectFit: "cover", borderRadius: "12px" }
3118
+ }
3119
+ ) : /* @__PURE__ */ jsx24("span", { style: { fontSize: "28px", filter: isDark ? "drop-shadow(0 1px 2px rgba(0,0,0,0.2))" : "none" }, children: getIconEmoji(data.iconType) }) }),
3044
3120
  data.status && /* @__PURE__ */ jsx24("div", { style: {
3045
3121
  position: "absolute",
3046
3122
  bottom: "-2px",
@@ -3049,7 +3125,9 @@ var CustomNode = ({ data, theme = "light" }) => {
3049
3125
  height: "12px",
3050
3126
  borderRadius: "50%",
3051
3127
  border: `2px solid ${isDark ? "#1e293b" : "#ffffff"}`,
3052
- backgroundColor: getStatusColor(data.status)
3128
+ backgroundColor: getStatusColor(data.status),
3129
+ animation: data.status === "warning" ? "pulse 2s infinite" : "none",
3130
+ boxShadow: isDark ? "0 0 0 1px rgba(0,0,0,0.2)" : "none"
3053
3131
  } })
3054
3132
  ] }),
3055
3133
  /* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: 0 }, children: [
@@ -3057,13 +3135,21 @@ var CustomNode = ({ data, theme = "light" }) => {
3057
3135
  /* @__PURE__ */ jsx24("div", { style: subtitleStyle, children: data.subtitle }),
3058
3136
  data.description && /* @__PURE__ */ jsx24("div", { style: descriptionStyle, children: data.description })
3059
3137
  ] })
3060
- ] }),
3061
- /* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, isConnectable: true })
3138
+ ] })
3062
3139
  ] });
3063
- };
3140
+ });
3141
+ CustomNode.displayName = "CustomNode";
3064
3142
  var nodeTypes = {
3065
3143
  custom: CustomNode
3066
3144
  };
3145
+ var getEdgeStyle = (theme, isHovered, isSelected) => {
3146
+ const baseColor = theme === "dark" ? "#7c8ba0" : "#a0aec0";
3147
+ const hoverColor = "#ff8e8e";
3148
+ const selectedColor = "#ff6b6b";
3149
+ if (isSelected) return { stroke: selectedColor, strokeWidth: 2.5 };
3150
+ if (isHovered) return { stroke: hoverColor, strokeWidth: 2.5 };
3151
+ return { stroke: baseColor, strokeWidth: 1.8 };
3152
+ };
3067
3153
  var RelationContent = ({
3068
3154
  nodes: propNodes,
3069
3155
  edges: propEdges,
@@ -3087,9 +3173,12 @@ var RelationContent = ({
3087
3173
  enableEdgeCreation = true,
3088
3174
  enableNodeDrag = true,
3089
3175
  onNodeContextMenu,
3090
- theme: propTheme = "light"
3176
+ theme: propTheme = "light",
3177
+ edgeStyles = {},
3178
+ nodeStyles = {},
3179
+ showHandles = false
3091
3180
  }) => {
3092
- const [nodes, , onNodesChange] = useNodesState(propNodes || []);
3181
+ const [nodes, setNodes, onNodesChange] = useNodesState(propNodes || []);
3093
3182
  const [edges, setEdges, onEdgesChange] = useEdgesState(propEdges || []);
3094
3183
  const { fitView: fitViewFn } = useReactFlow();
3095
3184
  const theme = propTheme;
@@ -3097,18 +3186,31 @@ var RelationContent = ({
3097
3186
  const bgColor = isDark ? "#0f172a" : "#f5f7fa";
3098
3187
  useEffect13(() => {
3099
3188
  if (fitView && fitViewFn && (propNodes?.length || 0) > 0) {
3100
- setTimeout(() => {
3101
- fitViewFn({ duration: 300, ...fitViewOptions }).catch((error) => {
3189
+ const timer = setTimeout(() => {
3190
+ fitViewFn({ duration: 300, padding: 0.2, ...fitViewOptions }).catch((error) => {
3102
3191
  console.warn("Fit view failed:", error);
3103
3192
  });
3104
3193
  }, 100);
3194
+ return () => clearTimeout(timer);
3105
3195
  }
3106
3196
  }, [fitView, fitViewFn, fitViewOptions, propNodes]);
3197
+ useEffect13(() => {
3198
+ if (propNodes) {
3199
+ setNodes(propNodes);
3200
+ }
3201
+ }, [propNodes, setNodes]);
3202
+ useEffect13(() => {
3203
+ if (propEdges) {
3204
+ setEdges(propEdges);
3205
+ }
3206
+ }, [propEdges, setEdges]);
3107
3207
  const handleNodesChange = useCallback12(
3108
3208
  (changes) => {
3109
3209
  onNodesChange(changes);
3110
3210
  if (onNodesChangeProp) {
3111
- onNodesChangeProp(nodes);
3211
+ setTimeout(() => {
3212
+ onNodesChangeProp(nodes);
3213
+ }, 0);
3112
3214
  }
3113
3215
  },
3114
3216
  [onNodesChange, onNodesChangeProp, nodes]
@@ -3117,7 +3219,9 @@ var RelationContent = ({
3117
3219
  (changes) => {
3118
3220
  onEdgesChange(changes);
3119
3221
  if (onEdgesChangeProp) {
3120
- onEdgesChangeProp(edges);
3222
+ setTimeout(() => {
3223
+ onEdgesChangeProp(edges);
3224
+ }, 0);
3121
3225
  }
3122
3226
  },
3123
3227
  [onEdgesChange, onEdgesChangeProp, edges]
@@ -3126,18 +3230,25 @@ var RelationContent = ({
3126
3230
  (params) => {
3127
3231
  const newEdge = {
3128
3232
  ...params,
3129
- id: `edge-${Date.now()}-${Math.random()}`,
3130
- type: "smoothstep",
3131
- style: { stroke: "#ff6b6b", strokeWidth: 2 },
3132
- markerEnd: { type: MarkerType.ArrowClosed, color: "#ff6b6b" },
3133
- label: "\u65B0\u8FDE\u63A5"
3233
+ id: `edge-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
3234
+ type: "straight",
3235
+ style: { stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"), strokeWidth: 1.8 },
3236
+ markerEnd: {
3237
+ type: MarkerType.ArrowClosed,
3238
+ color: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
3239
+ width: 12,
3240
+ height: 12
3241
+ },
3242
+ label: "",
3243
+ labelStyle: { fill: isDark ? "#fff" : "#333", fontSize: 11, fontWeight: 400 },
3244
+ labelBgStyle: { fill: "transparent", fillOpacity: 0 }
3134
3245
  };
3135
3246
  setEdges((eds) => addEdge(newEdge, eds));
3136
3247
  if (onConnectProp) {
3137
3248
  onConnectProp(params);
3138
3249
  }
3139
3250
  },
3140
- [setEdges, onConnectProp]
3251
+ [setEdges, onConnectProp, edgeStyles.defaultColor, isDark]
3141
3252
  );
3142
3253
  const handleNodeClick = useCallback12(
3143
3254
  (_event, node) => {
@@ -3172,18 +3283,107 @@ var RelationContent = ({
3172
3283
  },
3173
3284
  [onEdgeClick]
3174
3285
  );
3175
- const nodesWithTheme = nodes.map((node) => ({
3176
- ...node,
3177
- data: { ...node.data, theme }
3178
- }));
3286
+ const nodesWithTheme = React13.useMemo(() => {
3287
+ return nodes.map((node) => ({
3288
+ ...node,
3289
+ data: {
3290
+ ...node.data,
3291
+ theme,
3292
+ showHandles
3293
+ },
3294
+ className: `relation-node ${node.className || ""}`
3295
+ }));
3296
+ }, [nodes, theme, showHandles]);
3297
+ const edgesWithStyle = React13.useMemo(() => {
3298
+ return edges.map((edge) => ({
3299
+ ...edge,
3300
+ type: edge.type || "straight",
3301
+ style: {
3302
+ ...edge.style,
3303
+ ...getEdgeStyle(theme)
3304
+ },
3305
+ labelStyle: {
3306
+ fill: isDark ? "#fff" : "#333",
3307
+ fontSize: 11,
3308
+ fontWeight: 400,
3309
+ ...edge.labelStyle
3310
+ },
3311
+ labelBgStyle: {
3312
+ fill: "transparent",
3313
+ fillOpacity: 0,
3314
+ ...edge.labelBgStyle
3315
+ },
3316
+ markerEnd: {
3317
+ type: MarkerType.ArrowClosed,
3318
+ color: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
3319
+ width: 12,
3320
+ height: 12,
3321
+ ...edge.markerEnd
3322
+ }
3323
+ }));
3324
+ }, [edges, theme, isDark, edgeStyles.defaultColor]);
3179
3325
  const globalStyle = `
3180
- .react-flow__background,
3181
- .react-flow__pane,
3182
- .react-flow__renderer,
3183
- .react-flow__viewport {
3184
- background-color: ${bgColor} !important;
3185
- }
3186
- `;
3326
+ .relation-container {
3327
+ position: relative;
3328
+ width: 100%;
3329
+ height: 100%;
3330
+ overflow: hidden;
3331
+ }
3332
+ .react-flow__background,
3333
+ .react-flow__pane,
3334
+ .react-flow__renderer,
3335
+ .react-flow__viewport {
3336
+ background-color: ${bgColor} !important;
3337
+ }
3338
+ .relation-node {
3339
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;
3340
+ }
3341
+ .relation-node:hover {
3342
+ transform: translateY(-4px) scale(1.02);
3343
+ box-shadow: ${isDark ? "0 12px 28px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.2)" : "0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.05)"};
3344
+ }
3345
+ .react-flow__edge-path {
3346
+ transition: stroke-width 0.2s ease, stroke 0.2s ease;
3347
+ }
3348
+ .react-flow__edge:hover .react-flow__edge-path {
3349
+ stroke-width: 2.5px;
3350
+ stroke: ${edgeStyles.hoverColor || (isDark ? "#ffa5a5" : "#ff8e8e")};
3351
+ }
3352
+ /* \u8FDE\u63A5\u70B9\u60AC\u505C\u6548\u679C */
3353
+ .react-flow__handle {
3354
+ transition: all 0.2s ease;
3355
+ }
3356
+ .react-flow__handle:hover {
3357
+ transform: scale(1.3);
3358
+ background-color: ${isDark ? "#ffa5a5" : "#ff8e8e"} !important;
3359
+ }
3360
+ @keyframes pulse {
3361
+ 0%, 100% {
3362
+ opacity: 1;
3363
+ transform: scale(1);
3364
+ }
3365
+ 50% {
3366
+ opacity: 0.7;
3367
+ transform: scale(1.2);
3368
+ }
3369
+ }
3370
+ /* \u7B80\u7EA6\u6EDA\u52A8\u6761 */
3371
+ .relation-container ::-webkit-scrollbar {
3372
+ width: 6px;
3373
+ height: 6px;
3374
+ }
3375
+ .relation-container ::-webkit-scrollbar-track {
3376
+ background: ${isDark ? "#1e293b" : "#e2e8f0"};
3377
+ border-radius: 3px;
3378
+ }
3379
+ .relation-container ::-webkit-scrollbar-thumb {
3380
+ background: ${isDark ? "#475569" : "#cbd5e1"};
3381
+ border-radius: 3px;
3382
+ }
3383
+ .relation-container ::-webkit-scrollbar-thumb:hover {
3384
+ background: ${isDark ? "#ff8e8e" : "#ff6b6b"};
3385
+ }
3386
+ `;
3187
3387
  return /* @__PURE__ */ jsxs18(
3188
3388
  "div",
3189
3389
  {
@@ -3192,9 +3392,8 @@ var RelationContent = ({
3192
3392
  width,
3193
3393
  height,
3194
3394
  ...style,
3195
- position: "relative",
3196
- overflow: "hidden",
3197
- backgroundColor: bgColor
3395
+ backgroundColor: bgColor,
3396
+ borderRadius: nodeStyles.borderRadius || "12px"
3198
3397
  },
3199
3398
  children: [
3200
3399
  /* @__PURE__ */ jsx24("style", { children: globalStyle }),
@@ -3202,7 +3401,7 @@ var RelationContent = ({
3202
3401
  ReactFlow,
3203
3402
  {
3204
3403
  nodes: nodesWithTheme,
3205
- edges,
3404
+ edges: edgesWithStyle,
3206
3405
  onNodesChange: handleNodesChange,
3207
3406
  onEdgesChange: handleEdgesChange,
3208
3407
  onConnect: enableEdgeCreation ? onConnect : void 0,
@@ -3220,15 +3419,24 @@ var RelationContent = ({
3220
3419
  snapGrid,
3221
3420
  nodesDraggable: enableNodeDrag,
3222
3421
  nodesConnectable: enableEdgeCreation,
3223
- connectionLineType: ConnectionLineType.SmoothStep,
3224
- connectionLineStyle: { stroke: "#ff6b6b", strokeWidth: 2 },
3422
+ connectionLineType: ConnectionLineType.Straight,
3423
+ connectionLineStyle: {
3424
+ stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
3425
+ strokeWidth: 1.8
3426
+ },
3225
3427
  attributionPosition: "bottom-right",
3226
3428
  zoomOnScroll: true,
3227
3429
  zoomOnPinch: true,
3228
3430
  zoomOnDoubleClick: false,
3229
3431
  panOnScroll: false,
3230
3432
  panOnDrag: true,
3231
- proOptions: { hideAttribution: true }
3433
+ proOptions: { hideAttribution: true },
3434
+ elevateEdgesOnSelect: true,
3435
+ defaultEdgeOptions: {
3436
+ type: "straight",
3437
+ style: { stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"), strokeWidth: 1.8 },
3438
+ markerEnd: { type: MarkerType.ArrowClosed, width: 12, height: 12 }
3439
+ }
3232
3440
  }
3233
3441
  )
3234
3442
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowcloudai-ui",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "author": "flowcloudai",
6
6
  "module": "dist/index.js",