import * as React from 'react'; import { TouchableRipple, TouchableRippleProps, Text } from 'react-native-paper'; import { StyleProp, StyleSheet, TextStyle, View } from 'react-native'; import Icon from '../Icon'; import { _ } from '@joplin/lib/locale'; import shim from '@joplin/lib/shim'; import { themeStyle } from '../global-style'; export enum ToggleState { Hidden = 0, Expanded, Collapsed, } type Props = { icon: React.ReactNode|null; text: string; textStyle?: StyleProp; touchableProps: Partial; themeId: number; selected: boolean; depth: number; } & ( { toggleState: ToggleState.Collapsed|ToggleState.Expanded; onToggle: ()=> void } | { toggleState: ToggleState.Hidden; onToggle?: ()=> void } ); const SideMenuItem: React.FC = ({ icon, text, textStyle, touchableProps, toggleState, themeId, onToggle, selected, depth, }) => { const styles = useStyles({ themeId, depth, selected, hasIcon: !!icon }); let toggleButton: React.ReactNode|null = null; if (toggleState !== ToggleState.Hidden) { const collapsed = toggleState === ToggleState.Collapsed; const toggleIcon = ; toggleButton = ( {toggleIcon} ); } // React Native doesn't seem to include an equivalent to web's aria-level. // To allow screen reader users to determine whether a notebook is a subnotebook or not, // depth is specified with an accessibilityLabel: const folderDepthDescription = depth > 0 ? _('(level %d)', depth) : ''; const accessibilityLabel = `${text} ${folderDepthDescription}`.trim(); return ( {icon} {text} {toggleButton} ); }; interface StylesProps { themeId: number; depth: number; selected: boolean; hasIcon: boolean; } const useStyles = ({ themeId, depth, selected, hasIcon }: StylesProps) => { return React.useMemo(() => { const theme = themeStyle(themeId); const iconMarginRight = depth === 0 ? theme.marginSmall : theme.marginExtraSmall; return StyleSheet.create({ buttonWrapper: { flexDirection: 'row', }, button: { flex: 1, flexBasis: 'auto', height: 42, }, buttonContent: { flex: 1, flexDirection: 'row', flexBasis: 'auto', alignItems: 'center', paddingRight: theme.marginRight, backgroundColor: selected ? theme.selectedColor : undefined, paddingLeft: depth * 10 + theme.marginLeft, }, text: { ...theme.normalText, paddingLeft: hasIcon ? iconMarginRight : 0, }, toggleIcon: { ...theme.icon, fontSize: theme.fontSizeLarger, color: theme.color, }, toggleIconWrapper: { paddingLeft: theme.margin, paddingRight: theme.margin, justifyContent: 'center', backgroundColor: selected ? theme.selectedColor : undefined, }, }); }, [themeId, selected, depth, hasIcon]); }; export default SideMenuItem;