buefy 0.9.12 → 0.9.13

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.
Files changed (208) hide show
  1. package/dist/buefy.css +1 -1
  2. package/dist/buefy.esm.js +106 -104
  3. package/dist/buefy.esm.min.js +2 -2
  4. package/dist/buefy.js +106 -104
  5. package/dist/buefy.min.css +1 -1
  6. package/dist/buefy.min.js +2 -2
  7. package/dist/cjs/autocomplete.js +4 -4
  8. package/dist/cjs/button.js +2 -2
  9. package/dist/cjs/carousel.js +5 -5
  10. package/dist/cjs/{chunk-47e1b22b.js → chunk-114191ae.js} +2 -2
  11. package/dist/cjs/{chunk-db3fa73a.js → chunk-2062216d.js} +1 -1
  12. package/dist/cjs/{chunk-d9a33552.js → chunk-2911aa4b.js} +45 -45
  13. package/dist/cjs/{chunk-de7a7f98.js → chunk-2ae50815.js} +3 -3
  14. package/dist/cjs/{chunk-01268607.js → chunk-2c7de785.js} +0 -0
  15. package/dist/cjs/{chunk-30d55827.js → chunk-30670fac.js} +2 -2
  16. package/dist/cjs/{chunk-c3495010.js → chunk-34949503.js} +0 -0
  17. package/dist/cjs/{chunk-2dc027c9.js → chunk-3cc5d9a6.js} +0 -0
  18. package/dist/cjs/{chunk-a14ca5bf.js → chunk-61023b09.js} +1 -1
  19. package/dist/cjs/{chunk-c5a552d4.js → chunk-6cb902f8.js} +0 -0
  20. package/dist/cjs/{chunk-7b13241d.js → chunk-7da0c017.js} +4 -2
  21. package/dist/cjs/{chunk-bd1feb6c.js → chunk-9e4cf4c5.js} +0 -0
  22. package/dist/cjs/{chunk-ea7e1e7e.js → chunk-a11294f9.js} +1 -1
  23. package/dist/cjs/{chunk-3aaecc36.js → chunk-c6fbc7b4.js} +1 -1
  24. package/dist/cjs/{chunk-dcf024d2.js → chunk-c7b2aa4b.js} +0 -0
  25. package/dist/cjs/{chunk-40697b2f.js → chunk-d0f8ea39.js} +6 -6
  26. package/dist/cjs/{chunk-c00639be.js → chunk-d120e215.js} +0 -0
  27. package/dist/cjs/{chunk-cb3ee6f4.js → chunk-d54e40f6.js} +0 -0
  28. package/dist/cjs/{chunk-adaa5792.js → chunk-f5106717.js} +2 -2
  29. package/dist/cjs/{chunk-66710d19.js → chunk-fe2f57ee.js} +1 -1
  30. package/dist/cjs/{chunk-344f6275.js → chunk-fefd7b77.js} +0 -0
  31. package/dist/cjs/clockpicker.js +7 -7
  32. package/dist/cjs/datepicker.js +8 -8
  33. package/dist/cjs/datetimepicker.js +10 -10
  34. package/dist/cjs/dialog.js +10 -10
  35. package/dist/cjs/dropdown.js +2 -2
  36. package/dist/cjs/field.js +1 -1
  37. package/dist/cjs/helpers.js +50 -50
  38. package/dist/cjs/icon.js +1 -1
  39. package/dist/cjs/image.js +1 -1
  40. package/dist/cjs/index.js +21 -21
  41. package/dist/cjs/input.js +3 -3
  42. package/dist/cjs/loading.js +1 -1
  43. package/dist/cjs/menu.js +1 -1
  44. package/dist/cjs/message.js +2 -2
  45. package/dist/cjs/modal.js +1 -1
  46. package/dist/cjs/notification.js +3 -3
  47. package/dist/cjs/numberinput.js +6 -6
  48. package/dist/cjs/pagination.js +2 -2
  49. package/dist/cjs/progress.js +1 -1
  50. package/dist/cjs/rate.js +1 -1
  51. package/dist/cjs/select.js +3 -3
  52. package/dist/cjs/slider.js +1 -1
  53. package/dist/cjs/snackbar.js +1 -1
  54. package/dist/cjs/steps.js +4 -4
  55. package/dist/cjs/table.js +7 -7
  56. package/dist/cjs/tabs.js +4 -4
  57. package/dist/cjs/taginput.js +4 -4
  58. package/dist/cjs/timepicker.js +9 -9
  59. package/dist/cjs/toast.js +1 -1
  60. package/dist/cjs/tooltip.js +1 -1
  61. package/dist/cjs/upload.js +1 -1
  62. package/dist/components/autocomplete/index.js +5 -5
  63. package/dist/components/autocomplete/index.min.js +1 -1
  64. package/dist/components/breadcrumb/index.js +1 -1
  65. package/dist/components/breadcrumb/index.min.js +1 -1
  66. package/dist/components/button/index.js +3 -3
  67. package/dist/components/button/index.min.js +1 -1
  68. package/dist/components/carousel/index.js +26 -26
  69. package/dist/components/carousel/index.min.js +1 -1
  70. package/dist/components/checkbox/index.js +1 -1
  71. package/dist/components/checkbox/index.min.js +1 -1
  72. package/dist/components/clockpicker/index.js +22 -20
  73. package/dist/components/clockpicker/index.min.js +2 -2
  74. package/dist/components/collapse/index.js +1 -1
  75. package/dist/components/collapse/index.min.js +1 -1
  76. package/dist/components/datepicker/index.js +71 -69
  77. package/dist/components/datepicker/index.min.js +2 -2
  78. package/dist/components/datetimepicker/index.js +71 -69
  79. package/dist/components/datetimepicker/index.min.js +2 -2
  80. package/dist/components/dialog/index.js +10 -10
  81. package/dist/components/dialog/index.min.js +1 -1
  82. package/dist/components/dropdown/index.js +6 -6
  83. package/dist/components/dropdown/index.min.js +1 -1
  84. package/dist/components/field/index.js +5 -3
  85. package/dist/components/field/index.min.js +2 -2
  86. package/dist/components/icon/index.js +3 -3
  87. package/dist/components/icon/index.min.js +1 -1
  88. package/dist/components/image/index.js +4 -4
  89. package/dist/components/image/index.min.js +1 -1
  90. package/dist/components/input/index.js +3 -3
  91. package/dist/components/input/index.min.js +1 -1
  92. package/dist/components/loading/index.js +3 -3
  93. package/dist/components/loading/index.min.js +1 -1
  94. package/dist/components/menu/index.js +3 -3
  95. package/dist/components/menu/index.min.js +1 -1
  96. package/dist/components/message/index.js +3 -3
  97. package/dist/components/message/index.min.js +1 -1
  98. package/dist/components/modal/index.js +3 -3
  99. package/dist/components/modal/index.min.js +1 -1
  100. package/dist/components/navbar/index.js +1 -1
  101. package/dist/components/navbar/index.min.js +1 -1
  102. package/dist/components/notification/index.js +3 -3
  103. package/dist/components/notification/index.min.js +1 -1
  104. package/dist/components/numberinput/index.js +6 -6
  105. package/dist/components/numberinput/index.min.js +1 -1
  106. package/dist/components/pagination/index.js +3 -3
  107. package/dist/components/pagination/index.min.js +1 -1
  108. package/dist/components/progress/index.js +6 -6
  109. package/dist/components/progress/index.min.js +1 -1
  110. package/dist/components/radio/index.js +1 -1
  111. package/dist/components/radio/index.min.js +1 -1
  112. package/dist/components/rate/index.js +3 -3
  113. package/dist/components/rate/index.min.js +1 -1
  114. package/dist/components/select/index.js +3 -3
  115. package/dist/components/select/index.min.js +1 -1
  116. package/dist/components/sidebar/index.js +1 -1
  117. package/dist/components/sidebar/index.min.js +1 -1
  118. package/dist/components/skeleton/index.js +1 -1
  119. package/dist/components/skeleton/index.min.js +1 -1
  120. package/dist/components/slider/index.js +7 -7
  121. package/dist/components/slider/index.min.js +1 -1
  122. package/dist/components/snackbar/index.js +3 -3
  123. package/dist/components/snackbar/index.min.js +1 -1
  124. package/dist/components/steps/index.js +14 -14
  125. package/dist/components/steps/index.min.js +1 -1
  126. package/dist/components/switch/index.js +1 -1
  127. package/dist/components/switch/index.min.js +1 -1
  128. package/dist/components/table/index.js +10 -10
  129. package/dist/components/table/index.min.js +1 -1
  130. package/dist/components/tabs/index.js +14 -14
  131. package/dist/components/tabs/index.min.js +1 -1
  132. package/dist/components/tag/index.js +1 -1
  133. package/dist/components/tag/index.min.js +1 -1
  134. package/dist/components/taginput/index.js +5 -5
  135. package/dist/components/taginput/index.min.js +1 -1
  136. package/dist/components/timepicker/index.js +22 -20
  137. package/dist/components/timepicker/index.min.js +2 -2
  138. package/dist/components/toast/index.js +3 -3
  139. package/dist/components/toast/index.min.js +1 -1
  140. package/dist/components/tooltip/index.js +1 -1
  141. package/dist/components/tooltip/index.min.js +1 -1
  142. package/dist/components/upload/index.js +1 -1
  143. package/dist/components/upload/index.min.js +1 -1
  144. package/dist/esm/autocomplete.js +5 -5
  145. package/dist/esm/button.js +3 -3
  146. package/dist/esm/carousel.js +5 -5
  147. package/dist/esm/{chunk-3dbb54cd.js → chunk-18e8b067.js} +1 -1
  148. package/dist/esm/{chunk-7d9db167.js → chunk-21fc0948.js} +6 -6
  149. package/dist/esm/{chunk-a146937d.js → chunk-22e9f916.js} +45 -45
  150. package/dist/esm/{chunk-18fcd4ac.js → chunk-29ca0df8.js} +0 -0
  151. package/dist/esm/{chunk-affd6df1.js → chunk-3773c62d.js} +0 -0
  152. package/dist/esm/{chunk-7ee6c15c.js → chunk-4b67a181.js} +1 -1
  153. package/dist/esm/{chunk-f97f6a90.js → chunk-6019fd7a.js} +2 -2
  154. package/dist/esm/{chunk-d9794c38.js → chunk-71a547bc.js} +0 -0
  155. package/dist/esm/{chunk-161dac72.js → chunk-75a5af93.js} +0 -0
  156. package/dist/esm/{chunk-4f046bae.js → chunk-799e084d.js} +0 -0
  157. package/dist/esm/{chunk-6b53dd42.js → chunk-83eb0d37.js} +2 -2
  158. package/dist/esm/{chunk-80ec133b.js → chunk-8d0f95b8.js} +3 -3
  159. package/dist/esm/{chunk-50188ced.js → chunk-9f7f7441.js} +0 -0
  160. package/dist/esm/{chunk-3098b0e9.js → chunk-ae8ab23a.js} +2 -2
  161. package/dist/esm/{chunk-0f30042f.js → chunk-b07e3182.js} +4 -2
  162. package/dist/esm/{chunk-a64bdef6.js → chunk-b0c0c6b0.js} +0 -0
  163. package/dist/esm/{chunk-cdfb7fda.js → chunk-c9c58d0c.js} +0 -0
  164. package/dist/esm/{chunk-f6b30428.js → chunk-d7f92d97.js} +1 -1
  165. package/dist/esm/{chunk-9957ac1a.js → chunk-d92f0cd9.js} +0 -0
  166. package/dist/esm/{chunk-72ad8d50.js → chunk-e7c9b2cb.js} +1 -1
  167. package/dist/esm/{chunk-8b279c1f.js → chunk-ece062a7.js} +1 -1
  168. package/dist/esm/clockpicker.js +7 -7
  169. package/dist/esm/datepicker.js +9 -9
  170. package/dist/esm/datetimepicker.js +10 -10
  171. package/dist/esm/dialog.js +10 -10
  172. package/dist/esm/dropdown.js +3 -3
  173. package/dist/esm/field.js +2 -2
  174. package/dist/esm/helpers.js +50 -50
  175. package/dist/esm/icon.js +2 -2
  176. package/dist/esm/image.js +2 -2
  177. package/dist/esm/index.js +21 -21
  178. package/dist/esm/input.js +4 -4
  179. package/dist/esm/loading.js +2 -2
  180. package/dist/esm/menu.js +1 -1
  181. package/dist/esm/message.js +2 -2
  182. package/dist/esm/modal.js +2 -2
  183. package/dist/esm/notification.js +3 -3
  184. package/dist/esm/numberinput.js +6 -6
  185. package/dist/esm/pagination.js +3 -3
  186. package/dist/esm/progress.js +1 -1
  187. package/dist/esm/rate.js +1 -1
  188. package/dist/esm/select.js +4 -4
  189. package/dist/esm/slider.js +1 -1
  190. package/dist/esm/snackbar.js +1 -1
  191. package/dist/esm/steps.js +4 -4
  192. package/dist/esm/table.js +7 -7
  193. package/dist/esm/tabs.js +4 -4
  194. package/dist/esm/taginput.js +4 -4
  195. package/dist/esm/timepicker.js +10 -10
  196. package/dist/esm/toast.js +1 -1
  197. package/dist/esm/tooltip.js +2 -2
  198. package/dist/esm/upload.js +1 -1
  199. package/package.json +171 -171
  200. package/src/components/breadcrumb/BreadcrumbItem.spec.js +25 -25
  201. package/src/components/carousel/CarouselList.vue +313 -313
  202. package/src/components/carousel/__snapshots__/CarouselList.spec.js.snap +156 -156
  203. package/src/components/datepicker/Datepicker.vue +843 -843
  204. package/src/components/dialog/Dialog.vue +256 -256
  205. package/src/components/field/Field.vue +3 -3
  206. package/src/components/image/Image.vue +309 -309
  207. package/src/components/numberinput/Numberinput.vue +309 -309
  208. package/src/utils/helpers.js +291 -291
