Skip to content

Commit

Permalink
[change] Image deprecate resizeMode and tintColor styles
Browse files Browse the repository at this point in the history
The resizeMode and tintColor props should be used instead. The styles
will be removed in a future release.

Fix #2383
  • Loading branch information
necolas committed Dec 27, 2022
1 parent 785b73f commit 6c77d8e
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 52 deletions.
34 changes: 17 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"prop-types": "^15.6.0",
"react": ">=17.0.2",
"react-dom": ">=17.0.2",
"react-native-web": "0.18.8"
"react-native-web": "0.18.9"
},
"devDependencies": {
"babel-loader": "^8.2.5",
"babel-plugin-react-native-web": "0.18.8",
"babel-plugin-react-native-web": "0.18.9",
"css-loader": "^6.7.1",
"style-loader": "^3.3.1",
"url-loader": "^4.1.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,14 +329,14 @@ exports[`components/Image prop "style" removes other unsupported View styles 1`]
>
<div
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
style="filter: url(#tint-57);"
style="filter: url(#tint-55);"
/>
<svg
style="position: absolute; height: 0px; visibility: hidden; width: 0px;"
>
<defs>
<filter
id="tint-57"
id="tint-55"
>
<feflood
flood-color="blue"
Expand All @@ -351,28 +351,29 @@ exports[`components/Image prop "style" removes other unsupported View styles 1`]
</div>
`;

exports[`components/Image prop "style" supports "resizeMode" property 1`] = `
exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = `
<div
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
>
<div
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-ehq7j7"
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
style="filter: drop-shadow(1px 1px 0px rgba(255,0,0,1.00));"
/>
</div>
`;

exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = `
exports[`components/Image prop "testID" 1`] = `
<div
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
data-testid="testID"
>
<div
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
style="filter: drop-shadow(1px 1px 0px rgba(255,0,0,1.00));"
/>
</div>
`;

exports[`components/Image prop "style" supports "tintcolor" property (convert to filter) 1`] = `
exports[`components/Image prop "tintColor" convert to filter 1`] = `
<div
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
>
Expand Down Expand Up @@ -405,14 +406,3 @@ exports[`components/Image prop "style" supports "tintcolor" property (convert to
</svg>
</div>
`;

exports[`components/Image prop "testID" 1`] = `
<div
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
data-testid="testID"
>
<div
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
/>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,6 @@ describe('components/Image', () => {
});

describe('prop "style"', () => {
test('supports "resizeMode" property', () => {
const { container } = render(<Image style={{ resizeMode: 'contain' }} />);
expect(container.firstChild).toMatchSnapshot();
});

test('supports "shadow" properties (convert to filter)', () => {
const { container } = render(
<Image
Expand All @@ -362,17 +357,19 @@ describe('components/Image', () => {
expect(container.firstChild).toMatchSnapshot();
});

test('supports "tintcolor" property (convert to filter)', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
test('removes other unsupported View styles', () => {
const { container } = render(
<Image defaultSource={defaultSource} style={{ tintColor: 'red' }} />
<Image style={{ overlayColor: 'red', tintColor: 'blue' }} />
);
expect(container.firstChild).toMatchSnapshot();
});
});

test('removes other unsupported View styles', () => {
describe('prop "tintColor"', () => {
test('convert to filter', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
const { container } = render(
<Image style={{ overlayColor: 'red', tintColor: 'blue' }} />
<Image defaultSource={defaultSource} tintColor={'red'} />
);
expect(container.firstChild).toMatchSnapshot();
});
Expand Down
24 changes: 20 additions & 4 deletions packages/react-native-web/src/exports/Image/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import PixelRatio from '../PixelRatio';
import StyleSheet from '../StyleSheet';
import TextAncestorContext from '../Text/TextAncestorContext';
import View from '../View';
import { warnOnce } from '../../modules/warnOnce';

export type { ImageProps };

Expand Down Expand Up @@ -50,10 +51,23 @@ function createTintColorSVG(tintColor, id) {
) : null;
}

function getFlatStyle(style, blurRadius, filterId) {
function getFlatStyle(style, blurRadius, filterId, tintColorProp) {
const flatStyle = StyleSheet.flatten(style);
const { filter, resizeMode, shadowOffset, tintColor } = flatStyle;

if (flatStyle.resizeMode) {
warnOnce(
'Image.style.resizeMode',
'Image: style.resizeMode is deprecated. Please use props.resizeMode.'
);
}
if (flatStyle.tintColor) {
warnOnce(
'Image.style.tintColor',
'Image: style.tintColor is deprecated. Please use props.tintColor.'
);
}

// Add CSS filters
// React Native exposes these features as props and proprietary styles
const filters = [];
Expand All @@ -71,7 +85,7 @@ function getFlatStyle(style, blurRadius, filterId) {
filters.push(`drop-shadow(${shadowString})`);
}
}
if (tintColor && filterId != null) {
if ((tintColorProp || tintColor) && filterId != null) {
filters.push(`url(#tint-${filterId})`);
}

Expand Down Expand Up @@ -209,12 +223,14 @@ const Image: React.AbstractComponent<
const requestRef = React.useRef(null);
const shouldDisplaySource =
state === LOADED || (state === LOADING && defaultSource == null);
const [flatStyle, _resizeMode, filter, tintColor] = getFlatStyle(
const [flatStyle, _resizeMode, filter, _tintColor] = getFlatStyle(
style,
blurRadius,
filterRef.current
filterRef.current,
props.tintColor
);
const resizeMode = props.resizeMode || _resizeMode || 'cover';
const tintColor = props.tintColor || _tintColor;
const selectedSource = shouldDisplaySource ? source : defaultSource;
const displayImageUri = resolveAssetUri(selectedSource);
const imageSizeStyle = resolveAssetDimensions(selectedSource);
Expand Down
4 changes: 3 additions & 1 deletion packages/react-native-web/src/exports/Image/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export type ImageStyle = {
boxShadow?: string,
filter?: string,
opacity?: number,
// @deprecated
resizeMode?: ResizeMode,
tintColor?: ColorValue
};
Expand All @@ -115,5 +116,6 @@ export type ImageProps = {
onProgress?: (e: any) => void,
resizeMode?: ResizeMode,
source?: Source,
style?: GenericStyleProp<ImageStyle>
style?: GenericStyleProp<ImageStyle>,
tintColor?: ColorValue
};
27 changes: 27 additions & 0 deletions packages/react-native-web/src/modules/warnOnce/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/

const warnedKeys: { [string]: boolean, ... } = {};

/**
* A simple function that prints a warning message once per session.
*
* @param {string} key - The key used to ensure the message is printed once.
* This should be unique to the callsite.
* @param {string} message - The message to print
*/
export function warnOnce(key: string, message: string) {
if (warnedKeys[key]) {
return;
}

console.warn(message);

warnedKeys[key] = true;
}

0 comments on commit 6c77d8e

Please sign in to comment.