render: function() { const source = resolveAssetSource(this.props.source); const loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource); // As opposed to the ios version, here we render `null` when there is no source, source.uri // or source array. if (source && source.uri === '') { console.warn('source.uri should not be an empty string'); } if (this.props.src) { console.warn('The <Image> component requires a `source` property rather than `src`.'); } if (source && (source.uri || Array.isArray(source))) { let style; let sources; if (source.uri) { const {width, height} = source; style = flattenStyle([{width, height}, styles.base, this.props.style]); sources = [{uri: source.uri}]; } else { style = flattenStyle([styles.base, this.props.style]); sources = source; } const {onLoadStart, onLoad, onLoadEnd} = this.props; const nativeProps = merge(this.props, { style, shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd), src: sources, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, }); if (nativeProps.children) { // TODO(6033040): Consider implementing this as a separate native component const containerStyle = filterObject(style, (val, key) => !ImageSpecificStyleKeys.has(key)); const imageStyle = filterObject(style, (val, key) => ImageSpecificStyleKeys.has(key)); const imageProps = merge(nativeProps, { style: [imageStyle, styles.absoluteImage], children: undefined, }); return ( <View style={containerStyle}> <RKImage {...imageProps}/> {this.props.children} </View> ); } else { if (this.context.isInAParentText) { return <RCTTextInlineImage {...nativeProps}/>; } else { return <RKImage {...nativeProps}/>; } } } return null; }
render: function() { var name = this.props.name; var glyph = glyphMap[name] || '?'; if(typeof glyph === 'number') { glyph = String.fromCharCode(glyph); } var containerStyle = _.pick(flattenStyle([styles.container, this.props.style]), Object.keys(ViewStylePropTypes)); var textStyle = _.pick( flattenStyle([this.props.style, styles.text]), Object.keys(TextStylePropTypes) ); var size = this.props.size || textStyle.fontSize || DEFAULT_ICON_SIZE; var color = this.props.color || textStyle.color || DEFAULT_ICON_COLOR; textStyle.fontSize = size; textStyle.lineHeight = size; textStyle.height = size; textStyle.color = color; return ( <View {...this.props} style={containerStyle}> <Text style={textStyle}>{glyph}</Text> {this.props.children} </View> ); }
render: function() { const source = resolveAssetSource(this.props.source) || { uri: undefined, width: undefined, height: undefined }; let sources; let style; if (Array.isArray(source)) { style = flattenStyle([styles.base, this.props.style]) || {}; sources = source; } else { const {width, height, uri} = source; style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; sources = [source]; if (uri === '') { console.warn('source.uri should not be an empty string'); } } const resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 if (this.props.src) { console.warn('The <Image> component requires a `source` property rather than `src`.'); } return ( <RCTImageView {...this.props} style={style} resizeMode={resizeMode} tintColor={tintColor} source={sources} /> ); },
function diffNestedProperty( updatePayload: null | Object, prevProp: NestedNode, nextProp: NestedNode, validAttributes: AttributeConfiguration, ): null | Object { if (!updatePayload && prevProp === nextProp) { // If no properties have been added, then we can bail out quickly on object // equality. return updatePayload; } if (!prevProp || !nextProp) { if (nextProp) { return addNestedProperty(updatePayload, nextProp, validAttributes); } if (prevProp) { return clearNestedProperty(updatePayload, prevProp, validAttributes); } return updatePayload; } if (!Array.isArray(prevProp) && !Array.isArray(nextProp)) { // Both are leaves, we can diff the leaves. return diffProperties(updatePayload, prevProp, nextProp, validAttributes); } if (Array.isArray(prevProp) && Array.isArray(nextProp)) { // Both are arrays, we can diff the arrays. return diffNestedArrayProperty( updatePayload, prevProp, nextProp, validAttributes, ); } if (Array.isArray(prevProp)) { return diffProperties( updatePayload, // $FlowFixMe - We know that this is always an object when the input is. flattenStyle(prevProp), // $FlowFixMe - We know that this isn't an array because of above flow. nextProp, validAttributes, ); } return diffProperties( updatePayload, prevProp, // $FlowFixMe - We know that this is always an object when the input is. flattenStyle(nextProp), validAttributes, ); }
let Image = ( props: ImagePropsType, forwardedRef: ?React.Ref<'RCTImageView'>, ) => { const source = resolveAssetSource(props.source) || { uri: undefined, width: undefined, height: undefined, }; let sources; let style: ImageStyleProp; if (Array.isArray(source)) { // $FlowFixMe flattenStyle is not strong enough style = flattenStyle([styles.base, props.style]) || {}; sources = source; } else { const {width, height, uri} = source; // $FlowFixMe flattenStyle is not strong enough style = flattenStyle([{width, height}, styles.base, props.style]) || {}; sources = [source]; if (uri === '') { console.warn('source.uri should not be an empty string'); } } const resizeMode = props.resizeMode || style.resizeMode || 'cover'; const tintColor = style.tintColor; if (props.src != null) { console.warn( 'The <Image> component requires a `source` property rather than `src`.', ); } if (props.children != null) { throw new Error( 'The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.', ); } return ( <RCTImageView {...props} ref={forwardedRef} style={style} resizeMode={resizeMode} tintColor={tintColor} source={sources} /> ); };
render: function() { const source = resolveAssetSource(this.props.source) || { uri: undefined, width: undefined, height: undefined, }; let sources; let style; if (Array.isArray(source)) { style = flattenStyle([styles.base, this.props.style]) || {}; sources = source; } else { const {width, height, uri} = source; style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; sources = [source]; if (uri === '') { console.warn('source.uri should not be an empty string'); } } const resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 const tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 if (this.props.src) { console.warn( 'The <Image> component requires a `source` property rather than `src`.', ); } if (this.props.children) { throw new Error( 'The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.', ); } return ( <RCTImageView {...this.props} style={style} resizeMode={resizeMode} tintColor={tintColor} source={sources} /> ); },
render: function() { const source = resolveAssetSource(this.props.source); const loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource); // As opposed to the ios version, here we render `null` when there is no source, source.uri // or source array. if (source && source.uri === '') { console.warn('source.uri should not be an empty string'); } if (this.props.src) { console.warn('The <Image> component requires a `source` property rather than `src`.'); } if (this.props.children) { throw new Error('The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.'); } if (source && (source.uri || Array.isArray(source))) { let style; let sources; if (source.uri) { const {width, height} = source; style = flattenStyle([{width, height}, styles.base, this.props.style]); sources = [{uri: source.uri}]; } else { style = flattenStyle([styles.base, this.props.style]); sources = source; } const {onLoadStart, onLoad, onLoadEnd, onError} = this.props; const nativeProps = merge(this.props, { style, shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError), src: sources, headers: source.headers, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, }); if (this.context.isInAParentText) { return <RCTTextInlineImage {...nativeProps}/>; } else { return <RKImage {...nativeProps}/>; } } return null; }
render: function() { var source = resolveAssetSource(this.props.source) || {}; var {width, height, uri} = source; var style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; var isNetwork = uri && uri.match(/^https?:/); var RawImage = isNetwork ? RCTNetworkImageView : RCTImageView; var resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 var tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 // This is a workaround for #8243665. RCTNetworkImageView does not support tintColor // TODO: Remove this hack once we have one image implementation #8389274 if (isNetwork && tintColor) { RawImage = RCTImageView; } if (this.context.isInAParentText) { RawImage = RCTVirtualImage; if (!width || !height) { console.warn('You must specify a width and height for the image %s', uri); } } return ( <RawImage {...this.props} style={style} resizeMode={resizeMode} tintColor={tintColor} source={source} /> ); },
it('should override style properties', () => { var style1 = {backgroundColor: '#000', width: 10}; var style2 = {backgroundColor: '#023c69', width: null}; var flatStyle = flattenStyle([style1, style2]); expect(flatStyle.backgroundColor).toBe('#023c69'); expect(flatStyle.width).toBe(null); });
it('should merge style objects', () => { var style1 = {width: 10}; var style2 = {height: 20}; var flatStyle = flattenStyle([style1, style2]); expect(flatStyle.width).toBe(10); expect(flatStyle.height).toBe(20); });
setNativeProps: function(nativeProps: Object) { // nativeProps contains a style attribute that's going to be flattened // and all the attributes expanded in place. In order to make this // process do as few allocations and copies as possible, we return // one if the other is empty. Only if both have values then we create // a new object and merge. var hasOnlyStyle = true; for (var key in nativeProps) { if (key !== 'style') { hasOnlyStyle = false; break; } } var style = precomputeStyle(flattenStyle(nativeProps.style)); var props = null; if (hasOnlyStyle) { props = style; } else if (!style) { props = nativeProps; } else { props = mergeFast(nativeProps, style); } RCTUIManager.updateView( findNodeHandle(this), this.viewConfig.uiViewClassName, props ); },
_splitProps(props: Object) { this._focusableProps = {}; // Prevent the child (that is View in most of the cases) from being collapsed. // Passed parameters can override this this._componentProps = { collapsable: false }; for (const key in props) { if (key in FocusableWindowsTemplate.focusablePropTypes) { // Property supported by WindowsControl this._focusableProps[key] = props[key]; } else if (key !== 'style') { // Property supported by Component this._componentProps[key] = props[key]; } else { // Style case is special because it has to be split: // - "transform" should go to WindowsControl // - everything else goes to Component const styles = props['style']; if (styles) { let focusableStyle = {}; let componentStyle = {}; const flattenedStyles = flattenStyle(styles); for (const styleName in flattenedStyles) { if (styleName === 'transform' || styleName === 'display') { focusableStyle[styleName] = flattenedStyles[styleName]; } else { componentStyle[styleName] = flattenedStyles[styleName]; } } this._focusableProps['style'] = focusableStyle; this._componentProps['style'] = componentStyle; } } } }
render: function() { for (var prop in nativeOnlyProps) { if (this.props[prop] !== undefined) { console.warn('Prop `' + prop + ' = ' + this.props[prop] + '` should ' + 'not be set directly on Image.'); } } var source = resolveAssetSource(this.props.source) || {}; var {width, height} = source; var style = flattenStyle([{width, height}, styles.base, this.props.style]); invariant(style, 'style must be initialized'); var isNetwork = source.uri && source.uri.match(/^https?:/); invariant( !(isNetwork && source.isStatic), 'static image uris cannot start with "http": "' + source.uri + '"' ); var isStored = !source.isStatic && !isNetwork; var RawImage = isNetwork ? RCTExNetworkImage : RCTExStaticImage; if (this.props.style && this.props.style.tintColor) { warning(RawImage === RCTExStaticImage, 'tintColor style only supported on static images.'); } var resizeMode = this.props.resizeMode || style.resizeMode || 'cover'; var nativeProps = merge(this.props, { style, tintColor: style.tintColor, resizeMode: resizeMode, }); if (nativeProps.cacheThumbnail === undefined) { nativeProps.cacheThumbnail = false; } if (isStored) { nativeProps.imageInfo = { imageTag: source.uri, prezSize: { width: style.width || 0, height: style.height || 0, }, cacheThumbnail: nativeProps.cacheThumbnail, } } else { nativeProps.src = source.uri; } if (this.props.defaultSource) { nativeProps.defaultImageSrc = this.props.defaultSource.uri; } nativeProps.onExLoadStart = nativeProps.onLoadStart; nativeProps.onExLoadProgress = nativeProps.onLoadProgress; nativeProps.onExLoadError = nativeProps.onLoadError; nativeProps.onExLoaded = nativeProps.onLoaded; delete nativeProps.onLoadStart; delete nativeProps.onLoadProgress; delete nativeProps.onLoadError; delete nativeProps.onLoaded; return <RawImage {...nativeProps} />; }
render: function() { var style = flattenStyle(this.props.style); var selection = this.props.selection; // Without the `TouchableWithoutFeedback`, taps on this inspector pane // would change the inspected element to whatever is under the inspector return ( <TouchableWithoutFeedback> <View style={styles.info}> <View style={styles.breadcrumb}> {mapWithSeparator( this.props.hierarchy, (item, i) => ( <TouchableHighlight style={[styles.breadItem, i === selection && styles.selected]} onPress={() => this.props.setSelection(i)}> <Text style={styles.breadItemText}> {item.getName ? item.getName() : 'Unknown'} </Text> </TouchableHighlight> ), () => <Text style={styles.breadSep}>▸</Text> )} </View> <View style={styles.row}> <StyleInspector style={style} /> <BoxInspector style={style} frame={this.props.frame} /> </View> </View> </TouchableWithoutFeedback> ); }
render: function () { var style = flattenStyle([styles.base, this.props.style]); var nativeProps = merge(this.props, { style }); return <RNPieChart {...nativeProps}/> }
render: function() { for (var prop in cfg.nativeOnly) { if (this.props[prop] !== undefined) { console.warn('Prop `' + prop + ' = ' + this.props[prop] + '` should ' + 'not be set directly on Image.'); } } var source = resolveAssetSource(this.props.source) || {}; var defaultSource = (this.props.defaultSource && resolveAssetSource(this.props.defaultSource)) || {}; var {width, height} = source; var style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; var isNetwork = source.uri && source.uri.match(/^https?:/); var RawImage = isNetwork ? RCTNetworkImageView : RCTImageView; var resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 var tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 return ( <RawImage {...this.props} style={style} resizeMode={resizeMode} tintColor={tintColor} src={source.uri} defaultSrc={defaultSource.uri} /> ); }
render() { var style = flattenStyle(this.props.style) || {}; var margin = resolveBoxStyle('margin', style); var padding = resolveBoxStyle('padding', style); var frameStyle = this.props.frame; if (margin) { frameStyle = { top: frameStyle.top - margin.top, left: frameStyle.left - margin.left, height: frameStyle.height + margin.top + margin.bottom, width: frameStyle.width + margin.left + margin.right, }; } var contentStyle = { width: this.props.frame.width, height: this.props.frame.height, }; if (padding) { contentStyle = { width: contentStyle.width - padding.left - padding.right, height: contentStyle.height - padding.top - padding.bottom, }; } return ( <View style={[styles.frame, frameStyle]} pointerEvents="none"> <BorderBox box={margin} style={styles.margin}> <BorderBox box={padding} style={styles.padding}> <View style={[styles.content, contentStyle]} /> </BorderBox> </BorderBox> </View> ); }
render: function() { for (var prop in cfg.nativeOnly) { if (this.props[prop] !== undefined) { console.warn('Prop `' + prop + ' = ' + this.props[prop] + '` should ' + 'not be set directly on Image.'); } } var source = resolveAssetSource(this.props.source) || {}; var defaultSource = (this.props.defaultSource && resolveAssetSource(this.props.defaultSource)) || {}; var {width, height} = source; var style = flattenStyle([{width, height}, styles.base, this.props.style]) || {}; var isNetwork = source.uri && source.uri.match(/^https?:/); var RawImage = isNetwork ? RCTNetworkImageView : RCTImageView; var resizeMode = this.props.resizeMode || (style || {}).resizeMode || 'cover'; // Workaround for flow bug t7737108 var tintColor = (style || {}).tintColor; // Workaround for flow bug t7737108 // This is a workaround for #8243665. RCTNetworkImageView does not support tintColor // TODO: Remove this hack once we have one image implementation #8389274 if (isNetwork && tintColor) { RawImage = RCTImageView; } return ( <RawImage {...this.props} style={style} resizeMode={resizeMode} tintColor={tintColor} src={source.uri} defaultImageSrc={defaultSource.uri} /> ); }
_opacityInactive: function(duration: number) { var childStyle = flattenStyle(this.props.style) || {}; this.setOpacityTo( childStyle.opacity === undefined ? 1 : childStyle.opacity, duration ); },
render() { const style = flattenStyle(this.props.style); // $FlowFixMe found when converting React.createClass to ES6 const selection = this.props.selection; let openFileButton; const source = this.props.source; const {fileName, lineNumber} = source || {}; if (fileName && lineNumber) { const parts = fileName.split('/'); const fileNameShort = parts[parts.length - 1]; openFileButton = ( <TouchableHighlight style={styles.openButton} onPress={openFileInEditor.bind(null, fileName, lineNumber)}> <Text style={styles.openButtonTitle} numberOfLines={1}> {fileNameShort}:{lineNumber} </Text> </TouchableHighlight> ); } // Without the `TouchableWithoutFeedback`, taps on this inspector pane // would change the inspected element to whatever is under the inspector return ( <TouchableWithoutFeedback> <View style={styles.info}> <View style={styles.breadcrumb}> {mapWithSeparator( this.props.hierarchy, (item, i) => ( <TouchableHighlight key={'item-' + i} style={[styles.breadItem, i === selection && styles.selected]} // $FlowFixMe found when converting React.createClass to ES6 onPress={() => this.props.setSelection(i)}> <Text style={styles.breadItemText}> {getInstanceName(item)} </Text> </TouchableHighlight> ), (i) => ( <Text key={'sep-' + i} style={styles.breadSep}> ▸ </Text> ) )} </View> <View style={styles.row}> <View style={styles.col}> <StyleInspector style={style} /> {openFileButton} </View> { // $FlowFixMe found when converting React.createClass to ES6 <BoxInspector style={style} frame={this.props.frame} />} </View> </View> </TouchableWithoutFeedback> ); }
_opacityInactive: function() { this.clearTimeout(this._hideTimeout); this._hideTimeout = null; var childStyle = flattenStyle(this.props.style) || {}; this.setOpacityTo( childStyle.opacity === undefined ? 1 : childStyle.opacity ); },
it('should recursively flatten arrays', () => { var style1 = {width: 10}; var style2 = {height: 20}; var style3 = {width: 30}; var flatStyle = flattenStyle([null, [], [style1, style2], style3]); expect(flatStyle.width).toBe(30); expect(flatStyle.height).toBe(20); });
function diffNestedProperty( updatePayload :? Object, prevProp, // inferred nextProp, // inferred validAttributes : AttributeConfiguration ) : ?Object { // The style property is a deeply nested element which includes numbers // to represent static objects. Most of the time, it doesn't change across // renders, so it's faster to spend the time checking if it is different // before actually doing the expensive flattening operation in order to // compute the diff. if (!styleDiffer(prevProp, nextProp)) { return updatePayload; } // TODO: Walk both props in parallel instead of flattening. var previousFlattenedStyle = flattenStyle(prevProp); var nextFlattenedStyle = flattenStyle(nextProp); if (!previousFlattenedStyle || !nextFlattenedStyle) { if (nextFlattenedStyle) { return addProperties( updatePayload, nextFlattenedStyle, validAttributes ); } if (previousFlattenedStyle) { return clearProperties( updatePayload, previousFlattenedStyle, validAttributes ); } return updatePayload; } // recurse return diffProperties( updatePayload, previousFlattenedStyle, nextFlattenedStyle, validAttributes ); }
return function(props, propName, componentName, location?, ...rest) { let newProps = props; if (props[propName]) { // Just make a dummy prop object with only the flattened style newProps = {}; newProps[propName] = flattenStyle(props[propName]); } return shapePropType(newProps, propName, componentName, location, ...rest); };
constructor(style: any) { super(); style = flattenStyle(style) || {}; if (style.transform) { style = { ...style, transform: new AnimatedTransform(style.transform), }; } this._style = style; }
render: function() { for (var prop in nativeOnlyProps) { if (this.props[prop] !== undefined) { console.warn('Prop `' + prop + ' = ' + this.props[prop] + '` should ' + 'not be set directly on Image.'); } } var style = flattenStyle([styles.base, this.props.style]); invariant(style, "style must be initialized"); var source = this.props.source; invariant(source, "source must be initialized"); var isNetwork = source.uri && source.uri.match(/^https?:/); invariant( !(isNetwork && source.isStatic), 'static image uris cannot start with "http": "' + source.uri + '"' ); var isStored = !source.isStatic && !isNetwork; var RawImage = isNetwork ? RCTNetworkImage : RCTStaticImage; if (this.props.style && this.props.style.tintColor) { warning(RawImage === RCTStaticImage, 'tintColor style only supported on static images.'); } var resizeMode = this.props.resizeMode || style.resizeMode; var contentModes = NativeModules.UIManager.UIView.ContentMode; var contentMode; if (resizeMode === ImageResizeMode.stretch) { contentMode = contentModes.ScaleToFill; } else if (resizeMode === ImageResizeMode.contain) { contentMode = contentModes.ScaleAspectFit; } else { // ImageResizeMode.cover or undefined contentMode = contentModes.ScaleAspectFill; } var nativeProps = merge(this.props, { style, contentMode, tintColor: style.tintColor, }); if (Platform.OS === 'android') { // TODO: update android native code to not need this nativeProps.resizeMode = contentMode; delete nativeProps.contentMode; } if (isStored) { nativeProps.imageTag = source.uri; } else { nativeProps.src = source.uri; } if (this.props.defaultSource) { nativeProps.defaultImageSrc = this.props.defaultSource.uri; } return <RawImage {...nativeProps} />; }
_enableScene: function(sceneIndex) { // First, determine what the defined styles are for scenes in this navigator var sceneStyle = flattenStyle([styles.baseScene, this.props.sceneStyle]); // Then restore the left value for this scene var enabledSceneNativeProps = { left: sceneStyle.left, }; if (sceneIndex !== this.state.transitionFromIndex && sceneIndex !== this.state.presentedIndex) { // If we are not in a transition from this index, make sure opacity is 0 // to prevent the enabled scene from flashing over the presented scene enabledSceneNativeProps.opacity = 0; } this.refs['scene_' + sceneIndex] && this.refs['scene_' + sceneIndex].setNativeProps(enabledSceneNativeProps); },
render: function() { var style = flattenStyle([styles.base, this.props.style]); aspect = NativeModules.BarcodeScannerManager.aspects[this.state.aspect]; type = NativeModules.BarcodeScannerManager.cameras[this.state.type]; orientation = NativeModules.BarcodeScannerManager.orientations[this.state.orientation]; var nativeProps = merge(this.props, { style, aspect: aspect, type: type, orientation: orientation, }); return <RCTBarcodeScanner {... nativeProps} /> },
render() { const style = flattenStyle(this.props.style) || {}; const margin = resolveBoxStyle('margin', style); const padding = resolveBoxStyle('padding', style); const frameStyle = {...this.props.frame}; const contentStyle = { width: this.props.frame.width, height: this.props.frame.height, }; if (margin != null) { frameStyle.top -= margin.top; frameStyle.left -= margin.left; frameStyle.height += margin.top + margin.bottom; frameStyle.width += margin.left + margin.right; if (margin.top < 0) { contentStyle.height += margin.top; } if (margin.bottom < 0) { contentStyle.height += margin.bottom; } if (margin.left < 0) { contentStyle.width += margin.left; } if (margin.right < 0) { contentStyle.width += margin.right; } } if (padding != null) { contentStyle.width -= padding.left + padding.right; contentStyle.height -= padding.top + padding.bottom; } return ( <View style={[styles.frame, frameStyle]} pointerEvents="none"> <BorderBox box={margin} style={styles.margin}> <BorderBox box={padding} style={styles.padding}> <View style={[styles.content, contentStyle]} /> </BorderBox> </BorderBox> </View> ); }
render: function() { const source = resolveAssetSource(this.props.source); const loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource); // As opposed to the ios version, here it render `null` // when no source or source.uri... so let's not break that. if (source && source.uri === '') { console.warn('source.uri should not be an empty string'); } if (this.props.src) { console.warn('The <Image> component requires a `source` property rather than `src`.'); } if (source && source.uri) { const style = flattenStyle([styles.base, this.props.style]); const {onLoadStart, onLoad, onLoadEnd} = this.props; const nativeProps = merge(this.props, { style, shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd), source: source, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, }); /** * by default set the renderGroup if any transform as been set */ if ( nativeProps.style && nativeProps.style['renderGroup'] === undefined && nativeProps.style.transform ) { nativeProps.style.renderGroup = true; } if (this.context.isInAParentText) { // RCTTextInlineImage isn't implemented yet return <RKImage {...nativeProps} />; } else { return <RKImage {...nativeProps} />; } } return null; },