@@ -1,309 +1,309 @@
1
- <template>
2
- <figure
3
- class="b-image-wrapper"
4
- :class="figureClasses"
5
- :style="figureStyles"
6
- >
7
- <figcaption v-if="isCaptionFirst">
8
- <slot name="caption" />
9
- </figcaption>
10
- <transition name="fade">
11
- <img
12
- v-if="isDisplayed"
13
- :srcset="computedSrcset"
14
- :src="computedSrc"
15
- :alt="alt"
16
- :class="imgClasses"
17
- :width="computedWidth"
18
- :sizes="computedSizes"
19
- :loading="computedNativeLazy"
20
- @load="onLoad"
21
- @error="onError"
22
- >
23
- </transition>
24
- <transition name="fade">
25
- <slot
26
- v-if="isPlaceholderDisplayed"
27
- name="placeholder"
28
- >
29
- <img
30
- :src="computedPlaceholder"
31
- :alt="alt"
32
- :class="imgClasses"
33
- class="placeholder"
34
- >
35
- </slot>
36
- </transition>
37
- <figcaption v-if="isCaptionLast">
38
- <slot name="caption" />
39
- </figcaption>
40
- </figure>
41
- </template>
42
-
43
- <script>
44
- import config from '../../utils/config'
45
- import { isWebpSupported } from '../../utils/helpers'
46
-
47
- export default {
48
- name: 'BImage',
49
- props: {
50
- src: String,
51
- alt: String,
52
- srcFallback: String,
53
- webpFallback: {
54
- type: String,
55
- default: () => {
56
- return config.defaultImageWebpFallback
57
- }
58
- },
59
- lazy: {
60
- type: Boolean,
61
- default: () => {
62
- return config.defaultImageLazy
63
- }
64
- },
65
- responsive: {
66
- type: Boolean,
67
- default: () => {
68
- return config.defaultImageResponsive
69
- }
70
- },
71
- ratio: {
72
- type: String,
73
- default: () => {
74
- return config.defaultImageRatio
75
- }
76
- },
77
- placeholder: String,
78
- srcset: String,
79
- srcsetSizes: Array,
80
- srcsetFormatter: {
81
- type: Function,
82
- default: (src, size, vm) => {
83
- if (typeof config.defaultImageSrcsetFormatter === 'function') {
84
- return config.defaultImageSrcsetFormatter(src, size)
85
- } else {
86
- return vm.formatSrcset(src, size)
87
- }
88
- }
89
- },
90
- rounded: {
91
- type: Boolean,
92
- default: false
93
- },
94
- captionFirst: {
95
- type: Boolean,
96
- default: false
97
- },
98
- customClass: String
99
- },
100
- data() {
101
- return {
102
- clientWidth: 0,
103
- webpSupportVerified: false,
104
- webpSupported: false,
105
- useNativeLazy: false,
106
- observer: null,
107
- inViewPort: false,
108
- bulmaKnownRatio: ['square', '1by1', '5by4', '4by3', '3by2', '5by3', '16by9', 'b2y1', '3by1', '4by5', '3by4', '2by3', '3by5', '9by16', '1by2', '1by3'],
109
- loaded: false,
110
- failed: false
111
- }
112
- },
113
- computed: {
114
- ratioPattern() {
115
- return new RegExp(/([0-9]+)by([0-9]+)/)
116
- },
117
- hasRatio() {
118
- return this.ratio && this.ratioPattern.test(this.ratio)
119
- },
120
- figureClasses() {
121
- const classes = { image: this.responsive }
122
- if (this.hasRatio && this.bulmaKnownRatio.indexOf(this.ratio) >= 0) {
123
- classes[`is-${this.ratio}`] = true
124
- }
125
- return classes
126
- },
127
- figureStyles() {
128
- if (
129
- this.hasRatio &&
130
- this.bulmaKnownRatio.indexOf(this.ratio) < 0
131
- ) {
132
- const ratioValues = this.ratioPattern.exec(this.ratio)
133
- return {
134
- paddingTop: `${(ratioValues[2] / ratioValues[1]) * 100}%`
135
- }
136
- }
137
- },
138
- imgClasses() {
139
- return {
140
- 'is-rounded': this.rounded,
141
- 'has-ratio': this.hasRatio,
142
- [this.customClass]: !!this.customClass
143
- }
144
- },
145
- srcExt() {
146
- return this.getExt(this.src)
147
- },
148
- isWepb() {
149
- return this.srcExt === 'webp'
150
- },
151
- computedSrc() {
152
- let src = this.src
153
- if (this.failed && this.srcFallback) {
154
- src = this.srcFallback
155
- }
156
- if (!this.webpSupported && this.isWepb && this.webpFallback) {
157
- if (this.webpFallback.startsWith('.')) {
158
- return src.replace(/\.webp/gi, `${this.webpFallback}`)
159
- }
160
- return this.webpFallback
161
- }
162
- return src
163
- },
164
- computedWidth() {
165
- if (this.responsive && this.clientWidth > 0) {
166
- return this.clientWidth
167
- }
168
- },
169
- computedNativeLazy() {
170
- if (this.lazy && this.useNativeLazy) {
171
- return 'lazy'
172
- }
173
- },
174
- isDisplayed() {
175
- return (
176
- (this.webpSupportVerified || !this.isWepb) &&
177
- (!this.lazy || this.useNativeLazy || this.inViewPort)
178
- )
179
- },
180
- placeholderExt() {
181
- if (this.placeholder) {
182
- return this.getExt(this.placeholder)
183
- }
184
- },
185
- isPlaceholderWepb() {
186
- if (this.placeholder) {
187
- return this.placeholderExt === 'webp'
188
- }
189
- },
190
- computedPlaceholder() {
191
- if (!this.webpSupported && this.isPlaceholderWepb && this.webpFallback && this.webpFallback.startsWith('.')) {
192
- return this.placeholder.replace(/\.webp/gi, `${this.webpFallback}`)
193
- }
194
- return this.placeholder
195
- },
196
- isPlaceholderDisplayed() {
197
- return (
198
- !this.loaded &&
199
- (
200
- this.$slots.placeholder || (
201
- this.placeholder &&
202
- (this.webpSupportVerified || !this.isPlaceholderWepb)
203
- )
204
- )
205
- )
206
- },
207
- computedSrcset() {
208
- if (this.srcset) {
209
- if (!this.webpSupported && this.isWepb && this.webpFallback && this.webpFallback.startsWith('.')) {
210
- return this.srcset.replace(/\.webp/gi, `${this.webpFallback}`)
211
- }
212
- return this.srcset
213
- }
214
- if (
215
- this.srcsetSizes && Array.isArray(this.srcsetSizes) && this.srcsetSizes.length > 0
216
- ) {
217
- return this.srcsetSizes.map((size) => {
218
- return `${this.srcsetFormatter(this.computedSrc, size, this)} ${size}w`
219
- }).join(',')
220
- }
221
- },
222
- computedSizes() {
223
- if (this.computedSrcset && this.computedWidth) {
224
- return `${this.computedWidth}px`
225
- }
226
- },
227
- isCaptionFirst() {
228
- return this.$slots.caption && this.captionFirst
229
- },
230
- isCaptionLast() {
231
- return this.$slots.caption && !this.captionFirst
232
- }
233
- },
234
- methods: {
235
- getExt(filename, clean = true) {
236
- if (filename) {
237
- const noParam = clean ? filename.split('?')[0] : filename
238
- return noParam.split('.').pop()
239
- }
240
- return ''
241
- },
242
- setWidth() {
243
- this.clientWidth = this.$el.clientWidth
244
- },
245
- formatSrcset(src, size) {
246
- const ext = this.getExt(src, false)
247
- const name = src.split('.').slice(0, -1).join('.')
248
- return `${name}-${size}.${ext}`
249
- },
250
- onLoad(event) {
251
- this.loaded = true
252
- this.emit('load', event)
253
- },
254
- onError(event) {
255
- this.emit('error', event)
256
- if (!this.failed) {
257
- this.failed = true
258
- }
259
- },
260
- emit(eventName, event) {
261
- const { target } = event
262
- this.$emit(eventName, event, target.currentSrc || target.src || this.computedSrc)
263
- }
264
- },
265
- created() {
266
- if (this.isWepb) {
267
- isWebpSupported().then((supported) => {
268
- this.webpSupportVerified = true
269
- this.webpSupported = supported
270
- })
271
- }
272
- if (this.lazy) {
273
- // We use native lazy loading if supported
274
- // We try to use Intersection Observer if native lazy loading is not supported
275
- // We use the lazy attribute anyway if we cannot detect support (SSR for example).
276
- const nativeLazySupported = typeof window !== 'undefined' && 'HTMLImageElement' in window && 'loading' in HTMLImageElement.prototype
277
- const intersectionObserverSupported = typeof window !== 'undefined' && 'IntersectionObserver' in window
278
- if (!nativeLazySupported && intersectionObserverSupported) {
279
- this.observer = new IntersectionObserver((events) => {
280
- const {target, isIntersecting} = events[0]
281
- if (isIntersecting && !this.inViewPort) {
282
- this.inViewPort = true
283
- this.observer.unobserve(target)
284
- }
285
- })
286
- } else {
287
- this.useNativeLazy = true
288
- }
289
- }
290
- },
291
- mounted() {
292
- if (this.lazy && this.observer) {
293
- this.observer.observe(this.$el)
294
- }
295
- this.setWidth()
296
- if (typeof window !== 'undefined') {
297
- window.addEventListener('resize', this.setWidth)
298
- }
299
- },
300
- beforeDestroy() {
301
- if (this.observer) {
302
- this.observer.disconnect()
303
- }
304
- if (typeof window !== 'undefined') {
305
- window.removeEventListener('resize', this.setWidth)
306
- }
307
- }
308
- }
309
- </script>
1
+ <template>
2
+ <figure
3
+ class="b-image-wrapper"
4
+ :class="figureClasses"
5
+ :style="figureStyles"
6
+ >
7
+ <figcaption v-if="isCaptionFirst">
8
+ <slot name="caption" />
9
+ </figcaption>
10
+ <transition name="fade">
11
+ <img
12
+ v-if="isDisplayed"
13
+ :srcset="computedSrcset"
14
+ :src="computedSrc"
15
+ :alt="alt"
16
+ :class="imgClasses"
17
+ :width="computedWidth"
18
+ :sizes="computedSizes"
19
+ :loading="computedNativeLazy"
20
+ @load="onLoad"
21
+ @error="onError"
22
+ >
23
+ </transition>
24
+ <transition name="fade">
25
+ <slot
26
+ v-if="isPlaceholderDisplayed"
27
+ name="placeholder"
28
+ >
29
+ <img
30
+ :src="computedPlaceholder"
31
+ :alt="alt"
32
+ :class="imgClasses"
33
+ class="placeholder"
34
+ >
35
+ </slot>
36
+ </transition>
37
+ <figcaption v-if="isCaptionLast">
38
+ <slot name="caption" />
39
+ </figcaption>
40
+ </figure>
41
+ </template>
42
+
43
+ <script>
44
+ import config from '../../utils/config'
45
+ import { isWebpSupported } from '../../utils/helpers'
46
+
47
+ export default {
48
+ name: 'BImage',
49
+ props: {
50
+ src: String,
51
+ alt: String,
52
+ srcFallback: String,
53
+ webpFallback: {
54
+ type: String,
55
+ default: () => {
56
+ return config.defaultImageWebpFallback
57
+ }
58
+ },
59
+ lazy: {
60
+ type: Boolean,
61
+ default: () => {
62
+ return config.defaultImageLazy
63
+ }
64
+ },
65
+ responsive: {
66
+ type: Boolean,
67
+ default: () => {
68
+ return config.defaultImageResponsive
69
+ }
70
+ },
71
+ ratio: {
72
+ type: String,
73
+ default: () => {
74
+ return config.defaultImageRatio
75
+ }
76
+ },
77
+ placeholder: String,
78
+ srcset: String,
79
+ srcsetSizes: Array,
80
+ srcsetFormatter: {
81
+ type: Function,
82
+ default: (src, size, vm) => {
83
+ if (typeof config.defaultImageSrcsetFormatter === 'function') {
84
+ return config.defaultImageSrcsetFormatter(src, size)
85
+ } else {
86
+ return vm.formatSrcset(src, size)
87
+ }
88
+ }
89
+ },
90
+ rounded: {
91
+ type: Boolean,
92
+ default: false
93
+ },
94
+ captionFirst: {
95
+ type: Boolean,
96
+ default: false
97
+ },
98
+ customClass: String
99
+ },
100
+ data() {
101
+ return {
102
+ clientWidth: 0,
103
+ webpSupportVerified: false,
104
+ webpSupported: false,
105
+ useNativeLazy: false,
106
+ observer: null,
107
+ inViewPort: false,
108
+ bulmaKnownRatio: ['square', '1by1', '5by4', '4by3', '3by2', '5by3', '16by9', 'b2y1', '3by1', '4by5', '3by4', '2by3', '3by5', '9by16', '1by2', '1by3'],
109
+ loaded: false,
110
+ failed: false
111
+ }
112
+ },
113
+ computed: {
114
+ ratioPattern() {
115
+ return new RegExp(/([0-9]+)by([0-9]+)/)
116
+ },
117
+ hasRatio() {
118
+ return this.ratio && this.ratioPattern.test(this.ratio)
119
+ },
120
+ figureClasses() {
121
+ const classes = { image: this.responsive }
122
+ if (this.hasRatio && this.bulmaKnownRatio.indexOf(this.ratio) >= 0) {
123
+ classes[`is-${this.ratio}`] = true
124
+ }
125
+ return classes
126
+ },
127
+ figureStyles() {
128
+ if (
129
+ this.hasRatio &&
130
+ this.bulmaKnownRatio.indexOf(this.ratio) < 0
131
+ ) {
132
+ const ratioValues = this.ratioPattern.exec(this.ratio)
133
+ return {
134
+ paddingTop: `${(ratioValues[2] / ratioValues[1]) * 100}%`
135
+ }
136
+ }
137
+ },
138
+ imgClasses() {
139
+ return {
140
+ 'is-rounded': this.rounded,
141
+ 'has-ratio': this.hasRatio,
142
+ [this.customClass]: !!this.customClass
143
+ }
144
+ },
145
+ srcExt() {
146
+ return this.getExt(this.src)
147
+ },
148
+ isWepb() {
149
+ return this.srcExt === 'webp'
150
+ },
151
+ computedSrc() {
152
+ let src = this.src
153
+ if (this.failed && this.srcFallback) {
154
+ src = this.srcFallback
155
+ }
156
+ if (!this.webpSupported && this.isWepb && this.webpFallback) {
157
+ if (this.webpFallback.startsWith('.')) {
158
+ return src.replace(/\.webp/gi, `${this.webpFallback}`)
159
+ }
160
+ return this.webpFallback
161
+ }
162
+ return src
163
+ },
164
+ computedWidth() {
165
+ if (this.responsive && this.clientWidth > 0) {
166
+ return this.clientWidth
167
+ }
168
+ },
169
+ computedNativeLazy() {
170
+ if (this.lazy && this.useNativeLazy) {
171
+ return 'lazy'
172
+ }
173
+ },
174
+ isDisplayed() {
175
+ return (
176
+ (this.webpSupportVerified || !this.isWepb) &&
177
+ (!this.lazy || this.useNativeLazy || this.inViewPort)
178
+ )
179
+ },
180
+ placeholderExt() {
181
+ if (this.placeholder) {
182
+ return this.getExt(this.placeholder)
183
+ }
184
+ },
185
+ isPlaceholderWepb() {
186
+ if (this.placeholder) {
187
+ return this.placeholderExt === 'webp'
188
+ }
189
+ },
190
+ computedPlaceholder() {
191
+ if (!this.webpSupported && this.isPlaceholderWepb && this.webpFallback && this.webpFallback.startsWith('.')) {
192
+ return this.placeholder.replace(/\.webp/gi, `${this.webpFallback}`)
193
+ }
194
+ return this.placeholder
195
+ },
196
+ isPlaceholderDisplayed() {
197
+ return (
198
+ !this.loaded &&
199
+ (
200
+ this.$slots.placeholder || (
201
+ this.placeholder &&
202
+ (this.webpSupportVerified || !this.isPlaceholderWepb)
203
+ )
204
+ )
205
+ )
206
+ },
207
+ computedSrcset() {
208
+ if (this.srcset) {
209
+ if (!this.webpSupported && this.isWepb && this.webpFallback && this.webpFallback.startsWith('.')) {
210
+ return this.srcset.replace(/\.webp/gi, `${this.webpFallback}`)
211
+ }
212
+ return this.srcset
213
+ }
214
+ if (
215
+ this.srcsetSizes && Array.isArray(this.srcsetSizes) && this.srcsetSizes.length > 0
216
+ ) {
217
+ return this.srcsetSizes.map((size) => {
218
+ return `${this.srcsetFormatter(this.computedSrc, size, this)} ${size}w`
219
+ }).join(',')
220
+ }
221
+ },
222
+ computedSizes() {
223
+ if (this.computedSrcset && this.computedWidth) {
224
+ return `${this.computedWidth}px`
225
+ }
226
+ },
227
+ isCaptionFirst() {
228
+ return this.$slots.caption && this.captionFirst
229
+ },
230
+ isCaptionLast() {
231
+ return this.$slots.caption && !this.captionFirst
232
+ }
233
+ },
234
+ methods: {
235
+ getExt(filename, clean = true) {
236
+ if (filename) {
237
+ const noParam = clean ? filename.split('?')[0] : filename
238
+ return noParam.split('.').pop()
239
+ }
240
+ return ''
241
+ },
242
+ setWidth() {
243
+ this.clientWidth = this.$el.clientWidth
244
+ },
245
+ formatSrcset(src, size) {
246
+ const ext = this.getExt(src, false)
247
+ const name = src.split('.').slice(0, -1).join('.')
248
+ return `${name}-${size}.${ext}`
249
+ },
250
+ onLoad(event) {
251
+ this.loaded = true
252
+ this.emit('load', event)
253
+ },
254
+ onError(event) {
255
+ this.emit('error', event)
256
+ if (!this.failed) {
257
+ this.failed = true
258
+ }
259
+ },
260
+ emit(eventName, event) {
261
+ const { target } = event
262
+ this.$emit(eventName, event, target.currentSrc || target.src || this.computedSrc)
263
+ }
264
+ },
265
+ created() {
266
+ if (this.isWepb) {
267
+ isWebpSupported().then((supported) => {
268
+ this.webpSupportVerified = true
269
+ this.webpSupported = supported
270
+ })
271
+ }
272
+ if (this.lazy) {
273
+ // We use native lazy loading if supported
274
+ // We try to use Intersection Observer if native lazy loading is not supported
275
+ // We use the lazy attribute anyway if we cannot detect support (SSR for example).
276
+ const nativeLazySupported = typeof window !== 'undefined' && 'HTMLImageElement' in window && 'loading' in HTMLImageElement.prototype
277
+ const intersectionObserverSupported = typeof window !== 'undefined' && 'IntersectionObserver' in window
278
+ if (!nativeLazySupported && intersectionObserverSupported) {
279
+ this.observer = new IntersectionObserver((events) => {
280
+ const {target, isIntersecting} = events[0]
281
+ if (isIntersecting && !this.inViewPort) {
282
+ this.inViewPort = true
283
+ this.observer.unobserve(target)
284
+ }
285
+ })
286
+ } else {
287
+ this.useNativeLazy = true
288
+ }
289
+ }
290
+ },
291
+ mounted() {
292
+ if (this.lazy && this.observer) {
293
+ this.observer.observe(this.$el)
294
+ }
295
+ this.setWidth()
296
+ if (typeof window !== 'undefined') {
297
+ window.addEventListener('resize', this.setWidth)
298
+ }
299
+ },
300
+ beforeDestroy() {
301
+ if (this.observer) {
302
+ this.observer.disconnect()
303
+ }
304
+ if (typeof window !== 'undefined') {
305
+ window.removeEventListener('resize', this.setWidth)
306
+ }
307
+ }
308
+ }
309
+ </script>