@vunk/graph 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,8 @@
1
1
  import VkGraph from './src/index.vue';
2
2
  export * as __VkGraph from './src/types';
3
+ export { useEdgeReducer } from './src/useEdgeReducer';
3
4
  export { useGraph } from './src/useGraph';
5
+ export { useNodeReducer } from './src/useNodeReducer';
4
6
  export { useSigma } from './src/useSigma';
5
7
  export { VkGraph, };
6
8
  export default VkGraph;
@@ -1,4 +1,4 @@
1
- import { provide, inject, defineComponent, ref, onMounted, onBeforeUnmount, createElementBlock, openBlock, createElementVNode, createVNode, unref, withCtx, createBlock, createCommentVNode, renderSlot } from 'vue';
1
+ import { shallowReactive, provide, inject, defineComponent, ref, onMounted, onBeforeUnmount, createElementBlock, openBlock, createElementVNode, createVNode, unref, withCtx, createBlock, createCommentVNode, renderSlot } from 'vue';
2
2
  import { VkLabelProvider } from '@vunk/graph/components/label';
3
3
  import { VkPopupProvider } from '@vunk/graph/components/popup';
4
4
  import Sigma from 'sigma';
@@ -17,20 +17,96 @@ const emits = {
17
17
  load: (e) => e
18
18
  };
19
19
 
20
- const key$1 = "vunk-graph";
20
+ const key$3 = "vunk-graph-edge_reducer";
21
+ function initEdgeReducer() {
22
+ const middlewares = shallowReactive([]);
23
+ function addMiddleware(middleware) {
24
+ middlewares.push(middleware);
25
+ }
26
+ function removeMiddleware(middleware) {
27
+ const index = middlewares.indexOf(middleware);
28
+ if (index > -1) {
29
+ middlewares.splice(index, 1);
30
+ }
31
+ }
32
+ function edgeReducer(edge, data) {
33
+ let currentData = { ...data };
34
+ for (const middleware of middlewares) {
35
+ const res = middleware(edge, currentData);
36
+ if (res) {
37
+ currentData = { ...currentData, ...res };
38
+ }
39
+ }
40
+ return currentData;
41
+ }
42
+ const context = {
43
+ edgeReducer,
44
+ addMiddleware,
45
+ removeMiddleware
46
+ };
47
+ provide(key$3, context);
48
+ return context;
49
+ }
50
+ function useEdgeReducer() {
51
+ const edgeReducerContext = inject(key$3);
52
+ if (!edgeReducerContext) {
53
+ throw new Error("EdgeReducer is not provided");
54
+ }
55
+ return edgeReducerContext;
56
+ }
57
+
58
+ const key$2 = "vunk-graph";
21
59
  function initGraph() {
22
60
  const graph = new Graph();
23
- provide(key$1, graph);
61
+ provide(key$2, graph);
24
62
  return graph;
25
63
  }
26
64
  function useGraph() {
27
- const graph = inject(key$1);
65
+ const graph = inject(key$2);
28
66
  if (!graph) {
29
67
  throw new Error("Graph is not provided");
30
68
  }
31
69
  return graph;
32
70
  }
33
71
 
72
+ const key$1 = "vunk-graph-node_reducer";
73
+ function initNodeReducer() {
74
+ const middlewares = shallowReactive([]);
75
+ function addMiddleware(middleware) {
76
+ middlewares.push(middleware);
77
+ }
78
+ function removeMiddleware(middleware) {
79
+ const index = middlewares.indexOf(middleware);
80
+ if (index > -1) {
81
+ middlewares.splice(index, 1);
82
+ }
83
+ }
84
+ function nodeReducer(node, data) {
85
+ let currentData = { ...data };
86
+ for (const middleware of middlewares) {
87
+ const res = middleware(node, currentData);
88
+ if (res) {
89
+ currentData = { ...currentData, ...res };
90
+ }
91
+ }
92
+ return currentData;
93
+ }
94
+ const context = {
95
+ nodeReducer,
96
+ addMiddleware,
97
+ removeMiddleware
98
+ };
99
+ provide(key$1, context);
100
+ return context;
101
+ }
102
+ function useNodeReducer() {
103
+ const nodeReducerContext = inject(key$1);
104
+ if (!nodeReducerContext) {
105
+ throw new Error("NodeReducer is not provided");
106
+ }
107
+ return nodeReducerContext;
108
+ }
109
+
34
110
  const key = "vunk-graph-sigma";
