vuetify
Version:
Vue Material Component Framework
136 lines (125 loc) • 3.51 kB
text/typescript
// Styles
import '../../styles/components/_selection-controls.sass'
import './VSwitch.sass'
// Mixins
import Selectable from '../../mixins/selectable'
import VInput from '../VInput'
// Directives
import Touch from '../../directives/touch'
// Components
import { VFabTransition } from '../transitions'
import VProgressCircular from '../VProgressCircular/VProgressCircular'
// Helpers
import { keyCodes } from '../../util/helpers'
// Types
import { VNode, VNodeData } from 'vue'
/* @vue/component */
export default Selectable.extend({
name: 'v-switch',
directives: { Touch },
props: {
inset: Boolean,
loading: {
type: [Boolean, String],
default: false,
},
flat: {
type: Boolean,
default: false,
},
},
computed: {
classes (): object {
return {
...VInput.options.computed.classes.call(this),
'v-input--selection-controls v-input--switch': true,
'v-input--switch--flat': this.flat,
'v-input--switch--inset': this.inset,
}
},
attrs (): object {
return {
'aria-checked': String(this.isActive),
'aria-disabled': String(this.isDisabled),
role: 'switch',
}
},
// Do not return undefined if disabled,
// according to spec, should still show
// a color when disabled and active
validationState (): string | undefined {
if (this.hasError && this.shouldValidate) return 'error'
if (this.hasSuccess) return 'success'
if (this.hasColor !== null) return this.computedColor
return undefined
},
switchData (): VNodeData {
return this.setTextColor(this.loading ? undefined : this.validationState, {
class: this.themeClasses,
})
},
},
methods: {
genDefaultSlot (): (VNode | null)[] {
return [
this.genSwitch(),
this.genLabel(),
]
},
genSwitch (): VNode {
return this.$createElement('div', {
staticClass: 'v-input--selection-controls__input',
}, [
this.genInput('checkbox', {
...this.attrs,
...this.attrs$,
}),
this.genRipple(this.setTextColor(this.validationState, {
directives: [{
name: 'touch',
value: {
left: this.onSwipeLeft,
right: this.onSwipeRight,
},
}],
})),
this.$createElement('div', {
staticClass: 'v-input--switch__track',
...this.switchData,
}),
this.$createElement('div', {
staticClass: 'v-input--switch__thumb',
...this.switchData,
}, [this.genProgress()]),
])
},
genProgress (): VNode {
return this.$createElement(VFabTransition, {}, [
this.loading === false
? null
: this.$slots.progress || this.$createElement(VProgressCircular, {
props: {
color: (this.loading === true || this.loading === '')
? (this.color || 'primary')
: this.loading,
size: 16,
width: 2,
indeterminate: true,
},
}),
])
},
onSwipeLeft () {
if (this.isActive) this.onChange()
},
onSwipeRight () {
if (!this.isActive) this.onChange()
},
onKeydown (e: KeyboardEvent) {
if (
(e.keyCode === keyCodes.left && this.isActive) ||
(e.keyCode === keyCodes.right && !this.isActive)
) this.onChange()
},
},
})