wave-ui 3.19.0 → 3.20.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 (72) hide show
  1. package/dist/types/$waveui.d.ts +2 -2
  2. package/dist/types/components/WAccordion.d.ts +2 -2
  3. package/dist/types/components/WAlert.d.ts +2 -2
  4. package/dist/types/components/WApp.d.ts +3 -4
  5. package/dist/types/components/WBadge.d.ts +3 -4
  6. package/dist/types/components/WBreadcrumbs.d.ts +3 -4
  7. package/dist/types/components/WButton.d.ts +3 -4
  8. package/dist/types/components/WCard.d.ts +3 -4
  9. package/dist/types/components/WCheckbox.d.ts +2 -2
  10. package/dist/types/components/WCheckboxes.d.ts +2 -2
  11. package/dist/types/components/WConfirm.d.ts +2 -2
  12. package/dist/types/components/WDialog.d.ts +2 -2
  13. package/dist/types/components/WDivider.d.ts +3 -4
  14. package/dist/types/components/WDrawer.d.ts +5 -5
  15. package/dist/types/components/WFlex.d.ts +3 -4
  16. package/dist/types/components/WForm.d.ts +2 -2
  17. package/dist/types/components/WFormElement.d.ts +2 -2
  18. package/dist/types/components/WGrid.d.ts +3 -4
  19. package/dist/types/components/WIcon.d.ts +3 -4
  20. package/dist/types/components/WImage.d.ts +2 -2
  21. package/dist/types/components/WInput.d.ts +2 -2
  22. package/dist/types/components/WList.d.ts +2 -2
  23. package/dist/types/components/WMenu.d.ts +2 -2
  24. package/dist/types/components/WNotification.d.ts +2 -2
  25. package/dist/types/components/WNotificationManager.d.ts +4 -6
  26. package/dist/types/components/WOverlay.d.ts +2 -2
  27. package/dist/types/components/WProgress.d.ts +3 -4
  28. package/dist/types/components/WRadio.d.ts +2 -2
  29. package/dist/types/components/WRadios.d.ts +2 -2
  30. package/dist/types/components/WRating.d.ts +2 -2
  31. package/dist/types/components/WSelect.d.ts +4 -4
  32. package/dist/types/components/WSlider.d.ts +2 -2
  33. package/dist/types/components/WSpinner.d.ts +3 -4
  34. package/dist/types/components/WSteps.d.ts +3 -4
  35. package/dist/types/components/WSwitch.d.ts +2 -2
  36. package/dist/types/components/WTable.d.ts +2 -2
  37. package/dist/types/components/WTabs.d.ts +2 -2
  38. package/dist/types/components/WTag.d.ts +2 -2
  39. package/dist/types/components/WTextarea.d.ts +2 -2
  40. package/dist/types/components/WTimeline.d.ts +3 -4
  41. package/dist/types/components/WToolbar.d.ts +3 -4
  42. package/dist/types/components/WTooltip.d.ts +2 -2
  43. package/dist/types/components/WTree.d.ts +2 -2
  44. package/dist/types/extra-vue-types.d.ts +1 -1
  45. package/dist/types/plugin.d.ts +2 -2
  46. package/dist/wave-ui.cjs.js +1 -1
  47. package/dist/wave-ui.css +1 -1
  48. package/dist/wave-ui.es.js +439 -420
  49. package/dist/wave-ui.umd.js +1 -1
  50. package/package.json +24 -29
  51. package/src/wave-ui/components/transitions/w-transition-expand.vue +3 -3
  52. package/src/wave-ui/components/w-autocomplete.vue +3 -3
  53. package/src/wave-ui/components/w-badge.vue +2 -2
  54. package/src/wave-ui/components/w-card.vue +2 -2
  55. package/src/wave-ui/components/w-checkboxes.vue +1 -1
  56. package/src/wave-ui/components/w-icon.vue +1 -1
  57. package/src/wave-ui/components/w-image.vue +1 -1
  58. package/src/wave-ui/components/w-input.vue +2 -2
  59. package/src/wave-ui/components/w-list.vue +2 -2
  60. package/src/wave-ui/components/w-menu.vue +13 -5
  61. package/src/wave-ui/components/w-scrollable.vue +2 -2
  62. package/src/wave-ui/components/w-table.vue +7 -7
  63. package/src/wave-ui/components/w-tabs/index.vue +2 -2
  64. package/src/wave-ui/components/w-textarea.vue +1 -1
  65. package/src/wave-ui/components/w-toolbar.vue +2 -2
  66. package/src/wave-ui/components/w-tooltip.vue +1 -1
  67. package/src/wave-ui/components/w-tree.vue +1 -1
  68. package/src/wave-ui/core.js +25 -5
  69. package/src/wave-ui/index.d.ts +1 -1
  70. package/src/wave-ui/mixins/detachable.js +1 -1
  71. package/src/wave-ui/utils/colors.js +1 -1
  72. package/src/wave-ui/utils/notification-manager.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "3.19.0",
