wave-ui 1.42.1 → 1.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "1.42.1",
3
+ "version": "1.44.0",
4
4
  "description": "An emerging UI framework for Vue.js & Vue 3 with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
6
  "main": "./dist/wave-ui.umd.js",
@@ -5,9 +5,10 @@ export { default as WApp } from './w-app.vue'
5
5
  export { default as WBadge } from './w-badge.vue'
6
6
  export { default as WBreadcrumbs } from './w-breadcrumbs.vue'
7
7
  export { default as WButton } from './w-button.vue'
8
+ export { default as WCard } from './w-card.vue'
8
9
  export { default as WCheckbox } from './w-checkbox.vue'
9
10
  export { default as WCheckboxes } from './w-checkboxes.vue'
10
- export { default as WCard } from './w-card.vue'
11
+ export { default as WConfirm } from './w-confirm.vue'
11
12
  export { default as WDatePicker } from './w-date-picker.vue'
12
13
  export { default as WDialog } from './w-dialog.vue'
13
14
  export { default as WDivider } from './w-divider.vue'
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- .w-app(:class="{ 'theme--dark': dark, 'd-block': block }")
2
+ .w-app(:class="classes")
3
3
  slot
4
4
  notification-manager
5
5
  </template>
@@ -16,7 +16,17 @@ export default {
16
16
  name: 'w-app',
17
17
  props: {
18
18
  dark: { type: Boolean },
19
- block: { type: Boolean }
19
+ block: { type: Boolean },
20
+ row: { type: Boolean },
21
+ alignCenter: { type: Boolean },
22
+ alignEnd: { type: Boolean },
23
+ justifyCenter: { type: Boolean },
24
+ justifyEnd: { type: Boolean },
25
+ justifySpaceBetween: { type: Boolean },
26
+ justifySpaceAround: { type: Boolean },
27
+ justifySpaceEvenly: { type: Boolean },
28
+ textCenter: { type: Boolean },
29
+ textRight: { type: Boolean }
20
30
  },
21
31
 
22
32
  components: { NotificationManager },
@@ -26,6 +36,25 @@ export default {
26
36
  notifManager: null
27
37
  }),
28
38
 
