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.
Files changed (42) hide show
  1. package/dist/wave-ui.cjs.js +1 -1
  2. package/dist/wave-ui.css +1 -1
  3. package/dist/wave-ui.es.js +508 -114
  4. package/dist/wave-ui.umd.js +1 -1
  5. package/package.json +14 -14
  6. package/src/wave-ui/components/index.js +1 -0
  7. package/src/wave-ui/components/transitions/w-transition-expand.vue +2 -4
  8. package/src/wave-ui/components/w-accordion.vue +1 -4
  9. package/src/wave-ui/components/w-alert.vue +1 -4
  10. package/src/wave-ui/components/w-autocomplete.vue +404 -0
  11. package/src/wave-ui/components/w-badge.vue +1 -0
  12. package/src/wave-ui/components/w-button/button.vue +7 -9
  13. package/src/wave-ui/components/w-card.vue +2 -0
  14. package/src/wave-ui/components/w-checkbox.vue +3 -2
  15. package/src/wave-ui/components/w-checkboxes.vue +4 -1
  16. package/src/wave-ui/components/w-drawer.vue +2 -8
  17. package/src/wave-ui/components/w-icon.vue +1 -1
  18. package/src/wave-ui/components/w-image.vue +2 -8
  19. package/src/wave-ui/components/w-input.vue +19 -16
  20. package/src/wave-ui/components/w-list.vue +8 -11
  21. package/src/wave-ui/components/w-menu.vue +12 -1
  22. package/src/wave-ui/components/w-notification-manager.vue +3 -3
  23. package/src/wave-ui/components/w-progress.vue +2 -8
  24. package/src/wave-ui/components/w-rating.vue +1 -4
  25. package/src/wave-ui/components/w-select.vue +94 -48
  26. package/src/wave-ui/components/w-slider.vue +6 -5
  27. package/src/wave-ui/components/w-spinner.vue +2 -0
  28. package/src/wave-ui/components/w-switch.vue +1 -1
  29. package/src/wave-ui/components/w-table.vue +221 -211
  30. package/src/wave-ui/components/w-tabs/index.vue +1 -4
  31. package/src/wave-ui/components/w-tag.vue +1 -4
  32. package/src/wave-ui/components/w-textarea.vue +1 -1
  33. package/src/wave-ui/components/w-timeline.vue +1 -0
  34. package/src/wave-ui/components/w-toolbar.vue +1 -2
  35. package/src/wave-ui/components/w-tooltip.vue +44 -10
  36. package/src/wave-ui/components/w-tree.vue +7 -7
  37. package/src/wave-ui/core.js +36 -2
  38. package/src/wave-ui/mixins/detachable.js +27 -6
  39. package/src/wave-ui/scss/_base.scss +18 -0
  40. package/src/wave-ui/scss/_variables.scss +103 -9
  41. package/src/wave-ui/scss/index.scss +0 -1
  42. 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
- w-icon.w-input__icon.w-input__icon--inner-left(
24
- v-if="innerIconLeft"
25
- tag="label"
26
- :for="`w-input--${_uid}`"
27
- @click="$emit('click:inner-icon-left', $event)") {{ innerIconLeft }}
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
- template(v-if="labelPosition === 'inside' && showLabelInside")
78
- label.w-input__label.w-input__label--inside.w-form-el-shakable(
79
- v-if="$slots.default || label"
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
- :class="labelClasses")
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 : undefined)
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.color]: !!item.color,
233
- [this.SelectionColor]: item._selected && !item.color && this.SelectionColor,
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
- .forEach(val => {
411
- const foundItem = this.listItems.find(item => item._value === val)
412
- if (foundItem) foundItem._selected = true
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
- top: 0;
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
- '--w-menu-bg-color': this.arrow && this.$waveui.colors[this.bgColor || 'white']
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
- top: 0;
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
- top: 0;
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
- top: 0;
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
- top: 0;
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
- :for="`w-select--${_uid}`"
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="!$event && closeMenu()"
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="{ on }")
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
- :id="`w-select--${_uid}`"
51
- :class="{ 'w-select__selection--placeholder': !$scopedSlots.selection && !selectionString && placeholder }"
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 && (this.showMenu = false) /* Will call closeMenu() from w-menu(@close). */"
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
- :for="`w-select--${_uid}`"
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.hasValue && !this.placeholder)
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 && this.inputValue.map(
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.hasValue ? 'filled' : 'empty'}`]: true,
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
- this.onInput(items[index])
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 the item value otherwise.
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] !== undefined ? item[this.itemValueKey] : (item[this.itemLabelKey] !== undefined ? item[this.itemLabelKey] : item)
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'].focus(), 50)
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: 6px;}
512
- &--inner-right {right: 6px;}
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
- top: 50%;
547
- left: 0;
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: 22px;}
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
- // move label with underline style.
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(-160%) scale(0.85);
632
+ transform: translateY(-80%) scale(0.85);
579
633
  }
580
- // Chrome & Safari - Must remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
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(-160%) scale(0.85);
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 remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
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
- background-color: rgba(0, 0, 0, 0.2);
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
- left: 0;
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;
@@ -252,7 +252,7 @@ $disabled-color: #ddd;
252
252
 
253
253
  // The focus outline & ripple on switch activation.
254
254
  &__input:before {
255
- content: "";
255
+ content: '';
256
256
  position: absolute;
257
257
  left: 0;
258
258
  top: 0;