Skip to content

Commit 95c8a54

Browse files
committed
[change] Image deprecate resizeMode and tintColor styles
The resizeMode and tintColor props should be used instead. The styles will be removed in a future release. Fix #2383
1 parent 1f5d092 commit 95c8a54

File tree

7 files changed

+1728
-6114
lines changed

7 files changed

+1728
-6114
lines changed

package-lock.json

Lines changed: 1661 additions & 6079 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/benchmarks/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
"prop-types": "^15.6.0",
1414
"react": ">=17.0.2",
1515
"react-dom": ">=17.0.2",
16-
"react-native-web": "0.18.8"
16+
"react-native-web": "0.18.9"
1717
},
1818
"devDependencies": {
1919
"babel-loader": "^8.2.5",
20-
"babel-plugin-react-native-web": "0.18.8",
20+
"babel-plugin-react-native-web": "0.18.9",
2121
"css-loader": "^6.7.1",
2222
"style-loader": "^3.3.1",
2323
"url-loader": "^4.1.1",

packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,14 @@ exports[`components/Image prop "style" removes other unsupported View styles 1`]
329329
>
330330
<div
331331
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"
332-
style="filter: url(#tint-57);"
332+
style="filter: url(#tint-55);"
333333
/>
334334
<svg
335335
style="position: absolute; height: 0px; visibility: hidden; width: 0px;"
336336
>
337337
<defs>
338338
<filter
339-
id="tint-57"
339+
id="tint-55"
340340
>
341341
<feflood
342342
flood-color="blue"
@@ -351,28 +351,29 @@ exports[`components/Image prop "style" removes other unsupported View styles 1`]
351351
</div>
352352
`;
353353

354-
exports[`components/Image prop "style" supports "resizeMode" property 1`] = `
354+
exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = `
355355
<div
356356
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
357357
>
358358
<div
359-
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"
359+
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"
360+
style="filter: drop-shadow(1px 1px 0px rgba(255,0,0,1.00));"
360361
/>
361362
</div>
362363
`;
363364

364-
exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = `
365+
exports[`components/Image prop "testID" 1`] = `
365366
<div
366367
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
368+
data-testid="testID"
367369
>
368370
<div
369371
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"
370-
style="filter: drop-shadow(1px 1px 0px rgba(255,0,0,1.00));"
371372
/>
372373
</div>
373374
`;
374375

375-
exports[`components/Image prop "style" supports "tintcolor" property (convert to filter) 1`] = `
376+
exports[`components/Image prop "tintColor" convert to filter 1`] = `
376377
<div
377378
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
378379
>
@@ -405,14 +406,3 @@ exports[`components/Image prop "style" supports "tintcolor" property (convert to
405406
</svg>
406407
</div>
407408
`;
408-
409-
exports[`components/Image prop "testID" 1`] = `
410-
<div
411-
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
412-
data-testid="testID"
413-
>
414-
<div
415-
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"
416-
/>
417-
</div>
418-
`;

packages/react-native-web/src/exports/Image/__tests__/index-test.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,6 @@ describe('components/Image', () => {
348348
});
349349

350350
describe('prop "style"', () => {
351-
test('supports "resizeMode" property', () => {
352-
const { container } = render(<Image style={{ resizeMode: 'contain' }} />);
353-
expect(container.firstChild).toMatchSnapshot();
354-
});
355-
356351
test('supports "shadow" properties (convert to filter)', () => {
357352
const { container } = render(
358353
<Image
@@ -362,17 +357,19 @@ describe('components/Image', () => {
362357
expect(container.firstChild).toMatchSnapshot();
363358
});
364359

365-
test('supports "tintcolor" property (convert to filter)', () => {
366-
const defaultSource = { uri: 'https://google.com/favicon.ico' };
360+
test('removes other unsupported View styles', () => {
367361
const { container } = render(
368-
<Image defaultSource={defaultSource} style={{ tintColor: 'red' }} />
362+
<Image style={{ overlayColor: 'red', tintColor: 'blue' }} />
369363
);
370364
expect(container.firstChild).toMatchSnapshot();
371365
});
366+
});
372367

373-
test('removes other unsupported View styles', () => {
368+
describe('prop "tintColor"', () => {
369+
test('convert to filter', () => {
370+
const defaultSource = { uri: 'https://google.com/favicon.ico' };
374371
const { container } = render(
375-
<Image style={{ overlayColor: 'red', tintColor: 'blue' }} />
372+
<Image defaultSource={defaultSource} tintColor={'red'} />
376373
);
377374
expect(container.firstChild).toMatchSnapshot();
378375
});

packages/react-native-web/src/exports/Image/index.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import PixelRatio from '../PixelRatio';
1919
import StyleSheet from '../StyleSheet';
2020
import TextAncestorContext from '../Text/TextAncestorContext';
2121
import View from '../View';
22+
import { warnOnce } from '../../modules/warnOnce';
2223

2324
export type { ImageProps };
2425

@@ -50,10 +51,23 @@ function createTintColorSVG(tintColor, id) {
5051
) : null;
5152
}
5253

53-
function getFlatStyle(style, blurRadius, filterId) {
54+
function getFlatStyle(style, blurRadius, filterId, tintColorProp) {
5455
const flatStyle = StyleSheet.flatten(style);
5556
const { filter, resizeMode, shadowOffset, tintColor } = flatStyle;
5657

58+
if (flatStyle.resizeMode) {
59+
warnOnce(
60+
'Image.style.resizeMode',
61+
'Image: style.resizeMode is deprecated. Please use props.resizeMode.'
62+
);
63+
}
64+
if (flatStyle.tintColor) {
65+
warnOnce(
66+
'Image.style.tintColor',
67+
'Image: style.tintColor is deprecated. Please use props.tintColor.'
68+
);
69+
}
70+
5771
// Add CSS filters
5872
// React Native exposes these features as props and proprietary styles
5973
const filters = [];
@@ -71,7 +85,7 @@ function getFlatStyle(style, blurRadius, filterId) {
7185
filters.push(`drop-shadow(${shadowString})`);
7286
}
7387
}
74-
if (tintColor && filterId != null) {
88+
if ((tintColorProp || tintColor) && filterId != null) {
7589
filters.push(`url(#tint-${filterId})`);
7690
}
7791

@@ -209,12 +223,14 @@ const Image: React.AbstractComponent<
209223
const requestRef = React.useRef(null);
210224
const shouldDisplaySource =
211225
state === LOADED || (state === LOADING && defaultSource == null);
212-
const [flatStyle, _resizeMode, filter, tintColor] = getFlatStyle(
226+
const [flatStyle, _resizeMode, filter, _tintColor] = getFlatStyle(
213227
style,
214228
blurRadius,
215-
filterRef.current
229+
filterRef.current,
230+
props.tintColor
216231
);
217232
const resizeMode = props.resizeMode || _resizeMode || 'cover';
233+
const tintColor = props.tintColor || _tintColor;
218234
const selectedSource = shouldDisplaySource ? source : defaultSource;
219235
const displayImageUri = resolveAssetUri(selectedSource);
220236
const imageSizeStyle = resolveAssetDimensions(selectedSource);

packages/react-native-web/src/exports/Image/types.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export type ImageStyle = {
9898
boxShadow?: string,
9999
filter?: string,
100100
opacity?: number,
101+
// @deprecated
101102
resizeMode?: ResizeMode,
102103
tintColor?: ColorValue
103104
};
@@ -115,5 +116,6 @@ export type ImageProps = {
115116
onProgress?: (e: any) => void,
116117
resizeMode?: ResizeMode,
117118
source?: Source,
118-
style?: GenericStyleProp<ImageStyle>
119+
style?: GenericStyleProp<ImageStyle>,
120+
tintColor?: ColorValue
119121
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict
8+
*/
9+
10+
const warnedKeys: { [string]: boolean, ... } = {};
11+
12+
/**
13+
* A simple function that prints a warning message once per session.
14+
*
15+
* @param {string} key - The key used to ensure the message is printed once.
16+
* This should be unique to the callsite.
17+
* @param {string} message - The message to print
18+
*/
19+
export function warnOnce(key: string, message: string) {
20+
if (warnedKeys[key]) {
21+
return;
22+
}
23+
24+
console.warn(message);
25+
26+
warnedKeys[key] = true;
27+
}

0 commit comments

Comments
 (0)