Newer
Older
import { computed, type Ref, watch } from 'vue';
import { iconsSet } from '@/common/constants/icons';
import type { IDrawerProps } from '@interfaces/componentsProps';

Дмитрий Малюгин
committed
import { convertThemeToColor, convertThemeToSecondaryColor, convertThemeToTextColor } from '@helpers/common';
import type { CustomWindow } from '@interfaces/common';
const props = withDefaults(defineProps<IDrawerProps>(), {
position: 'left',
width: 400,
modal: true,
dismissible: true,
theme: 'white',

Дмитрий Малюгин
committed
darknessTheme: '500',
headerDivider: false,
footerDivider: false,
});
const body = document.querySelector('body')!;
const emit = defineEmits(['onClose']);
const visible = defineModel<boolean>('visible', {
set(value) {
if (!value) {
(window as CustomWindow).blockPopupActions = false;
body.style.overflow = 'auto';
watch(visible, () => {
if (visible.value) {
(window as CustomWindow).blockPopupActions = true;
body.style.overflow = 'hidden';
}
});
const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));

Дмитрий Малюгин
committed
const secondaryColor = computed(() => convertThemeToSecondaryColor(props.theme, props.darknessTheme));
const color = computed(() =>
props.textColor
? convertThemeToColor(props.textColor, props.darknessTextColor)
: convertThemeToTextColor(props.theme, props.darknessTheme),
const drawerWidth = computed(() => {
if (+props.width < 200) return '200px';
return `${props.width}px`;
});
</script>
<template>
<article>
<section
v-if="modal"
:class="[
'drawerBackground',
{
drawerBackgroundOpened: visible,
},
]"
@pointerdown="() => (dismissible ? (visible = false) : '')"

Дмитрий Малюгин
committed
:style="`color: ${color}; background-color: ${themeColor}`"
:class="[
'drawer',
{
drawerLeft: position === 'left',
drawerRight: position === 'right',
drawerTop: position === 'top',
drawerBottom: position === 'bottom',
drawerVertical: position === 'top' || position === 'bottom',
},
]"
>
<header class="drawerHeader">
<slot name="header" />
<button class="buttonClose" @click.prevent="visible = false">

Дмитрий Малюгин
committed
<component :is="iconsSet[closeIcon]" :color="color" />
<div v-if="headerDivider" class="divider divider-header"></div>
<div class="main">
<slot />
</div>
<div v-if="footerDivider" class="divider"></div>
<footer class="drawerFooter">
<slot name="footer" />
</footer>
</div>
</section>
</article>
</template>
<style scoped>
.drawerBackground {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
transition: all ease-out 0.2s;
z-index: -50;
opacity: 0;
}
.drawerBackgroundOpened {
opacity: 1;
}
.drawer {
width: v-bind(drawerWidth);
position: fixed;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
transition: transform ease-out 0.2s;

Дмитрий Малюгин
committed
border-right: 2px solid v-bind(secondaryColor);
}
.drawerVertical {
width: 100vw !important;
height: v-bind(drawerWidth) !important;
transform: translateX(0) !important;
}
.drawerLeft {
transform: translateX(-100%);
top: 0;
left: 0;
}
.drawerRight {
transform: translateX(100%);
top: 0;
right: 0;
}
.drawerTop {
transform: translateY(-100%);
top: 0;
left: 0;
}
.drawerBottom {
transform: translateY(100%);
bottom: 0;
left: 0;
}
.drawerHeader {
font-weight: bold;
font-size: 32px;
width: calc(100% - 30px);
overflow: auto;
}
.main {
flex: 1 1 auto;
overflow: auto;
padding-right: 10px;

Дмитрий Малюгин
committed
background-color: v-bind(secondaryColor);
.divider-header {
position: absolute;
left: 20px;
top: 65px;
width: calc(100% - 40px);
}
.buttonClose {
position: absolute;
right: 20px;
width: 30px;
display: flex;
align-items: center;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;

Дмитрий Малюгин
committed
background-color: v-bind(secondaryColor);