Merge branch 'master' of ssh://github.com/bd-js/wcui
commit
c902c775f9
|
@ -19,7 +19,7 @@
|
||||||
- [x] `wc-space`间隔组件
|
- [x] `wc-space`间隔组件
|
||||||
- [ ] `wc-avatar`头像组件
|
- [ ] `wc-avatar`头像组件
|
||||||
- [x] `wc-badge`徽标组件
|
- [x] `wc-badge`徽标组件
|
||||||
- [ ] `wc-drawer`抽屉组件
|
- [x] `wc-drawer`抽屉组件
|
||||||
- [ ] `wc-collapse`折叠组件
|
- [ ] `wc-collapse`折叠组件
|
||||||
- [ ] `wc-counter`倒计时组件
|
- [ ] `wc-counter`倒计时组件
|
||||||
- [ ] `wc-drag`拖拽组件
|
- [ ] `wc-drag`拖拽组件
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@bd/wcui",
|
"name": "@bd/ui",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/**
|
||||||
|
* 拖拽插件的核心部分
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2019/08/23 19:41:21
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { $, bind, unbind, fire } from '@bd/core'
|
||||||
|
|
||||||
|
const DEF_OPT = {
|
||||||
|
axis: '', // x | y | xy 拖拽方向
|
||||||
|
limit: false, // false | window | parent 拖拽范围
|
||||||
|
overflow: true // 是否可拖拽出可视区外
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Drag {
|
||||||
|
constructor(elem) {
|
||||||
|
this.$elem = elem
|
||||||
|
|
||||||
|
this.#init()
|
||||||
|
}
|
||||||
|
|
||||||
|
#init() {
|
||||||
|
this.$elem.style.transform = ''
|
||||||
|
var { x, y } = this.$elem.getBoundingClientRect()
|
||||||
|
// _x, _y是位移,用于数据修正
|
||||||
|
this.pos = { x, y, _x: 0, _y: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag by
|
||||||
|
by(node, opt = {}) {
|
||||||
|
this.$drag = node
|
||||||
|
this.opt = Object.assign(Object.create(null), DEF_OPT, opt)
|
||||||
|
|
||||||
|
//
|
||||||
|
if (this.opt.limit !== false) {
|
||||||
|
this.opt.overflow = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鼠标状态图标
|
||||||
|
node.style.cursor = 'move'
|
||||||
|
|
||||||
|
this._handleResize = bind(window, 'resize', this.#init.bind(this))
|
||||||
|
|
||||||
|
// let
|
||||||
|
this._handleMousedown = bind(node, 'mousedown', ev => {
|
||||||
|
if (this.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var bcr = this.$elem.getBoundingClientRect()
|
||||||
|
|
||||||
|
/* 修正由于页面有滚动距离,导致拖拽位移计算不正确的情况 */
|
||||||
|
if (bcr.x - this.pos._x !== this.pos.x) {
|
||||||
|
this.pos.x = bcr.x - this.pos._x
|
||||||
|
}
|
||||||
|
if (bcr.y - this.pos._y !== this.pos.y) {
|
||||||
|
this.pos.y = bcr.y - this.pos._y
|
||||||
|
}
|
||||||
|
|
||||||
|
let mx = ev.pageX
|
||||||
|
let my = ev.pageY
|
||||||
|
|
||||||
|
let ww = document.documentElement.clientWidth
|
||||||
|
let wh = document.documentElement.clientHeight
|
||||||
|
|
||||||
|
let tw = bcr.width
|
||||||
|
let th = bcr.height
|
||||||
|
|
||||||
|
//限制区域, 4个值依次是: 上, 右, 下, 左
|
||||||
|
let limit = [0, ww - tw, wh - th, 0]
|
||||||
|
if (this.opt.limit === 'parent') {
|
||||||
|
let pbcr = this.$elem.parentNode.getBoundingClientRect()
|
||||||
|
limit = [pbcr.top, pbcr.right - tw, pbcr.bottom - th, pbcr.left]
|
||||||
|
}
|
||||||
|
|
||||||
|
let handleMove = bind(document, 'mousemove', ev => {
|
||||||
|
// 防止拖动到边缘时导致页面滚动
|
||||||
|
ev.preventDefault()
|
||||||
|
|
||||||
|
let _x = ev.pageX - mx + (bcr.x - this.pos.x)
|
||||||
|
let _y = ev.pageY - my + (bcr.y - this.pos.y)
|
||||||
|
|
||||||
|
// 将另外一个方向的值清零来实现单向拖拽
|
||||||
|
if (this.opt.axis === 'x') {
|
||||||
|
_y = 0
|
||||||
|
}
|
||||||
|
if (this.opt.axis === 'y') {
|
||||||
|
_x = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 限制不可拖拽出指定区域(可视区或者父容器)
|
||||||
|
if (this.opt.overflow === false) {
|
||||||
|
if (_x < limit[3] - this.pos.x) {
|
||||||
|
_x = limit[3] - this.pos.x
|
||||||
|
} else if (_x > limit[1] - this.pos.x) {
|
||||||
|
_x = limit[1] - this.pos.x
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_y < limit[0] - this.pos.y) {
|
||||||
|
_y = limit[0] - this.pos.y
|
||||||
|
} else if (_y > limit[2] - this.pos.y) {
|
||||||
|
_y = limit[2] - this.pos.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.pos._x = _x
|
||||||
|
this.pos._y = _y
|
||||||
|
fire(this.$elem, 'dragging', {
|
||||||
|
offset: {
|
||||||
|
x: this.pos.x + _x,
|
||||||
|
y: this.pos.y + _y
|
||||||
|
},
|
||||||
|
moved: { x: _x, y: _y }
|
||||||
|
})
|
||||||
|
this.$elem.style.transform = `translate(${_x}px, ${_y}px)`
|
||||||
|
})
|
||||||
|
|
||||||
|
let handleUp = bind(document, 'mouseup', ev => {
|
||||||
|
fire(this.$elem, 'dragged', {
|
||||||
|
offset: {
|
||||||
|
x: this.pos.x + this.pos._x,
|
||||||
|
y: this.pos.y + this.pos._y
|
||||||
|
},
|
||||||
|
moved: { x: this.pos._x, y: this.pos._y }
|
||||||
|
})
|
||||||
|
|
||||||
|
unbind(document, 'mousemove', handleMove)
|
||||||
|
unbind(document, 'mouseup', handleUp)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
unbind(window, 'resize', this._handleResize)
|
||||||
|
unbind(this.$drag, 'mousedown', this._handleMousedown)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,37 +4,56 @@
|
||||||
* @date 2023/03/27 10:39:29
|
* @date 2023/03/27 10:39:29
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { css, html, Component, nextTick, styleMap } from '@bd/core'
|
||||||
css,
|
|
||||||
html,
|
|
||||||
bind,
|
|
||||||
unbind,
|
|
||||||
Component,
|
|
||||||
outsideClick,
|
|
||||||
clearOutsideClick,
|
|
||||||
nextTick,
|
|
||||||
classMap,
|
|
||||||
styleMap
|
|
||||||
} from '@bd/core'
|
|
||||||
|
|
||||||
const DIRECTION = {
|
const ANIMATION = {
|
||||||
left: 'l2r-in',
|
left: {
|
||||||
right: 'r2l-in',
|
custom: [
|
||||||
top: 't2b-in',
|
{ transform: ' translateX(-100%)' },
|
||||||
bottom: 'b2t-in'
|
{ 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)' }
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Drawer extends Component {
|
class Drawer extends Component {
|
||||||
|
static animation = {}
|
||||||
static props = {
|
static props = {
|
||||||
title: { type: String, default: '', attribute: false },
|
title: '',
|
||||||
from: 'right',
|
from: 'right',
|
||||||
visible: false
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
observer(v) {
|
||||||
|
this.$anim.start(!v)
|
||||||
|
this.$refs.drawer.$anim.start(!v)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
width: '',
|
||||||
|
height: '',
|
||||||
|
'mask-close': false
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: none;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -42,9 +61,8 @@ class Drawer extends Component {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
transition: opacity 0.3s linear;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer {
|
.drawer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -54,19 +72,6 @@ class Drawer extends Component {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 24px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 0 24px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
&.l2r-in {
|
|
||||||
animation: l2r-in 0.3s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
&.r2l-in {
|
|
||||||
animation: r2l-in 0.3s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
&.t2b-in {
|
|
||||||
animation: t2b-in 0.3s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
&.b2t-in {
|
|
||||||
animation: b2t-in 0.3s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@ -90,11 +95,6 @@ class Drawer extends Component {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([visible]) {
|
|
||||||
display: block;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
css`
|
css`
|
||||||
:host([from='left']),
|
:host([from='left']),
|
||||||
|
@ -131,40 +131,6 @@ class Drawer extends Component {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
}
|
}
|
||||||
`,
|
|
||||||
css`
|
|
||||||
@keyframes r2l-in {
|
|
||||||
from {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes l2r-in {
|
|
||||||
from {
|
|
||||||
transform: translateX(-100%);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes b2t-in {
|
|
||||||
from {
|
|
||||||
transform: translateY(100%);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes t2b-in {
|
|
||||||
from {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -173,24 +139,35 @@ class Drawer extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
console.log('mounted title: ', this.title)
|
this.$on('click', ev => {
|
||||||
|
let path = ev.composedPath()
|
||||||
|
|
||||||
|
if (path[0] === ev.currentTarget && this['mask-close']) {
|
||||||
|
this.closeDrawer()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let classes = classMap({
|
let style = {}
|
||||||
drawer: true,
|
if ((this.from === 'left' || this.from === 'right') && this.width) {
|
||||||
[DIRECTION[this.from]]: this.visible
|
style = { width: this.width }
|
||||||
})
|
} else if ((this.from === 'top' || this.from === 'bottom') && this.height) {
|
||||||
|
style = { height: this.height }
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class=${classes}>
|
<div
|
||||||
|
class="drawer"
|
||||||
|
style=${styleMap(style)}
|
||||||
|
ref="drawer"
|
||||||
|
#animation=${ANIMATION[this.from]}
|
||||||
|
>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<span class="title"><slot name="title">${this.title}</slot></span>
|
<span class="title"><slot name="title">${this.title}</slot></span>
|
||||||
<wc-icon name="close" @click=${this.closeDrawer}></wc-icon>
|
<wc-icon name="close" @click=${this.closeDrawer}></wc-icon>
|
||||||
</header>
|
</header>
|
||||||
<main class="wrapper">
|
<main class="wrapper"><slot></slot></main>
|
||||||
<slot></slot>
|
|
||||||
</main>
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,6 @@ class CheckboxItem extends Component {
|
||||||
:host {
|
:host {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
line-height: 1;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ class RadioItem extends Component {
|
||||||
:host {
|
:host {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
line-height: 1;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ class Switch extends Component {
|
||||||
default: '',
|
default: '',
|
||||||
attribute: false
|
attribute: false
|
||||||
},
|
},
|
||||||
checked: false,
|
|
||||||
disabled: false,
|
disabled: false,
|
||||||
readonly: false
|
readonly: false
|
||||||
}
|
}
|
||||||
|
@ -23,7 +22,6 @@ class Switch extends Component {
|
||||||
:host {
|
:host {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
line-height: 1;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
@ -46,26 +44,13 @@ class Switch extends Component {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 14px;
|
width: 36px;
|
||||||
height: 14px;
|
height: 18px;
|
||||||
margin-right: 4px;
|
padding: 3px;
|
||||||
border: 1px solid var(--color-dark-1);
|
margin-right: 5px;
|
||||||
border-radius: 4px;
|
border-radius: 16px;
|
||||||
background: #fff;
|
background: var(--color-dark-1);
|
||||||
transition: box-shadow 0.15s linear;
|
transition: box-shadow 0.15s linear;
|
||||||
|
|
||||||
wc-icon {
|
|
||||||
display: block;
|
|
||||||
visibility: hidden;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
transform: scale(0);
|
|
||||||
transition: transform 0.15s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:host([checked]) .dot wc-icon {
|
|
||||||
visibility: visible;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -112,8 +97,8 @@ class Switch extends Component {
|
||||||
font-size: map.get($v, 'f');
|
font-size: map.get($v, 'f');
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
width: #{map.get($v, 'f')};
|
width: #{map.get($v, 'f') * 2.5};
|
||||||
height: #{map.get($v, 'f')};
|
height: #{map.get($v, 'f') * 1.25};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,15 +118,11 @@ class Switch extends Component {
|
||||||
@loop $t, $c in $colors {
|
@loop $t, $c in $colors {
|
||||||
:host([type='#{$t}']) {
|
:host([type='#{$t}']) {
|
||||||
label {
|
label {
|
||||||
color: var(--color-#{$c}-2);
|
color: var(--color-#{$c}-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
border-color: var(--color-#{$c}-2);
|
background: var(--color-#{$c}-1);
|
||||||
|
|
||||||
&::after {
|
|
||||||
background: var(--color-#{$c}-2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:host(:focus-within) .dot {
|
&:host(:focus-within) .dot {
|
||||||
|
@ -201,7 +182,7 @@ class Switch extends Component {
|
||||||
@click=${this.handleClick}
|
@click=${this.handleClick}
|
||||||
@keydown=${this.handleClick}
|
@keydown=${this.handleClick}
|
||||||
>
|
>
|
||||||
<span class="dot"><wc-icon name="get"></wc-icon></span>
|
<span class="dot"></span>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</label>`
|
</label>`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue