wave-ui 3.14.3 → 3.16.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-ui",
3
- "version": "3.14.3",
3
+ "version": "3.16.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",
@@ -43,39 +43,38 @@
43
43
  "ui"
44
44
  ],
45
45
  "devDependencies": {
46
- "@eslint/js": "^9.8.0",
46
+ "@eslint/js": "^9.10.0",
47
47
  "@faker-js/faker": "^8.4.1",
48
- "@mdi/font": "^6.9.96",
49
- "@tsconfig/recommended": "^1.0.6",
50
- "@typescript-eslint/eslint-plugin": "^6.21.0",
51
- "@typescript-eslint/parser": "^6.21.0",
52
- "@vitejs/plugin-vue": "^5.0.5",
53
- "@vue/compiler-sfc": "3.4.26",
54
- "autoprefixer": "^10.4.19",
55
- "axios": "^1.7.2",
56
- "eslint": "^9.8.0",
48
+ "@mdi/font": "^7.4.47",
49
+ "@tsconfig/recommended": "^1.0.7",
50
+ "@typescript-eslint/eslint-plugin": "^8.4.0",
51
+ "@typescript-eslint/parser": "^8.4.0",
52
+ "@vitejs/plugin-vue": "^5.1.3",
53
+ "autoprefixer": "^10.4.20",
54
+ "axios": "^1.7.7",
55
+ "eslint": "^9.10.0",
57
56
  "eslint-config-standard": "^17.1.0",
58
- "eslint-plugin-import": "^2.29.1",
59
- "eslint-plugin-n": "^17.10.1",
60
- "eslint-plugin-promise": "^7.0.0",
61
- "eslint-plugin-vue": "^9.27.0",
57
+ "eslint-plugin-import": "^2.30.0",
58
+ "eslint-plugin-n": "^17.10.2",
59
+ "eslint-plugin-promise": "^7.1.0",
60
+ "eslint-plugin-vue": "^9.28.0",
62
61
  "font-awesome": "^4.7.0",
63
62
  "globals": "^15.9.0",
64
63
  "gsap": "^3.12.5",
65
64
  "ionicons": "^4.6.3",
66
65
  "material-design-icons": "^3.0.1",
67
- "postcss": "^8.4.38",
66
+ "postcss": "^8.4.45",
68
67
  "pug": "^3.0.3",
69
68
  "rollup-plugin-delete": "^2.0.0",
70
- "sass": "^1.77.6",
71
- "simple-syntax-highlighter": "^3.0.5",
69
+ "sass": "^1.78.0",
70
+ "simple-syntax-highlighter": "^3.0.10",
72
71
  "splitpanes": "^3.1.5",
73
- "typescript": "^5.5.2",
74
- "typescript-eslint": "^8.0.0",
75
- "vite": "^5.3.1",
72
+ "typescript": "^5.5.4",
73
+ "typescript-eslint": "^8.4.0",
74
+ "vite": "^5.4.3",
76
75
  "vite-svg-loader": "^5.1.0",
77
- "vue": "^3.4.30",
78
- "vue-router": "^4.4.0",
76
+ "vue": "^3.5.3",
77
+ "vue-router": "^4.4.3",
79
78
  "vueperslides": "^3.5.1",
80
79
  "vuex": "^4.1.0"
81
80
  },
@@ -87,7 +86,7 @@
87
86
  "build": "vite build --base /wave-ui/",
88
87
  "build-types": "tsc -p ./tsconfig.json",
89
88
  "build-bundle": "BUNDLE=true vite build && npm run build-types && mv ./dist/style.css ./dist/wave-ui.css",
90
- "serve": "vite preview --base /wave-ui/",
89
+ "preview": "vite preview --base /wave-ui/",
91
90
  "lint": "vite lint",
92
91
  "publish-doc": "npm run build && npm run build-bundle && git add . && git commit -m 'Publish documentation on Github.' && git push && git push --tag"
93
92
  }
@@ -2,7 +2,7 @@
2
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
- w-icon.w-alert__icon.mr2(v-if="type || icon") {{ type ? typeIcon : icon }}
5
+ w-icon.w-alert__icon(v-if="type || icon") {{ type ? typeIcon : icon }}
6
6
  .w-alert__content
