diff --git a/packages/node-resizer/package.json b/packages/node-resizer/package.json
index f8fb66d1..7406aa57 100644
--- a/packages/node-resizer/package.json
+++ b/packages/node-resizer/package.json
@@ -32,8 +32,13 @@
"@vue-flow/core": "^1.0.0",
"vue": "^3.2.37"
},
- "dependencies": {},
+ "dependencies": {
+ "d3-drag": "^3.0.0",
+ "d3-selection": "^3.0.0"
+ },
"devDependencies": {
+ "@types/d3-drag": "^3.0.1",
+ "@types/d3-selection": "^3.0.3",
"@vue-flow/core": "workspace:*",
"@vitejs/plugin-vue": "^3.2.0",
"unplugin-auto-import": "^0.12.0",
diff --git a/packages/node-resizer/src/NodeResizer.vue b/packages/node-resizer/src/NodeResizer.vue
index b42b7377..43dbb797 100644
--- a/packages/node-resizer/src/NodeResizer.vue
+++ b/packages/node-resizer/src/NodeResizer.vue
@@ -1,91 +1,57 @@
-
-
-
-
-
+
+
diff --git a/packages/node-resizer/src/ResizeControl.vue b/packages/node-resizer/src/ResizeControl.vue
new file mode 100644
index 00000000..28530f83
--- /dev/null
+++ b/packages/node-resizer/src/ResizeControl.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
diff --git a/packages/node-resizer/src/ResizeControlLine.vue b/packages/node-resizer/src/ResizeControlLine.vue
new file mode 100644
index 00000000..d2ce734f
--- /dev/null
+++ b/packages/node-resizer/src/ResizeControlLine.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/packages/node-resizer/src/index.ts b/packages/node-resizer/src/index.ts
index 42746d6b..2a471fe3 100644
--- a/packages/node-resizer/src/index.ts
+++ b/packages/node-resizer/src/index.ts
@@ -1,2 +1,4 @@
+import './style.css'
export * from './types'
export { default as NodeResizer } from './NodeResizer.vue'
+export { default as NodeResizeControl } from './ResizeControl.vue'
diff --git a/packages/node-resizer/src/style.css b/packages/node-resizer/src/style.css
new file mode 100644
index 00000000..b7852a1c
--- /dev/null
+++ b/packages/node-resizer/src/style.css
@@ -0,0 +1,103 @@
+.vue-flow__resize-control {
+ position: absolute;
+}
+
+.vue-flow__resize-control.left,
+.vue-flow__resize-control.right {
+ cursor: ew-resize;
+}
+
+.vue-flow__resize-control.top,
+.vue-flow__resize-control.bottom {
+ cursor: ns-resize;
+}
+
+.vue-flow__resize-control.top.left,
+.vue-flow__resize-control.bottom.right {
+ cursor: nwse-resize;
+}
+
+.vue-flow__resize-control.bottom.left,
+.vue-flow__resize-control.top.right {
+ cursor: nesw-resize;
+}
+
+/* handle styles */
+.vue-flow__resize-control.handle {
+ width: 4px;
+ height: 4px;
+ border: 1px solid #fff;
+ border-radius: 1px;
+ background-color: #3367d9;
+ transform: translate(-50%, -50%);
+}
+
+.vue-flow__resize-control.handle.left {
+ left: 0;
+ top: 50%;
+}
+.vue-flow__resize-control.handle.right {
+ left: 100%;
+ top: 50%;
+}
+.vue-flow__resize-control.handle.top {
+ left: 50%;
+ top: 0;
+}
+.vue-flow__resize-control.handle.bottom {
+ left: 50%;
+ top: 100%;
+}
+.vue-flow__resize-control.handle.top.left {
+ left: 0;
+}
+.vue-flow__resize-control.handle.bottom.left {
+ left: 0;
+}
+.vue-flow__resize-control.handle.top.right {
+ left: 100%;
+}
+.vue-flow__resize-control.handle.bottom.right {
+ left: 100%;
+}
+
+/* line styles */
+.vue-flow__resize-control.line {
+ border-color: #3367d9;
+ border-width: 0;
+ border-style: solid;
+}
+
+.vue-flow__resize-control.line.left,
+.vue-flow__resize-control.line.right {
+ width: 1px;
+ transform: translate(-50%, 0);
+ top: 0;
+ height: 100%;
+}
+
+.vue-flow__resize-control.line.left {
+ left: 0;
+ border-left-width: 1px;
+}
+.vue-flow__resize-control.line.right {
+ left: 100%;
+ border-right-width: 1px;
+}
+
+.vue-flow__resize-control.line.top,
+.vue-flow__resize-control.line.bottom {
+ height: 1px;
+ transform: translate(0, -50%);
+ left: 0;
+ width: 100%;
+}
+
+.vue-flow__resize-control.line.top {
+ top: 0;
+ border-top-width: 1px;
+}
+.vue-flow__resize-control.line.bottom {
+ border-bottom-width: 1px;
+ top: 100%;
+}
diff --git a/packages/node-resizer/src/types.ts b/packages/node-resizer/src/types.ts
index b01e8796..875fc2db 100644
--- a/packages/node-resizer/src/types.ts
+++ b/packages/node-resizer/src/types.ts
@@ -1,8 +1,56 @@
-import type { Position } from '@vue-flow/core'
+import type { D3DragEvent, SubjectPosition } from 'd3-drag'
+import type { CSSProperties } from 'vue'
-export interface NodeToolbarProps {
- nodeId?: string | string[]
- isVisible?: boolean
- position?: Position
- offset?: number
+export interface ResizeEventParams {
+ x: number
+ y: number
+ width: number
+ height: number
}
+
+export interface NodeResizerProps {
+ nodeId?: string
+ color?: string
+ handleClassName?: string
+ handleStyle?: CSSProperties
+ lineClassName?: string
+ lineStyle?: CSSProperties
+ isVisible?: boolean
+ minWidth?: number
+ minHeight?: number
+}
+
+export interface NodeResizerEmits {
+ (event: 'resizeStart', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
+ (event: 'resize', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
+ (event: 'resizeEnd', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
+}
+
+export type ControlLinePosition = 'top' | 'bottom' | 'left' | 'right'
+
+export type ControlPosition = ControlLinePosition | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
+
+export enum ResizeControlVariant {
+ Line = 'line',
+ Handle = 'handle',
+}
+
+export interface ResizeControlProps {
+ nodeId?: string
+ color?: string
+ minWidth?: number
+ minHeight?: number
+ position?: ControlPosition
+ variant?: ResizeControlVariant
+}
+
+export interface ResizeControlLineProps {
+ nodeId?: string
+ color?: string
+ minWidth?: number
+ minHeight?: number
+ variant?: ResizeControlVariant
+ position?: ControlLinePosition
+}
+
+export type ResizeDragEvent = D3DragEvent