wave-ui 3.11.0 → 3.13.1
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/dist/types/$waveui.d.ts +200 -2
- package/dist/types/components/WInput.d.ts +14 -0
- package/dist/types/components/WSelect.d.ts +80 -35
- package/dist/types/components/WTable.d.ts +130 -32
- package/dist/types/components/WTabs.d.ts +64 -22
- package/dist/types/components/WTextarea.d.ts +14 -0
- package/dist/types/components/index.d.ts +2 -2
- package/dist/wave-ui.cjs.js +1 -1
- package/dist/wave-ui.css +1 -1
- package/dist/wave-ui.es.js +1406 -1355
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +17 -17
- package/src/wave-ui/components/w-alert.vue +1 -1
- package/src/wave-ui/components/w-autocomplete.vue +1 -8
- package/src/wave-ui/components/w-badge.vue +1 -1
- package/src/wave-ui/components/w-button/button.vue +8 -4
- package/src/wave-ui/components/w-icon.vue +0 -1
- package/src/wave-ui/components/w-input.vue +3 -1
- package/src/wave-ui/components/w-select.vue +10 -8
- package/src/wave-ui/components/w-switch.vue +9 -2
- package/src/wave-ui/components/w-table.vue +18 -1
- package/src/wave-ui/components/w-tag.vue +0 -1
- package/src/wave-ui/components/w-textarea.vue +14 -11
- package/src/wave-ui/core.js +1 -1
- package/src/wave-ui/utils/config.js +4 -0
- package/src/wave-ui/utils/dynamic-css.js +6 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.1",
|
|
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",
|
|
@@ -52,35 +52,35 @@
|
|
|
52
52
|
"publish-doc": "npm run build && npm run build-bundle && git add . && git commit -m 'Publish documentation on Github.' && git push && git push --tag"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@babel/core": "^7.
|
|
56
|
-
"@babel/eslint-parser": "^7.
|
|
55
|
+
"@babel/core": "^7.24.5",
|
|
56
|
+
"@babel/eslint-parser": "^7.24.5",
|
|
57
57
|
"@faker-js/faker": "^8.4.1",
|
|
58
58
|
"@mdi/font": "^6.9.96",
|
|
59
|
-
"@tsconfig/recommended": "^1.0.
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
61
|
-
"@typescript-eslint/parser": "^6.
|
|
59
|
+
"@tsconfig/recommended": "^1.0.6",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
61
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
62
62
|
"@vitejs/plugin-vue": "^5.0.4",
|
|
63
|
-
"@vue/compiler-sfc": "3.4.
|
|
64
|
-
"autoprefixer": "^10.4.
|
|
65
|
-
"axios": "^1.6.
|
|
66
|
-
"eslint": "^8.
|
|
67
|
-
"eslint-plugin-vue": "^9.
|
|
63
|
+
"@vue/compiler-sfc": "3.4.26",
|
|
64
|
+
"autoprefixer": "^10.4.19",
|
|
65
|
+
"axios": "^1.6.8",
|
|
66
|
+
"eslint": "^8.57.0",
|
|
67
|
+
"eslint-plugin-vue": "^9.25.0",
|
|
68
68
|
"font-awesome": "^4.7.0",
|
|
69
69
|
"gsap": "^3.12.5",
|
|
70
70
|
"ionicons": "^4.6.3",
|
|
71
71
|
"material-design-icons": "^3.0.1",
|
|
72
|
-
"postcss": "^8.4.
|
|
72
|
+
"postcss": "^8.4.38",
|
|
73
73
|
"pug": "^3.0.2",
|
|
74
74
|
"rollup-plugin-delete": "^2.0.0",
|
|
75
|
-
"sass": "^1.
|
|
75
|
+
"sass": "^1.76.0",
|
|
76
76
|
"simple-syntax-highlighter": "^3.0.2",
|
|
77
77
|
"splitpanes": "^3.1.5",
|
|
78
78
|
"standard": "^17.1.0",
|
|
79
|
-
"typescript": "^5.
|
|
80
|
-
"vite": "^5.
|
|
79
|
+
"typescript": "^5.4.5",
|
|
80
|
+
"vite": "^5.2.11",
|
|
81
81
|
"vite-svg-loader": "^5.1.0",
|
|
82
|
-
"vue": "^3.4.
|
|
83
|
-
"vue-router": "^4.2
|
|
82
|
+
"vue": "^3.4.26",
|
|
83
|
+
"vue-router": "^4.3.2",
|
|
84
84
|
"vueperslides": "^3.5.1",
|
|
85
85
|
"vuex": "^4.1.0"
|
|
86
86
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
.w-alert(v-if="show"
|
|
2
|
+
.w-alert(v-if="show" :class="classes")
|
|
3
3
|
//- Add a wrapper around the content when needed.
|
|
4
4
|
template(v-if="type || icon || dismiss")
|
|
5
5
|
w-icon.w-alert__icon.mr2(v-if="type || icon") {{ type ? typeIcon : icon }}
|
|
@@ -81,12 +81,6 @@ export default {
|
|
|
81
81
|
return this.normalize(this.keywords)
|
|
82
82
|
},
|
|
83
83
|
|
|
84
|
-
// Keep the autocomplete matching as fast as possible by caching optimized search strings.
|
|
85
|
-
// An array of optimized strings.
|
|
86
|
-
normalizedSelection () {
|
|
87
|
-
return this.selection.map(item => this.normalize(item?.searchable))
|
|
88
|
-
},
|
|
89
|
-
|
|
90
84
|
// Keep the autocomplete matching as fast as possible by caching optimized search strings.
|
|
91
85
|
optimizedItemsForSearch () {
|
|
92
86
|
return this.items.map((item, i) => ({
|
|
@@ -98,8 +92,7 @@ export default {
|
|
|
98
92
|
|
|
99
93
|
filteredItems () {
|
|
100
94
|
let items = this.optimizedItemsForSearch // Array of objects.
|
|
101
|
-
const
|
|
102
|
-
const isItemNotSelected = item => !selection.includes(item.searchable)
|
|
95
|
+
const isItemNotSelected = item => !this.selection.find(i => i.uid === item.uid)
|
|
103
96
|
|
|
104
97
|
if (this.keywords) {
|
|
105
98
|
items = items.filter(item => {
|
|
@@ -71,20 +71,24 @@ export default {
|
|
|
71
71
|
return this.hasRouter ? this.$router.resolve(this.route).href : this.route
|
|
72
72
|
},
|
|
73
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
|
+
|
|
74
78
|
// If the button is a router-link, we can't apply events on it since vue-router needs the .native
|
|
75
79
|
// modifier but it's not available with the v-on directive.
|
|
76
80
|
// So do a manual router.push if $router is present.
|
|
77
81
|
// eslint-disable-next-line multiline-ternary
|
|
78
82
|
return this.route && this.hasRouter && !this.forceLink && !this.externalLink ? {
|
|
79
|
-
...
|
|
83
|
+
...attrs,
|
|
80
84
|
click: e => {
|
|
81
|
-
if (
|
|
85
|
+
if (attrs.click) attrs.click(e)
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
router.push(this.route)
|
|
84
88
|
e.stopPropagation() // If going to a route, no need to bubble up the event.
|
|
85
89
|
e.preventDefault()
|
|
86
90
|
}
|
|
87
|
-
} :
|
|
91
|
+
} : attrs
|
|
88
92
|
},
|
|
89
93
|
size () {
|
|
90
94
|
return (
|
|
@@ -196,8 +196,9 @@ export default {
|
|
|
196
196
|
|
|
197
197
|
listeners () {
|
|
198
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.
|
|
199
200
|
// eslint-disable-next-line no-unused-vars
|
|
200
|
-
const { input, focus, blur, ...listeners } = this.$attrs
|
|
201
|
+
const { input, focus, blur, class: classes, style, ...listeners } = this.$attrs
|
|
201
202
|
return listeners
|
|
202
203
|
},
|
|
203
204
|
|
|
@@ -478,6 +479,7 @@ $inactive-color: #777;
|
|
|
478
479
|
align-items: center;
|
|
479
480
|
background: none;
|
|
480
481
|
border: none;
|
|
482
|
+
border-radius: inherit; // Mostly for the browser-autofilled appearance.
|
|
481
483
|
outline: none;
|
|
482
484
|
padding-left: 2 * $base-increment;
|
|
483
485
|
padding-right: 2 * $base-increment;
|
|
@@ -34,10 +34,11 @@ component(
|
|
|
34
34
|
:aria-owns="`w-select-menu--${_.uid}`"
|
|
35
35
|
:aria-activedescendant="`w-select-menu--${_.uid}_item-1`"
|
|
36
36
|
:class="inputWrapClasses")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
slot(name="icon-left")
|
|
38
|
+
w-icon.w-select__icon.w-select__icon--inner-left(
|
|
39
|
+
v-if="innerIconLeft"
|
|
40
|
+
tag="label"
|
|
41
|
+
@click="$emit('click:inner-icon-left', $event)") {{ innerIconLeft }}
|
|
41
42
|
.w-select__selection-slot(v-if="$slots.selection")
|
|
42
43
|
//- inputValue is always an array.
|
|
43
44
|
slot(name="selection" :item="multiple ? inputValue : inputValue[0]")
|
|
@@ -60,10 +61,11 @@ component(
|
|
|
60
61
|
v-if="$slots.default || label"
|
|
61
62
|
:class="labelClasses")
|
|
62
63
|
slot {{ label }}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
slot(name="icon-right")
|
|
65
|
+
w-icon.w-select__icon.w-select__icon--inner-right(
|
|
66
|
+
v-if="innerIconRight"
|
|
67
|
+
tag="label"
|
|
68
|
+
@click="$emit('click:inner-icon-right', $event)") {{ innerIconRight }}
|
|
67
69
|
w-list(
|
|
68
70
|
ref="w-list"
|
|
69
71
|
:model-value="inputValue"
|
|
@@ -29,7 +29,7 @@ component(
|
|
|
29
29
|
slot {{ label }}
|
|
30
30
|
.w-switch__input(
|
|
31
31
|
@click="$refs.input.focus();$refs.input.click()"
|
|
32
|
-
v-on="
|
|
32
|
+
v-on="listeners"
|
|
33
33
|
:class="inputClasses")
|
|
34
34
|
.w-switch__track(v-if="$slots.track")
|
|
35
35
|
slot(name="track")
|
|
@@ -84,6 +84,13 @@ export default {
|
|
|
84
84
|
},
|
|
85
85
|
|
|
86
86
|
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.
|
|
90
|
+
// eslint-disable-next-line no-unused-vars
|
|
91
|
+
const { click, class: classes, style, ...listeners } = this.$attrs
|
|
92
|
+
return listeners
|
|
93
|
+
},
|
|
87
94
|
hasLabel () {
|
|
88
95
|
return this.label || this.$slots.default
|
|
89
96
|
},
|
|
@@ -150,6 +157,7 @@ $outline-width: 2px;
|
|
|
150
157
|
align-items: center;
|
|
151
158
|
vertical-align: middle;
|
|
152
159
|
cursor: pointer;
|
|
160
|
+
-webkit-tap-highlight-color: transparent;
|
|
153
161
|
|
|
154
162
|
@include themeable;
|
|
155
163
|
|
|
@@ -157,7 +165,6 @@ $outline-width: 2px;
|
|
|
157
165
|
&--disabled, &--readonly {
|
|
158
166
|
cursor: not-allowed;
|
|
159
167
|
touch-action: initial;
|
|
160
|
-
-webkit-tap-highlight-color: transparent;
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
// Hidden checkbox.
|
|
@@ -609,16 +609,33 @@ export default {
|
|
|
609
609
|
})
|
|
610
610
|
},
|
|
611
611
|
|
|
612
|
+
/**
|
|
613
|
+
* Updates the pagination object and fills up missing variables to always maintain the paginationConfig
|
|
614
|
+
* object accurate for external use (read and write).
|
|
615
|
+
* The following vars will always be up to date and if one changes from outside the rest of them
|
|
616
|
+
* will update accordingly: itemsPerPage, itemsPerPageOptions, start, end, page, total.
|
|
617
|
+
*
|
|
618
|
+
* @param {Object} config The config object defining the pagination.
|
|
619
|
+
* This object can have at most itemsPerPage, page, total, and it will define the start, end and
|
|
620
|
+
* pagesCount from the given or current itemsPerPage, page and total.
|
|
621
|
+
* - If a total is given for update, trust it blindly (could come from a backend), and recompute
|
|
622
|
+
* the rest as long as itemsPerPage is defined.
|
|
623
|
+
* - If a page is given for update, it will navigate to that page.
|
|
624
|
+
* - If an itemsPerPage is given for update, it will navigate to that page.
|
|
625
|
+
*/
|
|
612
626
|
updatePaginationConfig ({ itemsPerPage, page, total }) {
|
|
613
627
|
if (total) this.paginationConfig.total = total
|
|
614
628
|
if (itemsPerPage !== undefined) {
|
|
615
629
|
this.paginationConfig.itemsPerPage = itemsPerPage
|
|
616
630
|
itemsPerPage = itemsPerPage || this.paginationConfig.total // If `0`, take all the results.
|
|
617
631
|
this.paginationConfig.page = page || this.paginationConfig.page || 1
|
|
632
|
+
|
|
618
633
|
page = this.paginationConfig.page // Shorthand var for next lines.
|
|
619
634
|
total = this.paginationConfig.total // Shorthand var for next lines.
|
|
635
|
+
const itemsInAllPages = itemsPerPage * page
|
|
620
636
|
this.paginationConfig.start = 1
|
|
621
|
-
this.paginationConfig.end = total >=
|
|
637
|
+
this.paginationConfig.end = total >= itemsInAllPages ? itemsInAllPages : (total % itemsInAllPages)
|
|
638
|
+
|
|
622
639
|
this.paginationConfig.pagesCount = Math.ceil(total / itemsPerPage)
|
|
623
640
|
}
|
|
624
641
|
if (page) this.goToPage(page)
|
|
@@ -17,11 +17,12 @@ component(
|
|
|
17
17
|
|
|
18
18
|
//- Input wrapper.
|
|
19
19
|
.w-textarea__textarea-wrap(:class="inputWrapClasses")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
slot(name="icon-left" :input-id="`w-textarea--${_.uid}`")
|
|
21
|
+
w-icon.w-textarea__icon.w-textarea__icon--inner-left(
|
|
22
|
+
v-if="innerIconLeft"
|
|
23
|
+
tag="label"
|
|
24
|
+
:for="`w-textarea--${_.uid}`"
|
|
25
|
+
@click="$emit('click:inner-icon-left', $event)") {{ innerIconLeft }}
|
|
25
26
|
textarea.w-textarea__textarea(
|
|
26
27
|
ref="textarea"
|
|
27
28
|
v-model="inputValue"
|
|
@@ -44,11 +45,12 @@ component(
|
|
|
44
45
|
v-if="$slots.default || label"
|
|
45
46
|
:class="labelClasses")
|
|
46
47
|
slot {{ label }}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
slot(name="icon-right" :input-id="`w-textarea--${_.uid}`")
|
|
49
|
+
w-icon.w-textarea__icon.w-textarea__icon--inner-right(
|
|
50
|
+
v-if="innerIconRight"
|
|
51
|
+
tag="label"
|
|
52
|
+
:for="`w-textarea--${_.uid}`"
|
|
53
|
+
@click="$emit('click:inner-icon-right', $event)") {{ innerIconRight }}
|
|
52
54
|
|
|
53
55
|
//- Right label.
|
|
54
56
|
template(v-if="labelPosition === 'right'")
|
|
@@ -111,8 +113,9 @@ export default {
|
|
|
111
113
|
computed: {
|
|
112
114
|
listeners () {
|
|
113
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.
|
|
114
117
|
// eslint-disable-next-line no-unused-vars
|
|
115
|
-
const { input, focus, blur, ...listeners } = this.$attrs
|
|
118
|
+
const { input, focus, blur, class: classes, style, ...listeners } = this.$attrs
|
|
116
119
|
return listeners
|
|
117
120
|
},
|
|
118
121
|
hasValue () {
|
package/src/wave-ui/core.js
CHANGED
|
@@ -85,7 +85,7 @@ export default class WaveUI {
|
|
|
85
85
|
document.documentElement.setAttribute('data-theme', theme)
|
|
86
86
|
document.head.querySelector('#wave-ui-colors')?.remove?.()
|
|
87
87
|
const themeColors = this.config.colors[this.theme]
|
|
88
|
-
injectColorsCSSInDOM(themeColors)
|
|
88
|
+
injectColorsCSSInDOM(themeColors, this.config.css.colorShadeCssVariables)
|
|
89
89
|
this.colors = flattenColors(themeColors, colorPalette)
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -14,6 +14,10 @@ const config = reactive({
|
|
|
14
14
|
// Note: the color palette shades are always generated separately from SCSS.
|
|
15
15
|
colorShades: true,
|
|
16
16
|
|
|
17
|
+
// Generate CSS variables for color shades.
|
|
18
|
+
// Note: colorShades must be enabled for this to work.
|
|
19
|
+
colorShadeCssVariables: false,
|
|
20
|
+
|
|
17
21
|
// Generate palette colors and palette color shades.
|
|
18
22
|
// Can't have this option: color palette is generated via SCSS in colors.scss.
|
|
19
23
|
// colorPalette: true,
|
|
@@ -13,7 +13,7 @@ let currentBreakpoint = null
|
|
|
13
13
|
// :root {[color1-variable], [color2-variable]}
|
|
14
14
|
// .color1--bg {background-color: [color1-variable]}
|
|
15
15
|
// .color1 {color: [color1-variable]}
|
|
16
|
-
const generateColors = themeColors => {
|
|
16
|
+
const generateColors = (themeColors, generateShadeCssVariables) => {
|
|
17
17
|
let styles = ''
|
|
18
18
|
const cssVariables = {}
|
|
19
19
|
|
|
@@ -42,6 +42,9 @@ const generateColors = themeColors => {
|
|
|
42
42
|
// That only makes sense when there are 2 colors on the same element: e.g. `span.primary.error`.
|
|
43
43
|
const allColors = { ...colors, info, warning, success, error }
|
|
44
44
|
for (const colorName in allColors) cssVariables[colorName] = allColors[colorName]
|
|
45
|
+
if (generateShadeCssVariables) {
|
|
46
|
+
for (const colorName in shades) cssVariables[colorName] = shades[colorName]
|
|
47
|
+
}
|
|
45
48
|
let cssVariablesString = ''
|
|
46
49
|
Object.entries(cssVariables).forEach(([colorName, colorHex]) => {
|
|
47
50
|
cssVariablesString += `--w-${colorName}-color: ${colorHex};`
|
|
@@ -269,12 +272,12 @@ export const injectCSSInDOM = $waveui => {
|
|
|
269
272
|
window.addEventListener('resize', () => getBreakpoint($waveui))
|
|
270
273
|
}
|
|
271
274
|
|
|
272
|
-
export const injectColorsCSSInDOM = themeColors => {
|
|
275
|
+
export const injectColorsCSSInDOM = (themeColors, generateShadeCssVariables) => {
|
|
273
276
|
// Inject global dynamic CSS classes in document head.
|
|
274
277
|
if (!document.getElementById('wave-ui-colors')) {
|
|
275
278
|
const css = document.createElement('style')
|
|
276
279
|
css.id = 'wave-ui-colors'
|
|
277
|
-
css.innerHTML = generateColors(themeColors)
|
|
280
|
+
css.innerHTML = generateColors(themeColors, generateShadeCssVariables)
|
|
278
281
|
|
|
279
282
|
const firstStyle = document.head.querySelectorAll('style,link[rel="stylesheet"]')[0]
|
|
280
283
|
if (firstStyle) firstStyle.before(css)
|