ui/src/drawer/index.js

177 lines
3.5 KiB
JavaScript
Raw Normal View History

2023-03-27 19:34:30 +08:00
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2023/03/27 10:39:29
*/
2023-03-29 16:16:58 +08:00
import { css, html, Component, nextTick, styleMap } from '@bd/core'
2023-03-27 19:34:30 +08:00
2023-03-29 16:16:58 +08:00
const ANIMATION = {
left: {
custom: [
{ transform: ' translateX(-100%)' },
{ transform: ' translateX(0)' }
]
},
right: {
custom: [
{ transform: ' translateX(100%)' },
{ transform: ' translateX(0)' }
]
},
top: {
custom: [
{ transform: ' translateY(-100%)' },
{ transform: ' translateY(0)' }
]
},
bottom: {
custom: [
{ transform: ' translateY(100%)' },
{ transform: ' translateY(0)' }
]
}
2023-03-27 19:34:30 +08:00
}
class Drawer extends Component {
2023-03-28 19:40:39 +08:00
static animation = {}
2023-03-27 19:34:30 +08:00
static props = {
2023-03-28 19:40:39 +08:00
title: '',
2023-03-27 19:34:30 +08:00
from: 'right',
2023-03-28 19:40:39 +08:00
visible: {
type: Boolean,
default: false,
observer(v) {
2023-03-29 16:16:58 +08:00
this.$anim.start(!v)
this.$refs.drawer.$anim.start(!v)
2023-03-28 19:40:39 +08:00
}
},
2023-03-29 16:16:58 +08:00
width: '',
height: '',
'mask-close': false
2023-03-27 19:34:30 +08:00
}
static styles = [
css`
:host {
position: fixed;
left: 0;
top: 0;
z-index: 99;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
2023-03-28 19:40:39 +08:00
2023-03-27 19:34:30 +08:00
.drawer {
display: flex;
flex-direction: column;
position: absolute;
width: 50%;
height: 100%;
font-size: 14px;
background: #fff;
box-shadow: 0 0 24px rgba(0, 0, 0, 0.2);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
font-size: 16px;
color: var(--color-dark-2);
user-select: none;
wc-icon {
--size: 16px;
margin-right: 8px;
color: var(--color-grey-3);
cursor: pointer;
}
}
.wrapper {
flex: 1;
padding: 16px;
}
`,
css`
:host([from='left']),
:host([from='right']) {
.drawer {
width: 50%;
height: 100%;
}
}
:host([from='top']),
:host([from='bottom']) {
.drawer {
width: 100%;
height: 50%;
}
}
:host([from='left']) .drawer {
left: 0;
top: 0;
transform: translateX(-100%);
}
:host([from='top']) .drawer {
left: 0;
top: 0;
transform: translateY(-100%);
}
:host([from='right']) .drawer {
right: 0;
top: 0;
transform: translateX(100%);
}
:host([from='bottom']) .drawer {
left: 0;
bottom: 0;
transform: translateY(100%);
}
`
]
closeDrawer() {
this.$emit('close')
}
mounted() {
2023-03-28 19:40:39 +08:00
this.$on('click', ev => {
2023-03-29 16:16:58 +08:00
let path = ev.composedPath()
if (path[0] === ev.currentTarget && this['mask-close']) {
this.closeDrawer()
}
2023-03-28 19:40:39 +08:00
})
2023-03-27 19:34:30 +08:00
}
render() {
2023-03-29 16:16:58 +08:00
let style = {}
if ((this.from === 'left' || this.from === 'right') && this.width) {
style = { width: this.width }
} else if ((this.from === 'top' || this.from === 'bottom') && this.height) {
style = { height: this.height }
}
2023-03-27 19:34:30 +08:00
return html`
2023-03-29 16:16:58 +08:00
<div
class="drawer"
style=${styleMap(style)}
ref="drawer"
#animation=${ANIMATION[this.from]}
>
2023-03-27 19:34:30 +08:00
<header class="header">
<span class="title"><slot name="title">${this.title}</slot></span>
<wc-icon name="close" @click=${this.closeDrawer}></wc-icon>
</header>
2023-03-29 16:16:58 +08:00
<main class="wrapper"><slot></slot></main>
2023-03-27 19:34:30 +08:00
</div>
`
}
}
Drawer.reg('drawer')