wave-ui 2.29.0 → 2.31.2
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 +533 -497
- package/dist/wave-ui.umd.js +1 -1
- package/package.json +12 -9
- package/src/wave-ui/components/w-alert.vue +0 -1
- package/src/wave-ui/components/w-confirm.vue +35 -10
- package/src/wave-ui/components/w-input.vue +113 -32
- package/src/wave-ui/components/w-menu.vue +69 -275
- package/src/wave-ui/components/w-notification-manager.vue +9 -2
- package/src/wave-ui/components/w-progress.vue +4 -1
- package/src/wave-ui/components/w-rating.vue +1 -1
- package/src/wave-ui/components/w-select.vue +2 -2
- package/src/wave-ui/components/w-spinner.vue +2 -2
- package/src/wave-ui/components/w-table.vue +2 -2
- package/src/wave-ui/components/w-tag.vue +17 -6
- package/src/wave-ui/components/w-tooltip.vue +107 -223
- package/src/wave-ui/core.js +0 -8
- package/src/wave-ui/mixins/detachable.js +321 -0
- package/src/wave-ui/scss/_mixins.scss +23 -12
- 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": "2.
|
|
3
|
+
"version": "2.31.2",
|
|
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,29 +43,32 @@
|
|
|
43
43
|
"*.vue"
|
|
44
44
|
],
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@babel/core": "^7.
|
|
47
|
-
"@babel/eslint-parser": "^7.
|
|
48
|
-
"@babel/plugin-proposal-class-properties": "^7.16.
|
|
46
|
+
"@babel/core": "^7.17.0",
|
|
47
|
+
"@babel/eslint-parser": "^7.17.0",
|
|
48
|
+
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
|
49
49
|
"@mdi/font": "^5.9.55",
|
|
50
50
|
"@vitejs/plugin-vue": "^1.10.2",
|
|
51
51
|
"@vue/compiler-sfc": "3.1.5",
|
|
52
|
-
"autoprefixer": "^10.4.
|
|
53
|
-
"axios": "^0.
|
|
52
|
+
"autoprefixer": "^10.4.2",
|
|
53
|
+
"axios": "^0.25.0",
|
|
54
54
|
"eslint": "^7.32.0",
|
|
55
55
|
"font-awesome": "^4.7.0",
|
|
56
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.
|
|
60
|
+
"sass": "^1.49.7",
|
|
61
61
|
"simple-syntax-highlighter": "^2.2.0",
|
|
62
62
|
"splitpanes": "^3.0.6",
|
|
63
|
-
"vite": "^2.7.
|
|
63
|
+
"vite": "^2.7.13",
|
|
64
64
|
"vite-plugin-pug": "^0.3.0",
|
|
65
|
-
"vue": "^3.2.
|
|
65
|
+
"vue": "^3.2.31",
|
|
66
66
|
"vue-cal": "^4.2.0",
|
|
67
67
|
"vue-router": "^4.0.12",
|
|
68
68
|
"vueperslides": "^3.3.2",
|
|
69
69
|
"vuex": "^4.0.2"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"postcss": "^8.4.6"
|
|
70
73
|
}
|
|
71
74
|
}
|
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
.w-confirm
|
|
3
3
|
w-menu(v-model="showPopup" v-bind="wMenuProps")
|
|
4
4
|
template(#activator="{ on }")
|
|
5
|
-
w-button.w-confirm__button(v-
|
|
5
|
+
w-button.w-confirm__button(v-bind="{ ...$attrs, ...buttonProps, ...on }")
|
|
6
6
|
slot
|
|
7
7
|
w-flex(:column="!inline" align-center)
|
|
8
8
|
div
|
|
9
|
-
slot(name="question")
|
|
9
|
+
slot(name="question") {{ question }}
|
|
10
10
|
.w-flex.justify-end(:class="inline ? 'ml2' : 'mt2'")
|
|
11
11
|
w-button.mr2(
|
|
12
|
-
v-if="
|
|
13
|
-
v-bind="
|
|
12
|
+
v-if="cancel !== false"
|
|
13
|
+
v-bind="cancelButtonProps"
|
|
14
14
|
:bg-color="(cancelButton || {}).bgColor || 'error'"
|
|
15
15
|
@click="onCancel")
|
|
16
|
-
slot(name="cancel")
|
|
16
|
+
slot(name="cancel") {{ cancelButton.label }}
|
|
17
17
|
w-button(
|
|
18
|
-
v-bind="
|
|
18
|
+
v-bind="confirmButtonProps"
|
|
19
19
|
:bg-color="(confirmButton || {}).bgColor || 'success'"
|
|
20
20
|
@click="onConfirm")
|
|
21
|
-
slot(name="confirm")
|
|
21
|
+
slot(name="confirm") {{ confirmButton.label }}
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
24
|
<script>
|
|
@@ -30,11 +30,16 @@ export default {
|
|
|
30
30
|
color: { type: String },
|
|
31
31
|
icon: { type: String },
|
|
32
32
|
mainButton: { type: Object }, // Allow passing down an object of props to the w-button component.
|
|
33
|
+
question: { type: String, default: 'Are you sure?' },
|
|
33
34
|
|
|
34
35
|
// Cancel & confirm buttons props.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// Allow passing down an object of props to the w-button component.
|
|
37
|
+
// If a string is given, that will be the label of the button.
|
|
38
|
+
// If false, no cancel button.
|
|
39
|
+
cancel: { type: [Boolean, Object, String], default: undefined },
|
|
40
|
+
// Allow passing down an object of props to the w-button component.
|
|
41
|
+
// If a string is given, that will be the label of the button.
|
|
42
|
+
confirm: { type: [Object, String] },
|
|
38
43
|
|
|
39
44
|
// global menu props.
|
|
40
45
|
inline: { type: Boolean }, // The layout inside the menu.
|
|
@@ -63,6 +68,26 @@ export default {
|
|
|
63
68
|
}),
|
|
64
69
|
|
|
65
70
|
computed: {
|
|
71
|
+
cancelButton () {
|
|
72
|
+
let button = { label: typeof this.cancel === 'string' ? this.cancel : 'Cancel' }
|
|
73
|
+
if (typeof this.cancel === 'object') button = Object.assign({}, button, this.cancel)
|
|
74
|
+
return button
|
|
75
|
+
},
|
|
76
|
+
// Props to pass down to the w-button component.
|
|
77
|
+
cancelButtonProps () {
|
|
78
|
+
const { label, ...props } = this.cancelButton // Everything except label.
|
|
79
|
+
return props
|
|
80
|
+
},
|
|
81
|
+
confirmButton () {
|
|
82
|
+
let button = { label: typeof this.confirm === 'string' ? this.confirm : 'Confirm' }
|
|
83
|
+
if (typeof this.confirm === 'object') button = Object.assign({}, button, this.confirm)
|
|
84
|
+
return button
|
|
85
|
+
},
|
|
86
|
+
// Props to pass down to the w-button component.
|
|
87
|
+
confirmButtonProps () {
|
|
88
|
+
const { label, ...props } = this.confirmButton // Everything except label.
|
|
89
|
+
return props
|
|
90
|
+
},
|
|
66
91
|
wMenuProps () {
|
|
67
92
|
return {
|
|
68
93
|
top: this.top,
|
|
@@ -12,9 +12,16 @@ component(
|
|
|
12
12
|
template(v-else)
|
|
13
13
|
//- Left label.
|
|
14
14
|
template(v-if="labelPosition === 'left'")
|
|
15
|
-
label.w-input__label.w-input__label--left.w-form-el-shakable(
|
|
15
|
+
label.w-input__label.w-input__label--left.w-form-el-shakable(
|
|
16
|
+
v-if="$slots.default"
|
|
17
|
+
:for="`w-input--${_.uid}`"
|
|
18
|
+
:class="validationClasses")
|
|
16
19
|
slot
|
|
17
|
-
label.w-input__label.w-input__label--left.w-form-el-shakable(
|
|
20
|
+
label.w-input__label.w-input__label--left.w-form-el-shakable(
|
|
21
|
+
v-else-if="label"
|
|
22
|
+
:for="`w-input--${_.uid}`"
|
|
23
|
+
:class="validationClasses"
|
|
24
|
+
v-html="label")
|
|
18
25
|
|
|
19
26
|
//- Input wrapper.
|
|
20
27
|
.w-input__input-wrap(:class="inputWrapClasses")
|
|
@@ -58,35 +65,45 @@ component(
|
|
|
58
65
|
@blur="onBlur"
|
|
59
66
|
@change="onFileChange"
|
|
60
67
|
:multiple="multiple || null"
|
|
61
|
-
v-bind="attrs"
|
|
62
|
-
|
|
68
|
+
v-bind="attrs"
|
|
69
|
+
:data-progress="overallFilesProgress /* Needed to emit the overallProgress. */")
|
|
70
|
+
transition-group.w-input__input.w-input__input--file(
|
|
71
|
+
tag="label"
|
|
72
|
+
name="fade"
|
|
73
|
+
:for="`w-input--${_.uid}`")
|
|
63
74
|
span.w-input__no-file(v-if="!inputFiles.length && isFocused" key="no-file")
|
|
64
75
|
slot(name="no-file")
|
|
65
76
|
template(v-if="$slots['no-file'] === undefined") No file
|
|
66
77
|
span(v-for="(file, i) in inputFiles" :key="file.lastModified")
|
|
67
78
|
| {{ i ? ', ': '' }}
|
|
68
79
|
span.filename(:key="`${i}b`") {{ file.base }}
|
|
69
|
-
| {{ file.extension }}
|
|
80
|
+
| {{ file.extension ? `.${file.extension}` : '' }}
|
|
70
81
|
|
|
71
82
|
template(v-if="labelPosition === 'inside' && showLabelInside")
|
|
72
83
|
label.w-input__label.w-input__label--inside.w-form-el-shakable(
|
|
73
84
|
v-if="$slots.default"
|
|
74
85
|
:for="`w-input--${_.uid}`"
|
|
75
|
-
:class="
|
|
86
|
+
:class="validationClasses")
|
|
76
87
|
slot
|
|
77
88
|
label.w-input__label.w-input__label--inside.w-form-el-shakable(
|
|
78
89
|
v-else-if="label"
|
|
79
90
|
:for="`w-input--${_.uid}`"
|
|
80
91
|
v-html="label"
|
|
81
|
-
:class="
|
|
92
|
+
:class="validationClasses")
|
|
82
93
|
w-icon.w-input__icon.w-input__icon--inner-right(
|
|
83
94
|
v-if="innerIconRight"
|
|
84
95
|
tag="label"
|
|
85
96
|
:for="`w-input--${_.uid}`"
|
|
86
97
|
@click="$emit('click:inner-icon-right', $event)") {{ innerIconRight }}
|
|
87
98
|
|
|
99
|
+
w-progress.fill-width(
|
|
100
|
+
v-if="hasLoading || (showProgress && (uploadInProgress || uploadComplete))"
|
|
101
|
+
size="2"
|
|
102
|
+
:color="progressColor || color"
|
|
103
|
+
:model-value="showProgress ? (uploadInProgress || uploadComplete) && overallFilesProgress : loadingValue")
|
|
104
|
+
|
|
88
105
|
//- Files preview.
|
|
89
|
-
label.d-flex(v-if="type === 'file' && inputFiles.length" :for="`w-input--${_.uid}`")
|
|
106
|
+
label.d-flex(v-if="type === 'file' && preview && inputFiles.length" :for="`w-input--${_.uid}`")
|
|
90
107
|
template(v-for="(file, i) in inputFiles")
|
|
91
108
|
i.w-icon.wi-spinner.w-icon--spin.size--sm.w-input__file-preview.primary(
|
|
92
109
|
v-if="file.progress < 100"
|
|
@@ -96,20 +113,23 @@ component(
|
|
|
96
113
|
:key="`${i}b`"
|
|
97
114
|
:src="file.preview"
|
|
98
115
|
alt="")
|
|
99
|
-
i.w-icon.
|
|
116
|
+
i.w-icon.w-input__file-preview.primary.size--md(
|
|
117
|
+
v-else
|
|
118
|
+
:key="`${i}c`"
|
|
119
|
+
:class="preview && typeof preview === 'string' ? preview : 'wi-file'")
|
|
100
120
|
|
|
101
121
|
//- Right label.
|
|
102
122
|
template(v-if="labelPosition === 'right'")
|
|
103
123
|
label.w-input__label.w-input__label--right.w-form-el-shakable(
|
|
104
124
|
v-if="$slots.default"
|
|
105
|
-
:for="`w-input--${_.uid}`"
|
|
125
|
+
:for="`w-input--${_.uid}`"
|
|
126
|
+
:class="validationClasses")
|
|
106
127
|
slot
|
|
107
128
|
label.w-input__label.w-input__label--right.w-form-el-shakable(
|
|
108
129
|
v-else-if="label"
|
|
109
130
|
:for="`w-input--${_.uid}`"
|
|
131
|
+
:class="validationClasses"
|
|
110
132
|
v-html="label")
|
|
111
|
-
|
|
112
|
-
w-progress.fill-width(v-if="loading" size="2" :color="progressColor || color")
|
|
113
133
|
</template>
|
|
114
134
|
|
|
115
135
|
<script>
|
|
@@ -148,13 +168,17 @@ export default {
|
|
|
148
168
|
shadow: { type: Boolean },
|
|
149
169
|
tile: { type: Boolean },
|
|
150
170
|
multiple: { type: Boolean }, // Only for file uploads.
|
|
151
|
-
preview: { type: Boolean }, // Only for file uploads.
|
|
152
|
-
loading: { type: Boolean }
|
|
171
|
+
preview: { type: [Boolean, String], default: true }, // Only for file uploads.
|
|
172
|
+
loading: { type: [Boolean, Number], default: false }, // If a number is given, it will be the value of the progress.
|
|
173
|
+
showProgress: { type: [Boolean] }, // Only for file uploads.
|
|
174
|
+
// Allow syncing the files 1 way: prefilling a file is not possible.
|
|
175
|
+
// https://stackoverflow.com/questions/16365668/pre-populate-html-form-file-input
|
|
176
|
+
files: { type: Array }
|
|
153
177
|
// Props from mixin: name, disabled, readonly, required, tabindex, validators.
|
|
154
178
|
// Computed from mixin: inputName, isDisabled & isReadonly.
|
|
155
179
|
},
|
|
156
180
|
|
|
157
|
-
emits: ['input', 'update:modelValue', 'focus', 'blur', 'click:inner-icon-left', 'click:inner-icon-right'],
|
|
181
|
+
emits: ['input', 'update:modelValue', 'focus', 'blur', 'click:inner-icon-left', 'click:inner-icon-right', 'update:overallProgress'],
|
|
158
182
|
|
|
159
183
|
data () {
|
|
160
184
|
return {
|
|
@@ -183,29 +207,62 @@ export default {
|
|
|
183
207
|
const { input, focus, blur, ...listeners } = this.$attrs
|
|
184
208
|
return listeners
|
|
185
209
|
},
|
|
210
|
+
|
|
186
211
|
attrs () {
|
|
187
212
|
// eslint-disable-next-line no-unused-vars
|
|
188
213
|
const { class: Class, ...htmlAttrs } = this.$attrs
|
|
189
214
|
return htmlAttrs
|
|
190
215
|
},
|
|
216
|
+
|
|
191
217
|
hasValue () {
|
|
192
|
-
|
|
193
|
-
this.
|
|
194
|
-
this.inputValue === 0 ||
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
218
|
+
switch (this.type) {
|
|
219
|
+
case 'file': return !!this.inputFiles.length
|
|
220
|
+
case 'number': return this.inputValue || this.inputValue === 0 || this.inputNumberError
|
|
221
|
+
case 'date':
|
|
222
|
+
case 'time':
|
|
223
|
+
return true
|
|
224
|
+
default:
|
|
225
|
+
return this.inputValue || this.inputValue === 0
|
|
226
|
+
}
|
|
199
227
|
},
|
|
200
228
|
|
|
201
229
|
hasLabel () {
|
|
202
230
|
return this.label || this.$slots.default
|
|
203
231
|
},
|
|
204
232
|
|
|
233
|
+
hasLoading () {
|
|
234
|
+
return ![undefined, false].includes(this.loading)
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
loadingValue () {
|
|
238
|
+
let value
|
|
239
|
+
if (typeof this.loading === 'number') value = this.loading
|
|
240
|
+
else if (this.loading) {
|
|
241
|
+
value = this.type === 'file' && this.overallFilesProgress ? this.overallFilesProgress : undefined
|
|
242
|
+
}
|
|
243
|
+
return value
|
|
244
|
+
},
|
|
245
|
+
|
|
205
246
|
showLabelInside () {
|
|
206
247
|
return !this.staticLabel || (!this.hasValue && !this.placeholder)
|
|
207
248
|
},
|
|
208
249
|
|
|
250
|
+
overallFilesProgress () {
|
|
251
|
+
const progress = this.inputFiles.reduce((total, file) => total + file.progress, 0)
|
|
252
|
+
const total = progress / this.inputFiles.length
|
|
253
|
+
this.$emit('update:overallProgress', this.inputFiles.length ? total : undefined)
|
|
254
|
+
|
|
255
|
+
return total
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
uploadInProgress () {
|
|
259
|
+
return this.overallFilesProgress > 0 && this.overallFilesProgress < 100
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
uploadComplete () {
|
|
263
|
+
return this.overallFilesProgress === 100
|
|
264
|
+
},
|
|
265
|
+
|
|
209
266
|
classes () {
|
|
210
267
|
return {
|
|
211
268
|
'w-input': true,
|
|
@@ -223,6 +280,12 @@ export default {
|
|
|
223
280
|
}
|
|
224
281
|
},
|
|
225
282
|
|
|
283
|
+
validationClasses () {
|
|
284
|
+
return this.isFocused && {
|
|
285
|
+
[this.valid === false ? 'error' : this.color]: this.color || this.valid === false
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
|
|
226
289
|
inputWrapClasses () {
|
|
227
290
|
return {
|
|
228
291
|
[this.valid === false ? 'error' : this.color]: this.color || this.valid === false,
|
|
@@ -235,7 +298,8 @@ export default {
|
|
|
235
298
|
'w-input__input-wrap--underline': !this.outline,
|
|
236
299
|
'w-input__input-wrap--shadow': this.shadow,
|
|
237
300
|
'w-input__input-wrap--no-padding': !this.outline && !this.bgColor && !this.shadow && !this.round,
|
|
238
|
-
'w-input__input-wrap--loading': this.loading
|
|
301
|
+
'w-input__input-wrap--loading': this.loading || (this.showProgress && this.uploadInProgress),
|
|
302
|
+
'w-input__input-wrap--upload-complete': this.uploadComplete
|
|
239
303
|
}
|
|
240
304
|
}
|
|
241
305
|
},
|
|
@@ -260,35 +324,44 @@ export default {
|
|
|
260
324
|
// For file input.
|
|
261
325
|
onFileChange (e) {
|
|
262
326
|
this.inputFiles = [...e.target.files].map(original => {
|
|
263
|
-
|
|
327
|
+
// `full` if there is no filename but only an extension.
|
|
328
|
+
const [, base = '', extension = '', full = ''] = original.name.match(/^(.*?)\.([^.]*)$|(.*)/)
|
|
329
|
+
|
|
264
330
|
const file = reactive({
|
|
265
331
|
name: original.name,
|
|
266
|
-
base,
|
|
332
|
+
base: base || full,
|
|
267
333
|
extension,
|
|
268
334
|
type: original.type,
|
|
269
335
|
size: original.size,
|
|
270
336
|
lastModified: original.lastModified,
|
|
271
337
|
preview: null,
|
|
272
|
-
progress: 0
|
|
338
|
+
progress: 0,
|
|
339
|
+
file: original
|
|
273
340
|
})
|
|
274
341
|
|
|
275
|
-
this.
|
|
342
|
+
this.readFile(original, file)
|
|
276
343
|
|
|
277
344
|
return file
|
|
278
345
|
})
|
|
279
346
|
this.$emit('update:modelValue', this.inputFiles)
|
|
347
|
+
this.$emit('input', this.inputFiles)
|
|
280
348
|
},
|
|
281
349
|
|
|
282
350
|
// For file input.
|
|
283
|
-
|
|
351
|
+
readFile (original, file) {
|
|
284
352
|
const reader = new FileReader()
|
|
285
353
|
|
|
354
|
+
// If the preview prop is a string, the user is setting the preview to an icon and
|
|
355
|
+
// don't need the actual file preview.
|
|
356
|
+
const isPreviewAnIcon = typeof this.preview === 'string'
|
|
357
|
+
const isFileAnImage = original.type && original.type.startsWith('image/')
|
|
286
358
|
// Check if the file is an image and set a preview image.
|
|
287
|
-
if (
|
|
359
|
+
if (this.preview && !isPreviewAnIcon && isFileAnImage) {
|
|
288
360
|
reader.addEventListener('load', e => {
|
|
289
361
|
file.preview = e.target.result
|
|
290
362
|
})
|
|
291
363
|
}
|
|
364
|
+
else delete file.preview
|
|
292
365
|
|
|
293
366
|
// Used to display a spinner while the file is loading.
|
|
294
367
|
reader.addEventListener('progress', e => {
|
|
@@ -303,7 +376,7 @@ export default {
|
|
|
303
376
|
// On page load, check if the field is autofilled by the browser.
|
|
304
377
|
// 20211229. Only a problem on Chrome. Firefox ok, Safari always prompts before filling up.
|
|
305
378
|
setTimeout(() => {
|
|
306
|
-
if (this.$refs.input.matches(':-webkit-autofill')) this.isAutofilled = true
|
|
379
|
+
if (this.$refs.input && this.$refs.input.matches(':-webkit-autofill')) this.isAutofilled = true
|
|
307
380
|
}, 400) // Can't be less than 350: time for the browser to autofill.
|
|
308
381
|
},
|
|
309
382
|
|
|
@@ -331,6 +404,8 @@ $inactive-color: #777;
|
|
|
331
404
|
&--file {
|
|
332
405
|
flex-wrap: nowrap;
|
|
333
406
|
align-items: flex-end;
|
|
407
|
+
|
|
408
|
+
span.fade-leave-to {position: absolute;}
|
|
334
409
|
}
|
|
335
410
|
|
|
336
411
|
// Input field wrapper.
|
|
@@ -360,7 +435,10 @@ $inactive-color: #777;
|
|
|
360
435
|
&--round {border-radius: 99em;}
|
|
361
436
|
&--tile {border-radius: initial;}
|
|
362
437
|
&--shadow {box-shadow: $box-shadow;}
|
|
363
|
-
&--loading
|
|
438
|
+
&--loading, &--upload-complete {
|
|
439
|
+
border-bottom-color: transparent;
|
|
440
|
+
flex-wrap: wrap;
|
|
441
|
+
}
|
|
364
442
|
&--loading ~ .w-progress {
|
|
365
443
|
height: 2px;
|
|
366
444
|
position: absolute;
|
|
@@ -369,7 +447,8 @@ $inactive-color: #777;
|
|
|
369
447
|
}
|
|
370
448
|
|
|
371
449
|
.w-input--focused & {border-color: currentColor;}
|
|
372
|
-
.w-input--focused &--loading
|
|
450
|
+
.w-input--focused &--loading,
|
|
451
|
+
.w-input--focused &--upload-complete {border-bottom-color: transparent;}
|
|
373
452
|
|
|
374
453
|
// Underline.
|
|
375
454
|
&--underline:after {
|
|
@@ -480,6 +559,8 @@ $inactive-color: #777;
|
|
|
480
559
|
margin-left: 4px;
|
|
481
560
|
max-height: 2em;
|
|
482
561
|
align-self: flex-end;
|
|
562
|
+
|
|
563
|
+
&.w-icon {margin-bottom: 4px;}
|
|
483
564
|
}
|
|
484
565
|
|
|
485
566
|
// Icons inside.
|