Skip to content

Commit 0d5fb0f

Browse files
roskonecolas
authored andcommitted
[feat] Support style boxShadow as array
1 parent de32e19 commit 0d5fb0f

File tree

2 files changed

+101
-6
lines changed

2 files changed

+101
-6
lines changed

packages/react-native-web/src/exports/StyleSheet/__tests__/preprocess-test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,43 @@ describe('StyleSheet/preprocess', () => {
107107
expect(preprocess({ aspectRatio: undefined })).toEqual({});
108108
});
109109

110+
describe('boxShadow', () => {
111+
// passthrough if boxShadow value is ever a string
112+
test('string', () => {
113+
const boxShadow = '0 1px 2px rgba(0, 0, 0, 0.5)';
114+
const style = { boxShadow };
115+
const resolved = preprocess(style);
116+
117+
expect(resolved).toEqual({ boxShadow });
118+
});
119+
120+
test('array', () => {
121+
const boxShadow = [
122+
'0 1px 2px rgba(0, 0, 0, 0.5)',
123+
{
124+
offsetX: 1,
125+
offsetY: 2,
126+
blurRadius: 3
127+
},
128+
{
129+
offsetX: 5,
130+
offsetY: 6,
131+
blurRadius: 7,
132+
spreadDistance: 8,
133+
color: 'rgba(0, 255, 0, 0.75)',
134+
inset: true
135+
}
136+
];
137+
const style = { boxShadow };
138+
const resolved = preprocess(style);
139+
140+
expect(resolved).toEqual({
141+
boxShadow:
142+
'0 1px 2px rgba(0, 0, 0, 0.5), 1px 2px 3px 0 black, inset 5px 6px 7px 8px rgba(0,255,0,0.75)'
143+
});
144+
});
145+
});
146+
110147
test('fontVariant', () => {
111148
expect(
112149
preprocess({ fontVariant: 'common-ligatures small-caps' })
@@ -190,6 +227,43 @@ describe('StyleSheet/preprocess', () => {
190227
boxShadow: '1px 2px 3px rgba(50,60,70,0.25)'
191228
});
192229
});
230+
231+
test('shadow styles and string boxShadow together', () => {
232+
expect(
233+
preprocess({
234+
shadowColor: 'rgba(50,60,70,0.5)',
235+
shadowOffset: { width: 1, height: 2 },
236+
shadowOpacity: 0.5,
237+
shadowRadius: 3,
238+
boxShadow: '4px 5px 6px black'
239+
})
240+
).toEqual({
241+
boxShadow: '4px 5px 6px black, 1px 2px 3px rgba(50,60,70,0.25)'
242+
});
243+
});
244+
245+
test('shadow styles and array boxShadow together', () => {
246+
expect(
247+
preprocess({
248+
shadowColor: 'rgba(50,60,70,0.5)',
249+
shadowOffset: { width: 1, height: 2 },
250+
shadowOpacity: 0.5,
251+
shadowRadius: 3,
252+
boxShadow: [
253+
{
254+
offsetX: 2,
255+
offsetY: 3,
256+
spreadDistance: 5,
257+
color: 'rgba(10,20,30,0.45)',
258+
inset: true
259+
}
260+
]
261+
})
262+
).toEqual({
263+
boxShadow:
264+
'inset 2px 3px 0 5px rgba(10,20,30,0.45), 1px 2px 3px rgba(50,60,70,0.25)'
265+
});
266+
});
193267
});
194268

195269
describe('preprocesses multiple textShadow styles into a single declaration', () => {

packages/react-native-web/src/exports/StyleSheet/preprocess.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ export const createTextShadowValue = (style: Object): void | string => {
5656
}
5757
};
5858

59+
// { offsetX: 1, offsetY: 2, blurRadius: 3, spreadDistance: 4, color: 'rgba(255, 0, 0)', inset: true }
60+
// => 'rgba(255, 0, 0) 1px 2px 3px 4px inset'
61+
const mapBoxShadow = (boxShadow: Object | string): string => {
62+
if (typeof boxShadow === 'string') {
63+
return boxShadow;
64+
}
65+
const offsetX = normalizeValueWithProperty(boxShadow.offsetX) || 0;
66+
const offsetY = normalizeValueWithProperty(boxShadow.offsetY) || 0;
67+
const blurRadius = normalizeValueWithProperty(boxShadow.blurRadius) || 0;
68+
const spreadDistance =
69+
normalizeValueWithProperty(boxShadow.spreadDistance) || 0;
70+
const color = normalizeColor(boxShadow.color) || 'black';
71+
const position = boxShadow.inset ? 'inset ' : '';
72+
return `${position}${offsetX} ${offsetY} ${blurRadius} ${spreadDistance} ${color}`;
73+
};
74+
export const createBoxShadowArrayValue = (value: Array<Object>): string => {
75+
return value.map(mapBoxShadow).join(', ');
76+
};
77+
5978
// { scale: 2 } => 'scale(2)'
6079
// { translateX: 20 } => 'translateX(20px)'
6180
// { matrix: [1,2,3,4,5,6] } => 'matrix(1,2,3,4,5,6)'
@@ -126,12 +145,8 @@ export const preprocess = <T: {| [key: string]: any |}>(
126145
`"shadow*" style props are deprecated. Use "boxShadow".`
127146
);
128147
const boxShadowValue = createBoxShadowValue(style);
129-
if (boxShadowValue != null && nextStyle.boxShadow == null) {
130-
const { boxShadow } = style;
131-
const value = boxShadow
132-
? `${boxShadow}, ${boxShadowValue}`
133-
: boxShadowValue;
134-
nextStyle.boxShadow = value;
148+
if (boxShadowValue != null) {
149+
nextStyle.boxShadow = boxShadowValue;
135150
}
136151
}
137152

@@ -184,6 +199,12 @@ export const preprocess = <T: {| [key: string]: any |}>(
184199

185200
if (prop === 'aspectRatio' && typeof value === 'number') {
186201
nextStyle[prop] = value.toString();
202+
} else if (prop === 'boxShadow') {
203+
if (Array.isArray(value)) {
204+
value = createBoxShadowArrayValue(value);
205+
}
206+
const { boxShadow } = nextStyle;
207+
nextStyle.boxShadow = boxShadow ? `${value}, ${boxShadow}` : value;
187208
} else if (prop === 'fontVariant') {
188209
if (Array.isArray(value) && value.length > 0) {
189210
/*

0 commit comments

Comments
 (0)