wave-ui 1.62.0 → 1.63.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/wave-ui.cjs.js +1 -1
- package/dist/wave-ui.css +1 -1
- package/dist/wave-ui.es.js +580 -486
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +1 -1
- package/src/wave-ui/components/index.js +1 -0
- package/src/wave-ui/components/w-button/index.vue +9 -1
- package/src/wave-ui/components/w-list.vue +4 -1
- package/src/wave-ui/components/w-notification-manager.vue +2 -3
- package/src/wave-ui/components/w-scrollbar.vue +24 -0
- package/src/wave-ui/components/w-select.vue +1 -1
- package/src/wave-ui/components/w-table.vue +10 -2
- package/src/wave-ui/components/w-tree.vue +49 -16
- package/src/wave-ui/core.js +45 -69
- package/src/wave-ui/scss/_layout.scss +1 -1
- package/src/wave-ui/utils/colors.js +56 -2
- package/src/wave-ui/utils/config.js +17 -8
- package/src/wave-ui/utils/dynamic-css.js +2 -2
- package/src/wave-ui/utils/notification-manager.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.63.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",
|
|
@@ -28,6 +28,7 @@ export { default as WProgress } from './w-progress.vue'
|
|
|
28
28
|
export { default as WRadio } from './w-radio.vue'
|
|
29
29
|
export { default as WRadios } from './w-radios.vue'
|
|
30
30
|
export { default as WRating } from './w-rating.vue'
|
|
31
|
+
export { default as WScrollbar } from './w-scrollbar.vue'
|
|
31
32
|
export { default as WSelect } from './w-select.vue'
|
|
32
33
|
export { default as WSlider } from './w-slider.vue'
|
|
33
34
|
export { default as WSpinner } from './w-spinner.vue'
|
|
@@ -61,7 +61,15 @@ export default {
|
|
|
61
61
|
computed: {
|
|
62
62
|
buttonProps () {
|
|
63
63
|
const { tooltip, tooltipProps, ...props } = this.$props
|
|
64
|
-
return {
|
|
64
|
+
return {
|
|
65
|
+
...props,
|
|
66
|
+
...this.$attrs,
|
|
67
|
+
// Vue 2 specific:
|
|
68
|
+
// The classes and styles are not in $attrs. Add them from $vnode.data.staticClass, so
|
|
69
|
+
// the button gets these classes wen used with tooltip.
|
|
70
|
+
// https://v2.vuejs.org/v2/guide/components-props.html#Disabling-Attribute-Inheritance
|
|
71
|
+
class: this.tooltip && this.$vnode.data.staticClass
|
|
72
|
+
}
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
}
|
|
@@ -407,7 +407,10 @@ export default {
|
|
|
407
407
|
if (!this.isMultipleSelect) this.listItems.forEach(item => (item._selected = false))
|
|
408
408
|
|
|
409
409
|
this.checkSelection(selection) // Create an array with the selected values.
|
|
410
|
-
.forEach(val =>
|
|
410
|
+
.forEach(val => {
|
|
411
|
+
const foundItem = this.listItems.find(item => item._value === val)
|
|
412
|
+
if (foundItem) foundItem._selected = true
|
|
413
|
+
})
|
|
411
414
|
}
|
|
412
415
|
},
|
|
413
416
|
|
|
@@ -63,12 +63,12 @@ export default {
|
|
|
63
63
|
.w-notification-manager {
|
|
64
64
|
position: fixed;
|
|
65
65
|
top: 0;
|
|
66
|
-
|
|
66
|
+
max-height: 100%;
|
|
67
67
|
right: 0;
|
|
68
68
|
z-index: 1000;
|
|
69
|
-
pointer-events: none;
|
|
70
69
|
width: 280px;
|
|
71
70
|
overflow-x: hidden;
|
|
71
|
+
overflow-y: auto;
|
|
72
72
|
|
|
73
73
|
&--left {right: auto;left: 0;}
|
|
74
74
|
|
|
@@ -79,7 +79,6 @@ export default {
|
|
|
79
79
|
right: 0;
|
|
80
80
|
margin: 8px;
|
|
81
81
|
flex-grow: 1;
|
|
82
|
-
pointer-events: all;
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template lang="pug">
|
|
2
|
+
.w-scrollbar
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
export default {
|
|
7
|
+
name: 'w-scrollbar',
|
|
8
|
+
props: {
|
|
9
|
+
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
emits: [],
|
|
13
|
+
|
|
14
|
+
data: () => ({
|
|
15
|
+
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<style lang="scss">
|
|
21
|
+
.w-scrollbar {
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
@@ -525,7 +525,7 @@ export default {
|
|
|
525
525
|
top: 50%;
|
|
526
526
|
left: 0;
|
|
527
527
|
right: 0;
|
|
528
|
-
// Use margin instead of padding as the scale transformation
|
|
528
|
+
// Use margin instead of padding as the scale transformation below decreases the real padding
|
|
529
529
|
// size and misaligns the label.
|
|
530
530
|
margin-left: 2 * $base-increment;
|
|
531
531
|
transform: translateY(-50%);
|
|
@@ -820,10 +820,18 @@ $tr-border-top: 1px;
|
|
|
820
820
|
|
|
821
821
|
// Mobile layout.
|
|
822
822
|
.w-table--mobile {
|
|
823
|
+
display: flex;
|
|
824
|
+
|
|
823
825
|
thead {display: none;}
|
|
824
|
-
|
|
826
|
+
tbody {
|
|
827
|
+
display: flex;
|
|
828
|
+
flex-direction: column;
|
|
829
|
+
flex-grow: 1;
|
|
830
|
+
}
|
|
825
831
|
tr {
|
|
826
|
-
display:
|
|
832
|
+
display: flex;
|
|
833
|
+
flex-direction: column;
|
|
834
|
+
flex-grow: 1;
|
|
827
835
|
padding-top: $base-increment;
|
|
828
836
|
padding-bottom: $base-increment;
|
|
829
837
|
}
|
|
@@ -4,22 +4,27 @@ ul.w-tree(:class="classes")
|
|
|
4
4
|
v-for="(item, i) in currentDepthItems"
|
|
5
5
|
:key="i"
|
|
6
6
|
:class="itemClasses(item)")
|
|
7
|
-
.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
//- The keys `route` & `disabled` are always present in any currentDepthItems.
|
|
8
|
+
component.w-tree__item-label(
|
|
9
|
+
:is="!disabled && !item.disabled && item.route ? (!$router || hasExternalLink(item) ? 'a' : 'router-link') : 'div'"
|
|
10
|
+
v-bind="item.route && { [!$router || hasExternalLink(item) ? 'href' : 'to']: item.route }"
|
|
11
|
+
@click="!disabled && !item.disabled && onLabelClick(item, $event)"
|
|
12
|
+
@keydown="!disabled && !item.disabled && onLabelKeydown(item, $event)"
|
|
13
|
+
:tabindex="!disabled && !item.disabled && (item.children || item.branch || selectable) && !(unexpandableEmpty && !item.children) ? 0 : null")
|
|
14
|
+
//- @click.stop to not follow link if item is a link.
|
|
11
15
|
w-button.w-tree__item-expand(
|
|
12
16
|
v-if="(item.children || item.branch) && ((expandOpenIcon && item.open) || expandIcon) && !(unexpandableEmpty && !item.children)"
|
|
17
|
+
@click.stop="!disabled && !item.disabled && onLabelClick(item, $event)"
|
|
13
18
|
color="inherit"
|
|
14
19
|
:icon="(item.open && expandOpenIcon) || expandIcon"
|
|
15
20
|
:icon-props="{ rotate90a: !item.open }"
|
|
16
21
|
:tabindex="-1"
|
|
17
|
-
:disabled="disabled"
|
|
22
|
+
:disabled="disabled || item.disabled"
|
|
18
23
|
text
|
|
19
24
|
sm)
|
|
20
|
-
slot(name="item
|
|
25
|
+
slot(name="item" :item="item.originalItem" :depth="depth" :open="item.open")
|
|
21
26
|
w-icon(v-if="itemIcon(item)" class="w-tree__item-icon" :color="item.originalItem[itemIconColorKey] || iconColor") {{ itemIcon(item) }}
|
|
22
|
-
span
|
|
27
|
+
span(v-html="item.label")
|
|
23
28
|
span.ml1(v-if="counts && (item.children || item.branch)").
|
|
24
29
|
({{ item.originalItem.children ? item.originalItem.children.length : 0 }})
|
|
25
30
|
component(
|
|
@@ -39,16 +44,15 @@ ul.w-tree(:class="classes")
|
|
|
39
44
|
@click="$emit('click', $event)"
|
|
40
45
|
@select="$emit('select', $event)"
|
|
41
46
|
@input="$emit('input', $event)")
|
|
42
|
-
template(#item
|
|
43
|
-
slot(name="item
|
|
47
|
+
template(#item="{ item, depth, open }")
|
|
48
|
+
slot(name="item" :item="item" :depth="depth" :open="open")
|
|
44
49
|
</template>
|
|
45
50
|
|
|
46
51
|
<script>
|
|
52
|
+
import { consoleWarn } from '../utils/console'
|
|
47
53
|
/**
|
|
48
|
-
* @todo
|
|
49
|
-
* -
|
|
50
|
-
* - icon per item
|
|
51
|
-
* - left border?
|
|
54
|
+
* @todo:
|
|
55
|
+
* - option to add a left border.
|
|
52
56
|
**/
|
|
53
57
|
|
|
54
58
|
export default {
|
|
@@ -74,7 +78,11 @@ export default {
|
|
|
74
78
|
counts: { type: Boolean },
|
|
75
79
|
itemIconKey: { type: String, default: 'icon' }, // Support a different icon per item.
|
|
76
80
|
iconColor: { type: String }, // Applies a color on all the label item icons.
|
|
77
|
-
|
|
81
|
+
itemLabelKey: { type: String, default: 'label' }, // Specify a different key for the item label.
|
|
82
|
+
itemIconColorKey: { type: String, default: 'iconColor' }, // Applies a specific color on each label item icons.
|
|
83
|
+
itemRouteKey: { type: String, default: 'route' }, // Uses a router link if the item has the `route` key.
|
|
84
|
+
itemDisabledKey: { type: String, default: 'disabled' }, // Disables the item click and selection.
|
|
85
|
+
itemOpenKey: { type: String, default: 'open' } // Open the item by default.
|
|
78
86
|
},
|
|
79
87
|
|
|
80
88
|
emits: ['input', 'before-open', 'open', 'before-close', 'close', 'click', 'select'],
|
|
@@ -100,15 +108,23 @@ export default {
|
|
|
100
108
|
updateCurrentDepthTree (items, oldItems = []) {
|
|
101
109
|
this.currentDepthItems = []
|
|
102
110
|
|
|
111
|
+
if (!Array.isArray(items) && typeof items !== 'object') {
|
|
112
|
+
return consoleWarn(`[w-tree] the tree items must be of type array or object, ${typeof items} received.`, items)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!Array.isArray(items)) items = [items]
|
|
116
|
+
|
|
103
117
|
items.forEach((item, i) => {
|
|
104
118
|
this.currentDepthItems.push({
|
|
105
119
|
originalItem: item, // Store the original item to return it on event emits.
|
|
106
120
|
_uid: this.depth.toString() + (i + 1),
|
|
107
|
-
label: item.
|
|
121
|
+
label: item[this.itemLabelKey],
|
|
108
122
|
children: !!item.children, // The children tree remains available in originalItem.
|
|
109
123
|
branch: item.branch,
|
|
124
|
+
route: item[this.itemRouteKey],
|
|
125
|
+
disabled: item[this.itemDisabledKey],
|
|
110
126
|
depth: this.depth,
|
|
111
|
-
open: !!(oldItems[i]?.open || this.expandAll)
|
|
127
|
+
open: !!(oldItems[i]?.open || this.expandAll || item[this.itemOpenKey])
|
|
112
128
|
})
|
|
113
129
|
})
|
|
114
130
|
},
|
|
@@ -135,6 +151,9 @@ export default {
|
|
|
135
151
|
},
|
|
136
152
|
|
|
137
153
|
onLabelClick (item, e) {
|
|
154
|
+
const route = item[this.itemRouteKey]
|
|
155
|
+
if (route && this.$router && !this.hasExternalLink(item)) e.preventDefault()
|
|
156
|
+
|
|
138
157
|
this.$emit('click', { item: item.originalItem, depth: this.depth, e })
|
|
139
158
|
if (item.children || (item.branch && !this.unexpandableEmpty)) this.expandDepth(item)
|
|
140
159
|
|
|
@@ -219,9 +238,14 @@ export default {
|
|
|
219
238
|
)
|
|
220
239
|
},
|
|
221
240
|
|
|
241
|
+
hasExternalLink (item) {
|
|
242
|
+
return /^(https?:)?\/\/|mailto:|tel:/.test(item[this.itemRouteKey])
|
|
243
|
+
},
|
|
244
|
+
|
|
222
245
|
itemClasses (item) {
|
|
223
246
|
return {
|
|
224
247
|
[item.children || item.branch ? 'w-tree__item--branch' : 'w-tree__item--leaf']: true,
|
|
248
|
+
'w-tree__item--disabled': item[this.itemDisabledKey],
|
|
225
249
|
'w-tree__item--empty': item.branch && !item.children,
|
|
226
250
|
'w-tree__item--unexpandable': item.branch && !item.children && this.unexpandableEmpty
|
|
227
251
|
}
|
|
@@ -264,6 +288,7 @@ $expand-icon-size: 20px;
|
|
|
264
288
|
position: relative;
|
|
265
289
|
display: inline-flex;
|
|
266
290
|
align-items: center;
|
|
291
|
+
user-select: none;
|
|
267
292
|
|
|
268
293
|
&:before {
|
|
269
294
|
content: '';
|
|
@@ -274,16 +299,24 @@ $expand-icon-size: 20px;
|
|
|
274
299
|
right: - $base-increment - 2px;
|
|
275
300
|
border-radius: $border-radius;
|
|
276
301
|
}
|
|
302
|
+
&:hover:before {background-color: rgba($primary, 0.05);}
|
|
277
303
|
&:focus:before {background-color: rgba($primary, 0.1);}
|
|
278
304
|
}
|
|
279
305
|
&__item--leaf &__item-label:before {
|
|
280
306
|
left: - $base-increment;
|
|
281
307
|
right: - $base-increment;
|
|
282
308
|
}
|
|
309
|
+
&__item--disabled &__item-label {opacity: 0.5;}
|
|
310
|
+
&__item--disabled &__item-label:before {display: none;}
|
|
283
311
|
|
|
284
312
|
&__item-expand {margin-right: 2px;}
|
|
285
313
|
|
|
286
314
|
&__item--branch > &__item-label {cursor: pointer;}
|
|
315
|
+
&__item--disabled > &__item-label {
|
|
316
|
+
color: $disabled-color;
|
|
317
|
+
cursor: not-allowed;
|
|
318
|
+
-webkit-tap-highlight-color: transparent;
|
|
319
|
+
}
|
|
287
320
|
&__item--unexpandable > &__item-label {
|
|
288
321
|
margin-left: $expand-icon-size + 2px;
|
|
289
322
|
cursor: auto;
|
package/src/wave-ui/core.js
CHANGED
|
@@ -1,40 +1,45 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { mergeConfig } from './utils/config'
|
|
2
2
|
import NotificationManager from './utils/notification-manager'
|
|
3
|
-
import
|
|
3
|
+
import { colorPalette, generateColorShades, flattenColors } from './utils/colors'
|
|
4
4
|
// import * as directives from './directives'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Inject presets into a Vue component props defaults before its registration into the app.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} component the Vue component to inject presets into.
|
|
10
|
+
* @param {Object} presets the presets to inject. E.g. `{ bgColor: 'green' }`.
|
|
11
|
+
*/
|
|
12
|
+
const injectPresets = (component, presets) => {
|
|
13
|
+
for (const preset in presets) {
|
|
14
|
+
component.props[preset].default = presets[preset]
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
export default class WaveUI {
|
|
13
19
|
static instance = null
|
|
14
20
|
static vueInstance = null // Needed until constructor is called.
|
|
15
|
-
#notificationManager
|
|
16
21
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// Exposed as a global object and also `app.provide`d.
|
|
23
|
+
// Accessible from this.$waveui, or inject('$waveui').
|
|
24
|
+
$waveui = {
|
|
25
|
+
breakpoint: {
|
|
26
|
+
name: '',
|
|
27
|
+
xs: false,
|
|
28
|
+
sm: false,
|
|
29
|
+
md: false,
|
|
30
|
+
lg: false,
|
|
31
|
+
xl: false
|
|
32
|
+
},
|
|
33
|
+
config: {},
|
|
34
|
+
colors: {}, // Object of pairs of color-name => color hex.
|
|
35
|
+
_notificationManager: null,
|
|
36
|
+
|
|
37
|
+
// Callable from this.$waveui.
|
|
38
|
+
notify (...args) {
|
|
39
|
+
this._notificationManager.notify(...args)
|
|
40
|
+
}
|
|
25
41
|
}
|
|
26
42
|
|
|
27
|
-
// A public object containing pairs of color-name => color hex.
|
|
28
|
-
// Accessible from anywhere via `this.$waveui.colors`.
|
|
29
|
-
// These colors generate the CSS in `w-app` on mounted.
|
|
30
|
-
colors = colors.reduce((obj, color) => {
|
|
31
|
-
obj[color.label] = color.color
|
|
32
|
-
color.shades.forEach(shade => (obj[shade.label] = shade.color))
|
|
33
|
-
return obj
|
|
34
|
-
}, { ...config.colors, black: '#000', white: '#fff', transparent: 'transparent', inherit: 'inherit' })
|
|
35
|
-
|
|
36
|
-
config = {} // Store and expose the config in the $waveui object.
|
|
37
|
-
|
|
38
43
|
static install (Vue, options = {}) {
|
|
39
44
|
// Register directives.
|
|
40
45
|
// for (const id in directives) {
|
|
@@ -57,6 +62,8 @@ export default class WaveUI {
|
|
|
57
62
|
const { components = {} } = options || {}
|
|
58
63
|
for (let id in components) {
|
|
59
64
|
const component = components[id]
|
|
65
|
+
// If presets are defined for this component inject them into the props defaults.
|
|
66
|
+
if (options.presets?.[component.name]) injectPresets(component, options.presets[component.name])
|
|
60
67
|
Vue.component(component.name, component)
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -74,53 +81,22 @@ export default class WaveUI {
|
|
|
74
81
|
constructor (options = {}) {
|
|
75
82
|
if (WaveUI.instance) return WaveUI.instance
|
|
76
83
|
|
|
77
|
-
|
|
78
|
-
this.#notificationManager = new NotificationManager()
|
|
79
|
-
|
|
80
|
-
// Merge user options into the default config.
|
|
81
|
-
mergeConfig(options)
|
|
82
|
-
|
|
83
|
-
// Add color shades for each custom color given in options.
|
|
84
|
-
if (config.css.colorShades) {
|
|
85
|
-
config.colorShades = {}
|
|
86
|
-
|
|
87
|
-
for (let color in config.colors) {
|
|
88
|
-
color = { label: color, color: config.colors[color].replace('#', '') }
|
|
89
|
-
const col = color.color
|
|
90
|
-
if (col.length === 3) color.color = col[0] + '' + col[0] + col[1] + col[1] + col[2] + col[2]
|
|
84
|
+
this.$waveui._notificationManager = new NotificationManager()
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
// Merge user options into the default config.
|
|
87
|
+
this.$waveui.config = mergeConfig(options)
|
|
88
|
+
const config = this.$waveui.config
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
this.colors[`${color.label}-light${i}`] = lighterColor
|
|
98
|
-
this.colors[`${color.label}-dark${i}`] = darkerColor
|
|
90
|
+
// Generates color shades for each color of each theme and store in the config.colors object.
|
|
91
|
+
if (config.css.colorShades) generateColorShades(config)
|
|
92
|
+
this.$waveui.colors = flattenColors(config.colors, colorPalette)
|
|
99
93
|
|
|
100
|
-
|
|
101
|
-
config.colorShades[`${color.label}-light${i}`] = lighterColor
|
|
102
|
-
config.colorShades[`${color.label}-dark${i}`] = darkerColor
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
this.config = config
|
|
108
|
-
this.notify = (...args) => notificationManager.notify(...args)
|
|
109
|
-
WaveUI.instance = this
|
|
94
|
+
WaveUI.instance = this
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
// Make Wave UI reactive and expose the single instance in the app.
|
|
97
|
+
const $waveui = WaveUI.vueInstance.observable(this.$waveui)
|
|
98
|
+
WaveUI.vueInstance.prototype.$waveui = $waveui
|
|
113
99
|
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
notify (...args) {
|
|
119
|
-
this.#notificationManager.notify(...args)
|
|
100
|
+
delete WaveUI.vueInstance // Get rid of the Vue instance that we don't need anymore.
|
|
120
101
|
}
|
|
121
102
|
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Returns the WaveUI instance. Equivalent to using `$waveui` inside templates.
|
|
125
|
-
*/
|
|
126
|
-
export const useWaveUI = () => inject('$waveui')
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
|
|
171
171
|
// Sizes.
|
|
172
172
|
// ----------------------------------------------
|
|
173
|
-
// In all the sizes
|
|
173
|
+
// In all the sizes below, round(x / 2) * 2 to always have even numbers.
|
|
174
174
|
// Different heights with a mix of odd and even numbers will misalign
|
|
175
175
|
// when vertically centering (vertical-align or align-items center).
|
|
176
176
|
.size--xs {font-size: round(0.85 * $base-font-size);}
|
|
@@ -1,4 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
const shadeColor = (color, amount) => {
|
|
2
|
+
return '#' + color.slice(1).match(/../g)
|
|
3
|
+
.map(x => {
|
|
4
|
+
x = +`0x${x}` + amount
|
|
5
|
+
return (x < 0 ? 0 : (x > 255 ? 255 : x)).toString(16).padStart(2, 0)
|
|
6
|
+
})
|
|
7
|
+
.join('')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generates the color shades for each custom color and status colors for the current theme (only),
|
|
12
|
+
* and save it in the config object.
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} config
|
|
15
|
+
*/
|
|
16
|
+
export const generateColorShades = config => {
|
|
17
|
+
config.shades = {}
|
|
18
|
+
|
|
19
|
+
for (let color in config.colors) {
|
|
20
|
+
color = { label: color, color: config.colors[color].replace('#', '') }
|
|
21
|
+
const col = color.color
|
|
22
|
+
if (col.length === 3) color.color = col[0] + '' + col[0] + col[1] + col[1] + col[2] + col[2]
|
|
23
|
+
|
|
24
|
+
for (let i = 1; i <= 3; i++) {
|
|
25
|
+
const lighterColor = shadeColor(`#${color.color}`, i * 40)
|
|
26
|
+
const darkerColor = shadeColor(`#${color.color}`, -i * 40)
|
|
27
|
+
|
|
28
|
+
// Adding the shades to the config object to generate the CSS from w-app.
|
|
29
|
+
config.shades[`${color.label}-light${i}`] = lighterColor
|
|
30
|
+
config.shades[`${color.label}-dark${i}`] = darkerColor
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const flattenColors = (themeColors, colorPalette) => {
|
|
36
|
+
const colors = {
|
|
37
|
+
...colorPalette.reduce((obj, color) => {
|
|
38
|
+
obj[color.label] = color.color
|
|
39
|
+
const shades = (color.shades || []).reduce((obj, color) => {
|
|
40
|
+
obj[color.label] = color.color
|
|
41
|
+
return obj
|
|
42
|
+
}, {})
|
|
43
|
+
return { ...obj, ...shades }
|
|
44
|
+
}, { ...themeColors, ...themeColors.shades })
|
|
45
|
+
}
|
|
46
|
+
delete colors.shades
|
|
47
|
+
|
|
48
|
+
return colors
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const colorPalette = [
|
|
2
52
|
{
|
|
3
53
|
label: 'pink',
|
|
4
54
|
color: '#e91e63',
|
|
@@ -342,5 +392,9 @@ export default [
|
|
|
342
392
|
{ label: 'grey-dark5', color: '#353535' },
|
|
343
393
|
{ label: 'grey-dark6', color: '#252525' }
|
|
344
394
|
]
|
|
345
|
-
}
|
|
395
|
+
},
|
|
396
|
+
{ label: 'black', color: '#000' },
|
|
397
|
+
{ label: 'white', color: '#fff' },
|
|
398
|
+
{ label: 'transparent', color: 'transparent' },
|
|
399
|
+
{ label: 'inherit', color: 'inherit' }
|
|
346
400
|
]
|
|
@@ -11,7 +11,7 @@ const config = Vue.observable({
|
|
|
11
11
|
},
|
|
12
12
|
css: {
|
|
13
13
|
// Generate shades for custom colors and status colors.
|
|
14
|
-
//
|
|
14
|
+
// Note: the color palette shades are always generated separately from SCSS.
|
|
15
15
|
colorShades: true,
|
|
16
16
|
|
|
17
17
|
// Generate palette colors and palette color shades.
|
|
@@ -27,10 +27,10 @@ const config = Vue.observable({
|
|
|
27
27
|
colors: {
|
|
28
28
|
primary: '#234781',
|
|
29
29
|
secondary: '#d3ebff',
|
|
30
|
-
|
|
31
|
-
error: '#f65555',
|
|
30
|
+
info: '#3d9ff5',
|
|
32
31
|
warning: '#f80',
|
|
33
|
-
|
|
32
|
+
success: '#54b946',
|
|
33
|
+
error: '#f65555'
|
|
34
34
|
},
|
|
35
35
|
icons: [],
|
|
36
36
|
iconsLigature: false,
|
|
@@ -44,9 +44,18 @@ const config = Vue.observable({
|
|
|
44
44
|
export { config as default }
|
|
45
45
|
|
|
46
46
|
export const mergeConfig = (options, conf = config) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
// If the conf object is empty, populate with options (case of presets).
|
|
48
|
+
if (!Object.keys(conf).length) conf = Object.assign(conf, options)
|
|
49
|
+
|
|
50
|
+
else {
|
|
51
|
+
for (const key in options) {
|
|
52
|
+
const option = options[key]
|
|
53
|
+
if (typeof option === 'object') {
|
|
54
|
+
mergeConfig(options[key], conf[key])
|
|
55
|
+
}
|
|
56
|
+
else conf[key] = option
|
|
57
|
+
}
|
|
51
58
|
}
|
|
59
|
+
|
|
60
|
+
return conf
|
|
52
61
|
}
|
|
@@ -19,8 +19,8 @@ const generateColors = config => {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// Color shades are generated in core.js, if the option is on.
|
|
22
|
-
if (config.css.colorShades && config.
|
|
23
|
-
Object.entries(config.
|
|
22
|
+
if (config.css.colorShades && config.shades) {
|
|
23
|
+
Object.entries(config.shades).forEach(([label, color]) => {
|
|
24
24
|
styles +=
|
|
25
25
|
`${cssScope} .${label}--bg{background-color:${color}}` +
|
|
26
26
|
`${cssScope} .${label}{color:${color}}`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Vue from 'vue'
|
|
2
2
|
|
|
3
3
|
export default class NotificationManager {
|
|
4
|
-
static instance
|
|
4
|
+
static #instance
|
|
5
5
|
notifications
|
|
6
6
|
// Private fields.
|
|
7
7
|
#uid // A unique ID for each notification.
|
|
@@ -9,9 +9,9 @@ export default class NotificationManager {
|
|
|
9
9
|
|
|
10
10
|
constructor () {
|
|
11
11
|
// Singleton pattern.
|
|
12
|
-
if (NotificationManager
|
|
12
|
+
if (NotificationManager.#instance) return NotificationManager.#instance
|
|
13
13
|
|
|
14
|
-
NotificationManager
|
|
14
|
+
NotificationManager.#instance = this
|
|
15
15
|
this.notifications = []
|
|
16
16
|
this.#uid = 0
|
|
17
17
|
this.#notificationDefaults = {
|