Merge branch 'master' of ssh://github.com/bd-js/wcui
commit
8d9c42b019
|
@ -4,17 +4,8 @@
|
||||||
* @date 2023/03/06 15:17:25
|
* @date 2023/03/06 15:17:25
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { css, html, Component, bind, styleMap } from '@bd/core'
|
||||||
css,
|
|
||||||
html,
|
|
||||||
Component,
|
|
||||||
bind,
|
|
||||||
unbind,
|
|
||||||
nextTick,
|
|
||||||
styleMap
|
|
||||||
} from '@bd/core'
|
|
||||||
import '../form/input.js'
|
import '../form/input.js'
|
||||||
import Drag from '../drag/core.js'
|
|
||||||
|
|
||||||
let uniqueInstance = null // 缓存当前打开的alert/confirm/prompt类型的弹窗
|
let uniqueInstance = null // 缓存当前打开的alert/confirm/prompt类型的弹窗
|
||||||
let toastInstance = null // 缓存toast的实例
|
let toastInstance = null // 缓存toast的实例
|
||||||
|
@ -23,9 +14,11 @@ const LANG_TITLE = '提示'
|
||||||
const LANG_BTNS = ['取消', '确定']
|
const LANG_BTNS = ['取消', '确定']
|
||||||
// 要保证弹层唯一的类型
|
// 要保证弹层唯一的类型
|
||||||
const UNIQUE_TYPES = ['alert', 'confirm', 'prompt']
|
const UNIQUE_TYPES = ['alert', 'confirm', 'prompt']
|
||||||
const BUILDIN_TYPES = UNIQUE_TYPES.concat(['notify', 'toast'])
|
const BUILDIN_TYPES = UNIQUE_TYPES.concat(['toast'])
|
||||||
|
|
||||||
class Layer extends Component {
|
class Layer extends Component {
|
||||||
|
static animation = {}
|
||||||
|
|
||||||
static props = {
|
static props = {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -38,7 +31,8 @@ class Layer extends Component {
|
||||||
right: { type: String, attribute: false },
|
right: { type: String, attribute: false },
|
||||||
top: { type: String, attribute: false },
|
top: { type: String, attribute: false },
|
||||||
bottom: { type: String, attribute: false },
|
bottom: { type: String, attribute: false },
|
||||||
fixed: false,
|
background: { type: String, attribute: false },
|
||||||
|
'mask-color': { type: String, attribute: false },
|
||||||
mask: false,
|
mask: false,
|
||||||
'mask-close': false,
|
'mask-close': false,
|
||||||
title: { type: String, default: '', attribute: false },
|
title: { type: String, default: '', attribute: false },
|
||||||
|
@ -63,7 +57,6 @@ class Layer extends Component {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
:host([type='toast']),
|
:host([type='toast']),
|
||||||
:host([type='notify']),
|
|
||||||
:host([type='common']) {
|
:host([type='common']) {
|
||||||
.layer {
|
.layer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -148,7 +141,9 @@ class Layer extends Component {
|
||||||
text-indent: 8px;
|
text-indent: 8px;
|
||||||
--size: 16px;
|
--size: 16px;
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
::slotted(&__toast + &__toast) {
|
::slotted(&__toast + &__toast) {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
@ -255,19 +250,11 @@ class Layer extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:host([type='notify']) {
|
|
||||||
.layer {
|
|
||||||
width: 300px;
|
|
||||||
height: 120px;
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
padding: 0 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:host([type='toast']) {
|
:host([type='toast']) {
|
||||||
.layer {
|
.layer {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
background: none;
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -285,7 +272,6 @@ class Layer extends Component {
|
||||||
]
|
]
|
||||||
|
|
||||||
#wrapped = false
|
#wrapped = false
|
||||||
#dragIns = null
|
|
||||||
|
|
||||||
#resolve = null
|
#resolve = null
|
||||||
#reject = null
|
#reject = null
|
||||||
|
@ -301,36 +287,17 @@ class Layer extends Component {
|
||||||
this.promise.host = this
|
this.promise.host = this
|
||||||
}
|
}
|
||||||
|
|
||||||
#toggleDrag() {
|
|
||||||
// 这3类弹层不允许拖拽
|
|
||||||
if (UNIQUE_TYPES.includes(this.type)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.fixed) {
|
|
||||||
// 如之前有拖拽实例, 先销毁
|
|
||||||
if (this.#dragIns) {
|
|
||||||
this.#dragIns.destroy()
|
|
||||||
this.#dragIns = null
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let $title = this.$refs.box.firstElementChild
|
|
||||||
|
|
||||||
this.#dragIns = new Drag(this.$refs.box).by($title, {
|
|
||||||
overflow: !!this.overflow
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#intercept(value) {
|
#intercept(value) {
|
||||||
if (this.intercept) {
|
if (this.intercept) {
|
||||||
this.intercept(value, _ => {
|
this.intercept(value, _ => {
|
||||||
delete this.intercept
|
delete this.intercept
|
||||||
this.#resolve(value)
|
this.#resolve(value)
|
||||||
|
this.$animate(true)
|
||||||
this.$refs.box.$animate(true).then(_ => this.close())
|
this.$refs.box.$animate(true).then(_ => this.close())
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.#resolve(value)
|
this.#resolve(value)
|
||||||
|
this.$animate(true)
|
||||||
this.$refs.box.$animate(true).then(_ => this.close())
|
this.$refs.box.$animate(true).then(_ => this.close())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,21 +316,21 @@ class Layer extends Component {
|
||||||
fill: 'forwards'
|
fill: 'forwards'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
elem._anim.reverse()
|
elem._anim.reverse()
|
||||||
elem._anim.onfinish = _ => {
|
elem._anim.onfinish = _ => {
|
||||||
elem.remove()
|
elem.remove()
|
||||||
}
|
if (this.children.length === 0) {
|
||||||
if (this.children.length === 0) {
|
this.close()
|
||||||
this.close()
|
toastInstance = null
|
||||||
toastInstance = null
|
}
|
||||||
}
|
}
|
||||||
}, 3000)
|
}, 3000)
|
||||||
break
|
break
|
||||||
case 'notify':
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
this.$animate()
|
||||||
this.$refs.box.$animate()
|
this.$refs.box.$animate()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -375,6 +342,8 @@ class Layer extends Component {
|
||||||
bind(this.$refs.input, 'submit', ev => {
|
bind(this.$refs.input, 'submit', ev => {
|
||||||
this.#intercept(ev.target.value)
|
this.#intercept(ev.target.value)
|
||||||
})
|
})
|
||||||
|
} else if (this.type === 'toast') {
|
||||||
|
this.style.display = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有遮罩层时
|
// 有遮罩层时
|
||||||
|
@ -401,7 +370,9 @@ class Layer extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#toggleDrag()
|
if (this.background) {
|
||||||
|
this.$refs.box.style.backgroundColor = this.background
|
||||||
|
}
|
||||||
|
|
||||||
this.#play()
|
this.#play()
|
||||||
}
|
}
|
||||||
|
@ -426,49 +397,25 @@ class Layer extends Component {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭实例
|
* 关闭实例
|
||||||
* @param force {Boolean} 是否强制关闭
|
|
||||||
*/
|
*/
|
||||||
close(force) {
|
close() {
|
||||||
//
|
//
|
||||||
|
|
||||||
if (this.#wrapped) {
|
if (this.#wrapped) {
|
||||||
this.type = null
|
this.type = null
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
} else {
|
} else {
|
||||||
// 有拖拽实例, 先销毁
|
|
||||||
if (this.#dragIns) {
|
|
||||||
this.#dragIns.destroy()
|
|
||||||
}
|
|
||||||
// 不允许多开的类型, 需要清除
|
// 不允许多开的类型, 需要清除
|
||||||
if (UNIQUE_TYPES.includes(this.type)) {
|
if (UNIQUE_TYPES.includes(this.type)) {
|
||||||
uniqueInstance = null
|
uniqueInstance = null
|
||||||
}
|
}
|
||||||
|
this.$emit('close')
|
||||||
// 离场动画
|
this.remove()
|
||||||
if (this.from && !force) {
|
|
||||||
let _style = 'opacity:0;'
|
|
||||||
for (let k in this.from) {
|
|
||||||
_style += `${k}:${this.from[k]};`
|
|
||||||
}
|
|
||||||
this.$refs.box.style.cssText += _style
|
|
||||||
this.timer = setTimeout(() => {
|
|
||||||
this.$emit('close')
|
|
||||||
this.remove()
|
|
||||||
}, 200)
|
|
||||||
} else {
|
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.$emit('close')
|
|
||||||
this.remove()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按钮的点击事件
|
// 按钮的点击事件
|
||||||
handleBtnClick(ev) {
|
handleBtnClick(ev) {
|
||||||
if (
|
if (ev.target.tagName === 'BUTTON') {
|
||||||
ev.target.tagName === 'BUTTON' ||
|
|
||||||
ev.target.className === 'notify-button'
|
|
||||||
) {
|
|
||||||
let idx = +ev.target.dataset.idx || 0
|
let idx = +ev.target.dataset.idx || 0
|
||||||
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
|
@ -480,6 +427,7 @@ class Layer extends Component {
|
||||||
case 'prompt':
|
case 'prompt':
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
this.#reject()
|
this.#reject()
|
||||||
|
this.$animate(true)
|
||||||
this.$refs.box.$animate(true).then(_ => this.close())
|
this.$refs.box.$animate(true).then(_ => this.close())
|
||||||
} else {
|
} else {
|
||||||
let value = this.type === 'prompt' ? this.$refs.input.value : null
|
let value = this.type === 'prompt' ? this.$refs.input.value : null
|
||||||
|
@ -517,13 +465,6 @@ class Layer extends Component {
|
||||||
style=${styleMap({ display: !!this.title ? '' : 'none' })}
|
style=${styleMap({ display: !!this.title ? '' : 'none' })}
|
||||||
>
|
>
|
||||||
${this.title}
|
${this.title}
|
||||||
${this.type === 'notify'
|
|
||||||
? html`<wc-icon
|
|
||||||
name="close"
|
|
||||||
class="notify-button"
|
|
||||||
@click=${this.handleBtnClick}
|
|
||||||
></wc-icon>`
|
|
||||||
: ''}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="layer__content">
|
<div class="layer__content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
@ -541,29 +482,19 @@ class Layer extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
function layer(opt = {}) {
|
function layer(opt = {}) {
|
||||||
let layDom = document.createElement('wc-layer')
|
|
||||||
let { type = 'common', content = '' } = opt
|
let { type = 'common', content = '' } = opt
|
||||||
let alreadyInTree = false
|
let layDom =
|
||||||
|
type === 'toast'
|
||||||
|
? toastInstance || document.createElement('wc-layer')
|
||||||
|
: document.createElement('wc-layer')
|
||||||
|
let alreadyInTree = type === 'toast' && !!toastInstance
|
||||||
|
|
||||||
|
layDom.type = opt.type
|
||||||
|
|
||||||
if (type === 'toast') {
|
if (type === 'toast') {
|
||||||
opt = {
|
toastInstance = layDom
|
||||||
type,
|
|
||||||
content,
|
|
||||||
from: { top: 0 },
|
|
||||||
to: { top: '30px' }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toastInstance) {
|
|
||||||
// toastInstance.close(true)
|
|
||||||
layDom = toastInstance
|
|
||||||
alreadyInTree = true
|
|
||||||
} else {
|
|
||||||
toastInstance = layDom
|
|
||||||
}
|
|
||||||
layDom.top = '20px'
|
layDom.top = '20px'
|
||||||
} else {
|
} else {
|
||||||
layDom.mask = opt.mask
|
|
||||||
|
|
||||||
if (opt.btns && opt.btns.length) {
|
if (opt.btns && opt.btns.length) {
|
||||||
layDom.btns = opt.btns
|
layDom.btns = opt.btns
|
||||||
}
|
}
|
||||||
|
@ -573,50 +504,26 @@ function layer(opt = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
layDom.mask = opt.mask
|
layDom.mask = opt.mask
|
||||||
layDom['mask-close'] = opt['mask-close']
|
layDom.title = opt.title
|
||||||
|
|
||||||
if (opt.hasOwnProperty('overflow')) {
|
|
||||||
layDom.overflow = opt.overflow
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 额外样式 */
|
|
||||||
|
|
||||||
layDom.radius = opt.radius
|
|
||||||
layDom.background = opt.background
|
|
||||||
|
|
||||||
if (opt.size && typeof opt.size === 'object') {
|
|
||||||
layDom.size = opt.size
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这3种类型, 只允许同时存在1个, 如果之前有弹出则关闭
|
// 这3种类型, 只允许同时存在1个, 如果之前有弹出则关闭
|
||||||
if (UNIQUE_TYPES.includes(opt.type)) {
|
if (UNIQUE_TYPES.includes(type)) {
|
||||||
if (uniqueInstance) {
|
if (uniqueInstance) {
|
||||||
uniqueInstance.close(true)
|
uniqueInstance.$animate(true).then(_ => {
|
||||||
|
uniqueInstance.close()
|
||||||
|
uniqueInstance = layDom
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uniqueInstance = layDom
|
||||||
}
|
}
|
||||||
uniqueInstance = layDom
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.to && typeof opt.to === 'object') {
|
|
||||||
layDom.to = opt.to
|
|
||||||
if (opt.from && typeof opt.from === 'object') {
|
|
||||||
layDom.from = opt.from
|
|
||||||
} else {
|
|
||||||
layDom.from = opt.to
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layDom.type = opt.type
|
|
||||||
layDom.title = opt.title
|
|
||||||
|
|
||||||
layDom.fixed = !!opt.fixed
|
|
||||||
|
|
||||||
if (alreadyInTree) {
|
if (alreadyInTree) {
|
||||||
let tmp = document.createElement('template')
|
let tmp = document.createElement('template')
|
||||||
tmp.innerHTML = opt.content
|
tmp.innerHTML = content
|
||||||
|
|
||||||
layDom.appendChild(tmp.content.cloneNode(true))
|
layDom.appendChild(tmp.content.cloneNode(true))
|
||||||
|
|
||||||
layDom.updated()
|
layDom.updated()
|
||||||
} else {
|
} else {
|
||||||
layDom.innerHTML = content
|
layDom.innerHTML = content
|
||||||
|
@ -685,20 +592,6 @@ layer.prompt = function (title = LANG_TITLE, defaultValue = '', intercept) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.notify = function (content) {
|
|
||||||
return this({
|
|
||||||
type: 'notify',
|
|
||||||
title: '通知',
|
|
||||||
content,
|
|
||||||
fixed: true,
|
|
||||||
mask: false,
|
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
from: { right: '-300px', top: 0 },
|
|
||||||
to: { right: 0 }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
layer.toast = function (txt, type = 'info') {
|
layer.toast = function (txt, type = 'info') {
|
||||||
var ico = type
|
var ico = type
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
Loading…
Reference in New Issue