@stonecrop/node-editor 0.2.24 → 0.2.25
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.js +12 -0
- package/dist/node-editor.d.ts +28 -0
- package/dist/node-editor.js +6370 -6037
- package/dist/node-editor.js.map +1 -1
- package/dist/node-editor.umd.cjs +3 -2
- package/dist/node-editor.umd.cjs.map +1 -1
- package/dist/node_editor/src/tsdoc-metadata.json +11 -0
- package/dist/node_editor.tsbuildinfo +1 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +27 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/style.css +1 -1
- package/dist/types/index.js +0 -0
- package/package.json +26 -19
- package/src/components/EditableEdge.vue +36 -50
- package/src/components/EditableNode.vue +24 -42
- package/src/components/NodeEditor.vue +87 -112
- package/src/components/StateEditor.vue +78 -67
- package/src/index.ts +7 -1
- package/src/shims-vue.d.ts +5 -0
- package/src/types/index.ts +24 -0
- package/src/histoire.setup.ts +0 -7
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.47.0"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"5.5.2"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import NodeEditor from '@/components/NodeEditor.vue';
|
|
3
|
+
import StateEditor from '@/components/StateEditor.vue';
|
|
4
|
+
export type { EditorStates, FlowElement, FlowElements, Layout } from '@/types';
|
|
5
|
+
/**
|
|
6
|
+
* Install all Node Editor components
|
|
7
|
+
* @param app - Vue app instance
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
declare function install(app: App): void;
|
|
11
|
+
export { install, NodeEditor, StateEditor };
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAE9E;;;;GAIG;AACH,iBAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAGxB;AAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Elements, type Element, type XYPosition, Position } from '@vue-flow/core';
|
|
2
|
+
import type { AnyStateMachine, AnyStateNodeDefinition, StatesConfig } from 'xstate';
|
|
3
|
+
export type EditorStates = {
|
|
4
|
+
[key: string]: Partial<AnyStateMachine | AnyStateNodeDefinition> | StatesConfig<any, any, any>;
|
|
5
|
+
};
|
|
6
|
+
export type FlowElements = Elements<{
|
|
7
|
+
hasInput?: boolean;
|
|
8
|
+
hasOutput?: boolean;
|
|
9
|
+
}, {
|
|
10
|
+
hasInput?: boolean;
|
|
11
|
+
hasOutput?: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
export type FlowElement = Element<{
|
|
14
|
+
hasInput?: boolean;
|
|
15
|
+
hasOutput?: boolean;
|
|
16
|
+
}, {
|
|
17
|
+
hasInput?: boolean;
|
|
18
|
+
hasOutput?: boolean;
|
|
19
|
+
}>;
|
|
20
|
+
export type Layout = {
|
|
21
|
+
[key: string]: {
|
|
22
|
+
position?: XYPosition;
|
|
23
|
+
targetPosition?: Position;
|
|
24
|
+
sourcePosition?: Position;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAEnF,MAAM,MAAM,YAAY,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,sBAAsB,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAC9F,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,CAClC;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3C;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAC3C,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,CAChC;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAC3C;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAC3C,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG;QACd,QAAQ,CAAC,EAAE,UAAU,CAAA;QACrB,cAAc,CAAC,EAAE,QAAQ,CAAA;QACzB,cAAc,CAAC,EAAE,QAAQ,CAAA;KACzB,CAAA;CACD,CAAA"}
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.editable-edge-label{background-color:#fff;position:relative;font-size:12px}.label-input-wrapper{position:absolute;top:0;left:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center}.label-input{text-align:center}.vue-flow{position:relative;width:100%;height:100%;overflow:hidden;z-index:0}.vue-flow__container{position:absolute;height:100%;width:100%;left:0;top:0}.vue-flow__pane{z-index:1}.vue-flow__pane.draggable{cursor:grab}.vue-flow__pane.dragging{cursor:grabbing}.vue-flow__pane.selection{cursor:pointer}.vue-flow__transformationpane{transform-origin:0 0;z-index:2;pointer-events:none}.vue-flow__viewport{z-index:4}.vue-flow__selection{z-index:6}.vue-flow__edge-labels{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vue-flow__nodesselection-rect:focus,.vue-flow__nodesselection-rect:focus-visible{outline:none}.vue-flow .vue-flow__edges{pointer-events:none;overflow:visible}.vue-flow__edge-path,.vue-flow__connection-path{stroke:#b1b1b7;stroke-width:1;fill:none}.vue-flow__edge{pointer-events:visibleStroke;cursor:pointer}.vue-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.vue-flow__edge.inactive{pointer-events:none}.vue-flow__edge.selected,.vue-flow__edge:focus,.vue-flow__edge:focus-visible{outline:none}.vue-flow__edge.selected .vue-flow__edge-path,.vue-flow__edge:focus .vue-flow__edge-path,.vue-flow__edge:focus-visible .vue-flow__edge-path{stroke:#555}.vue-flow__edge-textwrapper{pointer-events:all}.vue-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vue-flow__connection{pointer-events:none}.vue-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.vue-flow__connectionline{z-index:1001}.vue-flow__nodes{pointer-events:none;transform-origin:0 0}.vue-flow__node-default,.vue-flow__node-input,.vue-flow__node-output{border-width:1px;border-style:solid;border-color:#bbb}.vue-flow__node-default.selected,.vue-flow__node-default:focus,.vue-flow__node-default:focus-visible,.vue-flow__node-input.selected,.vue-flow__node-input:focus,.vue-flow__node-input:focus-visible,.vue-flow__node-output.selected,.vue-flow__node-output:focus,.vue-flow__node-output:focus-visible{outline:none;border:1px solid #555}.vue-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:grab}.vue-flow__node.dragging{cursor:grabbing}.vue-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.vue-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.vue-flow__nodesselection-rect.dragging{cursor:grabbing}.vue-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px}.vue-flow__handle.connectable{pointer-events:all;cursor:crosshair}.vue-flow__handle-bottom{
|
|
1
|
+
.editable-edge-label{background-color:#fff;position:relative;font-size:12px}.label-input-wrapper{position:absolute;top:0;left:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center}.label-input{text-align:center}.vue-flow{position:relative;width:100%;height:100%;overflow:hidden;z-index:0;direction:ltr}.vue-flow__container{position:absolute;height:100%;width:100%;left:0;top:0}.vue-flow__pane{z-index:1}.vue-flow__pane.draggable{cursor:grab}.vue-flow__pane.dragging{cursor:grabbing}.vue-flow__pane.selection{cursor:pointer}.vue-flow__transformationpane{transform-origin:0 0;z-index:2;pointer-events:none}.vue-flow__viewport{z-index:4;overflow:clip}.vue-flow__selection{z-index:6}.vue-flow__edge-labels{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vue-flow__nodesselection-rect:focus,.vue-flow__nodesselection-rect:focus-visible{outline:none}.vue-flow .vue-flow__edges{pointer-events:none;overflow:visible}.vue-flow__edge-path,.vue-flow__connection-path{stroke:#b1b1b7;stroke-width:1;fill:none}.vue-flow__edge{pointer-events:visibleStroke;cursor:pointer}.vue-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.vue-flow__edge.animated path.vue-flow__edge-interaction{stroke-dasharray:none;animation:none}.vue-flow__edge.inactive{pointer-events:none}.vue-flow__edge.selected,.vue-flow__edge:focus,.vue-flow__edge:focus-visible{outline:none}.vue-flow__edge.selected .vue-flow__edge-path,.vue-flow__edge:focus .vue-flow__edge-path,.vue-flow__edge:focus-visible .vue-flow__edge-path{stroke:#555}.vue-flow__edge-textwrapper{pointer-events:all}.vue-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.vue-flow__connection{pointer-events:none}.vue-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.vue-flow__connectionline{z-index:1001}.vue-flow__nodes{pointer-events:none;transform-origin:0 0}.vue-flow__node-default,.vue-flow__node-input,.vue-flow__node-output{border-width:1px;border-style:solid;border-color:#bbb}.vue-flow__node-default.selected,.vue-flow__node-default:focus,.vue-flow__node-default:focus-visible,.vue-flow__node-input.selected,.vue-flow__node-input:focus,.vue-flow__node-input:focus-visible,.vue-flow__node-output.selected,.vue-flow__node-output:focus,.vue-flow__node-output:focus-visible{outline:none;border:1px solid #555}.vue-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.vue-flow__node.draggable{cursor:grab;pointer-events:all}.vue-flow__node.draggable.dragging{cursor:grabbing}.vue-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.vue-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.vue-flow__nodesselection-rect.dragging{cursor:grabbing}.vue-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px}.vue-flow__handle.connectable{pointer-events:all;cursor:crosshair}.vue-flow__handle-bottom{left:50%;bottom:0;transform:translate(-50%,50%)}.vue-flow__handle-top{left:50%;top:0;transform:translate(-50%,-50%)}.vue-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.vue-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.vue-flow__edgeupdater{cursor:move;pointer-events:all}.vue-flow__panel{position:absolute;z-index:5;margin:15px}.vue-flow__panel.top{top:0}.vue-flow__panel.bottom{bottom:0}.vue-flow__panel.left{left:0}.vue-flow__panel.right{right:0}.vue-flow__panel.center{left:50%;transform:translate(-50%)}@keyframes dashdraw{0%{stroke-dashoffset:10}}:root{--vf-node-bg: #fff;--vf-node-text: #222;--vf-connection-path: #b1b1b7;--vf-handle: #555}.vue-flow__edge.updating .vue-flow__edge-path{stroke:#777}.vue-flow__edge-text{font-size:10px}.vue-flow__edge-textbg{fill:#fff}.vue-flow__connection-path{stroke:var(--vf-connection-path)}.vue-flow__node{cursor:grab}.vue-flow__node.selectable:focus,.vue-flow__node.selectable:focus-visible{outline:none}.vue-flow__node-default,.vue-flow__node-input,.vue-flow__node-output{padding:10px;border-radius:3px;width:150px;font-size:12px;text-align:center;border-width:1px;border-style:solid;color:var(--vf-node-text);background-color:var(--vf-node-bg);border-color:var(--vf-node-color)}.vue-flow__node-default.selected,.vue-flow__node-default.selected:hover,.vue-flow__node-input.selected,.vue-flow__node-input.selected:hover,.vue-flow__node-output.selected,.vue-flow__node-output.selected:hover{box-shadow:0 0 0 .5px var(--vf-box-shadow)}.vue-flow__node-default .vue-flow__handle,.vue-flow__node-input .vue-flow__handle,.vue-flow__node-output .vue-flow__handle{background:var(--vf-handle)}.vue-flow__node-default.selectable:hover,.vue-flow__node-input.selectable:hover,.vue-flow__node-output.selectable:hover{box-shadow:0 1px 4px 1px #00000014}.vue-flow__node-input{--vf-node-color: var(--vf-node-color, #0041d0);--vf-handle: var(--vf-node-color, #0041d0);--vf-box-shadow: var(--vf-node-color, #0041d0);background:var(--vf-node-bg);border-color:var(--vf-node-color, #0041d0)}.vue-flow__node-input.selected,.vue-flow__node-input:focus,.vue-flow__node-input:focus-visible{outline:none;border:1px solid var(--vf-node-color, #0041d0)}.vue-flow__node-default{--vf-handle: var(--vf-node-color, #1a192b);--vf-box-shadow: var(--vf-node-color, #1a192b);background:var(--vf-node-bg);border-color:var(--vf-node-color, #1a192b)}.vue-flow__node-default.selected,.vue-flow__node-default:focus,.vue-flow__node-default:focus-visible{outline:none;border:1px solid var(--vf-node-color, #1a192b)}.vue-flow__node-output{--vf-handle: var(--vf-node-color, #ff0072);--vf-box-shadow: var(--vf-node-color, #ff0072);background:var(--vf-node-bg);border-color:var(--vf-node-color, #ff0072)}.vue-flow__node-output.selected,.vue-flow__node-output:focus,.vue-flow__node-output:focus-visible{outline:none;border:1px solid var(--vf-node-color, #ff0072)}.vue-flow__nodesselection-rect,.vue-flow__selection{background:#0059dc14;border:1px dotted rgba(0,89,220,.8)}.vue-flow__nodesselection-rect:focus,.vue-flow__nodesselection-rect:focus-visible,.vue-flow__selection:focus,.vue-flow__selection:focus-visible{outline:none}.vue-flow__handle{width:6px;height:6px;background:var(--vf-handle);border:1px solid #fff;border-radius:100%}.chart-controls-left,.chart-controls-right{height:1.8em;display:flex;flex-direction:row;align-items:center;padding-top:.2em}.chart-controls-right div{margin-left:5px}.chart-controls{padding-left:20px;padding-right:20px;height:1.8em;border-bottom:1px solid #ccc;display:flex;flex-direction:row;justify-content:space-between}.chart-controls div{margin-bottom:5px}.defaultContainerClass{height:90vh;width:100%;border:1px solid #ccc}.default-input-node.vue-flow__node-input,.default-output-node.vue-flow__node-output{border-color:#000}.default-input-node.vue-flow__node-input .vue-flow__handle,.default-output-node.vue-flow__node-output .vue-flow__handle{background-color:#000}.default-input-node.vue-flow__node-input.selected,.default-output-node.vue-flow__node-output.selected{box-shadow:0 0 0 .5px #000}button.button-default{background-color:#fff;padding:1px 12px;border-radius:3px;border:1px solid #ccc;cursor:pointer;white-space:nowrap}button.button-default:hover{background-color:#f2f2f2}.vue-flow{background-size:40px 40px;background-image:linear-gradient(to right,#ccc 1px,transparent 1px),linear-gradient(to bottom,#ccc 1px,transparent 1px)}input.label-editor{position:absolute}.node-editor-wrapper{position:relative}
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/node-editor",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Node editor UI for Stonecrop",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,29 +18,37 @@
|
|
|
18
18
|
},
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
|
-
"import":
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/node_editor/src/index.d.ts",
|
|
23
|
+
"default": "./dist/node-editor.js"
|
|
24
|
+
},
|
|
22
25
|
"require": "./dist/node-editor.umd.cjs"
|
|
23
26
|
},
|
|
24
27
|
"./styles": "./dist/style.css"
|
|
25
28
|
},
|
|
26
|
-
"
|
|
27
|
-
"module": "dist/node-editor.js",
|
|
28
|
-
"umd": "dist/node-editor.umd.cjs",
|
|
29
|
+
"typings": "./dist/node_editor/src/index.d.ts",
|
|
29
30
|
"files": [
|
|
30
31
|
"dist/*",
|
|
31
32
|
"src/*"
|
|
32
33
|
],
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@vue-flow/core": "
|
|
35
|
-
"vue": "^3.4.
|
|
36
|
-
"vue-router": "^4",
|
|
37
|
-
"xstate": "
|
|
35
|
+
"@vue-flow/core": "^1.37.1",
|
|
36
|
+
"vue": "^3.4.31",
|
|
37
|
+
"vue-router": "^4.4.0",
|
|
38
|
+
"xstate": "^4.38.3"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@
|
|
42
|
-
"
|
|
43
|
-
"
|
|
41
|
+
"@microsoft/api-documenter": "^7.25.3",
|
|
42
|
+
"@rushstack/heft": "^0.66.18",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
|
44
|
+
"@typescript-eslint/parser": "^7.14.1",
|
|
45
|
+
"@vitejs/plugin-vue": "^5.0.5",
|
|
46
|
+
"eslint": "^8.40.0",
|
|
47
|
+
"eslint-config-prettier": "^8.8.0",
|
|
48
|
+
"eslint-plugin-vue": "^9.11.1",
|
|
49
|
+
"typescript": "^5.5.2",
|
|
50
|
+
"vite": "^5.3.2",
|
|
51
|
+
"stonecrop-rig": "0.2.22"
|
|
44
52
|
},
|
|
45
53
|
"publishConfig": {
|
|
46
54
|
"access": "public"
|
|
@@ -49,12 +57,11 @@
|
|
|
49
57
|
"node": ">=20.11.0"
|
|
50
58
|
},
|
|
51
59
|
"scripts": {
|
|
52
|
-
"prepublish": "vite build",
|
|
53
|
-
"build": "vite build",
|
|
60
|
+
"prepublish": "heft build && vite build && rushx docs",
|
|
61
|
+
"build": "heft build && vite build && rushx docs",
|
|
54
62
|
"dev": "vite",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"story:preview": "histoire preview"
|
|
63
|
+
"docs": "api-documenter markdown -i temp -o ../docs/node_editor",
|
|
64
|
+
"lint": "eslint . --ext .ts,.vue",
|
|
65
|
+
"preview": "vite preview"
|
|
59
66
|
}
|
|
60
67
|
}
|
|
@@ -1,38 +1,47 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
import { EdgeLabelRenderer, getBezierPath, useVueFlow } from '@vue-flow/core'
|
|
4
|
-
import type { CSSProperties } from 'vue'
|
|
5
|
-
import { computed, ref, nextTick } from 'vue'
|
|
6
|
-
|
|
7
|
-
interface EditableEdgeProps<T = any> extends EdgeProps<T> {
|
|
8
|
-
id: string
|
|
9
|
-
sourceX: number
|
|
10
|
-
sourceY: number
|
|
11
|
-
targetX: number
|
|
12
|
-
targetY: number
|
|
13
|
-
sourcePosition: Position
|
|
14
|
-
targetPosition: Position
|
|
15
|
-
data: T
|
|
16
|
-
markerEnd: string
|
|
17
|
-
style: CSSProperties
|
|
18
|
-
label: string
|
|
19
|
-
}
|
|
1
|
+
<template>
|
|
2
|
+
<path :id="id" :style="style" class="vue-flow__edge-path" :d="path[0]" :marker-end="markerEnd" />
|
|
20
3
|
|
|
21
|
-
|
|
4
|
+
<EdgeLabelRenderer>
|
|
5
|
+
<div
|
|
6
|
+
:style="{
|
|
7
|
+
pointerEvents: 'all',
|
|
8
|
+
position: 'absolute',
|
|
9
|
+
transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
|
|
10
|
+
}"
|
|
11
|
+
class="nodrag nopan editable-edge-label"
|
|
12
|
+
@click="labelOnClick()">
|
|
13
|
+
<div class="vue-flow__edge-label">{{ props.label }}</div>
|
|
14
|
+
<div v-if="showInput" class="label-input-wrapper">
|
|
15
|
+
<input
|
|
16
|
+
ref="labelInput"
|
|
17
|
+
class="label-input"
|
|
18
|
+
v-model="newLabel"
|
|
19
|
+
@blur="showInput = false"
|
|
20
|
+
@keypress.enter="submitNewLabel" />
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</EdgeLabelRenderer>
|
|
24
|
+
</template>
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { type EdgeProps, EdgeLabelRenderer, getBezierPath /* useVueFlow */ } from '@vue-flow/core'
|
|
28
|
+
import { computed, ref, nextTick } from 'vue'
|
|
24
29
|
|
|
30
|
+
const props = defineProps<EdgeProps>()
|
|
25
31
|
const emit = defineEmits(['change'])
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
const
|
|
33
|
+
// TODO: Implement edge removal
|
|
34
|
+
// const { removeEdges } = useVueFlow()
|
|
35
|
+
|
|
36
|
+
const labelInput = ref<HTMLElement>()
|
|
37
|
+
const newLabel = ref<EdgeProps['label']>('')
|
|
29
38
|
const showInput = ref(false)
|
|
30
39
|
let lastClick = 0
|
|
31
40
|
|
|
32
|
-
const labelOnClick = () => {
|
|
41
|
+
const labelOnClick = async () => {
|
|
33
42
|
let now = Date.now()
|
|
34
43
|
if (now - lastClick < 500 && !showInput.value) {
|
|
35
|
-
showLabelInput()
|
|
44
|
+
await showLabelInput()
|
|
36
45
|
}
|
|
37
46
|
lastClick = now
|
|
38
47
|
}
|
|
@@ -58,37 +67,13 @@ export default {
|
|
|
58
67
|
}
|
|
59
68
|
</script>
|
|
60
69
|
|
|
61
|
-
<template>
|
|
62
|
-
<path :id="id" :style="style" class="vue-flow__edge-path" :d="path[0]" :marker-end="markerEnd" />
|
|
63
|
-
|
|
64
|
-
<EdgeLabelRenderer>
|
|
65
|
-
<div
|
|
66
|
-
:style="{
|
|
67
|
-
pointerEvents: 'all',
|
|
68
|
-
position: 'absolute',
|
|
69
|
-
transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
|
|
70
|
-
}"
|
|
71
|
-
class="nodrag nopan editable-edge-label"
|
|
72
|
-
@click="labelOnClick()">
|
|
73
|
-
<div class="vue-flow__edge-label">{{ props.label }}</div>
|
|
74
|
-
<div v-if="showInput" class="label-input-wrapper">
|
|
75
|
-
<input
|
|
76
|
-
ref="labelInput"
|
|
77
|
-
class="label-input"
|
|
78
|
-
v-model="newLabel"
|
|
79
|
-
@blur="showInput = false"
|
|
80
|
-
@keypress.enter="submitNewLabel" />
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</EdgeLabelRenderer>
|
|
84
|
-
</template>
|
|
85
|
-
|
|
86
70
|
<style>
|
|
87
71
|
.editable-edge-label {
|
|
88
72
|
background-color: white;
|
|
89
73
|
position: relative;
|
|
90
74
|
font-size: 12px;
|
|
91
75
|
}
|
|
76
|
+
|
|
92
77
|
.label-input-wrapper {
|
|
93
78
|
position: absolute;
|
|
94
79
|
top: 0;
|
|
@@ -99,6 +84,7 @@ export default {
|
|
|
99
84
|
align-items: center;
|
|
100
85
|
justify-content: center;
|
|
101
86
|
}
|
|
87
|
+
|
|
102
88
|
.label-input {
|
|
103
89
|
text-align: center;
|
|
104
90
|
}
|
|
@@ -1,38 +1,35 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div @click="nodeOnClick()">
|
|
3
|
+
<div>{{ props.label }}</div>
|
|
4
|
+
<div v-if="showInput" class="label-input-wrapper">
|
|
5
|
+
<input
|
|
6
|
+
ref="labelInput"
|
|
7
|
+
class="label-input"
|
|
8
|
+
v-model="newLabel"
|
|
9
|
+
@blur="showInput = false"
|
|
10
|
+
@keypress.enter="submitNewLabel" />
|
|
11
|
+
</div>
|
|
12
|
+
<Handle v-if="props.data.hasInput" id="a" type="target" :position="props.targetPosition" />
|
|
13
|
+
<Handle v-if="props.data.hasOutput" id="b" type="source" :position="props.sourcePosition" />
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
import { NodeProps, Handle } from '@vue-flow/core'
|
|
19
|
+
import { ref, nextTick } from 'vue'
|
|
14
20
|
|
|
21
|
+
const props = defineProps<NodeProps>()
|
|
15
22
|
const emit = defineEmits(['change'])
|
|
16
23
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
right: Position.Right,
|
|
20
|
-
bottom: Position.Bottom,
|
|
21
|
-
left: Position.Left,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const sourcePosition = computed(() => positionMap[props.sourcePosition])
|
|
25
|
-
const targetPosition = computed(() => positionMap[props.targetPosition])
|
|
26
|
-
|
|
27
|
-
const labelInput = ref()
|
|
28
|
-
const newLabel = ref('')
|
|
24
|
+
const labelInput = ref<HTMLInputElement>()
|
|
25
|
+
const newLabel = ref<NodeProps['label']>('')
|
|
29
26
|
const showInput = ref(false)
|
|
30
27
|
let lastClick = 0
|
|
31
28
|
|
|
32
|
-
const nodeOnClick = () => {
|
|
29
|
+
const nodeOnClick = async () => {
|
|
33
30
|
let now = Date.now()
|
|
34
31
|
if (now - lastClick < 500 && !showInput.value) {
|
|
35
|
-
showLabelInput()
|
|
32
|
+
await showLabelInput()
|
|
36
33
|
}
|
|
37
34
|
lastClick = now
|
|
38
35
|
}
|
|
@@ -50,22 +47,6 @@ const submitNewLabel = () => {
|
|
|
50
47
|
}
|
|
51
48
|
</script>
|
|
52
49
|
|
|
53
|
-
<template>
|
|
54
|
-
<div @click="nodeOnClick()">
|
|
55
|
-
<div>{{ props.label }}</div>
|
|
56
|
-
<div v-if="showInput" class="label-input-wrapper">
|
|
57
|
-
<input
|
|
58
|
-
ref="labelInput"
|
|
59
|
-
class="label-input"
|
|
60
|
-
v-model="newLabel"
|
|
61
|
-
@blur="showInput = false"
|
|
62
|
-
@keypress.enter="submitNewLabel" />
|
|
63
|
-
</div>
|
|
64
|
-
<Handle v-if="props.data.hasInput" id="a" type="target" :position="targetPosition" />
|
|
65
|
-
<Handle v-if="props.data.hasOutput" id="b" type="source" :position="sourcePosition" />
|
|
66
|
-
</div>
|
|
67
|
-
</template>
|
|
68
|
-
|
|
69
50
|
<style>
|
|
70
51
|
.label-input-wrapper {
|
|
71
52
|
position: absolute;
|
|
@@ -77,6 +58,7 @@ const submitNewLabel = () => {
|
|
|
77
58
|
align-items: center;
|
|
78
59
|
justify-content: center;
|
|
79
60
|
}
|
|
61
|
+
|
|
80
62
|
.label-input {
|
|
81
63
|
text-align: center;
|
|
82
64
|
}
|