UNPKG

react-native-vector-icons

Version:

Customizable Icons for React Native with support for NavBar/TabBar/ToolbarAndroid, image source and full styling.

146 lines (132 loc) 4.77 kB
/* eslint-disable react/no-unused-prop-types */ import isEqual from 'lodash/isEqual'; import pick from 'lodash/pick'; import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { ToolbarAndroid } from './react-native'; const ICON_PROP_NAMES = ['iconSize', 'iconColor', 'titleColor']; const LOGO_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'logoName']; const NAV_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'navIconName']; const OVERFLOW_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'overflowIconName']; const ACTIONS_PROP_NAMES = [...ICON_PROP_NAMES, 'actions']; const arePropsEqual = keys => (prevProps, nextProps) => isEqual(pick(prevProps, keys), pick(nextProps, keys)); const areLogoIconPropsEqual = arePropsEqual(LOGO_ICON_PROP_NAMES); const areNavIconPropsEqual = arePropsEqual(NAV_ICON_PROP_NAMES); const areOverflowIconPropsEqual = arePropsEqual(OVERFLOW_ICON_PROP_NAMES); const areActionPropsEqual = arePropsEqual(ACTIONS_PROP_NAMES); export default function createToolbarAndroidComponent( IconNamePropType, getImageSource ) { return class IconToolbarAndroid extends PureComponent { static propTypes = { logoName: IconNamePropType, navIconName: IconNamePropType, overflowIconName: IconNamePropType, actions: PropTypes.arrayOf( PropTypes.shape({ title: PropTypes.string.isRequired, iconName: IconNamePropType, iconSize: PropTypes.number, iconColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), show: PropTypes.oneOf(['always', 'ifRoom', 'never']), showWithText: PropTypes.bool, }) ), iconSize: PropTypes.number, iconColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), titleColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), }; static defaultProps = { iconSize: 24, }; state = { logo: undefined, navIcon: undefined, overflowIcon: undefined, actions: undefined, }; componentDidMount() { this.updateLogoIconSource(); this.updateNavIconSource(); this.updateOverflowIconSource(); this.updateActionIconSources(); } componentDidUpdate(prevProps) { if (!areLogoIconPropsEqual(prevProps, this.props)) { this.updateLogoIconSource(); } if (!areNavIconPropsEqual(prevProps, this.props)) { this.updateNavIconSource(); } if (!areOverflowIconPropsEqual(prevProps, this.props)) { this.updateOverflowIconSource(); } if (!areActionPropsEqual(prevProps, this.props)) { this.updateActionIconSources(); } } async updateLogoIconSource() { const { logoName, iconSize, iconColor, titleColor } = this.props; if (logoName) { const logo = await getImageSource( logoName, iconSize, iconColor || titleColor ); this.setState({ logo }); // eslint-disable-next-line react/destructuring-assignment } else if (this.state.logo) { this.setState({ logo: undefined }); } } async updateNavIconSource() { const { navIconName, iconSize, iconColor, titleColor } = this.props; if (navIconName) { const navIcon = await getImageSource( navIconName, iconSize, iconColor || titleColor ); this.setState({ navIcon }); // eslint-disable-next-line react/destructuring-assignment } else if (this.state.navIcon) { this.setState({ navIcon: undefined }); } } async updateOverflowIconSource() { const { overflowIconName, iconSize, iconColor, titleColor } = this.props; if (overflowIconName) { const overflowIcon = await getImageSource( overflowIconName, iconSize, iconColor || titleColor ); this.setState({ overflowIcon }); // eslint-disable-next-line react/destructuring-assignment } else if (this.state.overflowIcon) { this.setState({ overflowIcon: undefined }); } } async updateActionIconSources() { const { actions, iconSize, iconColor, titleColor } = this.props; const updatedActions = await Promise.all( (actions || []).map(action => { if (action.iconName) { return getImageSource( action.iconName, action.iconSize || iconSize, action.iconColor || iconColor || titleColor ).then(icon => ({ ...action, icon })); } return Promise.resolve(action); }) ); this.setState({ actions: updatedActions }); } render() { return <ToolbarAndroid {...this.props} {...this.state} />; } }; }