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