wave-ui 2.28.1 → 2.29.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "2.28.1",
3
+ "version": "2.29.0",
4
4
  "description": "An emerging UI framework for Vue.js & Vue 3 with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
6
  "main": "./dist/wave-ui.umd.js",
@@ -43,24 +43,24 @@
43
43
  "*.vue"
44
44
  ],
45
45
  "devDependencies": {
46
- "@babel/core": "^7.16.0",
47
- "@babel/eslint-parser": "^7.16.3",
48
- "@babel/plugin-proposal-class-properties": "^7.16.0",
46
+ "@babel/core": "^7.16.5",
47
+ "@babel/eslint-parser": "^7.16.5",
48
+ "@babel/plugin-proposal-class-properties": "^7.16.5",
49
49
  "@mdi/font": "^5.9.55",
50
- "@vitejs/plugin-vue": "^1.9.4",
50
+ "@vitejs/plugin-vue": "^1.10.2",
51
51
  "@vue/compiler-sfc": "3.1.5",
52
- "autoprefixer": "^10.4.0",
52
+ "autoprefixer": "^10.4.1",
53
53
  "axios": "^0.21.4",
54
54
  "eslint": "^7.32.0",
55
55
  "font-awesome": "^4.7.0",
56
- "gsap": "^3.8.0",
56
+ "gsap": "^3.9.1",
57
57
  "ionicons": "^4.6.3",
58
58
  "material-design-icons": "^3.0.1",
59
59
  "rollup-plugin-delete": "^2.0.0",
60
- "sass": "^1.43.4",
60
+ "sass": "^1.45.1",
61
61
  "simple-syntax-highlighter": "^2.2.0",
62
62
  "splitpanes": "^3.0.6",
63
- "vite": "^2.6.14",
63
+ "vite": "^2.7.9",
64
64
  "vite-plugin-pug": "^0.3.0",
65
65
  "vue": "^3.2.26",
66
66
  "vue-cal": "^4.2.0",
@@ -19,7 +19,8 @@
19
19
  :tabindex="-1"
20
20
  text
21
21
  @keypress.stop
22
- @click.stop="!item._disabled && toggleItem(item, $event)")
22
+ @click.stop="!item._disabled && toggleItem(item, $event)"
23
+ :class="{ 'w-accordion__expand-icon--expanded': item._expanded }")
23
24
  //- Title.
24
25
  slot(
25
26
  v-if="$slots[`item-title.${item.id || i + 1}`]"
@@ -34,7 +35,8 @@
34
35
  :icon="(item._expanded && collapseIcon) || expandIcon"
35
36
  text
36
37
  @keypress.stop
37
- @click.stop="!item._disabled && toggleItem(item, $event)")
38
+ @click.stop="!item._disabled && toggleItem(item, $event)"
39
+ :class="{ 'w-accordion__expand-icon--expanded': item._expanded }")
38
40
  //- Content.
39
41
  w-transition-expand(y)
40
42
  .w-accordion__item-content(v-if="item._expanded" :class="contentClass")
@@ -148,8 +150,8 @@ export default {
148
150
  margin-right: $base-increment;
149
151
 
150
152
  .w-accordion--rotate-icon & {@include default-transition;}
151
- .w-accordion--rotate-icon .w-accordion__item--expanded & {transform: rotate(-180deg);}
152
- .w-accordion--rotate-icon.w-accordion--icon-right .w-accordion__item--expanded & {transform: rotate(180deg);}
153
+ &--expanded {transform: rotate(-180deg);}
154
+ .w-accordion--icon-right &--expanded {transform: rotate(180deg);}
153
155
 
154
156
  .w-icon:before {font-size: 1.1em;}
155
157
  }
