import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { useTranslation } from 'react-i18next';
import { StyleSheet, TouchableOpacity, View, Platform } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import type { CredentialSortOrder } from '@/utils/db/repositories/SettingsRepository';
import { useColors } from '@/hooks/useColorScheme';
import { SORT_OPTIONS } from '@/hooks/useItemSort';
import { ThemedText } from '@/components/themed/ThemedText';
import { ThemedView } from '@/components/themed/ThemedView';
interface SortMenuProps {
/**
* Whether the menu is visible.
*/
visible: boolean;
/**
* Current sort order.
*/
sortOrder: CredentialSortOrder;
/**
* Callback when a sort option is selected.
*/
onSelect: (order: CredentialSortOrder) => void;
/**
* Callback when the menu should close.
*/
onClose: () => void;
/**
* Optional top offset for the menu position.
* If not provided, uses default position based on platform.
*/
topOffset?: number;
}
/**
* Reusable sort menu overlay component.
* Displays a dropdown menu with sort options (Oldest First, Newest First, Alphabetical).
*/
export function SortMenu({
visible,
sortOrder,
onSelect,
onClose,
topOffset,
}: SortMenuProps): React.ReactNode {
const { t } = useTranslation();
const colors = useColors();
const insets = useSafeAreaInsets();
if (!visible) {
return null;
}
// Calculate default top offset based on platform
const defaultTopOffset = Platform.OS === 'ios' ? insets.top + 112 : 8;
const menuTop = topOffset ?? defaultTopOffset;
const styles = StyleSheet.create({
backdrop: {
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
zIndex: 1000,
},
menuOverlay: {
backgroundColor: colors.accentBackground,
borderColor: colors.accentBorder,
borderRadius: 8,
borderWidth: 1,
elevation: 8,
overflow: 'hidden',
position: 'absolute',
right: 14,
shadowColor: colors.black,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 4,
top: menuTop,
width: 200,
zIndex: 1001,
},
menuItem: {
alignItems: 'center',
flexDirection: 'row',
gap: 8,
paddingHorizontal: 16,
paddingVertical: 12,
},
menuItemIcon: {
width: 18,
},
menuItemText: {
color: colors.text,
fontSize: 14,
},
menuItemTextActive: {
color: colors.primary,
fontWeight: '600',
},
});
return (
<>
{/* Backdrop to close menu when tapping outside */}
{/* Menu content */}
{SORT_OPTIONS.map((option) => (
{
onSelect(option.value);
onClose();
}}
>
{sortOrder === option.value ? (
) : (
)}
{t(option.labelKey)}
))}
>
);
}
interface SortButtonProps {
/**
* Callback when button is pressed.
*/
onPress: () => void;
/**
* Optional style variant for different contexts.
*/
variant?: 'header' | 'inline';
}
/**
* Reusable sort button component.
* Can be used in headers or inline with other controls.
*/
export function SortButton({ onPress, variant = 'inline' }: SortButtonProps): React.ReactNode {
const colors = useColors();
const styles = StyleSheet.create({
button: {
padding: 8,
marginRight: variant === 'header' ? 8 : 0,
},
});
return (
);
}