/** * {} * @author yutent * @date 2023/03/21 16:14:10 */ import { nextTick, css, html, Component } from '@bd/core' import '../icon/index.js' class Checkbox extends Component { static props = { value: { type: Array, default: [], attribute: false, observer() { this.#updateChildrenStat() } }, disabled: false, readonly: false } static styles = css` :host { display: inline-flex; flex-wrap: wrap; align-items: center; } ` mounted() { this.$on('child-change', ev => { ev.stopPropagation() let idx = this.value.indexOf(ev.value) if (idx > -1) { this.value.splice(idx, 1) } else { this.value.push(ev.value) } this.$emit('change', { data: this.value }) }) this.#updateChildrenStat(true) } #updateChildrenStat(checkAll) { Array.from(this.children).forEach(it => { if (it.tagName === 'WC-CHECKBOX') { if (it.root) { if (checkAll) { it.disabled = this.disabled it.readOnly = this.readOnly } it.checked = this.value.includes(it.value) } } else { it.remove() } }) } } class CheckboxItem extends Component { static props = { value: { type: String, default: '', attribute: false }, checked: false, disabled: false, readonly: false } static styles = [ css` :host { display: inline-flex; align-items: center; line-height: 1; font-size: 14px; cursor: pointer; label { display: flex; justify-content: center; align-items: center; min-width: 32px; padding-right: 16px; line-height: 1; -moz-user-select: none; user-select: none; white-space: nowrap; cursor: inherit; outline: none; color: var(--color-dark-1); } .dot { display: flex; justify-content: center; align-items: center; width: 16px; height: 16px; margin-right: 4px; border: 1px solid var(--color-dark-1); border-radius: 4px; background: #fff; 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); } } `, css` :host(:focus-within) .dot { box-shadow: 0 0 0 2px var(--color-plain-a); } `, // 尺寸 css` @use 'sass:map'; $sizes: ( 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 ) ); @loop $s, $v in $sizes { :host([size='#{$s}']) { height: map.get($v, 'h'); font-size: map.get($v, 'f'); .dot { width: #{map.get($v, 'f')}; height: #{map.get($v, 'f')}; } } } `, // 配色 css` $colors: ( primary: 'teal', info: 'blue', success: 'green', warning: 'orange', danger: 'red', secondary: 'dark', help: 'grey' ); @loop $t, $c in $colors { :host([type='#{$t}']) { label { color: var(--color-#{$c}-2); } .dot { border-color: var(--color-#{$c}-2); &::after { background: var(--color-#{$c}-2); } } &:host(:focus-within) .dot { box-shadow: 0 0 0 2px var(--color-#{$c}-a); } } } `, // 状态 css` :host([readonly]), :host([disabled]) { cursor: not-allowed; opacity: 0.6; } :host([readonly]) { cursor: default; } ` ] toggleCheck(ev) { if (this.disabled || this.readOnly) { return } ev.stopPropagation() this.checked = !this.checked let data = { value: this.value, checked: this.checked } if (this.inGroup) { this.parentNode.$emit('child-change', data) } else { this.$emit('change', data) } } handleClick(ev) { if (ev.type === 'click' || ev.keyCode === 32) { this.toggleCheck(ev) } } mounted() { if (this.parentNode?.tagName === 'WC-CHECKBOX-GROUP') { this.inGroup = true } } render() { return html` ` } } Checkbox.reg('checkbox-group') CheckboxItem.reg('checkbox')