3
+ "version": "3.20.0",
4
4
  "description": "A UI framework for Vue.js 3 (and 2) with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
6
  "homepage": "https://antoniandre.github.io/wave-ui",
@@ -42,22 +42,27 @@
42
42
  "vue framework",
43
43
  "ui"
44
44
  ],
45
+ "scripts": {
46
+ "dev": "vite",
47
+ "build": "vite build --base /wave-ui/",
48
+ "build-types": "tsc -p ./tsconfig.json",
49
+ "build-bundle": "BUNDLE=true vite build && npm run build-types",
50
+ "preview": "vite preview --base /wave-ui/",
51
+ "lint": "biome check .",
52
+ "lint:fix": "biome check --apply .",
53
+ "format": "biome format .",
54
+ "format:fix": "biome format --write .",
55
+ "publish-doc": "npm run build && npm run build-bundle && git add . && git commit -m 'Publish documentation on Github.' && git push && git push --tag"
56
+ },
45
57
  "devDependencies": {
46
- "@eslint/js": "^9.21.0",
47
- "@faker-js/faker": "^9.5.1",
58
+ "@babel/core": "^7.26.10",
59
+ "@biomejs/biome": "^1.9.4",
60
+ "@faker-js/faker": "^9.6.0",
48
61
  "@mdi/font": "^7.4.47",
49
62
  "@tsconfig/recommended": "^1.0.8",
50
- "@typescript-eslint/eslint-plugin": "^8.25.0",
51
- "@typescript-eslint/parser": "^8.25.0",
52
- "@vitejs/plugin-vue": "^5.2.1",
53
- "autoprefixer": "^10.4.20",
54
- "axios": "^1.8.1",
55
- "eslint": "^9.21.0",
56
- "eslint-config-standard": "^17.1.0",
57
- "eslint-plugin-import": "^2.31.0",
58
- "eslint-plugin-n": "^17.15.1",
59
- "eslint-plugin-promise": "^7.2.1",
60
- "eslint-plugin-vue": "^9.32.0",
63
+ "@vitejs/plugin-vue": "^5.2.3",
64
+ "autoprefixer": "^10.4.21",
65
+ "axios": "^1.8.4",
61
66
  "font-awesome": "^4.7.0",
62
67
  "globals": "^16.0.0",
63
68
  "gsap": "^3.12.7",
@@ -65,13 +70,12 @@
65
70
  "material-design-icons": "^3.0.1",
66
71
  "postcss": "^8.5.3",
67
72
  "pug": "^3.0.3",
68
- "rollup-plugin-delete": "^3.0.0",
69
- "sass": "^1.85.1",
73
+ "rollup-plugin-delete": "^3.0.1",
74
+ "sass": "^1.86.2",
70
75
  "simple-syntax-highlighter": "^3.1.1",
71
- "splitpanes": "^3.1.8",
76
+ "splitpanes": "^4.0.3",
72
77
  "typescript": "^5.8.2",
73
- "typescript-eslint": "^8.25.0",
74
- "vite": "^6.2.0",
78
+ "vite": "^6.2.4",
75
79
  "vite-svg-loader": "^5.1.0",
76
80
  "vue": "^3.5.13",
77
81
  "vue-router": "^4.5.0",
@@ -84,14 +88,5 @@
84
88
  "engines": {
85
89
  "node": ">=16.0.0",
86
90
  "pnpm": ">=8.0.0"
87
- },
88
- "scripts": {
89
- "dev": "vite",
90
- "build": "vite build --base /wave-ui/",
91
- "build-types": "tsc -p ./tsconfig.json",
92
- "build-bundle": "BUNDLE=true vite build && npm run build-types",
93
- "preview": "vite preview --base /wave-ui/",
94
- "lint": "vite lint",
95
- "publish-doc": "npm run build && npm run build-bundle && git add . && git commit -m 'Publish documentation on Github.' && git push && git push --tag"
96
91
  }
97
- }
92
+ }
@@ -135,7 +135,7 @@ export default {
135
135
  },
