wave-ui 3.7.1 → 3.8.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.
@@ -10,7 +10,7 @@ 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
 
@@ -24,10 +24,9 @@ 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
- v-on="on"
31
30
  @click="!isDisabled && !isReadonly && onInputFieldClick()"
32
31
  role="button"
33
32
  aria-haspopup="listbox"
@@ -44,17 +43,11 @@ component(
44
43
  slot(name="selection" :item="multiple ? inputValue : inputValue[0]")
45
44
  .w-select__selection(
46
45
  ref="selection-input"
47
- :contenteditable="isDisabled || isReadonly ? 'false' : 'true'"
48
46
  @focus="!isDisabled && !isReadonly && onFocus($event)"
49
47
  @blur="onBlur"
50
48
  @keydown="!isDisabled && !isReadonly && onKeydown($event)"
51
- :id="`w-select--${_.uid}`"
52
- :class="{ 'w-select__selection--placeholder': !$slots.selection && !selectionString && placeholder }"
53
- :disabled="isDisabled || null"
54
- readonly
55
- aria-readonly="true"
56
- :tabindex="tabindex || null"
57
- v-html="$slots.selection ? '' : selectionString || placeholder")
49
+ v-bind="selectionAttributes"
50
+ v-html="selectionHtml")
58
51
  //- For standard HTML form submission.