35
111
  function provideSigma(sigma) {
36
112
  provide(key, sigma);
@@ -54,6 +130,8 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
54
130
  setup(__props, { emit: __emit }) {
55
131
  const props = __props;
56
132
  const emit = __emit;
133
+ const { nodeReducer } = initNodeReducer();
134
+ const { edgeReducer } = initEdgeReducer();
57
135
  const elRef = ref();
58
136
  const graph = initGraph();
59
137
  const ready = ref(false);
@@ -61,6 +139,8 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
61
139
  const sigma = new Sigma(graph, elRef.value, {
62
140
  renderEdgeLabels: true,
63
141
  enableEdgeEvents: true,
142
+ nodeReducer,
143
+ edgeReducer,
64
144
  ...props.defaultOptions
65
145
  });
66
146
  provideSigma(sigma);
@@ -109,4 +189,4 @@ _sfc_main.install = (app) => {
109
189
  app.component(_sfc_main.name || "VkGraph", _sfc_main);
110
190
  };
111
191
 
112
- export { _sfc_main as VkGraph, types as __VkGraph, _sfc_main as default, useGraph, useSigma };
192
+ export { _sfc_main as VkGraph, types as __VkGraph, _sfc_main as default, useEdgeReducer, useGraph, useNodeReducer, useSigma };
@@ -14,6 +14,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
14
14
  onLoad?: ((e: import("./types").LoadEvent) => any) | undefined;
15
15
  }> & {}>;
16
16
  emit: (event: "load", e: import("./types").LoadEvent) => void;
17
+ nodeReducer: (node: string, data: any) => Partial<import("sigma/types").NodeDisplayData>;
18
+ edgeReducer: (edge: string, data: any) => Partial<import("sigma/types").EdgeDisplayData>;
17
19
  elRef: Ref<HTMLDivElement, HTMLDivElement>;
18
20
  graph: import("graphology").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
19
21
  ready: Ref<boolean, boolean>;
@@ -22,29 +24,29 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
22
24
  }>[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
23
25
  readonly VkPopupProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
24
26
  modelValue: {
25
- type: BooleanConstructor;
26
- default: boolean;
27
+ type: StringConstructor;
28
+ default: undefined;
27
29
  };
28
- closeable: {
29
- type: BooleanConstructor;
30
- default: boolean;
30
+ trigger: {
31
+ type: import("vue").PropType<"hover" | "click" | "none">;
32
+ default: string;
31
33
  };
32
34
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
33
35
  'update:modelValue': null;
34
36
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
35
37
  modelValue: {
36
- type: BooleanConstructor;
37
- default: boolean;
38
+ type: StringConstructor;
39
+ default: undefined;
38
40
  };
39
- closeable: {
40
- type: BooleanConstructor;
41
- default: boolean;
41
+ trigger: {
42
+ type: import("vue").PropType<"hover" | "click" | "none">;
43
+ default: string;
42
44
  };
43
45
  }>> & Readonly<{
44
46
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
45
47
  }>, {
46
- modelValue: boolean;
47
- closeable: boolean;
48
+ modelValue: string;
49
+ trigger: "none" | "click" | "hover";
48
50
  }, {}, {
49
51
  VkGraphViewUi: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
50
52
  coordinates: {
@@ -0,0 +1,13 @@
1
+ import type { EdgeDisplayData } from 'sigma/types';
2
+ type Middleware = (edge: string, data: any) => Partial<EdgeDisplayData> | null;
3
+ export declare function initEdgeReducer(): {
4
+ edgeReducer: (edge: string, data: any) => Partial<EdgeDisplayData>;
5
+ addMiddleware: (middleware: Middleware) => void;
6
+ removeMiddleware: (middleware: Middleware) => void;
7
+ };
8
+ export declare function useEdgeReducer(): {
9
+ edgeReducer: (edge: string, data: any) => Partial<EdgeDisplayData> | null;
10
+ addMiddleware: (middleware: Middleware) => void;
11
+ removeMiddleware: (middleware: Middleware) => void;
12
+ };
13
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { NodeDisplayData } from 'sigma/types';
2
+ type Middleware = (node: string, data: any) => Partial<NodeDisplayData> | null;
3
+ export declare function initNodeReducer(): {
4
+ nodeReducer: (node: string, data: any) => Partial<NodeDisplayData>;
5
+ addMiddleware: (middleware: Middleware) => void;
6
+ removeMiddleware: (middleware: Middleware) => void;
7
+ };
8
+ export declare function useNodeReducer(): {
9
+ nodeReducer: (node: string, data: any) => Partial<NodeDisplayData> | null;
10
+ addMiddleware: (middleware: Middleware) => void;
11
+ removeMiddleware: (middleware: Middleware) => void;
12
+ };
13
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, reactive, watch, onMounted, onBeforeUnmount, createBlock, createCommentVNode, openBlock, unref, withCtx, renderSlot } from 'vue';
2
2
  import { ContextMenu } from '@vunk/graph/components/context-menu';
3
- import { useSigma, useGraph } from '@vunk/graph/components/graph';
3
+ import { useSigma, useGraph, useEdgeReducer } from '@vunk/graph/components/graph';
4
4
 
5
5
  const props = {
6
6
  /**
@@ -37,6 +37,13 @@ const props = {
37
37
  activeColor: {
38
38
  type: String,
39
39
  default: "#409EFF"
40
+ },
41
+ /**
42
+ * before leave 当返回 false 时阻止隐藏
43
+ */
44
+ beforeLeave: {
45
+ type: Function,
46
+ default: void 0
40
47
  }
41
48
  };
42
49
  const emits = {
@@ -54,6 +61,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
54
61
  const emit = __emit;
55
62
  const sigma = useSigma();
56
63
  const graph = useGraph();
64
+ const { addMiddleware, removeMiddleware } = useEdgeReducer();
57
65
  const contextmenuState = reactive({
58
66
  edge: "",
59
67
  show: false,
@@ -62,34 +70,25 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
62
70
  y: 0
63
71
  }
64
72
  });
65
- let oldNodeReducer = null;
66
- let oldEdgeReducer = null;
67
- let isApplied = false;
68
- watch(() => props.modelValue, (edgeId) => {
69
- if (edgeId && graph.hasEdge(edgeId)) {
70
- if (!isApplied) {
71
- oldNodeReducer = sigma.getSetting("nodeReducer");
72
- oldEdgeReducer = sigma.getSetting("edgeReducer");
73
- isApplied = true;
74
- }
75
- sigma.setSetting("edgeReducer", (edge, data) => {
76
- const baseData = oldEdgeReducer ? oldEdgeReducer(edge, data) : data;
77
- if (edge === edgeId) {
78
- const res = { ...baseData, zIndex: 10, forceLabel: true };
79
- if (props.activeColor) {
80
- res.color = props.activeColor;
81
- }
82
- return res;
83
- }
84
- return baseData;
85
- });
86
- } else {
87
- if (isApplied) {
88
- sigma.setSetting("nodeReducer", oldNodeReducer);
89
- sigma.setSetting("edgeReducer", oldEdgeReducer);
90
- isApplied = false;
73
+ function edgeMiddleware(edge) {
74
+ const edgeId = props.modelValue;
75
+ if (edgeId && graph.hasEdge(edgeId) && edge === edgeId) {
76
+ const res = { zIndex: 10, forceLabel: true };
77
+ if (props.activeColor) {
78
+ res.color = props.activeColor;
91
79
  }
80
+ return res;
92
81
  }
82
+ return null;
83
+ }
84
+ watch(() => props.modelValue, () => {
85
+ sigma.refresh();
86
+ });
87
+ onMounted(() => {
88
+ addMiddleware(edgeMiddleware);
89
+ });
90
+ onBeforeUnmount(() => {
91
+ removeMiddleware(edgeMiddleware);
93
92
  });
94
93
  let enterTimer = null;
95
94
  let leaveTimer = null;
@@ -104,6 +103,11 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
104
103
  leaveTimer = setTimeout(() => {
105
104
  if (props.contextMenu && contextmenuState.show)
106
105
  return;
106
+ if (props.beforeLeave) {
107
+ const v = props.beforeLeave();
108
+ if (v === false)
109
+ return;
110
+ }
107
111
  emit("update:modelValue", "");
108
112
  }, props.leaveDelay);
109
113
  }
@@ -116,10 +120,6 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
116
120
  clearTimeout(leaveTimer);
117
121
  sigma.off("enterEdge", enterHandler);
118
122
  sigma.off("leaveEdge", leaveHandler);
119
- if (isApplied) {
120
- sigma.setSetting("nodeReducer", oldNodeReducer);
121
- sigma.setSetting("edgeReducer", oldEdgeReducer);
122
- }
123
123
  });
124
124
  onMounted(() => {
125
125
  sigma.on("rightClickEdge", rightClickHandler);
@@ -1,3 +1,5 @@
1
+ import type { AnyFunc } from '@vunk/shared';
2
+ import type { PropType } from 'vue';
1
3
  import type { RightClickEvent } from './types';
2
4
  export declare const props: {
3
5
  /**
@@ -35,6 +37,13 @@ export declare const props: {
35
37
  type: StringConstructor;
36
38
  default: string;
37
39
  };
40
+ /**
41
+ * before leave 当返回 false 时阻止隐藏
42
+ */
43
+ beforeLeave: {
44
+ type: PropType<AnyFunc>;
45
+ default: undefined;
46
+ };
38
47
  };
39
48
  export declare const emits: {
40
49
  'update:modelValue': null;
@@ -19,6 +19,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
19
19
  type: StringConstructor;
20
20
  default: string;
21
21
  };
22
+ beforeLeave: {
23
+ type: import("vue").PropType<import("@vunk/shared").AnyFunc>;
24
+ default: undefined;
25
+ };
22
26
  }>, {
23
27
  props: import("@vue/shared").LooseRequired<Readonly<import("vue").ExtractPropTypes<{
24
28
  contextMenu: {
@@ -41,6 +45,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
41
45
  type: StringConstructor;
42
46
  default: string;
43
47
  };
48
+ beforeLeave: {
49
+ type: import("vue").PropType<import("@vunk/shared").AnyFunc>;
50
+ default: undefined;
51
+ };
44
52
  }>> & Readonly<{
45
53
  onRightClick?: ((e: import("./types").RightClickEvent) => any) | undefined;
46
54
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
@@ -48,6 +56,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
48
56
  emit: ((event: "rightClick", e: import("./types").RightClickEvent) => void) & ((event: "update:modelValue", ...args: any[]) => void);
49
57
  sigma: import("sigma").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
50
58
  graph: import("graphology").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
59
+ addMiddleware: (middleware: (edge: string, data: any) => Partial<import("sigma/types").EdgeDisplayData> | null) => void;
60
+ removeMiddleware: (middleware: (edge: string, data: any) => Partial<import("sigma/types").EdgeDisplayData> | null) => void;
51
61
  contextmenuState: {
52
62
  edge: string;
53
63
  show: boolean;
@@ -56,9 +66,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
56
66
  y: number;
57
67
  };
58
68
  };
59
- oldNodeReducer: any;
60
- oldEdgeReducer: any;
61
- isApplied: boolean;
69
+ edgeMiddleware: (edge: string) => any;
62
70
  enterTimer: any;
63
71
  leaveTimer: any;
64
72
  enterHandler: ({ edge }: {
@@ -181,6 +189,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
181
189
  type: StringConstructor;
182
190
  default: string;
183
191
  };
192
+ beforeLeave: {
193
+ type: import("vue").PropType<import("@vunk/shared").AnyFunc>;
194
+ default: undefined;
195
+ };
184
196
  }>> & Readonly<{
185
197
  onRightClick?: ((e: import("./types").RightClickEvent) => any) | undefined;
186
198
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
@@ -190,5 +202,6 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
190
202
  leaveDelay: number;
191
203
  enterDelay: number;
192
204
  activeColor: string;
205
+ beforeLeave: import("@vunk/shared").AnyFunc;
193
206
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
194
207
  export default _default;
@@ -1,4 +1,4 @@
1
- import { useSigma } from '@vunk/graph/composables';
1
+ import { useSigma, useNodeReducer, useEdgeReducer } from '@vunk/graph/composables';
2
2
  import { defineComponent, watch, onMounted, onUnmounted, renderSlot } from 'vue';
3
3
  import { _ as _export_sfc } from '../_plugin-vue_export-helper.mjs';
4
4
 
@@ -43,52 +43,49 @@ var _sfc_main = defineComponent({
43
43
  setup(props2, { emit }) {
44
44
  const sigma = useSigma();
45
45
  const graph = sigma.getGraph();
46
- let oldNodeReducer = null;
47
- let oldEdgeReducer = null;
48
- let isApplied = false;
49
- watch(() => props2.modelValue, (nodeId) => {
50
- if (nodeId) {
51
- if (!isApplied) {
52
- oldNodeReducer = sigma.getSetting("nodeReducer");
53
- oldEdgeReducer = sigma.getSetting("edgeReducer");
54
- isApplied = true;
55
- }
56
- const hoveredColor = sigma.getNodeDisplayData(nodeId)?.color || "";
57
- sigma.setSetting("nodeReducer", (node, data) => {
58
- const baseData = oldNodeReducer ? oldNodeReducer(node, data) : data;
59
- if (node === nodeId) {
60
- return { ...baseData, zIndex: 3 };
61
- }
62
- if (graph.hasEdge(node, nodeId) || graph.hasEdge(nodeId, node)) {
63
- return { ...baseData, zIndex: 2 };
64
- }
65
- return {
66
- ...baseData,
67
- zIndex: 0,
68
- label: "",
69
- color: props2.nodeFadeColor,
70
- highlighted: false
71
- };
72
- });
73
- sigma.setSetting("edgeReducer", (edge, data) => {
74
- const baseData = oldEdgeReducer ? oldEdgeReducer(edge, data) : data;
75
- if (graph.hasExtremity(edge, nodeId)) {
76
- return { ...baseData, color: hoveredColor, zIndex: 10 };
77
- }
78
- return {
79
- ...baseData,
80
- color: props2.edgeFadeColor,
81
- label: "",
82
- zIndex: 0
83
- };
84
- });
85
- } else {
86
- if (isApplied) {
87
- sigma.setSetting("nodeReducer", oldNodeReducer);
88
- sigma.setSetting("edgeReducer", oldEdgeReducer);
89
- isApplied = false;
90
- }
46
+ const { addMiddleware: addNodeMiddleware, removeMiddleware: removeNodeMiddleware } = useNodeReducer();
47
+ const { addMiddleware: addEdgeMiddleware, removeMiddleware: removeEdgeMiddleware } = useEdgeReducer();
48
+ const nodeMiddleware = (node) => {
49
+ const nodeId = props2.modelValue;
50
+ if (!nodeId)
51
+ return null;
52
+ if (node === nodeId) {
53
+ return { zIndex: 3 };
91
54
  }
55
+ if (graph.hasEdge(node, nodeId) || graph.hasEdge(nodeId, node)) {
56
+ return { zIndex: 2 };
57
+ }
58
+ return {
59
+ zIndex: 0,
60
+ label: "",
61
+ color: props2.nodeFadeColor,
62
+ highlighted: false
63
+ };
64
+ };
65
+ const edgeMiddleware = (edge) => {
66
+ const nodeId = props2.modelValue;
67
+ if (!nodeId)
68
+ return null;
69
+ const hoveredColor = sigma.getNodeDisplayData(nodeId)?.color || "";
70
+ if (graph.hasExtremity(edge, nodeId)) {
71
+ return { color: hoveredColor, zIndex: 10 };
72
+ }
73
+ return {
74
+ color: props2.edgeFadeColor,
75
+ label: "",
76
+ zIndex: 0
77
+ };
78
+ };
79
+ watch(() => props2.modelValue, () => {
80
+ sigma.refresh();
81
+ });
82
+ onMounted(() => {
83
+ addNodeMiddleware(nodeMiddleware);
84
+ addEdgeMiddleware(edgeMiddleware);
85
+ });
86
+ onUnmounted(() => {
87
+ removeNodeMiddleware(nodeMiddleware);
88
+ removeEdgeMiddleware(edgeMiddleware);
92
89
  });
93
90
  let timer = null;
94
91
  const enterHandler = ({ node }) => {
@@ -108,10 +105,8 @@ var _sfc_main = defineComponent({
108
105
  clearTimeout(timer);
109
106
  sigma.off("enterNode", enterHandler);
110
107
  sigma.off("leaveNode", leaveHandler);
111
- if (isApplied) {
112
- sigma.setSetting("nodeReducer", oldNodeReducer);
113
- sigma.setSetting("edgeReducer", oldEdgeReducer);
114
- }
108
+ removeNodeMiddleware(nodeMiddleware);
109
+ removeEdgeMiddleware(edgeMiddleware);
115
110
  });
116
111
  return {};
117
112
  }
@@ -4,6 +4,20 @@ import { defineComponent, reactive, onMounted, onBeforeUnmount, resolveComponent
4
4
  import { _ as _export_sfc } from '../_plugin-vue_export-helper.mjs';
5
5
 
6
6
  const props = {
7
+ /**
8
+ * 是否启用popup功能
9
+ */
10
+ popup: {
11
+ type: Boolean,
12
+ default: false
13
+ },
14
+ /**
15
+ * 触发方式,可选值有 click 和 hover
16
+ */
17
+ popupTrigger: {
18
+ type: String,
19
+ default: "hover"
20
+ },
7
21
  /**
8
22
  * 是否启用右键菜单功能
9
23
  */
@@ -31,6 +45,13 @@ const props = {
31
45
  enterDelay: {
32
46
  type: Number,
33
47
  default: 0
48
+ },
49
+ /**
50
+ * before leave 当返回 false 时阻止隐藏
51
+ */
52
+ beforeLeave: {
53
+ type: Function,
54
+ default: void 0
34
55
  }
35
56
  };
36
57
  const emits = {
@@ -68,6 +89,11 @@ var _sfc_main = defineComponent({
68
89
  leaveTimer = setTimeout(() => {
69
90
  if (props2.contextMenu && contextmenuState.show)
70
91
  return;
92
+ if (props2.beforeLeave) {
93
+ const v = props2.beforeLeave();
94
+ if (v === false)
95
+ return;
96
+ }
71
97
  emit("update:modelValue", "");
72
98
  }, props2.leaveDelay);
73
99
  };
@@ -1,5 +1,21 @@
1
+ import type { AnyFunc } from '@vunk/shared';
2
+ import type { PropType } from 'vue';
1
3
  import type { RightClickEvent } from './types';
2
4
  export declare const props: {
5
+ /**
6
+ * 是否启用popup功能
7
+ */
8
+ popup: {
9
+ type: BooleanConstructor;
10
+ default: boolean;
11
+ };
12
+ /**
13
+ * 触发方式,可选值有 click 和 hover
14
+ */
15
+ popupTrigger: {
16
+ type: PropType<"click" | "hover">;
17
+ default: string;
18
+ };
3
19
  /**
4
20
  * 是否启用右键菜单功能
5
21
  */
@@ -28,6 +44,13 @@ export declare const props: {
28
44
  type: NumberConstructor;
29
45
  default: number;
30
46
  };
47
+ /**
48
+ * before leave 当返回 false 时阻止隐藏
49
+ */
50
+ beforeLeave: {
51
+ type: PropType<AnyFunc>;
52
+ default: undefined;
53
+ };
31
54
  };
32
55
  export declare const emits: {
33
56
  'update:modelValue': null;
@@ -1,4 +1,12 @@
1
1
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
+ popup: {
3
+ type: BooleanConstructor;
4
+ default: boolean;
5
+ };
6
+ popupTrigger: {
7
+ type: import("vue").PropType<"click" | "hover">;
8
+ default: string;
9
+ };
2
10
  contextMenu: {
3
11
  type: BooleanConstructor;
4
12
  default: boolean;
@@ -15,6 +23,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
15
23
  type: NumberConstructor;
16
24
  default: number;
17
25
  };
26
+ beforeLeave: {
27
+ type: import("vue").PropType<import("@vunk/shared").AnyFunc>;
28
+ default: undefined;
29
+ };
18
30
  }>, {
19
31
  changeContextmenuShow: (show: boolean) => void;
20
32
  contextmenuState: {
@@ -29,6 +41,14 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
29
41
  'update:modelValue': null;
30
42
  rightClick: (e: import("./types").RightClickEvent) => import("./types").RightClickEvent;
31
43
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
44
+ popup: {
45
+ type: BooleanConstructor;
46
+ default: boolean;
47
+ };
48
+ popupTrigger: {
49
+ type: import("vue").PropType<"click" | "hover">;
50
+ default: string;
51
+ };
32
52
  contextMenu: {
33
53
  type: BooleanConstructor;
34
54
  default: boolean;
@@ -45,6 +65,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
45
65
  type: NumberConstructor;
46
66
  default: number;
47
67
  };
68
+ beforeLeave: {
69
+ type: import("vue").PropType<import("@vunk/shared").AnyFunc>;
70
+ default: undefined;
71
+ };
48
72
  }>> & Readonly<{
49
73
  onRightClick?: ((e: import("./types").RightClickEvent) => any) | undefined;
50
74
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
@@ -53,6 +77,9 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
53
77
  modelValue: string;
54
78
  leaveDelay: number;
55
79
  enterDelay: number;
80
+ beforeLeave: import("@vunk/shared").AnyFunc;
81
+ popup: boolean;
82
+ popupTrigger: "click" | "hover";
56
83
  }, {}, {
57
84
  ContextMenu: {
58
85
  new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
@@ -1,5 +1,6 @@
1
+ import VkPopupEdge from './src/edge.vue';
1
2
  import VkPopup from './src/index.vue';
2
3
  import VkPopupProvider from './src/provider.vue';
3
4
  export * as __VkPopup from './src/types';
4
- export { VkPopup, VkPopupProvider, };
5
+ export { VkPopup, VkPopupEdge, VkPopupProvider, };
5
6
  export default VkPopup;
@@ -1,5 +1,6 @@
1
- import { defineComponent, shallowRef, ref, computed, onMounted, onBeforeUnmount, createBlock, openBlock, unref, withCtx, createElementVNode, mergeProps, renderSlot, resolveComponent, withDirectives, createVNode, resolveDynamicComponent, vShow } from 'vue';
1
+ import { defineComponent, shallowRef, ref, computed, watch, onBeforeUnmount, createBlock, openBlock, unref, withCtx, createElementVNode, mergeProps, renderSlot, resolveComponent, withDirectives, createVNode, resolveDynamicComponent, vShow } from 'vue';
2
2
  import { useSigma, useGraph } from '@vunk/graph/composables';
3
+ import { useModelComputed } from '@vunk/core/composables';
3
4
  import { createGlobalRenderer } from '@vunk/core/components/global-renderer';
4
5
  import { VkGraphViewUi } from '@vunk/graph/components/graph-view-ui';
5
6
  import { _ as _export_sfc } from '../_plugin-vue_export-helper.mjs';
@@ -10,22 +11,129 @@ const {
10
11
  } = createGlobalRenderer("vunk-graph-popup");
11
12
 
12
13
  const props = {
14
+ /**
15
+ * 当前激活的node或edge
16
+ */
13
17
  modelValue: {
14
- type: Boolean,
15
- default: false
18
+ type: String,
19
+ default: void 0
16
20
  },
17
21
  /**
18
- * @description 是否显示关闭按钮
22
+ * 触发方式
19
23
  */
20
- closeable: {
21
- type: Boolean,
22
- default: false
24
+ trigger: {
25
+ type: String,
26
+ default: "click"
23
27
  }
24
28
  };
25
29
  const emits = {
26
30
  "update:modelValue": null
27
31
  };
28
32
 
33
+ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
34
+ ...{
35
+ name: "VkPopupEdge",
36
+ inheritAttrs: false
37
+ },
38
+ __name: "edge",
39
+ props: props,
40
+ emits,
41
+ setup(__props, { emit: __emit }) {
42
+ const props = __props;
43
+ const emit = __emit;
44
+ const model = useModelComputed({
45
+ default: "",
46
+ key: "modelValue"
47
+ }, props, emit);
48
+ const sigma = useSigma();
49
+ const graph = useGraph();
50
+ const coordinates = shallowRef([0, 0]);
51
+ const currentEdge = ref("");
52
+ const attributes = ref({});
53
+ const state = computed(() => ({
54
+ edge: currentEdge.value,
55
+ attributes: attributes.value,
56
+ visible: !!model.value,
57
+ coordinates: coordinates.value
58
+ }));
59
+ watch(() => props.modelValue, (edge) => {
60
+ if (edge) {
61
+ const source = graph.source(edge);
62
+ const target = graph.target(edge);
63
+ const sourceAttrs = graph.getNodeAttributes(source);
64
+ const targetAttrs = graph.getNodeAttributes(target);
65
+ if (typeof sourceAttrs.x === "number" && typeof sourceAttrs.y === "number" && typeof targetAttrs.x === "number" && typeof targetAttrs.y === "number") {
66
+ const x = (sourceAttrs.x + targetAttrs.x) / 2;
67
+ const y = (sourceAttrs.y + targetAttrs.y) / 2;
68
+ currentEdge.value = edge;
69
+ attributes.value = graph.getEdgeAttributes(edge);
70
+ coordinates.value = [x, y];
71
+ }
72
+ } else {
73
+ currentEdge.value = "";
74
+ attributes.value = {};
75
+ }
76
+ }, { immediate: true });
77
+ function onClickEdge(e) {
78
+ model.value = e.edge;
79
+ }
80
+ function onEnterEdge(e) {
81
+ model.value = e.edge;
82
+ }
83
+ function onLeaveEdge() {
84
+ model.value = "";
85
+ }
86
+ function onClickStage() {
87
+ model.value = "";
88
+ }
89
+ watch(() => props.trigger, (val) => {
90
+ sigma.off("clickEdge", onClickEdge);
91
+ sigma.off("enterEdge", onEnterEdge);
92
+ sigma.off("leaveEdge", onLeaveEdge);
93
+ sigma.off("clickStage", onClickStage);
94
+ if (val === "click") {
95
+ sigma.on("clickEdge", onClickEdge);
96
+ sigma.on("clickStage", onClickStage);
97
+ } else if (val === "hover") {
98
+ sigma.on("enterEdge", onEnterEdge);
99
+ sigma.on("leaveEdge", onLeaveEdge);
100
+ sigma.on("clickStage", onClickStage);
101
+ }
102
+ }, { immediate: true });
103
+ onBeforeUnmount(() => {
104
+ sigma.off("clickEdge", onClickEdge);
105
+ sigma.off("enterEdge", onEnterEdge);
106
+ sigma.off("leaveEdge", onLeaveEdge);
107
+ sigma.off("clickStage", onClickStage);
108
+ });
109
+ return (_ctx, _cache) => {
110
+ return openBlock(), createBlock(unref(GlobalRendererTemplate), {
111
+ active: state.value.visible,
112
+ data: state.value
113
+ }, {
114
+ default: withCtx(() => [
115
+ createElementVNode(
116
+ "div",
117
+ mergeProps({ class: "vkg-popup" }, _ctx.$attrs),
118
+ [
119
+ renderSlot(_ctx.$slots, "default", {
120
+ edge: state.value.edge,
121
+ attributes: state.value.attributes,
122
+ coordinates: state.value.coordinates,
123
+ visible: state.value.visible
124
+ })
125
+ ],
126
+ 16
127
+ /* FULL_PROPS */
128
+ )
129
+ ]),
130
+ _: 3
131
+ /* FORWARDED */
132
+ }, 8, ["active", "data"]);
133
+ };
134
+ }
135
+ });
136
+
29
137
  var _sfc_main$1 = /* @__PURE__ */ defineComponent({
30
138
  ...{
31
139
  name: "VkPopup",
@@ -39,39 +147,67 @@ var _sfc_main$1 = /* @__PURE__ */ defineComponent({
39
147
  const emit = __emit;
40
148
  const sigma = useSigma();
41
149
  const graph = useGraph();
150
+ const model = useModelComputed({
151
+ default: "",
152
+ key: "modelValue"
153
+ }, props, emit);
42
154
  const coordinates = shallowRef([0, 0]);
43
155
  const currentNode = ref("");
44
156
  const attributes = ref({});
45
157
  const state = computed(() => ({
46
158
  node: currentNode.value,
47
159
  attributes: attributes.value,
48
- visible: props.modelValue,
160
+ visible: !!model.value,
49
161
  coordinates: coordinates.value
50
162
  }));
163
+ watch(model, (node) => {
164
+ if (node) {
165
+ const attrs = graph.getNodeAttributes(node);
166
+ if (typeof attrs.x === "number" && typeof attrs.y === "number") {
167
+ currentNode.value = node;
168
+ attributes.value = attrs;
169
+ coordinates.value = [attrs.x, attrs.y];
170
+ }
171
+ } else {
172
+ currentNode.value = "";
173
+ attributes.value = {};
174
+ }
175
+ }, { immediate: true });
51
176
  function onClickNode(e) {
52
- const { node } = e;
53
- const attrs = graph.getNodeAttributes(node);
54
- if (typeof attrs.x !== "number" || typeof attrs.y !== "number")
55
- return;
56
- currentNode.value = node;
57
- attributes.value = attrs;
58
- coordinates.value = [attrs.x, attrs.y];
59
- emit("update:modelValue", true);
177
+ model.value = e.node;
178
+ }
179
+ function onEnterNode(e) {
180
+ model.value = e.node;
181
+ }
182
+ function onLeaveNode() {
183
+ model.value = "";
60
184
  }
61
185
  function onClickStage() {
62
- emit("update:modelValue", false);
186
+ model.value = "";
63
187
  }
64
- onMounted(() => {
65
- sigma.on("clickNode", onClickNode);
66
- sigma.on("clickStage", onClickStage);
67
- });
188
+ watch(() => props.trigger, (val) => {
189
+ sigma.off("clickNode", onClickNode);
190
+ sigma.off("enterNode", onEnterNode);
191
+ sigma.off("leaveNode", onLeaveNode);
192
+ sigma.off("clickStage", onClickStage);
193
+ if (val === "click") {
194
+ sigma.on("clickNode", onClickNode);
195
+ sigma.on("clickStage", onClickStage);
196
+ } else if (val === "hover") {
197
+ sigma.on("enterNode", onEnterNode);
198
+ sigma.on("leaveNode", onLeaveNode);
199
+ sigma.on("clickStage", onClickStage);
200
+ }
201
+ }, { immediate: true });
68
202
  onBeforeUnmount(() => {
69
203
  sigma.off("clickNode", onClickNode);
204
+ sigma.off("enterNode", onEnterNode);
205
+ sigma.off("leaveNode", onLeaveNode);
70
206
  sigma.off("clickStage", onClickStage);
71
207
  });
72
208
  return (_ctx, _cache) => {
73
209
  return openBlock(), createBlock(unref(GlobalRendererTemplate), {
74
- active: _ctx.modelValue,
210
+ active: state.value.visible,
75
211
  data: state.value
76
212
  }, {
77
213
  default: withCtx(() => [
@@ -150,8 +286,4 @@ var types = /*#__PURE__*/Object.freeze({
150
286
  __proto__: null
151
287
  });
152
288
 
153
- _sfc_main$1.install = (app) => {
154
- app.component(_sfc_main$1.name || "VkPopup", _sfc_main$1);
155
- };
156
-
157
- export { _sfc_main$1 as VkPopup, provider as VkPopupProvider, types as __VkPopup, _sfc_main$1 as default };
289
+ export { _sfc_main$1 as VkPopup, _sfc_main$2 as VkPopupEdge, provider as VkPopupProvider, types as __VkPopup, _sfc_main$1 as default };
@@ -1,14 +1,18 @@
1
+ import type { PropType } from 'vue';
1
2
  export declare const props: {
3
+ /**
4
+ * 当前激活的node或edge
5
+ */
2
6
  modelValue: {
3
- type: BooleanConstructor;
4
- default: boolean;
7
+ type: StringConstructor;
8
+ default: undefined;
5
9
  };
6
10
  /**
7
- * @description 是否显示关闭按钮
11
+ * 触发方式
8
12
  */
9
- closeable: {
10
- type: BooleanConstructor;
11
- default: boolean;
13
+ trigger: {
14
+ type: PropType<"hover" | "click" | "none">;
15
+ default: string;
12
16
  };
13
17
  };
14
18
  export declare const emits: {
@@ -0,0 +1,84 @@
1
+ import type { NormalObject } from '@vunk/shared';
2
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
3
+ modelValue: {
4
+ type: StringConstructor;
5
+ default: undefined;
6
+ };
7
+ trigger: {
8
+ type: import("vue").PropType<"hover" | "click" | "none">;
9
+ default: string;
10
+ };
11
+ }>, {
12
+ props: import("@vue/shared").LooseRequired<Readonly<import("vue").ExtractPropTypes<{
13
+ modelValue: {
14
+ type: StringConstructor;
15
+ default: undefined;
16
+ };
17
+ trigger: {
18
+ type: import("vue").PropType<"hover" | "click" | "none">;
19
+ default: string;
20
+ };
21
+ }>> & Readonly<{
22
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
23
+ }> & {}>;
24
+ emit: (event: "update:modelValue", ...args: any[]) => void;
25
+ model: import("vue").WritableComputedRef<string, string>;
26
+ sigma: import("sigma").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
27
+ graph: import("graphology").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
28
+ coordinates: import("vue").ShallowRef<number[], number[]>;
29
+ currentEdge: import("vue").Ref<string, string>;
30
+ attributes: import("vue").Ref<NormalObject, NormalObject>;
31
+ state: import("vue").ComputedRef<{
32
+ edge: string;
33
+ attributes: NormalObject;
34
+ visible: boolean;
35
+ coordinates: number[];
36
+ }>;
37
+ onClickEdge: (e: {
38
+ edge: string;
39
+ }) => void;
40
+ onEnterEdge: (e: {
41
+ edge: string;
42
+ }) => void;
43
+ onLeaveEdge: () => void;
44
+ onClickStage: () => void;
45
+ readonly GlobalRendererTemplate: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
46
+ active: {
47
+ type: BooleanConstructor;
48
+ default: boolean;
49
+ };
50
+ data: {
51
+ type: import("vue").PropType<import("@vunk/graph/entry").NormalObject>;
52
+ default: () => {};
53
+ };
54
+ }>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
55
+ active: {
56
+ type: BooleanConstructor;
57
+ default: boolean;
58
+ };
59
+ data: {
60
+ type: import("vue").PropType<import("@vunk/graph/entry").NormalObject>;
61
+ default: () => {};
62
+ };
63
+ }>> & Readonly<{}>, {
64
+ data: import("@vunk/graph/entry").NormalObject;
65
+ active: boolean;
66
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
67
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
68
+ 'update:modelValue': null;
69
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
70
+ modelValue: {
71
+ type: StringConstructor;
72
+ default: undefined;
73
+ };
74
+ trigger: {
75
+ type: import("vue").PropType<"hover" | "click" | "none">;
76
+ default: string;
77
+ };
78
+ }>> & Readonly<{
79
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
80
+ }>, {
81
+ modelValue: string;
82
+ trigger: "none" | "click" | "hover";
83
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
84
+ export default _default;
@@ -1,21 +1,21 @@
1
1
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
2
  modelValue: {
3
- type: BooleanConstructor;
4
- default: boolean;
3
+ type: StringConstructor;
4
+ default: undefined;
5
5
  };
6
- closeable: {
7
- type: BooleanConstructor;
8
- default: boolean;
6
+ trigger: {
7
+ type: import("vue").PropType<"hover" | "click" | "none">;
8
+ default: string;
9
9
  };
10
10
  }>, {
11
11
  props: import("@vue/shared").LooseRequired<Readonly<import("vue").ExtractPropTypes<{
12
12
  modelValue: {
13
- type: BooleanConstructor;
14
- default: boolean;
13
+ type: StringConstructor;
14
+ default: undefined;
15
15
  };
16
- closeable: {
17
- type: BooleanConstructor;
18
- default: boolean;
16
+ trigger: {
17
+ type: import("vue").PropType<"hover" | "click" | "none">;
18
+ default: string;
19
19
  };
20
20
  }>> & Readonly<{
21
21
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
@@ -23,6 +23,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
23
23
  emit: (event: "update:modelValue", ...args: any[]) => void;
24
24
  sigma: import("sigma").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
25
25
  graph: import("graphology").default<import("graphology-types").Attributes, import("graphology-types").Attributes, import("graphology-types").Attributes>;
26
+ model: import("vue").WritableComputedRef<string, string>;
26
27
  coordinates: import("vue").ShallowRef<number[], number[]>;
27
28
  currentNode: import("vue").Ref<string, string>;
28
29
  attributes: import("vue").Ref<{}, {}>;
@@ -35,6 +36,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
35
36
  onClickNode: (e: {
36
37
  node: string;
37
38
  }) => void;
39
+ onEnterNode: (e: {
40
+ node: string;
41
+ }) => void;
42
+ onLeaveNode: () => void;
38
43
  onClickStage: () => void;
39
44
  readonly GlobalRendererTemplate: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
40
45
  active: {
@@ -62,17 +67,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
62
67
  'update:modelValue': null;
63
68
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
64
69
  modelValue: {
65
- type: BooleanConstructor;
66
- default: boolean;
70
+ type: StringConstructor;
71
+ default: undefined;
67
72
  };
68
- closeable: {
69
- type: BooleanConstructor;
70
- default: boolean;
73
+ trigger: {
74
+ type: import("vue").PropType<"hover" | "click" | "none">;
75
+ default: string;
71
76
  };
72
77
  }>> & Readonly<{
73
78
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
74
79
  }>, {
75
- modelValue: boolean;
76
- closeable: boolean;
80
+ modelValue: string;
81
+ trigger: "none" | "click" | "hover";
77
82
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
78
83
  export default _default;
@@ -1,28 +1,28 @@
1
1
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
2
  modelValue: {
3
- type: BooleanConstructor;
4
- default: boolean;
3
+ type: StringConstructor;
4
+ default: undefined;
5
5
  };
6
- closeable: {
7
- type: BooleanConstructor;
8
- default: boolean;
6
+ trigger: {
7
+ type: import("vue").PropType<"hover" | "click" | "none">;
8
+ default: string;
9
9
  };
10
10
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
11
  'update:modelValue': null;
12
12
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
13
13
  modelValue: {
14
- type: BooleanConstructor;
15
- default: boolean;
14
+ type: StringConstructor;
15
+ default: undefined;
16
16
  };
17
- closeable: {
18
- type: BooleanConstructor;
19
- default: boolean;
17
+ trigger: {
18
+ type: import("vue").PropType<"hover" | "click" | "none">;
19
+ default: string;
20
20
  };
21
21
  }>> & Readonly<{
22
22
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
23
23
  }>, {
24
- modelValue: boolean;
25
- closeable: boolean;
24
+ modelValue: string;
25
+ trigger: "none" | "click" | "hover";
26
26
  }, {}, {
27
27
  VkGraphViewUi: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
28
28
  coordinates: {
@@ -1 +1 @@
1
- export { useGraph, useSigma } from '@vunk/graph/components/graph';
1
+ export { useEdgeReducer, useGraph, useNodeReducer, useSigma } from '@vunk/graph/components/graph';
@@ -1 +1 @@
1
- export { useGraph, useSigma } from '@vunk/graph/components/graph';
1
+ export { useEdgeReducer, useGraph, useNodeReducer, useSigma } from '@vunk/graph/components/graph';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vunk/graph",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "license": "ISC",