From 6c77d8e24b4a03173be48df42f3236b289f38616 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 30 Aug 2022 14:34:55 -0700 Subject: [PATCH] [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 --- package-lock.json | 34 +++++++++---------- packages/benchmarks/package.json | 4 +-- .../__snapshots__/index-test.js.snap | 26 +++++--------- .../src/exports/Image/__tests__/index-test.js | 17 ++++------ .../src/exports/Image/index.js | 24 ++++++++++--- .../src/exports/Image/types.js | 4 ++- .../src/modules/warnOnce/index.js | 27 +++++++++++++++ 7 files changed, 84 insertions(+), 52 deletions(-) create mode 100644 packages/react-native-web/src/modules/warnOnce/index.js diff --git a/package-lock.json b/package-lock.json index fe0c2362e..bbef3085d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14928,11 +14928,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", @@ -14942,15 +14942,15 @@ } }, "packages/benchmarks/node_modules/babel-plugin-react-native-web": { - "version": "0.18.8", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.18.8.tgz", - "integrity": "sha512-4UwlBe9ZiWNMes8nK+qRn9ql6nZuSKcgu87YuFmnU9maEYIP1megcRcjbA5mAViaV3ct6PTyntTVf8thathf6Q==", + "version": "0.18.9", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.18.9.tgz", + "integrity": "sha512-A9rrSfV98CFRS+ACgZorxaHH8gDrVyK2Nea8OHepY4Sv/Mf+vk8uvQq+tRUEBpHnUvd/qRDKIjFLbygecAt9VA==", "dev": true }, "packages/benchmarks/node_modules/react-native-web": { - "version": "0.18.8", - "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.18.8.tgz", - "integrity": "sha512-NOjFgzD0eAldYCpLJIr47FreitcxkJka8CdGBYRmnZLvSU1AUwCR4PtxzHNbb4hAwO+/fKGh+aoRsGSwQo0cBA==", + "version": "0.18.9", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.18.9.tgz", + "integrity": "sha512-BaV5Mpe7u9pN5vTRDW2g+MLh6PbPBJZpXRQM3Jr2cNv7hNa3sxCGh9T+NcW6wOFzf/+USrdrEPI1M9wNyr7vyA==", "dependencies": { "@babel/runtime": "^7.18.6", "create-react-class": "^15.7.0", @@ -15058,7 +15058,7 @@ "next": "^12.2.0", "react": "^18.0.0", "react-dom": "^18.0.0", - "react-native-web": "0.18.8" + "react-native-web": "0.18.10" }, "devDependencies": { "@babel/core": "^7.18.6", @@ -18128,14 +18128,14 @@ "version": "file:packages/benchmarks", "requires": { "babel-loader": "^8.2.5", - "babel-plugin-react-native-web": "0.18.8", + "babel-plugin-react-native-web": "0.18.9", "classnames": "^2.3.1", "css-loader": "^6.7.1", "d3-scale-chromatic": "^3.0.0", "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", "style-loader": "^3.3.1", "url-loader": "^4.1.1", "webpack": "^5.73.0", @@ -18144,15 +18144,15 @@ }, "dependencies": { "babel-plugin-react-native-web": { - "version": "0.18.8", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.18.8.tgz", - "integrity": "sha512-4UwlBe9ZiWNMes8nK+qRn9ql6nZuSKcgu87YuFmnU9maEYIP1megcRcjbA5mAViaV3ct6PTyntTVf8thathf6Q==", + "version": "0.18.9", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.18.9.tgz", + "integrity": "sha512-A9rrSfV98CFRS+ACgZorxaHH8gDrVyK2Nea8OHepY4Sv/Mf+vk8uvQq+tRUEBpHnUvd/qRDKIjFLbygecAt9VA==", "dev": true }, "react-native-web": { - "version": "0.18.8", - "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.18.8.tgz", - "integrity": "sha512-NOjFgzD0eAldYCpLJIr47FreitcxkJka8CdGBYRmnZLvSU1AUwCR4PtxzHNbb4hAwO+/fKGh+aoRsGSwQo0cBA==", + "version": "0.18.9", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.18.9.tgz", + "integrity": "sha512-BaV5Mpe7u9pN5vTRDW2g+MLh6PbPBJZpXRQM3Jr2cNv7hNa3sxCGh9T+NcW6wOFzf/+USrdrEPI1M9wNyr7vyA==", "requires": { "@babel/runtime": "^7.18.6", "create-react-class": "^15.7.0", diff --git a/packages/benchmarks/package.json b/packages/benchmarks/package.json index ed7717941..d1e31db97 100644 --- a/packages/benchmarks/package.json +++ b/packages/benchmarks/package.json @@ -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", diff --git a/packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap b/packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap index 04b41e3ef..1a5b7d075 100644 --- a/packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap +++ b/packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap @@ -329,14 +329,14 @@ exports[`components/Image prop "style" removes other unsupported View styles 1`] >
`; -exports[`components/Image prop "style" supports "resizeMode" property 1`] = ` +exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = `
`; -exports[`components/Image prop "style" supports "shadow" properties (convert to filter) 1`] = ` +exports[`components/Image prop "testID" 1`] = `
`; -exports[`components/Image prop "style" supports "tintcolor" property (convert to filter) 1`] = ` +exports[`components/Image prop "tintColor" convert to filter 1`] = `
@@ -405,14 +406,3 @@ exports[`components/Image prop "style" supports "tintcolor" property (convert to
`; - -exports[`components/Image prop "testID" 1`] = ` -
-
-
-`; diff --git a/packages/react-native-web/src/exports/Image/__tests__/index-test.js b/packages/react-native-web/src/exports/Image/__tests__/index-test.js index e335fa047..e7e8fc5c2 100644 --- a/packages/react-native-web/src/exports/Image/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/Image/__tests__/index-test.js @@ -348,11 +348,6 @@ describe('components/Image', () => { }); describe('prop "style"', () => { - test('supports "resizeMode" property', () => { - const { container } = render(); - expect(container.firstChild).toMatchSnapshot(); - }); - test('supports "shadow" properties (convert to filter)', () => { const { container } = render( { 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( - + ); 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( - + ); expect(container.firstChild).toMatchSnapshot(); }); diff --git a/packages/react-native-web/src/exports/Image/index.js b/packages/react-native-web/src/exports/Image/index.js index 7f6a62fe1..f9381c96d 100644 --- a/packages/react-native-web/src/exports/Image/index.js +++ b/packages/react-native-web/src/exports/Image/index.js @@ -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 }; @@ -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 = []; @@ -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})`); } @@ -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); diff --git a/packages/react-native-web/src/exports/Image/types.js b/packages/react-native-web/src/exports/Image/types.js index 55ad3cb9f..fe4984451 100644 --- a/packages/react-native-web/src/exports/Image/types.js +++ b/packages/react-native-web/src/exports/Image/types.js @@ -98,6 +98,7 @@ export type ImageStyle = { boxShadow?: string, filter?: string, opacity?: number, + // @deprecated resizeMode?: ResizeMode, tintColor?: ColorValue }; @@ -115,5 +116,6 @@ export type ImageProps = { onProgress?: (e: any) => void, resizeMode?: ResizeMode, source?: Source, - style?: GenericStyleProp + style?: GenericStyleProp, + tintColor?: ColorValue }; diff --git a/packages/react-native-web/src/modules/warnOnce/index.js b/packages/react-native-web/src/modules/warnOnce/index.js new file mode 100644 index 000000000..7493906cf --- /dev/null +++ b/packages/react-native-web/src/modules/warnOnce/index.js @@ -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; +}