Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Fabric implementation of inset logical properties #35692

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Libraries/Components/View/ReactNativeStyleAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
flexWrap: true,
gap: true,
height: true,
inset: true,
insetBlock: true,
insetBlockEnd: true,
insetBlockStart: true,
insetInline: true,
insetInlineEnd: true,
insetInlineStart: true,
justifyContent: true,
left: true,
margin: true,
Expand Down
8 changes: 8 additions & 0 deletions Libraries/NativeComponent/BaseViewConfig.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ const validAttributesForNonEventProps = {
top: true,
bottom: true,

inset: true,
insetBlock: true,
insetBlockEnd: true,
insetBlockStart: true,
insetInline: true,
insetInlineEnd: true,
insetInlineStart: true,

position: true,

style: ReactNativeStyleAttributes,
Expand Down
8 changes: 8 additions & 0 deletions Libraries/NativeComponent/BaseViewConfig.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ const validAttributesForNonEventProps = {
bottom: true,
left: true,

inset: true,
insetBlock: true,
insetBlockEnd: true,
insetBlockStart: true,
insetInline: true,
insetInlineEnd: true,
insetInlineStart: true,

width: true,
height: true,

Expand Down
7 changes: 7 additions & 0 deletions Libraries/StyleSheet/StyleSheetTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ export interface FlexStyle {
flexShrink?: number | undefined;
flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse' | undefined;
height?: number | string | undefined;
inset?: number | string | undefined;
insetBlock?: number | string | undefined;
insetBlockEnd?: number | string | undefined;
insetBlockStart?: number | string | undefined;
insetInline?: number | string | undefined;
insetInlineEnd?: number | string | undefined;
insetInlineStart?: number | string | undefined;
justifyContent?:
| 'flex-start'
| 'flex-end'
Expand Down
16 changes: 16 additions & 0 deletions Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ type ____LayoutStyle_Internal = $ReadOnly<{
*/
top?: DimensionValue,

/** `inset` is a shorthand that corresponds to the top, right, bottom, and/or left properties.
*
* It works similarly to `inset` in CSS, but in React Native you
* must use points or percentages. Ems and other units are not supported.
*
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset
* for more details of how `inset` affects layout.
*/
inset?: DimensionValue,
insetBlock?: DimensionValue,
insetBlockEnd?: DimensionValue,
insetBlockStart?: DimensionValue,
insetInline?: DimensionValue,
insetInlineEnd?: DimensionValue,
insetInlineStart?: DimensionValue,

/** `minWidth` is the minimum width for this component, in logical pixels.
*
* It works similarly to `min-width` in CSS, but in React Native you
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,21 @@ void YogaLayoutableShadowNode::updateYogaProps() {
YGStyle result{baseStyle};

// Aliases with precedence
if (!props.inset.isUndefined()) {
result.position()[YGEdgeAll] = props.inset;
}
if (!props.insetBlock.isUndefined()) {
result.position()[YGEdgeVertical] = props.insetBlock;
}
if (!props.insetInline.isUndefined()) {
result.position()[YGEdgeHorizontal] = props.insetInline;
}
if (!props.insetInlineEnd.isUndefined()) {
result.position()[YGEdgeEnd] = props.insetInlineEnd;
}
if (!props.insetInlineStart.isUndefined()) {
result.position()[YGEdgeStart] = props.insetInlineStart;
}
if (!props.marginInline.isUndefined()) {
result.margin()[YGEdgeHorizontal] = props.marginInline;
}
Expand All @@ -359,6 +374,12 @@ void YogaLayoutableShadowNode::updateYogaProps() {
}

// Aliases without precedence
if (CompactValue(result.position()[YGEdgeBottom]).isUndefined()) {
result.position()[YGEdgeBottom] = props.insetBlockEnd;
}
if (CompactValue(result.position()[YGEdgeTop]).isUndefined()) {
result.position()[YGEdgeTop] = props.insetBlockStart;
}
if (CompactValue(result.margin()[YGEdgeTop]).isUndefined()) {
result.margin()[YGEdgeTop] = props.marginBlockStart;
}
Expand Down
55 changes: 55 additions & 0 deletions ReactCommon/react/renderer/components/view/YogaStylableProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ void YogaStylableProps::setProp(
REBUILD_FIELD_YG_EDGES(border, "border", "Width");

// Aliases
RAW_SET_PROP_SWITCH_CASE(inset, "inset", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetBlock, "insetBlock", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetBlockEnd, "insetBlockEnd", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetBlockStart, "insetBlockStart", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetInline, "insetInline", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetInlineEnd, "insetInlineEnd", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
insetInlineStart, "insetInlineStart", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
marginInline, "marginInline", CompactValue::ofUndefined());
RAW_SET_PROP_SWITCH_CASE(
Expand Down Expand Up @@ -245,6 +258,48 @@ void YogaStylableProps::convertRawPropAliases(
const PropsParserContext &context,
YogaStylableProps const &sourceProps,
RawProps const &rawProps) {
inset = convertRawProp(
context,
rawProps,
"inset",
sourceProps.inset,
CompactValue::ofUndefined());
insetBlock = convertRawProp(
context,
rawProps,
"insetBlock",
sourceProps.insetBlock,
CompactValue::ofUndefined());
insetBlockEnd = convertRawProp(
context,
rawProps,
"insetBlockEnd",
sourceProps.insetBlockEnd,
CompactValue::ofUndefined());
insetBlockStart = convertRawProp(
context,
rawProps,
"insetBlockStart",
sourceProps.insetBlockStart,
CompactValue::ofUndefined());
insetInline = convertRawProp(
context,
rawProps,
"insetInline",
sourceProps.insetInline,
CompactValue::ofUndefined());
insetInlineEnd = convertRawProp(
context,
rawProps,
"insetInlineEnd",
sourceProps.insetInlineEnd,
CompactValue::ofUndefined());
insetInlineStart = convertRawProp(
context,
rawProps,
"insetInlineStart",
sourceProps.insetInlineStart,
CompactValue::ofUndefined());
marginInline = convertRawProp(
context,
rawProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class YogaStylableProps : public Props {

// Duplicates of existing properties with different names, taking
// precendence. E.g. "marginBlock" instead of "marginVertical"
CompactValue inset;
CompactValue insetInline;
CompactValue insetInlineEnd;
CompactValue insetInlineStart;

CompactValue marginInline;
CompactValue marginInlineStart;
CompactValue marginInlineEnd;
Expand All @@ -56,6 +61,10 @@ class YogaStylableProps : public Props {
// BlockEnd/BlockStart map to top/bottom (no writing mode), but we preserve
// Yoga's precedence and prefer specific edges (e.g. top) to ones which are
// flow relative (e.g. blockStart).
CompactValue insetBlock;
CompactValue insetBlockEnd;
CompactValue insetBlockStart;

CompactValue marginBlockStart;
CompactValue marginBlockEnd;

Expand Down
86 changes: 86 additions & 0 deletions packages/rn-tester/js/examples/View/ViewExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,4 +652,90 @@ exports.examples = [
return <FlexGapExample />;
},
},
{
title: 'Insets',
render(): React.Node {
return (
<View style={{rowGap: 10}}>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
inset: 10,
}}>
<Text style={{fontSize: 11}}>inset 10</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetBlock: 5,
}}>
<Text style={{fontSize: 11}}>insetBlock 5</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetBlockEnd: 5,
}}>
<Text style={{fontSize: 11}}>insetBlockEnd 5</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetBlockStart: 5,
}}>
<Text style={{fontSize: 11}}>insetBlockStart 5</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetInline: 5,
}}>
<Text style={{fontSize: 11}}>insetInline 5</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetInlineEnd: 5,
}}>
<Text style={{fontSize: 11}}>insetInlineEnd 5</Text>
</View>
</View>
<View style={{position: 'relative', height: 50, borderWidth: 1}}>
<View
style={{
backgroundColor: '#527FE4',
padding: 5,
position: 'absolute',
insetInlineStart: 5,
}}>
<Text style={{fontSize: 11}}>insetInlineStart 5</Text>
</View>
</View>
</View>
);
},
},
];