39
+ computed: {
40
+ classes () {
41
+ return {
42
+ 'd-block': this.block,
43
+ 'row': this.row,
44
+ 'align-center': this.alignCenter,
45
+ 'align-end': this.alignEnd,
46
+ 'justify-center': this.justifyCenter,
47
+ 'justify-end': this.justifyEnd,
48
+ 'justify-space-between': this.justifySpaceBetween,
49
+ 'justify-space-around': this.justifySpaceAround,
50
+ 'justify-space-evenly': this.justifySpaceEvenly,
51
+ 'text-center': this.textCenter,
52
+ 'text-right': this.textRight,
53
+ 'theme--dark': this.dark
54
+ }
55
+ }
56
+ },
57
+
29
58
  methods: {
30
59
  getBreakpoint () {
31
60
  const width = window.innerWidth
@@ -85,6 +114,17 @@ export default {
85
114
  flex-direction: column;
86
115
  min-height: 100vh;
87
116
 
117
+ &.row {flex-direction: row;}
88
118
  &.d-block {display: block;}
119
+ &.align-center {align-items: center;}
120
+ &.align-end {align-items: flex-end;}
121
+ &.justify-center {justify-content: center;}
122
+ &.justify-end {justify-content: flex-end;}
123
+ &.justify-space-between {justify-content: space-between;}
124
+ &.justify-space-around {justify-content: space-around;}
125
+ &.justify-space-evenly {justify-content: space-evenly;}
126
+ &.text-center {text-align: center;}
127
+ &.text-right {text-align: right;}
128
+
89
129
  }
90
130
  </style>
@@ -2,12 +2,12 @@
2
2
  .w-card(:class="classes" :style="styles")
3
3
  .w-card__title(
4
4
  v-if="$slots.title"
5
- :class="{ 'w-card__title--has-toolbar': titleHasToolbar, [titleClass]: titleClass || false }")
5
+ :class="{ 'w-card__title--has-toolbar': titleHasToolbar, ...titleClasses }")
6
6
  slot(name="title")
7
- .w-card__title(v-else-if="title" :class="titleClass || false" v-html="title")
7
+ .w-card__title(v-else-if="title" :class="titleClasses" v-html="title")
8
8
  w-image.w-card__image(v-if="image" :src="image" v-bind="imgProps")
9
9
  slot(name="image-content")
10
- .w-card__content(:class="contentClass || false")
10
+ .w-card__content(:class="contentClasses")
11
11
  slot
12
12
  .w-card__actions(
13
13
  v-if="$slots.actions"
@@ -16,6 +16,8 @@
16
16
  </template>
17
17
 
18
18
  <script>
19
+ import { objectifyClasses } from '../utils/index'
20
+
19
21
  export default {
20
22
  name: 'w-card',
21
23
 
@@ -28,21 +30,31 @@ export default {
28
30
  title: { type: String },
29
31
  image: { type: String },
30
32
  imageProps: { type: Object },
31
- titleClass: { type: String },
32
- contentClass: { type: String }
33
+ titleClass: { type: [String, Object, Array] },
34
+ contentClass: { type: [String, Object, Array] }
33
35
  },
34
36
 
35
37
  emits: [],
36
38
 
37
39
  computed: {
40
+ titleClasses () {
41
+ return objectifyClasses(this.titleClass)
42
+ },
43
+
44
+ contentClasses () {
45
+ return objectifyClasses(this.contentClass)
46
+ },
47
+
38
48
  titleHasToolbar () {
39
49
  const { title } = this.$slots
40
50
  return title && title.map(vnode => vnode.tag).join('').includes('w-toolbar')
41
51
  },
52
+
42
53
  actionsHasToolbar () {
43
54
  const { actions } = this.$slots
44
55
  return actions && actions.map(vnode => vnode.tag).join('').includes('w-toolbar')
45
56
  },
57
+
46
58
  imgProps () {
47
59
  return {
48
60
  tag: 'div',
@@ -50,6 +62,7 @@ export default {
50
62
  ...this.imageProps
51
63
  }
52
64
  },
65
+
53
66
  classes () {
54
67
  return {
55
68
  [this.color]: this.color,
@@ -59,6 +72,7 @@ export default {
59
72
  'w-card--shadow': this.shadow
60
73
  }
61
74
  },
75
+
62
76
  styles () {
63
77
  return false
64
78
  }
@@ -0,0 +1,103 @@
1
+ <template lang="pug">
2
+ .w-confirm
3
+ w-menu(v-model="showPopup" v-bind="wMenuProps")
4
+ template(#activator="{ on }")
5
+ w-button.w-confirm__button(v-on="on" v-bind="buttonProps")
6
+ slot
7
+ w-flex(:column="!inline" align-center)
8
+ div
9
+ slot(name="question") Are you sure?
10
+ .w-flex.justify-end(:class="inline ? 'ml2' : 'mt2'")
11
+ w-button.mr2(
12
+ v-if="!noCancel"
13
+ v-bind="cancelButton"
14
+ :bg-color="(cancelButton || {}).bgColor || 'error'"
15
+ @click="onCancel")
16
+ slot(name="cancel") Cancel
17
+ w-button(
18
+ v-bind="confirmButton"
19
+ :bg-color="(confirmButton || {}).bgColor || 'success'"
20
+ @click="onConfirm")
21
+ slot(name="confirm") Confirm
22
+ </template>
23
+
24
+ <script>
25
+ export default {
26
+ name: 'w-confirm',
27
+ props: {
28
+ // Main button props.
29
+ bgColor: { type: String },
30
+ color: { type: String },
31
+ icon: { type: String },
32
+ mainButton: { type: Object }, // Allow passing down an object of props to the w-button component.
33
+
34
+ // Cancel & confirm buttons props.
35
+ noCancel: { type: Boolean }, // Removes the cancel button.
36
+ cancelButton: { type: [Boolean, Object] }, // Allow passing down an object of props to the w-button component.
37
+ confirmButton: { type: Object }, // Allow passing down an object of props to the w-button component.
38
+
39
+ // global menu props.
40
+ inline: { type: Boolean }, // The layout inside the menu.
41
+
42
+ // W-menu props.
43
+ menu: { type: Object }, // Allow passing down an object of props to the w-menu component.
44
+ // All the menu props shorthands, as long as they don't conflict with the button props.
45
+ noArrow: { type: Boolean }, // Adds a directional triangle to the edge of the menu, like a tooltip.
46
+ top: { type: Boolean },
47
+ bottom: { type: Boolean },
48
+ left: { type: Boolean },
49
+ right: { type: Boolean },
50
+ alignTop: { type: Boolean },
51
+ alignBottom: { type: Boolean },
52
+ alignLeft: { type: Boolean },
53
+ alignRight: { type: Boolean },
54
+ persistent: { type: Boolean },
55
+ transition: { type: String }
56
+ },
57
+
58
+ emits: ['cancel', 'confirm'],
59
+
60
+ data: () => ({
61
+ showPopup: false,
62
+ props: []
63
+ }),
64
+
65
+ computed: {
66
+ wMenuProps () {
67
+ return {
68
+ top: this.top,
69
+ bottom: this.bottom,
70
+ left: this.left,
71
+ right: this.right,
72
+ arrow: !this.noArrow,
73
+ alignTop: this.alignTop,
74
+ alignBottom: this.alignBottom,
75
+ alignLeft: this.alignLeft,
76
+ alignRight: this.alignRight,
77
+ persistent: this.persistent,
78
+ transition: this.transition,
79
+ ...this.menu
80
+ }
81
+ },
82
+ buttonProps () {
83
+ return {
84
+ bgColor: this.bgColor,
85
+ color: this.color,
86
+ icon: this.icon,
87
+ ...this.mainButton
88
+ }
89
+ }
90
+ },
91
+
92
+ methods: {
93
+ onCancel () {
94
+ this.$emit('cancel')
95
+ this.showPopup = false
96
+ },
97
+ onConfirm () {
98
+ this.$emit('confirm')
99
+ this.showPopup = false
100
+ }
101
+ }
102
+ }
103
+ </script>
@@ -119,9 +119,7 @@ export default {
119
119
  &.size--lg {font-size: round(1.7 * $base-font-size);}
120
120
  &.size--xl {font-size: 2 * $base-font-size;}
121
121
 
122
- // Icon's vertical alignment in button.
123
- .w-button &, .w-button &:before {line-height: inherit;}
124
- // Always an even number to vertical align well in button.
122
+ // Always an even number to align well vertically in a button.
125
123
  .w-button.size--xs & {font-size: round(0.95 * divide($base-font-size, 2)) * 2;}
126
124
  .w-alert.size--xs & {font-size: $base-font-size;}
127
125
  .w-button.size--sm &, .w-alert.size--sm & {font-size: round(1.15 * $base-font-size);}
@@ -1,11 +1,10 @@
1
1
  <template lang="pug">
2
- .w-menu-wrap(ref="wrapper")
2
+ .w-menu-wrap
3
3
  slot(name="activator" :on="activatorEventHandlers")
4
- transition(:name="transitionName")
4
+ transition(:name="transitionName" appear)
5
5
  .w-menu(
6
- v-if="custom"
6
+ v-if="custom && menuVisible"
7
7
  ref="menu"
8
- v-show="showMenu"
9
8
  @click="hideOnMenuClick && closeMenu(true)"
10
9
  @mouseenter="showOnHover && (hoveringMenu = true)"
11
10
  @mouseleave="showOnHover && ((hoveringMenu = false), closeMenu())"
@@ -13,15 +12,14 @@
13
12
  :style="styles")
14
13
  slot
15
14
  w-card.w-menu(
16
- v-else
15
+ v-else-if="menuVisible"
17
16
  ref="menu"
18
- v-show="showMenu"
19
17
  @click.native="hideOnMenuClick && closeMenu(true)"
20
18
  @mouseenter.native="showOnHover && (hoveringMenu = true)"
21
19
  @mouseleave.native="showOnHover && ((hoveringMenu = false), closeMenu())"
22
20
  :tile="tile"
23
- :title-class="titleClass"
24
- :content-class="contentClass"
21
+ :title-class="titleClasses"
22
+ :content-class="contentClasses"
25
23
  :shadow="shadow"
26
24
  :no-border="noBorder"
27
25
  :class="classes"
@@ -34,12 +32,12 @@
34
32
  w-overlay(
35
33
  v-if="overlay"
36
34
  ref="overlay"
37
- :value="showMenu"
35
+ :value="menuVisible"
38
36
  :persistent="persistent"
39
- :class="overlayClass || null"
37
+ :class="overlayClasses"
40
38
  v-bind="overlayProps"
41
39
  :z-index="(zIndex || 200) - 1"
42
- @input="showMenu = false")
40
+ @input="menuVisible = false")
43
41
  </template>
44
42
 
45
43
  <script>
@@ -52,6 +50,7 @@
52
50
  * and move the menu elsewhere in the DOM.
53
51
  */
54
52
 
53
+ import { objectifyClasses } from '../utils/index'
55
54
  import { consoleWarn } from '../utils/console'
56
55
 
57
56
  // const marginFromWindowSide = 4 // Amount of px from a window side, instead of overflowing.
@@ -71,10 +70,11 @@ export default {
71
70
  round: { type: Boolean },
72
71
  noBorder: { type: Boolean },
73
72
  transition: { type: String },
74
- menuClass: { type: String },
75
- titleClass: { type: String },
76
- contentClass: { type: String },
73
+ menuClass: { type: [String, Object, Array] },
74
+ titleClass: { type: [String, Object, Array] },
75
+ contentClass: { type: [String, Object, Array] },
77
76
  // Position.
77
+ arrow: { type: Boolean }, // The small triangle pointing toward the activator.
78
78
  detachTo: { type: [String, Boolean, Object] },
79
79
  fixed: { type: Boolean },
80
80
  top: { type: Boolean },
@@ -88,7 +88,7 @@ export default {
88
88
  zIndex: { type: [Number, String, Boolean] },
89
89
  minWidth: { type: [Number, String] }, // can be like: `40`, `5em`, `activator`.
90
90
  overlay: { type: Boolean },
91
- overlayClass: { type: String },
91
+ overlayClass: { type: [String, Object, Array] },
92
92
  overlayProps: { type: Object }, // Allow passing down an object of props to the w-overlay component.
93
93
  persistent: { type: Boolean },
94
94
  noPosition: { type: Boolean }
@@ -97,7 +97,7 @@ export default {
97
97
  emits: ['input', 'update:modelValue', 'open', 'close'],
98
98
 
99
99
  data: () => ({
100
- showMenu: false,
100
+ menuVisible: false,
101
101
  hoveringActivator: false,
102
102
  hoveringMenu: false,
103
103
  // The menu computed top & left coordinates.
@@ -165,27 +165,46 @@ export default {
165
165
  )
166
166
  },
167
167
 
168
+ menuClasses () {
169
+ return objectifyClasses(this.menuClass)
170
+ },
171
+
172
+ titleClasses () {
173
+ return objectifyClasses(this.titleClass)
174
+ },
175
+
176
+ contentClasses () {
177
+ return objectifyClasses(this.contentClass)
178
+ },
179
+
180
+ overlayClasses () {
181
+ return objectifyClasses(this.overlayClass)
182
+ },
183
+
168
184
  classes () {
169
185
  return {
170
186
  [this.color]: this.color,
171
187
  [`${this.bgColor}--bg`]: this.bgColor,
172
- [this.menuClass]: this.menuClass,
173
- [`w-menu--${this.position}`]: true,
174
- [`w-menu--align-${this.alignment}`]: this.alignment,
188
+ ...this.menuClasses,
189
+ [`w-menu--${this.position}`]: !this.noPosition,
190
+ [`w-menu--align-${this.alignment}`]: !this.noPosition && this.alignment,
175
191
  'w-menu--tile': this.tile,
176
192
  'w-menu--card': !this.custom,
177
193
  'w-menu--round': this.round,
194
+ 'w-menu--arrow': this.arrow,
178
195
  'w-menu--shadow': this.shadow,
179
196
  'w-menu--fixed': this.fixed
180
197
  }
181
198
  },
182
199
 
200
+ // The floatting menu styles.
183
201
  styles () {
184
202
  return {
185
203
  zIndex: this.zIndex || this.zIndex === 0 || (this.overlay && !this.zIndex && 200) || null,
186
204
  top: (this.menuCoordinates.top && `${~~this.menuCoordinates.top}px`) || null,
187
205
  left: (this.menuCoordinates.left && `${~~this.menuCoordinates.left}px`) || null,
188
- minWidth: (this.minWidth && this.menuMinWidth) || null
206
+ minWidth: (this.minWidth && this.menuMinWidth) || null,
207
+ '--w-menu-bg-color': this.arrow && this.$waveui.colors[this.bgColor || 'white']
189
208
  }
190
209
  },
191
210
 
@@ -218,7 +237,7 @@ export default {
218
237
 
219
238
  methods: {
220
239
  toggleMenu (e) {
221
- let shouldShowMenu = this.showMenu
240
+ let shouldShowMenu = this.menuVisible
222
241
  if ('ontouchstart' in window && this.showOnHover && e.type === 'click') {
223
242
  shouldShowMenu = !shouldShowMenu
224
243
  }
@@ -234,11 +253,20 @@ export default {
234
253
 
235
254
  this.timeoutId = clearTimeout(this.timeoutId)
236
255
 
237
- if (shouldShowMenu) this.openMenu(e)
256
+ if (shouldShowMenu) {
257
+ this.$emit('update:modelValue', (this.menuVisible = true))
258
+ this.$emit('input', true)
259
+ this.$emit('open')
260
+
261
+ this.openMenu(e)
262
+ }
238
263
  else this.closeMenu()
239
264
  },
240
265
 
241
- openMenu (e) {
266
+ async openMenu (e) {
267
+ this.menuVisible = true
268
+ await this.insertMenu()
269
+
242
270
  if (this.minWidth === 'activator') this.activatorWidth = this.activatorEl.offsetWidth
243
271
 
244
272
  if (!this.noPosition) this.computeMenuPosition(e)
@@ -247,10 +275,10 @@ export default {
247
275
  // if we don't postpone the Menu apparition it will start transition from a visible menu and
248
276
  // thus will not transition.
249
277
  this.timeoutId = setTimeout(() => {
250
- this.$emit('update:modelValue', (this.showMenu = true))
278
+ this.$emit('update:modelValue', true)
251
279
  this.$emit('input', true)
252
280
  this.$emit('open')
253
- }, 10)
281
+ }, 0)
254
282
 
255
283
  if (!this.persistent) document.addEventListener('mousedown', this.onOutsideMousedown)
256
284
  if (!this.noPosition) window.addEventListener('resize', this.onResize)
@@ -269,14 +297,14 @@ export default {
269
297
  async closeMenu (force = false) {
270
298
  // Might be already closed.
271
299
  // E.g. showOnHover & hideOnMenuClick: on click, force hide then mouseleave is also firing.
272
- if (!this.showMenu) return
300
+ if (!this.menuVisible) return
273
301
 
274
302
  if (this.showOnHover && !force) {
275
303
  await new Promise(resolve => setTimeout(resolve, 10))
276
304
  if (this.showOnHover && (this.hoveringMenu || this.hoveringActivator)) return
277
305
  }
278
306
 
279
- this.$emit('update:modelValue', (this.showMenu = false))
307
+ this.$emit('update:modelValue', (this.menuVisible = false))
280
308
  this.$emit('input', false)
281
309
  this.$emit('close')
282
310
  // Remove the mousedown listener if the menu got closed without a mousedown outside of the menu.
@@ -286,7 +314,7 @@ export default {
286
314
 
287
315
  onOutsideMousedown (e) {
288
316
  if (!this.menuEl.contains(e.target) && !this.activatorEl.contains(e.target)) {
289
- this.$emit('update:modelValue', (this.showMenu = false))
317
+ this.$emit('update:modelValue', (this.menuVisible = false))
290
318
  this.$emit('input', false)
291
319
  this.$emit('close')
292
320
  document.removeEventListener('mousedown', this.onOutsideMousedown)
@@ -401,49 +429,53 @@ export default {
401
429
  this.menuEl.style.visibility = null
402
430
 
403
431
  // The menu coordinates are also recalculated while resizing window with open menu: keep the menu visible.
404
- if (!this.showMenu) this.menuEl.style.display = 'none'
432
+ if (!this.menuVisible) this.menuEl.style.display = 'none'
405
433
 
406
434
  this.menuCoordinates = { top, left }
407
435
  },
408
436
 
409
437
  insertMenu () {
410
- const wrapper = this.$refs.wrapper
411
- this.menuEl = this.$refs.menu.$el || this.$refs.menu
412
- // Unwrap the activator element.
413
- wrapper.parentNode.insertBefore(this.activatorEl, wrapper)
414
-
415
- // Unwrap the overlay.
416
- if (this.overlay) wrapper.parentNode.insertBefore(this.overlayEl, wrapper)
417
-
418
- // Move the menu elsewhere in the DOM.
419
- // wrapper.parentNode.insertBefore(this.menuEl, wrapper)
420
- this.detachToTarget.appendChild(this.menuEl)
438
+ return new Promise(resolve => {
439
+ this.$nextTick(() => {
440
+ this.menuEl = this.$refs.menu?.$el || this.$refs.menu
441
+
442
+ // Move the menu elsewhere in the DOM.
443
+ // wrapper.parentNode.insertBefore(this.menuEl, wrapper)
444
+ this.detachToTarget.appendChild(this.menuEl)
445
+ resolve()
446
+ })
447
+ })
421
448
  },
422
449
 
423
450
  removeMenu () {
424
- // el.remove() doesn't work on IE11.
425
- if (this.menuEl && this.menuEl.parentNode) this.menuEl.parentNode.removeChild(this.menuEl)
451
+ if (this.menuEl && this.menuEl.parentNode) this.menuEl.remove()
426
452
  }
427
453
  },
428
454
 
429
455
  mounted () {
430
- this.activatorEl = this.$refs.wrapper.firstElementChild
431
- this.overlayEl = this.overlay ? this.$refs.overlay.$el : null
432
- this.insertMenu()
456
+ const wrapper = this.$el
457
+ this.activatorEl = wrapper.firstElementChild
458
+ // Unwrap the activator element.
459
+ wrapper.parentNode.insertBefore(this.activatorEl, wrapper)
460
+
461
+ // Unwrap the overlay.
462
+ if (this.overlay) {
463
+ this.overlayEl = this.$refs.overlay?.$el
464
+ wrapper.parentNode.insertBefore(this.overlayEl, wrapper)
465
+ }
433
466
 
434
467
  if (this.value) this.toggleMenu({ type: 'click', target: this.activatorEl })
435
468
  },
436
469
 
437
470
  beforeDestroy () {
438
471
  this.removeMenu()
439
- // el.remove() doesn't work on IE11.
440
- if (this.overlay && this.overlayEl.parentNode) this.overlayEl.parentNode.removeChild(this.overlayEl)
441
- if (this.activatorEl && this.activatorEl.parentNode) this.activatorEl.parentNode.removeChild(this.activatorEl)
472
+ if (this.overlay && this.overlayEl.parentNode) this.overlayEl.remove()
473
+ if (this.activatorEl && this.activatorEl.parentNode) this.activatorEl.remove()
442
474
  },
443
475
 
444
476
  watch: {
445
477
  value (bool) {
446
- if (!!bool !== this.showMenu) this.toggleMenu({ type: 'click', target: this.activatorEl })
478
+ if (!!bool !== this.menuVisible) this.toggleMenu({ type: 'click', target: this.activatorEl })
447
479
  },
448
480
  detachTo () {
449
481
  this.removeMenu()
@@ -473,5 +505,14 @@ export default {
473
505
  &--bottom {margin-top: 3 * $base-increment;}
474
506
  &--left {margin-left: -3 * $base-increment;}
475
507
  &--right {margin-left: 3 * $base-increment;}
508
+
509
+ &--arrow {
510
+ &.w-menu--top {margin-top: -4 * $base-increment;}
511
+ &.w-menu--bottom {margin-top: 4 * $base-increment;}
512
+ &.w-menu--left {margin-left: -4 * $base-increment;}
513
+ &.w-menu--right {margin-left: 4 * $base-increment;}
514
+
515
+ @include triangle(var(--w-menu-bg-color), '.w-menu', 9px);
516
+ }
476
517
  }
477
518
  </style>
@@ -1,7 +1,7 @@
1
1
  <template lang="pug">
2
2
  .w-tooltip-wrap(ref="wrapper" :class="{ 'w-tooltip-wrap--attached': !detachTo }")
3
3
  slot(name="activator" :on="eventHandlers")
4
- transition(:name="transitionName")
4
+ transition(:name="transitionName" appear)
5
5
  .w-tooltip(ref="tooltip" v-show="showTooltip" :class="classes" :style="styles")
6
6
  //- When there is a bg color, another div wrapper is needed for the triangle
7
7
  //- to inherit the current color.
@@ -20,6 +20,7 @@
20
20
  * and move the tooltip elsewhere in the DOM.
21
21
  */
22
22
 
23
+ import { objectifyClasses } from '../utils/index'
23
24
  import { consoleWarn } from '../utils/console'
24
25
 
25
26
  const marginFromWindowSide = 4 // Amount of px from a window side, instead of overflowing.
@@ -36,8 +37,8 @@ export default {
36
37
  shadow: { type: Boolean },
37
38
  tile: { type: Boolean },
38
39
  round: { type: Boolean },
39
- transition: { type: String, default: '' },
40
- tooltipClass: { type: String },
40
+ transition: { type: String },
41
+ tooltipClass: { type: [String, Object, Array] },
41
42
  // Position.
42
43
  detachTo: {},
43
44
  fixed: { type: Boolean },
@@ -65,6 +66,10 @@ export default {
65
66
  }),
66
67
 
67
68
  computed: {
69
+ tooltipClasses () {
70
+ return objectifyClasses(this.tooltipClass)
71
+ },
72
+
68
73
  transitionName () {
69
74
  const direction = this.position.replace(/top|bottom/, m => ({ top: 'up', bottom: 'down' }[m]))
70
75
  return this.transition || `w-tooltip-slide-fade-${direction}`
@@ -137,7 +142,7 @@ export default {
137
142
  return {
138
143
  [this.color]: !this.bgColor,
139
144
  [`${this.bgColor} ${this.bgColor}--bg`]: this.bgColor,
140
- [this.tooltipClass]: this.tooltipClass,
145
+ ...this.tooltipClasses,
141
146
  [`w-tooltip--${this.position}`]: true,
142
147
  'w-tooltip--tile': this.tile,
143
148
  'w-tooltip--round': this.round,
@@ -274,8 +279,7 @@ export default {
274
279
  },
275
280
 
276
281
  removeTooltip () {
277
- // el.remove() doesn't work on IE11.
278
- if (this.tooltipEl && this.tooltipEl.parentNode) this.tooltipEl.parentNode.removeChild(this.tooltipEl)
282
+ if (this.tooltipEl && this.tooltipEl.parentNode) this.tooltipEl.remove()
279
283
  }
280
284
 
281
285
  },
@@ -290,8 +294,7 @@ export default {
290
294
  beforeDestroy () {
291
295
  this.removeTooltip()
292
296
 
293
- // el.remove() doesn't work on IE11.
294
- if (this.activatorEl && this.activatorEl.parentNode) this.activatorEl.parentNode.removeChild(this.activatorEl)
297
+ if (this.activatorEl && this.activatorEl.parentNode) this.activatorEl.remove()
295
298
  },
296
299
 
297
300
  watch: {