@@ -40,7 +40,7 @@ export default {
40
40
  classes () {
41
41
  return {
42
42
  'd-block': this.block,
43
- 'row': this.row,
43
+ row: this.row,
44
44
  'align-center': this.alignCenter,
45
45
  'align-end': this.alignEnd,
46
46
  'justify-center': this.justifyCenter,
@@ -26,6 +26,7 @@ export default {
26
26
  justifyEnd: { type: Boolean },
27
27
  justifySpaceBetween: { type: Boolean },
28
28
  justifySpaceAround: { type: Boolean },
29
+ justifySpaceEvenly: { type: Boolean },
29
30
  basisZero: { type: Boolean },
30
31
  gap: { type: Number, default: 0 }
31
32
  },
@@ -48,6 +49,7 @@ export default {
48
49
  'justify-end': this.justifyEnd,
49
50
  'justify-space-between': this.justifySpaceBetween,
50
51
  'justify-space-around': this.justifySpaceAround,
52
+ 'justify-space-evenly': this.justifySpaceEvenly,
51
53
  'basis-zero': this.basisZero,
52
54
  [`w-flex--gap${this.gap}`]: this.gap
53
55
  }
@@ -23,8 +23,10 @@ component(
23
23
  tag="label"
24
24
  :for="`w-input--${_.uid}`"
25
25
  @click="$emit('click:inner-icon-left', $event)") {{ innerIconLeft }}
26
+ //- All types of input except file.
26
27
  input.w-input__input(
27
28
  v-if="type !== 'file'"
29
+ ref="input"
28
30
  v-model="inputValue"
29
31
  v-on="listeners"
30
32
  @input="onInput"
@@ -45,8 +47,10 @@ component(
45
47
  :required="required || null"
46
48
  :tabindex="tabindex || null"
47
49
  v-bind="attrs")
48
- template(v-if="type === 'file'")
50
+ //- Input type file.
51
+ template(v-else)
49
52
  input(
53
+ ref="input"
50
54
  :id="`w-input--${_.uid}`"
51
55
  type="file"
52
56
  :name="name || null"
@@ -160,7 +164,8 @@ export default {
160
164
  inputNumberError: false,
161
165
  isFocused: false,
162
166
  inputFiles: [], // For input type file.
163
- fileReader: null // For input type file.
167
+ fileReader: null, // For input type file.
168
+ isAutofilled: false
164
169
  }
165
170
  },
166
171
 
@@ -186,6 +191,7 @@ export default {
186
191
  hasValue () {
187
192
  return (
188
193
  this.inputValue ||
194
+ this.inputValue === 0 ||
189
195
  ['date', 'time'].includes(this.type) ||
190
196
  (this.type === 'number' && this.inputNumberError) ||
191
197
  (this.type === 'file' && this.inputFiles.length)
@@ -206,7 +212,7 @@ export default {
206
212
  'w-input--file': this.type === 'file',
207
213
  'w-input--disabled': this.isDisabled,
208
214
  'w-input--readonly': this.isReadonly,
209
- [`w-input--${this.hasValue ? 'filled' : 'empty'}`]: true,
215
+ [`w-input--${this.hasValue || this.isAutofilled ? 'filled' : 'empty'}`]: true,
210
216
  'w-input--focused': this.isFocused && !this.isReadonly,
211
217
  'w-input--dark': this.dark,
212
218
  'w-input--floating-label': this.hasLabel && this.labelPosition === 'inside' && !this.staticLabel,
@@ -293,9 +299,19 @@ export default {
293
299
  }
294
300
  },
295
301
 
302
+ mounted () {
303
+ // On page load, check if the field is autofilled by the browser.
304
+ // 20211229. Only a problem on Chrome. Firefox ok, Safari always prompts before filling up.
305
+ setTimeout(() => {
306
+ if (this.$refs.input.matches(':-webkit-autofill')) this.isAutofilled = true
307
+ }, 400) // Can't be less than 350: time for the browser to autofill.
308
+ },
309
+
296
310
  watch: {
297
311
  modelValue (value) {
298
312
  this.inputValue = value
313
+ // When clearing the field value, also reset the isAutofilled var for the CSS class.
314
+ if (!value && value !== 0) this.isAutofilled = false
299
315
  }
300
316
  }
301
317
  }
@@ -117,25 +117,29 @@ export default {
117
117
  },
118
118
 
119
119
  // DOM element to attach menu to.
120
+ // ! \ This computed uses the DOM - NO SSR (only trigger from beforeMount and later).
120
121
  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'
122
+ const defaultTarget = '.w-app'
123
+
124
+ let target = this.detachTo || defaultTarget
125
+ if (target === true) target = defaultTarget
126
+ else if (target && !['object', 'string'].includes(typeof target)) target = defaultTarget
124
127
  else if (typeof target === 'object' && !target.nodeType) {
125
- target = '.w-app'
128
+ target = defaultTarget
126
129
  consoleWarn('Invalid node provided in w-menu `detach-to`. Falling back to .w-app.', this)
127
130
  }
128
131
  if (typeof target === 'string') target = document.querySelector(target)
129
132
 
130
133
  if (!target) {
131
- consoleWarn(`Unable to locate ${this.detachTo ? `target ${this.detachTo}` : '.w-app'}`, this)
132
- target = document.querySelector('.w-app')
134
+ consoleWarn(`Unable to locate ${this.detachTo ? `target ${this.detachTo}` : defaultTarget}`, this)
135
+ target = document.querySelector(defaultTarget)
133
136
  }
134
137
 
135
138
  return target
136
139
  },
137
140
 
138
141
  // DOM element that will receive the menu.
142
+ // ! \ This computed uses the DOM - NO SSR (only trigger from beforeMount and later).
139
143
  menuParentEl () {
140
144
  return this.detachToTarget
141
145
  },
@@ -197,7 +201,7 @@ export default {
197
201
  }
198
202
  },
199
203
 
200
- // The floatting menu styles.
204
+ // The floating menu styles.
201
205
  styles () {
202
206
  return {
203
207
  zIndex: this.zIndex || this.zIndex === 0 || (this.overlay && !this.zIndex && 200) || null,
@@ -227,8 +231,10 @@ export default {
227
231
  }, 10)
228
232
  }
229
233
  }
230
-
231
- if ('ontouchstart' in window) handlers.click = this.toggleMenu
234
+ // Check the window exists: SSR-proof.
235
+ if (typeof window !== 'undefined' && 'ontouchstart' in window) {
236
+ handlers.click = this.toggleMenu
237
+ }
232
238
  }
233
239
  else handlers = { click: this.toggleMenu }
234
240
  return handlers
@@ -236,6 +242,7 @@ export default {
236
242
  },
237
243
 
238
244
  methods: {
245
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
239
246
  toggleMenu (e) {
240
247
  let shouldShowMenu = this.menuVisible
241
248
  if ('ontouchstart' in window && this.showOnHover && e.type === 'click') {
@@ -263,6 +270,7 @@ export default {
263
270
  else this.closeMenu()
264
271
  },
265
272
 
273
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
266
274
  async openMenu (e) {
267
275
  this.menuVisible = true
268
276
  await this.insertMenu()
@@ -289,6 +297,7 @@ export default {
289
297
  * - click of activator
290
298
  * - hover outside if showOnHover
291
299
  * - click inside menu if hideOnMenuClick.
300
+ * / ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
292
301
  *
293
302
  * @param {Boolean} force when showOnHover is set to true, hovering menu should keep it open.
294
303
  * But if hideOnMenuClick is also set to true, this should force close
@@ -312,6 +321,7 @@ export default {
312
321
  window.removeEventListener('resize', this.onResize)
313
322
  },
314
323
 
324
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
315
325
  onOutsideMousedown (e) {
316
326
  if (!this.menuEl.contains(e.target) && !this.activatorEl.contains(e.target)) {
317
327
  this.$emit('update:modelValue', (this.menuVisible = false))
@@ -327,6 +337,7 @@ export default {
327
337
  this.computeMenuPosition()
328
338
  },
329
339
 
340
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
330
341
  getCoordinates (e) {
331
342
  // Get the activator coordinates relative to window.
332
343
  const { top, left, width, height } = (e ? e.target : this.activatorEl).getBoundingClientRect()
@@ -346,6 +357,7 @@ export default {
346
357
  return coords
347
358
  },
348
359
 
360
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
349
361
  computeMenuPosition (e) {
350
362
  // Get the activator coordinates.
351
363
  let { top, left, width, height } = this.getCoordinates(e)
@@ -116,7 +116,7 @@ export default {
116
116
  return listeners
117
117
  },
118
118
  hasValue () {
119
- return this.inputValue
119
+ return this.inputValue || this.inputValue === 0
120
120
  },
121
121
  hasLabel () {
122
122
  return this.label || this.$slots.default
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- .w-tooltip-wrap(ref="wrapper" :class="{ 'w-tooltip-wrap--attached': !detachTo }")
2
+ .w-tooltip-wrap(:class="{ 'w-tooltip-wrap--attached': !detachTo }")
3
3
  slot(name="activator" :on="eventHandlers")
4
4
  transition(:name="transitionName" appear)
5
5
  //- In Vue 3, a ref in a transition doesn't stay in $refs, it must be set as a function.
@@ -9,11 +9,7 @@
9
9
  v-show="showTooltip"
10
10
  :class="classes"
11
11
  :style="styles")
12
- //- When there is a bg color, another div wrapper is needed for the triangle
13
- //- to inherit the current color.
14
- div(v-if="bgColor" :class="color")
15
- slot
16
- slot(v-else)
12
+ slot
17
13
  </template>
18
14
 
19
15
  <script>
@@ -81,27 +77,32 @@ export default {
81
77
  return this.transition || `w-tooltip-slide-fade-${direction}`
82
78
  },
83
79
 
80
+ // DOM element to attach tooltip to.
81
+ // ! \ This computed uses the DOM - NO SSR (only trigger from beforeMount and later).
84
82
  detachToTarget () {
85
- let target = this.detachTo || '.w-app'
86
- if (target === true) target = '.w-app'
87
- else if (target && !['object', 'string'].includes(typeof target)) target = '.w-app'
83
+ const defaultTarget = '.w-app'
84
+
85
+ let target = this.detachTo || defaultTarget
86
+ if (target === true) target = defaultTarget
87
+ else if (target && !['object', 'string'].includes(typeof target)) target = defaultTarget
88
88
  else if (typeof target === 'object' && !target.nodeType) {
89
- target = '.w-app'
89
+ target = defaultTarget
90
90
  consoleWarn('Invalid node provided in w-tooltip `attach-to`. Falling back to .w-app.', this)
91
91
  }
92
92
  if (typeof target === 'string') target = document.querySelector(target)
93
93
 
94
94
  if (!target) {
95
- consoleWarn(`Unable to locate ${this.detachTo ? `target ${this.detachTo}` : '.w-app'}`, this)
96
- target = document.querySelector('.w-app')
95
+ consoleWarn(`Unable to locate ${this.detachTo ? `target ${this.detachTo}` : defaultTarget}`, this)
96
+ target = document.querySelector(defaultTarget)
97
97
  }
98
98
 
99
99
  return target
100
100
  },
101
101
 
102
102
  // DOM element that will receive the tooltip.
103
+ // ! \ This computed uses the DOM - NO SSR (only trigger from beforeMount and later).
103
104
  tooltipParentEl () {
104
- return this.detachTo ? this.detachToTarget : this.$refs.wrapper
105
+ return this.detachTo ? this.detachToTarget : this.$el
105
106
  },
106
107
 
107
108
  position () {
@@ -146,8 +147,8 @@ export default {
146
147
 
147
148
  classes () {
148
149
  return {
149
- [this.color]: !this.bgColor,
150
- [`${this.bgColor} ${this.bgColor}--bg`]: this.bgColor,
150
+ [this.color]: this.color,
151
+ [`${this.bgColor}--bg`]: this.bgColor,
151
152
  ...this.tooltipClasses,
152
153
  [`w-tooltip--${this.position}`]: true,
153
154
  'w-tooltip--tile': this.tile,
@@ -160,11 +161,13 @@ export default {
160
161
  }
161
162
  },
162
163
 
164
+ // The tooltip styles.
163
165
  styles () {
164
166
  return {
165
167
  zIndex: this.zIndex || this.zIndex === 0 || null,
166
- top: `${~~this.tooltipCoordinates.top}px`,
167
- left: `${~~this.tooltipCoordinates.left}px`
168
+ top: (this.tooltipCoordinates.top && `${~~this.tooltipCoordinates.top}px`) || null,
169
+ left: (this.tooltipCoordinates.left && `${~~this.tooltipCoordinates.left}px`) || null,
170
+ '--w-tooltip-bg-color': this.$waveui.colors[this.bgColor || 'white']
168
171
  }
169
172
  },
170
173
 
@@ -179,16 +182,18 @@ export default {
179
182
  mouseleave: this.toggle
180
183
  }
181
184
 
182
- if ('ontouchstart' in window) handlers.click = this.toggle
185
+ // Check the window exists: SSR-proof.
186
+ if (typeof window !== 'undefined' && 'ontouchstart' in window) handlers.click = this.toggle
183
187
  }
184
188
  return handlers
185
189
  }
186
190
  },
187
191
 
188
192
  methods: {
193
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
189
194
  toggle (e) {
190
195
  let shouldShowTooltip = this.showTooltip
191
- if ('ontouchstart' in window) {
196
+ if (typeof window !== 'undefined' && 'ontouchstart' in window) {
192
197
  if (e.type === 'click') shouldShowTooltip = !shouldShowTooltip
193
198
  }
194
199
  else if (e.type === 'click' && this.showOnClick) shouldShowTooltip = !shouldShowTooltip
@@ -216,6 +221,7 @@ export default {
216
221
  }
217
222
  },
218
223
 
224
+ // ! \ This function uses the DOM - NO SSR (only trigger from beforeMount and later).
219
225
  getCoordinates () {
220
226
  const { top, left, width, height } = this.activatorEl.getBoundingClientRect()
221
227
  let coords = { top, left, width, height }
@@ -273,7 +279,7 @@ export default {
273
279
  },
274
280
 
275
281
  insertTooltip () {
276
- const wrapper = this.$refs.wrapper
282
+ const wrapper = this.$el
277
283
 
278
284
  // Unwrap the activator element.
279
285
  wrapper.parentNode.insertBefore(this.activatorEl, wrapper)
@@ -290,7 +296,7 @@ export default {
290
296
  },
291
297
 
292
298
  mounted () {
293
- this.activatorEl = this.$refs.wrapper.firstElementChild
299
+ this.activatorEl = this.$el.firstElementChild
294
300
  if (this.detachTo) this.insertTooltip()
295
301
 
296
302
  if (this.modelValue) this.toggle({ type: 'click', target: this.activatorEl })
@@ -366,94 +372,17 @@ export default {
366
372
 
367
373
  &--custom-transition {transform: none;}
368
374
 
369
- &:after {
370
- content: '';
371
- position: absolute;
372
- width: 0;
373
- height: 0;
374
- border: 6px solid transparent;
375
- }
376
- &--top:after {
377
- top: 100%;
378
- left: 50%;
379
- border-top-color: $tooltip-bg-color;
380
- transform: translateX(-50%);
381
- margin-top: 1px;
382
- }
383
- &--bottom:after {
384
- bottom: 100%;
385
- left: 50%;
386
- border-bottom-color: $tooltip-bg-color;
387
- transform: translateX(-50%);
388
- margin-bottom: 1px;
389
- }
390
- &--left:after {
391
- left: 100%;
392
- top: 50%;
393
- border-left-color: $tooltip-bg-color;
394
- transform: translateY(-50%);
395
- margin-left: 1px;
396
- }
397
- &--right:after {
398
- right: 100%;
399
- top: 50%;
400
- border-right-color: $tooltip-bg-color;
401
- transform: translateY(-50%);
402
- margin-right: 1px;
403
- }
404
-
405
375
  // Tooltip without border.
406
376
  // --------------------------------------------------------
407
- &--no-border.w-tooltip--top:after {margin-top: -1px;border-top-color: inherit;}
408
- &--no-border.w-tooltip--bottom:after {margin-bottom: -1px;border-bottom-color: inherit;}
409
- &--no-border.w-tooltip--left:after {margin-left: -1px;border-left-color: inherit;}
410
- &--no-border.w-tooltip--right:after {margin-right: -1px;border-right-color: inherit;}
377
+ &--no-border {
378
+ @include triangle(var(--w-tooltip-bg-color), '.w-tooltip', 7px, 0);
379
+ }
411
380
 
412
381
  // Tooltip with border.
413
382
  // --------------------------------------------------------
414
- &:not(&--no-border).w-tooltip--top:after {margin-top: -1px;}
415
- &:not(&--no-border).w-tooltip--bottom:after {margin-bottom: -1px;}
416
- &:not(&--no-border).w-tooltip--left:after {margin-left: -1px;}
417
- &:not(&--no-border).w-tooltip--right:after {margin-right: -1px;}
418
-
419
383
  &:not(&--no-border) {
420
- &:before {
421
- content: '';
422
- position: absolute;
423
- width: 0;
424
- height: 0;
425
- border: 7px solid transparent;
426
- }
427
- &.w-tooltip--top:before {
428
- top: 100%;
429
- left: 50%;
430
- border-top-color: inherit;
431
- transform: translateX(-50%);
432
- margin-top: 0;
433
- }
434
- &.w-tooltip--bottom:before {
435
- bottom: 100%;
436
- left: 50%;
437
- border-bottom-color: inherit;
438
- transform: translateX(-50%);
439
- margin-bottom: 0;
440
- }
441
- &.w-tooltip--left:before {
442
- left: 100%;
443
- top: 50%;
444
- border-left-color: inherit;
445
- transform: translateY(-50%);
446
- margin-left: 0;
447
- }
448
- &.w-tooltip--right:before {
449
- right: 100%;
450
- top: 50%;
451
- border-right-color: inherit;
452
- transform: translateY(-50%);
453
- margin-right: 0;
454
- }
384
+ @include triangle(var(--w-tooltip-bg-color), '.w-tooltip', 7px);
455
385
  }
456
- // --------------------------------------------------------
457
386
  }
458
387
 
459
388
  // Transitions.
@@ -6,6 +6,6 @@
6
6
  */
7
7
  export const objectifyClasses = (classes = {}) => {
8
8
  if (typeof classes === 'string') classes = { [classes]: true }
9
- else if (typeof classes === 'array') classes = { [classes.join(' ')]: true }
9
+ else if (Array.isArray(classes)) classes = { [classes.join(' ')]: true }
10
10
  return classes
11
11
  }