Files
bibliomane/front/src/CollectionFormElement.vue

190 lines
4.2 KiB
Vue

<script setup>
import { ref } from 'vue'
import BookListElement from './BookListElement.vue'
const props = defineProps({
id: Number,
position: Number,
book: Array,
isDragover: Boolean,
isDragoverFromAbove: Boolean,
})
const emit = defineEmits(['positionchange', 'startgrab', 'stopgrab', 'grabbing', 'delete'])
const vFocus = {
mounted: (el) => el.focus(),
}
const isInputtingPosition = ref(false)
const inputtedPosition = ref('')
const initialGrabPosition = ref(null)
const draggedPosition = ref(null)
function onPositionInput() {
if (inputtedPosition.value != '' && !isNaN(inputtedPosition.value)) {
const parsedPosition = parseInt(inputtedPosition.value)
if (parsedPosition != props.position) {
emit('positionchange', parsedPosition)
}
}
clearPositionInput()
}
function clearPositionInput() {
isInputtingPosition.value = false
inputtedPosition.value = ''
}
function clearGrabVariables() {
initialGrabPosition.value = null
draggedPosition.value = null
}
function onPointerUp() {
clearGrabVariables()
emit('stopgrab')
}
function onPointerDown(e) {
initialGrabPosition.value = e.pageY
e.preventDefault()
emit('startgrab')
}
function onPointerMove(e) {
if (initialGrabPosition.value == null) {
return
}
e.preventDefault()
draggedPosition.value = e.pageY - initialGrabPosition.value
emit('grabbing', draggedPosition.value)
}
</script>
<template>
<div>
<div v-if="isDragover && !isDragoverFromAbove" class="dragover" />
<div
:style="
draggedPosition
? 'transform: translateY(' + draggedPosition + 'px);position:relative;z-index:3'
: ''
"
ref="collectionitembox"
class="collectionitembox"
@pointermove="onPointerMove"
@pointerup="onPointerUp"
@pointerleave="clearGrabVariables"
>
<BookListElement v-bind="props.book">
<template v-slot:left>
<div class="inputpositionwidget centered">
<div
v-if="!isInputtingPosition"
@click="isInputtingPosition = true"
class="positionindicator centered is-narrow clickable"
>
{{ props.position }}
</div>
<div v-else>
<input
type="text"
v-model="inputtedPosition"
v-focus
@blur="clearPositionInput"
@keyup.enter="onPositionInput"
size="1"
class="positioninput"
:placeholder="props.position"
/>
</div>
</div>
<div class="separator" />
</template>
<template v-slot:right>
<div class="separator" />
<div class="positionwidget centered is-narrow" @pointerdown="onPointerDown">
<b-icon-list />
</div>
<div @click="$emit('delete')" class="centered closebtn clickable">
<b-icon-x />
</div>
</template>
</BookListElement>
</div>
<div v-if="isDragover && isDragoverFromAbove" class="dragover" />
</div>
</template>
<style scoped>
.collectionitembox {
transition: ease-in-out 0.04s;
display: flex;
z-index: 2;
}
.collectionitembox:hover {
transform: scale(1.01);
transition: ease-in-out 0.02s;
}
.separator {
width: 5px;
background: var(--bulma-scheme-main);
}
.positionindicator {
font-size: 36px;
margin-left: 40px;
margin-right: 40px;
}
.positioninput {
font-size: 36px;
margin-left: 20px;
margin-right: 20px;
text-align: center;
background: var(--bulma-scheme-main);
border-radius: 10%;
color: var(--bulma-body-color);
}
.positionwidget {
color: var(--bulma-scheme-main);
font-size: 48px;
margin-left: 30px;
border-top-right-radius: var(--bulma-box-radius);
border-bottom-right-radius: var(--bulma-box-radius);
cursor: grab;
touch-action: none;
}
.positionwidget:active {
cursor: grabbing;
}
.dragover {
border: 3px solid var(--bulma-primary);
border-radius: 10px;
}
.closebtn {
height: 40px;
width: 40px;
font-size: 36px;
}
@media (max-width: 1024px) {
.inputpositionwidget {
margin-top: 10px;
}
.positionwidget {
margin-bottom: 10px;
}
}
</style>