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/dist/wave-ui.cjs.js +1 -1
- package/dist/wave-ui.css +1 -1
- package/dist/wave-ui.es.js +310 -147
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +1 -1
- package/src/wave-ui/components/index.js +2 -1
- package/src/wave-ui/components/w-app.vue +42 -2
- package/src/wave-ui/components/w-card.vue +19 -5
- package/src/wave-ui/components/w-confirm.vue +103 -0
- package/src/wave-ui/components/w-icon.vue +1 -3
- package/src/wave-ui/components/w-menu.vue +90 -49
- package/src/wave-ui/components/w-tooltip.vue +11 -8
- package/src/wave-ui/scss/_mixins.scss +100 -0
- package/src/wave-ui/scss/_variables.scss +0 -9
- package/src/wave-ui/scss/index.scss +1 -0
- package/src/wave-ui/utils/index.js +11 -0
package/package.json
CHANGED
|
@@ -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
|
|
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="
|
|
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,
|
|
5
|
+
:class="{ 'w-card__title--has-toolbar': titleHasToolbar, ...titleClasses }")
|
|
6
6
|
slot(name="title")
|
|
7
|
-
.w-card__title(v-else-if="title" :class="
|
|
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="
|
|
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
|
-
//
|
|
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
|
|
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="
|
|
24
|
-
:content-class="
|
|
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="
|
|
35
|
+
:value="menuVisible"
|
|
38
36
|
:persistent="persistent"
|
|
39
|
-
:class="
|
|
37
|
+
:class="overlayClasses"
|
|
40
38
|
v-bind="overlayProps"
|
|
41
39
|
:z-index="(zIndex || 200) - 1"
|
|
42
|
-
@input="
|
|
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
|
-
|
|
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
|
-
|
|
173
|
-
[`w-menu--${this.position}`]:
|
|
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.
|
|
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)
|
|
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',
|
|
278
|
+
this.$emit('update:modelValue', true)
|
|
251
279
|
this.$emit('input', true)
|
|
252
280
|
this.$emit('open')
|
|
253
|
-
},
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
|
|
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
|
-
|
|
431
|
-
this.
|
|
432
|
-
|
|
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
|
-
|
|
440
|
-
if (this.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: {
|