Added resizing logics to modal + option to disable this
This commit is contained in:
parent
7e11a86604
commit
2f7153fbfe
4
public/assets/icons/resize-icon.svg
Normal file
4
public/assets/icons/resize-icon.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M21 15L15 21M21 8L8 21" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 346 B |
@ -122,6 +122,7 @@ async function registerFunc() {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: rgba($white, 0.5);
|
background-color: rgba($white, 0.5);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
border: $light-gray 1px solid;
|
||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<div class="modal-container" :style="{ top: y + 'px', left: x + 'px' }" v-if="isModalOpenRef">
|
<div class="modal-container" v-if="isModalOpenRef" :style="{ top: y + 'px', left: x + 'px', width: width + 'px', height: height + 'px' }">
|
||||||
<div class="modal-header" @mousedown="startDrag">
|
<div class="modal-header" @mousedown="startDrag">
|
||||||
<slot name="modalHeader" />
|
<slot name="modalHeader" />
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
@ -10,6 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<slot name="modalBody" />
|
<slot name="modalBody" />
|
||||||
|
<img v-if="isResizable" src="/assets/icons/resize-icon.svg" alt="resize" class="resize" @mousedown="startResize" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$slots.modalFooter" class="modal-footer">
|
<div v-if="$slots.modalFooter" class="modal-footer">
|
||||||
<slot name="modalFooter" />
|
<slot name="modalFooter" />
|
||||||
@ -29,6 +30,18 @@ const properties = defineProps({
|
|||||||
closable: {
|
closable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
isResizable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
modalWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 500
|
||||||
|
},
|
||||||
|
modalHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 280
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -46,6 +59,35 @@ function close() {
|
|||||||
emit('modal:close')
|
emit('modal:close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (re)size logics
|
||||||
|
const width = ref(properties.modalWidth)
|
||||||
|
const height = ref(properties.modalHeight)
|
||||||
|
let minWidth = ref(200)
|
||||||
|
let minHeight = ref(100)
|
||||||
|
let isResizing = ref(false)
|
||||||
|
|
||||||
|
let startWidth = 0
|
||||||
|
let startHeight = 0
|
||||||
|
|
||||||
|
const startResize = (event: MouseEvent) => {
|
||||||
|
isResizing.value = true
|
||||||
|
startWidth = width.value - event.clientX
|
||||||
|
startHeight = height.value - event.clientY
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeModal = (event: MouseEvent) => {
|
||||||
|
if (!isResizing.value) return
|
||||||
|
let newWidth = startWidth + event.clientX
|
||||||
|
let newHeight = startHeight + event.clientY
|
||||||
|
width.value = newWidth > minWidth.value ? newWidth : minWidth.value
|
||||||
|
height.value = newHeight > minHeight.value ? newHeight : minHeight.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopResize = () => {
|
||||||
|
isResizing.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// make modal draggable
|
// make modal draggable
|
||||||
let startX = 0
|
let startX = 0
|
||||||
let startY = 0
|
let startY = 0
|
||||||
@ -85,13 +127,41 @@ const stopDrag = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
addEventListener('mousemove', drag)
|
addEventListener('mousemove', drag)
|
||||||
addEventListener('mouseup', stopDrag)
|
addEventListener('mouseup', stopDrag)
|
||||||
|
addEventListener('mousemove', resizeModal)
|
||||||
|
addEventListener('mouseup', stopResize)
|
||||||
|
addEventListener('resize', handleResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
removeEventListener('mousemove', drag)
|
removeEventListener('mousemove', drag)
|
||||||
removeEventListener('mouseup', stopDrag)
|
removeEventListener('mouseup', stopDrag)
|
||||||
|
removeEventListener('mousemove', resizeModal)
|
||||||
|
removeEventListener('mouseup', stopResize)
|
||||||
|
removeEventListener('resize', handleResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure modal doesn't go off screen
|
||||||
|
watch(
|
||||||
|
() => x.value, (value) => {
|
||||||
|
if (value < 0) { x.value = 0 } else if (value + width.value > window.innerWidth) { x.value = window.innerWidth - width.value }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
watch(
|
||||||
|
() => y.value, (value) => {
|
||||||
|
if (value < 0) { y.value = 0 } else if (value + height.value > window.innerHeight) { y.value = window.innerHeight - height.value }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// also on window resize function
|
||||||
|
function handleResize() {
|
||||||
|
if (x.value + width.value > window.innerWidth) {
|
||||||
|
x.value = window.innerWidth - width.value
|
||||||
|
}
|
||||||
|
if (y.value + height.value > window.innerHeight) {
|
||||||
|
y.value = window.innerHeight - height.value
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -102,8 +172,6 @@ onUnmounted(() => {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
min-width: 500px;
|
|
||||||
min-height: 280px;
|
|
||||||
background-color: rgba($dark-gray, 0.8);
|
background-color: rgba($dark-gray, 0.8);
|
||||||
border: 2px solid $dark-cyan;
|
border: 2px solid $dark-cyan;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
@ -158,6 +226,16 @@ onUnmounted(() => {
|
|||||||
padding: 15px;
|
padding: 15px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.resize {
|
||||||
|
filter: invert(60%);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
cursor: nwse-resize;
|
||||||
|
}
|
||||||
|
|
||||||
.submit {
|
.submit {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
button {
|
button {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user