Merge branch 'master' of ssh://github.com/bd-js/wcui

master
chenjiajian 2023-03-29 19:31:11 +08:00
commit c902c775f9
7 changed files with 210 additions and 117 deletions

View File

@ -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`拖拽组件

View File

@ -1,5 +1,5 @@
{ {
"name": "@bd/wcui", "name": "@bd/ui",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"files": [ "files": [

137
src/drag/core.js Normal file
View File

@ -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)
}
}

View File

@ -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>
` `
} }

View File

@ -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;

View File

@ -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;

View File

@ -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>`
} }