完成popconfirm组件的重构

master
yutent 2023-11-22 18:19:43 +08:00
parent 2f2d1ebbe9
commit 007ee67e87
2 changed files with 122 additions and 23 deletions

View File

@ -4,13 +4,26 @@
* @date 2023/03/21 16:14:10 * @date 2023/03/21 16:14:10
*/ */
import { css, html, Component, bind, styleMap, offset } from 'wkit' import {
css,
html,
Component,
bind,
unbind,
styleMap,
offset,
outsideClick,
clearOutsideClick
} from 'wkit'
import '../form/button.js'
const DEFAULT_TIPS = '请确认你的操作!' const DEFAULT_TIPS = '请确认你的操作!'
class PopConfirm extends Component { class PopConfirm extends Component {
static props = { static props = {
title: 'str!' title: 'str!',
confirmButtonType: 'str!primary'
} }
static styles = [ static styles = [
@ -29,14 +42,14 @@ class PopConfirm extends Component {
z-index: 9; z-index: 9;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
max-width: 360px; max-width: 260px;
min-width: 32px; min-width: 32px;
padding: 6px 8px; padding: 8px 12px 12px;
border-radius: 3px; border-radius: 3px;
font-size: var(--wc-tooltip-font, 14px); font-size: var(--wc-popconfirm-font, 14px);
background: var(--wc-tooltip-background, #fff); background: var(--wc-popconfirm-background, #fff);
color: var(--wc-tooltip-color, var(--color-dark-1)); color: var(--wc-popconfirm-color, var(--color-dark-1));
box-shadow: 0 0 3px var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.2)); box-shadow: 0 0 3px var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.3));
word-break: break-all; word-break: break-all;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
@ -47,17 +60,18 @@ class PopConfirm extends Component {
width: 8px; width: 8px;
height: 8px; height: 8px;
border-radius: 2px; border-radius: 2px;
background: var(--wc-tooltip-background, #fff); background: var(--wc-popconfirm-background, #fff);
content: ''; content: '';
transform: rotate(45deg); transform: rotate(45deg);
box-shadow: -1px -1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1)); box-shadow: -1px -1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1));
} }
&[placement='left-top'] { &[placement='left-top'] {
&::after { &::after {
right: 16px; right: 16px;
bottom: -4px; bottom: -4px;
box-shadow: 1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1)); box-shadow: 1px 1px 0
var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1));
} }
} }
&[placement='left-bottom'] { &[placement='left-bottom'] {
@ -70,7 +84,8 @@ class PopConfirm extends Component {
&::after { &::after {
left: 16px; left: 16px;
bottom: -4px; bottom: -4px;
box-shadow: 1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1)); box-shadow: 1px 1px 0
var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1));
} }
} }
&[placement='right-bottom'] { &[placement='right-bottom'] {
@ -80,23 +95,68 @@ class PopConfirm extends Component {
} }
} }
} }
`,
css`
.title {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 0;
--wc-icon-size: 16px;
wc-icon {
flex-shrink: 0;
color: var(--wc-popconfirm-icon-color, var(--color-red-1));
}
}
:host([hide-icon]) {
.title wc-icon {
display: none;
}
}
.actions {
display: flex;
justify-content: flex-end;
gap: 4px;
margin-top: 8px;
wc-button {
min-width: 40px;
height: 20px;
font-size: 12px;
&:first-child {
--wc-button-border-color: none;
}
}
}
` `
] ]
#poped = false
#click(ev) { #click(ev) {
let { left, top } = offset(this) let { left, top } = offset(this)
let placement = 'left' let placement = 'left'
let styles = { display: 'block' } let styles = { display: 'block' }
let st = document.documentElement.scrollTop
if (left < 360 || (left > 360 && window.innerWidth - left > 360)) { if (this.#poped) {
return
}
if (left < 260 || (left > 260 && window.innerWidth - left > 260)) {
placement = 'right' placement = 'right'
styles.left = left + 'px' styles.left = left + 'px'
} else { } else {
let right = window.innerWidth - left - this.clientWidth let right = window.innerWidth - left + this.clientWidth
styles.right = right + 'px' styles.right = right + 'px'
} }
if (top < 96) { if (top < 160) {
top += 8 + this.clientHeight top += 8 + this.clientHeight
placement += '-bottom' placement += '-bottom'
styles.top = top + 'px' styles.top = top + 'px'
@ -104,28 +164,68 @@ class PopConfirm extends Component {
let bottom = window.innerHeight - top + 8 let bottom = window.innerHeight - top + 8
placement += '-top' placement += '-top'
styles.bottom = bottom + 'px' styles.bottom = bottom + 'px'
if (st > 0) {
styles.transform = `translateY(-${st}px)`
} }
}
this.#poped = true
// //
this.$refs.tips.setAttribute('placement', placement) this.$refs.tips.setAttribute('placement', placement)
this.$refs.tips.style.cssText = styleMap(styles) this.$refs.tips.style.cssText = styleMap(styles)
this.$refs.tips.$animate() this.$refs.tips.$animate()
} }
#close() {
if (this.#poped) {
this.#poped = false
this.$refs.tips.$animate(true)
}
}
#confirm() {
this.$emit('confirm')
this.#close()
}
mounted() { mounted() {
// bind(this.$refs.wrap, 'mouseleave', ev => { this._outFn = outsideClick(this, _ => this.#close())
// this.$refs.tips.$animate(true)
// }) this._scrollFn = bind(document, 'scroll', ev => {
if (this.#poped) {
let st = document.documentElement.scrollTop
this.$refs.tips.style.transform = `translateY(-${st}px)`
}
})
}
unmounted() {
unbind(document, 'scroll', this._scrollFn)
clearOutsideClick(this._outFn)
} }
render() { render() {
return html` return html`
<main class="container"> <main class="container">
<div class="wrapper" ref="wrap" @click=${this.#click}> <div class="wrapper" @click=${this.#click}>
<slot></slot> <slot></slot>
</div> </div>
<div class="tooltip" ref="tips" #animation=${{}}> <div class="tooltip" ref="tips" #animation=${{}}>
<slot name="title">${this.title || DEFAULT_TIPS}</slot <header class="title">
><i class="trigon"></i> <wc-icon name="info"></wc-icon>
${this.title || DEFAULT_TIPS}
</header>
<footer class="actions">
<wc-button @click=${this.#close}>取消</wc-button>
<wc-button
solid
type=${this.confirmButtonType || 'primary'}
@click=${this.#confirm}
>确定</wc-button
>
</footer>
<i class="trigon"></i>
</div> </div>
</main> </main>
` `

View File

@ -34,7 +34,7 @@ class Tooltip extends Component {
font-size: var(--wc-tooltip-font, 14px); font-size: var(--wc-tooltip-font, 14px);
background: var(--wc-tooltip-background, #fff); background: var(--wc-tooltip-background, #fff);
color: var(--wc-tooltip-color, var(--color-dark-1)); color: var(--wc-tooltip-color, var(--color-dark-1));
box-shadow: 0 0 3px var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.2)); box-shadow: 0 0 3px var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.3));
word-break: break-all; word-break: break-all;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
@ -104,7 +104,6 @@ class Tooltip extends Component {
top += 8 + this.clientHeight top += 8 + this.clientHeight
placement += '-bottom' placement += '-bottom'
styles.top = top + 'px' styles.top = top + 'px'
// console.log('<><><>', st)
} else { } else {
let bottom = window.innerHeight - top + 8 + st let bottom = window.innerHeight - top + 8 + st
placement += '-top' placement += '-top'