wave-ui 2.28.1 → 2.31.1
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 +567 -520
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +14 -11
- package/src/wave-ui/components/w-accordion.vue +6 -4
- package/src/wave-ui/components/w-alert.vue +0 -1
- package/src/wave-ui/components/w-app.vue +1 -1
- package/src/wave-ui/components/w-confirm.vue +35 -10
- package/src/wave-ui/components/w-flex.vue +2 -0
- package/src/wave-ui/components/w-input.vue +130 -33
- package/src/wave-ui/components/w-menu.vue +76 -270
- package/src/wave-ui/components/w-notification-manager.vue +9 -2
- package/src/wave-ui/components/w-progress.vue +4 -1
- package/src/wave-ui/components/w-rating.vue +1 -1
- package/src/wave-ui/components/w-select.vue +2 -2
- package/src/wave-ui/components/w-spinner.vue +2 -2
- package/src/wave-ui/components/w-table.vue +2 -2
- package/src/wave-ui/components/w-tag.vue +17 -6
- package/src/wave-ui/components/w-textarea.vue +1 -1
- package/src/wave-ui/components/w-tooltip.vue +121 -308
- package/src/wave-ui/core.js +0 -8
- package/src/wave-ui/mixins/detachable.js +321 -0
- package/src/wave-ui/scss/_mixins.scss +23 -12
- package/src/wave-ui/scss/_variables.scss +1 -1
- package/src/wave-ui/utils/index.js +1 -1
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
slot(name="activator" :on="activatorEventHandlers")
|
|
4
4
|
transition(:name="transitionName" appear)
|
|
5
5
|
.w-menu(
|
|
6
|
-
v-if="custom &&
|
|
7
|
-
ref="
|
|
8
|
-
@click="hideOnMenuClick &&
|
|
6
|
+
v-if="custom && detachableVisible"
|
|
7
|
+
ref="detachable"
|
|
8
|
+
@click="hideOnMenuClick && close(true)"
|
|
9
9
|
@mouseenter="showOnHover && (hoveringMenu = true)"
|
|
10
|
-
@mouseleave="showOnHover && ((hoveringMenu = false),
|
|
10
|
+
@mouseleave="showOnHover && ((hoveringMenu = false), close())"
|
|
11
11
|
:class="classes"
|
|
12
12
|
:style="styles")
|
|
13
13
|
slot
|
|
14
14
|
w-card.w-menu(
|
|
15
|
-
v-else-if="
|
|
16
|
-
ref="
|
|
17
|
-
@click.native="hideOnMenuClick &&
|
|
15
|
+
v-else-if="detachableVisible"
|
|
16
|
+
ref="detachable"
|
|
17
|
+
@click.native="hideOnMenuClick && close(true)"
|
|
18
18
|
@mouseenter.native="showOnHover && (hoveringMenu = true)"
|
|
19
|
-
@mouseleave.native="showOnHover && ((hoveringMenu = false),
|
|
19
|
+
@mouseleave.native="showOnHover && ((hoveringMenu = false), close())"
|
|
20
20
|
:tile="tile"
|
|
21
21
|
:title-class="titleClasses"
|
|
22
22
|
:content-class="contentClasses"
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
w-overlay(
|
|
33
33
|
v-if="overlay"
|
|
34
34
|
ref="overlay"
|
|
35
|
-
:model-value="
|
|
35
|
+
:model-value="detachableVisible"
|
|
36
36
|
:persistent="persistent"
|
|
37
37
|
:class="overlayClasses"
|
|
38
38
|
v-bind="overlayProps"
|
|
39
39
|
:z-index="(zIndex || 200) - 1"
|
|
40
|
-
@update:model-value="
|
|
40
|
+
@update:model-value="detachableVisible = false")
|
|
41
41
|
</template>
|
|
42
42
|
|
|
43
43
|
<script>
|
|
@@ -51,12 +51,13 @@
|
|
|
51
51
|
*/
|
|
52
52
|
|
|
53
53
|
import { objectifyClasses } from '../utils/index'
|
|
54
|
-
import
|
|
54
|
+
import DetachableMixin from '../mixins/detachable'
|
|
55
55
|
|
|
56
56
|
// const marginFromWindowSide = 4 // Amount of px from a window side, instead of overflowing.
|
|
57
57
|
|
|
58
58
|
export default {
|
|
59
59
|
name: 'w-menu',
|
|
60
|
+
mixins: [DetachableMixin],
|
|
60
61
|
|
|
61
62
|
props: {
|
|
62
63
|
modelValue: {}, // Show or hide.
|
|
@@ -73,98 +74,53 @@ export default {
|
|
|
73
74
|
menuClass: { type: [String, Object, Array] },
|
|
74
75
|
titleClass: { type: [String, Object, Array] },
|
|
75
76
|
contentClass: { type: [String, Object, Array] },
|
|
76
|
-
// Position.
|
|
77
77
|
arrow: { type: Boolean }, // The small triangle pointing toward the activator.
|
|
78
|
-
detachTo: { type: [String, Boolean, Object] },
|
|
79
|
-
fixed: { type: Boolean },
|
|
80
|
-
top: { type: Boolean },
|
|
81
|
-
bottom: { type: Boolean },
|
|
82
|
-
left: { type: Boolean },
|
|
83
|
-
right: { type: Boolean },
|
|
84
|
-
alignTop: { type: Boolean },
|
|
85
|
-
alignBottom: { type: Boolean },
|
|
86
|
-
alignLeft: { type: Boolean },
|
|
87
|
-
alignRight: { type: Boolean },
|
|
88
|
-
zIndex: { type: [Number, String, Boolean] },
|
|
89
78
|
minWidth: { type: [Number, String] }, // can be like: `40`, `5em`, `activator`.
|
|
90
79
|
overlay: { type: Boolean },
|
|
91
80
|
overlayClass: { type: [String, Object, Array] },
|
|
92
81
|
overlayProps: { type: Object }, // Allow passing down an object of props to the w-overlay component.
|
|
93
82
|
persistent: { type: Boolean },
|
|
94
|
-
|
|
83
|
+
delay: { type: Number }
|
|
84
|
+
// Other props in the detachable mixin:
|
|
85
|
+
// detachTo, appendTo, fixed, top, bottom, left, right, alignTop, alignBottom, alignLeft,
|
|
86
|
+
// alignRight, noPosition, zIndex, activator.
|
|
95
87
|
},
|
|
96
88
|
|
|
97
89
|
emits: ['input', 'update:modelValue', 'open', 'close'],
|
|
98
90
|
|
|
99
91
|
data: () => ({
|
|
100
|
-
|
|
92
|
+
detachableVisible: false,
|
|
101
93
|
hoveringActivator: false,
|
|
102
94
|
hoveringMenu: false,
|
|
103
95
|
// The menu computed top & left coordinates.
|
|
104
|
-
|
|
96
|
+
detachableCoords: {
|
|
105
97
|
top: 0,
|
|
106
98
|
left: 0
|
|
107
99
|
},
|
|
108
|
-
activatorEl: null,
|
|
109
100
|
activatorWidth: 0,
|
|
110
|
-
|
|
101
|
+
detachableEl: null,
|
|
111
102
|
timeoutId: null
|
|
112
103
|
}),
|
|
113
104
|
|
|
114
105
|
computed: {
|
|
106
|
+
/**
|
|
107
|
+
* Other computed in the detachable mixin:
|
|
108
|
+
* - `appendToTarget`
|
|
109
|
+
* - `detachableParentEl`
|
|
110
|
+
* - `activatorEl`
|
|
111
|
+
* - `position`
|
|
112
|
+
* - `alignment`
|
|
113
|
+
**/
|
|
114
|
+
|
|
115
115
|
transitionName () {
|
|
116
116
|
return this.transition || 'scale-fade'
|
|
117
117
|
},
|
|
118
118
|
|
|
119
|
-
// DOM element to attach menu to.
|
|
120
|
-
detachToTarget () {
|
|
121
|
-
let target = this.detachTo || '.w-app'
|
|
122
|
-
if (target === true) target = '.w-app'
|
|
123
|
-
else if (target && !['object', 'string'].includes(typeof target)) target = '.w-app'
|
|
124
|
-
else if (typeof target === 'object' && !target.nodeType) {
|
|
125
|
-
target = '.w-app'
|
|
126
|
-
consoleWarn('Invalid node provided in w-menu `detach-to`. Falling back to .w-app.', this)
|
|
127
|
-
}
|
|
128
|
-
if (typeof target === 'string') target = document.querySelector(target)
|
|
129
|
-
|
|
130
|
-
if (!target) {
|
|
131
|
-
consoleWarn(`Unable to locate ${this.detachTo ? `target ${this.detachTo}` : '.w-app'}`, this)
|
|
132
|
-
target = document.querySelector('.w-app')
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return target
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
// DOM element that will receive the menu.
|
|
139
|
-
menuParentEl () {
|
|
140
|
-
return this.detachToTarget
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
position () {
|
|
144
|
-
return (
|
|
145
|
-
(this.top && 'top') ||
|
|
146
|
-
(this.bottom && 'bottom') ||
|
|
147
|
-
(this.left && 'left') ||
|
|
148
|
-
(this.right && 'right') ||
|
|
149
|
-
'bottom'
|
|
150
|
-
)
|
|
151
|
-
},
|
|
152
|
-
|
|
153
119
|
menuMinWidth () {
|
|
154
120
|
if (this.minWidth === 'activator') return this.activatorWidth ? `${this.activatorWidth}px` : 0
|
|
155
121
|
else return isNaN(this.minWidth) ? this.minWidth : (this.minWidth ? `${this.minWidth}px` : 0)
|
|
156
122
|
},
|
|
157
123
|
|
|
158
|
-
alignment () {
|
|
159
|
-
return (
|
|
160
|
-
((this.top || this.bottom) && this.alignLeft && 'left') ||
|
|
161
|
-
((this.top || this.bottom) && this.alignRight && 'right') ||
|
|
162
|
-
((this.left || this.right) && this.alignTop && 'top') ||
|
|
163
|
-
((this.left || this.right) && this.alignBottom && 'bottom') ||
|
|
164
|
-
''
|
|
165
|
-
)
|
|
166
|
-
},
|
|
167
|
-
|
|
168
124
|
menuClasses () {
|
|
169
125
|
return objectifyClasses(this.menuClass)
|
|
170
126
|
},
|
|
@@ -197,12 +153,12 @@ export default {
|
|
|
197
153
|
}
|
|
198
154
|
},
|
|
199
155
|
|
|
200
|
-
// The
|
|
156
|
+
// The floating menu styles.
|
|
201
157
|
styles () {
|
|
202
158
|
return {
|
|
203
159
|
zIndex: this.zIndex || this.zIndex === 0 || (this.overlay && !this.zIndex && 200) || null,
|
|
204
|
-
top: (this.
|
|
205
|
-
left: (this.
|
|
160
|
+
top: (this.detachableCoords.top && `${~~this.detachableCoords.top}px`) || null,
|
|
161
|
+
left: (this.detachableCoords.left && `${~~this.detachableCoords.left}px`) || null,
|
|
206
162
|
minWidth: (this.minWidth && this.menuMinWidth) || null,
|
|
207
163
|
'--w-menu-bg-color': this.arrow && this.$waveui.colors[this.bgColor || 'white']
|
|
208
164
|
}
|
|
@@ -213,31 +169,44 @@ export default {
|
|
|
213
169
|
|
|
214
170
|
if (this.showOnHover) {
|
|
215
171
|
handlers = {
|
|
216
|
-
focus: this.
|
|
217
|
-
blur: this.
|
|
172
|
+
focus: this.toggle,
|
|
173
|
+
blur: this.toggle,
|
|
218
174
|
mouseenter: e => {
|
|
219
175
|
this.hoveringActivator = true
|
|
220
|
-
this.
|
|
176
|
+
this.open(e)
|
|
221
177
|
},
|
|
222
178
|
mouseleave: e => {
|
|
223
179
|
this.hoveringActivator = false
|
|
224
180
|
// Wait 10ms, the time to get the hoveringMenu updated on mouseenter on the menu.
|
|
225
181
|
setTimeout(() => {
|
|
226
|
-
if (!this.hoveringMenu) this.
|
|
182
|
+
if (!this.hoveringMenu) this.close()
|
|
227
183
|
}, 10)
|
|
228
184
|
}
|
|
229
185
|
}
|
|
230
|
-
|
|
231
|
-
if ('ontouchstart' in window)
|
|
186
|
+
// Check the window exists: SSR-proof.
|
|
187
|
+
if (typeof window !== 'undefined' && 'ontouchstart' in window) {
|
|
188
|
+
handlers.click = this.toggle
|
|
189
|
+
}
|
|
232
190
|
}
|
|
233
|
-
else handlers = { click: this.
|
|
191
|
+
else handlers = { click: this.toggle }
|
|
234
192
|
return handlers
|
|
235
193
|
}
|
|
236
194
|
},
|
|
237
195
|
|
|
238
196
|
methods: {
|
|
239
|
-
|
|
240
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Other methods in the `detachable` mixin:
|
|
199
|
+
* - `getActivatorCoordinates`
|
|
200
|
+
* - `computeDetachableCoords`
|
|
201
|
+
* - `onResize`
|
|
202
|
+
* - `onOutsideMousedown`
|
|
203
|
+
* - `insertInDOM`
|
|
204
|
+
* - `removeFromDOM`
|
|
205
|
+
**/
|
|
206
|
+
|
|
207
|
+
// ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
|
|
208
|
+
toggle (e) {
|
|
209
|
+
let shouldShowMenu = this.detachableVisible
|
|
241
210
|
if ('ontouchstart' in window && this.showOnHover && e.type === 'click') {
|
|
242
211
|
shouldShowMenu = !shouldShowMenu
|
|
243
212
|
}
|
|
@@ -253,25 +222,29 @@ export default {
|
|
|
253
222
|
|
|
254
223
|
this.timeoutId = clearTimeout(this.timeoutId)
|
|
255
224
|
|
|
256
|
-
if (shouldShowMenu)
|
|
257
|
-
|
|
258
|
-
this.$emit('input', true)
|
|
259
|
-
this.$emit('open')
|
|
260
|
-
|
|
261
|
-
this.openMenu(e)
|
|
262
|
-
}
|
|
263
|
-
else this.closeMenu()
|
|
225
|
+
if (shouldShowMenu) this.open(e)
|
|
226
|
+
else this.close()
|
|
264
227
|
},
|
|
265
228
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
229
|
+
// ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
|
|
230
|
+
async open (e) {
|
|
231
|
+
// A tiny delay may help positioning the detachable correctly in case of multiple activators
|
|
232
|
+
// with different menu contents.
|
|
233
|
+
if (this.delay) await new Promise(resolve => setTimeout(resolve, this.delay))
|
|
234
|
+
|
|
235
|
+
this.detachableVisible = true
|
|
236
|
+
|
|
237
|
+
// If the activator is external, there might be multiple,
|
|
238
|
+
// so on open, the activator will be set to the event target.
|
|
239
|
+
if (this.activator) this.activatorEl = e.target
|
|
240
|
+
|
|
241
|
+
await this.insertInDOM()
|
|
269
242
|
|
|
270
243
|
if (this.minWidth === 'activator') this.activatorWidth = this.activatorEl.offsetWidth
|
|
271
244
|
|
|
272
|
-
if (!this.noPosition) this.
|
|
245
|
+
if (!this.noPosition) this.computeDetachableCoords(e)
|
|
273
246
|
|
|
274
|
-
// In `
|
|
247
|
+
// In `getActivatorCoordinates` accessing the menu computed styles takes a few ms (less than 10ms),
|
|
275
248
|
// if we don't postpone the Menu apparition it will start transition from a visible menu and
|
|
276
249
|
// thus will not transition.
|
|
277
250
|
this.timeoutId = setTimeout(() => {
|
|
@@ -289,199 +262,32 @@ export default {
|
|
|
289
262
|
* - click of activator
|
|
290
263
|
* - hover outside if showOnHover
|
|
291
264
|
* - click inside menu if hideOnMenuClick.
|
|
265
|
+
* / ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
|
|
292
266
|
*
|
|
293
267
|
* @param {Boolean} force when showOnHover is set to true, hovering menu should keep it open.
|
|
294
268
|
* But if hideOnMenuClick is also set to true, this should force close
|
|
295
269
|
* even while hovering the menu.
|
|
296
270
|
*/
|
|
297
|
-
async
|
|
271
|
+
async close (force = false) {
|
|
298
272
|
// Might be already closed.
|
|
299
273
|
// E.g. showOnHover & hideOnMenuClick: on click, force hide then mouseleave is also firing.
|
|
300
|
-
if (!this.
|
|
274
|
+
if (!this.detachableVisible) return
|
|
301
275
|
|
|
302
276
|
if (this.showOnHover && !force) {
|
|
303
277
|
await new Promise(resolve => setTimeout(resolve, 10))
|
|
304
278
|
if (this.showOnHover && (this.hoveringMenu || this.hoveringActivator)) return
|
|
305
279
|
}
|
|
306
280
|
|
|
307
|
-
this.$emit('update:modelValue', (this.
|
|
281
|
+
this.$emit('update:modelValue', (this.detachableVisible = false))
|
|
308
282
|
this.$emit('input', false)
|
|
309
283
|
this.$emit('close')
|
|
310
284
|
// Remove the mousedown listener if the menu got closed without a mousedown outside of the menu.
|
|
311
285
|
document.removeEventListener('mousedown', this.onOutsideMousedown)
|
|
312
286
|
window.removeEventListener('resize', this.onResize)
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
onOutsideMousedown (e) {
|
|
316
|
-
if (!this.menuEl.contains(e.target) && !this.activatorEl.contains(e.target)) {
|
|
317
|
-
this.$emit('update:modelValue', (this.menuVisible = false))
|
|
318
|
-
this.$emit('input', false)
|
|
319
|
-
this.$emit('close')
|
|
320
|
-
document.removeEventListener('mousedown', this.onOutsideMousedown)
|
|
321
|
-
window.removeEventListener('resize', this.onResize)
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
onResize () {
|
|
326
|
-
if (this.minWidth === 'activator') this.activatorWidth = this.activatorEl.offsetWidth
|
|
327
|
-
this.computeMenuPosition()
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
getCoordinates (e) {
|
|
331
|
-
// Get the activator coordinates relative to window.
|
|
332
|
-
const { top, left, width, height } = (e ? e.target : this.activatorEl).getBoundingClientRect()
|
|
333
|
-
let coords = { top, left, width, height }
|
|
334
|
-
|
|
335
|
-
// If absolute position, adjust top & left.
|
|
336
|
-
if (!this.fixed) {
|
|
337
|
-
const { top: targetTop, left: targetLeft } = this.menuParentEl.getBoundingClientRect()
|
|
338
|
-
const computedStyles = window.getComputedStyle(this.menuParentEl, null)
|
|
339
|
-
coords = {
|
|
340
|
-
...coords,
|
|
341
|
-
top: top - targetTop + this.menuParentEl.scrollTop - parseInt(computedStyles.getPropertyValue('border-top-width')),
|
|
342
|
-
left: left - targetLeft + this.menuParentEl.scrollLeft - parseInt(computedStyles.getPropertyValue('border-left-width'))
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return coords
|
|
347
|
-
},
|
|
348
|
-
|
|
349
|
-
computeMenuPosition (e) {
|
|
350
|
-
// Get the activator coordinates.
|
|
351
|
-
let { top, left, width, height } = this.getCoordinates(e)
|
|
352
|
-
|
|
353
|
-
// 1. First display the menu but hide it (So we can get its dimension).
|
|
354
|
-
// --------------------------------------------------
|
|
355
|
-
this.menuEl.style.visibility = 'hidden'
|
|
356
|
-
this.menuEl.style.display = 'flex'
|
|
357
|
-
const computedStyles = window.getComputedStyle(this.menuEl, null)
|
|
358
|
-
|
|
359
|
-
// 2. Position the menu top, left, right, bottom and apply chosen alignment.
|
|
360
|
-
// --------------------------------------------------
|
|
361
|
-
// Subtract half or full activator width or height and menu width or height according to the
|
|
362
|
-
// menu alignment.
|
|
363
|
-
// Note: the menu position relies on transform translate, the custom animation may override the
|
|
364
|
-
// css transform property so do without it i.e. no translateX(-50%), and recalculate top & left
|
|
365
|
-
// manually.
|
|
366
|
-
switch (this.position) {
|
|
367
|
-
case 'top': {
|
|
368
|
-
top -= this.menuEl.offsetHeight
|
|
369
|
-
if (this.alignRight) {
|
|
370
|
-
// left: 100% of activator.
|
|
371
|
-
left += width - this.menuEl.offsetWidth +
|
|
372
|
-
parseInt(computedStyles.getPropertyValue('border-right-width'))
|
|
373
|
-
}
|
|
374
|
-
else if (!this.alignLeft) left += (width - this.menuEl.offsetWidth) / 2 // left: 50% of activator - half menu width.
|
|
375
|
-
break
|
|
376
|
-
}
|
|
377
|
-
case 'bottom': {
|
|
378
|
-
top += height
|
|
379
|
-
if (this.alignRight) {
|
|
380
|
-
// left: 100% of activator.
|
|
381
|
-
left += width - this.menuEl.offsetWidth +
|
|
382
|
-
parseInt(computedStyles.getPropertyValue('border-right-width'))
|
|
383
|
-
}
|
|
384
|
-
else if (!this.alignLeft) left += (width - this.menuEl.offsetWidth) / 2 // left: 50% of activator - half menu width.
|
|
385
|
-
break
|
|
386
|
-
}
|
|
387
|
-
case 'left': {
|
|
388
|
-
left -= this.menuEl.offsetWidth
|
|
389
|
-
if (this.alignBottom) top += height - this.menuEl.offsetHeight
|
|
390
|
-
else if (!this.alignTop) top += (height - this.menuEl.offsetHeight) / 2 // top: 50% of activator - half menu height.
|
|
391
|
-
break
|
|
392
|
-
}
|
|
393
|
-
case 'right': {
|
|
394
|
-
left += width
|
|
395
|
-
if (this.alignBottom) {
|
|
396
|
-
top += height - this.menuEl.offsetHeight +
|
|
397
|
-
parseInt(computedStyles.getPropertyValue('margin-top'))
|
|
398
|
-
}
|
|
399
|
-
else if (!this.alignTop) {
|
|
400
|
-
top += (height - this.menuEl.offsetHeight) / 2 + // top: 50% of activator - half menu height.
|
|
401
|
-
parseInt(computedStyles.getPropertyValue('margin-top'))
|
|
402
|
-
}
|
|
403
|
-
break
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// 3. Keep fully in viewport.
|
|
408
|
-
// @todo: do this.
|
|
409
|
-
// --------------------------------------------------
|
|
410
|
-
// if (this.position === 'top' && ((top - this.menuEl.offsetHeight) < 0)) {
|
|
411
|
-
// const margin = - parseInt(computedStyles.getPropertyValue('margin-top'))
|
|
412
|
-
// top -= top - this.menuEl.offsetHeight - margin - marginFromWindowSide
|
|
413
|
-
// }
|
|
414
|
-
// else if (this.position === 'left' && left - this.menuEl.offsetWidth < 0) {
|
|
415
|
-
// const margin = - parseInt(computedStyles.getPropertyValue('margin-left'))
|
|
416
|
-
// left -= left - this.menuEl.offsetWidth - margin - marginFromWindowSide
|
|
417
|
-
// }
|
|
418
|
-
// else if (this.position === 'right' && left + width + this.menuEl.offsetWidth > window.innerWidth) {
|
|
419
|
-
// const margin = parseInt(computedStyles.getPropertyValue('margin-left'))
|
|
420
|
-
// left -= left + width + this.menuEl.offsetWidth - window.innerWidth + margin + marginFromWindowSide
|
|
421
|
-
// }
|
|
422
|
-
// else if (this.position === 'bottom' && top + height + this.menuEl.offsetHeight > window.innerHeight) {
|
|
423
|
-
// const margin = parseInt(computedStyles.getPropertyValue('margin-top'))
|
|
424
|
-
// top -= top + height + this.menuEl.offsetHeight - window.innerHeight + margin + marginFromWindowSide
|
|
425
|
-
// }
|
|
426
|
-
|
|
427
|
-
// 4. Hide the menu again so the transition happens correctly.
|
|
428
|
-
// --------------------------------------------------
|
|
429
|
-
this.menuEl.style.visibility = null
|
|
430
|
-
|
|
431
|
-
// The menu coordinates are also recalculated while resizing window with open menu: keep the menu visible.
|
|
432
|
-
if (!this.menuVisible) this.menuEl.style.display = 'none'
|
|
433
|
-
|
|
434
|
-
this.menuCoordinates = { top, left }
|
|
435
|
-
},
|
|
436
|
-
|
|
437
|
-
insertMenu () {
|
|
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
|
-
})
|
|
448
|
-
},
|
|
449
|
-
|
|
450
|
-
removeMenu () {
|
|
451
|
-
if (this.menuEl && this.menuEl.parentNode) this.menuEl.remove()
|
|
452
|
-
}
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
mounted () {
|
|
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
|
-
}
|
|
466
|
-
|
|
467
|
-
if (this.modelValue) this.toggleMenu({ type: 'click', target: this.activatorEl })
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
beforeUnmount () {
|
|
471
|
-
this.removeMenu()
|
|
472
|
-
if (this.overlay && this.overlayEl.parentNode) this.overlayEl.remove()
|
|
473
|
-
if (this.activatorEl && this.activatorEl.parentNode) this.activatorEl.remove()
|
|
474
|
-
},
|
|
475
|
-
|
|
476
|
-
watch: {
|
|
477
|
-
modelValue (bool) {
|
|
478
|
-
if (!!bool !== this.menuVisible) this.toggleMenu({ type: 'click', target: this.activatorEl })
|
|
479
|
-
},
|
|
480
|
-
detachTo () {
|
|
481
|
-
this.removeMenu()
|
|
482
|
-
this.insertMenu()
|
|
483
287
|
}
|
|
484
288
|
}
|
|
289
|
+
|
|
290
|
+
// watch, mounted & beforeDestroy hooks are set in the detachable.js mixin.
|
|
485
291
|
}
|
|
486
292
|
</script>
|
|
487
293
|
|
|
@@ -11,8 +11,8 @@ transition-group(
|
|
|
11
11
|
:key="notif._uid"
|
|
12
12
|
v-model="notif._value"
|
|
13
13
|
@close="notifManager.dismiss(notif._uid)"
|
|
14
|
-
v-bind="notif")
|
|
15
|
-
|
|
14
|
+
v-bind="notifProps(notif)")
|
|
15
|
+
div(v-html="notif.message")
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script>
|
|
@@ -42,6 +42,13 @@ export default {
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
|
|
45
|
+
methods: {
|
|
46
|
+
notifProps (notif) {
|
|
47
|
+
const { _value, _uid, message, timeout, ...props } = notif
|
|
48
|
+
return props
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
45
52
|
created () {
|
|
46
53
|
this.notifManager = new NotificationManager()
|
|
47
54
|
},
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
.w-progress(:class="classes" :style="styles")
|
|
3
3
|
//- Linear progress.
|
|
4
|
-
.w-progress__progress(
|
|
4
|
+
.w-progress__progress(
|
|
5
|
+
v-if="!circle"
|
|
6
|
+
:class="{ full: progressValue === 100 }"
|
|
7
|
+
:style="`width: ${progressValue}%`")
|
|
5
8
|
|
|
6
9
|
//- Circular progress.
|
|
7
10
|
template(v-else)
|
|
@@ -3,7 +3,7 @@ component(
|
|
|
3
3
|
ref="formEl"
|
|
4
4
|
:is="formRegister ? 'w-form-element' : 'div'"
|
|
5
5
|
v-bind="formRegister && { validators, inputValue: rating, disabled: isDisabled, readonly: isReadonly }"
|
|
6
|
-
:valid
|
|
6
|
+
v-model:valid="valid"
|
|
7
7
|
@reset="$emit('update:modelValue', rating = null);$emit('input', null)"
|
|
8
8
|
:class="classes")
|
|
9
9
|
input(:id="inputName" :name="inputName" type="hidden" :value="rating")
|
|
@@ -21,7 +21,7 @@ component(
|
|
|
21
21
|
v-model="showMenu"
|
|
22
22
|
:menu-class="`w-select__menu ${menuClass || ''}`"
|
|
23
23
|
transition="slide-fade-down"
|
|
24
|
-
:
|
|
24
|
+
:append-to="(menuProps || {}).appendTo !== undefined ? (menuProps || {}).appendTo : '.w-app'"
|
|
25
25
|
align-left
|
|
26
26
|
custom
|
|
27
27
|
min-width="activator"
|
|
@@ -329,7 +329,7 @@ export default {
|
|
|
329
329
|
setTimeout(() => {
|
|
330
330
|
const itemIndex = this.inputValue.length ? this.inputValue[0].index : 0 // Real index starts at 0.
|
|
331
331
|
// User visible index starts at 1.
|
|
332
|
-
this.$refs['w-list'].$el.querySelector(`#w-select-menu--${this._.uid}_item-${itemIndex + 1}`)
|
|
332
|
+
this.$refs['w-list'].$el.querySelector(`#w-select-menu--${this._.uid}_item-${itemIndex + 1}`)?.focus()
|
|
333
333
|
}, 100)
|
|
334
334
|
},
|
|
335
335
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
.w-spinner(v-if="
|
|
2
|
+
.w-spinner(v-if="modelValue || modelValue === undefined" :class="classes" :style="styles")
|
|
3
3
|
span(v-if="isThreeDots")
|
|
4
4
|
</template>
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
export default {
|
|
8
8
|
name: 'w-spinner',
|
|
9
9
|
props: {
|
|
10
|
-
|
|
10
|
+
modelValue: {},
|
|
11
11
|
color: { type: String, default: 'primary' },
|
|
12
12
|
xs: { type: Boolean },
|
|
13
13
|
sm: { type: Boolean },
|
|
@@ -313,7 +313,7 @@ export default {
|
|
|
313
313
|
}
|
|
314
314
|
)
|
|
315
315
|
|
|
316
|
-
// Keep external `expanded-rows.sync` updated.
|
|
316
|
+
// Keep external `expanded-rows.sync` (Vue 2) or v-model:expanded-rows (Vue 3) updated.
|
|
317
317
|
this.$emit('update:expanded-rows', this.expandedRowsInternal)
|
|
318
318
|
}
|
|
319
319
|
|
|
@@ -342,7 +342,7 @@ export default {
|
|
|
342
342
|
}
|
|
343
343
|
)
|
|
344
344
|
|
|
345
|
-
// Keep external `selected-rows.sync` updated.
|
|
345
|
+
// Keep external `selected-rows.sync` (Vue 2) or v-model:selected-rows (Vue 3) updated.
|
|
346
346
|
this.$emit('update:selected-rows', this.selectedRowsInternal)
|
|
347
347
|
}
|
|
348
348
|
}
|
|
@@ -89,7 +89,6 @@ export default {
|
|
|
89
89
|
background-color: rgba(255, 255, 255, 0.85);
|
|
90
90
|
padding-left: 2 * $base-increment;
|
|
91
91
|
padding-right: 2 * $base-increment;
|
|
92
|
-
font-size: round(0.85 * $base-font-size);
|
|
93
92
|
cursor: default;
|
|
94
93
|
user-select: none;
|
|
95
94
|
|
|
@@ -100,23 +99,35 @@ export default {
|
|
|
100
99
|
&--tile {border-radius: initial;}
|
|
101
100
|
&--shadow {box-shadow: $box-shadow;}
|
|
102
101
|
|
|
103
|
-
&.size--xs {
|
|
102
|
+
&.size--xs {
|
|
103
|
+
$font-size: round(0.7 * $base-font-size);
|
|
104
|
+
font-size: $font-size;
|
|
105
|
+
line-height: $font-size + 2px;
|
|
106
|
+
}
|
|
104
107
|
&.size--sm {
|
|
105
|
-
font-size: round(0.82 * $base-font-size);
|
|
108
|
+
$font-size: round(0.82 * $base-font-size);
|
|
109
|
+
font-size: $font-size;
|
|
110
|
+
line-height: $font-size + 2px;
|
|
106
111
|
padding: round(0.25 * $base-increment) $base-increment;
|
|
107
112
|
}
|
|
108
113
|
&.size--md {
|
|
109
|
-
font-size: round(0.
|
|
114
|
+
$font-size: round(0.85 * $base-font-size);
|
|
115
|
+
font-size: $font-size;
|
|
116
|
+
line-height: $font-size + 4px;
|
|
110
117
|
padding-top: round(0.25 * $base-increment);
|
|
111
118
|
padding-bottom: round(0.25 * $base-increment);
|
|
112
119
|
}
|
|
113
120
|
&.size--lg {
|
|
114
|
-
font-size: round(1.1 * $base-font-size);
|
|
121
|
+
$font-size: round(1.1 * $base-font-size);
|
|
122
|
+
font-size: $font-size;
|
|
123
|
+
line-height: $font-size + 4px;
|
|
115
124
|
padding-top: round(0.5 * $base-increment);
|
|
116
125
|
padding-bottom: round(0.5 * $base-increment);
|
|
117
126
|
}
|
|
118
127
|
&.size--xl {
|
|
119
|
-
font-size: round(1.3 * $base-font-size);
|
|
128
|
+
$font-size: round(1.3 * $base-font-size);
|
|
129
|
+
font-size: $font-size;
|
|
130
|
+
line-height: $font-size + 4px;
|
|
120
131
|
padding-top: round(1 * $base-increment);
|
|
121
132
|
padding-bottom: round(1 * $base-increment);
|
|
122
133
|
}
|