import React, { memo, forwardRef } from 'react'; import Spinner from '../Spinner'; import { usePropsResolution } from '../../../hooks/useThemeProps'; import { default as Box, IBoxProps } from '../Box'; import HStack from '../Stack/HStack'; import { Pressable } from '../Pressable'; import type { IButtonProps } from './types'; import { composeEventHandlers } from '../../../utils'; import { useHover, useFocus, useIsPressed, } from '../../primitives/Pressable/Pressable'; import { useFocusRing } from '@react-native-aria/focus'; import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps'; const Button = ( { //@ts-ignore children, startIcon, rightIcon, leftIcon, endIcon, spinner, isDisabled, isLoading, isHovered: isHoveredProp, isPressed: isPressedProp, isFocused: isFocusedProp, isFocusVisible: isFocusVisibleProp, spinnerPlacement = 'start', ...props }: IButtonProps & IBoxProps, ref: any ) => { const { hoverProps, isHovered } = useHover(); const { pressableProps, isPressed } = useIsPressed(); const { focusProps, isFocused } = useFocus(); const { isFocusVisible, focusProps: focusRingProps }: any = useFocusRing(); const { onPressIn, onPressOut, onHoverIn, onHoverOut, onFocus, onBlur, _text, _stack, _spinner, isLoadingText, _icon, ...resolvedProps } = usePropsResolution('Button', props, { isDisabled, isHovered: isHoveredProp || isHovered, isFocused: isFocusedProp || isFocused, isPressed: isPressedProp || isPressed, isLoading, isFocusVisible: isFocusVisibleProp || isFocusVisible, }); //TODO: refactor for responsive prop if (useHasResponsiveProps(props)) { return null; } if (leftIcon) { startIcon = leftIcon; } if (rightIcon) { endIcon = rightIcon; } if (endIcon && React.isValidElement(endIcon)) { endIcon = React.Children.map( endIcon, (child: JSX.Element, index: number) => { return React.cloneElement(child, { key: `button-end-icon-${index}`, ..._icon, ...child.props, }); } ); } if (startIcon && React.isValidElement(startIcon)) { startIcon = React.Children.map( startIcon, (child: JSX.Element, index: number) => { return React.cloneElement(child, { key: `button-start-icon-${index}`, ..._icon, ...child.props, }); } ); } const spinnerElement = spinner ? ( spinner ) : ( ); const boxChildren = (child: any) => { return child ? {child} : null; }; return ( {startIcon && !isLoading ? startIcon : null} {isLoading && spinnerPlacement === 'start' ? spinnerElement : null} {isLoading ? isLoadingText ? boxChildren(isLoadingText) : null : boxChildren(children)} {endIcon && !isLoading ? endIcon : null} {isLoading && spinnerPlacement === 'end' ? spinnerElement : null} ); }; export default memo(forwardRef(Button));