Files

99 lines
2.6 KiB
TypeScript

import React, { ComponentProps, FC } from "react";
import { Image, TouchableOpacity, View } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import type { TrainIconEntry } from "@/lib/trainIconEntries";
type StackVariant = "header" | "list";
type StatusIcon = ComponentProps<typeof Ionicons>;
type Props = {
entries: TrainIconEntry[];
direction?: boolean;
hidden?: boolean;
onPressEntry?: (entry: TrainIconEntry, index: number) => void;
statusIcon?: StatusIcon;
variant?: StackVariant;
};
const iconSize = {
header: {
width: 24,
height: 30,
stackedWidth: 12,
stackedHeight: 15,
marginRight: 5,
stackedMarginLeft: -10,
stackedMarginTop: 10,
statusSize: 24,
},
list: {
width: 20,
height: 22,
stackedWidth: 10,
stackedHeight: 12,
marginRight: 2,
stackedMarginLeft: -8,
stackedMarginTop: 8,
statusSize: 18,
},
} as const;
export const TrainIconStack: FC<Props> = ({
entries,
direction,
hidden = false,
onPressEntry,
statusIcon,
variant = "header",
}) => {
const size = iconSize[variant];
return (
<View style={{ flexDirection: "row", alignItems: "flex-start" }}>
{entries.map((entry, index) => {
const trainIcon = direction
? entry.vehicle_info_img
: entry.vehicle_info_right_img || entry.vehicle_info_img;
if (!trainIcon) return null;
const content = (
<View>
<View style={{ opacity: hidden ? 0 : 1 }}>
<Image
source={{ uri: trainIcon }}
style={{
height: index > 0 ? size.stackedHeight : size.height,
width: index > 0 ? size.stackedWidth : size.width,
marginRight: size.marginRight,
marginLeft: index > 0 ? size.stackedMarginLeft : 0,
marginTop: index > 0 ? size.stackedMarginTop : 0,
}}
resizeMethod="resize"
/>
</View>
{statusIcon && hidden && (
<View style={{ position: "absolute", top: 0, left: 0 }}>
<Ionicons {...statusIcon} size={size.statusSize} />
</View>
)}
</View>
);
if (!onPressEntry) {
return <View key={`${trainIcon}-${index}`}>{content}</View>;
}
return (
<TouchableOpacity
key={`${trainIcon}-${index}`}
onPress={() => onPressEntry(entry, index)}
disabled={!entry.vehicle_info_url}
>
{content}
</TouchableOpacity>
);
})}
</View>
);
};