Camelize filter function names in object notation (#45503)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45503

Kebab case object literals are a pain as an API to give folks. Keep string parsing using the kebab-case web names, like in CSS, but keep object notation camelCase.

This is super super hacked up, and we should burn away all these viewconfig processors as soon as we can.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D59793095

fbshipit-source-id: 888cad31142d7aeed42687ab23c2023ac7e4882d
This commit is contained in:
Nick Gerleman
2024-07-17 20:35:17 -07:00
committed by Facebook GitHub Bot
parent 27c6fcbe72
commit f96a4c0d5d
8 changed files with 54 additions and 59 deletions
@@ -232,12 +232,12 @@ export type FilterPrimitive =
| {blur: number | string}
| {contrast: number | string}
| {grayscale: number | string}
| {'hue-rotate': number | string}
| {hueRotate: number | string}
| {invert: number | string}
| {opacity: number | string}
| {saturate: number | string}
| {sepia: number | string}
| {'drop-shadow': DropShadowPrimitive | string};
| {dropShadow: DropShadowPrimitive | string};
export type DropShadowPrimitive = {
offsetX: number | string;
@@ -695,12 +695,12 @@ export type FilterPrimitive =
| {blur: number | string}
| {contrast: number | string}
| {grayscale: number | string}
| {'hue-rotate': number | string}
| {hueRotate: number | string}
| {invert: number | string}
| {opacity: number | string}
| {saturate: number | string}
| {sepia: number | string}
| {'drop-shadow': DropShadowPrimitive | string};
| {dropShadow: DropShadowPrimitive | string};
export type DropShadowPrimitive = {
offsetX: number | string,
@@ -40,12 +40,12 @@ describe('processFilter', () => {
},
]);
testNumericFilter('hue-rotate', 0, [{'hue-rotate': 0}]);
testUnitFilter('hue-rotate', 90, 'deg', [{'hue-rotate': 90}]);
testNumericFilter('hue-rotate', 0, [{hueRotate: 0}]);
testUnitFilter('hue-rotate', 90, 'deg', [{hueRotate: 90}]);
testUnitFilter('hue-rotate', 1.5708, 'rad', [
{'hue-rotate': (180 * 1.5708) / Math.PI},
{hueRotate: (180 * 1.5708) / Math.PI},
]);
testUnitFilter('hue-rotate', -90, 'deg', [{'hue-rotate': -90}]);
testUnitFilter('hue-rotate', -90, 'deg', [{hueRotate: -90}]);
testUnitFilter('hue-rotate', 1.5, 'grad', []);
testNumericFilter('hue-rotate', 90, []);
testUnitFilter('hue-rotate', 50, '%', []);
@@ -56,14 +56,9 @@ describe('processFilter', () => {
{brightness: 0.5},
{opacity: 0.5},
{blur: 5},
{'hue-rotate': '90deg'},
{hueRotate: '90deg'},
]),
).toEqual([
{brightness: 0.5},
{opacity: 0.5},
{blur: 5},
{'hue-rotate': 90},
]);
).toEqual([{brightness: 0.5}, {opacity: 0.5}, {blur: 5}, {hueRotate: 90}]);
});
it('multiple filters one invalid', () => {
expect(
@@ -71,7 +66,7 @@ describe('processFilter', () => {
{brightness: 0.5},
{opacity: 0.5},
{blur: 5},
{'hue-rotate': '90foo'},
{hueRotate: '90foo'},
]),
).toEqual([]);
});
@@ -98,7 +93,7 @@ describe('processFilter', () => {
),
).toEqual([
{brightness: 0.5},
{'hue-rotate': 90},
{hueRotate: 90},
{brightness: 0.5},
{brightness: 0.5},
]);
@@ -118,12 +113,7 @@ describe('processFilter', () => {
it('string multiple filters', () => {
expect(
processFilter('brightness(0.5) opacity(0.5) blur(5) hue-rotate(90deg)'),
).toEqual([
{brightness: 0.5},
{opacity: 0.5},
{blur: 5},
{'hue-rotate': 90},
]);
).toEqual([{brightness: 0.5}, {opacity: 0.5}, {blur: 5}, {hueRotate: 90}]);
});
it('string multiple filters one invalid', () => {
expect(
@@ -220,7 +210,7 @@ function createFilterPrimitive(
case 'grayscale':
return {grayscale: value};
case 'hue-rotate':
return {'hue-rotate': value};
return {hueRotate: value};
case 'invert':
return {invert: value};
case 'opacity':
@@ -238,7 +228,7 @@ function testDropShadow() {
it('should parse string drop-shadow', () => {
expect(processFilter('drop-shadow(4px 4 10px red)')).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
color: processColor('red'),
@@ -251,7 +241,7 @@ function testDropShadow() {
it('should parse string negative offsets drop-shadow', () => {
expect(processFilter('drop-shadow(-4 -4)')).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: -4,
offsetY: -4,
},
@@ -264,19 +254,19 @@ function testDropShadow() {
processFilter('drop-shadow(4 4) drop-shadow(4 4) drop-shadow(4 4)'),
).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
},
},
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
},
},
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
},
@@ -289,7 +279,7 @@ function testDropShadow() {
processFilter(' drop-shadow(4px 4 10px red) '),
).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
color: processColor('red'),
@@ -306,7 +296,7 @@ function testDropShadow() {
),
).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
color: processColor('red'),
@@ -321,7 +311,7 @@ function testDropShadow() {
it('should parse string drop-shadow with color', () => {
expect(processFilter('drop-shadow(50 50 purple)')).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 50,
offsetY: 50,
color: processColor('purple'),
@@ -333,7 +323,7 @@ function testDropShadow() {
it('should parse string with mixed case drop-shadow', () => {
expect(processFilter('DroP-sHaDOw(50 50 purple)')).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 50,
offsetY: 50,
color: processColor('purple'),
@@ -346,7 +336,7 @@ function testDropShadow() {
expect(
processFilter([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
color: '#FFFFFF',
@@ -356,7 +346,7 @@ function testDropShadow() {
]),
).toEqual([
{
'drop-shadow': {
dropShadow: {
offsetX: 4,
offsetY: 4,
standardDeviation: 10,
@@ -390,7 +380,7 @@ function testDropShadow() {
expect(
// $FlowExpectedError[incompatible-call]
processFilter([
{'drop-shadow': {offsetX: 4, offsetY: 5, invalid: 'invalid arg'}},
{dropShadow: {offsetX: 4, offsetY: 5, invalid: 'invalid arg'}},
]),
).toEqual([]);
});
@@ -398,7 +388,7 @@ function testDropShadow() {
it('should fail on invalid argument for drop-shadow object', () => {
expect(
// $FlowExpectedError[incompatible-call]
processFilter([{'drop-shadow': 8}]),
processFilter([{dropShadow: 8}]),
).toEqual([]);
});
}
+14 -8
View File
@@ -21,12 +21,12 @@ type ParsedFilter =
| {blur: number}
| {contrast: number}
| {grayscale: number}
| {'hue-rotate': number}
| {hueRotate: number}
| {invert: number}
| {opacity: number}
| {saturate: number}
| {sepia: number}
| {'drop-shadow': ParsedDropShadow};
| {dropShadow: ParsedDropShadow};
type ParsedDropShadow = {
offsetX: number,
@@ -49,17 +49,23 @@ export default function processFilter(
if (filterName === 'drop-shadow') {
const dropShadow = parseDropShadow(matches[2]);
if (dropShadow != null) {
result.push({'drop-shadow': dropShadow});
result.push({dropShadow});
} else {
return [];
}
} else {
const amount = _getFilterAmount(filterName, matches[2]);
const camelizedName =
filterName === 'drop-shadow'
? 'dropShadow'
: filterName === 'hue-rotate'
? 'hueRotate'
: filterName;
const amount = _getFilterAmount(camelizedName, matches[2]);
if (amount != null) {
const filterPrimitive = {};
// $FlowFixMe The key will be the correct one but flow can't see that.
filterPrimitive[filterName] = amount;
filterPrimitive[camelizedName] = amount;
// $FlowFixMe The key will be the correct one but flow can't see that.
result.push(filterPrimitive);
} else {
@@ -73,13 +79,13 @@ export default function processFilter(
} else {
for (const filterPrimitive of filter) {
const [filterName, filterValue] = Object.entries(filterPrimitive)[0];
if (filterName === 'drop-shadow') {
if (filterName === 'dropShadow') {
// $FlowFixMe
const dropShadow = parseDropShadow(filterValue);
if (dropShadow == null) {
return [];
}
result.push({'drop-shadow': dropShadow});
result.push({dropShadow});
} else {
const amount = _getFilterAmount(filterName, filterValue);
@@ -125,7 +131,7 @@ function _getFilterAmount(filterName: string, filterArgs: mixed): ?number {
switch (filterName) {
// Hue rotate takes some angle that can have a unit and can be
// negative. Additionally, 0 with no unit is allowed.
case 'hue-rotate':
case 'hueRotate':
if (filterArgAsNumber === 0) {
return 0;
}
@@ -7688,12 +7688,12 @@ export type FilterPrimitive =
| { blur: number | string }
| { contrast: number | string }
| { grayscale: number | string }
| { \\"hue-rotate\\": number | string }
| { hueRotate: number | string }
| { invert: number | string }
| { opacity: number | string }
| { saturate: number | string }
| { sepia: number | string }
| { \\"drop-shadow\\": DropShadowPrimitive | string };
| { dropShadow: DropShadowPrimitive | string };
export type DropShadowPrimitive = {
offsetX: number | string,
offsetY: number | string,
@@ -8049,12 +8049,12 @@ exports[`public API should not change unintentionally Libraries/StyleSheet/proce
| { blur: number }
| { contrast: number }
| { grayscale: number }
| { \\"hue-rotate\\": number }
| { hueRotate: number }
| { invert: number }
| { opacity: number }
| { saturate: number }
| { sepia: number }
| { \\"drop-shadow\\": ParsedDropShadow };
| { dropShadow: ParsedDropShadow };
type ParsedDropShadow = {
offsetX: number,
offsetY: number,
@@ -39,12 +39,11 @@ internal object FilterHelper {
"grayscale" -> createGrayscaleEffect((filter.value as Double).toFloat(), chainedEffects)
"sepia" -> createSepiaEffect((filter.value as Double).toFloat(), chainedEffects)
"saturate" -> createSaturateEffect((filter.value as Double).toFloat(), chainedEffects)
"hue-rotate" ->
createHueRotateEffect((filter.value as Double).toFloat(), chainedEffects)
"hueRotate" -> createHueRotateEffect((filter.value as Double).toFloat(), chainedEffects)
"invert" -> createInvertEffect((filter.value as Double).toFloat(), chainedEffects)
"blur" -> createBlurEffect((filter.value as Double).toFloat(), chainedEffects)
"opacity" -> createOpacityEffect((filter.value as Double).toFloat(), chainedEffects)
"drop-shadow" ->
"dropShadow" ->
parseAndCreateDropShadowEffect(filter.value as ReadableMap, chainedEffects)
else -> throw IllegalArgumentException("Invalid filter name: $filterName")
}
@@ -69,7 +68,7 @@ internal object FilterHelper {
"grayscale" -> createGrayscaleColorMatrix(amount)
"sepia" -> createSepiaColorMatrix(amount)
"saturate" -> createSaturateColorMatrix(amount)
"hue-rotate" -> createHueRotateColorMatrix(amount)
"hueRotate" -> createHueRotateColorMatrix(amount)
"invert" -> createInvertColorMatrix(amount)
"opacity" -> createOpacityColorMatrix(amount)
else -> throw IllegalArgumentException("Invalid color matrix filter: $filterName")
@@ -44,7 +44,7 @@ inline FilterType filterTypeFromString(std::string_view filterName) {
return FilterType::Contrast;
} else if (filterName == "grayscale") {
return FilterType::Grayscale;
} else if (filterName == "hue-rotate") {
} else if (filterName == "hueRotate") {
return FilterType::HueRotate;
} else if (filterName == "invert") {
return FilterType::Invert;
@@ -54,7 +54,7 @@ inline FilterType filterTypeFromString(std::string_view filterName) {
return FilterType::Saturate;
} else if (filterName == "sepia") {
return FilterType::Sepia;
} else if (filterName == "drop-shadow") {
} else if (filterName == "dropShadow") {
return FilterType::DropShadow;
} else {
throw std::invalid_argument(std::string(filterName));
@@ -174,13 +174,13 @@ exports.examples = [
},
{
title: 'Hue Rotate',
description: 'hue-rotate(-90deg)',
name: 'hue-rotate',
description: 'hueRotate(-90deg)',
name: 'hueRotate',
platform: 'android',
render(): React.Node {
return (
<StaticViewAndImage
style={{experimental_filter: [{'hue-rotate': '-90deg'}]}}
style={{experimental_filter: [{hueRotate: '-90deg'}]}}
/>
);
},
@@ -219,7 +219,7 @@ exports.examples = [
return (
<StaticViewAndImage
style={{
experimental_filter: [{'drop-shadow': '30px 10px 4px #4444dd'}],
experimental_filter: [{dropShadow: '30px 10px 4px #4444dd'}],
}}
testID="filter-test-drop-shadow"
imageSource={alphaHotdog}