mirror of https://github.com/mashirozx/sakura.git
97 lines
1.9 KiB
Vue
97 lines
1.9 KiB
Vue
<template>
|
|
<div :class="['image__container', state]">
|
|
<img
|
|
:class="['image', state]"
|
|
:src="$props.src"
|
|
:alt="$props.alt"
|
|
:draggable="$props.draggable"
|
|
@error="handleError"
|
|
@load="handleLoad"
|
|
/>
|
|
<img
|
|
v-if="placeholderImage"
|
|
:class="['default', state]"
|
|
:src="placeholderImage"
|
|
:alt="$props.alt"
|
|
:draggable="$props.draggable"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, computed } from 'vue'
|
|
import { useState } from '@/hooks'
|
|
import gravatar from '@/utils/gravatar'
|
|
|
|
export default defineComponent({
|
|
emits: ['error', 'load'],
|
|
props: {
|
|
src: String,
|
|
placeholder: { type: String, default: '' },
|
|
avatar: { type: Boolean, default: false },
|
|
alt: String,
|
|
draggable: { type: Boolean, default: false },
|
|
},
|
|
setup(props, { emit }) {
|
|
const [state, setState] = useState('loading')
|
|
const placeholderImage = computed(() => {
|
|
if (!props.src) {
|
|
setState('error')
|
|
emit('error', new Event('error'))
|
|
}
|
|
if (props.placeholder) return props.placeholder
|
|
if (props.avatar) return gravatar('wapuu@wordpress.example')
|
|
})
|
|
|
|
const handleError = (event: Event) => {
|
|
setState('error')
|
|
emit('error', event)
|
|
}
|
|
|
|
const handleLoad = (event: Event) => {
|
|
setState('load')
|
|
emit('load', event)
|
|
}
|
|
|
|
return {
|
|
placeholderImage,
|
|
handleError,
|
|
handleLoad,
|
|
state,
|
|
}
|
|
},
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@use '@/styles/mixins/skeleton';
|
|
.image__container {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
&.loading,
|
|
&.error {
|
|
@include skeleton.skeleton-loading;
|
|
}
|
|
.image,
|
|
.default {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: var(--object-fit, cover);
|
|
}
|
|
.image {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
&.error {
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
.default {
|
|
.load {
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
}
|
|
</style>
|