UNPKG

3.05 kBTypeScriptView Raw
1import * as React from 'react';
2import {
3 Image,
4 I18nManager,
5 Platform,
6 ImageSourcePropType,
7} from 'react-native';
8import { Consumer as SettingsConsumer } from '../core/settings';
9import { accessibilityProps } from './MaterialCommunityIcon';
10import { withTheme } from '../core/theming';
11
12type IconSourceBase = string | ImageSourcePropType;
13
14export type IconSource =
15 | IconSourceBase
16 | Readonly<{ source: IconSourceBase; direction: 'rtl' | 'ltr' | 'auto' }>
17 | ((props: IconProps & { color: string }) => React.ReactNode);
18
19type IconProps = {
20 size: number;
21 allowFontScaling?: boolean;
22};
23
24type Props = IconProps & {
25 color?: string;
26 source: any;
27 /**
28 * @optional
29 */
30 theme: ReactNativePaper.Theme;
31};
32
33const isImageSource = (source: any) =>
34 // source is an object with uri
35 (typeof source === 'object' &&
36 source !== null &&
37 Object.prototype.hasOwnProperty.call(source, 'uri') &&
38 typeof source.uri === 'string') ||
39 // source is a module, e.g. - require('image')
40 typeof source === 'number' ||
41 // image url on web
42 (Platform.OS === 'web' &&
43 typeof source === 'string' &&
44 (source.startsWith('data:image') ||
45 /\.(bmp|jpg|jpeg|png|gif|svg)$/.test(source)));
46
47const getIconId = (source: any) => {
48 if (
49 typeof source === 'object' &&
50 source !== null &&
51 Object.prototype.hasOwnProperty.call(source, 'uri') &&
52 typeof source.uri === 'string'
53 ) {
54 return source.uri;
55 }
56
57 return source;
58};
59
60export const isValidIcon = (source: any) =>
61 typeof source === 'string' ||
62 typeof source === 'function' ||
63 isImageSource(source);
64
65export const isEqualIcon = (a: any, b: any) =>
66 a === b || getIconId(a) === getIconId(b);
67
68const Icon = ({ source, color, size, theme, ...rest }: Props) => {
69 const direction =
70 typeof source === 'object' && source.direction && source.source
71 ? source.direction === 'auto'
72 ? I18nManager.isRTL
73 ? 'rtl'
74 : 'ltr'
75 : source.direction
76 : null;
77 const s =
78 typeof source === 'object' && source.direction && source.source
79 ? source.source
80 : source;
81 const iconColor = color || theme.colors.text;
82
83 if (isImageSource(s)) {
84 return (
85 <Image
86 {...rest}
87 source={s}
88 style={[
89 {
90 transform: [{ scaleX: direction === 'rtl' ? -1 : 1 }],
91 },
92 // eslint-disable-next-line react-native/no-inline-styles
93 {
94 width: size,
95 height: size,
96 tintColor: color,
97 resizeMode: 'contain',
98 },
99 ]}
100 {...accessibilityProps}
101 />
102 );
103 } else if (typeof s === 'string') {
104 return (
105 <SettingsConsumer>
106 {({ icon }) => {
107 return icon({
108 name: s,
109 color: iconColor,
110 size,
111 direction,
112 });
113 }}
114 </SettingsConsumer>
115 );
116 } else if (typeof s === 'function') {
117 return s({ color: iconColor, size, direction });
118 }
119
120 return null;
121};
122
123export default withTheme(Icon);