react-kggraph 0.0.14 → 0.0.15

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 CHANGED
@@ -1,16 +1,183 @@
1
- # React + Vite
1
+ # react-kggraph
2
2
 
3
- This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3
+ 基于 Cytoscape.js React 知识图谱可视化组件库。
4
4
 
5
- Currently, two official plugins are available:
5
+ ## 特性
6
6
 
7
- - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
8
- - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
7
+ - 🚀 基于 Cytoscape.js 强大的图可视化能力
8
+ - 📊 支持多种布局算法(cose-bilkent、cise、fcose、storm)
9
+ - 🎨 支持节点、边的自定义样式
10
+ - 🔍 支持节点搜索、高亮路径分析
11
+ - 📦 支持知识图谱展开、节点详情查看
12
+ - 📱 响应式设计,支持缩放、拖拽等交互
9
13
 
10
- ## React Compiler
14
+ ## 安装
11
15
 
12
- The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
16
+ ```bash
17
+ npm install react-kggraph
18
+ ```
13
19
 
14
- ## Expanding the ESLint configuration
20
+ ## 依赖
15
21
 
16
- If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
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 Te from "./index.es15.js";
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 Ze = ({ data: te, getAllGraphData: S, searchType: je, highPathAnalysis: N = [], graphInfo: f, stepNextApi: oe, knowledgeCardApi: ne }) => {
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({}), [T, P] = m({}), [se, de] = m("cose-bilkent"), X = E(null), J = E(null), [ae, Q] = m(["", ""]), [c, C] = 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
- }), [j, V] = m({
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: T });
44
- }, [w(v), w(k), w(T)]), q(() => {
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
- ), R = e.edges().filter((l) => l.data("appendedBy") === d), B = r.merge(b).merge(R).filter((l) => l.data().zktype === o.zktype);
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(R).map((ye) => {
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: R } = A(n.data, { graphData: v, typeObj: k, relationObj: T, zktype: o.zktype });
167
- if (I(b), P(R), console.log(555e3, r), !((r == null ? void 0 : r.length) > 0)) {
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: T
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
- j.visible && /* @__PURE__ */ y(
332
+ R.visible && /* @__PURE__ */ y(
326
333
  "div",
327
334
  {
328
335
  style: {
329
336
  position: "absolute",
330
- left: `${j.x}px`,
331
- top: `${j.y}px`,
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: j.content
352
+ children: R.content
346
353
  }
347
354
  )
348
355
  ] }),
349
356
  /* @__PURE__ */ y(we, { ref: X }),
350
- /* @__PURE__ */ y(Te, { ref: J })
357
+ /* @__PURE__ */ y(je, { ref: J })
351
358
  ] }) });
352
359
  };
353
360
  export {
354
- Ze as default
361
+ Ye as default
355
362
  };
@@ -1,8 +1,3 @@
1
- import { SearchType } from './types';
2
- declare const CytoscapeReact: ({ data, getAllGraphData, searchType, highPathAnalysis, graphInfo, stepNextApi, knowledgeCardApi }: {
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 4px}.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)}
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.14",
3
+ "version": "0.0.15",
4
4
  "description": "A knowledge graph visualization component based on Cytoscape",
5
5
  "type": "module",
6
6
  "main": "./lib/index.es.js",