You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.9 KiB
64 lines
1.9 KiB
import { Image, StyleSheet, Text, View } from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import type { ComponentProps } from 'react';
|
|
import { colors } from '../../../src/theme';
|
|
import { ASSET_REGISTRY, type AssetName } from '../assets';
|
|
|
|
type IconName = ComponentProps<typeof Ionicons>['name'];
|
|
|
|
interface Props {
|
|
/** 素材位名(见 assets.ts 的 ASSET_REGISTRY) */
|
|
name: AssetName;
|
|
width: number;
|
|
height: number;
|
|
radius?: number;
|
|
}
|
|
|
|
/**
|
|
* 内容配图槽位:素材已提供则渲染真实图,否则画一个**带文字标注**的占位框。
|
|
*
|
|
* 与 `Illustration` 的分工:那个是「小尺寸图标位」(头像 / Logo),占位只画色块;
|
|
* 这个是「内容大图位」,占位必须让看图的人知道这里要放什么图,
|
|
* 所以把 `assets.ts` 里的 hint 直接标在页面上,补图后标注自动消失。
|
|
*/
|
|
export function ImageSlot({ name, width, height, radius = 16 }: Props) {
|
|
const def = ASSET_REGISTRY[name];
|
|
|
|
if (def.source) {
|
|
return (
|
|
<Image source={def.source} style={{ width, height, borderRadius: radius }} resizeMode="cover" />
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={[styles.slot, { width, height, borderRadius: radius, backgroundColor: def.tint }]}>
|
|
<Ionicons name={def.icon as IconName} size={26} color={colors.primary} />
|
|
<Text style={styles.tag}>配图待补</Text>
|
|
<Text style={styles.hint}>{def.hint}</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
slot: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingHorizontal: 20,
|
|
borderWidth: 1,
|
|
borderStyle: 'dashed',
|
|
borderColor: colors.primaryBorder,
|
|
},
|
|
tag: {
|
|
marginTop: 8,
|
|
fontSize: 12,
|
|
fontWeight: '700',
|
|
color: colors.primaryText,
|
|
},
|
|
hint: {
|
|
marginTop: 4,
|
|
fontSize: 12,
|
|
lineHeight: 18,
|
|
textAlign: 'center',
|
|
color: colors.textSecondary,
|
|
},
|
|
});
|
|
|