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.
87 lines
2.7 KiB
87 lines
2.7 KiB
import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
import { ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
import { colors } from '../../../src/theme';
|
|
|
|
const ITEM_H = 44;
|
|
|
|
function Column({
|
|
items,
|
|
value,
|
|
onValueChange,
|
|
width,
|
|
}: {
|
|
items: string[];
|
|
value: string;
|
|
onValueChange: (v: string) => void;
|
|
width: number;
|
|
}) {
|
|
const idx = Math.max(0, items.indexOf(value));
|
|
const handleEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
const y = e.nativeEvent.contentOffset.y;
|
|
const i = Math.min(items.length - 1, Math.max(0, Math.round(y / ITEM_H)));
|
|
const v = items[i];
|
|
if (v !== value) onValueChange(v);
|
|
};
|
|
|
|
return (
|
|
<View style={[styles.col, { width }]}>
|
|
<View style={styles.highlight} pointerEvents="none" />
|
|
<ScrollView
|
|
style={styles.scroll}
|
|
showsVerticalScrollIndicator={false}
|
|
snapToInterval={ITEM_H}
|
|
snapToAlignment="center"
|
|
decelerationRate="fast"
|
|
contentOffset={{ x: 0, y: idx * ITEM_H }}
|
|
contentContainerStyle={{ paddingVertical: ITEM_H }}
|
|
onMomentumScrollEnd={handleEnd}
|
|
>
|
|
{items.map((it) => (
|
|
<View key={it} style={styles.item}>
|
|
<Text style={[styles.itemText, it === value && styles.itemTextActive]}>{it}</Text>
|
|
</View>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
interface DualProps {
|
|
year: string;
|
|
month: string;
|
|
onYearChange: (v: string) => void;
|
|
onMonthChange: (v: string) => void;
|
|
}
|
|
|
|
/** 年月双滚轮:用于出生年月 / 首次参加工作 / 入职时间 */
|
|
export function YearMonthWheel({ year, month, onYearChange, onMonthChange }: DualProps) {
|
|
const years = Array.from({ length: 40 }, (_, i) => `${2026 - i}年`);
|
|
const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
|
|
return (
|
|
<View style={styles.dual}>
|
|
<Column items={years} value={year} onValueChange={onYearChange} width={130} />
|
|
<Column items={months} value={month} onValueChange={onMonthChange} width={110} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
col: { height: ITEM_H * 3, position: 'relative' },
|
|
scroll: { flex: 1 },
|
|
highlight: {
|
|
position: 'absolute',
|
|
top: ITEM_H,
|
|
left: 0,
|
|
right: 0,
|
|
height: ITEM_H,
|
|
borderTopWidth: 1,
|
|
borderBottomWidth: 1,
|
|
borderColor: colors.border,
|
|
backgroundColor: colors.primaryLight,
|
|
opacity: 0.45,
|
|
},
|
|
item: { height: ITEM_H, alignItems: 'center', justifyContent: 'center' },
|
|
itemText: { fontSize: 18, color: colors.textHint },
|
|
itemTextActive: { fontSize: 20, fontWeight: '700', color: colors.textPrimary },
|
|
dual: { flexDirection: 'row', justifyContent: 'center', gap: 14 },
|
|
});
|
|
|