-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.vue
187 lines (154 loc) · 4.45 KB
/
index.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<!-- Vue Visual -->
<template lang='pug'>
//- Root container
.vv-visual(
:class='containerClasses'
:style='dimensionStyles')
//- Set the aspect ratio
.vv-aspect-shim(
v-if='hasAspect && !expand'
:style='{ paddingTop: aspectPadding }'
:class='shimAlignClasses')
//- Show a placeholder shape until an asset is loaded
transition(:name='transition')
.vv-placeholder(
v-if='placeholderColor && !showImage'
:style='{ backgroundColor: placeholderColor }')
//- Image asset
//- The wrapper constainer is needed for the object-fit polyfill
.vv-wrapper(v-if='image && shouldLoad')
transition(:name='transition')
picture.vv-picture(v-show='showImage')
//- Webp sources
source(
v-if='webpSrcset'
type='image/webp'
:srcset='webpSrcset'
:sizes='sizes')
//- Slotted sources
slot(name='image-source')
//- Img tag /w srcset support
img.vv-asset.vv-image(
ref='image'
:src='image'
:srcset='srcset'
:sizes='sizes'
:alt='alt'
:style='assetStyles'
@load='onAssetLoad("image")')
//- Video asset
.vv-wrapper(v-if='video && shouldLoad')
transition(:name='transition')
//- Video tag.
//- Preload because it is only rendered if it's load time.
video.vv-asset.vv-video(
v-show='showVideo'
ref='video'
playsinline
preload='auto'
:autoplay='shouldAutoplay'
:loop='loop'
:muted='muted'
:controls='controls'
:aria-label='alt'
:style='assetStyles'
@canplaythrough='onAssetLoad("video")')
//- Generated sources
source(
v-for='{src, type} in videoSources'
:key='type'
:src='src'
:type='type')
//- Slotted sources
slot(name='video-source')
//- Render content after the assets
.vv-slot(
v-if='$slots.default'
:class='slotAlignClasses'): slot
</template>
<!-- ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– -->
<script lang='coffee'>
import fitsAssets from './concerns/fits-assets.coffee'
import loadsAssets from './concerns/loads-assets.coffee'
import observesViewport from './concerns/observes-viewport'
import slotsContent from './concerns/slots-content.coffee'
import supportsImages from './concerns/supports-images'
import supportsVideos from './concerns/supports-videos'
export default
name: 'VueVisual'
mixins: [
fitsAssets
loadsAssets
observesViewport
slotsContent
supportsImages
supportsVideos
]
props: alt: String
computed:
# Classes that get added to the visual container
containerClasses: -> [
@slotsContentContainerClasses
@fitsAssetsContainerClasses
@loadsAssetsContainerClasses
].filter (val) -> !!val
</script>
<!-- ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– -->
<!-- Intentionally unscoped so they can be more easily overriden -->
<style lang='stylus'>
// Default container sizes
.vv-visual
position relative
overflow hidden
font-size 0 // For slot alignment and clearing of line-height
// Fill the parent
.vv-expand
position absolute
left 0
top 0
width 100%
height 100%
// Uses to prop block open when an aspect is passed in
.vv-aspect-shim
display inline-block
height 100%
// Expand the image if using an aspect-shim or if expanding the container
.vv-has-aspect, .vv-expand
.vv-wrapper, .vv-picture, .vv-asset
@extend .vv-expand
// Fill the space with a placeholder shape
.vv-placeholder
position absolute
left 0
top 0
width 100%
height 100%
// Slot container
.vv-slot
font-size 1rem // Restore font size
position relative // Layer above position:absolute backgrounds
display inline-block // Prep for vetical centering
max-width 100% // Prevent wrapping lines pushing slot below shim
// Add vertical align rules
.vv-align-bottom
vertical-align bottom
.vv-align-middle
vertical-align middle
.vv-align-top
vertical-align top
// Add horizontal align rules
.vv-align-left
text-align left
.vv-align-center
text-align center
.vv-align-right
text-align right
// A simple, defualt, transition
.vv-fade-enter-active, .vv-fade-leave-active
transition opacity .3s
.vv-fade-leave-active
position absolute // Crossfade when new asset is revealed
transition-delay 0.3s // Let video transition ontop
.vv-fade-enter, .vv-fade-leave-to
opacity 0
</style>