Skip to content

Commit b56ce9d

Browse files
jorge-cabfacebook-github-bot
authored andcommitted
JS plumbing to get dropShadow into native (#44939)
Summary: Pull Request resolved: #44939 DropShadow is a filter so we need to add the logic for sending it to native through the same process function for the other filters. Drop shadow can have more arguments than the other filters. I'm following a similar pattern to boxShadow D57872933. Changelog: [Internal] Reviewed By: joevilches Differential Revision: D58370127 fbshipit-source-id: dba06bb2e0ea2799d20e8b0b9065a5729df22bb6
1 parent 9ba600c commit b56ce9d

File tree

6 files changed

+504
-71
lines changed

6 files changed

+504
-71
lines changed

packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,25 @@ import {Animated} from '../Animated/Animated';
1111
import {ImageResizeMode} from '../Image/ImageResizeMode';
1212
import {ColorValue} from './StyleSheet';
1313

14+
export type FilterPrimitive =
15+
| {brightness: number | string}
16+
| {blur: number | string}
17+
| {contrast: number | string}
18+
| {grayscale: number | string}
19+
| {'hue-rotate': number | string}
20+
| {invert: number | string}
21+
| {opacity: number | string}
22+
| {saturate: number | string}
23+
| {sepia: number | string}
24+
| {'drop-shadow': DropShadowPrimitive | string};
25+
26+
export type DropShadowPrimitive = {
27+
offsetX: number | string;
28+
offsetY: number | string;
29+
standardDeviation?: number | string | undefined;
30+
color?: ColorValue | number | undefined;
31+
};
32+
1433
type FlexAlignType =
1534
| 'flex-start'
1635
| 'flex-end'

packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
'use strict';
1212

1313
import type AnimatedNode from '../Animated/nodes/AnimatedNode';
14-
import type {FilterPrimitive} from '../StyleSheet/processFilter';
1514
import type {
1615
____DangerouslyImpreciseStyle_InternalOverrides,
1716
____ImageStyle_InternalOverrides,
@@ -35,6 +34,25 @@ export type EdgeInsetsValue = {
3534
bottom: number,
3635
};
3736

37+
export type FilterPrimitive =
38+
| {brightness: number | string}
39+
| {blur: number | string}
40+
| {contrast: number | string}
41+
| {grayscale: number | string}
42+
| {'hue-rotate': number | string}
43+
| {invert: number | string}
44+
| {opacity: number | string}
45+
| {saturate: number | string}
46+
| {sepia: number | string}
47+
| {'drop-shadow': DropShadowPrimitive | string};
48+
49+
export type DropShadowPrimitive = {
50+
offsetX: number | string,
51+
offsetY: number | string,
52+
standardDeviation?: number | string,
53+
color?: ____ColorValue_Internal | number,
54+
};
55+
3856
export type DimensionValue = number | string | 'auto' | AnimatedNode | null;
3957
export type AnimatableNumericValue = number | AnimatedNode;
4058

packages/react-native/Libraries/StyleSheet/__tests__/processFilter-test.js

Lines changed: 214 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
'use strict';
1313

14-
import type {FilterPrimitive} from '../processFilter';
14+
import type {FilterPrimitive} from '../StyleSheetTypes';
15+
16+
import processColor from '../processColor';
1517

1618
const processFilter = require('../processFilter').default;
1719

@@ -38,33 +40,38 @@ describe('processFilter', () => {
3840
},
3941
]);
4042

41-
testNumericFilter('hueRotate', 0, [{hueRotate: 0}]);
42-
testUnitFilter('hueRotate', 90, 'deg', [{hueRotate: 90}]);
43-
testUnitFilter('hueRotate', 1.5708, 'rad', [
44-
{hueRotate: (180 * 1.5708) / Math.PI},
43+
testNumericFilter('hue-rotate', 0, [{'hue-rotate': 0}]);
44+
testUnitFilter('hue-rotate', 90, 'deg', [{'hue-rotate': 90}]);
45+
testUnitFilter('hue-rotate', 1.5708, 'rad', [
46+
{'hue-rotate': (180 * 1.5708) / Math.PI},
4547
]);
46-
testUnitFilter('hueRotate', -90, 'deg', [{hueRotate: -90}]);
47-
testUnitFilter('hueRotate', 1.5, 'grad', []);
48-
testNumericFilter('hueRotate', 90, []);
49-
testUnitFilter('hueRotate', 50, '%', []);
48+
testUnitFilter('hue-rotate', -90, 'deg', [{'hue-rotate': -90}]);
49+
testUnitFilter('hue-rotate', 1.5, 'grad', []);
50+
testNumericFilter('hue-rotate', 90, []);
51+
testUnitFilter('hue-rotate', 50, '%', []);
5052

5153
it('multiple filters', () => {
5254
expect(
5355
processFilter([
5456
{brightness: 0.5},
5557
{opacity: 0.5},
5658
{blur: 5},
57-
{hueRotate: '90deg'},
59+
{'hue-rotate': '90deg'},
5860
]),
59-
).toEqual([{brightness: 0.5}, {opacity: 0.5}, {blur: 5}, {hueRotate: 90}]);
61+
).toEqual([
62+
{brightness: 0.5},
63+
{opacity: 0.5},
64+
{blur: 5},
65+
{'hue-rotate': 90},
66+
]);
6067
});
6168
it('multiple filters one invalid', () => {
6269
expect(
6370
processFilter([
6471
{brightness: 0.5},
6572
{opacity: 0.5},
6673
{blur: 5},
67-
{hueRotate: '90foo'},
74+
{'hue-rotate': '90foo'},
6875
]),
6976
).toEqual([]);
7077
});
@@ -83,6 +90,20 @@ describe('processFilter', () => {
8390
{brightness: 0.5},
8491
]);
8592
});
93+
94+
it('should parse mixed case filters', () => {
95+
expect(
96+
processFilter(
97+
'brIGhTneSs(0.5) hUE-rOTatE(90deg) briGhtNess(0.5) Brightness(0.5)',
98+
),
99+
).toEqual([
100+
{brightness: 0.5},
101+
{'hue-rotate': 90},
102+
{brightness: 0.5},
103+
{brightness: 0.5},
104+
]);
105+
});
106+
86107
it('empty', () => {
87108
expect(processFilter([])).toEqual([]);
88109
});
@@ -96,12 +117,17 @@ describe('processFilter', () => {
96117
});
97118
it('string multiple filters', () => {
98119
expect(
99-
processFilter('brightness(0.5) opacity(0.5) blur(5) hueRotate(90deg)'),
100-
).toEqual([{brightness: 0.5}, {opacity: 0.5}, {blur: 5}, {hueRotate: 90}]);
120+
processFilter('brightness(0.5) opacity(0.5) blur(5) hue-rotate(90deg)'),
121+
).toEqual([
122+
{brightness: 0.5},
123+
{opacity: 0.5},
124+
{blur: 5},
125+
{'hue-rotate': 90},
126+
]);
101127
});
102128
it('string multiple filters one invalid', () => {
103129
expect(
104-
processFilter('brightness(0.5) opacity(0.5) blur(5) hueRotate(90foo)'),
130+
processFilter('brightness(0.5) opacity(0.5) blur(5) hue-rotate(90foo)'),
105131
).toEqual([]);
106132
});
107133
it('string multiple same filters', () => {
@@ -131,6 +157,8 @@ describe('processFilter', () => {
131157
// $FlowExpectedError[incompatible-call]
132158
expect(processFilter('brightness(.5)')).toEqual([{brightness: 0.5}]);
133159
});
160+
161+
testDropShadow();
134162
});
135163

