react-kggraph 0.0.14 → 0.0.16
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/README.md +176 -9
- package/lib/index.es3.js +24 -17
- package/lib/src/components/Graph/index.d.ts +2 -7
- package/lib/src/components/Graph/types.d.ts +44 -0
- package/lib/style.css +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,16 +1,183 @@
|
|
|
1
|
-
#
|
|
1
|
+
# react-kggraph
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
基于 Cytoscape.js 的 React 知识图谱可视化组件库。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 特性
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- 🚀 基于 Cytoscape.js 强大的图可视化能力
|
|
8
|
+
- 📊 支持多种布局算法(cose-bilkent、cise、fcose、storm)
|
|
9
|
+
- 🎨 支持节点、边的自定义样式
|
|
10
|
+
- 🔍 支持节点搜索、高亮路径分析
|
|
11
|
+
- 📦 支持知识图谱展开、节点详情查看
|
|
12
|
+
- 📱 响应式设计,支持缩放、拖拽等交互
|
|
9
13
|
|
|
10
|
-
##
|
|
14
|
+
## 安装
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
```bash
|
|
17
|
+
npm install react-kggraph
|
|
18
|
+
```
|
|
13
19
|
|
|
14
|
-
##
|
|
20
|
+
## 依赖
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
react-kggraph 依赖以下 peerDependencies,请确保已安装:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install react react-dom antd cytoscape cytoscape-cise cytoscape-cose-bilkent cytoscape-fcose cytoscape-layout-utilities storm-layout
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 使用
|
|
29
|
+
|
|
30
|
+
### 基础用法
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { CytoscapeReact } from 'react-kggraph';
|
|
34
|
+
import 'react-kggraph/style.css';
|
|
35
|
+
|
|
36
|
+
const App = () => {
|
|
37
|
+
const data = {
|
|
38
|
+
nodes: [
|
|
39
|
+
{ data: { id: '1', label: '刘培' } },
|
|
40
|
+
{ data: { id: '2', label: '许冉' } },
|
|
41
|
+
],
|
|
42
|
+
edges: [
|
|
43
|
+
{ data: { source: '1', target: '2', label: '同事' } },
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div style={{ width: '100%', height: '600px' }}>
|
|
49
|
+
<CytoscapeReact
|
|
50
|
+
data={data}
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 完整示例
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { CytoscapeReact, SearchType } from 'react-kggraph';
|
|
61
|
+
import 'react-kggraph/style.css';
|
|
62
|
+
|
|
63
|
+
const App = () => {
|
|
64
|
+
const data = {
|
|
65
|
+
nodes: [
|
|
66
|
+
{ data: { id: '1', label: '刘培' } },
|
|
67
|
+
{ data: { id: '2', label: '许冉' } },
|
|
68
|
+
],
|
|
69
|
+
edges: [
|
|
70
|
+
{ data: { source: '1', target: '2', label: '同事' } },
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// 获取完整图谱数据
|
|
75
|
+
const getAllGraphData = async (params) => {
|
|
76
|
+
const response = await fetch('/api/graph', {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: JSON.stringify(params),
|
|
79
|
+
});
|
|
80
|
+
return response.json();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// 节点展开 API
|
|
84
|
+
const stepNextApi = async (params) => {
|
|
85
|
+
const response = await fetch('/api/stepNext', {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
body: JSON.stringify(params),
|
|
88
|
+
});
|
|
89
|
+
return response.json();
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// 知识卡片 API
|
|
93
|
+
const knowledgeCardApi = async (params) => {
|
|
94
|
+
const response = await fetch('/api/knowledgeCard', {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
body: JSON.stringify(params),
|
|
97
|
+
});
|
|
98
|
+
return response.json();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div style={{ width: '100%', height: '600px' }}>
|
|
103
|
+
<CytoscapeReact
|
|
104
|
+
data={data}
|
|
105
|
+
getAllGraphData={getAllGraphData}
|
|
106
|
+
searchType={SearchType.KNOWLEDGE}
|
|
107
|
+
highPathAnalysis={['1', '2']}
|
|
108
|
+
graphInfo={{ kgId: 3, searchNodes: ['刘培', '许冉'] }}
|
|
109
|
+
stepNextApi={stepNextApi}
|
|
110
|
+
knowledgeCardApi={knowledgeCardApi}
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Props
|
|
118
|
+
|
|
119
|
+
| 属性 | 类型 | 必填 | 说明 |
|
|
120
|
+
|------|------|------|------|
|
|
121
|
+
| data | `GraphData \| any[]` | ✅ | 图谱数据 |
|
|
122
|
+
| getAllGraphData | `(params?: any) => Promise<any>` | ❌ | 获取完整图谱数据的回调函数 |
|
|
123
|
+
| searchType | `SearchType` | ❌ | 搜索类型 |
|
|
124
|
+
| highPathAnalysis | `string[]` | ❌ | 高亮路径分析的节点ID数组 |
|
|
125
|
+
| graphInfo | `GraphInfo` | ❌ | 图谱配置信息 |
|
|
126
|
+
| stepNextApi | `(params: any) => Promise<any>` | ❌ | 下一步API(用于知识图谱展开) |
|
|
127
|
+
| knowledgeCardApi | `(params: any) => Promise<any>` | ❌ | 知识卡片API |
|
|
128
|
+
|
|
129
|
+
## 类型定义
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
### GraphData
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface GraphData {
|
|
136
|
+
nodes: GraphNode[];
|
|
137
|
+
edges: GraphEdge[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface GraphNode {
|
|
141
|
+
data: {
|
|
142
|
+
id: string;
|
|
143
|
+
label: string;
|
|
144
|
+
type?: string;
|
|
145
|
+
properties?: Record<string, any>;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface GraphEdge {
|
|
150
|
+
data: {
|
|
151
|
+
id?: string;
|
|
152
|
+
source: string;
|
|
153
|
+
target: string;
|
|
154
|
+
label?: string;
|
|
155
|
+
type?: string;
|
|
156
|
+
properties?: Record<string, any>;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### GraphInfo
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
interface GraphInfo {
|
|
165
|
+
kgId: number | string;
|
|
166
|
+
searchNodes?: string[];
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 图谱布局
|
|
171
|
+
|
|
172
|
+
组件支持多种布局算法:
|
|
173
|
+
|
|
174
|
+
| 布局名称 | 说明 |
|
|
175
|
+
|---------|------|
|
|
176
|
+
| cose-bilkent | 力导向布局(默认) |
|
|
177
|
+
| cise | 聚类布局 |
|
|
178
|
+
| fcose | 快速力导向布局 |
|
|
179
|
+
| storm | 风暴布局 |
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT
|
package/lib/index.es3.js
CHANGED
|
@@ -17,21 +17,28 @@ import { jsonStringify as w } from "./index.es11.js";
|
|
|
17
17
|
import Ee from "./index.es12.js";
|
|
18
18
|
import we from "./index.es13.js";
|
|
19
19
|
import { GraphProvider as Le } from "./index.es14.js";
|
|
20
|
-
import
|
|
20
|
+
import je from "./index.es15.js";
|
|
21
21
|
x.use(Ce);
|
|
22
22
|
x.use(me);
|
|
23
23
|
x.use(he);
|
|
24
24
|
x.use(ve);
|
|
25
25
|
x.use(fe);
|
|
26
|
-
const
|
|
26
|
+
const Ye = ({
|
|
27
|
+
data: te,
|
|
28
|
+
getAllGraphData: S,
|
|
29
|
+
highPathAnalysis: N = [],
|
|
30
|
+
graphInfo: f,
|
|
31
|
+
stepNextApi: oe,
|
|
32
|
+
knowledgeCardApi: ne
|
|
33
|
+
}) => {
|
|
27
34
|
var Y, Z;
|
|
28
|
-
const L = E(null), [v, D] = m([]), p = E(null), F = E(null), H = 1, [Re, K] = m(!1), [k, I] = m({}), [
|
|
35
|
+
const L = E(null), [v, D] = m([]), p = E(null), F = E(null), H = 1, [Re, K] = m(!1), [k, I] = m({}), [j, P] = m({}), [se, de] = m("cose-bilkent"), X = E(null), J = E(null), [ae, Q] = m(["", ""]), [c, C] = m({
|
|
29
36
|
visible: !1,
|
|
30
37
|
x: 0,
|
|
31
38
|
y: 0,
|
|
32
39
|
targetNode: null,
|
|
33
40
|
bgColor: ""
|
|
34
|
-
}), [
|
|
41
|
+
}), [R, V] = m({
|
|
35
42
|
visible: !1,
|
|
36
43
|
x: 0,
|
|
37
44
|
y: 0,
|
|
@@ -40,8 +47,8 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
40
47
|
q(() => {
|
|
41
48
|
(N == null ? void 0 : N.length) > 1 && xe(p, { pathNodes: N, isGrayed: !1 });
|
|
42
49
|
}, [w(N), w(v)]), q(() => {
|
|
43
|
-
S == null || S({ graphData: v, nodeStatic: k, relationStatic:
|
|
44
|
-
}, [w(v), w(k), w(
|
|
50
|
+
S == null || S({ graphData: v, nodeStatic: k, relationStatic: j });
|
|
51
|
+
}, [w(v), w(k), w(j)]), q(() => {
|
|
45
52
|
var a;
|
|
46
53
|
if (!L.current || p.current) return;
|
|
47
54
|
const { elements: o, typeListObj: d, relationListObj: z } = A(te, { typeObj: k, graphInfo: f });
|
|
@@ -129,7 +136,7 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
129
136
|
if (t.length > 0) {
|
|
130
137
|
const n = t.map((l) => l.id()), r = t.connectedEdges(), b = e.edges().filter(
|
|
131
138
|
(l) => l.data("source") === d && n.includes(l.data("target"))
|
|
132
|
-
),
|
|
139
|
+
), T = e.edges().filter((l) => l.data("appendedBy") === d), B = r.merge(b).merge(T).filter((l) => l.data().zktype === o.zktype);
|
|
133
140
|
t.animate({
|
|
134
141
|
style: { opacity: 0 }
|
|
135
142
|
}, {
|
|
@@ -142,7 +149,7 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
142
149
|
if (u.group === "nodes" && n.includes((h = u.data) == null ? void 0 : h.id) && i && i === o.zktype)
|
|
143
150
|
return !1;
|
|
144
151
|
if (u.group === "edges" && i && i === o.zktype) {
|
|
145
|
-
const pe = Array.from(
|
|
152
|
+
const pe = Array.from(T).map((ye) => {
|
|
146
153
|
const U = ye.data();
|
|
147
154
|
return `${U.source}-${U.target}-${U.label}`;
|
|
148
155
|
}), M = u.data, ge = pe.includes(`${M.source}-${M.target}-${M.label}`), ue = ((_ = u.data) == null ? void 0 : _.appendedBy) === d;
|
|
@@ -163,8 +170,8 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
163
170
|
content: "正在展开...",
|
|
164
171
|
duration: 0
|
|
165
172
|
});
|
|
166
|
-
const n = await oe({ uri: d, queryType: 1, kgId: z, zktype: o.zktype }), { elements: r, typeListObj: b, relationListObj:
|
|
167
|
-
if (I(b), P(
|
|
173
|
+
const n = await oe({ uri: d, queryType: 1, kgId: z, zktype: o.zktype }), { elements: r, typeListObj: b, relationListObj: T } = A(n.data, { graphData: v, typeObj: k, relationObj: j, zktype: o.zktype });
|
|
174
|
+
if (I(b), P(T), console.log(555e3, r), !((r == null ? void 0 : r.length) > 0)) {
|
|
168
175
|
O.warning("暂无数据"), setTimeout(() => {
|
|
169
176
|
O.destroy();
|
|
170
177
|
}, 2e3);
|
|
@@ -294,7 +301,7 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
294
301
|
initNodeScale: H,
|
|
295
302
|
cyContainerRef: L,
|
|
296
303
|
typeObj: k,
|
|
297
|
-
relationObj:
|
|
304
|
+
relationObj: j
|
|
298
305
|
}
|
|
299
306
|
),
|
|
300
307
|
/* @__PURE__ */ G("div", { style: { position: "relative" }, children: [
|
|
@@ -322,13 +329,13 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
322
329
|
children: /* @__PURE__ */ y(Ee, { items: re, centerImage: (Z = c == null ? void 0 : c.targetNode) == null ? void 0 : Z.data().image, onClick: (o) => ce(o) })
|
|
323
330
|
}
|
|
324
331
|
),
|
|
325
|
-
|
|
332
|
+
R.visible && /* @__PURE__ */ y(
|
|
326
333
|
"div",
|
|
327
334
|
{
|
|
328
335
|
style: {
|
|
329
336
|
position: "absolute",
|
|
330
|
-
left: `${
|
|
331
|
-
top: `${
|
|
337
|
+
left: `${R.x}px`,
|
|
338
|
+
top: `${R.y}px`,
|
|
332
339
|
transform: "translateX(-50%)",
|
|
333
340
|
backgroundColor: "rgba(0, 0, 0, 0.85)",
|
|
334
341
|
color: "#fff",
|
|
@@ -342,14 +349,14 @@ const Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N
|
|
|
342
349
|
overflow: "hidden",
|
|
343
350
|
textOverflow: "ellipsis"
|
|
344
351
|
},
|
|
345
|
-
children:
|
|
352
|
+
children: R.content
|
|
346
353
|
}
|
|
347
354
|
)
|
|
348
355
|
] }),
|
|
349
356
|
/* @__PURE__ */ y(we, { ref: X }),
|
|
350
|
-
/* @__PURE__ */ y(
|
|
357
|
+
/* @__PURE__ */ y(je, { ref: J })
|
|
351
358
|
] }) });
|
|
352
359
|
};
|
|
353
360
|
export {
|
|
354
|
-
|
|
361
|
+
Ye as default
|
|
355
362
|
};
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare const CytoscapeReact:
|
|
3
|
-
data: any;
|
|
4
|
-
getAllGraphData: any;
|
|
5
|
-
searchType?: SearchType;
|
|
6
|
-
highPathAnalysis?: Array<string>;
|
|
7
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
import { CytoscapeReactProps } from './types';
|
|
2
|
+
declare const CytoscapeReact: React.FC<CytoscapeReactProps>;
|
|
8
3
|
export default CytoscapeReact;
|
|
@@ -4,3 +4,47 @@ export declare enum SearchType {
|
|
|
4
4
|
ATTRIBUTE = "attribute",// 查属性
|
|
5
5
|
TIMELINE = "timeline"
|
|
6
6
|
}
|
|
7
|
+
export interface GraphNode {
|
|
8
|
+
data: {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
type?: string;
|
|
12
|
+
properties?: Record<string, any>;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface GraphEdge {
|
|
17
|
+
data: {
|
|
18
|
+
id?: string;
|
|
19
|
+
source: string;
|
|
20
|
+
target: string;
|
|
21
|
+
label?: string;
|
|
22
|
+
type?: string;
|
|
23
|
+
properties?: Record<string, any>;
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface GraphData {
|
|
28
|
+
nodes: GraphNode[];
|
|
29
|
+
edges: GraphEdge[];
|
|
30
|
+
}
|
|
31
|
+
export interface GraphInfo {
|
|
32
|
+
kgId: number | string;
|
|
33
|
+
searchNodes?: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface CytoscapeReactProps {
|
|
36
|
+
/** 图谱数据 */
|
|
37
|
+
data: GraphData | any[];
|
|
38
|
+
/** 获取完整图谱数据的回调函数 */
|
|
39
|
+
getAllGraphData?: (params?: any) => void;
|
|
40
|
+
/** 搜索类型 */
|
|
41
|
+
searchType?: SearchType;
|
|
42
|
+
/** 高亮路径分析的节点ID数组 */
|
|
43
|
+
highPathAnalysis?: string[];
|
|
44
|
+
/** 图谱配置信息 */
|
|
45
|
+
graphInfo?: GraphInfo;
|
|
46
|
+
/** 下一步API(用于知识图谱展开) */
|
|
47
|
+
stepNextApi?: (params: any) => Promise<any>;
|
|
48
|
+
/** 知识卡片API */
|
|
49
|
+
knowledgeCardApi?: (params: any) => Promise<any>;
|
|
50
|
+
}
|
package/lib/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.cytoscape-container{width:100%;max-width:100%;margin:20px auto}.search-input{padding:8px 12px;width:300px;margin-bottom:10px;border:1px solid #ddd;border-radius:4px}.btn-group{margin-bottom:10px}.btn{padding:8px 16px;margin:0 5px;border:none;border-radius:4px;background:#4285f4;color:#fff;cursor:pointer}.btn:hover{background:#3367d6}.result-text{margin-bottom:10px;color:#333;font-size:14px}.cy-container{width:100%;height:calc(100vh - 180px)}.cy-container :global(.grayed){opacity:.3!important;background-color:#bdbdbd!important;color:#757575!important}.cy-container :global(.highlighted){background-color:#ffeb3b!important;border-color:#fbc02d!important;color:#333!important}.cy-container :global(.selected){border-color:#4caf50!important;background-color:#a5d6a7!important;color:#1b5e20!important}.cy-container .cy-edge:selected{line-color:#ea4335;line-width:3px;line-style:solid}.cy-container .cy-node:hover:not(:selected){background-color:#3367d6}.cy-container .cy-edge:hover:not(:selected){line-color:#757575}.path-nodes-container{margin-bottom:15px}.path-nodes-container h3{margin:10px 0;font-size:16px;color:#333}.node-input-row{display:flex;align-items:center;margin-bottom:8px}.node-input-row span{margin-right:10px;min-width:60px}.node-input-row input{flex:1;margin-right:10px}.remove-node-btn{background:#f44336;padding:6px 12px;font-size:12px}.add-node-btn{background:#4caf50;padding:8px 16px;margin-top:10px}.menuBtn:nth-child(1){transform:rotate(0) skew(31deg)}.menuBtn:nth-child(2){transform:rotate(51deg) skew(31deg)}.menuBtn:nth-child(3){transform:rotate(102deg) skew(31deg)}.menuBtn:nth-child(4){transform:rotate(153deg) skew(31deg)}.menuBtn:nth-child(5){transform:rotate(204deg) skew(31deg)}.menuBtn:nth-child(6){transform:rotate(255deg) skew(31deg)}.menuBtn:nth-child(7){transform:rotate(306deg) skew(35deg)}.menuBtn .menu-item{color:#fff;display:block;width:50px;height:20px;position:absolute;text-align:center;font-size:12px}.menuBtn .menu-item:hover{background:transparent!important}.menuBtn .menu-item{bottom:5px;right:19px;transform:skew(-30deg) translate(-9%) rotate(2deg) translateY(0)}.menuCertent{width:60px;height:60px;display:flex;align-items:center;justify-content:center;position:absolute;top:50%;left:50%;margin-top:-15%;margin-left:-15%;z-index:999;border-radius:50%;color:#fff;text-align:center;font-size:16px;cursor:pointer;border:2px solid #c9cec9}.opacity-30{opacity:.3}.cursor{cursor:pointer}.my-4px{margin:0
|
|
1
|
+
.cytoscape-container{width:100%;max-width:100%;margin:20px auto}.search-input{padding:8px 12px;width:300px;margin-bottom:10px;border:1px solid #ddd;border-radius:4px}.btn-group{margin-bottom:10px}.btn{padding:8px 16px;margin:0 5px;border:none;border-radius:4px;background:#4285f4;color:#fff;cursor:pointer}.btn:hover{background:#3367d6}.result-text{margin-bottom:10px;color:#333;font-size:14px}.cy-container{width:100%;height:calc(100vh - 180px)}.cy-container :global(.grayed){opacity:.3!important;background-color:#bdbdbd!important;color:#757575!important}.cy-container :global(.highlighted){background-color:#ffeb3b!important;border-color:#fbc02d!important;color:#333!important}.cy-container :global(.selected){border-color:#4caf50!important;background-color:#a5d6a7!important;color:#1b5e20!important}.cy-container .cy-edge:selected{line-color:#ea4335;line-width:3px;line-style:solid}.cy-container .cy-node:hover:not(:selected){background-color:#3367d6}.cy-container .cy-edge:hover:not(:selected){line-color:#757575}.path-nodes-container{margin-bottom:15px}.path-nodes-container h3{margin:10px 0;font-size:16px;color:#333}.node-input-row{display:flex;align-items:center;margin-bottom:8px}.node-input-row span{margin-right:10px;min-width:60px}.node-input-row input{flex:1;margin-right:10px}.remove-node-btn{background:#f44336;padding:6px 12px;font-size:12px}.add-node-btn{background:#4caf50;padding:8px 16px;margin-top:10px}.menuBtn:nth-child(1){transform:rotate(0) skew(31deg)}.menuBtn:nth-child(2){transform:rotate(51deg) skew(31deg)}.menuBtn:nth-child(3){transform:rotate(102deg) skew(31deg)}.menuBtn:nth-child(4){transform:rotate(153deg) skew(31deg)}.menuBtn:nth-child(5){transform:rotate(204deg) skew(31deg)}.menuBtn:nth-child(6){transform:rotate(255deg) skew(31deg)}.menuBtn:nth-child(7){transform:rotate(306deg) skew(35deg)}.menuBtn .menu-item{color:#fff;display:block;width:50px;height:20px;position:absolute;text-align:center;font-size:12px}.menuBtn .menu-item:hover{background:transparent!important}.menuBtn .menu-item{bottom:5px;right:19px;transform:skew(-30deg) translate(-9%) rotate(2deg) translateY(0)}.menuCertent{width:60px;height:60px;display:flex;align-items:center;justify-content:center;position:absolute;top:50%;left:50%;margin-top:-15%;margin-left:-15%;z-index:999;border-radius:50%;color:#fff;text-align:center;font-size:16px;cursor:pointer;border:2px solid #c9cec9}.opacity-30{opacity:.3}.cursor{cursor:pointer}.my-4px{margin:4px 0}.z-10{z-index:10}.hidden{display:none}.w-20px{width:20px}.rounded-50{border-radius:10%}.relaative{position:relative}.absolute{position:absolute}.w-100{width:100%}.graph-bar{display:flex;height:60px;background:#fff;box-shadow:0 4px 20px #100dae33;border-radius:6px;align-items:center}.graph-bar .graph-bar-min{display:flex}.graph-bar .graph-bar-menu{position:relative;cursor:pointer;margin:0 10px;white-space:nowrap;display:flex;align-items:center}.graph-bar .graph-bar-menu:hover .grap-menu-dropdown-item{color:#145afd}.graph-bar .grap-menu-dropdown{background:#fff;box-shadow:0 4px 20px #0000003b;border-radius:6px;position:absolute;padding:5px 0;z-index:99;top:60px}.graph-bar .grap-menu-dropdown p{white-space:nowrap;padding:5px 15px}.graph-bar .grap-menu-dropdown p:hover{background:#f5f5f5;color:#145afd}.graph-bar .grap-menu-dropdown-item{display:flex;cursor:pointer;flex-direction:column;align-items:center}.graph-bar .hide{display:none}.graph-bar .show{display:block}.gtaph-statics{right:0;z-index:1;background:#fff;padding:10px;border-radius:10px;width:200px;box-shadow:0 4px 20px #0000003b}.hove-active{cursor:pointer;font-size:14px}.hove-active:hover{color:#145afd}.query-node{width:300px;position:absolute;background-color:#fff;right:0;top:20px;padding:10px 20px;border-radius:10px}.path-node{width:380px;position:absolute;background-color:#fff;right:0;padding:10px 20px;border-radius:10px;box-shadow:0 4px 20px #0000003b;z-index:10}.path-node .title{display:flex;justify-content:space-between;height:35px;align-items:center;margin-bottom:10px;font-weight:700;font-size:14px}.path-node .search-input{margin-bottom:0;padding-bottom:5px}.path-node .btn-group{display:flex;justify-content:flex-end;margin-top:20px}.path-node .ant-select-suffix{width:10px}.query-node{width:300px;position:absolute;background-color:#fff;right:0;padding:10px 20px;border-radius:10px;box-shadow:0 4px 20px #0000003b}.query-node .title{display:flex;justify-content:space-between;height:35px;align-items:center;margin-bottom:10px;font-weight:700;font-size:14px}.radial-menu{position:relative;display:inline-flex;align-items:center;justify-content:center}.radial-svg{position:absolute;top:0;left:0}.sector-group{cursor:pointer;transition:all .2s ease}.sector-group .sector-path{transition:all .2s ease}.sector-group:hover .sector-path{filter:brightness(1.15) drop-shadow(0 2px 4px rgba(0,0,0,.3))}.sector-label{pointer-events:none;text-shadow:0 1px 3px rgba(0,0,0,.4);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.center-avatar{position:absolute;z-index:10;background:linear-gradient(135deg,#667eea,#764ba2);border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 15px #0000004d;transition:all .3s ease;overflow:hidden;color:#fff;font-weight:500}.center-avatar img{width:100%;height:100%;object-fit:cover}.center-avatar .center-text{font-size:14px;text-align:center}.center-avatar:hover{transform:scale(1.08);box-shadow:0 6px 20px #0006}.center-avatar:active{transform:scale(.95)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-kggraph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "A knowledge graph visualization component based on Cytoscape",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.es.js",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"./style.css": "./lib/style.css"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"lib"
|
|
15
|
+
"lib",
|
|
16
|
+
"README.md"
|
|
16
17
|
],
|
|
17
18
|
"style": "lib/style.css",
|
|
18
19
|
"keywords": [
|