1
// Styles
2 1
import '../../styles/components/_selection-controls.sass'
3 1
import './VSwitch.sass'
4

5
// Mixins
6 1
import Selectable from '../../mixins/selectable'
7 1
import VInput from '../VInput'
8

9
// Directives
10 1
import Touch from '../../directives/touch'
11

12
// Components
13 1
import { VFabTransition } from '../transitions'
14 1
import VProgressCircular from '../VProgressCircular/VProgressCircular'
15

16
// Helpers
17 1
import { keyCodes } from '../../util/helpers'
18

19
// Types
20
import { VNode, VNodeData } from 'vue'
21

22
/* @vue/component */
23 1
export default Selectable.extend({
24
  name: 'v-switch',
25

26
  directives: { Touch },
27

28
  props: {
29
    inset: Boolean,
30
    loading: {
31
      type: [Boolean, String],
32
      default: false,
33
    },
34
    flat: {
35
      type: Boolean,
36
      default: false,
37
    },
38
  },
39

40
  computed: {
41 1
    classes (): object {
42 1
      return {
43
        ...VInput.options.computed.classes.call(this),
44
        'v-input--selection-controls v-input--switch': true,
45
        'v-input--switch--flat': this.flat,
46
        'v-input--switch--inset': this.inset,
47
      }
48
    },
49 1
    attrs (): object {
50 1
      return {
51
        'aria-checked': String(this.isActive),
52
        'aria-disabled': String(this.isDisabled),
53
        role: 'switch',
54
      }
55
    },
56
    // Do not return undefined if disabled,
57
    // according to spec, should still show
58
    // a color when disabled and active
59 1
    validationState (): string | undefined {
60 1
      if (this.hasError && this.shouldValidate) return 'error'
61 1
      if (this.hasSuccess) return 'success'
62 1
      if (this.hasColor !== null) return this.computedColor
63 0
      return undefined
64
    },
65 1
    switchData (): VNodeData {
66 1
      return this.setTextColor(this.loading ? undefined : this.validationState, {
67
        class: this.themeClasses,
68
      })
69
    },
70
  },
71

72
  methods: {
73 1
    genDefaultSlot (): (VNode | null)[] {
74 1
      return [
75
        this.genSwitch(),
76
        this.genLabel(),
77
      ]
78
    },
79 1
    genSwitch (): VNode {
80 1
      return this.$createElement('div', {
81
        staticClass: 'v-input--selection-controls__input',
82
      }, [
83
        this.genInput('checkbox', {
84
          ...this.attrs,
85
          ...this.attrs$,
86
        }),
87
        this.genRipple(this.setTextColor(this.validationState, {
88
          directives: [{
89
            name: 'touch',
90
            value: {
91
              left: this.onSwipeLeft,
92
              right: this.onSwipeRight,
93
            },
94
          }],
95
        })),
96
        this.$createElement('div', {
97
          staticClass: 'v-input--switch__track',
98
          ...this.switchData,
99
        }),
100
        this.$createElement('div', {
101
          staticClass: 'v-input--switch__thumb',
102
          ...this.switchData,
103
        }, [this.genProgress()]),
104
      ])
105
    },
106 1
    genProgress (): VNode {
107 1
      return this.$createElement(VFabTransition, {}, [
108
        this.loading === false
109 1
          ? null
110 1
          : this.$slots.progress || this.$createElement(VProgressCircular, {
111
            props: {
112 1
              color: (this.loading === true || this.loading === '')
113 1
                ? (this.color || 'primary')
114 0
                : this.loading,
115
              size: 16,
116
              width: 2,
117
              indeterminate: true,
118
            },
119
          }),
120
      ])
121
    },
122 1
    onSwipeLeft () {
123 1
      if (this.isActive) this.onChange()
124
    },
125 1
    onSwipeRight () {
126 1
      if (!this.isActive) this.onChange()
127
    },
128 1
    onKeydown (e: KeyboardEvent) {
129 1
      if (
130 1
        (e.keyCode === keyCodes.left && this.isActive) ||
131 1
        (e.keyCode === keyCodes.right && !this.isActive)
132 1
      ) this.onChange()
133
    },
134
  },
135
})

Read our documentation on viewing source code .

Loading