vuetify
Version:
Vue Material Component Framework
155 lines (133 loc) • 3.5 kB
text/typescript
// Components
import VIcon from '../VIcon'
// Mixins
import Colorable from '../../mixins/colorable'
import { inject as RegistrableInject } from '../../mixins/registrable'
// Directives
import ripple from '../../directives/ripple'
// Utilities
import mixins from '../../util/mixins'
// Types
import { VNode } from 'vue'
import { PropValidator } from 'vue/types/options'
type VuetifyStepperRuleValidator = () => string | boolean
const baseMixins = mixins(
Colorable,
RegistrableInject('stepper', 'v-stepper-step', 'v-stepper')
)
interface options extends InstanceType<typeof baseMixins> {
stepClick: (step: number | string) => void
}
/* @vue/component */
export default baseMixins.extend<options>().extend({
name: 'v-stepper-step',
directives: { ripple },
inject: ['stepClick'],
props: {
color: {
type: String,
default: 'primary',
},
complete: Boolean,
completeIcon: {
type: String,
default: '$complete',
},
editable: Boolean,
editIcon: {
type: String,
default: '$edit',
},
errorIcon: {
type: String,
default: '$error',
},
rules: {
type: Array,
default: () => [],
} as PropValidator<VuetifyStepperRuleValidator[]>,
step: [Number, String],
},
data () {
return {
isActive: false,
isInactive: true,
}
},
computed: {
classes (): object {
return {
'v-stepper__step--active': this.isActive,
'v-stepper__step--editable': this.editable,
'v-stepper__step--inactive': this.isInactive,
'v-stepper__step--error error--text': this.hasError,
'v-stepper__step--complete': this.complete,
}
},
hasError (): boolean {
return this.rules.some(validate => validate() !== true)
},
},
mounted () {
this.stepper && this.stepper.register(this)
},
beforeDestroy () {
this.stepper && this.stepper.unregister(this)
},
methods: {
click (e: MouseEvent) {
e.stopPropagation()
this.$emit('click', e)
if (this.editable) {
this.stepClick(this.step)
}
},
genIcon (icon: string) {
return this.$createElement(VIcon, icon)
},
genLabel () {
return this.$createElement('div', {
staticClass: 'v-stepper__label',
}, this.$slots.default)
},
genStep () {
const color = (!this.hasError && (this.complete || this.isActive)) ? this.color : false
return this.$createElement('span', this.setBackgroundColor(color, {
staticClass: 'v-stepper__step__step',
}), this.genStepContent())
},
genStepContent () {
const children = []
if (this.hasError) {
children.push(this.genIcon(this.errorIcon))
} else if (this.complete) {
if (this.editable) {
children.push(this.genIcon(this.editIcon))
} else {
children.push(this.genIcon(this.completeIcon))
}
} else {
children.push(String(this.step))
}
return children
},
toggle (step: number | string) {
this.isActive = step.toString() === this.step.toString()
this.isInactive = Number(step) < Number(this.step)
},
},
render (h): VNode {
return h('div', {
staticClass: 'v-stepper__step',
class: this.classes,
directives: [{
name: 'ripple',
value: this.editable,
}],
on: { click: this.click },
}, [
this.genStep(),
this.genLabel(),
])
},
})