import type { ReactNode } from 'react'; import { useCallback, useState } from 'react'; import { Modal, Pressable, StyleSheet, Text, View } from 'react-native'; import { AppIcon, APP_ICON_SIZE } from './app-icon'; import { fonts, m3Colors, m3Elevation, spacing } from '../theme/proulr-theme'; export type FloatingCreateMenuAction = { id: string; label: string; tone?: 'primary' | 'surface'; icon: ReactNode; onPress: () => void; }; const MAIN_FAB_SIZE = 56; const ACTION_FAB_SIZE = 48; export function FloatingCreateMenu({ bottomInset, actions, accessibilityLabel = 'Criar conteúdo', }: { bottomInset: number; actions: FloatingCreateMenuAction[]; accessibilityLabel?: string; }) { const [open, setOpen] = useState(false); const close = useCallback(() => setOpen(false), []); const onActionPress = useCallback( (action: FloatingCreateMenuAction) => { close(); action.onPress(); }, [close], ); const orderedActions = actions; return ( <> setOpen((value) => !value)} accessibilityRole="button" accessibilityLabel={open ? 'Fechar menu de criação' : accessibilityLabel} style={({ pressed }) => [ styles.mainFab, { bottom: bottomInset + spacing.sm }, open && styles.mainFabOpen, pressed && { opacity: 0.9 }, ]} > {orderedActions.map((action) => { const isPrimary = action.tone === 'primary'; return ( onActionPress(action)} accessibilityRole="button" accessibilityLabel={action.label} style={({ pressed }) => [styles.labelBtn, pressed && { opacity: 0.85 }]} > {action.label} onActionPress(action)} accessibilityRole="button" accessibilityLabel={action.label} style={({ pressed }) => [ styles.actionFab, isPrimary ? styles.actionFabPrimary : styles.actionFabSurface, pressed && { opacity: 0.9 }, ]} > {action.icon} ); })} ); } const styles = StyleSheet.create({ mainFab: { position: 'absolute', right: spacing.sm, width: MAIN_FAB_SIZE, height: MAIN_FAB_SIZE, borderRadius: MAIN_FAB_SIZE / 2, backgroundColor: m3Colors.secondary, alignItems: 'center', justifyContent: 'center', zIndex: 20, ...m3Elevation.level3, }, mainFabOpen: { backgroundColor: m3Colors.surfaceContainerHighest, borderWidth: 1, borderColor: m3Colors.outlineVariant, }, overlay: { flex: 1, }, backdrop: { ...StyleSheet.absoluteFill, backgroundColor: m3Colors.scrim, }, stack: { position: 'absolute', right: spacing.sm, alignItems: 'flex-end', gap: spacing.md, }, row: { flexDirection: 'row', alignItems: 'center', gap: spacing.sm, }, labelBtn: { paddingHorizontal: spacing.sm, paddingVertical: spacing.xs, }, label: { color: m3Colors.onSurface, fontFamily: fonts.semibold, fontSize: 16, }, actionFab: { width: ACTION_FAB_SIZE, height: ACTION_FAB_SIZE, borderRadius: ACTION_FAB_SIZE / 2, alignItems: 'center', justifyContent: 'center', ...m3Elevation.level2, }, actionFabPrimary: { backgroundColor: m3Colors.primary, }, actionFabSurface: { backgroundColor: m3Colors.inverseSurface, }, });