64 lines
No EOL
1.7 KiB
Vue
64 lines
No EOL
1.7 KiB
Vue
<template>
|
|
<div
|
|
class="flex items-center justify-center text-xl w-0 flex-grow py-4 bg-opacity-60"
|
|
:class="$style.root"
|
|
:data-has-floating="hasFloating"
|
|
>
|
|
<span>{{ label }}</span>
|
|
</div>
|
|
</template>
|
|
|
|
<style module lang="scss">
|
|
.root {
|
|
transition: transform 200ms ease;
|
|
|
|
&[data-has-floating="true"] {
|
|
transform: scale(1.2)
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script setup lang="ts">
|
|
import interact from "@interactjs/interact"
|
|
import { useCurrentElement } from "@vueuse/core"
|
|
import { onMounted, onUnmounted } from "vue"
|
|
|
|
const props = defineProps<{
|
|
label: string
|
|
hasFloating: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
"object-change": [string, boolean]
|
|
"object-drop": [string]
|
|
}>()
|
|
|
|
const element = useCurrentElement()
|
|
|
|
onMounted(() => {
|
|
const interactable = interact(element.value as HTMLElement).dropzone({
|
|
overlap: "pointer",
|
|
ondragenter(event) {
|
|
const draggedElement = event.relatedTarget
|
|
const objectId = draggedElement.dataset?.objectId
|
|
if (objectId === undefined) return
|
|
emit("object-change", objectId, true)
|
|
},
|
|
ondragleave(event) {
|
|
const draggedElement = event.relatedTarget
|
|
const objectId = draggedElement.dataset?.objectId
|
|
if (objectId === undefined) return
|
|
emit("object-change", objectId, false)
|
|
},
|
|
ondrop(event) {
|
|
const draggedElement = event.relatedTarget
|
|
const objectId = draggedElement.dataset?.objectId
|
|
if (objectId === undefined) return
|
|
emit("object-change", objectId, false)
|
|
emit("object-drop", objectId)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => interactable.unset())
|
|
})
|
|
</script> |