/** * {按钮组件} * @author yutent * @date 2023/03/06 15:17:25 */ import { css, html, Component, nextTick } from '@bd/core' import '../icon/index.js' class Button extends Component { static props = { type: 'primary', icon: '', size: 'l', autofocus: false, loading: { type: Boolean, default: false, observer(val) { if (val) { this.cacheIcon = this.icon this.icon = 'loading' } else { this.icon = this.cacheIcon || '' } } }, disabled: false, lazy: 0 // 并发拦截时间, 单位毫秒 } static styles = [ // 基础样式 css` :host { overflow: hidden; display: inline-flex; border: 0; border-radius: 3px; user-select: none; -moz-user-select: none; color: var(--color-dark-1); font-size: 14px; cursor: pointer; transition: box-shadow 0.15s linear; button { display: flex; justify-content: center; align-items: center; width: 100%; min-width: 1px; height: inherit; padding: var(--button-padding, 0 4px); line-height: 1; border: 1px solid transparent; border-radius: inherit; white-space: nowrap; background: #fff; font-size: inherit; font-family: inherit; outline: none; color: inherit; cursor: inherit; transition: background 0.15s linear; &::-moz-focus-inner { border: none; } } .icon { --size: var(--icon-size, 18px); margin-right: 4px; } } :host(:focus-within) { box-shadow: 0 0 0 2px var(--color-plain-a); } `, // 尺寸 css` @use 'sass:map'; $sizes: ( s: ( w: 52px, h: 20px, f: 12px ), m: ( w: 72px, h: 24px, f: 12px ), l: ( w: 108px, h: 32px, f: 14px ), xl: ( w: 132px, h: 36px, f: 14px ), xxl: ( w: 160px, h: 44px, f: 14px ), xxxl: ( w: 192px, h: 52px, f: 16px ), xxxxl: ( w: 212px, h: 64px, f: 18px ) ); @loop $s, $v in $sizes { :host([size='#{$s}']) { min-width: map.get($v, 'w'); height: map.get($v, 'h'); font-size: map.get($v, 'f'); .icon { --size: #{map.get($v, 'f')}; } } :host([size='#{$s}'][circle]) { width: map.get($v, 'h'); height: map.get($v, 'h'); } } :host([dashed]) button { border-style: dashed; } :host([round]) { border-radius: 32px; } :host([circle]) { min-width: 0; border-radius: 50%; button { padding: 0; } .icon { margin-right: 0; } slot { display: none; } } `, // 配色 css` $colors: ( primary: 'teal', info: 'blue', success: 'green', warning: 'orange', danger: 'red', secondary: 'dark', help: 'grey' ); @loop $t, $c in $colors { :host([type='#{$t}']) { button { color: var(--color-#{$c}-2); border-color: var(--color-#{$c}-2); &:hover { color: var(--color-#{$c}-1); border-color: var(--color-#{$c}-1); } &:active { color: var(--color-#{$c}-3); } &:disabled { color: var(--color-#{$c}-2); } } &:host([solid]) button { border: 0; color: #fff; background: var(--color-#{$c}-2); &:hover { background: var(--color-#{$c}-1); } &:active { background: var(--color-#{$c}-3); } &:disabled { background: var(--color-#{$c}-2); } } &:host(:focus-within) { box-shadow: 0 0 0 2px var(--color-#{$c}-a); } } } `, // 状态 css` :host([loading]), :host([disabled]) { cursor: not-allowed; opacity: 0.6; } ` ] created() { this.stamp = 0 this._clickFn = this.$on( 'click', ev => { let { loading, disabled, lazy } = this let now = Date.now() if (loading || disabled) { return ev.stopPropagation() } // 并发拦截 if (lazy > 0 && now - this.stamp < lazy) { return ev.stopPropagation() } this.stamp = now }, true ) } mounted() { if (this.autofocus) { this.$refs.btn.setAttribute('autofocus', '') // 需要focus()才能聚焦成功 nextTick(_ => this.$refs.btn.focus()) } } unmounted() { this.$off('click', this._clickFn) } render() { return html` ` } } customElements.define('wc-button', Button)