230 lines
4.6 KiB
JavaScript
230 lines
4.6 KiB
JavaScript
/**
|
|
* {}
|
|
* @author yutent<yutent.io@gmail.com>
|
|
* @date 2023/03/21 16:14:10
|
|
*/
|
|
|
|
import { nextTick, css, html, Component, classMap } from 'wkit'
|
|
|
|
class Switch extends Component {
|
|
static props = {
|
|
value: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
inactiveText: '',
|
|
activeText: '',
|
|
inlineText: false,
|
|
disabled: false,
|
|
readonly: false
|
|
}
|
|
|
|
static styles = [
|
|
css`
|
|
:host {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
|
|
label {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-width: 32px;
|
|
padding: 0 8px 0 2px;
|
|
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;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
min-width: 36px;
|
|
height: 18px;
|
|
padding: 0 4px;
|
|
margin-right: 5px;
|
|
line-height: 14px;
|
|
border-radius: 16px;
|
|
background: var(--color-plain-3);
|
|
transition: box-shadow 0.2s ease, background 0.2s ease;
|
|
|
|
&::before {
|
|
display: block;
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
content: '';
|
|
}
|
|
|
|
&::after {
|
|
display: flex;
|
|
padding: 0 2px;
|
|
font-size: 12px;
|
|
content: attr(st);
|
|
color: #fff;
|
|
}
|
|
|
|
&.open {
|
|
flex-direction: row-reverse;
|
|
background: var(--color-teal-1);
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
|
|
css`
|
|
:host(:focus-within) .dot {
|
|
box-shadow: 0 0 0 2px var(--color-plain-a);
|
|
}
|
|
`,
|
|
// 尺寸
|
|
css`
|
|
@use 'sass:map';
|
|
@use 'sass:math';
|
|
$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
|
|
)
|
|
);
|
|
|
|
@function double($n) {
|
|
$m: math.round($n);
|
|
|
|
@if $m % 2 == 0px {
|
|
@return $m;
|
|
}
|
|
@return $m + 1;
|
|
}
|
|
|
|
@loop $s, $v in $sizes {
|
|
:host([size='#{$s}']) {
|
|
height: map.get($v, 'h');
|
|
font-size: map.get($v, 'f');
|
|
|
|
.dot {
|
|
min-width: #{map.get($v, 'f') * 2.5};
|
|
height: #{double(map.get($v, 'f') * 1.25)};
|
|
line-height: #{map.get($v, 'f')};
|
|
|
|
&::before {
|
|
width: #{map.get($v, 'f')};
|
|
height: #{map.get($v, 'f')};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
// 配色
|
|
css`
|
|
$colors: (
|
|
primary: 'teal',
|
|
info: 'blue',
|
|
success: 'green',
|
|
warning: 'orange',
|
|
danger: 'red'
|
|
);
|
|
|
|
@loop $t, $c in $colors {
|
|
:host([type='#{$t}']) {
|
|
.dot.open {
|
|
background: var(--color-#{$c}-1);
|
|
}
|
|
|
|
&: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.value = !this.value
|
|
let data = {
|
|
value: this.value
|
|
}
|
|
|
|
this.$emit('input')
|
|
this.$emit('change', data)
|
|
}
|
|
|
|
handleClick(ev) {
|
|
if (ev.type === 'click' || ev.keyCode === 32) {
|
|
ev.preventDefault()
|
|
this.toggleCheck(ev)
|
|
}
|
|
}
|
|
|
|
mounted() {}
|
|
|
|
render() {
|
|
let classes = classMap({ dot: true, open: this.value })
|
|
return html` <label
|
|
tabindex=${this.disabled || this.readOnly ? 'none' : 0}
|
|
@click=${this.handleClick}
|
|
@keydown=${this.handleClick}
|
|
>
|
|
<span
|
|
class=${classes}
|
|
st=${this.inlineText
|
|
? this.value
|
|
? this.activeText
|
|
: this.inactiveText
|
|
: ''}
|
|
></span>
|
|
<slot
|
|
>${!this.inlineText
|
|
? this.value
|
|
? this.activeText
|
|
: this.inactiveText
|
|
: ''}</slot
|
|
>
|
|
</label>`
|
|
}
|
|
}
|
|
|
|
Switch.reg('switch')
|
JavaScript
98.9%
CSS
1.1%