136
136
  applyShowStyles (el) {
137
137
  if (this.animX) {
138
- el.style.width = this.el.width + 'px'
138
+ el.style.width = `${this.el.width}px`
139
139
  el.style.marginLeft = this.el.marginLeft
140
140
  el.style.marginRight = this.el.marginRight
141
141
  el.style.paddingLeft = this.el.paddingLeft
@@ -144,7 +144,7 @@ export default {
144
144
  el.style.borderRightWidth = this.el.borderRightWidth
145
145
  }
146
146
  if (this.animY) {
147
- el.style.height = this.el.height + 'px'
147
+ el.style.height = `${this.el.height}px`
148
148
  el.style.marginTop = this.el.marginTop
149
149
  el.style.marginBottom = this.el.marginBottom
150
150
  el.style.paddingTop = this.el.paddingTop
@@ -153,7 +153,7 @@ export default {
153
153
  el.style.borderBottomWidth = this.el.borderBottomWidth
154
154
  }
155
155
 
156
- el.style.transition = this.duration + 'ms ease-in-out'
156
+ el.style.transition = `${this.duration}ms ease-in-out`
157
157
  },
158
158
  applyOriginalStyles (el) {
159
159
  el.style.cssText = this.el.originalStyles
@@ -99,8 +99,8 @@ export default {
99
99
  if (this.keywords) {
100
100
  items = items.filter(item => {
101
101
  if (!item.searchable.includes(this.normalizedKeywords)) return false
102
- else if (this.multiple && !this.allowDuplicates) return isItemNotSelected(item)
103
- else return true
102
+ if (this.multiple && !this.allowDuplicates) return isItemNotSelected(item)
103
+ return true
104
104
  })
105
105
  }
106
106
 
@@ -111,7 +111,7 @@ export default {
111
111
 
112
112
  highlightedItemIndex () {
113
113
  if (this.highlightedItem === null) return -1
114
- else if (this.highlightedItem === 'extra-item') return this.filteredItems.length
114
+ if (this.highlightedItem === 'extra-item') return this.filteredItems.length
115
115
 
116
116
  return this.filteredItems.findIndex(item => item.uid === this.highlightedItem)
117
117
  },
@@ -66,13 +66,13 @@ export default {
66
66
  ]
67
67
  },
68
68
  classes () {
69
- const slotText = this.$slots.badge && this.$slots.badge().map(item => item.children).join('')
69
+ const slotText = this.$slots.badge?.().map(item => item.children).join('')
70
70
 
71
71
  return {
72
72
  [this.color]: this.color,
73
73
  [`${this.bgColor}--bg`]: this.bgColor,
74
74
  [this.badgeClass]: this.badgeClass || null,
75
- 'w-badge--round': this.round || (slotText || this.modelValue + '' || '').length < 2,
75
+ 'w-badge--round': this.round || (slotText || `${this.modelValue}` || '').length < 2,
76
76
  'w-badge--dark': this.dark,
77
77
  'w-badge--light': this.light,
78
78
  'w-badge--outline': this.outline,
@@ -52,12 +52,12 @@ export default {
52
52
 
53
53
  titleHasToolbar () {
54
54
  const { title } = this.$slots
55
- return title && title().map(vnode => vnode.type.name).join('').includes('w-toolbar')
55
+ return title?.()?.map(vnode => vnode.type.name).join('').includes('w-toolbar')
56
56
  },
57
57
 
58
58
  actionsHasToolbar () {
59
59
  const { actions } = this.$slots
60
- return actions && actions().map(vnode => vnode.type.name).join('').includes('w-toolbar')
60
+ return actions?.()?.map(vnode => vnode.type.name).join('').includes('w-toolbar')
61
61
  },
62
62
 
63
63
  imgProps () {
@@ -75,7 +75,7 @@ export default {
75
75
  _index: i,
76
76
  value: itemValue, // If no value is set then add one to prevent error.
77
77
  color: item[this.itemColorKey] || this.color,
78
- _isChecked: this.modelValue && this.modelValue.includes(itemValue)
78
+ _isChecked: this.modelValue?.includes(itemValue)
79
79
  })
80
80
  })
81
81
  },
@@ -87,7 +87,7 @@ export default {
87
87
  methods: {
88
88
  readIcon () {
89
89
  const { default: slot } = this.$slots
90
- const [fontName = '', icon = ''] = (typeof slot === 'function' && slot()[0].children.trim().split(' ')) || []
90
+ const [fontName = '', icon = ''] = (typeof slot === 'function' && slot()?.[0]?.children?.trim()?.split(' ')) || []
91
91
  this.fontName = fontName
92
92
  this.icon = icon
93
93
 
@@ -183,7 +183,7 @@ export default {
183
183
 
184
184
  if (this.lazy) {
185
185
  const IntersectObserver = new IntersectionObserver(entry => {
186
- if (entry[0] && entry[0].isIntersecting) {
186
+ if (entry[0]?.isIntersecting) {
187
187
  this.loadImage()
188
188
  IntersectObserver.disconnect()
189
189
  }
@@ -335,7 +335,7 @@ export default {
335
335
  // If the preview prop is a string, the user is setting the preview to an icon and
336
336
  // don't need the actual file preview.
337
337
  const isPreviewAnIcon = typeof this.preview === 'string'
338
- const isFileAnImage = original.type && original.type.startsWith('image/')
338
+ const isFileAnImage = original.type?.startsWith('image/')
339
339
  // Check if the file is an image and set a preview image.
340
340
  if (this.preview && !isPreviewAnIcon && isFileAnImage) {
341
341
  reader.addEventListener('load', e => {
@@ -357,7 +357,7 @@ export default {
357
357
  // On page load, check if the field is autofilled by the browser.
358
358
  // 20211229. Only a problem on Chrome. Firefox ok, Safari always prompts before filling up.
359
359
  setTimeout(() => {
360
- if (this.$refs.input && this.$refs.input.matches(':-webkit-autofill')) this.isAutofilled = true
360
+ if (this.$refs.input?.matches(':-webkit-autofill')) this.isAutofilled = true
361
361
  }, 400) // Can't be less than 350: time for the browser to autofill.
362
362
  },
363
363
 
@@ -133,9 +133,9 @@ export default {
133
133
  getItemValue (item) {
134
134
  if (item && typeof item === 'object') {
135
135
  if (item[this.itemValueKey] !== undefined) return item[this.itemValueKey]
136
- else return item[this.itemLabelKey] !== undefined ? item[this.itemLabelKey] : item.index
136
+ return item[this.itemLabelKey] !== undefined ? item[this.itemLabelKey] : item.index
137
137
  }
138
- else return item
138
+ return item
139
139
  },
140
140
 
141
141
  // Action of selecting 1 item.
@@ -122,12 +122,12 @@ export default {
122
122
 
123
123
  menuMinWidth () {
124
124
  if (this.minWidth === 'activator') return this.activatorWidth ? `${this.activatorWidth}px` : 0
125
- else return isNaN(this.minWidth) ? this.minWidth : (this.minWidth ? `${this.minWidth}px` : 0)
125
+ return isNaN(this.minWidth) ? this.minWidth : (this.minWidth ? `${this.minWidth}px` : 0)
126
126
  },
127
127
 
128
128
  menuMaxWidth () {
129
129
  if (this.maxWidth === 'activator') return this.activatorWidth ? `${this.activatorWidth}px` : 0
130
- else return isNaN(this.maxWidth) ? this.maxWidth : (this.maxWidth ? `${this.maxWidth}px` : 0)
130
+ return isNaN(this.maxWidth) ? this.maxWidth : (this.maxWidth ? `${this.maxWidth}px` : 0)
131
131
  },
132
132
 
133
133
  menuClasses () {
@@ -190,7 +190,7 @@ export default {
190
190
  this.hoveringActivator = true
191
191
  this.open(e)
192
192
  },
193
- mouseleave: e => {
193
+ mouseleave: () => {
194
194
  this.hoveringActivator = false
195
195
  // Wait 10ms, the time to get the hoveringMenu updated on mouseenter on the menu.
196
196
  setTimeout(() => {
@@ -313,7 +313,15 @@ export default {
313
313
  &.w-menu--left {margin-left: -4 * $base-increment;}
314
314
  &.w-menu--right {margin-left: 4 * $base-increment;}
315
315
 
316
- @include triangle(var(--w-menu-bg-color), '.w-menu', 9px);
317
- }
316
+ // Menu without border.
317
+ &.w-menu--no-border {
318
+ @include triangle(var(--w-menu-bg-color), '.w-menu', 9px, 0);
319
+ }
320
+
321
+ // Menu with border.
322
+ &:not(.w-menu--no-border) {
323
+ @include triangle(var(--w-menu-bg-color), '.w-menu', 9px);
324
+ }
325
+ }
318
326
  }
319
327
  </style>
@@ -148,7 +148,7 @@ export default {
148
148
  this.scrollable.hovered = false
149
149
  },
150
150
 
151
- onResize (e) {
151
+ onResize () {
152
152
  },
153
153
 
154
154
  onMouseWheel (e) {
@@ -156,7 +156,7 @@ export default {
156
156
 
157
157
  // When scrolling beyond limits, release the mousewheel and scroll the parent.
158
158
  if (this.scrollValuePercent <= 0 && e[this.m.deltaXorY] < 0) return
159
- else if (this.scrollValuePercent >= 100 - this.thumbSizePercent && e[this.m.deltaXorY] > 0) return
159
+ if (this.scrollValuePercent >= 100 - this.thumbSizePercent && e[this.m.deltaXorY] > 0) return
160
160
 
161
161
  e.preventDefault() // Hold the scroll in the hovered w-scrollable element.
162
162
 
@@ -262,7 +262,7 @@ export default {
262
262
  type: [Boolean, Object, String],
263
263
  validator: object => {
264
264
  if (!object) return true // Accept any falsy value.
265
- else if (typeof object === 'object' && (!object.itemsPerPage || (object.page && isNaN(object.page)))) {
265
+ if (typeof object === 'object' && (!object.itemsPerPage || (object.page && isNaN(object.page)))) {
266
266
  consoleError(
267
267
  'Wrong pagination config received in the w-table\'s `pagination` prop (received: `' + JSON.stringify(object) + '`). ' +
268
268
  '\nExpected object: { itemsPerPage: Integer, page: Integer } or { itemsPerPage: Integer, start: Integer }.'
@@ -539,8 +539,8 @@ export default {
539
539
  const newNextColWidth = nextColWidth - deltaX
540
540
 
541
541
  // 1. Apply the change of width.
542
- columnEl.style.width = colWidth + deltaX + 'px'
543
- nextColumnEl.style.width = nextColWidth - deltaX + 'px'
542
+ columnEl.style.width = `${colWidth + deltaX}px`
543
+ nextColumnEl.style.width = `${nextColWidth - deltaX}px`
544
544
 
545
545
  // 2. Check if we went too far (the width applied is different than the browser-computed one).
546
546
  const minWidthReached = (deltaX < 0 && columnEl.offsetWidth > newColWidth) ||
@@ -551,13 +551,13 @@ export default {
551
551
  // Make sure we don't shrink enough to push other left cells.
552
552
  if (minWidthReached) {
553
553
  const newWidth = Math.max(columnEl.offsetWidth, minColumnWidth)
554
- columnEl.style.width = newWidth + 'px'
555
- nextColumnEl.style.width = maxWidth - newWidth + 'px'
554
+ columnEl.style.width = `${newWidth}px`
555
+ nextColumnEl.style.width = `${maxWidth - newWidth}px`
556
556
  }
557
557
  // Make sure we don't grow enough to push other right cells.
558
558
  else if (maxWidthReached) {
559
- columnEl.style.width = maxWidth - nextColumnEl.offsetWidth + 'px'
560
- nextColumnEl.style.width = nextColumnEl.offsetWidth + 'px'
559
+ columnEl.style.width = `${maxWidth - nextColumnEl.offsetWidth}px`
560
+ nextColumnEl.style.width = `${nextColumnEl.offsetWidth}px`
561
561
  }
562
562
  },
563
563
 
@@ -257,7 +257,7 @@ export default {
257
257
  updateSlider (domLookup = true) {
258
258
  if (domLookup) {
259
259
  const ref = this.$refs['tabs-bar']
260
- this.activeTabEl = ref && ref.querySelector('.w-tabs__bar-item--active')
260
+ this.activeTabEl = ref?.querySelector('.w-tabs__bar-item--active')
261
261
  }
262
262
 
263
263
  if (!this.fillBar && this.activeTabEl) {
@@ -285,7 +285,7 @@ export default {
285
285
  // Scroll the new active tab item title into view if needed.
286
286
  this.$nextTick(() => {
287
287
  const ref = this.$refs['tabs-bar']
288
- this.activeTabEl = ref && ref.querySelector(`.w-tabs__bar-item:nth-child(${index + 1})`)
288
+ this.activeTabEl = ref?.querySelector(`.w-tabs__bar-item:nth-child(${index + 1})`)
289
289
  if (this.activeTabEl) {
290
290
  this.activeTabEl.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
291
291
  }
@@ -191,7 +191,7 @@ export default {
191
191
  this.$refs.textarea.style.height = ''
192
192
  const linesCount = (this.$refs.textarea.scrollHeight - this.paddingY) / this.lineHeight
193
193
  const height = Math.max(linesCount, this.rows) * this.lineHeight + this.paddingY
194
- this.$refs.textarea.style.height = height + 'px'
194
+ this.$refs.textarea.style.height = `${height}px`
195
195
  },
196
196
  getLineHeight () {
197
197
  const computedStyles = window.getComputedStyle(this.$refs.textarea, null)
@@ -31,13 +31,13 @@ export default {
31
31
  toolbarHeight () {
32
32
  const h = this.height
33
33
  // If a number is passed without units, append `px`.
34
- return h && parseInt(h) == h ? h + 'px' : h
34
+ return h && parseInt(h) === h ? `${h}px` : h
35
35
  },
36
36
  // Return the width value if defined, or false otherwise.
37
37
  toolbarWidth () {
38
38
  const w = this.width
39
39
  // If a number is passed without units, append `px`.
40
- return w && parseInt(w) == w ? w + 'px' : w
40
+ return w && parseInt(w) === w ? `${w}px` : w
41
41
  },
42
42
  classes () {
43
43
  return {
@@ -136,7 +136,7 @@ export default {
136
136
  this.hoveringActivator = true
137
137
  this.open(e)
138
138
  },
139
- mouseleave: e => {
139
+ mouseleave: () => {
140
140
  this.hoveringActivator = false
141
141
  this.close()
142
142
  }
@@ -295,7 +295,7 @@ export default {
295
295
  },
296
296
 
297
297
  focusTreeItem (liNode) {
298
- liNode && liNode.querySelector('.w-tree__item-label').focus()
298
+ liNode?.querySelector('.w-tree__item-label').focus()
299
299
  },
300
300
 
301
301
  itemIcon (item) {
@@ -45,7 +45,6 @@ const injectPresets = (component, presets) => {
45
45
 
46
46
  // If the given prop (= preset) is still not found in the mixins props raise warning.
47
47
  if (!foundProp) consoleWarn(`Attempting to set a preset on a prop that doesn't exist: \`${component.name}.${preset}\`.`)
48
- continue // Continue to the next preset.
49
48
  }
50
49
  }
51
50
 
@@ -74,19 +73,40 @@ export default class WaveUI {
74
73
  theme: null, // The current theme (light or dark).
75
74
  _notificationManager: null,
76
75
 
77
- // Callable from this.$waveui.
76
+ /**
77
+ * Notify the user. (Callable from this.$waveui)
78
+ *
79
+ * @param {...any} args - The arguments to pass to the notification manager.
80
+ */
78
81
  notify (...args) {
79
82
  this._notificationManager.notify(...args)
80
83
  },
81
84
 
82
- // Callable from this.$waveui.
83
- switchTheme (theme, skipFlatten = false) {
85
+ /**
86
+ * Switch the theme. (Callable from this.$waveui)
87
+ *
88
+ * @param {string} theme - The theme to switch to.
89
+ */
90
+ switchTheme (theme) {
84
91
  this.theme = theme
85
92
  document.documentElement.setAttribute('data-theme', theme)
86
93
  document.head.querySelector('#wave-ui-colors')?.remove?.()
87
94
  const themeColors = this.config.colors[this.theme]
88
95
  injectColorsCSSInDOM(themeColors, this.config.css.colorShadeCssVariables)
89
96
  this.colors = flattenColors(themeColors, colorPalette)
97
+ },
98
+
99
+ /**
100
+ * Set the classes of the app element. (Callable from this.$waveui)
101
+ *
102
+ * @param {string} classes - The classes to set.
103
+ */
104
+ setAppClasses (...classes) {
105
+ const wApp = document.querySelector('.w-app')
106
+ if (wApp) {
107
+ wApp.className = 'w-app' // First reset the classes.
108
+ wApp.classList.add(...classes)
109
+ }
90
110
  }
91
111
  }
92
112
 
@@ -134,7 +154,7 @@ export default class WaveUI {
134
154
  injectNotifManagerInDOM(app)
135
155
 
136
156
  // This mixin must only run once, we can delete it.
137
- app._context.mixins.find(mixin => mixin.mounted && delete mixin.mounted)
157
+ app._context.mixins.find(mixin => mixin.mounted && (mixin.mounted = undefined))
138
158
  }
139
159
  }
140
160
  })
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/ban-types */
2
2
  declare module 'wave-ui/src/wave-ui' {
3
- import { App } from 'vue'
3
+ import type { App } from 'vue'
4
4
 
5
5
  import type { $waveui } from '@/types/$waveui'
6
6
  import type { ConstructorOptions } from '@/types/plugin'
@@ -306,7 +306,7 @@ export default {
306
306
  removeFromDOM () {
307
307
  document.removeEventListener('mousedown', this.onOutsideMousedown)
308
308
  window.removeEventListener('resize', this.onResize)
309
- if (this.detachableEl && this.detachableEl.parentNode) {
309
+ if (this.detachableEl?.parentNode) {
310
310
  this.detachableVisible = false
311
311
  this.detachableEl.remove()
312
312
  this.detachableEl = null
@@ -20,7 +20,7 @@ export const generateColorShades = config => {
20
20
  const color = { label, color: (themeOfColors[label]?.color ?? themeOfColors[label])?.replace?.('#', '') }
21
21
  const col = color.color
22
22
  if (!col) continue // Don't break if a color is only set for one of the themes.
23
- if (col.length === 3) color.color = col[0] + '' + col[0] + col[1] + col[1] + col[2] + col[2]
23
+ if (col.length === 3) color.color = `${col[0]}${col[0]}${col[1]}${col[1]}${col[2]}${col[2]}`
24
24
 
25
25
  for (let i = 1; i <= 6; i++) {
26
26
  const lighterColor = lighten(`#${color.color}`, i * (colorInfo?.lightIncrement ?? 16) + (colorInfo?.lightOffset ?? 0))
@@ -4,7 +4,7 @@ import WNotificationManager from '../components/w-notification-manager.vue'
4
4
  export class NotificationManager {
5
5
  static #instance
6
6
  notifications
7
- // Private fields.
7
+ // Private fields.
8
8
  _uid // A unique ID for each notification.
9
9
  _notificationDefaults
10
10