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