118 lines
2.2 KiB
Vue
118 lines
2.2 KiB
Vue
|
|
|
|
<template>
|
|
<div class="files">
|
|
<div @click="openAside" style="cursor: pointer;">
|
|
<slot name="handle">Files</slot>
|
|
</div>
|
|
|
|
<div
|
|
popover
|
|
ref="popover"
|
|
class="files__aside"
|
|
:class="{ 'files__aside--dragging': dragging }"
|
|
>
|
|
<div
|
|
class="files__aside-content"
|
|
ref="content"
|
|
@dragstart="onDragStart"
|
|
@dragleave="onDragLeave"
|
|
@dragover.prevent
|
|
>
|
|
<FileManager @filePreview="loadFilePreview" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import {onUnmounted, ref} from 'vue';
|
|
import FileManager from '../FileManager/FileManager.vue';
|
|
import FilePreview from '../FileManager/FilePreview.vue';
|
|
import {VirtualFile} from '../../model/FileSystem/types';
|
|
|
|
const popover = ref<HTMLDivElement>()
|
|
const content = ref<HTMLDivElement>()
|
|
const filePreview = ref<VirtualFile>();
|
|
|
|
function openAside(){
|
|
popover.value?.showPopover();
|
|
}
|
|
|
|
function loadFilePreview(file: VirtualFile){
|
|
filePreview.value = file;
|
|
}
|
|
|
|
|
|
const dragging = ref(false);
|
|
|
|
function onDragStart(){
|
|
dragging.value = true;
|
|
}
|
|
|
|
function onDragLeave(event) {
|
|
if (!content.value?.contains(event.relatedTarget)) {
|
|
popover.value?.hidePopover();
|
|
}
|
|
}
|
|
|
|
function onDragEnd(){
|
|
dragging.value = false;
|
|
}
|
|
|
|
window.addEventListener('dragend', onDragEnd, {passive: true});
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('dragend', onDragEnd);
|
|
})
|
|
</script>
|
|
<style>
|
|
|
|
.files__aside {
|
|
--animation-duration: 200ms;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: fixed;
|
|
inset: auto;
|
|
height: auto;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 500px;
|
|
max-width: 100vw;
|
|
background: rgba(255, 255, 255, 0.5);
|
|
backdrop-filter: blur(10px);
|
|
transform: translateX(100%);
|
|
border: none;
|
|
transition: all var(--animation-duration) allow-discrete;
|
|
}
|
|
|
|
.files__aside-content {
|
|
position: absolute;
|
|
inset: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.files__aside:popover-open {
|
|
transform: translateX(0);
|
|
transition-behavior: allow-discrete;
|
|
}
|
|
|
|
@starting-style {
|
|
.files__aside:popover-open {
|
|
transform: translateX(100%);
|
|
}
|
|
}
|
|
|
|
.files__aside--dragging:popover-open {
|
|
transform: translateX(25%);
|
|
}
|
|
|
|
.files__file-preview {
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
</style> |