import { forwardRef, memo, useMemo } from 'react'; import { Text } from 'react-native'; import type { ViewProps, TextProps, ViewStyle } from 'react-native'; import type { MD3Elevation } from '../../types/theme'; import { useActionState } from '../../hooks'; import { Surface, type SurfaceProps } from '../Surface'; import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple'; import { Icon, type IconProps, type IconType } from '../Icon'; import { FABVariant } from './types'; import { resolveStateVariant } from '../../utils'; import { StateLayer } from '../StateLayer'; import { fabStyles, iconSizeMap } from './utils'; export type Props = Omit & { /** * name of the icon * */ iconName: string; /** * type of the icon * */ iconType?: IconType; /** * icon component's props * */ iconProps?: Omit; /** * Label of the FAB, if provided the FAB will be on extended mode * */ label?: string; /** * Props of the label * */ labelProps?: Omit, 'children'>; /** * Props for the surface container * */ containerProps?: Omit; /** * Props for the innner touchable container * */ innerContainerStyle?: ViewStyle; /** * sizes of the FAB * @default 'md' * */ size?: 'sm' | 'md' | 'lg'; /** * variants of the FAB * */ variant?: FABVariant; /** * Elevation level * @default 2 * */ elevation?: MD3Elevation; /** * Props for the state layer * */ stateLayerProps?: ViewProps; }; const emptyObj = {}; const FAB = ( { iconName, iconType, iconProps = emptyObj, label, variant = 'primary', size = 'md', elevation: elevationProp, containerProps, innerContainerStyle: innerContainerStyleProp = emptyObj, labelProps = emptyObj, stateLayerProps = emptyObj, disabled = false, onPress, style, testID, ...rest }: Props, ref: any, ) => { const { hovered, actionsRef } = useActionState({ ref, actionsToListen: ['hover'] }); const elevation = useMemo( () => (elevationProp === undefined ? 3 : elevationProp), [elevationProp], ); const state = resolveStateVariant({ disabled, hovered, }); fabStyles.useVariants({ variant, size, state: state as any, }); const { containerStyle, innerContainerStyle, iconStyle, labelStyle, iconSize, stateLayerStyle, } = useMemo(() => { return { containerStyle: [fabStyles.root, style], innerContainerStyle: [fabStyles.innerContainer, innerContainerStyleProp], iconStyle: [fabStyles.icon, iconProps?.style], // @ts-ignore labelStyle: [fabStyles.label, labelProps?.style], iconSize: iconSizeMap[size], stateLayerStyle: [fabStyles.stateLayer, stateLayerProps?.style], }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [ iconProps?.style, innerContainerStyleProp, labelProps?.style, stateLayerProps?.style, style, state, variant, size, ]); // TODO: abstract the stateLayer return ( <> {label && ( {label} )} ); }; export default memo(forwardRef(FAB));