7
7
  slot
8
8
  w-button.w-alert__dismiss(
@@ -31,6 +31,7 @@ export default {
31
31
  iconOutside: { type: Boolean },
32
32
  plain: { type: Boolean },
33
33
  dismiss: { type: Boolean },
34
+ bold: { type: Boolean },
34
35
  // Types (with icon).
35
36
  success: { type: Boolean },
36
37
  info: { type: Boolean },
@@ -43,14 +44,12 @@ export default {
43
44
  lg: { type: Boolean },
44
45
  xl: { type: Boolean },
45
46
  // Borders.
46
- noBorder: { type: Boolean },
47
+ border: { type: Boolean },
47
48
  borderLeft: { type: Boolean },
48
49
  borderRight: { type: Boolean },
49
50
  borderTop: { type: Boolean },
50
51
  borderBottom: { type: Boolean },
51
- outline: { type: Boolean },
52
- dark: { type: Boolean },
53
- light: { type: Boolean }
52
+ outline: { type: Boolean }
54
53
  },
55
54
 
56
55
  emits: ['input', 'update:modelValue', 'close'],
@@ -93,14 +92,16 @@ export default {
93
92
  },
94
93
 
95
94
  hasSingleBorder () {
96
- return this.borderLeft || this.borderRight ||
97
- this.borderTop || this.borderBottom
95
+ return this.borderLeft || this.borderRight || this.borderTop || this.borderBottom
98
96
  },
99
97
 
100
98
  classes () {
99
+ const bgColor = this.bgColor || (this.plain && this.type)
100
+ const color = this.color || (!this.plain && this.type) || (!bgColor && 'primary')
101
+
101
102
  return {
102
- [`${this.bgColor || (this.plain && this.type)}--bg w-alert--bg`]: this.bgColor || (this.plain && this.type),
103
- [this.color || (!this.plain && this.type)]: this.color || (!this.plain && this.type),
103
+ [`${bgColor}--bg w-alert--bg`]: bgColor,
104
+ [color]: color,
104
105
  [`size--${this.presetSize}`]: this.presetSize,
105
106
  [`w-alert--${this.type}`]: this.type,
106
107
  'w-alert--has-icon': this.type || this.icon || this.dismiss,
@@ -109,15 +110,14 @@ export default {
109
110
  'w-alert--outline': this.outline,
110
111
  'w-alert--tile': this.tile,
111
112
  'w-alert--round': this.round,
112
- 'w-alert--no-border': this.noBorder || (this.plain && this.type),
113
113
  'w-alert--one-border': this.hasSingleBorder || this.iconOutside,
114
114
  'w-alert--border-left': (!this.noBorder && this.borderLeft) || this.iconOutside,
115
115
  'w-alert--border-right': !this.noBorder && this.borderRight,
116
116
  'w-alert--border-top': !this.noBorder && this.borderTop,
117
117
  'w-alert--border-bottom': !this.noBorder && this.borderBottom,
118
+ 'w-alert--border': this.border && !this.hasSingleBorder,
118
119
  'w-alert--shadow': this.shadow,
119
- 'w-alert--dark': this.dark,
120
- 'w-alert--light': this.light
120
+ 'w-alert--bold': this.bold
121
121
  }
122
122
  }
123
123
  },
@@ -136,19 +136,19 @@ export default {
136
136
  margin-top: 4 * $base-increment;
137
137
  margin-bottom: 4 * $base-increment;
138
138
  padding: 2 * $base-increment;
139
- font-size: round(1.1 * $base-font-size);
140
- font-weight: 700;
139
+ font-size: $base-font-size;
141
140
  border-radius: $border-radius;
142
- border: 1px solid currentColor;
141
+ border: 0 solid currentColor;
143
142
 
144
143
  @include themeable;
145
144
 
145
+ &--bold {font-weight: 700;}
146
146
  &--has-icon {
147
147
  display: flex;
148
148
  align-items: center;
149
149
  }
150
150
 
151
- &--outline {border-color: currentColor;}
151
+ &--border, &--outline {border-width: 1px;}
152
152
  &--tile {border-radius: 0;}
153
153
  &--round {
154
154
  border-radius: 99em;
@@ -156,7 +156,7 @@ export default {
156
156
  padding-right: 3 * $base-increment;
157
157
  }
158
158
  &--shadow {box-shadow: $box-shadow;}
159
- &--no-border, &--one-border, &--plain {border: transparent;}
159
+ &--one-border, &--plain {border: transparent;}
160
160
 
161
161
  // Before for the border, after for the background color.
162
162
  // ------------------------------------------------------
@@ -224,7 +224,7 @@ export default {
224
224
  margin-right: 2 * $base-increment;
225
225
  font-size: 1.3em;
226
226
  }
227
- &--has-icon &__content {flex-grow: 1;align-self: flex-start;}
227
+ &--has-icon &__content {flex-grow: 1;}
228
228
  @-moz-document url-prefix() {
229
229
  &--has-icon &__content {margin-top: 0.18em;}
230
230
  }
@@ -1,17 +1,20 @@
1
1
  <template lang="pug">
2
- component.w-image-wrap(:is="wrapperTag" :class="wrapperClasses" :style="wrapperStyles")
2
+ component.w-image(:is="wrapperTag" :class="wrapperClasses" :style="wrapperStyles")
3
3
  transition(:name="transition" appear)
4
- component.w-image(
4
+ component.w-image__image(
5
5
  v-if="loaded"
6
- :is="tag"
6
+ :is="normalized.tag"
7
7
  :class="imageClasses"
8
8
  :style="imageStyles"
9
- :src="tag === 'img' ? imgSrc : null")
10
- .w-image__loader(v-if="!noSpinner && loading")
9
+ :src="normalized.tag === 'img' ? computedImg.src : null")
10
+ span.w-image__loader(v-if="!noSpinner && loading")
11
11
  slot(v-if="$slots.loading" name="loading")
12
12
  w-progress(v-else circle indeterminate v-bind="spinnerColor ? { color: spinnerColor } : {}")
13
13
  component.w-image__content(v-if="$slots.default" :is="wrapperTag" :class="contentClass")
14
14
  slot
15
+ figcaption.w-image__caption.caption(v-if="$slots.caption" :class="captionClass")
16
+ slot(name="caption")
17
+ figcaption.w-image__caption.caption(v-else-if="caption" :class="captionClass" v-html="caption")
15
18
  </template>
16
19
 
17
20
  <script>
@@ -23,7 +26,7 @@ component.w-image-wrap(:is="wrapperTag" :class="wrapperClasses" :style="wrapperS
23
26
  * - adaptive size: given ratio + height 100% (use bg)
24
27
  * - adaptive & locked size: given width or height and using <img>
25
28
  *
26
- * @todo handle figure, captions, srcset, webp.
29
+ * @todo handle srcset.
27
30
  **/
28
31
 
29
32
  import { consoleWarn } from '../utils/console'
@@ -31,10 +34,12 @@ import { consoleWarn } from '../utils/console'
31
34
  export default {
32
35
  name: 'w-image',
33
36
  props: {
34
- tag: { type: String, default: 'span' },
37
+ tag: { type: String, default: 'span' }, // span, div, figure, img.
35
38
  src: { type: String },
36
39
  width: { type: [Number, String] },
37
40
  height: { type: [Number, String] },
41
+ maxWidth: { type: [Number, String] },
42
+ maxHeight: { type: [Number, String] },
38
43
  ratio: { type: [Number, String] },
39
44
  lazy: { type: Boolean },
40
45
  absolute: { type: Boolean },
@@ -44,7 +49,9 @@ export default {
44
49
  spinnerColor: { type: String },
45
50
  fallback: { type: String },
46
51
  transition: { type: String, default: 'fade' },
47
- contentClass: { type: [String, Array, Object] }
52
+ contentClass: { type: [String, Array, Object] },
53
+ caption: { type: String },
54
+ captionClass: { type: String }
48
55
  },
49
56
 
50
57
  emits: ['loading', 'loaded', 'error'],
@@ -53,49 +60,78 @@ export default {
53
60
  return {
54
61
  loading: false,
55
62
  loaded: false,
56
- imgSrc: '',
57
- imgWidth: this.width || 0,
58
- imgHeight: this.height || 0,
59
- imgComputedRatio: 0
63
+ // The computed image source, and real image dimensions.
64
+ computedImg: {
65
+ src: '',
66
+ width: 0,
67
+ height: 0,
68
+ ratio: 0
69
+ }
60
70
  }
61
71
  },
62
72
 
63
73
  computed: {
64
- imgGivenRatio () {
65
- return parseFloat(this.ratio)
74
+ // Normalized props.
75
+ normalized () {
76
+ return {
77
+ width: (!isNaN(this.width) ? `${this.width}px` : this.width) || null,
78
+ height: (!isNaN(this.height) ? `${this.height}px` : this.height) || null,
79
+ maxWidth: (!isNaN(this.maxWidth) ? `${this.maxWidth}px` : this.maxWidth) || null,
80
+ maxHeight: (!isNaN(this.maxHeight) ? `${this.maxHeight}px` : this.maxHeight) || null,
81
+ ratio: parseFloat(this.ratio) || undefined,
82
+ tag: this.tag === 'img' || this.tag === 'figure' || this.caption ? 'img' : 'span'
83
+ }
66
84
  },
67
85
 
68
86
  wrapperTag () {
87
+ if (this.caption || this.tag === 'figure') return 'figure'
69
88
  return ['span', 'div'].includes(this.tag) ? this.tag : 'span'
70
89
  },
71
90
 
72
91
  wrapperClasses () {
73
92
  return {
74
- 'w-image-wrap--absolute': this.absolute,
75
- 'w-image-wrap--fixed': this.fixed,
76
- 'w-image-wrap--has-ratio': this.imgGivenRatio
93
+ 'w-image--absolute': this.absolute,
94
+ 'w-image--fixed': this.fixed,
95
+ 'w-image--has-ratio': this.normalized.ratio
77
96
  }
78
97
  },
79
98
 
80
99
  wrapperStyles () {
100
+ let width = this.normalized.width
101
+ const height = this.normalized.height
102
+ let maxWidth = this.normalized.maxWidth
103
+ let aspectRatio = this.normalized.ratio
104
+
105
+ if (aspectRatio && !width && !height) width = '100%'
106
+ else if (!width && !height) {
107
+ width = '100%'
108
+ maxWidth = this.normalized.maxWidth || `${this.computedImg.width}px`
109
+ aspectRatio = aspectRatio || (this.computedImg.width / this.computedImg.height)
110
+ }
111
+ else if ((width && !height) || (height && !width)) {
112
+ aspectRatio = aspectRatio || (this.computedImg.width / this.computedImg.height)
113
+ }
114
+
81
115
  return {
82
- width: this.imgGivenRatio ? null : ((!isNaN(this.imgWidth) ? `${this.imgWidth}px` : this.imgWidth) || null),
83
- height: this.imgGivenRatio || this.tag === 'img' ? null : ((!isNaN(this.imgHeight) ? `${this.imgHeight}px` : this.imgHeight) || null),
84
- 'padding-bottom': this.imgGivenRatio && `${this.imgGivenRatio * 100}%`
116
+ width,
117
+ height,
118
+ maxWidth,
119
+ maxHeight: this.normalized.maxHeight,
120
+ aspectRatio
85
121
  }
86
122
  },
87
123
 
88
124
  imageClasses () {
89
125
  return {
90
- 'w-image--loading': this.loading,
91
- 'w-image--loaded': this.loaded,
92
- 'w-image--contain': this.contain
126
+ 'w-image__image--loading': this.loading,
127
+ 'w-image__image--loaded': this.loaded,
128
+ 'w-image__image--contain': this.contain
93
129
  }
94
130
  },
95
131
 
96
132
  imageStyles () {
97
133
  return {
98
- 'background-image': this.tag !== 'img' && this.loaded ? `url('${this.imgSrc}')` : null
134
+ 'background-image': this.normalized.tag !== 'img' && this.loaded ? `url('${this.computedImg.src}')` : null
99
135
  }
100
136
  }
101
137
  },
@@ -112,16 +148,14 @@ export default {
112
148
  return new Promise(resolve => {
113
149
  const img = new Image()
114
150
  img.onload = e => {
115
- if (!this.width && !this.height && !this.imgGivenRatio) {
116
- this.imgWidth = e.target.width
117
- this.imgHeight = e.target.height
118
- }
119
- this.imgComputedRatio = e.target.height / e.target.width
151
+ this.computedImg.width = e.target.width
152
+ this.computedImg.height = e.target.height
153
+ this.computedImg.ratio = e.target.height / e.target.width
120
154
 
121
155
  this.loading = false
122
156
  this.loaded = true
123
- this.imgSrc = loadFallback ? this.fallback : this.src
124
- this.$emit('loaded', this.imgSrc)
157
+ this.computedImg.src = loadFallback ? this.fallback : this.src
158
+ this.$emit('loaded', this.computedImg.src)
125
159
 
126
160
  return resolve(img)
127
161
  }
@@ -162,43 +196,28 @@ export default {
162
196
  watch: {
163
197
  src () {
164
198
  this.loadImage()
165
- },
166
- width (value) {
167
- this.imgWidth = value
168
- },
169
- height (value) {
170
- this.imgHeight = value
171
199
  }
172
200
  }
173
201
  }
174
202
  </script>
175
203
 
176
204
  <style lang="scss">
177
- .w-image-wrap {
205
+ .w-image {
178
206
  position: relative;
179
207
  display: inline-flex;
208
+ flex-direction: column;
180
209
  flex-grow: 0;
181
210
  flex-shrink: 0;
182
- width: 4em;
183
211
 
184
212
  &--has-ratio {width: 100%;}
185
- &[class^="bdrs"], &[class*=" bdrs"] {overflow: hidden;}
213
+ &--has-ratio, &[class^="bdrs"], &[class*=" bdrs"] {overflow: hidden;}
186
214
 
187
215
  img {
188
216
  width: 100%;
189
- height: auto;
217
+ height: 100%; // Allow stretching by design.
218
+ overflow: hidden; // Should be contained in the parent.
190
219
  position: static;
191
220
  }
192
- }
193
-
194
- .w-image {
195
- background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); // 1x1 blank gif.
196
- background-repeat: no-repeat;
197
- background-size: cover;
198
- position: absolute;
199
- inset: 0;
200
-
201
- &--contain {background-size: contain;}
202
221
 
203
222
  &__loader, &__content {
204
223
  position: absolute;
@@ -208,5 +227,20 @@ export default {
208
227
  align-items: center;
209
228
  z-index: 1;
210
229
  }
230
+
231
+ &__image {
232
+ background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); // 1x1 blank gif.
233
+ background-repeat: no-repeat;
234
+ background-size: cover;
235
+ position: absolute;
236
+ inset: 0;
237
+
238
+ &--contain {background-size: contain;}
239
+ }
240
+
241
+ &__caption {
242
+ padding-top: $base-increment;
243
+ text-align: right;
244
+ }
211
245
  }
212
246
  </style>
@@ -168,11 +168,11 @@
168
168
  // In all the sizes below, round(x / 2) * 2 to always have even numbers.
169
169
  // Different heights with a mix of odd and even numbers will misalign
170
170
  // when vertically centering (vertical-align or align-items center).
171
- .size--xs {font-size: round(0.85 * $base-font-size);}
172
- .size--sm {font-size: round(1 * $base-font-size);}
173
- .size--md {font-size: round(1.1 * $base-font-size);}
174
- .size--lg {font-size: round(1.4 * $base-font-size);}
175
- .size--xl {font-size: round(1.65 * $base-font-size);}
171
+ .size--xs {font-size: round(0.8 * $base-font-size);}
172
+ .size--sm {font-size: round(0.9 * $base-font-size);}
173
+ .size--md {font-size: round(1 * $base-font-size);}
174
+ .size--lg {font-size: round(1.2 * $base-font-size);}
175
+ .size--xl {font-size: round(1.4 * $base-font-size);}
176
176
  // ----------------------------------------------
177
177
 
178
178
  // Grid system.
@@ -2,7 +2,6 @@
2
2
  .headline, .title1 {
3
3
  font-size: round(2.2 * $base-font-size);
4
4
  font-weight: 100;
5
- letter-spacing: 1px;
6
5
  }
7
6
 
8
7
  .title2 {