59
52
  input(
60
53
  v-for="(val, i) in (inputValue.length ? inputValue : [{}])"
@@ -65,7 +58,6 @@ component(
65
58
  template(v-if="labelPosition === 'inside' && showLabelInside")
66
59
  label.w-select__label.w-select__label--inside.w-form-el-shakable(
67
60
  v-if="$slots.default || label"
68
- :for="`w-select--${_.uid}`"
69
61
  :class="labelClasses")
70
62
  slot {{ label }}
71
63
  w-icon.w-select__icon.w-select__icon--inner-right(
@@ -79,7 +71,7 @@ component(
79
71
  @item-click="$emit('item-click', $event)"
80
72
  @item-select="onListItemSelect"
81
73
  @keydown:enter="noUnselect && !multiple && closeMenu()"
82
- @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). */"
83
75
  :items="selectItems"
84
76
  :multiple="multiple"
85
77
  arrows-navigation
@@ -90,7 +82,7 @@ component(
90
82
  :item-color-key="itemColorKey"
91
83
  role="listbox"
92
84
  tabindex="-1")
93
- template(v-for="i in items.length" v-slot:[`item.${i}`]="{ item, selected, index }")
85
+ template(v-for="i in items.length" #[`item.${i}`]="{ item, selected, index }")
94
86
  slot(
95
87
  v-if="$slots[`item.${i}`] && $slots[`item.${i}`](item, selected, index)"
96
88
  :name="`item.${i}`"
@@ -103,7 +95,7 @@ component(
103
95
  template(v-if="labelPosition === 'right'")
104
96
  label.w-select__label.w-select__label--right.w-form-el-shakable(
105
97
  v-if="$slots.default || label"
106
- :for="`w-select--${_.uid}`"
98
+ @click="$refs['selection-input'].click()"
107
99
  :class="labelClasses")
108
100
  slot {{ label }}
109
101
  </template>
@@ -181,20 +173,32 @@ export default {
181
173
  return obj
182
174
  })
183
175
  },
184
- hasValue () {
185
- return Array.isArray(this.inputValue) ? this.inputValue.length : (this.inputValue !== null)
186
- },
187
176
  hasLabel () {
188
177
  return this.label || this.$slots.default
189
178
  },
190
179
  showLabelInside () {
191
- return !this.staticLabel || (!this.hasValue && !this.placeholder)
180
+ return !this.staticLabel || (!this.inputValue.length && !this.placeholder)
181
+ },
182
+ selectionAttributes () {
183
+ return {
184
+ class: { 'w-select__selection--placeholder': !this.$slots.selection && !this.selectionString && this.placeholder },
185
+ disabled: this.isDisabled || null,
186
+ readonly: true,
187
+ ariareadonly: 'true',
188
+ tabindex: this.tabindex ?? null,
189
+ contenteditable: this.isDisabled || this.isReadonly ? 'false' : 'true'
190
+ }
192
191
  },
193
192
  selectionString () {
194
- return this.inputValue && this.inputValue.map(
193
+ return this.inputValue.map(
195
194
  item => item[this.itemValueKey] !== undefined ? item[this.itemLabelKey] : (item[this.itemLabelKey] ?? item)
196
195
  ).join(', ')
197
196
  },
197
+ selectionHtml () {
198
+ if (!this.inputValue.length) return this.placeholder || ''
199
+ if (this.$slots.selection) return ''
200
+ return this.selectionString
201
+ },
198
202
  classes () {
199
203
  return {
200
204
  'w-select': true,
@@ -203,7 +207,7 @@ export default {
203
207
  'w-select--disabled': this.isDisabled,
204
208
  'w-select--fit-to-content': this.fitToContent,
205
209
  'w-select--readonly': this.isReadonly,
206
- [`w-select--${this.hasValue ? 'filled' : 'empty'}`]: true,
210
+ [`w-select--${this.inputValue.length ? 'filled' : 'empty'}`]: true,
207
211
  'w-select--focused': (this.isFocused || this.showMenu) && !this.isReadonly,
208
212
  'w-select--floating-label': this.hasLabel && this.labelPosition === 'inside' && !this.staticLabel,
209
213
  'w-select--no-padding': !this.outline && !this.bgColor && !this.shadow && !this.round,
@@ -274,7 +278,25 @@ export default {
274
278
  index = (index + items.length + direction) % items.length
275
279
  }
276
280
 
277
- this.onInput(items[index])
281
+ // If the current item is disabled, find the next one enabled (forward or backward).
282
+ let allItemsAreDisabled = false
283
+ if (items[index].disabled) {
284
+ const direction = e.keyCode === 38 ? -1 : 1 // Prev or next.
285
+
286
+ // Modulo to prevent out of range; + items.length to also work with negative values.
287
+ let newIndex = (index + direction + items.length) % items.length
288
+ const itemsCount = items.length
289
+ let loop = 0 // While-safety: will always end at least after 1 full array cycle.
290
+ while (loop < itemsCount && items[newIndex].disabled) {
291
+ // Circle through the array of items forward or backward, and reloop when out of range.
292
+ newIndex = (newIndex + items.length + direction) % items.length
293
+ loop++
294
+ }
295
+ if (loop >= itemsCount) allItemsAreDisabled = true
296
+ index = newIndex
297
+ }
298
+
299
+ if (!allItemsAreDisabled) this.onInput(items[index])
278
300
  }
279
301
  }
280
302
  },
@@ -283,7 +305,7 @@ export default {
283
305
  onInput (items) {
284
306
  this.inputValue = items === null ? [] : (this.multiple ? items : [items])
285
307
  // Return the original items when returnObject is true (no `value` if there wasn't),
286
- // or the the item value otherwise.
308
+ // or the item value otherwise.
287
309
  items = this.inputValue.map(item => this.returnObject ? this.items[item.index] : item.value)
288
310
 
289
311
  // Emit the selection to the v-model.
@@ -292,6 +314,7 @@ export default {
292
314
  this.$emit('update:modelValue', selection)
293
315
  this.$emit('input', selection)
294
316
  },
317
+
295
318
  onInputFieldClick () {
296
319
  if (this.showMenu) this.showMenu = false // Will call `closeMenu()` from w-menu(@close).
297
320
  else this.openMenu()
@@ -324,7 +347,7 @@ export default {
324
347
  return items.map(item => {
325
348
  let value = item
326
349
  if (item && typeof item === 'object') { // `null` is also an object!
327
- value = item[this.itemValueKey] !== undefined ? item[this.itemValueKey] : (item[this.itemLabelKey] !== undefined ? item[this.itemLabelKey] : item)
350
+ value = item[this.itemValueKey] ?? item[this.itemLabelKey] ?? item
328
351
  }
329
352
 
330
353
  return this.selectItems[allValues.indexOf(value)]
@@ -459,6 +482,9 @@ export default {
459
482
  align-items: center;
460
483
  cursor: pointer;
461
484
  caret-color: transparent;
485
+ border-radius: inherit;
486
+
487
+ &--placeholder {color: #888;}
462
488
 
463
489
  .w-select__selection-slot + & {
464
490
  position: absolute;
@@ -485,8 +511,6 @@ export default {
485
511
  }
486
512
 
487
513
  .w-select--readonly & {cursor: auto;}
488
-
489
- &--placeholder {color: #888;}
490
514
  }
491
515
 
492
516
  &__selection-slot {
@@ -512,8 +536,8 @@ export default {
512
536
  -webkit-tap-highlight-color: transparent;
513
537
  }
514
538
 
515
- &--inner-left {left: 6px;}
516
- &--inner-right {right: 6px;}
539
+ &--inner-left {left: $base-increment;}
540
+ &--inner-right {right: $base-increment;}
517
541
  .w-select--no-padding &--inner-left {left: 1px;}
518
542
  .w-select--no-padding &--inner-right {right: 1px;}
519
543
 
@@ -548,17 +572,15 @@ export default {
548
572
 
549
573
  &__label--inside {
550
574
  position: absolute;
551
- top: 50%;
552
- left: 0;
553
- right: 0;
575
+ inset: 0 0 auto;
576
+ min-height: inherit;
554
577
  white-space: nowrap;
555
578
  // Use margin instead of padding as the scale transformation below decreases the real padding
556
579
  // size and misaligns the label.
557
580
  margin-left: 2 * $base-increment;
558
- transform: translateY(-50%);
559
581
  pointer-events: none;
560
582
 
561
- .w-select--inner-icon-right & {padding-right: 22px;}
583
+ .w-select--inner-icon-right & {padding-right: 26px;}
562
584
 
563
585
  .w-select--no-padding & {
564
586
  left: 0;
@@ -575,28 +597,19 @@ export default {
575
597
  transition: $transition-duration ease;
576
598
  }
577
599
 
578
- // move label with underline style.
579
- .w-select--focused.w-select--floating-label &,
600
+ // Move label with underline style.
580
601
  .w-select--open.w-select--floating-label &,
581
602
  .w-select--filled.w-select--floating-label &,
582
603
  .w-select--has-placeholder.w-select--floating-label & {
583
- transform: translateY(-160%) scale(0.85);
604
+ transform: translateY(-80%) scale(0.85);
584
605
  }
585
- // Chrome & Safari - Must remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
606
+ // Chrome & Safari - Must stay a separated rule or Firefox discards the whole rule seeing -webkit-.
586
607
  .w-select--floating-label .w-select__select:-webkit-autofill & {
587
- transform: translateY(-160%) scale(0.85);
588
- }
589
- // Move label with outline style or with shadow.
590
- .w-select--focused.w-select--floating-label .w-select__selection-wrap--box &,
591
- .w-select--open.w-select--floating-label .w-select__selection-wrap--box &,
592
- .w-select--filled.w-select--floating-label .w-select__selection-wrap--box &,
593
- .w-select--has-placeholder.w-select--floating-label .w-select__selection-wrap--box & {
594
- transform: translateY(-180%) scale(0.85);
608
+ transform: translateY(-80%) scale(0.85);
595
609
  }
596
- .w-select--focused.w-select--floating-label.w-select--inner-icon-left &,
597
610
  .w-select--open.w-select--floating-label.w-select--inner-icon-left &,
598
611
  .w-select--filled.w-select--floating-label.w-select--inner-icon-left & {left: 0;}
599
- // Chrome & Safari - Must remain in a separated rule as Firefox discard the whole rule seeing -webkit-.
612
+ // Chrome & Safari - Must stay a separated rule or Firefox discards the whole rule seeing -webkit-.
600
613
  .w-select--floating-label.w-select--inner-icon-left .w-select__select:-webkit-autofill & {left: 0;}
601
614
  }
602
615
 
@@ -42,7 +42,6 @@ component(
42
42
  template(v-if="labelPosition === 'inside' && showLabelInside")
43
43
  label.w-textarea__label.w-textarea__label--inside.w-form-el-shakable(
44
44
  v-if="$slots.default || label"
45
- :for="`w-textarea--${_.uid}`"
46
45
  :class="labelClasses")
47
46
  slot {{ label }}
48
47
  w-icon.w-textarea__icon.w-textarea__icon--inner-right(