You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.8 KiB
Vue

<template>
<view class="wd-skeleton" :class="[props.customClass]" :style="props.customStyle">
<view class="wd-skeleton__content" v-if="parsedRowCols.length">
<view class="wd-skeleton__row" v-for="(row, index) of parsedRowCols" :key="`row-${index}`">
<view v-for="(col, idx) of row" :key="`col-${idx}`" :class="col.class" :style="col.style" />
</view>
</view>
</view>
</template>
<script lang="ts">
export default {
// #ifdef H5
name: 'wd-skeleton',
// #endif
options: { virtualHost: true, addGlobalClass: true, styleIsolation: 'shared' }
}
</script>
<script lang="ts" setup>
import type { CSSProperties } from 'vue'
import { ref, computed, watch } from 'vue'
import type { SkeletonRowCol, SkeletonRowColObj } from './types'
import { skeletonProps } from './types'
import { isNumber, addUnit } from '../common/util'
const themeMap = {
avatar: [{ type: 'circle', height: '64px', width: '64px' }],
image: [{ type: 'rect', height: '64px', width: '64px' }],
text: [
1,
[
{ width: '24%', height: '16px', marginRight: '16px' },
{ width: '76%', height: '16px' }
]
],
paragraph: [1, 1, 1, { width: '55%' }]
}
const props = defineProps(skeletonProps)
const rowCols = ref<SkeletonRowCol>([])
const parsedRowCols = computed(() => {
return rowCols.value.map((item) => {
if (isNumber(item)) {
return [
{
class: getColItemClass({ type: 'text' }),
style: {}
}
]
}
if (Array.isArray(item)) {
return item.map((col) => {
return {
...col,
class: getColItemClass(col),
style: getColItemStyle(col)
}
})
}
const nItem = item as SkeletonRowColObj
return [
{
...nItem,
class: getColItemClass(nItem),
style: getColItemStyle(nItem)
}
]
})
})
function getColItemClass(rowCol: SkeletonRowColObj) {
return ['wd-skeleton__col', `wd-skeleton--type-${rowCol.type || 'text'}`, { [`wd-skeleton--animation-${props.animation}`]: props.animation }]
}
function getColItemStyle(rowCol: SkeletonRowColObj) {
const style: CSSProperties = {}
const styleName = ['size', 'width', 'height', 'margin', 'background', 'marginLeft', 'marginRight', 'borderRadius', 'backgroundColor']
for (const name of styleName) {
if (Object.prototype.hasOwnProperty.call(rowCol, name)) {
const px = addUnit(rowCol[name])
if (name === 'size') {
style.width = px
style.height = px
} else {
style[name] = px
}
}
}
return style
}
watch(
() => props.rowCol,
(rowCol) => {
rowCols.value = [...(Array.isArray(rowCol) && rowCol.length ? props.rowCol : themeMap[props.theme])]
},
{ immediate: true }
)
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>