1
// Styles
2
import './VAlert.sass'
3

4
// Extensions
5
import VSheet from '../VSheet'
6

7
// Components
8
import VBtn from '../VBtn'
9
import VIcon from '../VIcon'
10

11
// Mixins
12
import Toggleable from '../../mixins/toggleable'
13
import Themeable from '../../mixins/themeable'
14
import Transitionable from '../../mixins/transitionable'
15

16
// Utilities
17
import mixins from '../../util/mixins'
18
import { breaking } from '../../util/console'
19

20
// Types
21
import { VNodeData } from 'vue'
22
import { VNode } from 'vue/types'
23

24
/* @vue/component */
25
export default mixins(
26
  VSheet,
27
  Toggleable,
28
  Transitionable
29
).extend({
30
  name: 'v-alert',
31

32
  props: {
33
    border: {
34
      type: String,
35 1
      validator (val: string) {
36 1
        return [
37
          'top',
38
          'right',
39
          'bottom',
40
          'left',
41
        ].includes(val)
42
      },
43
    },
44
    closeLabel: {
45
      type: String,
46
      default: '$vuetify.close',
47
    },
48
    coloredBorder: Boolean,
49
    dense: Boolean,
50
    dismissible: Boolean,
51
    closeIcon: {
52
      type: String,
53
      default: '$cancel',
54
    },
55
    icon: {
56
      default: '',
57
      type: [Boolean, String],
58 1
      validator (val: boolean | string) {
59 1
        return typeof val === 'string' || val === false
60
      },
61
    },
62
    outlined: Boolean,
63
    prominent: Boolean,
64
    text: Boolean,
65
    type: {
66
      type: String,
67 1
      validator (val: string) {
68 1
        return [
69
          'info',
70
          'error',
71
          'success',
72
          'warning',
73
        ].includes(val)
74
      },
75
    },
76
    value: {
77
      type: Boolean,
78
      default: true,
79
    },
80
  },
81

82
  computed: {
83 1
    __cachedBorder (): VNode | null {
84 1
      if (!this.border) return null
85

86 1
      let data: VNodeData = {
87
        staticClass: 'v-alert__border',
88
        class: {
89
          [`v-alert__border--${this.border}`]: true,
90
        },
91
      }
92

93 1
      if (this.coloredBorder) {
94 1
        data = this.setBackgroundColor(this.computedColor, data)
95 1
        data.class['v-alert__border--has-color'] = true
96
      }
97

98 1
      return this.$createElement('div', data)
99
    },
100 1
    __cachedDismissible (): VNode | null {
101 1
      if (!this.dismissible) return null
102

103 1
      const color = this.iconColor
104

105 1
      return this.$createElement(VBtn, {
106
        staticClass: 'v-alert__dismissible',
107
        props: {
108
          color,
109
          icon: true,
110
          small: true,
111
        },
112
        attrs: {
113
          'aria-label': this.$vuetify.lang.t(this.closeLabel),
114
        },
115
        on: {
116 1
          click: () => (this.isActive = false),
117
        },
118
      }, [
119
        this.$createElement(VIcon, {
120
          props: { color },
121
        }, this.closeIcon),
122
      ])
123
    },
124 1
    __cachedIcon (): VNode | null {
125 1
      if (!this.computedIcon) return null
126

127 1
      return this.$createElement(VIcon, {
128
        staticClass: 'v-alert__icon',
129
        props: { color: this.iconColor },
130
      }, this.computedIcon)
131
    },
132 1
    classes (): object {
133 1
      const classes: Record<string, boolean> = {
134
        ...VSheet.options.computed.classes.call(this),
135
        'v-alert--border': Boolean(this.border),
136
        'v-alert--dense': this.dense,
137
        'v-alert--outlined': this.outlined,
138
        'v-alert--prominent': this.prominent,
139
        'v-alert--text': this.text,
140
      }
141

142 1
      if (this.border) {
143 1
        classes[`v-alert--border-${this.border}`] = true
144
      }
145

146 1
      return classes
147
    },
148 1
    computedColor (): string {
149 1
      return this.color || this.type
150
    },
151 1
    computedIcon (): string | boolean {
152 1
      if (this.icon === false) return false
153 1
      if (typeof this.icon === 'string' && this.icon) return this.icon
154 1
      if (!['error', 'info', 'success', 'warning'].includes(this.type)) return false
155

156 1
      return `$${this.type}`
157
    },
158 1
    hasColoredIcon (): boolean {
159 1
      return (
160 1
        this.hasText ||
161 1
        (Boolean(this.border) && this.coloredBorder)
162
      )
163
    },
164 1
    hasText (): boolean {
165 1
      return this.text || this.outlined
166
    },
167 1
    iconColor (): string | undefined {
168 1
      return this.hasColoredIcon ? this.computedColor : undefined
169
    },
170 1
    isDark (): boolean {
171 1
      if (
172 1
        this.type &&
173 1
        !this.coloredBorder &&
174 1
        !this.outlined
175 1
      ) return true
176

177 1
      return Themeable.options.computed.isDark.call(this)
178
    },
179
  },
180

181 1
  created () {
182
    /* istanbul ignore next */
183
    if (this.$attrs.hasOwnProperty('outline')) {
184
      breaking('outline', 'outlined', this)
185
    }
186
  },
187

188
  methods: {
189 1
    genWrapper (): VNode {
190 1
      const children = [
191 1
        this.$slots.prepend || this.__cachedIcon,
192
        this.genContent(),
193
        this.__cachedBorder,
194
        this.$slots.append,
195 1
        this.$scopedSlots.close
196 0
          ? this.$scopedSlots.close({ toggle: this.toggle })
197 1
          : this.__cachedDismissible,
198
      ]
199

200 1
      const data: VNodeData = {
201
        staticClass: 'v-alert__wrapper',
202
      }
203

204 1
      return this.$createElement('div', data, children)
205
    },
206 1
    genContent (): VNode {
207 1
      return this.$createElement('div', {
208
        staticClass: 'v-alert__content',
209
      }, this.$slots.default)
210
    },
211 1
    genAlert (): VNode {
212 1
      let data: VNodeData = {
213
        staticClass: 'v-alert',
214
        attrs: {
215
          role: 'alert',
216
        },
217
        on: this.listeners$,
218
        class: this.classes,
219
        style: this.styles,
220
        directives: [{
221
          name: 'show',
222
          value: this.isActive,
223
        }],
224
      }
225

226 1
      if (!this.coloredBorder) {
227 1
        const setColor = this.hasText ? this.setTextColor : this.setBackgroundColor
228 1
        data = setColor(this.computedColor, data)
229
      }
230

231 1
      return this.$createElement('div', data, [this.genWrapper()])
232
    },
233
    /** @public */
234 1
    toggle () {
235 1
      this.isActive = !this.isActive
236
    },
237
  },
238

239 1
  render (h): VNode {
240 1
    const render = this.genAlert()
241

242 1
    if (!this.transition) return render
243

244 0
    return h('transition', {
245
      props: {
246
        name: this.transition,
247
        origin: this.origin,
248
        mode: this.mode,
249
      },
250
    }, [render])
251
  },
252
})

Read our documentation on viewing source code .

Loading