import * as React from 'react'; import { I18nManager, Image, ImageSourcePropType, Platform, } from 'react-native'; import { accessibilityProps } from './MaterialCommunityIcon'; import { Consumer as SettingsConsumer } from '../core/settings'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; type IconSourceBase = string | ImageSourcePropType; export type IconSource = | IconSourceBase | Readonly<{ source: IconSourceBase; direction: 'rtl' | 'ltr' | 'auto' }> | ((props: IconProps & { color: string }) => React.ReactNode); type IconProps = { /** * Size of icon. */ size: number; allowFontScaling?: boolean; }; const isImageSource = (source: any) => // source is an object with uri (typeof source === 'object' && source !== null && Object.prototype.hasOwnProperty.call(source, 'uri') && typeof source.uri === 'string') || // source is a module, e.g. - require('image') typeof source === 'number' || // image url on web (Platform.OS === 'web' && typeof source === 'string' && (source.startsWith('data:image') || /\.(bmp|jpg|jpeg|png|gif|svg)$/.test(source))); const getIconId = (source: any) => { if ( typeof source === 'object' && source !== null && Object.prototype.hasOwnProperty.call(source, 'uri') && typeof source.uri === 'string' ) { return source.uri; } return source; }; export const isValidIcon = (source: any) => typeof source === 'string' || typeof source === 'function' || isImageSource(source); export const isEqualIcon = (a: any, b: any) => a === b || getIconId(a) === getIconId(b); export type Props = IconProps & { /** * Icon to display. */ source: any; /** * Color of the icon. */ color?: string; /** * TestID used for testing purposes */ testID?: string; /** * @optional */ theme?: ThemeProp; }; /** * An icon component which renders icon from vector library. * * ## Usage * ```js * import * as React from 'react'; * import { Icon, MD3Colors } from 'react-native-paper'; * * const MyComponent = () => ( * * ); * * export default MyComponent; * ``` */ const Icon = ({ source, color, size, theme: themeOverrides, testID, ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); const direction = typeof source === 'object' && source.direction && source.source ? source.direction === 'auto' ? I18nManager.getConstants().isRTL ? 'rtl' : 'ltr' : source.direction : null; const s = typeof source === 'object' && source.direction && source.source ? source.source : source; const iconColor = color || (theme.isV3 ? theme.colors.onSurface : theme.colors.text); if (isImageSource(s)) { return ( ); } else if (typeof s === 'string') { return ( {({ icon }) => { return icon?.({ name: s, color: iconColor, size, direction, testID, }); }} ); } else if (typeof s === 'function') { return s({ color: iconColor, size, direction, testID }); } return null; }; export default Icon;