2020-12-26 15:03:12 +01:00
|
|
|
<template>
|
|
|
|
<div class="dropdown-container" ref="container">
|
2021-01-05 00:50:24 +01:00
|
|
|
<button :title="title" ref="button" @click.stop="toggle($event)">
|
2020-12-26 15:03:12 +01:00
|
|
|
<i class="icon" :class="iconClass" v-if="iconClass" />
|
|
|
|
<span class="text" v-text="text" v-if="text" />
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<div class="dropdown fade-in" :id="id" :class="{hidden: !visible}" ref="dropdown">
|
|
|
|
<slot />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
name: "Dropdown",
|
|
|
|
emits: ['click'],
|
|
|
|
props: {
|
|
|
|
id: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
|
|
|
|
items: {
|
|
|
|
type: Array,
|
|
|
|
default: () => [],
|
|
|
|
},
|
|
|
|
|
|
|
|
iconClass: {
|
2021-01-14 00:15:35 +01:00
|
|
|
default: 'fa fa-ellipsis-h',
|
2020-12-26 15:03:12 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
text: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
|
|
|
|
title: {
|
|
|
|
type: String,
|
|
|
|
},
|
2022-04-10 01:57:39 +02:00
|
|
|
|
|
|
|
keepOpenOnItemClick: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
2020-12-26 15:03:12 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
visible: false,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
documentClickHndl(event) {
|
|
|
|
if (!this.visible)
|
|
|
|
return
|
|
|
|
|
|
|
|
let element = event.target
|
|
|
|
while (element) {
|
2021-01-18 01:28:10 +01:00
|
|
|
if (!this.$refs.dropdown)
|
|
|
|
break
|
|
|
|
if (element === this.$refs.dropdown.element)
|
2020-12-26 15:03:12 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
element = element.parentElement
|
|
|
|
}
|
|
|
|
|
|
|
|
this.close()
|
|
|
|
},
|
|
|
|
|
|
|
|
close() {
|
|
|
|
this.visible = false
|
|
|
|
document.removeEventListener('click', this.documentClickHndl)
|
|
|
|
},
|
|
|
|
|
|
|
|
open() {
|
|
|
|
document.addEventListener('click', this.documentClickHndl)
|
|
|
|
this.visible = true
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
const element = this.$refs.dropdown
|
|
|
|
element.style.left = 0
|
|
|
|
element.style.top = parseFloat(getComputedStyle(this.$refs.button).height) + 'px'
|
|
|
|
|
2020-12-31 01:36:02 +01:00
|
|
|
if (element.getBoundingClientRect().left > window.innerWidth/2)
|
|
|
|
element.style.left = (-element.clientWidth + parseFloat(getComputedStyle(this.$refs.button).width)) + 'px'
|
2020-12-26 15:03:12 +01:00
|
|
|
|
2020-12-31 01:36:02 +01:00
|
|
|
if (element.getBoundingClientRect().top > window.innerHeight/2)
|
|
|
|
element.style.top = (-element.clientHeight + parseFloat(getComputedStyle(this.$refs.button).height)) + 'px'
|
2020-12-26 15:03:12 +01:00
|
|
|
}, 10)
|
|
|
|
},
|
|
|
|
|
2021-01-05 00:50:24 +01:00
|
|
|
toggle(event) {
|
|
|
|
event.stopPropagation()
|
|
|
|
this.$emit('click')
|
2020-12-26 15:03:12 +01:00
|
|
|
this.visible ? this.close() : this.open()
|
|
|
|
},
|
2023-05-05 20:46:42 +02:00
|
|
|
|
|
|
|
onKeyUp(event) {
|
|
|
|
event.stopPropagation()
|
|
|
|
if (event.key === 'Escape') {
|
|
|
|
this.close()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
mounted() {
|
|
|
|
document.body.addEventListener('keyup', this.onKeyUp)
|
|
|
|
},
|
|
|
|
|
|
|
|
unmounted() {
|
|
|
|
document.body.removeEventListener('keyup', this.onKeyUp)
|
2020-12-26 15:03:12 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.dropdown-container {
|
|
|
|
position: relative;
|
2022-03-30 01:43:59 +02:00
|
|
|
display: inline-flex;
|
2020-12-26 15:03:12 +01:00
|
|
|
flex-direction: column;
|
|
|
|
|
2023-05-04 02:19:09 +02:00
|
|
|
button {
|
|
|
|
background: $default-bg-2;
|
|
|
|
border: 0;
|
|
|
|
padding: 0.5em;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
color: $default-hover-fg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-26 15:03:12 +01:00
|
|
|
.dropdown {
|
|
|
|
position: absolute;
|
|
|
|
width: max-content;
|
|
|
|
background: $dropdown-bg;
|
|
|
|
border-radius: .25em;
|
|
|
|
border: $default-border-3;
|
|
|
|
box-shadow: $dropdown-shadow;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
z-index: 1;
|
|
|
|
}
|
|
|
|
}
|
2023-05-04 02:19:09 +02:00
|
|
|
|
|
|
|
:deep(.dropdown-container) {
|
|
|
|
button {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
color: $default-fg-2;
|
|
|
|
background: $dropdown-bg;
|
|
|
|
border: 0;
|
|
|
|
padding: 0.75em 0.5em;
|
|
|
|
text-align: left;
|
|
|
|
letter-spacing: 0.01em;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
background: $hover-bg;
|
|
|
|
color: $default-fg-2;
|
|
|
|
}
|
|
|
|
|
|
|
|
.text {
|
|
|
|
padding-left: 0.25em;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-26 15:03:12 +01:00
|
|
|
</style>
|