Skip to content

Commit 67b8e18

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Add Fabric implementation of flow-relative padding and margin (#35342)
Summary: Pull Request resolved: #35342 This is a native implementation of the JS shimmed layout-specific properties in #35316. There is an experiment splitting the prop splitting codepath in Fabric, so this change effectively has two implementations depending on whether `enablePropIteratorSetter` is enabled. None of these changes make sense to propagate Yoga. `inlineEnd`, etc are already mapped to `YGEdgeStart` and `YGEdgeEnd`, but RN's mapping used a different name. Then `blockStart`, `blockEnd`, map directly to existing edges in all cases since we don't support a writing mode. On web, the last value in the style which computes the given dimension is given precedence. E.g. if "left" comes after "start" it will be chosen. Yoga stylesheets are unordered, and precedence for edges is given based on specificity (left > start > horizontal > all). We give precedence to new renamings (e.g. start to inlineStart), but to preserve consistent behavior, we give precedence to specific edges before overwriting them with flow relative ones (e.g. marginTop has precedence over marginBlockStar). Changelog: [General][Added] - Add Fabric implementation of flow-relative padding and margin Reviewed By: javache Differential Revision: D41267765 fbshipit-source-id: 896e2ed71fe8bf83aef00b0a9d70fd20b2ce47a7
1 parent 0bc4547 commit 67b8e18

File tree

9 files changed

+338
-24
lines changed

9 files changed

+338
-24
lines changed

Libraries/Components/View/ReactNativeStyleAttributes.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,15 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
4949
justifyContent: true,
5050
left: true,
5151
margin: true,
52+
marginBlock: true,
53+
marginBlockEnd: true,
54+
marginBlockStart: true,
5255
marginBottom: true,
5356
marginEnd: true,
5457
marginHorizontal: true,
58+
marginInline: true,
59+
marginInlineEnd: true,
60+
marginInlineStart: true,
5561
marginLeft: true,
5662
marginRight: true,
5763
marginStart: true,
@@ -63,9 +69,15 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
6369
minWidth: true,
6470
overflow: true,
6571
padding: true,
72+
paddingBlock: true,
73+
paddingBlockEnd: true,
74+
paddingBlockStart: true,
6675
paddingBottom: true,
6776
paddingEnd: true,
6877
paddingHorizontal: true,
78+
paddingInline: true,
79+
paddingInlineEnd: true,
80+
paddingInlineStart: true,
6981
paddingLeft: true,
7082
paddingRight: true,
7183
paddingStart: true,

Libraries/NativeComponent/BaseViewConfig.android.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,24 +212,36 @@ const validAttributesForNonEventProps = {
212212
display: true,
213213

214214
margin: true,
215-
marginVertical: true,
216-
marginHorizontal: true,
217-
marginStart: true,
218-
marginEnd: true,
219-
marginTop: true,
215+
marginBlock: true,
216+
marginBlockEnd: true,
217+
marginBlockStart: true,
220218
marginBottom: true,
219+
marginEnd: true,
220+
marginHorizontal: true,
221+
marginInline: true,
222+
marginInlineEnd: true,
223+
marginInlineStart: true,
221224
marginLeft: true,
222225
marginRight: true,
226+
marginStart: true,
227+
marginTop: true,
228+
marginVertical: true,
223229

224230
padding: true,
225-
paddingVertical: true,
226-
paddingHorizontal: true,
227-
paddingStart: true,
228-
paddingEnd: true,
229-
paddingTop: true,
231+
paddingBlock: true,
232+
paddingBlockEnd: true,
233+
paddingBlockStart: true,
230234
paddingBottom: true,
235+
paddingEnd: true,
236+
paddingHorizontal: true,
237+
paddingInline: true,
238+
paddingInlineEnd: true,
239+
paddingInlineStart: true,
231240
paddingLeft: true,
232241
paddingRight: true,
242+
paddingStart: true,
243+
paddingTop: true,
244+
paddingVertical: true,
233245

234246
borderWidth: true,
235247
borderStartWidth: true,

Libraries/NativeComponent/BaseViewConfig.ios.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -249,25 +249,37 @@ const validAttributesForNonEventProps = {
249249
// borderEndWidth: true,
250250
// borderWidth: true,
251251

252-
marginTop: true,
253-
marginRight: true,
252+
margin: true,
253+
marginBlock: true,
254+
marginBlockEnd: true,
255+
marginBlockStart: true,
254256
marginBottom: true,
257+
marginEnd: true,
258+
marginHorizontal: true,
259+
marginInline: true,
260+
marginInlineEnd: true,
261+
marginInlineStart: true,
255262
marginLeft: true,
263+
marginRight: true,
256264
marginStart: true,
257-
marginEnd: true,
265+
marginTop: true,
258266
marginVertical: true,
259-
marginHorizontal: true,
260-
margin: true,
261267

262-
paddingTop: true,
263-
paddingRight: true,
268+
padding: true,
269+
paddingBlock: true,
270+
paddingBlockEnd: true,
271+
paddingBlockStart: true,
264272
paddingBottom: true,
273+
paddingEnd: true,
274+
paddingHorizontal: true,
275+
paddingInline: true,
276+
paddingInlineEnd: true,
277+
paddingInlineStart: true,
265278
paddingLeft: true,
279+
paddingRight: true,
266280
paddingStart: true,
267-
paddingEnd: true,
281+
paddingTop: true,
268282
paddingVertical: true,
269-
paddingHorizontal: true,
270-
padding: true,
271283

272284
flex: true,
273285
flexGrow: true,

Libraries/StyleSheet/StyleSheetTypes.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,15 @@ export interface FlexStyle {
6969
| undefined;
7070
left?: number | string | undefined;
7171
margin?: number | string | undefined;
72+
marginBlock?: number | string | undefined;
73+
marginBlockEnd?: number | string | undefined;
74+
marginBlockStart?: number | string | undefined;
7275
marginBottom?: number | string | undefined;
7376
marginEnd?: number | string | undefined;
7477
marginHorizontal?: number | string | undefined;
78+
marginInline?: number | string | undefined;
79+
marginInlineEnd?: number | string | undefined;
80+
marginInlineStart?: number | string | undefined;
7581
marginLeft?: number | string | undefined;
7682
marginRight?: number | string | undefined;
7783
marginStart?: number | string | undefined;
@@ -84,8 +90,14 @@ export interface FlexStyle {
8490
overflow?: 'visible' | 'hidden' | 'scroll' | undefined;
8591
padding?: number | string | undefined;
8692
paddingBottom?: number | string | undefined;
93+
paddingBlock?: number | string | undefined;
94+
paddingBlockEnd?: number | string | undefined;
95+
paddingBlockStart?: number | string | undefined;
8796
paddingEnd?: number | string | undefined;
8897
paddingHorizontal?: number | string | undefined;
98+
paddingInline?: number | string | undefined;
99+
paddingInlineEnd?: number | string | undefined;
100+
paddingInlineStart?: number | string | undefined;
89101
paddingLeft?: number | string | undefined;
90102
paddingRight?: number | string | undefined;
91103
paddingStart?: number | string | undefined;

Libraries/StyleSheet/StyleSheetTypes.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@ type ____LayoutStyle_Internal = $ReadOnly<{
179179
*/
180180
margin?: DimensionValue,
181181

182+
/** Setting `marginBlock` has the same effect as setting both
183+
* `marginTop` and `marginBottom`.
184+
*/
185+
marginBlock?: DimensionValue,
186+
187+
/** `marginBlockEnd` works like `margin-block-end`in CSS. Because React
188+
* Native doesn not support `writing-mode` this is always mapped to
189+
* `margin-bottom`. See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-block-end
190+
* for more details.
191+
*/
192+
marginBlockEnd?: DimensionValue,
193+
194+
/** `marginBlockEnd` works like `margin-block-end`in CSS. Because React
195+
* Native doesn not support `writing-mode` this is always mapped to
196+
* `margin-top`. See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-block-end
197+
* for more details.
198+
*/
199+
marginBlockStart?: DimensionValue,
200+
182201
/** `marginBottom` works like `margin-bottom` in CSS.
183202
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom
184203
* for more details.
@@ -196,6 +215,23 @@ type ____LayoutStyle_Internal = $ReadOnly<{
196215
*/
197216
marginHorizontal?: DimensionValue,
198217

218+
/** Setting `marginInline` has the same effect as setting
219+
* both `marginLeft` and `marginRight`.
220+
*/
221+
marginInline?: DimensionValue,
222+
223+
/**
224+
* When direction is `ltr`, `marginInlineEnd` is equivalent to `marginRight`.
225+
* When direction is `rtl`, `marginInlineEnd` is equivalent to `marginLeft`.
226+
*/
227+
marginInlineEnd?: DimensionValue,
228+
229+
/**
230+
* When direction is `ltr`, `marginInlineStart` is equivalent to `marginLeft`.
231+
* When direction is `rtl`, `marginInlineStart` is equivalent to `marginRight`.
232+
*/
233+
marginInlineStart?: DimensionValue,
234+
199235
/** `marginLeft` works like `margin-left` in CSS.
200236
* See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left
201237
* for more details.
@@ -232,6 +268,23 @@ type ____LayoutStyle_Internal = $ReadOnly<{
232268
*/
233269
padding?: DimensionValue,
234270

271+
/** Setting `paddingBlock` is like setting both of
272+
* `paddingTop` and `paddingBottom`.
273+
*/
274+
paddingBlock?: DimensionValue,
275+
276+
/** `paddingBlockEnd` works like `padding-bottom` in CSS.
277+
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom
278+
* for more details.
279+
*/
280+
paddingBlockEnd?: DimensionValue,
281+
282+
/** `paddingBlockStart` works like `padding-top` in CSS.
283+
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top
284+
* for more details.
285+
*/
286+
paddingBlockStart?: DimensionValue,
287+
235288
/** `paddingBottom` works like `padding-bottom` in CSS.
236289
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom
237290
* for more details.
@@ -249,6 +302,23 @@ type ____LayoutStyle_Internal = $ReadOnly<{
249302
*/
250303
paddingHorizontal?: DimensionValue,
251304

305+
/** Setting `paddingInline` is like setting both of
306+
* `paddingLeft` and `paddingRight`.
307+
*/
308+
paddingInline?: DimensionValue,
309+
310+
/**
311+
* When direction is `ltr`, `paddingInlineEnd` is equivalent to `paddingRight`.
312+
* When direction is `rtl`, `paddingInlineEnd` is equivalent to `paddingLeft`.
313+
*/
314+
paddingInlineEnd?: DimensionValue,
315+
316+
/**
317+
* When direction is `ltr`, `paddingInlineStart` is equivalent to `paddingLeft`.
318+
* When direction is `rtl`, `paddingInlineStart` is equivalent to `paddingRight`.
319+
*/
320+
paddingInlineStart?: DimensionValue,
321+
252322
/** `paddingLeft` works like `padding-left` in CSS.
253323
* See https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left
254324
* for more details.

ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,13 +316,62 @@ void YogaLayoutableShadowNode::updateYogaProps() {
316316
ensureUnsealed();
317317

318318
auto props = static_cast<YogaStylableProps const &>(*props_);
319+
auto styleResult = applyAliasedProps(props.yogaStyle, props);
319320

320321
// Resetting `dirty` flag only if `yogaStyle` portion of `Props` was changed.
321-
if (!yogaNode_.isDirty() && (props.yogaStyle != yogaNode_.getStyle())) {
322+
if (!yogaNode_.isDirty() && (styleResult != yogaNode_.getStyle())) {
322323
yogaNode_.setDirty(true);
323324
}
324325

325-
yogaNode_.setStyle(props.yogaStyle);
326+
yogaNode_.setStyle(styleResult);
327+
}
328+
329+
/*static*/ YGStyle YogaLayoutableShadowNode::applyAliasedProps(
330+
const YGStyle &baseStyle,
331+
const YogaStylableProps &props) {
332+
YGStyle result{baseStyle};
333+
334+
// Aliases with precedence
335+
if (!props.marginInline.isUndefined()) {
336+
result.margin()[YGEdgeHorizontal] = props.marginInline;
337+
}
338+
if (!props.marginInlineStart.isUndefined()) {
339+
result.margin()[YGEdgeStart] = props.marginInlineStart;
340+
}
341+
if (!props.marginInlineEnd.isUndefined()) {
342+
result.margin()[YGEdgeEnd] = props.marginInlineEnd;
343+
}
344+
if (!props.marginBlock.isUndefined()) {
345+
result.margin()[YGEdgeVertical] = props.marginBlock;
346+
}
347+
if (!props.paddingInline.isUndefined()) {
348+
result.padding()[YGEdgeHorizontal] = props.paddingInline;
349+
}
350+
if (!props.paddingInlineStart.isUndefined()) {
351+
result.padding()[YGEdgeStart] = props.paddingInlineStart;
352+
}
353+
if (!props.paddingInlineEnd.isUndefined()) {
354+
result.padding()[YGEdgeEnd] = props.paddingInlineEnd;
355+
}
356+
if (!props.paddingBlock.isUndefined()) {
357+
result.padding()[YGEdgeVertical] = props.paddingBlock;
358+
}
359+
360+
// Aliases without precedence
361+
if (CompactValue(result.margin()[YGEdgeTop]).isUndefined()) {
362+
result.margin()[YGEdgeTop] = props.marginBlockStart;
363+
}
364+
if (CompactValue(result.margin()[YGEdgeBottom]).isUndefined()) {
365+
result.margin()[YGEdgeBottom] = props.marginBlockEnd;
366+
}
367+
if (CompactValue(result.padding()[YGEdgeTop]).isUndefined()) {
368+
result.padding()[YGEdgeTop] = props.paddingBlockStart;
369+
}
370+
if (CompactValue(result.padding()[YGEdgeBottom]).isUndefined()) {
371+
result.padding()[YGEdgeBottom] = props.paddingBlockEnd;
372+
}
373+
374+
return result;
326375
}
327376

328377
void YogaLayoutableShadowNode::setSize(Size size) const {

ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ namespace facebook {
2424
namespace react {
2525

2626
class YogaLayoutableShadowNode : public LayoutableShadowNode {
27+
using CompactValue = facebook::yoga::detail::CompactValue;
28+
2729
public:
2830
using UnsharedList = butter::small_vector<
2931
YogaLayoutableShadowNode *,
@@ -173,6 +175,14 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
173175
static void swapLeftAndRightInYogaStyleProps(
174176
YogaLayoutableShadowNode const &shadowNode);
175177

178+
/*
179+
* Combine a base YGStyle with aliased properties which should be flattened
180+
* into it. E.g. reconciling "marginInlineStart" and "marginStart".
181+
*/
182+
static YGStyle applyAliasedProps(
183+
const YGStyle &baseStyle,
184+
const YogaStylableProps &props);
185+
176186
#pragma mark - Consistency Ensuring Helpers
177187

178188
void ensureConsistency() const;

0 commit comments

Comments
 (0)