wave-ui 3.8.1 → 3.9.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 +1675 -1163
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +15 -15
- package/src/wave-ui/components/w-accordion.vue +1 -4
- package/src/wave-ui/components/w-alert.vue +1 -4
- package/src/wave-ui/components/w-autocomplete.vue +86 -25
- package/src/wave-ui/components/w-badge.vue +1 -0
- package/src/wave-ui/components/w-button/button.vue +3 -8
- package/src/wave-ui/components/w-drawer.vue +2 -8
- package/src/wave-ui/components/w-icon.vue +1 -1
- package/src/wave-ui/components/w-image.vue +2 -8
- package/src/wave-ui/components/w-input.vue +1 -1
- package/src/wave-ui/components/w-list.vue +1 -4
- package/src/wave-ui/components/w-notification-manager.vue +1 -3
- package/src/wave-ui/components/w-progress.vue +2 -8
- package/src/wave-ui/components/w-rating.vue +1 -4
- package/src/wave-ui/components/w-scrollable.vue +28 -28
- package/src/wave-ui/components/w-slider.vue +5 -4
- package/src/wave-ui/components/w-spinner.vue +2 -0
- package/src/wave-ui/components/w-switch.vue +1 -1
- package/src/wave-ui/components/w-table.vue +217 -210
- package/src/wave-ui/components/w-tabs/index.vue +1 -4
- package/src/wave-ui/components/w-tag.vue +1 -4
- package/src/wave-ui/components/w-timeline.vue +1 -0
- package/src/wave-ui/scss/_base.scss +1 -1
- package/src/wave-ui/scss/_variables.scss +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.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",
|
|
@@ -50,30 +50,30 @@
|
|
|
50
50
|
"publish-doc": "npm run build && npm run build-bundle && git add . && git commit -m 'Publish documentation on Github.' && git push && git push --tag"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@babel/core": "^7.23.
|
|
54
|
-
"@babel/eslint-parser": "^7.
|
|
55
|
-
"@faker-js/faker": "^8.
|
|
53
|
+
"@babel/core": "^7.23.7",
|
|
54
|
+
"@babel/eslint-parser": "^7.23.3",
|
|
55
|
+
"@faker-js/faker": "^8.3.1",
|
|
56
56
|
"@mdi/font": "^6.9.96",
|
|
57
|
-
"@vitejs/plugin-vue": "^
|
|
58
|
-
"@vue/compiler-sfc": "3.
|
|
57
|
+
"@vitejs/plugin-vue": "^5.0.2",
|
|
58
|
+
"@vue/compiler-sfc": "3.4.4",
|
|
59
59
|
"autoprefixer": "^10.4.16",
|
|
60
|
-
"axios": "^1.6.
|
|
61
|
-
"eslint": "^8.
|
|
62
|
-
"eslint-plugin-vue": "^9.
|
|
60
|
+
"axios": "^1.6.3",
|
|
61
|
+
"eslint": "^8.56.0",
|
|
62
|
+
"eslint-plugin-vue": "^9.19.2",
|
|
63
63
|
"font-awesome": "^4.7.0",
|
|
64
|
-
"gsap": "^3.12.
|
|
64
|
+
"gsap": "^3.12.4",
|
|
65
65
|
"ionicons": "^4.6.3",
|
|
66
66
|
"material-design-icons": "^3.0.1",
|
|
67
|
-
"postcss": "^8.4.
|
|
67
|
+
"postcss": "^8.4.32",
|
|
68
68
|
"pug": "^3.0.2",
|
|
69
69
|
"rollup-plugin-delete": "^2.0.0",
|
|
70
|
-
"sass": "^1.69.
|
|
70
|
+
"sass": "^1.69.7",
|
|
71
71
|
"simple-syntax-highlighter": "^3.0.2",
|
|
72
72
|
"splitpanes": "^3.1.5",
|
|
73
73
|
"standard": "^17.1.0",
|
|
74
|
-
"vite": "^
|
|
75
|
-
"vite-svg-loader": "^
|
|
76
|
-
"vue": "^3.
|
|
74
|
+
"vite": "^5.0.10",
|
|
75
|
+
"vite-svg-loader": "^5.1.0",
|
|
76
|
+
"vue": "^3.4.4",
|
|
77
77
|
"vue-router": "^4.2.5",
|
|
78
78
|
"vueperslides": "^3.5.1",
|
|
79
79
|
"vuex": "^4.1.0"
|
|
@@ -162,10 +162,7 @@ export default {
|
|
|
162
162
|
// ------------------------------------------------------
|
|
163
163
|
&:before, &:after {
|
|
164
164
|
position: absolute;
|
|
165
|
-
|
|
166
|
-
bottom: 0;
|
|
167
|
-
left: 0;
|
|
168
|
-
right: 0;
|
|
165
|
+
inset: 0;
|
|
169
166
|
background-color: currentColor;
|
|
170
167
|
pointer-events: none;
|
|
171
168
|
}
|
|
@@ -2,26 +2,41 @@
|
|
|
2
2
|
.w-autocomplete(:class="classes" @click="onClick")
|
|
3
3
|
template(v-if="selection.length")
|
|
4
4
|
.w-autocomplete__selection(v-for="(item, i) in selection")
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
slot(name="selection" :item="item" :unselect="i => unselectItem(i)")
|
|
6
|
+
span(v-html="item[itemLabelKey]")
|
|
7
|
+
w-button(@click.stop="unselectItem(i)" icon="wi-cross" xs text color="currentColor")
|
|
8
|
+
.w-autocomplete__placeholder(
|
|
9
|
+
v-if="!selection.length && !keywords && placeholder"
|
|
10
|
+
v-html="placeholder")
|
|
8
11
|
input.w-autocomplete__input(
|
|
9
12
|
ref="input"
|
|
10
|
-
:
|
|
13
|
+
:value="keywords"
|
|
11
14
|
v-on="inputEventListeners")
|
|
12
|
-
w-transition-slide-fade
|
|
13
|
-
ul.w-autocomplete__menu(
|
|
15
|
+
w-transition-slide-fade
|
|
16
|
+
ul.w-autocomplete__menu(
|
|
17
|
+
v-if="menuOpen"
|
|
18
|
+
ref="menu"
|
|
19
|
+
@mousedown="menuIsBeingClicked = true"
|
|
20
|
+
@mouseup="setEndOfMenuClick"
|
|
21
|
+
@touchstart="menuIsBeingClicked = true"
|
|
22
|
+
@touchend="setEndOfMenuClick")
|
|
14
23
|
li(
|
|
15
24
|
v-for="(item, i) in filteredItems"
|
|
16
25
|
:key="i"
|
|
17
|
-
@click.stop="selectItem(item)"
|
|
26
|
+
@click.stop="selectItem(item), $emit('item-click', item)"
|
|
18
27
|
:class="{ highlighted: highlightedItem === item.uid }")
|
|
19
|
-
|
|
28
|
+
slot(name="item" :item="item" :highlighted="highlightedItem === item.uid")
|
|
29
|
+
span(v-html="item[itemLabelKey]")
|
|
20
30
|
li.w-autocomplete__no-match(
|
|
21
31
|
v-if="!filteredItems.length"
|
|
22
32
|
:class="{ 'w-autocomplete__no-match--default': !$slots.noMatch }")
|
|
23
33
|
slot(name="no-match")
|
|
24
34
|
.caption(v-html="noMatch ?? 'No match.'")
|
|
35
|
+
li.w-autocomplete__extra-item(
|
|
36
|
+
v-if="$slots['extra-item']"
|
|
37
|
+
@click="selectExtraItem"
|
|
38
|
+
:class="{ highlighted: highlightedItem === 'extra-item' }")
|
|
39
|
+
slot(name="extra-item")
|
|
25
40
|
</template>
|
|
26
41
|
|
|
27
42
|
<script>
|
|
@@ -47,13 +62,17 @@ export default {
|
|
|
47
62
|
itemSearchableKey: { type: String, default: 'searchable' }
|
|
48
63
|
},
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
// item-select is also from keyboard, 'item-click' may be useful for mouseenter mouseleave events.
|
|
66
|
+
emits: ['update:modelValue', 'input', 'focus', 'blur', 'keydown', 'item-click', 'item-select', 'extra-item-select'],
|
|
51
67
|
|
|
52
68
|
data: () => ({
|
|
53
69
|
keywords: '',
|
|
54
70
|
selection: [],
|
|
55
71
|
menuOpen: false,
|
|
56
|
-
highlightedItem: null
|
|
72
|
+
highlightedItem: null,
|
|
73
|
+
// The focus-blur events occur more times than it should emit to the outside due to the menu
|
|
74
|
+
// item clicking. So keep the focus on as long as the user is interacting with the autocomplete.
|
|
75
|
+
menuIsBeingClicked: false
|
|
57
76
|
}),
|
|
58
77
|
|
|
59
78
|
computed: {
|
|
@@ -97,6 +116,7 @@ export default {
|
|
|
97
116
|
|
|
98
117
|
highlightedItemIndex () {
|
|
99
118
|
if (this.highlightedItem === null) return -1
|
|
119
|
+
else if (this.highlightedItem === 'extra-item') return this.filteredItems.length
|
|
100
120
|
return this.filteredItems.findIndex(item => item.uid === this.highlightedItem)
|
|
101
121
|
},
|
|
102
122
|
|
|
@@ -105,10 +125,19 @@ export default {
|
|
|
105
125
|
...this.$attrs,
|
|
106
126
|
input: e => {
|
|
107
127
|
this.keywords = e.target.value
|
|
108
|
-
if (typeof this.$attrs.input === 'function') this.$attrs.input(this.keywords)
|
|
109
128
|
},
|
|
110
|
-
focus:
|
|
111
|
-
|
|
129
|
+
focus: e => {
|
|
130
|
+
if (this.menuIsBeingClicked) return
|
|
131
|
+
this.onFocus(e)
|
|
132
|
+
this.$emit('focus', e)
|
|
133
|
+
},
|
|
134
|
+
blur: e => {
|
|
135
|
+
if (!this.menuIsBeingClicked) this.$emit('blur', e)
|
|
136
|
+
},
|
|
137
|
+
keydown: e => {
|
|
138
|
+
this.onKeydown(e)
|
|
139
|
+
this.$emit('keydown', e)
|
|
140
|
+
},
|
|
112
141
|
drop: this.onDrop,
|
|
113
142
|
compositionstart: this.onCompositionStart,
|
|
114
143
|
compositionupdate: this.onCompositionUpdate
|
|
@@ -137,7 +166,11 @@ export default {
|
|
|
137
166
|
this.selection.push(item)
|
|
138
167
|
this.highlightedItem = item.uid
|
|
139
168
|
this.keywords = ''
|
|
140
|
-
|
|
169
|
+
const emitPayload = this.multiple ? this.selection.map(item => item[this.itemValueKey]) : item[this.itemValueKey]
|
|
170
|
+
// Unlike input, item-select is only emitted when selecting (not unselecting).
|
|
171
|
+
this.$emit('item-select', item)
|
|
172
|
+
this.$emit('update:modelValue', emitPayload)
|
|
173
|
+
this.$emit('input', emitPayload)
|
|
141
174
|
this.$refs.input.focus()
|
|
142
175
|
if (!this.multiple) this.closeMenu()
|
|
143
176
|
},
|
|
@@ -145,10 +178,21 @@ export default {
|
|
|
145
178
|
unselectItem (i) {
|
|
146
179
|
this.selection.splice(i ?? this.selection.length - 1, 1)
|
|
147
180
|
this.highlightedItem = null
|
|
181
|
+
this.$emit('update:modelValue', null)
|
|
148
182
|
this.$emit('input', null)
|
|
149
183
|
this.$refs.input.focus()
|
|
150
184
|
},
|
|
151
185
|
|
|
186
|
+
selectExtraItem () {
|
|
187
|
+
this.keywords = ''
|
|
188
|
+
this.$emit('extra-item-select')
|
|
189
|
+
this.closeMenu()
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
setEndOfMenuClick () {
|
|
193
|
+
setTimeout(() => (this.menuIsBeingClicked = false), 100)
|
|
194
|
+
},
|
|
195
|
+
|
|
152
196
|
onClick () {
|
|
153
197
|
if (!this.openOnKeydown) this.openMenu()
|
|
154
198
|
this.$refs.input.focus()
|
|
@@ -166,7 +210,7 @@ export default {
|
|
|
166
210
|
// },
|
|
167
211
|
|
|
168
212
|
onKeydown (e) {
|
|
169
|
-
const itemsCount = this.filteredItems.length
|
|
213
|
+
const itemsCount = this.filteredItems.length + (this.$slots['extra-item'] ? 1 : 0)
|
|
170
214
|
// `e.key.length === 1`: is all the keyboard keys that generate a character.
|
|
171
215
|
if (!this.openOnKeydown || ((this.keywords || e.key.length === 1) && !this.menuOpen)) this.openMenu()
|
|
172
216
|
|
|
@@ -181,7 +225,8 @@ export default {
|
|
|
181
225
|
// Enter key.
|
|
182
226
|
else if (e.keyCode === 13) {
|
|
183
227
|
e.preventDefault() // Prevent form submissions.
|
|
184
|
-
if (this.
|
|
228
|
+
if (this.highlightedItem === 'extra-item') this.selectExtraItem()
|
|
229
|
+
else if (this.highlightedItemIndex >= 0) this.selectItem(this.filteredItems[this.highlightedItemIndex])
|
|
185
230
|
}
|
|
186
231
|
|
|
187
232
|
// Up & down arrow keys.
|
|
@@ -191,16 +236,20 @@ export default {
|
|
|
191
236
|
if (index === -1) index = e.keyCode === 38 ? itemsCount - 1 : 0
|
|
192
237
|
else index = (index + (e.keyCode === 38 ? -1 : 1) + itemsCount) % itemsCount // Never out of range.
|
|
193
238
|
|
|
194
|
-
this
|
|
239
|
+
if (this.$slots['extra-item'] && index === itemsCount - 1) this.highlightedItem = 'extra-item'
|
|
240
|
+
else this.highlightedItem = this.filteredItems[index]?.uid || 0
|
|
195
241
|
|
|
196
242
|
// Scroll the container if highlighted item is not in view.
|
|
197
243
|
const menuEl = this.$refs.menu
|
|
198
244
|
if (menuEl) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
245
|
+
if (this.$slots['extra-item'] && index === itemsCount - 1) menuEl.scrollTop = menuEl.scrollHeight
|
|
246
|
+
else {
|
|
247
|
+
const { offsetHeight: itemElHeight, offsetTop: itemElTop } = menuEl.childNodes[index] || {}
|
|
248
|
+
if (menuEl.scrollTop + menuEl.offsetHeight - itemElHeight < itemElTop) {
|
|
249
|
+
menuEl.scrollTop = itemElTop - menuEl.offsetHeight + itemElHeight
|
|
250
|
+
}
|
|
251
|
+
else if (menuEl.scrollTop > itemElTop) menuEl.scrollTop = itemElTop
|
|
202
252
|
}
|
|
203
|
-
else if (menuEl.scrollTop > itemElTop) menuEl.scrollTop = itemElTop
|
|
204
253
|
}
|
|
205
254
|
}
|
|
206
255
|
|
|
@@ -249,6 +298,18 @@ export default {
|
|
|
249
298
|
|
|
250
299
|
beforeUnmount () {
|
|
251
300
|
document.removeEventListener('click', this.onDocumentClick)
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
watch: {
|
|
304
|
+
modelValue (value) {
|
|
305
|
+
this.selection = []
|
|
306
|
+
if (value) {
|
|
307
|
+
const arrayOfValues = Array.isArray(value) ? value : [value]
|
|
308
|
+
arrayOfValues.forEach(value => {
|
|
309
|
+
this.selection.push(this.optimizedItemsForSearch.find(item => item[this.itemValueKey] === +value))
|
|
310
|
+
})
|
|
311
|
+
}
|
|
312
|
+
}
|
|
252
313
|
}
|
|
253
314
|
}
|
|
254
315
|
</script>
|
|
@@ -259,7 +320,7 @@ export default {
|
|
|
259
320
|
flex-wrap: wrap;
|
|
260
321
|
gap: 4px;
|
|
261
322
|
position: relative;
|
|
262
|
-
border-radius:
|
|
323
|
+
border-radius: $border-radius;
|
|
263
324
|
border: $border;
|
|
264
325
|
padding: 2px 4px;
|
|
265
326
|
user-select: none;
|
|
@@ -274,7 +335,7 @@ export default {
|
|
|
274
335
|
align-items: center;
|
|
275
336
|
background: rgba(var(--w-contrast-bg-color-rgb), 0.035);
|
|
276
337
|
border: 1px solid rgba(var(--w-contrast-bg-color-rgb), 0.05);
|
|
277
|
-
border-radius:
|
|
338
|
+
border-radius: $border-radius;
|
|
278
339
|
padding: 0 2px 0 4px;
|
|
279
340
|
flex-shrink: 0;
|
|
280
341
|
|
|
@@ -306,8 +367,8 @@ export default {
|
|
|
306
367
|
background-color: $base-bg-color;
|
|
307
368
|
border: 1px solid rgba(var(--w-contrast-bg-color-rgb), 0.2);
|
|
308
369
|
border-top: none;
|
|
309
|
-
border-bottom-left-radius:
|
|
310
|
-
border-bottom-right-radius:
|
|
370
|
+
border-bottom-left-radius: $border-radius;
|
|
371
|
+
border-bottom-right-radius: $border-radius;
|
|
311
372
|
overflow: auto;
|
|
312
373
|
z-index: 10;
|
|
313
374
|
|
|
@@ -203,6 +203,7 @@ $spinner-size: 40;
|
|
|
203
203
|
aspect-ratio: 1;
|
|
204
204
|
border-radius: 99em;
|
|
205
205
|
padding: 0;
|
|
206
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
206
207
|
}
|
|
207
208
|
&--tile {border-radius: initial;}
|
|
208
209
|
&--shadow {box-shadow: $box-shadow;}
|
|
@@ -236,10 +237,7 @@ $spinner-size: 40;
|
|
|
236
237
|
&:before {
|
|
237
238
|
content: '';
|
|
238
239
|
position: absolute;
|
|
239
|
-
|
|
240
|
-
left: 0;
|
|
241
|
-
right: 0;
|
|
242
|
-
bottom: 0;
|
|
240
|
+
inset: 0;
|
|
243
241
|
opacity: 0;
|
|
244
242
|
background-color: #000;
|
|
245
243
|
border-radius: inherit;
|
|
@@ -302,10 +300,7 @@ $spinner-size: 40;
|
|
|
302
300
|
|
|
303
301
|
&__loader {
|
|
304
302
|
position: absolute;
|
|
305
|
-
|
|
306
|
-
bottom: 0;
|
|
307
|
-
left: 0;
|
|
308
|
-
right: 0;
|
|
303
|
+
inset: 0;
|
|
309
304
|
display: flex;
|
|
310
305
|
align-items: center;
|
|
311
306
|
justify-content: center;
|
|
@@ -204,10 +204,7 @@ export default {
|
|
|
204
204
|
|
|
205
205
|
&--absolute {
|
|
206
206
|
position: absolute;
|
|
207
|
-
|
|
208
|
-
left: 0;
|
|
209
|
-
bottom: 0;
|
|
210
|
-
right: 0;
|
|
207
|
+
inset: 0;
|
|
211
208
|
overflow: hidden;
|
|
212
209
|
}
|
|
213
210
|
|
|
@@ -223,10 +220,7 @@ export default {
|
|
|
223
220
|
|
|
224
221
|
.w-overlay {
|
|
225
222
|
position: absolute;
|
|
226
|
-
|
|
227
|
-
bottom: 0;
|
|
228
|
-
left: 0;
|
|
229
|
-
right: 0;
|
|
223
|
+
inset: 0;
|
|
230
224
|
z-index: 2;
|
|
231
225
|
}
|
|
232
226
|
.w-drawer {position: absolute;}
|
|
@@ -111,7 +111,7 @@ export default {
|
|
|
111
111
|
line-height: 1;
|
|
112
112
|
font-size: 1.2em;
|
|
113
113
|
width: 1em;
|
|
114
|
-
// The aspect ratio will not work if the content
|
|
114
|
+
// The aspect ratio will not work if the content overflows (needs overflow hidden, but we don't want that in the library).
|
|
115
115
|
height: 1em;
|
|
116
116
|
|
|
117
117
|
&.size--xs {font-size: round(0.85 * $base-font-size);}
|
|
@@ -196,19 +196,13 @@ export default {
|
|
|
196
196
|
background-repeat: no-repeat;
|
|
197
197
|
background-size: cover;
|
|
198
198
|
position: absolute;
|
|
199
|
-
|
|
200
|
-
left: 0;
|
|
201
|
-
right: 0;
|
|
202
|
-
bottom: 0;
|
|
199
|
+
inset: 0;
|
|
203
200
|
|
|
204
201
|
&--contain {background-size: contain;}
|
|
205
202
|
|
|
206
203
|
&__loader, &__content {
|
|
207
204
|
position: absolute;
|
|
208
|
-
|
|
209
|
-
left: 0;
|
|
210
|
-
right: 0;
|
|
211
|
-
bottom: 0;
|
|
205
|
+
inset: 0;
|
|
212
206
|
display: flex;
|
|
213
207
|
justify-content: center;
|
|
214
208
|
align-items: center;
|
|
@@ -237,7 +237,7 @@ export default {
|
|
|
237
237
|
overallFilesProgress () {
|
|
238
238
|
const progress = +this.inputFiles.reduce((total, file) => total + file.progress, 0)
|
|
239
239
|
const total = progress / this.inputFiles.length
|
|
240
|
-
this.$emit('update:overallProgress', this.inputFiles.length ? total :
|
|
240
|
+
this.$emit('update:overallProgress', this.inputFiles.length ? total : 0)
|
|
241
241
|
|
|
242
242
|
return total
|
|
243
243
|
},
|
|
@@ -154,10 +154,7 @@ $circle-size: 40;
|
|
|
154
154
|
&.w-progress--default-bg:after {
|
|
155
155
|
content: '';
|
|
156
156
|
position: absolute;
|
|
157
|
-
|
|
158
|
-
bottom: 0;
|
|
159
|
-
left: 0;
|
|
160
|
-
right: 0;
|
|
157
|
+
inset: 0;
|
|
161
158
|
border-radius: inherit;
|
|
162
159
|
background-color: currentColor;
|
|
163
160
|
opacity: 0.15;
|
|
@@ -188,10 +185,7 @@ $circle-size: 40;
|
|
|
188
185
|
&:before, &:after {
|
|
189
186
|
content: '';
|
|
190
187
|
position: absolute;
|
|
191
|
-
|
|
192
|
-
bottom: 0;
|
|
193
|
-
left: 0;
|
|
194
|
-
right: -5%;
|
|
188
|
+
inset: 0 -5% 0 0;
|
|
195
189
|
background: currentColor;
|
|
196
190
|
z-index: 1;
|
|
197
191
|
will-change: transform;
|
|
@@ -238,10 +238,7 @@ export default {
|
|
|
238
238
|
&__button:after {
|
|
239
239
|
content: "";
|
|
240
240
|
position: absolute;
|
|
241
|
-
|
|
242
|
-
left: 0;
|
|
243
|
-
right: 0;
|
|
244
|
-
bottom: 0;
|
|
241
|
+
inset: 0;
|
|
245
242
|
background-color: currentColor;
|
|
246
243
|
border-radius: 100%;
|
|
247
244
|
transform: translateX(100%) scale(0);
|
|
@@ -15,23 +15,23 @@
|
|
|
15
15
|
<script>
|
|
16
16
|
const domProps = {
|
|
17
17
|
h: {
|
|
18
|
-
|
|
18
|
+
direction: 'horizontal',
|
|
19
19
|
topOrLeft: 'left',
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
size: 'width',
|
|
21
|
+
offsetSize: 'offsetWidth',
|
|
22
|
+
maxSize: 'max-width',
|
|
23
|
+
scrollSize: 'scrollWidth',
|
|
24
24
|
clientXorY: 'clientX',
|
|
25
25
|
deltaXorY: 'deltaX',
|
|
26
26
|
scrollTopOrLeft: 'scrollLeft'
|
|
27
27
|
},
|
|
28
28
|
v: {
|
|
29
|
-
|
|
29
|
+
direction: 'vertical',
|
|
30
30
|
topOrLeft: 'top',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
size: 'height',
|
|
32
|
+
offsetSize: 'offsetHeight',
|
|
33
|
+
maxSize: 'max-height',
|
|
34
|
+
scrollSize: 'scrollHeight',
|
|
35
35
|
clientXorY: 'clientY',
|
|
36
36
|
deltaXorY: 'deltaY',
|
|
37
37
|
scrollTopOrLeft: 'scrollTop'
|
|
@@ -72,27 +72,26 @@ export default {
|
|
|
72
72
|
|
|
73
73
|
scrollableClasses () {
|
|
74
74
|
return {
|
|
75
|
-
[`w-scrollable--${this.m.
|
|
75
|
+
[`w-scrollable--${this.m.direction}`]: true
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
78
|
|
|
79
79
|
scrollbarClasses () {
|
|
80
80
|
return {
|
|
81
|
-
[`w-scrollbar--${this.m.
|
|
81
|
+
[`w-scrollbar--${this.m.direction}`]: true
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
84
|
|
|
85
85
|
thumbSizePercent () {
|
|
86
86
|
if (!this.mounted) return 0
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return (widthOrHeight * 100 / this.$refs.scrollable?.[this.m.scrollWidthOrHeight]) || 0
|
|
87
|
+
const size = this[this.m.size] ?? this.$refs.scrollable[[this.m.offsetSize]]
|
|
88
|
+
// if (size === undefined) size = this.$refs.scrollable.offsetSize
|
|
89
|
+
return (size * 100 / this.$refs.scrollable?.[this.m.scrollSize]) || 0
|
|
91
90
|
},
|
|
92
91
|
|
|
93
92
|
scrollableStyles () {
|
|
94
93
|
return {
|
|
95
|
-
[this.m.
|
|
94
|
+
[this.m.maxSize]: `${this[this.m.size]}px`
|
|
96
95
|
}
|
|
97
96
|
},
|
|
98
97
|
|
|
@@ -100,7 +99,7 @@ export default {
|
|
|
100
99
|
let topOrLeftValue = this.scrollValuePercent
|
|
101
100
|
topOrLeftValue = Math.max(0, Math.min(topOrLeftValue, 100 - this.thumbSizePercent))
|
|
102
101
|
return {
|
|
103
|
-
[this.m.
|
|
102
|
+
[this.m.size]: `${this.thumbSizePercent}%`,
|
|
104
103
|
[this.m.topOrLeft]: `${topOrLeftValue}%`
|
|
105
104
|
}
|
|
106
105
|
}
|
|
@@ -149,6 +148,9 @@ export default {
|
|
|
149
148
|
this.scrollable.hovered = false
|
|
150
149
|
},
|
|
151
150
|
|
|
151
|
+
onResize (e) {
|
|
152
|
+
},
|
|
153
|
+
|
|
152
154
|
onMouseWheel (e) {
|
|
153
155
|
if (!this.scrollable.hovered) return // Only scroll a w-scrollable element that is being hovered.
|
|
154
156
|
|
|
@@ -166,12 +168,12 @@ export default {
|
|
|
166
168
|
computeScroll (cursorPositionXorY) {
|
|
167
169
|
const { top, left, width, height } = this.$refs.scrollable.getBoundingClientRect()
|
|
168
170
|
const topOrLeft = this.isHorizontal ? left : top
|
|
169
|
-
const
|
|
170
|
-
this.scrollValuePercent = Math.max(0, Math.min(((cursorPositionXorY - topOrLeft) /
|
|
171
|
+
const size = this.isHorizontal ? width : height
|
|
172
|
+
this.scrollValuePercent = Math.max(0, Math.min(((cursorPositionXorY - topOrLeft) / size) * 100, 100))
|
|
171
173
|
},
|
|
172
174
|
|
|
173
175
|
scroll () {
|
|
174
|
-
this.$refs.scrollable[this.m.scrollTopOrLeft] = this.scrollValuePercent * this.$refs.scrollable?.[this.m.
|
|
176
|
+
this.$refs.scrollable[this.m.scrollTopOrLeft] = this.scrollValuePercent * this.$refs.scrollable?.[this.m.scrollSize] / 100
|
|
175
177
|
this.updateThumbPosition()
|
|
176
178
|
},
|
|
177
179
|
|
|
@@ -187,7 +189,9 @@ export default {
|
|
|
187
189
|
this.scrollable.left = left
|
|
188
190
|
|
|
189
191
|
this.$el.parentNode.style.position = 'relative'
|
|
190
|
-
this.$el.parentNode.style
|
|
192
|
+
this.$el.parentNode.style.padding = 0
|
|
193
|
+
|
|
194
|
+
window.addEventListener('resize', this.onResize)
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
197
|
</script>
|
|
@@ -204,15 +208,11 @@ export default {
|
|
|
204
208
|
user-select: none;
|
|
205
209
|
|
|
206
210
|
&--horizontal {
|
|
207
|
-
|
|
208
|
-
right: 0;
|
|
209
|
-
bottom: 0;
|
|
211
|
+
inset: auto 0 0;
|
|
210
212
|
height: 8px;
|
|
211
213
|
}
|
|
212
214
|
&--vertical {
|
|
213
|
-
|
|
214
|
-
bottom: 0;
|
|
215
|
-
right: 0;
|
|
215
|
+
inset: 0 0 0 auto;
|
|
216
216
|
width: 8px;
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -302,6 +302,7 @@ export default {
|
|
|
302
302
|
top: 0;
|
|
303
303
|
width: $base-increment;
|
|
304
304
|
aspect-ratio: 1;
|
|
305
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
305
306
|
background-color: $slider-step-label-bg-color;
|
|
306
307
|
border-radius: 99em;
|
|
307
308
|
// box-shadow: 0 0 0 1px #fff;
|
|
@@ -365,6 +366,7 @@ export default {
|
|
|
365
366
|
position: absolute;
|
|
366
367
|
width: 3 * $base-increment;
|
|
367
368
|
aspect-ratio: 1;
|
|
369
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
368
370
|
left: 100%;
|
|
369
371
|
top: 50%;
|
|
370
372
|
transform: translate(-50%, -50%);
|
|
@@ -380,6 +382,7 @@ export default {
|
|
|
380
382
|
top: 0;
|
|
381
383
|
width: 100%;
|
|
382
384
|
aspect-ratio: 1;
|
|
385
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
383
386
|
border: none;
|
|
384
387
|
border-radius: 99em;
|
|
385
388
|
cursor: pointer;
|
|
@@ -395,10 +398,7 @@ export default {
|
|
|
395
398
|
}
|
|
396
399
|
// Colored border on thumb when hover and active - but with a transparency.
|
|
397
400
|
&:before {
|
|
398
|
-
|
|
399
|
-
right: 0;
|
|
400
|
-
top: 0;
|
|
401
|
-
bottom: 0;
|
|
401
|
+
inset: 0;
|
|
402
402
|
opacity: 0.5;
|
|
403
403
|
border: 1px solid currentColor;
|
|
404
404
|
}
|
|
@@ -459,6 +459,7 @@ export default {
|
|
|
459
459
|
border-radius: 99em 99em 99em 0;
|
|
460
460
|
width: 2.8em;
|
|
461
461
|
aspect-ratio: 1;
|
|
462
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
462
463
|
|
|
463
464
|
& > div {
|
|
464
465
|
position: absolute;
|
|
@@ -62,6 +62,7 @@ export default {
|
|
|
62
62
|
font-size: 2rem;
|
|
63
63
|
width: 1em;
|
|
64
64
|
aspect-ratio: 1;
|
|
65
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
65
66
|
|
|
66
67
|
&.size--xs {font-size: round(0.9 * divide($base-font-size, 2)) * 2;}
|
|
67
68
|
&.size--sm {font-size: round(1.5 * $base-font-size);}
|
|
@@ -74,6 +75,7 @@ export default {
|
|
|
74
75
|
position: absolute;
|
|
75
76
|
width: 100%;
|
|
76
77
|
aspect-ratio: 1;
|
|
78
|
+
min-width: 0; // Safari ratio fix (e.g. losing ratio if height is set and side padding are added).
|
|
77
79
|
top: 0;
|
|
78
80
|
left: 0;
|
|
79
81
|
background-color: currentColor;
|