wave-ui 3.13.2 → 3.13.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "3.13.2",
3
+ "version": "3.13.4",
4
4
  "description": "An emerging UI framework for Vue.js (2 & 3) with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
6
  "homepage": "https://antoniandre.github.io/wave-ui",
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- .w-autocomplete(:class="classes" @click="onClick")
2
+ .w-autocomplete(:class="classes" @click="onClick" :style="$attrs.style")
3
3
  template(v-if="selection.length")
4
4
  .w-autocomplete__selection(v-for="(item, i) in selection")
5
5
  slot(name="selection" :item="item" :unselect="i => unselectItem(i)")
@@ -11,7 +11,8 @@
11
11
  input.w-autocomplete__input(
12
12
  ref="input"
13
13
  :value="keywords"
14
- v-on="inputEventListeners")
14
+ v-on="inputEventListeners"
15
+ v-bind="inputAttrs")
15
16
  w-transition-slide-fade
16
17
  ul.w-autocomplete__menu(
17
18
  v-if="menuOpen"
@@ -42,6 +43,7 @@
42
43
  <script>
43
44
  export default {
44
45
  name: 'w-autocomplete',
46
+ inheritAttrs: false, // The attrs should only be added to the input not the wrapper.
45
47
 
46
48
  props: {
47
49
  items: { type: Array, required: true },
@@ -110,12 +112,25 @@ export default {
110
112
  highlightedItemIndex () {
111
113
  if (this.highlightedItem === null) return -1
112
114
  else if (this.highlightedItem === 'extra-item') return this.filteredItems.length
115
+
113
116
  return this.filteredItems.findIndex(item => item.uid === this.highlightedItem)
114
117
  },
115
118
 
119
+ wrapperAttrs () {
120
+ const { style, class: classes } = this.$attrs
121
+ return { style, class: classes }
122
+ },
123
+
124
+ inputAttrs () {
125
+ // Remove class and style which are meant to stay on the wrapper.
126
+ // eslint-disable-next-line no-unused-vars
127
+ const { style, class: classes, ...attrs } = this.$attrs
128
+
129
+ return attrs
130
+ },
131
+
116
132
  inputEventListeners () {
117
133
  return {
118
- ...this.$attrs,
119
134
  input: e => {
120
135
  this.keywords = e.target.value
121
136
  },
@@ -142,7 +157,9 @@ export default {
142
157
  'w-autocomplete--open': this.menuOpen,
143
158
  'w-autocomplete--filled': this.selection.length,
144
159
  'w-autocomplete--has-keywords': this.keywords,
145
- 'w-autocomplete--empty': !this.selection.length && !this.keywords
160
+ 'w-autocomplete--empty': !this.selection.length && !this.keywords,
161
+ // With the inheritAttrs set to false any class on the component would be lost, so add it back.
162
+ [this.$attrs.class]: !!this.$attrs.class
146
163
  }
147
164
  }
148
165
  },
@@ -5,7 +5,7 @@ component.w-button(
5
5
  :href="(route && (externalLink ? route : resolvedRoute)) || null"
6
6
  :class="classes"
7
7
  :disabled="!!disabled || null"
8
- v-on="listeners"
8
+ v-bind="attrs"
9
9
  :style="styles")
10
10
  w-icon(v-if="icon" v-bind="iconProps || {}") {{ icon }}
11
11
  slot(v-else)
@@ -23,6 +23,10 @@ component.w-button(
23
23
 
24
24
  <script>
25
25
  export default {
26
+ // Fully handle the attrs and listeners manually for the case of a router link that has both a
27
+ // route and onClick.
28
+ inheritAttrs: false,
29
+
26
30
  props: {
27
31
  color: { type: String },
28
32
  bgColor: { type: String },
@@ -70,25 +74,21 @@ export default {
70
74
  resolvedRoute () {
71
75
  return this.hasRouter ? this.$router.resolve(this.route).href : this.route
72
76
  },
73
- listeners () {
74
- // Extract the potential class & style from v-on listeners. It will still be added from the
75
- // built-in attributes fallthrough (implicit v-bind="$attrs" when single root node).
76
- const { class: classes, style, ...attrs } = this.$attrs
77
-
77
+ attrs () {
78
78
  // If the button is a router-link, we can't apply events on it since vue-router needs the .native
79
79
  // modifier but it's not available with the v-on directive.
80
80
  // So do a manual router.push if $router is present.
81
- // eslint-disable-next-line multiline-ternary
82
- return this.route && this.hasRouter && !this.forceLink && !this.externalLink ? {
83
- ...attrs,
84
- click: e => {
85
- if (attrs.click) attrs.click(e)
81
+ const attrsForRouterLink = {
82
+ ...this.$attrs,
83
+ onClick: e => {
84
+ if (this.$attrs.onClick) this.$attrs.onClick(e)
86
85
 
87
86
  this.$router.push(this.route)
88
87
  e.stopPropagation() // If going to a route, no need to bubble up the event.
89
88
  e.preventDefault()
90
89
  }
91
- } : attrs
90
+ }
91
+ return this.route && this.hasRouter && !this.forceLink && !this.externalLink ? attrsForRouterLink : this.$attrs
92
92
  },
93
93
  size () {
94
94
  return (
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- component(v-if="tooltip" is="w-tooltip" v-bind="tooltipProps || {}")
2
+ component(v-if="tooltip" is="w-tooltip" v-bind="tooltipProps")
3
3
  template(#activator="{ on }")
4
4
  button-partial(v-bind="buttonProps" v-on="on")
5
5
  slot
@@ -62,7 +62,7 @@ export default {
62
62
 
63
63
  computed: {
64
64
  buttonProps () {
65
- const { tooltip, tooltipProps, ...props } = this.$props
65
+ const { tooltip, tooltipProps = {}, ...props } = this.$props
66
66
  return { ...props, ...this.$attrs }
67
67
  }
68
68
  }
@@ -6,7 +6,8 @@ component(
6
6
  v-model:valid="valid"
7
7
  @reset="$emit('update:modelValue', inputValue = '');$emit('input', '')"
8
8
  :wrap="hasLabel && labelPosition !== 'inside'"
9
- :class="classes")
9
+ :class="classes"
10
+ :style="$attrs.style")
10
11
  input(v-if="type === 'hidden'" type="hidden" :name="name || null" v-model="inputValue")
11
12
 
12
13
  template(v-else)
@@ -31,7 +32,6 @@ component(
31
32
  v-if="type !== 'file'"
32
33
  ref="input"
33
34
  v-model="inputValue"
34
- v-on="listeners"
35
35
  @input="onInput"
36
36
  @focus="onFocus"
37
37
  @blur="onBlur"
@@ -133,6 +133,7 @@ import { reactive } from 'vue'
133
133
  export default {
134
134
  name: 'w-input',
135
135
  mixins: [FormElementMixin],
136
+ inheritAttrs: false, // The attrs should only be added to the input not the wrapper.
136
137
 
137
138
  props: {
138
139
  modelValue: { default: '' },
@@ -186,20 +187,13 @@ export default {
186
187
 
187
188
  computed: {
188
189
  attrs () {
189
- // Keep the `class` attribute bound to the wrapper and not the input.
190
+ // Remove class and style which are meant to stay on the wrapper.
191
+ // Note: in Vue 3 $attrs may contain both HTML attributes AND JS events (onClick, onFocus, etc.).
190
192
  // eslint-disable-next-line no-unused-vars
191
- const { class: classes, ...htmlAttrs } = this.$attrs
193
+ const { class: classes, style, ...attrs } = this.$attrs
192
194
  // Resets the input[type=file] the native HTML way.
193
- if (this.type === 'file' && !this.inputFiles.length) htmlAttrs.value = null
194
- return htmlAttrs
195
- },
196
-
197
- listeners () {
198
- // Remove the events that are fired separately, so they don't fire twice.
199
- // Also remove class and style which are meant to stay on the wrapper.
200
- // eslint-disable-next-line no-unused-vars
201
- const { input, focus, blur, class: classes, style, ...listeners } = this.$attrs
202
- return listeners
195
+ if (this.type === 'file' && !this.inputFiles.length) attrs.value = null
196
+ return attrs
203
197
  },
204
198
 
205
199
  hasValue () {
@@ -265,7 +259,9 @@ export default {
265
259
  'w-input--no-padding': !this.outline && !this.bgColor && !this.shadow && !this.round,
266
260
  'w-input--has-placeholder': this.placeholder,
267
261
  'w-input--inner-icon-left': this.innerIconLeft,
268
- 'w-input--inner-icon-right': this.innerIconRight
262
+ 'w-input--inner-icon-right': this.innerIconRight,
263
+ // With the inheritAttrs set to false any class on the component would be lost, so add it back.
264
+ [this.$attrs.class]: !!this.$attrs.class
269
265
  }
270
266
  },
271
267
 
@@ -5,7 +5,8 @@ component(
5
5
  v-bind="formRegister && { validators, inputValue: isOn, disabled: isDisabled, readonly: isReadonly }"
6
6
  v-model:valid="valid"
7
7
  @reset="$emit('update:modelValue', isOn = null);$emit('input', null)"
8
- :class="classes")
8
+ :class="classes"
9
+ :style="$attrs.style")
9
10
  input(
10
11
  ref="input"
11
12
  :id="`w-switch--${_.uid}`"
@@ -17,6 +18,7 @@ component(
17
18
  :aria-readonly="isReadonly ? 'true' : 'false'"
18
19
  :required="required || null"
19
20
  :tabindex="tabindex || null"
21
+ v-bind="attrs"
20
22
  @change="onInput() /* Edge doesn't fire input on checkbox/radio/select change */"
21
23
  @focus="$emit('focus', $event)"
22
24
  :aria-checked="isOn || 'false'"
@@ -29,7 +31,6 @@ component(
29
31
  slot {{ label }}
30
32
  .w-switch__input(
31
33
  @click="$refs.input.focus();$refs.input.click()"
32
- v-on="listeners"
33
34
  :class="inputClasses")
34
35
  .w-switch__track(v-if="$slots.track")
35
36
  slot(name="track")
@@ -54,6 +55,7 @@ import FormElementMixin from '../mixins/form-elements'
54
55
  export default {
55
56
  name: 'w-switch',
56
57
  mixins: [FormElementMixin],
58
+ inheritAttrs: false, // The attrs should only be added to the input not the wrapper.
57
59
 
58
60
  props: {
59
61
  modelValue: { default: false }, // v-model.
@@ -84,12 +86,12 @@ export default {
84
86
  },
85
87
 
86
88
  computed: {
87
- listeners () {
88
- // Remove the events that are fired separately, so they don't fire twice.
89
- // Also remove class and style which are meant to stay on the wrapper.
89
+ attrs () {
90
+ // Remove class and style which are meant to stay on the wrapper.
91
+ // Note: in Vue 3 $attrs may contain both HTML attributes AND JS events (onClick, onFocus, etc.).
90
92
  // eslint-disable-next-line no-unused-vars
91
- const { click, class: classes, style, ...listeners } = this.$attrs
92
- return listeners
93
+ const { class: classes, style, ...attrs } = this.$attrs
94
+ return attrs
93
95
  },
94
96
  hasLabel () {
95
97
  return this.label || this.$slots.default
@@ -106,7 +108,9 @@ export default {
106
108
  'w-switch--loading': this.loading,
107
109
  'w-switch--rippled': this.ripple.end,
108
110
  'w-switch--dark': this.dark,
109
- 'w-switch--light': this.light
111
+ 'w-switch--light': this.light,
112
+ // With the inheritAttrs set to false any class on the component would be lost, so add it back.
113
+ [this.$attrs.class]: !!this.$attrs.class
110
114
  }
111
115
  },
112
116
  inputClasses () {
@@ -6,7 +6,8 @@ component(
6
6
  v-model:valid="valid"
7
7
  :wrap="hasLabel && labelPosition !== 'inside'"
8
8
  @reset="$emit('update:modelValue', inputValue = '');$emit('input', '')"
9
- :class="classes")
9
+ :class="classes"
10
+ :style="$attrs.style")
10
11
  //- Left label.
11
12
  template(v-if="labelPosition === 'left'")
12
13
  label.w-textarea__label.w-textarea__label--left.w-form-el-shakable(
@@ -26,7 +27,7 @@ component(
26
27
  textarea.w-textarea__textarea(
27
28
  ref="textarea"
28
29
  v-model="inputValue"
29
- v-on="listeners"
30
+ v-bind="attrs"
30
31
  @input="onInput"
31
32
  @focus="onFocus"
32
33
  @blur="onBlur"
@@ -71,6 +72,7 @@ import FormElementMixin from '../mixins/form-elements'
71
72
  export default {
72
73
  name: 'w-textarea',
73
74
  mixins: [FormElementMixin],
75
+ inheritAttrs: false, // The attrs should only be added to the textarea not the wrapper.
74
76
 
75
77
  props: {
76
78
  modelValue: { default: '' },
@@ -111,12 +113,12 @@ export default {
111
113
  },
112
114
 
113
115
  computed: {
114
- listeners () {
115
- // Remove the events that are fired separately, so they don't fire twice.
116
- // Also remove class and style which are meant to stay on the wrapper.
116
+ attrs () {
117
+ // Remove class and style which are meant to stay on the wrapper.
118
+ // Note: in Vue 3 $attrs may contain both HTML attributes AND JS events (onClick, onFocus, etc.).
117
119
  // eslint-disable-next-line no-unused-vars
118
- const { input, focus, blur, class: classes, style, ...listeners } = this.$attrs
119
- return listeners
120
+ const { class: classes, style, ...attrs } = this.$attrs
121
+ return attrs
120
122
  },
121
123
  hasValue () {
122
124
  return this.inputValue || this.inputValue === 0
@@ -141,7 +143,9 @@ export default {
141
143
  'w-textarea--no-padding': !this.outline && !this.bgColor && !this.shadow,
142
144
  'w-textarea--has-placeholder': this.placeholder,
143
145
  'w-textarea--inner-icon-left': this.innerIconLeft,
144
- 'w-textarea--inner-icon-right': this.innerIconRight
146
+ 'w-textarea--inner-icon-right': this.innerIconRight,
147
+ // With the inheritAttrs set to false any class on the component would be lost, so add it back.
148
+ [this.$attrs.class]: !!this.$attrs.class
145
149
  }
146
150
  },
147
151
  inputWrapClasses () {
@@ -144,10 +144,7 @@ export default class WaveUI {
144
144
  }
145
145
 
146
146
  constructor (app, options = {}) {
147
- if (WaveUI.#registered) {
148
- console.warn('Wave UI is already instantiated.')
149
- return
150
- }
147
+ if (WaveUI.#registered) return // May happen with SSR.
151
148
 
152
149
  this.$waveui._notificationManager = new NotificationManager()
153
150