vuetify
Version:
Vue Material Component Framework
172 lines (148 loc) • 3.88 kB
text/typescript
// Components
import VInput from '../../components/VInput'
// Mixins
import Rippleable from '../rippleable'
import Comparable from '../comparable'
// Utilities
import mixins from '../../util/mixins'
export function prevent (e: Event) {
e.preventDefault()
}
/* @vue/component */
export default mixins(
VInput,
Rippleable,
Comparable
).extend({
name: 'selectable',
model: {
prop: 'inputValue',
event: 'change',
},
props: {
id: String,
inputValue: null as any,
falseValue: null as any,
trueValue: null as any,
multiple: {
type: Boolean,
default: null,
},
label: String,
},
data () {
return {
hasColor: this.inputValue,
lazyValue: this.inputValue,
}
},
computed: {
computedColor (): string | undefined {
if (!this.isActive) return undefined
if (this.color) return this.color
if (this.isDark && !this.appIsDark) return 'white'
return 'primary'
},
isMultiple (): boolean {
return this.multiple === true || (this.multiple === null && Array.isArray(this.internalValue))
},
isActive (): boolean {
const value = this.value
const input = this.internalValue
if (this.isMultiple) {
if (!Array.isArray(input)) return false
return input.some(item => this.valueComparator(item, value))
}
if (this.trueValue === undefined || this.falseValue === undefined) {
return value
? this.valueComparator(value, input)
: Boolean(input)
}
return this.valueComparator(input, this.trueValue)
},
isDirty (): boolean {
return this.isActive
},
rippleState (): string | undefined {
return !this.isDisabled && !this.validationState
? undefined
: this.validationState
},
},
watch: {
inputValue (val) {
this.lazyValue = val
this.hasColor = val
},
},
methods: {
genLabel () {
const label = VInput.options.methods.genLabel.call(this)
if (!label) return label
label!.data!.on = {
// Label shouldn't cause the input to focus
click: prevent,
}
return label
},
genInput (type: string, attrs: object) {
return this.$createElement('input', {
attrs: Object.assign({
'aria-checked': this.isActive.toString(),
disabled: this.isDisabled,
id: this.computedId,
role: type,
type,
}, attrs),
domProps: {
value: this.value,
checked: this.isActive,
},
on: {
blur: this.onBlur,
change: this.onChange,
focus: this.onFocus,
keydown: this.onKeydown,
click: prevent,
},
ref: 'input',
})
},
onBlur () {
this.isFocused = false
},
onClick (e: Event) {
this.onChange()
this.$emit('click', e)
},
onChange () {
if (!this.isInteractive) return
const value = this.value
let input = this.internalValue
if (this.isMultiple) {
if (!Array.isArray(input)) {
input = []
}
const length = input.length
input = input.filter((item: any) => !this.valueComparator(item, value))
if (input.length === length) {
input.push(value)
}
} else if (this.trueValue !== undefined && this.falseValue !== undefined) {
input = this.valueComparator(input, this.trueValue) ? this.falseValue : this.trueValue
} else if (value) {
input = this.valueComparator(input, value) ? null : value
} else {
input = !input
}
this.validate(true, input)
this.internalValue = input
this.hasColor = input
},
onFocus () {
this.isFocused = true
},
/** @abstract */
onKeydown (e: Event) {},
},
})