Version 1.0.0 - Finalisation de Account et de GuildHeader
This commit is contained in:
163
src/components/UI/Selector.vue
Normal file
163
src/components/UI/Selector.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<script setup lang="ts">
|
||||
import IconAction from './IconAction.vue';
|
||||
import { ref, onMounted, watch, onUnmounted } from 'vue';
|
||||
import { useSlots } from 'vue';
|
||||
|
||||
const slots = useSlots();
|
||||
const boxWidth = ref(0);
|
||||
const box = ref(null);
|
||||
|
||||
const allSlots = slots.default ? slots.default() : [];
|
||||
|
||||
var firstSlot = allSlots[0] || null;
|
||||
var otherSlots = allSlots.slice(1);
|
||||
|
||||
const showMenu = ref(false);
|
||||
|
||||
function selectOption(index) {
|
||||
// Make it like a select
|
||||
if (otherSlots[index]) {
|
||||
const oldFirstSlot = firstSlot;
|
||||
firstSlot = otherSlots[index];
|
||||
otherSlots.splice(index, 1);
|
||||
otherSlots.push(oldFirstSlot);
|
||||
showMenu.value = false; // Hide the menu after selection
|
||||
}
|
||||
updateModelValue(firstSlot ? firstSlot.props.value : '');
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: String
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
function updateModelValue(value) {
|
||||
emit('update:modelValue', value);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
window.addEventListener('rightclick', (e) => {
|
||||
e.preventDefault(); // Prevent default context menu
|
||||
});
|
||||
|
||||
window.addEventListener('click', (e) => {
|
||||
hideMenu(e);
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
showMenu.value = false;
|
||||
|
||||
});
|
||||
|
||||
updateModelValue(firstSlot ? firstSlot.props.value : '');
|
||||
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('rightclick', (e) => {
|
||||
e.preventDefault(); // Prevent default context menu
|
||||
});
|
||||
window.removeEventListener('click', (e) => {
|
||||
hideMenu(e);
|
||||
});
|
||||
|
||||
window.removeEventListener('resize', () => {
|
||||
showMenu.value = false;
|
||||
});
|
||||
});
|
||||
|
||||
function hideMenu(e) {
|
||||
// Check if the click is outside the context menu
|
||||
if (box.value && !box.value.contains(e.target)) {
|
||||
showMenu.value = false; // Hide context menu on click outside
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
firstSlot: () => {
|
||||
return firstSlot;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<div ref="box" :class="showMenu ? `showed firstbox` : 'firstbox'" @click="showMenu = !showMenu">
|
||||
<template v-if="firstSlot">
|
||||
<component :is="firstSlot" />
|
||||
</template>
|
||||
<IconAction
|
||||
:icon="showMenu ? 'fa-solid fa-angle-up' : 'fa-solid fa-angle-down'"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="otherSlots.length && showMenu">
|
||||
<div class="container">
|
||||
<div v-for="(slot, index) in otherSlots" :style="`width: ${box.offsetWidth - 10}px;`" class="option" @click="selectOption(index)" >
|
||||
<component :is="slot" :key="index" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</section>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.firstbox {
|
||||
background-color: var(--tertiary);
|
||||
color: var(--text);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
||||
color: var(--text);
|
||||
border: none;
|
||||
border-radius: 0px 0px 5px 5px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
justify-content: space-between;
|
||||
user-select: none;
|
||||
overflow-y: auto;
|
||||
max-height: 16vh;
|
||||
}
|
||||
|
||||
.container .option:last-child {
|
||||
border-radius: 0px 0px 5px 5px !important;
|
||||
}
|
||||
|
||||
.container .option:only-child {
|
||||
border-radius: 0px 0px 5px 5px !important;
|
||||
}
|
||||
|
||||
.container .option:first-child {
|
||||
border-top: 1px solid var(--secondary) !important;
|
||||
}
|
||||
|
||||
.option {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
background-color: var(--tertiary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: var(--primary-hover);
|
||||
color: var(--text-inverse);
|
||||
}
|
||||
|
||||
.showed {
|
||||
/* margin-bottom: 0 !important;
|
||||
padding-bottom: 0; */
|
||||
border-radius: 5px 5px 0 0 !important;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user