136164
function testStandardFilter(filter: string): void {
@@ -191,8 +219,8 @@ function createFilterPrimitive(
191219
return {contrast: value};
192220
case 'grayscale':
193221
return {grayscale: value};
194-
case 'hueRotate':
195-
return {hueRotate: value};
222+
case 'hue-rotate':
223+
return {'hue-rotate': value};
196224
case 'invert':
197225
return {invert: value};
198226
case 'opacity':
@@ -205,3 +233,172 @@ function createFilterPrimitive(
205233
throw new Error('Invalid filter: ' + filter);
206234
}
207235
}
236+
237+
function testDropShadow() {
238+
it('should parse string drop-shadow', () => {
239+
expect(processFilter('drop-shadow(4px 4 10px red)')).toEqual([
240+
{
241+
'drop-shadow': {
242+
offsetX: 4,
243+
offsetY: 4,
244+
color: processColor('red'),
245+
standardDeviation: 10,
246+
},
247+
},
248+
]);
249+
});
250+
251+
it('should parse string negative offsets drop-shadow', () => {
252+
expect(processFilter('drop-shadow(-4 -4)')).toEqual([
253+
{
254+
'drop-shadow': {
255+
offsetX: -4,
256+
offsetY: -4,
257+
},
258+
},
259+
]);
260+
});
261+
262+
it('should parse string multiple drop-shadows', () => {
263+
expect(
264+
processFilter('drop-shadow(4 4) drop-shadow(4 4) drop-shadow(4 4)'),
265+
).toEqual([
266+
{
267+
'drop-shadow': {
268+
offsetX: 4,
269+
offsetY: 4,
270+
},
271+
},
272+
{
273+
'drop-shadow': {
274+
offsetX: 4,
275+
offsetY: 4,
276+
},
277+
},
278+
{
279+
'drop-shadow': {
280+
offsetX: 4,
281+
offsetY: 4,
282+
},
283+
},
284+
]);
285+
});
286+
287+
it('should parse string drop-shadow with random whitespaces', () => {
288+
expect(
289+
processFilter(' drop-shadow(4px 4 10px red) '),
290+
).toEqual([
291+
{
292+
'drop-shadow': {
293+
offsetX: 4,
294+
offsetY: 4,
295+
color: processColor('red'),
296+
standardDeviation: 10,
297+
},
298+
},
299+
]);
300+
});
301+
302+
it('should parse string drop-shadow with multiple filters', () => {
303+
expect(
304+
processFilter(
305+
'drop-shadow(4px 4 10px red) brightness(0.5) brightness(0.5)',
306+
),
307+
).toEqual([
308+
{
309+
'drop-shadow': {
310+
offsetX: 4,
311+
offsetY: 4,
312+
color: processColor('red'),
313+
standardDeviation: 10,
314+
},
315+
},
316+
{brightness: 0.5},
317+
{brightness: 0.5},
318+
]);
319+
});
320+
321+
it('should parse string drop-shadow with color', () => {
322+
expect(processFilter('drop-shadow(50 50 purple)')).toEqual([
323+
{
324+
'drop-shadow': {
325+
offsetX: 50,
326+
offsetY: 50,
327+
color: processColor('purple'),
328+
},
329+
},
330+
]);
331+
});
332+
333+
it('should parse string with mixed case drop-shadow', () => {
334+
expect(processFilter('DroP-sHaDOw(50 50 purple)')).toEqual([
335+
{
336+
'drop-shadow': {
337+
offsetX: 50,
338+
offsetY: 50,
339+
color: processColor('purple'),
340+
},
341+
},
342+
]);
343+
});
344+
345+
it('should parse object drop-shadow', () => {
346+
expect(
347+
processFilter([
348+
{
349+
'drop-shadow': {
350+
offsetX: 4,
351+
offsetY: 4,
352+
color: '#FFFFFF',
353+
standardDeviation: '10',
354+
},
355+
},
356+
]),
357+
).toEqual([
358+
{
359+
'drop-shadow': {
360+
offsetX: 4,
361+
offsetY: 4,
362+
standardDeviation: 10,
363+
color: processColor('#FFFFFF'),
364+
},
365+
},
366+
]);
367+
});
368+
369+
it('should fail to parse string comma separated drop-shadow', () => {
370+
expect(processFilter('drop-shadow(4px, 4, 10px, red)')).toEqual([]);
371+
});
372+
373+
it('should fail to parse other symbols after args comma separated drop-shadow', () => {
374+
expect(processFilter('drop-shadow(4& 4* 10$ red)')).toEqual([]);
375+
});
376+
377+
it('should fail on color between lengths string drop-shadow', () => {
378+
expect(processFilter('drop-shadow(10 red 10 10')).toEqual([]);
379+
});
380+
381+
it('should fail on color between offset & blur string drop-shadow', () => {
382+
expect(processFilter('drop-shadow(10 10 red 10')).toEqual([]);
383+
});
384+
385+
it('should fail on negative blue', () => {
386+
expect(processFilter('drop-shadow(10 10 -10')).toEqual([]);
387+
});
388+
389+
it('should fail on invalid object drop-shadow', () => {
390+
expect(
391+
// $FlowExpectedError[incompatible-call]
392+
processFilter([
393+
{'drop-shadow': {offsetX: 4, offsetY: 5, invalid: 'invalid arg'}},
394+
]),
395+
).toEqual([]);
396+
});
397+
398+
it('should fail on invalid argument for drop-shadow object', () => {
399+
expect(
400+
// $FlowExpectedError[incompatible-call]
401+
processFilter([{'drop-shadow': 8}]),
402+
).toEqual([]);
403+
});
404+
}

0 commit comments

Comments
 (0)