feat(resize-rotate): add snappable

This commit is contained in:
braks
2022-08-30 22:16:10 +02:00
committed by Braks
parent 9440d4fe85
commit dd62165443
5 changed files with 365 additions and 212 deletions
+11 -8
View File
@@ -1,6 +1,7 @@
// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
@@ -24,7 +25,6 @@ declare global {
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
@@ -32,6 +32,8 @@ declare global {
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const logicAnd: typeof import('@vueuse/core')['logicAnd']
@@ -120,8 +122,8 @@ declare global {
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
@@ -202,11 +204,11 @@ declare global {
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
@@ -217,10 +219,10 @@ declare global {
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
@@ -237,9 +239,10 @@ declare global {
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
export {}
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import type { MoveableEvents } from 'vue3-moveable'
import type { MoveableEvents, MoveableProps } from 'vue3-moveable'
import Moveable from 'vue3-moveable'
import type { Position } from '@braks/vue-flow'
import { Handle, useVueFlow } from '@braks/vue-flow'
@@ -9,14 +9,27 @@ const props = defineProps<{
label: string
targetPosition: Position
sourcePosition: Position
nodeElement: HTMLDivElement
data: any
moveableProps?: MoveableProps
}>()
const { viewport, updateNodeDimensions, onPaneClick, onPaneScroll, onPaneContextMenu, getNode, onNodeClick, onNodeDragStart } =
useVueFlow()
const emits = defineEmits(['updateNodeInternals'])
const {
viewport,
updateNodeDimensions,
onPaneClick,
onPaneScroll,
onPaneContextMenu,
getNode,
onNodeClick,
onNodeDragStart,
snapGrid,
snapToGrid,
} = useVueFlow()
const el = ref()
const visible = ref(false)
const frame = {
@@ -37,28 +50,22 @@ const onRotateStart = (e: MoveableEvents['rotateStart']) => {
const onRotate = (e: MoveableEvents['rotate']) => {
frame.rotate = e.beforeRotate
e.target.style.transform = `rotate(${e.beforeRotate}deg)`
updateNodeDimensions([{ id: props.id, nodeElement: props.nodeElement, forceUpdate: true }])
emits('updateNodeInternals')
}
const onClick = () => {
visible.value = true
const toggleVisibility = (val?: boolean) => {
visible.value = val ?? !visible.value
}
onNodeClick(({ node }) => {
if (node.id === props.id) onClick()
toggleVisibility(node.id === props.id)
})
onNodeDragStart(({ node }) => {
if (node.id === props.id) onClick()
toggleVisibility(node.id === props.id)
})
const hideMoveable = () => {
visible.value = false
}
onPaneClick(hideMoveable)
onPaneScroll(hideMoveable)
onPaneContextMenu(hideMoveable)
onPaneClick(() => toggleVisibility(false))
</script>
<script lang="ts">
@@ -76,27 +83,41 @@ export default {
...data.style,
}"
style="position: relative"
@click="onClick"
>
<Handle type="target" :position="props.targetPosition" />
<slot>
{{ props.label }}
</slot>
<Handle type="source" :position="props.sourcePosition" />
</div>
<Moveable
v-if="visible"
v-bind="props.moveableProps"
class-name="nodrag"
:target="[`[data-moveable-id='${props.id}']`]"
:resizable="true"
:rotatable="true"
:draggable="true"
:snappable="snapToGrid"
:snap-element="snapToGrid"
:snap-gap="snapToGrid"
:snap-directions="snapToGrid"
:snap-digit="snapGrid[0]"
:snap-treshold="snapGrid[0]"
:snap-grid-width="snapGrid[0]"
:snap-grid-height="snapGrid[0]"
rotation-position="top"
:padding="{ left: 0, top: 0, right: 0, bottom: 0 }"
:origin="false"
:edge="true"
:start-drag-rotate="0"
:throttle-drag-rotate="0"
:throttle-resize="1"
:render-directions="['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se']"
:zoom="0.75"
:zoom="1"
@resize="onResize"
@rotate="onRotate"
/>