flowcloudai-ui 0.1.7 → 0.1.9
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.css +7 -3
- package/dist/index.d.ts +25 -52
- package/dist/index.js +409 -504
- package/package.json +3 -1
package/dist/index.css
CHANGED
|
@@ -467,7 +467,7 @@
|
|
|
467
467
|
display: flex;
|
|
468
468
|
flex-direction: column;
|
|
469
469
|
width: var(--sidebar-width);
|
|
470
|
-
height:
|
|
470
|
+
height: 100%;
|
|
471
471
|
background: var(--fc-color-bg-secondary);
|
|
472
472
|
border-right: 1px solid var(--fc-color-border);
|
|
473
473
|
overflow: hidden;
|
|
@@ -507,6 +507,7 @@
|
|
|
507
507
|
padding: var(--fc-space-sm, 8px) 0;
|
|
508
508
|
}
|
|
509
509
|
.fc-sidebar__footer {
|
|
510
|
+
flex-shrink: 0;
|
|
510
511
|
padding: var(--fc-space-sm, 8px) 0;
|
|
511
512
|
border-top: 1px solid var(--fc-color-border);
|
|
512
513
|
}
|
|
@@ -2037,10 +2038,13 @@
|
|
|
2037
2038
|
-webkit-app-region: no-drag;
|
|
2038
2039
|
}
|
|
2039
2040
|
.fc-tab-bar__tab--draggable {
|
|
2040
|
-
cursor:
|
|
2041
|
+
cursor: grab;
|
|
2042
|
+
will-change: transform;
|
|
2041
2043
|
}
|
|
2042
2044
|
.fc-tab-bar__tab--dragging {
|
|
2043
2045
|
opacity: 0.4;
|
|
2046
|
+
cursor: grabbing;
|
|
2047
|
+
z-index: 1;
|
|
2044
2048
|
}
|
|
2045
2049
|
.fc-tab-bar__tab-close {
|
|
2046
2050
|
display: inline-flex;
|
|
@@ -2074,7 +2078,7 @@
|
|
|
2074
2078
|
color: var(--fc-color-text-secondary);
|
|
2075
2079
|
cursor: pointer;
|
|
2076
2080
|
transition: all var(--fc-transition, 150ms ease);
|
|
2077
|
-
border-radius: var(--fc-radius-sm,
|
|
2081
|
+
border-radius: var(--fc-radius-sm, 2px);
|
|
2078
2082
|
background-color: var(--tab-bar-bg);
|
|
2079
2083
|
}
|
|
2080
2084
|
.fc-tab-bar__add-btn:hover {
|
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, FC
|
|
3
|
+
import React__default, { ReactNode, ComponentType, FC } from 'react';
|
|
4
4
|
|
|
5
5
|
type Theme = 'light' | 'dark' | 'system';
|
|
6
6
|
interface ThemeContextType {
|
|
@@ -455,17 +455,17 @@ interface TabBarProps {
|
|
|
455
455
|
/** 是否启用拖拽排序 */
|
|
456
456
|
draggable?: boolean;
|
|
457
457
|
/**
|
|
458
|
-
* Tab
|
|
458
|
+
* Tab 最小宽度,支持任意 CSS 长度值(如 "8rem"、"120px")。
|
|
459
459
|
* Tab 压缩至此宽度后触发横向滚动。
|
|
460
|
-
* @default
|
|
460
|
+
* @default "80px"
|
|
461
461
|
*/
|
|
462
|
-
|
|
462
|
+
minTabWidth?: string;
|
|
463
463
|
/**
|
|
464
|
-
* Tab
|
|
464
|
+
* Tab 最大宽度,支持任意 CSS 长度值(如 "16rem"、"200px")。
|
|
465
465
|
* Tab 较少时不超过此宽度。
|
|
466
|
-
* @default
|
|
466
|
+
* @default "200px"
|
|
467
467
|
*/
|
|
468
|
-
|
|
468
|
+
maxTabWidth?: string;
|
|
469
469
|
/**
|
|
470
470
|
* 控制 Tab 是否自动填充容器宽度。
|
|
471
471
|
* - true: flex: 1 1 0,Tab 会自动拉伸填满导航栏(默认行为)
|
|
@@ -641,59 +641,32 @@ interface ChatProps {
|
|
|
641
641
|
declare const Chat: React__default.FC<ChatProps>;
|
|
642
642
|
|
|
643
643
|
interface RelationNodeData {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
644
|
+
id: string;
|
|
645
|
+
name: string;
|
|
646
|
+
type?: 'person' | 'organization' | 'event' | 'location' | 'concept';
|
|
647
647
|
description?: string;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
metadata?: Record<string, any>;
|
|
648
|
+
avatar?: string;
|
|
649
|
+
importance?: number;
|
|
651
650
|
}
|
|
652
651
|
interface RelationEdgeData {
|
|
652
|
+
source: string;
|
|
653
|
+
target: string;
|
|
653
654
|
label?: string;
|
|
654
|
-
type?: '
|
|
655
|
-
|
|
656
|
-
animated?: boolean;
|
|
657
|
-
metadata?: Record<string, any>;
|
|
655
|
+
type?: 'friend' | 'enemy' | 'subordinate' | 'superior' | 'neutral';
|
|
656
|
+
strength?: number;
|
|
658
657
|
}
|
|
659
658
|
interface RelationProps {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
onNodeDoubleClick?: (nodeId: string, nodeData: RelationNodeData) => void;
|
|
664
|
-
onEdgeClick?: (edgeId: string, edgeData?: RelationEdgeData) => void;
|
|
665
|
-
onConnect?: (connection: any) => void;
|
|
666
|
-
onNodesChange?: (nodes: any[]) => void;
|
|
667
|
-
onEdgesChange?: (edges: any[]) => void;
|
|
668
|
-
fitView?: boolean;
|
|
669
|
-
fitViewOptions?: any;
|
|
670
|
-
className?: string;
|
|
671
|
-
style?: CSSProperties;
|
|
672
|
-
height?: string | number;
|
|
673
|
-
width?: string | number;
|
|
674
|
-
defaultViewport?: {
|
|
675
|
-
x: number;
|
|
676
|
-
y: number;
|
|
677
|
-
zoom: number;
|
|
659
|
+
data?: {
|
|
660
|
+
nodes: RelationNodeData[];
|
|
661
|
+
edges: RelationEdgeData[];
|
|
678
662
|
};
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
snapToGrid?: boolean;
|
|
682
|
-
snapGrid?: [number, number];
|
|
683
|
-
enableEdgeCreation?: boolean;
|
|
684
|
-
enableNodeDrag?: boolean;
|
|
685
|
-
onNodeContextMenu?: (nodeId: string, nodeData: RelationNodeData) => void;
|
|
663
|
+
onNodeClick?: (node: RelationNodeData) => void;
|
|
664
|
+
onEdgeClick?: (edge: RelationEdgeData) => void;
|
|
686
665
|
theme?: 'dark' | 'light';
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
};
|
|
692
|
-
nodeStyles?: {
|
|
693
|
-
borderRadius?: string;
|
|
694
|
-
minWidth?: string;
|
|
695
|
-
};
|
|
696
|
-
showHandles?: boolean;
|
|
666
|
+
height?: string | number;
|
|
667
|
+
width?: string | number;
|
|
668
|
+
className?: string;
|
|
669
|
+
style?: React__default.CSSProperties;
|
|
697
670
|
}
|
|
698
671
|
declare const Relation: FC<RelationProps>;
|
|
699
672
|
|
package/dist/index.js
CHANGED
|
@@ -2025,49 +2025,88 @@ var Card = ({
|
|
|
2025
2025
|
};
|
|
2026
2026
|
|
|
2027
2027
|
// src/components/Bar/TabBar.tsx
|
|
2028
|
-
import { useRef as useRef7, useCallback as useCallback8, memo as memo4, useEffect as useEffect8 } from "react";
|
|
2028
|
+
import { useRef as useRef7, useCallback as useCallback8, memo as memo4, useEffect as useEffect8, useMemo as useMemo5 } from "react";
|
|
2029
|
+
import {
|
|
2030
|
+
DndContext as DndContext2,
|
|
2031
|
+
closestCenter,
|
|
2032
|
+
PointerSensor as PointerSensor2,
|
|
2033
|
+
useSensor as useSensor2,
|
|
2034
|
+
useSensors as useSensors2
|
|
2035
|
+
} from "@dnd-kit/core";
|
|
2036
|
+
import {
|
|
2037
|
+
SortableContext,
|
|
2038
|
+
useSortable,
|
|
2039
|
+
horizontalListSortingStrategy,
|
|
2040
|
+
arrayMove
|
|
2041
|
+
} from "@dnd-kit/sortable";
|
|
2042
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
2029
2043
|
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2044
|
+
function useContainerBoundModifier(containerRef) {
|
|
2045
|
+
return useMemo5(() => ({ transform, activeNodeRect }) => {
|
|
2046
|
+
if (!containerRef.current || !activeNodeRect) {
|
|
2047
|
+
return { ...transform, y: 0 };
|
|
2048
|
+
}
|
|
2049
|
+
const { left, right } = containerRef.current.getBoundingClientRect();
|
|
2050
|
+
const minX = left - activeNodeRect.left;
|
|
2051
|
+
const maxX = right - activeNodeRect.right;
|
|
2052
|
+
return {
|
|
2053
|
+
...transform,
|
|
2054
|
+
y: 0,
|
|
2055
|
+
x: Math.min(Math.max(transform.x, minX), maxX)
|
|
2056
|
+
};
|
|
2057
|
+
}, [containerRef]);
|
|
2058
|
+
}
|
|
2030
2059
|
var TabItemView = memo4(({
|
|
2031
2060
|
item,
|
|
2032
2061
|
isActive,
|
|
2033
2062
|
closable,
|
|
2034
2063
|
draggable,
|
|
2064
|
+
stopMouseDown,
|
|
2035
2065
|
tabClassName,
|
|
2036
2066
|
activeTabClassName,
|
|
2037
2067
|
tabStyle,
|
|
2038
2068
|
activeTabStyle,
|
|
2039
2069
|
renderCloseIcon,
|
|
2040
2070
|
onClick,
|
|
2041
|
-
onClose
|
|
2042
|
-
onDragStart,
|
|
2043
|
-
onDragOver,
|
|
2044
|
-
onDrop,
|
|
2045
|
-
onDragEnd
|
|
2071
|
+
onClose
|
|
2046
2072
|
}) => {
|
|
2073
|
+
const {
|
|
2074
|
+
attributes,
|
|
2075
|
+
listeners,
|
|
2076
|
+
setNodeRef,
|
|
2077
|
+
transform,
|
|
2078
|
+
transition,
|
|
2079
|
+
isDragging
|
|
2080
|
+
} = useSortable({
|
|
2081
|
+
id: item.key,
|
|
2082
|
+
disabled: !draggable || !!item.disabled
|
|
2083
|
+
});
|
|
2047
2084
|
const showClose = item.closable !== void 0 ? item.closable : closable;
|
|
2048
2085
|
const classes = [
|
|
2049
2086
|
"fc-tab-bar__tab",
|
|
2050
2087
|
isActive && "fc-tab-bar__tab--active",
|
|
2051
2088
|
item.disabled && "fc-tab-bar__tab--disabled",
|
|
2052
2089
|
draggable && !item.disabled && "fc-tab-bar__tab--draggable",
|
|
2090
|
+
isDragging && "fc-tab-bar__tab--dragging",
|
|
2053
2091
|
tabClassName,
|
|
2054
2092
|
isActive && activeTabClassName
|
|
2055
2093
|
].filter(Boolean).join(" ");
|
|
2056
2094
|
const mergedStyle = {
|
|
2095
|
+
transform: CSS.Transform.toString(transform),
|
|
2096
|
+
transition,
|
|
2057
2097
|
...tabStyle,
|
|
2058
2098
|
...isActive ? activeTabStyle : void 0
|
|
2059
2099
|
};
|
|
2060
2100
|
return /* @__PURE__ */ jsxs13(
|
|
2061
2101
|
"div",
|
|
2062
2102
|
{
|
|
2103
|
+
ref: setNodeRef,
|
|
2063
2104
|
className: classes,
|
|
2064
2105
|
style: mergedStyle,
|
|
2065
2106
|
onClick: () => !item.disabled && onClick(item.key),
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
onDrop: (e) => onDrop(e, item.key),
|
|
2070
|
-
onDragEnd,
|
|
2107
|
+
onMouseDown: stopMouseDown ? (e) => e.stopPropagation() : void 0,
|
|
2108
|
+
...attributes,
|
|
2109
|
+
...listeners,
|
|
2071
2110
|
role: "tab",
|
|
2072
2111
|
"aria-selected": isActive,
|
|
2073
2112
|
"aria-disabled": item.disabled,
|
|
@@ -2078,6 +2117,7 @@ var TabItemView = memo4(({
|
|
|
2078
2117
|
"span",
|
|
2079
2118
|
{
|
|
2080
2119
|
className: "fc-tab-bar__tab-close",
|
|
2120
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
2081
2121
|
onClick: (e) => onClose(e, item.key),
|
|
2082
2122
|
role: "button",
|
|
2083
2123
|
"aria-label": "\u5173\u95ED",
|
|
@@ -2098,8 +2138,8 @@ var TabBar = memo4(({
|
|
|
2098
2138
|
closable = false,
|
|
2099
2139
|
addable = false,
|
|
2100
2140
|
draggable = false,
|
|
2101
|
-
|
|
2102
|
-
|
|
2141
|
+
minTabWidth = "80px",
|
|
2142
|
+
maxTabWidth = "200px",
|
|
2103
2143
|
fillWidth = true,
|
|
2104
2144
|
onChange,
|
|
2105
2145
|
onClose,
|
|
@@ -2138,8 +2178,8 @@ var TabBar = memo4(({
|
|
|
2138
2178
|
}
|
|
2139
2179
|
}
|
|
2140
2180
|
const mergedStyle = { ...overrideStyle, ...style };
|
|
2141
|
-
const dragKeyRef = useRef7(null);
|
|
2142
2181
|
const navRef = useRef7(null);
|
|
2182
|
+
const boundModifier = useContainerBoundModifier(navRef);
|
|
2143
2183
|
const prevItemsLengthRef = useRef7(items.length);
|
|
2144
2184
|
useEffect8(() => {
|
|
2145
2185
|
const prev = prevItemsLengthRef.current;
|
|
@@ -2173,38 +2213,19 @@ var TabBar = memo4(({
|
|
|
2173
2213
|
},
|
|
2174
2214
|
[onClose]
|
|
2175
2215
|
);
|
|
2176
|
-
const
|
|
2177
|
-
(
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
const target = e.currentTarget;
|
|
2181
|
-
requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
|
|
2182
|
-
},
|
|
2183
|
-
[]
|
|
2216
|
+
const sensors = useSensors2(
|
|
2217
|
+
useSensor2(PointerSensor2, {
|
|
2218
|
+
activationConstraint: { distance: 5 }
|
|
2219
|
+
})
|
|
2184
2220
|
);
|
|
2185
|
-
const
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
(
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
if (!dragKey || dragKey === targetKey || !onReorder) return;
|
|
2194
|
-
const fromIndex = items.findIndex((i) => i.key === dragKey);
|
|
2195
|
-
const toIndex = items.findIndex((i) => i.key === targetKey);
|
|
2196
|
-
if (fromIndex === -1 || toIndex === -1) return;
|
|
2197
|
-
const reordered = [...items];
|
|
2198
|
-
const [moved] = reordered.splice(fromIndex, 1);
|
|
2199
|
-
reordered.splice(toIndex, 0, moved);
|
|
2200
|
-
onReorder(reordered);
|
|
2201
|
-
},
|
|
2202
|
-
[items, onReorder]
|
|
2203
|
-
);
|
|
2204
|
-
const handleDragEnd = useCallback8((e) => {
|
|
2205
|
-
dragKeyRef.current = null;
|
|
2206
|
-
e.currentTarget.classList.remove("fc-tab-bar__tab--dragging");
|
|
2207
|
-
}, []);
|
|
2221
|
+
const handleDragEnd = useCallback8((event) => {
|
|
2222
|
+
const { active, over } = event;
|
|
2223
|
+
if (!over || active.id === over.id || !onReorder) return;
|
|
2224
|
+
const fromIndex = items.findIndex((i) => i.key === active.id);
|
|
2225
|
+
const toIndex = items.findIndex((i) => i.key === over.id);
|
|
2226
|
+
if (fromIndex === -1 || toIndex === -1) return;
|
|
2227
|
+
onReorder(arrayMove(items, fromIndex, toIndex));
|
|
2228
|
+
}, [items, onReorder]);
|
|
2208
2229
|
const rootClasses = [
|
|
2209
2230
|
"fc-tab-bar",
|
|
2210
2231
|
`fc-tab-bar--${variant}`,
|
|
@@ -2213,38 +2234,53 @@ var TabBar = memo4(({
|
|
|
2213
2234
|
className
|
|
2214
2235
|
].filter(Boolean).join(" ");
|
|
2215
2236
|
const navWrapStyle = {
|
|
2216
|
-
"--tab-min-width":
|
|
2217
|
-
"--tab-max-width":
|
|
2237
|
+
"--tab-min-width": minTabWidth,
|
|
2238
|
+
"--tab-max-width": maxTabWidth,
|
|
2218
2239
|
"--tab-fill-width": fillWidth ? "1" : "0"
|
|
2219
2240
|
};
|
|
2220
2241
|
const dragRegion = tauriDragRegion ? { "data-tauri-drag-region": "" } : {};
|
|
2242
|
+
const tabItems = items.map((item) => /* @__PURE__ */ jsx18(
|
|
2243
|
+
TabItemView,
|
|
2244
|
+
{
|
|
2245
|
+
item,
|
|
2246
|
+
isActive: activeKey === item.key,
|
|
2247
|
+
closable,
|
|
2248
|
+
draggable,
|
|
2249
|
+
stopMouseDown: tauriDragRegion,
|
|
2250
|
+
tabClassName,
|
|
2251
|
+
activeTabClassName,
|
|
2252
|
+
tabStyle,
|
|
2253
|
+
activeTabStyle,
|
|
2254
|
+
renderCloseIcon,
|
|
2255
|
+
onClick: handleClick,
|
|
2256
|
+
onClose: handleClose
|
|
2257
|
+
},
|
|
2258
|
+
item.key
|
|
2259
|
+
));
|
|
2221
2260
|
return /* @__PURE__ */ jsx18("div", { className: rootClasses, style: mergedStyle, role: "tablist", ...dragRegion, children: /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__nav-outer", ...dragRegion, children: /* @__PURE__ */ jsxs13("div", { className: "fc-tab-bar__nav-wrap", ref: navRef, style: navWrapStyle, children: [
|
|
2222
|
-
|
|
2223
|
-
|
|
2261
|
+
/* @__PURE__ */ jsx18(
|
|
2262
|
+
DndContext2,
|
|
2224
2263
|
{
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
onDragEnd: handleDragEnd
|
|
2240
|
-
},
|
|
2241
|
-
item.key
|
|
2242
|
-
)),
|
|
2264
|
+
sensors,
|
|
2265
|
+
collisionDetection: closestCenter,
|
|
2266
|
+
modifiers: [boundModifier],
|
|
2267
|
+
onDragEnd: handleDragEnd,
|
|
2268
|
+
children: /* @__PURE__ */ jsx18(
|
|
2269
|
+
SortableContext,
|
|
2270
|
+
{
|
|
2271
|
+
items: items.map((i) => i.key),
|
|
2272
|
+
strategy: horizontalListSortingStrategy,
|
|
2273
|
+
children: tabItems
|
|
2274
|
+
}
|
|
2275
|
+
)
|
|
2276
|
+
}
|
|
2277
|
+
),
|
|
2243
2278
|
addable && /* @__PURE__ */ jsx18(
|
|
2244
2279
|
"div",
|
|
2245
2280
|
{
|
|
2246
2281
|
className: "fc-tab-bar__add-btn",
|
|
2247
2282
|
onClick: onAdd,
|
|
2283
|
+
onMouseDown: tauriDragRegion ? (e) => e.stopPropagation() : void 0,
|
|
2248
2284
|
role: "button",
|
|
2249
2285
|
"aria-label": "\u6DFB\u52A0\u6807\u7B7E",
|
|
2250
2286
|
children: renderAddButton ? renderAddButton() : "+"
|
|
@@ -2555,7 +2591,7 @@ function ContextMenuProvider({
|
|
|
2555
2591
|
var useContextMenu = () => useContext4(ContextMenuContext);
|
|
2556
2592
|
|
|
2557
2593
|
// src/components/Chat/Chat.tsx
|
|
2558
|
-
import { useState as useState17, useRef as useRef10, useEffect as useEffect11, useCallback as useCallback10, useMemo as
|
|
2594
|
+
import { useState as useState17, useRef as useRef10, useEffect as useEffect11, useCallback as useCallback10, useMemo as useMemo6 } from "react";
|
|
2559
2595
|
|
|
2560
2596
|
// src/components/SmartMessage/SmartMessage.tsx
|
|
2561
2597
|
import { useState as useState16, useCallback as useCallback9 } from "react";
|
|
@@ -2665,7 +2701,7 @@ var Chat = ({
|
|
|
2665
2701
|
const messagesContainerRef = useRef10(null);
|
|
2666
2702
|
const messagesEndRef = useRef10(null);
|
|
2667
2703
|
const historyPanelRef = useRef10(null);
|
|
2668
|
-
const currentConversation =
|
|
2704
|
+
const currentConversation = useMemo6(
|
|
2669
2705
|
() => conversations.find((c) => c.id === currentConversationId),
|
|
2670
2706
|
[conversations, currentConversationId]
|
|
2671
2707
|
);
|
|
@@ -2693,7 +2729,7 @@ var Chat = ({
|
|
|
2693
2729
|
onMessageCopy?.(message);
|
|
2694
2730
|
}
|
|
2695
2731
|
}, [messages, onMessageCopy]);
|
|
2696
|
-
const containerStyle =
|
|
2732
|
+
const containerStyle = useMemo6(() => ({
|
|
2697
2733
|
height,
|
|
2698
2734
|
width,
|
|
2699
2735
|
...style
|
|
@@ -2865,484 +2901,353 @@ var Chat = ({
|
|
|
2865
2901
|
};
|
|
2866
2902
|
|
|
2867
2903
|
// src/components/Relation/Relation.tsx
|
|
2868
|
-
import
|
|
2904
|
+
import { useEffect as useEffect12, useState as useState18, useCallback as useCallback11, useRef as useRef11 } from "react";
|
|
2869
2905
|
import {
|
|
2870
2906
|
ReactFlow,
|
|
2871
2907
|
useNodesState,
|
|
2872
2908
|
useEdgesState,
|
|
2873
|
-
addEdge,
|
|
2874
|
-
Handle,
|
|
2875
|
-
Position,
|
|
2876
2909
|
MarkerType,
|
|
2877
|
-
ConnectionLineType,
|
|
2878
2910
|
useReactFlow,
|
|
2879
|
-
ReactFlowProvider
|
|
2911
|
+
ReactFlowProvider,
|
|
2912
|
+
Background,
|
|
2913
|
+
Position,
|
|
2914
|
+
Handle
|
|
2880
2915
|
} from "@xyflow/react";
|
|
2881
2916
|
import "@xyflow/react/dist/style.css";
|
|
2882
|
-
import {
|
|
2883
|
-
var
|
|
2884
|
-
const
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
default: "
|
|
2891
|
-
user: "\u{1F464}",
|
|
2892
|
-
shield: "\u{1F6E1}\uFE0F"
|
|
2917
|
+
import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2918
|
+
var getNodeColor = (type, isDark) => {
|
|
2919
|
+
const colors = {
|
|
2920
|
+
person: isDark ? "#60a5fa" : "#3b82f6",
|
|
2921
|
+
organization: isDark ? "#34d399" : "#10b981",
|
|
2922
|
+
event: isDark ? "#f472b6" : "#ec4899",
|
|
2923
|
+
location: isDark ? "#fb923c" : "#f97316",
|
|
2924
|
+
concept: isDark ? "#a78bfa" : "#8b5cf6",
|
|
2925
|
+
default: isDark ? "#94a3b8" : "#64748b"
|
|
2893
2926
|
};
|
|
2894
|
-
return
|
|
2927
|
+
return colors[type] || colors.default;
|
|
2895
2928
|
};
|
|
2896
|
-
var
|
|
2897
|
-
const
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2929
|
+
var getEdgeColor = (type, isDark) => {
|
|
2930
|
+
const colors = {
|
|
2931
|
+
friend: isDark ? "#34d399" : "#10b981",
|
|
2932
|
+
enemy: isDark ? "#f87171" : "#ef4444",
|
|
2933
|
+
subordinate: isDark ? "#60a5fa" : "#3b82f6",
|
|
2934
|
+
superior: isDark ? "#a78bfa" : "#8b5cf6",
|
|
2935
|
+
neutral: isDark ? "#94a3b8" : "#64748b",
|
|
2936
|
+
default: isDark ? "#94a3b8" : "#64748b"
|
|
2901
2937
|
};
|
|
2902
|
-
return
|
|
2938
|
+
return colors[type] || colors.default;
|
|
2903
2939
|
};
|
|
2904
|
-
var
|
|
2905
|
-
const
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
};
|
|
2913
|
-
const hiddenHandleStyle = {
|
|
2914
|
-
opacity: 0,
|
|
2915
|
-
width: "0px",
|
|
2916
|
-
height: "0px",
|
|
2917
|
-
pointerEvents: "none"
|
|
2940
|
+
var getIconForType = (type) => {
|
|
2941
|
+
const icons = {
|
|
2942
|
+
person: "\u{1F464}",
|
|
2943
|
+
organization: "\u{1F3E2}",
|
|
2944
|
+
event: "\u{1F4C5}",
|
|
2945
|
+
location: "\u{1F4CD}",
|
|
2946
|
+
concept: "\u{1F4A1}",
|
|
2947
|
+
default: "\u{1F517}"
|
|
2918
2948
|
};
|
|
2919
|
-
|
|
2920
|
-
return /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
2921
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-left", style: { ...actualStyle, left: "25%" } }),
|
|
2922
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-left-source", style: { ...actualStyle, left: "25%" } }),
|
|
2923
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-center", style: { ...actualStyle, left: "50%" } }),
|
|
2924
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-center-source", style: { ...actualStyle, left: "50%" } }),
|
|
2925
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "top-right", style: { ...actualStyle, left: "75%" } }),
|
|
2926
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "top-right-source", style: { ...actualStyle, left: "75%" } }),
|
|
2927
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-top", style: { ...actualStyle, top: "25%" } }),
|
|
2928
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-top-source", style: { ...actualStyle, top: "25%" } }),
|
|
2929
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-center", style: { ...actualStyle, top: "50%" } }),
|
|
2930
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-center-source", style: { ...actualStyle, top: "50%" } }),
|
|
2931
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "right-bottom", style: { ...actualStyle, top: "75%" } }),
|
|
2932
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "right-bottom-source", style: { ...actualStyle, top: "75%" } }),
|
|
2933
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-left", style: { ...actualStyle, left: "25%" } }),
|
|
2934
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-left-source", style: { ...actualStyle, left: "25%" } }),
|
|
2935
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-center", style: { ...actualStyle, left: "50%" } }),
|
|
2936
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-center-source", style: { ...actualStyle, left: "50%" } }),
|
|
2937
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "bottom-right", style: { ...actualStyle, left: "75%" } }),
|
|
2938
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "bottom-right-source", style: { ...actualStyle, left: "75%" } }),
|
|
2939
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-top", style: { ...actualStyle, top: "25%" } }),
|
|
2940
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-top-source", style: { ...actualStyle, top: "25%" } }),
|
|
2941
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-center", style: { ...actualStyle, top: "50%" } }),
|
|
2942
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-center-source", style: { ...actualStyle, top: "50%" } }),
|
|
2943
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "left-bottom", style: { ...actualStyle, top: "75%" } }),
|
|
2944
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "left-bottom-source", style: { ...actualStyle, top: "75%" } }),
|
|
2945
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "corner-top-left", style: { ...actualStyle, left: "10%" } }),
|
|
2946
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "corner-top-left-source", style: { ...actualStyle, left: "10%" } }),
|
|
2947
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, id: "corner-top-right", style: { ...actualStyle, left: "90%" } }),
|
|
2948
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Top, id: "corner-top-right-source", style: { ...actualStyle, left: "90%" } }),
|
|
2949
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "corner-bottom-left", style: { ...actualStyle, left: "10%" } }),
|
|
2950
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "corner-bottom-left-source", style: { ...actualStyle, left: "10%" } }),
|
|
2951
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Bottom, id: "corner-bottom-right", style: { ...actualStyle, left: "90%" } }),
|
|
2952
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, id: "corner-bottom-right-source", style: { ...actualStyle, left: "90%" } }),
|
|
2953
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "corner-left-top", style: { ...actualStyle, top: "10%" } }),
|
|
2954
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "corner-left-top-source", style: { ...actualStyle, top: "10%" } }),
|
|
2955
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, id: "corner-left-bottom", style: { ...actualStyle, top: "90%" } }),
|
|
2956
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Left, id: "corner-left-bottom-source", style: { ...actualStyle, top: "90%" } }),
|
|
2957
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "corner-right-top", style: { ...actualStyle, top: "10%" } }),
|
|
2958
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "corner-right-top-source", style: { ...actualStyle, top: "10%" } }),
|
|
2959
|
-
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Right, id: "corner-right-bottom", style: { ...actualStyle, top: "90%" } }),
|
|
2960
|
-
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, id: "corner-right-bottom-source", style: { ...actualStyle, top: "90%" } })
|
|
2961
|
-
] });
|
|
2949
|
+
return icons[type] || icons.default;
|
|
2962
2950
|
};
|
|
2963
|
-
var CustomNode =
|
|
2964
|
-
const isDark =
|
|
2965
|
-
const
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
2951
|
+
var CustomNode = ({ data }) => {
|
|
2952
|
+
const isDark = data.theme === "dark";
|
|
2953
|
+
const nodeColor = getNodeColor(data.type || "default", isDark);
|
|
2954
|
+
return /* @__PURE__ */ jsxs18(
|
|
2955
|
+
"div",
|
|
2956
|
+
{
|
|
2957
|
+
style: {
|
|
2958
|
+
background: isDark ? "#1e293b" : "#ffffff",
|
|
2959
|
+
border: `2px solid ${nodeColor}`,
|
|
2960
|
+
borderRadius: "12px",
|
|
2961
|
+
padding: "8px 12px",
|
|
2962
|
+
minWidth: "140px",
|
|
2963
|
+
cursor: "pointer",
|
|
2964
|
+
boxShadow: isDark ? "0 4px 12px rgba(0,0,0,0.3)" : "0 2px 8px rgba(0,0,0,0.1)",
|
|
2965
|
+
transition: "all 0.2s ease"
|
|
2966
|
+
},
|
|
2967
|
+
onMouseEnter: (e) => {
|
|
2968
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
2969
|
+
e.currentTarget.style.boxShadow = isDark ? "0 6px 16px rgba(0,0,0,0.4)" : "0 4px 12px rgba(0,0,0,0.15)";
|
|
2970
|
+
},
|
|
2971
|
+
onMouseLeave: (e) => {
|
|
2972
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
2973
|
+
e.currentTarget.style.boxShadow = isDark ? "0 4px 12px rgba(0,0,0,0.3)" : "0 2px 8px rgba(0,0,0,0.1)";
|
|
2974
|
+
},
|
|
2975
|
+
children: [
|
|
2976
|
+
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Top, style: { opacity: 0 } }),
|
|
2977
|
+
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Bottom, style: { opacity: 0 } }),
|
|
2978
|
+
/* @__PURE__ */ jsx24(Handle, { type: "target", position: Position.Left, style: { opacity: 0 } }),
|
|
2979
|
+
/* @__PURE__ */ jsx24(Handle, { type: "source", position: Position.Right, style: { opacity: 0 } }),
|
|
2980
|
+
/* @__PURE__ */ jsxs18("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
2981
|
+
/* @__PURE__ */ jsx24(
|
|
2982
|
+
"div",
|
|
2983
|
+
{
|
|
2984
|
+
style: {
|
|
2985
|
+
width: "32px",
|
|
2986
|
+
height: "32px",
|
|
2987
|
+
borderRadius: "50%",
|
|
2988
|
+
background: `linear-gradient(135deg, ${nodeColor}20, ${nodeColor}40)`,
|
|
2989
|
+
display: "flex",
|
|
2990
|
+
alignItems: "center",
|
|
2991
|
+
justifyContent: "center",
|
|
2992
|
+
fontSize: "16px"
|
|
2993
|
+
},
|
|
2994
|
+
children: getIconForType(data.type || "default")
|
|
2995
|
+
}
|
|
2996
|
+
),
|
|
2997
|
+
/* @__PURE__ */ jsxs18("div", { children: [
|
|
2998
|
+
/* @__PURE__ */ jsx24(
|
|
2999
|
+
"div",
|
|
3000
|
+
{
|
|
3001
|
+
style: {
|
|
3002
|
+
fontWeight: 600,
|
|
3003
|
+
fontSize: "12px",
|
|
3004
|
+
color: isDark ? "#ffffff" : "#1e293b"
|
|
3005
|
+
},
|
|
3006
|
+
children: data.name
|
|
3007
|
+
}
|
|
3008
|
+
),
|
|
3009
|
+
data.description && /* @__PURE__ */ jsx24(
|
|
3010
|
+
"div",
|
|
3011
|
+
{
|
|
3012
|
+
style: {
|
|
3013
|
+
fontSize: "10px",
|
|
3014
|
+
color: isDark ? "#94a3b8" : "#64748b",
|
|
3015
|
+
marginTop: "2px"
|
|
3016
|
+
},
|
|
3017
|
+
children: data.description
|
|
3018
|
+
}
|
|
3019
|
+
)
|
|
3020
|
+
] })
|
|
3021
|
+
] })
|
|
3022
|
+
]
|
|
3023
|
+
}
|
|
3024
|
+
);
|
|
3025
|
+
};
|
|
3026
|
+
var nodeTypes = { custom: CustomNode };
|
|
3027
|
+
var SmartEdge = ({ id, sourceX, sourceY, targetX, targetY, style = {}, markerEnd, data }) => {
|
|
3028
|
+
const dx = targetX - sourceX;
|
|
3029
|
+
const dy = targetY - sourceY;
|
|
3030
|
+
const offsetX = dx * 0.2;
|
|
3031
|
+
const offsetY = dy * 0.2;
|
|
3032
|
+
const path = `M ${sourceX} ${sourceY} C ${sourceX + offsetX} ${sourceY + offsetY}, ${targetX - offsetX} ${targetY - offsetY}, ${targetX} ${targetY}`;
|
|
3033
|
+
const midX = (sourceX + targetX) / 2;
|
|
3034
|
+
const midY = (sourceY + targetY) / 2;
|
|
3035
|
+
const getLabelStyle = () => {
|
|
3036
|
+
if (style.stroke === "#ef4444") return { bg: "#fee2e2", color: "#dc2626" };
|
|
3037
|
+
if (style.stroke === "#10b981") return { bg: "#d1fae5", color: "#065f46" };
|
|
3038
|
+
return { bg: "#e2e8f0", color: "#475569" };
|
|
3010
3039
|
};
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
/* @__PURE__ */
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
backgroundColor: getStatusColor(data.status),
|
|
3032
|
-
animation: data.status === "warning" ? "pulse 2s infinite" : "none",
|
|
3033
|
-
boxShadow: isDark ? "0 0 0 1px rgba(0,0,0,0.2)" : "none"
|
|
3034
|
-
} })
|
|
3035
|
-
] }),
|
|
3036
|
-
/* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3037
|
-
/* @__PURE__ */ jsx24("div", { style: titleStyle, children: data.title }),
|
|
3038
|
-
/* @__PURE__ */ jsx24("div", { style: subtitleStyle, children: data.subtitle }),
|
|
3039
|
-
data.description && /* @__PURE__ */ jsx24("div", { style: descriptionStyle, children: data.description })
|
|
3040
|
-
] })
|
|
3041
|
-
] })
|
|
3040
|
+
const labelStyle = getLabelStyle();
|
|
3041
|
+
return /* @__PURE__ */ jsxs18("g", { children: [
|
|
3042
|
+
/* @__PURE__ */ jsx24("path", { id, style, className: "react-flow__edge-path", d: path, markerEnd, fill: "none" }),
|
|
3043
|
+
data?.label && /* @__PURE__ */ jsx24("foreignObject", { x: midX - 30, y: midY - 10, width: 60, height: 20, style: { overflow: "visible" }, children: /* @__PURE__ */ jsx24(
|
|
3044
|
+
"div",
|
|
3045
|
+
{
|
|
3046
|
+
style: {
|
|
3047
|
+
background: labelStyle.bg,
|
|
3048
|
+
padding: "2px 6px",
|
|
3049
|
+
borderRadius: "10px",
|
|
3050
|
+
fontSize: "10px",
|
|
3051
|
+
fontWeight: 500,
|
|
3052
|
+
color: labelStyle.color,
|
|
3053
|
+
textAlign: "center",
|
|
3054
|
+
whiteSpace: "nowrap",
|
|
3055
|
+
pointerEvents: "none"
|
|
3056
|
+
},
|
|
3057
|
+
children: data.label
|
|
3058
|
+
}
|
|
3059
|
+
) })
|
|
3042
3060
|
] });
|
|
3043
|
-
});
|
|
3044
|
-
CustomNode.displayName = "CustomNode";
|
|
3045
|
-
var nodeTypes = {
|
|
3046
|
-
custom: CustomNode
|
|
3047
3061
|
};
|
|
3048
|
-
var
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
const
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3062
|
+
var edgeTypes = { smart: SmartEdge };
|
|
3063
|
+
var calculateTreeLayout = (nodes, edges) => {
|
|
3064
|
+
if (nodes.length === 0) return [];
|
|
3065
|
+
const childrenMap = /* @__PURE__ */ new Map();
|
|
3066
|
+
const parentMap = /* @__PURE__ */ new Map();
|
|
3067
|
+
edges.forEach((edge) => {
|
|
3068
|
+
if (!childrenMap.has(edge.source)) childrenMap.set(edge.source, []);
|
|
3069
|
+
childrenMap.get(edge.source).push(edge.target);
|
|
3070
|
+
parentMap.set(edge.target, edge.source);
|
|
3071
|
+
});
|
|
3072
|
+
const roots = nodes.filter((n) => !parentMap.has(n.id));
|
|
3073
|
+
const actualRoots = roots.length > 0 ? roots : [nodes[0]];
|
|
3074
|
+
const positioned = [];
|
|
3075
|
+
const levelNodes = /* @__PURE__ */ new Map();
|
|
3076
|
+
const queue = actualRoots.map((r) => ({ id: r.id, level: 0 }));
|
|
3077
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3078
|
+
while (queue.length > 0) {
|
|
3079
|
+
const item = queue.shift();
|
|
3080
|
+
if (visited.has(item.id)) continue;
|
|
3081
|
+
visited.add(item.id);
|
|
3082
|
+
if (!levelNodes.has(item.level)) levelNodes.set(item.level, []);
|
|
3083
|
+
levelNodes.get(item.level).push(item.id);
|
|
3084
|
+
const children = childrenMap.get(item.id) || [];
|
|
3085
|
+
children.forEach((childId) => {
|
|
3086
|
+
if (!visited.has(childId)) {
|
|
3087
|
+
queue.push({ id: childId, level: item.level + 1 });
|
|
3088
|
+
}
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3091
|
+
const startX = 50;
|
|
3092
|
+
const startY = 50;
|
|
3093
|
+
const levelHeight = 120;
|
|
3094
|
+
const nodeWidth = 180;
|
|
3095
|
+
const nodeGap = 30;
|
|
3096
|
+
for (const [level, nodeIds] of levelNodes.entries()) {
|
|
3097
|
+
const totalWidth = nodeIds.length * nodeWidth + (nodeIds.length - 1) * nodeGap;
|
|
3098
|
+
let currentX = startX + (800 - totalWidth) / 2;
|
|
3099
|
+
nodeIds.forEach((nodeId, index) => {
|
|
3100
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
3101
|
+
if (node) {
|
|
3102
|
+
positioned.push({
|
|
3103
|
+
...node,
|
|
3104
|
+
position: {
|
|
3105
|
+
x: currentX + index * (nodeWidth + nodeGap),
|
|
3106
|
+
y: startY + level * levelHeight
|
|
3107
|
+
}
|
|
3108
|
+
});
|
|
3109
|
+
}
|
|
3110
|
+
});
|
|
3111
|
+
}
|
|
3112
|
+
const positionedIds = new Set(positioned.map((p) => p.id));
|
|
3113
|
+
const remaining = nodes.filter((n) => !positionedIds.has(n.id));
|
|
3114
|
+
remaining.forEach((node, idx) => {
|
|
3115
|
+
positioned.push({
|
|
3116
|
+
...node,
|
|
3117
|
+
position: { x: 50 + idx % 3 * 200, y: 500 + Math.floor(idx / 3) * 100 }
|
|
3118
|
+
});
|
|
3119
|
+
});
|
|
3120
|
+
return positioned;
|
|
3055
3121
|
};
|
|
3056
3122
|
var RelationContent = ({
|
|
3057
|
-
|
|
3058
|
-
edges: propEdges,
|
|
3123
|
+
data,
|
|
3059
3124
|
onNodeClick,
|
|
3060
|
-
onNodeDoubleClick,
|
|
3061
3125
|
onEdgeClick,
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
onEdgesChange: onEdgesChangeProp,
|
|
3065
|
-
fitView = true,
|
|
3066
|
-
fitViewOptions,
|
|
3067
|
-
className = "",
|
|
3068
|
-
style = {},
|
|
3069
|
-
height = "70vh",
|
|
3126
|
+
theme = "light",
|
|
3127
|
+
height = "600px",
|
|
3070
3128
|
width = "100%",
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
maxZoom = 2,
|
|
3074
|
-
snapToGrid = false,
|
|
3075
|
-
snapGrid = [15, 15],
|
|
3076
|
-
enableEdgeCreation = true,
|
|
3077
|
-
enableNodeDrag = true,
|
|
3078
|
-
onNodeContextMenu,
|
|
3079
|
-
theme: propTheme = "light",
|
|
3080
|
-
edgeStyles = {},
|
|
3081
|
-
nodeStyles = {},
|
|
3082
|
-
showHandles = false
|
|
3129
|
+
className = "",
|
|
3130
|
+
style = {}
|
|
3083
3131
|
}) => {
|
|
3084
|
-
const [nodes, setNodes, onNodesChange] = useNodesState(
|
|
3085
|
-
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
|
3086
|
-
const { fitView
|
|
3087
|
-
const
|
|
3132
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
3133
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
3134
|
+
const { fitView } = useReactFlow();
|
|
3135
|
+
const [isReady, setIsReady] = useState18(false);
|
|
3136
|
+
const isInitialized = useRef11(false);
|
|
3088
3137
|
const isDark = theme === "dark";
|
|
3089
|
-
const bgColor = isDark ? "#0f172a" : "#
|
|
3090
|
-
useEffect12(() => {
|
|
3091
|
-
if (fitView && fitViewFn && (propNodes?.length || 0) > 0) {
|
|
3092
|
-
const timer = setTimeout(() => {
|
|
3093
|
-
fitViewFn({ duration: 300, padding: 0.2, ...fitViewOptions }).catch((error) => {
|
|
3094
|
-
console.warn("Fit view failed:", error);
|
|
3095
|
-
});
|
|
3096
|
-
}, 100);
|
|
3097
|
-
return () => clearTimeout(timer);
|
|
3098
|
-
}
|
|
3099
|
-
}, [fitView, fitViewFn, fitViewOptions, propNodes]);
|
|
3138
|
+
const bgColor = isDark ? "#0f172a" : "#f8fafc";
|
|
3100
3139
|
useEffect12(() => {
|
|
3101
|
-
if (
|
|
3102
|
-
setNodes(
|
|
3140
|
+
if (!data?.nodes?.length) {
|
|
3141
|
+
setNodes([]);
|
|
3142
|
+
setEdges([]);
|
|
3143
|
+
setIsReady(false);
|
|
3144
|
+
return;
|
|
3103
3145
|
}
|
|
3104
|
-
|
|
3146
|
+
const positionedNodes = calculateTreeLayout(data.nodes, data.edges);
|
|
3147
|
+
setNodes(
|
|
3148
|
+
positionedNodes.map((node) => ({
|
|
3149
|
+
id: node.id,
|
|
3150
|
+
type: "custom",
|
|
3151
|
+
position: node.position,
|
|
3152
|
+
data: {
|
|
3153
|
+
...node,
|
|
3154
|
+
theme
|
|
3155
|
+
}
|
|
3156
|
+
}))
|
|
3157
|
+
);
|
|
3158
|
+
setEdges(
|
|
3159
|
+
data.edges.map((edge) => {
|
|
3160
|
+
const edgeColor = getEdgeColor(edge.type || "neutral", isDark);
|
|
3161
|
+
return {
|
|
3162
|
+
id: `${edge.source}-${edge.target}`,
|
|
3163
|
+
source: edge.source,
|
|
3164
|
+
target: edge.target,
|
|
3165
|
+
type: "smart",
|
|
3166
|
+
label: edge.label,
|
|
3167
|
+
data: { label: edge.label },
|
|
3168
|
+
style: { stroke: edgeColor, strokeWidth: 2 },
|
|
3169
|
+
markerEnd: { type: MarkerType.ArrowClosed, width: 12, height: 12, color: edgeColor }
|
|
3170
|
+
};
|
|
3171
|
+
})
|
|
3172
|
+
);
|
|
3173
|
+
setIsReady(true);
|
|
3174
|
+
isInitialized.current = false;
|
|
3175
|
+
}, [data, theme, setNodes, setEdges]);
|
|
3105
3176
|
useEffect12(() => {
|
|
3106
|
-
if (
|
|
3107
|
-
|
|
3177
|
+
if (isReady && fitView && !isInitialized.current) {
|
|
3178
|
+
isInitialized.current = true;
|
|
3179
|
+
setTimeout(() => {
|
|
3180
|
+
fitView({ duration: 300, padding: 0.15 }).catch(() => {
|
|
3181
|
+
});
|
|
3182
|
+
}, 100);
|
|
3108
3183
|
}
|
|
3109
|
-
}, [
|
|
3110
|
-
const handleNodesChange = useCallback11(
|
|
3111
|
-
(changes) => {
|
|
3112
|
-
onNodesChange(changes);
|
|
3113
|
-
if (onNodesChangeProp) {
|
|
3114
|
-
setTimeout(() => {
|
|
3115
|
-
onNodesChangeProp(nodes);
|
|
3116
|
-
}, 0);
|
|
3117
|
-
}
|
|
3118
|
-
},
|
|
3119
|
-
[onNodesChange, onNodesChangeProp, nodes]
|
|
3120
|
-
);
|
|
3121
|
-
const handleEdgesChange = useCallback11(
|
|
3122
|
-
(changes) => {
|
|
3123
|
-
onEdgesChange(changes);
|
|
3124
|
-
if (onEdgesChangeProp) {
|
|
3125
|
-
setTimeout(() => {
|
|
3126
|
-
onEdgesChangeProp(edges);
|
|
3127
|
-
}, 0);
|
|
3128
|
-
}
|
|
3129
|
-
},
|
|
3130
|
-
[onEdgesChange, onEdgesChangeProp, edges]
|
|
3131
|
-
);
|
|
3132
|
-
const onConnect = useCallback11(
|
|
3133
|
-
(params) => {
|
|
3134
|
-
const newEdge = {
|
|
3135
|
-
...params,
|
|
3136
|
-
id: `edge-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
|
|
3137
|
-
type: "straight",
|
|
3138
|
-
style: { stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"), strokeWidth: 1.8 },
|
|
3139
|
-
markerEnd: {
|
|
3140
|
-
type: MarkerType.ArrowClosed,
|
|
3141
|
-
color: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
|
|
3142
|
-
width: 12,
|
|
3143
|
-
height: 12
|
|
3144
|
-
},
|
|
3145
|
-
label: "",
|
|
3146
|
-
labelStyle: { fill: isDark ? "#fff" : "#333", fontSize: 11, fontWeight: 400 },
|
|
3147
|
-
labelBgStyle: { fill: "transparent", fillOpacity: 0 }
|
|
3148
|
-
};
|
|
3149
|
-
setEdges((eds) => addEdge(newEdge, eds));
|
|
3150
|
-
if (onConnectProp) {
|
|
3151
|
-
onConnectProp(params);
|
|
3152
|
-
}
|
|
3153
|
-
},
|
|
3154
|
-
[setEdges, onConnectProp, edgeStyles.defaultColor, isDark]
|
|
3155
|
-
);
|
|
3184
|
+
}, [isReady, fitView]);
|
|
3156
3185
|
const handleNodeClick = useCallback11(
|
|
3157
3186
|
(_event, node) => {
|
|
3158
3187
|
if (onNodeClick && node.data) {
|
|
3159
|
-
|
|
3188
|
+
const { id, name, type, description, avatar, importance } = node.data;
|
|
3189
|
+
onNodeClick({ id, name, type, description, avatar, importance });
|
|
3160
3190
|
}
|
|
3161
3191
|
},
|
|
3162
3192
|
[onNodeClick]
|
|
3163
3193
|
);
|
|
3164
|
-
const handleNodeDoubleClick = useCallback11(
|
|
3165
|
-
(_event, node) => {
|
|
3166
|
-
if (onNodeDoubleClick && node.data) {
|
|
3167
|
-
onNodeDoubleClick(node.id, node.data);
|
|
3168
|
-
}
|
|
3169
|
-
},
|
|
3170
|
-
[onNodeDoubleClick]
|
|
3171
|
-
);
|
|
3172
|
-
const handleNodeContextMenu = useCallback11(
|
|
3173
|
-
(event, node) => {
|
|
3174
|
-
event.preventDefault();
|
|
3175
|
-
if (onNodeContextMenu && node.data) {
|
|
3176
|
-
onNodeContextMenu(node.id, node.data);
|
|
3177
|
-
}
|
|
3178
|
-
},
|
|
3179
|
-
[onNodeContextMenu]
|
|
3180
|
-
);
|
|
3181
3194
|
const handleEdgeClick = useCallback11(
|
|
3182
3195
|
(_event, edge) => {
|
|
3183
|
-
if (onEdgeClick) {
|
|
3184
|
-
|
|
3196
|
+
if (onEdgeClick && data?.edges) {
|
|
3197
|
+
const edgeData = data.edges.find((e) => `${e.source}-${e.target}` === edge.id);
|
|
3198
|
+
if (edgeData) onEdgeClick(edgeData);
|
|
3185
3199
|
}
|
|
3186
3200
|
},
|
|
3187
|
-
[onEdgeClick]
|
|
3201
|
+
[onEdgeClick, data]
|
|
3188
3202
|
);
|
|
3189
|
-
|
|
3190
|
-
return
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
},
|
|
3208
|
-
labelStyle: {
|
|
3209
|
-
fill: isDark ? "#fff" : "#333",
|
|
3210
|
-
fontSize: 11,
|
|
3211
|
-
fontWeight: 400,
|
|
3212
|
-
...edge.labelStyle
|
|
3213
|
-
},
|
|
3214
|
-
labelBgStyle: {
|
|
3215
|
-
fill: "transparent",
|
|
3216
|
-
fillOpacity: 0,
|
|
3217
|
-
...edge.labelBgStyle
|
|
3218
|
-
},
|
|
3219
|
-
markerEnd: {
|
|
3220
|
-
type: MarkerType.ArrowClosed,
|
|
3221
|
-
color: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
|
|
3222
|
-
width: 12,
|
|
3223
|
-
height: 12,
|
|
3224
|
-
...edge.markerEnd
|
|
3203
|
+
if (!data?.nodes?.length) {
|
|
3204
|
+
return /* @__PURE__ */ jsx24(
|
|
3205
|
+
"div",
|
|
3206
|
+
{
|
|
3207
|
+
style: {
|
|
3208
|
+
width,
|
|
3209
|
+
height,
|
|
3210
|
+
backgroundColor: bgColor,
|
|
3211
|
+
borderRadius: "12px",
|
|
3212
|
+
display: "flex",
|
|
3213
|
+
alignItems: "center",
|
|
3214
|
+
justifyContent: "center",
|
|
3215
|
+
color: isDark ? "#94a3b8" : "#64748b"
|
|
3216
|
+
},
|
|
3217
|
+
children: /* @__PURE__ */ jsxs18("div", { style: { textAlign: "center" }, children: [
|
|
3218
|
+
/* @__PURE__ */ jsx24("div", { style: { fontSize: "48px", marginBottom: "16px" }, children: "\u{1F4CA}" }),
|
|
3219
|
+
/* @__PURE__ */ jsx24("div", { children: "\u6682\u65E0\u5173\u7CFB\u6570\u636E" })
|
|
3220
|
+
] })
|
|
3225
3221
|
}
|
|
3226
|
-
|
|
3227
|
-
}
|
|
3228
|
-
|
|
3229
|
-
.relation-container {
|
|
3230
|
-
position: relative;
|
|
3231
|
-
width: 100%;
|
|
3232
|
-
height: 100%;
|
|
3233
|
-
overflow: hidden;
|
|
3234
|
-
}
|
|
3235
|
-
.react-flow__background,
|
|
3236
|
-
.react-flow__pane,
|
|
3237
|
-
.react-flow__renderer,
|
|
3238
|
-
.react-flow__viewport {
|
|
3239
|
-
background-color: ${bgColor} !important;
|
|
3240
|
-
}
|
|
3241
|
-
.relation-node {
|
|
3242
|
-
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;
|
|
3243
|
-
}
|
|
3244
|
-
.relation-node:hover {
|
|
3245
|
-
transform: translateY(-4px) scale(1.02);
|
|
3246
|
-
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)"};
|
|
3247
|
-
}
|
|
3248
|
-
.react-flow__edge-path {
|
|
3249
|
-
transition: stroke-width 0.2s ease, stroke 0.2s ease;
|
|
3250
|
-
}
|
|
3251
|
-
.react-flow__edge:hover .react-flow__edge-path {
|
|
3252
|
-
stroke-width: 2.5px;
|
|
3253
|
-
stroke: ${edgeStyles.hoverColor || (isDark ? "#ffa5a5" : "#ff8e8e")};
|
|
3254
|
-
}
|
|
3255
|
-
/* \u8FDE\u63A5\u70B9\u60AC\u505C\u6548\u679C */
|
|
3256
|
-
.react-flow__handle {
|
|
3257
|
-
transition: all 0.2s ease;
|
|
3258
|
-
}
|
|
3259
|
-
.react-flow__handle:hover {
|
|
3260
|
-
transform: scale(1.3);
|
|
3261
|
-
background-color: ${isDark ? "#ffa5a5" : "#ff8e8e"} !important;
|
|
3262
|
-
}
|
|
3263
|
-
@keyframes pulse {
|
|
3264
|
-
0%, 100% {
|
|
3265
|
-
opacity: 1;
|
|
3266
|
-
transform: scale(1);
|
|
3267
|
-
}
|
|
3268
|
-
50% {
|
|
3269
|
-
opacity: 0.7;
|
|
3270
|
-
transform: scale(1.2);
|
|
3271
|
-
}
|
|
3272
|
-
}
|
|
3273
|
-
/* \u7B80\u7EA6\u6EDA\u52A8\u6761 */
|
|
3274
|
-
.relation-container ::-webkit-scrollbar {
|
|
3275
|
-
width: 6px;
|
|
3276
|
-
height: 6px;
|
|
3277
|
-
}
|
|
3278
|
-
.relation-container ::-webkit-scrollbar-track {
|
|
3279
|
-
background: ${isDark ? "#1e293b" : "#e2e8f0"};
|
|
3280
|
-
border-radius: 3px;
|
|
3281
|
-
}
|
|
3282
|
-
.relation-container ::-webkit-scrollbar-thumb {
|
|
3283
|
-
background: ${isDark ? "#475569" : "#cbd5e1"};
|
|
3284
|
-
border-radius: 3px;
|
|
3285
|
-
}
|
|
3286
|
-
.relation-container ::-webkit-scrollbar-thumb:hover {
|
|
3287
|
-
background: ${isDark ? "#ff8e8e" : "#ff6b6b"};
|
|
3288
|
-
}
|
|
3289
|
-
`;
|
|
3290
|
-
return /* @__PURE__ */ jsxs18(
|
|
3222
|
+
);
|
|
3223
|
+
}
|
|
3224
|
+
return /* @__PURE__ */ jsx24(
|
|
3291
3225
|
"div",
|
|
3292
3226
|
{
|
|
3293
3227
|
className: `relation-container ${className}`,
|
|
3294
|
-
style: {
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
fitViewOptions,
|
|
3318
|
-
defaultViewport,
|
|
3319
|
-
minZoom,
|
|
3320
|
-
maxZoom,
|
|
3321
|
-
snapToGrid,
|
|
3322
|
-
snapGrid,
|
|
3323
|
-
nodesDraggable: enableNodeDrag,
|
|
3324
|
-
nodesConnectable: enableEdgeCreation,
|
|
3325
|
-
connectionLineType: ConnectionLineType.Straight,
|
|
3326
|
-
connectionLineStyle: {
|
|
3327
|
-
stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"),
|
|
3328
|
-
strokeWidth: 1.8
|
|
3329
|
-
},
|
|
3330
|
-
attributionPosition: "bottom-right",
|
|
3331
|
-
zoomOnScroll: true,
|
|
3332
|
-
zoomOnPinch: true,
|
|
3333
|
-
zoomOnDoubleClick: false,
|
|
3334
|
-
panOnScroll: false,
|
|
3335
|
-
panOnDrag: true,
|
|
3336
|
-
proOptions: { hideAttribution: true },
|
|
3337
|
-
elevateEdgesOnSelect: true,
|
|
3338
|
-
defaultEdgeOptions: {
|
|
3339
|
-
type: "straight",
|
|
3340
|
-
style: { stroke: edgeStyles.defaultColor || (isDark ? "#7c8ba0" : "#a0aec0"), strokeWidth: 1.8 },
|
|
3341
|
-
markerEnd: { type: MarkerType.ArrowClosed, width: 12, height: 12 }
|
|
3342
|
-
}
|
|
3343
|
-
}
|
|
3344
|
-
)
|
|
3345
|
-
]
|
|
3228
|
+
style: { width, height, ...style, backgroundColor: bgColor, borderRadius: "12px", overflow: "hidden" },
|
|
3229
|
+
children: /* @__PURE__ */ jsx24(
|
|
3230
|
+
ReactFlow,
|
|
3231
|
+
{
|
|
3232
|
+
nodes,
|
|
3233
|
+
edges,
|
|
3234
|
+
onNodesChange,
|
|
3235
|
+
onEdgesChange,
|
|
3236
|
+
onNodeClick: handleNodeClick,
|
|
3237
|
+
onEdgeClick: handleEdgeClick,
|
|
3238
|
+
nodeTypes,
|
|
3239
|
+
edgeTypes,
|
|
3240
|
+
nodesDraggable: false,
|
|
3241
|
+
nodesConnectable: false,
|
|
3242
|
+
fitView: false,
|
|
3243
|
+
minZoom: 0.3,
|
|
3244
|
+
maxZoom: 2,
|
|
3245
|
+
zoomOnScroll: true,
|
|
3246
|
+
panOnDrag: true,
|
|
3247
|
+
proOptions: { hideAttribution: true },
|
|
3248
|
+
children: /* @__PURE__ */ jsx24(Background, { color: isDark ? "#1e293b" : "#e2e8f0", gap: 20, size: 1 })
|
|
3249
|
+
}
|
|
3250
|
+
)
|
|
3346
3251
|
}
|
|
3347
3252
|
);
|
|
3348
3253
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowcloudai-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "flowcloudai",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@dnd-kit/core": "^6.3.1",
|
|
38
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
39
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
38
40
|
"@uiw/react-md-editor": "^4.0.4",
|
|
39
41
|
"@xyflow/react": "^12.10.2"
|
|
40
42
|
}
|