wave-ui 1.68.1 → 1.70.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 +508 -114
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +14 -14
- package/src/wave-ui/components/index.js +1 -0
- package/src/wave-ui/components/transitions/w-transition-expand.vue +2 -4
- package/src/wave-ui/components/w-accordion.vue +1 -4
- package/src/wave-ui/components/w-alert.vue +1 -4
- package/src/wave-ui/components/w-autocomplete.vue +404 -0
- package/src/wave-ui/components/w-badge.vue +1 -0
- package/src/wave-ui/components/w-button/button.vue +7 -9
- package/src/wave-ui/components/w-card.vue +2 -0
- package/src/wave-ui/components/w-checkbox.vue +3 -2
- package/src/wave-ui/components/w-checkboxes.vue +4 -1
- package/src/wave-ui/components/w-drawer.vue +2 -8
- package/src/wave-ui/components/w-icon.vue +1 -1
- package/src/wave-ui/components/w-image.vue +2 -8
- package/src/wave-ui/components/w-input.vue +19 -16
- package/src/wave-ui/components/w-list.vue +8 -11
- package/src/wave-ui/components/w-menu.vue +12 -1
- package/src/wave-ui/components/w-notification-manager.vue +3 -3
- package/src/wave-ui/components/w-progress.vue +2 -8
- package/src/wave-ui/components/w-rating.vue +1 -4
- package/src/wave-ui/components/w-select.vue +94 -48
- package/src/wave-ui/components/w-slider.vue +6 -5
- package/src/wave-ui/components/w-spinner.vue +2 -0
- package/src/wave-ui/components/w-switch.vue +1 -1
- package/src/wave-ui/components/w-table.vue +221 -211
- package/src/wave-ui/components/w-tabs/index.vue +1 -4
- package/src/wave-ui/components/w-tag.vue +1 -4
- package/src/wave-ui/components/w-textarea.vue +1 -1
- package/src/wave-ui/components/w-timeline.vue +1 -0
- package/src/wave-ui/components/w-toolbar.vue +1 -2
- package/src/wave-ui/components/w-tooltip.vue +44 -10
- package/src/wave-ui/components/w-tree.vue +7 -7
- package/src/wave-ui/core.js +36 -2
- package/src/wave-ui/mixins/detachable.js +27 -6
- package/src/wave-ui/scss/_base.scss +18 -0
- package/src/wave-ui/scss/_variables.scss +103 -9
- package/src/wave-ui/scss/index.scss +0 -1
- package/src/wave-ui/utils/dynamic-css.js +19 -8
|
@@ -20,11 +20,12 @@ component(
|
|
|
20
20
|
|
|
21
21
|
//- Input wrapper.
|
|
22
22
|
.w-input__input-wrap(:class="inputWrapClasses")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
slot(name="icon-left" :input-id="`w-input--${_uid}`")
|
|
24
|
+
w-icon.w-input__icon.w-input__icon--inner-left(
|
|
25
|
+
v-if="innerIconLeft"
|
|
26
|
+
tag="label"
|
|
27
|
+
:for="`w-input--${_uid}`"
|
|
28
|
+
@click="$emit('click:inner-icon-left', $event)") {{ innerIconLeft }}
|
|
28
29
|
//- All types of input except file.
|
|
29
30
|
input.w-input__input(
|
|
30
31
|
v-if="type !== 'file'"
|
|
@@ -61,6 +62,7 @@ component(
|
|
|
61
62
|
@change="onFileChange"
|
|
62
63
|
:multiple="multiple || null"
|
|
63
64
|
v-bind="attrs"
|
|
65
|
+
:disabled="isDisabled || null"
|
|
64
66
|
:data-progress="overallFilesProgress /* Needed to emit the overallProgress. */")
|
|
65
67
|
transition-group.w-input__input.w-input__input--file(
|
|
66
68
|
tag="label"
|
|
@@ -74,17 +76,17 @@ component(
|
|
|
74
76
|
span.filename(:key="`${i}b`") {{ file.base }}
|
|
75
77
|
| {{ file.extension ? `.${file.extension}` : '' }}
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
label.w-input__label.w-input__label--inside.w-form-el-shakable(
|
|
80
|
+
v-if="labelPosition === 'inside' && showLabelInside && ($slots.default || label)"
|
|
81
|
+
:class="labelClasses")
|
|
82
|
+
slot {{ label }}
|
|
83
|
+
|
|
84
|
+
slot(name="icon-right" :input-id="`w-input--${_uid}`")
|
|
85
|
+
w-icon.w-input__icon.w-input__icon--inner-right(
|
|
86
|
+
v-if="innerIconRight"
|
|
87
|
+
tag="label"
|
|
80
88
|
:for="`w-input--${_uid}`"
|
|
81
|
-
|
|
82
|
-
slot {{ label }}
|
|
83
|
-
w-icon.w-input__icon.w-input__icon--inner-right(
|
|
84
|
-
v-if="innerIconRight"
|
|
85
|
-
tag="label"
|
|
86
|
-
:for="`w-input--${_uid}`"
|
|
87
|
-
@click="$emit('click:inner-icon-right', $event)") {{ innerIconRight }}
|
|
89
|
+
@click="$emit('click:inner-icon-right', $event)") {{ innerIconRight }}
|
|
88
90
|
|
|
89
91
|
w-progress.fill-width(
|
|
90
92
|
v-if="hasLoading || (showProgress && (uploadInProgress || uploadComplete))"
|
|
@@ -228,7 +230,7 @@ export default {
|
|
|
228
230
|
overallFilesProgress () {
|
|
229
231
|
const progress = +this.inputFiles.reduce((total, file) => total + file.progress, 0)
|
|
230
232
|
const total = progress / this.inputFiles.length
|
|
231
|
-
this.$emit('update:overallProgress', this.inputFiles.length ? total :
|
|
233
|
+
this.$emit('update:overallProgress', this.inputFiles.length ? total : 0)
|
|
232
234
|
|
|
233
235
|
return total
|
|
234
236
|
},
|
|
@@ -558,6 +560,7 @@ $inactive-color: #777;
|
|
|
558
560
|
&__label {
|
|
559
561
|
transition: color $transition-duration;
|
|
560
562
|
cursor: pointer;
|
|
563
|
+
user-select: none;
|
|
561
564
|
|
|
562
565
|
&--left {margin-right: 2 * $base-increment;}
|
|
563
566
|
&--right {margin-left: 2 * $base-increment;}
|
|
@@ -229,8 +229,8 @@ export default {
|
|
|
229
229
|
'w-list__item-label--focused': item._focused,
|
|
230
230
|
'w-list__item-label--hoverable': this.hover,
|
|
231
231
|
'w-list__item-label--selectable': this.isSelectable,
|
|
232
|
-
[item.
|
|
233
|
-
[this.SelectionColor]: item._selected && !item.
|
|
232
|
+
[item[this.itemColorKey]]: !!item[this.itemColorKey],
|
|
233
|
+
[this.SelectionColor]: item._selected && !item[this.itemColorKey] && this.SelectionColor,
|
|
234
234
|
[item[this.itemClassKey] || this.itemClass]: item[this.itemClassKey] || this.itemClass
|
|
235
235
|
}
|
|
236
236
|
},
|
|
@@ -406,11 +406,11 @@ export default {
|
|
|
406
406
|
// Reset the selections when single selection allowed for w-select.
|
|
407
407
|
if (!this.isMultipleSelect) this.listItems.forEach(item => (item._selected = false))
|
|
408
408
|
|
|
409
|
-
this.checkSelection(selection) // Create an array with the selected values.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
409
|
+
const selectedItems = this.checkSelection(selection) // Create an array with the selected values.
|
|
410
|
+
// Update which items are selected or not.
|
|
411
|
+
this.listItems.forEach(item => {
|
|
412
|
+
item._selected = selectedItems.find(val => item._value === val) !== undefined
|
|
413
|
+
})
|
|
414
414
|
}
|
|
415
415
|
},
|
|
416
416
|
|
|
@@ -508,10 +508,7 @@ export default {
|
|
|
508
508
|
&:before {
|
|
509
509
|
content: '';
|
|
510
510
|
position: absolute;
|
|
511
|
-
|
|
512
|
-
left: 0;
|
|
513
|
-
bottom: 0;
|
|
514
|
-
right: 0;
|
|
511
|
+
inset: 0;
|
|
515
512
|
background-color: currentColor;
|
|
516
513
|
opacity: 0;
|
|
517
514
|
transition: 0.2s;
|
|
@@ -79,6 +79,7 @@ export default {
|
|
|
79
79
|
contentClass: { type: [String, Object, Array] },
|
|
80
80
|
arrow: { type: Boolean }, // The small triangle pointing toward the activator.
|
|
81
81
|
minWidth: { type: [Number, String] }, // can be like: `40`, `5em`, `activator`.
|
|
82
|
+
maxWidth: { type: [Number, String] }, // can be like: `40`, `5em`, `activator`.
|
|
82
83
|
overlay: { type: Boolean },
|
|
83
84
|
overlayClass: { type: [String, Object, Array] },
|
|
84
85
|
overlayProps: { type: Object }, // Allow passing down an object of props to the w-overlay component.
|
|
@@ -132,6 +133,11 @@ export default {
|
|
|
132
133
|
else return isNaN(this.minWidth) ? this.minWidth : (this.minWidth ? `${this.minWidth}px` : 0)
|
|
133
134
|
},
|
|
134
135
|
|
|
136
|
+
menuMaxWidth () {
|
|
137
|
+
if (this.maxWidth === 'activator') return this.activatorWidth ? `${this.activatorWidth}px` : 0
|
|
138
|
+
else return isNaN(this.maxWidth) ? this.maxWidth : (this.maxWidth ? `${this.maxWidth}px` : 0)
|
|
139
|
+
},
|
|
140
|
+
|
|
135
141
|
menuClasses () {
|
|
136
142
|
return objectifyClasses(this.menuClass)
|
|
137
143
|
},
|
|
@@ -174,7 +180,8 @@ export default {
|
|
|
174
180
|
top: (this.detachableCoords.top && `${~~this.detachableCoords.top}px`) || null,
|
|
175
181
|
left: (this.detachableCoords.left && `${~~this.detachableCoords.left}px`) || null,
|
|
176
182
|
minWidth: (this.minWidth && this.menuMinWidth) || null,
|
|
177
|
-
|
|
183
|
+
maxWidth: (this.maxWidth && this.menuMaxWidth) || null,
|
|
184
|
+
'--w-menu-bg-color': this.arrow && (this.$waveui.colors[this.bgColor] || 'rgb(var(--w-base-bg-color-rgb))')
|
|
178
185
|
}
|
|
179
186
|
},
|
|
180
187
|
|
|
@@ -254,6 +261,10 @@ export default {
|
|
|
254
261
|
* even while hovering the menu.
|
|
255
262
|
*/
|
|
256
263
|
async close (force = false) {
|
|
264
|
+
// The user may open and close the detachable so fast (like when toggling on hover) that it
|
|
265
|
+
// should not show up at all. This cancels the opening timer (if there is a set delay prop).
|
|
266
|
+
this.openTimeout = clearTimeout(this.openTimeout)
|
|
267
|
+
|
|
257
268
|
// Might be already closed.
|
|
258
269
|
// E.g. showOnHover & hideOnMenuClick: on click, force hide then mouseleave is also firing.
|
|
259
270
|
if (!this.detachableVisible) return
|
|
@@ -47,10 +47,9 @@ export default {
|
|
|
47
47
|
<style lang="scss">
|
|
48
48
|
.w-notification-manager {
|
|
49
49
|
position: fixed;
|
|
50
|
-
|
|
51
|
-
max-height: 100%;
|
|
52
|
-
right: 0;
|
|
50
|
+
inset: 0 0 0 auto;
|
|
53
51
|
z-index: 1000;
|
|
52
|
+
pointer-events: none;
|
|
54
53
|
width: 280px;
|
|
55
54
|
overflow-x: hidden;
|
|
56
55
|
overflow-y: auto;
|
|
@@ -64,6 +63,7 @@ export default {
|
|
|
64
63
|
right: 0;
|
|
65
64
|
margin: 8px;
|
|
66
65
|
flex-grow: 1;
|
|
66
|
+
pointer-events: all;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
</style>
|
|
@@ -154,10 +154,7 @@ $circle-size: 40;
|
|
|
154
154
|
&.w-progress--default-bg:after {
|
|
155
155
|
content: '';
|
|
156
156
|
position: absolute;
|
|
157
|
-
|
|
158
|
-
bottom: 0;
|
|
159
|
-
left: 0;
|
|
160
|
-
right: 0;
|
|
157
|
+
inset: 0;
|
|
161
158
|
border-radius: inherit;
|
|
162
159
|
background-color: currentColor;
|
|
163
160
|
opacity: 0.15;
|
|
@@ -188,10 +185,7 @@ $circle-size: 40;
|
|
|
188
185
|
&:before, &:after {
|
|
189
186
|
content: '';
|
|
190
187
|
position: absolute;
|
|
191
|
-
|
|
192
|
-
bottom: 0;
|
|
193
|
-
left: 0;
|
|
194
|
-
right: -5%;
|
|
188
|
+
inset: 0 -5% 0 0;
|
|
195
189
|
background: currentColor;
|
|
196
190
|
z-index: 1;
|
|
197
191
|
will-change: transform;
|
|
@@ -232,10 +232,7 @@ export default {
|
|
|
232
232
|
&__button:after {
|
|
233
233
|
content: "";
|
|
234
234
|
position: absolute;
|
|
235
|
-
|
|
236
|
-
left: 0;
|
|
237
|
-
right: 0;
|
|
238
|
-
bottom: 0;
|
|
235
|
+
inset: 0;
|
|
239
236
|
background-color: currentColor;
|
|
240
237
|
border-radius: 100%;
|
|
241
238
|
transform: translateX(100%) scale(0);
|
|
@@ -10,13 +10,13 @@ component(
|
|
|
10
10
|
template(v-if="labelPosition === 'left'")
|
|
11
11
|
label.w-select__label.w-select__label--left.w-form-el-shakable(
|
|
12
12
|
v-if="$slots.default || label"
|
|
13
|
-
|
|
13
|
+
@click="$refs['selection-input'].click()"
|
|
14
14
|
:class="labelClasses")
|
|
15
15
|
slot {{ label }}
|
|
16
16
|
|
|
17
17
|
w-menu(
|
|
18
18
|
v-model="showMenu"
|
|
19
|
-
@close="
|
|
19
|
+
@close="closeMenu"
|
|
20
20
|
:menu-class="`w-select__menu ${menuClass || ''}`"
|
|
21
21
|
transition="slide-fade-down"
|
|
22
22
|
:append-to="(menuProps || {}).appendTo !== undefined ? (menuProps || {}).appendTo : undefined"
|
|
@@ -24,7 +24,7 @@ component(
|
|
|
24
24
|
custom
|
|
25
25
|
min-width="activator"
|
|
26
26
|
v-bind="menuProps || {}")
|
|
27
|
-
template(#activator
|
|
27
|
+
template(#activator)
|
|
28
28
|
//- Input wrapper.
|
|
29
29
|
.w-select__selection-wrap(
|
|
30
30
|
@click="!isDisabled && !isReadonly && onInputFieldClick()"
|
|
@@ -43,17 +43,11 @@ component(
|
|
|
43
43
|
slot(name="selection" :item="multiple ? inputValue : inputValue[0]")
|
|
44
44
|
.w-select__selection(
|
|
45
45
|
ref="selection-input"
|
|
46
|
-
:contenteditable="isDisabled || isReadonly ? 'false' : 'true'"
|
|
47
46
|
@focus="!isDisabled && !isReadonly && onFocus($event)"
|
|
48
47
|
@blur="onBlur"
|
|
49
48
|
@keydown="!isDisabled && !isReadonly && onKeydown($event)"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
:disabled="isDisabled || null"
|
|
53
|
-
readonly
|
|
54
|
-
aria-readonly="true"
|
|
55
|
-
:tabindex="tabindex || null"
|
|
56
|
-
v-html="($scopedSlots.selection ? '' : selectionString) || placeholder")
|
|
49
|
+
v-bind="selectionAttributes"
|
|
50
|
+
v-html="selectionHtml")
|
|
57
51
|
//- For standard HTML form submission.
|
|
58
52
|
input(
|
|
59
53
|
v-for="(val, i) in (inputValue.length ? inputValue : [{}])"
|
|
@@ -64,7 +58,6 @@ component(
|
|
|
64
58
|
template(v-if="labelPosition === 'inside' && showLabelInside")
|
|
65
59
|
label.w-select__label.w-select__label--inside.w-form-el-shakable(
|
|
66
60
|
v-if="$slots.default || label"
|
|
67
|
-
:for="`w-select--${_uid}`"
|
|
68
61
|
:class="labelClasses")
|
|
69
62
|
slot {{ label }}
|
|
70
63
|
w-icon.w-select__icon.w-select__icon--inner-right(
|
|
@@ -76,8 +69,9 @@ component(
|
|
|
76
69
|
@input="onInput"
|
|
77
70
|
@item-click="$emit('item-click', $event)"
|
|
78
71
|
@item-select="onListItemSelect"
|
|
72
|
+
@keydown.native="onWListKeydown"
|
|
79
73
|
@keydown:enter="noUnselect && !multiple && closeMenu()"
|
|
80
|
-
@keydown:escape="showMenu && (
|
|
74
|
+
@keydown:escape="showMenu && (showMenu = false) /* Will call closeMenu() from w-menu(@close). */"
|
|
81
75
|
:value="inputValue"
|
|
82
76
|
:items="selectItems"
|
|
83
77
|
:multiple="multiple"
|
|
@@ -103,7 +97,7 @@ component(
|
|
|
103
97
|
template(v-if="labelPosition === 'right'")
|
|
104
98
|
label.w-select__label.w-select__label--right.w-form-el-shakable(
|
|
105
99
|
v-if="$slots.default || label"
|
|
106
|
-
|
|
100
|
+
@click="$refs['selection-input'].click()"
|
|
107
101
|
:class="labelClasses")
|
|
108
102
|
slot {{ label }}
|
|
109
103
|
</template>
|
|
@@ -163,7 +157,10 @@ export default {
|
|
|
163
157
|
showMenu: false,
|
|
164
158
|
menuMinWidth: 0,
|
|
165
159
|
isFocused: false,
|
|
166
|
-
selectionWrapRef: undefined
|
|
160
|
+
selectionWrapRef: undefined,
|
|
161
|
+
// Lookup a select list item from typing the first characters.
|
|
162
|
+
// If typing is too slow (> 1s), the lookup string is cleared.
|
|
163
|
+
quickLookup: { string: '', timeout: null }
|
|
167
164
|
}),
|
|
168
165
|
|
|
169
166
|
computed: {
|
|
@@ -180,27 +177,39 @@ export default {
|
|
|
180
177
|
return obj
|
|
181
178
|
})
|
|
182
179
|
},
|
|
183
|
-
hasValue () {
|
|
184
|
-
return Array.isArray(this.inputValue) ? this.inputValue.length : (this.inputValue !== null)
|
|
185
|
-
},
|
|
186
180
|
hasLabel () {
|
|
187
181
|
return this.label || this.$slots.default
|
|
188
182
|
},
|
|
189
183
|
showLabelInside () {
|
|
190
|
-
return !this.staticLabel || (!this.
|
|
184
|
+
return !this.staticLabel || (!this.inputValue.length && !this.placeholder)
|
|
185
|
+
},
|
|
186
|
+
selectionAttributes () {
|
|
187
|
+
return {
|
|
188
|
+
class: { 'w-select__selection--placeholder': !this.$scopedSlots.selection && !this.selectionString && this.placeholder },
|
|
189
|
+
disabled: this.isDisabled || null,
|
|
190
|
+
readonly: true,
|
|
191
|
+
ariareadonly: 'true',
|
|
192
|
+
tabindex: this.tabindex ?? null,
|
|
193
|
+
contenteditable: this.isDisabled || this.isReadonly ? 'false' : 'true'
|
|
194
|
+
}
|
|
191
195
|
},
|
|
192
196
|
selectionString () {
|
|
193
|
-
return this.inputValue
|
|
197
|
+
return this.inputValue.map(
|
|
194
198
|
item => item[this.itemValueKey] !== undefined ? item[this.itemLabelKey] : (item[this.itemLabelKey] ?? item)
|
|
195
199
|
).join(', ')
|
|
196
200
|
},
|
|
201
|
+
selectionHtml () {
|
|
202
|
+
if (!this.inputValue.length) return this.placeholder || ''
|
|
203
|
+
if (this.$scopedSlots.selection) return ''
|
|
204
|
+
return this.selectionString
|
|
205
|
+
},
|
|
197
206
|
classes () {
|
|
198
207
|
return {
|
|
199
208
|
'w-select': true,
|
|
200
209
|
'w-select--disabled': this.isDisabled,
|
|
201
210
|
'w-select--fit-to-content': this.fitToContent,
|
|
202
211
|
'w-select--readonly': this.isReadonly,
|
|
203
|
-
[`w-select--${this.
|
|
212
|
+
[`w-select--${this.inputValue.length ? 'filled' : 'empty'}`]: true,
|
|
204
213
|
'w-select--focused': (this.isFocused || this.showMenu) && !this.isReadonly,
|
|
205
214
|
'w-select--dark': this.dark,
|
|
206
215
|
'w-select--floating-label': this.hasLabel && this.labelPosition === 'inside' && !this.staticLabel,
|
|
@@ -272,16 +281,61 @@ export default {
|
|
|
272
281
|
index = (index + items.length + direction) % items.length
|
|
273
282
|
}
|
|
274
283
|
|
|
275
|
-
|
|
284
|
+
// If the current item is disabled, find the next one enabled (forward or backward).
|
|
285
|
+
let allItemsAreDisabled = false
|
|
286
|
+
if (items[index].disabled) {
|
|
287
|
+
const direction = e.keyCode === 38 ? -1 : 1 // Prev or next.
|
|
288
|
+
|
|
289
|
+
// Modulo to prevent out of range; + items.length to also work with negative values.
|
|
290
|
+
let newIndex = (index + direction + items.length) % items.length
|
|
291
|
+
const itemsCount = items.length
|
|
292
|
+
let loop = 0 // While-safety: will always end at least after 1 full array cycle.
|
|
293
|
+
while (loop < itemsCount && items[newIndex].disabled) {
|
|
294
|
+
// Circle through the array of items forward or backward, and reloop when out of range.
|
|
295
|
+
newIndex = (newIndex + items.length + direction) % items.length
|
|
296
|
+
loop++
|
|
297
|
+
}
|
|
298
|
+
if (loop >= itemsCount) allItemsAreDisabled = true
|
|
299
|
+
index = newIndex
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (!allItemsAreDisabled) this.onInput(items[index])
|
|
276
303
|
}
|
|
277
304
|
}
|
|
305
|
+
|
|
306
|
+
// `e.key.length === 1`: only the keys that output a character.
|
|
307
|
+
else if (e.key.length === 1) this.focusItemOnQuickLookup(e)
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
onWListKeydown (e) {
|
|
311
|
+
// `e.key.length === 1`: only the keys that output a character.
|
|
312
|
+
if (e.key.length === 1) this.focusItemOnQuickLookup(e)
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
focusItemOnQuickLookup (e) {
|
|
316
|
+
// Reset the timer every time a new valid key is pressed so we concat the string of chars.
|
|
317
|
+
if (this.quickLookup.timeout) clearTimeout(this.quickLookup.timeout)
|
|
318
|
+
// On each keypress, wait for 1s and clear the lookup string unless a key is pressed again.
|
|
319
|
+
this.quickLookup.timeout = setTimeout(() => this.quickLookup.string = '', 1000)
|
|
320
|
+
|
|
321
|
+
// Form a lookup string that is tested (starting from the first char) on each list item until
|
|
322
|
+
// a match is found.
|
|
323
|
+
this.quickLookup.string += e.key
|
|
324
|
+
const re = new RegExp(`^${this.quickLookup.string}`, 'i')
|
|
325
|
+
const itemIndexToFocus = this.selectItems.findIndex(
|
|
326
|
+
item => !item.disabled && item[this.itemLabelKey].match(re)
|
|
327
|
+
) + 1 // 0 if not found, more if found.
|
|
328
|
+
if (itemIndexToFocus) {
|
|
329
|
+
const selector = `.w-list__item:nth-child(${itemIndexToFocus}) .w-list__item-label`
|
|
330
|
+
this.$refs['w-list']?.$el?.querySelector(selector)?.focus()
|
|
331
|
+
}
|
|
278
332
|
},
|
|
279
333
|
|
|
280
334
|
// The items are given by the w-list component.
|
|
281
335
|
onInput (items) {
|
|
282
336
|
this.inputValue = items === null ? [] : (this.multiple ? items : [items])
|
|
283
337
|
// Return the original items when returnObject is true (no `value` if there wasn't),
|
|
284
|
-
// or the
|
|
338
|
+
// or the item value otherwise.
|
|
285
339
|
items = this.inputValue.map(item => this.returnObject ? this.items[item.index] : item.value)
|
|
286
340
|
|
|
287
341
|
// Emit the selection to the v-model.
|
|
@@ -290,6 +344,7 @@ export default {
|
|
|
290
344
|
this.$emit('update:modelValue', selection)
|
|
291
345
|
this.$emit('input', selection)
|
|
292
346
|
},
|
|
347
|
+
|
|
293
348
|
onInputFieldClick () {
|
|
294
349
|
if (this.showMenu) this.showMenu = false // Will call `closeMenu()` from w-menu(@close).
|
|
295
350
|
else this.openMenu()
|
|
@@ -322,7 +377,7 @@ export default {
|
|
|
322
377
|
return items.map(item => {
|
|
323
378
|
let value = item
|
|
324
379
|
if (item && typeof item === 'object') { // `null` is also an object!
|
|
325
|
-
value = item[this.itemValueKey]
|
|
380
|
+
value = item[this.itemValueKey] ?? item[this.itemLabelKey] ?? item
|
|
326
381
|
}
|
|
327
382
|
|
|
328
383
|
return this.selectItems[allValues.indexOf(value)]
|
|
@@ -346,7 +401,7 @@ export default {
|
|
|
346
401
|
|
|
347
402
|
this.showMenu = false
|
|
348
403
|
// Set the focus back on the main w-select input.
|
|
349
|
-
setTimeout(() => this.$refs['selection-input']
|
|
404
|
+
setTimeout(() => this.$refs['selection-input']?.focus(), 50)
|
|
350
405
|
}
|
|
351
406
|
},
|
|
352
407
|
|
|
@@ -455,6 +510,9 @@ export default {
|
|
|
455
510
|
align-items: center;
|
|
456
511
|
cursor: pointer;
|
|
457
512
|
caret-color: transparent;
|
|
513
|
+
border-radius: inherit;
|
|
514
|
+
|
|
515
|
+
&--placeholder {color: #888;}
|
|
458
516
|
|
|
459
517
|
.w-select__selection-slot + & {
|
|
460
518
|
position: absolute;
|
|
@@ -481,8 +539,6 @@ export default {
|
|
|
481
539
|
}
|
|
482
540
|
|
|
483
541
|
.w-select--readonly & {cursor: auto;}
|
|
484
|
-
|
|
485
|
-
&--placeholder {color: #888;}
|
|
486
542
|
}
|
|
487
543
|
|
|
488
544
|
&__selection-slot {
|
|
@@ -508,8 +564,8 @@ export default {
|
|
|
508
564
|
-webkit-tap-highlight-color: transparent;
|
|
509
565
|
}
|
|
510
566
|
|
|
511
|
-
&--inner-left {left:
|
|
512
|
-
&--inner-right {right:
|
|
567
|
+
&--inner-left {left: $base-increment;}
|
|
568
|
+
&--inner-right {right: $base-increment;}
|
|
513
569
|
.w-select--no-padding &--inner-left {left: 1px;}
|
|
514
570
|
.w-select--no-padding &--inner-right {right: 1px;}
|
|
515
571
|
|
|
@@ -526,6 +582,7 @@ export default {
|
|
|
526
582
|
align-items: center;
|
|
527
583
|
transition: color $transition-duration;
|
|
528
584
|
cursor: pointer;
|
|
585
|
+
user-select: none;
|
|
529
586
|
|
|
530
587
|
&--left {margin-right: 2 * $base-increment;}
|
|
531
588
|
&--right {margin-left: 2 * $base-increment;}
|
|
@@ -543,17 +600,15 @@ export default {
|
|
|
543
600
|
|
|
544
601
|
&__label--inside {
|
|
545
602
|
position: absolute;
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
right: 0;
|
|
603
|
+
inset: 0 0 auto;
|
|
604
|
+
min-height: inherit;
|
|
549
605
|
white-space: nowrap;
|
|
550
606
|
// Use margin instead of padding as the scale transformation below decreases the real padding
|
|
551
607
|
// size and misaligns the label.
|
|
552
608
|
margin-left: 2 * $base-increment;
|
|
553
|
-
transform: translateY(-50%);
|
|
554
609
|
pointer-events: none;
|
|
555
610
|
|
|
556
|
-
.w-select--inner-icon-right & {padding-right:
|
|
611
|
+
.w-select--inner-icon-right & {padding-right: 26px;}
|
|
557
612
|
|
|
558
613
|
.w-select--no-padding & {
|
|
559
614
|
left: 0;
|
|
@@ -570,28 +625,19 @@ export default {
|
|
|
570
625
|
transition: $transition-duration ease;
|
|
571
626
|
}
|
|
572
627
|
|
|
573
|
-
//
|
|
574
|
-
.w-select--focused.w-select--floating-label &,
|
|
628
|
+
// Move label with underline style.
|
|
575
629
|
.w-select--open.w-select--floating-label &,
|
|
576
630
|
.w-select--filled.w-select--floating-label &,
|
|
577
631
|
.w-select--has-placeholder.w-select--floating-label & {
|
|
578
|
-
transform: translateY(-
|
|
632
|
+
transform: translateY(-80%) scale(0.85);
|
|
579
633
|
}
|
|
580
|
-
// Chrome & Safari - Must
|
|
634
|
+
// Chrome & Safari - Must stay a separated rule or Firefox discards the whole rule seeing -webkit-.
|
|
581
635
|
.w-select--floating-label .w-select__select:-webkit-autofill & {
|
|
582
|
-
transform: translateY(-
|
|
583
|
-
}
|
|
584
|
-
// Move label with outline style or with shadow.
|
|
585
|
-
.w-select--focused.w-select--floating-label .w-select__selection-wrap--box &,
|
|
586
|
-
.w-select--open.w-select--floating-label .w-select__selection-wrap--box &,
|
|
587
|
-
.w-select--filled.w-select--floating-label .w-select__selection-wrap--box &,
|
|
588
|
-
.w-select--has-placeholder.w-select--floating-label .w-select__selection-wrap--box & {
|
|
589
|
-
transform: translateY(-180%) scale(0.85);
|
|
636
|
+
transform: translateY(-80%) scale(0.85);
|
|
590
637
|
}
|
|
591
|
-
.w-select--focused.w-select--floating-label.w-select--inner-icon-left &,
|
|
592
638
|
.w-select--open.w-select--floating-label.w-select--inner-icon-left &,
|
|
593
639
|
.w-select--filled.w-select--floating-label.w-select--inner-icon-left & {left: 0;}
|
|
594
|
-
// Chrome & Safari - Must
|
|
640
|
+
// Chrome & Safari - Must stay a separated rule or Firefox discards the whole rule seeing -webkit-.
|
|
595
641
|
.w-select--floating-label.w-select--inner-icon-left .w-select__select:-webkit-autofill & {left: 0;}
|
|
596
642
|
}
|
|
597
643
|
|
|
@@ -296,7 +296,8 @@ export default {
|
|
|
296
296
|
top: 0;
|
|
297
297
|
width: $base-increment;
|
|
298
298
|
aspect-ratio: 1;
|
|
299
|
-
|
|
299
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
300
|
+
background-color: $slider-step-label-bg-color;
|
|
300
301
|
border-radius: 99em;
|
|
301
302
|
// box-shadow: 0 0 0 1px #fff;
|
|
302
303
|
box-sizing: border-box;
|
|
@@ -359,6 +360,7 @@ export default {
|
|
|
359
360
|
position: absolute;
|
|
360
361
|
width: 3 * $base-increment;
|
|
361
362
|
aspect-ratio: 1;
|
|
363
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
362
364
|
left: 100%;
|
|
363
365
|
top: 50%;
|
|
364
366
|
transform: translate(-50%, -50%);
|
|
@@ -374,6 +376,7 @@ export default {
|
|
|
374
376
|
top: 0;
|
|
375
377
|
width: 100%;
|
|
376
378
|
aspect-ratio: 1;
|
|
379
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
377
380
|
border: none;
|
|
378
381
|
border-radius: 99em;
|
|
379
382
|
cursor: pointer;
|
|
@@ -389,10 +392,7 @@ export default {
|
|
|
389
392
|
}
|
|
390
393
|
// Colored border on thumb when hover and active - but with a transparency.
|
|
391
394
|
&:before {
|
|
392
|
-
|
|
393
|
-
right: 0;
|
|
394
|
-
top: 0;
|
|
395
|
-
bottom: 0;
|
|
395
|
+
inset: 0;
|
|
396
396
|
opacity: 0.5;
|
|
397
397
|
border: 1px solid currentColor;
|
|
398
398
|
}
|
|
@@ -453,6 +453,7 @@ export default {
|
|
|
453
453
|
border-radius: 99em 99em 99em 0;
|
|
454
454
|
width: 2.8em;
|
|
455
455
|
aspect-ratio: 1;
|
|
456
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
456
457
|
|
|
457
458
|
& > div {
|
|
458
459
|
position: absolute;
|
|
@@ -62,6 +62,7 @@ export default {
|
|
|
62
62
|
font-size: 2rem;
|
|
63
63
|
width: 1em;
|
|
64
64
|
aspect-ratio: 1;
|
|
65
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
65
66
|
|
|
66
67
|
&.size--xs {font-size: round(0.9 * divide($base-font-size, 2)) * 2;}
|
|
67
68
|
&.size--sm {font-size: round(1.5 * $base-font-size);}
|
|
@@ -74,6 +75,7 @@ export default {
|
|
|
74
75
|
position: absolute;
|
|
75
76
|
width: 100%;
|
|
76
77
|
aspect-ratio: 1;
|
|
78
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
77
79
|
top: 0;
|
|
78
80
|
left: 0;
|
|
79
81
|
background-color: currentColor;
|